Creating a bookmarklet that doesn't get blocked - javascript

Goal: To create a bookmarklet that calls a remote javascript file that opens a popup window. The popup window is functionally similar to what Delicious's bookmarklet does.
Background: Currently, I'm using window.open within this javascript file, however the popup is getting blocked by pretty much every major browser.
The alternative solution to this is very similar to the way Delicious wrote their bookmarklet - calling window.open through a javascript query within the bookmarklet itself. However, I need the ability to modify the other contents of my javascript file in the future without requiring users to continually grab newest releases of the bookmarklet.
What I've determined to be happening: Since the window.open call is not occurring directly as a result of a click by the user, the browser feels this is something that should be blocked. Here's a source on this.
This is the tutorial I referenced most recently in creating the call to the remote js file.
Here is a basic example of what my code is doing; the window.open/popup portion is the only significant part I'm including as it's the only part I feel is causing the complication:
Example of the remote javascript file:
if (typeof jQuery == 'undefined') {
var jQ = document.createElement('script');
jQ.type = 'text/javascript';
jQ.onload=runthis;
jQ.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
document.body.appendChild(jQ);
} else {
runthis();
}
function runthis() {
window.open('http://www.google.com/', 'a title',
'location=yes,links=no,scrollbars=no,toolbar=no,width=550,height=550');
}
I'd really appreciate any help as this has been stumping me for a while!

An approach that looks better and side-steps the blocking issue is to have the bookmarklet insert an iframe in the page the user is currently viewing. Ended up taking this approach back when I asked this question. Worked out fine.

Related

Javascript redirect not working in Edge browser when opened with android ActionView intent, but working after manual reload

Situation
In our Android app (Xamarin), we open a web page using an ActionView intent. The code looks like this:
Intent intent = new Intent((string)Intent.ActionView, Android.Net.Uri.Parse(args.url));
intent.AddFlags(ActivityFlags.NewTask);
The opened page at some point does a JS redirect, with a line like this:
window.location = '...';
We tried many different variations of that line, including window.location.href = '...', window.location.assign('...'); and some more. All show the same behavior.
Problem
This has worked fine for years now, in all browsers - but now we ran into a problem, when the browser on the android device is the Edge browser:
When the browser tab is initially opened by the intent, the window.location = '...' line in Javascript is just ignored by the browser. No error message - just ignored.
However, if that same browser tab with exactly the same URL is opened manually (either by reloading or by copying and pasting the URL), the JS redirect is executed just fine.
Question
How do we fix this, how do we make the JS redirect reliably work?
My guess is that we are running into a security feature, which prevents JS redirects in browser tabs that the user has never interacted with.
Is there something (maybe an intent flag?) to circumvent this? We already tried the flag GrantWriteUriPermission, but it did not help.
Possible duplicates
Android Browser Facebook Redirect Does Not Always Trigger Intent for URL :
The proposed situation of setting the URL on a link and faking a click on it did not work.
Microsoft Edge security
Microsoft Edge recently fixed an issue regarding XSS Targeting Non-Script Elements (June 24, 2021).
The vulnerability was found by two researcher when they visited a website in another language via the Microsoft Edge browser and attempted to translate the page. The goal of the recent fix by Microsoft is to avoid vulnerability regarding accessing dynamically to a content from a third party application and specifically in the case of browser redirection. They need to act quickly because the vulnerability is quite huge.
In order to mitigate a large class of potential cross-site scripting issues, the Microsoft Edge Extension system has incorporated the general concept of Content Security Policy (CSP)
Ok, but ... is there any solution?
Maybe you can find a solution to solve your issue here, in particular the part concerning the <button onclick="...">.
Inline code is considered harmful in concept of CSP and microsoft recommend some good practices :
1 - The clickHandler definition must be moved into an external JavaScript
2 - The inline event handler definitions must be rewritten in terms of addEventListener and extracted into your external js file. If you are currently starting your program using code like <body onload="main();">, consider replacing it by hooking into the DOMContentLoaded event of the document, or the load event of the window, depending on your requirements. Use the former, since it generally triggers more quickly.
3 - Function inside onclick call must be rewritten to avoid converting the string of function into JavaScript for running.
The code exemple of the external .js file cited in the documentation look like this :
function awesome() {
// Do something awesome!
}
function totallyAwesome() {
// do something TOTALLY awesome!
}
function awesomeTask() {
awesome();
totallyAwesome();
}
function clickHandler(e) {
setTimeout(awesomeTask, 1000);
}
function main() {
// Initialization work goes here.
}
// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click',
clickHandler);
main();
});
Hope it's helps

