From 83478a68ed1c210e5144f2939c3a3bf5f5ebd81b Mon Sep 17 00:00:00 2001 From: Tarik Eshaq Date: Wed, 23 Nov 2022 19:01:44 -0500 Subject: [PATCH] Fixes local builds not delivering send tabs --- Account/FxAPushMessageHandler.swift | 137 ++++++++++++++-------------- 1 file changed, 71 insertions(+), 66 deletions(-) diff --git a/Account/FxAPushMessageHandler.swift b/Account/FxAPushMessageHandler.swift index cf67d842b0dd5..464dba99611bc 100644 --- a/Account/FxAPushMessageHandler.swift +++ b/Account/FxAPushMessageHandler.swift @@ -61,82 +61,87 @@ extension FxAPushMessageHandler { // return handle(plaintext: string) let deferred = PushMessageResults() - RustFirefoxAccounts.reconfig(prefs: profile.prefs).uponQueue(.main) { accountManager in - accountManager.deviceConstellation()?.processRawIncomingAccountEvent(pushPayload: string) { - result in - guard case .success(let events) = result, !events.isEmpty else { - let err: PushMessageError - if case .failure(let error) = result { - SentryIntegration.shared.send(message: "Failed to get any events from FxA", tag: .fxaClient, severity: .error, description: error.localizedDescription) - err = PushMessageError.messageIncomplete(error.localizedDescription) - } else { - SentryIntegration.shared.send(message: "Got zero events from FxA", tag: .fxaClient, severity: .error, description: "no events retrieved from fxa") - err = PushMessageError.messageIncomplete("empty message") + // Reconfig has to happen on the main thread, since it calls `startup` + // and `startup` asserts that we are on the main thread. Otherwise the notification + // service will crash. + DispatchQueue.main.async { + RustFirefoxAccounts.reconfig(prefs: self.profile.prefs).uponQueue(.main) { accountManager in + accountManager.deviceConstellation()?.processRawIncomingAccountEvent(pushPayload: string) { + result in + guard case .success(let events) = result, !events.isEmpty else { + let err: PushMessageError + if case .failure(let error) = result { + SentryIntegration.shared.send(message: "Failed to get any events from FxA", tag: .fxaClient, severity: .error, description: error.localizedDescription) + err = PushMessageError.messageIncomplete(error.localizedDescription) + } else { + SentryIntegration.shared.send(message: "Got zero events from FxA", tag: .fxaClient, severity: .error, description: "no events retrieved from fxa") + err = PushMessageError.messageIncomplete("empty message") + } + deferred.fill(Maybe(failure: err)) + return } - deferred.fill(Maybe(failure: err)) - return - } - var messages: [PushMessage] = [] - - // It's possible one of the messages is a device disconnection - // in that case, we have an async call to get the name of the device - // we should make sure not to resolve our own value before that name retrieval - // is done - var waitForClient: Deferred>? - for event in events { - switch event { - case .commandReceived(let deviceCommand): - switch deviceCommand { - case .tabReceived(_, let tabData): - let title = tabData.entries.last?.title ?? "" - let url = tabData.entries.last?.url ?? "" - messages.append(PushMessage.commandReceived(tab: ["title": title, "url": url])) - if let json = try? accountManager.gatherTelemetry() { - let events = FxATelemetry.parseTelemetry(fromJSONString: json) - events.forEach { $0.record(intoPrefs: self.profile.prefs) } + var messages: [PushMessage] = [] + + // It's possible one of the messages is a device disconnection + // in that case, we have an async call to get the name of the device + // we should make sure not to resolve our own value before that name retrieval + // is done + var waitForClient: Deferred>? + for event in events { + switch event { + case .commandReceived(let deviceCommand): + switch deviceCommand { + case .tabReceived(_, let tabData): + let title = tabData.entries.last?.title ?? "" + let url = tabData.entries.last?.url ?? "" + messages.append(PushMessage.commandReceived(tab: ["title": title, "url": url])) + if let json = try? accountManager.gatherTelemetry() { + let events = FxATelemetry.parseTelemetry(fromJSONString: json) + events.forEach { $0.record(intoPrefs: self.profile.prefs) } + } + } + case .deviceConnected(let deviceName): + messages.append(PushMessage.deviceConnected(deviceName)) + case let .deviceDisconnected(deviceId, isLocalDevice): + if isLocalDevice { + // We can't disconnect the device from the account until we have access to the application, so we'll handle this properly in the AppDelegate (as this code in an extension), + // by calling the FxALoginHelper.applicationDidDisonnect(application). + self.profile.prefs.setBool(true, forKey: PendingAccountDisconnectedKey) + messages.append(PushMessage.thisDeviceDisconnected) } - } - case .deviceConnected(let deviceName): - messages.append(PushMessage.deviceConnected(deviceName)) - case let .deviceDisconnected(deviceId, isLocalDevice): - if isLocalDevice { - // We can't disconnect the device from the account until we have access to the application, so we'll handle this properly in the AppDelegate (as this code in an extension), - // by calling the FxALoginHelper.applicationDidDisonnect(application). - self.profile.prefs.setBool(true, forKey: PendingAccountDisconnectedKey) - messages.append(PushMessage.thisDeviceDisconnected) - } - - guard let profile = self.profile as? BrowserProfile else { - // We can't look up a name in testing, so this is the same as not knowing about it. - messages.append(PushMessage.deviceDisconnected(nil)) - break - } - waitForClient = Deferred>() - profile.remoteClientsAndTabs.getClient(fxaDeviceId: deviceId).uponQueue(.main) { result in - guard let device = result.successValue else { - waitForClient?.fill(Maybe(failure: result.failureValue ?? "Unknown Error")) - return + guard let profile = self.profile as? BrowserProfile else { + // We can't look up a name in testing, so this is the same as not knowing about it. + messages.append(PushMessage.deviceDisconnected(nil)) + break } - messages.append(PushMessage.deviceDisconnected(device?.name)) - waitForClient?.fill(Maybe(success: device?.name ?? "Unknown Device")) - if let id = device?.guid { - profile.remoteClientsAndTabs.deleteClient(guid: id).uponQueue(.main) { _ in - print("deleted client") + + waitForClient = Deferred>() + profile.remoteClientsAndTabs.getClient(fxaDeviceId: deviceId).uponQueue(.main) { result in + guard let device = result.successValue else { + waitForClient?.fill(Maybe(failure: result.failureValue ?? "Unknown Error")) + return + } + messages.append(PushMessage.deviceDisconnected(device?.name)) + waitForClient?.fill(Maybe(success: device?.name ?? "Unknown Device")) + if let id = device?.guid { + profile.remoteClientsAndTabs.deleteClient(guid: id).uponQueue(.main) { _ in + print("deleted client") + } } } + default: + // There are other events, but we ignore them at this level. + do {} } - default: - // There are other events, but we ignore them at this level. - do {} } - } - if let waitForClient = waitForClient { - waitForClient.upon { _ in + if let waitForClient = waitForClient { + waitForClient.upon { _ in + deferred.fill(Maybe(success: messages)) + } + } else { deferred.fill(Maybe(success: messages)) } - } else { - deferred.fill(Maybe(success: messages)) } } }