Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onclick or inline script isn't working in extension

This seems to be the easiest thing to do, but it's just not working. In a normal browser the .html and .js files works perfectly, but in the Chrome/Firefox extension the onClick function is not performing what it's supposed to do.

.js file:

function hellYeah(text) {   document.getElementById("text-holder").innerHTML = text; } 

.html file:

<!doctype html> <html>   <head>     <title>       Getting Started Extension's Popup     </title>     <script src="popup.js"></script>   </head>   <body>     <div id="text-holder">       ha     </div>     <br />     <a onClick=hellYeah("xxx")>       hyhy     </a>   </body> </html> 

So basically once the user clicks "hyhy", "ha" should change into "xxx". And again - it works perfectly in the browser but does not work in the extension. Do you know why? Just in case I'm attaching the manifest.json below as well.

manifest.json:

{   "name": "My First Extension",   "version": "1.0",   "manifest_version": 2,   "description": "The first extension that I made.",   "browser_action": {     "default_icon": "icon.png",     "default_popup": "popup.html"   },   "permissions": [     "http://api.flickr.com/"   ] } 
like image 495
teeZee Avatar asked Nov 27 '12 19:11

teeZee


2 Answers

Chrome Extensions don't allow you to have inline JavaScript (documentation).
The same goes for Firefox WebExtensions (documentation).

You are going to have to do something similar to this:

Assign an ID to the link (<a onClick=hellYeah("xxx")> becomes <a id="link">), and use addEventListener to bind the event. Put the following in your popup.js file:

document.addEventListener('DOMContentLoaded', function() {     var link = document.getElementById('link');     // onClick's logic below:     link.addEventListener('click', function() {         hellYeah('xxx');     }); }); 

popup.js should be loaded as a separate script file:

<script src="popup.js"></script> 
like image 107
David Avatar answered Sep 19 '22 18:09

David


Reason

This does not work, because Chrome forbids any kind of inline code in extensions via Content Security Policy.

Inline JavaScript will not be executed. This restriction bans both inline <script> blocks and inline event handlers (e.g. <button onclick="...">).

How to detect

If this is indeed the problem, Chrome would produce the following error in the console:

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

To access a popup's JavaScript console (which is useful for debug in general), right-click your extension's button and select "Inspect popup" from the context menu.

More information on debugging a popup is available here.

How to fix

One needs to remove all inline JavaScript. There is a guide in Chrome documentation.

Suppose the original looks like:

<a onclick="handler()">Click this</a> <!-- Bad --> 

One needs to remove the onclick attribute and give the element a unique id:

<a id="click-this">Click this</a> <!-- Fixed --> 

And then attach the listener from a script (which must be in a .js file, suppose popup.js):

// Pure JS: document.addEventListener('DOMContentLoaded', function() {   document.getElementById("click-this").addEventListener("click", handler); });  // The handler also must go in a .js file function handler() {   /* ... */ } 

Note the wrapping in a DOMContentLoaded event. This ensures that the element exists at the time of execution. Now add the script tag, for instance in the <head> of the document:

<script src="popup.js"></script> 

Alternative if you're using jQuery:

// jQuery $(document).ready(function() {   $("#click-this").click(handler); }); 

Relaxing the policy

Q: The error mentions ways to allow inline code. I don't want to / can't change my code, how do I enable inline scripts?

A: Despite what the error says, you cannot enable inline script:

There is no mechanism for relaxing the restriction against executing inline JavaScript. In particular, setting a script policy that includes 'unsafe-inline' will have no effect.

Update: Since Chrome 46, it's possible to whitelist specific inline code blocks:

As of Chrome 46, inline scripts can be whitelisted by specifying the base64-encoded hash of the source code in the policy. This hash must be prefixed by the used hash algorithm (sha256, sha384 or sha512). See Hash usage for <script> elements for an example.

However, I do not readily see a reason to use this, and it will not enable inline attributes like onclick="code".

like image 36
3 revs, 2 users 99% Avatar answered Sep 20 '22 18:09

3 revs, 2 users 99%