setTimeout to chrome.scripting.executeScript - javascript

I was trying to set Timeout to my extension popup .I see after the work is done, it doesn't get automatically closed until clicked on somewhere on the page. I was trying to set timeout for auto closing of my extension popup. Below is my code.
a.addEventListener("click", async () => {
button.style.backgroundColor = 'white';
document.getElementById("button").style.backgroundColor = 'white';
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: codeWork,
});
});
I followed many suggestions available but it is throwing the error shown in Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in Content Security Pol
Please help me on how to set timer to my popup function.
Also my func:codeWork return response. The response might contain error. I want to change the color of the button based on the response . How to do that ?
Any help is really appreciated!!!!

This is the answer to the first question.
This sample popup will automatically close after 10 seconds.
popup.js
const elmCounter = document.getElementById("counter");
counter();
async function counter() {
for (let i = 0; i < 10; i++) {
elmCounter.innerText = i;
await new Promise(r => setTimeout(r, 1000));
}
window.close();
}
popup.html
<!DOCTYPE html>
<html>
<body>
<div id="counter">
<script src="popup.js"></script>
</body>
</html>
manifest.json
{
"name": "hoge",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html"
}
}

This is the answer to the second question.
popup.js
const elmExec = document.getElementById("exec");
elmExec.onclick = async () => {
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
await chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
func: func
});
}
const func = () => {
const color = ["red", "blue", "green"];
const getRandomInt = (max) => {
return Math.floor(Math.random() * max);
}
chrome.runtime.sendMessage({ color: color[getRandomInt(3)] });
}
chrome.runtime.onMessage.addListener((message) => {
elmExec.style.backgroundColor = message.color;
});
popup.html
<!DOCTYPE html>
<html>
<body>
<div id="counter">
<input type="button" id="exec" value="exec">
<script src="popup.js"></script>
</body>
</html>
manifest.json
{
"name": "hogehoge",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"activeTab",
"scripting"
],
"action": {
"default_popup": "popup.html"
}
}

Related

Getting active tab and generating confirm window

I'm trying to develop extension that gets active tab and generate confirm window at current open tab. But I cannot do this with "window.confirm" because window is not defined. Here's my code:
BACKGROUND.JS
var notifyTimer = setInterval(func,5*1000);
console.log('setinterval ran');
function func(){
let ActiveTab = getCurrentTab();
console.log(ActiveTab)
}
async function getCurrentTab() {
let queryOptions = { active: true, lastFocusedWindow: true };
let [tab] = await chrome.tabs.query(queryOptions);
console.log(tab.url)
//alert(" Hello!")
// SOME CODE TO GENERATE CONFIRM WINDOW or ALERT
return tab;
}
Currently it's fetching current active tab but I don't know how to generate confirm window
Kindly help me to generate alert with this code.
Is this what you want to do?
manifest.json
{
"name": "hoge",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting"
],
"host_permissions":[
"<all_urls>"
],
"background": {
"service_worker": "background.js"
}
}
background.js
var notifyTimer = setInterval(func, 5 * 1000);
console.log('setinterval ran');
function func() {
let ActiveTab = getCurrentTab();
console.log(ActiveTab)
}
const alert = () => {
alert(" Hello!");
}
async function getCurrentTab() {
let queryOptions = { active: true, lastFocusedWindow: true };
let [tab] = await chrome.tabs.query(queryOptions);
console.log(tab.url)
//alert(" Hello!")
// SOME CODE TO GENERATE CONFIRM WINDOW or ALERT
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: alert
});
return tab;
}

Send message to background.js from options.js in Chrome Extension

