Copy as Markdown 是我自2012年開發至今的瀏覽器擴充套件,主要功能是把網頁上的超連結或分頁轉換成 Markdown,然後複製到剪貼簿。WAU大約一萬人。有在 Chrome、 Firefox、Edge 的官方商城上架。一直以來都維持低度維護,主要是工作之餘無暇兼顧。最近因為育嬰假有些空閒可以來改,而隨著育嬰假即將結束,也許不會再有時間改了,所以記錄一下這個里程碑。
過去三個月以來主要做了這些事情:
- 加入基於 Selenium 的 E2E 測試
- 將大部分權限改為選配
- 改善了 Firefox 版本的穩定度(主要是改回 Manifest V2)
- 在 Firefox 加上了複製書籤的功能
- 在 Chrome 加上了複製分頁群組的功能
- 加入HTML複製成Markdown的功能
- 一些程式改善(主要是改成 async/await)
- CSS套版,主要是 Bulma.css
本文亦有英文版。This post is also available in English
E2E 測試
如前所述,向來都是低度維護的情況下,功能很少,測試工具都是靠手動,一時要加上新功能,就要各種瀏覽器各種OS交叉測試,過去12年也不時會把功能改爛。以往都是在 macOS 開發測試,從來沒有在 Windows 和 Linux 桌面好好測試過;最近買了一台二手的 PC,至少有 Windows 和 Linux 可以測。但手動測還是很累,所以研究了 E2E 測試。
所謂 E2E 測試,理想上還是直接發鍵盤滑鼠事件,但實際上要測試瀏覽器擴充套件並不是那麼容易,尤其要與原生UI互動,這其中包括分頁、鍵盤快速鍵、滑鼠右鍵選單、權限警告等。Chrome 官方的指南並不是很齊全,只大略列出有哪些工具可以用,例如 Selenium、WebDriver、Puppeteer等,但各家的指南也不是很齊全,花了不少時間自己摸索,也曾經考慮 Sikuli 和 Robot Framework,但工具鏈不是很好上手,所以作罷。又如 Puppeteer / WebDriver 是基於 Chrome Developer Protocol 的,只能控制瀏覽器裡面的網頁,摸不到 OS 的 native UI,也不太適合。
最後選用了 Selenium 的 Java 版本,因為可以調用 AWT 的 Robot 函式庫來對 OS 送出鍵盤滑鼠事件。事實證明這是對的決定,因為 Java 的跨平台特性讓我少掉很多麻煩,Selenium 和 AWT 也都是歷史悠久的工具,要找問答和奇怪的 tips & tricks 並不難。例如:
- Robot 只能送事件到當前應用程式。用 TestNG 開 Selenium,焦點會在 Test Runner,要用
driver.switchTo().window(handle)
切換視窗焦點。 - 用 Robot 送出 macOS 的組合鍵需要在 modifier keys 和 non-modifiers 之間加入 200ms 的 delay;在 Windows 則需要視情況呼叫
keyRelease()
。 - 瀏覽右鍵選單的時候可以直接用鍵盤事件「打字」——但並非每次都會成功。
- 在 Selenium 裡面只看得到 Window,看不到 Tab,當然也看不到 Tab Groups,因此我另外做了一個 E2E Testing Support Extension 來調用 Chrome 的 API 開啟測試用分頁。
- 選配權限警告,在 Firefox 可以直接改
extensions.webextOptionalPermissionPrompts=false
關閉警告,在 Chrome 則只需要允許一次,所以就在跑測試前先用鍵盤事件全部允許。
全部跑完大約要3分鐘左右,其實還算可以接受,但有點覺得是不是過度測試,而且 Windows 和 Linux (KDE) 還是有些問題無法全部通過。正在想把一些測試改到 Puppeteer,直接呼叫 background.js
的 event handlers 就算數,畢竟我可以假設瀏覽器本身可以正確呼叫鍵盤和右鍵選單的事件。但那又要折騰另一套 framework,所以暫時作罷。
開發的過程中,用了 JetBrains Aqua,及 PasteNow 來紀錄剪貼簿內容,很方便,推薦。
選配權限
Copy as Markdown 在很初期就有匯出分頁的功能,所以有 tabs
權限。日前加上了 tabGroups
的功能,可以同時匯出Chrome和Edge的分頁群組。當擴充套件要求新的權限時,Chrome就會出現警告。不久後就有零星的用戶抱怨「為什麼要看我的瀏覽紀錄?」而且也有很多使用者選擇解除安裝(大約5%)。原來是 Chrome 的權限警告會顯示「讀取您的瀏覽紀錄」,其實就是存取分頁的 tabs
權限。技術上也沒錯,因為可以拿到分頁的資料就表示可以隨時監控你瀏覽了什麼網頁,但老實說這實在是太嚇唬人了,一般用戶會覺得這個程式會無時無刻監控。
我覺得這個churning實在太傷,所以開始花時間改權限,目標是安裝時不會出現任何權限警告,把所有會出現警告的都放在選配,讓使用者自行決定,也做了功能讓使用者隨時取消,希望可以藉此止血。
沒錯,我的程式是開放原始碼,但我不可能期待那10000週活用戶都先看得懂程式碼再來用。作為一個實質上的PM,當然有義務改善這部分的UI。這件事的教訓就是,要給使用者選擇是否可以存取敏感的資訊。
在過去三個月裡,除了原本的分頁 tabs
改成了選配,新功能分頁群組 tabGroups
和書籤 bookmarks
也改成了選配。後者必須是選配,因為相關功能只支援 Firefox。
Firefox 版回歸 Manifest V2(暫時)
Manifest 的版本可以簡單理解為瀏覽器擴充套件的 API 版本。現在的最新版是 V3,名義上是某 W3C 群組主導的規格,實務上是 Chrome 挾市場地位主導的。MV3 在 Chrome 已經變成必備,舊版 MV2 已經無法上架,但因為各種原因,Firefox 目前是 MV2 和 MV3 都同時支援。兩者之間的 API 大同小異,主要差異在 Promise,但那些小異已經讓我必須加入一大堆 if (typeof chrome.xyz === 'undefined')
,以及 callback-to-Promise wrapper,相當煩人。
由於 Chrome 力推 MV3,帶著 Firefox 被迫跟上。原本我也是抱持 MV3 會統一天下,加上程式碼的維護考量,所以在 Firefox 上了 MV3。豈料 Firefox 因此出現了神秘的右鍵選單消失問題,我試了好幾種 hack 都無法解決,最後還是退回了 MV2。
然而這就回到了 callback vs Promise API 的問題。本來是覺得只有幾個 API 就自己包,但愈寫愈覺得麻煩,於是就導入了 Mozilla 出的 webextension-polyfill.js ,至少現在大部分的程式都可以用 async/await 寫了。
長期目標還是想要改為 MV3,但現在能動就暫時放著吧,反正有 E2E 測試不怕改爛(?
鳴謝
這三個月有時間可以來做大改動,是來自育嬰假,首先感謝我的女兒 Rena 出生,這個 3.0 版是為了紀念她而跳的版號。第二是孩子的媽,我的太太 Serena,她同時也是全職 UI/UX 設計師,在 UI 設計的過程中給了我很多寶貴意見。此外也要感謝我的公司 BONX Inc 讓我休育嬰假,我們的軟體開發團隊長期在徵才(日本東京)。最後也要感謝日本政府的育嬰假津貼。
附帶一提,現在 Copy as Markdown 有贊助連結,如果想要贊助的話請隨緣~