Я нахожусь в процессе создания расширения Chrome, и для того, чтобы все работало так, как я хотел бы, мне нужен внешний сценарий JavaScript, чтобы иметь возможность определять, установлено ли у пользователя мое расширение.
Например: пользователь устанавливает мой плагин, а затем переходит на веб-сайт с моим скриптом. Веб-сайт определяет, что мое расширение установлено, и соответствующим образом обновляет страницу.
Это возможно?
javascript
google-chrome
google-chrome-extension
Иегуда Кац
источник
источник
Ответы:
Я уверен, что существует прямой способ (вызов функций вашего расширения напрямую или с использованием классов JS для расширений), но косвенный метод (пока не появится что-то лучшее):
Попросите расширение Chrome искать определенный DIV или другой элемент на вашей странице с очень конкретным идентификатором.
Например:
<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);
источник
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; });
Это позволит вам позвонить с веб-сайта:
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/*"] },
источник
Другой метод - предоставить доступ к веб-ресурсу , хотя это позволит любому веб-сайту проверить, установлено ли ваше расширение.
Предположим, у вашего расширения есть ID
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-адрес для конкретного экземпляра доступным веб-ресурсам:
Однако, хотя расширение можно использовать
runtime.getURL()
для получения этого адреса, вы не можете жестко запрограммировать его на своем веб-сайте.источник
Я думал, что поделюсь своим исследованием по этому поводу. Мне нужно было определить, было ли установлено конкретное расширение для работы некоторых ссылок 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) для обнаружения установки любого количества расширений.
источник
Другое возможное решение, если вы являетесь владельцем веб-сайта, - использовать встроенную установку .
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 у меня есть одна строка:
document.cookie = "extension_downloaded=True";
и на моей странице index.html я ищу этот файл cookie.
if (document.cookie.indexOf('extension_downloaded') != -1){ document.getElementById('install-btn').style.display = 'none'; }
источник
Вы можете настроить расширение для файлов cookie, а JavaScript на ваших веб-сайтах будет проверять наличие этого файла cookie и обновлять его соответствующим образом. Этот и, вероятно, большинство других упомянутых здесь методов, конечно, могут быть обойдены пользователем, если только вы не попытаетесь заставить расширение создавать пользовательские файлы cookie в зависимости от временных меток и т. Д., И пусть ваше приложение проанализирует их на стороне сервера, чтобы увидеть, действительно ли это пользователь с расширение или кто-то, претендующий на его наличие, изменив свои файлы cookie.
источник
В этом сообщении групп Google показан еще один метод . Короче говоря, вы можете попробовать определить, успешно ли загружается значок расширения. Это может быть полезно, если проверяемое расширение не принадлежит вам.
источник
Веб-страница взаимодействует с расширением через фоновый скрипт.
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>
источник
Ваше расширение может взаимодействовать с сайтом (например, изменять переменные), и ваш сайт может это обнаружить.
Но должен быть способ сделать это лучше. Интересно, как это делает Google в своей галерее расширений (уже установленные приложения отмечены).
Редактировать:
В галерее используется функция chrome.management.get . Пример:
chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});
Но вы можете получить доступ к этому методу только со страниц с соответствующими разрешениями.
источник
Uncaught TypeError: Cannot read property 'get' of undefined
Многие ответы здесь относятся только к 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 или манипулирования страницей.
источник
Вот еще один современный подход:
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') })
источник
Если у вас есть контроль над расширением 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')){}
И закинуть соответствующее сообщение.
источник
Если вы пытаетесь обнаружить какое-либо расширение с любого веб-сайта, этот пост помог: 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) }
источник
Вот как вы можете обнаружить конкретное установленное расширение и показать предупреждающее сообщение.
Сначала вам нужно открыть файл манифеста расширения, перейдя в chrome-extension: //extension_id_here_hkdppipefbchgpohn/manifest.json и найдите любое имя файла в разделе «web_accessible_resources».
<div class="chromewarning" style="display:none"> <script type="text/javascript"> $.get("chrome-extension://extension_id_here_hkdppipefbchgpohn/filename_found_in_ web_accessible_resources.png").done(function () { $(".chromewarning").show(); }).fail(function () { // alert("failed."); }); </script> <p>We have detected a browser extension that conflicts with learning modules in this course.</p> </div>
источник