Sending Messages in JS
Last week I worked on a small feature for the Wiser chrome extension. I added functionality such that when a user highlights text on the webpage and then opens the extension, the selected text gets pulled into the excerpt field in the extension.
The tricky part was, there are three layers to the extension, the webpage, the popup, and the iframe within the popup. Neither the popup nor the iframe could see the highlighted text. So I set up a series of listeners and sent the message (the selected text) from the webpage, to the popup, and finally to the iframe.
I sent these messages using two different methods: the chrome extension api and javascript's postMessage function. The latter allows you to send cross-origin messages, which I needed to do in order to get the text from the popup to the iframe.
Here's a picture of how the message flow works:
Here is the javascript from the three layers. The numbers in the comments correspond with the numbers in the picture.
content_script.js (runs in the webpage)
// (5) sends a message to popup.js using chrome extension api function tell (message) { chrome.extension.sendRequest({message: message, data: "from content_script"}); }; // (4) grab the selected text and send it using the tell function tell(window.getSelection().toString());
popup.js (runs in the extension popup)
// (7) calls tell function if response has a non-empty message function onPostMessage (request) { if (!request.message) { return; } else { tell(request.message) return; } }; // (8) sends message to iframe using postMessage function tell (message) { chrome.tabs.getSelected(null, function (tab) { if (!tab) { return; } iframe.contentWindow.postMessage(message, "*"); }); }; // (3) runs content_script.js using chrome extension api function iFrameReady () { chrome.tabs.executeScript(null, { file: "content_script.js" }); }; // (6) listener for message from content_script.js using chrome extension api // it's important that this listener is set up before we run content_script, // otherwise the message from content_script will arrive before the listener exists chrome.extension.onRequest.addListener(function(request) { onPostMessage(request); }); // (2) listener for message from iframe // (not using chrome extension api here because the message is sent using postMessage window.addEventListener("message", function(request) { if (request.data.data == "ready") { // when iframe is ready, run content_script iFrameReady(); } }, false);
in the iframe
// (1) send a message to popup.js saying we're ready using postMessage window.parent.postMessage({message: "", data: "ready"}, "*") // (10) gets a message from popup.js with the quote text in it // fills the excerpt form field with the text function receiveMessage (event) { $(“#selection").val(event.data); }; // (9) listener for message from popup.js window.addEventListener("message", receiveMessage, false);










