Saving a variable from Chrome extension to be locally accessible [duplicate] - javascript

This is my issue:
I update the localStorage in popup.js in a new tab. I access the same localStorage(same key) in the background.js.
Now this is returning null in every tab apart from the chrome://extensions tab(when I load the extensions.)
I thought localStorage was persistant across all tabs.
Code:
popup.js:
$(document).ready(function (){
alert(localStorage.getItem('filters'));
var oldFilters = localStorage.getItem('filters');
//All the filters show up on the popup.html page.
document.getElementById('td1').innerHTML = oldFilters;
var dat = oldFilters + "," + newArray[j]
localStorage.setItem('filters',String(dat));
}
background.js:
$(window).ready(function() {
// Handler for .ready() called.
var filters = localStorage.getItem('filters');
alert("background + "+ filters);
//This shows all the filters in the chrome:extensions page but always pops up "background + null" in every new tab load.
//changeImage(filters);
});

Background and Browser Action(In your case) Pages live in isolated worlds, their local storage details are not accessible to each other, if you want this sort of access to happen use chrome.storage for your storage needs.
It has few advantages
Your extension's content scripts can directly access user data without the need for a background page.
A user's extension settings can be persisted even when using split incognito behavior.
User data can be stored as objects (the localStorage API stores data in strings).
Methods used
chrome.storage.local.get
chrome.storage.local.set
(use sync instead of local if the data needs to be synchronized with Google Sync)
Demonstration
manifest.json
Ensure all permissions are available for accessing storage API.
{
"name":"Local Storage Demo",
"description":"This is a small use case for using local storage",
"version":"1",
"manifest_version":2,
"background":{
"scripts":["background.js"]
},
"browser_action":{
"default_popup":"popup.html",
"default_icon":"logo.png"
},
"permissions":["storage"]
}
popup.html
A trivial popup html page which refers popup.js to surpass CSP.
<!doctype html>
<html>
<head>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
background.js
This scripts sets content to chrome storage
//Set some content from background page
chrome.storage.local.set({"identifier":"Some awesome Content"},function (){
console.log("Storage Succesful");
});
//get all contents of chrome storage
chrome.storage.local.get(null,function (obj){
console.log(JSON.stringify(obj));
});
popup.js
This script retrieves and sets content from\to chrome storage
document.addEventListener("DOMContentLoaded",function (){
//Fetch all contents
chrome.storage.local.get(null,function (obj){
console.log(JSON.stringify(obj));
});
//Set some content from browser action
chrome.storage.local.set({"anotherIdentifier":"Another awesome Content"},function (){
console.log("Storage Succesful");
});
});
If you look at outputs of these js pages, communication of storage (Background -> popup and popup -> background) is achieved.

Related

What is the best way to develop shopping offers chrome extension?

I have a requirement of developing chrome extension which will display latest offers and coupons if I visit any affiliate store like amazon, aliexpress, flipkart, myntra etc.
When I visit their website and if my extension is installed then that website will should be injected with popup having offers and coupons of that website. (I have a webservice from where i will fetch offers and coupons).
It will be something like shown in below image.
I have tried something similar this way but i'm not sure it's the right way to do.
From Manifest.json
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["jquery.js","myscript.js"],
"css":["offers.css"]
}
],
"web_accessible_resources":[
"offers.html",
"offers.js"
]
myscript.js
var url = chrome.extension.getURL('offers.html');
var iframe = "<iframe src='"+url+"' id='IframeID'></iframe>";
var host = window.location.host;
var splittedHost = host.split('.');
var title = $(document).find("title").text();
if(title != ''){
$('body').append(iframe);
}
offers.html
<html>
<head>
<meta charset="UTF-8">
<title>test| Latest Offers</title>
<script src="jquery.js"></script>
<script src="offers.js"></script>
</head>
<body id="bodyText">
<h1>
Welcome
</h1>
...
</body>
</html>
Using This I got something like this in every page I visit:
That iframe is actually offers page and to get offers data I need host name from url. I tried getting window.localtion.host in offers.js injected in offers.html but I get chrome://extension.
Can anyone suggest me how to get host name in offers.js or is there any way I can append data in offers.html from myscripts.js? and where to call the API and how to append result in to iframe body?
Can anyone suggest me how to get host name in offers.js or is there any way I can append data in offers.html from myscripts.js?
As a quick solution, if you only need the URL, you can pass it as a query parameter:
// myscript.js
var url = chrome.extension.getURL('offers.html?url=' + window.location.host);
// offers.js
// Using https://developer.mozilla.org/en-US/docs/Web/API/URL
var host = new URL(location.href).searchParams.get('url');
If you do need to extract more information from the page, you can use postMessage for communication with the embedded window.
// myscript.js
iframe.contentWindow.postMessage(message, chrome.runtime.getURL(""));
// offers.js
window.addEventListener("message", function(event) {
var message = event.data;
/* ... */
});
This can be made bi-directional as well, though this is outside the question's scope.
where to call the API and how to append result in to iframe body?
Well, in offers.js, and then modify the DOM of that page.
Edit: Apparently, this is problematic as security policies from the page leak into the iframe, blocking a call to HTTP endpoint.
You should use HTTPS to begin with. It's the privacy of your users that is at stake.
You can work around it by delegating the API call to a background page using Messaging. A background page does not have this restriction.
..you still should be using HTTPS. This can be a reason for rejection when your extension is reviewed.

