38

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

Community
  • 1
  • 1
woojoo666
  • 7,801
  • 7
  • 45
  • 57

5 Answers5

24

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

woojoo666
  • 7,801
  • 7
  • 45
  • 57
12

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.

MrOrz
  • 157
  • 1
  • 4
  • 1
    Great solution! I've found the same thing but even using windo.gapi_onload is not very comfartable in modular application (I'm writing backbone.js application). Didn't you find any useful wrappers around this API? – Artem Volkhin Jul 03 '14 at 21:52
  • 4
    when I include the gapi-client.js in my manifest, it tries to include a third external script from apis.google.com in the background.html source. Did you see this at all? Because it is effectively the same error for me. Here is the full url for the script: https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.7_g8FbFMIhg.O/m=client/rt=j/sv=1/d=1/ed=1/am=AQ/rs=AItRSTNRC9ZdcUhJFGX80OZ8GW_8Ym1GpA/cb=gapi.loaded_0 – not_shitashi Sep 23 '14 at 05:25
  • Tried it just now, didn't work for me. It prints `undefined undefined`. I think perhaps the client script was changed since this answer was posted. The first answer (with modifying CSP) did work. – Yossi Vainshtein Jan 23 '19 at 08:01
  • that worked perfectly. After initializing gapi, I just had to get chrome token and send it to get user info. Saved my day. Thanks ! if u just copy paste, yes, it will return undefined undefined, because you must have a token to use with it. – Oliver White Oct 27 '20 at 11:39
3

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'",
goodhyun
  • 4,814
  • 3
  • 33
  • 25
1

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

Community
  • 1
  • 1
  • er the problem is with loading the library, not the callback function, which I omitted for simplicity's purposes – woojoo666 Sep 08 '13 at 08:30
  • actually, this solved a side issue I was having, but not the main problem...thanks anyways! I edited my post to prevent confusion – woojoo666 Sep 08 '13 at 08:36
1

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'",

zhonglin
  • 69
  • 6
  • I get the error: `'content_security_policy.extension_pages': Insecure CSP value "'unsafe-eval'" in directive 'script-src'.` – AlwaysLearning Jul 20 '23 at 11:20