插件文件安装地址
/Users/xxx/Library/Application Support/Google/Chrome/Default/Extensions
Refused to evaluate a string as JavaScript because ‘unsafe-eval’ is not an allowed source of script in the following Content Security Policy directive: “script-src ‘self’ blob: filesystem:”
“content_security_policy”: “script-src ‘self’ ‘unsafe-eval’; object-src ‘self’;”,
目录:
- Tabs 相关
- storage 数据储存获取与 onMessage 通信相关
- 语言本地化
- 消息传递 & 跨扩展程序消息传递
- 读取页面内全局变量 & content_scripts & web_accessible_resources
- 遗留问题
- 其他重要备忘
Tabs 相关
chrome.tabs.getSelected(null, tab => {// ...});chrome.tabs.getCurrent(tab => {// ...});
可以通过上面这两种方式获取当前 Tab 标签页,得到其 id、url 等属性,之后可以进行多种操作,例如往该标签页执行特定 js 文件,如下:
chrome.tabs.executeScript(tab.id, {file: 'logic.js'});
document.addEventListener('visibilitychange', () => {if (document.visibilityState === 'visible') {// 当 Tab 可见 do something} else {// 当 Tab 不可见 do something}
storage 数据储存获取与 onMessage 通信相关
Unchecked runtime.lastError while running storage.set: QUOTA_BYTES_PER_ITEM quota exceeded
This error comes when you use chrome.storage.sync.set…
to set the data greater than 8,192 bytes for a single item as chrome.storage.sync.set allows 8,192 QUOTA_BYTES_PER_ITEM.
按说应该只在 background 的初始化中创建特定对象,并通过 storage 存储
// 创建与存储let testObj = {0: false,1: false,2: false,3: false,4: false,5: false};chrome.storage.local.set({ testObj: testObj });
之后在其他页面中只需要通过 storage 获取需要的数据对象,可以是直接修改后重新存入,也可以通过 sendMessage 向 background 传递 payload,统一在 background 进行数据的处理存储
// 在 background 中注册 onMessage 事件chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {if (request.to === 'background') {switch(request.msg) {case 'toggleItem':chrome.storage.local.get(['testObj'], r => {testObj = r.testObj;testObj[request.payload.id] = request.payload.flag;chrome.storage.local.set({testObj: testObj});});break;// ...}}});// 这里补充事件发送sth.addEventListener('click', (e) => {// ...chrome.runtime.sendMessage({to: 'background',msg: 'toggleItem',payload: {id: tmpId,flag: tmpFlag}});});
此外,其他特定页面为了保持数据一致,可设置事件 onChanged 监听 storage,一旦特定对象有修改,可进行相应的同步操作
chrome.storage.onChanged.addListener(function(changes, namespace) {for (var key in changes) {var storageChange = changes[key];console.log('Storage key "%s" in namespace "%s" changed. ' +'Old value was "%s", new value is "%s".',key,namespace,storageChange.oldValue,storageChange.newValue);console.log('storageChange.oldValue: ', storageChange.oldValue);console.log('storageChange.newValue: ', storageChange.newValue);if (key === 'testObj') {renderBox(storageChange.newValue);}}});
语言本地化
其中一种方式,可以自建对象集合,以 window.navigator.language 为依据来选用具体对象
var msg = {en: {noPinDomain: "Sorry, pinning is not allowed from this domain. Please contact the site operator if you have any questions.",noPinMeta: "Sorry, pinning is not allowed from this page. Please contact the site operator if you have any questions.",noPinnablesFound: "Sorry, couldn't find any pinnable things on this page."},zh: {noPinDomain: "抱歉,不允许从此域收藏 Pin 图。如有疑虑请联系网站运营商。",noPinMeta: "抱歉,不允许从此域收藏 Pin 图。如有疑虑请联系网站运营商。",noPinnablesFound: "抱歉,未在此页面中找到可收藏的 Pin 图。"},// ...};var local = stringsHandleFunc(window.navigator.language);var theObjWeNeed = msg[local];// ...
消息传递 & 跨扩展程序消息传递
page 中 content、logic 只能向 bg 发送消息
关键词 onMessageExternal、onConnectExternal,以及 manifest 中的 “externally_connectable”
读取页面内全局变量 & content_scripts & web_accessible_resources
回忆以下内容
编译文件 直接在项目 html 模板注入 & 通过插件 content_scripts 形式注入
前者可以读到 window 下 xxx 对象,后者不行
“dist/dll/reactForPinit.dll.js”,
“dist/js/pinit.min.js”
通过 content_scripts 注入的内容应该是执行在一个独立、特殊的(虚拟?)环境
和网页本身的 window 不共享
所以当需要’读取页面内全局变量’时,建议通过如下方式注入 css、script
function loadCSS(url) {var head = document.getElementsByTagName('head')[0];var link = document.createElement('link');link.type = 'text/css';link.rel = 'stylesheet';url = chrome.extension.getURL(url);console.log('loadCSS: ', url);link.href = url;head.appendChild(link);}function loadScript(url) {var tail = document.body;var script = document.createElement('script');script.type = 'text/javascript';url = chrome.extension.getURL(url);console.log('loadScript: ', url);script.src = url;tail.appendChild(script);}loadCSS(cssArr[0]);loadScript(jsArr[0]);
此外,从以上内容出发,可以扩展到’本地 js 调试线上页面’,如利用 sources 下 overrides、文件代理替换等方式
遗留问题
- 按说一般网页不可调用 chrome 的一些 api,但是在已授权权限情况下,content.js 可以调用 chrome.storage.local.get,而又不可调用 chrome.tabs,之后不妨了解下还有哪些可调用的
关于通信后 debug 调试
比方从 background 向 logic.js sendMessage 之后,因为代码是在闭包内,如果有错误代码中断了,控制台看不到,很要命,目前完全不知道怎么办
其他重要备忘
关于 web_accessible_resources,浏览器对插件内资源授权访问
比如要在页面内添加 iframe,src 为插件内 /html/create.html、/html/grid.html,则需要在 manifest.json 中添加如下:
"web_accessible_resources": [ "/html/create.html", "/html/grid.html" ]
How to inject CSS using content script file in Chrome extension?
通信过程中值传递需要注意
比方在 logic.js 将 document.images 通过 background 中转到 grid 所在 iframe,纠结纳闷了好一会,为什么得到的数据是个空对象 {} 的数组?
其实是环境变了,原本值本是个指向当前文档特定 DOM 的指针。
