通信详细介绍

popup和background

popup可以直接调用background中的JS方法,也可以直接访问background的DOM:

  1. // background.js
  2. function test()
  3. {
  4. alert('我是background!');
  5. }
  6. // popup.js
  7. var bg = chrome.extension.getBackgroundPage();
  8. bg.test(); // 访问bg的函数
  9. alert(bg.document.body.innerHTML); // 访问bg的DOM

小插曲,今天碰到一个情况,发现popup无法获取background的任何方法,找了半天才发现是因为background的js报错了,而你如果不主动查看background的js的话,是看不到错误信息的,特此提醒。

至于background访问popup如下(前提是popup已经打开):

  1. var views = chrome.extension.getViews({type:'popup'});
  2. if(views.length > 0) {
  3. console.log(views[0].location.href);
  4. }

popup或者bg向content主动发送消息

background.js或者popup.js:

  1. function sendMessageToContentScript(message, callback)
  2. {
  3. chrome.tabs.query({active: true, currentWindow: true}, function(tabs)
  4. {
  5. chrome.tabs.sendMessage(tabs[0].id, message, function(response)
  6. {
  7. if(callback) callback(response);
  8. });
  9. });
  10. }
  11. sendMessageToContentScript({cmd:'test', value:'你好,我是popup!'}, function(response)
  12. {
  13. console.log('来自content的回复:'+response);
  14. });

content-script.js接收:

  1. chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
  2. {
  3. // console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");
  4. if(request.cmd == 'test') alert(request.value);
  5. sendResponse('我收到了你的消息!');
  6. });

双方通信直接发送的都是JSON对象,不是JSON字符串,所以无需解析,很方便(当然也可以直接发送字符串)。

网上有些老代码中用的是chrome.extension.onMessage,没有完全查清二者的区别(貌似是别名),但是建议统一使用chrome.runtime.onMessage

content-script主动发消息给后台

content-script.js:

  1. chrome.runtime.sendMessage({greeting: '你好,我是content-script呀,我主动发消息给后台!'}, function(response) {
  2. console.log('收到来自后台的回复:' + response);
  3. });

background.js 或者 popup.js:

  1. // 监听来自content-script的消息
  2. chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
  3. {
  4. console.log('收到来自content-script的消息:');
  5. console.log(request, sender, sendResponse);
  6. sendResponse('我是后台,我已收到你的消息:' + JSON.stringify(request));
  7. });

注意事项:

  • content_scripts向popup主动发消息的前提是popup必须打开!否则需要利用background作中转;
  • 如果background和popup同时监听,那么它们都可以同时收到消息,但是只有一个可以sendResponse,一个先发送了,那么另外一个再发送就无效;

injected script和content-script

content-script和页面内的脚本(injected-script自然也属于页面内的脚本)之间唯一共享的东西就是页面的DOM元素,有2种方法可以实现二者通讯:

  1. 可以通过window.postMessagewindow.addEventListener来实现二者消息通讯;
  2. 通过自定义DOM事件来实现;

第一种方法(推荐):

injected-script中:

  1. window.postMessage({"test": '你好!'}, '*');

content script中:

  1. window.addEventListener("message", function(e)
  2. {
  3. console.log(e.data);
  4. }, false);

第二种方法:

injected-script中:

  1. var customEvent = document.createEvent('Event');
  2. customEvent.initEvent('myCustomEvent', true, true);
  3. function fireCustomEvent(data) {
  4. hiddenDiv = document.getElementById('myCustomEventDiv');
  5. hiddenDiv.innerText = data
  6. hiddenDiv.dispatchEvent(customEvent);
  7. }
  8. fireCustomEvent('你好,我是普通JS!');

content-script.js中:

  1. var hiddenDiv = document.getElementById('myCustomEventDiv');
  2. if(!hiddenDiv) {
  3. hiddenDiv = document.createElement('div');
  4. hiddenDiv.style.display = 'none';
  5. document.body.appendChild(hiddenDiv);
  6. }
  7. hiddenDiv.addEventListener('myCustomEvent', function() {
  8. var eventData = document.getElementById('myCustomEventDiv').innerText;
  9. console.log('收到自定义事件消息:' + eventData);
  10. });

injected-script与popup通信

injected-script无法直接和popup通信,必须借助content-script作为中间人。

//TODO 示例代码有待完善。