I can find plenty of questions for sending a message from Bbackground to content scripts or from popup to background scripts, but I can't find any on how to send a message from options.js (triggered from my options page) to background.js for my Chrome extension
manifest.js
{
...
"manifest_version": 3,
"permissions": [
"alarms",
"contextMenus",
"notifications",
"storage"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
},
"options_page": "options.html",
"icons": {
"48": "/assets/icons/icon-48.png",
"128": "/assets/icons/icon-128.png"
}
}
Code in options.js
// Save options
document.querySelector('#save').addEventListener('click', ()=> {
// Check for selected regions
let selectedRegions = [];
regionChecks.forEach(elm => {
if (elm.checked)
selectedRegions.push(elm.id.replace('region-', ''))
});
// Save selections
chrome.storage.sync.set({ 'regions': selectedRegions });
// Check for refresh period
let refreshPeriod = document.querySelector('#refresh');
if (refreshPeriod) {
refreshPeriod = parseInt(refreshPeriod.value);
if (refreshPeriod === NaN) {
refreshPeriod = 5;
} else if(refreshPeriod < 2) {
refreshPeriod = 2;
} else if (refreshPeriod > 120) {
refreshPeriod = 120;
}
// Save period
chrome.storage.sync.set({ 'refresh': refreshPeriod });
}
// Loop through features and remove if region gone
chrome.storage.local.get(['features'], featuresData => {
let featureCount = 0;
if (featuresData.features) {
featureSet = featuresData.features;
Object.keys(featureSet).forEach(key => {
if (!selectedRegions.includes(featureSet[key].Region)) {
delete featureSet[key];
} else if (featureSet[key].Status !== "read") {
featureCount = featureCount + 1;
}
});
// Update features data
chrome.storage.local.set({ 'features': featureSet });
// Update the badge
if (featureCount > 0) {
chrome.action.setBadgeText({ text: featureCount.toString() });
} else {
chrome.action.setBadgeText({ text: '' });
}
}
});
// Trigger an update
chrome.runtime.sendMessage('', {
type: 'update'
});
// Close the options page
close();
});
Code in background.js
// Listen for messages
chrome.runtime.onMessage.addListener(data => {
console.log(data);
if (data.type === 'update') {
scheduleRequest();
}
});
But nothing is happening
I've tried using tabs.sendMessage, but even if I put tabs in permissions it tells me that it isn't defined when I add it to the function chrome.tabs.sendMessage(tabs[0].id, {...
My test results contradict your claim.
manifest.json
{
"manifest_version": 3,
"name": "hoge",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"options_page": "options.html"
}
background.js
// Listen for messages
chrome.runtime.onMessage.addListener(data => {
console.log(data);
if (data.type === 'update') {
console.log("hoge")
// scheduleRequest();
}
});
options.js
// Trigger an update
chrome.runtime.sendMessage('', {
type: 'update'
});
options.html
<html>
<body>
options page
<script src="options.js"></script>
</body>
</html>
After some input from #woxxom and #Norio, and a little bit more troubleshooting, this is how I managed to get it to work
option.js:
// Trigger an update
chrome.runtime.sendMessage({ type: 'update' }, result => {
// Close the options page
close();
});
I had to move the close(); event into the return function so it didn't prematurely close off the code. I also had to have a paramter in the return function for some reason otherwise it wouldn't run with an empty arrow function.
background.js:
// Listen for messages
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'update') {
startRequest(true).then(sendResponse);
return true;
}
});
My function to be triggered in the background.js file was already an async promise function, so I had to add a .then() for the onMessage response function to trigger once it had run. It also wouldn't work without having return true; in there.

beginner to chrome extension

I am trying to learn chrome extensions and I am trying to build a simple one which tries to find if there are forms or not in webpage.
My code is as simple as possible and the following snippet is content script - javascript.js and popup page - index.html.
function sendMessage() {
chrome.extension.sendMessage({
action: "findurls"
});
}
document.addEventListener('DOMContentLoaded', function () {
var show = document.getElementById('show');
show.addEventListener('click', findValidForms);
});
const findValidForms = () => {
let list = [];
let message = "Available forms are: \n ";
let forms = document.querySelectorAll('form');
if (forms.length > 0) {
for (var i = 0; i < forms.length; i++) {
list.push(forms[i].action);
message += `${list[i]}<br />`;
}
}
else {
message = "no forms";
}
alert(message);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>testing</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="cgi">
<div class="heading">
<h3 center> Test title </h3>
</div>
<div id='ah!'> </div>
<button id='show'>find forms</button>
<script src="jquery-3.5.0.min.js"></script>
<script type="text/javascript" src="javascript.js"></script>
</body>
</html>
manifest:
"manifest_version": 2,
"name": "form",
"version": "1.0",
"description": "find form url ",
"icons": {
"16": "chrome_16.png",
"32": "chrome_32.png"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"javascript.js",
"jquery-3.5.0.min.js"
],
"css": [
"style.css"
]
}
],
"browser_action": {
"default_icon": "chrome_16.png",
"default_popup":"index.html",
"default_title": "test"
},
"permissions": [
"activeTab"
]
}
background.js:
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse)
{
if (request.action == "findurls")
chrome.tabs.executeScript({ file: 'test.js' });
}
);
Thanks
Clicked the button placed in index.html, the extension should send a message to content script - javascript.js in your solution. So the content script needs a event listener that monitors the message triggered from background script. Once it's arrived, the corresponding method should be executed.
Here is the quick link to resolve but let me briefly describe here.
Create a js file (ie index.js) and inject into your index.html. (honestly, popup.html and popup.js will be better than the current name - index). Give this code into the index.js
In your content script - index.js, add the code to listen message sent from the popup page's script (index.js) with handler the current function you created. (Original function name was Forms)
popup.js
const sendMessage = () => {
chrome.tabs.query(
{
active: true,
currentWindow: true
}, (tabs) => {
chrome.tabs.sendMessage(
tabs[0].id,
{
action: "get-urls"
}, (response) => {
console.log(response)
}
);
}
);
}
document.addEventListener('DOMContentLoaded', function () {
var geturls = document.getElementById('btn-get-urls');
geturls.addEventListener('click', sendMessage);
});
content_script.js
const FindAllForms = () => {
let list = [],
message = "Available forms are: \n ",
availableForms = document.querySelectorAll('form');
if (availableForms.length > 0) {
for (var i = 0; i < availableForms.length; i++) {
list.push(availableForms[i].action);
message += "" + list[i] + "" + "\n";
}
}
else {
message = "no forms";
}
alert(message);
}
chrome.extension.onMessage.addListener(
(request, sender, sendResponse) => {
if (request.action == "get-urls") {
FindAllForms()
sendResponse({'success': true})
}
}
);
In the popup script, you should send a message to current/active tab's content script as this answer.
I hope this will help you.
Thank you

