所以我正在创建一个嵌入 <webview>
的 Chrome 应用程序元素。嵌入式Web应用程序包含大量遗留代码,例如window.showModalDialog
调用(Chrome 不再支持)。
我现在想做的就是填充这些调用。我创建了一个简单的测试示例:
<webview src="http://legacyCodeIsAwesome.com/" style="width:100%; height:100%"></webview>
对webview元素进行操作的代码:
webview.addEventListener('contentload', function() {
webview.executeScript(
{
code: 'window.showModalDialog = function() { console.log ("Hello, world");}',
runAt: 'document_start'
}
);
});
上面的代码运行(添加调试console.log
有效),只是它没有做它应该做的事情,即覆盖showModalDialog
功能。
window
上的覆盖函数是否有某种限制? WebView 中的对象?有办法解决吗?
最佳答案
当您调用webview.executeScript
时,您实际上创建了一个 Content Script .
内容脚本的核心原则之一是 isolated world :内容脚本看到 window
的单独副本对象。
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts.
因此,您的覆盖有效,但仅限于内容脚本上下文。
内容脚本可以创建<script>
页面上的元素;所述元素中的代码将在页面上下文中执行。您可以阅读有关此技术的信息,称为页面级脚本或注入(inject)脚本,in this canonical question .
// Content script
var script = document.createElement('script');
script.textContent = `
window.showModalDialog = function() {
console.log("Hello, world");
}
`;
(document.head||document.documentElement).appendChild(script);
script.remove();
也就是说,您注入(inject)代码已经太晚了。上contentload
有问题的 JS 可能已经执行,并添加 "document_start"
时间不会倒带。
幸运的是,您可以declare in advance the content scripts you want to have :
webview.addContentScripts([
{
name: "showModalDialogPolyfill",
matches: ["https://webapp.example.com/*"],
js: { files: ['content.js'] },
run_at: 'document_start'
}
]);
webview.src = "https://webapp.example.com/";
关于javascript - 在 web View 中填充 window.showModalDialog,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38327257/