一起来做Chrome/Firefox Extension《一些问题》
一起来做Chrome/Firefox Extension《一些问题》
| 更新时间 | 说明 |
|---|---|
| 2019.4.16 | 增加:关于chrome.tabs.getCurrent() |
目录
- Unchecked runtime.lastError: The message port closed before a response wa received.
- 使用 eval
- Content script注入iframe
- Extenstion内的html
- 站外连接
- 关于chrome.tabs.getCurrent()
1. Unchecked runtime.lastError: The message port closed before a response wa received.
此错误一般发生在background js和content js通讯的时候,问题描述得也非常清楚,解决方法非常简单,即在收到消息后,在同步时间里send respnose就可以了。
注意:send response如果在异步方法里,并不能解决这个问题。
// Example:
// background js 或content js
chrome.extension.onMessage.addListener(function(request, _, sendResponse) {
sendResponse('');
});
2. 使用eval
Chrome Extension默认是禁止使用eval方法的,使用之前,需要先在manifest.json里开启,如下:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
3. 使用iframe
注入iframe同样受content_security_policy限制,而且会受到目标站点的content_security_policy限制。关于content_security_policy内容比较多,这里分成两种情况
3.1 Extension内的html
注入的iframe加载Extension内的html稍微没有这么麻烦,只需要在manifest.json里指定要加载的html就好了
"web_accessible_resources": ["example.html"]
注入iframe的src,可以使用chrome.runtime.getUrl()来获取地址
let src = chrome.runtime.getURL('example.html')
注:要注入网站的content_security_policy对这样的iframe注入会不会有影响,目前还没有测试到。
此方法在 Fika (reader-mode) 扩展里有使用
3.2 站外连接
如上所说,注入iframe是受目标网站的content_security_policy限制的,所以,如果目标网站不允许,你的注入将会失败,如medium.com的content_security_policy关于frame-src的部分:
default-src 'self';
...
frame-src chromenull: https: webviewprogressproxy: medium: 'self';
...
它允许了https的地址,所以,注入的iframe加载https地址是没有问题的,而http的地址将被拒绝。因为注入已经离开了Chrome Extenstion的范围,所以,不管你怎么对Chrome Extension的content_security_policy进行设置并不会有用。
关于content_security_policy,可以看 https://www.html5rocks.com/en/tutorials/security/content-security-policy/
4.关于chrome.tabs.getCurrent()
首先看看官方文档说明:
Gets the tab that this script call is being made from. May be undefined if called from a non-tab context (for example, a background page or popup view).
可以看到,它只说无法在没有tab的context里得到,如background page和popup,正常人都会觉得它可以在content script里使用,但其实chrome.tabs API只能在background page和extension单独页面里使用,content script是不能使用chrome.tabs API的,所以getCurrent()是只能在textension单独页面里使用的。
那么如果想要打开了个未激活的tab时做一些操作browser icon的操作时,如果正确的获取脚本运行页面的tab id呢?如:右键链接在新Tab里打开,chrome会新开了一个tab打开页面,但这个tab并未激活(激活指点击tab,这这个tab处于浏览器的活动界面里)。
我在这里做两件事:
- 监听tab的激活事件,激活时往content script发消息
- content script接到消息检查自己的状态对象,如果OK给background发消息,通知它处理browser icon的变化。
chrome.tabs.onActivated.addListener(function(activeInfo) {
let tabId = activeInfo.tabId;
// 给对应tabId的content script发消息
});
问题:
当onActivated解法的时候,如果当前页面没有content script注入接受并返回response,就会报一个接受方法不存在的错误。如打开扩展管理界面。好在并不会有什么影响,扩展发布后,也不会有这个报错。
所以,其实最好是能在content script里使用chrome.tabs.getCurrent()API来处理这类事情。