2015年8月30日 星期日

Chrome 的「禁讀令」 讓 web app 不太可能取代 hybrid app

要寫 app 讓手機平板用, 有三種方式: Web APP、 Native APP、 Hybrid APP。 每種方式各有何優缺點? Kuro 大大 在 ICOS 2013 所做的 這份簡報 的第16頁有個簡單比較表。

其中 "Web app 不支援原生功能" 這件事已有改變: 搜尋 「javascript device API」 會看到已有很多 API 讓 web app 設計師可以跟手機平板互動。 W3C 做了一個 清單 列出目前可用的 API。 例如, 請拿你的手機/平板去開 這一頁: 它用 orientation API 偵測你的手機面向東西南北上下哪一方。

樂觀的 web app 開發者會期待有一天, 這些 API 讓 web app 幾乎可以取代像 cordova 這樣的 hybrid app。

但是 web app 終究會卡在信任/安全的防線之外: 為了避免用戶不小心逛到惡意網站手機馬上被入侵, 這些 API 一定會在某些地方畫上紅線。 比方說, 基於安全理由, 未來也不太可能會出現一個 API 讓陌生的 web app 任意瀏覽讀寫你手機的 /sdcard。 不過本文要探討另一個意料之外的挑戰。

貴哥同時身兼 「懶惰生疏的程式設計師」 及 「重視隱私、手機上網吃不飽的使用者」 兩種身份, 我心目中最理想的方案是: 瀏覽器允許用戶啟動一個 「local javascript」 的模式, 讓用戶可以執行 sdcard 上的 javascript, 並且選擇性地對它開放更多權限, 例如 「可讀寫同目錄以下的所有檔案」 或 「可讀寫整個 sdcard 上的所有檔案」。 總之就是希望手機程式設計門檻降低 (只需要會 javascript 系列 web 技術)、 用戶離線也可以做很多事。 (對啊, 我也希望只要學寫 web app 就夠了。 光是這樣對老人家而言就已經很挑戰了。)

拿一個例子請大家體驗。 sozi-test.tgz 是我用 sozi 所做的簡報。 你的 PowerPoint 簡報如果想在電腦/手機/平板上面播放, 就還需要安裝 MS Office 或其他 app; 但我的 sozi 簡報不論在哪個平臺上都可以直接用瀏覽器打開! 請先在電腦上解壓縮, 然後 用 adb 傳到你的手機/平板 上面去、 在瀏覽器的網址列打 file:///sdcard/sozi-test/odf2.svg 或任一個 odf*.svg 的路徑就可以播放了! 請依據你放置檔案位置修改路徑。 注意: 若試圖用檔案總管開它, 檔案總管有可能根本就不給你選用瀏覽器開啟的機會。 它其實不過就是 svg + javascript + 一堆圖片而已。 「善用開放的技術用排列組合取代肥大的軟體」 讓我的電腦/手機生活比大多數人簡潔有效率 ^_^

可是另一個例子就沒那麼幸運了。 tc-streets.tgz 是 「可離線的臺中市街道簡圖」。 裡面的 tiles/ 子目錄下有一堆 *.json 檔 (街道座標及名稱)。 首先在 linux/windows/Mac 電腦上面用瀏覽器開啟 index.html, 可能會看到地圖 (firefox), 也可能會看到一片空白 (chrome)。 你必須 (根據不同的瀏覽器) 鬆綁一些安全設定 才能看見地圖:

  1. firefox 不必設定。 但如果想允許 js 存取本目錄之外的檔案, 就必須在 about:config 頁面下把 security.fileuri.strict_origin_policy 設成 false。 詳見 官網說明
  2. chrome (或 chromium): 關閉所有 chrome 視窗、 在命令列上重下: chrome --allow-file-access-from-files
  3. safari: 在 「develop」 底下取消 「Disable local file restrictions」。

根據 chromium 開發者的解釋, 這是為了安全起見。 但我覺得這是過度解釋 same-origin policy 了; firefox 的做法合理多了。

