I'm opening a chrome extension programmatically from the background script with the following code:
background.js
chrome.windows.getLastFocused().then((window) => {
const width = 600 + 100;
const height = 400 + 100;
const left = window.width - width;
chrome.windows.create({url: "./index.html", type: "popup", height: height, width: width, left: left, focused: true});
});
This works perfectly fine for ./index.html, but not for any other path like ./approvals.html although this page exists.
Navigating in the extension with a link from index.html to approvals.html works smooth, but directly opening the extension with this path results in ERR_FILE_NOT_FOUND.
I think it might be related to some missing permissions, following my manifest.json:
{
"name": "Chrome React Extension",
"description": "The power of React for building interactive Chrome extensions",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "index.html",
"default_title": "Open the popup"
},
"permissions": [
"storage"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"service_worker": "background.js"
}
}
Any help is really appreciated!
Related
I'm pretty new to chrome extension development, I'm trying to make a better PiP (Picture in Picture) that doesn't have the maximum window size limitation.
I'm using this extension as reference, it basically behaves the same way as the default PiP works with video.requestPictureInPicture() which is what I don't want to use because extension popup has limited window size.
Instead, I have a index.html page with my extension that is loaded with window.open in background.js, this index page will have a video element that the HTMLVideoElement is passed to.
I've tried using chrome.runtime.sendMessage to send the video to the video.js that the index.html page loads, but this doesn't seem to work with a HTMLVideoElement? I read elsewhere that I should do JSON.stringify/JSON.parse for this object but that results in undefined.
Relevant manifest.json:
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"all_frames": true,
"js": [ "content.js" ],
"matches": [ "*://*/*" ],
"run_at": "document_start"
}],
"web_accessible_resources": [{
"resources": [ "index.html" ],
"matches": [ "*://*/*" ]
}],
"manifest_version": 3,
"permissions": [ "storage", "scripting", "activeTab", "tabs" ],
content.js:
const videos = new Set();
window.addEventListener('canplay', e => {
if(e.target.tagName === 'VIDEO') {
videos.add(e.target);
chrome.runtime.sendMessage({
method: 'VIDEO_PLAYING'
});
}
}, true);
background.js:
await chrome.scripting.executeScript({
...
var win = window.open(chrome.runtime.getURL('index.html'), 'PiP');
win.focus();
chrome.runtime.sendMessage({
method: 'VIDEO',
data: JSON.stringify(video)
});
video.js: - this is the js that is just included on index.html
const onMessage = (request, sender) => {
if(request.method === 'VIDEO') {
var data = JSON.parse(request.data);
console.log(video.src); //undefined
}
};
chrome.runtime.onMessage.addListener(onMessage);
Maybe my method of going about doing this is entirely wrong. Are there other ways I can pass such objects to index.html like this?
Creating chrome extension which opens link in new tab and trying to click the button on newly opened tab -
I am able to open new tab using the extension but the content script is not executing on new tab.
Manifest File
{
"manifest_version": 2,
"name": " New Tab Launcher",
"description": "Create the tab and button click ",
"version": "1.0",
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"tabs"
],
"content_scripts": [
{
"matches": [
"http://*/*", "https://*/*"
],
"js": [
"jquery-3.6.0.slim.min.js","contentScript.js"
],
"run_at": "document_end"
}
]
}
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('addMeetingUrl');
checkPageButton.addEventListener('click', function() {
chrome.tabs.create({'url': "youtube.com"});
}, false);
}, false);
contentScript.js
alert("This is test");
$(document).load(function (e) {
alert("Testing content script" +$('#logo').text());
});
In above the first alert come successfully by next script does not launch.
I have tried Removing the $(document).load and adding $(document).ready both are not working for me.
#logo could be added to the DOM after the load and ready events are fired.
Check with the debugger if I've stated is true.
If so you will need to use MutationObserver.
Try removing "run at" as it will default to "document_idle" which is usually safer option
My extension checks for broken images on a website. Everything works fine if I open an URL at a time but if I open several URLs from one site, the summary in popup.html is always the same as the active tab (it's not updated for each site).
I don't know how to refer to the actual URL of the analysis and avoid the "active tab". Any ideas?
Manifest.json
{
"name": "Test",
"permissions": ["activeTab", "declarativeContent", "storage","tabs"],
"version": "1.0.0",
"description": "Test",
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*", "https://www.google.com/_/chrome/newtab*"],
"exclude_globs": ["*#*"],
"js": ["jquery-3.4.1.min.js", "content.js"]
}
],
"web_accessible_resources": ["popup.html"],
"browser_action": {
"default_icon": {
"16": "images/ico.png",
"32": "images/ico.png",
"48": "images/ico.png",
"128": "images/ico.png"
}
},
"manifest_version": 2
}
Content.js
chrome.runtime.onMessage.addListener((msg, sender, response) => {
if (msg.subject === 'DOMInfo') {
var domInfo = {
images: number_images
};
response(domInfo);
}
});
Popup.js
window.addEventListener('DOMContentLoaded', () => {
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id,
{subject: 'DOMInfo'},
setDOMInfo);
});
});
I'm pretty sure is the tabs[0].id that causes the problem but I'm not sure how I can refer to the current URL that run the content.js script and make sure the popup.html gets the analysis from this URL. Any ideas?
In the background.js I had no problem referring the sender tab:
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse)
{
chrome.tabs.query({active:true, windowType:"normal", currentWindow: true},function(d){
var tabId = sender.tab.id;
....
Assuming popup.html is loaded into an iframe inside the web pages by your content script, you need chrome.tabs.getCurrent that returns the tab where this code is running so each iframe will find its own tab:
chrome.tabs.getCurrent(tab => {
chrome.tabs.sendMessage(tab.id, {subject: 'DOMInfo'}, callback);
});
P.S. When using sender.tab.id you don't need chrome.tabs.query - you already have the id.
Hi i've been looking at lots of tutorials and can't find anything it might be my poor google skills but I hoped the answer was quick and simple.
The Plan
The aim is to make an extension which will append any website using javascript.
Current State
I current have the javascript append coded and basic manifesto created
document.body.innerHTML += '<div id="adBar" style="background-color: #933131; width: 150px; height: 400px; position: fixed; left: 10px; top: 25%;"></div>'
The Problem
I can't find anywhere how to create a chrome extension which would allow this script to run in the background on every page, I can only find how to make a pop-up on click.
I hope this is clear and simple. All help is appreciated!
You need to set matches to <all_urls> (also you can add a button to the extension to trigger it). Here is my full example:
Extension Buttons
My Extension
├── manifest.json
├── background.js
├── content.js
├── jquery-2.2.0.min.js
├── icon.png
manifest.json
{
"manifest_version": 2,
"name": "My Extension",
"version": "0.1",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-2.2.0.min.js","content.js"]
}
],
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"scripts": ["background.js"]
},
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
}
}
background.js
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"});
});
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
//YOUR CODE GOES HERE
}
}
);
Basically I added a button to the extension that calls the content.js once it is pressed. The listener is on background.js.
You can wrap the code in content scripts and use "all_urls" for match patterns.
manifest.json
{
"name": "Test",
"version": "1.0",
"description": "Test",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"content.js"
],
"run_at": "document_end",
"all_frames": true
}
],
"manifest_version": 2
}
content.js
document.body.innerHTML += '<div id="adBar" style="background-color: #933131; width: 150px; height: 400px; position: fixed; left: 10px; top: 25%;"></div>'
i can't figure out how to make it work. My script works by itself. but doesn't work with background.js. I want my google extension to work only if the user clicks on it's icon, so I have created the file background.js and putted the code:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "change_content.js"});
});
my manifest.json here:
{
"manifest_version": 2,
"name": "Name",
"description": "change content.",
"version": "3.0",
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["change_content.js"]
}
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [
"tabs", "http://*/*"
]
}
and here is the change_content.js:
var oldSource = document.documentElement.innerHTML;
document.body.innerHTML = changeContent(oldSource);
function changeContent(source){
.....
}
The reason you are having the issue where change_content.js is executing before you press the button is because thats how content scripts work. If you include a content script in your manifest.json it will load and execute that script. Try removing the "content_scripts" section from the manifest and you should see it work as it should.
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "change_content.js"});
});
I've got a feeling the error lies in you using "null" as it might be searching for a tab with the tabId - null, you should try doing this instead?
chrome.tabs.executeScript({file: "change_content.js"});