web-dev-qa-db-ja.com

ユーザーにChrome拡張機能がインストールされているかどうかを確認します

私はChrome拡張機能を構築中です。すべてが私が望むように機能するためには、ユーザーが拡張機能がインストールされました。

例:ユーザーがプラグインをインストールしてから、スクリプトを含むWebサイトに移動します。 Webサイトは拡張機能がインストールされていることを検出し、それに応じてページを更新します。

これは可能ですか?

86
user179169

直接的な方法(拡張機能の関数を直接呼び出すか、拡張機能にJSクラスを使用する)がありますが、間接的な方法(何かがうまくいくまで)はあると確信しています。

Chrome拡張機能で、ページ上の特定のDIVまたはその他の要素を、非常に具体的なIDで探してください。

例えば:

<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>

getElementByIdを実行し、innerHTMLを拡張機能などのバージョン番号に設定します。その後、そのクライアント側のコンテンツを読み取ることができます。

ただし、使用可能な方法がある場合は、直接的な方法を使用する必要があります。


編集:直接メソッドが見つかりました!!

ここにある接続方法を使用します。 https://developer.chrome.com/extensions/extension#global-events

未テストですが、できるはずです...

var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
42
Brad

Chromeは、ウェブサイトから拡張機能にメッセージを送信できるようになりました。

そのため、拡張子background.js(content.jsは機能しません)に次のようなものを追加します。

chrome.runtime.onMessageExternal.addListener(
    function(request, sender, sendResponse) {
        if (request) {
            if (request.message) {
                if (request.message == "version") {
                    sendResponse({version: 1.0});
                }
            }
        }
        return true;
    });

これにより、Webサイトから電話をかけることができます。

var hasExtension = false;

chrome.runtime.sendMessage(extensionId, { message: "version" },
    function (reply) {
        if (reply) {
            if (reply.version) {
                if (reply.version >= requiredVersion) {
                    hasExtension = true;
                }
            }
        }
        else {
          hasExtension = false;
        }
    });

その後、hasExtension変数を確認できます。唯一の欠点は呼び出しが非同期であるため、どうにかして回避する必要があります。

編集:以下で説明するように、アドオンにメッセージを送信できるドメインをリストするmanifest.jsonにエントリを追加する必要があります。例えば:

"externally_connectable": {
    "matches": ["*://localhost/*", "*://your.domain.com/*"]
},
103
BJury

別の方法は Webアクセス可能なリソースを公開する ですが、これにより、どのWebサイトでも拡張機能がインストールされているかどうかをテストできます。

拡張機能のIDがaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaで、拡張機能のファイルに_test.png_としてファイル(透明ピクセル画像など)を追加するとします。

次に、_web_accessible_resources_マニフェストキーを使用して、このファイルをWebページに公開します。

_  "web_accessible_resources": [
    "test.png"
  ],
_

Webページで、このファイルを完全なURL(_<img>_タグ内、XHR経由、またはその他の方法)で読み込むことができます。

_chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.png
_

ファイルがロードされると、拡張機能がインストールされます。このファイルの読み込み中にエラーが発生した場合、拡張機能はインストールされていません。

_// Code from https://groups.google.com/a/chromium.org/d/msg/chromium-extensions/8ArcsWMBaM4/2GKwVOZm1qMJ
function detectExtension(extensionId, callback) { 
  var img; 
  img = new Image(); 
  img.src = "chrome-extension://" + extensionId + "/test.png"; 
  img.onload = function() { 
    callback(true); 
  }; 
  img.onerror = function() { 
    callback(false); 
  };
}
_

注意:このファイルのロード中にエラーが発生した場合、コンソールにネットワークスタックエラーが表示され、沈黙する可能性はありません。 Chromecastがこの方法を使用した場合、 かなりの論争を引き起こしました このため;単に非常に具体的なエラーをブラックリストに登録 Chromeチームによる完全に開発ツールから).


重要な注意:このメソッドはFirefox WebExtensionsでは機能しません。 URLはIDを知ることで予測できるため、Webアクセス可能なリソースは本質的に拡張機能をフィンガープリントに公開します。 Firefoxは、Webアクセス可能なリソースに インスタンス固有のランダムURLを割り当てる によってその穴を閉じることにしました。

ファイルは、次のようなURLを使用して利用可能になります。

_moz-extension://<random-UUID>/<path/to/resource>
_

