Skip to content

Commit c5a79a7

Browse files
authored
Organize WKScriptMessageHandler message handling (home-assistant#3566)
<!-- Thank you for submitting a Pull Request and helping to improve Home Assistant. Please complete the following sections to help the processing and review of your changes. Please do not delete anything from this template. --> ## Summary <!-- Provide a brief summary of the changes you have made and most importantly what they aim to achieve --> ## Screenshots <!-- If this is a user-facing change not in the frontend, please include screenshots in light and dark mode. --> ## Link to pull request in Documentation repository <!-- Pull requests that add, change or remove functionality must have a corresponding pull request in the Companion App Documentation repository (https://github.com/home-assistant/companion.home-assistant). Please add the number of this pull request after the "#" --> Documentation: home-assistant/companion.home-assistant# ## Any other notes <!-- If there is any other information of note, like if this Pull Request is part of a bigger change, please include it here. -->
1 parent adaf0bf commit c5a79a7

File tree

1 file changed

+75
-53
lines changed

1 file changed

+75
-53
lines changed

Sources/App/WebView/WebViewController+WKScriptMessageHandler.swift

Lines changed: 75 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -27,72 +27,94 @@ extension WebViewController: WKScriptMessageHandler {
2727

2828
switch WKUserContentControllerMessage(rawValue: message.name) {
2929
case .externalBus:
30-
webViewExternalMessageHandler.handleExternalMessage(messageBody)
30+
handleExternalBus(messageBody)
3131
case .updateThemeColors:
32-
handleThemeUpdate(messageBody)
32+
handleUpdateThemeColors(messageBody)
3333
case .getExternalAuth:
34-
guard let callbackName = messageBody["callback"] else { return }
35-
36-
let force = messageBody["force"] as? Bool ?? false
37-
38-
Current.Log.verbose("getExternalAuth called, forced: \(force)")
39-
40-
firstly {
41-
Current.api(for: server)?.tokenManager
42-
.authDictionaryForWebView(forceRefresh: force) ??
43-
.init(error: HomeAssistantAPI.APIError.noAPIAvailable)
44-
}.done { dictionary in
45-
let jsonData = try? JSONSerialization.data(withJSONObject: dictionary)
46-
if let jsonString = String(data: jsonData!, encoding: .utf8) {
47-
let script = "\(callbackName)(true, \(jsonString))"
48-
self.webView.evaluateJavaScript(script, completionHandler: { result, error in
49-
if let error {
50-
Current.Log.error("Failed to trigger getExternalAuth callback: \(error)")
51-
}
52-
53-
Current.Log.verbose("Success on getExternalAuth callback: \(String(describing: result))")
54-
})
55-
}
56-
}.catch { error in
57-
self.webView.evaluateJavaScript("\(callbackName)(false, 'Token unavailable')")
58-
Current.Log.error("Failed to authenticate webview: \(error)")
59-
}
34+
handleGetExternalAuth(messageBody)
6035
case .revokeExternalAuth:
61-
guard let callbackName = messageBody["callback"] else { return }
62-
63-
Current.Log.warning("Revoking access token")
64-
65-
firstly {
66-
Current.api(for: server)?.tokenManager
67-
.revokeToken() ?? .init(error: HomeAssistantAPI.APIError.noAPIAvailable)
68-
}.done { [server] _ in
69-
Current.servers.remove(identifier: server.identifier)
36+
handleRevokeExternalAuth(messageBody)
37+
case .logError:
38+
handleLogError(messageBody)
39+
default:
40+
Current.Log.error("unknown message: \(message.name)")
41+
}
42+
}
7043

71-
let script = "\(callbackName)(true)"
44+
/// Handle theme changes from frontend, updating local cache and UI
45+
private func handleThemeUpdate(_ messageBody: [String: Any]) {
46+
ThemeColors.updateCache(with: messageBody, for: traitCollection)
47+
styleUI()
48+
}
7249

73-
Current.Log.verbose("Running revoke external auth callback \(script)")
50+
/// Handles externalBus messages by passing them to the webViewExternalMessageHandler.
51+
private func handleExternalBus(_ messageBody: [String: Any]) {
52+
webViewExternalMessageHandler.handleExternalMessage(messageBody)
53+
}
7454

75-
self.webView.evaluateJavaScript(script, completionHandler: { _, error in
76-
Current.onboardingObservation.needed(.logout)
55+
/// Updates the theme colors based on the message body.
56+
private func handleUpdateThemeColors(_ messageBody: [String: Any]) {
57+
handleThemeUpdate(messageBody)
58+
}
7759

60+
/// Retrieves an authentication token for the web view and invokes a JavaScript callback with the result.
61+
private func handleGetExternalAuth(_ messageBody: [String: Any]) {
62+
guard let callbackName = messageBody["callback"] else { return }
63+
let force = messageBody["force"] as? Bool ?? false
64+
65+
Current.Log.verbose("getExternalAuth called, forced: \(force)")
66+
67+
firstly {
68+
Current.api(for: server)?.tokenManager
69+
.authDictionaryForWebView(forceRefresh: force) ??
70+
.init(error: HomeAssistantAPI.APIError.noAPIAvailable)
71+
}.done { dictionary in
72+
let jsonData = try? JSONSerialization.data(withJSONObject: dictionary)
73+
if let jsonString = String(data: jsonData!, encoding: .utf8) {
74+
let script = "\(callbackName)(true, \(jsonString))"
75+
self.webView.evaluateJavaScript(script, completionHandler: { result, error in
7876
if let error {
79-
Current.Log.error("Failed calling sign out callback: \(error)")
77+
Current.Log.error("Failed to trigger getExternalAuth callback: \(error)")
8078
}
81-
82-
Current.Log.verbose("Successfully informed web client of log out.")
79+
Current.Log.verbose("Success on getExternalAuth callback: \(String(describing: result))")
8380
})
84-
}.catch { error in
85-
Current.Log.error("Failed to revoke token: \(error)")
8681
}
87-
case .logError:
88-
Current.Log.error("WebView error: \(messageBody.description.replacingOccurrences(of: "\n", with: " "))")
89-
default:
90-
Current.Log.error("unknown message: \(message.name)")
82+
}.catch { error in
83+
self.webView.evaluateJavaScript("\(callbackName)(false, 'Token unavailable')")
84+
Current.Log.error("Failed to authenticate webview: \(error)")
9185
}
9286
}
9387

94-
func handleThemeUpdate(_ messageBody: [String: Any]) {
95-
ThemeColors.updateCache(with: messageBody, for: traitCollection)
96-
styleUI()
88+
/// Revokes the current authentication token and informs the web view via a JavaScript callback.
89+
private func handleRevokeExternalAuth(_ messageBody: [String: Any]) {
90+
guard let callbackName = messageBody["callback"] else { return }
91+
92+
Current.Log.warning("Revoking access token")
93+
94+
firstly {
95+
Current.api(for: server)?.tokenManager
96+
.revokeToken() ?? .init(error: HomeAssistantAPI.APIError.noAPIAvailable)
97+
}.done { [server] _ in
98+
Current.servers.remove(identifier: server.identifier)
99+
let script = "\(callbackName)(true)"
100+
101+
Current.Log.verbose("Running revoke external auth callback \(script)")
102+
103+
self.webView.evaluateJavaScript(script, completionHandler: { _, error in
104+
Current.onboardingObservation.needed(.logout)
105+
106+
if let error {
107+
Current.Log.error("Failed calling sign out callback: \(error)")
108+
}
109+
110+
Current.Log.verbose("Successfully informed web client of log out.")
111+
})
112+
}.catch { error in
113+
Current.Log.error("Failed to revoke token: \(error)")
114+
}
115+
}
116+
117+
private func handleLogError(_ messageBody: [String: Any]) {
118+
Current.Log.error("WebView error: \(messageBody.description.replacingOccurrences(of: "\n", with: " "))")
97119
}
98120
}

0 commit comments

Comments
 (0)