load page and execute javascript in a url

Hello wonderful stackoverflow users.
I have a question about url loading.
In many browsers and web viewers, there is the functionality to load a url to a website, but also a url to execute javascript.
Load a website: http://www.google.com
Load a script: javascript:alert("Hello!");
My question is, is there a way to load an http request as well as a javascript.
The answer is most likely no, but I want to confirm because I can't find any resources that describe this.
I was thinking it would be something like:
http://www.google.com&&javascript:alert("Hello!");
but the problem is, of course, this is not correct.
The reason why I am doing this is to provide a url that once it is clicked, it will also execute a certain javascript function. This will be in Android.
I appreciate any response, and understand that the answer may be no.
It all depends on whether you have control of the page being linked to. If you cannot modify the source of the linked page, then the answer is quite simply, no.
But, if it is your page, you can pass arguments in the hash, and then read the hash when the page loads and execute script accordingly.
window.onload = function () {
if (location.hash.indexOf("doSomething") > -1) {
// do something
}
};
You can execute javascript when a page loads using Browser plugins, such as GreaseMonkey for Firefox, or TamperMonkey for Chrome.
https://addons.mozilla.org/en-us/firefox/addon/greasemonkey/
http://tampermonkey.net/index.php?version=3.11&ext=dhdg&updated=true

CKEditor variable is available in console, but not from a Chrome userscript?

I'm writing a Chrome userscript to locally auto-save content in a CKEditor. I'm using this CKEditor auto-save plugin as inspiration.
I have written a function that fires every half second (via an interval) to register the CKEditor event handler:
var intervalId = window.setInterval(function() {
if (CKEDITOR) {
window.clearInterval(intervalId);
CKEDITOR.plugins.add("user-script-auto-save", {
init : function(editor) {
editor.on('key', startTimer);
}
});
}
}, 500);
However, it never properly completes, and complains that "CKEDITOR is undefined" on the if (CKEDITOR) statement.
Meanwhile, if I drop into Chrome's console and type CKEDITOR, the console prints out the expected object.
What am I missing? The editor is embedded within an iframe; might that have an impact on scoping? Or am I fighting against Chrome's sandboxing here? And if so, is there some other way I can dig into CKEditor to pull out the content every second or something to do the auto-saves?
I have not yet tried the script in Firefox; that's next on my list.
Worth noting: I'm a long-time JavaScript novice. So I could easily be doing something dumb with scoping or something like that.
According to this little tutorial video on YouTube, all the 3 "devices" are separated from each other in order to prevent XSS attacks from the user script to the browser / website and vice versa. Although the user scripts / content scripts are running in the website's context, they are still kept separated from the actual website script context. You can easily acknowledge this by simply trying to access for example jQuery from a content script. Just as the CKEditor, it will not be available.
So what I've come up with in order to deal with this is using the content script to include external JavaScripts in the head tag. AFAIK, this is not possible for files directly in the extension's root directory, so I've taken a remote server to host my files.
I'm not sure if this is the best approach and I think it is an ugly bypass, possibly way to powerfull and disabled by the Chromium Project some time.
(Edited by OP, so I can select this answer and route karma appropriately)
This answer, combined with some of the suggestions and links in the comments, ended up getting me to where I needed to be.
I ended up with the following function:
var insertScriptIntoDocument = function(scriptUrl, doc) {
// inspired by http://blog.afterthedeadline.com/2010/05/14/how-to-jump-through-hoops-and-make-a-chrome-extension/
var scriptText = doc.createTextNode(
'(function(loc) { \
var embeddedScript = document.createElement("script"); \
embeddedScript.type = "text/javascript"; \
embeddedScript.src = loc; \
document.getElementsByTagName("head")[0].appendChild(embeddedScript); \
})("' + scriptUrl + '");');
var injectorElement = doc.createElement('script');
injectorElement.appendChild(scriptText);
doc.body.appendChild(injectorElement);
};
Usage looks like so:
var embeddedScriptUrl = chrome.extension.getURL("embedded-script.js");
insertScriptIntoDocument(embeddedScriptUrl, document);
For now, I'm executing this from within a Chrome extension, but I suspect that the pattern might work in a GreaseMonkey script deployed via the Chrome TamperMonkey extension provided that the URL of the script to be embedded was hosted somewhere reachable.
FTR, as it turns out, I did not actually need to get to the iframe -- the CKEDITOR variable was defined in the top-level document, but was simply not visible because of the rules of the Chrome sandbox

