Difficulties saving URL from Chrome tab (for Chrome extension) - javascript

I'm attempting to build a Chrome extension which will check (through a "link:URL" Google search) which sites link to the one that is currently open in the active tab. But my code fails to properly save the tab's URL into a variable. I have found similar questions (and their answers) here on stackoverflow and I understand it may have sth to do with the fact that js is asynchronous, but I wasn't able to make it work. Any hint(s) would be hugely appreciated. Thanks!
// this is the part that doesn't work
chrome.tabs.query({'active': true}, function (tabs) {
var query = tabs[0].url;
});
// this is the part that works just fine
chrome.browserAction.onClicked.addListener(function(activeTab)
{
var stemURL = "http://www.google.com/#q=link:";
chrome.tabs.create({ url: (stemURL + query) });
});
Here's how I set the permissions in the manifest, which should be right
"permissions": [
"tabs", "http://*/*", "https://*/*"
],

This is because when you declare your "query" variable, it only has scope within your callback function in chrome.tabs.query. Now, you could declare your variable at the top of your script to give it scope within the entire script:
var query;
chrome.tabs.query({'active': true}, function (tabs) {
query = tabs[0].url;
});
chrome.browserAction.onClicked.addListener(function(activeTab)
{
var stemURL = "http://www.google.com/#q=link:";
chrome.tabs.create({ url: (stemURL + query) });
});
...or you could use your activeTab variable that chrome.browserAction.onClick passes to you and grab the active tab's URL from that to ensure that you open the search results for the tab that the user was viewing when they clicked your extension's button, which would also have the added advantage of cutting out the first half of your code:
chrome.browserAction.onClicked.addListener(function(activeTab)
{
var stemURL = "http://www.google.com/#q=link:";
chrome.tabs.create({ url: (stemURL + activeTab.url) });
});
I would recommend the latter approach; it's faster, cleaner, and more reliable. Good luck!

Related

Open new tab from Chrome Extension Context Menu

UPDATE:
So because of the way my folder is structured, it looks like instead of chrome-extension://meajimhgfmioppbkoppphhkbcmapfngh/index.html it should be chrome-extension://meajimhgfmioppbkoppphhkbcmapfngh/html/index.html. When I type this in manually into the search bar it works but is still not working when I update my code to this:
chrome.contextMenus.onClicked.addListener(function (result) {
if (result['menuItemId'] === 'open-sesame') {
chrome.tabs.create({ 'url': chrome.extension.getURL("/html/index.html") }, function (tab) {
})
}
})
I have a chrome extension where users are presented my extension as a new tab. A new feature I am implementing is the ability to switch back to the default google search page and now users can access the extension from the browser action context menu. I referenced this answer when trying to come up with a solution.
I am now stuck at the contextMenu since when I click on it, I come up to the page where it says file could not be accessed.
background.js
chrome.contextMenus.create({
title: "Open",
contexts: ['browser_action'],
id: 'open-sesame',
})
chrome.contextMenus.onClicked.addListener(function (result) {
if (result['menuItemId'] === 'open-sesame') {
chrome.tabs.create({ 'url': chrome.extension.getURL("index.html") }, function (tab) {
})
}
})
The url that the new tab opens to is chrome-extension://meajimhgfmioppbkoppphhkbcmapfngh/index.html which seems like it would be correct to open my extension but it is still not working for whatever reason.
Folder Structure
html
index.html
js
background.js
css
style.css
Turns out I had to add the right file pathing to access my index.html and update the extension to get it to work.

How to get Chrome Extension's Options value in Extension? [duplicate]

