Can background page use window.location - google-chrome-extension

I am trying to create chrome extension that will scrap data from my webpage and then will display it in browser action window. I wanted to use background page for this, cause if i understand extensions correctly, it is only element capable of non-stop working, without need of visible tab.
The problem is, the script i wrote for background.js doesn't work properly, when i use background.js:
var location = window.location.href = 'http://localhost/index.php';
console.log(location);
manifest.json:
"background": {
"scripts": ["src/background/background.js"]
},
The answer i get is chrome-extension://some_random_text/_generated_background_page.html.
It is possible to use background pages to navigate to my webpage, then fill some forms and scrap data for later use?

This is an old question, but I recently wanted to do exactly the same.
So I'll provide an answer for others who are interested.
Setting window.location still does not work in Chrome52.
There is a workaround though. You can first fetch the web page with fetch(), and then use document.write to set the content.
This works fine, and you can then query the document and do everything you want with it.
Here is an example. (Note that I'm using the fetch API, arrow functions and LET, which all work fine now in Chrome52).
fetch("http://cnn.com").then((resp) => {
return resp.text();
}).then((html) => {
document.open("text/html");
document.write(html);
document.close();
// IMPORTANT: need to use setTimeout because chrome takes a little
// while to update the document.
setTimeout(function() {
let allLinks = document.querySelectorAll('a');
// Do something with the links.
}, 250);
});

A chrome extension has two main parts, the extension process and the browser itself. The Background Page works on the extension process. It does not have direct access and information about your webpages.
To have scripts working non-stop on your webpages, you will need to use Content Scripts.
You can then communicate between your Content Script and your Background Page using messages
contentScript.js
var location = window.location.href = 'http://localhost/index.php';
chrome.runtime.sendMessage({location: location}, function(response) {});
background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(request.location);
});

Related

How would I make a chrome extension to block each tab's favicons?

I'm trying to replace all favicons with a Chrome extension with some Javascript. In order to do that I need to find the dom element that contains the favicon.
On most websites I can do something similar to this:
document.querySelector('link[rel="icon"]').href = "//data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="
However on some websites such as apple.com, I can't figure out the dom element that contains the favicon by just viewing the page source, how would I go about blocking the favicon in that case?
I realized I was going about this all wrong. Instead of trying to replace the html element after the page was loaded, I should just block the network request which fetches the favicon.
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
return {cancel: ["favicon.ico", "favicon"].includes(details.url.split('/').pop().split('?')[0].split('#')[0]) };
},
{urls: ["<all_urls>"]},
["blocking"]);

chrome.extension.onMessage.addListener Cannot read property 'onMessage' of undefined

In the background.html:
chrome.tabs.query({active:true, currentWindow:true},function(tabs){
chrome.tabs.sendMessage(tabs[0].id,"target.js");
});
In the content.js:
chrome.extension.onMessage.addListener(function(msg,sender,sendResponse){
if (msg == "target.js"){
extensionID = sender.id;
}
});
However, it doesn't work;
Uncaught TypeError: Cannot read property 'onMessage' of undefined
How to make it right?
You said "content.js is a content script and it is injected to the current tab by another content script.".
Herein lies your problem. Injected scripts are executed in the context of a page (as if they were created by the page itself), and therefore they have no access to any of the Chrome extension APIs.
You could use a custom event or postMessage to communicate between the page and your content script, which in turn communicates with the background page.
For instance, see this basic example:
// Injected script script
addEventListener('message', function(event) {
if (event.data && event.data.extensionMessage) {
alert(event.data.extensionMessage);
}
});
// Content script which injects the script:
chrome.extension.onMessage.addListener(function(message) {
postMessage({extensionMessage: message}, '*');
});
I think that you want to use content.js as a real content script though, rather than an injected script. If you want to know the differences between injected scripts and content scripts, see Chrome extension code vs Content scripts vs Injected scripts.
It looks like you're trying to do some action to the current tab. Are you sure you need a message to do that? I'm assuming that background.html is your extension's background page and content.js is your content script. Now I skip the background.html page and simply run a javascript file for my background page. My manifest.json page would look something like this.
"background": {
"scripts": [ "js/background.js"]
},
In that page, I add message listeners to my background page since that's the only way I know to interact with the background.js file. In your case however, it's the background page that doing the action therefore you could use the chrome.tab method to modify the current tab directly. Instead of onMessage, you may try something executeScript where the InjectDetails is the javascript or whatever you want to execute.
chrome.tabs.query({active:true, currentWindow:true},function(tabs){
chrome.tabs.executeScript(tabs[0].id, InjectDetails);
});
See more on that HERE.

