Chromium (or Firefox) extension for right clicking and downloading media - javascript

I am trying to implement this in a chromium extension:
On start of browser:
Create an event listener for right click events on the document
When a right click event is triggered:
Prevent the default context menu from appearing
Check if the target element of the right click event is of type "video", "audio" or "image"
If the target element is of type "video", "audio" or "image":
Get the URL of the media file
Check if the media file is already present in the default download destination
If the media file is not present in the default download destination:
Start a download with the URL and the original file name
Else:
Do nothing
I tried various permutations and combinations of this code. This is the latest what I have for background.js
document.addEventListener("contextmenu", function(event) {
event.preventDefault();
let media = event.target;
let url = media.src;
let ext = url.substring(url.lastIndexOf("."));
let xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = function() {
if (xhr.status === 200) {
let blob = xhr.response;
let filename = media.currentSrc.split("/").pop();
let link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
}
};
xhr.send();
}, false);
This is my manifest.json
{
"manifest_version": 2,
"name": "Media Saver",
"version": "1.0",
"description": "Saves media files with the correct extension.",
"permissions": [
"contextMenus",
"storage",
"<all_urls>"
],
"background": {
"scripts": [
"background.js"
]
}
}
Chromium still shows the context menu, and still does not download any media. My goals are this:
When I right click, no menu should be visible. The only action should be that the media file gets downloaded.
Make it automatically download the media silently in the default destination, rather than prompting the user for destination.
The name of the media must be the original name.
So not download the file if the file is already present in the destination.
Any help would be much appreciated. The extension can be made to work either in Chromium, or Firefox.

Related

Download File to Specific Directory JS

I'm taking inputs from an HTML form and putting them into a file. I've currently got it so it automatically downloads the file to the downloads folder but I want it to download to a specific directory:
%AppData%/Code/User/snippets/
Here is the code I've got at the moment:
function createSnippet() {
var snipName = document.getElementById('snipName').value;
var snipScope = document.getElementById('snipScope').value;
var snipPrefix = document.getElementById('snipPrefix').value;
var snipBody = document.getElementById('snipBody').value;
var snipDesc = document.getElementById('snipDesc').value;
// Final
let CONTENT = (`
{
"${snipName}": {
"scope": "${snipScope}",
"prefix": "${snipPrefix}",
"body": [
"${snipBody}"
],
"description": "${snipDesc}"
}
}
`);
var a = document.createElement("a");
a.href = window.URL.createObjectURL(new Blob([CONTENT], {type: "text/plain"}));
a.download = `${snipName}.code-snippets`; // I want this to download to the directory shown above
a.click();
}
Using JS, this cannot be done. If your trying to download a file to specific destination in the drive it is not possible. This possess a huge security risk if browsers allow it.
When a user is viewing a website, they are using a browser to access the webpage and browser decides what all permissions a website can have and what limitations it should put.
The only way that you download a file in specific folder is,the user doing to himself. Otherwise downloads made by browser will be stored at some default destination like /user/Downloads or user chosen path /user/Downloads/Chrome_Downloads.

downloaded html page not opening in chrome or edge but in IE and giving noscript error - vue application

In my application, i am trying to download html of current page which is with same domain name. I have written some method to download the html and it is downloading.
But, i have tried to open it in chrome as well as edge and it is not opening. But, in IE it is opening and displaying text of noscript tag (We're sorry but app doesn't work properly without JavaScript enabled.Please enable it to continue.).
I am inputting intranet site URL and clicking the download button. Here is my method below.
downloadHtml() {
let url = this.urlInput; // input text v-model value
fetch(url)
.then((res) => res.text())
.then((html) => this.downloadAsFile("report.html", html)); // by this name it is downloading
},
downloadAsFile(name, text) {
const link = this.createDownloadableLink(name, text);
const clickEvent = new MouseEvent("click");
link.dispatchEvent(clickEvent);
},
createDownloadableLink(fileName, content) {
let link = document.createElement("a");
link.href = 'data:attachment/text,' + encodeURIComponent(document.documentElement.outerHTML);
link.target = '_blank';
link.download = fileName;
return link;
},
**The problems are :
1. The app root signifies the public/index.html and that downloaded html is this one not the current page's html.
2. Chrome or Edge is not opening that html page even i checked browser is javascript enabled.
So, what i have to change the download the current page html?
The problem is that an HTML file in not an application/octet-stream file type. The mime type of an HTML page is text/html
I'm unsure of the way you try to create your download link. I don't have time to test it, but there is the way I do it usually using the createObjectURL API :
async function fetchHTML(url) {
let content = await fetch(url).then(resp => resp.text());
let file = new Blob([content],{type:'text/html'});
let href = window.URL.createObjectURL(file);
let a = document.createElement('a');
a.href = href;
a.setAttribute('download', 'report.html');
document.body.appendChild(a);
a.dispatchEvent(new MouseEvent('click'));
}
Another problem is that you don't append your link into the DOM in the code you provided. So the DOM cannot trigger your mouse event and so starting the download (it's needed by some browsers).
With the good mime type, the file in a proper format and a link in to the dom, it should be ok.

How can I download a video given its URL in JavaScript?

