为什么 Firefox 不允许您在主框架中执行脚本?
Why doesn't Firefox allow you to execute a script in the main frame?
我正在使用基于 Chrome 的 Firefox 新的 webExtensions 框架编写一个 webextension。所有示例扩展都在 Nightly 构建中工作,所以这就是我正在测试的地方。我想要做的是 运行 内容页面加载时的脚本。这是我的 background.js 页面:
background.js
"use strict";
function onCompletedFunc(details) {
var script = 'console.log("ok");';
console.log("Details are %o", details);
chrome.tabs.executeScript(details['tabId'], {
code: script,
runAt: 'document_end'
});
};
chrome.webRequest.onCompleted.addListener(onCompletedFunc,
{'urls': ['<all_urls>']},
['responseHeaders']);
//Does not work:
/*
chrome.webRequest.onCompleted.addListener(onCompletedFunc,
{'urls': ['<all_urls>'], 'types':["main_frame"]},
['responseHeaders']);
*/
这适用于 Nightly。我从后台页面获得详细信息列表 ("Details are ..."),在内容页面的控制台上获得几行 "ok",它加载的每个资源对应一行。它 运行 在 Chrome 中相同(清单文件略有不同)。
我想要的是第二个变体,它在页面上只出现一次运行。这在 Chrome 中工作正常。在 Nightly 中,它显示来自主框架的一条 "Details" 消息,但内容页面的控制台中没有任何显示。
我确定这是时间问题,但这里有什么问题?
manifest.json(删除 "applications":{...} 以便与 Chrome 一起使用)
{
"description": "",
"manifest_version": 2,
"name": "execute_script",
"version": "1.0",
"applications": {
"gecko": {
"id": "user-agent-rewriter@mozilla.org",
"strict_min_version": "45.0"
}
},
"permissions": [
"webRequest", "webRequestBlocking", "<all_urls>"
],
"background": {
"scripts": ["background.js"]
}
}
您的第一个代码段(没有 types
)之所以有效,是因为您不仅收到了对 main_frame
的请求,而且还收到了另一个子资源。如果您想注入脚本,webRequest.onCompleted
不是正确的事件。无法保证选项卡中的页面与您收到请求的页面相匹配。
如果要无条件运行编码,只需在清单文件中声明内容脚本即可。有关详细信息,请参阅 content script documentation.
如果编程注入是必须的,请使用 chrome.webNavigation.onCommitted
事件而不是 webRequest 事件。通过此事件,您知道选项卡现在显示对给定 URL 的响应。例如:
chrome.webNavigation.onCommitted.addListener(function(details) {
// Example: Only run in main frame and URLs containing "example"
if (details.frameId === 0 && details.url.includes('example')) {
chrome.tabs.executeScript(details.tabId, {
code: 'console.log("Injected at " + document.URL);',
runAt: 'document_end'
});
}
});
// filter (the second parameter, not used above) is supported as of Firefox 50.
如果您使用 webNavigation.onCommitted
事件,您 必须 考虑到 API 是非阻塞的。有可能(但概率很低)发生以下情况:
- 用户开始请求。
webNavigation.onCompleted
触发。
- 您调用
tabs.executeScript
.
- 与此同时该选项卡导航到其他网站。
tabs.executeScript
请求到达选项卡,同时切换到另一个 URL。
- 糟糕,您刚刚在页面中注入了一个与您预期不同的脚本。
如果 URL 不匹配是不可取的,那么在继续内容脚本逻辑之前检查 document.URL
or location
是否具有预期值。
我正在使用基于 Chrome 的 Firefox 新的 webExtensions 框架编写一个 webextension。所有示例扩展都在 Nightly 构建中工作,所以这就是我正在测试的地方。我想要做的是 运行 内容页面加载时的脚本。这是我的 background.js 页面:
background.js
"use strict";
function onCompletedFunc(details) {
var script = 'console.log("ok");';
console.log("Details are %o", details);
chrome.tabs.executeScript(details['tabId'], {
code: script,
runAt: 'document_end'
});
};
chrome.webRequest.onCompleted.addListener(onCompletedFunc,
{'urls': ['<all_urls>']},
['responseHeaders']);
//Does not work:
/*
chrome.webRequest.onCompleted.addListener(onCompletedFunc,
{'urls': ['<all_urls>'], 'types':["main_frame"]},
['responseHeaders']);
*/
这适用于 Nightly。我从后台页面获得详细信息列表 ("Details are ..."),在内容页面的控制台上获得几行 "ok",它加载的每个资源对应一行。它 运行 在 Chrome 中相同(清单文件略有不同)。
我想要的是第二个变体,它在页面上只出现一次运行。这在 Chrome 中工作正常。在 Nightly 中,它显示来自主框架的一条 "Details" 消息,但内容页面的控制台中没有任何显示。
我确定这是时间问题,但这里有什么问题?
manifest.json(删除 "applications":{...} 以便与 Chrome 一起使用)
{
"description": "",
"manifest_version": 2,
"name": "execute_script",
"version": "1.0",
"applications": {
"gecko": {
"id": "user-agent-rewriter@mozilla.org",
"strict_min_version": "45.0"
}
},
"permissions": [
"webRequest", "webRequestBlocking", "<all_urls>"
],
"background": {
"scripts": ["background.js"]
}
}
您的第一个代码段(没有 types
)之所以有效,是因为您不仅收到了对 main_frame
的请求,而且还收到了另一个子资源。如果您想注入脚本,webRequest.onCompleted
不是正确的事件。无法保证选项卡中的页面与您收到请求的页面相匹配。
如果要无条件运行编码,只需在清单文件中声明内容脚本即可。有关详细信息,请参阅 content script documentation.
如果编程注入是必须的,请使用 chrome.webNavigation.onCommitted
事件而不是 webRequest 事件。通过此事件,您知道选项卡现在显示对给定 URL 的响应。例如:
chrome.webNavigation.onCommitted.addListener(function(details) {
// Example: Only run in main frame and URLs containing "example"
if (details.frameId === 0 && details.url.includes('example')) {
chrome.tabs.executeScript(details.tabId, {
code: 'console.log("Injected at " + document.URL);',
runAt: 'document_end'
});
}
});
// filter (the second parameter, not used above) is supported as of Firefox 50.
如果您使用 webNavigation.onCommitted
事件,您 必须 考虑到 API 是非阻塞的。有可能(但概率很低)发生以下情况:
- 用户开始请求。
webNavigation.onCompleted
触发。- 您调用
tabs.executeScript
. - 与此同时该选项卡导航到其他网站。
tabs.executeScript
请求到达选项卡,同时切换到另一个 URL。- 糟糕,您刚刚在页面中注入了一个与您预期不同的脚本。
如果 URL 不匹配是不可取的,那么在继续内容脚本逻辑之前检查 document.URL
or location
是否具有预期值。