39

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

5 Answers 5

25

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

Sign up to request clarification or add additional context in comments.

Comments

13

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.

4 Comments

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?
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: apis.google.com/_/scs/apps-static/_/js/…
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.
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.
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'",

Comments

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

2 Comments

er the problem is with loading the library, not the callback function, which I omitted for simplicity's purposes
actually, this solved a side issue I was having, but not the main problem...thanks anyways! I edited my post to prevent confusion
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'",

1 Comment

I get the error: 'content_security_policy.extension_pages': Insecure CSP value "'unsafe-eval'" in directive 'script-src'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.