Chrome extensions (can't get and click elements on new chrome tabs) - javascript

That's it. Lemme explaim myself.
I coded a chrome extension that when clicking on a button, it will open a new resized tab (a paypal login) , but I can't manage to click the "log in button" of paypal because trying to
document.getElementById('btnLogin').click();
isn't working, neither adding that:
var paypal = window.open("https://www.paypal.com/es/signin", "PayPal", "width=400,height=400,location=yes,menubar=yes,status=yes,titilebar=yes,resizable=yes");
paypal.onload = function() {
paypal.document.getElementById('btnLogin').click();
}
Check out all of my code:
manifest.json
{
"manifest_version": 2,
"name": "Zapatillao",
"description": "Yatusabe te cojo sapatilla",
"version": "2.0.0",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"browser_action": {
"default_popup": "popup.html",
"default_icon": "icon128.jpg"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"chrome://*/*"
]
}
content.js
document.getElementById('paypal_prelog').addEventListener('click', function() {
chrome.tabs.executeScript({
file: "paypal_prelog.js"
});
});
popup.html
<html>
<head>
<style>
html, body {
height: 200px;
width: 200px;
}
</style>
</head>
<body>
<h1>Discord: Loan#2334</h1>
<button id='paypal_prelog'>PayPal Prelogin</button>
<script src='content.js'></script>
</body>
</html>
paypal_prelog.js
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var paypal = window.open("https://www.paypal.com/es/signin", "PayPal", "width=400,height=400,location=yes,menubar=yes,status=yes,titilebar=yes,resizable=yes");
paypal.onload = function() {
paypal.document.getElementById('btnLogin').click();
}
function closeWin() {
paypal.close();
}
I have tried thousand of things, hope you can help me.

The solution for a ManifestV2 extension, which you are writing, in short, is to open a new paypal sign-in window using chrome.windows.create and then use chrome.tabs.executeScript to inject a content script code that clicks btnLogin . Your current code does it all wrong though.
Remove content_scripts, tabs, and chrome://*/* from manifest.json.
Remove content.js from your extension and popup.html
Remove paypal_prelog.js
Create popup.js
document.getElementById('paypal_prelog').onclick = () => {
chrome.windows.create({
url: 'https://www.paypal.com/es/signin',
width: 400,
height: 400,
}, w => {
chrome.tabs.executeScript(w.tabs[0].id, {
code: `(${() => {
document.getElementById('btnLogin').click();
}})()`,
});
});
};
load popup.js in popup.html:
<script src="popup.js"></script>
</body>

Related

How from extensions popup repeatedly running a script inserted into the web site (injection from chrome extensions)

I use the manifest (V3) to insert the script into the website
{
"name": "GpxNaMapy",
"description": "example",
"version": "111",
"manifest_version": 3,
"background": {"service_worker": "background.js"},
"permissions": ["storage", "activeTab", "scripting", "webRequest"],
"action": {
"default_popup": "popupGPX.html"
},
"content_scripts": [{
"matches": ["https://*.gpxmapy.cz/*"],
"js": ["content.js"]
}],
"web_accessible_resources": [{
"resources": ["inject.js"],
"matches": ["https://*.gpxmapy.cz/*"]
}]
}
content.js will inject inject.js into the site and inject.js will run
window.onload = function() {
var s = document.createElement("script")
s.setAttribute("id", "GpxNaMapy")
s.src = chrome.runtime.getURL("inject.js")
document.body.appendChild(s)
}
inject.js has become part of the page and its function myFunc1 is visible in list console.log(window) and the function has access to all other scripts of the site!
function myFunc1(a) {
console.log(window)
alert(a)
}
myFunc1("OK, script injected")
But now I need to repeatedly run this custom embedded function myFunc1() from the extensions popup window. According to the following, it is not possible
popupGPX.html
<!DOCTYPE html>
<meta charset="UTF-8">
<html>
<head></head>
<body>
<button id="example">example</button>
<script src="popupGPX.js"></script>
</body>
</html>
popupGPX.js
let button = document.getElementById("example")
button.addEventListener("click", async () => {
let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: script1,
args: ["example Hello"]
});
});
function script1(a) {
console.log(window)
alert(a)
window.myFunc1(a) //error
};
script1() is running in the background of the website (alert "example Hello" is displayed), but there are no other scripts in the console "window", not even my embedded one, so it cannot be run.
How to do it?
(for English I use Google Translate...)

Chrome extension message listener fires twice

