JavaScript: ошибка openpgp не определена в сценарии содержимого расширения Firefox

Оригинальный вопрос:

описание проблемы

Я разрабатываю расширение для браузера, которое использует OpenPGP.js для шифрования и дешифрования выбранного текста на веб-странице. Расширение отлично работает в Chrome, но я столкнулся с проблемой в Firefox, когда объект openpgp не определен.

Также еще одна ошибка в openpgp.min.js.

Error: concatUint8Array: Data must be in the form of a Uint8Array

Фрагмент кода

Вот соответствующая часть моего сценария контента:

async function encryptSelectedText() {
  const selection = window.getSelection().toString();
  console.info("Selected text:", selection);
  const selectionObj = window.getSelection().getRangeAt(0);
  console.info("Selection object:", selectionObj);

  if (selection) {
    try {
      // Get the selected public key from storage
      browser.storage.sync.get("selectedPublicKey", async function (data) {
        // console.info("Selected public key:", data.selectedPublicKey);
        const publicKeyArmored = data.selectedPublicKey;
        console.info("Public key:", publicKeyArmored);
        if (publicKeyArmored) {
          const publicKey = await openpgp.readKey({
            armoredKey: publicKeyArmored,
          });
          // further code but i get error here

Openpgp.js уже включен в скрипты контента:

{
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["src/openpgp.min.js", "src/content.js"]
    }
  ]
}

Моя файловая структура:

├── manifest.json
└── src
    ├── background.js
    ├── content.js
    ├── openpgp.min.js
    ├── openpgp.min.js.map
    └── popup
        ├── popup.css
        ├── popup.html
        └── popup.js

Ожидаемое поведение

Объект openpgp должен быть определен в Firefox так же, как и в Chrome, чтобы функции шифрования и дешифрования работали правильно.

Искал в Интернете похожие проблемы, но безрезультатно. Тоже спрашивал чатгпт, но тоже не помогло

Объект openpgp должен быть определен в Firefox так же, как и в Chrome, чтобы функции шифрования и дешифрования работали правильно, но в Firefox он не работает.


Обновлять:

После дальнейшего расследования я обнаружил, что проблема заключалась в том, как Uint8Array распознавался в Firefox. Хотя элементы являются экземплярами Uint8Array, Firefox не распознал их как таковые.

Ниже приведен фрагмент из openpgp.js

  function isUint8Array(input) {
    return Uint8Array.prototype.isPrototypeOf(input);
  }

function concatUint8Array(arrays) {
  if (arrays.length === 1) return arrays[0];

  console.info("arrays:", arrays);

  let totalLength = 0;
  for (let i = 0; i < arrays.length; i++) {
    const element = arrays[i];
    console.info("Element at index", i, ":", element);
    console.info("Is Uint8Array:", isUint8Array(element));
    console.info("Element constructor:", element.constructor.name);
    console.info("Instance of Uint8Array:", element instanceof Uint8Array);

    if (!isUint8Array(element)) {
      throw new Error('concatUint8Array: Data must be in the form of a Uint8Array');
    }

    totalLength += element.length;
  }

  const result = new Uint8Array(totalLength);
  let pos = 0;
  arrays.forEach(function (element) {
    result.set(element, pos);
    pos += element.length;
  });

  return result;
}

Он показывает следующее Firefox

Element at index 0 : 
Uint8Array(14) [ 79, 112, 101, 110, 80, 71, 80, 32, 88, 50, … ]
Is Uint8Array: false 
Element constructor: Uint8Array 
Instance of Uint8Array: false

Это отлично работает в Chrome, но не в Firefox.

Кроме того, если я просто верну true из isUint8Array, шифрование будет работать, но при расшифровке возникнет следующая ошибка.

Ошибка: Permission denied to access property "constructor"

Звучит как bugzil.la/1208775. Попробуйте использовать window.openpgp или замените первое назначение const t в openpgp.min.js на const t=this.

woxxom 20.07.2024 16:10

Я обновил свой вопрос, добавив дополнительные шаги и выводы по устранению неполадок.

Sukhmeet Singh 20.07.2024 18:44

Похоже на еще одну ошибку в Firefox или, возможно, ваш массив из другой «области». Покажите код, создающий массив.

woxxom 20.07.2024 19:09
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После ссылки на это обсуждение на github следующие изменения решили мою проблему:

Изменение

function isUint8Array(input) {
    return Uint8Array.prototype.isPrototypeOf(input);
  }

к этому:

function isUint8Array(input) {
    return Uint8Array.prototype.isPrototypeOf(input) || input instanceof globalThis.Uint8Array;
  }

и arr.push(result);

к

const fixedArray = new Uint8Array(result);
arr.push(fixedArray);

Другие вопросы по теме