很多時候為了方便,我們都需要從頁面上啟動一些本地的程式,從客戶端來實現更好的操作,比如 QQ 快速登入,點選旺旺圖示開啟客戶端等,這種在以往可以透過外掛實現通訊,例如 IE 的 ActiveX,早期 Chrome 與 Firefox 支援的 NPAPI,但 NPAPI 提供的許可權過大,導致了很多安全和效能問題,目前現代瀏覽器已停止支援,實際上單純頁面實現與本地程式進行通訊,我們有更通用的方式實現。

這裡暫時僅討論 Windows 的情況,Mac 和 Linux 還需要其他方式實現。

註冊協議(Register protocol)

註冊協議是一種用於透過連結傳送,接收和處理資訊的方法,瀏覽器可以處理的常見協議包括http,https,ftp 和 mailto。為了實現檢視透過特定協議傳送的資訊,這種協議必須註冊在登錄檔中註冊,常見的我們可以透過點選一個郵件地址調起第三方郵件客戶端。

協議被註冊後,該網址就可以由指定的程式(瀏覽器或第三方檢視器)進行處理。例如 mailto://abc

http://

xyz。com

可以使用註冊了協議 mailto 的郵件客戶端新建一封收件人地址為 abcxyz。com 的郵件。同理我們可以利用這種方式實現在瀏覽器中頁面調起本地程式。

除預設協議外,其他協議需要透過建立一個 。reg 檔案來進行註冊,例如註冊一個 test:// 協議:

[HKEY_CLASSES_ROOT\test]

@=“URL:test Protocol“

”URL Protocol“=”“

[HKEY_CLASSES_ROOT\test\shell]

[HKEY_CLASSES_ROOT\test\shell\open]

[HKEY_CLASSES_ROOT\test\shell\open\command]

@=”\“C:\\Program Files\\Application\\program。exe\” \“%1\””

執行這個 。reg 檔案註冊後,瀏覽器就可以呼叫 program。exe 處理 test://。當瀏覽器碰到 test://… 連結時,自動呼叫 program。exe,並把 test://… 地址作為第一個引數傳遞給 program。exe,透過 program。exe 判斷傳入的引數格式,若正確則檢查系統中是否存在 program。exe 程序,不存在會提示“系統檢測到您的機器上沒有啟動 program”,若存在則判斷 program 是否已登入,沒有登陸的話調起後先進行登入,若已登陸則直接進行後續操作。

也就是說 test://… 後續的資訊是交給 program。exe 進行處理的,在這裡我們就可以針對不同情況在連結中加入一些內容,也可以透過請求一個 URL,伺服器根據 URL 傳遞的 uid 和其他的一些引數,返回一段新的 HTML,新的 htm 中包含了自動執行的 js,執行完後程序得到響應,也可以將相關 js 包含在本頁,點選後直接交給 js 函式進行處理。

淘寶頁面中的 URL 啟動

後外掛時代頁面如何喚起本地程式

後外掛時代頁面如何喚起本地程式

旺旺有一個專門的服務叫做“旺旺亮燈”,實現原理是在 html 頁面中,寫一些特定 id 的元素,最外層的 span 將在相關 js 載入的時候動態的進行渲染,顯示成旺旺是否線上的圖示以及附加上相關的單擊事件,這樣在單擊圖示的時候,便會由 js 來進行處理。從程式碼中看還支援 NPAPI 外掛。當然如果發現本機沒有安裝旺旺的情況下,會跳轉到 web 版旺旺的頁面。

QQ 郵箱快速登入

後外掛時代頁面如何喚起本地程式

後外掛時代頁面如何喚起本地程式

如果我們在本機電腦上啟動了 QQ,再使用瀏覽器訪問 QQ 郵箱登入頁,頁面會提示我們已經登入了的 QQ,點選即可登入。

QQ 的實現方式是在客戶端開一個 Server,瀏覽器裡面請求這個地址,當訪問 QQ 郵箱登入頁時網頁會去訪問這個 Web Server,地址就是:127。0。0。1(localhost),由於這個 Web Server 是 QQ 建立的,所以 QQ 可以根據自己的登入狀況給訪問者返回對應的資訊。

我們來驗證一下,開啟開發者工具,切換到網路請求,重新整理頁面,過濾一下 localhost 的請求:

後外掛時代頁面如何喚起本地程式

後外掛時代頁面如何喚起本地程式

- 看一下完整響應:

var var_sso_uin_list=[{“account”:”QQ賬號“,”client_type“:65793,”face_index“:528,”gender“:1,”nickname“:”火狐測試“,”uin“:”QQ賬號”,“uin_flag”:512}];ptui_getuins_CB(var_sso_uin_list);

很明顯是當前登入的使用者資訊。

- ping 一下這個請求的 domain:

正在 Ping localhost。ptlogin2。qq。com [127。0。0。1] 具有 32 位元組的資料

顯示是 127。0。0。1。

- 現在我們驗證下是否是 QQ 開了這個 Server,檢視哪個程式佔用了 4301 埠:

netstat -ano | findstr “4301”

TCP 127。0。0。1:4301 0。0。0。0:0 LISTENING 9872

- 得到 pid 我們就可以看否是 QQ 在監聽這個埠了:

tasklist | findstr “9872”

QQ。exe 9872 Console 1 170,380 K

然後透過隨機數與郵箱伺服器配合加上 HTTPS 防止資料竊聽。

目前個人覺得 QQ 的方式較好,旺旺由於多個大型站點(淘寶、天貓、阿里巴巴中文站、國際站)分支較多,似乎沒有一個統一的方式來管理,會造成部分情況下無法調起的情況。

參考連結:

Registering an Application to a URI Scheme