Chrome extension, Javascript: getting URL from address bar - javascript

I have an extension that I am working on that has a "pop-up" putton on the bar,
I visit a site (for example google.com) the button is pressed, I run this code in popup.html:
window.addEventListener("load", windowLoaded, false);
function windowLoaded() {
chrome.tabs.getSelected(null, function(tab) {
localStorage['url_in_address_bar']=tab.url;
});
}
but instead of saving the google address, it saves it's own address like this: "chrome://extensions/".
How do I get it to save the last address instead of itself?

Your code shows the problem. getSelected returns the tab as a callback, which means the callback is executed when Chrome has found the selected tab. This is asynchronous, and is executed later:
window.addEventListener("load", windowLoaded, false);
function windowLoaded() {
// 1) request selected tab
chrome.tabs.getSelected(null, function(tab) {
localStorage['url_in_address_bar']=tab.url; // 3) selected tab is stored
});
}
// 2) a tab is created
var saved_email = localStorage['blocker_user_email'];
if (saved_email === undefined || saved_email == "a#a.com")
{
//self.close();
chrome.tabs.create({url: '0_register.html'});
} else{
// self.close();
chrome.tabs.create({url: '1_options.html'});
}
You could solve it by putting the second part of your code into the callback function:
window.addEventListener("load", windowLoaded, false);
function windowLoaded() {
chrome.tabs.getSelected(null, function(tab) {
localStorage['url_in_address_bar']=tab.url;
var saved_email = localStorage['blocker_user_email'];
if (saved_email === undefined || saved_email == "a#a.com")
{
//self.close();
chrome.tabs.create({url: '0_register.html'});
} else{
// self.close();
chrome.tabs.create({url: '1_options.html'});
}
});
}
A callback function is a function you provide as an argument to another function (e.g. getSelected). When that other function has completed its task (e.g. find selected tab), it will execute the provided function. In the meantime, however, the code coming after the request will be executed regularly.

Related

JavaScript callback / async problem? Background script of Chrome Extension stops function before finishing

I am trying to create a small crawler as a chrome extension. How it works is:
Open new window or tab.
Perform a search for Google / Google News / YouTube with given keywords.
Store information of the results in a small database
I first created and tested the functions with a popup.html. There it works perfectly.You click on a button and all pages are visited and the results are stored in a database. But I want to start the program without clicking anything first. That's why I migrated it to background.js. There it also works, but only if the Service Worker / DevTool console is open. Only then it runs completely.
I would be grateful for any helpful answer.
const keywords = [
"Keyword1",
"Keyword2",
// ...
"Keyword13"
];
chrome.runtime.onStartup.addListener(() => {
chrome.tabs.onUpdated.addListener(loadingWindow);
openWindow();
});
// Opens new Window or Tab with the correct URL
function openWindow() {
chrome.tabs.onUpdated.addListener(loadingWindow);
if (runs == 0) {
chrome.windows.create({ url: getUrl(keywords[runs]), type: "normal" }, newWindow => {
window_id = newWindow.id;
});
} else {
chrome.tabs.update(tab_id, { url: getUrl(keywords[runs]) });
}
}
// Wait to load the new tab
function loadingWindow(tabId, changeInfo, tab) {
if (changeInfo.status === 'complete' && tab.status == 'complete' && tab.windowId == window_id) {
tab_id = tabId;
console.log(tab.windowId);
chrome.tabs.onUpdated.removeListener(loadingWindow);
chrome.tabs.sendMessage(tab.id, { text: source }, doStuffWithDom);
}
};
// Get information from content script -> payload and then send to database
function doStuffWithDom(domContent) {
let payload = {... }
var data = new FormData();
data.append("json", JSON.stringify(payload));
fetch(".../store.php", { method: "POST", body: data });
crawlDone();
}
// open new window / tab or close the open window
function crawlDone() {
runs++;
if (runs < keywords.length) {
openWindow();
} else if (runs == keywords.length) {
chrome.windows.remove(window_id);
}
};
I switched to Manifest version 2. Then I could include the Background.js via the Background.html, which also runs to the end.

chrome.runtime.onMessage listener is never fired

