Checking if user has a certain extension installed

2019-01-14 04:07发布

问题:

I just found out that the Screen Capture by Google extension makes my website's window.onresize event not fire.

I want to perform a javascript check to see if the user has ScreenCapture installed and if so, warn the user of the problem.

A year ago I think I heard of some javascript code that could do this, maybe using some google API, but I don't remember.

Any insight on this? I haven't developed any extensions so I don't really know how they work.

[EDIT] So I have been asked to show some code. As seen in my previous question ( window.onresize not firing in Chrome but firing in Chrome Incognito ), the problem occurs on any window.onresize event function, so I don't think my code really matters.

Also, there is quite a lot of my code, I don't know how much of it to paste or if it would be helpful.

        var debounce = function (func, threshold, execAsap) 
    {
        var timeout;

        return function debounced () {//alert("1.1 Y U NO WORK?");
            var obj = this, args = arguments;
            function delayed () {
                if (!execAsap)
                    func.apply(obj, args);
                timeout = null; 
            }

            if (timeout)
                clearTimeout(timeout);
            else if (execAsap)
                func.apply(obj, args);

            timeout = setTimeout(delayed, threshold || 100); 
        };
    };


    window.onresize = debounce(function (e) { //alert("1.2 Y U NO WORK?");
        flag = true;
        var point = window.center({width:1,height:1});
        doCenter(point);
        // does something here, but only once after mouse cursor stops 
    }, 100, false);

I would like to stress that the problem is not due to the debounce. window.onresize = t; function t (e) { alert("wtf?");} won't work either.

[EDIT2]

Here's the result:

    var screenCapture = null;
    var screenCaptureImg = document.createElement("img");
     screenCaptureImg.setAttribute("src", "chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/images/arrow.png");
    /*
     * Add event listeners for both "load"- and "error"-event
     * Set the variable showing the existence of the extension by
     * setting it to "true" or "false" according to the fired event
     */
    screenCaptureImg.addEventListener("load", doLoad, false);
    function doLoad(e){
        screenCapture = true; //removeImgTag(e);

        alert("I've so cleverly detected that your Chrome has the ScreenCapture extension enabled. \n\nThis extension interferes with my website's DOM and long story short, it won't be able to scale properly.\n\nSo please disable it. \nConsider this extension: \"Disable All Extensions Plus\", it's a handy selective disabler.");
    }

    screenCaptureImg.addEventListener("error", function(e){
        screenCapture = false; //removeImgTag(e);
    }, false);
    /*
    function removeImgTag(e) {
        e.currentTarget.parentNode.removeChild(e.currentTarget);
    }
    */

Note that I couldn't get removeImgTag to work, because (at least in chrome), I don't seem to have access to the document object in order to create or remove elements from my page, from within these event functions. This is also why I'm displaying an alert instead of elegantly writing up a document.getElementById("something").innerHTML=...

回答1:

To detect if an extension is installed in Chrome, you can check for a known resource included in the extension such as an image. Resources for the extension are referenced using the following URL pattern:

chrome-extension://<extensionID>/<pathToFile>

The basic detection technique involves creating a hidden image tag and attaching load and error events to it to see if the image loads (as described here for Firefox):

extensionImg.setAttribute("src", "chrome-extension://<INSERT EXTENSION ID HERE>/images/someImage.png"); // See below for discussion of how to find this

/*
 * Add event listeners for both "load"- and "error"-event
 * Set the variable showing the existence of the extension by
 * setting it to "true" or "false" according to the fired event
 */
extensionImg.addEventListener("load", function(e) {
    extensionExists = true;
    removeImgTag(e);
}, false);
extensionImg.addEventListener("error", function(e) {
    extensionExists = false;
    removeImgTag(e);
}, false);

function removeImgTag(e) {
    e.currentTarget.parentNode.removeChild(e.currentTarget);
}

