プロキシを設定できるChrome拡張はすでに高機能なものがいくつかあるが、Chromeウェブストアでは「ベスト プラクティスに沿わないため、まもなくサポートされなくなる可能性があります。」などと警告が表示されているものもある。
使用できなくなると困るので念のため自前で作成することにした。
- Proxy SwitchyOmega https://chromewebstore.google.com/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif?hl=ja
- Proxy SwitchySharp https://chromewebstore.google.com/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm?hl=ja
Chrome拡張のManifest V2は廃止が決定しており、警告が表示されているのはManifest V2を使用したままのためと思われる。
なお、この記事のコードはManifest V3の仕様で作成している。
Google Developers Japan: Manifest V2 の段階的廃止を開始 - https://developers-jp.googleblog.com/2024/06/manifest-v2-phase-out-begins.html
Chrome拡張でプロキシを設定するには
そもそもなぜChrome拡張でプロキシを設定できるのか謎だが、chrome.proxyのリファレンスを見るとたしかに設定できると書いてある。
設定を変更するにはchrome.proxy.settings.set
メソッドを呼び出す。
async function setProxySettingsFixedServer() {
// 省略
let config = {
mode: "fixed_servers",
rules: {
singleProxy: {
host: "proxy.example.com",
port: 8080
},
}
};
await chrome.proxy.settings.set({ value: config });
}
value
にはmode
とrules
を指定する必要がある。
プロキシサーバーのホスト名を自前で設定するならmode
にはfixed_servers
を指定する。
rules
にはプロキシサーバーのホスト名などを指定する。
単に設定するならsingleProxy
とhost
を設定する。
必要に応じてscheme
とport
も指定する。
プロキシサーバーを使用したくない場合はmode
にdirect
を指定することもできる。
プロキシサーバーがhttpとhttpsで分かれている場合はそれぞれ指定することもできるらしい。
(今時サーバーをわけるメリットはあまりないと思われるが)
// プロキシサーバーがhttpとhttpsで分かれている場合はたぶんこんな感じ(動作未確認)
let config = {
mode: "fixed_servers",
rules: {
proxyForHttp: {
scheme: "http",
host: "proxy.example.com"
},
proxyForHttps: {
scheme: "https",
host: "proxy2.example.com"
}
}
};
設定したプロキシの設定を元に戻すにはchrome.proxy.settings.clear
を呼び出す。
async function clearProxySettings() {
await chrome.proxy.settings.clear({ scope: 'regular' });
}
なお、chrome.proxy
を使用するにはmanifest.json
でpermissions
にproxy
の指定が必要である。
"permissions": [
"proxy",
"storage",
"tabs"
]
ここではchrome.storage
とchrome.tabs
も使用するのでstorage
とtabs
も指定している。
Chrome拡張のアイコンをクリックしたときの処理
アイコンをクリックしたときの処理を受け取るにはmanifest.json
にaction
の指定が必要になる。
"action": {}
action
の指定は空でよいが必要。
消してはいけない。
ようやくメインのコードだが、アイコンがクリックされるとchrome.action.onClicked
のイベントが呼ばれるのでaddListener
で処理を追加しておく。
プロキシ設定を有効にしたかのフラグはchrome.storage.session
から取得・保存しておく。
proxyEnableの値を反転して、値によりプロキシの設定をするか、設定をクリアするか切り替える。
chrome.action.onClicked.addListener(async () => {
chrome.storage.session.setAccessLevel({ accessLevel: 'TRUSTED_AND_UNTRUSTED_CONTEXTS' });
let data = await chrome.storage.session.get('proxyEnable');
let proxyEnable = !data.proxyEnable;
if (proxyEnable) {
await setProxySettingsFixedServer();
}
else {
await clearProxySettings();
}
await chrome.storage.session.set({ "proxyEnable": proxyEnable });
});
chrome.storage.session
を使用するには先にsetAccessLevel
を呼び出す必要がある。
ブラウザを閉じたときの設定クリア
実はchrome.proxy.settings.set
メソッドで設定した内容はブラウザを閉じても残っている。(終了時に自動で破棄されるような設定はみあたらなかった)
このため、ブラウザを再度開いた際に「Chrome拡張をクリックしてないのにプロキシがONになってるぞ??」という事態になってしまう。
これを避けるため、ブラウザを閉じたときに設定をクリアしておく。
ブラウザを閉じたかの判定はchrome.tabs.onRemoved
でremoveInfo.isWindowClosing
をチェックすればよい。
ここではremoveInfo.isWindowClosing
がセットされていたらプロキシ設定をクリアする。
chrome.tabs.onRemoved.addListener((_tabId, removeInfo) => {
if (removeInfo.isWindowClosing) {
clearProxySettings();
}
});
ソースコード