Je suis en train de construire une extension Chrome, et pour que tout fonctionne comme je le voudrais, j'ai besoin d'un script JavaScript externe pour pouvoir détecter si un utilisateur a mon extension installée.
Par exemple: Un utilisateur installe mon plugin, puis accède à un site Web contenant mon script. Le site Web détecte que mon extension est installée et met la page à jour en conséquence.
Est-ce possible?
Je suis sûr qu'il existe un moyen direct (d'appeler directement des fonctions sur votre extension ou en utilisant les classes JS pour les extensions), mais une méthode indirecte (jusqu'à ce que quelque chose de mieux se présente):
Demandez à votre extension Chrome de rechercher un DIV ou un autre élément spécifique sur votre page, avec un identifiant très spécifique.
Par exemple:
<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>
Faites un getElementById
et réglez le innerHTML
sur le numéro de version de votre extension ou de quelque chose. Vous pouvez ensuite lire le contenu de ce côté client.
Encore une fois cependant, vous devriez utiliser une méthode directe s'il en existe une disponible.
EDIT: méthode directe trouvée !!
Utilisez les méthodes de connexion trouvées ici: https://developer.chrome.com/extensions/extension#global-events
Non testé, mais vous devriez pouvoir le faire ...
var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
Chrome a maintenant la possibilité d'envoyer des messages du site Web à l'extension.
Donc dans l'extension background.js (content.js ne fonctionnera pas), ajoutez quelque chose comme:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request) {
if (request.message) {
if (request.message == "version") {
sendResponse({version: 1.0});
}
}
}
return true;
});
Cela vous permettra ensuite de passer un appel depuis le site 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;
}
});
Vous pouvez ensuite vérifier la variable hasExtension. Le seul inconvénient est que l'appel est asynchrone, vous devez donc contourner ce problème.
Edit: Comme mentionné ci-dessous, vous devrez ajouter une entrée à la liste manifest.json répertoriant les domaines pouvant envoyer un message à votre addon. Par exemple:
"externally_connectable": {
"matches": ["*://localhost/*", "*://your.domain.com/*"]
},
Une autre méthode consiste à exposer une ressource accessible sur le Web , bien que cela permette à tout site Web de vérifier si votre extension est installée.
Supposons que l'ID de votre extension est aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
et que vous ajoutez un fichier (disons, une image en pixels transparente) sous la forme test.png
Dans les fichiers de votre extension.
Ensuite, vous exposez ce fichier aux pages Web avec la clé de manifeste web_accessible_resources
:
"web_accessible_resources": [
"test.png"
],
Dans votre page Web, vous pouvez essayer de charger ce fichier par son URL complète (dans une balise <img>
, Via XHR ou de toute autre manière):
chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.png
Si le fichier est chargé, l'extension est installée. En cas d'erreur lors du chargement de ce fichier, l'extension n'est pas installée.
// 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);
};
}
A noter: s'il y a une erreur lors du chargement de ce fichier, dit pile réseau une erreur apparaîtra dans la console sans possibilité de la désactiver. Lorsque Chromecast a utilisé cette méthode, a provoqué pas mal de controverse à cause de cela; avec l’éventuelle solution très laide de simplement liste noire des erreurs très spécifiques de Dev Tools totalement par l’équipe Chrome.
Remarque importante: cette méthode ne fonctionnera pas dans Firefox WebExtensions. Les ressources accessibles sur le Web exposent l’extension à l’empreinte digitale, car l’URL est prévisible en connaissant l’ID. Firefox a décidé de fermer ce trou en affectant une URL aléatoire spécifique à l'instance à des ressources accessibles par le Web:
Les fichiers seront alors disponibles en utilisant une URL telle que:
moz-extension://<random-UUID>/<path/to/resource>
Cet UUID est généré de manière aléatoire pour chaque instance de navigateur et n'est pas l'ID de votre extension. Cela empêche les sites Web de prendre les empreintes digitales sur les extensions qu'un utilisateur a installées.
Cependant, bien que l'extension puisse utiliser runtime.getURL()
pour obtenir cette adresse, vous ne pouvez pas la coder en dur dans votre site Web.
Je pensais partager mes recherches à ce sujet. Je devais être capable de détecter si une extension spécifique était installée pour que certains liens fichier: /// puissent fonctionner. Je suis tombé sur cet article ici Cela expliquait une méthode pour obtenir le fichier manifest.json d'une extension.
J'ai ajusté le code un peu et suis venu avec:
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'); };
}
Avec cela, vous devriez pouvoir utiliser Ext_Detect (ExtensionName, ExtensionID) pour détecter l'installation d'un nombre quelconque d'extensions.
Une autre solution possible si vous possédez le site Web consiste à utiliser installation en ligne .
if (chrome.app.isInstalled) {
// extension is installed.
}
Je connais cette question comme une vieille question, mais cette méthode a été introduite dans Chrome 15 et j’ai donc pensé que je l’aurais répertorié pour tous ceux qui recherchent une réponse maintenant.
Votre extension pourrait interagir avec le site Web (par exemple, modifier des variables) et votre site Web pourrait le détecter.
Mais il devrait y avoir un meilleur moyen de le faire. Je me demande comment Google le fait sur sa galerie d'extensions (les applications déjà installées sont marquées).
Modifier:
La galerie utilise la fonction chrome.management.get . Exemple:
chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});
Mais vous ne pouvez accéder à la méthode qu'à partir de pages disposant des autorisations appropriées.
Vous pouvez avoir l'extension définir un cookie et faire vérifier par votre site Web si ce cookie est présent et le mettre à jour en conséquence. Ceci et probablement la plupart des autres méthodes mentionnées ici pourraient bien sûr être évitées par l'utilisateur, à moins que vous essayiez de faire en sorte que l'extension crée des cookies personnalisés en fonction d'horodatages, etc., et demandez à votre application de les analyser côté serveur pour voir s’il s’agit bien d’un utilisateur avec l’extension ou de quelqu'un prétendant l’avoir en modifiant ses cookies.
Une autre méthode est indiquée à l'adresse cet article de Google Groupes . En bref, vous pouvez essayer de détecter si l’icône d’extension se charge correctement. Cela peut être utile si l'extension que vous recherchez n'est pas la vôtre.
J'ai utilisé la méthode des cookies:
Dans mon fichier manifest.js, j'ai inclus un script de contenu qui ne s'exécute que sur mon site:
"content_scripts": [
{
"matches": [
"*://*.mysite.co/*"
],
"js": ["js/mysite.js"],
"run_at": "document_idle"
}
],
dans mon js/mysite.js j'ai une ligne:
document.cookie = "extension_downloaded=True";
et dans ma page index.html, je cherche ce cookie.
if (document.cookie.indexOf('extension_downloaded') != -1){
document.getElementById('install-btn').style.display = 'none';
}
Jusqu'à présent, la plupart des réponses sont Chrome seulement ou encourent une pénalité de surcharge HTTP. La solution que nous utilisons est un peu différente:
{
"matches": ["https://www.yoursite.com/*"],
"js": [
"install_notifier.js"
],
"run_at": "document_idle"
}
Cela permettra au code de install_notifier.js de s'exécuter sur ce site (si vous n'y avez pas déjà obtenu les autorisations).
Ajoutez quelque chose comme ceci à install_notifier.js (notez qu'il s'agit d'une fermeture pour éviter que les variables ne soient globales, mais ce n'est pas strictement nécessaire):
// 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
}, "*");
})();
Votre message peut dire n'importe quoi, mais il est utile d'envoyer la version pour que vous sachiez à quoi vous avez affaire. Ensuite...
Ajoutez ceci à votre site web quelque part:
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");
}
});
Cela fonctionne dans Firefox et Chrome, et n'entraîne pas de surcharge HTTP ni de manipulation de la page.
La page Web interagit avec l'extension via un script en arrière-plan.
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>
Si vous essayez de détecter une extension de n'importe quel site Web, ce message vous a aidé: https://ide.hey.network/post/5c3b6c7aa7af38479accc0c7
Fondamentalement, la solution serait simplement d'essayer d'obtenir un fichier spécifique (manifeste.json ou une image) à partir de l'extension en spécifiant son chemin. Voici ce que j'ai utilisé. Travailler vraiment:
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)
}
Vous pouvez également utiliser une méthode multi-navigateur de ce que j'ai utilisé. Utilise le concept d'ajouter un div.
dans votre script de contenu (chaque fois que le script est chargé, vous devriez le faire)
if ((window.location.href).includes('*myurl/urlregex*')) {
$('html').addClass('ifextension');
}
dans votre site Web, vous affirmez quelque chose comme:
if (!($('html').hasClass('ifextension')){}
Et lancer le message approprié.
Si vous avez le contrôle sur l’extension Chrome, vous pouvez essayer ce que j’ai fait:
// Inside Chrome extension
var div = document.createElement('div');
div.setAttribute('id', 'myapp-extension-installed-div');
document.getElementsByTagName('body')[0].appendChild(div);
Et alors:
// On web page that needs to detect extension
if ($('#myapp-extension-installed-div').length) {
}
Cela me semble un peu hacky, mais je ne pouvais pas faire fonctionner les autres méthodes, et je m'inquiète pour Chrome change son API ici. Il est peu probable que cette méthode cesse de fonctionner dans un avenir rapproché.