Why is window.open() and window.close() not working in Extension? - javascript

Alright so I'm currently in the process of trying to automate some tasks via a chrome extension. Here are all my files, the issue is with my content.js:
manifest.json:
{
"manifest_version": 2,
"name": "Click to execute",
"description": "Execute script after click in popup.html (chrome extension) http://stackoverflow.com/questions/20764517/execute-script-after-click-in-popup-html-chrome-extension.",
"version": "1.0",
"icons": {
"48": "icon.png"
},
"permissions": [
"tabs", "<all_urls>"
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
popup.html:
<!DOCTYPE html>
<html>
<body style="width: 300px">
Open this page and then
<button id="clickme">click me</button>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
popup.js:
function hello() {
chrome.tabs.executeScript({
file: 'content.js'
});
}
document.getElementById('clickme').addEventListener('click', hello);
content.js:
let firstCl = function(){
document.getElementsByClassName('nav-link')[6].click();
};
let openWin = function(){
window.open('www.google.com');
};
let closeWin = function(){
window.close()
}
setTimeout(firstCl, 3000);
setTimeout(openWin, 6000);
setTimeout(closeWin, 9000);
Im trying to click on a link, then open a new tab with google.com, then wait a while and close that tab automatically. For some reason the window.close(); method inst doing anything, google opens and then just stays open. Any ideas?

So two things I see that will help you out.
If you want a new tab to open you will need to do add '_blank' otherwise it will just take over the current window. so window.open('www.google.com', '_blank');
You need to reference the window you opened. So assign it to a variable and then close that specific window that was spawned
let theWindow;
let firstCl = function() {
document.getElementsByClassName('nav-link')[6].click();
};
let openWin = function() {
theWindow = window.open('www.google.com', '_blank');
};
let closeWin = function() {
theWindow.close()
}
setTimeout(firstCl, 3000);
setTimeout(openWin, 6000);
setTimeout(closeWin, 9000);

Related

Chrome extension crashes when trying to access from two different windows?

I open a chrome extension, then open a new window (incognito for example) and try to open the extension again, it crashes. I then need to reload the app through the chrome extensions page. There are no errors in this.
The question is how can I work with the extension from different windows at the same time
{
"manifest_version": 2,
"name": "Such Activity",
"description": "Wow",
"version": "1.0",
"permissions": ["tabs","webRequest", "webRequestBlocking", "storage", "http://*/","https://*/"],
"browser_action": {
"default_title": "Click Me",
"default_popup": "popup.html",
"default_icon": "start.png"
}
}
and my popup.js
function injectTheScript() {
console.log("start script")
if (nfts.length <= 0) {
console.log("successfull")
return;
}
id = nfts.pop()
var newURL = "url"+id;
chrome.tabs.update({url: newURL}, myTab => {
function listener(tabId, changeInfo, tab) {
if (tabId === myTab.id && changeInfo.status == 'complete') {
chrome.tabs.query({active: true, currentWindow: true}, tabs => {
chrome.tabs.executeScript(tab.id, {file: "content_script.js"});
})
counter++;
document.getElementById('count').textContent = counter
console.log("hoba"+counter)
setTimeout(injectTheScript, 7000);
}
};
if (!isInjected) {
chrome.tabs.onUpdated.addListener(listener);
isInjected = true;
}
});
}
document.getElementById('clickactivity').addEventListener('click', injectTheScript)
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
return { cancel: true };
},
{urls: ["*://*/*checkUser"]},
["blocking"]
);
the extension crashes before I interact with it. it crashes when i click on its icon in chrome
It's a bug in stable version Chrome, it's fixed in Chrome Canary
thx wOxxOm for

Unable to connect different files of Chrome Extension

