插件文件安装地址
/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 的指针。