JS postMessage does not work - javascript

So on subdomain of my domain I have a html file, for example called file.html, which also includes <script src="https://example.com/script.js"> in itself.
Then, this script.js has some listeners connected with this html, and also the function to send messages to parent, which look as follows:
v.sendMessageToParent = function (message) {
var jsonMessage = {
action: message
};
var win = window.frames.target;
win.postMessage(jsonMessage, '*');
};
v.sendActionMessageToParent = function (action) {
var jsonMessage = {
action: 'action',
type: action
};
var win = window.frames.target;
win.postMessage(jsonMessage, '*');
};
Then, on another domain I have an iframe, which src is file.html.
This another domain also has some <script src="example.com/main.js">, and I need this main.js to listen to messages sent from script.js.
In main.js I have this code:
if (window.addEventListener) {
window.addEventListener("message", messageHandler);
} else {
window.attachEvent("onmessage", messageHandler);
}
function messageHandler(event) {
console.log(event.data);
}
But I don't get anything. No JS, domain or other errors are shown, just silence in console.
Where am I wrong?

Probably you forgot to name your iframe "target":
<iframe src="http://target.com" name="target">
<script>
var win = window.frames.target;
win.postMessage("message", *);
</script>

Related

Stop HTML iFrame function from running on page load

I have an HTML iFrame inside which there is a function which I do not want to run until the site sends a message using window.postMessage() to the iFrame.
My iFrame Code:
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('pk_test_XXXXXXXXXXXXXXXXXX');
window.onmessage = (event) => {
if (event.data) {
let jackpotId = event.data.id;
myFunction(jackpotId);
}}
function myFunction(jackpotId) { //this function runs on page load
stripe.redirectToCheckout({
sessionId: jackpotId
}).then(function (result) {
});
}
</script>
I want the above myFunction() to run only when the page runs this code:
let obj = {
id: response.id
};
$w("#html2").postMessage(obj);
Currently the iFrame function runs on page load and gives error in the console due to the missing session ID.

Post a message to newly opened browser

I'm trying to post a message using the postMessage function to a browser that I've opened using window.open and while I've found a couple of articles explaining on how to do it:
Window.postMessage()
HTML5’s window.postMessage API
I just can't get it to work.
In my grid, when double clicking on a row, I call the following code:
var win = window.open('#Url.Action("Index", "StandaloneViewer")', '_blank',
'width=600,height=800,scrollbars=yes');
var domainOrigin = document.location.origin;
var message = 'My Message';
win.postMessage(message, domainOrigin);
and in my Index.cshtml, I've got the following:
$(document).ready(function () {
window.addEventListener('message', function (event) {
debugger;
var domainOrigin = document.origin;
var domainPath = document.location.href;
if (event.origin !== domainOrigin) return;
...
}, false);
});
I've also tried the same code in the load event:
$(window).on("load", function () {
window.addEventListener('message', function (event) {
debugger;
var domainOrigin = document.origin;
var domainPath = document.location.href;
if (event.origin !== domainOrigin) return;
...
}, false);
});
but to no avail! Any ideas what I may be missing? I've got the same scenario working just fine when sending a message to an iframe but I have a use case where I need to launch a separate browser and send a message to it.
I'm currently testing this on the latest version of Chrome.
Thanks.

postMessage is not working with dynamically added iframe in firefox addon using xul

I am creating a firefox addon using xul. I have added a dynamic iframe using following script:
//addon script:
let chromeUrl = 'https://myserver/downloadProduct.html';
Components.utils.import('resource://gre/modules/Services.jsm');//Services
let activeWindow = Services.wm.getMostRecentWindow('navigator:browser');
let mainDocument = activeWindow.document;
let iframeEl;
iframeEl = mainDocument.createElement('iframe');
iframeEl.id = "d";
iframeEl.setAttribute('src',chromeUrl);
iframeEl.setAttribute("tooltip", "aHTMLTooltip");
iframeEl.setAttribute("autocompleteenabled", true);
iframeEl.setAttribute("autocompletepopup", "PopupAutoComplete");
iframeEl.setAttribute("disablehistory",true);
iframeEl.setAttribute('type', 'content');
iframeEl.setAttribute('height', '32px');
window.document.documentElement.insertBefore(iframeEl, window.document.documentElement.window);
window.addEventListener("message", receiveMessage,false);
Above script is successfully adding a new iframe on page. Now I want to receive messages from iframe to my addon. I have created a postMessage event in iframe script, script as follows:
//iFrame Script:
<script type="text/javascript">
$(document).ready(function () {
$("#Download").click(function () {
parent.postMessage({ Action: "DOWNLOADED", Result: null }, "*");
})
$("#NotNow").click(function () {
parent.postMessage({ Action: "NOT_NOW", Result: null }, "*");
})
$("#Never").click(function () {
parent.postMessage({ Action: "DO_NOT_SHOW", Result: null }, "*");
})
});
</script>
But I am not able to receive message in my firefox addon.
Can anybody help?
Solution is:
window.document.getElementById("iframeId").contentWindow.document.getElementById("elementId").addEventListener('click', function() {
//Do something
}, false);
This script can be added just after adding dynamic iframe on the page.