Chrome Extension that copies image URL on click

I'm brand new to making Chrome Extensions and have done the simple tutorials, but I'm having trouble finding what I need. I want the extension to allow a user to chose an image on a webpage, and then copy the URL for that image into the extension. Can anyone help me out? I'm sure if I see an example I'd get a better grasp on how extensions can interact with a page.
From what I understand of your question, I'd say you want to create a context menu item that shows up when you right-click an image. For example, in your background script, use:
chrome.contextMenus.create({
title: "Use URL of image somehow",
contexts:["image"],
onclick: function(info) {
handleImageURL(info.srcUrl);
}
});
function handleImageURL(url) {
// now do something with the URL string in the background page
}
This will add a context menu item that shows up on all pages, but only when you right-click on images. When the user selects it, the onclick handler of the menu item fires handleImageURL with the URL of the image as the argument. The URL can be processed in any way you like, e.g., saved in a localStorage list, sent to a server via Ajax, or passed in a message to a listening content script in the current tab.
EDIT with alternative:
You might want a content script that gets injected into every page. The script could bind an event listener to every image element at load time:
// in my_content_script.js...
var imgs = document.getElementsByTagName("img");
for(var i = 0, i < imgs.length; ++i) {
imgs[i].addEventListener("click", function() {
alert(this.src);
// do things with the image URL, this.src
});
}
To inject it into all subdomains of example.com, your manifest would include:
...
"content_scripts": {
"matches":["*://*.example.com/*"],
"scripts":["my_content_script.js"]
},
...
Note that this pure-JS solution doesn't attach listeners to images dynamically added after load time. To do that in your content script with jQuery, use:
$(document).on("click", " img", function() {
alert(this.src);
});
And add your jQuery file name to the scripts array in your manifest, next to my_content_script.js.
Based on this Google Chrome Extension sample:
var images = [].slice.apply(document.getElementsByTagName('img'));
var imageURLs = images.map(function(image) {
return image.src;
});
chrome.extension.sendRequest(images);
For a more detailed example (e.g. how to handle the request), you can check out this extension I wrote called Image Downloader

Inject chrome browser extension content script based on URL

I'd like to have my background page watch the URL and call chrome.tabs.executeScript on certain URLs. What API should I call to watch the URL in such a manner?
chrome.tabs.onUpdated.addListener can be used to detect tab loads. This will not detect navigation within frames though:
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
if (info.status === 'complete' && /some_reg_ex_pattern/.test(tab.url)) {
// ...
}
});
For this purpose, you'd better use a content script, with all_frames set to true. Within the content script, you can inject code using the methods as described in this answer. Then use the page's location object to filter URLs.

Chrome Tab Extensions: getCurrent vs. getSelected?

I'm writing a Chrome extension. As part of the extension, I want to get the URL of the tab that the extension was called from. What's the difference between using:
chrome.tabs.getSelected(null, function(tab) { var myTabUrl = tab.url; });
and
chrome.tabs.getCurrent(function(tab) { var myTabUrl = tab.url; });
?
Method chrome.tabs.getSelected has been deprecated. You should use chrome.tabs.query instead now.
You can't find the official doc for obsolete method chrome.tabs.getSelected. Here is the doc for method chrome.tabs.query.
getCurrent should be what you need, getSelected is a tab that is currently selected in a browser. When they could be different - maybe your extension runs some background cronjob in tabs, so that tab could be not currently selected by a user.
Ok I got it all wrong apparently. getCurrent should be used only inside extension's own pages that have a tab associated with them (options.html for example), you can't use it from a background or popup page. getSelected is a tab that is currently selected in a browser.
As to your original question - you probably need neither of those two. If you are sending a request from a content script to a background page, then the tab this request is being made from is passed as a sender parameter.
For those who is looking for working example of chrome.tabs.query instead of deprecated chrome.tabs.getSelected:
chrome.tabs.query({
active: true,
lastFocusedWindow: true
}, function (tabs) {
var myTabUrl = tabs[0].url;
});

Resources