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

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

Related

Can't get chrome extension to get innerText when loading

I am building my first chrome extension and want to read the entire text in the website whenever a new tab is loaded. Everything works with a button, but I can't trigger it automatically.
Here's what I have in my popup.js
let getWords = document.getElementById("getWords");
// When the button is clicked, inject getPageText into current page
getWords.addEventListener("click", async () => {
let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: getPageText,
});
});
chrome.tabs.onUpdated.addListener(function(tab) {
chrome.tabs.executeScript({
target: { tabId: tab.id },
func: getPageText,
});
});
// The body of this function will be executed as a content script inside the
// current page
function getPageText() {
let websiteWords = document.body.innerText;
console.log(websiteWords);
}
My popup.html
<html>
<head>
<link rel="stylesheet" href="assets/css/layout.css" />
<link rel="stylesheet" href="assets/css/ui.css" />
</head>
<body>
BODY
</body>
<button id="getWords">Words</button>
<script src="popup.js"></script>
</html>
on my background.js I tried this but it doesn't work:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status === "complete"){
console.log("loaded....")
}
});
function getPageText() {
let websiteWords = document.body.innerText;
console.log(websiteWords);
}
Finally my manifest.json
"manifest_version": 3,
"permissions": [
"activeTab",
"webNavigation",
"storage",
"scripting"
],
"host_permissions": [
"https://*/*"
],
"background": {
"service_worker": "background.js",
"type": "module"
},
"action": {
"default_popup": "popup.html"
},
I think you should use content_scripts.
manifest.json
{
"name": "hoge",
"version": "1.0",
"manifest_version": 3,
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"matches.js"
]
}
]
}
matches.js
function getPageText() {
let websiteWords = document.body.innerText;
console.log(websiteWords);
}
getPageText();

Chrome extension is nor running on gmail pages

I'm trying to create a chrome extension (for personal use) that will run every time I open a gmail message, however I can't seem to get the function to run in gmail pages. When I try it on other pages it runs successfully, but not on gmail. I have tried different kind of listeners and added a couple of alerts as an indication for what's running, but on gmail nothing runs at all.
Manifest:
{
"name": "***",
"version": "0.99",
"manifest_version": 2,
"content_scripts" : [
{
"matches": ["<all_urls>"],
"js": ["agent.js"],
"css": ["style.css"],
"all_frames": true
}
],
"icons": {
"16": "icon16.png",
"48": "icon16.png",
"128": "icon16.png"
},
"browser_action": {
"default_popup": "popup.html"
}
}
agent.js:
function replaceText() {
if ((document.body.innerHTML.search("****")) >= 0) {
alert("Found")
var prev = document.getElementsByTagName("table")...
prev = prev.replace(...)
prev = prev.replace(...)
document.getElementsByTagName("table")... = prev
}
}
window.addEventListener('load', function () {
alert("Started")
replaceText()
})
new MutationObserver(() => {
alert("Started")
replaceText()
}).observe(document, {subtree: true, childList: true});
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
alert("Started")
replaceText()
}
})

How to load content script in chrome extension v3

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

Messages not exchanged between content scripts, background.js and popup.js

I am trying to make a google-chrome extension which fetches selected text from the webpage and displays it in the popup. I've read google-chrome docs and have followed many questions but I have been unable to resolve this issue. Selected text cannot be sent to background.js and furthur to popup.js.
manifest.json:
{
"name": "Wordomania",
"version": "1.0",
"manifest_version": 2,
"description": "Displays word on popup",
"icons": {
"16": "images/W.png"
},
"background": {
"scripts": [
"jquery-3.3.1.js",
"background.js"
],
"persistent": false
},
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": ["content.js"]
}
],
"permissions": [
"background",
"tabs",
"http://*/*",
"https://*/*",
"activeTab"
],
"browser_action": {
"default_icon": "images/W.png",
"default_title": "Wordomania"
}
}
background.js :
chrome.browserAction.onClicked.addListener(function (tab) {
console.log('Extension button clicked');
chrome.tabs.sendMessage(tab[0].id, {
action: 'sendWord'
}, function (wordObject) {
console.log('Word received');
let obj = {
word: wordObject.word,
from: 'back'
};
chrome.runtime.sendMessage(obj, function (status) {
console.log(status);
});
});
});
content.js :
function getSelectionText() {
let text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type !== 'Control') {
text = document.selection.createRange().text;
}
return text;
}
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.action === 'sendWord') {
let text = getSelectionText();
sendResponse({word: text});
}
});
popup.html :
<!DOCTYPE html>
<html>
<head>
<title>Wordomania</title>
<script src="popup.js"></script>
</head>
<body>
<h1><p id="word"></p></h1>
<div id="body-of-popup"></div>
</body>
</html>
Help required!
Basically, you will need to do a few changes in your approach. Since, we can have only one event at a time assoiciated with the browserAction either popup or chrome.browserAction.onClicked. In your case you have a popup assoiciated so you can not use chrome.browserAction.onClicked.
But still you can achieve what you want using the code below.
// Add below code in your popup.js
document.body.onload = function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "sendWord"}, function(response) {
alert(response.word);
});
});
};
Let the your content.js file as is.
manifest.json
"browser_action": {
"default_icon": "images/W.png",
"default_popup": "popup.html",
"default_title": "Wordomania"
}
Hope this will solve your problem.