I'm trying to set a badge text specific for each tab in Chrome.
I've followed along with this answer https://stackoverflow.com/a/32168534/8126260 to do so, though the chrome.runtime.onMessage event handler is never being fired.
// tab specific badges https://stackoverflow.com/questions/32168449/how-can-i-get-different-badge-value-for-every-tab-on-chrome
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
console.log('runtime message');
if (message.badgeText) {
console.log('runtime message with badge text');
chrome.tabs.get(sender.tab.id, function(tab) {
if (chrome.runtime.lastError) {
return; // the prerendered tab has been nuked, happens in omnibox search
}
if (tab.index >= 0) { // tab is visible
chrome.browserAction.setBadgeText({tabId:tab.id, text:message.badgeText});
console.log('set message');
} else { // prerendered tab, invisible yet, happens quite rarely
var tabId = sender.tab.id, text = message.badgeText;
chrome.webNavigation.onCommitted.addListener(function update(details) {
if (details.tabId == tabId) {
chrome.browserAction.setBadgeText({tabId: tabId, text: text});
chrome.webNavigation.onCommitted.removeListener(update);
}
});
}
});
}
});
// block outgoing requests for help widgets
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
//send message
console.log('send message');
chrome.runtime.sendMessage({badgeText: "HELP"});
if (isDisabled) {
return { cancel: false } // this should return from the function (details) level
} else {
return { cancel: true }
}
},
{urls: [
"a bunch of urls irrelevant to this question"
]},
["blocking"]);
(the entire source code is on https://github.com/bcye/Hello-Goodbye)
Looking into the console of my background script, send message appears, meaning that chrome.runtime.sendMessage({badgeText: "HELP"}); should have been executed.
None of the console.log statements in the onMessage listener get executed though.
Solved it, as #wOxxOm said this is impossible.
Though webRequest passes a tabId in the details dictionary.
This can be used to replicate that.

Chrome extension message passing & order of execution [duplicate]

This question already has an answer here:
Clipboard Copy / Paste on Content script (Chrome Extension)
(1 answer)
Closed 6 years ago.
Quick summary
The code below is a file called popup.js. It listens for a click, and sends a message to background.js. Background.js executes another script, and a variable is created.
I somehow need to pass this variable back to popup.js, and continue within the userHasClicked function. The way it is now the response I get is "undefined", and there's nowhere to go from there.
var theParent = document.querySelector("#MENY");
theParent.addEventListener("click", userHasClicked, false);
function userHasClicked(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
chrome.runtime.sendMessage({type: "ResponseType", directive: clickedItem}, function(response) {
console.log(response);
this.close();
});
};
e.stopPropagation();
}
Routine:
User clicks on an option in popup.html
Event("click") -> sendmessage("type of click")
background.js listens for the message, and executes content.js
content.js creates the variable and can send it back to anyone who listens.
The problem:
The variable must come as a response argument to step 2 (within eventloop)
Save the response as variable.
document.execCommand("copy").
Done
This code below is the relevant part of background.js.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.type) {
case "ResponseType":
var LoggType = request.directive;
console.log(LoggType)
chrome.tabs.executeScript(null, {
code: 'var LoggType = "'+LoggType+'";'
}, function() {
chrome.tabs.executeScript(null, {file:"content.js"});
});
chrome.runtime.onMessage.addListener(function(req, snd, sndRes) {
if (req.type = "LogIsGenerated") {
var Logg = req.directive;
console.log(Logg);
} sndRes({});
});
if (typeof Logg !== "undefined") {
alert("Feedback from content.js received");
sendResponse({type: "FinalVar", directive: Logg});
}
else {
alert("No feedback received");
sendResponse({});
};
break};
return true;
}
);
content.js ends with this line.
chrome.extension.sendMessage({type: "LogIsGenerated", directive: Logg});
Logg is the variable containing the text string I want to add to the clipboard.
At the moment this the code below alerts for No feedback received.
chrome.runtime.onMessage.addListener(function(req, snd, sndRes) {
if (req.type = "LogIsGenerated") {
var Logg = req.directive;
console.log(Logg);
} sndRes({});
});
if (typeof Logg !== "undefined") {
alert("Feedback from content.js received");
sendResponse({type: "FinalVar", directive: Logg});
}
else {
alert("No feedback received");
sendResponse({});
};
Rob W presented a solution here: Background script can write to clipboard in a very simple manner
Worked excellently.

