在Chrome扩展中访问当前标签页的所有窗口变量

10

有人可以发布在Chrome扩展中访问window变量的代码吗? 当我点击Chrome扩展按钮时,我需要访问window变量。 我得到了window对象,但并没有加载所有变量。 我知道我们可以通过注入脚本来创建它。 但是我不知道如何实现。 目前,我正在尝试使用以下代码获取当前活动选项卡的页面源代码。

 chrome.tabs.executeScript({code:
            "document.getElementsByTagName('html')[0].innerHTML"
        }, function(result) {
    var value = result[0];
    console.log(value);
    chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
        callback({
            url: tabs[0].url,
            title: tabs[0].title,
            jsonValue: value
        });
    });
}); 
请帮我解决这个问题。非常感激。

现在使用这个脚本会得到什么?它何时被执行? - Emrys Myrooin
@EmrysMyrooin,我正在获取当前选项卡的页面源代码。但是我需要获取页面源代码中所有窗口变量,而不是这个。 - Srinivas B
那么为什么不直接返回 window 对象呢?像这样 chrome.tabs.executeScript({code: "window" }, function(result) { ... }) 我没有尝试过,但没有理由不起作用 :-) - Emrys Myrooin
好的,先不考虑这个问题。发送window变量没有简单的解决方案。原因是它包含循环引用,在JSON格式中无法表示。所以更好的解决方案是从window对象中提取所需的值,然后只发送这些提取的值。或者您可以尝试使用其他格式来表示数据,但是为此您必须注入外部库... - Emrys Myrooin
嗯,appData是什么?它不是window对象的属性。 - Emrys Myrooin
显示剩余6条评论
1个回答

20
您所询问的是如何注入脚本并获取在原始页面脚本中定义的变量的值。对于这个问题有两个答案:

1. Google官方答复

这是不可能的。注入到页面中的内容脚本被隔离,无法访问原始页面JavaScript作用域。这意味着你不能访问在原始页面JavaScript中定义的变量、函数和对象。而且你定义的变量、函数和对象也将无法从原始页面访问。

只有页面的DOM是共享的。这允许您修改页面的内容。但例如,您无法删除现有事件处理程序。

这是出于明显的安全和安全原因。如果你在不知情的情况下覆盖原始页面的某个函数,它会破坏它。

点击这里查看更多信息

2. 非官方和不正当的答案

有一种方法可以绕过Chrome沙盒限制。这是通过共享的DOM来实现的,它允许您在页面中添加<script src="..."><\script>。脚本将在原始页面的JavaScript VM中加载和执行,因此您将可以访问全局JavaScript作用域。

但是这种方法将无法访问Chrome扩展API,因为你是在原始页面中运行代码。所以与后台页或注入的内容脚本进行通信将变得困难。

一个常见的方法是向页面添加一个隐藏的<div>,并在其中放置您想要发送到内容脚本的结果。您将结果以文本形式存储(例如使用JSON.stringify),然后使用您的内容脚本读取结果。

这是非常不正当的,只有在最后尝试时才应该使用。


或在插件和主页面JavaScript之间来回发送消息,例如:https://dev59.com/5Wkw5IYBdhLWcg3w2-Mk#9636008 - rogerdpack
3
这个答案是错误的。根本不需要采用肮脏的解决方法。官方的 Google 方法支持 window.postMessage。请参见 https://developer.chrome.com/extensions/content_scripts#host-page-communication。 - Pacerier
2
@Pacerier 这个答案对于一个非常精确的问题是正确的。这个答案是为了回答“我能获取宿主页面的窗口属性吗?”而制作的。在他的情况下,他无法访问宿主页面的源代码。他不能修改宿主页面的主要JavaScript,因此他无法在主脚本和扩展之间进行任何通信(至少不使用肮脏的黑客技巧)。 - Emrys Myrooin
@EmrysMyrooin,你还没有明白... "dirty" 共享 DOM 不是唯一的方式;这就是我建议使用 window.postMessage 进行通信的原因。所以你可以取变量 x 并通过 window.postMessage(x, '*') 传递它,然后你注入的内容脚本将能够通过监听 window.addEventListener("message", (e) => console.log(e.data)) 来读取变量 x。不需要使用 DOM 骇客。你可以用同样的方法将数据从内容脚本传递到网页中。 - Pacerier
2
这些评论非常有用!我同意 @Pacerier 的观点,window.postMessage 是在这里做事情的正确方法,但插入脚本对我也非常有用。在我的情况下,我想记录到原始窗口的控制台,我通过按照 @Emrys 描述的方式将脚本插入页面来实现... 太棒了! - ptim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接