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.
Related
I'm struggling with trying to develop a simple Chrome Extension for my "portfolio".
What I want to do is really simple. I think I can do it in two different ways!
First way:
I have an input field into my popup.html. What I want to do is get the text prompted into this input field and save it into the storage. After that, into my contentScript, I want to read the text/field saved into the storage and use it for some JS logic.
So, basically this is the input from popup.html:
<input class="custom-input-script-length" type="text" name="custom" id="values-input"/>
This is a function that get as parameter the value from the input. It's declared/called inside my popup.js:
function saveValue(value) {
if(value !== '') {
chrome.storage.local.set({'valuesInput': value}, function() {
console.log("Values saved!");
})
}
}
Now, I've tried many ways to read the value directly from the chrome tab (not from the extension, I've tried into the contentScript) but it never works, it will always return an "undefined".
How should I read that value?
What my extension must do it's just grab the entire responseHeader and search for a specific value from the toString (for example: cache-control). If it will find it it will just show the value into a new div added into the DOM, that's all.
Another solution could be send/read the entire responseHeader from the chrome tab from inside the popup but even in this way it never works. All I get is "undefined" or the responseHeader of the extension context...
Do you have any advice?
I'm usind the Manifest V3 and I already have the storage permissions added into it.
Thanks for everyone who will answer!
This is a response to OP's question which is too long for a comment.
The only way I could reproduce the problem was by trying to set the popup input value before the page had completed loading. The Chrome storage method calls worked as expected. To avoid problems, initialization code should be loaded at the end of the page or else wrapped in a DOMContentLoaded event.
OP also asks how to pass the stored value between popup and content pages. And in this case the content page can read the value directly from storage, which is shared between the pages. The content page may also receive notifications when the value changes by using the chrome.storage.onChanged event.
The relevant parts of the Chrome extension are shown below:
popup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Popup</title>
</head>
<body>
<input class="custom-input-script-length" type="text" name="custom" id="values-input"/>
<!-- script must load last -->
<script src="scripts/popup.js"></script>
</body>
</html>
popup.js
let valuesInput = document.getElementById("values-input");
valuesInput.addEventListener("change", (event) => {
chrome.storage.local.set({valuesInput: valuesInput.value});
})
chrome.storage.local.get('valuesInput', function(obj) {
if(obj.valuesInput !== undefined && obj.valuesInput !== '') {
valuesInput.value = obj.valuesInput;
}else {
console.log("input field can't be empty.");
}
});
content.js
let valuesInput = null;
chrome.storage.local.get('valuesInput', (result) => {
console.log('storage.get', result);
valuesInput = result.valuesInput;
})
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.
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.
I'm trying to build a basic Chrome extension that, from a browser action popup, opens a website in a new tab, and fills in the login credentials. I can get the Chrome extension to open the new page but can't seem to get it to input text into the input fields.
Manifest.json
{
"manifest_version": 2,
"name": "Vena",
"description": "This extension will allow users to login to vena accounts",
"version": "1.0",
"browser_action": {
"default_icon": "images/icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>Auto-Login</title>
<script src="popup.js"></script>
</head>
<body>
<h1>Login</h1>
<button id="checkPage">Login!</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() {
var newURL = "https://vena.io/";
chrome.tabs.create({ url: newURL });
var loginField = document.getElementsByClassName('js-email form-control input-lg');
var passwordField = document.getElementsByClassName('js-password form-control input-lg');
loginField.value = 'gsand';
passwordField.value = '123';
}, false);
}, false);
How do I fill in the information in the input areas of the new tab?
Another time, you may want to use something other than a popup (e.g. just a plain browser action button, or a panel) to test out your functionality. It is easier to debug things other than a popup due to the fact that the popup will disappear under so many conditions. Once you have the basic functionality debugged, you can move it into a popup and deal with the issues specific to using a popup.
Issues
You need to use a content script to interact with web pages:
The primary issue is that you have to use a content script to interact with a web page, such as manipulating the DOM, as you desire to do. Content scripts have to be injected into the web page. This can be done with a content_scripts entry in your manifest.json, or with chrome.tabs.executeScript() from JavaScript that is in the background context (background scripts, event scripts, popups, panels, tabs containing pages from your add-on, etc.). For what you are doing, chrome.tabs.executeScript() is the way to go.
Additional issues:
chrome.tabs.create() is asynchronous. You need to wait for the callback to execute so the tab exists in order to inject a content script. You can not inject scripts into a tab that does not yet exist. Note: You could use other, more complex, methods of determining when to inject the content script, but the callback for chrome.tabs.create() is a good way to do it in this case.
Once you create the new tab, you want to inject a script. This is not the "active tab", so you need to add "https://vena.io/*" to your permissions in your manifest.json.
The elements you desire to interact with are not immediately available on the page when the content script is run. You need to wait until they are available. I just used a setTimeout loop to poll until the elements are available. I chose to poll on 250ms intervals a maximum of 100 times (25 seconds). The elements were there each time after the first delay.
document.getElementsByClassName() returns an HTMLCollection, not a single element.
Popups close when you activate a different tab. Once the popup is closed/destroyed, you can not do any more processing within the code for the popup. In order to get around that:
In your chrome.tabs.create(), include active:false to prevent the new tab from becoming active immediately.
Call chrome.tabs.update() in the callback for chrome.tabs.executeScript() to active the tab once the content script has been injected (i.e. when you are done with all the processing you are going to do in the popup).
Code
Changes were only needed in your manifest.json and popup.js.
manifest.json
{
"manifest_version": 2,
"name": "Vena",
"description": "This extension will allow users to login to vena accounts",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab", //This is not needed as you never interact with the active tab
"https://vena.io/*"
]
}
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() {
var newURL = "https://vena.io/";
//Must not make the tab active, or the popup will be destroyed preventing any
// further processing.
chrome.tabs.create({ url: newURL,active:false }, function(tab){
console.log('Attempting to inject script into tab:',tab);
chrome.tabs.executeScript(tab.id,{code:`
(function(){
var count = 100; //Only try 100 times
function changeLoginWhenExists(){
var loginField = document.getElementsByClassName('js-email form-control input-lg')[0];
var passwordField = document.getElementsByClassName('js-password form-control input-lg')[0];
//loginField and passwordField are each an HTMLCollection
if( loginField && passwordField ){
loginField.value = 'gsand';
passwordField.value = '123';
} else {
if(count-- > 0 ){
//The elements we need don't exist yet, wait a bit to try again.
//This could more appropriately be a MutationObserver
setTimeout(changeLoginWhenExists,250);
}
}
}
changeLoginWhenExists();
})();
`},function(results){
//Now that we are done with processing, make the tab active. This will
// close/destroy the popup.
chrome.tabs.update(tab.id,{active:true});
});
});
}, false);
}, false);
May need use document.execCommand('insertText', false, text);
Depending on the page, you may need/want to use:
document.execCommand('insertText', false, textValue);
If you do so, you will need to first select/focus the desired element. This would be instead of setting the .value property. Which you use will depend on what you are actually doing and the composition of the page you are altering. For the specific example in the question, setting the element's .value property works. For inserting text, using `document.execCommand('insertText') is more generally applicable.
May need a MutationObserver
In the above code I use a setTimeout() loop to delay until the desired elements exist. While that works in the above case, depending on your use case, it may be more appropriate for you to use a MutationObserver. Largely, which to use will depend on how immediately you need to respond to the desired elements being added and what type of load you are putting on the page by looking for the elements. For more information about watching for DOM changes see: Is there a JavaScript/jQuery DOM change listener?
UI comment
Currently you have a popup that has a single button: "Login". From a user interaction point of view, it would probably be better to just use a plain browser action button. If you are intending to add functionality to your popup, then go ahead and keep the popup. If you are not going to add functionality, it does not make a lot of sense to force your user to click twice (click: open popup, then click: login) when they could have just clicked once.
Use an actual Password Manager
If this is functionality that you desire, rather than just something you are putting together just to learn, you should use an actual Password Manager. The functionality of securely storing passwords and inserting them appropriately in websites is non-trivial. You can easily make mistakes that result in compromising your security. I strongly recommend that you investigate the various ones available and choose one which fits your needs. Basically, all the ones that I have seen would easily provide you with the functionality you have at this time: open a popup; select the site; go to the site and fill in the user name and password. A password manager is a very significant project. It is not a project to be taken on lightly, or for someone who is not experienced in security issues.
Really new to HTML, JavaScript, and Jquery, but I am looking to learn and eventually hoping to make a "shoe bot" program by way of a google chrome extension.
Right now, I just want to link my "Go!" button to take the user to google.com.
It works when I load my HTML document into Chrome directly, however when I try to do the same inside the extension I created, nothing happens.
Here's my manifest file:
{
"manifest_version": 1,
"name": "Shoe bot",
"description": "This extension will provides an ATC & purchase service
for shoes",
"version": "1.0",
"browser_action": {
"default_icon": "yeezy.png",
"default_popup": "popup.html"
},
"content_scripts":[{
"js": ["jquery.js","popup.js"],
"matches": ["http://*/*", "https://*/*"]
}]
}
And then my HTML (popup.html):
<!doctype html>
<html>
<head>
<script src="jquery.js"></script>
<script src="popup.js"></script>
<h1>Size</h1>
<p>
</p>
<select>
<option value = "5.0">5.0</option>
<option value = "6.0">6.0</option>
<option value = "7.0">7.0</option>
<option value = "8.0">8.0</option>
<option value = "9.0">9.0</option>
<option value = "10.0">10.0</option>
<option value = "11.0">11.0</option>
<option value = "12.0">12.0</option>
</select>
<p>
</p>
</head>
<body>
<p>
</p>
<button>Go!</button>
</body>
</html>
And then my JavaScript file (popup.js):
$(document).ready(function(){
$("button").click(function(){
window.location.href = "http://www.google.com";
});
});
Any tips/help is appreciated
I agree with the first answer, that HTML should be used instead of JavaScript for redirection purposes:
Go!
However, if you want to use JavaScript for this (since you said you want to learn), I have listed a few issues I noticed in your code:
Head tag
There are user controls inside the head tag, instead of the body tag. Inside the headtag, there should only be stuff invisible to the user, but relevant to the browser, such as title, scriptand link. Therefore, move your </head> and <body>tag up like so:
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<title>Size</title>
</head>
<body>
<!--Site content begins here-->
<h1>Size</h1>
External URLs
For any URL to an external website, should always start with "http://" or "https://". Otherwise you will end up on http://example.com/google.com. For the function, change into this:
window.location.href = "http://google.com";
Bonus debugging tips
Use the console in your browser to check any errors. This is usually accessible by hitting F12 in your browser. Check all the red errors and try to make sense of them. In my experience, the best way to learn to code is to analyze the errors.
if the only function of the button is to redirect the user to another page - the have it as a link and style it like a button using css:
Go!
if you are using Bootstrap - you can incoroporate button styling into the link
Go!
Just use html for this. I created a simple working JSfiddle to demonstrate: https://jsfiddle.net/tnw78uvc/
simply wrap an <a> tag with your link around your <button>
There is something about the button tag you'll need to know, it causes a page reload natively. Basically what you're doing with $('#runBot').click(function () { ... }) is assigning a function (event handler) to the event click of the button. You're doing good this far, but button already has an event handler assigned to it by the browser, and it causes the page to reload before your event handler gets its stuff done.
Thankfully browsers provide a way of preventing native event handlers from firing (running themselves)
When you do
$('#runBot').on('click', function () { ... });
That function you're declaring, gets a parameter called the event parameter, which has properties and methods that let you know more about what happened (a click) and manipulate how the browser handles that click, let's call it ev.
$('#runBot').on('click', function (ev) {
window.location = "google.com";
});
ev has a method called preventDefault which makes exactly what you need, prevent the browser from firing it's default event handler for the event you just received.
So you have to do this:
$('#runBot').on('click', function (ev) {
window.location = "google.com";
ev.preventDefault();
});
NOTE ev in jQuery is not the native event from the browser, but it makes things easier fixing incompatibilities between browsers that do whatever they want with the event, specially IE.
Hope you got that! Now let's look on why your code is not working.
Basically window.location is not how you redirect to another page, you have two ways of doing that, let's use one of them window.location.href
$('#runBot').on('click', function (ev) {
window.location.href = "google.com";
ev.preventDefault();
});
This may be as easy as changing your markup:
<button type=button id="runBot">Go!</button>
The default type for a button, "submit" tries to submit a form.
You should write the link completely if not it will only redirect as your local page !
You also linked the jquery file path in <script> tag .Look like that path https:// don't forget also to add .href to anchor link....
$(document).ready(function(){
$('#runBot').click(function() {
window.location.href = "https://google.com";
});
});