Chrome extension getSelection not working

I am trying to create a chrome extension which only consist of a button. When this button is clicked, it should make an alert box which contains the highlighted textarea on a page. I can't get it to work. I can make it alert a hardcoded string, but not make it alert some highlighted text / selected textarea on a page.
Here is the javascript code popup.js:
document.addEventListener('DOMContentLoaded', function() {
test.addEventListener('click', function() {
var selObj = document.getSelection();
alert(selObj);
}, false);
}, false);
manifest.json
{
"manifest_version": 2,
"name": "test ",
"description": "test",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"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="test">Test</button>
</body>
</html>
You could fetch the selection by loading a script into the page using the executeScript method in the Tabs API. You may have to add the tabs permission to your manifest.json.
To execute the script you first need to fetch the tab ID, you can do that using query and querying on fetching the active tab in the current window.
document.addEventListener('DOMContentLoaded', function() {
const test = document.querySelector('#test');
test.addEventListener('click', function() {
chrome.tabs.query({ currentWindow: true, active: true }, (tabs) => {
chrome.tabs.executeScript(tabs[0].id, { code: `document.getSelection().toString()` }, (result) => {
alert(result);
});
});
});
});

Removing the injected script through the chrome extension

I'm building a chrome dev tool extension to capture page elements and store. For now, I'm able to capture the page element by using click method in the content script which I've injected. To send the captured element from content script to background script, I used stopPropagation and preventDefault methods to disable the click event on the element.
Problem Statement: Now I would like to revert to the element's default event after selecting an element. This is where I'm stuck on how to revert back.
manifest.json:
{
"name": "My app",
"version": "0.0.1",
"description": "My app",
"manifest_version": 2,
"devtools_page": "devtools.html",
"background": {
"scripts": [
"background.js"
]
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"file://*/*"
]
}
The devtools.html has devtools.js script which creates the new tab panel in chrome dev tools and loads the panel.html.
panel.html:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<button id="insertscript">Insert script</button>
<button id="clearscript">Clear Script</button>
<input type="text" id="tagName" />
<script src="panel.js"></script>
<script src="background.js"></script>
</body>
</html>
panel.js:
(function createChannel() {
var port = chrome.extension.connect({
name: "Sample Communication" //Given a Name
});
port.onMessage.addListener(function (message) {
document.querySelector('#tagName').value = message.tagName;
});
}());
function sendObjectToInspectedPage(message) {
message.tabId = chrome.devtools.inspectedWindow.tabId;
chrome.extension.sendMessage(message);
}
document.querySelector('#insertscript').addEventListener('click', function() {
sendObjectToInspectedPage({action: "script", content: "selectitem.js"});
}, false);
document.querySelector('#clearscript').addEventListener('click', function() {
sendObjectToInspectedPage({action: "clear-script", content: "clearscript.js"});
}, false);
background.js:
chrome.extension.onConnect.addListener(function (port) {
var extensionListener = function(message, sender, sendResponse) {
if (message.tabId && message.content) {
// Attach a script to inspected page
if (message.action === "script") {
chrome.tabs.executeScript(message.tabId, {file: "assets/jquery-2.0.3.js"});
chrome.tabs.executeScript(message.tabId, {file: message.content});
} else if (message.action === "clear-script") {
chrome.tabs.executeScript(message.tabId, {code: "document.removeEventListener('click', onClick);"});
}
} else {
port.postMessage(message);
}
if (message.type === "selectedElement") {
sendResponse(message);
}
};
chrome.extension.onMessage.addListener(extensionListener);
port.onDisconnect.addListener(function(port) {
chrome.extension.onMessage.removeListener(extensionListener);
});
});
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
return true;
});
selectitem.js:
function onClick(evt) {
evt.stopPropagation();
evt.preventDefault();
var elem = document.elementFromPoint(evt.clientX, evt.clientY);
chrome.extension.sendMessage({
type: "selectedElement",
tagName: elem.tagName
});
}
document.addEventListener('click', onClick, true);
Now when I click on Clear script method, I wanted to remove the stopPropagation and preventDefault which I added in selectitem.js. Because the element which I've selected could be an Anchor tag or Button or can be anything which is clickable.
I don't know on how to do this.
I found the solution with the help of this script: https://github.com/oldprojects/Simple-JavaScript-DOM-Inspector/blob/master/inspector.js
Thought this might be helpful for anyone, hence adding this as an answer.

Categories