i'm adjusting my extension to Firefox multiprocess (e10s).
I want to send the webpage some data using a postMessage from the frame-script.
The Firefox documnatation says i should try to use 'content' object instead of the 'window' object. When trying to access the content page i get an error: .
// frame-script.js
addMessageListener("message_from_ext", function(message){
try{
var _message = {
from: "content",
to: "web",
data: message
};
content.postMessage(_message, "*"); //getting <unavailable> on the content object
}catch(e){
console.log(e);
}
});
how should i access the content object? should i load anything to my frame-script.js?
(I already succeeded in getting data from the webpage, and sending it to the extension and getting back other data from the extension)
<unavailable> is not an error, it just means the console you have open cannot display the object properly because it lives in another process.
Open the browser content toolbox and use its console instead to view messages in the content process.
Related
I'm creating a script that runs on every website (using temperMonkey). On a shortcut I inject a form into the page. So if I am in stackoveflow, I pres cmd+esc and I embed a local vuejs page
Step 1: Inject an iframe to (say) stack overflow and send a message to the embedded site**
var iframe = document.createElement("iframe");
iframe.type="text/html"
iframe.src="http://localhost:8080/webhighlights"
iframe.id="localFrame"
var data = {title: document.title, url: window.location,}
iframe.onload= function(){
var t = document.getElementById('localFrame');
t.contentWindow.postMessage({
data
}, 'http://localhost:8080/webhighlights');
}
Step 2: get the message from the site that has embedded me:
mounted: function () {
/* eslint-disable */
window.top.addEventListener('message',receiveMessage, false);
function receiveMessage (event) {
console.log('event data: ', event)
}
}
The message doesn't come through. The error I get in the console is Failed to execute 'postMessage' on 'Window': Location object could not be cloned. at HTMLIFrameElement.iframe.onload
You are sending a message to your iframe's context, so from this iframe you don't want to listen for top's messages, but only for this iframe's window ones.
Change
window.top.addEventListener('message',...
to
window.addEventListener('message',...
If you want to understand better how messaging works, I invite you to read this answer of mine.
Baiscally with an iframe, one port is in the main context, under HTMLIframeElement.contentWindow, and the other one is in the iframe's context, under window. To communicate between both contexts, each context should listen to and talk in their own port.
When this is fixed you will face a new issue that the location object can't be cloned. Since apparently you only want to send the current URL of the main page, then only send this:
var data = {title: document.title, url: window.location.href };
I open a file download from a remote API on my webpage via window.open(). The API (a Flask server) has error handling and returns the error message if there's an internal server error, like this:
#app.errorhandler(502) //all other errors are handled the same way, including 500, etc.
#crossdomain(origin='*')
def bad_gateway_error(error):
return "Bad Gateway Error - Please make sure you're using a properly formatted file! Details: " + str(error), 200
I want to display this error on my site instead of redirecting to the error page. I'm trying to catch it via:
try {
window.open("https://API/receivedoc?timestamp="+timestamp,"_self")
} catch(e) {
filerootdiv.querySelector('.output').innerHTML = String(e);
}
This however does nothing (tested in Chrome). How could I catch the error when I'm using window.open? I guess it might be because in the error handling I return a 200 message so that the string I return actually gets returned instead of just crashing the server (this needs to stay this way as it's working just fine with all the other errors when I'm not trying to return a file). The issue is that I can't tell if the API request would return a file or a string before doing a window.open().
UPDATE
I've tried implementing:
let new_window = window.open("https://flaskmin.run.aws-usw02-pr.ice.predix.io/receivedoc?timestamp="+timestamp,"_self")
newWindow.onerror = function() {
filerootdiv.querySelector('.output').innerHTML = "Error!";
However this still only opens a new window with the error. I guess it's because of the error handling on the server side (I cannot change this). Can I somehow probe the content of new_window before redirecting to it, and just not open it if it's just a string containing the word 'error'?
I have one situation,where i need to pass some json from one window to new window in the same domain.I have first window lets say it window1 and second window,let say it window2.
I have following code in window1:
var params = [
'height=750',
'width=720',
'scrollbars=yes',
'left=0',
'top=0',
'fullscreen=no', // only works in IE, but here for completeness
'location=no'
].join(',');
var port = location.port;
var url = "http://" + hostName + ':' + port + "/isecalreport" + location.search;
var newWindow = window.open(url,'photocal_report',params);
while(true){
if(newWindow! == undefined) {
newWindow.location.state={payloadFromIseCalWeekly : payloadFromIseCalWeekly,instrumentIdObj : instrumentIdObj};
break;
}
}
Code in window2:
var payloadFromIseCalWeekly = location.state.payloadFromIseCalWeekly ? location.state.payloadFromIseCalWeekly : {};
I want to make use of the json set in window.location.state.
So the problem is ,It works fine in chrome ,mozilla,but fails in IE 11(when debugger is not open.)
When i open debugger in IE11 ,it works fine.
I debugged it and found out that after the instruction which is opening the new window ,the next instruction get run and it doesnot find the new window object.
Its strange as it works when developer console is open.
It would be good if i can get insights about how to resolve the issue.
My aim is to open a new window ,to which i need to pass some data and using that data i want to do an API call.
With few exceptions, you cannot tell one window, tab or frame to talk to another directly. This is to prevent malicious scripts in one of these contexts from hijacking another across pages.
To cope with this, you have two options, you can use postMessage() or simply pass your data via the URL that you open in the new window. There are technically more options if you're on the same domain, but I recommend against going down that rabbit hole.
Sending data via the URL is a one-way affair. You can send query string variables in the URL that the new window can read, but it can't send anything back to the window that created it.
postMessage(), on the other hand, can be used to communicate between multiple contexts and across domains. It is considered secure because it requires that all participants be listening for messages, rather than allowing direct code access.
Your various pages can listen for messages with a simple event listener.
// listen for incoming messages on this page
window.addEventListener('message', function(e) {
// this is the handler function
// do we trust where this was sent from?
if (event.origin !== "http://example.com") {
// if so, print the resulting event object
console.log('message received', e);
}
}, false);
You can then send a message from another page to your window.
// the * is the targetOrigin, read the docs!
newWindow.postMessage("some message data", "*");
Creating browser extension where I have to open new tab from background.js and pass JSON data to this new tab. In new tab I am manipulating/rendering DOM using passed JSON data.
Below is part of my background.js where I create new tab with custom URL and send JSON data object
....
var analyticsUrl = chrome.extension.getURL("analytics.html");
chrome.tabs.create({ url: analyticsUrl, selected: true }, sendDataToAnalytics);
function sendDataToAnalytics(tab)
{
console.log(JSON.stringify(txnDataJSON));
chrome.tabs.sendMessage(tab.id, {"action" : "renderChartsTxns", "txns" : JSON.stringify(txnDataJSON)});
}
....
My custom analytics.html page has
<script src="analytics.js" type="text/javascript"></script>
And analytics.js looks like below
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.action == "renderChartsTxns")
{
// JSON parsing and analytics.html DOM processing
});
Problem is, my analytics.js listener is never receiving any messages. I've confirmed that background.js is sending JSON message as expected (using background page debugging)
BTW, analytics.js/html are not registered as part of manifest.json file but these files are part of extension package.
I did this setup today morning and everything was working properly for few hours (was able to receive JSON data in analytics.js), not sure what changed later and I lost message receiving in analytics.js (for debugging I tried clearing browser cache, uninstall and reinstalled chrome and much more but no luck yet!)
The callback of chrome.tabs.create returns as soon as the tab is created, not after it fully loads.
As such, you have a race condition: your message is potentially sent before the listener is initialized. Since it's a race condition, it can sometimes work.
The correct logic here would be to send a message requesting data from the newly opened tab, and use sendResponse to pass that data from the background.
// analytics.js
chrome.runtime.sendMessage({"action" : "getTxns"}, function(txns) {
// Process the data
});
// background.js
// Register this before opening the tab
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.action == "getTxns") {
sendResponse(txnDataJSON); // No need to serialize yourself!
}
});
I am getting an error which seems to be originating from one of the page scripts.
file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1
return c.apply(undefined,a)}catch(d){webengage.eLog(d);if(!b){throw d}}}else{t
^
TypeError: Cannot call method 'call' of undefined
at new exports.NOT_IMPLEMENTED (/usr/local/lib/node_modules/jsdom/lib/jsdom/browser/utils.js:9:13)
at Object.webengage.eLog (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:366)
at t.extend.u (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:19160)
at Object.t.extend.error (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:19299)
at file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:66518
at Object.webengage.withELog (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:640)
at Timer.<anonymous> (file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1:937)
at Timer.exports.setInterval.timer.ontimeout (timers.js:234:14)
I am getting this error from the following code:
try {
var document = jsdom.jsdom(str, null, {});
} catch(e) {
console.log("Got ERROR...");
console.log(e);
}
console.log("Page Document Loaded.");
var window = document.parentWindow;
//console.log(window.document.innerHTML);
console.log(window.innerWidth);
console.log(typeof window.document.getElementsByClassName);
here str is the html that i got earlier. I am able to see printed results, the html the innerWidth and the typeof getElementsByClassName i.e.. function. But after around 20 seconds i am getting the above error and my application crashes, without printing Got ERROR... from above.
The first question that i have is why is my application still running after printing the last thing. Is this a normal behavior for jsdom that it keeps on running like how in a browser a script keeps on running until window.close() is given.
The actual problem is, how can i resolve this. I want to trigger few events in this window object and interact with it but it keeps on crashing.
The url for the script is a little confusing:
file://cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1
this is because the page is fetching this script resource in an ajax call with the url:
//cdn.widgets.webengage.com/js/widget/webengage-min-v-3.0.js:1
although jsdom is able to get the resource, i checked that this script has that line where it is showing the error.