Proxy 切り替えアドオン @Firefox 59

Firefox 57 では、PAC を変更することしかできなかった WebExtension API
Firefox 59 で、ようやくプロクシの設定を切り替える手段ができた。

ぼくは、「プロクシなし」と「システム設定」を切り替えたいだけなので、こんな感じのアドオンで十分。

ファイル構成

manifest.json
background.js
icons/
    blank.png
    none.png
    system.png

manifest.json

{
    "manifest_version": 2,
    "name": "Toggle Proxy",
    "description": "Toggle Proxy",
    "version": "1.0",
    "homepage_url": "http://q.hatena.ne.jp/a-kuma3",

    "background": {
        "scripts": [
            "background.js"
        ]
    },
    "browser_action":{
        "default_icon": {
            "16": "/icons/blank.png"
        }
    },
    "permissions": [
        "browserSettings"
    ]
}

background.js

function display(proxyType) {
    browser.browserAction.setIcon({path: `/icons/${proxyType}.png`});
    browser.browserAction.setTitle({
        title: "Toggle Proxy - " + ({system: "System Setting", none: "No Proxy"})[proxyType],
    });
}

browser.browserSettings.proxyConfig.get({}).then(settings => {
    display(settings.value.proxyType);
});

browser.browserAction.onClicked.addListener((mes, sender) => {
    browser.browserSettings.proxyConfig.get({}).then(settings => {
        const dest = settings.value.proxyType == "system" ? "none" : "system";
        console.log(`${settings.value.proxyType} ---> ${dest}`);
        browser.browserSettings.proxyConfig.set({value: {proxyType: dest}});
        display(dest);
    });
});

注意)後述してます(2018-5-3 追記)が、Firefox 61 から実装が変わります。上記のコードは 60.0b15(release版だと 60.0 のひとつ前)までしか動きません。

強いて言えば

Firefox では、BrowserSetting が(これを書いている時点で)onChange イベントをサポートしていないので、オプションからプロクシの設定を変更したときに、見た目がついてこないというのはあるのだけれど。
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/types/BrowserSetting

でも、アドオンからプロクシの設定を切り替えられるようになったら、オプションから変更することはないから、たいしたことじゃあないな。

後述してます(2018-5-3 追記)が、Firefox 60 から、アドオンでプロクシの設定を変更すると、オプション画面からプロクシの設定が変更できなくなります。なので、こちらも気にする必要がない、と。


快適 :-)

FF 60.0b16 で動かなくなってる (2018-5-1 追記)

15:27:53.182 fun is not a function ExtensionParent.jsm:772
call/result< resource://gre/modules/ExtensionParent.jsm:772:57
withPendingBrowser resource://gre/modules/ExtensionParent.jsm:427:26
InterpretGeneratorResume self-hosted:1256:8
next self-hosted:1211:9
call resource://gre/modules/ExtensionParent.jsm:771:20
InterpretGeneratorResume self-hosted:1256:8
next self-hosted:1211:9
15:27:53.183 Error: An unexpected error occurred undefined
15:27:53.980 [Exception... "Component returned failure code: 0xc1f30001 (NS_ERROR_NOT_INITIALIZED) [nsIMessageSender.sendAsyncMessage]" nsresult: "0xc1f30001 (NS_ERROR_NOT_INITIALIZED)" location: "JS frame :: resource://gre/modules/ExtensionUtils.jsm :: sendAsyncMessage :: line 533" data: no]

FF 60.0b15 では動くので、Firefox の修正待ち、かな

実装が変わった (2018-5-3 追記)

FF 61.0b1 でも動かない。
今度のエラーはもっと分かりやすくて、
TypeError: browser.browserSettings.proxyConfig is undefined

コンソールで browser.browserSettings を見ても、proxyConfig がない(そりゃ当然)。
https://developer.mozilla.org/en-US/Firefox/Releases/61 には、まだ情報が記載されてない。
うーむ。

"browserSettings site:dxr.mozilla.org/mozilla-central/"で関係しそうなソースをググってみる。
mozilla-central/toolkit/components/extensions/schemas/browser_settings.json のソース。
直近の diff
うわ、消されてるじゃん

Log を見てみると "Shane Caraveo - Bug 1455755 Move browserSettings.proxyConfig to proxy.settings, r=aswan" ...
これかっ!

その revision のソースを流し読みした感じだと browser.browserSettings.proxyConfig が browser.proxy に変わった感じみたい。
Google Chrome の API に寄せた、と言うことね。
proxy.register() しかなかったときのアドオンとか見てても、proxy.settings の Polyfill で対応しているようなのがあったもんなあ。


というわけで、browser.browserSettings.proxyConfig を browser.proxy.settings に変えて、permission を proxy に変更したら動くようになったよ :-)

manifest.json (FF 60.0b16 以降)
{
    ...
    "permissions": [
        "proxy"             ★
    ]
}
background.js (FF 60.0b16 以降)
    ...
browser.proxy.settings.get({}).then(settings => {       ★
    display(settings.value.proxyType);
});

browser.browserAction.onClicked.addListener((mes, sender) => {
    browser.proxy.settings.get({}).then(settings => {const dest = settings.value.proxyType == "system" ? "none" : "system";
        console.log(`${settings.value.proxyType} ---> ${dest}`);
        browser.proxy.settings.set({value: {proxyType: dest}});         ★
        display(dest);
    });
});



ちなみに、BrowserSetting が onChange イベントをサポートしてないやつについて。
"Bug 1429593 Show that a WebExtension is managing the proxy config setting" で、Firefox 60 から、アドオンからプロクシの設定をしている場合には、オプションからプロクシの設定ができなくなってます。
なので、アドオンでは、自身以外から変更されたときに内部状態や表示を同期を取らなくちゃいけないという心配をする必要がなくなりました。
# ちょっと不便な気もするけど