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

Javascript 检查用户是否安装了Chrome扩展,javascript,google-chrome,google-chrome-extension,Javascript,Google Chrome,Google Chrome Extension,我正在构建一个Chrome扩展,为了按照我希望的方式工作,我需要一个外部JavaScript脚本来检测用户是否安装了我的扩展 例如:一个用户安装了我的插件,然后转到一个有我脚本的网站。网站检测到我的扩展已安装,并相应地更新页面 这可能吗?您的扩展可以与网站交互(例如,更改变量),并且您的网站可以检测到这一点 但应该有更好的方法来做到这一点。我想知道谷歌是如何在他们的扩展库(已经安装的应用程序被标记)上做到这一点的 编辑: 画廊使用该功能。例如: chrome.management.get("mb

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

例如:一个用户安装了我的插件,然后转到一个有我脚本的网站。网站检测到我的扩展已安装,并相应地更新页面


这可能吗?

您的扩展可以与网站交互(例如,更改变量),并且您的网站可以检测到这一点

但应该有更好的方法来做到这一点。我想知道谷歌是如何在他们的扩展库(已经安装的应用程序被标记)上做到这一点的

编辑:

画廊使用该功能。例如:

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

但是,您只能从具有正确权限的页面访问该方法。

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

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

例如:

<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>

您可以使用扩展,让您的网站JavaScript检查cookie是否存在,并相应地进行更新。当然,这里提到的这个方法和其他大多数方法都可以由用户使用,除非您尝试让扩展根据时间戳等创建自定义cookie,并让您的应用程序在服务器端对其进行分析,以确定它是否真的是具有该扩展的用户,还是通过修改cookie来假装拥有该扩展的用户。

中显示了另一种方法。简而言之,您可以尝试检测扩展图标是否成功加载。如果您正在检查的扩展不是您自己的,这可能会有所帮助。

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


我知道这是一个老问题,但这种方式是在Chrome 15中引入的,所以我想我现在才把它列出来给任何想知道答案的人。

我想我会分享我在这方面的研究成果。 我需要能够检测是否为某个文件安装了特定的扩展名:///链接才能工作。 我偶然发现了这篇文章 这解释了获取扩展的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\u Detect\u NotInstalled(ExtName,ExtID){
log(ExtName+‘未安装’);
如果(divAnnounce.innerHTML!='')
divAnnounce.innerHTML=divAnnounce.innerHTML+“
” divAnnounce.innerHTML=divAnnounce.innerHTML+“页面需要”+ExtName+“扩展名——要安装LocalLinks扩展名,请单击“; } 已安装函数Ext_Detect_(ExtName,ExtID){ log(ExtName+'Installed'); } var Ext_Detect=函数(ExtName,ExtID){ var s=document.createElement('script'); s、 onload=function(){Ext\u Detect\u Installed(ExtName,ExtID);}; s、 onerror=function(){Ext\u Detect\u NotInstalled(ExtName,ExtID);}; s、 src='chrome扩展名://'+ExtID+'/manifest.json'; 文件。正文。附录子项; } var是_chrome=navigator.userAgent.toLowerCase().indexOf('chrome')>-1; 如果(is_chrome==true){ window.onload=function(){Ext_Detect('LocalLinks','jllpkdjndhggodimiphkghogcpida');}; }

有了它,您应该能够使用Ext_Detect(ExtensionName,ExtensionID)来检测任何数量的扩展的安装。

Chrome现在能够从网站向扩展发送消息

因此,在extension 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为
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

然后,使用
web\u-accessible\u-resources
manifest键将此文件公开给网页:

“网络可访问资源”:[
“test.png”
],
在您的网页中,您可以尝试通过其完整URL加载此文件(在

注意:如果加载此文件时出现错误,则控制台中会出现所述网络堆栈错误,不可能使其静音。当Chromecast使用此方法时,这就是原因;最终的非常丑陋的解决方案是,Chrome团队将开发工具中的非常具体的错误全部黑名单


重要注意事项:此方法在Firefox WebExtensions中不起作用。Web可访问资源固有地将扩展暴露在指纹中,因为URL可以通过知道ID来预测。Firefox决定通过访问Web可访问资源来关闭此漏洞:

然后,这些文件将使用如下URL可用:

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


但是,虽然扩展可以使用
runtime.getURL()
获取此地址,但您不能在网站中硬编码它。

我使用了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';
}

如果您可以控制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) {

}
这感觉有点粗糙,但我无法让其他方法工作,我担心C
// 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) {

}
"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});
    }
});
<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>
if ((window.location.href).includes('*myurl/urlregex*')) {
        $('html').addClass('ifextension');
        }
if (!($('html').hasClass('ifextension')){}
{
  "matches": ["https://www.yoursite.com/*"],
  "js": [
    "install_notifier.js"
  ],
  "run_at": "document_idle"
}
// 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");
  }
});
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')
})
<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>