I have a URL, for example this:
https://r6---sn-vgqsrn76.googlevideo.com/videoplayback?expire=1566535969&ei=wRxfXezPAoORV-3ogpgK&ip=185.27.134.50&id=o-ALFdSvuvmX_bqDsm4oRW7q9c4igbKlBmECWdISuA4Jxe&itag=22&source=youtube&requiressl=yes&mime=video%2Fmp4&ratebypass=yes&dur=624.175&lmt=1529213992430932&fvip=6&c=WEB&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cmime%2Cratebypass%2Cdur%2Clmt&sig=ALgxI2wwRAIgZzTTsBPpVznwCvzArBFuSF7Bm3yhcO0rwQdfOjBibnsCIBqf8iHuAwahqi0T6qZ3MNbj8BfLgGo2Y3fPOi96RgEV&redirect_counter=1&cm2rm=sn-aigeey7d&req_id=8f890b1c72fda3ee&cms_redirect=yes&mip=2607:fea8:4d9f:fa68:40a2:35d0:8863:2d17&mm=34&mn=sn-vgqsrn76&ms=ltu&mt=1566514280&mv=m&mvi=5&pl=41&lsparams=mip,mm,mn,ms,mv,mvi,pl&lsig=AHylml4wRQIgSCcxaGd_IpVykCuglJtHwewUuZZIyKKr1FBbNP5MvqsCIQCYQEUoM9SpfpySHA_13lB6SvevIuMvhyFDEcrsX0y0ig==
How can I download the video in this URL programmatically through JavaScript? I cannot use PHP, Apache, JQuery etc, only Pure JavaScript and HTML.
I have tried using download.js, but I do not think that is the right approach to download videos. I have also looked/tried at various other websites and Stack Overflow answers, but none of them fixed this issue.
EDIT: The other SO answer that someone suggested will not work since the video is on a different baseurl than my own, which means that
<a href="file" download="filename">
will not work on Chrome. Doing this just opens the video.
function downloadImage() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://via.placeholder.com/150', true);
xhr.responseType = 'blob';
xhr.onload = function () {
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL(this.response);
var tag = document.createElement('a');
tag.href = imageUrl;
tag.target = '_blank';
tag.download = 'sample.png';
document.body.appendChild(tag);
tag.click();
document.body.removeChild(tag);
};
xhr.onerror = err => {
alert('Failed to download picture');
};
xhr.send();
}
I found the solution to the problem. The link was a YouTube source video link that I was trying to download, and on all videos (except the ones with music or the music genre) all you needed to do was to add
&title=[NAME OF FILE HERE]
which would download the video.
Edit: Downloading these videos worked with download.js. You need to make a XMLHTTP request to the video to get the data, and then use the function
download(data, name, mime)
For more documentation, look on the download.js GitHub page.

Unable to download blob loaded into an iframe

Following is my code which sets src attribute of an iframe to the blob url that I have created:-
function downloadFromIframeUsingBody(filebody: any) {
const iframe = document.createElement('iframe');
iframe.setAttribute('style', 'display: none;');
const newurl = window.URL.createObjectURL(new Blob([filebody.data],{type: 'application/pdf'}));
iframe.setAttribute('src', newurl);
const register = () => {
if (iframe.contentWindow) {
setTimeout(function() {
// Clean after 1 minute, by then it should already have started downloading
iframe.parentNode!.removeChild(iframe);
}, 60000);
} else {
setTimeout(register, 100);
}
};
register();
document.body.appendChild(iframe);
}
What I would like is for this iframe to download the blob containing pdf to be downloaded automatically. Currently nothing happens when this gets executed.
If you mean "download" as "save on disk" then just use an HTMLAnchorElement and its download attribute.
Or even handle all the edge cases (old IE and Safari quirks) with the ligthweight FileSaver script.
var blob = new Blob(["I'm just a text file..."], {type: 'plain/text'});
saveAs(blob, 'myFile.txt');
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.js"></script>
Note that this is true for any cases. iframe hack is just a bad hack that should only be used when it's been determined that no other better ways will work.
Now to explain why it won't work, well, it's because browsers actually are able to display pdf files, and will thus [try to] do it instead of forcing a download.
<iframe src="https://cdn.jsdelivr.net/gh/mozilla/pdf.js/test/pdfs/S2.pdf"></iframe>
(Note that current Chrome seems to have a bug that will make the pdf-reader to fail when in nested iframes, so here is a link to a plunker, where you can see it live in this browser by clicking the expand button on the right panel.

Copy image to clipboard from Chrome App (not Extension or Page)

I am struggling to copy an image to the clipboard from my Chrome App. Please keep in mind that I am specifically asking in relation to the new Chrome Apps (formerly known as Chrome Packaged Apps) not from a Chrome Extension or from a regular web page in Chrome.
I have requested the "clipboardWrite" and "clipboardRead" permissions in the manifest.json
"permissions": [
{"fileSystem": ["write", "retainEntries", "directory"]},
"https://www.google-analytics.com/",
"storage",
"clipboardWrite",
"clipboardRead"
],
Based on related "copy image to clipboard" questions here on StackOverflow, I have tried 4 different approaches.
function onClickButton() {
document.oncopy = function(event) {
var dataURL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC";
// base64 decode the data url, skipping the data url prefix
var data = atob(dataURL.substring("data:image/png;base64,".length));
// copy the decoded data to an binary array
var dataArray = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++) {
dataArray[i] = data.charCodeAt(i);
}
// approach 1 - failed, pastes nothing
event.clipboardData.setData('image/png', dataArray);
// approach 2 - failed, pastes nothing
event.clipboardData.setData('text/uri-list', dataURL);
// approach 3 - failed, ends up pasting the text "image.png"
var file = new File(dataArray, "image.png", {type: "image/png"});
event.clipboardData.items.add(file);
// approach 4 - failed, pastes nothing
event.clipboardData.items.add(dataURL, 'text/uri-list');
event.preventDefault();
};
document.execCommand("Copy");
}
This code is run with only 1 of the 4 approaches uncommented. Is there an approach that works?? FYI, approach 1 works fine with "text/plain" and some sample text. So I am reasonably sure that at least that approach is working with APIs that do something.

Categories

Resources