Несколько дней назад я опубликовал пост о том, как начать создавать расширение Chrome с помощью React. Этот пост был лишь отправной точкой для расширения.
В этом посте мы немного углубимся, и я объясню, как добавить в расширение возможности веб-перехвата с помощью API разработчика Chrome.
Примечание. Этот пост основан на предыдущем сообщении, поэтому обязательно прочтите предыдущий пост перед чтением.
Добавление фонового скрипта
Фоновый сценарий - это длительный сценарий, который может обрабатывать длительную задачу или состояние вашего расширения. Он работает как часть процесса расширения, но не имеет пользовательского интерфейса и выполняется отдельно от пользовательского интерфейса расширения. У каждого расширения может быть только один фоновый сценарий, существующий в течение всего времени существования расширения.
Чтобы создать фоновый сценарий, вам нужно сделать две вещи - добавить файл сценария для фонового сценария и обновить манифест расширения для поддержки этого сценария.
В расширении добавьте к общедоступной папке папку app и добавьте в нее файл background.js. Сначала файл будет пустым. Затем добавьте в манифест расширения следующее свойство:
"background": { "scripts": ["app/background.js"] }
Теперь проект будет выглядеть так:
Снова запустите сборку с помощью команды npm run build и перейдите к списку расширений Chrome. Используйте Ctrl + R или нажмите ссылку Обновить в элементе списка расширений, чтобы обновить расширение до последней версии.
В расширении вы увидите новую строку со ссылкой:
Inspect views: background page
Ссылка на фоновую страницу откроет фоновый сценарий в режиме отладки, который будет полезен позже для целей отладки.
Теперь мы готовы двигаться дальше и реализовать некоторые функции фонового скрипта.
Работа с Chrome webRequest API
Как было сказано в начале поста, мы захотим сделать наше расширение прокси-сервером для сетевых запросов. Чтобы перехватывать HTTP-запросы, вы должны знать API Chrome webRequest.
Chrome webRequest API - это набор полезных событий и функций, которые позволяют нам отслеживать и анализировать веб-трафик. Вы можете подключиться к жизненному циклу веб-запроса с помощью встроенных событий, а затем решить, что делать. Например, блокировщики рекламы используют такой механизм перехвата для отмены запросов к известным рекламным доменам.
Чтобы использовать API, вы должны объявить разрешение webRequest как часть манифеста расширения. В манифесте просто добавьте в массив разрешений webRequest и домен, который вы хотите отслеживать:
"permissions": [ "webRequest", "*://developer.mozilla.org/" ]
Примечание. Если вы не укажете разрешения, вы не сможете использовать API в своем расширении.
Наиболее полезные события, которые вы, вероятно, захотите прослушать:
- onBeforeRequest - запускается перед отправкой запроса.
- onCompleted - запускается при успешном завершении запроса.
- onErrorOccured - срабатывает при ошибке запроса.
Примечание. Есть и другие события жизненного цикла запроса, которые очень полезны, но я не буду их обсуждать в этой публикации.
В файл background.js добавьте следующий код:
(function() { const tabStorage = {}; const networkFilters = { urls: [ "*://developer.mozilla.org/*" ] }; chrome.webRequest.onBeforeRequest.addListener((details) => { const { tabId, requestId } = details; if (!tabStorage.hasOwnProperty(tabId)) { return; } tabStorage[tabId].requests[requestId] = { requestId: requestId, url: details.url, startTime: details.timeStamp, status: 'pending' }; console.log(tabStorage[tabId].requests[requestId]); }, networkFilters); chrome.webRequest.onCompleted.addListener((details) => { const { tabId, requestId } = details; if (!tabStorage.hasOwnProperty(tabId) || !tabStorage[tabId].requests.hasOwnProperty(requestId)) { return; } const request = tabStorage[tabId].requests[requestId]; Object.assign(request, { endTime: details.timeStamp, requestDuration: details.timeStamp - request.startTime, status: 'complete' }); console.log(tabStorage[tabId].requests[details.requestId]); }, networkFilters); chrome.webRequest.onErrorOccurred.addListener((details)=> { const { tabId, requestId } = details; if (!tabStorage.hasOwnProperty(tabId) || !tabStorage[tabId].requests.hasOwnProperty(requestId)) { return; } const request = tabStorage[tabId].requests[requestId]; Object.assign(request, { endTime: details.timeStamp, status: 'error', }); console.log(tabStorage[tabId].requests[requestId]); }, networkFilters); chrome.tabs.onActivated.addListener((tab) => { const tabId = tab ? tab.tabId : chrome.tabs.TAB_ID_NONE; if (!tabStorage.hasOwnProperty(tabId)) { tabStorage[tabId] = { id: tabId, requests: {}, registerTime: new Date().getTime() }; } }); chrome.tabs.onRemoved.addListener((tab) => { const tabId = tab.tabId; if (!tabStorage.hasOwnProperty(tabId)) { return; } tabStorage[tabId] = null; }); }());
Давайте разберемся, что делает код.
Вначале мы объявляем хранилище в памяти для хранения информации о запросах на вкладках. Мы также объявляем объект сетевого фильтра, который позже будет использоваться любым событием webRequest для фильтрации только желаемых запросов. В примере кода, только если кто-то перейдет в Mozilla Developer Network (MDN), мы запустим наш код.
После объявления переменных мы добавляем слушателей к событиям onBeforeRequest, onCompleted и onErrorOccured. В каждом случае мы добавляем некоторые данные запроса, которые собираемся использовать позже, в наше хранилище. Обратите внимание, что для каждой вкладки мы создаем собственный сборщик запросов.
И последнее, но не менее важное: мы используем chrome.tabs.onActivated для отслеживания создания вкладки и chrome.tabs.onRemoved для отслеживания удаления вкладки. Для каждой вкладки мы добавим новый объект вкладки в tabStorage или удалим его. Когда веб-запрос будет отправлен, мы сможем добавить его детали к уже доступному объекту вкладки. Это пока что в фоновом скрипте.
Теперь вы можете скомпилировать расширение, перезагрузить его в списке расширений Chrome, а затем открыть фоновый скрипт для отладки. Для этого используйте ссылку на фоновую страницу в списке расширений Chrome. Затем перейдите на веб-страницу в MDN и просмотрите в консоли собранную информацию.
Резюме
В этом посте я объяснил, как добавить фоновый скрипт к расширению Chrome. Я также показал вам, как использовать фоновый скрипт для отслеживания веб-запросов с помощью API webRequest. В следующем посте я покажу вам, как отражать данные, которые мы собрали, во всплывающем пользовательском интерфейсе с помощью React.
Увидимся в следующем посте!