mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
* perf(mobile): warm WebKit's processes on iOS before the first page opens Builds a blank, non-persistent WKWebView a second after Home has a paired host, so the first page open starts against WebContent, GPU and Network processes already running. A release before the delayed start now makes the start a no-op. Based on #32163 by Jinwoo-H. Co-authored-by: Jinwoo-H <73622457+Jinwoo-H@users.noreply.github.com> * fix(mobile): guard warmUp on older binaries and release the warm view on page failure Co-authored-by: Jinwoo-H <73622457+Jinwoo-H@users.noreply.github.com> --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local> Co-authored-by: Jinwoo-H <73622457+Jinwoo-H@users.noreply.github.com>
42 lines
1.7 KiB
Swift
42 lines
1.7 KiB
Swift
import UIKit
|
|
import WebKit
|
|
|
|
/// The first page view in a process waits for WebKit to launch its helper processes. A blank view
|
|
/// loaded while Home is idle pays that instead. It is held until the first page has loaded, so that
|
|
/// page starts against processes already up, or until the app backgrounds, memory runs low or a
|
|
/// minute passes. It has its own non-persistent store and no bridge or scripts, so it shares no
|
|
/// state with a page.
|
|
enum MobileWebShellWarmUp {
|
|
private static var view: WKWebView?
|
|
private static var started = false
|
|
private static var observers: [NSObjectProtocol] = []
|
|
|
|
static func start() {
|
|
dispatchPrecondition(condition: .onQueue(.main))
|
|
// A launch into the background may never show a page, so it gets no web process.
|
|
guard !started, UIApplication.shared.applicationState == .active else { return }
|
|
started = true
|
|
let configuration = WKWebViewConfiguration()
|
|
configuration.websiteDataStore = .nonPersistent()
|
|
let view = WKWebView(frame: .zero, configuration: configuration)
|
|
view.loadHTMLString("", baseURL: nil)
|
|
self.view = view
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 60) { release() }
|
|
observers = [
|
|
UIApplication.didReceiveMemoryWarningNotification,
|
|
UIApplication.didEnterBackgroundNotification
|
|
].map { name in
|
|
NotificationCenter.default.addObserver(forName: name, object: nil, queue: .main) { _ in release() }
|
|
}
|
|
}
|
|
|
|
static func release() {
|
|
dispatchPrecondition(condition: .onQueue(.main))
|
|
// A page that finished before the delayed start already has its processes, so start must no-op.
|
|
started = true
|
|
view = nil
|
|
observers.forEach { NotificationCenter.default.removeObserver($0) }
|
|
observers = []
|
|
}
|
|
}
|