Chrome 확장 프로그램을 구축하는 중이며 모든 작업이 원하는 방식으로 작동하려면 사용자가 확장 프로그램을 설치했는지 감지 할 수있는 외부 JavaScript 스크립트가 필요합니다.
예 : 사용자가 내 플러그인을 설치 한 다음 내 스크립트가있는 웹 사이트로 이동합니다. 웹 사이트는 내 확장 프로그램이 설치되었음을 감지하고 그에 따라 페이지를 업데이트합니다.
이게 가능해?
Chrome 확장 프로그램을 구축하는 중이며 모든 작업이 원하는 방식으로 작동하려면 사용자가 확장 프로그램을 설치했는지 감지 할 수있는 외부 JavaScript 스크립트가 필요합니다.
예 : 사용자가 내 플러그인을 설치 한 다음 내 스크립트가있는 웹 사이트로 이동합니다. 웹 사이트는 내 확장 프로그램이 설치되었음을 감지하고 그에 따라 페이지를 업데이트합니다.
이게 가능해?
답변:
직접적인 방법 (확장 기능을 직접 호출하거나 확장을 위해 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;
});
그러면 웹 사이트에서 전화를 걸 수 있습니다.
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가이 방법을 사용했을 때 이로 인해 상당한 논란 이 생겼습니다 . Chrome 팀에 의해 개발 도구의 매우 구체적인 오류 를 블랙리스트에 올리는 매우 추악한 해결책이 있습니다.
중요 참고 : 이 방법은 Firefox WebExtensions에서 작동하지 않습니다. 웹에서 액세스 할 수있는 리소스는 ID를 알면 URL을 예측할 수 있으므로 기본적으로 확장을 지문에 노출합니다. Firefox는 웹에서 액세스 할 수있는 리소스에 인스턴스 별 임의 URL 을 할당하여이 구멍을 막기 로 결정했습니다 .
그러면 다음과 같은 URL을 사용하여 파일을 사용할 수 있습니다.
moz-extension://<random-UUID>/<path/to/resource>
이 UUID는 모든 브라우저 인스턴스에 대해 무작위로 생성되며 확장 프로그램의 ID가 아닙니다. 이렇게하면 웹 사이트에서 사용자가 설치 한 확장 프로그램에 지문을 생성하지 못합니다.
그러나 확장 프로그램 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에서 도입되었으므로 지금은 대답을 찾는 사람을 위해 이드를 나열한다고 생각했습니다.
쿠키 방법을 사용했습니다.
내 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 페이지에서 해당 쿠키를 찾습니다.
if (document.cookie.indexOf('extension_downloaded') != -1){
document.getElementById('install-btn').style.display = 'none';
}
확장 프로그램 에서 쿠키를 설정하고 웹 사이트 JavaScript가 해당 쿠키가 있는지 확인하고 그에 따라 업데이트하도록 할 수 있습니다. 확장 프로그램이 타임 스탬프 등에 따라 사용자 지정 쿠키를 생성하고 애플리케이션이 서버 측에서이를 분석하여 실제로 사용자인지 확인 하지 않는 한 , 여기에 언급 된 대부분의 다른 방법은 물론 사용자가 관심을 가질 수 있습니다. 확장 프로그램 또는 쿠키를 수정하여이를 가지고있는 척하는 사람.
이 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 오버 헤드 페널티가 발생합니다. 우리가 사용하는 솔루션은 약간 다릅니다.
{
"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')){}
그리고 적절한 메시지를 던지십시오.
웹 사이트에서 확장 프로그램을 감지하려는 경우이 게시물이 도움이되었습니다. 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')
})