사용자에게 Chrome 확장 프로그램이 설치되어 있는지 확인


97

Chrome 확장 프로그램을 구축하는 중이며 모든 작업이 원하는 방식으로 작동하려면 사용자가 확장 프로그램을 설치했는지 감지 할 수있는 외부 JavaScript 스크립트가 필요합니다.

예 : 사용자가 내 플러그인을 설치 한 다음 내 스크립트가있는 웹 사이트로 이동합니다. 웹 사이트는 내 확장 프로그램이 설치되었음을 감지하고 그에 따라 페이지를 업데이트합니다.

이게 가능해?


2
예, 확장 ID를 알고있는 한 확장을 감지 할 수 있습니다. 자세한 내용은이 사이트를 확인하세요. blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html '애드온을 하나씩 찾기'섹션으로 건너 뛰세요. 행운을 빕니다!
Martin Hughes

이를 구현하는 적절한 방법은 BJury 벨로우가 설명합니다.
Rahatur

이 게시물이 도움이되었습니다 : ide.hey.network/post/5c3b6c7aa7af38479accc0c7
nab.

답변:


46

직접적인 방법 (확장 기능을 직접 호출하거나 확장을 위해 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);

2
hmmm chrome.extension.connect는 확장 (또는 확장) 내에서 실행될 때만 작동하는 것 같습니다. 임의의 js 스크립트에서 작동하려면 필요합니다. 어떤 아이디어?

이상하게도 문서에 작동해야한다고 나와 있습니다. "다른 크롬과 달리. * API를, chrome.extension의 일부가 내용 스크립트에서 사용할 수있는"과 목록 sendRequest(), onRequest, connect(), onRequest,와 getURL().
Brad

@James 호스팅 된 스크립트에서 .connect ()를 사용하는 스크립트를 실행하고 있습니까? Chrome은 보안 목적으로 호스팅되지 않는 로컬 파일만으로는 작업을 수행하지 않으려 고합니다. -그냥 확인 해봐.
JamesEggers 2011 년

@James 내가 .connect () 실행중인 스크립트가 같은 서버에 있다는 뜻입니까?

23
마지막 방법은 더 이상 유효하지 않습니다 같은 connect기능이 이동 된 chrome.runtime네임 스페이스. 최신 버전은 BJury의 답변 (및 의견)을 참조하십시오
Xan

117

