Google Chromeブラウザーの拡張機能を開発してきた5年間で、いくつかの経験が蓄積されており、一連の記事で共有し、可能であれば、微妙さ、落とし穴のいくつかを説明し、最新のフロントエンドテクノロジーがどのようにうまく適用されたかについて説明したいと思います。
パート1
はじめに
Amazonストアフロントから商品を積極的に購入していた2012年に、Google Chromeブラウザーの拡張機能に遭遇しました。ロシア連邦に商品を配送し、配送費用を考慮して最も収益性の高い販売者を探すのは非常に不便でした。 ここで、私は自分自身と他の顧客にとっても楽になるように、「Amazonがあなたに出荷する」拡張機能を作成することに
しました 。 時間が経つにつれて、それは無関係になりました、なぜなら 数年後、通常のフィルターがAmazonのディスプレイウィンドウで作成され、出版物から削除しました。
それから、
Y.Muzykと
Y.Radioのサービスを使用する時が来ました。Y.Muzykiがバックグラウンドタブでプレイしているとき、少なくともホットキーを使ってプレイするとき、私は本当にプレーヤーコントロールを欠いていました。 その結果、経験豊富な人として、アナログを見つけられなかったため、
Yandexからの
公式の拡張にもかかわらず、このための
拡張機能「Yandex.Music-player control」を作成することにしました。
読者は、拡張要素の基本構造(
manifest.json 、
背景ページ 、
コンテンツスクリプト 、
popup )に既に精通している必要があります。 以下のネタバレの下での簡単な教育プログラム。
サンドボックス
典型的な拡張タスクは、特定のサイトの機能を拡張することです。そのためには、ランディングページにコードを埋め込む必要があります。 Ya.Muzykuを例に挙げます(以下):ポップアップ拡張ウィンドウ(スクリーンショット1を参照)でサイトのプレーヤーを制御するには、ページの開始を追跡し、コードを埋め込みます。コードとDOMがショーケースを表示し、拡張機能へのすべての変更を転送するため、ポップアップウィンドウを開いたときに、常にショーケースにプレーヤーの現在の状態が表示されます。 これは、私が始めたい重要なものが現れる場所であり、そのセクションの名前は
サンドボックスです。

(スクリーンショット番号1)
メインの拡張コントローラーであるバックグラウンド拡張ページは、適切な拡張機能(
tabs、activeTab )がある場合、
chrome.tabs.onUpdatedを使用して
music.yandex.ruページの開始を追跡し、
chrome.tabs.executeScriptを
介してコード(コンテンツスクリプト)をウィンドウに埋め込むことができます
。 。 ただし、埋め込みコードはサンドボックス(B)にあり、そこからストアフロントDOMドキュメントにアクセスできますが、サンドボックス(A)で実行されるストアフロントjs-codeにはアクセスできません。 理論的には、ウィンドウ上のDOM要素の変更を追跡して現在の状態を拡張機能に変換することは可能ですが(たとえば、トラックが変更されました-DOMからトラックの名前を取得します)、これは希望どおりに機能しません:ウィンドウの更新の遅延ではなく、ストアフロントの現在のディスプレイや、エクステンションを実際に使用しているときにストアフロントとエクステンションのディスプレイ間でデータの同期が取れないその他のものに、常にターゲットDOM要素を提示します。 ショーケースjsコード(サンドボックスA)にアクセスするにはどうすればよいですか?
コンテンツスクリプトからサンドボックスAにjs-codeを埋め込むには、次の「ハック」が役立ちます(以降、es6表記)。
function injectCode(func, ...args) { let script = document.createElement('script'); script.textContent = 'try {(' + func + ')(' + args + '); } catch(e) {console.error("injected error", e);};'; (document.head || document.documentElement).appendChild(script); script.parentNode.removeChild(script); }
その結果、コンテンツスクリプトは、ショーケースAPIにアクセスするためにコードをショーケースjs-codeのサンドボックスに埋め込み、低レベルでプレーヤー、プレイリスト、その他のショーケースエンティティのオブジェクトとイベントにアクセスできます。 ただし、それだけではありません。たとえば、埋め込みコードがトラックの再生を開始したイベントを「キャッチ」しましたが、どのようにコンテンツスクリプトに送り返すことができますか?コンテンツスクリプトには、拡張機能のバックグラウンドページにデータを転送するメカニズムがあります?
残念ながら、サンドボックスAからサンドボックスBへのアクセスはありません。いずれにしても、私には不明です。 しかし、これは恐ろしいことではありません。サンドボックスBのコンテンツスクリプトがストアフロントのDOMドキュメントにアクセスできることを覚えているからです。したがって、出力:サンドボックスAに埋め込まれたコードは任意のイベントを作成できます。
document.dispatchEvent(new CustomEvent(CUSTOM_EVENT_NAME, {detail: payload}));
そして、コンテンツスクリプトはそれらをキャッチできます。
document.addEventListener(CUSTOM_EVENT_NAME, e => { console.log(e.detail);
次のスキームが判明します。
その後、コンテンツスクリプトは、
chrome.runtime.sendMessageまたは
chrome.runtime.connectの いずれかのメカニズムを使用してこのイベントをバックグラウンドページに
渡します。 それらの違いは、最初のメソッドはチャネルを開き、データを送信し、チャネルを閉じ、2番目のメソッドはデータが送信される永続的なチャネルを作成することです。 トラックを再生するとき、進行状況イベントは常に送信されています(現在の再生時間)。したがって、選択は明白になりました:コンテンツスクリプトとバックグラウンドページ間の通信の一定のチャネルを上げることで、明らかではない別のボーナスを提供します:さまざまな理由によるショーケースとの接続の喪失の制御タブを閉じる前のjsコードの例外(ただし、タブを閉じることは
chrome.tabs.onRemovedで簡単に追跡でき
ます )。
これらのサンドボックスは完成しましたが、それだけではありません。背景ページのサンドボックス(B)とポップアップウィンドウのサンドボックス(G)がまだあります。 ここではすべてが少しシンプルになり、これらのサンドボックスはAPIを介して相互にアクセスできます。
ただし、落とし穴があります。たとえば、ポップアップウィンドウはイベントリスナーをバックグラウンドページに追加できませんが、上記のメソッドは(同じスレッドで実行されているため)互いにウィンドウオブジェクトにアクセスできます。 相互通信の均一性と、ポップアップウィンドウコードからのバックグラウンドページコードの強制的な分離のために(そうでない場合、ポップアップはbgオブジェクトを変更し、コンテンツスクリプトからバックグラウンドページへの一方向のデータストリームを中断し、現在の状態をそこからポップアップウィンドウに保存します)、同じに切り替えましたチャンネルを上げるだけでなく、コンテンツスクリプトとバックグラウンドページの間で。
コードと例が少ないのは、 すべてはドキュメントにあります。メソッドとAPIについては可能な限り言及しますが、コードに関しては、ここに追加するものはありません。 チュートリアルステータスのふりをしません(コード全体をコピーして何かを獲得できる場合)。 しかし、コンセプト自体は噛む価値がありました。 プログラマーワークショップで同僚に繰り返し説明しました。 このセクションは次のように要約できます。
次のパートでは、拡張機能
「Yandex.Music-player control」の 、現在人気のあるReact + Reduxへの翻訳の履歴について説明します。これは、ポップアップ拡張ウィンドウにプレーヤーのステータスを表示するのに適していました。