I'm working on Chrome extensions. I try to learn messaging between content and background. I develop simple project for this. But I have issue.
Basic idea is
User click button on extension popup
A function (bot.js) find image from content of tab then extension (background.js) will download it.
The issue is port.onMessage.addListener() in background.js fired twice.
When background.js sends message to contentscript.js there are two same messages in console or when I try to download in background.js (the code line "Do Something") it download the file twice.
How can I solve this problem?
popup.html
<!doctype html>
<html>
<head>
<title>Test Plugin</title>
<script src="background.js"></script>
<script src="popup.js"></script>
</head>
<body>
<h1>Test Plugin</h1>
<button id="btnStart">Button</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('btnStart');
checkPageButton.addEventListener('click', function() {
GetImages("Some URL");
}, false);
}, false);
var tab_title = '';
function GetImages(pageURL){
// Tab match for pageURL and return index
chrome.tabs.query({}, function(tabs) {
var tab=null;
for(var i=0;i<tabs.length;i++){
if(tabs[i].url==undefined || tabs[i].url=="" || tabs[i]==null){}
else{
if(tabs[i].url.includes(pageURL)){
tab=tabs[i];
break;
}
}
}
if(tab!=null){
chrome.tabs.executeScript(tab.id, {
file: "bot.js"
}, function(results){
console.log(results);
});
}
});
}
bot.js
var thumbImagesCount = document.querySelectorAll('.classifiedDetailThumbList .thmbImg').length;
var megaImageURL=document.querySelectorAll('.mega-photo-img img')[0].src;
console.log(megaImageURL + " from bot.js");
port.postMessage({key:"download", text: megaImageURL});
background.js
chrome.runtime.onConnect.addListener(function (port) {
console.assert(port.name == "content-script");
port.onMessage.addListener(function(message) {
console.log(message);
if(message.key=="download"){
// Do Something
// Event fires twice
port.postMessage({key:"download", text: "OK"});
}
})
});
contentscript.js
console.log("content script loaded!");
var port = chrome.runtime.connect({name: "content-script"});
port.onMessage.addListener(function(message){
console.log(message);
});
manifest.json
{
"manifest_version": 2,
"name": "Test Extension",
"description": "This extension will download images from gallery",
"version": "1.0",
"icons": {
"16": "bot16.png",
"48": "bot48.png",
"128": "bot128.png" },
"browser_action": {
"default_icon": "bot48.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"downloads",
"http://*/",
"https://*/"
],
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["contentscript.js"]
}
]
}
The background script declared in manifest.json already has its own page, a hidden background page where it runs, so you should not load it in the popup as it makes no sense in case there are listeners for API events, the background page is already listening for them. In this case the copy also creates the second listener while the popup is open.
Solution: don't load background.js in popup.
See also Accessing console and devtools of extension's background.js.

How can I run a extension with Google Chrome for Youtube?

Hello there,
I want to remove thumbnail images that appear on YouTube. I am using the following code for this.
while (true) {
$("ytd-thumbnail").remove()
}
When I paste this code into console, all thumbnail images are removed. I want it to work on the backplane by adding an extension. The code for the plug-in I'm preparing is below.
manifest.json;
{
"manifest_version": 2,
"name": "test",
"description": "test extension",
"version": "1.0",
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>TEST</title>
<script src="popup.js"></script>
</head>
<body>
<h1>TEST</h1>
<button id="checkPage">Check !</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() {
chrome.tabs.getSelected(null, function(tab) {
d = document;
while (true) {
$("ytd-thumbnail").remove()
}
});
}, false);
}, false);
When I press the checkPage button nothing happens. But this code works when I add a console. What is the problem? Thanks in advance.
There are several issues with the extension :
You are trying to use $ i.e. jquery which is not available in your
popup.js
You are trying to access "ytd-thumbnail" dom elements which belong
to youtube page and not your popup.html. So, even if you replace $
with document.querySelector , you won't find those elements.
I created a working version that looks something like this. I have not included popup.html which is same as yours.
manifest.json
{
"manifest_version": 2,
"name": "Hello Extensions",
"description" : "Base Level Extension",
"version": "1.0",
"browser_action": {
"default_icon": "hello_extensions.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["background.js"],
"all_frames" : true
}
],
"permissions": [
"activeTab",
"tabs"
]
}
2.popup.js
document.addEventListener('DOMContentLoaded', function()
{
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function()
{
chrome.tabs.query({"active":true}, function (tabs){
chrome.tabs.sendMessage(tabs[0].id, "removeThumbnails", function (response) {
});
});
});
});
When the button is clicked, retrieve the active tab and send it a "removeThumbnails" message.
3.background.js
chrome.runtime.onMessage.addListener(function(message, callback) {
if (message == "removeThumbnails")
{
var elements = document.querySelectorAll("ytd-thumbnail");
elements.forEach(a => a.parentNode.removeChild(a));
}
});
background.js is content script and runs in youtube page. It can now access all the dom elements in youtube page. When we receive a "removeThumbnails" message , get all ytd-thumbnail elements and remove them from page.

