内容脚本中的页面变量

esq*_*qew 30 javascript google-chrome google-chrome-extension

有没有办法从谷歌Chrome内容脚本中检索页面的javascript变量?

npd*_*oty 63

如果你真的需要,你可以<script>在页面的DOM中插入一个元素; <script>将执行元素内的代码,并且该代码可以访问窗口范围内的JavaScript变量.然后,您可以使用data-属性和触发自定义事件将它们传回内容脚本.

听起来很尴尬?为什么是,它是,并且故意是因为serg引用的文档中的所有原因.但如果你真的真的需要这样做,那就可以做到.有关详细信息,请参阅此处此处.还有祝你好运!

  • 哇,这真的很有效,谢谢! (3认同)

Lir*_*mer 20

我创建了一个小帮手方法,玩得开心:)

检索窗口的变量"lannister","always","pays","his","debts",执行以下命令:

var windowVariables = retrieveWindowVariables(["lannister", "always", "pays", "his", "debts"]);
console.log(windowVariables.lannister);
console.log(windowVariables.always);
Run Code Online (Sandbox Code Playgroud)

我的代码:

function retrieveWindowVariables(variables) {
    var ret = {};

    var scriptContent = "";
    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        scriptContent += "if (typeof " + currVariable + " !== 'undefined') $('body').attr('tmp_" + currVariable + "', " + currVariable + ");\n"
    }

    var script = document.createElement('script');
    script.id = 'tmpScript';
    script.appendChild(document.createTextNode(scriptContent));
    (document.body || document.head || document.documentElement).appendChild(script);

    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        ret[currVariable] = $("body").attr("tmp_" + currVariable);
        $("body").removeAttr("tmp_" + currVariable);
    }

    $("#tmpScript").remove();

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

请注意我使用jQuery ..您可以轻松地使用本机js "removeAttribute""removeChild".

  • 很棒,但这不适用于对象,查看更正版本,滚动底部由用户"Taras"发布 (3认同)

小智 14

使用Liran的解决方案,我正在添加一些修复Objects,这是正确的解决方案:

function retrieveWindowVariables(variables) {
    var ret = {};

    var scriptContent = "";
    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        scriptContent += "if (typeof " + currVariable + " !== 'undefined') $('body').attr('tmp_" + currVariable + "', JSON.stringify(" + currVariable + "));\n"
    }

    var script = document.createElement('script');
    script.id = 'tmpScript';
    script.appendChild(document.createTextNode(scriptContent));
    (document.body || document.head || document.documentElement).appendChild(script);

    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        ret[currVariable] = $.parseJSON($("body").attr("tmp_" + currVariable));
        $("body").removeAttr("tmp_" + currVariable);
    }

     $("#tmpScript").remove();

    return ret;
}
Run Code Online (Sandbox Code Playgroud)


CTS*_*_AE 7

Chrome 的文档为您提供了一个很好的起点:https : //developer.chrome.com/extensions/content_scripts#host-page-communication

此方法允许您将全局页面变量提取到内容脚本中。它还使用一个想法来只接受您在握手时识别的传入消息。你也可以只Math.random()用于握手,但我玩得很开心。

解释

  1. 此方法创建一个脚本标记
  2. 它将函数字符串化propagateVariable并将当前的 handShake 和目标变量名称传递到字符串中以进行保存,因为函数将无法访问我们的内容脚本范围。
  3. 然后它将该脚本标记注入页面。
  4. 然后我们在我们的内容脚本中创建一个监听器,等待从页面返回我们所追求的变量。
  5. 到目前为止,注入的脚本已经命中页面。
  6. 注入的代码包含在IIFE 中,因此它会自行运行,将数据推送到侦听器。
  7. 可选:监听器确保它有正确的握手,瞧,我们可以信任数据的来源(它实际上并不安全,但在这种情况下它有助于创建一个标识符,这给了我们一定程度的信任)。

第1轮

v1.0

const globalToExtract = 'someVariableName';
const array = new Uint32Array(5);
const handShake = window.crypto.getRandomValues(array).toString();

function propagateVariable(handShake, variableName) {
  const message = { handShake };
  message[variableName] = window[variableName];
  window.postMessage(message, "*");
}

(function injectPropagator() {
  const script = `( ${propagateVariable.toString()} )('${handShake}', '${globalToExtract}');`
  const scriptTag = document.createElement('script');
  const scriptBody = document.createTextNode(script);
  
  scriptTag.id = 'chromeExtensionDataPropagator';
  scriptTag.appendChild(scriptBody);
  document.body.append(scriptTag);
})();

window.addEventListener("message", function({data}) {
  console.log("INCOMINGGGG!", data);
  // We only accept messages from ourselves
  if (data.handShake != handShake) return;

  console.log("Content script received: ", data);
}, false);
Run Code Online (Sandbox Code Playgroud)

v1.1 承诺!

function extractGlobal(variableName) {

  const array = new Uint32Array(5);
  const handShake = window.crypto.getRandomValues(array).toString();

  function propagateVariable(handShake, variableName) {
    const message = { handShake };
    message[variableName] = window[variableName];
    window.postMessage(message, "*");
  }

  (function injectPropagator() {
    const script = `( ${propagateVariable.toString()} )('${handShake}', '${variableName}');`
    const scriptTag = document.createElement('script');
    const scriptBody = document.createTextNode(script);

    scriptTag.id = 'chromeExtensionDataPropagator';
    scriptTag.appendChild(scriptBody);
    document.body.append(scriptTag);
  })();

  return new Promise(resolve => {
    window.addEventListener("message", function({data}) {
      // We only accept messages from ourselves
      if (data.handShake != handShake) return;
      resolve(data);
    }, false);
  });
}

extractGlobal('someVariableName').then(data => {
  // Do Work Here
});
Run Code Online (Sandbox Code Playgroud)

第 2 轮 - 课堂和承诺

v2.0

如果使用 es 模块,我建议将类放入自己的文件中并将其导出为默认值。然后它就变成了:

ExtractPageVariable('someGlobalPageVariable').data.then(pageVar => {
  // Do work here 
});
Run Code Online (Sandbox Code Playgroud)

ExtractPageVariable('someGlobalPageVariable').data.then(pageVar => {
  // Do work here 
});
Run Code Online (Sandbox Code Playgroud)


SHa*_*mel 5

正如其他答案中部分解释的那样,页面中的 JS 变量与 Chrome 扩展内容脚本隔离。通常,没有办法访问它们。

但是,如果您在页面中注入 JavaScript 标记,您将可以访问那里定义的任何变量。

我使用实用程序函数将脚本注入页面中:

/**
 * inject - Inject some javascript in order to expose JS variables to our content JavaScript
 * @param {string} source - the JS source code to execute
 * Example: inject('(' + myFunction.toString() + ')()');
 */
function inject(source) {
  const j = document.createElement('script'),
    f = document.getElementsByTagName('script')[0];
  j.textContent = source;
  f.parentNode.insertBefore(j, f);
  f.parentNode.removeChild(j);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

function getJSvar(whichVar) {
   document.body.setAttribute('data-'+whichVar,whichVar);
}
inject('(' + getJSvar.toString() + ')("somePageVariable")');

var pageVar = document.body.getAttribute('data-somePageVariable');
Run Code Online (Sandbox Code Playgroud)

请注意,如果变量是复杂的数据类型(对象、数组...),则需要将值作为 JSON 字符串存储在 getJSvar() 中,并通过 JSON.parse 将其返回到内容脚本中。