이제 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/*"]
},

2
이것은 매력처럼 작동합니다. 또 다른 단점은 확장 프로그램을 제어해야한다는 것입니다. 임의의 타사 확장 프로그램이 설치되어 있는지 확인하기 위해이를 사용할 수 없습니다.
Eric P

2
@EricP 원래 질문은 확장 프로그램을 작성하고 있다고 명시했기 때문에 문제가 있습니다.
BJury

13
또한 manifest.json에 다음을 추가해야합니다. "externally_connectable": { "matches": [ " : // .yourdomain.com / *"]}
noname

3
{version : 1.0}이 아닌 {version : '1.0'}이어야합니다. 그렇지 않으면 확장 Inspect보기 콘솔에 'Uncaught SyntaxError : Unexpected number'가 표시됩니다.
ET-CS

1
"확인"쪽 (주어진 확장 프로그램의 가용성을 확인하려는 웹 페이지)에서 chrome.runtime은 정의되지 않았으며 Linux에서는 chrome 36입니다.
reallynice

22

또 다른 방법은 웹에서 액세스 할 수있는 리소스노출하는 것입니다. 이렇게하면 모든 웹 사이트에서 확장 프로그램이 설치되었는지 테스트 할 수 있습니다.

확장 프로그램의 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()이이 주소를 얻는 데 사용할 수 있지만 웹 사이트에서 하드 코딩 할 수는 없습니다.


이 답변은 stackoverflow.com/a/9216924/1504300 에서 "주스"를 얻지 만 IMHO는 확장에 리소스를 노출하고 존재를 확인하기 위해 ajax 요청을 사용할 수 있다는 사실과 같은 꽤 중요한 정보를 추가합니다 (Image object 내가 잘못 goo.gl/HBeI1i 아닌 경우 HTML5에서만 사용할 수있는 것 같습니다 . 나는이 문제를 해결할 수있었습니다이 대답의 정보와 함께, 나는 "상자 밖으로"와 같은 솔루션을 발견
reallynice

@niconic 그 대답 (어쨌든 링크 전용으로 좋지 않음)은 매니페스트 버전 2가 적용되기 전의 상황을 나타냅니다. 이전에는 웹에서 액세스 할 수있는 리소스를 선언 할 필요가 없었습니다.
Xan

19

나는 이것에 대한 나의 연구를 공유 할 것이라고 생각했다. 일부 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)를 사용하여 확장 설치를 검색 할 수 있어야합니다.


2
Google에서 보안을 강화한 것 같습니다. Ext_Detect ()를 실행하면 다음 오류가 발생합니다. Denying load of chrome-extension : // [my_extension_id] /manifest.json. 확장 외부 페이지에서 리소스를로드하려면 web_accessible_resources 매니페스트 키에 리소스가 나열되어야합니다.
Lounge9

2014
2

1
@ Lounge9이 말했듯이. manifest_version 2 (또는 그 이상)를 사용하는 패키지 내부의 리소스는 기본적으로 차단되며 manifest.json : "web_accessible_resources": [ "manifest..json"],
ET-CS

@BJury 답변을 사용하면 확장에서 스크립트 (예 : 확장 버전)로 데이터를 쉽게 전달할 수 있으며 확장에서 파일을 노출 할 필요가 없습니다.
ET-CS

1
확장 프로그램이 여러 도메인에서 사용되며 새 도메인이 정기적으로 추가 될 때 미리 정의 할 수 없기 때문에 이것은 저에게 가장 효과적이었습니다. manifest.json에 액세스하는 대신 새 파일 version.json을 만들고 내부에 버전 번호를 넣었습니다. 이것은 똑같이 작동합니다.
Paul Haggo 2015

7

웹 사이트를 소유 한 경우 가능한 또 다른 해결책은 인라인 설치 를 사용하는 것 입니다.

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

나는 이것이 오래된 질문이라는 것을 알고 있지만이 방법은 Chrome 15에서 도입되었으므로 지금은 대답을 찾는 사람을 위해 이드를 나열한다고 생각했습니다.


12
이것은 Chrome 에서는 잘 작동 하지만 Chrome 확장 프로그램에는 적합하지 않습니다. AFAIK
Eran Medan

웹 사이트는 확장 프로그램 을 인라인 설치 하는 방법을 알려 주지만 "확장 프로그램은 콘텐츠 스크립트를 통해 임베딩 페이지와 통신하여 이미 설치되었음을 알릴 수 있습니다."라고 권장합니다. chrome.app.isInstalled를 사용할 수있는 대신. ... 나도 혼란
rogerdpack


4

쿠키 방법을 사용했습니다.

내 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';
}

위의 모든 솔루션을 시도했지만 작동하지 않습니다. 그러면 귀하의 답변이 표시됩니다. 이것이 제가 찾고있는 것입니다!
John Doe

이것은 이후 모든 HTTP 요청에 오버 헤드를 추가합니다.
mlissner

3

확장 프로그램 에서 쿠키를 설정하고 웹 사이트 JavaScript가 해당 쿠키가 있는지 확인하고 그에 따라 업데이트하도록 할 수 있습니다. 확장 프로그램이 타임 스탬프 등에 따라 사용자 지정 쿠키를 생성하고 애플리케이션이 서버 측에서이를 분석하여 실제로 사용자인지 확인 하지 않는 한 , 여기에 언급 된 대부분의 다른 방법은 물론 사용자가 관심을 가질 수 있습니다. 확장 프로그램 또는 쿠키를 수정하여이를 가지고있는 척하는 사람.


5
유일한 문제는 사용자가 확장 프로그램을 삭제하는 경우입니다. 쿠키는 아마도 설정된 상태로 유지됩니다.
Chase Roberts

3

이 Google 그룹스 게시물에 다른 방법이 표시됩니다 . 간단히 말해서 확장 아이콘이 성공적으로로드되는지 여부를 감지 할 수 있습니다. 확인중인 확장이 자신의 것이 아닌 경우 유용 할 수 있습니다.


1
확인. 확장 아이콘이 있는지 어떻게 확인합니까?
Michael Rogers

3

웹 페이지는 백그라운드 스크립트를 통해 확장과 상호 작용합니다.

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>

externally_connectable이 지원되지 않는 Firefox WebExtensions에서는 작동하지 않습니다.
mlissner

3

확장 프로그램은 웹 사이트와 상호 작용할 수 있으며 (예 : 변수 변경) 웹 사이트에서이를 감지 할 수 있습니다.

하지만 더 나은 방법이 있어야합니다. Google이 확장 갤러리에서 어떻게 작동하는지 궁금합니다 (이미 설치된 애플리케이션이 표시되어 있음).

편집하다:

갤러리는 chrome.management.get 함수를 사용합니다 . 예:

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

그러나 올바른 권한이있는 페이지에서만 메소드에 액세스 할 수 있습니다.


1
느리거나 구현하기 어렵고 버그가 많은 모든 탭의 모든 사이트와 상호 작용하려면 확장 프로그램이 필요합니다 :-/

문제는 크롬의 보안 모델로 인해 다른 방향 (페이지에서 확장)으로의 통신이 불가능하다는 것입니다. '상호 작용'방식으로 가고 싶지 않다면 쿠키 방식을 취하십시오.
Fox32 2014-06-09

2
Fox32, chrome.management.get @ 친애하는 ...이 오류를 반환Uncaught TypeError: Cannot read property 'get' of undefined
하면서 스토리지 Aqajani

3

지금까지 여기에있는 많은 답변은 Chrome 전용이거나 HTTP 오버 헤드 페널티가 발생합니다. 우리가 사용하는 솔루션은 약간 다릅니다.

1. 다음과 같이 manifest 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 오버 헤드를 발생 시키거나 페이지를 조작하지 않습니다.


0

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를 변경하는 것에 대해 걱정합니다. 이 방법이 곧 작동을 멈출지는 의문입니다.


위에서 언급했듯이-나는 이것을 테스트했지만 작업 순서가 이상해 보입니다. 어떤 스크립트가 먼저 실행됩니까?
Brady Moritz

0

내가 사용한 크로스 브라우저 방법을 사용할 수도 있습니다. div 추가 개념을 사용합니다.

콘텐츠 스크립트에서 (스크립트가로드 될 때마다이 작업을 수행해야 함)

if ((window.location.href).includes('*myurl/urlregex*')) {
        $('html').addClass('ifextension');
        }

웹 사이트에서 다음과 같이 주장합니다.

if (!($('html').hasClass('ifextension')){}

그리고 적절한 메시지를 던지십시오.


나는 이것을 테스트했지만 작업 순서가 이상해 보입니다. 어떤 스크립트가 먼저 실행됩니까?
Brady Moritz

@BradyMoritz는 대답과 동일한 순서입니다. 먼저 클래스를 추가 한 다음 어설 션하십시오.
Prakash Palnati

내 콘텐츠 스크립트가 내 페이지 내 스크립트 이전에 반드시 실행되지 않은 것 같습니까?
Brady Moritz

그것은 고치기 쉽다고 생각합니다. regex를 사용하여 필요한 URL / 경로를 입력 한 직후에 콘텐츠 스크립트가 실행되는지 확인할 수 있습니다.
Prakash Palnati

0

웹 사이트에서 확장 프로그램을 감지하려는 경우이 게시물이 도움이되었습니다. 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)
}

0

다음은 다른 현대적인 접근 방식입니다.

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')
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.