Popup HTML page doesnot show messages unless dev tools are open - javascript

I am trying to pass message from my content script to Chrome extension Popup HTML page.
The messages are rendered in the popup page only when I open dev tools. It works perfectly fine.
Here is the script:
Content JS:
chrome.runtime.sendMessage(message);
POP UP:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
{ document.getElementById("text").innerHTML+="<br\>"+request;
})
I have tried another approach to which it works but then messages in the popup page doesnot append.
So i am stuck in both the approach.
Content JS:
The "message" is based on few case conditions where it keeps changing and I want to append all the values and show it in the popup page, it works fine in 1st approach ,but here appending doesnot work.Only the 1st element shows up,other responses simply overwrite it.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "hello")
{
sendResponse({getmessage: message});}
});
POP Up page:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response)
{
const node = document.createElement("li");
const textnode = document.createTextNode(response.farewell);
node.appendChild(textnode);
document.getElementById("MyData").appendChild(node);
});
});
I have tried the two approaches mentioned in the description but I am stuck in both approach.
The first approach needs the dev tool to be opened first and the 2nd approach doesnot append the 2nd message to the 1st one while displaying data in the pop up page.

Pop up:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response)
{
const node = document.createElement("li");
const textnode = document.createTextNode(response.farewell);
node.appendChild(textnode);
document.getElementById("myList").appendChild(node);
});
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse)
{
document.getElementById("text").innerHTML+="<br\>"+request;
});
POPUP HTML:
<!DOCTYPE html>
<html>
<head>
<style>
body {
width: 300px;height: 100px
}
</style>
</head>
<body>
</input>
<div id="text"> </div>
<ul id="myList">
</ul>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
Content JS:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "hello")
{
sendResponse({farewell: "hello"});}
});
window.addEventListener('mouseup', ClickFunction);
function ClickFunction() {
const labels = document.getElementsByTagName("label");
let l=0;
for (const label of labels) {
label.addEventListener('click', function onClick()
{
txt = label.innerText;
b=this.text;
message='Field: '+txt+';';
console.log(message);
chrome.runtime.sendMessage(message);
});
}
}
Manifest:
{
"manifest_version": 3,
"name": "test1",
"version": "0.1",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"permissions": [
"storage",
"activeTab",
"scripting"
],
"action": {
"default_popup": "popup.html",
}
}

Related

use chrome extension to open another tab and do something in the DOM

I am trying to build a simple chrome extension to get a value from a page and populate a second page after.
I'm new to chrome extensions, and I'm really only doing this to make something I have to do often simpler.
So I got the part where I open the first page, get the value I need and then I open the second page in another tab. Now I'm not sure how to populate the field.
Since I already have the value on content.js, is it possible to know when the other tab has loaded to just look for the field where i need to put that value in? Or is there another way to do it? I can't get it to work.. I also tried to listen to page loads, but I don't think that will help me, as I'm only interested in one particular page.
Manifest:
{
"manifest_version": 2,
"name": "my Extension",
"version": "1",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-3.2.1.min.js", "content.js"]
}
],
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"scripts": ["background.js"]
}
}
background.js
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
// Send a message to the active tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
});
});
//
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url},
function(tab){ alert(tab.id) });
}
}
);
chrome.tabs.onUpdated.addListener(function (tabId , info) {
if (info.status === 'complete') {
chrome.tabs.sendMessage(activeTab.id, {"message": "page_loaded"});
}
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
var myUrl = "http://www.google.com";
var myValue = document.getElementById("thisId").value;
if(myValue ) {
chrome.runtime.sendMessage({
"message": "open_new_tab",
"url": myUrl,
"myValue ": myValue
});
}
}
if( request.message === "page_loaded" ) {
alert("hi");
}
});

sendMessage not working in chrome extension

