Мы разрабатываем расширения для Safari на iOS, используя WebExtension API с учётом жёстких ограничений мобильной платформы. В отличие от desktop-браузеров, расширение упаковывается внутри нативного iOS-приложения, распространяется через App Store и активируется пользователем вручную в настройках Safari. Портировать Chrome-расширение напрямую не получится — половина desktop-логики ломается из-за особенностей iOS. Наш опыт: 5 лет в iOS-разработке, более 50 успешных проектов, гарантируем прохождение App Store Review. В среднем 80% JS-кода переносится без изменений, остальное требует ручной адаптации.
Почему iOS Safari Extension сложнее desktop-версии?
Desktop-браузеры позволяют фоновым скриптам работать постоянно, перехватывать сетевые запросы через webRequest и получать доступ ко всем вкладкам. На iOS эти возможности недоступны или работают иначе. Рассмотрим ключевые отличия.
Background scripts не работают
В Chrome background.js живёт постоянно. В iOS Safari Service Worker (MV3) выгружается сразу после выполнения задачи. Любое состояние, которое desktop-расширение хранит в памяти background script, на iOS нужно персистировать через browser.storage.local или передавать через нативный хост.
webRequest API отсутствует
Перехват и модификация сетевых запросов на iOS выполняются через Content Blockers (WKContentRuleList), а не через webRequest. Если ваше расширение блокирует рекламу через webRequest.onBeforeRequest, этот код не перенести напрямую.
Доступ к вкладкам ограничен
browser.tabs.query() возвращает только активную вкладку. Итерация по всем открытым вкладкам, как на desktop, недоступна.
Content scripts инжектируются с задержкой
На iOS страница может полностью загрузиться до того, как content script начнёт выполняться. Код, который рассчитывает на перехват DOMContentLoaded, может не успеть.
Как мы адаптируем расширение под iOS
Мы используем Swift 5.9+ для нативной части и JavaScript (ES2020) для веб-части. Каждое расширение проходит рефакторинг: миграцию с webRequest на WKContentRuleList, замену background.js на Service Worker с персистентностью в browser.storage.local. Вот пример нативного обработчика сообщений от JS:
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { func beginRequest(with context: NSExtensionContext) { guard let item = context.inputItems.first as? NSExtensionItem, let message = item.userInfo?[SFExtensionMessageKey] else { context.completeRequest(returningItems: nil, completionHandler: nil) return } // обрабатываем message от JS let response = NSExtensionItem() response.userInfo = [SFExtensionMessageKey: ["status": "ok"]] context.completeRequest(returningItems: [response], completionHandler: nil) } } Сравнение desktop и iOS Safari Extension
| Возможность | Desktop (Chrome) | iOS Safari |
|---|---|---|
| Фоновые скрипты | Постоянно активны | Service Worker выгружается |
| Перехват запросов | webRequest | WKContentRuleList |
| Доступ к вкладкам | Все вкладки | Только активная |
| Инжекция контента | В момент DOMContentLoaded | С задержкой |
| Native messaging | Через chrome.runtime.connectNative | browser.runtime.sendNativeMessage |
Типичные сложности при портировании
| Проблема | Решение | Время адаптации |
|---|---|---|
| Background script с состоянием | Перенос в storage.local | от 2 до 5 дней |
| Использование webRequest | Замена на WKContentRuleList | от 1 до 3 дней |
| Доступ к нескольким вкладкам | Переработка под активную вкладку | от 1 до 2 дней |
Типичный сценарий: менеджер паролей
Допустим, нужно автозаполнение через content script. JS инжектируется в страницу, находит <input type="password">, сообщает нативному хосту через browser.runtime.sendNativeMessage(). Нативный хост обращается к keychain через Security.framework и возвращает данные. Content script заполняет поле.
Проблема: sendNativeMessage на iOS работает только когда нативное Extension target запущено. Если пользователь не открывал приложение после перезагрузки устройства — Extension Host может не успеть стартовать. Нужен retry-механизм на стороне JS.
Как портировать Chrome-расширение в Safari?
- Запуск конвертера: выполните
xcrun safari-web-extension-converter --bundle-name YourExt path/to/extension. Утилита создаст Xcode-проект с native-обёрткой. - Анализ несовместимых API: проверьте использование
webRequest,background.js, неограниченный доступ к вкладкам. Эти участки подлежат замене. - Адаптация background: замените постоянный background script на Service Worker с персистентностью в
storage.local. Перепишите обработчики событий. - Миграция блокировки запросов: если используется
webRequest, перепишите наWKContentRuleList. Учтите, что Content Blocker поддерживает ограниченный набор правил (до 50 000 правил на блок). - Тестирование на реальном устройстве: используйте TestFlight для установки билда на iPhone. Проверьте работу content script на разных сайтах.
Что входит в работу
- Анализ вашего desktop-расширения (если есть) и составление карты несовместимых API
- Разработка нативного Extension target на Swift с обработчиками сообщений
- Адаптация JS-логики под iOS: замена
webRequest, фоновых скриптов, персистентность - Конфигурация манифеста и разрешений (обоснование для App Store)
- Интеграция с App Store Connect, TestFlight, Provisioning Profile
- Документация по сборке и публикации
- Поддержка в течение 30 дней после сдачи
Сроки и стоимость
Срок разработки: от 1 до 3 недель в зависимости от сложности JS-логики и объёма нативного взаимодействия. Стоимость рассчитывается индивидуально. Мы оценим проект после согласования требований.
Какие разрешения требуются для App Store?
App Store требует обоснования каждого разрешения в манифесте. tabs — для чего? storage — что именно хранится? Размытые ответы в форме подачи приводят к 4.0 Design rejection с просьбой уточнить функциональность.
Расширения с <all_urls> в host_permissions проходят усиленную проверку. Apple может запросить видеодемонстрацию работы расширения на реальном устройстве.
Почему мы?
Нативные обработчики на Swift в 10-20 раз быстрее JS для задач криптографии и работы с файлами. Если ваше расширение выполняет тяжёлые вычисления, перенос логики в нативный код даст заметный прирост производительности. Больше 50 портированных проектов подтверждают этот подход.
Свяжитесь с нами для оценки вашего проекта — мы подготовим предложение в течение 2 рабочих дней. Получите консультацию по адаптации вашего расширения уже сегодня.
Подробнее в документации Safari Web Extensions.







