How to pass the entire DOM of the current page to background.js using contentScript? - google-chrome-extension

How do I pass the entire DOM content of Codechef.com to the background.js via contentScript?
I just want to get the problem tag of codechef question. This will help me to fetch the problem code. For this I need to query the dom.
{
"manifest_version": 3,
"name": "CodechefNotifier",
"version": "1.0",
"description": "Notifier for CodeChef",
"action": {
"default_popup": "index.html"
},
"permissions": [
"webRequest", "debugger", "tabs", "<all_urls>", "notifications", "scripting",
"activeTab"
],
"host_permissions": [
"https://www.codechef.com/"
],
"background": {
"service_worker": "background.js"
},
"content_scripts":[
{
"matches":["<all_urls>"],
"js":["contentScript.js"]
}
]
}
const button = document.createElement('button');
button.textContent = 'Greet me!'
document.body.insertAdjacentElement('afterbegin', button);
var tags = [ "h1" ];
var all_headings = [];
var h1s = document.querySelectorAll("h1");
all_headings.push(document.body.innerHTML);
var urlRegex = /^https?:\/\/(?:[^./?#]+\.)?codechef\.com/;
// A function to use as callback
function doStuffWithDom(domContent) {
console.log('I received the following DOM content:\n' + domContent);
}
// When the browser-action button is clicked...w
window.addEventListener('load',function (tab) {
// ...check the URL of the active tab against our pattern and...
if (urlRegex.test(tab.url)) {
// ...if it matches, send a message specifying a callback too
chrome.tabs.sendMessage(tab.id, {text: 'report_back'}, doStuffWithDom);
}
I want to pass dom content to the background script

Related

Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist

I am trying to pass message from background to content script but it is showing error
Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
I have tried too many solutions but nothing work. Here actually I am trying to create side panel in chrome extension for that I am passing message background to content script. My content script file is side-panel.js
background.js
chrome.action.onClicked.addListener((tab) => {
chrome.tabs.sendMessage(tab.id, "toggle");
console.log("message sent");
});
content (side-panel.js)
console.log("side-panel script loaded");
chrome.runtime.onMessage.addListener(function (msg, sender) {
if (msg == "toggle") {
console.log("message received");
toggle();
}
});
var iframe = document.createElement("iframe");
iframe.style.background = "green";
iframe.style.height = "100%";
iframe.style.width = "0px";
iframe.style.position = "fixed";
iframe.style.top = "0px";
iframe.style.right = "0px";
iframe.style.zIndex = "9000000000000000000";
iframe.style.border = "0px";
iframe.src = chrome.runtime.getURL("popup.html");
document.body.appendChild(iframe);
function toggle() {
if (iframe.style.width == "0px") {
iframe.style.width = "400px";
} else {
iframe.style.width = "0px";
}
}
manifest.json
{
"version": "1.0",
"manifest_version": 3,
"name": "test",
"key": "ahhechlhmhicciahdcegooimkdnhbphh",
"background": {
"service_worker": "background.js"
},
"action": {},
"content_scripts": [
{
"matches": [
"https://*/*",
"http://*/*"
],
"js": [
"side-panel.js"
]
}
],
"web_accessible_resources": [
{
"resources": [
"popup.html"
],
"matches": [
"https://*/*",
"http://*/*"
],
"extension_ids": [
"ahhechlhmhicciahdcegooimkdnhbphh"
]
}
]
}

Can't load html file from Chrome extension file system

I'm trying to load an HTML file from the file system of my Chrome extension. I've added "modal.html" as a web accessible resource in my manifest:
{
"name": "Test Extension",
"action": {},
"manifest_version": 3,
"version": "0.1",
"description": "Just learning for now",
"permissions": [
"activeTab",
"scripting",
],
"background": {
"service_worker": "background.js"
},
"web_accessible_resources": [
{
"resources": [ "modal.html" ],
"matches": [ "https://mypage.co.uk/*" ]
}
]
}
My background.js file tries to load modal.html with an xhr:
function initPage() {
let node = document.createElement("div");
node.setAttribute("id", "mySpecialId");
document.body.appendChild(node);
var xhr = new XMLHttpRequest();
xhr.open("GET", chrome.runtime.getURL('modal.html'), true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
document.getElementById("mySpecialId").innerText = xhr.responseText;
}
}
xhr.send();
}
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: initPage
});
});
I get the error:
Denying load of chrome-extension://lmdjgmkmficfccbahcpgnmaplajdljid/modal.html. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.
I'm sure this is a really basic problem, but I just can't figure it out.
I got this working by adding the use_dynamic_url key in the web_accessible_resources declaration:
"web_accessible_resources": [
{
"resources": [ "modal.html" ],
"matches": [ "https://www.mypage.co.uk/*" ],
"use_dynamic_url": true
}
]
I don't yet understand why this worked though!
Edit: This was a bug in Chrome. The original code was correct and worked after a reboot.