postMessage not being received from iframe

Here is the code in the iframe with src="example.com"
<script>
var domain = "http://example2.com";
function redirectRequest(){
console.log("window.opener",window.opener); // NULL
console.log("window.top",window.top); // script_name
console.log("window.parent",window.parent); // script_name
opener.postMessage("redirect", domain); //fails because null
//top and parent also do not work BUT do not display errors
}
</script>
and here is the code running in example2.com which contains the postMessage receiver (and also contains the iframe):
function message_listener(event) { //nothing is ever received...
console.log("event received",event);
var data = event.data;
console.log("data received",data);
}
if (window.addEventListener) {
window.addEventListener("message", message_listener);
} else {
// IE8
window.attachEvent("onmessage", message_listener);
}
Any idea what might be off? Thank you very much...
For iframe you need to replace opener to parent.
replace this:
opener.postMessage("redirect", domain);
to this:
window.parent.postMessage("redirect", domain);
In my case for some reason this helped:
// Inside iframe
window.parent.socket.postMessage('msg example', '*');

Add-on Builder: Multiple Workers Using port?

Referring to this question: Add-on Builder: ContentScript and back to Addon code?
Here is my addon code:
var widget = widgets.Widget({
id: "addon",
contentURL: data.url("icon.png"),
onClick: function() {
var workers = [];
for each (var tab in windows.activeWindow.tabs) {
var worker = tab.attach({contentScriptFile: [data.url("jquery.js"), data.url("myScript.js")]});
workers.push(worker);
}
}
});
And here is myScript.js:
var first = $(".avatar:first");
if (first.length !== 0) {
var url = first.attr("href");
self.port.emit('got-url', {url: url});
}
Now that I have multiple workers where do I put
worker.port.on('got-url', function(data) {
worker.tab.url = data.url;
});
Since in the other question I only had one worker but now I have an array of workers.
The code would be:
// main.js:
var data = require("self").data;
var windows = require("windows").browserWindows;
var widget = require("widget").Widget({
id: "addon",
label: "Some label",
contentURL: data.url("favicon.png"),
onClick: function() {
//var workers = [];
for each (var tab in windows.activeWindow.tabs) {
var worker = tab.attach({
contentScriptFile: [data.url("jquery.js"),
data.url("inject.js")]
});
worker.port.on('got-url', function(data) {
console.log(data.url);
// worker.tab.url = data.url;
});
worker.port.emit('init', true);
console.log("got here");
//workers.push(worker);
}
}
});
// inject.js
$(function() {
self.port.on('init', function() {
console.log('in init');
var first = $(".avatar:first");
if (first.length !== 0) {
var url = first.attr("href");
console.log('injected!');
self.port.emit('got-url', {url: url});
}
});
});
Edit: sorry, should have actually run the code, we had a timing issue there where the content script was injected before the worker listener was set up, so the listener was not yet created when the 'got-url' event was emitted. I work around this by deferring any action in the content script until the 'init' event is emitted into the content script.
Here's a working example on builder:
https://builder.addons.mozilla.org/addon/1045470/latest/
The remaining issue with this example is that there is no way to tell if a tab has been injected by our add-on, so we will 'leak' or use more memory every time the widget is clicked. A better approach might be to inject the content script using a page-mod when it is loaded, and only emit the 'init' event in the widget's onclick handler.

Categories

Resources