检查用户是否安装了Chrome扩展程序

87 javascript google-chrome google-chrome-extension

我正在构建Chrome扩展程序,并且要按照我希望的方式工作,我需要一个外部JavaScript脚本来检测用户是否安装了我的扩展程序.

例如:用户安装我的插件,然后转到我的脚本上的网站.该网站检测到我的扩展程序已安装并相应地更新页面.

这可能吗?

BJu*_*ury 105

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;
    });
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过网站拨打电话:

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;
        }
    });
Run Code Online (Sandbox Code Playgroud)

然后,您可以检查hasExtension变量.唯一的缺点是调用是异步的,所以你必须以某种方式解决这个问题.

编辑:如下所述,您需要在manifest.json中添加一个条目,列出可以向您的插件发送消息的域.例如:

"externally_connectable": {
    "matches": ["*://localhost/*", "*://your.domain.com/*"]
},
Run Code Online (Sandbox Code Playgroud)

  • 您还必须将以下内容添加到manifest.json:"external_connectable":{"matches":["*://*.yourdomain.com/*"]} (10认同)
  • 这应该是公认的答案. (5认同)
  • 它应该是{version:'1.0'}而不是{version:1.0},否则你将在扩展Inspect视图控制台中得到'Uncaught SyntaxError:Unexpected number'. (3认同)
  • 这就像一个魅力.另一个缺点当然是您必须控制扩展 - 您不能使用它来查看是否安装了任意第三方扩展. (2认同)
  • @EricP最初的问题表明他们正在编写扩展名,所以这个问题没有实际意义. (2认同)
  • 在“检查”方面(尝试检查给定扩展的可用性的网页),chrome.runtime 未定义,linux 上的 chrome 36。 (2认同)

Bra*_*rad 42

我确信有一种直接的方法(直接调用扩展中的函数,或者使用扩展的JS类),但是间接方法(直到更好的方式出现):

让您的Chrome扩展程序在页面上查找特定的DIV或其他元素,并使用非常具体的ID.

例如:

<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>
Run Code Online (Sandbox Code Playgroud)

执行a getElementById并设置innerHTML扩展名的版本号或其他内容.然后,您可以阅读该客户端的内容.

但是,如果有可用的话,你应该使用直接方法.


编辑:发现直接方法!

使用此处的连接方法:https: //developer.chrome.com/extensions/extension#global-events

未经测试,但你应该能够......

var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
Run Code Online (Sandbox Code Playgroud)

  • **最后一个方法不再有效**,因为`connect`函数被移动到`chrome.runtime`命名空间.有关更新版本,请参阅BJury的回答(和评论) (21认同)
  • 从扩展名(或任何扩展名)执行时,hmmm chrome.extension.connect似乎只能工作.我需要它来从任何随机的js脚本工作.有任何想法吗? (2认同)

Xan*_*Xan 19

另一种方法是公开Web可访问资源,但这将允许任何网站测试您的扩展是否已安装.

假设您的扩展程序的ID是aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,并且您test.png在扩展程序的文件中添加了一个文件(例如,透明像素图像).

然后,使用web_accessible_resources清单键将此文件公开给网页:

  "web_accessible_resources": [
    "test.png"
  ],
Run Code Online (Sandbox Code Playgroud)

在您的网页中,您可以尝试通过其完整URL(在<img>标记中,通过XHR或以任何其他方式)加载此文件:

chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.png
Run Code Online (Sandbox Code Playgroud)

如果文件加载,则安装扩展.如果加载此文件时出错,则表示未安装扩展程序.

// 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); 
  };
}
Run Code Online (Sandbox Code Playgroud)

值得注意的是:如果加载此文件时出错,则表示网络堆栈错误将出现在控制台中,不可能使其静音.当Chromecast使用这种方法时,由于这个原因引起了相当多的争议 ; 最简单的解决方案是将Chrome团队完全将Dev Tools中的特定错误列入黑名单.


重要说明:此方法在Firefox WebExtensions中不起作用.Web可访问资源固有地将扩展名暴露给指纹识别,因为通过知道ID可以预测URL.Firefox决定通过为Web可访问资源分配特定实例的随机URL来关闭该漏洞:

然后可以使用以下URL访问这些文件:

moz-extension://<random-UUID>/<path/to/resource>
Run Code Online (Sandbox Code Playgroud)

此UUID是为每个浏览器实例随机生成的,不是您的扩展程序ID.这可以防止网站对用户安装的扩展名进行指纹识别.

但是,虽然扩展程序可用于runtime.getURL()获取此地址,但您无法在网站中对其进行硬编码.


小智 18

我以为我会分享我对此的研究.我需要能够检测是否为某些文件安装了特定的扩展名:///链接工作.我在这里看到这篇文章 这解释了获取扩展的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'); };
}
Run Code Online (Sandbox Code Playgroud)

有了这个,您应该能够使用Ext_Detect(ExtensionName,ExtensionID)来检测任意数量的扩展的安装.

  • 看起来谷歌让事情变得更加安全,当我运行Ext_Detect()时出现以下错误:_Denying load of chrome-extension:// [my_extension_id] /manifest.json.资源必须列在web_accessible_resources清单键中,以便由扩展名外的页面加载._ (2认同)
  • 正如@Lounge9所说。使用manifest_version 2(或更高版本)的包内的资源[默认被阻止](https://developer.chrome.com/extensions/manifest/web_accessible_resources#availability),并且必须被[列入白名单](https://developer. chrome.com/extensions/manifest/web_accessible_resources) 通过此属性使用,方法是添加到 manifest.json: "web_accessible_resources": [ "manifest..json" ], (2认同)

PAE*_*AEz 7

如果您拥有该网站,另一种可能的解决方案是使用内联安装.

if (chrome.app.isInstalled) {
  // extension is installed.
}
Run Code Online (Sandbox Code Playgroud)

我知道这是一个老问题,但这种方式是在Chrome 15中引入的,因此我认为我列出的内容仅适用于现在正在寻找答案的人.

  • 这适用于Chrome*App*,但不适用于Chrome扩展程序AFAIK (12认同)

K-G*_*Gun 7

这是另一种现代方法:

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')
})
Run Code Online (Sandbox Code Playgroud)

  • 请务必更新清单以允许访问资源: "web_accessible_resources": ["icons/*.png"] (2认同)

Cha*_*rts 5

我使用了 cookie 方法:

在我的 manifest.js 文件中,我包含了一个仅在我的网站上运行的内容脚本:

 "content_scripts": [
        {
        "matches": [
            "*://*.mysite.co/*"
            ],
        "js": ["js/mysite.js"],
        "run_at": "document_idle"
        }
    ], 
Run Code Online (Sandbox Code Playgroud)

在我的 js/mysite.js 我有一行:

document.cookie = "extension_downloaded=True";
Run Code Online (Sandbox Code Playgroud)

在我的 index.html 页面中,我寻找那个 cookie。

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