Is there any way to count number of tabs are opened in chrome?

I am trying to find a way to count a number of tabs that are currently open in Chrome by javascript.
I have searched and found chrome.tabs.query(). But when I opened my console and tried it I got an undefined message.
Is it not supported anymore by Chrome, or can it only be used in extension development?
As wscourge has implied, chrome.tabs.query() is a Chrome extension API, which is only available to extensions, not web page JavaScript. In fact, it is only available in the background context of an extension (i.e. not content scripts).
To find the number of tabs that are open, you could do something like:
chrome.tabs.query({windowType:'normal'}, function(tabs) {
console.log('Number of open tabs in all normal browser windows:',tabs.length);
});
If you want to run this from a console, you will need to have an extension loaded that has a background page. You will then need to open the console for the background page. From that console, you can execute the above code.
I found the answer to this question here: https://superuser.com/questions/967064/how-to-get-tab-count-in-chrome-desktop-without-app-extension
Go to chrome://inspect/#pages
Run the following line of code in the javascript console:
document.getElementById("pages-list").childElementCount
The tabs count will be printed to the console.
Local and Session storage
In case when we want count only tabs witch our website - first on page load (open tab) event we generate tab hash and we save it in sessionStorage (not shared between tabs) and as key in TabsOpen object in localStorage (which is shared between tabs). Then in event page unload (close tab) we remove current tab hash (saved in sesionStorage) from TabsOpen in localStorage.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My project</title>
...
<script>
function tabLoadEventHandler() {
let hash = 'tab_' + +new Date();
sessionStorage.setItem('TabHash',hash);
let tabs = JSON.parse(localStorage.getItem('TabsOpen')||'{}');
tabs[hash]=true;
localStorage.setItem('TabsOpen',JSON.stringify(tabs));
}
function tabUnloadEventHandler() {
let hash= sessionStorage.getItem('TabHash');
let tabs = JSON.parse(localStorage.getItem('TabsOpen')||'{}');
delete tabs[hash];
localStorage.setItem('TabsOpen',JSON.stringify(tabs));
}
</script>
...
</head>
<body onunload="tabUnloadEventHandler()" onload="tabLoadEventHandler()">
...
</body>
</html>
Thanks to this in TabsOpen object in localStorage we have information about current open tabs which can be read by
let tabsCount = Object.keys( JSON.parse(localStorage.getItem('TabsOpen')||'{}') ).length
It can only be used in extension development.
You are not able to access that information from document level.
This is not a solution using javascript, but maybe it can help double-check the count against another solution. It is by far the easiest (one-click) solution that works for me:
If you have chrome sync enabled, simply navigate to chrome.google.com/sync
It should give you the count of open tabs, among other counts (e.g. bookmarks, extensions, etc)

how to load JS from a chrome extension popup

background
I simply want to create a chrome extension where I click on the extension icon, it loads a popup that loads a javascript file.
I was able to do an html only popup simply by adding these two files:
manifest.json
{
..
"browser_action": {
"default_popup": "popup.html",
..
}
}
popup.html
<html>
..
hello world
</html>
problem
I want to actually load a chrome events page so that the popup page calls the events page and interacts with it.
what i have tried
I added this to manifest.json
"background": {
"scripts": ["eventsPage.js"],
"persistent": false
}
and added a simple eventsPage.js file:
chrome.runtime.onInstalled.addListener(onInit);
chrome.runtime.onStartup.addListener(onStartup);
function onInit() {
console.log("on init");
}
function onStartup() {
console.log("on startup");
}
if (chrome.runtime && chrome.runtime.onStartup) {
chrome.runtime.onStartup.addListener(function() {
console.log('on startup stuff');
});
}
when I launch the extension and click on inspect to see chrome dev tools.. nothing shows up on the console:
I've also tried adding the src of eventsPage.js to popup.html:
</head>
..
<script src="eventsPage.js"></script>
<body>
..
but that changes nothing, I can't even find the eventsPage.js source in chrome dev tools.
How do I do this?
Many ways:
Add a script for example popup.js in popup.html and call chrome.runtime.getBackgroundPage(function callback) to interact with event page.
popup.html
...
<script src="popup.js"></script>
...
popup.js
chrome.runtime.getBackgroundPage(backgroundPage => backgroundPage.testMethod());
eventsPage.js
const testMethod = () => console.log('test');
Use Message Passing(there are many examples in this link) to communicate with event page.
Since you want to transfer data between popup page and event page, there are many other workarounds, for example, we could use global storage such as chrome.storage to save/load/react to changes.