Chrome extension - how to pass the values to background page

I have a small assignment.I need help on that..i am new to this stackoverflow..
The problem is of my extension..i have tried many methods in various tutorials and articles..
i need to achieve this.
I have an extension and when i click on it ,it should capture the current url of the page and open a new tab with the url and the source code (html structure) of the page..both the sourcecode and url must be stored somewhere .. like in an object or something..
So far i have done this.
manifest.json
{
"name": "ncubicx",
"version": "0.0.1",
"manifest_version": 2,
"browser_action": {
"default_icon": {
"19": "img/19x19.png",
"38": "img/38x38.png"
},
"default_title": "That's the tool tip"
},
"permissions": [
"activeTab",
"tabs",
"cookies",
"contextMenus",
"<all_urls>"
],
"background": {
"scripts": ["background.js"],
"persistent": true
}
}
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
var url = tabs[0].url;
});
chrome.tabs.create({url: 'newtab.html'}) ;
});
I dont know how to display the url in newtab.html or how to store the url's somewhere.
Hope someone helps me in this..
Thanks in advance..
You can capture the url of tab from background page and html source code from content script. Once you have both, open a new tab and send the object to this new tab where you can populate the html by yourself.
Note : Before sending the object to new tab, you need to wait for tab to load. So i have added a check for that.
Here's the whole code:
manifest.json:
{
"name": "Demo",
"version": "0.0.1",
"manifest_version": 2,
"description": "practice",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"default_locale": "en",
"background": {
"scripts": [
"src/bg/background.js"
],
"persistent": true
},
"browser_action": {
"default_icon": "icons/icon19.png",
"default_title": "browser action demo"
},
"permissions": [
"https://*/*","tabs"
],
"content_scripts": [
{
"matches": [
"https://*/*"
],
"js": [
"js/jquery/jquery.min.js",
"src/content/content.js"
]
}
]
}
background.js:
chrome.browserAction.onClicked.addListener(function(){
chrome.tabs.query({active: true,currentWindow: true}, function(tabs){
var url = tabs[0].url;
chrome.tabs.sendMessage(tabs[0].id, {message : "getHtml"},function(response){
var html = response.html;
var obj ={
tabUrl : url,
tabHtml : html
};
createNewtab(obj);
});
});
});
function createNewtab(obj){
var targetId = null;
chrome.tabs.onUpdated.addListener(function listener(tabId, changedProps) {
if (tabId != targetId || changedProps.status != "complete")
return;
chrome.runtime.sendMessage({message: "loadNewTab", data: obj});
});
var newTabUrl = chrome.extension.getURL('newTab.html');
chrome.tabs.create({ url: newTabUrl}, function(tab) {
targetId = tab.id;
});
}
content.js:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
switch (request.message){
case "getHtml":
var src = $("html").html();
sendResponse({html: src});
break;
}
});
newTab.html:
<html>
<head>
<script src="src/newTab.js"></script>
</head>
<body>
//You can populate data as you like
</body>
</html>
newTab.js:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
switch (request.message){
case "loadNewTab":
console.log(request.data);
//You have the object as request.data with tabUrl and tabHtml
break;
}
});

Categories