Обходной путь для манифеста версии 3

Я работал над расширением Chrome, которое включало всплывающее окно и сценарий контента; используя action.onClicked. Я ожидал, что пользователь щелкнет значок на панели расширений. Затем событие щелчка откроет всплывающее окно, вызовет сценарий контента и позволит пользователю получить доступ к текущей веб-странице.

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

Они работали независимо, почему бы им не работать в тандеме? Ну, как выясняется…

Событие action.onClicked не будет отправлено, если в расширении указано всплывающее окно, которое будет отображаться при нажатии на текущую вкладку. — Документы для разработчиков Chrome

Поэтому возникает вопрос: как мне заставить мой скрипт содержимого выполняться только при открытии всплывающего окна? Чтобы ответить на этот вопрос, нам нужно понять, что такое контент-скрипт.

Сценарии контента — это файлы, которые запускаются в контексте веб-страниц… они могут считывать сведения о веб-страницах, которые посещает браузер, вносить в них изменения и передавать информацию своему родительскому расширению. — Документы для разработчиков Chrome

Во-первых, чтобы использовать скрипт содержимого в своем расширении, вам нужно объявить его в файле manifest.json. См. ниже.

"content_scripts": [
   {
     "matches": ["<all_urls>"],
     "css": ["my.css"],
     "js": ["content.js"]
   }
 ],

Это объявление может связать ваш JavaScript, CSS и многое другое с вашей веб-страницей. В приведенном выше случае content.js и my.css оба имеют доступ к вашей веб-странице. Это то, что мы хотим!

Однако мы хотим, чтобы он обращался к веб-странице и выполнял логику при открытии всплывающего окна.

Как написано выше, так не пойдет.

content.js будет работать, когда веб-страница простаивает. Если вы хотите указать другое время для его запуска, вы можете использовать свойство runAt. Вы можете добавить его в свойство content_script, как показано ниже.

"content_scripts": [
   {
     "matches": ["<all_urls>"],
     "css": ["my.css"],
     "js": ["content.js"],
     "run_at": "document_start" //right here
   }
 ],

Вы можете выбрать из document_start, document_idle и document_end. Я подробнее расскажу об этом в следующем посте. На данный момент все, что нам нужно знать, это то, что проблема с этими параметрами заключается в том, что ни один из них не выполняется при открытии всплывающего окна.

Итак, как мы можем это сделать?

Что ж, мы можем просто… не объявлять никаких content_scripts.

Я знаю, о чем вы могли подумать… ЭТО БЕЗУМИЕ.

No…

Хорошо, если серьезно, выслушайте меня.

Вместо объявления скриптов контента мы можем внедрить скрипт когда захотим. Мы можем сделать это, используя chrome.scripting.

Возможно, вы помните это из моего предыдущего поста о фоновых скриптах. Мы будем делать то же самое, но на этот раз с JavaScript нашего всплывающего окна.

Во-первых, в вашем файле manifest.json вам нужно указать разрешения scripting, чтобы разрешить выполнение сценариев. См. наши последние manifest ниже.

{
    "name": "Popup and Content Script",
    "description": "How to use a content script with a popup",
    "version": "1.0.0",
    "manifest_version": 3,
    "permissions": [
        "scripting",
    ],
    "host_permissions": [
        "<all_urls>"
    ],
    "action":{
        "default_title": "Popup and Content Script",
        "default_popup": "popup.html"
    }
}

Обратите внимание, как мы удалили объявление content_scripts. Нам больше не нужно ссылаться на него, так как мы будем внедрять его.

Получите весь мой последний контент, создав учетную запись в партнерской программе Medium и подписавшись на мои электронные письма. :)

Затем мы можем начать работать с файлом JavaScript нашего всплывающего окна, popup.js. Ради краткости я не буду освещать HTML-сторону в этом посте. Все, что вам нужно знать, это то, что вы должны указать popup.js в конце тега body в popup.html.

Весь код для этого поста можно найти на GitHub.

В popup.js мы будем писать логику, используемую для вызова нашего импровизированного сценария контента (content.js). Здесь нам понадобится вкладка текущей страницы.

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

getCurrentTab = async () => {
  let queryOptions = { active: true };
  let [tab] = await chrome.tabs.query(queryOptions);
  return tab;
}

chrome.tabs.query... вернет Promise. Чтобы получить доступ к результирующему tab внутри Promise, мы можем вызвать getCurrentTab внизу popup.js.

getCurrentTab().then((tab)=>{
  injectContentScript(tab)
})

Теперь, когда мы это настроили, мы можем начать писать логику для injectContentScript в верхней части popup.js. Эта функция будет использовать executeScript для внедрения скрипта содержимого при открытии всплывающего окна.

injectContentScript = (tab) => {
  const {id, url} = tab;
  chrome.scripting.executeScript(
    {
      target: {tabId: id, allFrames: true},
      files: ['content.js']
    }
  )
  console.log(`Loading: ${url}`); 
}

Идеальный! Наш executeScript теперь внедряет наш скрипт content.js на нашу веб-страницу. Теперь, когда мы установили это соединение, мы наконец можем начать писать content.js.

В этом файле мы напишем простой скрипт, который просто устанавливает белый цвет всех тегов p на текущей странице, а также применяет красную рамку. Мы можем назвать эту функцию whiteout. См. ниже.

whiteout = () => {

    var ptags = document.getElementsByTagName("p")

    for (var i = 0; i < ptags.length; ++i){
        ptags[i].style.color = "white"
        ptags[i].style.border = "solid 1px red"
    }

}

whiteout()

Довольно просто, нет? Давайте проверим это!

Просто перейдите на chrome://extensions/ и загрузите распакованный проект. Включите расширение в своем браузере, а затем нажмите на него, чтобы попробовать! Вам следует…

  1. Увидеть всплывающее окно с указанным содержимым
  2. Посмотрите, как теги p на вашей текущей веб-странице «забелены»

Вот так выглядит мой.

Вот оно! Теперь у вас есть сценарий содержимого, который выполняется, когда вы открываете всплывающее окно расширения Chrome. Это может быть полезно, когда вам нужно передать содержимое веб-страницы во всплывающее окно, чтобы пользователь мог видеть показатели или статистику или… просто поиграть со стилем.

Следите за моим следующим постом, в котором я более подробно расскажу о сценариях контента! И снова весь сопроводительный код к этому посту можно найти на GitHub.

Какие классные расширения для Chrome вы сделали? Дай мне знать в комментариях!

Обновите бесплатную подписку на Medium и получайте неограниченное количество статей без рекламы от тысяч авторов в самых разных изданиях. Это партнерская ссылка, и часть вашего членства помогает мне получать вознаграждение за контент, который я создаю.

Вы также можете подписаться по электронной почте и получать уведомления, когда я публикую что-то новое!

Рекомендации