Проверьте, установлено ли расширение Chrome

Я нахожусь в процессе создания расширения Chrome, и для всего этого, чтобы работать так, как я хотел бы, мне нужен внешний скрипт JavaScript, чтобы иметь возможность определить, если пользователь имеет мое расширение установлено.

например: пользователь устанавливает мой плагин, затем переходит на веб-сайт с моим скриптом на нем. Веб-сайт обнаруживает, что мое расширение установлено и обновляет страницу соответствующим образом.

это возможно?

13 ответов


Я уверен, что есть прямой способ (вызов функций на вашем расширении напрямую или с помощью классов JS для расширений), но косвенный метод (пока не появится что-то лучшее):

попросите ваше расширение Chrome искать конкретный DIV или другой элемент на Вашей странице с очень конкретным идентификатором.

например:

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

сделать getElementById и выберите innerHTML к номеру версии вашего расширения или что-то в этом роде. Затем вы можете прочитать содержимое на стороне клиента.

опять же, вы должны использовать прямой метод, если он доступен.


EDIT: прямой метод найден!!

используйте методы подключения, найденные здесь:https://developer.chrome.com/extensions/extension#global-events

непроверенных, но вы должны быть в состоянии сделать...

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

Chrome теперь имеет возможность отправлять сообщения с веб-сайта на расширение.

Итак, в фоновом режиме расширения.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;
    });
Это позволит вам сделать звонок с сайта:
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. Единственным недостатком является асинхронный вызов, поэтому вам нужно как-то обойти это.

изменить: Как указано ниже, вам нужно добавить запись к манифест.в JSON список доменов, которые могут отправлять сообщения вашему аддону. Например:

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

другой метод -выставляем сетевой ресурс, хотя это позволит любому веб-сайту проверить, установлено ли ваше расширение.

предположим, что идентификатор вашего расширения aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, и вы добавляете файл (скажем, прозрачное пиксельное изображение) как test.png в файлы с расширением.

затем вы выставляете этот файл на веб-страницы с помощью web_accessible_resources ключ манифеста:

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

на вашей веб-странице вы можете попытаться загрузить этот файл по его полному 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 использовал этот метод, он вызвало немало споров из-за это; с окончательным очень уродливым решением просто черный список очень конкретных ошибок из Dev Tools в целом командой Chrome.


важное замечание: этот метод не будет работать в Firefox WebExtensions. Веб-доступные ресурсы по своей сути предоставляют расширение для снятия отпечатков пальцев, поскольку URL-адрес предсказуем, зная идентификатор. Firefox решил закрыть эту дыру назначение случайного URL-адреса для конкретного экземпляра в интернете доступные ресурсы:

файлы будут доступны с помощью URL-адреса, например:

moz-extension://<random-UUID>/<path/to/resource>

этот UUID генерируется случайным образом для каждого экземпляра браузера и не является идентификатором вашего расширения. Это предотвращает веб-сайты от снятия отпечатков пальцев расширений, установленных пользователем.

однако, в то время как расширение может использовать runtime.getURL() получить этот адрес, вы не можете жестко закодировать его на свой сайт.


Я думал, что поделюсь своими исследованиями по этому вопросу. Мне нужно было определить, установлено ли определенное расширение для какого-либо файла:/// ссылки на работу. Я наткнулся на эту статью здесь Это объясняло метод получения манифеста.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) для обнаружения установки любого количества увеличение.


другое возможное решение, если вы владеете веб-сайтом, - использовать установка роликовых.

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

Я знаю, что это старый вопрос, но этот способ был введен в Chrome 15, и поэтому я думал, что Id перечислит его для тех, кто только сейчас ищет ответ.


У вас может быть расширение установить cookie и ваши веб-сайты JavaScript проверьте, присутствует ли этот файл cookie и обновите его соответствующим образом. Этот и, вероятно, большинство других методов, упомянутых здесь, конечно, могут быть cirvumvented пользователем,Если вы пытаетесь и имеете расширение создавать пользовательские куки в зависимости от временных меток и т. д., и ваше приложение анализирует их на стороне сервера, чтобы увидеть, действительно ли это пользователь с расширением или кто-то притворяется, что он изменение его печенья.


есть еще один метод, показанный в это сообщение Google групп. Короче говоря, вы можете попробовать определить, успешно ли загружается значок расширения. Это может быть полезно, если расширение вы проверяете не свои собственные.


я использовал метод cookie:

В моем манифесте.JS файл я включил скрипт контента, которая работает только на моем сайте:

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

в моем JS / mysite.js у меня одна строка:

document.cookie = "extension_downloaded=True";

и в мой индекс.html-страница я ищу этот файл cookie.

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

Веб-страница взаимодействует с расширением через фоновый скрипт.

манифест.в 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});
    }
});

страница.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>

расширения могут взаимодействовать с веб-сайтом (например, изменение переменных) и ваш сайт мог обнаружить это.

но должен быть лучший способ сделать это. Интересно, как Google делает это в своей галерее расширений (уже установленные приложения отмечены).

Edit:

галерея использовать chrome.управление.get. Пример:

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

но вы можете получить доступ только к методу со страниц с правильные разрешения.


многие ответы здесь до сих пор только 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. На вашем сайте, слушайте это сообщение.

добавьте это на свой сайт где-нибудь:

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')){}

и выдать соответствующие сообщение.