2013-08-25 10 views
5

Per visualizzare gli annunci da uno scambio banner, sto caricando una webview contenente un iframe che collega al server degli annunci. Attraverso alcuni javascript posso avere il target del link dell'annuncio come "_blank" in modo che l'annuncio si apra in una finestra separata del browser, altrimenti si aprirà nella stessa piccola webview.Come aprire una nuova finestra da un collegamento in una webview in un'app cromato

Tuttavia non funziona e ottengo questo nella console:

<webview>: A new window was blocked. 

Delle idee come fare questo?

risposta

12

Il fatto è che per impostazione predefinita una vista Web non consente all'ospite di aprire finestre arbitrarie. Invece, emetterà un evento 'newwindow', che puoi intercettare e decidere cosa fare con esso. In una forma meno spaventoso, questo avrà un aspetto simile:

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, ...); 
     }); 
     }; 
    } 
); 
}); 

Penso che questo dovrebbe funzionare per voi, date le condizioni che hai descritto.

in una situazione peggiore, alcuni siti web può essere l'apertura di nuove finestre/tabs in questo modo:

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(); 
} 

Se tale sito web è avvolto in una WebView, tutto diventa più difficile: e.targetUrl nel 'NewWindow il precedente comando conterrà "about: blank", quindi senza modifiche il codice aprirà una finestra/scheda vuota. Per intercettare il successivo reindirizzamento da parte del cliente, l'applicazione avrà anche di utilizzare la chrome.webRequest API (la documentazione sembra essere solo per le estensioni, ma l'API è già disponibile per le applicazioni pacchettizzate nel canale stabile, anche):

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); 
} 
+0

Non ho parlato dell'evento newwindow, grazie. Anche il secondo metodo è un bel trucco. –

+0

Non intendevo il secondo metodo come soluzione al problema originale. Volevo dire che alcuni siti Web, ad esempio Gmail, a volte utilizzano questa tecnica per aprire nuove schede e indirizzarle all'URL di destinazione. Aggiornerò la mia risposta per renderla più chiara e aggiungerò anche una soluzione per questo caso più difficile. –

+0

Mi è appena venuto in mente che tutto quello che stavo dicendo si basava sul presupposto che hai a che fare con i link target = '_ blank', quando in realtà tu stesso chi aggiunge target = '_ blank' ai link. In tal caso, il problema può essere risolto solo con l'API webRequest utilizzata direttamente sulla tua webview (dato che viene utilizzata per la proxy webview nel secondo esempio), quindi nessuna visualizzazione web proxy o ascolto della 'nuova finestra' è necessaria. Spero possa aiutare. –

Problemi correlati