GeckoSessionHandler.swift (2324B)
1 // This Source Code Form is subject to the terms of the Mozilla Public 2 // License, v. 2.0. If a copy of the MPL was not distributed with this 3 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 protocol GeckoSessionHandlerCommon: EventListener { 6 var moduleName: String { get } 7 var events: [String] { get } 8 var enabled: Bool { get } 9 } 10 11 class GeckoSessionHandler<Delegate, Event: CaseIterable & RawRepresentable<String>>: 12 GeckoSessionHandlerCommon 13 { 14 let moduleName: String 15 let handle: @MainActor (GeckoSession, Delegate?, Event, [String: Any?]?) async throws -> Any? 16 17 private(set) weak var session: GeckoSession? 18 private var registeredListeners: Bool = false 19 var delegate: Delegate? { 20 didSet { 21 if let session { 22 if !registeredListeners && delegate != nil { 23 for event in events { 24 session.dispatcher.addListener(type: event, listener: self) 25 } 26 registeredListeners = true 27 } 28 29 // If session is not open, we will update module state during session opening. 30 if !session.isOpen() { 31 return 32 } 33 34 let message: [String: Any] = [ 35 "module": moduleName, 36 "enabled": delegate != nil, 37 ] 38 session.dispatcher.dispatch(type: "GeckoView:UpdateModuleState", message: message) 39 } 40 } 41 } 42 43 var events: [String] { 44 Event.allCases.map { $0.rawValue } 45 } 46 var enabled: Bool { 47 delegate != nil 48 } 49 50 init( 51 moduleName: String, session: GeckoSession, 52 handle: @escaping @MainActor (GeckoSession, Delegate?, Event, [String: Any?]?) async throws 53 -> 54 Any? 55 ) { 56 self.moduleName = moduleName 57 self.session = session 58 self.handle = handle 59 } 60 61 func handleMessage(type: String, message: [String: Any?]?) async throws -> Any? { 62 guard let event = Event(rawValue: type) else { 63 throw HandlerError("unknown message \(type)") 64 } 65 guard let session else { throw HandlerError("session has been destroyed") } 66 67 return try await self.handle(session, delegate, event, message) 68 } 69 }