最近工做中遇到一個需求,場景是:將一個pc端a頁面做爲主要展現內容內嵌在另外一個pc端b頁面中,用戶在a頁面中點擊關閉的時候,而後b頁面也實現關閉的效果。算法
這裏首先想到就是經過iframe將a頁面內嵌到b頁面中,而後a頁面經過postMessage
方法,把變化的數據發送給b頁面,b頁面經過addEventListener
接收數據,進行關閉操做。chrome
targetWindow.postMessage(message,targetOrigin,[ transfer ]);複製代碼
targetWindow
window.open
(生成一個新窗口而後引用它),window.opener
(引用產生這個的窗口),HTMLIFrameElement.contentWindow
(<iframe>
從其父窗口引用嵌入式,可簡單理解爲從父級頁面向本身頁面進行數據傳遞),window.parent
(從嵌入式內部引用父窗口<iframe>
,可簡單理解爲從子級頁面向父級頁面傳遞數據)(當前場景下所用的window.parent
)window.frames
+索引值(命名或數字)。message
要發送到其餘窗口的數據。使用結構化克隆算法序列化數據。這意味着能夠將各類各樣的數據對象安全地傳遞到目標窗口,而無需本身序列化。api
targetOrigin
targetWindow
的原點,能夠是文字字符串
"*"
(表示沒有首選項),也能夠是URI。若是在計劃調度事件時,
targetWindow
文檔的方案,主機名或端口與
targetOrigin
提供的內容不匹配,則不會調度該事件;只有當全部的三個條件都匹配時,將調度該事件。該機制能夠控制發送消息的位置;例如,若是
postMessage()
用於傳輸密碼,則該參數必須是URI,其來源與包含密碼的消息的預期接收者相同,以防止惡意第三方攔截密碼。始終提供具體的
targetOrigin
,而不是
*
,若是您知道其餘窗口的文檔應該位於何處。未能提供特定目標會泄露您發送給任何感興趣的惡意站點的數據。
Transferable
對象序列。這些對象的全部權將提供給目標端,而且它們在發送端再也不可用。
window.addEventListener("message", msgHandler, false);
function msgHandler(event){
if (event.origin !== "http://yourhost.com") return;
// ...
}複製代碼
相關屬性說明:
data
從另外一個窗口傳遞的對象。安全
origin
bash
postMessage
。此字符串是協議和「://」的串聯,若是存在,則爲主機名,若是存在端口,則「:」後跟端口號,而且與給定協議的默認端口不一樣。典型起源的例子是
https://example.org
(意味着端口爲
443
),
http://example.net
(意味着端口爲
80
)和
http://example.com:8080
。請注意,此來源
postMessage
後的其餘位置。
source
app
window
對象的引用;你可使用它來創建兩個不一樣來源的窗口之間的雙向通訊。
window.parent.postMessage('isClosed', 'http://yourhost.com');複製代碼
在b頁面中,經過下面代碼便可接收到消息:post
window.addEventListener('message', msgHandler, false);複製代碼
安全問題部分ui
若是您不但願從其餘站點接收消息,請不要爲message事件添加任何事件偵聽器。這是避免安全問題的徹底萬無一失的方法。
spa
若是您確實但願從其餘站點接收消息,則請始終使用origin和可能的source屬性驗證發件人的身份。任何窗口(例如,包括http://evil.example.com)均可以向任何其餘窗口發送消息,而且您沒法保證未知發件人不會發送惡意消息。可是,在驗證了身份後,您仍應始終驗證收到的消息的語法。不然,您信任的站點中的安全漏洞只能發送受信任的消息,而後能夠在站點中打開跨站點腳本漏洞。.net
在postMessage用於將數據發送到其餘窗口時,始終指定精確的目標原點,而不是*。惡意站點能夠在您不知情的狀況下更改窗口的位置,所以它能夠攔截使用postMessage發送的數據。
在擴展中使用window.postMessage
window.postMessage可用於在chrome代碼中運行的JavaScript(例如,在擴展和特權代碼中),但調度事件的source屬性始終爲null,以此做爲安全限制。(其餘屬性具備預期值。)
內容或Web上下文腳本沒法指定targetOrigin直接與擴展(後臺腳本或內容腳本)通訊。Web或內容的腳本可使用帶有"*"的targetOrigin的window.postMessage與來廣播到每個偵聽器,可是不鼓勵這樣作,由於擴展不能肯定這樣的消息,和其餘偵聽器(包括那些你不控制的偵聽器)能夠偵聽。
內容腳本應使用runtime.sendMessage與後臺腳本進行通訊。Web上下文腳本可使用自定義事件與內容腳本進行通訊(若是須要,能夠隨機生成事件名稱,以防止從客戶頁面進行窺探)。
最後,將消息發佈到file:URL處的頁面,當前要求targetOrigin參數爲"*"。file://不能用做安全限制;此限制可能會在未來修改。