webview中的polyfill window.showModalDialog

时间:2016-07-12 11:13:06

标签: javascript webview modal-dialog google-chrome-app legacy-code

所以我正在创建一个嵌入了<webview>元素的Chrome应用。嵌入式网络应用程序包含许多遗留代码,例如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函数。

对于覆盖webviews中window对象的函数有什么限制吗?有办法吗?

1 个答案:

答案 0 :(得分:2)

当您致电webview.executeScript时,您基本上会创建一个Content Script

内容脚本的核心原则之一是isolated world:内容脚本会看到window对象的单独副本。

  

内容脚本在称为孤立世界的特殊环境中执行。他们可以访问注入页面的DOM,但不能访问页面创建的任何JavaScript变量或函数。它将每个内容脚本视为在其运行的页面上没有执行其他JavaScript。反过来也是如此:页面上运行的JavaScript无法调用任何函数或访问内容脚本定义的任何变量。

因此,您的覆盖有效,但仅限于内容脚本上下文。

要在页面上下文中执行覆盖,我们需要更深入We need to go deeper

内容脚本可以在页面上创建<script>元素;所述元素中的代码将在页面的上下文中执行。您可以阅读有关此技术的信息,称为页面级脚本或注入脚本,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();

那就是说,你太晚注射你的代码了。在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/";