7

我正在尋找一種方式來顯示使用WebExtensions一些網站一個孤立的覆蓋。
一個IFRAME似乎喜歡的方式去爲這個,因爲它提供了CSS,JS和DOM整體單獨範圍。另一個好消息是目標網站將無法讀取或更改內容。火狐WebExtension,孤立的HTML覆蓋

在Chrome擴展,似乎沒有任何問題是可能的,但WebExtensions在Firefox中,即使它們共享相同的語法,我收到安全警告/錯誤,這是行不通的。

我試過兩個不同的東西:

  • 創建一個iframe沒有src屬性,並注入到該網站的身體。 這種方法失敗了,因爲我得到CSP錯誤/警告,當我做iframe.contentWindow.document.open()
    相關內容腳本代碼:

    let html = ` 
        <!DOCTYPE html> 
        <html> 
         <head></head> 
         <body> 
         <h1>TEST</h1> 
         </body> 
        </html> 
    ` 
    let iframe = document.createElement('iframe') 
    document.body.appendChild(iframe) 
    iframe.contentWindow.document.open() 
    iframe.contentWindow.document.write(html) 
    iframe.contentWindow.document.close() 
    
  • 我想(這將使方式更有意義,因爲它會從訪問內容禁止的網站)的另一件事,是把我的iframe的代碼到一個文件中( overlay.html)在我WebExtension,使IFRAME通過設置它的SRC到browser.extension.getURL('overlay.html')加載它。
    相關內容腳本代碼:

    let iframe = document.createElement('iframe') 
    iframe.src = browser.extension.getURL('overlay.html') 
    document.body.appendChild(iframe) 
    

    在清單中,我定義的overlay.html爲web_accessible_resources此:

    "web_accessible_resources": [ 
        "overlay.html" 
    ], 
    

    有關的事情是,在iframe根本不加載overlay.html文件。但它絕對可用,否則location.href = browser.extension.getURL('overlay.html')將無法​​正常工作。如果這樣做能夠工作,這將非常方便,因爲我可以將整個疊加層(html,css,js)作爲單獨的文件存儲在我的擴展中。就好像它將是一個獨立的網站。使用內容腳本我可以訪問它來添加新的數據或其他內容。

編輯:

目前,我用我的iframe來設置源代碼,它應該包含(感謝wOxxOm爲)的srcdoc屬性。所以至少我現在有一些工作。但是我真的不喜歡這種方法,我無法與我的內容腳本中的iframe內容交互。有趣的是,我可以在iframe的js代碼中與父頁面進行交互,但又不能與內容腳本進行交互。這也很麻煩,不方便,很難保持把所有的html,css,js代碼放到一個字符串中,而不是像普通網站那樣的多個文件。

+2

也許你已經嘗試定義一個非常嚴格的CSP的網站?我會嘗試'iframe.srcdoc'。至於風格隔離,你可以使用Shadow DOM而不是iframe。 – wOxxOm

+0

非常感謝您的幫助! – Forivin

+0

1)關於CSP問題:我不認爲它是網站。它在'file:/// C:/'上給我同樣的錯誤。我認爲這與擴展自己的CSP有關。我仍然不熟悉語法,所以不能提供解決方案。如果不能完全理解您可能無意中允許的其他內容,請謹慎地鑽孔。 2)我創建,然後立即附加iframe。直接賦值對於所有屬性不起作用,儘管'iframe.src'確實對我有用。嘗試用iframe.setAttribute(attribute,value)指定ALL屬性;'具體來說,我認爲'class'是有問題的。 – user314159

回答

3

的問題

首先,我們知道問題是安全問題,究竟是什麼問題?那麼當試圖通過設置iframe來擴展資源加載到一個IFRAME SRC瀏覽器抱怨安全和防止IFRAME從連接在不同的協議,在這種情況下「MOZ擴展://」。

負載從擴展上下文的HTML等和注入爲字符串。

細節問題

爲了解決這個問題,我們可以iframe的src屬性設置爲data:text/html;charset=utf8,${markup}

這直接告訴iframe內容是html,它使用utf8編碼,後面跟着原始標記。我們完全繞過了通過網絡加載任何資源的iframe需求。

Firefox內容腳本的執行上下文與它所加載的頁面是分離的。這意味着您可以在不違反CSP的情況下提出xhr請求。

如果您對標記進行xhr請求,則可以將響應的內容作爲字符串獲取,並直接將其注入到iframe src屬性中。

這樣的內容腳本:

function loaded (evt) { 
    if (this.readyState === 4 && this.status === 200) { 
     var html = this.responseText; 
     console.log(html); 
     var iframe = document.createElement('iframe'); 

     iframe.src = 'data:text/html;charset=utf-8,' + html; 
     document.body.appendChild(iframe); 

     console.log('iframe.contentWindow =', iframe.contentWindow); 
    } else { 
     console.log('problem loading'); 
    } 
} 

var xhr = new XMLHttpRequest(); 
xhr.overrideMimeType("text/html"); 
xhr.open("GET", browser.extension.getURL('test.html'), false); 
xhr.addEventListener("readystatechange", loaded); 


xhr.send(null); 

了簡單的HTML文件

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title>Test</title> 
    <meta charset="utf8" /> 
</head> 
<body> 
    <h1>Hello World</h1> 
</body> 
</html> 

所以,現在你已經成功地注入了HTML模板到目標iframe中。

如果您需要任何圖像,腳本,css文件等,您需要根據上述方法編寫引導加載程序,將新腳本標記等注入到iframe文檔中。

0

順便說一句,有時人們使用不同的協議IFRAME URL,即
https://(而當前頁面是http://)。

因此,IFRAME網址相對應,像src="//example.com"

+0

從擴展文件系統訪問文件的Firefox擴展的上下文而不是網站上下文,它將無法工作。 Firefox擴展文件駐留在moz-extension協議上。 –