web-dev-qa-db-ja.com

Chromeコンテンツスクリプトが機能していません:DOMContentLoadedリスナーが実行されません

1つのフォーラムでスペルミスを修正する拡張機能をコーディングしようとしています。

コンテンツスクリプトを使用して<p>タグにアクセスしようとしていますが、何も変更されません(以下のコードを使用)。

document.addEventListener("DOMContentLoaded", function() {
    document.getElementsByTagName("P")[4].innerHTML = "correct_Word"; 
}); 

拡張機能として追加しても何も変更されません。明らかに、ページをwgetしてそこにスクリプトを配置すると、すべて機能します。何かご意見は?

私のmanifest.jsonファイル:

{
    "manifest_version": 2,
    "name": "Extension",
    "description": "Description",
    "version": "1.0",
    "content_scripts": [{
        "run_at": "document_end",
        "matches": ["http://example.com/"],
        "js": ["script.js"]
    }],
    "web_accessible_resources": ["Filedeleted(really).html"]
}

コンテンツスクリプトとWWWページのサンドボックスが異なることは知っていますが、コンテンツスクリプトがページ(およびタグ)にアクセスできない可能性がありますか?

11
J morris

火災をリッスンしているイベントの後にスクリプトを挿入しています(この場合、 DOMContentLoaded )。したがって、リスナーを追加した後はイベントが発生しないため、リスナーにあるコードは実行されません。

Chrome拡張機能とFirefoxWebExtensionsでは、 コンテンツスクリプト を挿入する時間を指定するときに、_"document_start"_、_"document_end"_、を指定できます。または_"document_idle"_。1manifest.jsonでは、これは_run_at_プロパティに指定された値です。 tabs.executeScript() の場合、これはrunAtプロパティです。

  • _document_start_
    インジェクションは、DOMが作成される前、またはページのスクリプトが実行される前に行われます。これは、_document.body_と_document.head_がまだ存在しないことを意味します。 DOMContentLoadedおよびwindowloadイベントはまだ発生していません。 _document.documentElement_に追加することで、DOMに追加できます。 MutationObserver を使用して、DOMに追加することに関心のある要素を監視するか、DOMContentLoadedのようなイベントを待ってDOMが利用可能です。
  • _document_end_(デフォルト)
    インジェクションは、DOMが完了した後、サブリソース(画像やフレームなど)が読み込まれる前に行われます。これは通常、DOMContentLoadedが発生した後、windowloadイベントが発生する前です。
  • _document_idle_
    インジェクションは、_document_end_の後、およびwindowloadイベントが発生した直後に行われます。 「run_at:document_idleコンテンツスクリプトはいつ実行されますか?」への回答 は、これが次のいずれか早い方であることを示します。

    • windowloadイベントが発生した後、または
    • DOMContentLoadedイベントが発生してから200ミリ秒。

    これは、DOMContentLoadedが発生した後にコンテンツスクリプトが挿入されるが、windowloadイベントがすでに発生している場合と発生していない場合があることを意味します。

DOMContentLoaded 、またはwindowloadをリッスンするときは、最初に _document.readyState_ を確認する必要があります。

DOMContentLoadedリスナーまたはwindowloadリスナーを使用するときはいつでも、追加する前に常に _document.readyState_ を確認する必要があります。リスナーを使用して、DOMContentLoadedイベントが発生する前(または、loadイベントが発生する前)にリスナーを追加していることを確認します。これらのイベントを聞きたいときは、これは通常の習慣です。イベントの発生後にリスナーを追加すると、リスナーは実行されません。

DOMContentLoadedリスナーを追加するには、次のようなものを使用する必要があります。

_if(document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded',afterDOMLoaded);
} else {
    afterDOMLoaded();
}

function afterDOMLoaded(){
    //Everything that needs to happen after the DOM has initially loaded.
}
_

windowloadリスナーを追加するには、次のようなものを使用できます。

_if(document.readyState !== 'complete') {
    window.addEventListener('load',afterWindowLoaded);
} else {
    afterWindowLoaded();
}

function afterWindowLoaded(){
    //Everything that needs to happen after the window is fully loaded.
}
_

  1. tabs.executeScript()を使用している場合、runAtに指定する値は、スクリプトを挿入する最も早い時期のみを示します。その時間より前にtabs.executeScript()を実行している場合、注入は指定された時間まで遅延されます。 _document_start_の場合、tabs.executeScript()を実行するときに新しいページで有効になるポイントは複雑なトピックであり、独自の質問/回答に値することに注意してください。
  2. この回答の一部は 「アクティブなHTMLページでのボタンクリックの検出と処理」に対する私の回答 からコピーされました。
15
Makyen