javascript - Insert code into the page context using a content script -


i'm learning how create chrome extensions. started developing 1 catch youtube events. want use youtube flash player (later try make compatible html5).

manifest.json:

{     "name": "myextension",     "version": "1.0",     "description": "gotta catch youtube events!",     "permissions": ["tabs", "http://*/*"],     "content_scripts" : [{         "matches" : [ "www.youtube.com/*"],         "js" : ["myscript.js"]     }] } 

myscript.js:

function state() { console.log("state changed!"); } var player = document.getelementbyid("movie_player"); player.addeventlistener("onstatechange", "state"); console.log("started!"); 

the problem console gives me "started!", there no "state changed!" when play/pause youtube videos.

when code put in console, worked. doing wrong?

content scripts executed in "isolated world" environment. have inject state() method page itself.

when want use 1 of chrome.* apis in script, have implement special event handler, described in answer: chrome extension - retrieving gmail's original message.

otherwise, if don't have use chrome.* apis, recommend inject of js code in page via adding <script> tag:

table of contents

  • method 1: inject file
  • method 2: inject embedded code
  • method 2b: using function
  • method 3: using inline event
  • dynamic values in injected code

method 1: inject file

this easiest/best method when have lots of code. include actual js code in file within extension, script.js. let content script follows (explained here: google chome “application shortcut” custom javascript):

var s = document.createelement('script'); // todo: add "script.js" web_accessible_resources in manifest.json s.src = chrome.extension.geturl('script.js'); s.onload = function() {     this.remove(); }; (document.head || document.documentelement).appendchild(s); 

note: if use method, injected script.js file has added "web_accessible_resources" section (example). if not, chrome refuse load script , display following error in console:

denying load of chrome-extension://[extensionid]/script.js. resources must listed in web_accessible_resources manifest key in order loaded pages outside extension.

method 2: inject embedded code

this method useful when want run small piece of code. (see also: how disable facebook hotkeys chrome extension?).

var actualcode = `// code here. // if want use variable, use $ , curly braces. // example, use fixed random number: var somefixedrandomvalue = ${ math.random() }; // note: not insert unsafe variables in way, see below // @ "dynamic values in injected code" `;  var script = document.createelement('script'); script.textcontent = actualcode; (document.head||document.documentelement).appendchild(script); script.remove(); 

note: template literals supported in chrome 41 , above. if want extension work in chrome 40-, use:

var actualcode = ['/* code here. example: */' + 'alert(0);',                   '// beware! array have joined',                   '// using newline. otherwise, missing semicolons',                   '// or single-line comments (//) mess your',                   '// code ----->'].join('\n'); 

method 2b: using function

for big chunk of code, quoting string not feasible. instead of using array, function can used, , stringified:

var actualcode = '(' + function() {     // code executed in local scope.     // example, following not overwrite global `alert` method     var alert = null;     // overwrite global variable, prefix `window`:     window.alert = null; } + ')();'; var script = document.createelement('script'); script.textcontent = actualcode; (document.head||document.documentelement).appendchild(script); script.remove(); 

this method works, because + operator on strings , function converts objects string. if intend on using code more once, it's wise create function avoid code repetition. implementation might like:

function injectscript(func) {     var actualcode = '(' + func + ')();'     ... } injectscript(function() {    alert("injected script"); }); 

note: since function serialized, original scope, , bound properties lost!

var scripttoinject = function() {     console.log(typeof scripttoinject); }; injectscript(scripttoinject); // console output:  "undefined" 

method 3: using inline event

sometimes, want run code immediately, e.g. run code before <head> element created. can done inserting <script> tag textcontent (see method 2/2b).

an alternative, but not recommended use inline events. not recommended because if page defines content security policy forbids inline scripts, inline event listeners blocked. inline scripts injected extension, on other hand, still run. if still want use inline events, how:

var actualcode = '// code example \n' +                   'console.log(document.documentelement.outerhtml);';  document.documentelement.setattribute('onreset', actualcode); document.documentelement.dispatchevent(new customevent('reset')); document.documentelement.removeattribute('onreset'); 

note: method assumes there no other global event listeners handle reset event. if there is, can pick 1 of other global events. open javascript console (f12), type document.documentelement.on, , pick on of available events.

dynamic values in injected code

occasionally, need pass arbitrary variable injected function. example:

var greeting = "hi, i'm "; var name = "rob"; var scripttoinject = function() {     alert(greeting + name); }; 

to inject code, need pass variables arguments anonymous function. sure implement correctly! following not work:

var scripttoinject = function (greeting, name) { ... }; var actualcode = '(' + scripttoinject + ')(' + greeting + ',' + name ')'; // previous work numbers , booleans, not strings. // see why, have @ resulting string: var actualcode = "(function(greeting, name) {...})(hi i'm,rob)"; //                                                 ^^^^^^ ^^^ no string literals! 

the solution use json.stringify before passing argument. example:

var actualcode = '(' + function(greeting, name) { ... } + ')(' + json.stringify(greeting) + ',' + json.stringify(name) + ')'; 

if have many variables, it's worthwhile use json.stringify once, improve readability, follows:

... } + ')(' + json.stringify([arg1, arg2, arg3, arg4]) + ')'; 

Comments

Popular posts from this blog

Command prompt result in label. Python 2.7 -

javascript - How do I use URL parameters to change link href on page? -

amazon web services - AWS Route53 Trying To Get Site To Resolve To www -