Execute content.js on button click, not page load

Not a duplicate of Executing Chrome extension onclick instead of page load because I need to execute script on a button press in popup.html, not when the user presses the icon.
This is my first chrome extension and I've got my content.js working the way it should on page load, but I only want to execute it after the user pushes a button in popup.html. I know you can specify run_at in manifest.json, but this doesn't work because I want it to only run when the user clicks a button (not the icon), and I'm using pageAction so I need the icon to be grayed out on urls which don't contain the letter 'g', hence the specification in my background.js. I think I must be missing something regarding the communication between background.js and content.js, but I'm feeling very lost so if anyone can explain what I'm missing that would be great.
Here is my manifest.json:
{
"manifest_version": 2,
"name": "my extension",
"description": "it doesnt work",
"version": "0.1",
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [
"declarativeContent"
],
"page_action": {
"default_popup": "popup.html"
},
"icons" : { "16": "16.png",
"48": "48.png",
"128": "128.png" },
"content_scripts": [
{
"js": ["content.js"],
"matches": ["<all_urls>"],
"run_at": "document_end"
}
]
}
Background.js:
chrome.runtime.onInstalled.addListener(function() {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlContains: 'g' },
})
],
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "content.js"});
}); ]
}
]);
});
});
Content.js:
document.addEventListener("DOMSubtreeModified", function(event){
if(document.getElementsByClassName(".class")) {
var x = document.querySelectorAll(".class");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.visibility = "hidden";
} }
});
popup.html:
<html>
<head>
<script type="text/javascript" src="content.js"></script>
</head>
<body>
<p>Turn off <span>class, "class"</span></p>
<button type="button">Turn off</button>
</body>
</html>
This will run if you are on the selected tab. You may need to change how you select that tab though. Basically this will will send a request to the tab and the tab listens for these requests. If you get the proper greeting, you can do your function.
popup.html
<html>
<head>
<script type="text/javascript" src="content.js"></script>
</head>
<body>
<p>Turn off <span>class, "class"</span></p>
<button type="button" id="button">Turn off</button>
</body>
</html>
background.js
$('#button').on('click',function()
{
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "content_script.js"});
});
});
content.js
if(document.getElementsByClassName(".class")) {
var x = document.querySelectorAll(".class");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.visibility = "hidden";
}
}
Also, as #Makyen had suggested, remove content scripts from your manifest so it isn't always being injected into every tab. I edited my answer as well per this suggestion.

Fill forms with a data from popup.html

I have been trying to create an extension that fills a form with data from a popup, I'm a bit confused regarding the use of "background" and "content" files, I don't think I need one. Here is my code:
Manifest:
{
"name": "Browser action for Form",
"description": "Fill a form with data from the popup",
"version": "1.0",
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"browser_action": {
"default_title": "Form Test",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["https://the-site-with-a-form.com/*"],
"js": ["jquery-3.1.1.min.js", "content.js"]
}
],
"manifest_version": 2
}
popup.html
<!doctype html>
<html>
<head>
<title>Form</title>
<script src="popup.js"></script>
</head>
<body>
<form>
<textarea id="txtArea"></textarea>
<input type="button" id="btn1" value="Run">
</form>
</body>
</html>
popup.js
function click(){
var text = document.getElementById("txtArea")
chrome.tabs.sendMessage(
tabs[0].id,
{from: 'popup', subject: 'DOMInfo',data1: text});
}
content.js
chrome.runtime.onMessage.addListener(function (msg, sender, response) {
if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) {
//Fill the form with the data of the popup
document.getElementById("The textbox from the form").value = msg.data1;
}
});
what is wrong in the code?
Thanks!
Please learn to debug extension popups. If you did, you would see an informative error message.
With that in mind, tabs in your popup code doesn't come from anywhere - so your code there stops with an error. Clearly, that part is ripped out of context (of a tabs.query call, most likely). Note that if your intent is to message the currently active tab, you can just skip the first argument of sendMessage entirely.
You defintiely do need a content script, since it's the only part of an extension that can interact with a webpage's form. Recommended reading: How do all types of Chrome extension scripts work?
Here is the popup.js with the fixed "tabs" argument
function click(e) {
chrome.tabs.query({currentWindow: true, active: true}, function (tabs){
var activeTab = tabs[0];
var text = document.getElementById("txtArea").value;
chrome.tabs.sendMessage(activeTab.id, {from: 'popup', subject: 'DOMInfo',data1: text});
});
window.close();
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('submitBtn').addEventListener('click', click);
});

Categories