I'm developing chrome extension for my coworkers and myself. The goal is to download single image by clicking a button at behance.net.
The problem is that some of my coworkers using "Ask where to save each file before downloading" option, so the code doesn't work for them. I don't use this option, so download is successfull for me.
I've tried to set different options for chrome.downloads.download(), but I got nothing. Save As dialog not showing.
Manifest
{
"name": "Begrab",
"description": "Download pics right from Behance",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"permissions": ["activeTab", "downloads","tabs", "background"],
"content_scripts": [
{
"matches": ["https://*.behance.net/*"],
"run_at": "document_end",
"css": ["content.css"],
"js": ["content.js"]
}
]}
content.js
window.setTimeout(()=> {
codeRun();
}, 1000)
let projectLinks = document.querySelectorAll('.ProjectCoverNeue-coverLink-102')
Array.from(projectLinks).forEach(projectLink => {
projectLink.addEventListener('click', function(){
window.setTimeout(()=> {
codeRun();
}, 4000)
})
})
function codeRun() {
let imageParents = document.querySelectorAll('.js-project-lightbox-link');
Array.from(imageParents).forEach(imageParent => {
let button = document.createElement('a'),
buttonCopy = document.createElement('a'),
buttonsWrap = document.createElement('div'),
img = imageParent.querySelector('img'),
controls = imageParent.querySelector('.project-module__actions');
if(img) {
button.innerText = "Download";
button.className = "begrab__btn";
buttonsWrap.className = "begrab__wrap";
buttonsWrap.appendChild(button);
imageParent.appendChild(buttonsWrap)
button.addEventListener('click', (e) => {
let param = {src: img.src,
fileName: window.location.href};
e.stopPropagation()
chrome.runtime.sendMessage(param);
});
}
});
}
background.js
chrome.runtime.onMessage.addListener(
function(arg, sender, sendResponse) {
if(arg.src){
chrome.downloads.download({
url: arg.src,
conflictAction: "prompt"
}, function (downloadId) {
console.log(downloadId);
});
}
});
Did anyone face the same problem? Hope that somebody would help me. Thanks!
After some debugging i found out that the user is canceling the download for some reason.
The onChanged event outputs the following:
{
"error": {
"current": "USER_CANCELED"
},
"id": 1,
"state": {
"current": "interrupted",
"previous": "in_progress"
}
}
The only way i was able to get it work was downgrading the manifest to v2:
{
"manifest_version": 2,
"background": {
"persistent": true,
"scripts": [
"background.js"
]
}
}
I don't know if this is an option for you.
Related
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);
});
});
}
I'm using MV3 to create a chrome extension which injects a download button onto the document body. I'm trying to get that download button to download an example PDF hosted on another URL, but am unable to do so. When I click on the button, Chrome just opens the PDF in the current tab. I need to instead download it to the computer like a regular file. I have the download permission in my manifest, but am unsure what I'm doing wrong. Any help would be greatly appreciated!
This is where the download button is stored is my contentScript.JS file.
function createModal() {
var auroraModal = document.createElement('div');
auroraModal.className = '_aurora__modal';
auroraModal.id = '_aurora__modal';
var downloadLink = document.createElement('a');
downloadLink.download = "Example.pdf";
downloadLink.href = "https://www.africau.edu/images/default/sample.pdf";
downloadLink.innerHTML = 'Download';
auroraModal.innerHTML = '<p>Woo-hoo <strong>'+dataFromPromise+'</strong>! Your custom PDF is ready!</p>';
auroraModal.appendChild(downloadLink)
document.body.appendChild(auroraModal)
}
And here is my manifest.JSON:
{
"name": "Aurora Extension",
"manifest_version": 3,
"description": "Aurora extension attempt with FB9 and MV3",
"permissions": ["storage", "tabs", "downloads"],
"host_permissions": ["https://*.stackoverflow.com/*"],
"background": { "service_worker": "background/index.js" },
"content_scripts": [
{
"js": ["content/index.js"],
"css": ["content/coupon.css"],
"matches": ["https://*.stackoverflow.com/*"]
}
],
"action": { "default_popup": "pages/popup/index.html" }
}
This used content scripts and service worker.
manifest.json
{
"name": "chrome.downloads.download used content_scripts + service_worker",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"downloads"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"js": [
"matches.js"
],
"matches": [
"<all_urls>"
]
}
]
}
matches.js
console.log("matches.js");
const button = document.createElement("button");
button.innerText = "button";
button.onclick = () => {
chrome.runtime.sendMessage("");
console.log("Send");
}
document.body.insertBefore(button, document.body.firstElementChild);
background.js
console.log("background.js");
chrome.runtime.onMessage.addListener(() => {
console.log("Receive");
chrome.downloads.download({
filename: "Example.pdf",
url: "https://www.africau.edu/images/default/sample.pdf"
});
});
Please user chrome.downloads.download.
manifest.json
{
"name": "chrome.downloads.download",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"downloads"
],
"action": {
"default_popup": "popup.html"
}
}
popup.html
<html>
<body>
<script src="popup.js"></script>
</body>
</html>
popup.js
chrome.downloads.download({
filename: "Example.pdf",
url: "https://www.africau.edu/images/default/sample.pdf"
});
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"]
}]
}
I'm building an extension to copy text to the clipboard without including the line breaks. It runs on every URL but not on PDFs.
Background script:
chrome.commands.onCommand.addListener(function (command) {
if (command === "copy") {
chrome.tabs.query({'currentWindow':true,'active':true}, function(tabs){
chrome.tabs.sendMessage(tabs[0].id,'hi');
})
}
}
);
Here is the content script:
async function copyPageUrl() {
try {
const text = navigator.clipboard
yo = window.getSelection().toString();
yon = yo.replace(/(\r\n|\n|\r)/gm, " ");
await text.writeText(yon);
console.log('Page URL copied to clipboard');
console.log(yon);
} catch (err) {
console.error('Failed to copy: ', err);
}
}
chrome.runtime.onMessage.addListener(function(request){
alert(request);
console.log('copy was pressed');
copyPageUrl()
})
FYI, this is the manifest
{
"name": "Line Break remover",
"version": "1.0",
"description": "Remove Line Breaks when copying from PDFs!",
"background":{
"scripts": ["text.js"],
"persistent": false
},
"manifest_version": 2,
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["ContentScript.js"]
}
],
"commands": {
"copy" : {
"suggested_key": {
"default": "Shift+Ctrl+X"
},
"description": "Copy a text"
}
},
"permissions": [
"tabs",
"background",
"clipboardRead",
"clipboardWrite"
]
}
You can view the error in the console.
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;
}
});