jquery - Calling webpage JavaScript methods from browser extension -
i developing firefox extension using webextensions me ease work scenario below.
i have click around 50-60 buttons on site update task status. on click of button, web page calling webpage's updtask(id)
javascript function making web-service call update task.
i not able content script using code below:
manifest.json:
"permissions": [ "activetab", "cross-domain-content": ["http://workdomain.com/","http://workdomain.org/","http://www.workdomain.com/","http://www.workdomain.org/"] ]
content-script code:
function taskupdate(request, sender, sendresponse) { console.log(request.start + 'inside task update'); updatetask(45878); chrome.runtime.onmessage.removelistener(taskupdate); } function updatetask(id) { //todo: code buttons , task id's updtask(id); // not working }
plugin script:
document.addeventlistener("click", function(e) { if (e.target.classlist.contains("startbutton")) { chrome.tabs.executescript(null, { file: "/content_scripts/taskupdate.js" }); chrome.tabs.query({active: true, currentwindow: true}, function(tabs) { chrome.tabs.sendmessage(tabs[0].id, {start: "start"}); }); return; } else if (e.target.classlist.contains("clear")) { chrome.tabs.reload(); window.close(); return; } });
could point me in right direction, missing here??
your content script in different context/scope of page scripts (scripts exist in webpage). content script has higher privileges granted page scripts. keeping content scripts separate page scripts normal architecture browser extensions done security reasons.
in order execute code in page script context, have create , insert <script>
element page's dom.
you like:
function updatetask(id) { let newscript = document.createelement('script'); newscript.innerhtml='updtask(' + id + ');'; document.head.appendchild(newscript); //newscript.remove(); //can removed, if desired. }
the added script gets run in page context because <script>
element in dom. browser recognizes <script>
element added , evaluates (executes code contained) script inserted no longer processing. same thing other element add dom. because part of page, code inside gets run in page script context/scope.
generalized code execute in page context content script
the easiest way maintain code going execute in page context write function in content script, inject function page context. here generalized code while passing parameters function executing in page context:
/* executeinpage takes function defined in context, converts * string , inserts page context inside <script>. placed * inside iife , passed of additional parameters passed * executeinpage. * parameters: * func function desire execute in page. * leaveinpage if not evaluate truthy value, <script> * removed page after insertion. * thing if function not performing * asynchronously. if asynchronous (event * listeners, ajax, etc.) value must true in order * code still exist when async. operation completes/calls * callback/executes event listener/etc. * id if non-blank string, used id <script> * additional parameters passed function executing in page. * done converting them json , back. thus, such * parameters *must* json-ifiable. if need communicate dom * elements, need pass selectors, or other descriptors of * them (e.g. temporarily assign them unique class), or otherwise * communicate them script (e.g. dispatch custom * event once script inserted page context). */ function executeinpage(functiontoruninpage, leaveinpage, id) { //execute function in page context. // additional arguments passed function passed page // functiontoruninpage. // such arguments must json-ifiable (also date, function, , regexp) (prototypes // not copied). // using () => doesn't set arguments, can't use define function. // has done without jquery, jquery creates script // within context, not page context, results in // permission denied run function. function converttotext(args) { //this uses fact arguments converted text interpreted // within <script>. means can create other types of objects // recreating normal javascript representation. // it's easier without json.strigify() whole // object/array. var astext = ''; var level = 0; function lineseparator(adj, isntlast) { level += adj - ((typeof isntlast === 'undefined' || isntlast) ? 0 : 1); astext += (isntlast ? ',' : '') + '\n' + (new array(level * 2 + 1)).join(''); } function recurseobject(obj) { if (array.isarray(obj)) { astext += '['; lineseparator(1); obj.foreach(function(value, index, array) { recurseobject(value); lineseparator(0, index !== array.length - 1); }); astext += ']'; } else if (obj === null) { astext +='null'; } else if (obj instanceof regexp || typeof obj === 'function') { astext += obj.tostring(); } else if (obj instanceof date) { astext += 'new date("' + obj.tojson() + '")'; } else if (typeof obj === 'object') { astext += '{'; lineseparator(1); object.keys(obj).foreach(function(prop, index, array) { astext += json.stringify(prop) + ': '; recurseobject(obj[prop]); lineseparator(0, index !== array.length - 1); }); astext += '}'; } else if (['boolean', 'number', 'string'].indexof(typeof obj) > -1) { astext += json.stringify(obj); } else { console.log('didn\'t handle: typeof obj:', typeof obj, ':: obj:', obj); } } recurseobject(args); return astext; } var newscript = document.createelement('script'); if(typeof id === 'string' && id) { newscript.id = id; } var args = []; //using .slice(), or other array methods, on arguments prevents optimization for(var index=3;index<arguments.length;index++){ args.push(arguments[index]); } newscript.textcontent = '(' + functiontoruninpage.tostring() + ').apply(null,' + converttotext(args) + ");"; (document.head || document.documentelement).appendchild(newscript); if(!leaveinpage) { //synchronous scripts executed , can removed. //scripts asynchronous functionality of type must remain in page // until complete. document.head.removechild(newscript); } return newscript; };
using excuteinpage()
:
function loginpagecontext(arg0,arg1,arg2,arg3){ console.log('arg0:', arg0); console.log('arg1:', arg1); console.log('arg2:', arg2); console.log('arg3:', arg3); } executeinpage(loginpagecontext, false, '', 'this', 'is', 'a', 'test'); /* executeinpage takes function defined in context, converts * string , inserts page context inside <script>. placed * inside iife , passed of additional parameters passed * executeinpage. * parameters: * func function desire execute in page. * leaveinpage if not evaluate truthy value, <script> * removed page after insertion. * thing if function not performing * asynchronously. if asynchronous (event * listeners, ajax, etc.) value must true in order * code still exist when async. operation completes/calls * callback/executes event listener/etc. * id if non-blank string, used id <script> * additional parameters passed function executing in page. * done converting them json , back. thus, such * parameters *must* json-ifiable. if need communicate dom * elements, need pass selectors, or other descriptors of * them (e.g. temporarily assign them unique class), or otherwise * communicate them script (e.g. dispatch custom * event once script inserted page context). */ function executeinpage(functiontoruninpage, leaveinpage, id) { //execute function in page context. // additional arguments passed function passed page // functiontoruninpage. // such arguments must json-ifiable (also date, function, , regexp) (prototypes // not copied). // using () => doesn't set arguments, can't use define function. // has done without jquery, jquery creates script // within context, not page context, results in // permission denied run function. function converttotext(args) { //this uses fact arguments converted text // interpreted within <script>. means can create other types of // objects recreating normal javascript representation. // it's easier without json.strigify() whole // object/array. var astext = ''; var level = 0; function lineseparator(adj, isntlast) { level += adj - ((typeof isntlast === 'undefined' || isntlast) ? 0 : 1); astext += (isntlast ? ',' : '') +'\n'+ (new array(level * 2 + 1)).join(''); } function recurseobject(obj) { if (array.isarray(obj)) { astext += '['; lineseparator(1); obj.foreach(function(value, index, array) { recurseobject(value); lineseparator(0, index !== array.length - 1); }); astext += ']'; } else if (obj === null) { astext +='null'; } else if (obj instanceof regexp || typeof obj === 'function') { astext += obj.tostring(); } else if (obj instanceof date) { astext += 'new date("' + obj.tojson() + '")'; } else if (typeof obj === 'object') { astext += '{'; lineseparator(1); object.keys(obj).foreach(function(prop, index, array) { astext += json.stringify(prop) + ': '; recurseobject(obj[prop]); lineseparator(0, index !== array.length - 1); }); astext += '}'; } else if (['boolean', 'number', 'string'].indexof(typeof obj) > -1) { astext += json.stringify(obj); } else { console.log('didn\'t handle: typeof obj:', typeof obj, ':: obj:', obj); } } recurseobject(args); return astext; } var newscript = document.createelement('script'); if(typeof id === 'string' && id) { newscript.id = id; } var args = []; //using .slice(), or other array methods, on arguments prevents optimization for(var index=3;index<arguments.length;index++){ args.push(arguments[index]); } newscript.textcontent = '(' + functiontoruninpage.tostring() + ').apply(null,' + converttotext(args) + ");"; (document.head || document.documentelement).appendchild(newscript); if(!leaveinpage) { //synchronous scripts executed , can removed. //scripts asynchronous functionality of type must remain in page // until complete. document.head.removechild(newscript); } return newscript; };
the text answer largely taken other answers: this one , this one.
Comments
Post a Comment