I have an options page where the user can define certain options and it saves it in localStorage: options.html
Now, I also have a content script that needs to get the options that were defined in the options.html page, but when I try to access localStorage from the content script, it doesn't return the value from the options page.
How do I make my content script get values from localStorage, from the options page or even the background page?
Update 2016:
Google Chrome released the storage API: https://developer.chrome.com/docs/extensions/reference/storage/
It is pretty easy to use like the other Chrome APIs and you can use it from any page context within Chrome.
// Save it using the Chrome extension storage API.
chrome.storage.sync.set({'foo': 'hello', 'bar': 'hi'}, function() {
console.log('Settings saved');
});
// Read it using the storage API
chrome.storage.sync.get(['foo', 'bar'], function(items) {
message('Settings retrieved', items);
});
To use it, make sure you define it in the manifest:
"permissions": [
"storage"
],
There are methods to "remove", "clear", "getBytesInUse", and an event listener to listen for changed storage "onChanged"
Using native localStorage (old reply from 2011)
Content scripts run in the context of webpages, not extension pages. Therefore, if you're accessing localStorage from your contentscript, it will be the storage from that webpage, not the extension page storage.
Now, to let your content script to read your extension storage (where you set them from your options page), you need to use extension message passing.
The first thing you do is tell your content script to send a request to your extension to fetch some data, and that data can be your extension localStorage:
contentscript.js
chrome.runtime.sendMessage({method: "getStatus"}, function(response) {
console.log(response.status);
});
background.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.method == "getStatus")
sendResponse({status: localStorage['status']});
else
sendResponse({}); // snub them.
});
You can do an API around that to get generic localStorage data to your content script, or perhaps, get the whole localStorage array.
I hope that helped solve your problem.
To be fancy and generic ...
contentscript.js
chrome.runtime.sendMessage({method: "getLocalStorage", key: "status"}, function(response) {
console.log(response.data);
});
background.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.method == "getLocalStorage")
sendResponse({data: localStorage[request.key]});
else
sendResponse({}); // snub them.
});
Sometimes it may be better to use chrome.storage API. It's better then localStorage because you can:
store information from your content script without the need for
message passing between content script and extension;
store your data as JavaScript objects without serializing them to JSON (localStorage only stores strings).
Here's a simple code demonstrating the use of chrome.storage. Content script gets the url of visited page and timestamp and stores it, popup.js gets it from storage area.
content_script.js
(function () {
var visited = window.location.href;
var time = +new Date();
chrome.storage.sync.set({'visitedPages':{pageUrl:visited,time:time}}, function () {
console.log("Just visited",visited)
});
})();
popup.js
(function () {
chrome.storage.onChanged.addListener(function (changes,areaName) {
console.log("New item in storage",changes.visitedPages.newValue);
})
})();
"Changes" here is an object that contains old and new value for a given key. "AreaName" argument refers to name of storage area, either 'local', 'sync' or 'managed'.
Remember to declare storage permission in manifest.json.
manifest.json
...
"permissions": [
"storage"
],
...
Another option would be to use the chromestorage API. This allows storage of user data with optional syncing across sessions.
One downside is that it is asynchronous.
https://developer.chrome.com/extensions/storage.html
[For manifest v3]
You can execute a script that returns localstorage items from the webpage. This script can be executed from popup or background service worker.
Add this line in manifest.json:
"permissions": ["scripting"]
let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
// Execute script in the current tab
const fromPageLocalStore = await chrome.scripting.executeScript({
target: { tabId: tabId },
func: () => {
return JSON.stringify(localStorage)
}
})
const localStorageItems = JSON.parse(fromPageLocalStore[0].result)

Chrome extension and .click() loops using values from localStorage

