Preserve toggle between different tabs

时间:2019-04-08 13:31:37

标签: javascript google-chrome-extension

I'm working on a Google Chrome Extension that you're supposed to be able to turn on and off using the symbol in the extension toolbar. This toggle should be universal, meaning that no matter where you turn it on or off, the current state is preserved everywhere. Doesn't matter in what tab or window you were, the status is shared everywhere.

Let's just say for our example, it's supposed to write "I'm on!" in the console when it's turned on and you press the A key. If it's turned off and you press A, it will say "I'm off!".

manifest.json:

{
  "name": "Test Extension",
  "version": "1.0",
  "manifest_version": 2,
  "description": "Just a test for Stack Overflow.",
  "browser_action": {
    "default_icon": "images/icon.png"
  },
  "background": {
    "scripts": ["background.js"]
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
}

background.js:

var extensionMode = true;

chrome.browserAction.onClicked.addListener(function(tab) {

  extensionMode = !extensionMode;

  if(extensionMode) {
    chrome.browserAction.setIcon({
      path : "images/icon.png"
    });
  } else {
    chrome.browserAction.setIcon({
      path : "images/icon_disabled.png"
    });
  }

  let msg = {
    extensionMode: extensionMode
  }

  chrome.tabs.sendMessage(tab.id, msg);
});

content.js:

var extensionMode = true;

chrome.runtime.onMessage.addListener(gotMessage);

function gotMessage(message, sender, sendResponse) {
  extensionMode = message.extensionMode;
}

onkeydown = onkeyup = function(e){
  if(extensionMode) {
    if(event.keyCode == 65) { // A
        console.log("I'm on!");
    }
  } else {
    if(event.keyCode == 65) { // A
        console.log("I'm off!");
    }
  }
}

The above code works when you stay in the tab you are, but not when you switch... the icon will stay disabled, but extensionMode actually reverses back to true.

What am I doing wrong here? Is this the wrong approach for what I'm trying to do?

1 个答案:

答案 0 :(得分:0)

chrome.tabs.sendMessage targets just one tab so you would need to get a list of all tabs using chrome.tabs.query and send the message to each one:

const ignoreRuntimeError = () => chrome.runtime.lastError;
chrome.tabs.query({}, tabs => {
  tabs.forEach(tab => chrome.tabs.sendMessage(tab.id, msg, ignoreRuntimeError));
});

You would also need to query the state in content scripts on tabs navigated/opened later:

chrome.runtime.sendMessage('getState', state => extensionMode = state);

For which the background script should have a listener:

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg === 'getState') {
    sendResponse(extensionMode);
  }
});

A more efficient approach for you to consider:

  • use a nonpersistent event page and store the state in chrome.storage.local
  • run the content scripts only when enabled using chrome.tabs.executeScript and register/unregister the DOM listeners when toggled