Chrome extension message passing from popup to content

I'm trying to create a chrome extension to learn front-end technologies, and got stuck on message passing between popup and content script.
The following is what I'm trying to do:
1. Let background page hold a global var.
2. When user clicking a button on the popup html, the global var is modified. Meanwhile, the popup sends the global var to the content scripts for all of the tabs.
In the background.js I have:
var settings = {
version: 1,
enabled: false
};
popup.js:
$(document).ready(function(){
$("#switcher").click(function( event ) {
event.preventDefault();
var bg = chrome.extension.getBackgroundPage();
var settings = bg.settings;
settings.enabled = !settings.enabled;
// send message to the content for all the tabs
chrome.tabs.query({active: true}, function (tabs) {
for (var i = 0; i < tabs.length; ++i) {
console.log("sending message to tab " + i);
chrome.runtime.sendMessage(tabs[i].id, {enabled: settings.enabled}, function(response) {
console.log(response);
});
}
});
});
});
Finally, the content.js:
$(document).ready(function(){
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
console.log("request is: " + request.enabled);
sendResponse("get it");
}
);
});
I tried to debug it, but I found the 'sendMessage' function never got returned back.. and the 'onMessage' never got triggered. Did I miss something?
My manifest file:
{
"name": "__MSG_appName__",
"version": "0.0.1",
"manifest_version": 2,
"description": "__MSG_appDescription__",
"icons": {
"16": "images/icon-16.png",
"128": "images/icon-128.png"
},
"default_locale": "en",
"permissions": [
"contextMenus", "storage", "tabs"
],
"background": {
"scripts": [
"scripts/background.js"
],
"persistent": true
},
"browser_action": {
"default_icon": {
"19": "images/icon-19.png",
"38": "images/icon-38.png"
},
"default_popup": "popup.html"
},
"content_scripts": [
{
"run_at":"document_start",
"all_frames":true,
"matches": ["*://*/*"],
"js": ["bower_components/jquery/dist/jquery.min.js", "scripts/content.js"]
}
],
"web_accessible_resources": ["bower_components/jquery/dist/jquery.min.map"]
}
You should be using chrome.tabs.sendMessage instead of chrome.runtime.sendMessage to send messages to content scripts in tabs.

Display Page Action Icon on specific url

I'm trying to get my page action icon to show on a specific url. I've tried implementing the examples here but these require the trunk/dev release.
The current code I have is taken from a SO answer. But this doesn't seem to work because the tab object never has a url property in my testing to be able to restrict on.
// background.js
function checkURL(tabId, info, tab) {
if (info.status === "complete") {
if (tab.url) {
// restrict here
chrome.pageAction.show(tabId);
}
}
}
chrome.tabs.onUpdated.addListener(checkURL);
// manifest
{
"manifest_version": 2,
"name": "My first extension",
"version": "1.0",
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"js": [
"script.js"
],
"run_at": "document_idle"
}
],
"background": {
"page": "background.html",
"persistent": false
},
"page_action": {
"default_icon": "icon.png"
}
}
What am I doing wrong?
This works for me:
//background.js
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (~tab.url.indexOf('.pl')) {
chrome.pageAction.show(tabId);
}
});
//manifest.json
"permissions": [
"tabs"
]
and I'm not using persistent:false
I'm late to answer this, but this may help anyone else having the same issue. I just spent about 20 minutes looking for it for my own extension.
Look here https://developer.chrome.com/extensions/declarativeContent
Add this to your manifest.json
"background" : {
"scripts": ["background.js"]
}
"permissions" : [
"declarativeContent"
]
Then in background.js
var rule1 = {
conditions: [
new chrome.declarativeContent.PageStateMatcher({
// If I wanted my extension to work only on SO I would put
// hostContains: 'stackoverflow.com'
// You can check out the link above for more options for the rules
pageUrl: { hostContains: 'some string' }
})
],
actions: [ new chrome.declarativeContent.ShowPageAction() ]
};
chrome.runtime.onInstalled.addListener(function (details) {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([rule1])
})
})

