Chrome Extension: How to get current webpage url from background.html - javascript

From my knowledge it is not possible directly by getting tab.url (only possible in the popup.html) and doing message passing also requires that popup.html be open. Is there anyway to bypass this and get the current page url from background.html?
My best shot was with message passing, which I used this code in background.html
var bg = chrome.extension.getPopupPage();
var myURL = bg.myURL;
then in popup.html I had:
chrome.tabs.getSelected(null, function(tab) {
var myURL = tab.url;
})
Anyways the above does't work at all. Anybody know of a way to do this without having to actually open up the popup?

chrome.tabs.query is supported from background pages, of course as long as you have the tabs permission. This is the supported route as of Chrome 19.
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
var tab = tabs[0];
var url = tab.url;
});
Note that currentWindow is needed because it would otherwise return the active tab for every window. This should be guaranteed to only return one tab.
Of course, keep in mind that this is an asynchronous API – you can’t access any data it provides except from within the callback function. You can store values (such as url here) at a higher scope so another function can access it, but that will still only provide the correct result after the callback is executed.
(The below is my original answer kept for posterity – this method is no longer necessary, requires an always-running background page, and getSelected() is deprecated.)
First put this in background.html and make the myURL variable global:
var myURL = "about:blank"; // A default url just in case below code doesn't work
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { // onUpdated should fire when the selected tab is changed or a link is clicked
chrome.tabs.getSelected(null, function(tab) {
myURL = tab.url;
});
});
Then run this in popup.html when you want to get the page url:
chrome.extension.getBackgroundPage().myURL;
So if I were to make that appear inside the popup and I went to Google and clicked your page or browser action, I'll see http://google.com/webhp in the popup.

Upon seeing this post I felt that there should be a way to mark a discussion as "obsolete".
Reasons being...
This question needs to migrate to manifest v2 and...
The answers both are not working. I am using a select onchange and posting the current tab's url which is not working.
Might be these all worked in manifest v1.
My answer is ...
var myURL = "not set yet";
window.addEventListener('load', function () {
chrome.tabs.getSelected(null,function(tab){
myURL=tab.url;
});

This is a little more work but works like a charm...
I would use a content script; it's relatively simple & allows you to get any info from current page you might want. Have the background page "inject" the script into the current webpage to gather the info you need. The script then just passes it back to the background.
background.js:
// Icon is clicked and triggers content script to be injected into current webpage
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: 'inject.js' });
});
// Listens for message back from content script and then runs
chrome.runtime.onMessage.addListener(function (request) {
var URL = request.url;
});
inject.js (content script):
// Gathers up in the information that you need from webpage
var pageInfo = {
"url": window.location.href
};
// Sends the information back to background.js
chrome.runtime.sendMessage(pageInfo);
Hope this helps someone!

chrome.tabs.getSelected(null, function(tab) {
var myURL = tab.url;
});
I don not understand, the code above can be used in background page to get the current tab's url.

Related

Grab current URL from within extension?

For my Google Chrome extension, I need to grab the current URL. I know that, in regular JavaScript, I can just use this to get the link and host:
var hostname = window.location.hostname;
var url = window.location.href;
But how can I do that within an extension? I actually got it to work by using this as an example, but it seems a bit overkill for what I want to do. Is there a better way to get the current URL, maybe without injecting a script into the page?
You can use chrome.tabs.query() to get the current URL into a variable inside your extension code:
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function(tabs) {
var url = tabs[0].url;
});
Remember: the part of your code that'll use the url variable should be inside the (anonymous) callback function above, not elsewhere. Otherwise, you'll get an undefined value, as Chrome extension code is executed asynchronously.

javascript check which URL loaded and give notification

