I would know what is the difference between those three lines of code :
console.log("");
document.write("");
alert(""); (or windows.alert("");)
console.log("") outputs whatever is passed as the parameter.
e.g. console.log("test") will output "test" to your console
document.write("") adds whatever you want to html.
e.g. document.write("<p>paragraph</p>") will add a new paragraph to a document
alert("") is a popup alert.
console.log('foo');
will write 'foo' in your debugging console. You can access it via F12 on most browsers or right click on your page and inspect. You should see a "console" panel on the debugging window.
Be careful of what information you dump, it will be shown to every one browsing the page. Some browsers may not like those logs and you could encounter errors on production websites if you forget to remove them.
document.write('foo');
will append 'foo' to the DOM of your current page. This statement is not to be used for debugging purpose.
alert('foo');
will display a popup window to your browser with a single button to close it. "foo" will be the text displayed on the popup. You can use this method to send very important information to the person browsing the page, but try not to abuse of them as they "block" the visitor by requiring to dismiss the modal before doing anything else.
Developers use console.log() for logging useful info.
document.write modifies what user sees in the browser by adding additional content to DOM.
Alerts are used to alert end users who access the web page.
console.log() is used by developers to just debug their code by printing the value inside console.log() in their console......
document.write() is used to add something to the webpage
Related
So, I've got a situation where I want a background and content script to be run everytime the browser extension icon is clicked. The ideal behaviour is that extension icon is clicked, the script runs, and the popup will open, displaying the data that was grabbed by the script (but this should happen quickly, the script runs and gets the data very fast). Since chrome.pageAction.onClicked will not work if there is a default_popup defined in manifest.json, I think this leaves me with two options:
Use default_popup and figure out that the extension icon has been clicked some other way. I found this solution in another stack overflow post, but the workaround is to use default_popup: "popup.html", and then the popup.js that is defined in popup.html will send a message saying that the icon has been clicked, then when background.js receives this message, it executes the script. I implemented this idea and it worked... kinda. The trouble is, the popup will always come up before the script is fully executed, so you can't actually display the data grabbed by the script in the popup until the next click. I'm not sure there's any way to get the behaviour I desire using this method, so on to the next:
The other solution I can possible think of is to use onClicked, and then make the popup come up some other way, besides using default_popup in manifest.json. I'm also not sure if this is possible, I have looked on stackoverflow and haven't found anything similar.
Is the second method possible? Can the first method work somehow?
Your option #1 is correct, I think all that is needed is a loading screen when the user first sees the popup, and add some code that updates the popup as soon as it hears from the backend. Might need to see some code to better help there.
Option #2 will not really work, unless you opened the popup in a new tab (or just made it a whole new HTML page). I say this because there is a note here from the Chrome Dev team they will not support opening a popup unless it is from a user gesture -- https://stackoverflow.com/a/10484764/4875295.
If you wanted to go that route it would probably look something like:
Delete from your manifest.json browser_action.default_popup
In your background script add something like:
chrome.browserAction.onClicked.addListener(() => {
const data = dataMaker();
chrome.tabs.create({
url: `${chrome.runtime.getURL("app.html")}?data=${data}`
});
});
Then in your html file have some JS that reads the query string and updates the page accordingly.
Though, that's a different approach than you asked for and I think your original route may still be the best bet (with some added JS around loading).
The problem
I've had this issue for months now, but the concept is pretty straightforward: I want to block some Malicious Site™ from programmatically opening tabs or popup windows.
With the chrome.tabs API, I can listen with onCreated when a new tab is created, and I can easily check who (i.e. which tab) opened that particular tab accessing the openerTabId property of the Tab object passed to the callback function.
Now, I would like to do the exact same thing when a new window is created: I would like to know which tab opened the window (if any, because it could have been opened by the user too), check its URL to see if it is the Malicious Site™, and act accordingly (i.e. block the popup). I tried doing it in the exact same way: request the array of tabs in the new window and check their openerTabId property, but unfortunately such property is not defined! I searched the documentation and Googled for hours, but sadly it looks like there's no simple way to check who opened a window.
A very clumsy solution
Stated the above, the only way I was able to do something even remotely close to what I really want, is the following:
Every time a new window is created, its ID is added to an array called windowWatchlist.
Every time a tab is updated (NB: updated, not created), a script is injected inside it to check its document.referrer, which should contain the URL of the site which opened the tab: if the referrer URL contains the address of the Malicious Site™ I want to block popups from, the window is then closed and removed from the windowWatchlist.
Every time a window is closed, if its ID is in the windowWatchlist, it gets removed from it.
Here's the code (which runs in my background.js script):
// Called on chrome.windows.onCreated
function watchPopupWindow(window) {
windowWatchlist.push(window.id);
console.log('Added window #' + window.id + ' to watchlist.');
}
// Called on chrome.windows.onRemoved
function unwatchPopupWindow(windowID) {
var index = windowWatchlist.indexOf(windowID);
// If the windowID is in the watchlist:
if (index != -1) {
// Remove it:
windowWatchlist.splice(index, 1);
console.log('Removed window #' + windowID + ' from watchlist.');
}
}
// Called on chrome.tabs.onUpdated
function blockPopupWindow(tabID, info, tab) {
// If this tab is in a window which is in the watchlist:
if (windowWatchlist.indexOf(tab.windowId) != -1 && info.url && info.url != 'about:blank') {
// Check the referrer of this tab:
chrome.tabs.executeScript(tabID, {code: 'document.referrer;'}, function(ref) {
// If the referrer is the malicious site to block:
if (ref && ref[0] && ref[0].indexOf("http://MALICIOUS-SITE.XXX") != -1) {
// Close the popup window:
chrome.windows.remove(tab.windowId, function() {
console.log('Blocked popup window #' + tab.windowId + '.');
if (chrome.runtime.lastError)
console.error(chrome.runtime.lastError.message);
});;
}
});
}
}
var windowWatchlist = [];
chrome.windows.onCreated.addListener(watchPopupWindow, {windowTypes: ['popup']});
chrome.windows.onRemoved.addListener(unwatchPopupWindow, {windowTypes: ['popup']});
chrome.tabs.onUpdated.addListener(blockPopupWindow);
Now, you may be wondering: why do you need all this mess only to check a referrer? Couldn't you just check the tabs contained in the window when the window is opened and check their referrer directly inside the callback of chrome.window.onCreated? That's a clever question, and the answer is simple: the problem is that I cannot check the referrer of the tabs right when they are created, because they almost always need some time to load, and the referrer isn't loaded until the page starts loading inside the tab. Therefore, I need to check when a tab is updated, see if its window is in my watchlist, and then check its referrer. This is why chrome.tabs.onUpdated is needed, since it fires its listeners whenever a tab changes state (e.g. tab.status changes from "loading" to "complete").
Why this solution doesn't work
The reason why I call this solution "clumsy" and the reason why it doesn't really work should be already clear to anyone with some experience of JavaScript and web developing: document.referrer isn't reliable at all, and is very often undefined or (in case of multiple redirects) not the right one. This makes my script fail about 90% of the times, because it is unable to determine whether the popup window was opened by the Malicious Site™ or not.
Moreover, the Malicious Site™ often opens popups with URL about:blank or no URL at all, and only when they are loaded, injects data into them, making them basically impossible to detect, even with chrome.tabs.onUpdated which doesn't fire any listener in this situation.
I could decide to block any popup with URL about:blank or undefined, and this is what I'm doing right now indeed, but is a pretty bad compromise, since that I end up closing popups opened by any site which uses this method, and not only the Malicious Site™ I want to block.
In conclusion
My question is simple, but I don't know about its solution: does anyone know any other more reliable method which could be used to detect which tab opened a new window? Nothing comes to my mind, maybe something could be possible using the chrome.webRequest API? I don't really know. For months I've been accepting the fact that a simple solution just wasn't possible, and helplessly waited for an update or something, but I never actually thought about asking here, because the problem looked above the competence of an average Chrome Extension programmer, but hopefully I was wrong.
UPDATE: The solution to inject a script inside the site and replace the window.open function with something else isn't viable: if an <iframe> is loaded without a src attribute, but with an already written DOM inside the srcdoc attribute, Chrome will not execute a content script inside it, even if the call to chrome.tabs.executeScript is made with allFrames: true, and even if the content script is declared inside the extension's manifest.
I came across the same problem and found the webNavigation.onCreatedNavigationTarget event that yields the source tab/frame id when a new window is opened.
Solution found from this post: Is it possible to determine a tab's opener within a Google Chrome extension?
Since you are already doing code injection this is what I would do.
Inject code to override window.open and have it window.postMessage to child window telling them who opened them. Also will need to inject code to listen to the effect of window.addEventListener('message', messageHandler) which will decided if they should window.close().
On second though I think I would just override window.open and not even open the child windows if you don't want to allow a give site to open windows.
Basically what i am trying to do was, whenever a user tries to close the current tab(when he was on my site), i want to display a pop up with three choices about why he was leaving and want to store that choice some where
So i have written the following in main.js which will be loaded through entire site pages
$(document).ready(function() {
// Before closing the current tab, ask user for a reason
$(window).on('beforeunload', function(event){
$('#load_choices_up').click();
event.stopPropagation();
event.preventDefault();
debugger;
});
});
So i have three issues with the above jquery code
*.This code was executing even when i click another link on the same page(I mean if i navigate to another page from current page), but i only want this code to run when the current tab/page was closed(about to close) completely, but not when navigating to another page on my site
*. After this line $('#load_choices_up').click() was executed, a choices pop up was opening as expected, but immediately the default processing of browser(that is closing functionality) was not being stopped with two lines event.stopPropagation(); and event.preventDefault();, i mean these two methods of stopping the behaviour is not working and the browser is closed, but i want to do some processing based on user choices input and then based on that i will close tab.
*. When i used return "Why do you want to leave the page", instead of choices pop up, the browser was displaying different message based on browser type like "You have unsaved changes" in chrome, and some different message in firefox, instead of displaying my custom message
So finally, why event.stopPropagation(); and event.preventDefault(); are not working ? and why i can't able to display my custom message ?
You can't prevent someone from closing the browser. This is for obvious security reasons. Imagine a spam-website preventing you from closing the website while pumping you full of god knows what.
You can at most pull one function like an alert() or a prompt. After a user closes them, the tab will close either way.
beforeUnload is also extremely short-timed. You won't be able to run massive scripts with it, as the user would probably close the tap before any script would run properly. (I tried it with an ajax call, didn't work)
So, even if you're able to get the options you want in there, the moment a user chooses one of the options, you're not going to be able to save it anywhere. Your script will never make it that far.
You can customize the "are you sure?" message like so:
$(document).ready(function() {
window.onbeforeunload = function(e) {
return 'Dialog text here.';
};
});
but again, you can only change the text. It's a browser's native functionality, and you cannot change it.
I have been looking for the answer to this question, but it only took me to the solution for debugging the extension itself, while I want to debug the webpage.
I want to create an extension that allows me to modify a particular web page (obviously only on my computer).
I have created a very simple script following the "activeTab" permission tutorial on the chrome developer's site, then I have made the following:
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
// No tabs or host permissions needed!
chrome.tabs.executeScript({
code:'
var oSwitchContainer = document.getElementById("norm");
console.log(oSwitchContainer.childNodes);
'
});
});
When I inspect the page I cannot see any console messages, however, I can change the content of that oSwitchContainer easily by modifying its innerHTML.
Is there any way to see the console logs of the page after I enable the extension?
You say that you found solutions to debug "the extension itself".
Take a look at the Architecture Overview.
What you refer to as "extension itself" is its background page, and that's where your browserAction.onClicked listener executes. If you execute console.log() statements from that code, it will go to the background page's console.
However, using chrome.tabs.executeScript, you pass code to be executed in the context1 of an open tab instead of executing it in the background page. All console.log() calls from that context go to the open page's own console - you should look there.
console.log("This will show in the background page console");
chrome.tabs.executeScript(
{ code: 'console.log("This will show in the current tab console");' }
);
1 To be precise, the extension creates an isolated context, but it still belongs to the open page. See Content Scripts documentation for more details.
I would like to put a link to a webpage in an alert dialog box so that I can give a more detailed description of how to fix the error that makes the dialog box get created.
How can I make the dialog box show something like this:
There was an error. Go to this page to fix it.
wwww.TheWebPageToFix.com
Thanks.
You can't. Alert boxes don't support html. You should display the error as part of the page, it's nicer than JS alerts anyway.
You can't - but here are some options:
window.open() - make your own dialog
Use prompt() and instruct the user to copy the url
Use JavaScript to just navigate them to the url directly (maybe after using confirm() to ask them)
Include a div on your page with a [FIX IT] button and unhide it
Use JavaScript to put a fix it URL into the user's clipboard (not recommended)
If you really wanted to, you could override the default behavior of the alert() function. Not saying you should do this.
Here's an example that uses the YUI library, but you don't have to use YUI to do it:
YUI-based alert box - replace your ugly JavaScript alert box
You could try asking them if they wish to visit via window.prompt:
if(window.prompt('Do you wish to visit the following website?','http://www.google.ca'))
location.href='http://www.google.ca/';
Also, Internet Explorer supports modal dialogs so you could try showing one of those:
if (window.showModalDialog)
window.showModalDialog("mypage.html","popup","dialogWidth:255px;dialogHeight:250px");
else
window.open("mypage.html","name","height=255,width=250,toolbar=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,modal=yes");
Or use window.open and put the link there.
Even if you could, alert() boxes are generally modal - so any page opened from one would have to open in a new window. Annoying!
alert("There was an error. Got to this page to fix it.\nwww.TheWebPageToFix.com");
That's the best you can do from a JavaScript alert(). Your alternative option is to try and open a new tiny window that looks like a dialog. With IE you can open it modal.