-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add comments to new rust fxa code, split app delegate up for clarity (#…
…6280) * Add comments to new rust fxa code * Split up app delegate for push notification handling, and sync sent tab handling * fix swift lint issues * address nits
- Loading branch information
1 parent
db84e6a
commit 1e6e116
Showing
6 changed files
with
263 additions
and
160 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
import Shared | ||
import Storage | ||
import Sync | ||
import XCGLogger | ||
import UserNotifications | ||
import Account | ||
|
||
private let log = Logger.browserLogger | ||
|
||
/** | ||
* This exists because the Sync code is extension-safe, and thus doesn't get | ||
* direct access to UIApplication.sharedApplication, which it would need to display a notification. | ||
* This will also likely be the extension point for wipes, resets, and getting access to data sources during a sync. | ||
*/ | ||
enum SentTabAction: String { | ||
case view = "TabSendViewAction" | ||
|
||
static let TabSendURLKey = "TabSendURL" | ||
static let TabSendTitleKey = "TabSendTitle" | ||
static let TabSendCategory = "TabSendCategory" | ||
|
||
static func registerActions() { | ||
let viewAction = UNNotificationAction(identifier: SentTabAction.view.rawValue, title: Strings.SentTabViewActionTitle, options: .foreground) | ||
|
||
// Register ourselves to handle the notification category set by NotificationService for APNS notifications | ||
let sentTabCategory = UNNotificationCategory(identifier: "org.mozilla.ios.SentTab.placeholder", actions: [viewAction], intentIdentifiers: [], options: UNNotificationCategoryOptions(rawValue: 0)) | ||
UNUserNotificationCenter.current().setNotificationCategories([sentTabCategory]) | ||
} | ||
} | ||
|
||
extension AppDelegate { | ||
func pushNotificationSetup() { | ||
UNUserNotificationCenter.current().delegate = self | ||
SentTabAction.registerActions() | ||
|
||
NotificationCenter.default.addObserver(forName: .RegisterForPushNotifications, object: nil, queue: .main) { _ in | ||
UNUserNotificationCenter.current().getNotificationSettings { settings in | ||
DispatchQueue.main.async { | ||
if settings.authorizationStatus != .denied { | ||
UIApplication.shared.registerForRemoteNotifications() | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
private func openURLsInNewTabs(_ notification: UNNotification) { | ||
guard let urls = notification.request.content.userInfo["sentTabs"] as? [NSDictionary] else { return } | ||
for sentURL in urls { | ||
if let urlString = sentURL.value(forKey: "url") as? String, let url = URL(string: urlString) { | ||
receivedURLs.append(url) | ||
} | ||
} | ||
|
||
// Check if the app is foregrounded, _also_ verify the BVC is initialized. Most BVC functions depend on viewDidLoad() having run –if not, they will crash. | ||
if UIApplication.shared.applicationState == .active && BrowserViewController.foregroundBVC().isViewLoaded { | ||
BrowserViewController.foregroundBVC().loadQueuedTabs(receivedURLs: receivedURLs) | ||
receivedURLs.removeAll() | ||
} | ||
} | ||
} | ||
|
||
extension AppDelegate: UNUserNotificationCenterDelegate { | ||
// Called when the user taps on a sent-tab notification from the background. | ||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { | ||
openURLsInNewTabs(response.notification) | ||
} | ||
|
||
// Called when the user receives a tab (or any other notification) while in foreground. | ||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { | ||
|
||
if profile?.prefs.boolForKey(PendingAccountDisconnectedKey) ?? false { | ||
FxALoginHelper.sharedInstance.disconnect() | ||
// show the notification | ||
completionHandler([.alert, .sound]) | ||
} else { | ||
openURLsInNewTabs(notification) | ||
} | ||
} | ||
} | ||
|
||
extension AppDelegate { | ||
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { | ||
RustFirefoxAccounts.shared.pushNotifications.didRegister(withDeviceToken: deviceToken) | ||
} | ||
|
||
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { | ||
print("failed to register. \(error)") | ||
Sentry.shared.send(message: "Failed to register for APNS") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
import Shared | ||
import Storage | ||
import Sync | ||
import XCGLogger | ||
import UserNotifications | ||
import Account | ||
|
||
private let log = Logger.browserLogger | ||
|
||
extension UIApplication { | ||
var syncDelegate: SyncDelegate { | ||
return AppSyncDelegate(app: self) | ||
} | ||
} | ||
|
||
/** | ||
Sent tabs can be displayed not only by receiving push notifications, but by sync. | ||
Sync will get the list of sent tabs, and try to display any in that list. | ||
Thus, push notifications are not needed to receive sent tabs, they can be handled | ||
when the app performs a sync. | ||
*/ | ||
class AppSyncDelegate: SyncDelegate { | ||
let app: UIApplication | ||
|
||
init(app: UIApplication) { | ||
self.app = app | ||
} | ||
|
||
func displaySentTab(for url: URL, title: String, from deviceName: String?) { | ||
DispatchQueue.main.sync { | ||
if app.applicationState == .active { | ||
BrowserViewController.foregroundBVC().switchToTabForURLOrOpen(url) | ||
return | ||
} | ||
|
||
// check to see what the current notification settings are and only try and send a notification if | ||
// the user has agreed to them | ||
UNUserNotificationCenter.current().getNotificationSettings { settings in | ||
if settings.alertSetting != .enabled { | ||
return | ||
} | ||
if Logger.logPII { | ||
log.info("Displaying notification for URL \(url.absoluteString)") | ||
} | ||
|
||
let notificationContent = UNMutableNotificationContent() | ||
let title: String | ||
if let deviceName = deviceName { | ||
title = String(format: Strings.SentTab_TabArrivingNotification_WithDevice_title, deviceName) | ||
} else { | ||
title = Strings.SentTab_TabArrivingNotification_NoDevice_title | ||
} | ||
notificationContent.title = title | ||
notificationContent.body = url.absoluteDisplayExternalString | ||
notificationContent.userInfo = [SentTabAction.TabSendURLKey: url.absoluteString, SentTabAction.TabSendTitleKey: title] | ||
notificationContent.categoryIdentifier = "org.mozilla.ios.SentTab.placeholder" | ||
|
||
// `timeInterval` must be greater than zero | ||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false) | ||
|
||
// The identifier for each notification request must be unique in order to be created | ||
let requestIdentifier = "\(SentTabAction.TabSendCategory).\(url.absoluteString)" | ||
let request = UNNotificationRequest(identifier: requestIdentifier, content: notificationContent, trigger: trigger) | ||
|
||
UNUserNotificationCenter.current().add(request) { error in | ||
if let error = error { | ||
log.error(error.localizedDescription) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.