I would like to implement a hotkey that triggers a function in my content script.
The content script (main.js) is executed on page laod from my popup.js file.
i have added the command into my manifest.json and when I add the onCommand listener to my popup.js I can console log that it gets triggered when I press my hotkey (Ctrl+Shift+K)
However I can not get it passed to my content script.
manifest.json
{
"manifest_version": 2,
"name": "Ccghjj",
"description": "hdjdjdjsjs",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "*storage", "activeTab"],
"content_scripts": [
{
"matches": ["*://"],
"css": ["style.css"],
"js": ["jquery.js", "main.js"]
}
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'",
"web_accessible_resources": ["toolbar.html", "style.css"],
"commands": {
"show_deals": {
"suggested_key": {
"default": "Ctrl+Shift+K"
},
"description": "Highlight Deals"
}
}
}
popup.js
function registerButtonAction(tabId, button, action) {
// clicking button will send a message to
// content script in the same tab as the popup
button.addEventListener('click', () => chrome.tabs.sendMessage(tabId, { [action]: true }));
}
function setupButtons(tabId) {
// add click actions to each 3 buttons
registerButtonAction(tabId, document.getElementById('start-btn'), 'startSearch');
registerButtonAction(tabId, document.getElementById('deals-btn'), 'startDeals');
registerButtonAction(tabId, document.getElementById('stop-btn'), 'stopSearch');
}
function injectStartSearchScript() {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
// Injects JavaScript code into a page
// chrome.tabs.executeScript(tabs[0].id, { file: 'main.js' });
// add click handlers for buttons
setupButtons(tabs[0].id);
});
}
injectStartSearchScript();
// hotkey command listener
chrome.commands.onCommand.addListener((show_deals) => {
console.log(`Command "${show_deals}" triggered`);
// how can I get to main.js to call deals()
});
main.js (content script)
async function deals() {
// should be fired when I press my hotkey Ctrl+Shift+K
Use messages like below
popup.js
chrome.commands.onCommand.addListener((show_deals) => {
console.log(`Command "${show_deals}" triggered`);
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tab.id, { msg: "deals"})
})
});
and in your content script
if (!window.firstTimeExecuted) {
window.firstTimeExecuted = true;
chrome.runtime.onMessage.addListener((data, sender, sendResponse) => {
if (data.msg == 'deals') {
deals()
}
});
}
Related
I want to be able to click my icon and fill my form with N/A's as shown in my content.js:
chrome.runtime.onMessage.addListener(
function(sendResponse) {
try {
document.getElementById("Note_2").value = "N/A";
document.getElementById("Note_3").value = "N/A";
document.getElementById("Note_4").value = "N/A";
sendResponse({status: "Success!"});
} catch (error) {
console.log(error)
sendResponse({status: "Exception occurred!"});
}
}
);
This is my background.js:
chrome.runtime.onInstalled.addListener(async () => {
let url = chrome.runtime.getURL("welcome/hello.html");
let tab = await chrome.tabs.create({ url });
console.log(`Created tab ${tab.id}`);
});
script.js:
/* Auto fill form */
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
}, function(response) {
console.log(response.status);
});
});
});
and lastly, my manifest.json:
{
"name": "LBOT",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "welcome/background.js"
},
"action": {
"default_popup": "ext/index.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"permissions": ["storage","activeTab","declarativeContent"]
}
I've tried various combinations of
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "testScript.js"});
});
and
chrome.action.onClicked.addListener(function (tab) {
console.log("Hello")
});
am struggling to wrap my head around this. How can I modify the extension so that when I click on the icon, it populates? I'd prefer to get rid of the button/gui all together. Hope you can help.
I am working on a google chrome extension project where content.js script sends message to popup.js. Also trying to get some text from content.js to be turned into the same thing but on popup.js. Here is all my code.
This is my manifest file.
manifest.json
{
"name": "hoko's ext",
"description": "my ext",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["https://*/*", "http://*/*"],
"js": ["content-script.js"]
}
],
"background": {
"service_worker": "background.js"
},
"permissions": [
"tabs",
"activeTab"
]
}
This is the popup you get when you click on the icon in the toolbar.
popup.html
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>I am the popup</h1>
<p id="extensionpopupcontent"></p>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
This is my content script called content-script.js
function injectScript(file_path, tag) {
var node = document.getElementsByTagName(tag)[0];
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', file_path);
node.appendChild(script);
}
injectScript(chrome.runtime.getURL('inject.js'), 'body');
chrome.runtime.sendMessage(document.getElementsByTagName('title')[0].innerText);
In background.js, I am receiving the message from content-script.js.
chrome.runtime.onMessage.addListener(function(response, sender, sendResponse) {
function onMessage(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello") {
sendResponse({farewell: "goodbye"});
}
}
})
In popup.js, it is receiving from background.js to output the code from content-script.js.
window.addEventListener('DOMContentLoaded', () => {
let bg = chrome.extension.getBackgroundPage();
chrome.tabs.query({active: true, currentWindow: true}, tabs => {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
document.getElementById('extensionpopupcontent').innerHTML = response;
});
});
});
I believe I need to inject this script that is inject.js.
function click() {
return document.getElementsByTagName('title')[0].innerText;
}
click();
remove background and content_scripts in manifest.json
remove tabs from permissions in manifest.json
remove background.js, content-script.js, and inject.js
rewrite popup.js as follows:
chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
document.getElementById('extensionpopupcontent').textContent = tabs[0]?.title;
});
The Manifest V3 JavaScript Chrome extension only has one button. When the button is clicked the browser should go to multiple pages and perform an action on each page before going to the next one.
What's currently happening, is the browser jumping to the last page and not performing any action.
How to fix my code, so that the extension visits each page one by one (in the same tab), then waits on the page until a button is detected, clicks the button, checks if the button is clicked, and then goes to the next page?
Manifest.json:
{
"name": "Twitch Follower",
"version": "0.1",
"manifest_version": 3,
"description": "Automatically follows Twitch users.",
"action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"tabs",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"host_permissions": [
"https://www.twitch.tv/*"
]
}
popup.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css#2/out/water.css">
</head>
<body>
<button id="start">Start</button>
<script src="popup.js"></script>
</body>
</html>
popup.js:
start.addEventListener("click", async () => {
chrome.runtime.sendMessage({ start: true });
});
background.js:
const list = ["https://www.twitch.tv/hello1", "https://www.twitch.tv/hello2"];
function clickFollow() {
document.querySelector("button[data-a-target='follow-button']").click();
}
function handleFollowButton(followButton) {
setTimeout(clickFollow, 1000);
}
// Check for a button
async function checkButton() {
const findButton = new Promise((resolve, reject) => {
const observerConfig = { attributes: true, attributeOldValue: true };
const observer = new MutationObserver((mutations) => {
const followButton = document.querySelector("button[data-a-target='follow-button']");
const unfollowButton = document.querySelector("button[data-a-target='unfollow-button']");
// If follow button is found, click it
if (followButton) {
handleFollowButton(followButton);
}
// If unfollow button is found, end observing and continue
if (unfollowButton) {
unfollowButtonFound = True;
observer.disconnect();
resolve;
}
});
window.setTimeout(() => {
if (!unfollowButtonFound) {
reject;
}
}, 5000);
observer.observe(document, {
childList: true,
subtree: true,
});
});
await findButton;
return true;
}
// When the start button is clicked
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.start === true) {
// Loop through every link
for (const link of list) {
console.log(link);
// Open the link and inject the script
chrome.tabs.update({ url: link }, (tab) => {
chrome.scripting.executeScript(
{
target: { tabId: tab.id },
func: checkButton,
},
(result) => {
console.log(results);
}
);
});
}
}
});
All I am trying to do change the value of popup.html on the basis of Specific URL. So I am sending message to background.js when user click on change ID of H2 from popup.html render the content by using specific JavaScript file
manifest.json
{
"manifest_version": 2,
"name": "Helpfullio",
"version": "0.1",
"content_scripts": [{
"matches": [
"*://google.com/*/*",
],
"js": ["jquery-3.2.1.js"]
}],
"browser_action": {
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
},
"permissions": ["tabs","http://*/*", "https://*/*"]
}
popup.html
<html>
<head>
</head>
<body>
<h2 id="change">Change ___________</h2>
<script src="popup.js"></script>
</body>
</html>
popup.js
function clickHandler(e) {
chrome.runtime.sendMessage({directive: "popup-click"}, function(response) {
// this.close(); finishes processing request
});
}
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('change').addEventListener('click', clickHandler);
})
background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.directive) {
case "popup-click":
chrome.tabs.query({
'active': true, 'lastFocusedWindow': true
}, function (tabs) {
var url = tabs[0].url;
var result = url.split('/');
var hostname = result[2];
if("bitlock" == hostname){
chrome.tabs.executeScript(null, {
file: "render.js",
// allFrames: true
});
}else{
hrome.tabs.executeScript(null, {
file: "secondrender.js",
// allFrames: true
});
}
sendResponse({});
});
break;
default:
alert("Unmatched request of '" + request + "' from script to background.js from " + sender);
}
}
);;
JavaScript doesn't render the content of popup.html as it is not finding the elementID "change" . SO here how can I give reference of popup.html file in render.js file
render.js
document.getElementById("change").textContent = 'new text';
Im trying to send message to Background, and as well receive back to content script.
This is my content_script.js
init();
function init() {
function notifyBackgroundPage(event) {
chrome.runtime.sendMessage(chromeExtID, {
greeting: "Greeting from the content script"
});
}
window.addEventListener("click", notifyBackgroundPage);
// accept messages from background
// below line addListener is undefined
chrome.runtime.onMessage.addListener(function backgroundListener(request, sender, sendResponse) {
console.log("BgExt.js says: " + request);
});
}
BgExt.js
define([], function GmailExt() {
return {
start: function () {
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
console.log('inside response');
// to send back your response to the current tab
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {farewell: response}, function (response) {
});
});
return true;
}
);
}
};
});
This GmailExt file is loaded inside all.js (while all.js is inserted in index.html)
require([
"base_host/chrome/Server",
"kernel/Kernel",
"hydra/version",
"base_host/chrome/StartupConfig",
"hydra/apps",
"dojo/_base/Deferred",
"talkto_util/common",
"dojo/i18n!base_host/nls/CommonStrings",
"base_host/chrome/BgExt",
"dojo/domReady!"
], function (Server, Kernel, version, StartupConfig, apps, Deferred, talktoUtil, nls, BgExt) {
document.getElementById("logoMessage").innerText = nls.simple_secure_text;
var host = new Server();
//if app and not extension
chrome.browserAction && chrome.browserAction.onClicked.addListener(function() {
Deferred.when(kernel.onInit(), function () {
host.appManager.showShell();
});
return true;
});
BgExt.start();
});
client_base/host/chrome/index.html
<!DOCTYPE HTML>
<html>
<head>
<!-- Background Page for Extension/app -->
<title>Flock</title>
<meta charset="UTF-8">
<!--BUILD_REPLACE_BLOCK_START-->
<!-- This block will be remove by build.
All the files from libs/common/files.txt would be prepended to dojo.js -->
<script type="text/javascript" src="../../../hydra/src/libs/common/dojoConfig.js"></script>
<script type="text/javascript" src="../../../hydra/src/libs/common/underscore.js"></script>
<script type="text/javascript" src="../../../hydra/src/libs/common/underscore-ext.js"></script>
<!--BUILD_REPLACE_BLOCK_END-->
<script type="text/javascript" src="../../../hydra/src/libs/dojotoolkit/dojo/dojo.js"></script>
<script type="text/javascript" src="all.js"></script>
</head>
<body>
</body>
</html>
Manifest.json
{
"manifest_version": 2,
"content_security_policy": "script-src 'self' 'unsafe-eval' https://j.maxmind.com https://ssl.google-analytics.com https://flock-apps.flock.co https://flock-apps.flock-staging.co https://flock-apps.flock.com https://flock-apps.flock-staging.com; object-src 'self'",
"minimum_chrome_version": "22",
"options_page": "client_base/host/chrome/static/crx_browser_actions/index.html?app=preferences",
"name": "__MSG_extName__",
"description": "__MSG_extDescription__",
"background": {
"page": "client_base/host/chrome/index.html",
"persistent": true
},
"browser_action": {
"default_popup": "/gmail_ext/popup.html"
},
"web_accessible_resources": [
"client_base/host/chrome/static/blank.gif",
"gmail_ext/icons.png",
"gmail_ext/jquery-3.2.1.min.js",
"gmail_ext/gmail.js",
"gmail_ext/content_script.js"
],
"permissions": [
"<all_urls>",
"unlimitedStorage",
"notifications",
"idle",
"background",
"tabs",
"activeTab"
],
"optional_permissions": [
"clipboardWrite"
],
"externally_connectable": {
"matches": [
"https://*.google.com/*",
"http://localhost/*",
]
},
"content_scripts": [
{
"matches": [
"*://mail.google.com/*"
],
"css": [
"/gmail_ext/content_script.css"
],
"js": [
"/gmail_ext/loader.js"
],
"run_at": "document_end"
}
],
"version": "1.0"
}
I fixed it. The Solution was since I was using loader.js to load my content script and jquery via chrome.extension.getURL('/gmail_ext/content_script.js');
And was using "content_script.js" as a web_accessible_resources only loader.js had access to chrome object.
And yes, its a Dojo project, you can see the Working Extension here : https://chrome.google.com/webstore/detail/flock-chat-for-teams-and/enfaahabcinohafeakbliimmoholjeip?hl=en
I'm using page events now as showed here : https://developer.chrome.com/extensions/content_scripts#host-page-communication
At the top of loader.js I added below:
function initPort() {
var contentScriptPort,
chromeExtID = "lddaepjihbpbfpegjhjnkffjmmoigphe";
contentScriptPort = chrome.runtime.connect(chromeExtID);
contentScriptPort.onMessage.addListener(function (message) {
// Send data back to content script received from Background.
window.postMessage({type: "FROM_BACKGROUND", emails: message}, "*");
});
window.addEventListener("message", function _postMessage(event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE")) {
// console.log("Content script received: " + event.data.emails);
contentScriptPort.postMessage(event.data);
}
}, false);
}
initPort();