генерация HTML в WebExtension приводит к тому, что «this.mDialog имеет значение null» и «не может получить доступ к мертвому объекту»

Используя WebExtension, я пытаюсь программно сгенерировать такой HTML-файл:

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

а затем загрузите его, используя этот метод. (Фон: я создаю перенаправление на стороне клиента.)

Вот мой 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

Когда я это делаю, консоль браузера подтверждает, что функция выполняется от начала до конца.

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

Однако запроса на загрузку нет, и я получаю следующее сообщение об ошибке:

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

«Подробнее» просто ссылается на «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 

Ссылки «Подробнее» на информацию о мертвых объектах.

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

Я предполагаю, что элементы HTML не сохраняются между вызовами document.creatElement(). Я попытался переместить тело generateHTML() в его родительскую функцию, но это не помогло.

Как я могу убедиться, что HTML сохраняется? Я не хочу изменять фактический HTML-код вкладки, я просто хочу получить доступ к заголовку вкладки (и, в конечном итоге, к URL-адресу). Я посмотрел на API веб-хранилища, но я хочу хранить HTML, а не пары ключ-значение.

Я использую Firefox версии 63.0.3.


person Nathaniel M. Beaver    schedule 26.11.2018    source источник


Ответы (1)


Вам нужен настоящий 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, было бы проще установить "default_popup" в manifest.json.

person erosman    schedule 26.11.2018
comment
HTML предназначен только для иллюстрации; На самом деле мне нужно сгенерировать другой в зависимости от вкладки, и простое объединение строк может привести к проблемам с кодированием и экранированием. stackoverflow .com/questions/53197847/ - person Nathaniel M. Beaver; 26.11.2018
comment
@NathanielM.Beaver Код также был примером. Он должен быть адаптирован к желаемому использованию. - person erosman; 26.11.2018