How to load content script in chrome extension v3 - javascript

I'm migrating my v2 extension to v3. Now, the first thing that is not clear to me is how the content script is loaded into the page. I've implemented it as follows (background script):
chrome.action.onClicked.addListener(tab => {
chrome.windows.create({
// Just use the full URL if you need to open an external page
url: chrome.runtime.getURL("hello.html"),
type: "panel", height: 200, width:200
}, (win) => {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
const currTab = tabs[0];
if (currTab) {
chrome.scripting.executeScript({
target: {tabId: currTab.id},
files: ['/content.js'],
}, () => { });
}
});
});
});
I think that this example is my best attempt :)
So, when I run this code I get the following error in the console:
Unchecked runtime.lastError: Cannot access contents of url "". Extension manifest must request permission to access this host.
Here is my manifest:
{
"name": "Hello, World!",
"version": "1.0",
"manifest_version": 3,
"background": { "service_worker": "background.js" },
"action": {
"default_icon": {
"16": "icon16.png"
}
},
"permissions": [
"tabs",
"bookmarks",
"unlimitedStorage",
"activeTab",
"scripting"
],
"optional_permissions": [],
"host_permissions": [
"*://*/*"
],
"web_accessible_resources": [
{
"resources": ["/content.js"],
"matches": [],
"extension_ids": [],
"use_dynamic_url": true
}
]
}
If I'm on the right path here, there must be something missing in my manifest. Any suggestions?

try the following :-
chrome.action.onClicked.addListener(insertScript)
async function insertScript() {
tabId = await getTabId();
chrome.scripting.executeScript({
target: {tabId: tabId}
files: ['/content.js']
})
}
async function getTabId() {
var tabs = await chrome.tabs.query({active: true, currentWindow: true});
return tabs[0].id;
}

Related

Javascript: Browser Extension navigate.clipboard.write() not working in content.js

In my extension I have a button in a popup.js file that runs a listener for a button press and sends a command to a content.js file.
document.querySelector('#btn').addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) =>
chrome.tabs.sendMessage(tabs[0].id, { command: 'getClientName' })
);
});
My content.js file is a little involved and grabs some information off the page to copy to the clipbaord, but for purposes of my problem I just need a listener to wait for the command "getClientName" then save a value to the clipboard like below.
chrome.runtime.onMessage.addListener((msg, sender, response) => {
navigator.clipboard.writeText("I did it 2!")
.then(() => {alert("I did it 2!");
})
.catch(() => {
alert("I didn't it 2");
})
});
However, I cannot get navigator.clipboard.writeText() to work from the content.js page. It will only work if I run it directly from popup.js, which doesn't really work since I need to pull information off the page.
Right now it gets sent to .catch() and sends me the error message.
Manifest (replaced the actual URL in my manifest with "all" for privacy reasons):
{
"manifest_version": 3,
"name": "The Magic Button",
"version": "1.0.0",
"description": "Open P.P. client folder in sharepoint",
"action": {
"default_icon": {
"16": "/images/logo16.png",
"48": "/images/logo48.png",
"64": "/images/logo64.png",
"128": "/images/logo64.png"
},
"default_popup": "popup.html",
"default_title": "Open Sharepoint Folder"
},
"permissions": ["tabs",
"clipboardWrite"],
"content_scripts": [
{
"matches": [all],
"js": ["content.js"],
"css": ["/styles/contentStyle.css"],
"run_at": "document_idle",
"all_frames": false
}
]
}
This sample copies the web page title to the clipboard.
manifest.json
{
"name": "hoge",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting"
],
"host_permissions": [
"<all_urls>"
],
"action": {
"default_popup": "popup.html"
}
}
popup.html
<html>
<body>
<button id="copy">Copy</button>
<script src="popup.js"></script>
</body>
</html>
popup.js
const getTitle = () => {
console.log("getTitle() = " + document.title);
return document.title;
}
document.getElementById("copy").onclick = () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
console.log("Execute Script");
chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
func: getTitle
}, (result) => {
console.log("Recv result = " + result[0].result);
navigator.clipboard.writeText(result[0].result);
});
});
}

Chrome Extension Content-Script as Listener & Popup as Sender, But Gives Receiving End Does Not Exist

