Quantcast
Channel: 風柳メモ
Viewing all 92 articles
Browse latest View live

BIGLOBE光ネクストのv6プラス利用による通信速度改善について

$
0
0

furyu.hatenablog.com

で書いた通り、BIGLOBE光ネクスト ファミリー・スーパーハイスピードタイプ隼(NTT西日本エリア・最大1Gbps)にて、v6プラスを利用した際に速度改善効果が見られた。
これを IPv4 over IPv6 IPoE接続と、旧来のIPv4 PPPoE接続との、一日の通信速度変化を比較することで示す。

結果

2016/10/07 分

f:id:furyu-tei:20161008025125p:plain

IPv4 PPPoEでは、一日の間で通信速度の変動が激しく、特に00:00~01:30頃と18:30~24:00頃には数百Kbps~10Mbps程度にまで低下している。
一方で、v6プラスで提供されているIPv4 over IPv6 IPoEについては、一日を通して50~90Mbps程度の間であり、PPPoEと比較すると安定な水準にある。

[2016/10/15 追記] 2016/10/07~10/13 一週間分の結果

下記の記事参照。
furyu.hatenablog.com

[2016/11/29 追記] 平日と土日祝日の比較など

下記の記事参照。
furyu.hatenablog.com

測定条件など

環境

f:id:furyu-tei:20161010003054p:plain

条件
  • さくらのレンタルサーバ(スタンダード)上に、20MBのファイルを設置
  • Web サーバ(CentOS 6.x)上から、wget コマンドにて上記ファイルを10分間隔でダウンロードし、転送速度を記録
    IPv4 over IPv6 IPoE(eth1側)とIPv4 PPPoE(eth0側)とをrouteコマンドでGatewayを変更することにより切り替えている。また、それぞれの測定タイミングは5分ずつずらしている。
注意事項
  • さくらのレンタルサーバにおける帯域制限の影響については考慮していない。
    以前のデータ(2015/08/05~112015/08/12~18)と比較すると、PPPoEにおいても速度の上限はあがっている(~50Mbps→~90Mbps)ように見えるが、これが、さくら側の帯域制限緩和によるのか、それとも、ISP側の改善結果なのかは不明。

BIGLOBE光ネクストIPv4通信速度調査:PPPoE対v6プラス(2016/10/07~2016/10/13の一週間の傾向)

$
0
0

furyu.hatenablog.com
の続きで、一週間継続して測定した結果を示す。
測定条件等は前の記事を参照のこと。

IPv4 PPPoE については、以前一週間の傾向を調べたとき(2015/08/12~18)から改善は見られない(むしろ、夜間の通信速度低下は悪化して見える)ことから、同じような傾向で悩んでいる方は、v6プラスの利用を検討しても良いかもしれない。
まぁ、このあいだの記事でも書いたとおり、制約も多いのだけれども。

結果(2016/10/07~2016/10/13)

IPv4 PPPoE 対 IPv4 over IPv6 IPoE(v6プラス)比較

f:id:furyu-tei:20161015095825p:plain

  • PPPoEは高低の差が大きく、特に夜間には輻輳の影響のためか急激に速度が低下
  • IPv6 IPoE(v6プラス)は時間帯による通信速度の変化は小さい
IPv4 PPPoE

f:id:furyu-tei:20161015095747p:plain

  • 週間を通じて、夜間(19時頃~25時頃)の通信速度低下が顕著
  • 土日や祝日(10/8~10)には、09時頃から急な速度低下が見られる
IPv4 over IPv6 IPoE(v6プラス)

f:id:furyu-tei:20161015095557p:plain

  • 時間帯や、休日の影響による差は、現状PPPoE程は見られない

Evernote からエクスポートした HTML を Word 文書に一括変換する方法を調べてみた

$
0
0

Evernote のノートは HTML 形式でエクスポートできるが、そのままでは編集しづらいので Word 文書にできないか? という相談を受けたので、調べてみた。

基本的には、

  1. Evernote で対象となるノートを選択し、「複数の Web ページファイル (.html) でエクスポート」にてエクスポート
  2. Word で HTML ファイルを開き、Word 文書 (.docx) として保存しなおす

でいけるような気がしたが、 手動でいちいち変換するのは面倒なので、VBScript でまとめて処理できるようにしようとした。

ところが、VBScript に不慣れなのと、思わぬ問題も出てきて試行錯誤が必要になったため、その覚え書きとして記事の形にまとめておく。




EvernoteHtmlToWord (VBScript)

最終的にできあがった、Evernote からエクスポートした HTML を Word 文書化するための VBScript。
github.com

VBScript の処理内容と試行錯誤など

やっていることは、ドラッグ&ドロップされた *.html ファイル(もしくは、フォルダ直下に含まれる *.html ファイル)を順に Word で読み込み、Word 文書 (*.docx) 形式で保存しているだけ……なのだけれど、意外と苦労した。

画像が外部参照になってしまう

Word で HTML を読み込み、そのまま形式を Word 文書 (*.docx) として保存しただけだと、画像が外部ファイルへのリンクのままとなってしまう。
文書内に画像を埋め込もうとすると、 Word 上の操作では、

「ファイル」タブ→(右側の「関連ドキュメント」の)「ファイルへのリンクの編集」で、『種類:図』のリンク元ファイルを選択し[リンクの解除]を実施、「☑ 文書に図を保存する」にチェックをして[OK]をクリック

となるような処理を、VBScript 上でも行う必要があった。

Sub EmbedImages

Sub EmbedImages( objDocument )ForEach objShape In objDocument.InlineShapes
        IfNot objShape.LinkFormat IsNothingThen
            objShape.LinkFormat.SavePictureWithDocument =True
            objShape.LinkFormat.BreakLink
        EndIfNextEndSub

※参考:word VBA for save picture in document - Stack Overflow


ファイル名にタイムスタンプを付けたい

ファイル名で並べたときに、時系列順にしたいという要望があった。
これは、Evernote からエクスポートした際、オプションで「☑作成日(C)」にチェックして、*.html ファイル内に「作成日」等を埋め込み、これをファイル名に反映することで対応。
地味に、Wordの全テキスト取得方法を調べるのに手間取った……
Function EvernoteTimeStamp
ファイルの作成日時・更新日時を変えるようにした方がよかったかも?
更新日時については変更するようにしてみた(作成日時は変更方法がわからなかった)

タイムスタンプの時刻が一桁のときがある

Evernote からエクスポートした *.html の作成日は、「作成日: 2016/11/19 2:34」のように、時刻が一桁の時があるが、ファイル名に使うなら 0 パディングしたかったので、処理を追加。
Function PadLeft
※参考:まいてっくぶろぐ - 【VBS】文字列が指定桁数に満たない場合、0詰めする関数

作成日がうまく取得できない(日本語文字列が検索でひっかからない)

"作成日[^\d]*(\d+)/(\d+)/(\d+)[^\d]*(\d+):(\d+)"のような日本語を含む正規表現で検索しようとすると、うまくいかない。
これは、VBScript ファイル (EvernoteHtmlToWord.vbs) を UTF-8 で保存していたため。
ファイル形式を Unicode に変更すると、うまく検索できるようになった。
ファイル形式は Shift JIS でも可。

ファイル名が原因で変換されないファイルがある

ドラッグ&ドロップで指定したファイルのいくつかが変換されていなかった。
調べてみると、ファイル名に『〜』(U+301C)や『プ』(U+30D5 U+309A)等の文字が含まれる場合には、うまく変換できない模様。
これはどうも、WScript.Arguments からファイル名を取り出した時点ですでに化けてしまっているらしく、<FileSystemObject>.FileExists()が False を返す。

当該ファイルを直接ドラッグ&ドロップする場合にはうまい解決策が見つからなかったが、それらのファイルが入ったフォルダをドラッグ&ドロップし、<FileSystemObject>.GetFolder() で取得した Folder オブジェクトFiles コレクションからパス名(.Path)を取得するようにすると、こちらはうまく処理できる模様。

ドラッグ&ドロップするファイル数が多すぎると実行できない

ファイルをドラッグ&ドロップで指定する場合、数が多すぎると「実行できません。引数一覧が長すぎます。」というダイアログが出て、実行できない模様。
VBScript の制限だと思われる。自分の環境では、495ファイル以上でファイルで発生(494ファイルはOK)。これがマジックナンバーなのか、その他の要因があるのかは不明。
この場合は、対象ファイルが入ったフォルダをドラッグ&ドロップしてやれば、その中に495ファイル以上の *.html があっても、実行可能。

BIGLOBE光ネクストIPv4通信速度調査:PPPoE対v6プラス(平日と土日祝日の比較)

$
0
0

承前。
furyu.hatenablog.com

前回測定時に、平日と土日祝日で随分と(特にPPPoEの)傾向に違いがあるように思えたので、同じ日数分(19日分)のデータを使用して、平日と土日祝日とで分けてプロットしてみた。

平日と土日祝日の比較

平日

f:id:furyu-tei:20161129204321p:plain
02時~16時頃であれば、PPPoEの方がv6プラスよりも良い結果が出ているため、その時間帯ならPPPoEでも可……?
一般的な会社員にはいささか使いづらい時間帯ではあるが。

土日祝日

f:id:furyu-tei:20161129204334p:plain
03時~08時頃を除き、PPPoEでは速度の低下が著しいため、可能であればv6プラスを使用するのが吉。

ここ最近の推移

各期間(7日間)の時間帯毎の中央値をプロットしたものを参考までに示す。


2016/10/07~10/13

2016/10/14~10/20

2016/10/21~10/27

2016/10/28~11/03

2016/11/04~11/10

2016/11/11~11/17

2016/11/18~11/24

Windows 10 のバージョン 1703 が酷かったので、急いで 1709(Fall Creators Update)を適用した

$
0
0

バージョン 1703 の憂鬱

