頁面和應用之間的互動

genetalks_大資料發表於2019-04-30

前言

公司某個專案有一個功能,需要在網頁上通過使用者上傳檔案後,拉起本機的應用,然後應用顯示上傳速度等各種各樣的詳細資訊,網頁上顯示上傳進度等簡簡訊息。類似zoom的完美體現。我們知道js是執行在瀏覽器的,所以拉起應用肯定需要各個橋樑相互配合。本篇文章也是這個探索過程的總結。

URI

看到功能第一下就想到了通過URI來實現。通過安裝應用時的登錄檔來拉起應用。這是一個很普遍的拉起應用的方式,騰訊qq就是這種。但是不能做到互動。拉起就完事了。這不是我們想要的東西。

瀏覽器擴充套件

本文主要講的就是瀏覽器擴充套件。 瀏覽器擴充套件賦予了js操作瀏覽器的能力,我們可以通過擴充套件來實現很多功能,如去除廣告,瀏覽網頁翻譯,檢測莫名的js或者病毒的植入等等,當然也包括了與其他應用的通訊。其中用到的就是native Message。其中瀏覽器擴充套件的開發就不做過多的闡述了,網上很多。

大部分使用者應該是使用win來瀏覽網頁。我們主要也是講win。win平臺下的瀏覽器也是五花八門但是總結下來基本上就是谷歌,火狐,EDGE,IE。其中IE僅支援activeX來擴充套件,目前基本已經淘汰,不在我們這次的考慮中,但是ie也需要實現這項功能,暫時留著以後討論。

首先擴充套件的核心程式碼為

/// background.js
const nativeHostName = 'your nativeHostName'; // 定義nativeHostName,通常為com.chrome.app這種形式
const port = chrome.runtime.connectNative(nativeHostName);// 谷歌擴充套件下的寫法
const port = browser.runtime.connectNative(nativeHostName);// edge,火狐下的寫法
/// 獲得一個port物件,後面port的方法是一致的。
port.onDisconnect.addListener(function(){
// 失去連線port = null;
});
port.onMessage.addListener(function(message){
// 獲取應用端傳回來的message
});
port.postMessage({});// 給應用端傳送訊息

複製程式碼

外掛寫法雖然類似,但是註冊方法卻各不相同。其中谷歌的註冊清單json為

  {"name": "com.chrome.test",
    "description": "Chrome call native app and sent message to app.",
    "path": "C:\\Users\\Public\\GoogleNativeClient\\NativeMessagingApp.exe",
    "type": "stdio",

    "allowed_origins": [
        "chrome-extension://dkeepngffocdigjfgmbpffbcjpijdgppp/"
    ]}
    //json檔案,請記住name,因為註冊時需要這個name.path為拉起應用的路徑,type固定為'stdio',然後allowed_origins為陣列,記錄該擴充套件的id,即谷歌瀏覽器載入擴充套件後該擴充套件的id要與清單此處的id一直。
複製程式碼

火狐的註冊清單json為

{
    "name": "com.firefox.test",
    "description": "Chrome call native app and sent message to app.",
    "path": "C:\\Users\\Public\\GoogleNativeClient\\NativeMessagingApp.exe",
    "type": "stdio",
    "allowed_extensions": [ "testFirefox@example.org" ]
}
//和谷歌類似,但是最後為allowed_extensions,這裡為火狐瀏覽器的uid,可以通過manifest.json自定義.
// 注意!! 看似谷歌和火狐只是最後一個key不同,可以何必為同一個json,但是事實證明合併後是不能用的。

複製程式碼

edge需要用到c#技術,所以微軟這個註冊清單的方式怎麼不跟風呢?因為涉獵技術不夠所以停止了edge的研究。

接下來是註冊位置,win+R --> regedit


HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.chrome.test // 谷歌路徑
HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\NativeMessagingHosts\com.firefox.test // 火狐路徑
預設值都為我們清單json的絕對路徑
複製程式碼

此時就可以在拉起應用並通訊了。linux和mac下谷歌和火狐拉起應用方式一致,區別就是在於註冊清單方式不同,這裡就不過多討論了。

擴充套件的方式雖然可以很精確的和應用通訊,但是不難發現,不同瀏覽器需要開發不同的擴充套件,安裝不同的登錄檔和json。safari甚至還需要mac才能開發擴充套件,並且收費,還有諸如ie這種需要更底層的技術,難以做到統一。

websocket

ws可能是能夠找到的更加適合用來和應用通訊的東西了。一來都是js寫法,這樣子可以統一各個瀏覽器的通訊程式碼,二來支援ie10以上瀏覽器,相容性還可以。現在就存在一個如何拉起應用和確定websocket服務端介面的問題了。其實細細思考也不是很難,URI拉起應用,應用通知後臺拉起的應用的埠,後臺通知網頁已經拉起了應用和他的埠,網頁和應用建立ws連線通訊。看似簡單,而且程式碼統一,但是還有很多坑要去踩,如ws的安全性等...

總結

與應用通訊如果僅僅在單一系統下可以通過擴充套件的形式來實現,但是如果是多端多瀏覽器建議使用websocket。也許後面也會有更多更好的技術。


*作者簡介: 張栓,人和未來大資料前端工程師,專注於 html/css/js 的學習與開發。

相關文章