Running jquery script triggered by context menu in chrome extension

I am new to chrome extension development. The sample code I have is not running properly.
Requirement: Executing any jquery script(say $("body").hide();) on click of context menu button.
From the code, only jquery part is not working.
I have following files:
manifest.json
{
"manifest_version": 2,
"name": "jQuery DOM",
"version": "1",
"permissions": [
"contextMenus","tabs","activeTab"
],
"background": {
"scripts": ["jquery.min.js","sample.js"]
},
"description": "Manipulate the DOM when the page is done loading",
"browser_action": {
"name": "Manipulate DOM",
"icons": ["icon.png"],
"default_icon": "icon.png"
},
"content_scripts": [ {
"js": [ "jquery.min.js", "background.js" ],
"matches": [ "http://*/*", "https://*/*"],
"run_at": "document_end"
}]
}
background.js
$("body").append('Test');
I have icon.png in folder, and it gets loaded well.
jquery.min.js in same folder
sample.js
alert("Extension loaded");
function genericOnClick(info, tab) {
alert("Tab "+tab.id);
chrome.tabs.executeScript(tab.id, {
file: "jquery.min.js",
allFrames: true
},function(){
alert("callback");
$("body").hide();
});
alert("Completed");
$("body").hide();
}
var contexts = ["page"];
for (var i = 0; i < contexts.length; i++) {
var context = contexts[i];
var title = "Test Page menu item";
var id = chrome.contextMenus.create({"title": title, "contexts":[context],
"onclick": genericOnClick});
console.log("'" + context + "' item:" + id);
}
background.js works!
All the alerts work file, but .hide function from genericOnClick doesn't work.
Even if I move the code from sample.js to backgroud.js, it won't work.
Can you please tell me where did i go wrong ?
As I mentioned, a background script isn't allowed to interact with the DOM, (while a content script isn't allowed to use chrome.contextMenus). You need to combine both, and use message passing to tell the content script when to execute. Some other adjustments I made:
I renamed background.js and content.js so that their names now
reflect what they do, and made background.js into an event page.
I removed the browser action (the
extension would need browserAction.html or background.js would
need chrome.browserAction.onClicked.addListener to do anything
other than show the icon).
Programmatically injecting jquery means that always loading it as a
content script is unnecessary (although skipping programmatic injection allows you to omit the last three permissions).
background.js doesn't need jquery
anymore, so it isn't loaded there either.
The default executeScript
tab is the active tab, so we don't need it's id.
Here's the finished product:
manifest.json
{
"manifest_version": 2,
"name": "jQuery DOM",
"version": "1",
"permissions": [
"contextMenus", "activeTab", "tabs", "http://*/", "https://*/"
],
"background": {
"scripts": [ "background.js" ],
"persistent": false
},
"content_scripts": [ {
"js": [ "content.js" ],
"matches": [ "<all_urls>" ]
}],
"description": "Manipulate the DOM when the page is done loading"
}
background.js
function genericOnClick(info, tab) {
chrome.tabs.executeScript(null,
{"file": "jquery.min.js"},
function() {
chrome.tabs.sendMessage(tab.id,{"message":"hide"});
});
}
chrome.contextMenus.create({"title": "Test Page menu item",
"contexts":["page"],
"id":"contextId"});
chrome.contextMenus.onClicked.addListener(genericOnClick);
content.js
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.message == 'hide') {
$("body").hide();
}
sendResponse();
});
Your content.js is probably much larger than it is here (+1 for the SSCCE). But if it is small, another option would be to omit the content script entirely, and replace the sendMessage with chrome.tabs.executeScript(null,{code:"$('body').hide();"});.

Resources