Proxy 切り替えアドオン @Firefox 59
Firefox 57 では、PAC を変更することしかできなかった WebExtension API 。
Firefox 59 で、ようやくプロクシの設定を切り替える手段ができた。
- https://developer.mozilla.org/en-US/Firefox/Releases/59#WebExtensions
- https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/browserSettings/proxyConfig
ぼくは、「プロクシなし」と「システム設定」を切り替えたいだけなので、こんな感じのアドオンで十分。
- ファイル構成
- manifest.json
- background.js
- スクリーンショット
- 強いて言えば
- FF 60.0b16 で動かなくなってる (2018-5-1 追記)
- 実装が変わった (2018-5-3 追記)
- manifest.json (FF 60.0b16 以降)
- background.js (FF 60.0b16 以降)
offsetLeft の罠
こちらのさいとう先生の画像を切り取ろうとしたときのこと。
あれ、ずれてる...
offsetParent をたどって行けば、良いんじゃなかったっけ (´・ω・`)
let e = ... let x = 0, y = 0; do { x += e.offsetLeft; y += e.offsetTop; } while (e = e.offsetParent); console.log(x, y);
(468, 1455) と計算されるけど、Firefox のものさしツールで測ってみると (514, 1454)。
46px も足りてない。
# ↓に たどり着くまで、かなりの日数が経ってます
画像の offsetParent の DIV には、border-left が指定されてる。
.NA_articleFigure { position: relative; border-left: 46px solid #fff; }
ああ、border の分を足してあげなきゃダメなんだ(border で位置を調整するんじゃねえよ
汎用的にやるためには、box-sizing も考慮してあげなきゃいけない。
こんな感じか。
let e = ... let x = 0, y = 0; do { x += e.offsetLeft; y += e.offsetTop; if (e.offsetParent) { let {borderTopWidth, borderLeftWidth, boxSizing} = window.getComputedStyle(e.offsetParent); if (boxSizing != "border-box") { x += parseFloat(borderLeftWidth); y += parseFloat(borderTopWidth); } } } while (e = e.offsetParent); console.log(x, y);
→ (514, 1455)
今どきは、getBoundingClientRect() 使おうね、って話でした。
let e = ... let {x, y} = e.getBoundingClientRect(); x += document.documentElement.scrollLeft; y += document.documentElement.scrollTop; console.log(x, y);
→ (513.75 1455.8) : なんだ、この小数点……
Promise vs async/await
背景というか、状況というか
Firefox の addon で、コンテンツプロセスでスクリプトをロードしたり、コードを実行したりする browser.tabs.executeScript() を続けて実行したい、という場面。
- ライブラリを使いたいんだけど、一部がエラーになる
- ライブラリに機能を追加したい
- でも、(何となく)ライブラリはいじらずにおきたい
- コンテンツプロセスでは、前回の状態が残っているので、ライブラリのロードは一回にしたい
「一部がエラーになる」というのは、
convertStringEncoding: function(str) { // for subscript loader return decodeURIComponent(escape(str || '')); },
この関数がこんなふうに呼ばれてて、
SketchSwitch.Buttons.RedPen = function(sketch) { this.sketch = sketch }; SketchSwitch.Buttons.RedPen.prototype = SketchSwitch.Utils.extend({ shortcut: null, icon: 'data:image/png;base64,iVBOR...', name: SketchSwitch.Utils.convertStringEncoding('赤ペン'),
URIError: malformed URI sequence というエラーが出ちゃう。
どうやら、XPCOM で、設定ファイルで非ASCII 文字を扱うときの あるある らしく、件のコードは UTF-8 → UTF-16 コンバータとして機能するらしい。
- Firefox 拡張機能の設定項目の保存時に日本語が化ける - vivid memo
- 4章:XPCOM活用術 - Firefox拡張機能開発チュートリアル (XHTML)
- javascript - decodeURIComponent vs unescape, what is wrong with unescape? - Stack Overflow
そのライブラリは、XPCOM のアドオンだったのだけれど、文字列リテラルに必要な処理だったのかどうかは謎だし、WebExtension では必要ない(というか、エラーになる)。
対応としては、convertStringEncoding()
を書き換えれば良いだけなんだけど、
- ライブラリをいじらずにおきたい
- ロードするときに呼ばれてる処理なので、後から置き換えるという手が通じない
ということがあって、ライブラリをロードする前に decodeURIComponent() を書き換えて、ロードが終わった後に戻す(ある意味、荒業
# 素直に、ライブラリをいじった方が良いんじゃないか(という気はしてる
で、こんな感じの処理の流れになる。
- ライブラリがロード済みかどうかを確認
- ライブラリがロードされてなかったら
- decodeURIComponent の実装を保存して、書き換える
- ライブラリをロードする
- decodeURIComponent の実装を戻す
- ライブラリの機能追加/変更のスクリプトをロードする
- ライブラリを使う
前置きが長くなりました。
で、実際のコード
Promise を使って書いたコード。
function show_sketch_menu(tab) { // https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/background.js let loaded_first = false; browser.tabs.executeScript(tab.id, { code: "typeof SketchSwitch === 'function'", }).then(result => { if (!result || result[0] !== true) { // SketchSwitch is not defined loaded_first = true; // for malformed URI --- SketchSwitch.Utils.convertStringEncoding() return browser.tabs.executeScript(tab.id, { code: ` original__decodeURIComponent = decodeURIComponent; decodeURIComponent = s => unescape(s); true; // Script '<anonymous code>' result is non-structured-clonable data `, }); } }).then(result => { if (loaded_first) { return browser.tabs.executeScript(tab.id, { file: "/content/SketchSwitch.js", }); } }).then(_ => { if (loaded_first) { return browser.tabs.executeScript(tab.id, { code: ` decodeURIComponent = original__decodeURIComponent; true; `, }); } }).then(_ => { if (loaded_first) { return browser.tabs.executeScript(tab.id, { file: "/content/sketch-patch.js", }); } }).then(_ => { return browser.tabs.executeScript(tab.id, { code: ` (_ => { const canvas = document.getElementById("__sketch_switch_canvas__"); if (canvas) { // Sketch Menu is shown. return; } const sketch = new SketchSwitch(window, {}); sketch.show(); })(); `, }); }).catch(error => { console.error(error.message || error); console.dir(error); }); }
こちらが async/await を使って、書き直したコード。
async function show_sketch_menu(tab) { try { // https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/background.js const result = await browser.tabs.executeScript(tab.id, { code: "typeof SketchSwitch === 'function'", }); if (!result || result[0] !== true) { // SketchSwitch is not defined // for malformed URI --- SketchSwitch.Utils.convertStringEncoding() await browser.tabs.executeScript(tab.id, { code: ` original__decodeURIComponent = decodeURIComponent; decodeURIComponent = s => unescape(s); true; // Script '<anonymous code>' result is non-structured-clonable data `, }); await browser.tabs.executeScript(tab.id, { file: "/content/SketchSwitch.js", }); await browser.tabs.executeScript(tab.id, { code: ` decodeURIComponent = original__decodeURIComponent; true; `, }); await browser.tabs.executeScript(tab.id, { file: "/content/sketch-patch.js", }); } await browser.tabs.executeScript(tab.id, { code: ` (_ => { const canvas = document.getElementById("__sketch_switch_canvas__"); if (canvas) { // Sketch Menu is shown. return; } const sketch = new SketchSwitch(window, {}); sketch.show(); })(); `, }); } catch(error) { console.error(error.message || error); console.dir(error); } }
思ったこと
こんなハイクをした後に書きました。
Promise を返してくれる API だったら、async/await は、気持ちすっきりするかなあ、という感じ。
行数もインデントも減るし。
書きながら思ったけど、Promise の方は、最初の一発目だけを、もうひとつの Promise でくくってあげれば、余計なフラグを持つ必要はなくなるのかも(試してない
}).then(result => { return new Promise((resolve, reject) => { if (!result || result[0] !== true) { // SketchSwitch is not defined // for malformed URI --- SketchSwitch.Utils.convertStringEncoding() browser.tabs.executeScript(tab.id, { code: ` original__decodeURIComponent = decodeURIComponent; decodeURIComponent = s => unescape(s); true; // Script '<anonymous code>' result is non-structured-clonable data `, }) .then(_ => { return browser.tabs.executeScript(tab.id, { file: "/content/SketchSwitch.js", }); }).then(_ => { ... }).then(_ => { resolve(); }).catch(_ => { reject(); } } }; }).then(_ => { ...
余計な変数は必要なくなるけど、インデントは深くなる。
自分で Promise 書いちゃうと、すっきりしないなあという感じはする。
こんなハイクのやり取りも。
http://h.hatena.ne.jp/noromanba/316607276733271244
http://h.hatena.ne.jp/noromanba/315956334695317249
おしまい。
ようこそ、Firefox 57 @うちの事情
人呼んで、Firefox Quantum 。
UI が大幅に変更され、かなりスピードアップする半面、旧式のアドオンがすべて使えなくなってしまう。
9/20 だったかに 57.0b1 に更新してから二ヶ月近くもじたばたしてる。安定版を使っている人たちも 2017-11-14には直面することになる。
そんな Firefox 57(というか、もう 58.0b1 になってる)の、ぼくんとこの事情。
- 使っているアドオンの状況
- Stylish → Stylus
- Toggle Proxy → ?
- はてなスクリーンショット拡張 → ?
- Gyazo のアドオンのソースを追っかけてみる
- さて...
- Bookmark Favicon Changer → ?
- アドオン以外の話
- パンがなければ、自分で焼けば良いじゃない
たばこ税とか
ここを見てて気になったので。
数字の推移
関連するイベント
日付 | トピック | たばこ税 (増分) |
消費税 | 価格 |
---|---|---|---|---|
値上げ | ||||
値上げ | ||||
JT設立 | ||||
値上げ | +0.9 | |||
消費税導入 | 0% → 3% | |||
消費税増税 | 3% → 5% | |||
たばこ特別税 | +0.82 | |||
たばこ税税率変更 | +0.82 | |||
たばこ税税率変更 | +0.852 | |||
たばこ税税率変更 | +3.5 | |||
消費税増税 | 5% → 8% | |||
値上げ |
所感
たばこの値段が上がったから喫煙人口が減っているというふうには見えない。
1996年くらいからだいたい同じくらいの割合で喫煙人口が減っていってて、税収を確保するために税率を上げているという状況に見える。
鳩山くんのときの +3.5円/本の税率アップは、健康云々を謳ってたような気もするけれど、税収確保が先にあって後付けの理由じゃないかという気もする。
ひとり当たりの消費量は、一箱/日であまり変化してない。
健康を気にしてる人は、減らすんじゃなくて止める、とかだろうか。
禁煙外来で保険が使えるようになったのが 2006年4月だから、ライトなスモーカーは止めちゃおうか、というタイミングだったのかも(喫煙人口が減ってて、ひとり当たりの消費量が増えてる)。
2016年度に販売本数が落ち込んでいるのは、IQOS の影響大だと思う。
きっと、2017年度も落ち込み幅は大きいはず。
税収には含まれてるはず(→参考)なので、税収は販売本数ほど落ち込んでない。
参考
- http://www.health-net.or.jp/tobacco/product/pd090000.html
-
喫煙率 S40~H29
JT の調査
- http://www.health-net.or.jp/tobacco/product/pd100000.html
-
喫煙率 H1~H26
厚生労働省の調査では、H6~8 で喫煙率が上昇している
- http://www.stat.go.jp/data/jinsui/2.htm#series
-
人口推計資料 長期時系列データ
T9~H12、H12~H27
- http://www.mof.go.jp/tax_policy/summary/consumption/d09.htm
-
財務省 たばこ税の内訳
税収と販売数の推移
S60~S62、 H6~H27
- http://www.tioj.or.jp/data/
-
日本たばこ協会 販売数量
- http://www.tioj.or.jp/data/pdf/100423_02.pdf
H2~H21 国産と輸入の数字あり - http://www.tioj.or.jp/data/pdf/170421_02.pdf
H2~H28 合計のみ
- http://www.tioj.or.jp/data/pdf/100423_02.pdf
- http://www.mof.go.jp/about_mof/councils/fiscal_system_council/sub-of_tabacco/proceedings/material/tabakoa270529.pdf
-
財務省 たばこ産業を取り巻く状況
紙巻たばこの販売数量の推移 P19
S60~H26
- http://www.mof.go.jp/tax_policy/reference/account/data.htm
-
財務省 租税及び印紙収入決算額調べ
H9~H28
- http://www.soumu.go.jp/menu_seisaku/hakusyo/index.html
-
総務省 地方財政白書
道府県たばこ税、市町村たばこ税
平成29年度版まで
平成29年度版は、平成27年度の数字
- http://www.soumu.go.jp/main_content/000397821.pdf
-
平成28年度地方団体の歳入歳出総額の見込額
- http://www.health-net.or.jp/tobacco/product/pd070000.html
-
厚生労働省 販売本数と一人当たり消費本数
1920~2007
1985年(S60年)の販売本数が財務省のデータと違う。
- http://www.garbagenews.net/archives/2102668.html
-
たばこ税収
1996~2016
単位:兆円
- http://www.sangiin.go.jp/japanese/annai/chousa/keizai_prism/backnumber/h21pdf/20096623.pdf
-
平成元年付近の販売数量、税収(グラフだけ)
- http://www.cao.go.jp/zeicho/siryou/pdf/kiso15i.pdf
-
H1~H14 たばこ税税収
単位:億円
- http://www.tioj.or.jp/others/
-
H17~H26 たばこ税税収
単位:億円
- http://www.esri.go.jp/jp/archive/bun/bun077/bun77e.pdf
-
専売納付金
S35~S53 - http://kero.sq4u.jp/2012/06/22/%E3%82%BF%E3%83%90%E3%82%B3%E3%81%AE%E5%80%A4%E6%AE%B5%E6%8E%A8%E7%A7%BB/
-
価格の推移(マイルドセブン・メビウス)
- http://kokkai.ndl.go.jp/SENTAKU/sangiin/193/0015/19304100015004a.html
-
参議院 決済委員会 H29-4-10
IQOS なんかの税率 - https://ja.wikipedia.org/wiki/たばこ税
-
「税収の推移」の数字は、ちょっと誤解を招く。
「国たばこ税税収」は「たばこ特別税」を含んだ数字。
「都たばこ税」が、地方税の「道府県たばこ税」に含まれる。
23区のたばこ税は、「市町村たばこ税」に含まれる。 - http://www1.mhlw.go.jp/wp/2-3-1.html
-
厚生省 H9年厚生白書
喫煙率とたばこ販売量の推移
グラフだけ
以下、さほど参考にならないやつ
(´ー`)y-~~