How to manipulate Javascript websites in Perl

I have been asked to automate the logging into a webapp(what I assume to be one, that runs a lot of .aspx and .js scripts) that, currently, can only run in IE. Now i am programming in Perl and have tried to use Win32::IE::Mechanize to run the IE browser and log in. What i did was try an extract all the forms from the webapp, and given the users information, fill out the required forms, but this is where the problem arises, when I try and run the subroutine no forms appear......
So then I transitioned into WWW::Mechanize and used the post subroutine(from LWP::UserAgent) which solved the problem for the most part. Now i've run into a problem in the response, from the server, I get this script as the content of the response and I don't know what to do with it.
So my question is: Using Perl how can I go about to manipulate a Javascript functions in a website? Would that even be a valid solution to the problem?
I am open to writing this in other programming languages as well. Thanks in advance for the help!
(So that I can fully log in to the webapp)
Update: The content of the response:
var msgTimerID;
var strForceLogOff = "false";
function WindowOnLoad(){
if ("false" == "true" && "false" == "false")
MerlinSystemMsg("",64);
if ("false"=="true")
msgTimerID = window.setInterval("MerlinSystemMsg(10095,64)", 300000,'javascript');
}
function MyShowModal(){
showModalDialog("", window, strFeatures);}
function clearMsgInterval(){
window.clearInterval(msgTimerID);
}
function WindowOnUnLoad(){
if(top.frames(0).document.getElementById("OPMODE").value =="LOGOFF"){
strFeatures = "width=1,height=1,left=1000,top=1000,toolbar=no,scrollbars=no,menubar=no,location=no,directories=no,status=yes,resizable=1";
window.open("ForceLogOff.aspx","forcelogout",strFeatures);
}
}
window.onbeforeunload = WindowOnUnLoad;
window.onload = WindowOnLoad;
There is also this Frame Title that has the src:
FRAME TITLE="Service Desk Express Navigator" SRC="options_nailogo.aspx" MARGINWIDTH=0 MARGINHEIGHT=0 NORESIZE scrolling=no
Trying to emulate the browser with a fully functioning JS engine is going to be a mighty big task. Instead, I'd suggest that you just try to emulate the actual interaction with the web site and not care what HTML/JS is actually sent back. Your server side code doesn't care how the HTTP submissions take place, only that they do. Admittedly this is more fragile if the forms change a lot, but at least you're not trying to implement a full browser.
So look at modules like LWP::UserAgent, HTTP::Request and HTTP::Response.
I'm copying and pasting my answer to your other duplicate question here
(You should consider deleting one of these?)
That content is the website source :)
How WWW::Mechanize deals with FRAME SRC as a link:
Note that <FRAME SRC="..."> tags are parsed out of the the HTML and
treated as links so this method works with them.
You'll want to use follow_link on that link.
As far as dealing with Javascript, there is support for a Firefox Add-on called MozRepl that you can use in conjunction with WWW::Mechanize::Firefox that I have used in the past to call Javascript code while crawling a page.

Take Screenshot of Browser via JavaScript (or something else)