I have been trying to make a chrome extension that gives the meaning of the selected text using urban dictionary API. I have tried different approaches but unable to connect all the files for proper execution.
manifest.json
{
"manifest_version": 2,
"name": "Urban Dictionary",
"version": "0.1",
"description": "Dictionary based on Urban Dict.",
"browser_action": {
"default_popup": "popup.html"
},
"icons": {
"16": "images/images.jpg",
"32": "images/images.jpg",
"48": "images/images.jpg",
"128":"images/images.jpg"
},
"permissions": [
"tabs",
"activeTab"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>meaning</title>
</head>
<body>
<h1>meaning</h1>
<button id="test"></button>
<script src="popup.js"></script>
<script src="getword.js"></script>
</body>
</html>
popup.js
chrome.tabs.executeScript(null, {file: "getword.js"},(results)=>{ console.log(results); } );
getword.js
var something;
var term = window.getSelection().toString()
fetch("https://mashape-community-urban-dictionary.p.rapidapi.com/define?term="+term, {
"method": "GET",
"headers": {
"x-rapidapi-key": "My_API_KEY",
"x-rapidapi-host": "mashape-community-urban-dictionary.p.rapidapi.com"
}
})
.then(response => response.json())
.then(result => {
console.log(result)
something=result.list[0].definition
}
)
.catch(err => {
console.error(err);
});
console.log(something)
document.getElementById("test").innerHTML = something;
When trying to manipulate HTML using getword.js. The result comes out to be undefined.
I would be highly obliged if anyone can help me in any way to refactor this code.
In chrome extensions you always define your background scripts in manifest file otherwise it wont work.
like this :
"background": {
"scripts": [
"back.js"
],
"persistent": true
},
Secondly Popup.js needs to be included in your pop.html like we normally do <script src="popup.js"></script>
and lastly there is another type of script that is called content script which also needs to be included in manifest to work at all.
like this:
"content_scripts": [
{
"js": ["jquery-3.5.0.min.js","content.js"]
}
],
According to your need you should probably study content scripts i think.
There are several problems:
Injected code can't make cross-origin network requests.
getword.js's purpose is to be injected as a content script so it runs in the web page and thus shouldn't be listed in popup.html as the popup is a separate extension page in a separate window not related to the web page.
The solution is straightforward:
get the selected text from the web page,
transfer it to the popup script,
make the network request and show the result.
manifest.json (MV2) should list the API site in permissions:
"manifest_version": 2,
"permissions": [
"activeTab",
"https://mashape-community-urban-dictionary.p.rapidapi.com/"
]
popup.html: remove getword.js from html and delete getword.js file.
popup.js:
const API_HOST = 'mashape-community-urban-dictionary.p.rapidapi.com';
const API_OPTS = {
headers: {
'x-rapidapi-key': 'My_API_KEY',
'x-rapidapi-host': API_HOST,
},
};
chrome.tabs.executeScript({
code: 'getSelection().toString()',
}, async pageData => {
try {
const term = pageData[0].trim();
if (!term) throw new Error('No selection!');
const apiUrl = `https://${API_HOST}/define?term=${encodeURIComponent(term)}`;
const apiRes = await (await fetch(apiUrl, API_OPTS)).json();
const def = apiRes.list[0].definition;
document.getElementById('test').textContent = def;
} catch (e) {
document.getElementById('test').textContent =
chrome.runtime.lastError ? 'Cannot access this page' : e.message;
}
});

How To Call Chrome Extension Function After Page Redirect?

I am working on building a Javascript (in-browser) Instagram bot. However, I ran into a problem.
If you run this script, the first function will be called and the page will be redirected to "https://www.instagram.com/explore/tags/samplehashtag/" and the second function will be called immediately after (on the previous URL before the page changes to the new URL). Is there a way to make the second function be called after this second URL has been loaded completely?
I have tried setting it to a Window setInterval() Method for an extended time period, window.onload and a couple of other methods. However, I can't seem to get anything to work. Any chance someone has a solution?
This is my first chrome extension and my first real project, so I may be missing something simple..
manifest.json
{
"name": "Inject Me",
"version": "1.0",
"manifest_version": 2,
"description": "Injecting stuff",
"homepage_url": "http://danharper.me",
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
"browser_action": {
"default_title": "Inject!"
},
"permissions": [
"https://*/*",
"http://*/*",
"tabs"
]
}
inject.js
(function() {
let findUrl = () => {
let hashtag = "explore/tags/samplehashtag/";
location.replace("https://www.instagram.com/" + hashtag);
}
findUrl();
})();
background.js
// this is the background code...
// listen for our browerAction to be clicked
chrome.browserAction.onClicked.addListener(function(tab) {
// for the current tab, inject the "inject.js" file & execute it
chrome.tabs.executeScript(tab.ib, {
file: 'inject.js'
});
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
chrome.tabs.executeScript(tab.ib, {
file: 'inject2.js'
});
});
inject2.js
(function() {
if (window.location.href.indexOf("https://www.instagram.com/explore/tags/samplehashtag/") != -1){
let likeAndRepeat = () => {
let counter = 0;
let grabPhoto = document.querySelector('._9AhH0');
grabPhoto.click();
let likeAndSkip = function() {
let heart = document.querySelector('.glyphsSpriteHeart__outline__24__grey_9.u-__7');
let arrow = document.querySelector('a.coreSpriteRightPaginationArrow');
if (heart) {
heart.click();
counter++;
console.log(`You have liked ${counter} photographs`)
}
arrow.click();
}
setInterval(likeAndSkip, 3000);
//alert('likeAndRepeat Inserted');
};
likeAndRepeat();
}
})();
It is not clear from the question and the example, when you want to run your function. But in chrome extension there is something called Message Passing
https://developer.chrome.com/extensions/messaging
With message passing you can pass messages from one file to another, and similarly listen for messages.
So as it looks from your use case, you can listen for a particular message and then fire your method.
For example
background.js
chrome.runtime.sendMessage({message: "FIRE_SOME_METHOD"})
popup.js
chrome.runtime.onMessage.addListener(
function(request) {
if (request.message == "FIRE_SOME_METHOD")
someMethod();
});
EDIT
Also if you want to listen for the URL changes, you can simply put a listener provided as in the documentation.
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
console.log('updated tab');
});

