I've been trying to wed the google api javascript client library with a chrome extension for a while now, but it seems the chrome extension has a terrible case of cold feet. The link to the script is
https://apis.google.com/js/client.js
Downloading the files is messy because the script actually loads other scripts. I've tried including it in the manifest
manifest.json (excerpt)
"background": {
"scripts": [
"background.js",
"https://apis.google.com/js/client.js?onload=callbackFunction"
]
},
but then the extension doesn't load. I've also tried injecting the script into the background html
background.js (excerpt)
var body = document.getElementsByTagName('body')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://apis.google.com/js/client.js?onload=callbackFunction";
body.appendChild(script);
but the chrome debugger gives me
Refused to load the script 'https://apis.google.com/js/client.js' because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:".
Any ideas, or are they fated to be kept apart?
Edit: note that you must add "?onload=myCallbackFunction" to the script url if you want to utilize a callback function. Thanks Ilya. More info here
So far the only solution I've found is to first inject the script into the background html page like I did:
background.js (excerpt)
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://apis.google.com/js/client.js?onload=callbackFunction";
head.appendChild(script);
And then to bypass the security warning, edit the manifest file (source):
manifest.json (excerpt)
"content_security_policy": "script-src 'self' https://apis.google.com; object-src 'self'"
However, note that bypassing the security only works for https
links, and I also find it kind of hacky...any other solutions are welcome
I found something interesting in the source code of https://apis.google.com/js/client.js
. It reads:
gapi.load("client",{callback:window["gapi_onload"], ......
gapi.load
is invoked as soon as client.js
is loaded in the webpage. It seems like window.gapi_onload
will be invoked as a callback once gapi.client
is loaded.
As a proof of concept, I built this plunker: http://plnkr.co/edit/TGvzI9SMKwGM6KnFSs7U
Both gapi.auth
and gapi.client
are successfully printed to console.
Back to Chrome extensions.
I put this in the background section of my mainfest.json
:
"background": {
"scripts": [
"background.js",
"gapi-client.js"
]
}
in which background.js
is the main background script in my extension. All content of gapi-client.js
is directly copy-and-pasted from https://apis.google.com/js/client.js
.
Inside background.js
it reads:
window.gapi_onload = function(){
console.log('gapi loaded.', gapi.auth, gapi.client);
// Do things you want with gapi.auth and gapi.client.
}
Please note that background.js
is loaded prior to gapi-client.js
. Because gapi-client.js
reads window["gapi_onload"]
as soon as it's loaded, window.gapi_onload
must be specified before that.
As a result window.gapi_onload
is invoked as expected, with both gapi.auth
and gapi.client
populated.
In my solution I did not create a background.html
on my own. I did not modify the content security policy either. However, notice that the solution is rather undocumented, thus is subject to change in the future.
You can load them via background.html which loads your background.js.
<html>
<head>
<title></title>
<script src="background.js"></script>
</head>
<body>
</body>
<script src="https://apis.google.com/js/client.js"></script>
</html>
with manifest.json:
"background":
{
"page": "background.html"
},
"content_security_policy": "script-src 'self' https://apis.google.com; object-src 'self'",
You just need set the onload method for this library
https://apis.google.com/js/client.js?onload=handleClientLoad
and handleClientLoad - default your registration method.
Sample for js oauth
I tried to add the manifest file as woojoo666's suggestion, but it still failed,
It looks we need to add one more flag 'unsafe-eval':
"content_security_policy": "script-src 'self' 'unsafe-eval' https://apis.google.com; object-src 'self'",