Search code examples
javascriptgoogle-chromegoogle-chrome-extensiongoogle-plusgoogle-plus-one

How to use Google +1 in a content script without Content Security Policy error?


I'm trying to build chrome extension that uses +1 google api.

My manifest.json looks like:

"manifest_version": 2,
"content_security_policy": "script-src 'self' https://apis.google.com; object-src 'self'",
...
"matches": ["http://demosite.com/*"],
"js": ["js/jquery.js","js/social/plusone.js"]    

As you can see I've whitelisted apis.google.com.

My plusone.js looks like:

var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://apis.google.com/js/plusone.js";
head.appendChild(script);
    
$('li.subscription').before('<g:plusone></g:plusone>');

As you can see I just inject script tag from whitelisted site.

Unfortunately, when I load a page I got an error:

Refused to load the script apis.google.com//scs/apps-static//js/k=oz.gapi.ru.Fqrb4MMzOT8.O/m…sv=1/d=1/ed=1/am=IQ/rs=AItRSTNEKbnLkdtNZVz4hKH7VV4tY98scw/cb=gapi.loaded_0' because it violates the following Content Security Policy directive: "script-src 'self'".

All similar questions here say I should whitelist site with content_security_policy, but I've done it as you can see. Are there any ideas what's wrong?


Solution

  • The extension's Content security policy only applies to extension pages, not content scripts.
    When you insert a <script> tag, it becomes subject of the page's CSP, so changing the CSP string in the manifest file won't have any effect.

    To solve the problem, I suggest to load scriptTagContext.js before your other content script. First read README.md to understand the technique, then get it from https://github.com/Rob--W/chrome-api/tree/master/scriptTagContext.

    Example: G+1 on every Github page

    I'm taking Github as an example, because it enforces a strict Content security policy.

    manifest.json

    {
        "name": "Google +1 on Github",
        "version": "1",
        "manifest_version": 2,
        "content_scripts": [{
            "js": ["scriptTagContext.js", "contentscript.js"],
            "matches": ["*://*.github.com/*"]
        }],
        "permissions": [
            "*://apis.google.com/*"
        ]
    }

    scriptTagContext.js

    Get it from https://raw.github.com/Rob--W/chrome-api/master/scriptTagContext/scriptTagContext.js

    contentscript.js

    var script = document.createElement('script');
    script.src = 'https://apis.google.com/js/plusone.js';
    document.head.appendChild(script);
    
    // Next snippet is equivalent to jQuery's $('body').prepend('<g:plusone/>')
    document.body.insertAdjacentHTML('afterbegin', '<g:plusone></g:plusone>');