blob: 9d3c911cc459f096c6ac15982186554febfdf550 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/app/main_application_delegate.h"
#include "base/mac/foundation_util.h"
#import "base/mac/scoped_nsobject.h"
#import "ios/chrome/app/application_delegate/app_navigation.h"
#import "ios/chrome/app/application_delegate/app_state.h"
#import "ios/chrome/app/application_delegate/background_activity.h"
#import "ios/chrome/app/application_delegate/browser_launcher.h"
#import "ios/chrome/app/application_delegate/memory_warning_helper.h"
#import "ios/chrome/app/application_delegate/metrics_mediator.h"
#import "ios/chrome/app/application_delegate/startup_information.h"
#import "ios/chrome/app/application_delegate/tab_opening.h"
#import "ios/chrome/app/application_delegate/tab_switching.h"
#import "ios/chrome/app/application_delegate/url_opener.h"
#import "ios/chrome/app/application_delegate/user_activity_handler.h"
#import "ios/chrome/app/chrome_overlay_window.h"
#import "ios/chrome/app/main_application_delegate_testing.h"
#import "ios/chrome/app/main_controller.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#include "ios/public/provider/chrome/browser/signin/chrome_identity_service.h"
@interface MainApplicationDelegate () {
base::scoped_nsobject<MainController> _mainController;
// Memory helper used to log the number of memory warnings received.
base::scoped_nsobject<MemoryWarningHelper> _memoryHelper;
// Metrics mediator used to check and update the metrics accordingly to
// to the user preferences.
base::scoped_nsobject<MetricsMediator> _metricsMediator;
// Browser launcher to have a global launcher.
base::scoped_nsprotocol<id<BrowserLauncher>> _browserLauncher;
// Container for startup information.
base::scoped_nsprotocol<id<StartupInformation>> _startupInformation;
// Helper to open new tabs.
base::scoped_nsprotocol<id<TabOpening>> _tabOpener;
// Handles the application stage changes.
base::scoped_nsobject<AppState> _appState;
// Handles tab switcher.
base::scoped_nsprotocol<id<AppNavigation>> _appNavigation;
// Handles tab switcher.
base::scoped_nsprotocol<id<TabSwitching>> _tabSwitcherProtocol;
}
@end
@implementation MainApplicationDelegate
- (instancetype)init {
if (self = [super init]) {
_memoryHelper.reset([[MemoryWarningHelper alloc] init]);
_mainController.reset([[MainController alloc] init]);
_metricsMediator.reset([[MetricsMediator alloc] init]);
[_mainController setMetricsMediator:_metricsMediator];
_browserLauncher.reset([_mainController retain]);
_startupInformation.reset([_mainController retain]);
_tabOpener.reset([_mainController retain]);
_appState.reset([[AppState alloc]
initWithBrowserLauncher:_browserLauncher
startupInformation:_startupInformation
applicationDelegate:self]);
_tabSwitcherProtocol.reset([_mainController retain]);
_appNavigation.reset([_mainController retain]);
[_mainController setAppState:_appState];
}
return self;
}
- (UIWindow*)window {
return [_mainController window];
}
- (void)setWindow:(UIWindow*)newWindow {
DCHECK(newWindow);
[_mainController setWindow:newWindow];
// self.window has been set by this time. _appState window can now be set.
[_appState setWindow:newWindow];
}
#pragma mark - UIApplicationDelegate methods -
#pragma mark Responding to App State Changes and System Events
// Called by the OS to create the UI for display. The UI will not be displayed,
// even if it is ready, until this function returns.
// The absolute minimum work should be done here, to ensure that the application
// startup is fast, and the UI appears as soon as possible.
- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
// Main window must be ChromeOverlayWindow or a subclass of it.
self.window = [[[ChromeOverlayWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
BOOL inBackground =
[application applicationState] == UIApplicationStateBackground;
return [_appState requiresHandlingAfterLaunchWithOptions:launchOptions
stateBackground:inBackground];
}
- (void)applicationDidBecomeActive:(UIApplication*)application {
if ([_appState isInSafeMode])
return;
[_appState resumeSessionWithTabOpener:_tabOpener
tabSwitcher:_tabSwitcherProtocol];
}
- (void)applicationWillResignActive:(UIApplication*)application {
if ([_appState isInSafeMode])
return;
[_appState willResignActiveTabModel];
}
// Called when going into the background. iOS already broadcasts, so
// stakeholders can register for it directly.
- (void)applicationDidEnterBackground:(UIApplication*)application {
[_appState
applicationDidEnterBackground:application
memoryHelper:_memoryHelper
tabSwitcherIsActive:[_mainController isTabSwitcherActive]];
}
// Called when returning to the foreground.
- (void)applicationWillEnterForeground:(UIApplication*)application {
[_appState applicationWillEnterForeground:application
metricsMediator:_metricsMediator
memoryHelper:_memoryHelper
tabOpener:_tabOpener
appNavigation:_appNavigation];
}
- (void)applicationWillTerminate:(UIApplication*)application {
if ([_appState isInSafeMode])
return;
// Instead of adding code here, consider if it could be handled by listening
// for UIApplicationWillterminate.
[_appState applicationWillTerminate:application
applicationNavigation:_appNavigation];
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application {
if ([_appState isInSafeMode])
return;
[_memoryHelper handleMemoryPressure];
}
#pragma mark Downloading Data in the Background
- (void)application:(UIApplication*)application
performFetchWithCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {
if ([_appState isInSafeMode])
return;
if ([application applicationState] != UIApplicationStateBackground) {
// If this handler is called in foreground, it means it has to be activated.
// Returning |UIBackgroundFetchResultNewData| means that the handler will be
// called again in case of a crash.
completionHandler(UIBackgroundFetchResultNewData);
return;
}
[BackgroundActivity application:application
performFetchWithCompletionHandler:completionHandler
metricsMediator:_metricsMediator
browserLauncher:_browserLauncher];
}
- (void)application:(UIApplication*)application
handleEventsForBackgroundURLSession:(NSString*)identifier
completionHandler:(void (^)(void))completionHandler {
if ([_appState isInSafeMode])
return;
[BackgroundActivity handleEventsForBackgroundURLSession:identifier
completionHandler:completionHandler
browserLauncher:_browserLauncher];
}
#pragma mark Continuing User Activity and Handling Quick Actions
- (BOOL)application:(UIApplication*)application
willContinueUserActivityWithType:(NSString*)userActivityType {
if ([_appState isInSafeMode])
return NO;
return
[UserActivityHandler willContinueUserActivityWithType:userActivityType];
}
- (BOOL)application:(UIApplication*)application
continueUserActivity:(NSUserActivity*)userActivity
restorationHandler:(void (^)(NSArray*))restorationHandler {
if ([_appState isInSafeMode])
return NO;
BOOL applicationIsActive =
[application applicationState] == UIApplicationStateActive;
return [UserActivityHandler continueUserActivity:userActivity
applicationIsActive:applicationIsActive
tabOpener:_tabOpener
startupInformation:_startupInformation];
}
- (void)application:(UIApplication*)application
performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler {
if ([_appState isInSafeMode])
return;
[UserActivityHandler
performActionForShortcutItem:shortcutItem
completionHandler:completionHandler
tabOpener:_tabOpener
startupInformation:_startupInformation
browserViewInformation:[_mainController browserViewInformation]];
}
#pragma mark Opening a URL-Specified Resource
// Handles open URL. The registered URL Schemes are defined in project
// variables ${CHROMIUM_URL_SCHEME_x}.
// The url can either be empty, in which case the app is simply opened or
// can contain an URL that will be opened in a new tab.
- (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
options:(NSDictionary<NSString*, id>*)options {
if ([_appState isInSafeMode])
return NO;
if (ios::GetChromeBrowserProvider()
->GetChromeIdentityService()
->HandleApplicationOpenURL(application, url, options)) {
return YES;
}
BOOL applicationActive =
[application applicationState] == UIApplicationStateActive;
return [URLOpener openURL:url
applicationActive:applicationActive
options:options
tabOpener:_tabOpener
startupInformation:_startupInformation];
}
#pragma mark - chromeExecuteCommand
- (void)chromeExecuteCommand:(id)sender {
[_mainController chromeExecuteCommand:sender];
}
#pragma mark - Testing methods
- (MainController*)mainController {
return _mainController;
}
- (AppState*)appState {
return _appState;
}
+ (MainController*)sharedMainController {
return base::mac::ObjCCast<MainApplicationDelegate>(
[[UIApplication sharedApplication] delegate])
.mainController;
}
@end