问题在于,默认情况下,Webview 不会让客户端打开任意窗口。相反,它会发出一个 'newwindow' 事件,你可以拦截并决定如何处理它。以较简单的形式表述,代码如下:
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();
chrome.app.window.create(e.targetUrl, ...);
});
};
}
);
});
根据你描述的条件,我认为这应该适用于你。
在更糟糕的情况下,某些网站可能会像这样打开新窗口/标签页:
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();
}
如果一个网站被包裹在webview中,那么一切都变得更加困难:上面的'newwindow'处理程序中的e.targetUrl将包含"about:blank",所以如果不进行修改,代码将打开一个空白窗口/选项卡。为了拦截来自客户端的后续重定向,应用程序还必须使用
chrome.webRequest API(文档似乎仅适用于扩展,但该API已经在稳定通道中提供给打包的应用程序使用)。
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') {
newWindow_openInTab(e.targetUrl);
} else {
newWindow_openInTabAndInterceptRedirect(e.window);
});
};
}
);
});
function newWindow_openInTab(url) {
chrome.app.window.create(url, ...);
}
function newWindow_openInTabAndInterceptRedirect(newWindow) {
var proxyWebview = document.createElement('webview');
document.body.appendChild(proxyWebview);
var onBeforeRequestListener = function(e) {
if (e.type === "main_frame" && e.url !== 'about:blank') {
chrome.app.window.create(e.url, ...);
document.body.removeChild(proxyWebview);
return { cancel: true };
} else {
return { cancel: false };
}
};
proxyWebview.onBeforeRequest.addListener(
onBeforeRequestListener,
{ urls: [ "*://*/*" ] },
[ 'blocking' ]
);
newWindow.attach(proxyWebview);
}
window.open(e.targetUrl);
就可以了。 - Mike Bartlett