Closed30

DesmosのChrome拡張を作る

HyrodiumHyrodium

作りたいもの

  • Desmosの数式などをテキストでimport/exportできるようにする
  • Chrome拡張のアイコンをクリックするとテキストボックスとimport/exportのボタンがある

意義

  • グラフの保存がローカルでできるようになる
  • グラフをgit等でバージョン管理できるようになる
  • 色を標準の6色以上設定できるようになる
  • 画像を不可逆圧縮なしで挿入可能
  • LaTeX入力をお気に入りのエディタで編集できる
  • テーブルデータの取り込みができる
HyrodiumHyrodium

上記のconsole.log("hoge")のところでCalc.getState()したがCalcが定義されてないと怒られる。
スコープが違うのは当然だと思うが、どのように分離されてるのかまだ分かっていない

HyrodiumHyrodium

https://qiita.com/k7a/items/26d7a22233ecdf48fed8

特に「ページ内の変数や関数にアクセスができない」というのがなかなか厄介で、要するにContent Scriptはページ上のスクリプトから隔離されたスコープで実行されているということです。
この特殊な実行環境は公式ドキュメントによるとisolated worldと呼ばれています。
但し、DOMの取得・操作は出来るため、例えばページ内で定義されている関数を実行したい場合など、Webページのスコープ内でスクリプトを実行したい場合は、以下のようにscript要素を挿入してやることで実現できます。

を参考にmy-extension-bを作成して実行。しかし

myscript.js:3 Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval'". Either the 'unsafe-inline' keyword, a hash ('sha256-5KUX4DuAakiviv/EBxmQrE/U2E7Uvb+4BTX2tQ24DgU='), or a nonce ('nonce-...') is required to enable inline execution.

のエラーが出てしまった。
記事が古くてv3に対応していないのも影響してそうな気がする。

HyrodiumHyrodium

現時点での理解

  • Ctrl+Shift+IのConsoleで実行できたとしても、それをChrome拡張にするのは自明ではない
  • 変数のスコープが紛らわしく、Consoleと同じ環境で実行するにはdocument.bodyにinline scriptを入れる必要がある
  • しかし、inline scriptを許可するのはセキュリティによろしくなく、Chromeが禁止するようになった
  • 方法はありそうな気がするが…どうすれば…
HyrodiumHyrodium

よく分からんが https://stackoverflow.com/questions/67439012/chrome-extension-manifest-v3-content-security-policy をベースにしてスコープの問題は解決。

manifest.json

{
    "name": "My Extension C",
    "description": "My Extension C",
    "version": "1.0",
    "manifest_version": 3,
    "content_scripts": [
        {
            "matches": [
                "https://www.desmos.com/calculator/*"
            ],
            "run_at": "document_end",
            "js": [
                "inject.js"
            ]
        }
    ],
    "web_accessible_resources": [
        {
            "resources": [
                "myscript.js"
            ],
            "matches": [
                "https://*/*"
            ]
        }
    ]
}

inject.js

function injectCode(src) {
    const script = document.createElement('script');
    script.src = src;
    script.onload = function() {
        console.log("script injected");
        this.remove();
    };

    document.documentElement.appendChild(script);
}

injectCode(chrome.runtime.getURL('/myscript.js'));

myscript.js

(async () => {
    const sleep = (second) => new Promise(resolve => setTimeout(resolve, second * 1000))
    await sleep(3)
    state = Calc.getState();
    console.log(state);
})()
  • web_accessible_resourcesが何かはまだ分かっていない。
  • 参考の回答での"run_at": "document_start""run_at": "document_end"に置き換えている。ドキュメント読み込み終了時(?)に実行しないとCalcが未定義になるため。
  • 実行前に3秒のスリープを入れている。スリープしない場合、Calcが未定義の状態で実行を始めてしまう。
  • sleepのコードは https://www.wakuwakubank.com/posts/695-javascript-timer-sleep/ を参考にした。
  • 今後はpopup(?)のボタンを呼び出したときにコードを実行することになるので、sleepは不要になるはず。
HyrodiumHyrodium

上記のYukiさんの「【超基礎】Chrome拡張機能の作り方ハンズオン:version 3」がかなり参考になった。

popupのボタンを押してCalc.getState()するところまではできた。(my-extension-e)

ただし

  • myscript.jsの変数をcontent.jsに送る方法
  • その逆

が分からない

HyrodiumHyrodium

上記のteratailを参考にして少し進んだ。(my-extension-f)

  • my-extension-eではcontent.jsからconsoleにgetStateした結果を表示できない問題があった
  • これを部分的に解決して、content.js中でgetStateした結果をconsoleに送れた(気がする)。しかしwindow.dispatchEventwindow.addEventListenerの使い方が分かっていないために非同期処理や変数のスコープの問題を解決できていない。
  • addEventListenerをボタンを押すたびに実行するのは良くない…?
HyrodiumHyrodium

式を参照してテキストボックスへのコピーができるようになった〜🎉🎉🎉🎉🎉

HyrodiumHyrodium

元々やりたかった機能は実装できた🎉🎉🎉🎉🎉

あとは色々体裁を整えて完了かな

HyrodiumHyrodium

Desmosとしてはオンラインでグラフを保存して欲しいはずで、テキスト形式でローカルに保存するのは運営側の思想からは外れそう。オンライン保存→共有が便利すぎるので、営業妨害(?)にはならないとは思う。

どこかに確認取らなくて良いのだろうか

HyrodiumHyrodium

広告ブロック拡張が野放しになってるくらいだから開発ルールとしてはあまり気にしなくて良さそう。Desmosが好きなので、運営側に迷惑かけたくない気持ちの方が強い

HyrodiumHyrodium

欧州経済領域のルールが全然分からない…。

  • 市場(?)が金銭のやりとりを指すならトレーダーには該当しなさそう
  • 技術的な目的で活動しているならトレーダーには該当しそう
  • そもそもChrome Web StoreにDevelopperとして登録しているなら技術的な目的が包含されるのは当然では?

後から変更可能で、トレーダーを選択した場合は住所などを追加で設定する必要があったので、一旦は非トレーダーとして申告した

HyrodiumHyrodium

目的は全て果たしたのでこれにてスクラップをクローズします。上記のmy-extension-*は私のprivate repoに置いていますが、公開する意味がなさそうなのでprivateのままにしておきます。コードが気になる方は https://github.com/hyrodium/DesmosTextIO をご覧ください。

このスクラップは2022/08/10にクローズされました