I have made a Chrome extension to help using a small search engine in our company's intranet. That search engine is a very old webpage really convoluted, and it doesn't take parameters in the url. No chance that the original authors will assist:
The extension popup offers an input text box to type your query. Your
query is then saved in localStorage
There is a content script inserted in
the intranet page that reads the localStorage key and does a document.getElementById("textbox").value = "your query"; and then does
document.getElementById("textbox").click();
The expected result is that your search is performed. And that's all.
The problem is that the click gets performed unlimited times in an infinite loop, and I cannot see why it's repeating.
I would be grateful if you would be able to assist. This is my first Chrome extension and all what I have been learning about how to make them has been a great experience so far.
This is the relevant code:
The extension popup where you type your query
popup.html
<input type="search" id="cotext"><br>
<input type="button" value="Name Search" id="cobutton">
The attached js of the popup
popup.js
var csearch = document.getElementById("cotext");
var co = document.getElementById("cobutton");
co.addEventListener("click", function() {
localStorage["company"] = csearch.value;
window.open('url of intranet that has content script applied');
});
And now the background file to help with communication between parts:
background.js
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
sendResponse({data: localStorage[request.key]});
});
And finally the content script that is configured in the manifest to be injected on the url of that search engine.
incomingsearch.js
chrome.extension.sendRequest(
{method: "getLocalStorage", key: "company"},
function(response) {
var str = response.data;
if (document.getElementById("txtQSearch").value === "") {
document.getElementById("txtQSearch").value = str;
}
document.getElementById("btnQSearch").click();
});
So as I mentioned before, the code works... not just once (as it should) but many many times. Do I really have an infinite loop somewhere? I don't see it... For the moment I have disabled .click() and I have put .focus() instead, but it's a workaround. I would really like to use .click() here.
Thanks in advance!
The loop is probably caused by clicking the button even if it has a value. Try putting it inside your if. That said, you are overcomplicating it.
You can access the extension's data inside content scripts directly by replacing localstorage with the chrome.storage extension api. Add the "storage" (silent) permission to your manifest.json, like this:
"permissions": ["storage"]
Remove the message passing code in background.js. Then replace the popup button listener contents with:
chrome.storage.local.set({ "company": csearch.value }, function() {
chrome.tabs.create({ url: "whatever url" })
})
Replace the content script with:
chrome.storage.local.get("company", function(items) {
if(document.querySelector("#txtQSearch").value == "") {
document.querySelector("#txtQSearch").value = items.company
document.querySelector("#btnQSearch").click()
}
})
document.querySelector() performs the same function here as getElementById, but it is much more robust. It also has less capital letters, which makes it easier to type in my opinion.

Prompt on URL visit

I'm new to Javascript and Chrome extensions, and I'm working on one that triggers a prompt when the user visits a certain webpage, but It's not prompting when the user visits the webpage.
Here's a simplified version that reproduces the problem:
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
var url = tabs[0].url;
if (url === "example.com") {
confirm("You are visiting " + URL);
}
});
What I was hoping this would do is trigger the prompt when the user visits 'Example.com', but I think that I'm misunderstanding how Chrome pulls the URL from the active tab, and maybe how the event is triggered...
Any tips are appreciated.
In your answer, you quoted this question, and yet you picked a weird answer out of the bunch of answers there.
Instead of detecting a page load yourself, it's best to rely on Chrome's content script mechanism, which will ensure that your script is executed in every tab that loads the requested webpage.
If you know the list of the webpages in advance, you can filter by them in the manifest:
"content_scripts" : [{
"matches": ["*://*.example1.com/*", "*://*.example2.com/"],
"js": ["confirm.js"]
}],
And then have a very simple confirm.js:
confirm("You are visiting " + location.href);
This will be very efficient as Chrome will natively filter the requests for you.
If you don't know the list of the webpages in advance, you can use a content script on every page and filter it in your code:
"content_scripts" : [{
"matches": ["*://*/*"],
"js": ["confirm.js"]
}],
And the confirm.js (skeleton):
chrome.storage.local.get("hostFilterData", function(data){
if( checkUrl(location.host, data.hostFilterData) ) {
confirm("You are visiting " + location.href);
}
});
function checkUrl(location.host, filterData){
/* your logic goes here */
}
You might also want to add "run_at" : "document_start" if you want your JS to run at the earliest time possible.
If you really want to keep your logic in the background page, you can listen to various events. chrome.tabs.onUpdated filtered by changeInfo.status == 'complete' should work in most cases, but may not always be a good idea. It will fire very late if the page has a slow-loading resource, and might fire again if the page uses anchor-based navigation (you probably don't want that). Even if you go this route, there's little sense doing a tab query after that, since the event includes the tab ID of the page that fired it.
There's also chrome.webNavigation API providing relevant events.
Try changing
if(url === "example.com")
to
if(url === "example.com" || url === "http://example.com" || url === "https://example.com")

Get url from google chrome tab

I'm building an extension for chrome, and I'm trying to pass the chrome tab url (with JS) dynamically to the html file. I read other people questions regarding the same issue, but it didn't work in my case.
My knowledge of JS and HTML is basic, but I don't know how to move the parameter data between them.
Thanks!
First, set the permissions for the tab API :
"permissions": [
"tabs"
]
And then store the URL :
chrome.tabs.getSelected(null,function(tab) {
var tablink = tab.url;
});
Or another way: (preferred)
chrome.tabs.query({'active': true}, function (tabs) {
var url = tabs[0].url;
});

Categories

Resources