For support reasons I want to be able for a user to take a screenshot of the current browser window as easy as possible and send it over to the server.
Any (crazy) ideas?
That would appear to be a pretty big security hole in JavaScript if you could do this. Imagine a malicious user installing that code on your site with a XSS attack and then screenshotting all of your daily work. Imagine that happening with your online banking...
However, it is possible to do this sort of thing outside of JavaScript. I developed a Swing application that used screen capture code like this which did a great job of sending an email to the helpdesk with an attached screenshot whenever the user encountered a RuntimeException.
I suppose you could experiment with a signed Java applet (shock! horror! noooooo!) that hung around in the corner. If executed with the appropriate security privileges given at installation it might be coerced into executing that kind of screenshot code.
For convenience, here is the code from the site I linked to:
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
...
public void captureScreen(String fileName) throws Exception {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRectangle = new Rectangle(screenSize);
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(screenRectangle);
ImageIO.write(image, "png", new File(fileName));
}
...
Please see the answer shared here for a relatively successful implementation of this:
https://stackoverflow.com/a/6678156/291640
Utilizing:
https://github.com/niklasvh/html2canvas
You could try to render the whole page in canvas and save this image back to server. have fun :)
A webpage can't do this (or at least, I would be very surprised if it could, in any browser) but a Firefox extension can. See https://developer.mozilla.org/en/Drawing_Graphics_with_Canvas#Rendering_Web_Content_Into_A_Canvas -- when that page says "Chrome privileges" that means an extension can do it, but a web page can't.
Seems to me that support needs (at least) the answers for two questions:
What does the screen look like? and
Why does it look that way?
A screenshot -- a visual -- is very necessary and answers the first question, but it can't answer the second.
As a first attempt, I'd try to send the entire page up to support. The support tech could display that page in his browser (answers the first question); and could also see the current state of the customer's html (helps to answer the second question).
I'd try to send as much of the page as is available to the client JS by way of AJAX or as the payload of a form. I'd also send info not on the page: anything that affects the state of the page, like cookies or session IDs or whatever.
The cust might have a submit-like button to start the process.
I think that would work. Let's see: it needs some CGI somewhere on the server that catches the incoming user page and makes it available to support, maybe by writing a disk file. Then the support person can load (or have loaded automatically) that same page. All the other info (cookies and so on) can be put into the page that support sees.
PLUS: the client JS that handles the submit-button onclick( ) could also include any useful JS variable values!
Hey, this can work! I'm getting psyched :-)
HTH
-- pete
I've seen people either do this with two approaches:
setup a separate server for screenshotting and run a bunch of firefox instances on there, check out these two gem if you're doing it in ruby: selenium-webdriver and headless
use a hosted solution like http://url2png.com (way easier)
You can also do this with the Fireshot plugin. I use the following code (that I extracted from the API code so I don't need to include the API JS) to make a direct call to the Fireshot object:
var element = document.createElement("FireShotDataElement");
element.setAttribute("Entire", true);
element.setAttribute("Action", 1);
element.setAttribute("Key", "");
element.setAttribute("BASE64Content", "");
element.setAttribute("Data", "C:/Users/jagilber/Downloads/whatev.jpg");
if (typeof(CapturedFrameId) != "undefined")
element.setAttribute("CapturedFrameId", CapturedFrameId);
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("capturePageEvt", true, false);
element.dispatchEvent(evt);
Note: I don't know if this functionality is only available for the paid version or not.
Perhaps http://html2canvas.hertzen.com/ could be used. Then you can capture the display and then process it.
You might try PhantomJs, a headlesss browsing toolkit.
http://phantomjs.org/
The following Javascript example demonstrates basic screenshot functionality:
var page = require('webpage').create();
page.settings.userAgent = 'UltimateBrowser/100';
page.viewportSize = { width: 1200, height: 1200 };
page.clipRect = { top: 0, left: 0, width: 1200, height: 1200 };
page.open('https://google.com/', function () {
page.render('output.png');
phantom.exit();
});
I understand this post is 5 years old, but for the sake of future visits I'll add my own solution here which I think solves the original post's question without any third-party libraries apart from jQuery.
pageClone = $('html').clone();
// Make sure that CSS and images load correctly when opening this clone
pageClone.find('head').append("<base href='" + location.href + "' />");
// OPTIONAL: Remove potentially interfering scripts so the page is totally static
pageClone.find('script').remove();
htmlString = pageClone.html();
You could remove other parts of the DOM you think are unnecessary, such as the support form if it is in a modal window. Or you could choose not to remove scripts if you prefer to maintain some interaction with dynamic controls.
Send that string to the server, either in a hidden field or by AJAX, and then on the server side just attach the whole lot as an HTML file to the support email.
The benefits of this are that you'll get not just a screenshot but the entire scrollable page in its current form, plus you can even inspect and debug the DOM.
Print Screen? Old school and a couple of keypresses, but it works!
This may not work for you, but on IE you can use the snapsie plugin. It doesn't seem to be in development anymore, but the last release is available from the linked site.
i thing you need a activeX controls. without it i can't imagine. you can force user to install them first after the installation on client side activex controls should work and you can capture.
We are temporarily collecting Ajax states, data in form fields and session information. Then we re-render it at the support desk. Since we test and integrate for all browsers, there are hardly any support cases for display reasons.
Have a look at the red button at the bottom on holidaycheck
Alternatively there is html2canvas of Google. But it is only applicable for never browsers and I've never tried it.
In JavaScript? No. I do work for a security company (sort of NetNanny type stuff) and the only effective way we've found to do screen captures of the user is with a hidden application.

Categories

Resources