web_accessible_resources 无法访问 chrome.tabs.executeScript

web_accessible_resources can't access chrome.tabs.executeScript

我正在开发一个扩展,它使用 chrome.tabs.executeScript 从一个文件中加载 requirejs 的实例放置在闭包中以防止它污染全局 space。我们称这个闭包为 __MyGlobal。这按预期执行。

然后我在同一选项卡中使用 chrome.tabs.executeScript 到 运行 代码。此代码是基本的 __MyGlobal.require([dependencies],function(){}) 调用。这按预期执行。

正是 Require 调用的依赖项在其 __MyGlobal.declare() 调用中失败。

错误是Uncaught ReferenceError: __MyGlobal is not defined.


进一步测试如果我在控制台中输入 __MyGlobal 它未定义。 如果我将域更改为我的扩展名,那么控制台会按预期显示 __MyGlobal。

我不确定

简而言之

  1. chrome.tabs.executeScript 加载 require.js
  2. chrome.tabs.executeScript 加载具有依赖关系的 require() 语句
  3. require() 文件依赖加载(它们在 web_accessible_resources 中声明)
  4. require() 依赖项有它们自己的依赖项(定义语句)
  5. define 语句无法访问 requirejs

如何让代码加载 chrome.tabs.executeScript 并加载为 web_accessible_resources 以便一起玩?他们在不同的领域吗?谢谢!

chrome.tabs.executeScript 注入的脚本是 "Content Scripts",这意味着它们在自己的 javascript 环境中执行,不同于网站的环境。他们与网站进行互动 DOM。

requirejs 通过创建脚本标签来加载依赖项。因此,requirejs 加载的脚本被加载到页面的 javascript 环境中,而不是扩展程序的 javascript 环境中。

您可以阅读有关 chrome 扩展环境分离方式的更多信息 here. Programmatic-Injection and Execution-Environment 如果您为 chrome 做的不仅仅是最基本的开发,那么这两本书都值得一读。

下面的示例,归功于 wOxxOm (source here),可以添加到 require.js 文件的底部,以便在 requirejs 为 运行 时通过 ajax 加载 requirejs ] 在它自己的 javascript 环境中作为内容脚本。

var legacyLoad = requirejs.load;
requirejs.load = function(context, moduleName, url){
    if(location.protocol === 'chrome-extension:'){//works for extension pages
        legacyLoad(context, moduleName, url);        
    }
    else {//works for content scripts
        var x = new XMLHttpRequest();
        x.open('GET', url);
        x.onload = function() {
            if (x.status === 200) {
                // Run script in the current global context.
                try {
                    window.eval(x.responseText);
                } 
                finally {
                    context.completeLoad(moduleName);
                }
            } 
            else context.onScriptError(new Event('error'));

        };
        x.onerror = function() {
            ontext.onScriptError(new Event('error'));
        };
        x.send();
    }
}