问题
I am trying to fix some issues in an existing extension of Chrome. The extension is supposed to change the user agent of the sub frame which is a part of it. Now the problem is that when the event happens and I change the user agent of the header it is reflecting on all the tabs in browser and forcing the rest of the secured logins in those tabs to log off. I want to change the user agent of only that particular tab of the extension. Here is the code I am using in background.js
var requestFilter = {
urls: [
"<all_urls>"
],
types: ["main_frame", "sub_frame"]
};
chrome.tabs.query({
'active': true,
'windowId': chrome.windows.WINDOW_ID_CURRENT
},
function(tabs) {
chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
var headers = [];
headers = details.requestHeaders;
if (!localStorage['user-agent']) {
return;
}
for (var i = 0; i < headers.length; i++) {
if (headers[i].name != 'User-Agent') {
headers[i].name = 'User-Agent';
headers[i].value =
localStorage['user-agent'];
}
}
return {
requestHeaders: headers
};
}, requestFilter, ['requestHeaders', 'blocking']);
});
function focusOrCreateTab(url) {
chrome.windows.getAll({
"populate": false
}, function(windows) {
var existing_tab = null;
for (var i in windows) {
var tabs = windows[i].tabs;
for (var j in tabs) {
var tab = tabs[j];
if (tab.url == url) {
existing_tab = tab;
break;
}
}
}
if (existing_tab) {
chrome.tabs.update(existing_tab.id, {
"selected": true
});
} else {
chrome.tabs.create({
"url": url,
"selected": true
});
}
});
}
chrome.browserAction.onClicked.addListener(function(tab) {
var manager_url = chrome.extension.getURL("youTube_tool.html");
focusOrCreateTab(manager_url);
});
Kindly help me with this. I have been stuck for two weeks :-(
回答1:
Your chrome.tabs.query({active:true, ...})
call happens directly whenever the background script is loaded (thus once). This is incorrect, your callback will only receive the active tab from when the extension is loaded.
To fix this issue, call chrome.tabs.query
whenever you want the active tab.
For your specific case, this is not needed at all: the chrome.browserAction.onClicked event receives a Tab
object of the current tab when clicked. From the object, you can get the tab's ID using tab.id
and assign this value to requestFilter.tabId, as done below to restrict the event listener to that specific tab:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
// do whatever you want.
}, {
urls: [
'*://*/*'
],
types: ['main_frame', 'sub_frame'],
tabId: tab.id
}, ['requestHeaders', 'blocking']);
});
Note: If you want to get the ability to remove the event, you have to save the callback in some global variable. The example below shows how to toggle an event listener that blocks all document requests in the current tab.
var listeners = {};
chrome.browserAction.onClicked.addListener(function(tab) {
if (listeners[tab.id]) {
// Callback was previously set. Remove the listeners.
chrome.webRequest.onBeforeRequest.removeListener(listeners[tab.id]);
delete listeners[tab.id];
chrome.browserAction.setBadgeText({
text: '',
tabId: tab.id
});
} else {
listeners[tab.id] = function(details) {
return {cancel: true};
};
chrome.webRequest.onBeforeRequest.addListener(listeners[tab.id], {
urls: ['*://*/*'],
types: ['main_frame', 'sub_frame'],
tabId: tab.id
}, ['blocking']);
// Show indicator to show that the extension is active.
chrome.browserAction.setBadgeText({
text: 'ON',
tabId: tab.id
});
}
});
// Remove obsolete listener when the tab is closed.
chrome.tabs.onRemoved.addListener(function(tabId) {
if (listeners[tabId]) {
chrome.webRequest.onBeforeRequest.removeListener(listeners[tabId]);
delete listeners[tabId];
}
});
Here is a minimal manifest.json to test the previous code (background.js):
{
"name": "Toggle requests for a specific tab",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"],
"persistent": true
},
"browser_action": {
},
"permissions": [
"webRequest",
"webRequestBlocking",
"*://*/*"
]
}
回答2:
It's plain and clear in the docs: a RequestFilter
can contain a tab ID.
chrome.tabs.query({
'active': true,
'currentWindow': true // A much better way to write this
},
function(tabs) {
requestFilter.tabId = tabs[0].id; // Set the tab to filter on
chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
/* ... */
来源:https://stackoverflow.com/questions/27541467/restrict-addeventlistener-of-chrome-webrequest-to-the-current-tab-or-the-main-wi