I'm trying to find a way in javascript to check which URL is loaded, then have a popup notifying the user to update their old bookmarket and have it redirect to the new location in a few seconds.
For example, the url maybe Http:\abc\myappage and I want to check if they are on the http:\abc site which if they are, the notification pops up and redirects them.
Currently I have a simple redirect to take them to the new site, but I never considered anyone that has an old bookmark which would never get updated if you don't inform them about the change.
Thanks.
You can access the current url from within JavaScript with window.location.
Using window.location you can access the current domain and path, then by setting window.location.href = 'your new site' after a few seconds or after some user interaction will cause the browser to navigate to the supplied url.
if(window.location.host === 'abc'){
alert('This url is no longer valid.');
window.location.href = 'http://abc/myappage
}
You can use window.location to get some information regarding the current url:
window.location.origin in the console on this current page, prints:
"http://stackoverflow.com"
Then you could run some JS logic to check against your other url and use alert() to crete the pop up.
working JSBIN: https://jsbin.com/gijola/edit?js,console
adding code:
function checker (url) {
var here = window.location.origin;
l(here);
if (here !== 'whatever you want to check') {
alert('please update your bookmark!!');
}
}

Phantomjs customHeaders referrer not detecting by javascript

I am trying to test a webpage which will detect referrer using document.referrer . I am using this code below
page = webpage.create();
page.customHeaders = {
"Referer" : "http://example.com"
};
but It's not working!! document.refferer never detect referrer, visit from phantomjs .
Note thatpage.customHeaders determines what HTTP headers phantom browser sends to the server, not the ones that are received by the browser, document.referrer returns the latter.
You may want to navigate to http://example.com first, then open the page you are after, preferably by dropping an <a href="http://localhost/MyApp"/> tag and then getting phantom to click it.
A note on usage, you also want to make sure the page is loaded before checking the document object.
Here is an example I wrote using CasperJS as it abstracts all the async and event handling functionality making the code more readable.. Ie:
// Step 1, Navigate to http://example.com and drop a link to your app
casper.start("http://example.com", function() {
this.evaluate(function() {
var link = document.createElement("A");
link.id = "the-button";
link.href= "http://localhost/MyApp";
document.body.appendChild(link);
});
});
// Step 2, pretend to click on link, evaluate referrer when loaded
casper.thenClick("a#the-button", function() {
// The page is now loaded
var referrer = this.evaluate(function() {return document.referrer; }
console.log(referrer)
});

Chrome extension regarding injected script + localstorage

I am puzzling my way through my first 'putting it all together' Chrome extension, I'll describe what I am trying to do and then how I have been going about it with some script excerpts:
I have an options.html page and an options.js script that lets the user set a url in a textfield -- this gets stored using localStorage.
function load_options() {
var repl_adurl = localStorage["repl_adurl"];
default_img.src = repl_adurl;
tf_default_ad.value = repl_adurl;
}
function save_options() {
var tf_ad = document.getElementById("tf_default_ad");
localStorage["repl_adurl"] = tf_ad.value;
}
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click', save_options);
});
document.addEventListener('DOMContentLoaded', load_options );
My contentscript injects a script 'myscript' into the page ( so it can have access to the img elements from the page's html )
var s = document.createElement('script');
s.src = chrome.extension.getURL("myscript.js");
console.log( s.src );
(document.head||document.documentElement).appendChild(s);
s.parentNode.removeChild(s);
myscript.js is supposed to somehow grab the local storage data and that determines how the image elements are manipulated.
I don't have any trouble grabbing the images from the html source, but I cannot seem to access the localStorage data. I realize it must have to do with the two scripts having different environments but I am unsure of how to overcome this issue -- as far as I know I need to have myscript.js injected from contentscript.js because contentscript.js doesn't have access to the html source.
Hopefully somebody here can suggest something I am missing.
Thank you, I appreciate any help you can offer!
-Andy
First of all: You do not need an injected script to access the page's DOM (<img> elements). The DOM is already available to the content script.
Content scripts cannot directly access the localStorage of the extension's process, you need to implement a communication channel between the background page and the content script in order to achieve this. Fortunately, Chrome offers a simple message passing API for this purpose.
I suggest to use the chrome.storage API instead of localStorage. The advantage of chrome.storage is that it's available to content scripts, which allows you to read/set values without a background page. Currently, your code looks quite manageable, so switching from the synchronous localStorage to the asynchronous chrome.storage API is doable.
Regardless of your choice, the content script's code has to read/write the preferences asynchronously:
// Example of preference name, used in the following two content script examples
var key = 'adurl';
// Example using message passing:
chrome.extension.sendMessage({type:'getPref',key:key}, function(result) {
// Do something with result
});
// Example using chrome.storage:
chrome.storage.local.get(key, function(items) {
var result = items[key];
// Do something with result
});
As you can see, there's hardly any difference between the two. However, to get the first to work, you also have to add more logic to the background page:
// Background page
chrome.extension.onMessage.addListener(function(message, sender, sendResponse) {
if (message.type === 'getPref') {
var result = localStorage.getItem(message.key);
sendResponse(result);
}
});
On the other hand, if you want to switch to chrome.storage, the logic in your options page has to be slightly rewritten, because the current code (using localStorage) is synchronous, while chrome.storage is asynchronous:
// Options page
function load_options() {
chrome.storage.local.get('repl_adurl', function(items) {
var repl_adurl = items.repl_adurl;
default_img.src = repl_adurl;
tf_default_ad.value = repl_adurl;
});
}
function save_options() {
var tf_ad = document.getElementById('tf_default_ad');
chrome.storage.local.set({
repl_adurl: tf_ad.value
});
}
Documentation
chrome.storage (method get, method set)
Message passing (note: this page uses chrome.runtime instead chrome.extension. For backwards-compatibility with Chrome 25-, use chrome.extension (example using both))
A simple and practical explanation of synchronous vs asynchronous ft. Chrome extensions

URL hashchange problems with ajax loading

I have a functional wordpress theme that loads content via ajax. One issue that I'm having though is that when pages are loaded directly the ajax script no longer works. For example the link structure works as follows, while on www.example.com and the about page link is clicked then the link becomes www.example.com/#/about. But when I directly load the standalone page www.example.com/about, the other links clicked from this page turn into www.example.com/about/#/otherlinks. I modified the code a little bit from this tutuorial http://www.deluxeblogtips.com/2010/05/how-to-ajaxify-wordpress-theme.html. Here is my code. Thanks for the help.
jQuery(document).ready(function($) {
var $mainContent = $("#container"),
siteUrl = "http://" + top.location.host.toString(),
url = '';
$(document).delegate("a[href^='"+siteUrl+"']:not([href*=/wp-admin/]):not([href*=/wp-login.php]):not([href$=/feed/]))", "click", function() {
location.hash = this.pathname;
return false;
});
$(window).bind('hashchange', function(){
url = window.location.hash.substring(1);
if (!url) {
return;
}
url = url + " #ajaxContent";
$mainContent.fadeOut(function() {
$mainContent.load(url,function(){
$mainContent.fadeIn();
});
});
});
$(window).trigger('hashchange');
});
The problem you are expressing is not easily solved. There are multiple factors at stake but it boils down to this :
Any changes to a URL will trigger a page reload
Only exception is if only the hash part of the URL changes
As you can tell there is no hash part in the URL www.example.com/about/. Consequently, this part cannot be changed by your script, or else it will trigger page reload.
Knowing about that fact, your script will only change the URL by adding a new hash part or modifying the existing one, while leaving alone the "pathname" part of the URL. And so you get URLs like www.example.com/about/#/otherlinks.
Now, from my point of view there are two ways to solve your problem.
First, there is an API that can modify the whole URL pathame without reload, but it's not available everywhere. Using this solution and falling back to classical page reload for older browser is the cleaner method.
Else, you can force the page reload just once to reset the URL to www.example.com/ and start off from a good basis. Here is the code to do so :
$(document).delegate("a[href^='"+siteUrl+"']:not([href*=/wp-admin/]):not([href*=/wp-login.php]):not([href$=/feed/]))", "click", function() {
location = location.assign('#' + this.pathname);
return false;
});
It should be noted that this script won't work if your site is not at the root of the pathname. So for it to work for www.example.com/mysite/, you will need changes in the regex.
Please let me know how it went.

Categories