Chrome extension to store the keys users press

I am building a chrome extension which will store all the keys pressed by the user and will store those keys into a text file inside the directory.
I want to keep track of user key pressed whatever he searches or types i want to store it into a text file ..
For now I've made it store the keywords in an array and alert it when needed. The array isn't getting alerted.
Here is my JavaScript file:
var your_array = [];
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
document.onkeydown = function(e) {
var keyPress;
if (typeof event !== 'undefined') {
keyPress = event.keyCode;
} else if (e) {
keyPress = e.which;
}
your_array.push(String.fromCharCode(keyPress));
return false; // Prevents the default action
};
checkPageButton.addEventListener('click', function() {
alert(your_array);
die;
}, false);
}, false);
...and this is what my HTML file looks like:
<!doctype html>
<html>
<head>
<title>Storing Keyword</title>
<link rel='stylesheet' href='popup.css' />
<script src="popup.js"></script>
</head>
<body>
<h3>I can store your keywords</h3>
<button id="checkPage">Really Show Me !</button>
</body>
</html>
This is my JSON manifest file:
{
"manifest_version": 2,
"name": "Keyword store",
"description": "This extension will analyze a page using GTmetrix",
"version": "1.0",
"browser_action": {
"default_icon": "avator/icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
The issue is that the alert appears but it gets closed automatically within few milliseconds.
If anyone has any idea how to store keys in a text file please let me know about that too...
Thank you.
The issue is that the alert appears but it gets closed automatically within few milliseconds.
Chrome popups do not survive focus loss.
Your alert() cause the dialog box to appear, which loses focus and the page closed/destroyed.
Use console.log and inspect the popup for debugging instead.
If anyone has any idea how to store keys in a text file please let me know about that too
There was a recent question where I answered rather extensively about options to do it. If you need persistent storage, use chrome.storage API. If you need to specifically output a file, you can't get R/W access from an extension, though you can offer a file for "download".
I want to keep track of user key pressed whatever he searches or types
That's not going to be possible; your extension as it is now will only get notified about keystrokes within your popup. There isn't an extension API to globally intercept keypresses. At most, you can inject similar scripts in all tabs, but again this will not get you stuff typed in the address/search bar.

Chrome Extension Help: Trigger variable CSS from popup.html

Okay, I'm building an extension like so:
has a browseraction which invokes a popup.html that has an input field, a submit button, and a link that invokes a javascript action
a background.html page that receives the input value data via popup.html and then uses them to inject custom CSS into the page
I'm using localStorage to store the input data for future use. Here's what I need help with:
run javascript in the background.html (which injects the CSS) when a button is clicked in the popup.html
passing along the data from the input field in the popup.html to background.html
I scoured google source code but could not really find anything. I'm not looking to inject the CSS to every page (I know how to do that) or when the browser action icon is clicked (I know how to do that as well). I need to get that CSS injected only when a user inputs data into the popup.html and clicks on a link or button.
UPDATED:
I'm still not able to do what I need to do with this. Here's my code:
<script type="text/javascript">
var bgrSize = localStorage.getItem('gridSize');
function insert(){
chrome.tabs.executeScript(null, {code:'body{ backgroundImage: -webkit-linear-gradient(#eee 0.05em, transparent 0.05em); backgroundPosition: 100% 0 %; backgroundSize: 100% '+ bgrSize +';}'});
}
</script>
That's on my background.html page. Here's what fires from the popup.html page:
function showGrid(){
chrome.extension.getBackgroundPage().insert();
}
The "showGrid" function fires when a button is clicked. The gridSize data is already stored in localStorage (I have a section of the popup.html that updates to show the localStorage information).
What am I doing wrong? I just can't figure it out. Btw, the manifest.json includes my background.html
In popup use chrome.extension.getBackgroundPage and then execute proper function in background page. Inject data with insertCSS or executeScript
Pass data thru function parameter or localStorage if you want use it later.
Resuming:
// popup.html
<script>
window.onload = function(){
document.getElementById('my-form').addEventListener('submit', function(){
console.log('popup');
chrome.extension.getBackgroundPage().insert({
param: 'example',
input: document.getElementById('my-input').value
});
});
}
</script>
<form id="my-form">
<input type="text" id="my-input"/>
<input type="submit" />
</form>
// background.html
function insert(data){
console.log('inserting', data.input);
chrome.tabs.insertCSS(null, {
code: 'a { font-size: ' + data.input + 'px;}'
}, function(){
console.log('inserted');
});
}
// manifest.js
...
"permissions": ["tabs", "*://*/*"]
This example works - I have checked it manually ;)

Categories