Firefox 的 UI 修正方案

在「Firefox Proton UI userChrome.css fixes. (2021) (github.com/black7375)」這邊看到的,GitHub 上的專案頁面在「Lepton (old name: Proton Fix)」這邊。

作者先前有寫過,我在「Firefox 的 UI/UX 歷史」這篇,同一個 repository 裡面就包含了「修正方案」,補上了一些 icon,並且改了 css 效果。

不過我已經沒什麼在用 Firefox 了,而且目前看起來也不會回去了,看起來只有在交叉找問題的時候會用到...

UI Event 的順序

othree 寫了一篇「UI Event Order」在講滑鼠 (或是更廣廣義的 pointer 類) 以及鍵盤 (包括輸入法) 在瀏覽器上會產生的 event。

裡面有些是歷史 (提到 IE 上的實作方式),現在都不太會碰到了,可以直接看目前的幾份標準就好,然後蠻多標準都還是在 draft 階段,各家瀏覽器更新的速度不一樣,所以會有不同的行為冒出來。

我決定先把文章保留起來,等遇到的時候再回來看 XD

Web Audio API 當做 fingerprint 的方式

三年前的文章「How the Web Audio API is used for audio fingerprinting」講解了 AudioContext 是怎麼被拿來 fingerprint 的,最近在「How We Bypassed Safari 17's Advanced Audio Fingerprinting Protection」這篇看到的。

AudioContext 可以完全跟錄音設備無關,單純計算,然後因為不同瀏覽器實作上面有差異,就被拿來當作 fingerprint 了。

文章裡介紹的方法是透過 Oscillator 產生 440Hz 的正弦波,然後過 Compressor 降低音量 (運算):

The Web Audio API provides a DynamicsCompressorNode, which lowers the volume of the loudest parts of the signal and helps prevent distortion or clipping.

降低音量的運算再這塊各家的實作不同,就能夠區分不同的瀏覽器 (甚至是版本):

Historically, all major browser engines (Blink, WebKit, and Gecko) based their Web Audio API implementations on code originally developed by Google in 2011 and 2012 for the WebKit project.

Since then browser developers have made a lot of small changes. These changes, compounded by the large number of mathematical operations involved, lead to fingerprinting differences. Audio signal processing uses floating point arithmetic, which also contributes to discrepancies in calculations.

Additionally, browsers use different implementations for different CPU architectures and OSes to leverage features like SIMD. For example, Chrome uses a separate fast Fourier transform implementation on macOS (producing a different oscillator signal) and other vector operation implementations on different CPU architectures (used in the DynamicsCompressor implementation). These platform-specific changes also contribute to differences in the final audio fingerprint.

而這東西平常也不會用到,所以對 Tor Browser 這種特別重視 privacy 的瀏覽器就直接關掉他了:

Tor

In the case of the Tor browser, everything is simple. But unfortunately, web Audio API is disabled there, so audio fingerprinting is impossible.

用 Brave 的 brave://flags 設定

因為 Brave 會繼續支援 webRequest 的完整功能,所以早早就已經跳槽過來,不過 Brave 的垃圾功能太多 (一堆 cryptocurrency 相關的功能),有需要全部關掉,所以裝好後第一件事情就是到 brave://flags 裡面把所有 Brave 自家功能的設定關光光,只留下 Brave Sync V2 的功能。

先前都是用滑鼠一個一個關,剛剛覺得太累了,研究一下 js 直接在 dev console 裡面關:

document.querySelector('flags-app').shadowRoot.querySelectorAll('flags-experiment[id^=brave]').forEach(flag => {
  flag.shadowRoot.querySelectorAll('option').forEach(o => {
    if (o.innerText === 'Disabled') {
      o.selected = 'selected';
      o.parentElement.dispatchEvent(new Event('change'));
    }
  });
});

這樣會全部把 brave 開頭的 feature flag 都關掉;最後再手動把 Sync V2 開回來就可以重開 Brave 了。

後續就是 GUI 上面的選單再調整成自己要的。

這邊搞 javascript 的部分有遇到四個地方要處理... 第一個是現在 dev console 預設不讓你貼東西進去,貼了以後會顯示要輸入 allow pasting 後才行,這個字串以及方法之後不知道會不會改。

第二個是遇到 querySelectorAll 穿不過 shadow DOM,所以可以看到程式碼裡面需要先選出 shadow DOM 元素,用 shadowRoot 鑽進去再 querySelectorAll 一次。

第三個是 css selector 沒辦法針對 innerHTML 或是 innerText 的內容判斷,所以得自己拉出 option 後對 innerText 判斷。

最後一個是改變 select 的值後,得自己觸發 change event,這樣才會讓 Brave 偵測到並且儲存。

Keyboard Event:在網頁上自定義快速鍵

先前寫了一堆 userscript 針對不同的網站加上快速鍵 (像是翻下一頁或是上一頁):

然後發現太多重複的事情了,就寫成 Chrome 的 extension 了:「Keyboard Event」,程式碼在 GitHub 上有放:「gslin/keyboard-event」,不信任一致性的話也可以用 Chrome extension source viewer 直接看 chrome web store 上面放的版本。

這個 extension 的想法是設定 hostname、path 以及按鍵,接著設定按鍵按下後會觸發的 DOM element (用 CSS selector 選) 與 DOM event (像是 mouseover 這樣的 event 字串)。

