2021-11-30 15:56:00 +03:00
|
|
|
// Copyright © 2021 Tokenary. All rights reserved.
|
2021-11-08 20:46:03 +03:00
|
|
|
|
|
|
|
import SafariServices
|
|
|
|
|
|
|
|
let SFExtensionMessageKey = "message"
|
|
|
|
|
|
|
|
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
|
2021-11-22 13:11:34 +03:00
|
|
|
|
|
|
|
private var context: NSExtensionContext?
|
|
|
|
private let queue = DispatchQueue(label: "SafariWebExtensionHandler", qos: .default)
|
|
|
|
|
|
|
|
func beginRequest(with context: NSExtensionContext) {
|
|
|
|
guard let item = context.inputItems[0] as? NSExtensionItem,
|
|
|
|
let message = item.userInfo?[SFExtensionMessageKey],
|
2022-02-11 20:35:22 +03:00
|
|
|
let data = try? JSONSerialization.data(withJSONObject: message, options: []) else { return }
|
2021-12-15 18:52:51 +03:00
|
|
|
|
2022-02-11 20:35:22 +03:00
|
|
|
let jsonDecoder = JSONDecoder()
|
|
|
|
if let internalSafariRequest = try? jsonDecoder.decode(InternalSafariRequest.self, from: data) {
|
|
|
|
let id = internalSafariRequest.id
|
|
|
|
switch internalSafariRequest.subject {
|
|
|
|
case .getResponse:
|
|
|
|
#if !os(macOS)
|
|
|
|
if let response = ExtensionBridge.getResponse(id: id) {
|
|
|
|
self.context = context
|
|
|
|
respond(with: response)
|
|
|
|
ExtensionBridge.removeResponse(id: id)
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
break
|
|
|
|
#endif
|
|
|
|
case .didCompleteRequest:
|
2021-12-15 20:17:22 +03:00
|
|
|
ExtensionBridge.removeResponse(id: id)
|
2021-12-15 18:52:51 +03:00
|
|
|
}
|
2022-02-11 20:35:22 +03:00
|
|
|
} else if let query = String(data: data, encoding: .utf8)?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
|
2021-12-15 23:25:12 +03:00
|
|
|
let request = SafariRequest(query: query),
|
2021-12-15 18:52:51 +03:00
|
|
|
let url = URL(string: "tokenary://safari?request=\(query)") {
|
|
|
|
self.context = context
|
2022-02-11 20:35:22 +03:00
|
|
|
if case let .ethereum(ethereumRequest) = request.body,
|
|
|
|
ethereumRequest.method == .switchEthereumChain || ethereumRequest.method == .addEthereumChain {
|
|
|
|
if let chain = ethereumRequest.switchToChain {
|
|
|
|
let responseBody = ResponseToExtension.Ethereum(results: [ethereumRequest.address], chainId: chain.hexStringId, rpcURL: chain.nodeURLString)
|
|
|
|
let response = ResponseToExtension(for: request, body: .ethereum(responseBody))
|
|
|
|
respond(with: response.json)
|
2021-12-15 23:25:12 +03:00
|
|
|
} else {
|
2022-02-11 20:35:22 +03:00
|
|
|
let response = ResponseToExtension(for: request, error: "Failed to switch chain")
|
|
|
|
respond(with: response.json)
|
2021-12-15 23:25:12 +03:00
|
|
|
}
|
|
|
|
} else {
|
2022-02-11 20:35:22 +03:00
|
|
|
ExtensionBridge.makeRequest(id: request.id)
|
2021-12-15 23:25:12 +03:00
|
|
|
#if os(macOS)
|
|
|
|
NSWorkspace.shared.open(url)
|
|
|
|
#endif
|
2022-02-11 20:35:22 +03:00
|
|
|
poll(id: request.id)
|
2021-12-15 23:25:12 +03:00
|
|
|
}
|
2021-11-22 13:11:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func poll(id: Int) {
|
|
|
|
if let response = ExtensionBridge.getResponse(id: id) {
|
|
|
|
respond(with: response)
|
2021-12-15 20:17:22 +03:00
|
|
|
#if os(macOS)
|
|
|
|
ExtensionBridge.removeResponse(id: id)
|
|
|
|
#endif
|
2021-11-22 13:11:34 +03:00
|
|
|
} else {
|
|
|
|
queue.asyncAfter(deadline: .now() + .milliseconds(500)) { [weak self] in
|
|
|
|
self?.poll(id: id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-03 18:40:28 +03:00
|
|
|
private func respond(with response: [String: Any]) {
|
2021-11-22 13:11:34 +03:00
|
|
|
let item = NSExtensionItem()
|
2022-02-11 20:35:22 +03:00
|
|
|
item.userInfo = [SFExtensionMessageKey: response]
|
2021-11-22 13:11:34 +03:00
|
|
|
context?.completeRequest(returningItems: [item], completionHandler: nil)
|
|
|
|
context = nil
|
2021-11-08 20:46:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|