Open a new tab/window and write something to it? - javascript

I'm using Execute JS to write and test Javascript code within Firefox. I want to open a new tab/window and write something to it and I tried
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
printWindow = win.open("about:blank");
printWindow = wm.getMostRecentWindow("navigator:browser");
printWindow.gBrowser.selectedBrowser.contentDocument.write('hello');
And
myWindow=window.open('','','width=200,height=100')
myWindow.document.write("<p>This is 'myWindow'</p>")
myWindow.focus()
However I always get this error
[Exception... "The operation is insecure." code: "18" nsresult:
"0x80530012 (SecurityError)"
Is there any way to get through this exception?

Top-level navigation to data URLs has been blocked in Chrome, Firefox (with some exceptions), IE, and Edge (and likely other browsers to boot). They are apparently commonly used for phishing attacks, and major browser vendors decided that the danger outweighed the value provided by legitimate use cases.
This Mozilla security blog post explains that Firefox will block
Web page navigating to a new top-level data URL document using:
window.open("data:…");
window.location = "data:…"
clicking <a href="data:…"> (including ctrl+click, ‘open-link-in-*’, etc).
Web page redirecting to a new top-level data URL document using:
302 redirects to "data:…"
meta refresh to "data:…"
External applications (e.g., ThunderBird) opening a data URL in the browser
but will not block
User explicitly entering/pasting "data:…" into the address bar
Opening all plain text data files
Opening "data:image/*" in top-level window, unless it’s "data:image/svg+xml"
Opening "data:application/pdf" and "data:application/json"
Downloading a data: URL, e.g. ‘save-link-as’ of "data:…"
You can also read the proposal to deprecate and remove top-frame navigation to data URLs in Chrome and view the current Chrome status indicating that is has been removed.
As for how to actually open HTML in a new tab or window, this should be sufficient:
var tab = window.open('about:blank', '_blank');
tab.document.write(html); // where 'html' is a variable containing your HTML
tab.document.close(); // to finish loading the page
Note that at least in Chrome, external scripts injected via document.write might not be loaded on slower connections. That might not be relevant here, but something to watch out for.

Edit: As of 2018, this solution no longer works. So you are back to opening about:blank in a new window and adding content to it.
Don't "write" to the window, just open it with the contents you need:
var data = "<p>This is 'myWindow'</p>";
myWindow = window.open("data:text/html," + encodeURIComponent(data),
"_blank", "width=200,height=100");
myWindow.focus();
For reference: data URIs

var winPrint = window.open('', '', 'left=0,top=0,width=800,height=600,toolbar=0,scrollbars=0,status=0');
winPrint.document.write('<title>Print Report</title><br /><br />
Hellow World');
winPrint.document.close();
window.open(uri) does not work in chrome as of 2018

Related

open new window using window.open by "Post" parameters

i want to open a new window using window.open(). but the issue is i don't want to show the URL to user, so i have to use POST URL for this. but window.open() function opens the new window and shows the URL in URL bar. i have to hide the URL.
here is the Example :
window.open(URL,"_blank",'status=0,toolbar=0,resizable=0,menubar=0,titlebar=0,width=1180,height=770');
No, you can't hide address bar in modern browser.
location=no paramter will not working.
See the MDN document.
https://developer.mozilla.org/en-US/docs/Web/API/Window/open
In Firefox 3, dom.disable_window_open_feature.location now defaults to
true, forcing the presence of the Location Bar much like in IE7.
location parameter is also always enabled (means location=yes) in Google Chrome.
But you can assign a fake URL:
var win = window.open('/path/page.htm');
win.addEventListener('DOMContentLoaded', function () {
win.history.replaceState(null, null, '/fake.htm'); // must be same domain (or ignore domain)
});

Download S3 file from pre-signed URL without popup blocker

I have a Meteor application where I'm downloading files from S3 using pre-signed URLs (need to be generated with an API call).
I was having an issue with popup blockers preventing a new tab from opening with the url generated by the AWS-SDK so I changed my code to the following:
downloadDocument(document, event) {
// open tab immediately to prevent popup blocker
const myNewTab = window.open();
// call method to generate url
Meteor.call('Events.Methods.Document.Download', { key: document.key, eventId: event._id }, (error, res) => {
if (error) { ... } // removed handle error code
// if url generated, set tab location to url
if (res) myNewTab.location.href = res;
// auto close the tab after 1 second
myNewTab.setTimeout(() => { myNewTab.close(); }, 1000);
});
}
This code is working for the most part but it doesn't feel very clean. Also if the API call ever takes more than 1 second (slow internet) then the tab will close before the download begins
How can I change this so that I can wait for the download to happen, before closing the tab? Or a similar solution that would result in me ensuring the downloads always go through without popup blockers being an issue?
Thanks
You are always going to run afoul of pop-up blockers if you open a new window.
What you should do is generate an <a href="my-custom-server-generated-url" download> link with the download property, which will force a download without needing a new window.
Then you also don't need to close the window on a timer (which wasn't a good approach in the first place)
This was happening only in Safari, so we switched to always downloading the file instead of opening in a new window in Safari/mobile.

Accessing the DOM of a programatically opened tab that contains a different domain than the active tab

Overview of the problem
I cannot access the DOM of a window that I open programmatically in my chrome extension. I believe this may be due to origin/cross-site scripting restrictions. I have tried to give it the maximal permissions I can, including "<all_urls>", "activeTab" and "tabs"
I also played around with "content_security_policy_" settings but from the documentation I was hoping rather than expecting that to help.
I have a simple extension that runs code when the button is clicked, I want to open a few different tabs (but from different domains) and then access the DOM of each. However, it only seems to work if I'm on a tab of a domain and then I open another tab of the same of domain. Then I can access, for example, window onload of the new tab. I have no luck when it is a different domain.
e.g. if I press the button with activeTab "foo.com" then if it window.opens a new tab "foo.com/something" then I can access the document of that opened tab. But if it was "bar.com" then I wouldn't be able to access "foo.com/something"'s DOM
p.s. please note that executeScripts is used instead of manifest content scripts because it is necessary for my code to work. I must inject at least some of the files there this way, otherwise my code will not work (for reasons that are not completely apparent in the example)
my Question
What's way(s) can I get around this - I mean be able to access the DOM of any tab that I open, regardless of what site is in the active tab when the extension button is pressed in the toolbar?
Should I inject content scripts into a a tab that has been opened with window.open and somehow pass its document to Code.js? If so, how could I go about doing that? Can I somehow pass the document to the background.js? and somehow pass it to the injected Code.js?
If this will work (get around security restrictions) then can these content scripts be injected programatically (I don't know exactly what sites they will be until runtime, so I can't really specify them in the manifest)
or is there some way I can just relax the security restrictions and be able to directly access window.open's returned window's document? (which as I mentioned above currently only works on same-domain sites)
background.js
// this is the background code...
// listen for our browerAction to be clicked
chrome.browserAction.onClicked.addListener(function (tab) {
executeScripts(null, [ // jquery can be inserted here: https://stackoverflow.com/questions/21317476/how-to-use-jquery-in-chrome-extension
{ file: "lib/jquery-3.2.1.js" },
{ file: "lib/kotlin.js" },
{ file: "Code.js" } // don't include it in manifest "content_scripts" because it gives an error about kotlin.js not present that way
])
});
/*
* https://stackoverflow.com/questions/21535233/injecting-multiple-scripts-through-executescript-in-google-chrome
*/
function executeScripts(tabId, injectDetailsArray)
{
function createCallback(tabId, injectDetails, innerCallback) {
return function () {
chrome.tabs.executeScript(tabId, injectDetails, innerCallback);
};
}
var callback = null;
for (var i = injectDetailsArray.length - 1; i >= 0; --i)
callback = createCallback(tabId, injectDetailsArray[i], callback);
if (callback !== null)
callback(); // execute outermost function
}
code flow
background.js
Code.jscalls a function that starts with var w = window.open(url)
then w.addEventListener("load", ...), which is the problem. It only fires if the url belongs to the same domain as the active tab. (onLoad can't be used any-which-way, it never fires that's why I use addEventListener)
notes
I have "manifest_version": 2
I need to inject this way rather than include content scripts in the manifest (I guess I could put the jquery library in the manifest but the others I can't and I prefer to keep all injections together in the "code")

MS Edge - window.open gives error "The operation was canceled by the user."

I have two different window.open function calls that are both failing in Microsoft Edge:
var canvas = document.getElementById("diagramCanvas");
var imgUrl = canvas.toDataURL("image/png");
window.open(imgUrl);
and
window.open('data:application/vnd.ms-excel,' + encodeURIComponent($('#results').html()));
They both generate the error:
The operation was canceled by the user.
This looked like a popup blocker, so I disabled Edge popup blocking and both still fail, while obnoxious popups with real urls do pop up: http://www.popuptest.com/
Is there a way to make Edge open javascript-generated files in a new window?
It looks like the problem may be due to the length of the url in the new window declaration.
I found a workaround based on the answer to this question:
Download canvas to Image in IE using Javascript
From the answer:
Example code:
$("#save").click(function(){
var html="<p>Right-click on image below and Save-Picture-As</p>";
html+="<img src='"+canvas.toDataURL()+"' alt='from canvas'/>";
var tab=window.open();
tab.document.write(html);
});
By opening a new window then writing to the body, url length limits can be avoided.
This format works in IE9+ and Edge, as well as Chrome (and should work in all other modern browsers).

Open window in tab of new window

I want to open a tab inside an opened window. Something like this
(it should open a new window with "google.co.uk" with a new tab "google.de"
newWindow = window.open('http://www.google.co.uk', '', 'width=10');
newWindowTab = newWindow.open('http://www.google.de', '_blank');
but this opens "newWindowTab" only in the window, where this code is.
I have also tried this, to give the window time to load, until it (should) open the new tab:
newWindow = window.open('http://www.google.co.uk', '', 'width=10');
setTimeout(function() {
newWindowTab = newWindow.open('http://www.google.de', '_blank');
}, 500);
But then I get:
Error: Permission denied to access property "open"
I have used firefox. I heard that it might be possible to do in Chrome, but I want to use this script in Firefox.
This is not possible, unless the window being opened is from the same origin (ie the same domain). MDN says this:
The reference can be used to access properties and methods of the new
window provided it complies with Same origin policy security
requirements.

Categories