Chrome.debugger.attach() не прикрепляется к текущей вкладке

Я пытаюсь подключить отладчик к текущей вкладке, но он выдает эту ошибку

Uncaught (in promise) Error: Cannot access a chrome-extension:// URL of different extension

Вот мой файл фонового сценария, который обрабатывает это

chrome.runtime.onMessage.addListener(async (req, sender, sendResponse) => {
  if (req.name == "test") {
    const [tab] = await chrome.tabs.query({
      active: true
    })

    console.info(tab)
    const tabId = tab.id
    console.info(tabId)
    const text = "Hello there mate"

    await chrome.debugger.detach({ tabId: tabId })
    console.info("before attach")
    await chrome.debugger.attach({ tabId }, "1.2")
    console.info("after attach")

    await chrome.debugger.sendCommand({ tabId }, "Runtime.enable")
    await chrome.debugger.sendCommand({ tabId }, "DOM.enable")

    for (const char of text) {
      console.info(char)
      await chrome.debugger.sendCommand({ tabId }, "Input.dispatchKeyEvent", {
        type: "keyDown",
        text: char
      })
      await sleep(50)
      await chrome.debugger.sendCommand({ tabId }, "Input.dispatchKeyEvent", {
        type: "keyUp",
        text: char
      })
      await sleep(50)
    }
    sendResponse(tabId)
  }
})

Я отправляю сообщение из своего сценария содержимого через 5 секунд после загрузки сценария содержимого.

Почему это не работает?

Я ожидал, что он подключит отладчик и запустит событие отправки, чтобы записать в поле ввода.

Поведение ключевого слова "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) для оценки ваших знаний,...
0
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Ошибка означает, что вы подключаетесь к вкладке chrome-extension:// другого расширения или к обычной вкладке, содержащей iframe другого расширения.

  • Случай табуляции решается удалением chrome.tabs.query и использованием вместо него sender.tab.id.

  • Случай с iframe — это ошибка в Chrome, и обходной путь — удалить все такие iframe с вкладки в скрипте контента. 100% надежного способа их найти не существует, но в большинстве случаев достаточно проверить атрибут src:

    if (window.length) for (const el of document.querySelectorAll(
      `iframe[src^ = "chrome-extension://"]:not([src^ = "${chrome.runtime.getURL('')}"])`))
        el.remove();
    

    Однако некоторые расширения добавляют свои кадры внутри закрытого Shadow DOM, поэтому в этом случае вам нужно будет проверить все элементы в документе:

    (function removeExtensionFrames(root) {
      if (root || window.length)
        for (const el of (root || document).querySelectorAll(
        `iframe[src^ = "chrome-extension:"]:not([src^ = "${chrome.runtime.getURL('')}"])`))
          el.remove();
      for (let el of root.querySelectorAll('*'))
        if (!el.shadowRoot && (el = chrome.dom.openOrClosedShadowRoot(el)))
          removeExtensionFrames(el);
    })();
    

    Возможно, вы захотите где-нибудь сохранить элементы, чтобы впоследствии повторно добавить их.

P.S. Либо исправьте свой onMessage слушатель, либо не используйте async, подробнее.

Спасибо большое, похоже у меня в браузере был iframe другого расширения. Я удалил это, и это сработало. Также я сделаю так, чтобы мое расширение автоматически временно отключало другое расширение, используя разрешение «управление». И если это ошибка, куда мы можем о ней сообщить? Или уже сообщалось?

DevEnma 14.06.2024 17:37

А что вы думаете о подходе использования API отладчика для записи в поля ввода? Обычное поле ввода работало без использования отладчика, но в X (ранее twitter) секция ввода не является обычной секцией ввода, это элемент div со сложным механизмом. Когда я использую подход sendEvent(keyborad event, input event), это не так. Но, к счастью, этот подход отладчика сработал. Но думаете ли вы, что есть другие альтернативы?

DevEnma 14.06.2024 17:41

1) В ответе есть ссылка на ошибку. 2) Не существует универсально надежных альтернатив, но обычно можно отправлять события, используемые сайтом, что можно увидеть, проверив его код в devtools. Еще есть document.execCommand, пример.

woxxom 14.06.2024 18:04

Как я могу просмотреть, какое событие слушает конкретный div в devtools? И разве document.execCommand не устарел?

DevEnma 14.06.2024 18:43

1) Сделать это можно в devtools, там есть панель для прослушивателей событий. 2) Он по-прежнему работает и, вероятно, будет работать в обозримом будущем, поскольку альтернативы веб-платформе нет.

woxxom 14.06.2024 18:47

Привет @woxxom! Есть ли у вас какие-либо предложения, как мне справиться с состоянием загрузки в расширении браузера? Например, ожидание, пока сеть перестанет простаивать, как ожидание кукольника page.waitForNavigation({ waitUntil: 'networkidle0' }) или await page.waitForNetworkIdle().

DevEnma 17.06.2024 12:45

` await new Promise<void>((resolve) => { const Listener = async ( tabId: Number, ChangeInfo: chrome.tabs.TabChangeInfo ) => { if (tabId === updateTab.id &&changeInfo.status === "complete") { const tab = await chrome.tabs.get(tabId) console.info(tab) console.info(updatedTab) chrome.tabs.onUpdated.removeListener(listener) // Удалить прослушиватель после загрузки страницыsolve() } } chrome.tabs.onUpdated.addListener(listener) }) ` В настоящее время я использую этот подход.

DevEnma 17.06.2024 12:55

Но это не работает, поскольку большинство сайтов в настоящее время транслируются. Таким образом, статус завершен, хотя мы все еще загружаемся. Есть ли хорошее решение для этого?

DevEnma 17.06.2024 12:57

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