先日、Windows 10 が自動的にバージョン 1703 になっていたのだけれど、自分の環境(NJ5700E)ではこれが酷かった。

  • Capsに割り当ててあったCtrlが無効化されていた
  • "Microsoft KM-TEST Loopback Adapter"(CIFS over SSH用)が削除されていた
  • Windows 10 アップデート前に、タスクバーにピン留めしてあったアプリの一部が消えてしまっている
    エクスプローラー、IE、Chrome、Firefox、Vivaldi、FileZilla等……サードパーティ製ブラウザが軒並み消えていたのには悪意を感じてしまう……
  • ↑を再登録しても、再起動したりログオフ/オンするともとに戻ってしまった
  • タスクバーを引き伸ばして2段の状態で「タスクバーを固定する」にチェックを入れているのに、再起動等すると一段の状態に戻ってしまう
  • MS-EdgeのTampermonkeyでユーザースクリプトがインストールできなくなった(アイコン点滅・読み込み状態がずっと続く)
  • 無効化してあった Windows Search が有効になっていた
  • WZ Editor 9(WZ 9.0.29)が起動しなくなってしまった
    これは最新の WZ 9.0.46 をダウンロードして入れなおすことで解消

バージョン 1709(Fall Creators Update)の適用後

1703 での対処方法を探すのも面倒だし、すでに 1709 が提供されていたので、これを適用後に対処することに。

新たな問題
  • ディスプレイアダプタ(NVIDIA GeForce GT 640M)が、「ビデオ コントローラー(VGA 互換)」となってドライバが入っていない
  • ハイバネーション(休止状態)が有効になっていて、hiberfil.sys がディスク容量を圧迫
自動解決
  • タスクバーにピン留めしていたアプリが消えたり、再起動で無くなったりといった症状は改善
  • MS-Edge の Tampermonkey の上記不具合は解消、普通に動作するように
手動で対応
  • Caps → Ctrl は手動で再度設定(Ctrl2capを使用)
  • "Microsoft KM-TEST Loopback Adapter"は再インストール
    デバイスマネージャー → 操作(A)→レガシ ハードウェアの追加(L)から入れ直し
  • Windows Search は手動で無効化(こちらの記事を参照)
  • ディスプレイアダプタは、NVIDIAドライバダウンロードからドライバをダウンロード・インストールして対応
  • hiberfil.sys を削除(こちらの記事を参照)
未解決
  • タスクバーを2段に引き伸ばした状態での「タスクバーを固定する」はうまく動かないまま(再起動等すると1段に戻ってしまう)

Chrome 拡張機能の移植準備( Firefox Quantum・WebExtensions 編)

$
0
0


前書き

Firefox が Firefox Quantum (57) になり、旧来のアドオンとの互換性が無くなった代わり、Google Chrome 拡張機能等との互換性の高い WebExtensions という形式に変わった。

WebExtensions とは、クロスブラウザで動作可能なアドオンを開発するための技術です。WebExtensions API の大半は、Google Chrome や Opera でサポートされている extension APIと互換性があります。これらのブラウザ向けに書かれた拡張機能のほとんどは、少し変更を加えるだけで Firefox や Microsoft Edge でも動かせるようになります。また、WebExtensions API はすべて マルチプロセス Firefoxに対応しています。

WebExtensions とは何か? - Mozilla | MDN

それではということで、自作の Chrome 拡張機能を Firefox Quantum に移植してみようか(できればソースコードは完全に共通化したい)と思い立ち、とりあえず Firefox Quantum でのアドオン開発の準備をしてみた。

アドオン開発の手順

開発(移植)するアドオンの読み込み

