Referencing this post, I am trying to use executeScript or sendMessage to pass a variable to my content.js file. Using Chrome dev tools, I see that it is reaching my content.js file, and it also runs the test alert I insert, but when it gets to the
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
it skips it entirely. I'm not sure what is happening here?
popup.js
function search() {
var name = document.getElementById('txtSearch').value;
chrome.tabs.executeScript({ file: "jquery.js" }, function () {
chrome.tabs.executeScript(null, {
code: 'var name = ' + name + ';'
}, function () {
chrome.tabs.executeScript({ file: 'content.js' });
});
});
}
document.getElementById('btnSearch').addEventListener('click', search);
or popup.js using sendMessage
function search() {
var name = document.getElementById('txtSearch').value;
chrome.tabs.executeScript({ file: "jquery.js" }, function () {
chrome.tabs.executeScript({ file: 'content.js' }, function () {
chrome.tabs.sendMessage({ name: name });
});
});
}
document.getElementById('btnSearch').addEventListener('click', search);
content.js
alert('hi');
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
console.log(message.name);
});
Referencing a different answer I found on SO (cant find it atm), I was missing a function to pass the tab id to the content script.
chrome.tabs.query({ active: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {'type': type, 'name': name });
});
Related
In manifest v2 this code worked and injected the script when button was clicked:
popup.js v2 (works)
document.addEventListener('DOMContentLoaded', function () {
// Get button by ID
var button = document.getElementById('btnScan');
// Define button on click action
button.onclick = function () {
chrome.tabs.executeScript(null, {
file: 'Scripts/script.js'
});
window.close();
}
});
Now in manifest v3, chrome.tabs.executeScript is replaced with chrome.scripting.executeScript.
scripting permission is added in manifest.json.
popup.js v3 (not working)
document.addEventListener('DOMContentLoaded', function () {
// Get button by ID
var button = document.getElementById('btnScan');
// Define Scan button on click action
button.onclick = function () {
chrome.scripting.executeScript
(
{
target: { tabId: null}, // ???????
files: ['Scripts/script.js']
}
);
window.close();
}
});
The problem is that chrome.tabs.executeScript requires tabId value as one of the parameters.
How can I get tabId value in popup.js or convert the manifest v2 version javascript so that it works the same?
Thanks to #wOxxOm who posted a link as a comment.
The solution was to get the active tab and use its tabId.
document.addEventListener('DOMContentLoaded', function () {
// Get button by ID
var button = document.getElementById('btnScan');
button.onclick = injectScript;
});
async function injectScript() {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
await chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ['Scripts/script.js']
});
window.close();
}
I want to make a simple browser extension like Font Face Ninja which toggles UI when page_action or browser_action is clicked.
The following code using browser_action works -
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
console.log(`clicked browserAction`)
})
manifest.json
{
...
"browser_action": {
"default_icon": {
"19": "icon19.png",
"38": "icon38.png"
}
},
...
}
While the following code using page_action does not work -
background.js
chrome.pageAction.onClicked.addListener(function(tab) {
console.log(`clicked pageAction`)
})
manifest.json
{
...
"page_action": {
"default_icon": {
"19": "icon19.png",
"38": "icon38.png"
}
},
...
}
According to MDN docs,
Page actions are like browser actions, except that they are associated with particular web pages rather than with the browser as a whole. If an action is only relevant on certain pages, then you should use a page action and display it only on relevant pages. If an action is relevant to all pages or to the browser itself, use a browser action.
Which confirms I want to use page_action but its not working.
How do I make it work using page_action?
Page Action
A way to make page_action work can be found on my Github → https://github.com/deadcoder0904/insert-remove-ui-chrome-extension/tree/page_action
background.js
var hasExecutedOnce = false
function addUI(tabId) {
chrome.tabs.sendMessage(tabId, {
from: 'background',
subject: 'isUIAdded?',
})
}
chrome.runtime.onInstalled.addListener(function() {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: 'www.google.co.in' },
}),
],
actions: [new chrome.declarativeContent.ShowPageAction()],
},
])
})
})
chrome.pageAction.onClicked.addListener(function(tab) {
if (!hasExecutedOnce) {
chrome.tabs.executeScript(
tab.id,
{
file: 'contentScript.js',
},
function() {
addUI(tab.id)
},
)
hasExecutedOnce = true
}
addUI(tab.id)
})
contentScript.js
var body = document.getElementsByTagName('body')[0]
function insertUI() {
var div = document.createElement('div')
div.setAttribute('id', 'sample-extension-12345')
div.innerHTML = `<h1>Sample Extension</h1>`
body.appendChild(div)
}
function removeUI() {
document.getElementById('sample-extension-12345').remove()
}
function main() {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.subject === 'isUIAdded?') {
const id = document.getElementById('sample-extension-12345')
if (id === null) insertUI()
else removeUI()
}
})
}
main()
Browser Action
It also has a solution for browser_action on the master branch → https://github.com/deadcoder0904/insert-remove-ui-chrome-extension/
background.js
var hasExecutedOnce = false
function addUI(tabId) {
chrome.tabs.sendMessage(tabId, {
from: 'background',
subject: 'isUIAdded?',
})
}
chrome.browserAction.onClicked.addListener(function(tab) {
if (!hasExecutedOnce) {
chrome.tabs.executeScript(
tab.id,
{
file: 'contentScript.js',
},
function() {
addUI(tab.id)
},
)
hasExecutedOnce = true
}
addUI(tab.id)
})
contentScript.js
var body = document.getElementsByTagName('body')[0]
function insertUI() {
var div = document.createElement('div')
div.setAttribute('id', 'sample-extension-12345')
div.innerHTML = `<h1>Sample Extension</h1>`
body.appendChild(div)
}
function removeUI() {
document.getElementById('sample-extension-12345').remove()
}
function main() {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.subject === 'isUIAdded?') {
const id = document.getElementById('sample-extension-12345')
if (id === null) insertUI()
else removeUI()
}
})
}
main()
enerytime when i click the "send" button(blind the NativeMessaging method),it will launch a new instance , i just want make it only one instance with the connect running correctly,sot that i can send message sustainable.
Thanks a lot!
That's my background.js code:
var port = null;
console.log("visited test!");
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.type == "launch") {
console.log("visited 333!");
connectToNativeHost(request.message);
}
return true;
});
// chrome.runtime.onMessage.addListener(function(msg) {
// console.log("Received" + msg.text);
// });
//onNativeDisconnect
function onDisconnected() {
console.log(chrome.runtime.lastError);
console.log('disconnected from native app.');
port = null;
}
function onNativeMessage(message) {
console.log('recieved message from native app: ' +JSON.stringify(message));
}
//connect to native host and get the communicatetion port
function connectToNativeHost(msg) {
var nativeHostName = "com.example.test";
// console.log(typeof(nativeHostName));
// console.log(nativeHostName);
//port = chrome.runtime.connectNative(nativeHostName);
port = chrome.runtime.sendNativeMessage(nativeHostName,{ message: msg });
port.onMessage.addListener(onNativeMessage);
port.onDisconnect.addListener(onDisconnected);
port.postMessage({ message: msg });
}
That's my content.js code:
var launch_message;
document.addEventListener('myCustomEvent', function (evt) {
console.log("visited!");
chrome.runtime.sendMessage({ type: "launch", message: evt.detail }, function (response) {
console.log(response);
// console.log("visited here!");
});
}, false);
That's my test HTML file code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test Communicate with native app</title>
<script>
function startApp() {
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent('myCustomEvent', true, false, "im information");
// fire the event
document.dispatchEvent(evt);
console.log("The button was clicked!");
}
</script>
</head>
<body>
<button type="button" onclick="startApp()" id="startApp">startApp</button>
</body>
</html>
and i write the demo native application use C# language.
I should send data from my devtools panel to tab. When I send a message using chrome.tabs.sendMessage, why is it not received?
panel.js
$(".options").on("submit", "form", function(e) {
e.preventDefault();
newTabPort = chrome.runtime.connect({ name: "new tab" });
newTabPort.postMessage($(this).serializeArray());
});
background.js
chrome.runtime.onConnect.addListener(function(port) {
port.onMessage.addListener(function(message) {
console.log(message);
});
if (port.name == "new tab") {
chrome.tabs.create({'url': chrome.extension.getURL('page/request_sending_page.html')}, function(tab) {});
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {message: "olololololololo"});
});
}
});
my_extension_page.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
$("body").append("Hello world <br>");
$("body").append(request.message);
});
Thank you!
All Chrome API with function callbacks are asynchronous, so in your code chrome.tabs.create is executed after the entire function code has completed, thus chrome.tabs.query on the next line doesn't see the newly created tab.
Move the code that should work with the result of the asynchronous call into the callback
Wait for the new tab to be completely loaded before sending the message
There's no need for chrome.extension.getURL when you open the tab from background script.
chrome.tabs.create({url: '/page/request_sending_page.html'}, function(tab) {
var newTabId = tab.id;
chrome.tabs.onUpdated.addListener(function onComplete(tabId, info, tab) {
if (tabId == newTabId && info.status == "complete") {
chrome.tabs.onUpdated.removeListener(onComplete);
chrome.tabs.sendMessage(tabId, {message: "olololololololo"});
}
});
});
P.S. manifest.json: "permissions": ["tabs"]
So guys let me explain this problem all the code works fine but the .click is not working am trying to make it click on the website button but for some reason its not clicking on it is this a bug or something?
Thank you very much.
CODE:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('status').textContent = "Going To Localhost";
chrome.tabs.query( { active: true, currentWindow: true }, function( tabs ) {
chrome.tabs.update( tabs[0].id, { url: "http://localhost/" } );
});
var button = document.getElementById("mybutton");
button.addEventListener("click", function() {
chrome.tabs.executeScript(null, {code: 'document.getElementById("username").value = "user";'}, function(){
chrome.tabs.executeScript(null, {code: 'document.getElementById("password").value = "pass";'}, function(){
chrome.tabs.executeScript(null, {code: 'var this_button = document.getElementsByClassName("btnLogin"); this_button.click();'}, function(){
});
});
});
}, false);
},function(errorMessage) {
alert(errorMessage);
});
getElementsByClassName (note the pluralization) returns a NodeList. So you'd need to access the first element like:
chrome.tabs.executeScript(null, {code: 'var this_button = document.getElementsByClassName("btnLogin"); this_button[0].click();'});
OR, modern browser that Chrome is, you can use querySelector instead:
chrome.tabs.executeScript(null, {code: 'var this_button = document.querySelector(".btnLogin"); this_button[0].click();'});