Removing the injected script through the chrome extension - javascript

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.

Related

Popup HTML page doesnot show messages unless dev tools are open

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",
}
}

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);
});
});
});
});

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()

Categories