如何从Chrome打包的应用程序中的Web视图中的链接打开新窗口 [英] How to open a new window from a link in a webview in a chrome-packaged app

查看:108
本文介绍了如何从Chrome打包的应用程序中的Web视图中的链接打开新窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了展示来自横幅广告的广告,我正在加载一个包含链接到广告服务器的iframe的网络视图.通过一些JavaScript,我可以将广告链接目标设置为"_blank",这样广告将在单独的浏览器窗口中打开,否则将在相同的小型Web视图中打开.

In order to show ads from a banner exchange, I'm loading a webview containing an iframe linking to the ads server. Through some javascript I can have the ad link target to be "_blank" so the ad would open in a separate browser window, otherwise it would open in the same small webview.

但是它不起作用,我可以在控制台中找到它:

However it doesn't work and I get this in the console:

<webview>: A new window was blocked.

任何想法如何做到这一点?

Any ideas how to do this?

推荐答案

问题是,默认情况下,Web视图不会允许访客打开任意窗口.相反,它将发出"newwindow"事件,您可以拦截该事件并决定如何处理它.不太可怕的形式是:

The thing is that by default a webview will not let the guest open arbitrary windows. Instead, it will issue a 'newwindow' event, which you can intercept and decide what to do with it. In a less scary form, this will look something like:

chrome.app.runtime.onLaunched.addListener(function() {
  chrome.app.window.create(
    'main.html',
    { 'width': 1000, 'height': 1000 },
    function(win) {
      win.contentWindow.onload = function() {
        var webview = win.contentWindow.document.querySelector('#my_webview');
        webview.addEventListener('newwindow', function(e) {
          e.preventDefault();
          // e.targetUrl contains the target URL of the original link click
          // or window.open() call: use it to open your own window to it.
          // Something to keep in mind: window.open() called from the
          // app's event page is currently (Nov 2013) handicapped and buggy
          // (e.g. it doesn't have access to local storage, including cookie
          // store). You can try to use it here and below, but be prepare that
          // it may sometimes produce bad results.
          chrome.app.window.create(e.targetUrl, ...);
        });
      };
    }
  );
});

鉴于您所描述的条件,我认为这应该对您有用.

I think this should work for you, given the conditions that you've described.

在更糟的情况下,某些网站可能会像这样打开新的窗口/标签:

In a worse situation, certain websites may be opening new windows/tabs like this:

function open(href) {
    var w = window.open('', '_blank');
    w.opener = null;
    w.document.write(
      '<META HTTP-EQUIV="refresh" content="0; url=' + href + '">');
    w.document.close();
}

如果将这样的网站包装在Web视图中,则一切都会变得更加困难:上面"newwindow"处理程序中的e.targetUrl将包含"about:blank",因此如果不进行修改,代码将打开一个空白窗口/选项卡.要拦截来自访客的后续重定向,该应用还必须使用 chrome.webRequest API (该文档似乎仅适用于扩展程序,但该API也已在稳定渠道中用于打包的应用程序):

If such a website is wrapped in a webview, everything becomes more difficult: e.targetUrl in the 'newwindow' handler above will contain "about:blank", so without modification the code will open a blank window/tab. To intercept the subsequent redirect from the guest, the app will also have to use the chrome.webRequest API (the documentation appears to be for extensions only, but the API is already available for packaged apps in the stable channel, too):

chrome.app.runtime.onLaunched.addListener(function() {
  chrome.app.window.create(
    'main.html',
    { 'width': 2000, 'height': 1000 },
    function(win) {
      win.contentWindow.onload = function() {
        var webview = win.contentWindow.document.querySelector('#webview');
        webview.addEventListener('newwindow', function(e) {
          e.preventDefault();
          if (e.targetUrl !== 'about:blank') {
            // Easy case where the original link or window.open()
            // already contains a target URL.
            newWindow_openInTab(e.targetUrl);
          } else {
            // Harder case where the guest first opens a blank
            // window and then redirects it via a
            // 'META HTTP-EQUIV="refresh"'.
            newWindow_openInTabAndInterceptRedirect(e.window);
        });
      };
    }
  );
});

function newWindow_openInTab(url) {
  chrome.app.window.create(url, ...);
}

function newWindow_openInTabAndInterceptRedirect(newWindow) {
  // Create an invisible proxy webview to listen to redirect
  // requests from |newWindow| (the window that the guest is
  // trying to open). NOTE: The proxy webview currently has to
  // live somewhere in the DOM, so we append it to the body.
  // This requirement is in the process of being eliminated.
  var proxyWebview = document.createElement('webview');
  document.body.appendChild(proxyWebview);

  // Listen to onBeforeRequest event (chrome.webRequest API)
  // on proxyWebview in order to intercept newWindow's redirects.
  var onBeforeRequestListener = function(e) {
    // Only consider top-level non-blank redirects.
    if (e.type === "main_frame" && e.url !== 'about:blank') {
      chrome.app.window.create(e.url, ...);
      // Don't need proxyWebview anymore.
      document.body.removeChild(proxyWebview);
      // Handled this redirect: cancel further processing.
      return { cancel: true };
    } else {
      // Ignored this redirect: proceed with default processing.
      return { cancel: false };
    }
  };
  proxyWebview.onBeforeRequest.addListener(
    onBeforeRequestListener,
    { urls: [ "*://*/*" ] },
    [ 'blocking' ]
  );

  // Attach |newWindow| to proxyWebview. From the original
  // webview guest's point of view, the window is now opened
  // and ready to be redirected: when it does so, the redirect
  // will be intercepted by |onBeforeRequestListener|.
  newWindow.attach(proxyWebview);
}

这篇关于如何从Chrome打包的应用程序中的Web视图中的链接打开新窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