Chrome extension how to send data from script content to popup.html

I know this has been asked in numerous posts, but to be honest, I don't get them. I am new to JavaScript, Chrome extensions, and everything, and I have this class assignment. Therefore, I need to make a plugin that will read DOM objects on any given page using cross-domain queries. So far, I have been able to achieve this using the Chrome extension API. Now the problem is that I need to show the data on my popup.html page from the contentScript.js file. I do not know how to do this, I tried reading the documentation, but sending messages in chrome. I just donโ€™t understand what to do.

Below is the code.

manifest.json

{ "manifest_version":2, "name":"Dom Reader", "description":"Counts Dom Objects", "version":"1.0", "page_action": { "default_icon":"icon.png", "default_title":"Dom Reader", "default_popup":"popup.html" }, "background":{ "scripts":["eventPage.js"], "persistent":false }, "content_scripts":[ { "matches":["http://pluralsight.com/training/Courses/*", "http://pluralsight.com/training/Authors/Details/*", "https://www.youtube.com/user/*", "https://sites.google.com/site/*", "http://127.0.0.1:3667/popup.html"], "js":["domReader_cs.js","jquery-1.10.2.js"] //"css":["pluralsight_cs.css"] } ], "permissions":[ "tabs", "http://pluralsight.com/*", "http://youtube.com/*", "https://sites.google.com/*", "http://127.0.0.1:3667/*" ] 

popup.html

 <!doctype html> <html> <title> Dom Reader </title> <script src="jquery-1.10.2.js" type="text/javascript"></script> <script src="popup.js" type="text/javascript"></script> <body> <H1> Dom Reader </H1> <input type="submit" id="readDom" value="Read DOM Objects" /> <div id="domInfo"> </div> </body> </html> 

eventPage.js

 var value1,value2,value3; chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { if (request.action == "show") { chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { chrome.pageAction.show(tabs[0].id); }); } value1 = request.tElements; }); 

popup.js

 $(function (){ $('#readDom').click(function(){ chrome.tabs.query({active: true, currentWindow: true}, function (tabs){ chrome.tabs.sendMessage(tabs[0].id, {action: "readDom"}); }); }); }); 

contentScript

 var totalElements; var inputFields; var buttonElement; chrome.runtime.onMessage.addListener(function (request, sender, sendResponse){ if(request.action == "readDom"){ totalElements = $("*").length; inputFields = $("input").length; buttonElement = $("button").length; } }) chrome.runtime.sendMessage({ action: "show", tElements: totalElements, Ifields: inputFields, bElements: buttonElement }); 

Any help would be appreciated and please avoid any uselessness I did :)

+51
javascript jquery html google-chrome google-chrome-extension
Nov 16 '13 at 15:10
source share
2 answers

Although you are definitely in the right direction (and actually pretty close to the end), there are several (imo) bad practices in your code (e.g. injecting a whole library (jquery) for such a trivial task, declaring unnecessary permissions, making super-continuous calls API methods, etc.).
I have not tested your code myself, but from a brief review I think that fixing the following can lead to a working solution (although not very close to optimal):

  • In manifest.json : reorder content scripts, install jquery first. According to relevant documents :

    "js" [...] A list of JavaScript files that will be inserted into the corresponding pages. They are entered in the order they appear in this array.

    (my selection)

  • In contentcript.js : move the chrome.runtime.sendMessage ({...}) block inside the onMessage listener callback.




So here is my suggested approach:

Control flow:

  • The content of the script is entered on each page that matches certain criteria.
  • After entering, the content scripts send a message to the event page (non-constant background page), and the event page attaches page = action to this page.
  • As soon as the page action popup is loaded, it sends a message to the content script, requesting the information it needs.
  • The content of the script processes the request and responds so that a popup with page information can display the information.



Directory structure:

  root-directory/ |_____img |_____icon19.png |_____icon38.png |_____manifest.json |_____background.js |_____content.js |_____popup.js |_____popup.html 



manifest.json:

 { "manifest_version": 2, "name": "Test Extension", "version": "0.0", "offline_enabled": true, "background": { "persistent": false, "scripts": ["background.js"] }, "content_scripts": [{ "matches": ["*://*.stackoverflow.com/*"], "js": ["content.js"], "run_at": "document_idle", "all_frames": false }], "page_action": { "default_title": "Test Extension", //"default_icon": { // "19": "img/icon19.png", // "38": "img/icon38.png" //}, "default_popup": "popup.html" } // No special permissions required... //"permissions": [] } 



background.js:

 chrome.runtime.onMessage.addListener(function (msg, sender) { // First, validate the message structure if ((msg.from === 'content') && (msg.subject === 'showPageAction')) { // Enable the page-action for the requesting tab chrome.pageAction.show(sender.tab.id); } }); 



content.js:

 // Inform the background page that // this tab should have a page-action chrome.runtime.sendMessage({ from: 'content', subject: 'showPageAction' }); // Listen for messages from the popup chrome.runtime.onMessage.addListener(function (msg, sender, response) { // First, validate the message structure if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) { // Collect the necessary data // (For your specific requirements `document.querySelectorAll(...)` // should be equivalent to jquery `$(...)`) var domInfo = { total: document.querySelectorAll('*').length, inputs: document.querySelectorAll('input').length, buttons: document.querySelectorAll('button').length }; // Directly respond to the sender (popup), // through the specified callback */ response(domInfo); } }); 



popup.js:

 // Update the relevant fields with the new data function setDOMInfo(info) { document.getElementById('total').textContent = info.total; document.getElementById('inputs').textContent = info.inputs; document.getElementById('buttons').textContent = info.buttons; } // Once the DOM is ready... window.addEventListener('DOMContentLoaded', function () { // ...query for the active tab... chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { // ...and send a request for the DOM info... chrome.tabs.sendMessage( tabs[0].id, {from: 'popup', subject: 'DOMInfo'}, // ...also specifying a callback to be called // from the receiving end (content script) setDOMInfo); }); }); 



popup.html:

 <!DOCTYPE html> <html> <head> <script type="text/javascript" src="popup.js"></script> </head> <body> <h3 style="font-weight:bold; text-align:center;">DOM Info</h3> <table border="1" cellpadding="3" style="border-collapse:collapse;"> <tr> <td nowrap>Total number of elements:</td> <td align="right"><span id="total">N/A</span></td> </tr> <tr> <td nowrap>Number of input elements:</td> <td align="right"><span id="inputs">N/A</span></td> </tr> <tr> <td nowrap>Number of button elements:</td> <td align="right"><span id="buttons">N/A</span></td> </tr> </table> </body> </html> 
+113
Nov 16 '13 at 20:51
source share

You can use localStorage for this. You can store any data in a hash table format in your browserโ€™s memory, and then access it at any time. I'm not sure if we can access localStorage from the contents of the script (it was blocked earlier), try to do it yourself. Here's how to do it through your background page (first I pass the data from the contents of the script to the original page, and then save it to localStorage):

in contentScript.js:

 chrome.runtime.sendMessage({ total_elements: totalElements // or whatever you want to send }); 

in eventPage.js (your background page):

 chrome.runtime.onMessage.addListener( function(request, sender, sendResponse){ localStorage["total_elements"] = request.total_elements; } ); 

You can then access this variable in popup.js using localStorage ["total_elements"].

Perhaps you can access localStorage directly from the contents of the script in modern browsers. Then you do not need to transfer data through the wallpaper.

Good reading about localStorage: http://diveintohtml5.info/storage.html

+3
Nov 16 '13 at 17:59
source share



All Articles