I am trying to make a simple chrome extension. I'd be glad if someone can help.
Objective: When you click the button in extension popup (popup.html), the title of current webpage is displayed in div (with id 'div1').
Problem: I have searched internet for doing this and found that passing message can be used to achieve the same. So I tried my hands on it. But its not working. I want to know what went wrong.
Status:
= The extension is successfully imported in chrome.
= when extension icon is clicked, it shows proper popup.
= when button is clicked nothing happens.
= developer console shows no error.
Files:
=====================================
//manifest.json
{
"manifest_version": 2,
"name": "some_name_extension",
"version": "0.0.1",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-3.2.1.js", "content_script.js"]
}
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
=====================================
<!-- popup.html -->
<! doctype html>
<html>
<head>
<title>
</title>
<script type="text/javascript" src="popup.js">
</script>
<style>
html
{
height: 200;
width: 200;
}
</style>
</head>
<body>
<button id="btn1">
click me!
</button>
<div id="div1">
(title will be displayed here)
</div>
</body>
</html>
=====================================
//content_script.js
document.addEventListener('DOMContentLoaded', function() {
var title1=document.getElementsByTagName("title")[0].innerHTML;
chrome.extension.onMessage.addListener(
function(msg, sender, sendResponse) {
if(sender=="popup")
{
chrome.extension.sendMessage(title1,"content","1");
}
});
});
=====================================
//popup.js
document.addEventListener('DOMContentLoaded', function() {
var mainBtn = document.getElementById('btn1');
mainBtn.addEventListener('click', function() {
chrome.extension.sendMessage("button_clicked","popup","1");
});
chrome.extension.onMessage.addListener(
function(msg, sender, sendResponse) {
if(sender=="content")
{
document.getElementById("div1").innerHTML=msg;
}
}
);
});
=====================================
link to jquery script file : https://code.jquery.com/jquery-3.2.1.js
sender is an object that's set by the browser automatically, not a string that you can pass yourself. Use the devtools debugger to inspect your code and variables by setting breakpoints inside the callbacks, don't write the code blindly.
There's no need to check the sender in this case because content scripts cannot message each other anyway.
The correct method of sending a message to a content script from the popup is chrome.tabs.sendMessage with tabId as the first parameter:
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.sendMessage(tab.id, {
action: 'setTitle',
title: title1,
});
});
To send many values at once use an object: {action: 'setTitle', title: title1} or {action: 'buttonClicked', data: 1} and so on.
chrome.extension is deprecated for messaging, use chrome.runtime
Your code doesn't use jQuery so there's no need to inject it in manifest.json

Chrome plugin message passing callback undefined