このUUIDは、ブラウザインスタンスごとにランダムに生成され、拡張機能のIDではありません。これにより、ユーザーがインストールした拡張機能をWebサイトがフィンガープリントできなくなります。

ただし、拡張機能はruntime.getURL()を使用してこのアドレスを取得できますが、Webサイトでハードコーディングすることはできません。

19
Xan

これに関する私の研究を共有すると思いました。いくつかのfile:///リンクが機能するために、特定の拡張機能がインストールされているかどうかを検出できるようにする必要がありました。私はこの記事に出会いました here これは、拡張機能のmanifest.jsonを取得する方法を説明しました。

私はコードを少し調整して思いついた:

function Ext_Detect_NotInstalled(ExtName, ExtID) {
  console.log(ExtName + ' Not Installed');
  if (divAnnounce.innerHTML != '')
    divAnnounce.innerHTML = divAnnounce.innerHTML + "<BR>"

  divAnnounce.innerHTML = divAnnounce.innerHTML + 'Page needs ' + ExtName + ' Extension -- to intall the LocalLinks extension click <a href="https://chrome.google.com/webstore/detail/locallinks/' + ExtID + '">here</a>';
}

function Ext_Detect_Installed(ExtName, ExtID) {
  console.log(ExtName + ' Installed');
}

var Ext_Detect = function (ExtName, ExtID) {
  var s = document.createElement('script');
  s.onload = function () { Ext_Detect_Installed(ExtName, ExtID); };
  s.onerror = function () { Ext_Detect_NotInstalled(ExtName, ExtID); };
  s.src = 'chrome-extension://' + ExtID + '/manifest.json';
  document.body.appendChild(s);
}

var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;

if (is_chrome == true) {
  window.onload = function () { Ext_Detect('LocalLinks', 'jllpkdkcdjndhggodimiphkghogcpida'); };
}

これにより、Ext_Detect(ExtensionName、ExtensionID)を使用して、任意の数の拡張機能のインストールを検出できるはずです。

18
Nato

Webサイトを所有している場合の別の可能な解決策は、 インラインインストール を使用することです。

if (chrome.app.isInstalled) {
  // extension is installed.
}

私はこれを古い質問を知っていますが、この方法はChrome 15で導入されたので、答えを探している人だけにIdをリストすると思いました。

7
PAEz

あなたの拡張機能はウェブサイトと相互作用し(変数の変更など)、ウェブサイトはこれを検出できます。

しかし、これを行うためのより良い方法があるはずです。 Googleが拡張ギャラリーでどのように実行しているのだろう(既にインストールされているアプリケーションにはマークが付けられている)。

編集:

ギャラリーは chrome.management.get 関数を使用します。例:

chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});

ただし、適切な権限を持つページからのみメソッドにアクセスできます。

3
Fox32

拡張機能 Cookieを設定 を使用し、WebサイトでそのCookieが存在するかどうかをJavaScriptでチェックし、それに応じて更新することができます。これとおそらくここで言及した他のほとんどの方法は、もちろんユーザーによって暗号化される可能性があります、unlessあなたが試して、タイムスタンプなどに応じてカスタムCookieを作成する拡張サーバー側でアプリケーションを分析して、実際に拡張機能を持っているユーザーか、Cookieを変更してそれを持っているふりをしているかどうかを確認します。

3
Niklas

このGoogleグループの投稿 に示されている別の方法があります。つまり、拡張機能アイコンが正常にロードされるかどうかを検出してみることができます。これは、チェックしている拡張機能が自分のものではない場合に役立ちます。

3
Beau

Cookieメソッドを使用しました。

Manifest.jsファイルには、サイトでのみ実行されるコンテンツスクリプトを含めました。

 "content_scripts": [
        {
        "matches": [
            "*://*.mysite.co/*"
            ],
        "js": ["js/mysite.js"],
        "run_at": "document_idle"
        }
    ], 

私のjs/mysite.jsには1行あります:

document.cookie = "extension_downloaded=True";

そして、index.htmlページでそのCookieを探します。

if (document.cookie.indexOf('extension_downloaded') != -1){
    document.getElementById('install-btn').style.display = 'none';
}
3
Chase Roberts

ここまでの回答の多くは、Chromeのみであるか、HTTPオーバーヘッドのペナルティが発生します。使用しているソリューションは少し異なります。

