diff --git a/Client/Application/AppDelegate.swift b/Client/Application/AppDelegate.swift index 29714b86035b..3d137ef62336 100644 --- a/Client/Application/AppDelegate.swift +++ b/Client/Application/AppDelegate.swift @@ -32,6 +32,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati var tabManager: TabManager! var adjustIntegration: AdjustIntegration? var foregroundStartTime = 0 + var applicationCleanlyBackgrounded = true weak var application: UIApplication? var launchOptions: [AnyHashable: Any]? @@ -47,6 +48,24 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati var receivedURLs: [URL]? @discardableResult func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // + // Determine if the application cleanly exited last time it was used. We default to true in + // case we have never done this before. Then check if the "ApplicationCleanlyBackgrounded" user + // default exists and whether was properly set to true on app exit. + // + // Then we always set the user default to false. It will be set to true when we the application + // is backgrounded. + // + + self.applicationCleanlyBackgrounded = true + + let defaults = UserDefaults() + if defaults.object(forKey: "ApplicationCleanlyBackgrounded") != nil { + self.applicationCleanlyBackgrounded = defaults.bool(forKey: "ApplicationCleanlyBackgrounded") + } + defaults.set(false, forKey: "ApplicationCleanlyBackgrounded") + defaults.synchronize() + // Hold references to willFinishLaunching parameters for delayed app launch self.application = application self.launchOptions = launchOptions @@ -444,6 +463,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati return } + // + // We are back in the foreground, so set CleanlyBackgrounded to false so that we can detect that + // the application was cleanly backgrounded later. + // + + let defaults = UserDefaults() + defaults.set(false, forKey: "ApplicationCleanlyBackgrounded") + defaults.synchronize() + profile?.reopen() NightModeHelper.restoreNightModeBrightness((self.profile?.prefs)!, toForeground: true) @@ -475,6 +503,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati } func applicationDidEnterBackground(_ application: UIApplication) { + // + // At this point we are happy to mark the app as CleanlyBackgrounded. If a crash happens in background + // sync then that crash will still be reported. But we won't bother the user with the Restore Tabs + // dialog. We don't have to because at this point we already saved the tab state properly. + // + + let defaults = UserDefaults() + defaults.set(true, forKey: "ApplicationCleanlyBackgrounded") + defaults.synchronize() + syncOnDidEnterBackground(application: application) let elapsed = Int(Date().timeIntervalSince1970) - foregroundStartTime diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index 3ef81aa563c4..d36f4a68bfc5 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -549,7 +549,8 @@ class BrowserViewController: UIViewController { self.view.alpha = (profile.prefs.intForKey(IntroViewControllerSeenProfileKey) != nil) ? 1.0 : 0.0 } - if !displayedRestoreTabsAlert && hasPendingCrashReport() { + if !displayedRestoreTabsAlert && !cleanlyBackgrounded() && crashedLastLaunch() { + SentryIntegration.shared.send(message: "Asking to restore tabs", tag: "BrowserViewController", severity: .info, completion: nil) displayedRestoreTabsAlert = true showRestoreTabsAlert() } else { @@ -569,10 +570,17 @@ class BrowserViewController: UIViewController { object: nil) } - fileprivate func hasPendingCrashReport() -> Bool { + fileprivate func crashedLastLaunch() -> Bool { return SentryIntegration.crashedLastLaunch } + fileprivate func cleanlyBackgrounded() -> Bool { + guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { + return false + } + return appDelegate.applicationCleanlyBackgrounded + } + fileprivate func showRestoreTabsAlert() { if !canRestoreTabs() { self.tabManager.addTabAndSelect()