在 WebExtension 中生成 HTML 会导致 `this.mDialog is null` 和 `can't access dead object`

generating HTML in WebExtension results in `this.mDialog is null` and `can't access dead object`

使用 WebExtension,我试图以编程方式生成这样的 HTML 文件:

<html><head><meta><title>example</title></head><body><p>Hello, world!</p></body></html>

然后使用this method. (Background: 下载 一个 client-side redirect.)

这是我的 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"]
  }
}

这是我的 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);

我已经 运行 此页面上的扩展程序:

http://info.cern.ch/hypertext/WWW/TheProject.html

当我这样做时,浏览器控制台确认函数从头到尾 运行s。

Begin downloadHTML() background.js:2:3
End downloadHTML() background.js:31:3

但是没有下载提示,我收到这个错误信息:

TypeError: this.mDialog is null [Learn More] nsHelperAppDlg.js:173:5 

"Learn More" 只是链接到 "TypeError":

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Unexpected_type

当我调试扩展时,我发现了这些消息。

Webconsole context has changed

TypeError: can't access dead object [Learn More] accessible.js:140:5 

"Learn More" 链接到关于死亡 objects 的信息。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Dead_object

我猜测 HTML 元素在对 document.creatElement() 的调用之间没有持续存在。我试过将 generateHTML() 的 body 移到它的 parent 函数中,但这没有帮助。

如何确保 HTML 持续存在?我不想修改实际的选项卡 HTML,我只想访问选项卡的标题(最终 URL)。我查看了 Web 存储 API,但我想存储 HTML,而不是 key-value 对。

我运行正在使用 Firefox 版本 63.0.3。

您需要实际 DOM 才能点击它。

反正...可以简单很多

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

如果您想在 browserAction 上显示实际页面,那么在 manifest.json

中设置 "default_popup" 会更容易