JavaScript location redirect stalls AJAX call on Chrome

This is an issue I'm facing only on Chrome.
Code snippets -
// Bind methods to global AJAX events
jQuery(document).bind({
ajaxStart : function() {
showWaitMessage(); // this is where it hangs
},
ajaxStop : function() {
hideWaitMessage();
},
ajaxError : function(jqXHR, exception) {
// error handling
}
});
The location redirect -
var href = "downloadPack?clientName="+clientName+"&clientID="+clientID+"&fundName="+fundName+"&fundID="+fundID+"&navDate="+navDate+"&KD="+KD+"&status="+status;
//setTimeout(function(){document.location.href = href;}, 500);
//window.location.href = href;
jQuery(location).attr('href', href); // Have tried the above two lines too (same issue)
The AJAX call -
function getExceptions() {
jQuery.ajax({url:"exceptions",success:function(result){
jQuery('#subApp').html(result);
document.getElementById("subLink1").className = "";
document.getElementById("subLink2").className = "selected";
document.getElementById("subLink3").className = "last_item";
if(jQuery("#fund").val() == 'all')
jQuery('#fund').val(jQuery('#fund option').filter(function() { return jQuery(this).html() == selectedFund;}).val());
jQuery('#fund option[value="all"]').prop('disabled', true);
getNavDates(0);
}});
}
The loaction redirect is not used to go to a different page, but to trigger a download.
This is when I face the problem in Chrome-
Click the download link(location redirect).
Call the AJAX function.
AJAX call hangs at showWaitMessage();
Download goes on as usual.
Note: Everything works fine on other browsers. The AJAX call on Chrome also works fine if I do that before hitting the download link.
There is a workaround for this problem – use hidden iframe for downloading instead of current window. Just define this simple function:
var $idown; // Keep it outside of the function, so it's initialized once.
function downloadURL(url) {
if ($idown) {
$idown.attr('src', url);
} else {
$idown = $('<iframe>', { id: 'idown', src: url }).hide().appendTo('body');
}
}
And replace your line:
jQuery(location).attr('href', href);
With:
downloadURL(href);

Firefox extension: run when page loaded

I'm trying to write firefox extension which will run when a (specific) page is loaded (it will be same key words replace).
I write code like:
window.addEventListener("load", function() maApp.init(); }, false);
var maApp= {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", maApp.onPageLoad, true);
var messagepane = document.getElementById("messagepane"); // mail
if(messagepane)
messagepane.addEventListener("load", function(event) { maApp.onPageLoad(event); }, true);
},
onPageLoad: function() {
alert("test);
doSomething();
}
};
But onPageLoad is never run... no alert... Can somebody please tell me what I'm doing wrong?
First some words on getting the browser element. In Firefox this element has ID content, not appcontent. Still, the recommended way of getting it is the window.gBrowser variable. In Thunderbird 5 the ID of the browser element changed so your code will stop working - rather than going by ID you should use window.messageContent variable which will work both in the current and future versions. Together you get:
var browser = null;
if ("gBrowser" in window)
browser = window.gBrowser; // Firefox and SeaMonkey Browser
else if ("messageContent" in window)
browser = window.messageContent; // Thunderbird
else if ("getMessageBrowser" in window)
browser = window.getMessageBrowser(); // SeaMonkey Mail
if (browser)
...
Now about listening to page loads, the recommended approach here is progress listeners - see https://developer.mozilla.org/en/Code_snippets/Progress_Listeners. You attach a progress listener to the browser and look for state changes:
onStateChange: function(aWebProgress, aRequest, aFlag, aStatus)
{
if ((aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP) &&
(aFlag & Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW))
{
// A window finished loading
doSomething(aWebProgress.DOMWindow);
}
}
The accepted answer is outdated. The solution using the WebExtensions API would be
browser.tabs.onUpdated.addListener(function(tabId, changeInfo) {
if (changeInfo.status == "complete") {
//add your script
}
})
browser.tabs.onUpdated.addListener Listens to events within the Tab (Reference)
(changeInfo.status == "complete") filters the right event and executes the commands within the if statement.

Categories

Resources