Firefox extension 偵測新 URL 的載入

我想要寫出能夠偵測新頁面載入,並依 URL 附加特定 content script 的功能,目前試過用 page-modtabs 實做。

這是 page-mod
var data = require("self").data;
var pageMod = require("page-mod");
pageMod.PageMod({
include: /https?:\/\/www\.example\.com\/.+\/?$/,
contentScriptFile: [data.url("jquery-1.8.3.min.js"), data.url("read_aha.js")],
onAttach: function (worker) {
worker.port.on("testing", function (m) {
console.log(m);
});
}
});

這是 tabs
var data = require("self").data;
var tabs = require("tabs");
var { MatchPattern } = require("match-pattern");
var home_pattern = new MatchPattern(/https?:\/\/www\.example\.com\/?$/);
tabs.on('ready', function(tab) {
if ( home_pattern.test(tab.url) ) {
console.log('home_pattern matches!');
var worker = tab.attach({
contentScriptFile: [data.url("jquery-1.8.3.min.js"), data.url("read_aha.js")],
onMessage: function(msg) {
console.log(msg);
}
});
worker.port.on("testing", function(msg) {
console.log(msg);
});
}
});

兩個實做的功能相近,但是卻有不同的彈性與問題。

page-mod 的話,每一次 Firefox 送出新的 HTTP Request 就會進行比對,要是目標與 include 指定的 pattern 相符,就會觸發,載入 content script 。page-mod 麻煩的點在於,有時候請求的 URL 會包含一長串的 HTTP GET 參數,導致要設計 regular expression 的時候增加了很多複雜度。相對的,有一些網站頁面載入之後會自動移除那些 GET 參數,若是只需要偵測網址列 URL 的改變,那就簡單多了。

tabs 的話,則是偵測每一個分頁的網址列 URL 是否符合 pattern ,若符合才載入 content script 。但是我遇到很麻煩的問題是,對於使用者在網址列按 Enter 或重新整理的情況下,會觸發 pattern 檢查,但是若是使用者在頁面當中點了超連結,進入一個新的頁面,縱使網址列的 URL 已經改變,依然不會觸發檢查,因此 content script 永遠不可能被啓動。看起來用 tabs 的另一個好處是,相較於 page-modtabs 在檢查 pattern 時,可以引入其他的檢查條件,就在 if ( home_pattern.test(tab.url) ) 加上其他條件即可,我覺得未來我蠻有可能會用到其他檢查條件。

Stack Overflow 上面有人提到這個問題,乍看之下好像是無解,但是後來我查到用更低階的 XPCOM API 應該是可以做出這個功能,但是我還沒試。

Firefox Add-on SDK content script include

做個小筆記。

像是這樣:

pageMod.PageMod({
include: /https?:\/\/www\.example\.com\/.+\/?$/,
contentScriptFile: [data.url("jquery-1.8.3.min.js"), data.url("read_aha.js")],
onAttach: function (worker) {
worker.port.on("testing", function (m) {
console.log(m);
});
}
});

什麼時候會 include 這個 content script 呢?實驗發現

  • 當分頁 URL 符合這個 regex 的時候
  • 以下這些不會:
    • <link href="xxx.css">
    • XMLHttpRequest
  • 但是 <iframe> 會!