私はChrome拡張機能を作成している最中です。全体を思い通りに機能させるには、ユーザーが私の拡張機能をインストールしているかどうかを検出できる外部JavaScriptスクリプトが必要です。
例:ユーザーがプラグインをインストールしてから、スクリプトを実行しているWebサイトにアクセスします。ウェブサイトは私の拡張機能がインストールされていることを検出し、それに応じてページを更新します。
これは可能ですか?
私はChrome拡張機能を作成している最中です。全体を思い通りに機能させるには、ユーザーが私の拡張機能をインストールしているかどうかを検出できる外部JavaScriptスクリプトが必要です。
例:ユーザーがプラグインをインストールしてから、スクリプトを実行しているWebサイトにアクセスします。ウェブサイトは私の拡張機能がインストールされていることを検出し、それに応じてページを更新します。
これは可能ですか?
回答:
私は直接的な方法(拡張機能で関数を直接呼び出すか、拡張機能のJSクラスを使用して)があると確信していますが、間接的な方法(より良いものが来るまで):
Chrome拡張機能に、非常に具体的なIDを持つページ上の特定のDIVまたはその他の要素を検索させる。
例えば:
<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>
a getElementById
を実行しinnerHTML
て、拡張機能のバージョン番号などに設定します。その後、そのクライアント側のコンテンツを読み取ることができます。
繰り返しになりますが、直接的な方法がある場合は、それを使用する必要があります。
編集:ダイレクトメソッドが見つかりました!!
ここにある接続方法を使用してください:https : //developer.chrome.com/extensions/extension#global-events
未テストですが、実行できるはずです...
var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
sendRequest()
、onRequest
、connect()
、onRequest
、とgetURL()
。
connect
関数がchrome.runtime
名前空間に移動されたため、最後のメソッドは無効になりました。最新バージョンについては、BJuryの回答(およびコメント)を参照してください
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/*"]
},
別の方法は、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チームがDev Toolsからの非常に特定のエラーを単にブラックリストに登録するという、最終的には非常に醜いソリューションです。
重要な注意:このメソッドはFirefox WebExtensionsでは機能しません。URLはIDを知ることで予測できるため、Webアクセス可能なリソースは本質的に拡張機能をフィンガープリントに公開します。Firefoxは、インスタンス固有のランダムURLをWebアクセス可能なリソースに割り当てることにより、その穴を塞ぐことを決定しました:
ファイルは次のようなURLを使用して利用できるようになります。
moz-extension://<random-UUID>/<path/to/resource>
このUUIDは、すべてのブラウザーインスタンスに対してランダムに生成され、拡張機能のIDではありません。これにより、Webサイトがユーザーがインストールした拡張機能のフィンガープリントを作成できなくなります。
ただし、拡張機能はruntime.getURL()
このアドレスを取得するために使用できますが、Webサイトにハードコードすることはできません。
これに関する私の研究を共有したいと思いました。一部のfile:///リンクが機能するために特定の拡張機能がインストールされているかどうかを検出できるようにする必要がありました。ここでこの記事に遭遇しましたこれ は、拡張機能の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)を使用して、任意の数の拡張機能のインストールを検出できるはずです。
Webサイトを所有している場合に考えられる別の解決策は、インラインインストールを使用することです。
if (chrome.app.isInstalled) {
// extension is installed.
}
私はこれが古い質問であることを知っていますが、この方法はChrome 15で導入されたので、今答えを探している人だけにリストすることにしました。
私は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';
}
拡張機能でCookieを設定し、そのCookieが存在するかどうかをウェブサイトのJavaScriptでチェックして、それに応じて更新することができます。これはおそらく、ほとんどの他の方法は、ここで言及したが、もちろん、ユーザーによってcirvumventedすることができない限り、あなたがしようとすると、タイムスタンプなどに応じて、カスタムクッキーを拡張機能を作成しており、アプリケーションはそれが本当に持つユーザーであるかどうかを確認するために、それらのサーバー側を分析してい拡張機能または彼のCookieを変更してそれを装う人。
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>
拡張機能がWebサイトと対話し(変数の変更など)、Webサイトがこれを検出する可能性があります。
しかし、これを行うにはもっと良い方法があるはずです。Googleが拡張ギャラリーでそれをどのように行っているのか(すでにインストールされているアプリケーションにマークが付けられています)。
編集:
ギャラリーはchrome.management.get関数を使用します。例:
chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});
ただし、適切な権限を持つページからのみメソッドにアクセスできます。
Uncaught TypeError: Cannot read property 'get' of undefined
ここまでの答えの多くはChromeのみであるか、HTTPオーバーヘッドのペナルティが発生します。使用しているソリューションは少し異なります。
{
"matches": ["https://www.yoursite.com/*"],
"js": [
"install_notifier.js"
],
"run_at": "document_idle"
}
これにより、install_notifier.jsのコードをそのサイトで実行できるようになります(まだそこに権限がない場合)。
次のようなものを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
}, "*");
})();
あなたのメッセージは何でも言うことができますが、あなたがあなたが何を扱っているかを知ることができるようにバージョンを送ることは役に立ちます。その後...
これをあなたのウェブサイトのどこかに追加してください:
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オーバーヘッドが発生したり、ページを操作したりしません。
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を変更することを心配しています。この方法がすぐに機能しなくなるのは疑わしい。
また、私が使用したブラウザ間メソッドを使用することもできます。divを追加するという概念を使用します。
コンテンツスクリプト内(スクリプトが読み込まれるたびにこれを実行する必要があります)
if ((window.location.href).includes('*myurl/urlregex*')) {
$('html').addClass('ifextension');
}
あなたのウェブサイトであなたは何かを主張します、
if (!($('html').hasClass('ifextension')){}
そして適切なメッセージを投げます。
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)
}
ここに他の現代的なアプローチがあります:
const checkExtension = (id, src, callback) => {
let e = new Image()
e.src = 'chrome-extension://'+ id +'/'+ src
e.onload = () => callback(1), e.onerror = () => callback(0)
}
// "src" must be included to "web_accessible_resources" in manifest.json
checkExtension('gighmmpiobklfepjocnamgkkbiglidom', 'icons/icon24.png', (ok) => {
console.log('AdBlock: %s', ok ? 'installed' : 'not installed')
})
checkExtension('bhlhnicpbhignbdhedgjhgdocnmhomnp', 'images/checkmark-icon.png', (ok) => {
console.log('ColorZilla: %s', ok ? 'installed' : 'not installed')
})