55

私が取り組んでいる Chrome 拡張機能をインストールまたはアップグレードした後、コンテンツ スクリプト (マニフェストで指定) は再挿入されないため、拡張機能を機能させるにはページを更新する必要があります。スクリプトを強制的に再度挿入する方法はありますか?

マニフェストからそれらを削除し、バックグラウンド ページに挿入するページを処理することで、プログラムで再度挿入できると思いますが、これは良い解決策ではありません。

データの一部が失われる可能性があるため、ユーザーのタブを自動的に更新したくありません。Safari では、拡張機能をインストールまたはアップグレードすると、すべてのページが自動的に更新されます。

4

6 に答える 6

39

コンテンツ スクリプトの重い拡張機能をアップグレード後も引き続き機能させ、インストール後すぐに機能させる方法があります。

インストール/アップグレード

インストール方法は、すべてのウィンドウのすべてのタブを単純に反復し、一致する URL を持つタブにプログラムでいくつかのスクリプトを挿入することです。

もちろん、manifest.json で宣言されたバックグラウンド ページまたはイベント ページスクリプトで実行する必要があります。

"background": {
    "scripts": ["background.js"]
},

background.js:

// Add a `manifest` property to the `chrome` object.
chrome.manifest = chrome.runtime.getManifest();

var injectIntoTab = function (tab) {
    // You could iterate through the content scripts here
    var scripts = chrome.manifest.content_scripts[0].js;
    var i = 0, s = scripts.length;
    for( ; i < s; i++ ) {
        chrome.tabs.executeScript(tab.id, {
            file: scripts[i]
        });
    }
}

// Get all windows
chrome.windows.getAll({
    populate: true
}, function (windows) {
    var i = 0, w = windows.length, currentWindow;
    for( ; i < w; i++ ) {
        currentWindow = windows[i];
        var j = 0, t = currentWindow.tabs.length, currentTab;
        for( ; j < t; j++ ) {
            currentTab = currentWindow.tabs[j];
            // Skip chrome:// and https:// pages
            if( ! currentTab.url.match(/(chrome|https):\/\//gi) ) {
                injectIntoTab(currentTab);
            }
        }
    }
});

マニフェストV3

マニフェスト.json:

"background": {"service_worker": "background.js"},
"permissions": ["scripting"],
"host_permissions": ["<all_urls"],

これらの host_permissions は、コンテンツ スクリプトのmatches.

background.js:

chrome.runtime.onInstalled.addListener(async () => {
  for (const cs of chrome.runtime.getManifest().content_scripts) {
    for (const tab of await chrome.tabs.query({url: cs.matches})) {
      chrome.scripting.executeScript({
        target: {tabId: tab.id},
        files: cs.js,
      });
    }
  }
});

これは、フレームを処理しない単純化された例です。getAllFrames API を使用して、自分で URL を照合できます。パターンの照合については、ドキュメントを参照してください。

歴史のトリビア

古い Chrome 26 以前のコンテンツ スクリプトでは、バックグラウンド スクリプトへの接続を復元できました。2013 年にhttp://crbug.com/168263で修正されました。この回答の以前のリビジョンで、このトリックの例を見ることができます。

于 2012-07-22T08:23:56.067 に答える
24

ページを更新せずにコンテンツ スクリプトを強制的に挿入する唯一の方法は、プログラム インジェクションを使用することです。

chrome tabs API を使用して、すべてのタブを取得し、それらにコードを挿入できます。たとえば、マニフェスト バージョンをローカル ストレージに保存し、そのマニフェスト バージョンが古いバージョン (バックグラウンド ページ) であるかどうかを毎回確認できます。拡張機能が更新されていることを確認してください。

以下を使用してすべてのタブを取得:
chrome.tabs.query

コードをすべてのページに挿入します
chrome.tabs.executeScript(tabId, {file: "content_script.js"});

于 2012-06-20T18:11:05.613 に答える
0

https://bugs.chromium.org/p/chromium/issues/detail?id=168263により、コンテンツ スクリプトとバックグラウンド スクリプトの間の接続が切断されています。他の人が述べたように、この問題を回避する 1 つの方法は、コンテンツ スクリプトを再挿入することです。大まかな概要は、この StackOverflow answerで詳しく説明されています。

主なトリッキーな部分は、新しいコンテンツ スクリプトを挿入する前に、現在のコンテンツ スクリプトを「破棄」する必要があることです。破棄は非常に難しい場合があるため、破棄しなければならない状態の量を減らす 1 つの方法は、DOM を介してメイン コンテンツ スクリプトと対話する小さな再注入可能なスクリプトを作成することです。

于 2020-06-28T04:52:09.050 に答える
-13

バージョンアップしたcssやjsの最後に追加できない?ver=2.10の?

"content_scripts": [ {
      "css": [ "css/cs.css?ver=2.10" ],
      "js": [ "js/contentScript.js?ver=2.10" ],
      "matches": [ "http://*/*", "https://*/*" ],
      "run_at": "document_end"
   } ],
于 2012-10-31T17:34:06.430 に答える