在電腦上還勉強可以開啟 tc-streets/index.html [一個無趣但有點代表性的 web app]; 可是到了手機/平板上面, 你甚至連指定參數的機會都沒有 -- 請在你的 android 或 iphone 上面用瀏覽器開啟 tc-streets/index.html 看看。 凡是基於 webkit 核心的瀏覽器 (chrome、 tint、 lightening browser、 ...) 都無法完整開啟, 因為它禁止載入 *.json 資料檔 -- 即使是本地的檔案也不行 。 手機版 firefox 則可以正常開啟。

用 「javascript local json chrome」 會發現很多開發者都遇到這個困擾。 從 2010 年開始, chromium 開發論壇上的 40787 號議題 就已有人正式反應這個問題; 也有很多人提出各種可行的替代方案; 但是開發者 scarybeasts@gmail.com 堅持不退讓。 大家移師 47416 號議題 繼續論戰。 阻擋修改的 scarybeasts 甚至還說: 「我知道有少數人抱怨得很大聲; 但跟我們幾百萬的廣大用戶比起來, 這實在微不足道。」 奇怪了, 對的事就去做, 這跟抗議人數多少有什麼關係啊? (而且其實 一點也不少 啊!) 有那麼多 (不傷安全的) 替代方案為什麼堅持不用呢? 這跟一般自由軟體開發社群的現象很不一樣啊! 反倒比較像是 Sony rootkit 醜聞 爆開的時候, 副總裁 Thomas Hesse 的回應: 「我想多數人應該不知道 rootkit 是什麼吧? 所以他們幹嘛在乎這件事呢?」

[陰謀論: 事實上我覺得 chrome 核心開發者的這個堅持, 就是在服務 DRM 遙控數位枷鎖 無誤。 (雖然這個限制本身並不算是 DRM。) 對 google 來說, 除了可以阻止用戶輕易存取自身手機上的檔案之外, 又可以順便逼用戶盡量連線、 也提高 app 開發門檻 (見下一段)。 開始覺得 google 也很邪惡了...]

那麼 js 開發者到底該如何在手機上讀取自己的資料檔呢? 有些人提出不太漂亮的解決方式, 像是 把 json 資料檔包成 js 然後去 require 它 (但這僅適用於靜態資料檔); 或者 (像是半夜爬起來走到半公里外上廁所一樣辛苦的) jsonp 技術 [ 簡中正體]; 或是另外寫一個 app 提供 proxy server 的服務 (那又回到必須學 android 開發)。

[2016/6/30 後來我做了一個圖示分析: 用 jQuery 無痛讀檔、顯示]

看起來, 未來不論 js 的其他 device API 發展到什麼地步, 甚至侵犯用戶隱私 (很可能的), 對於 「禁止 js 程式設計師存取同目錄底下的檔案」 這件 (明明沒有安全顧慮的) 事, chrome 就就是堅持要封鎖。 這意謂著 (稍微有點規模、 需要動態讀資料檔的) web app 的開發者若想讓用戶離線執行你的程式, 還是需要學習 cordova 這種 hybrid 的開發方式 -- 反正 半小時就可以入門

至於如果想 讀寫 /sdcard 上面的東西 或是 讀寫真正的外接記憶卡, 那就更辛苦了。

也期待有更多開發者看出這個問題, 並且用中英文在部落格/論壇發聲, 讓 chrome 開發者看到這不是少數人的問題。 [我的英文文章沒有讀者群; 又欠缺程式碼的貢獻; 甚至連只是想要到 stackoverflow 去投票, 都還沒有足夠的點數 :-( ] 另外, 在 android 手機市場上, webkit 核心/chrome 瀏覽器獨大, 也是蠻危險的事。

又, 很好奇: 如果有人用 webkit 開發一個開放原始碼、 像 firefox 一樣允許 js 存取同目錄底下資料檔的 app, 會不會大受 web app 開發者的推薦呢? 就像 vmware 告訴用戶:「這是 chrome 的 bug, 請改用其他瀏覽器」 一樣。 如果 chrome 開發者覺得抱怨的是少數人, 那我們就讓幾百萬一般用戶都知道 chrome 的這個問題吧。

1 則留言:

  1. 來自 f-droid 的 "open in browser" 搭配 mBrowser 可以開啟 tc-streets 範例! https://newtoypia.blogspot.com/2018/11/html-svg.html

    回覆刪除

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。