Anping English

新分頁或 iframe

新分頁讓桌面用整個視窗。iframe 是你網頁裡的一個框,讓桌面留在你的網頁裡。

新分頁iframe
Anping 伺服器上的設定不用把你網站的網址加進 Oturl:FrameAncestors
Win、Alt+Tab全螢幕(Chrome、Edge)或 KeysKeys(框裡攔不到這些按鍵)
Ctrl+Alt+DelKeysKeys
重新整理一段時間內會重新連線(重新連線視窗)瀏覽器還記得這個連結時會重新連線(下方)

新分頁

在使用者點擊的當下先開分頁,再向你的伺服器要連結。晚一點才開的新視窗,瀏覽器會當成彈出式視窗擋掉。

button.addEventListener('click', async () => {
  const tab = window.open('', '_blank')   // during the click
  if (tab) tab.opener = null
  const response = await fetch('/api/anping-link', { method: 'POST' })
  const { url } = await response.json()   // your server asks Anping
  if (tab) tab.location.replace(url)
})
你的網頁本身放在受限制的框(sandbox)裡?

那個框的 sandbox 屬性需要 allow-popups 和 allow-popups-to-escape-sandbox,否則新分頁會被擋,或繼續受 sandbox 限制。

iframe

<iframe src="https://anping.example.com/oturl.html?key=...&pass=..."
        title="Remote desktop"
        allow="fullscreen; clipboard-read; clipboard-write; autoplay"
        referrerpolicy="no-referrer"
        style="width: 100%; height: 80vh; border: 0"></iframe>
allow 裡的項目為什麼需要
fullscreen工具列的 Full screen 按鈕。
clipboard-read, clipboard-write瀏覽器允許時,複製貼上會自動處理;否則使用者用 Clipboard 面板。
autoplay在你的網頁點過之後聲音就能開始,不必在 iframe 裡點。
更多沒有它的話,工具列會顯示 Enable sound,直到 iframe 裡的點擊或按鍵。
referrerpolicy="no-referrer"連結裡的機密部分(key 和 pass)永遠不會被送到別的網站。

resolution=fittobrowser 時,遠端畫面跟著框的大小。

允許你的網頁

只有連結頁面(/oturl.html)能放進框裡,而且只限你列出的網站。每個網站寫成 https:// 加主機名稱(和連接埠),不含路徑,或寫 'self'。

技術細節

Anping 以 Content-Security-Policy: frame-ancestors 送出這份清單。

Oturl__FrameAncestors__0=https://app.example.com
Oturl__FrameAncestors__1=https://portal.example.com

在框裡重新整理

瀏覽器用一個小 cookie 記住這個連結。在 https 的框裡,每個放 Anping 的網站各有自己的一份(技術細節:SameSite=None; Secure; Partitioned)。

瀏覽器重新整理你的網頁時
Chrome、Edge(114 以後)會重新連線(已測試)。
Firefox應該會重新連線;還沒完整測過。
Safari會擋別的網站的 cookie,所以多半出現已使用的訊息。
純 http(開發)只有你的網頁在同一個網站時才行(技術細節:SameSite=Strict)。
cookie 被擋時;在負載平衡器後面時

送給你網頁的訊息

框裡的頁面會告訴你的網頁發生了什麼事(用 postMessage)。只有 Oturl:FrameAncestors 列出的網站收得到。

內嵌事件:連線狀態變化時,連結頁面送出 connected、reconnecting、disconnected、ended 或 link_invalid;數字對應圖下的清單。 開啟連結 connected reconnecting disconnected ended link_invalid 1 2 3 4 5 6 7 8 9 內嵌事件:連線狀態變化時,連結頁面送出 connected、reconnecting、disconnected、ended 或 link_invalid;數字對應圖下的清單。 開啟連結 connected reconnecting disconnected ended link_invalid 1 2 3 4 5 6 7 8 9
每個箭頭都會送出它指向的事件。
  1. 桌面出現,每次重新連線後也會
  2. 連結已用過、過期或不存在
  3. 連線斷了:頁面自己重試
  4. 及時連回來
  5. 一分鐘內沒連回來(最終的錯誤:ended)
  6. Disconnect、遠端結束或錯誤
  7. 使用者按了 Reconnect
  8. 重新連線視窗過了
  9. End、閒置或時間上限、重新啟動、最終的錯誤:需要新的連結
window.addEventListener('message', (e) => {
  if (e.origin !== 'https://anping.example.com' || e.data?.source !== 'anping' || e.data.v !== 1) return
  // e.data.type: connected | reconnecting | disconnected | ended | link_invalid
})

每則訊息長這樣:{source: 'anping', v: 1, type, link, code?, until?}。link 是連結的代碼:不是機密,跟連線記錄裡的一樣,Anping 給出之前是 null。v 是版本:只有欄位的意義改變或被拿掉時才會改。下表中,type 是發生了什麼,code 是原因,until 是頁面會試到什麼時候,或 Reconnect 可以用到什麼時候。

typecodeuntil
connected無無
reconnectingconnection_lost 或其他短暫的錯誤停止重試的時間
disconnectedclosed(按了 Disconnect,或遠端結束)或錯誤代碼重新連線視窗結束的時間
endedsession_ended(使用者按了 End)、idle_timeout、max_duration、server_restart、其他錯誤代碼,或視窗過了之後的 disconnected 代碼無
link_invalid無無

聲音和自動播放

瀏覽器要等使用者互動後才允許聲音,所以連結的聲音(soundenabled=true)從第一次點擊或按鍵開始。在那之前工具列顯示 Enable sound,之後是 Mute 或 Unmute。用 iframe 時,請在 allow 加上 autoplay。

更多

之前送來的聲音會丟掉,所以之後不會一次全部播出來。