Answer Found
This extension is for google meet. What I have written in manifest.json is wrong, line "matches": ["*://*.meet.google.com/*"], should be "matches": ["*://meet.google.com/*"],
Original Question
I have this chrome extension, I want to let my contentScript.js to search for an element (tag) in a webpage when I press a button in popup.html. I set the sending message part in popup.js and the sending seems to work fine. But when I tried to receive it on the contentScript.js, console.log gives me Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
May someone please help me, any suggestions are welcome.
Code snippets:
popup.js
retrieveTabId();
function retrieveTabId() {
chrome.tabs.query({currentWindow: true, active: true}, function (tabs) {
var activeTab = tabs[0];
console.log("tabID", activeTab.id);
tabId = activeTab.id;
});
}
document.getElementById("btn").addEventListener('click', function (){
chrome.tabs.sendMessage(tabId, {type: "listener"}, function(response) {
console.log((response.success));
});
console.log("tabID", tabId);
})
content-script.js
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.type == 'listener') {
try {
let textarea = document.getElementsByTagName('textarea');
if (textarea.length == 0) {
sendResponse({success: false});
}
else {
console.log('find node -- textarea' + textarea);
sendResponse({success: true});
}
}
catch (e){
console.log(e);
sendResponse({success: false});
}
}
}
);
manifest.json
{
"name": "name",
"description": "Build an Extension!",
"version": "1.0",
"manifest_version": 3,
"permissions": ["storage", "activeTab", "scripting", "downloads", "notifications", "<all_urls>", "tabs"],
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": ["*://*.meet.google.com/*"],
"js": ["contentScript.js"]
}]
}

How to get access/permission for sendMessage to send data from any web pages to background script

I'm building cross browser extention, and face problem, i can't send sendMessage from chrome without 'externally_connectable' and 'matches' in it.
google guide said i can't matche URLs like this "" or this "http:///", only target URL like this: 'http://localhost:3000/', how avoid this and use 'runtime.sendMessage' from any web page?
my inpage scrypt
const ID = 'cb7b13f5efcbcc4453d4ebf63f7';
const send = (data) => new Promise((resolve, reject) => {
extensionizer.runtime.sendMessage(ID, { method: 'send', data }, (res) => {
if (res.error) reject(res.error);
resolve(res);
});
});
my background scrypt
const onExternalMessage = (request, sender, sendResponse) => {
const id = Date.now();
requestQueue.push({
data: request.data, sender, id, cb: sendResponse,
});
};
manifest.json
{
"short_name": "Send",
"name": "Sender",
"manifest_version": 2,
"browser_action": {
"default_popup": "./index.html",
},
"version": "1.0",
"background": {
"scripts": [
"background.js"
]
},
"content_scripts": [
{
"matches": [
"file://*/*",
"http://*/*",
"https://*/*"
],
"js": [
"./content.js"
],
"run_at": "document_start",
"all_frames": true
}
],
"permissions": [
"storage"
],
"web_accessible_resources": [
"inpage.js",
"background.js"
]
}

Redirect to new URL using onBeforeRequest and chrome.tabs.query (Chrome Extension)

Good time.
I have some interesting idea for which have to do changing URL after inputing pushing "enter" by user.
My manifest file:
{
"name": "The Pirate Bay_2",
"description": "Redirect The Pirate Bay to a different host",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"default_title": "Saving Studio generator",
"default_popup": "popup.html"
},
"background": {"scripts":["redirect.js"]},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["background.js"]
}
],
"permissions":
[
"webRequest",
"https://www.amazon.com/",
"webRequestBlocking",
"tabs",
"activeTab"
]
}
My redirect.js file:
var host = "https://2ch.hk/b/";
chrome.tabs.query({
'active': true, 'currentWindow': true
}, function (tabs) {
var url = tabs[0].url;
host = host+url;
console.log(url);
});
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if (localStorage.check_box == "true"){
console.log("start_1");
return {redirectUrl: host};
}
},
{
urls: ["https://www.amazon.com/" ],
types: ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"]
},
["blocking"]
);
Main is to how to take entered URL, change it by some regex pattern, return resulting URL to redirect to it. How it's possible to do? How to insert chrome.tabs.query inside onBeforeRequest or this needn't and there is another way?
Big thanks
I've had to do something similar using the chrome storage API which is also asynchronous. What I did was put the web request listener inside the callback of the async function. So in your case:
var host = "https://2ch.hk/b/";
chrome.tabs.query(
{
'active': true, 'currentWindow': true
},
function (tabs) {
var url = tabs[0].url;
host = host+url;
console.log(url);
}
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if (localStorage.check_box == "true"){
console.log("start_1");
return {redirectUrl: host};
}
},
{
urls: ["https://www.amazon.com/" ],
types: ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"]
},
["blocking"]
);
);
I haven't tested this but it's what I did when I needed to use the storage API, so give it a try.

chrome.runtime.onMessage.addListener not receiving events

Here's my manifest.json:
{
"manifest_version": 2,
"name": "Testing",
"version": "0.1",
"permissions": [
"tabs"
],
"background": {
"scripts": [
"background.js"
]
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"jquery-min-3.4.1.js",
"content.js"
]
}
],
"browser_action": {
"default_icon": "icon.png"
}
}
Here's what I've got in my content.js:
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
console.log(`message received, ${request}`)
}
);
Here's what I've got in my background.js:
chrome.browserAction.onClicked.addListener(function (tab) {
// Send a message to the active tab
console.log('on clicked')
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
var activeTab = tabs[0];
console.log(activeTab);
chrome.tabs.sendMessage(activeTab.id, { "message": "clicked_browser_action" });
});
});
When I click my browser action, I do see the 'on clicked' logged, and the active tab logged, but I don't get the 'message received' log. Not sure what's going on here

Categories