Reputation: 755
Using a WebExtension, I am trying to programmatically generate an HTML file like this:
<html><head><meta><title>example</title></head><body><p>Hello, world!</p></body></html>
and then download it using this method. (Background: I am generating a client-side redirect.)
Here's my manifest.json
:
{
"name": "Download HTML",
"description": "Generates an HTML file and downloads it",
"manifest_version": 2,
"version": "0.1",
"permissions": [
"activeTab"
],
"browser_action": {
"default_title": "Download HTML"
},
"background": {
"scripts": ["background.js"]
}
}
and here's my background.js
:
function downloadHTML(tab) {
console.log('Begin downloadHTML()')
function generateHTML(title) {
var newHTML = document.createElement('html');
var newHead = document.createElement('head');
var newTitle = document.createElement('title');
newTitle.text = title;
var newMeta = document.createElement('meta');
var newBody = document.createElement('body');
var newPar = document.createElement('p');
var newText = document.createTextNode('Hello, world!');
newPar.appendChild(newText);
newBody.appendChild(newPar);
newHead.appendChild(newMeta);
newHead.appendChild(newTitle);
newHTML.append(newHead);
newHTML.append(newBody);
return newHTML;
}
// Now make an anchor to click to download the HTML.
var tempAnchor = document.createElement('a');
var myHTML = generateHTML(tab.title);
var HTMLBlob = new Blob([myHTML.outerHTML], {type: 'text/html'});
tempAnchor.href = URL.createObjectURL(HTMLBlob);
var filename = 'index.html';
tempAnchor.download = filename
tempAnchor.style.display = 'none';
document.body.appendChild(tempAnchor);
tempAnchor.click();
document.body.removeChild(tempAnchor);
console.log('End downloadHTML()')
}
// Add downloadHTML() as a listener to clicks on the browser action.
browser.browserAction.onClicked.addListener(downloadHTML);
I've run the extension on this page:
http://info.cern.ch/hypertext/WWW/TheProject.html
When I do so, the browser console confirms that the function runs from start to finish.
Begin downloadHTML() background.js:2:3
End downloadHTML() background.js:31:3
However, there is no download prompt, and I receive this error message:
TypeError: this.mDialog is null [Learn More] nsHelperAppDlg.js:173:5
The "Learn More" just links to "TypeError":
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_type
When I debug the extension, I find these messages instead.
Webconsole context has changed
TypeError: can't access dead object [Learn More] accessible.js:140:5
The "Learn More" links to information about dead objects.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Dead_object
I'm guessing that the HTML elements are not persisting between calls to document.creatElement()
. I've tried moving the body of generateHTML()
out into its parent function, but that did not help.
How can I make sure the HTML persists? I don't want to modify the actual tab HTML, I just want to access the tab's title (and eventually URL). I looked at the Web Storage API, but I want to store HTML, not key-value pairs.
I am running Firefox version 63.0.3.
Upvotes: 0
Views: 161
Reputation: 7771
You need an actual DOM in order to click it.
Anyway ... it can be a lot simpler
browser.browserAction.onClicked.addListener(downloadHTML);
function downloadHTML() {
// download to file, downloads string (not DOM)
const data = '<html><head><meta><title>example</title></head><body><p>Hello, world!</p></body></html>';
const blob = new Blob([data], {type : 'text/plain;charset=utf-8'});
const filename = 'something.html';
// both are fine: chrome.downloads.download or browser.downloads.download
// requires "downloads" permission
browser.downloads.download({
url: URL.createObjectURL(blob),
filename,
saveAs: true, // pops up a Save As dialog, omitting it will save the file to the Downloads folder set in Firefox Options
conflictAction: 'uniquify' // renames file if filename already exists
});
}
If you want to show an actual page on browserAction
then it would be easier to set a "default_popup"
in manifest.json
Upvotes: 1