使用chrome.tabs.executeScript(...)时,避免多次动态注入相同的脚本

时间:2014-04-22 00:11:00

标签: javascript google-chrome-extension

我正在构建Google Chrome扩展程序。基本设置是我有一个浏览器操作按钮,当点击它来执行它时,它会将jQuery和另一部分JavaScript注入活动选项卡。

这是我的第一个Chrome扩展程序,但似乎用户点击该按钮以便第二次重新注入脚本时执行操作。这是一个问题,因为它将使用的主要页面都是AJAX,因此页面内容会发生显着变化,但实际页面URL永远不会更改。

这是一个合理的问题,还是我在想它,是否有一种简单的方法可以阻止脚本多次注入同一页面?我应该将这些指定为内容脚本吗?

2 个答案:

答案 0 :(得分:3)

这绝对是一个合理的问题。

简单的方法是使用类似于#ifndef的机制,包括C中的警卫。

定义一个内容脚本执行后设置的标志,并在执行任何操作之前检查它是否已定义。从同一扩展注入的所有脚本共享JS执行上下文,因此共享全局范围。

您的内容脚本可能如下所示:

if(!window.contentScriptInjected){
    contentScriptInjected = true; // global scope

    /* Do your initialization and work */
}

/* global function definitions */

答案 1 :(得分:0)

我相信更好的方法可能是在扩展级别上进行。如果包含第三方库,那么您也将重新包含它们,并且永远不知道会发生什么。

contentScript.js

(function () {

  var Sz = Sizzle;

  //listen for events from the extension
  chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {

    if (!request._extension || request._extension !== 'my-extension-name') {
      console.log('Non extension request');
      return;
    }

    var channel = (request._channel) ? request._channel : false;

    if (channel === 'is-loaded') {

      sendResponse({isLoaded: true});
      return true;

    } else if (channel === 'example') {
      //do stuff 
    }

    return true;

  });

  //other code goes here

});

Background.js

var util = {};

util.sendMessage = function (data, cb) {

  chrome.tabs.query({active: true, currentWindow: true}, tabsQuery_cb);

  data['_extension'] = 'my-extension-name';

  function tabsQuery_cb(tabs) {

    var tab = tabs[0];

    console.log('sending message to ' + tab.id);
    console.log(data);

    //let the content script know to open the ad page
    chrome.tabs.sendMessage(tabs[0].id, data, cb);

  }

}

util.loadContentScript = function(cb) {

  var attempts = 0;


  checkIfLoaded();

   //checks if ContentScript is loaded by sending a message to the current
  function checkIfLoaded() {

    util.sendMessage({ _channel: 'is-loaded'}, sendMessage_cb);

  }

  function sendMessage_cb(response) {

    console.log('isLoadedCheck')
    console.log(response);

    if (response && response.isLoaded === true) {
      console.log('Script already loaded!');
      cb(true);
    } else {
      console.log('loading scripts');
      loadScripts();
    }

  }

  function loadScripts() {

    attempts++;
    console.log('loadScripts, attempt no. ' + attempts);

    if (attempts > 1) {
      console.log('Script couldnt be loaded');
      return cb(false);
    }

    var scripts = [
      "assets/sizzle-2.3.4.min.js",
      "app/contentScript.js"
    ];

    var i = -1;

    scriptLoaded();

    function scriptLoaded() {

      i++;

      if (i > scripts.length) {
        //all scripts have loaded at this point, check if replies with message
        checkIfLoaded();
      } else {
        console.log('Loading script ' + scripts[i]);
        chrome.tabs.executeScript(null, { file: scripts[i] }, scriptLoaded);
      }


    }

  }

}

当然,包括第三方库似乎仍然是一种不好的做法,因为它可能会与网站的脚本产生偏差。但是还有其他方法。也许您可以走极端,创建一个引导内容脚本,该脚本将检查库的存在并告诉扩展脚本确切地需要包含哪些内容。这就是我要考虑的更严肃的项目。