f:id:furyu-tei:20171117072218p:plain
Firefox 開発ツール デバッガー(about:debugging#addons、≡→アドオン(Ctrl+Shift+A)→[歯車アイコン]→アドオンをデバッグ(B))を開き、「☑ アドオンのデバッグを有効化」にチェックを入れて、[一時的なアドオンを読み込む]を押す。

f:id:furyu-tei:20171117072224p:plain
開発対象となる拡張機能(アドオン)の manifest.json を選択して開く。

f:id:furyu-tei:20171117072229p:plain
manifest.json を元にして、当該拡張機能の情報が「一時的な拡張機能」欄に表示される。
ここで、エラーや警告等があれば、適宜修正する。
Quantum の manifest.json のチェックは、Chrome に比べてかなり甘いかも(適当にコメントっぽく書いた行とかでもエラーが出なかったり)。逆に、Chromeに持って行くとエラーが出てしまうことがあるので注意。

バックグラウンドページのデバッグ方法

f:id:furyu-tei:20171117072235p:plain
拡張機能のデバッグリンクをクリック。

f:id:furyu-tei:20171117072241p:plain
「リモートデバッグ接続要求」ダイアログが表示されるので、確認して[OK]を押す。
この手順を省略する方法はあるのかな……?

f:id:furyu-tei:20171117072247p:plain
開いた開発ツールを使ってデバッグを実施。

オプション画面のデバッグ方法

f:id:furyu-tei:20171117072251p:plain
オプション画面をデバッグしようと思って……

f:id:furyu-tei:20171117072256p:plain
コンテキストメニューを開くも、「要素を調査」とか出ない……どうやって開発ツールを開けばよいのか……

f:id:furyu-tei:20171117072301p:plain
……と、Firefox 開発ツール デバッガーの当該拡張機能のところに、マニフェストの URLというリンクがあるので、これをクリックしてみる。

f:id:furyu-tei:20171117072306p:plain
マニフェストがタブに開くので、URLの "/manifest.json"の箇所を……

f:id:furyu-tei:20171117072315p:plain
オプション画面の HTML がある相対パス(例では "/html/options.html")に書き換えて開く。

f:id:furyu-tei:20171117072323p:plain
すると、無事にオプション画面をタブに読み込むことが出来た。
後は、開発ツール([F12]、≡→ウェブ開発→開発ツールを表示(Ctrl+Shift+I))を開いて、デバッグを行うことが出来る。
もっとスマートな方法がありそうな気もする……。

Chrome 拡張機能の移植準備( Microsoft Edge 拡張機能編)

$
0
0


前書き

承前。
furyu.hatenablog.com

比較の意味もあって、Microsoft Edge に関しても拡張機能開発(移植)準備をしてみた。
結果から言えば、互換性や動作安定性が悪く、時期尚早だったな、と少し後悔している。

なお、MS-Edge の拡張機能は、まだ限られた開発者しか公開できない模様。
Microsoft Edge拡張機能の公開について - マイクロソフト コミュニティ
developer.microsoft.com

I have an extension ready for Edge. How can I get it submitted to the store?

For the Windows 10 Anniversary Update, we are intentionally starting with a small set of extensions. The list of extensions is locked - you can see the list at our extensions page here. We want to be mindful about what extensions are available on the platform and watch for telemetry and feedback and make sure the reliability, performance and functionality of the browser isn’t impacted by these new features. Extension developers can submit a request to https://aka.ms/extension-request to be considered for a future update.

Frequently Asked Questions - Microsoft Edge Development

拡張機能開発の手順

開発者向け設定の有効化

フラグ設定画面(about:flags)を開き、

f:id:furyu-tei:20171117203010p:plain
「開発者向け設定」の「☑ 拡張機能の開発者向け機能を有効にする (これによりデバイスが危険にさらされる可能性があります)」にチェックを入れる。

開発(移植)するアドオンの読み込み

右上にある「…」から、

f:id:furyu-tei:20171117203016p:plain
「拡張機能」を選択すると、[拡張機能の読み込み]というボタンが出来ている。

f:id:furyu-tei:20171117203024p:plain
これを押して、

f:id:furyu-tei:20171117203034p:plain
出てきたダイアログから、開発(移植)しようとする拡張機能の manifest.json が含まれたフォルダを選択する。

f:id:furyu-tei:20171117203039p:plain
マニフェストにエラーがあればその旨表示されるので、適宜修正して再読み込みする。
正常に読み込めたら、

f:id:furyu-tei:20171117203045p:plain
当該拡張機能が表示される(この時点で既に起動されている)。

ここで歯車アイコンをクリックすると、

f:id:furyu-tei:20171117204946p:plain
拡張機能の基本情報と操作用のメニューが表示される。

バックグラウンドページのデバッグ方法

拡張機能操作用メニューから

f:id:furyu-tei:20171117203052p:plain
「検査:バックグラウンド ページ」リンクをクリックすると、

f:id:furyu-tei:20171117203059p:plain
開発者ツールが開き、バックグラウンドページのデバッグを行うことが出来る。

オプション画面のデバッグ方法

右上にある当該拡張機能のアイコンをクリックすると、オプション画面がポップアップする。

f:id:furyu-tei:20171117203104p:plain
適当なところで右クリック(コンテキストメニュー)から、「要素の検査」を選択すると、

f:id:furyu-tei:20171117203110p:plain
開発者ツールが開き、オプション画面のデバッグが行える。

ポップアップから操作するのがやりにくい場合、少し面倒だがタブで開くこともできる。
拡張機能操作用メニューに表示されているIDから、

f:id:furyu-tei:20171117203124p:plain

ms-browser-extension://<拡張機能のID>/<オプション画面(HTML)への、manifest.json があるフォルダからの相対パス>

のようにして、URL が導かれるので、これをブラウザのアドレス欄に入れることで、オプション画面をタブで開くことが出来る。

f:id:furyu-tei:20171117203144p:plain

Chrome 拡張機能を Firefox Quantum の WebExtensions にも対応させた例

$
0
0


前書き

とりあえず、自作の Chrome 拡張機能のうち、二つを Firefox Quantum (WebExtentions) にも対応させてみた。
Twitter 原寸びゅー – Firefox 向けアドオン
Twitter メディアダウンローダ – Firefox 向けアドオン
この際に修正した箇所を中心に、覚え書きを記しておく。

修正方法等

manifest.json

最初、次のような警告が出ていた。

Reading manifest: Error processing background.persistent: Event pages are not currently supported. This will run as a persistent background page.
Reading manifest: Error processing options_page: An unexpected property was found in the WebExtension manifest.

上の方は、

,   "background": {"scripts" : ["js/background.js" ]
    ,   "persistent" : true}

の "persistent"オプションに関するもので、現状は Firefox ではサポートされておらず、無視される。動作的には特に問題ないので、このまま。

下の方は、

,   "options_page" : "html/options.html"

に関するもので、エラーとなっているが、このままでもオプションページは開くことが出来る。
現在は、

,   "options_ui" : {"page" : "html/options.html"
    }

という書き方になっているため、こちらに合わせておく。

jQuery

jQuery 読み込み時に、

  Content Security Policy: ページの設定により次のリソースの読み込みをブロックしました: self (“script-src moz-extension://7959b7cd-9bbb-443f-8362-df4673e654f6 'unsafe-eval'”) Source: onfocusin attribute on DIV element.

のようなエラーが出ていた。
どうも、v1.x 系を使用していると発生する模様(使用していたのは、v1.11.3)。
参考:Web Extension: Cannot load jQuery into background page, due to CSP - Development - Mozilla Discourse
これは、v2.x 系にて修正されているらしい。v2.2.4 にしたところ、発生しなくなった。

chrome.app.* は使わない

オプション画面の、拡張機能バージョンを取得する処理でエラーが発生していた。
原因は、chrome.app.getDetails().version を使用していたこと。
代わりに chrome.runtime.getManifest().version を使うことで解決した。
参考: [Where is chrome.app officially documented? - Stack Overflow](https://stackoverflow.com/questions/9167150/where-is-chrome-app-officially-documented)

browser.* ネームスペース対応

これまで chrome.* ネームスペースを使用していたが、今後の流れとしては browser.* ネームスペースを使う方が良さそう。
参考: [Chrome incompatibilities - Mozilla | MDN](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities)

といいつつ、既存のものを全部書き換えるのは煩わしいので、各スクリプトの先頭に

window.chrome = ( ( typeof browser != 'undefined' ) && browser.runtime ) ? browser : chrome;

のような一行を入れておくことでお茶を濁してある。

なお、Firefox Quantum の WebExtensions では、browser と chrome の両方が定義されているが、コンテキストによって微妙に見え方が違う。

バックグラウンドコンテキスト(background)

chromewindow.chromebrowserwindow.browser
Chrome 拡張機能××
Firefox WebExtensions
MS-Edge 拡張機能××

ユーザーコンテキスト(content_scripts)

chromewindow.chromebrowserwindow.browser
Chrome 拡張機能××
Firefox WebExtensions××
MS-Edge 拡張機能××

独り言

とりあえず、Twitter 原寸びゅーTwitter メディアダウンローダに関しては、以上のような修正を行うことで、無事、Firefox Quantum でも動作するようになり、かつ、Google Chrome 上でもこれまで通り動作しているので、共用化できたと言える。
もともと、ユーザースクリプトとしては両方の環境で動作するように作成してあったため、最低限の修正で済んだといえる。
まぁ、細かい不具合は出ているのだが……。


【覚書】Firefox アドオン (WebExtensions) を AMO で公開した際の手順

$
0
0


前書き

Chrome 拡張機能を Firefox Quantum (WebExtentions) にも対応させたので、せっかくだしと AMOにも登録してみることに。
その手順を覚え書きとして記しておく。

手順

アドオン開発者センターにユーザー登録

Firefoxアカウントを未所持の場合、アドオン開発者センターにて、ユーザー登録を行う。

f:id:furyu-tei:20171117232228p:plain
f:id:furyu-tei:20171117232239p:plain

自作アドオンのアップロード準備

当該アドオンの全ファイルを一つの ZIP アーカイブにまとめる(アドオンのパッケージ化)。
この際、manifest.json 及び同一フォルダ内のファイルが一番上の階層になるようにアーカイブすること。

あなたのWebExtensionは次のものを格納したディレクトリです。manifest.jsonとその他の必要なファイル-スクリプト、アイコン、HTMLドキュメント等。あなたはこれらを1つにまとめたzipファイルをAMOにアップロードする必要があります。

ひとつトリッキーなこととして、ZIPファイルはWebExtensionを構成するファイルを含み、ディレクトリに入ってはいません。

WebExtensionを公開する - Mozilla | MDN

At this point your extension will consist of a directory containing a manifest.json and any other files it needs - scripts, icons, HTML documents, and so on. You'll need to zip these into a single file for uploading to AMO.

One trick is that the ZIP file must be a ZIP of the extension's files themselves, not of the containing directory.

Publishing your extension - Mozilla | MDN

OKな例

manifest.json
html/options.html
js/background.js
 :

NGな例

src/manifest.json
src/html/options.html
src/js/background.js
 :

自分の場合、src/manifest.json のように src 以下に全て置いていたため、src フォルダを含む形で ZIP を作っていたところ(実際、Chrome 拡張機能の場合はこれでも問題なくアップロードできる)、AMOにアップロードしようとしたらエラーが出てしまった。

新しいアドオンの登録

アドオン開発者センター

f:id:furyu-tei:20171117232245p:plain
[新しいアドオンの登録]ボタンを押して、登録を開始する。

f:id:furyu-tei:20171117232252p:plain
配布手段を選択し、[続ける]を押す。
特に理由がなければ、「◉当サイト上で……」で良いと思う。

f:id:furyu-tei:20171117232258p:plain

f:id:furyu-tei:20171117232304p:plain
前の手順で準備した パッケージ(ZIP ファイル)をアップロードすると、アドオンの検証が行われ、結果が表示される。

f:id:furyu-tei:20171117232309p:plain
「検証レポートの詳細を見る」をクリックすると、詳細な検証レポートが開く。

f:id:furyu-tei:20171117232319p:plain
これをチェックし、問題があれば修正する。
eval等を使用しているといった警告はあったが、自作以外のライブラリなこともあり、対応はせずにそのまま。エラーでなければ継続できるらしい。

f:id:furyu-tei:20171117232325p:plain

f:id:furyu-tei:20171117232332p:plain
「アドオンの説明」画面に必要事項を記入・入力し(名前と概要は manifest.json に記載のものが転記されている)、[バージョンを登録]を押して登録する。

f:id:furyu-tei:20171117232338p:plain
登録完了後、[掲載ページを管理]を押すと、

f:id:furyu-tei:20171117232347p:plain
アドオンに関する各種情報を確認・変更できるので、必要に応じて追記や修正を行う。

余談

「『AMO』ってなんだろう、サイト名としては『Firefox Add-ons』か『Add-ons for Firefox』かだよね…」とか思っていたのだが、これ、ドメイン名である"addons.mozilla.org" の頭文字を取ったものだったのか……。

Chrome 拡張機能を Microsoft Edge の拡張機能にも対応させようとして挫折した件

$
0
0


前書き

承前。
furyu.hatenablog.com
furyu.hatenablog.com
せっかくだから、Firefox Quantum に対応できた拡張機能を、MS-Edge でも動かしたいと欲張ったのだが……見事に挫折した(哀)。

修正方法等

manifest.json

「マニフェスト解析エラー: 'author'フィールドが見つかりません。」と出たので、author フィールドを追加。

browser.* ネームスペース対応

WebExtensions 用に、予め対応してあった。

PATH の問題

オプション画面にて、chrome.browserAction.setIcon( { path : icon_path } ) を使ってアイコンを変化させる処理を書いてあったところ、MS-Edge ではアイコンが正常に表示されなくなった。
調べてみたところ、どうも、アイコンの PATH の指定が、

  • Chrome 拡張機能 / Firefox WebExtensions → 呼び出し元の HTML(オプション画面)からの相対パス
  • MS-Edge 拡張機能 → manifest.json のあるフォルダからの相対パス

のように違いがあるようで、場合分けが必要だった。

未解決問題

以下は、Microsoft Edge 41.16299.15.0 / Microsoft EdgeHTML 16.16299 で発生

fetch() や XMLHttpRequest で ArrayBuffer を使用すると未定義のエラーが発生

ユーザーコンテキスト(content_scripts)で fetch() を使用すると、

  SCRIPT65535: 未定義のエラーです。

どうやら、同様の現象が他でも見られるみたい。
Fetch API in Extension SCRIPT65535 error - Microsoft Edge Development
https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/attachment/14192157/8236868/

同様に、XMLHttpRequest で、xhr.responseType を 'arraybuffer'に設定した場合に、xhr.response を参照しようとするとエラーとなってしまう。

  SCRIPT65535: 未定義のエラーです。

いったん、responseType を 'blob'にして受けてやると response は参照できるので、これを ArrayBuffer 化することは可能だった。
ただ、その場合でも、JSZipの アーカイブ処理(JSZip#generateAsync)で失敗してしまう。

よって、MS-Edge の拡張機能では、Twitter 原寸びゅーや Twitter メディアダウンローダで使用している JSZip による ZIP 化が出来ず、ZIP ダウンロード機能が無効化してしまう。
特に、メディアダウンローダの方はほぼすべての機能が使えなくなってしまう……(哀)。

バックグラウンドでのダウンロードができない

バックグラウンドコンテキスト(background)内では、現状、ファイルのダウンロードができない模様。

Overarching issues
The following known issues span across the extension platform and will be fixed in the near future:
: (中略)
・Triggering a download via a hidden anchor tag will fail from background scripts. This should be done from an extension page instead.

Extensions - Supported APIs - Microsoft Edge Development | Microsoft Docs
  • browser.downloads API は存在しない(2017/04/11現在のロードマップで、"Under consideration" になっている
  • a タグの download 属性を使ったダウンロードも不可(click()してもダウンロードされない)
  • navigator.msSaveOrOpenBlob() 等も使えない
    SCRIPT16386: インターフェイスがサポートされていません
  • tabs.create() で新たにタブを開いてそちらでやろうとしても、background から開いた場合には上記の不具合が継承されてしまう

ということで、八方ふさがり。
Twitter 原寸びゅーのコンテキストメニューからの「原寸画像を保存」が実現出来ない。
background から content_scripts 宛に sendMessage() して、そちらで処理ならできるかも?でも面倒くさそう……。

余談

というわけで、自作拡張機能を MS-Edge に対応させることは、少なくとも現状では諦めた。
まぁ、出来た拡張機能を公式に公開するすべは今のところ無さそうだし良いけど。

それにしても MS-Edge は、拡張機能を開発しやすいとはお世辞にも言えないな……。

  • 拡張機能関連のメニューが自動的に隠れてしまうため、アクセスしずらい
    "about:flags"みたいに、タブに独立して出す方法はある?
  • 開発者ツールでデバッグしていると固まりやすく、またかなりの確率でブラウザごと落ちてしまう
  • 上記の fetch() のように、拡張機能のコンテキストでのみ動作しない不具合が多い

それでもめげず(?)、便利な拡張機能を公開されている限られた方々には頭が下がる訳だが。

少なくとも自分は、当面 MS-Edge では開発したくない。
幸い、MS-Edge にも Tampermonkey があるので、当方の拡張機能を使いたい方は、Tampermonkey を入れて、ユーザースクリプト版をお使いいただきたい。
とか言っていたら、MS-Edge 版の Tampermonkey が TweetDeck では異常が発生し、ユーザースクリプトを動かせない不具合を見つけてしまったり……。

ブラウザ拡張機能用に background で ZIP 化するためのライブラリを試作(Chrome拡張機能/Firefox Quantum WebExtensions 用)

$
0
0


前書き

WebExtensions について調べていると、Promise を使用して云々……という記述が出てきて、今さらながらに Promise というものの存在を知りました(ヲイ。
慣れれば使い勝手が良さそうなので、練習を兼ねて、ブラウザ拡張機能の background で ZIP 化することが出来るようなライブラリを試作してみました。
github.com
習作なので、いつも以上に動作保証できません。ご利用は計画的に(汗)。

概要

content_scripts に対し、ZipRequest クラスを提供します。
ZipRequest#open()/file()/generate()/close() という一連の関数にて、background に対してメッセージを送ることで ZIP 化に関する指示を出し、background からの応答メッセージで結果を受け取り、content_scrips に返します。
background での ZIP 化には、JSZipを使用しています。

比較する意味もあって、content_scripts 用には Promise を使ったもの(Promise版・zip_request.js) と、使わないもの(コールバック版・zip_request_legacy.js)とがあります。
background 用のもの(zip_worker.js)は共通です。

サンプル

はてなブログ("*://*.hatenablog.com/*")を開くと、画像を適当な数選んで ZIP 化・ダウンロードする、という迷惑な(汗)サンプルコード(抜粋)です。
サンプルソースコード全文は、こちらをご覧ください

並列処理

複数のファイルを同時並行で取得しながらアーカイブする処理です。
コールバック版(zip_request_legacy.js)の場合

'use strict';

( function () {var zip_request = new ZipRequest(),
// (中略)

zip_request.open();

files.forEach( function ( file ) {var url = file.src || file.href,
        filename = get_filename( url );
    
    console.log( '[start]', url, filename );
    
    zip_request.file( {
        url : url,
        filename : filename,
        zip_options : {
            date : newDate( '2017-01-01' )
        }}, function ( result ) {
        console.log( '[result]', url, filename, result );
    } );
} );

zip_request.generate( 'blob', function ( response ) {
    zip_request.close();
    
    // 以下、Aタグのdownload 属性を使ったダウンロード処理} );

} )();

Promise版(zip_request.js)の場合

'use strict';

( async function () {let zip_request = new ZipRequest(),
// (中略)

await zip_request.open();

await Promise.all(
    files.map( async ( file ) => {let result,
            url = file.src || file.href,
            filename = get_filename( url );
        
        console.log( '[start]', url, filename );
        
        result = await zip_request.file( {
            url : url,
            filename : filename,
            zip_options : {
                date : newDate( '2017-01-01' )
            }} )
        .catch( result => {return result } ); // Promise.all() を停止させないための対策
        
        console.log( '[result]', url, filename, result );
        
        return result;
    } )
);

let response,
    download_link;

response = await zip_request.generate( 'blob' );

await zip_request.close();

// 以下、Aタグのdownload 属性を使ったダウンロード処理} )();

コールバック版のライブラリ内で多少工夫をしていることもあり、並列処理に関しては、一見したところそれ程違いは無いかもしれません。
コールバック版では、例えば file() に対応する応答が background からまだ来ない状態で generate() が呼ばれたとしても、全てのファイルについて結果が返るのを待って background に要求を出すようにしているため、上記の書き方が可能。ただし、close() については、generate() のコールバック後に呼び出す必要あり。

直列処理

ファイルを一つずつ順番に取得しながら(逐次)アーカイブする処理です。
コールバック版(zip_request_legacy.js)の場合

'use strict';

( function () {var zip_request = new ZipRequest(),
// (中略)

zip_request.open( function ( result ) {var file_index = 0;
    
    function zip_files() {if ( files.length <= file_index ) {
            zip_request.generate( 'blob', function ( response ) {
                zip_request.close();
                
                // 以下、Aタグのdownload 属性を使ったダウンロード処理                                } );
            return;
        }var file = files[ file_index ++ ],
            url = file.src || file.href,
            filename = get_filename( url );
        
        console.log( '[start]', url, filename );
        
        zip_request.file( {
            url : url,
            filename : filename,
            zip_options : {
                date : newDate( '2017-01-01' )
            }}, function ( result ) {
            console.log( '[result]', url, filename, result );
            
            zip_files();
        } );
    }
    
    zip_files();
} );

} )();

Promise版(zip_request.js)の場合

'use strict';

( async function () {let zip_request = new ZipRequest(),
// (中略)

await zip_request.open();

for ( let file of files ) {// files.map( async ( file ) => { ... } ) は使えないことに注意// ※ map() では、コールバック関数の戻り値が Promise object になり、直列処理されないlet url = file.src || file.href,
        filename = get_filename( url ),
        result;
    
    console.log( '[start]', url, filename );
    
    result = await zip_request.file( {
        url : url,
        filename : filename,
        zip_options : {
            date : newDate( '2017-01-01' )
        }} )
    .catch( result => {return result } ); // エラーで停止させないための対策
    
    console.log( '[result]', url, filename, result );
}let response,
    download_link;

response = await zip_request.generate( 'blob' );

await zip_request.close();

// 以下、Aタグのdownload 属性を使ったダウンロード処理} )();

こちらは、Promise 版のメリットが出ていると思います。
コールバック版は処理の流れが一見解りにくいのに対し、Promise 版では上から下への自然な流れで解りやすくなっています。

はまった点など

  • Promise.all() は、並列実行中の Promise オブジェクトが一つでもエラーになると異常終了してしまう(catchされてしまう)ため、中断したくない場合、それぞれの Promise で reject() ではなく resolve() を呼び、戻り値によって判別するようにする
  • Array#map() 等のコールバック処理を持つものは、直列処理では使用できない(コールバックの結果が Promise オブジェクトで返されるため)
  • Promise の resolve() や reject() は、呼んだ後も続きが実行される(実行されないようにするには、直後に return が必要)
  • background における、browser/chrome.runtime.onMessage.addListener() のコールバック関数内で、非同期の処理を呼んでから sendResponse()を返す場合、コールバック関数の戻り値に true を設定する必要がある(chrome.runtime - Google Chrome
  • content_scripts と background 間のやり取り(sendMessage()/sendResponse())では、JSON で基本的にはシリアライズ可能なオブジェクトしか渡せない……ところが、渡せるオブジェクトの種類に、ブラウザ間で差異がある(関数オブジェクトは Firefox で NG、Blob が渡せるのは Firefox のみ、等)
  • background で URL.createObjectURL() により得られた Blob URL を content_scripts に送ると、Chrome では download 属性付き A タグでダウンロード可能なのに対し、Firefox や MS-Edge では不可(Firefoxについては、なぜか Blob がそのまま content_scripts に送れるため、そちらで Blob URL に変換することで対応している)
  • MS-Edge では、作成した ZIP をダウンロードさせる術が見つからない

Promise/async/awaitやclassの書き方でもっとはまると思っていたが、これらはそれ程でもなかった代わりに、拡張機能の仕様やブラウザ間の細かい差異の方が難解。

近傍ツイート検索で最近リツイートしたユーザーを表示する機能を追加しました(version 0.2.6.100)

$
0
0


前書き

近傍ツイート検索
furyu.hatenablog.com
にて、個別ツイートをリツイートした最近のユーザーを表示する機能を追加しました。
また、該当するユーザーが RT 前後の 10 分間にツイートしていた内容(概要)を表示することも出来るようになりました。

早い話が、『RtRT』("(Find the) Reference to ReTweet")や、
リツイート直後のツイートを表示するやつみたいなことを、ユーザースクリプトや拡張機能でもやりたかったのです……サイトに行って調べるのが面倒なので(苦笑)。
とは言っても色々と制限が厳しく、Webサービスみたいにはいきませんが……。
調子に乗ってあちこちのツイートで試していると API 制限(時間当たりの回数制限)に引っかかるかも知れません。悪しからずご了承ください。

新機能について

当然ながら、ブラウザに近傍ツイート検索の最新版がインストールされていることが前提です。
まだの方は、お使いのブラウザ環境に合わせて
github.com
chrome.google.com

近傍ツイート検索 – Firefox 向けアドオン

からインストールしてください。

使い方

インストール/更新後に Web 版公式ツイッターを開くと、リツイートされているツイートの下の方に [Re:RT] というボタンがついています。
f:id:furyu-tei:20171125034556p:plain

これをクリックすると、当該ツイートを RT したユーザーのうち、最近行った方々が表示されます。
f:id:furyu-tei:20171125034607p:plain

ユーザーのプロフィールの右側に [↓↑] というボタンが表示されますが、
f:id:furyu-tei:20171125034626p:plain

これをクリックすると、
f:id:furyu-tei:20171125034640p:plain

RT 前後 10 分間のツイート概要が表示されます。
RTした人は、その前後に当該ツイートについて言及していることもよくある、という経験則に基づきます。

オプションとしては、表示するユーザー数を変更できます。
f:id:furyu-tei:20171125034653p:plain
これは、最大 100 ユーザーまでです。
Twitter API の仕様による制限です。

注意書き

更新の際に無効化されてしまう

上記の機能に関して、拡張機能に新たな権限が追加されています。
f:id:furyu-tei:20171127045119p:plain

0.2.5.200以前バージョンから更新された場合、いったん拡張機能が無効化され、有効化しようとすると、

「近傍ツイート検索」の最新バージョンは、さらに許可が必要なため無効になっています。

のようにメッセージが表示されて、再度有効にするかどうかの確認があります。
f:id:furyu-tei:20171127034910p:plain

[再度有効にする]ボタンを押してください。
上記は Chrome の場合ですが、Firefox の場合にも同様のダイアログが表示されることがありますので、その場合は[更新(U)]ボタンを押してください。

※キャンセルを押してしまった場合などは……
 Google Chrome → 拡張機能の画面 chrome://extensions/ (「≡」(右上のハンバーガーメニュー)→「その他のツール(L)」→「拡張機能(E)」)を開き、「近傍ツイート検索」を探して、「□ 有効にする」のチェックボックスにチェックを入れてください。
 Firefox Quantum → アドオンマネージャー about:addons ([Ctrl]+[Shift]+[A]、「≡」(右上のハンバーガーメニュー)→アドオン)を開き、「近傍ツイート検索」を探して、[有効化]ボタンを押してください。

ここで、Google Chrome の場合には

・twitter.com の全サイト、twitter.com 上にある自分のデータの読み取りと変更

とあるので(特に『変更』と出てしまっているので)不安に思われる方もいらっしゃるようですが、「ユーザーデータには変更を加えてはいません」のでご安心ください。
Firefox Quantum の場合、同様のダイアログでは、「・twitter.com の保存されたデータへのアクセス」という表現になっていると思います。
作者本人がそう言っても不安だ・信用できない、という方は、公開しているソースコードをご覧になるか、使用をお控えください。

これは、今回の機能の中で、「個別ツイートをリツイートした最近のユーザー」の情報を取得するために、新たにアクセス権を追加したためです。
Twitter 側に設定してある本拡張機能用のアクセス権限は、「読み取り専用」(Read-only)としているのですが、
f:id:furyu-tei:20171127035554p:plain
拡張機能には「読み取り専用」という権限はなく、アクセスを許可しようとすると自動的に「読み取りと変更」ということになってしまいます。

なお、上記の権限に関して、実際に使用している Twitter の API は以下の通りです。

POST oauth2/token — Twitter Developers
GET application/rate_limit_status — Twitter Developers
GET statuses/retweets/:id — Twitter Developers

余談

【覚書】はてなブログのレスポンシブWebデザイン対応

$
0
0

ほんとうに今更ながら、はてなブログはテーマ(テンプレート)によってはレスポンシブWebデザインに対応していることに気付く。
スマートフォンでアクセスする際に「PCのときとURLが変わってしまうのは不便だなー」と思っていたことだし、本ブログも対応してみることに。

手順1:レスポンシブ対応のテーマをインストール

テーマ ストアでレスポンシブ対応のテーマを探してインストール。
なお現状、レスポンシブ対応のテーマを探す機能などはないので、自力で探すしかない。

自分は、たまたま目についたシンプルな

Simple Gray - テーマ ストア - はてなブログ

をインストールしてベースにさせていただいた。


今気が付いたが、レスポンシブ対応テーマを探すには、

はてなブログのレスポンシブデザイン対応のテーマ集24個【随時更新】(スマホでもPCとほぼ同じ表示になるテンプレート) - 広汎性発達障害の女が毒を吐くブログ

の記事が便利そう。

手順2:CSS等の調整

デザイン設定で、CSSを適当に(好みに合わせて)調整。
自分の場合、はてなダイアリーのときに使用していたテーマの色合いが気に入っていたので、それに近い感じにしてみた。

また、ヘッダの下に検索フォームを設置し、画面の横幅が 1150px 以下のときには表示されるようにしておいた。
サイドバーが下に落ちて、検索フォームにアクセスしづらくなったときの代用。

手順3:レスポンシブ(スマートフォン)対応設定

デザインCSS先頭に、

/*  Responsive: yes */

のようなコメントを追加したのち、スマートフォン→詳細設定にて、☑ レスポンシブデザインにチェックを入れる。

参考

レスポンシブデザインのテーマを作成する際の注意点

デザインCSSに Responsive: yes のコメントを入れるのは、忘れやすいので注意。

拡張機能のアイコンをSVGで作ろうとInkscapeを入れてみたところ、はまった点

$
0
0


前書き

最近、近傍ツイート検索
furyu.hatenablog.com
の拡張機能用のアイコンをリニューアルした。

実は、2014年6月当時にやっつけで作ったまま(厳密には2016年2月にマイナーチェンジしているが)だったので、いつか作り直そう……と思いつつ、面倒なので長らく放置していた。

(2014/6/9作成)(2016/2/1微修正)

それが先日、ふと「アイコンを SVG で作ってみよう」と思い立ち、初めて Inkscape なる OSS のベクトル画像ドローソフトをインストールしてみた。
ところが、まっとうに使い始める前に例によって色々とはまってしまったので*1、それらの点についてメモ書きしておく。
導入したバージョンは、Inkscape 0.92.2 (5c3e80d, 2017-08-06)

はまった点

Python のエラー……?

Inkscape がデフォルトで出力する SVG ファイル(Inkscape SVG フォーマット)は色々と情報が入っていてサイズが大きいので、これを圧縮する方法を調べていると……

SVGのエクスポート – Inkscape@JP

標準で、『最適化 SVG』というフォーマットがあり、これはかなりサイズが小さくなるっぽい。

で、『名前を付けて保存』メニューから、その出力を試そうとしたら……

The fantastic lxml wrapper for libxml2 is required by inkex.py and therefore this extension. Please download and install the latest version from http://cheeseshop.python.org/pypi/lxml/, or install it through your package manager by a command like: sudo apt-get install python-lxml

Inkscapeは、実行したスクリプトから追加データを受け取りました。スクリプトはエラーを返しませんでしたが、実行結果が意図しないものになっていることを示唆している可能性があります。

というエラーが出てしまい、保存に失敗する。

Inkscape が自分でインストールする Python 2.7 と、別件で既にインストールされていた Python 2.7 と競合しているのかと思って、PYTHONHOME や PYTHONPATH の設定変更や削除、C:\Python27 のリネーム等、いろいろと試してみたが、

Traceback (most recent call last):
  File "C:\Python\Lib\site-packages/site.py", line 73, in <module>
    __boot()
  File "C:\Python\Lib\site-packages/site.py", line 3, in __boot
    import os
ImportError: No module named os

とかいったエラーに変わるだけで、どう設定してもうまくいかない。

結局、いったん Inkscape をアンインストールしたあと、インストール時のコンポーネント選択で、
f:id:furyu-tei:20171202111555p:plain
☑ Python 2.7 のチェックを外してインストールしてみると、上記エラーが出なくなった。

なお、代わりに、自身が構築している Python 2.7 の環境には、いくつかのライブラリを手動でインストールしておく必要があるので、注意が必要。

> python -m pip install lxml numpy scour
デフォルトは mm 単位で、A4 サイズ……?

インストールした Inkscape を起動すると、新規ドキュメントが開くが、デフォルトではこれがサイズの単位が mm で、かつ、A4 サイズになっている。
f:id:furyu-tei:20171202113915p:plain

ドキュメントのプロパティ(ファイル(F)→ドキュメントのプロパティ(D))はこんな感じ。
f:id:furyu-tei:20171202111611p:plain

この設定ではアイコンを作るのには不便そうなので、Chrome 拡張機能の基本サイズ 96px × 96px にしようと思い、
f:id:furyu-tei:20171202113835p:plain
のように設定。
※変更したのは、

  • 『Display units』→ px
  • 『カスタムサイズ』→幅(W):96.0000、高さ(H):96.0000、単位(N):px
  • 『拡大縮小』→ Scale x:1.00000
  • 『Background』→☑ Checkerboard background(チェックを付ける)
  • 『境界線』→☑ 描画より前面に境界線を表示する(T)(チェックを付ける)、□ 境界線に影を表示する(S)(チェックを外す)

これで、ドキュメントは
f:id:furyu-tei:20171202113901p:plain
といった感じになる。

ただ、毎回設定するのは大変なので、デフォルトを変えたい。

Setting up page template - InkscapeForum.com

などを参考に、↑のように設定変更したドキュメントを

%UserProfile%\AppData\Roaming\inkscape\templates

の下に、default.ja.svg というファイル名で保存しておく。
すると、新規ドキュメントを開いたときに、上記設定が反映されるようになる。

『最適化 SVG』形式で保存すると……画面いっぱいのアイコンが?!

苦戦しつつもアイコンを描き終わり、『最適化SVG』形式で保存し、これをブラウザで表示してみると……
f:id:furyu-tei:20171202115705p:plain
……でかっ!!

エディタで当該 SVG ファイルを見てみると……

<?xml version="1.0" encoding="UTF-8"?><!-- Created with Inkscape (http://www.inkscape.org/) --><svg version="1.1"viewBox="0 0 96 96"xmlns="http://www.w3.org/2000/svg"xmlns:cc="http://creativecommons.org/ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

viewBox は指定されているものの、width と height が抜けている……?
そこで、SVG タグを

<svg version="1.1"viewBox="0 0 96 96"width="96"height="96"xmlns="http://www.w3.org/2000/svg"xmlns:cc="http://creativecommons.org/ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

のように、「width="96" height="96"」を付け加えたところ、

f:id:furyu-tei:20171202120010p:plain
のようになんとか普通に表示されるようになった。

なお、『Inkscape SVG』形式や、『プレーン SVG』形式の場合には、width・height は入っているため、『最適化 SVG』形式の場合の不具合かもと考えている。
ちなみに、

  • 『カスタムサイズ』→幅(W):25.4000、高さ(H):25.4000、単位(N):mm

にしておくと、『最適化 SVG』であっても width・height が入り、

<svg width="25.4mm"height="25.4mm"version="1.1"viewBox="0 0 96 96"xmlns="http://www.w3.org/2000/svg"xmlns:cc="http://creativecommons.org/ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

見た目上の表示もまっとうになる。

他のサイズで出力するには……?

96px × 96px で作成しているが、例えば Chrome 拡張機能用には、48px、96px、128px というサイズのアイコンが必要になる。
しかも、128pxは、96px のアイコンの周囲を 16px の透明ピクセルで囲んだもの。

SVG 形式の場合
ドキュメントのプロパティをその都度変更しつつ、名前を付けて保存してもよいが、96px の最適化 SVGを出力しておき、これをコピーして、テキストエディタで width、height、viewBox を書き換える方が簡単かも。
※ 96px
<svg version="1.1"viewBox="0 0 96 96"width="96"height="96"xmlns="http://www.w3.org/2000/svg"xmlns:cc="http://creativecommons.org/ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

※ 48px

<svg version="1.1"viewBox="0 0 96 96"width="48"height="48"xmlns="http://www.w3.org/2000/svg"xmlns:cc="http://creativecommons.org/ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

※ 128px(周囲16pxは透明)

<svg version="1.1"viewBox="-16 -16 128 128"width="128"height="128"xmlns="http://www.w3.org/2000/svg"xmlns:cc="http://creativecommons.org/ns#"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

ちなみに、view Box と width・height の関係は、以下のサイトの解説が分かりやすかった。
old-pine.net

PNG 形式の場合
Inkscape の『PNG 画像にエクスポート(E)』(Shift+Ctrl+E)により出力するのが簡単。
通常は、『画像サイズ』欄に出力したいサイズを入力して、エクスポートするだけでよい。
ただし Chrome 拡張機能の 128px の場合には、エクスポート領域で、透明ピクセル部分を含んだ x0、y0、x1、y1(-16, -16, 112, 112)を指定してやる必要がある。
f:id:furyu-tei:20171202124108p:plain

サゲ


苦労して(?)作成した SVG ファイルも、Chrome 拡張機能の manifest.json や、拡張機能のアイコン登録画面などでは、指定できない罠。

*1:絵心が無いとかそういう、人間のソフトウェアに依存したどうしようもない理由ではなく

Chrome拡張機能にてシークレットウィンドウとbackgroundとのメッセージ送受信時の注意

$
0
0


ハマったよ……

Twitter メディアローダ
furyu.hatenablog.com
にて、Google Chrome のシークレット ウィンドウ上で実行すると、ファイルダウンロード時に

失敗 - ファイルがありません

となって正常にダウンロードできない、という現象が発生した

シークレット ウィンドウでだけ発生するという訳の分からない状態だったので、途方に暮れていたのだが……。

何が起こっていたのか?

background → content_scripts に、ZIP化したコンテンツの Blob URL を sendResponse() で送信する仕組みにしていたのだが、なぜか受け取った content_scripts 側(シークレット ウィンドウ)で、その Blob URL にアクセスできない状態(404発生)になっていた。

原因

Manifest - Incognito - Google Chromeによると、manifest.json に指定できる "incognito"キーについて、シークレット ウィンドウ(匿名タブ)で動かせる拡張機能では"spanning"もしくは"split"が指定でき、

  • "spanning"(デフォルト)
    → 匿名タブと、その他の(一つのプロセス上で共有される)コンテキスト(これにはoptions_uiやbackgroundページも含む)とがあり、匿名タブは共有プロセスにアクセスできない
  • "split"
    →ひとつひとつの匿名タブ(と各々に対応する background ページ)は、それぞれ独立したプロセス上で動作し、メッセージ等のリソースもプロセス内のコンテキストのもののみを参照できる(匿名タブ間ではお互いにやり取り不可)
    1:1に対応しているbackgroundとは共通のリソースにアクセスできると思われる

となっているように読める。
英語の解読に自信はないので、読み取り間違っているかもしれない。その場合はご指摘を……。

なので、manifest.json で明示していなかったために "spanning"モードで動いていた本拡張機能では、background で作成した Blob URL に匿名タブからアクセスできなかったのだと思われる。

対策

manifest.json に

,   "incognito" : "split"

を追加。

念のため、backgroundでの ZIP 化を無効化するオプションも付けておいた

副作用

Firefox では、"incognito" キーはサポートしているが、選択肢として "split" がサポートされていない
このため、manifest.json を Chrome と共通にしていると、アドオン登録の検証時に

"/incognito" should be equal to one of the allowed values
エラー: Your JSON file could not be parsed.

というエラーが発生し、撥ねられてしまう。
やむを得ず、Chrome と Firefox とで manifest.json を分ける羽目に……せっかく共通化していたのに(苦笑)。


【アマゾン注文履歴フィルタ】確定申告にも便利かも?! Kindle 等のデジタルコンテンツの領収書をまとめて表示する拡張機能/アドオン/ユーザースクリプト

$
0
0

漫画家の方などが、確定申告用にアマゾン(Amazon.co.jp)の注文履歴から Kindle を検索して領収書を個別に表示・印刷するのが手間がかかる、というようなことを Twitter でつぶやいておられたので、まとめて印刷出来たら少しは楽かな?と思い、スクリプトを書いてみました。
PC 用ブラウザ向けの拡張機能/アドオン/ユーザースクリプトであり、Google Chrome/Firefox Quantum (ユーザースクリプトは Tampermonkey)上で動作確認しています。
拡張機能版は、Vivaldi、および、Opera+Install Chrome Extensionsでも動作する模様。
なお、MS-Edgeでは、拡張機能版/ユーザースクリプト版共に正常に動作せず(2018/02/05現在)。



インストール

Chrome 拡張機能版(Google Chrome/Vivaldi/Opera+Install Chrome Extensions対応)

chrome.google.com

より、[+CHROME に追加] ボタンを押してインストール。
ボタンの名称はブラウザによって異なります([+(ブラウザ名)に追加])。

Firefox Quantum アドオン版(WebExtensions)

https://addons.mozilla.org/ja/firefox/addon/amzorderhistoryfilter/addons.mozilla.org

より、ページ上に表示されている [+ Firefox へ追加] ボタンを押してインストール。

使い方

インストール後、注文履歴を表示し、対象となる年を選択します。
動作するのは、年を選択した場合だけです。「過去6カ月間」「過去30日間」では動作しませんので、ご注意を。
すると、対象月を選択するためのプルダウンメニュー、および絞り込み用チェックボックスが表示されます。
f:id:furyu-tei:20180204193820p:plain
対象月を選択すると、該当する注文一覧が表示されます。
表示されるまでに読み込みに時間がかかることがあります。

f:id:furyu-tei:20180204193814p:plain
[領収書印刷用画面]ボタンを押すと、別タブが開き、対象となる注文の領収書を読み込みます。
「☑デジタル」「☑デジタル以外」の両方にチェックしている場合、それぞれは別々のタブに開きます。

f:id:furyu-tei:20180204193810p:plain
領収書の読み込み完了するまでお待ちください。
対象となる注文の数が多いほど、読み込み時間も長くなります。

f:id:furyu-tei:20180204193806p:plain
読み込みが完了すると、同じページ内に複数の領収書がまとめて表示されます。
各領収書は横罫線で区切られ、便宜上のNo.が振られます。No.は個別領収書へのリンクになっています。
印刷時には、横罫線は表示されず、改ページとなります。また、No.リンクも非表示となります。

これで、ブラウザの機能により(「このページを印刷してご使用ください」リンクをクリックするか、[Ctrl]+[P]を押します)
f:id:furyu-tei:20180204193802p:plain
複数の領収書がまとめて印刷できます。
Firefox では、この方法ではプレビューは表示されません。プレビューを表示したい場合、右上のメニュー(≡)→「印刷...」とします。
まとめて印刷する関係上、ヘッダがあると 、URL 等の領収書と一致しないものが出てしまいますので、気になる場合にはヘッダ・フッタを印刷しないようにした方が良いでしょう。

Google Chrome では、印刷プレビュー画面左上にある「送信先」を「PDF に保存」に変更すると、印刷する代わりに PDF ファイルとして出力することができます。
後で見直したり、必要なものだけを印刷したりする場合には、PDF に保存しておいた方が便利かもしれません。

FIrefox では、標準では PDF で保存する機能は無いようですので(当方が知らないだけかも知れませんが)、別途そのためのアプリが必要になります。

無料のものだと、
www.cube-soft.jp
といったものがあるようです。

免責事項(念のため)

ご利用の際には全て自己責任でお願いします。
不具合があったり、使用した結果等により万一何らかの損害を被ったりした場合でも、作者は一切関知いたしませんので、悪しからず。

お問い合わせ先

お問い合わせやご要望などありましたら、この記事のコメント欄か、@までお願いします。
不具合報告やご要望などは、GitHubのIssuesへもどうぞ。

「気に入った!」のお気持ちは、ギフト券で!

せっかくのアマゾン用の拡張機能/アドオンなので(笑)、「気に入った」「役に立った」と思われたら、いくらかでも Amazon ギフト券で頂けると、大喜びします!

Amazonギフト券(Eメールタイプ)

  • 受取人メールアドレス:「furyutei@gmail.com」
  • メッセージで何かひとこといただけると嬉しいです


贈り方は、

Amazonギフト券Eメールタイプとは?使い方を写真付で解説

等をご参照ください。

開発経緯

Twitter 上で、




のようなツイートを見かけたことがきっかけです。

もっとも、自分自身は確定申告の経験が無いため、これで役に立つのかどうかは不明です(苦笑)。

オチ


野間美由紀さんはMacユーザーで、Safari を使っていらっしゃるため、Chrome も Firefox も入れていない模様……。
うーん、Safari 用 Tampermonkey を入れればユーザースクリプト版がもしかしたら動作するかもしれないのですが、手元に Mac が無いので試せないのですよね……。
来年……果たしてどうなっていますかねぇ……。
まさか節分過ぎたばかりでもう来年の話をするとは、この拡張機能を作るまでは思いもしませんでしたが(笑)。

覚書を兼ねた独り言

作成中にハマった点など

今回も思わぬところでハマりまくりました……。

  • 領収書専用のウィンドウを開いて、そこに領収書分だけタブを開き、後で全タブ選択して印刷すればできたりしないか?
    →タブを複数選択しても、印刷されるのは現在表示されているページだけだったのでダメ
  • 注文履歴ページを $.ajax() で取得すると、よくわからない(HTMLではない)ファイルが返る
    →リクエストヘッダに X-Requested-With : XMLHttpRequest が含まれると、Amazon から HTML ではない形式で返されてしまう模様
    →crossDomainパラメータをtrueで指定してやるとX-Requested-Withが送られなくなった(参考1参考2
  • Firefox のアドオン版として動かしたときだけ、$.ajax() によるページ読み込みが失敗する
    →$.ajaxに指定する際、url は相対パスだとだめ("SyntaxError: The URI is malformed."エラー)
    → new URL() で絶対パスに変換して大丈夫になった
  • 注文履歴を取得して表示する際、件数が多いと表示が固まってしまう
    →ブラウザのウィンドウ内で見えない分は非表示にし、スクロールしたときに必要分だけ表示するようにして対応
  • 領収書を $.ajax() 等で取得すると、支払情報等の欄が入っていない
    →スクリプトで動的に表示するようになっているらしい
    →裏で(IFRAMEで)開いて、表示が落ち着くまで監視し、落ち着いたら HTML を取得して親ウィンドウに postMessage() で送信することで対応
  • 領収書の数が多いと、ブラウザが固まる・応答しなくなる等の現象が発生
    →領収書の数だけIFRAME作っていたので(開きすぎだ)、一定数だけ開き、終わったら使いまわすことで対応
  • アイコン作成が面倒
    →面倒だけど、やるしかなかった(苦笑)
その他に気付いたことなど
  • 一度でも領収書を表示してしまうと、二度目からは問答無用で「再発行」扱いになるっぽい……(今のところ、デジタル注文の場合、再発行にはならないが)
    試しに表示した、とか、ブラウザが固まった、等の事情が一切考慮されないのが、ちとモヤっとする……
    これ、消したくなるな……普通にテキストだから修正できるんだよね……でもなぁ……

【アマゾン注文履歴フィルタ】注文履歴をCSVでダウンロードできるようになったり、いろいろ進化しました!

$
0
0

アマゾン注文履歴フィルタ
furyu.hatenablog.com

が思わぬ反響をいただいているようで、本人がいちばんびっくりしております。
ギフト券を送ってくださった方々、重ねてお礼申し上げます。

気をよくして(笑)、いくつかの機能追加等を行っております。いちど使っていただいた方も、新機能を試していただけると嬉しいです。
以下の機能説明は、2018/02/08時点(バージョン:0.1.0.601)でのものです。




注文履歴を CSV 形式でダウンロードできるようになりました

領収書印刷用画面で読み込みが完了すると、右上の方に[注文履歴CSV(参考用)ダウンロード]というボタンが表示されるようになります。
f:id:furyu-tei:20180208204609p:plain

これを押すと、
f:id:furyu-tei:20180208204626p:plain
現在開いている領収書の内容を元にしたデータが、CSV ファイルとしてダウンロードされます。

ダウンロードした CSV ファイルは Excel 等で開くことができますので、
f:id:furyu-tei:20180208204638p:plain
いろいろと使い道はあると思います。
CSV ファイルの文字コードは BOM付 UTF-8(改行コードはCR+LF)になっています。
ただ、Mac の Excel では開けない、というようなことを昔どこかで見た気がする……5年前(2013年)の記事か。今はどうなのかな?

なお、領収書印刷用画面に表示されるデータを適当に拾って並べただけですので、もともと表示されている以上のことはわかりません。
また、手抜きして表示されているデータであっても CSV の中には含まれないもの(Amazonポイントとか送料・手数料とか)も存在しますので、悪しからず。
ボタンに「(参考用)」とあるのはそのためです。
作りが甘いこともあって、間違っているところもあると思いますので、くれぐれもそのことを念頭に置いたうえで、ご利用ください。確定申告用等の重要な書類を作成される際には、必ず元データを確認するようにしてください。
結構ひどい古き良き時代を感じさせるHTMLだったため、スクレイピングには苦労しました……。

そうそう、「商品小計」「注文合計」「請求額」「クレカ請求額」の項が、同一の注文(搬送)内では最初(一番上)の行にしか含まれていないのは、わざとです。
縦の合計を計算するときなどに重複してしまうのを避けるため。

「お届け先」フィルタを追加しました

注文を「お届け先」で絞り込み出来る機能を追加しました。
f:id:furyu-tei:20180208204700p:plain
経費とその他に分けたい時などにご利用ください。
この機能は、ぬん。さん(@)よりご要望いただいたものです。

領収書の宛名を指定できるようになりました

領収書印刷用画面で読み込みが終わったら、
f:id:furyu-tei:20180208204718p:plain
[宛名変更]ボタンが表示され、これを押すと、
f:id:furyu-tei:20180208204736p:plain
プロンプトが出て、宛名を入れることが出来るようになります。

f:id:furyu-tei:20180208204756p:plain
「___様」に重なるように指定した宛名が表示されます。

元は宛名欄が空白なので、手動で入れないといけないのですが、あまりこれに関する愚痴などは聞きませんね……確定申告用の領収書は宛名は別に必要ないのでしょうか。まあ、必要な人だけ使ってください、ということで。

Firefox 向けに、印刷プレビューボタンが付きました

Firefox アドオン版のみですが、領収書印刷用画面で、
f:id:furyu-tei:20180208204857p:plain
[印刷プレビュー]ボタンが表示されるようになりました。
これを押すと、
f:id:furyu-tei:20180208204821p:plain
すぐプレビューできるので、わざわざハンバーガーメニュー(≡)を開いて、印刷をクリックしなくてもよくなります。
こっそりショートカットキーがもともとあったりしたら笑えますが。

その他

安定性の向上

最初の方の版では、いつまで経っても領収書読み込みが完了しない、という現象が、状況によっては割と頻繁に発生していました。
特に、一度に処理する領収書数が多い方の場合。

ひとつの原因として、領収書の取得を行うには認証状態であることが条件なのですが、読み込み処理中に認証期限が切れてサインインを要求されて(ログインフォームが表示されて)しまい、バックグラウンドで読んでいるページが処理が続けられなくなる、というのがありました。
処理が止まるタイミングは前回のサインインをいつ行ったかに依存するため(期間もかなり短くしてある模様・15分くらい?)、なるべく認証期間を有効に使うために、開始直前にサインインを行うように修正しました。

デメリットとして、領収書印刷用画面を開く毎に必ずサインイン画面が表示されるため、少し煩わしくなってしまいましたが、あと少しのところで固まるよりはマシだと割り切ってくださるよう、お願いします。

領収書読み込み時のカウンタ追加

領収書読み込み中、画面右上に
f:id:furyu-tei:20180208214629p:plain
のようにカウンタが表示されるようになったので、進行状況がすぐわかります。
また、何らかの不具合で固まってしまっても、見ていれば止まっているのが分かるようになりました……(汗)。
一応、一定時間待っても変化が無ければ、ダイアログが表示されて中断できるようにはしています。

蛇足

これがきっかけでブログに訪れて下さった方、他には Twitter 用の拡張機能(本人は便利だと思っている)も公開しておりますので、そちらもよかったら合わせてご覧ください。
furyu.hatenablog.com

【アマゾン注文履歴フィルタ】キーワードによる絞り込み・返金情報CSVダウンロード機能などを追加しました

$
0
0

前回の記事後のアマゾン注文履歴フィルタ
furyu.hatenablog.com
への機能追加分をまとめます。
以下の機能説明は、2018/02/12時点(バージョン:0.1.0.1001)でのものです。




キーワードによる絞り込みができるようになりました

「絞り込み」フィルタを追加し、
f:id:furyu-tei:20180212195646p:plain
キーワードによる絞り込みが可能となりました。

f:id:furyu-tei:20180212195652p:plain
""(スペース)区切りで AND 検索、" OR "区切りで OR 検索となります。

また、「☑ 除外」にチェックを付けると、
f:id:furyu-tei:20180212195700p:plain
キーワードで指定した以外のものが表示されます。

[クリア]ボタンは、キーワード入力をクリアするためのものです。

絞り込みの際の制限事項
  • 標準の [注文を検索] では
    「タイトル」「注文番号」「カテゴリー」「Eメールアドレス」「届け先」
    が対象ですが、アマゾン注文履歴フィルタでは
    「カテゴリー」「Eメールアドレス」
    については対象外となります。
    「届け先」は別途「お届け先」フィルタを組み合わせて指定してください。
  • 一件につき五品目以上を注文している場合には、五品目以降が検索にかかりません。

返金情報ファイルがダウンロードできるようになりました

領収書印刷用画面において、読み込み完了後、表示されている注文に対応した返金(払い戻し)がある場合には、右上に
f:id:furyu-tei:20180212194024p:plain
[返金情報CSV(参考用)ダウンロード]ボタンが表示されます。

これをクリックすると、返金情報が CSV 形式でダウンロードされ、Excel 等で開くことができます。
f:id:furyu-tei:20180212194035p:plain

その他

注文履歴 CSV ファイルに配送料、ポイント払い等の情報を追加・Amazonギフト券購入対応

配送料・手数料や、ポイント・ギフト券等による支払いの情報も、注文履歴 CSV ファイル中に含むようにしました。
また、Amazonギフト券購入情報が含まれていなかったので、これを追加しました

【覚書】クロスドメインな画像を任意のファイル名でダウンロードするためのユーザースクリプトの記述方法

$
0
0

Twitter の原寸画像は、例えば「https://pbs.twimg.com/media/CYhLLnfU0AAbHun.jpg:orig」のようなURLとなっており、これを Windows のブラウザでダウンロードしようとすると、「CYhLLnfU0AAbHun.jpg-orig」のようなおかしな拡張子に変換されて保存されてしまうことがある*1

いちいち拡張子を修正するのが面倒だったため、
furyu.hatenablog.com
では、リンク(A)要素の download 属性で、ちゃんとした拡張子のファイル名(例えば、「CYhLLnfU0AAbHun-orig.jpg」)を指定してやり、リネームの手間を省こうとしたのだが……。
以前、
furyu.hatenablog.com
でも書いたように、クロスドメイン(クロスサイト)に於いては、download属性で指定したファイル名は無視されてしまう。

■例

<ahref="https://pbs.twimg.com/media/CYhLLnfU0AAbHun.jpg:orig" download="<任意のファイル名>.jpg"id="download_link_sample_a">ダウンロードリンク-A</a>

これを何とかするための苦肉の策が以下のもの。
例によって、もっとスマートなやり方があればコメント願う。

ユーザースクリプトのサンプル

Cross-Domainなサイトの画像を任意のファイル名でダウンロードするユーザースクリプトのサンプル

このユーザースクリプトを Greasemonkey や Tampermonkey でインストールしてから、このページをリロードすると、↑の例のところに「ダウンロードリンク-B」というリンクが新たに表示されるはず。
これをクリックすると、「<任意のファイル名>.jpg」なるファイル名で画像がダウンロードできる……はず。
何をやっているかは、下記のソースコードを参照。また、このテスト以外には意味はないスクリプトなので、確認が終わったら削除しておくことを推奨。

// ==UserScript==// @name            sample_download_link// @namespace       http://furyu.hatenablog.com/// @author          furyu// @version         0.1.0.0// @include         http://furyu.hatenablog.com/*// @include         https://pbs.twimg.com/media/*// @description     Cross-Domainなサイトの画像を任意のファイル名でダウンロードするユーザースクリプトのサンプル// ==/UserScript==

( function () {'use strict';

var SCRIPT_NAME = 'SAMPLE_DOWNLOAD_LINK',
    IFRAME_NAME = SCRIPT_NAME + '_download_frame',
    filename = '<任意のファイル名>.jpg',
    current_url = window.location.href;

if ( window !== window.parent ) {if ( window.name != IFRAME_NAME ) {return;
    }// 親 window から呼び出された画像用 IFRAME の処理var image_url = current_url,
        link = document.createElement( 'a' );
    
    link.href = image_url;
    link.download = filename;
    
    document.documentElement.appendChild( link );
    link.click(); // ダウンロード開始return;
}// 親 window の処理var source_image_link = document.querySelector( 'div#download_sample_image_container a#download_link_sample_a' );

if ( ! source_image_link ) {return;
}var download_link = document.createElement( 'a' ),
    image_url = source_image_link.href;

download_link.href = image_url;
download_link.download = filename;
download_link.appendChild( document.createTextNode( 'ダウンロードリンク-B' ) );

download_link.addEventListener( 'click', function ( event ) {// リンクがクリックされたら、name を指定した隠し IFRAME を呼び出すevent.stopPropagation();
    event.preventDefault();
    
    var iframe = document.createElement( 'iframe' ),
        iframe_style = iframe.style;
    
    iframe_style.width = '0';
    iframe_style.height = '0';
    iframe_style.visibility = 'hidden';
    
    iframe.src = image_url;
    iframe.name = IFRAME_NAME;
    
    document.documentElement.appendChild( iframe );
    
    returnfalse;
}, false );

source_image_link.parentNode.appendChild( download_link );

} )()

注意

Google Chrome の拡張機能で上記の手法を使用するためには、manifest.json にて、

"content_scripts" : [{"matches" : ["http://furyu.hatenablog.com/*", "https://pbs.twimg.com/media/*"],
        "js" : ["js/main.js"],
        "run_at" : "document_end",
        "all_frames" : true}]

のように、「 "all_frames" : true 」を指定して、IFRAME 内に対してもスクリプトが動作するように設定しておく必要がある。

*1:Firefoxだと、「CYhLLnfU0AAbHun.jpg orig.jpg」のようになるので、一応 JPEG としては解釈される

【覚書】Chrome拡張機能にて、オプション画面の変更を即座に反映させたい場合

$
0
0

Google Chrome の拡張機能で、オプション画面で変更した内容を即座に反映させたい場合には、何らかの方法でオプション画面(options_page)からスクリプト(content_scripts)が動作しているタブ(tabs)に変更を通知してやる必要があるが、そのやり方の一例。

概要

タブ(tabs)上で動作している contents_script は、オプションが格納される(extension 用の) localStorage を直接参照することはできないため、オプションを取得するためにはbackground スクリプトを介在させる必要がある。

このため、典型的には、

  1. background は、あらかじめメッセージ待ち受け状態にしておく(chrome.runtime.onMessage.addListener())。
  2. contents_script がオプションを取得したいタイミングで、background へメッセージを送信(chrome.runtime.sendMessage())。
  3. background は、contents_script よりメッセージを受信すると、localStorage よりオプション値を読み出して適宜変換後*1、contents_script に返す。

のような作りとなる。

また、オプション画面(options_page)の典型的な作りは、

  1. 開いたタイミングで、localStorage よりオプション値を読み出し、ユーザーにわかりやすい形で表示。
  2. ユーザーの入力に応じて、localStorage にオプション値を書き出し。

のようになっている。

ここに新たに

  1. contents_script 側であらかじめメッセージを受け付けられる状態にしておく(chrome.runtime.onMessage.addListener())。
  2. options_page にて、localStorage にオプション値を書き出したタイミングで、contents_scriptの動作しているタブ(tabs)に対して、メッセージを送信(chrome.tabs.sendMessage())。
  3. contents_script は、options_page よりメッセージを受信すると、background よりオプションを取得する。

のような手順を追加してやることで、オプション画面からの変更が即座にタブ側(contents_script)もに反映されるようになる。
なお、options_page→contents_scriptへメッセージを送信するときに変更したオプション内容も一緒に送信してやれば、backgroundへのオプション問い合わせは省略できる。ただしその場合、options_page側でもオプション値の翻訳(ユーザーの入力値から、contents_scriptで用いる値への変換)を実装する必要があり、やや煩雑になる可能性がある。

サンプル

具体的な実装例は、

github.com

を参照のこと。

注意
  • タブに対するメッセージ送信のために、manifest.json に
    "permissions" : [ "tabs" ]の記述が必要。

経緯

GoogleChrome拡張機能「twitter画像原寸ボタン」ver. 2.0公開 - hogashi.*を入れていると、ときどき、Originalボタンが表示されなくなってしまう現象があり、調べていた
現時点の最新版である、2.0.4でも発生。

状況としては、

  • しばらく(一晩とか)放置しておいたタイムラインにて、新しいツイートを表示すると、[Original]ボタンが表示されなくなっていることがある。
  • 現象発生時、DOM ツリーに変化があるたびにコールされるようになっている関数(main.js 内の start())までは呼び出されているが、オプション設定を読み込むために発行したchrome.runtime.sendMessage()のコールバック関数が呼び出されていないように見える。
  • background.js 側のchrome.runtime.onMessage.addListener()で設定した関数も呼び出されていない(ただし、他タブでタイムラインを表示したところ、正しく呼び出される)。

ということで、sendMessage() コール後のメッセージ送受信処理のどこかで滞ってしまっている可能性が高い。

もし上記推測通りとすると、Chrome の不具合の可能性が高くなってくるため、ユーザー(拡張機能開発者)側で抜本的な対策を取るのは難しいかもしれない。

回避策としては、現状イベント発生(DOMツリー更新や[Enter]キー押下時)のたびにオプション取得(background.js とのメッセージ送受信)処理を実施しているのをやめ、なるべく頻度を減らす、という方向性はどうか?

  1. main.js が起動した直後の一回だけにする(結果として、オプション変更内容の反映はタブのリロード時に行われることとなるので、リアルタイムではなくなる)。
  2. 起動時とオプション画面からの変更時にのみ、実施する。

自作のスクリプト(原寸びゅー等)では手を抜いて基本、1. の方針にしているが、本来は 2. にすべきだろう……では、オプション変更時にどうやって各タブに通知すればよいのか?

という経緯と思考過程があって、記事にまとめてみた次第。

*1:localStorage には文字列しか格納できないため、contents_script が利用しやすい形(連想配列など)に変換してやる必要がある

Viewing all 92 articles
Browse latest View live