I am working on a Google Chrome extension. We need to display a pop-up login window for users to enter credentials, then handle logins. My extension project consists of three pages: extension, background and options. Options html and JavaScript pieces handle login, however reference to a window opened from options.html is always null.
Therefore, I tried sending a message from options to background scripts, and have the background script open the login window. That part is working, however I never receive any events from that popup, and therefore cannot process the results of login.
case 'openSignInWindow':
let loginWindowRef = window.open('https://myurl.com/client/signin.html', 'signinpopup', 'width=400,height=400,resizeable,scrollbars');
console.log('login window ref:', loginWindowRef);
loginWindowRef.onload = () => { alert("message one "); };
loginWindowRef.addEventListener('DOMAttrModified', event => {
console.log('event:', event);
});
break;
Tried onsubmit - the one that I am interested in, as well as other events. My ultimate goal is to catch the "DOM Mutation events."
What am I doing wrong?
Related
Hello StackOverflow community!
I've encountered a very weird problem and couldn't find any useful information on how to solve it.
Somehow, a piece of javascript code works only when the dev tools window is opened (docked or as a separate window) in google chrome.
The original problem: Due to our application structure, we need to open multiple popups automatically when a page is served. Since the popups are NOT opened through a direct user interaction (like onclick), modern browsers would automatically block these popups. Because of the large amount of code that would need to be refactored to avoid this, our solution was:
check if the browser is blocking some popups.
if so: inform the user about this and suggest to turn off their browser's popup blocking function for
our website (by adding it to the exception list for example).
Not a very elegant solution I know, but there was no other way so please don't comment on how to do this differently.
The javascript code:
let popupBlockingErrorShown = false;
this.OpenWindow = function (url, name, args) {
var i = Popups.length; //Popups is an array defined as a global variable that keeps track of all
//opened popup windows
Popups[i] = window.open(url, name, args);
try {
Popups[i].focus();
} catch (e) {
if (!popupBlockingErrorShown) {
alert("very user friendly message explaining to turn of popup blocking");
popupBlockingErrorShown = true;
}
};
}
The windows have to be popups. The popupBlockingErrorShown variable is to prevent having an alert message for each popup.
Works fine in firefox. But in google chrome there is this behaviour:
without dev tools open: the first popup opens normally, the others are blocked, there is no alert message.
with dev tools open: the first popup opens but gets 'stuck' on loading (it's an empty page). The alert message shows normally.
Keeping the browser-window open and simply switching between dev tools opened or closed gives the same behaviour.
Anyone can help me? Much appreciated!
This is my first stackoverflow question and I'm still very new to programming, I have a bit over a year of experience. Remarks on my 'asking questions'-skills are welcome.
Ok thanks to wOxxOm's comment I've found a workaround. So the problem was related to what window was focused on. I've added a piece of code in the catch-block to show an alert on a successfully opened popup (if there is one) :
try {
Popups[i].focus();
} catch (e) {
if (!popupBlockingErrorShown) {
if (Popups[i - 1]) { //there is a previous popup and it's been focused on.
Popups[i - 1].alert(UIMessages[33]); //show alert on opened popup.
popupBlockingErrorShown = true;
}
else {
alert(UIMessages[33]);
popupBlockingErrorShown = true;
}
}
}
Thanks #wOxxOm !
We have a Chrome extension download button on our site.
When you click it, it opens a popup that says 'Add extension', 'Cancel' etc.
http://i.imgur.com/RFuts0E.png
The image shows the popup I'm referring to.
It works fine, except for the cancel button opens a new tab and takes you to the plugins chrome store page.
I have no idea why it does this, or how to just get it to cancel.
The js:
chrome.webstore.install(webStoreURL, () => null, (error, errorCode) => {
window.open(PLUGIN_LINKS.Chrome, '_blank');
});
Any help is much appreciated.
Well, you indiscriminately try to open the Webstore page on "error". In fact, user clicking Cancel is one of many "error" conditions.
You need to analyze the errorCode to filter that out.
chrome.webstore.install(webStoreURL, () => null, (error, errorCode) => {
if (errorCode !== "userCanceled") {
window.open(PLUGIN_LINKS.Chrome, '_blank');
}
});
Note: as is obvious from the error code list, there are many other conditions that make opening the Web Store page useless. You should re-think this logic.
Subject
I am creating a chrome extension that requires me to send a message from my event page to a content script that is running on a specific frame
The message passing operation is invoked when a context menu option is clicked. Said option is only available when the element in focus is categorized as editable by the chrome.contextMenus API. I need to send it to the innermost frame in which the element is contained. (so I can modify its contents by accessing the document.activeElement object)
As of Chrome 41, you are able to send a message to a specific frame by filling the value of the frameID parameter of the options argument to the chrome.tabs.sendMessage() function.
However, Chrome 41 is currently in beta, so I obviously cant expect this feature to be compatible with my users' browsers.
So, I planned of sending a message to all of the frames in the tab (by registering listeners on a content script that had the all_frames property set to true) . Once inside the content script I could check to see if this was the right frame or not by comparing the value of window.location.href with the value I am expecting.
Problem
It appears as If I had a misconception about the way that either event listeners or message passing works. The documentation makes it pretty clear that chrome.tabs.sendMessage() is supposed to send a message to every frame in the tab, but it appears as if there can only be a single chrome.runtime.onMessage() event listener invoked per message, even if there are many listeners registered. Which one actually gets invoked appears to be somehow dictated by the initial loading of the page.
This can be demonstrated with a simplified version of my extension:
manifest.json:
{
"manifest_version":2,
"name":"Demo",
"description":"This is a demonstration",
"version":"1.0",
"permissions":[
"<all_urls>",
"contextMenus"
],
"background": {
"page":"background.html",
"persistent":false
},
"content_scripts":[{
"matches":["<all_urls>"],
"js":["content.js"],
"all_frames":true
}]
}
background.html:
<!DOCTYPE text/html>
<html>
<head>
<textarea id="temp"></textarea>
<script src="event.js"></script>
</head>
<body>
</body>
</html>
event.js:
chrome.contextMenus.onClicked.addListener(requestHandler);
chrome.contextMenus.create({
"title":"Click Me!!",
"contexts":["editable"],
"id":"1"
});
function requestHandler(info, tab)
{
chrome.tabs.sendMessage(tab.id, {"destination":info.frameUrl});
//this should get sent to every frame in the tab
}
content.js:
chrome.runtime.onMessage.addListener(handleRequest);
alert("Hi, i'm: " + window.location.host);
function handleRequest(message)
{
alert("You tried to send a message to: " + message.destination);
alert("I am: " + window.location.href);
}
If you visit a page with many frames, like youtube you should notice the following behavior:
You get many alerts upon the initial loading of the page, indicating that there are many frames being loaded (all with listeners)
When you click the context menu option, only a single alert pops up, indicating that only a single frame received the message
The frame that receives the message remains constant throughout multiple clicks of the context option, but is likely to change when you refresh the page. This indicates that the order in which the frames are initially loaded determines which frame is going to get your message.
So, how can I assure that the frame I am trying to talk with actually gets my message, without resorting to the frameID option that's only available in chrome 41?
At first I thought I could send a response back from the content script, indicating whether or not the message went to the right place. I could just keep doing this in a while loop in the event page until I got back a message telling me to stop, but like I said earlier, the message always seems to go to the same frame until the page is refreshed, so this approach does nothing for me.
Additional Details
Something else I have noticed is that if there are two frames on a page with the same origin, like plus.google.com for example, both frames will respond to the message, if that is the frame set that the message happened to get delivered to. So, the recipient seems to be based on origin rather than by some unique frame ID.
Here is a link to a video I took of the phenomena I am speaking of:
https://www.youtube.com/watch?v=WVz8zBVqgIw&feature=youtu.be
Notice that I got alerts initially from: youtube.com, accounts.google.com, plus.google.com and client6.google.com, but only client6 got my message
Your chrome.runtime.onMessage event listener calls alert. This method blocks the runtime until the dialog is closed. For some reason, this also prevents Chrome from correctly triggering the onMessage events in other frames (reported as crbug.com/456482).
A work-around is to use console.log for debugging instead of alert, or wrap the code within setTimeout to asynchronously process the onMessage event. E.g.
chrome.runtime.onMessage.addListener(function(message) {
setTimeout(function() {
alert('Message: ' + message);
});
});
I have written a script that allows a customer to log in, and download their contract in PDF.
We want the contract PDF to open in a popup, but are experiencing problems with customers who don't understand the basics of web browsers...
Basically, the customer logs in and a link is generated for their contract. The link is bound through jQuery's live event handler, that takes the request, sends it to an AJAX logging function then opens the PDF via window.open.
Since it is a user's action that opens the window, I can only think that because it goes through 2 other functions first, it is making the pop-up blocker kick in.
Does anybody have any better ideas?
My code is all over the place, in differnt namespaces, so I hope you guys can figure it all out:
Generate the link in a call back function, if the customer's credentials are correct:
$("#pdfLinks").prepend("<span><a href='#' id='pdfLink'><img src='img/btnDownloadPdf.png' alt='Downdload PDF' /><br>Download Adobe © PDF<\/a><\/span>");
$("#pdfLink").live('click', function() {
UI.showWorkingDialog();
net.tssol.contract.log(contractId['contract'], "DOWNLOAD_PDF", lead);
});
$("#pdfLinks").prepend("<h5>Adobe PDF<\/h5>");
the tssol.log function:
log: function(contract, method, lead) {
$.post("log.php", { lead: lead,
method: method},
function(log) {
if (log['success'] == true) {
if (method == "DOWNLOAD_PDF") {
// change to window.open for popup
window.open("http://oururl.net/public_html/viewPdf.php?verify=" + contract, '', 'scrollbars=1,menubar=0,height=600,width=800,resizable=1,toolbar=0,location=0,status=0');
Let me know if you guys see any way to make the user experience better.
Thanks
Maybe you can provide a HTML Version of the contract in a popup and add a "Download PDF" Button at the bottom of the popup content?
But in general you shouldnt use popups since they are often blocked by the web browsers and are in users head synced with trash and viagra-advertising.. you know what I mean ;)
I would do a jQuery Lightbox-like popup inside the website with the HTML-Contract, and optionally offer a PDF Download Button!
Have a look at this one: http://fancybox.net/
I am using a Facebook login method in my code on page load, but when I execute this code, the pop-up blocker closes the Facebook permission window.
How can I open this window with Javascript without needing to make an exception in the pop-up blocker?
Below is my code:
FB.login(function(response)
{
if(response.session!=null)
{
window.location.href='http://example.com';
}
},
{ perms: 'email,user_birthday,publish_stream' });
You can do something like -
var uri = encodeURI('http://example.com');
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
window.location.href=uri;
} else {
window.location = encodeURI("https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri="+uri+"&response_type=token");
}
This will just redirect directly instead of opening a pop-up
This is specifically denied in the documentation:
"You should only call this on a user event as it opens a popup. Most browsers block popups, unless they were initiated from a user event, such as a click on a button or a link."
It's also simply poor UX.
There'd be no point in popup blockers existing if you could just code around them. You'll either need to find a method that doesn't use a popup or require some user interaction with the browser to open the popup.
Yeah you need to call it with a user event, but strictly the onclick event, not any other:
Login <!-- works -->
Login <!-- doesnt work -->
Login <!-- doesnt work -->
If you try to open a popup automatically then there is a high possibility that popup blockers will become activated, as far as I know, it has to be based on some User action, for example click of a button. Try to execute this code on click of a button, it should work.