Check the installation directory of the extension in the Chrome configuration to find a likely target for detection. On my Linux workstation extensions are located in:

 ~/.config/chromium/Default/Extensions

You can see that I have 3 extensions installed right now:

~/.config/chromium/Default/Extensions$ ls
cpecbmjeidppdiampimghndkikcmoadk  nmpeeekfhbmikbdhlpjbfmnpgcbeggic
cpngackimfmofbokmjmljamhdncknpmg

The odd looking names are the unique IDs given to the extension when it is uploaded to the Chrome webstore. You can obtain the ID either from the webstore or by going to the Extensions tab (wrench -> Extensions) and hovering over the link to the extension in question, or "Screen Capture (by Google)" in this case (note the asterisked extension ID):

https://chrome.google.com/webstore/detail/**cpngackimfmofbokmjmljamhdncknpmg**

In the extension directory there will be one or more versions; you can ignore this. Within the version directory is the actual content of the extension:

~/.config/chromium/Default/Extensions/cpngackimfmofbokmjmljamhdncknpmg/5.0.3_0$ ls
account.js         images             page.js         sina_microblog.js
ajax.js            isLoad.js          picasa.js       site.js
background.html    _locales           plugin          style.css
editor.js          manifest.json      popup.html      ui.js
facebook.js        notification.html  sha1.js         upload_ui.js
hotkey_storage.js  oauth.js           shortcut.js
hub.html           options.html       showimage.css
i18n_styles        page_context.js    showimage.html

In the case of the Screen Capture extension there are a number of images to use:

~/.config/chromium/Default/Extensions/cpngackimfmofbokmjmljamhdncknpmg/5.0.3_0/images$ ls
arrow.png                icon_128.png    icon_save.png     print.png
copy.png                 icon_16.png     line.png          region.png
cross.png                icon_19.png     loading.gif       screen.png
custom.png               icon_32.png     loading_icon.gif  sina_icon.png
delete_account_icon.png  icon_48.png     mark.png          toolbar_bg.png
down_arrow.png           icon_close.png  picasa_icon.png   upload.png
facebook_icon.png        icon_copy.png   popup_bg.jpg      whole.png

These can be referenced under this URL:

chrome-extension://cpngackimfmofbokmjmljamhdncknpmg/images/arrow.png

This technique obviously depends on the stability of the content of the extension. I recommend using an image that looks likely to remain through all versions.


As mentioned above, the same technique can be used to detect Firefox extensions. In this case the content URL looks like this:

chrome://<EXTENSION NAME>/content/<PATH TO RESOURCE>

On my Linux workstation Firefox extensions are located in:

 ~/.mozilla/firefox/<USER PROFILE ID>/extensions

Where <USER PROFILE ID> looks something like this: "h4aqaewq.default"

You can see that I have 2 extensions installed right now, one of which is a directory installation and the other of which is a XPI (pronounced "zippy") file:

~/.mozilla/firefox/h4aqaewq.default/extensions$ ls
{3e9a3920-1b27-11da-8cd6-0800200c9a66}  staged
firebug@software.joehewitt.com.xpi

The "staged" directory is where Firefox keeps extensions that will be updated (I think). The GUID directory with the brackets is a directory-based extension installation, and the .xpi file is Firebug.

Note: XPI is going away (see the link above). It's basically a zip file that can be opened and inspected by anything that understands zip. I used Emacs.

Finding the extension ID in Firefox is a bit more involved. Go to "Tools -> Add-ons", click the Extensions tab, click the "More" link next to the extension description, then click the "reviews" link to go to the Firefox extension site and get the ID from the URL (note the asterisked extension ID):

https://addons.mozilla.org/en-US/firefox/addon/**firebug**/reviews/?src=api

There's probably an easier way to do this; suggestions welcome.

TODO: how to find a likely image in a Firefox extension.


As an extra note, in Chrome you can only communicate with an extension via the shared DOM of the page: Host page communication