為避免惡意指令碼濫用彈出式視窗等敏感 API, 全螢幕等等,瀏覽器會透過使用者來控管這些 API 的存取權 啟用。使用者啟用是指瀏覽工作階段中的相應狀態 轉換為「有效」「狀態」通常表示使用者 目前正在與網頁互動,或是在之後完成互動 載入。使用者手勢是相同概念的熱門但誤導性字詞。適用對象 舉例來說,使用者的滑動或閃爍手勢不會啟動網頁,因此 並非如此
現今的主要瀏覽器顯示使用者啟動方式截然不同的行為
控制啟用限制的 API。Chrome 的實作是以 Chrome 為基礎
採用符記式模型,因故難以定義
所有啟用管制 API 的行為舉例來說,Chrome 已
透過以下方式,以完整的方式存取啟用管制的 API
postMessage()
和
setTimeout()
呼叫;以及使用者啟用作業的
支援 Promise
XHR、
遊戲手把互動等。請注意,其中部分項目
也可能是長期存在的熱門錯誤
在第 72 版中,Chrome 提供「使用者啟用功能 2.0 版」, 所有啟動限制的 API 啟用期限都已完成。這可以解決問題 這些不一致的情況 (另外還有一些, MessageChannels)。 引導使用者啟用應用程式此外,新的實作方式 將提議的參考實作 新規格 。
使用者啟用 v2 的運作方式為何?
新 API 在每個 window
物件上都維持 2 位元使用者啟用狀態
區隔:適合歷來使用者啟用狀態的一個固定點 (如果
影格速率是指使用者啟動的影格數),而目前狀態的短暫位元
(使用者大約一秒後啟動了使用者啟動的影格)。便利性
設定影格後,影格生命週期不會重設暫時的位元
會在每次使用者互動時設定,並在到期後重設
或藉由呼叫啟用採用的 API
(例如 window.open()
)。
請注意,不同的啟用管制 API 仰賴使用者啟用作業的不同
管理方式;新的 API 不會變更上述任何 API 專屬行為。例如:
每次使用者啟用時,只允許一個彈出式視窗,因為「window.open()
」會使用
如以往的使用者啟動作業,Navigator.prototype.vibrate()
繼續
瀏覽過任何影格 (或其任何子頁框) 的使用者操作、
依此類推
異動內容
- 「使用者啟用 v2」針對使用者啟用可視性的概念正式闡明 跨影格邊界:使用者與特定影格互動時 啟用所有包含影格 (且僅限這些影格),無論其 來源。(在 Chrome 72 中,我們提供了暫時替代方案,將 可在所有相同來源影格的顯示設定我們會在執行初期 可讓您 將使用者啟用作業明確傳遞至子頁框)。
- 從已啟用的影格呼叫啟用管制的 API 時 事件處理常式程式碼之外,只要使用者啟用這個 API,這個 API 就能持續運作 狀態為「已啟用」例如未過期也未消耗。使用者之前 啟用第 2 版時,會無條件失敗。
- 在到期日間隔內多次未使用的使用者互動融合 對應至與最終互動對應的單次啟用中。
啟用管制 API 的一致性範例
以下是兩個彈出式視窗 (使用 window.open()
開啟) 的範例,
展示「使用者啟用第 2 版」如何產生啟用管制 API 的行為
保持一致
鏈結 setTimeout()
呼叫
這個範例來自
我們的 setTimeout()
示範。
如果 click
處理常式嘗試在一秒內嘗試開啟彈出式視窗,則預期會
就算程式碼的「撰寫」方式使用者啟用第 2 版符合
因此,下列每個事件處理常式都會在
click
(延遲 100 毫秒):
function popupAfter100ms() {
setTimeout(callWindowOpen, 100);
}
function asyncPopupAfter100ms() {
setTimeout(popupAfter100ms, 0);
}
someButton.addEventListener('click', popupAfter100ms);
someButton.addEventListener('click', asyncPopupAfter100ms);
在沒有使用者啟用第 2 版的情況下,第二個事件處理常式在所有的瀏覽器中都會失敗 目標使用者、使用的資料 以及模型訓練與測試方式(即使第 1 個 VM 無法使用 在某些情況下)。
跨網域 postMessage()
呼叫
我們來看一下
我們的 postMessage()
示範。
假設跨來源子頁框中的 click
處理常式會直接傳送兩則訊息
對應至上層頁框上層頁框應該可以開啟彈出式視窗
收到以下任一訊息 (但兩者只能擇一):
// Parent frame code
window.addEventListener('message', e => {
if (e.data === 'open_popup' && e.origin === child_origin)
window.open('about:blank');
});
// Child frame code:
someButton.addEventListener('click', () => {
parent.postMessage('hi_there', parent_origin);
parent.postMessage('open_popup', parent_origin);
});
如未啟用「使用者啟用 2.0 版」,上層頁框在收到回應時無法開啟彈出式視窗 傳送第二則訊息即便第一則訊息「鏈結」也是如此到另一個 跨來源頁框 (換言之,如果第一個接收端將訊息轉寄至其他來源) 其他)。
這項做法適用於「使用者啟用 2.0 版」,可用於原始形式和 鏈結。