OnClick inside Chrome extension not working

This seems to be the easiest thing, but it just doesn't work. In a normal browser, .html and .js files work fine, but in the Chrome extension, the onClick function onClick not do what it should do.

.js file:

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

.html file:

 <!doctype html> <html> <head> <title> Getting Started Extension 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, when the user clicks β€œhyhy”, β€œha” should be changed to β€œxxx”. And again - it works fine in the browser, but does not work in the extension. You know why? Just in case, I am attaching manifest.json below.

Thanks in advance!

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/" ] } 
+52
javascript google-chrome-extension onclick
Nov 27
source share
3 answers

Chrome extensions do not allow built-in JavaScript ( documentation ). You will need to do something similar to this.

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

 document.addEventListener('DOMContentLoaded', function() { var link = document.getElementById('link'); // onClick logic below: link.addEventListener('click', function() { hellYeah('xxx'); }); }); 
+98
Nov 27 '12 at 19:58
source share

Cause

This does not work because Chrome prohibits any inline code in extensions through the content security policy.

Inline JavaScript will not execute. This restriction prohibits how embedded <script> blocks embedded event handlers and (for example, <button onclick="..."> ).

How to detect

If this is really a problem, Chrome will create the following error in the console:

An embedded script was denied because it violates the following content security policy directive: "script -src" self "chrome-extension-resource:". To enable inline execution, either the "unsafe-inline" keyword or a hash ("sha256 -...") or nonce ("nonce -...") is required.

To access the JavaScript pop-up console (which is useful for debugging in general), right-click the extension button and select "View pop-up window" in the context menu.

Further information on popup debugging is available here .

How to fix

You need to remove all embedded JavaScript. The Chrome documentation has .

Suppose the original looks like this:

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

You need to remove the onclick attribute and give the element a unique identifier:

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

And then attach the listener from the script (which should be in the .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 wrapper in the DOMContentLoaded event. This ensures that the element exists at runtime. Now add the script tag, for example, in the <head> document:

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

Alternative if you use jQuery:

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

Policy relaxation

Q: This error mentions ways to allow inline code. I don’t want / cannot change my code, how do I enable inline scripts?

A: Although the error says, it cannot include the built-in script :

There is no mechanism to ease the restrictions on the execution of embedded JavaScript In particular, setting a script policy that includes 'unsafe-inline' will have no effect.

Update: Starting with Chrome 46, you can select a whitelist of specific built-in code blocks:

As with Chrome 46, inline scripts can be whitelisted by specifying a base64-based hash code in the policy. This hash must be the prefix of the hash algorithm used (sha256, sha384 or sha512). See Using hashes for <script> elements for an example.

However, I see no reason to use this, and it will not include built-in attributes such as onclick="code" .

+30
Sep 08 '14 at 9:46
source share

I had the same problem and didn’t want to rewrite the code, so I wrote a function to change the code and create built-in declared events:

 function compile(qSel){ var matches = []; var match = null; var c = 0; var html = $(qSel).html(); var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg; while (match = pattern.exec(html)) { var arr = []; for (i in match) { if (!isNaN(i)) { arr.push(match[i]); } } matches.push(arr); } var items_with_events = []; var compiledHtml = html; for ( var i in matches ){ var item_with_event = { custom_id : "my_app_identifier_"+i, code : matches[i][5], on : matches[i][3], }; items_with_events.push(item_with_event); compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8"); } $(qSel).html(compiledHtml); for ( var i in items_with_events ){ $("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function(){ eval(items_with_events[i].code); }); } } $(document).ready(function(){ compile('#content'); }) 

This should remove all inline events from the selected node and recreate them using jquery.

+1
Aug 04 '15 at 21:39
source share



All Articles