1.次のように、マニフェストのcontent_scriptsリストに新しいオブジェクトを追加します。

{
  "matches": ["https://www.yoursite.com/*"],
  "js": [
    "install_notifier.js"
  ],
  "run_at": "document_idle"
}

これにより、install_notifier.jsのコードがそのサイトで実行できるようになります(まだアクセス許可がない場合)。

2.上記のマニフェストキーのすべてのサイトにメッセージを送信します。

次のようなものをinstall_notifier.jsに追加します(変数がグローバルにならないようにクロージャーを使用していることに注意してください)

// Dispatch a message to every URL that's in the manifest to say that the extension is
// installed.  This allows webpages to take action based on the presence of the
// extension and its version. This is only allowed for a small whitelist of
// domains defined in the manifest.
(function () {
  let currentVersion = chrome.runtime.getManifest().version;
  window.postMessage({
    sender: "my-extension",
    message_name: "version",
    message: currentVersion
  }, "*");
})();

あなたのメッセージは何でも言うことができますが、あなたがあなたが何を扱っているかを知るためにバージョンを送ることは役に立ちます。その後...

3. Webサイトで、そのメッセージを聞きます。

これをあなたのウェブサイトのどこかに追加してください:

window.addEventListener("message", function (event) {
  if (event.source == window &&
    event.data.sender &&
    event.data.sender === "my-extension" &&
    event.data.message_name &&
    event.data.message_name === "version") {
    console.log("Got the message");
  }
});

これは、FirefoxとChromeで機能し、HTTPオーバーヘッドが発生したり、ページを操作したりすることはありません。

3
mlissner

Webページは、バックグラウンドスクリプトを介して拡張機能と対話します。

manifest.json:

"background": {
    "scripts": ["background.js"],
    "persistent": true
},
"externally_connectable": {
    "matches": ["*://(domain.ext)/*"]
},

background.js:
chrome.runtime.onMessageExternal.addListener(function(msg, sender, sendResponse) {
    if ((msg.action == "id") && (msg.value == id))
    {
        sendResponse({id : id});
    }
});

page.html:

<script>
var id = "some_ext_id";
chrome.runtime.sendMessage(id, {action: "id", value : id}, function(response) {
    if(response && (response.id == id)) //extension installed
    {
        console.log(response);
    }
    else //extension not installed
    {
        console.log("Please consider installig extension");
    }

});
</script>
3

どのWebサイトからも拡張子を検出しようとしている場合、この投稿は役に立ちました: https://ide.hey.network/post/5c3b6c7aa7af38479accc0c7

基本的に、解決策は、パスを指定することにより、拡張機能から特定のファイル(manifest.jsonまたはイメージ)を取得することです。これが私が使ったものです。間違いなく動作します:

const imgExists = function(_f, _cb) {
    const __i = new Image();
    __i.onload = function() {
        if (typeof _cb === 'function') {
            _cb(true);
        }
    }
    __i.onerror = function() {
        if (typeof _cb === 'function') {
            _cb(false);
        }
    }
    __i.src = _f;
    __i = null;
});

try {
    imgExists("chrome-extension://${CHROME_XT_ID}/xt_content/assets/logo.png", function(_test) {
        console.log(_test ? 'chrome extension installed !' : 'chrome extension not installed..');
        ifrm.xt_chrome = _test;
        // use that information
    });
} catch (e) {
    console.log('ERROR', e)
}
0
nab.

また、私が使用したクロスブラウザメソッドを使用することもできます。 divを追加するという概念を使用します。

コンテンツスクリプト内(スクリプトが読み込まれるたびに、これを行う必要があります)

if ((window.location.href).includes('*myurl/urlregex*')) {
        $('html').addClass('ifextension');
        }

あなたのウェブサイトでは

if (!($('html').hasClass('ifextension')){}

そして、適切なメッセージを投げます。

0
Prakash Palnati

Chrome拡張機能を制御できる場合は、私がやったことを試すことができます。

// Inside Chrome extension
var div = document.createElement('div');
div.setAttribute('id', 'myapp-extension-installed-div');
document.getElementsByTagName('body')[0].appendChild(div);

その後:

// On web page that needs to detect extension
if ($('#myapp-extension-installed-div').length) {

}

少しハックが感じられますが、他のメソッドを動作させることができず、Chrome=ここでAPIを変更することを心配します。

0
gwg