而其中 click event 常常不會動 (對應實際的呼叫是 element.dispatchEvent(new Event('click'))),在 debug 時發現需要用 click() (對應實際的呼叫是 element.click()),所以有特別接受 click() 這個字串。

這個舉個例子,我有一組設定是:

www.instagram.com
.*
<
div[role="dialog"] button[aria-label="Go back"]
click()

www.instagram.com
.*
>
div[role="dialog"] button[aria-label="Next"]
click()

在瀏覽器上面看 Instagram 的照片時可以用 <> 快速切換照片。

另外設定的部分支援 chrome.storage 的 browser sync,對於有多瀏覽器時會自動同步設定檔,不用每一台都設定一次...

這算是第一次寫 Manifest V3 的 extension (先前都是 V2),本來想用 Vue.js 處理設定頁 options.html,但遇到了 CSP 的問題,在 Manifest V3 上面無法設定 unsafe-eval,於是 Vue.js 只能用 runtime 版本,喪失了 template 好用的地方...

後來決定回頭用 jQuery + jQuery UI (用 sortable),然後自己處理一堆 data 更新時頁面的變化,一整個 2010 年老人味都出來了...

但這樣至少會動,先跑一陣子看看...

各家瀏覽器與工具對於 blur 效果的實際呈現比較

Hacker News 上看到「Blur Radius Comparison (bjango.com)」,原文在「Blur radius comparison」。

重點在這張:

前面九個分成三種效果在三個不同的瀏覽器呈現的結果,然後是 FigmaIllustratorPhotoshopSketch 的效果。

可以看出來在瀏覽器上的部分,大家的 rendering 沒有差太多。

而 Figma 所有 blur 類的效果,在瀏覽器上比較接近的只有 box-shadow,其他三套則是有不同的變化...

Firefox 與 Chrome 處理 Intermediate CA 的不同方式

Fediverse 上看到「The recording of my "Browsers biggest TLS Mistake" lightning talk at #37C3」這個,這是出自 37C3 的 lightning talk,影片不長,只有五分鐘,可以在「Browsers biggest TLS mistake」這邊看到。

正常的 HTTPS server 會送出 Intermediate CA certificate 與自己的 TLS certificate:

當伺服器端沒有設定好,通常是只送出自己的 TLS certificate:

這種情況在 Firefox 裡有處理,軟體本身會預載所有的 Intermediate CA 避免這種問題 (當然會需要跟著軟體更新),這點在三年前有提到過:「Firefox 試著透過預載 Intermediate CA 降低連線錯誤發生的機率?」,也就是這張投影片提到的情況:

Chrome 則是去看目前的 cache 資料,找看看是不是在其他地方有看到適合的 Intermediate CA 可以接起來:

這好像可以解釋為什麼之前遇到類似的問題的時候,在 Chrome 上面會需要進 chrome:// 裡面清東西才能重製...

Firefox 宣布從 Mercurial 換到 Git

Firefox 宣佈從 Mercurial 換到 Git:「Firefox Development Is Moving From Mercurial To Git」。

目前是 Mercurial 與 Git 都支援,理由是不想要維持兩套:

For a long time Firefox Desktop development has supported both Mercurial and
Git users. This dual SCM requirement places a significant burden on teams which
are already stretched thin in parts. We have made the decision to move Firefox
development to Git.

不過不知道決策的過程到底是怎麼產生的,算是 Mozilla 的老問題了...

最近 AV1 的支援度

HN 上「AV1 video codec gains broader hardware support (fullystacked.net)」這篇在說 AV1 的支援度變得更好了,原文不長,在「The AV1 video codec gains broader hardware support」這邊。

Can I Use 上的 AV1 video format 可以看的比較清楚:

不過在瀏覽器上離直接取代掉其他的 video codec 還早,但算是個起頭,至少 iPhone 15 Pro 與 iPhone 15 Pro Max 上的 Safari 支援了,接下來就是看桌機的 Edge 什麼時候才又想到要把 AV1 開回來:

Edge has stopped supporting AV1 completely at some point prior to version 116 (additional information required).

德國法院認為 DNT header 具有法律的告知效力

HN 上面看到「German court declares Do Not Track to be legally binding (vzbv.de)」這個消息,原文是德文:「Gericht untersagt Datenschutzverstöße von LinkedIn」,Google Translation 翻譯的結果:「Court bans LinkedIn data protection violations」。

LinkedIn 告知使用者他們不會理會 DNT,德國法院則是認為 DNT header 是已經告知對方不願意被追蹤了:

„Wenn Verbraucher:innen die ,Do-Not-Track‘-Funktion ihres Browsers aktivieren, ist das eine klare Botschaft: Sie wollen nicht, dass ihr Surfverhalten für Werbe- und andere Zwecke ausgespäht wird“, sagt Rosemarie Rodden, Rechtsreferenin beim vzbv. „Webseitenbetreiber müssen dieses Signal respektieren.“

“When consumers activate the 'Do Not Track' function of their browser, it sends a clear message: They do not want their surfing behavior to be spied on for advertising and other purposes,” says Rosemarie Rodden, legal officer at vzbv. “Website operators must respect this signal.”

這好像是第一次看到 DNT 相關的法律判決?可以看看後續有沒有新的消息 (上訴之類的),來看看最終的判決會是怎麼樣。