Display Page Action Icon on specific url - google-chrome-extension

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

Related

How to pass the entire DOM of the current page to background.js using contentScript?

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

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.

My chrome extension is not working on Edge

I have a piece of code which works fine on chrome. I did the following step mentioned here.
I'm able to load it properly, but the code doesn't run properly.
In the background console only the url gets printed, no other consoles or alerts work.
Please any help will be appreciated ! Please
window.onload = function() {
console.log("blah1");
var port = browser.runtime.connect({name: "knockknock"});
port.postMessage({request: "sendData"});
port.onMessage.addListener(function(msg) {
console.log("blah2");
if(msg != null){
}
});
}
var sendData = null;
var url = null;
browser.webRequest.onBeforeRequest.addListener(function(details) {
if(details != null && sendData == null && details.url.includes("www")){
console.log(details.url);
sendData = details.url;
}
},
{urls: ["<all_urls>"]},
["blocking", "requestBody"]
);
browser.runtime.onConnect.addListener(function(port) {
console.log("inside addListener")
port.onMessage.addListener(function(msg) {
if (msg.request == "sendData"){
console.log("sendData : ", sendData);
port.postMessage(sendData);
}else if (msg.answer == null){
sendData = null;
}
});
});
My manifest file
{
"manifest_version": 2,
"name": "test",
"version": "1.0.0",
"author": "medha",
"icons": {
"48": "esso.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"scripts": ["background.js"]
},
"permissions": [ "webRequest", "webRequestBlocking", "webNavigation", "tabs", "<all_urls>", "storage"],
"-ms-preload": {
"backgroundScript": "backgroundScriptsAPIBridge.js",
"contentScript": "contentScriptsAPIBridge.js"
}
}
I tested and found that if we remove window.onload then the extension will work well in Edge Legacy. It will print all the consoles.
You could set content.script run at document_idle. It's equal to window.onload and you do not need to listen for the window.onload event. For more detailed information, you could refer to this article.
My manifest.json is like below:
{
"manifest_version": 2,
"name": "test",
"version": "1.0.0",
"author": "medha",
"icons": {
"48": "esso.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"run_at": "document_idle",
"js": ["content.js"]
}
],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": [ "webRequest", "webRequestBlocking", "webNavigation", "tabs", "<all_urls>", "storage"],
"-ms-preload": {
"backgroundScript": "backgroundScriptsAPIBridge.js",
"contentScript": "contentScriptsAPIBridge.js"
}
}

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();"});.

Message passing Background.html -> Content Script

I've got the following in my background.html to sendRequest to contentscript...
chrome.tabs.getSelected(null,function(tab)
{
chrome.tabs.sendRequest(tab.id,{req:"func"});
});
However, it doesn't appear to be working. What am I doing wrong?
Portion of related manifest file...
"background_page": "background.html",
"browser_action":
{
"default_icon": "icon.png",
"popup": "popup.html"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"notifications",
"contextMenus"
],
"options_page": "options.html",
"content_scripts": [
{
"matches": ["http://*/*","https://*/*"],
"js": ["contentScript.js","jquery.js"],
"all_frames": false
}
],
contentscript...
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse)
{
switch(request.req)
{
case "func":
func();
sendResponse({});
break;
default:
sendResponse({});
}
});
Make this in the background page :
chrome.tabs.getSelected(null,function(tab)
{
chrome.tabs.sendRequest(tab.id,{req:"func"}, function(response){
alert(response.req); // Get The response
});
});
And on the Content Script :
sendResponse({ req: 'Your Response' });
Also change your manifest to :
{
"background_page": "background.html",
"browser_action":
{
"default_icon": "icon.png",
"popup": "popup.html"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"notifications",
"contextMenus"
],
"options_page": "options.html",
"content_scripts": [
{
"matches": ["http://*/*","https://*/*"],
"js": ["contentScript.js","jquery.js"],
"all_frames": false
}
],
"name" : "FirstExtension",
"version" : "1.0",
}
PS : Name and Version on the manifest are required...
Your code runs fine for me. Probably a content script is not loaded on that page when you are sending the request. Do you have some sort of condition before chrome.tabs.getSelected? You can't just run it right away, you need to be sure that a tab is loaded first.
PS. Also in your manifest you probably would want to load jquery before your content script.

Resources