Uncaught TypeError: Cannot read property 'chooseEntry' of undefined (while developing a chrome extension using fileSystem API)

I am using chrome's fileSystem API to develop a chrome extension which needs to save a file in .txt format. I have the following code -
manifest.json -
{
"version": "1.0",
"manifest_version": 2,
"permissions": [{"fileSystem": ["write", "retainEntries", "directory"]}],
"background": {
"scripts": ["js/background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": ["file:///index.html"],
"css": ["css/style.css"],
"js": ["js/app.js"]
}
]
}
app.js -
(function () {
var text = document.getElementById("content").innerHTML;
var saveAsButton = document.getElementById("saveas");
function errorHandler() {
return null;
}
saveAsButton.addEventListener('click', function(e) {
chrome.fileSystem.chooseEntry({type: 'saveFile'}, function(writableFileEntry) {
writableFileEntry.createWriter(function(writer) {
writer.onerror = errorHandler;
writer.onwriteend = function(e) {
console.log('write complete');
};
writer.write(new Blob([text], {type: 'text/plain'}));
}, errorHandler);
});
});
})();
index.html -
<html>
<head>
<title>note-in-chrome</title>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<button id="saveas">SAVE AS</button>
<div id="content" contenteditable="true" data-text="Enter text here"></div>
<script src="js/app.js"></script>
</body>
</html>
Whenever I click the SAVE AS button, a prompt to choose a file should open, but I get the following error - Uncaught TypeError: Cannot read property 'chooseEntry' of undefined.
The chrome.fileSystem API is available to Chrome apps, but not to Chrome extensions.

Chrome Extension -> ExecuteScript: function call doesn' work

He is my manifest.json:
{
"name": "Page Redder",
"description": "Make the current page red",
"version": "2.0",
"permissions": [
"activeTab","*://*/*"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_icon" : "icon.png",
"default_title": "Make this page red"
},
"manifest_version": 2
}
Here is background.js that works (the page becomes red):
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {code:'document.body.style.backgroundColor="red";'} );
});
If I change background.js in the following way, it fails to work:
function changeColor() {
document.body.style.backgroundColor="red";
}
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {code:';'}, function() {
changeColor();
});
});
Chrome build: 38.0.2125.111
The question: what am I doing wrong here? Why calling a function in executeScript doesn't work?
Thanks,
Racoon
You are not calling a function in executeScript.
You are calling the function in its callback, that runs in the original (background) page. It's a function describing "what to do when executeScript finishes", not the code to run.
The code that actually runs in the page you're injecting code to is ";" (which obviously does nothing).
You can run a function defined in your code with executeScript by properly converting it into a string. But note that it will not have any access to variables defined outside the function.
I think what you're trying to do is to make the code accept a parameter (color). Instead of crafting custom code each time, you should consider using Messaging to pass a command.
Example: add a file content.js with the following:
// Include guard: only execute once
if (!injected) {
injected = true;
init();
}
function init() {
// Get ready to receive a command
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if(message.action == "colorBackground") {
document.body.style.backgroundColor = message.color;
}
});
}
And in your background, you can do this:
chrome.tabs.executeScript(null, {file: "content.js"}, function() {
// File executed, it's ready for the message
chrome.tabs.sendMessage(null, { action: "backgroundColor", color: "green" });
}

Categories

Resources