Вы поклонник Flutter и хотите погрузиться в мир расширений Chrome? Не смотрите дальше! В этой статье мы отправим вас в путешествие по созданию базового расширения Chrome с использованием возможностей Flutter.

Мы будем использовать Flutter для создания начального приложения счетчика в Google Chrome. Но подождите, будет еще лучше. При каждом нажатии кнопки на экране веб-страницы пользователя будет появляться всплывающее окно. Увидьте себя на скриншоте ниже.

И как мы собираемся это сделать? Мы рассмотрим, как мы можем общатьсясDOM пользователя, используяAPI Chromeнепосредственно изFlutter.

Правильно, Флаттер и Хром сливаются вместе, как арахисовое масло и желе. Так что расслабьтесь, расслабьтесь и приготовьтесь повеселиться, потому что мы собираемся создать расширение для Chrome, которого вы никогда раньше не видели!

Как работает расширение Chrome?

Прежде чем начать, позвольте мне быстро и в общих чертах объяснить вам, как работает расширение Chrome.

Расширение Chrome состоит из нескольких частей, которые работают вместе, чтобы обеспечить беспрепятственный пользовательский интерфейс. Эти части включают фоновый сценарий, сценарий содержимого, всплывающее окно и файл манифеста.

фоновый скрипт постоянно работает в фоновом режиме и может выполнять такие задачи, как настройка прослушивателей или выполнение вызовов API. Важно отметить, что фоновый скрипт имеет ограниченный доступ к DOM, поэтому он не может напрямую взаимодействовать с веб-страницей пользователя, но может отправлять сообщения контентному скрипту.

Скрипт контента – это файл JavaScript, который запускается в контексте веб-страницы пользователя и может напрямую взаимодействовать с DOM. Это позволяет ему манипулировать веб-страницей, добавлять новые элементы или удалять существующие.

Всплывающее окно – это небольшой HTML-файл, который отображается, когда пользователь щелкает значок расширения на панели инструментов браузера. Это интерфейс, который позволяет пользователю взаимодействовать с расширением. Это то, что мы собираемся создать с помощью Flutter.

Файл манифеста с именем «manifest.json» действует как файл конфигурации для расширения Chrome. Он содержит информацию о расширении, такую ​​как его имя, описание, версию и сценарии, которые необходимо запустить. Он также указывает разрешения, которые требуются расширению, и действия браузера, которые оно должно выполнять.

Как мы будем использовать эти части?

В нашем случае мы будем отправлять сообщение из всплывающего окна в фоновый скрипт и отправлять эту информацию в скрипт содержимого. Затем сценарий содержимого получит это сообщение и выполнит требуемое действие. Такое взаимодействие между различными компонентами расширения Chrome стало возможным благодаря Chrome API, доступному только для Javascript.

И теперь у нас есть базовое понимание того, как работает расширение Chrome. Начнем!

1) Создание приложения Flutter

Во-первых, мы создадим приложение Flutter, выполнив следующую команду в своем терминале:

flutter create flutter_chrome_app

Далее мы установим пакет js из pubspec.yaml. Этот удобный небольшой пакет позволит нам совершать вызовы к Chrome API с помощью JavaScript, что значительно облегчит нам жизнь.

dependencies:
  js: ^0.6.4
  flutter:
    sdk: flutter

Затем создайте файл в папке lib с именем «chrome_api.dart» и поместите следующий код:

@JS('chrome')
library main; // library name can be whatever you want

import 'package:js/js.dart';

@JS('runtime.sendMessage')
external sendMessage(ParameterSendMessage parameterSendMessage);

@JS()
@anonymous
class ParameterSendMessage {
  external String get type;
  external String get data;

  external factory ParameterSendMessage({String type, String data});
}

Здесь мы используем метод разбора сообщений Chrome API. Подробнее об этом можно узнать здесь. То, как мы форматируем код здесь и почему мы это делаем, также объясняется в документации JS-пакета для Flutter.

Когда вы закончите, не забудьте изменить атрибут onPressed вашей плавающей кнопки действия следующим образом:

floatingActionButton: FloatingActionButton(
          onPressed: () {
            _incrementCounter();
            sendMessage(ParameterSendMessage(
                type: "counter", data: _counter.toString()));
          },
          ...
        ));

Здесь происходит то, что каждый раз, когда срабатывает плавающая кнопка, приложение Flutter обновляет свой пользовательский интерфейс с номером счетчика, но оно также отправляет сообщение в виде строки в фоновый скрипт.

2) Создайте папку для расширения Chrome.

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

Сначала измените файл «index.html» следующим образом:

  • добавление строки для измерения приложения внутри HTML вверху
<html style="height: 600px; width: 350px">
  • изменение сценария вашего файла, сохранив только эту строку
<script src="main.dart.js" type="application/javascript"></script>

Вот как должен выглядеть ваш HTML-файл:

<!DOCTYPE html>
<html style="height: 600px; width: 350px">
<head>

  <base href="$FLUTTER_BASE_HREF">

  <meta charset="UTF-8">
  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  <meta name="description" content="A new Flutter project.">

  <!-- iOS meta tags & icons -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="flutter_chrome_app">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">

  <!-- Favicon -->
  <link rel="icon" type="image/png" href="favicon.png"/>

  <title>flutter_chrome_app</title>
  <link rel="manifest" href="manifest.json">

