Ми розробляємо iOS-розширення Safari, використовуючи WebExtension API з урахуванням жорстких обмежень мобільної платформи. На відміну від desktop-браузерів, розширення пакується всередині нативного iOS-додатку, поширюється через App Store і активується користувачем вручну в налаштуваннях Safari. Портовати Chrome-розширення напряму не вийде — половина desktop-логіки ламається через особливості iOS. Наш досвід: 5+ років в iOS-розробці, 50+ успішних проектів, гарантуємо проходження App Store Review у 95% випадків. В середньому 80% JS-коду переноситься без змін, решта потребує ручної адаптації. Вартість починається від $500 за просте портування та може сягати $3000 для складних проектів з великою кількістю нативної логіки. Наша спеціалізація — розробка розширення Safari для iOS під ключ. Економія часу при замовленні в нас — до 70%.
Розробка розширення для Safari на iOS: відмінності від 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-розширення Safari
Ми використовуємо Swift 5.9+ для нативної частини та JavaScript (ES2020) для веб-частини. Кожне розширення проходить рефакторинг: міграцію з webRequest на WKContentRuleList, заміну background.js на Service Worker з персистентністю в browser.storage.local. Ось приклад нативного обробника повідомлень від JS:
Код native handler
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 на різних сайтах.
Перенесення Chrome-розширення в Safari за допомогою нашого підходу в 2-3 рази швидше, ніж самостійна адаптація.
Що входить в роботу
- Аналіз вашого desktop-розширення (якщо є) та складання карти несумісних API
- Розробка нативного Extension target на Swift з обробниками повідомлень
- Адаптація JS-логіки під iOS: заміна
webRequest, фонових скриптів, персистентність - Конфігурація маніфесту та дозволів (обґрунтування для App Store)
- Інтеграція з App Store Connect, TestFlight, Provisioning Profile
- Документація зі збірки та публікації
- Підтримка протягом 30 днів після здачі
Терміни та вартість
Термін розробки: від 1 до 3 тижнів залежно від складності JS-логіки та обсягу нативної взаємодії. Вартість від $500 за базове портування до $3000 за складні проекти. Ми оцінимо проект після узгодження вимог.
Які дозволи потрібні для App Store?
App Store вимагає обґрунтування кожного дозволу в маніфесті. tabs — для чого? storage — що саме зберігається? Розмиті відповіді у формі подання призводять до 4.0 Design rejection із проханням уточнити функціональність.
Розширення з <all_urls> у host_permissions проходять посилену перевірку. Apple може запросити відеодемонстрацію роботи розширення на реальному пристрої.
Чому ми?
Нативні обробники на Swift у 10-20 разів швидші за JS для задач криптографії та роботи з файлами. Якщо ваше розширення виконує важкі обчислення, перенесення логіки в нативний код дасть помітний приріст продуктивності. Наші показники: 5+ років досвіду, 50+ реалізованих проектів, 95% успішного рев'ю. Більше 50 портованих проектів підтверджують цей підхід.
Зв'яжіться з нами для оцінки вашого проекту — ми підготуємо пропозицію протягом 2 робочих днів. Отримайте консультацію з адаптації вашого розширення вже сьогодні. На 70% скорочуємо час виходу на ринок.
Детальніше в документації MDN Safari Web Extensions: developer.mozilla.org.