I managed to pass a message between two files/instances, namely my popup and my background scripts, but the callback function still returns undefined, so my popup script does not receive a reply. Can somebody assist me? My code is based on the docs from Google.
Background.js
chrome.runtime.onMessage.addListener(function (sender, sendResponse) {
var resp = {'navURL': "Not set yet"};
if (sender.greeting === "GetURL") {
sendResponse(resp);
}
});
popup.js
function getURL() {
chrome.runtime.sendMessage({
greeting: "GetURL"
},
function (response) {
// RESPONSE IS UNDEFINED //
console.log(response);
alert(response.navURL);
});
}
$("input[type='checkbox']").on('change', function () {
getURL();
});
Manifest.json
{
"name": "FaceBlock",
"description": "This extention gets rid of unwanted content on Facebook like sponsored posts, adds or annoying suggestions. The content you wish to see is enlarged for a better and richer social experience.",
"version": "0.0.1",
"manifest_version": 2,
"content_scripts": [
{
"matches": [
"http://*.facebook.com/*", "https://*.facebook.com/*"],
"css": ["css/popup.css"],
"js": ["js/jquery.min.js", "js/content.js"],
"run_at": "document_end",
"all_frames": true
}],
"options_page": "options.html",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "Faceblock"
},
"permissions": [
"activeTab",
"tabs",
"https://www.facebook.com/*",
"https://ajax.googleapis.com/",
"storage"
],
"background": {
"scripts": ["js/background.js"],
"persistent": false
},
"options_ui": {
// Required.
"page": "popup.html",
// Recommended.
"chrome_style": true
// Not recommended; only provided for backwards compatibility,
// and will be unsupported in a future version of Chrome (TBD).
//"open_in_tab": true
},
"web_accessible_resources": [
"images/faceblock.jpg",
"images/seigaiha.png",
"js/popup.js",
"icon.png",
"js/options.js",
"css/popup.css",
"popup.html",
"options.html"
]
}
Thanks in advance,
Niels Vermeiren
EDIT: I now have the following with the same problem
Background.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
sendResponse({msg: "Element " + sender.element + " zijn zichtbaarheid wordt nu: " + sender.checked});
return true;
});
Popup.js
function getCurrentTabUrl(callback) {
return new Promise(function (resolve, reject) {
// https://developer.chrome.com/extensions/tabs#method-query
var queryInfo = {
active: true,
currentWindow: true
};
chrome.tabs.query(queryInfo, function (tabs) {
if (callback(tabs[0].url)) {
return resolve();
} else {
return reject();
}
});
});
}
function changeFacebook(data) {
console.log(data);
chrome.runtime.sendMessage(
"changeFacebook",
data,
function (response //undefined) {
console.log(response.msg); // UNDEFINED
});
}
document.addEventListener('DOMContentLoaded', function () {
var callback = function getCurrentTab(tab) {
if (tab == "https://www.facebook.com/") {
return true;
} else {
return false;
}
}
getCurrentTabUrl(callback).then(function () {
alert('on facebook');
$('.section').hide();
}, function () {
alert('not on facebook');
});
$("input[type='checkbox']").on('change', function () {
var id = $(this).attr('id');
var check = this.checked;
var data = {
'element': id,
'checked': check
};
changeFacebook(data);
});
$('.menuItem').hide();
$('.menuItem:first').show();
jQuery('.navitem').on('click', function () {
var value = $(this).html().toLocaleLowerCase();
jQuery('.menuItem').hide();
jQuery('#' + value).show();
});
});
According to doc here:
https://developer.chrome.com/extensions/runtime#event-onMessage
In your background.js, it should be
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
...
});
Since you are missing the last argument, what you really have is this:
chrome.runtime.onMessage.addListener(function (request, sender) {
...
});
So your code pretty much renamed request => sender, sender => sendResponse.
Therefore, you are trying to invoke sender as a function. But the actual sendResponse callback function is undefined. If you inspect your background page (see tips for how), you should see the error.
Tips:
When developing chrome extension, you can Inspect views: background page in the chrome://extensions page if you have any background page running.
When your popup is opened, you can inspect the popup page just you normally do.
And you can throw debuggers wherever you want, and you will be able to play around with it.
Edit:
So I have tested your code, the issue is just missing argument as I stated above. I also noticed the doc says the first two arguments are optional (not sure what the fuzz that is). But if you change your code to as below, it will work.
Background.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
var resp = {'navURL': "Not set yet"};
if (request.greeting === "GetURL") {
sendResponse(resp);
}
});
Popup.js
function getURL() {
chrome.runtime.sendMessage({
greeting: "GetURL"
},
function (response) {
console.log(response);
alert(response.navURL);
});
}
To test it
Go to the background page inspect, and paste in the background page snippet.
Go to the popup page inspect (open your popup, and right click within the popup, then choose inspect)
Paste in the popup page snippet
In the popup page inspect, call getURL()

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.

Chrome extension

I am a novice at this and am trying to make a chrome extension for showing me in the popup window the id of all elements with certain class name in the website.
I wanted to know if my implementation was the best option to resolve the matter.
Thanks for your help, and sorry for my poor english.
manifest.json
{
"name": "Test",
"version": "1.0",
"manifest_version" : 2,
"description": "",
"browser_action": {
"default_icon": "images/icon.png",
"default_popup": "popup.html"
},
"permissions": [ "tabs","http://*/*" ]
}
popup.html
<!doctype html>
<html>
<head>
<style>
body{
height: 150px;
width: 800px;
overflow: hidden;
margin: 0px;
padding: 0px;
background: white;
}
</style>
<script src="scripts/popup.js"></script>
</head>
<body>
</body>
</html>
popup.js
// Inserting javascript code
chrome.tabs.executeScript(null, {file: "scripts/content.js"});
// Sending request
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
document.write(response.farewell);
});
});
content.js
// This function gets all the id of the elements that have a class name X and
// returns them in a string separated by ",".
function getId(className) {
// I get all elements containing className
var elements = document.getElementsByClassName(className);
// Creating array with id of the elements
var idElements= new Array();
for (var i = 0; i < elements.length; i++) {
idElements[i]=elements[i].id;
}
// Concatenate all id
var list = idElements.join(" , ");
return list;
}
var result=getId("classNameTest");
// Listening for message from popup.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting == "hello")
sendResponse({farewell: result});
});
Any feedback is appreciated, thanks!
U have not registrd content script file in ur manifest file...check the below link for more details...else other work seems to be fine
http://developer.chrome.com/extensions/content_scripts.html

Categories