</head>
<body>
  <script src="main.dart.js" type="application/javascript"></script>
</body>
</html>

Затем измените свой «manifest.json» следующим образом:

{
    "name": "flutter_chrome_app",   
    "description": "A new Flutter project.",
    "version": "1.0.0",
    "content_security_policy": {
        "extension_pages": "script-src 'self' ; object-src 'self'"
    },
    "background": {
        "service_worker": "background.js"
      },
    "content_scripts": [
        {
          "matches": [
            "<all_urls>"
          ],
          "js": [
            "contentScript.js"
          ]
        }
      ],
    "action": {
        "default_popup": "index.html",
        "default_icon": "icons/Icon-192.png"
    },
    "manifest_version": 3
}

И, наконец, используйте эту команду для создания папки:

flutter build web --web-renderer html --csp

3) Добавляем фон и скрипт контента

Теперь в вашем приложении Flutter у вас должна быть папка «build» с папкой «web» внутри. Не стесняйтесь переименовать его в «chrome-extension», чтобы избежать ошибок.

Теперь давайте создадим эти два файла внутри папки:

background.js

Следующий код позволяет отправлять сообщения между фоновым сценарием и сценарием содержимого.

chrome.runtime.onMessage.addListener прослушивает входящие сообщения с типом «счетчик» (это то, что мы отправляем из приложения Flutter).

Когда сообщение этого типа получено, она вызывает функцию sendMessage.
Эта функция sendMessage отправляет сообщение в скрипт контента с типом «уведомления» и параметром «сообщение» на активную вкладку в Google Chrome.

function sendMessage(message) {
  chrome.tabs.query({ active: !0, currentWindow: !0 }, function (tabs) {
    chrome.tabs.sendMessage(tabs[0].id, { "type": "notifications", "data": message });
  });
}

chrome.runtime.onMessage.addListener(async function (message, sender, sendResponse) {
  if (message.type === "counter") {
    sendMessage(message.data);
  }
});

contentScript.js

Код создает всплывающее сообщение с использованием JavaScript и API среды выполнения Chrome.

Когда браузер получает сообщение типа «уведомления», вызывается функция create_popup с данными сообщения в качестве аргумента.

Эта функция создает элемент div с элементом сообщения и кнопкой закрытия в div и добавляет div в тело документа. Кнопка закрытия имеет прослушиватель событий щелчка, который удаляет всплывающий элемент при нажатии. Всплывающее окно также автоматически исчезнет через 3 секунды, если оно не было закрыто пользователем.

function create_popup(message) {
  
    var popup = document.createElement("div");
    popup.id = "popup";
    popup.style.cssText = "position:fixed;bottom:20px;right:20px;width:200px;height:90px;background-color:rgba(35,68,128);z-index:9999;text-align:center;font-size:13px;padding:10px;border-radius: 10px;box-shadow: 0px 0px 5px #888888; display: flex; align-items: center; justify-content: center; flex-direction: column;";
    var messageItem = document.createElement("message-item");
    messageItem.innerHTML = message;
    messageItem.style.cssText = "margin: 0; padding-right:10px; color: white";

    var closeBtn = document.createElement("div");
    closeBtn.innerHTML = "<p>✖︎</p>";
    closeBtn.style.cssText = "position:absolute;top:0;right:10px;cursor:pointer;";

    popup.appendChild(messageItem);
    popup.appendChild(closeBtn);
    document.body.appendChild(popup);
    closeBtn.addEventListener("click", function () {
      popup.remove();
    });
    setTimeout(function () {
      popup.remove();
    }, 3000);
  
}

chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
  if (message.type == "notifications") {
    create_popup(message.data);
  }
});

Вот и все!

Вот как должна выглядеть ваша папка:

Вот Github со всем кодом, который мы создали.

4) Последний шаг: установите приложение в Google Chrome.

Наконец-то мы можем установить приложение:

1. Откройте Google Chrome и перейдите на страницу «Расширения», введя «chrome://extensions» в адресной строке и нажав «Ввод».

2. Включите тумблер «Режим разработчика» в правом верхнем углу страницы.

3. Нажмите кнопку «Загрузить распакованное» и выберите папку, содержащую расширение, которое вы хотите установить.

4. После выбора папки Chrome установит расширение, и вы увидите его в списке на странице «Расширения».

Теперь вы сможете использовать расширение Chrome! Не забудьте обновить страницу, на которой вы пытаетесь заставить его работать, будьте осторожны, это не сработает на странице расширений.

Заключение

В этой статье мы узнали, как создать базовое расширение Chrome с помощью Flutter и Chrome API.
Мы рассмотрели различные части расширения Chrome, включая фоновый сценарий, сценарий содержимого, всплывающее окно и файл манифеста.

Мы объяснили, как взаимодействовать между различными компонентами расширения с помощью функции Chrome sendMessage и как манипулировать DOM веб-страницы пользователя.

Если у вас есть какие-либо вопросы или замечания, не стесняйтесь оставлять комментарии. И следите за моим следующим руководством о том, как пройти аутентификацию в Firebase с помощью Flutter в расширении Chrome. Удачного кодирования!

Вот Github со всем кодом, который мы создали.