動的なページの読み込みが完了してからChrome拡張機能を実行する方法


やりたいこと

  • Chrome拡張機能において、ページの読み込み後に要素を取得する処理をしたい。
    • 該当のページは動的に生成され、取得したい要素が表示されるまでタイムラグが存在するため、Content Scriptだけでは実現できない。

実現方法

上記に書いてあることそのままですが、一応下記に説明を記載します。

完成したコード

manifest.json
{
  "name": "Name of Extension",
  "version": "1.0",
  "manifest_version": 2,
  "description": "説明",
  "icons": {
    "16": "16px.png"
  },
  "content_scripts": [
    {
      "matches": [
        "http://対象のURL/*"
      ],
      "js": [
        "script.js"
      ],
      "run_at": "document_end",
      "all_frames": true
    }
  ]
}
script.js
window.addEventListener("load", main, false);

function main(e) {
    const jsInitCheckTimer = setInterval(jsLoaded, 1000);
    function jsLoaded() {
        if (document.querySelector('#取得したい要素') != null) {
            clearInterval(jsInitCheckTimer);
  //要素を取得する処理
};

コードの説明

manifest.json
  "content_scripts": [
    {
      "matches": [
        "http://対象のURL/*"
      ],
      "js": [
        "script.js"
      ],
      "run_at": "document_end",
      "all_frames": true
    }
  ]

Content Scriptで、指定のURLを読み込み時にscript.jsが実行されるようにします。
(ページ内にフレームが含まれる場合には、"all_frames": trueとして、フレーム内のページもスクリプトの実行対象に含めます。)

"run_at": "document_end"を記載していますが、公式ドキュメントに記載の通り、フレームなどはロードされる前に実行されてしまいます。

Scripts are injected immediately after the DOM is complete, but before subresources like images and frames have loaded.
Content Scripts - Google Chrome

script.js
window.addEventListener("load", main, false);

そこで、DOM読込完了した時点ではaddEventListenerでウィンドウを監視して、フレームやJavascriptの読み込みが完了した時点でメインの処理を動かすようにします。

script.js
function main(e) {
    const jsInitCheckTimer = setInterval(jsLoaded, 1000);
    function jsLoaded() {
        if (document.querySelector('#取得したい要素') != null) {
            clearInterval(jsInitCheckTimer);
  //要素を取得する処理
};

更に、setIntervalを使用して、取得したい要素が読み込まれるまで、間隔を置いて処理を実行します。
これで、指定の要素が現れるのを待って、拡張機能を動かすことができます。

参考サイト