Commit 9132909e authored by Vasilii Sukhanov's avatar Vasilii Sukhanov Committed by Commit Bot

Revert "[iOS][multiball] Move AppURLLoadingServiceDelegate to Scene."

This reverts commit 4a58461b.

Reason for revert: broke compilation on iOS
https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket.appspot.com/8891643701272051152/+/steps/compile/0/stdout

Original change's description:
> [iOS][multiball] Move AppURLLoadingServiceDelegate to Scene.
> 
> Moves AppURLLoadingServiceDelegate from Main to Scene Controller.
> * adds SceneControllerGuts temporary interface to expose scene-level
> internals to MainController while the code is moved.
> 
> Bug: None
> Change-Id: I0c7dbe077a94ff5b9c598c401c9c7340cc8f969c
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1983226
> Commit-Queue: Stepan Khapugin <stkhapugin@chromium.org>
> Reviewed-by: Mark Cogan <marq@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#730151}

TBR=marq@chromium.org,stkhapugin@chromium.org

Change-Id: I65d0afac9c2296574c324784960b36ecb1802b43
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: None
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1995171Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#730160}
parent 1f6515df
......@@ -233,7 +233,6 @@ source_set("app_internal") {
"//ios/chrome/browser/ui/history",
"//ios/chrome/browser/ui/main",
"//ios/chrome/browser/ui/main:scene",
"//ios/chrome/browser/ui/main:scene_guts",
"//ios/chrome/browser/ui/promos",
"//ios/chrome/browser/ui/settings",
"//ios/chrome/browser/ui/settings:settings_root",
......
......@@ -86,7 +86,6 @@
_sceneController =
[[SceneController alloc] initWithSceneState:_sceneState];
// TODO(crbug.com/1040501): remove this.
// This is temporary plumbing that's not supposed to be here.
_sceneController.mainController = (id<MainControllerGuts>)_mainController;
_mainController.sceneController = _sceneController;
......
......@@ -17,9 +17,7 @@
@class AppState;
@class MetricsMediator;
@protocol AppURLLoadingServiceDelegate;
@protocol BrowsingDataCommands;
@protocol SceneControllerGuts;
@protocol TabSwitcherDelegate;
// The main controller of the application, owned by the MainWindow nib. Also
......@@ -47,10 +45,7 @@
@property(nonatomic, weak) MetricsMediator* metricsMediator;
// For temporary plumbing only.
@property(nonatomic, weak) id<ApplicationCommands,
TabSwitcherDelegate,
AppURLLoadingServiceDelegate,
SceneControllerGuts>
@property(nonatomic, weak) id<ApplicationCommands, TabSwitcherDelegate>
sceneController;
@end
......
......@@ -75,6 +75,7 @@
#include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "ios/chrome/browser/crash_report/breakpad_helper.h"
#include "ios/chrome/browser/crash_report/crash_loop_detection_util.h"
#import "ios/chrome/browser/crash_report/crash_restore_helper.h"
#include "ios/chrome/browser/download/download_directory_util.h"
#import "ios/chrome/browser/external_files/external_file_remover_factory.h"
#import "ios/chrome/browser/external_files/external_file_remover_impl.h"
......@@ -90,6 +91,7 @@
#include "ios/chrome/browser/metrics/first_user_action_recorder.h"
#import "ios/chrome/browser/metrics/previous_session_info.h"
#import "ios/chrome/browser/net/cookie_util.h"
#include "ios/chrome/browser/ntp/features.h"
#include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h"
#include "ios/chrome/browser/payments/ios_payment_instrument_launcher.h"
#include "ios/chrome/browser/payments/ios_payment_instrument_launcher_factory.h"
......@@ -124,7 +126,6 @@
#import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h"
#include "ios/chrome/browser/ui/history/history_coordinator.h"
#import "ios/chrome/browser/ui/main/browser_view_wrangler.h"
#import "ios/chrome/browser/ui/main/scene_controller_guts.h"
#import "ios/chrome/browser/ui/promos/signin_promo_view_controller.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#import "ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.h"
......@@ -238,6 +239,11 @@ void RegisterComponentsForUpdate() {
cus, GetApplicationContext()->GetApplicationLocale());
}
// Used to update the current BVC mode if a new tab is added while the tab
// switcher view is being dimissed. This is different than ApplicationMode in
// that it can be set to |NONE| when not in use.
enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
// The delay, in seconds, for cleaning external files.
const int kExternalFilesCleanupDelaySeconds = 60;
......@@ -280,7 +286,8 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
} // namespace
@interface MainController () <BrowserStateStorageSwitching,
@interface MainController () <AppURLLoadingServiceDelegate,
BrowserStateStorageSwitching,
PrefObserverDelegate,
WebStateListObserving> {
IBOutlet UIWindow* _window;
......@@ -296,13 +303,27 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
// BrowserViewInformation protocol.
BrowserViewWrangler* _browserViewWrangler;
// Parameters received at startup time when the app is launched from another
// app.
AppStartupParameters* _startupParameters;
// TabSwitcher object -- the tab grid.
id<TabSwitcher> _tabSwitcher;
// YES while animating the dismissal of tab switcher.
BOOL _dismissingTabSwitcher;
// If not NONE, the current BVC should be switched to this BVC on completion
// of tab switcher dismissal.
TabSwitcherDismissalMode _modeToDisplayOnTabSwitcherDismissal;
// True if the current session began from a cold start. False if the app has
// entered the background at least once since start up.
BOOL _isColdStart;
// Keeps track of the restore state during startup.
CrashRestoreHelper* _restoreHelper;
// An object to record metrics related to the user's first action.
std::unique_ptr<FirstUserActionRecorder> _firstUserActionRecorder;
......@@ -351,6 +372,22 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
// browser has started up to the FOREGROUND stage.
@property(nonatomic, readonly) TabGridCoordinator* mainCoordinator;
// A property to track whether the QR Scanner should be started upon tab
// switcher dismissal. It can only be YES if the QR Scanner experiment is
// enabled.
@property(nonatomic, readwrite)
NTPTabOpeningPostOpeningAction NTPActionAfterTabSwitcherDismissal;
// Returns YES if the settings are presented, either from
// self.settingsNavigationController or from SigninInteractionCoordinator.
@property(nonatomic, assign, readonly, getter=isSettingsViewPresented)
BOOL settingsViewPresented;
// Activates |mainBVC| and |otrBVC| and sets |currentBVC| as primary iff
// |currentBVC| can be made active.
- (void)activateBVCAndMakeCurrentBVCPrimary;
// Sets |currentBVC| as the root view controller for the window.
- (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox;
// Shows the tab switcher UI.
- (void)showTabSwitcher;
// Starts a voice search on the current BVC.
......@@ -359,6 +396,26 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
- (void)lastIncognitoTabClosed;
// Called when the last regular tab was closed.
- (void)lastRegularTabClosed;
// Opens a tab in the target BVC, and switches to it in a way that's appropriate
// to the current UI, based on the |dismissModals| flag:
// - If a modal dialog is showing and |dismissModals| is NO, the selected tab of
// the main tab model will change in the background, but the view won't change.
// - Otherwise, any modal view will be dismissed, the tab switcher will animate
// out if it is showing, the target BVC will become active, and the new tab will
// be shown.
// If the current tab in |targetMode| is a NTP, it can be reused to open URL.
// |completion| is executed after the tab is opened. After Tab is open the
// virtual URL is set to the pending navigation item.
- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)targetMode
withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
completion:(ProceduralBlock)completion;
// Checks the target BVC's current tab's URL. If this URL is chrome://newtab,
// loads |urlLoadParams| in this tab. Otherwise, open |urlLoadParams| in a new
// tab in the target BVC. |tabDisplayedCompletion| will be called on the new tab
// (if not nil).
- (void)openOrReuseTabInMode:(ApplicationMode)targetMode
withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
tabOpenedCompletion:(ProceduralBlock)tabOpenedCompletion;
// Returns whether the restore infobar should be displayed.
- (bool)mustShowRestoreInfobar;
// Switch all global states for the given mode (normal or incognito).
......@@ -450,8 +507,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
@synthesize isProcessingTabSwitcherCommand;
@synthesize isProcessingVoiceSearchCommand;
@synthesize signinInteractionCoordinator;
@synthesize dismissingTabSwitcher = _dismissingTabSwitcher;
@synthesize restoreHelper = _restoreHelper;
// Defined by public protocols.
// - BrowserLauncher
......@@ -467,8 +522,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
@synthesize NTPActionAfterTabSwitcherDismissal =
_NTPActionAfterTabSwitcherDismissal;
@synthesize tabSwitcherIsActive;
@synthesize modeToDisplayOnTabSwitcherDismissal =
_modeToDisplayOnTabSwitcherDismissal;
#pragma mark - Application lifecycle
......@@ -591,17 +644,17 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
_browserStateManager->GetLastUsedBrowserState();
// The CrashRestoreHelper must clean up the old browser state information
// before the tabModels can be created. |self.restoreHelper| must be kept
// alive until the BVC receives the browser state and tab model.
// before the tabModels can be created. |_restoreHelper| must be kept alive
// until the BVC receives the browser state and tab model.
BOOL postCrashLaunch = [self mustShowRestoreInfobar];
if (postCrashLaunch) {
self.restoreHelper =
_restoreHelper =
[[CrashRestoreHelper alloc] initWithBrowserState:chromeBrowserState];
[self.restoreHelper moveAsideSessionInformation];
[_restoreHelper moveAsideSessionInformation];
}
self.appURLLoadingService = new AppUrlLoadingService();
self.appURLLoadingService->SetDelegate(self.sceneController);
self.appURLLoadingService->SetDelegate(self);
// Initialize and set the main browser state.
[self initializeBrowserState:chromeBrowserState];
......@@ -684,16 +737,16 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
appState:self.appState];
_launchOptions = nil;
if (!self.startupParameters) {
if (!_startupParameters) {
// The startup parameters may create new tabs or navigations. If the restore
// infobar is displayed now, it may be dismissed immediately and the user
// will never be able to restore the session.
TabModel* currentTabModel = [self currentTabModel];
[self.restoreHelper
[_restoreHelper
showRestoreIfNeededUsingWebState:currentTabModel.webStateList
->GetActiveWebState()
sessionRestorer:currentTabModel];
self.restoreHelper = nil;
_restoreHelper = nil;
}
[self scheduleTasksRequiringBVCWithBrowserState];
......@@ -719,9 +772,9 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
[self markEulaAsAccepted];
if (self.startupParameters) {
if (_startupParameters) {
UrlLoadParams params =
UrlLoadParams::InNewTab(self.startupParameters.externalURL);
UrlLoadParams::InNewTab(_startupParameters.externalURL);
[self dismissModalsAndOpenSelectedTabInMode:ApplicationModeForTabOpening::
NORMAL
withUrlLoadParams:params
......@@ -1277,14 +1330,13 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
TabModel* tabModel;
if (launchMode == ApplicationMode::INCOGNITO) {
tabModel = otrTabModel;
[self.sceneController
setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
[self setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
} else {
tabModel = mainTabModel;
[self.sceneController setCurrentInterfaceForMode:ApplicationMode::NORMAL];
[self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
}
if (self.tabSwitcherIsActive) {
DCHECK(!self.dismissingTabSwitcher);
DCHECK(!_dismissingTabSwitcher);
[self beginDismissingTabSwitcherWithCurrentModel:self.mainTabModel
focusOmnibox:NO];
[self finishDismissingTabSwitcher];
......@@ -1299,7 +1351,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
if (firstRun) {
[self showFirstRunUI];
// Do not ever show the 'restore' infobar during first run.
self.restoreHelper = nil;
_restoreHelper = nil;
}
}
......@@ -1356,7 +1408,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
if (self.currentBVC == self.otrBVC)
return;
// Don't show promos if the app was launched from a URL.
if (self.startupParameters)
if (_startupParameters)
return;
// Show the sign-in promo if needed
......@@ -1405,6 +1457,26 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
#pragma mark - AppURLLoadingServiceDelegate
- (void)openURLInNewTabWithCommand:(OpenNewTabCommand*)command {
[self openURLInNewTab:command];
}
- (void)expectNewForegroundTabForMode:(ApplicationMode)targetMode {
id<BrowserInterface> interface =
targetMode == ApplicationMode::INCOGNITO
? self.interfaceProvider.incognitoInterface
: self.interfaceProvider.mainInterface;
DCHECK(interface);
[interface.bvc expectNewForegroundTab];
}
- (void)openNewTabFromOriginPoint:(CGPoint)originPoint
focusOmnibox:(BOOL)focusOmnibox {
[self.currentBVC openNewTabFromOriginPoint:originPoint
focusOmnibox:focusOmnibox];
}
#pragma mark - Preferences Management
......@@ -1443,7 +1515,34 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
return self.interfaceProvider.currentInterface.bvc;
}
// Note that the current tab of |browserCoordinator|'s BVC will normally be
// reloaded by this method. If a new tab is about to be added, call
// expectNewForegroundTab on the BVC first to avoid extra work and possible page
// load side-effects for the tab being replaced.
- (void)setCurrentInterfaceForMode:(ApplicationMode)mode {
DCHECK(self.interfaceProvider);
BOOL incognitio = mode == ApplicationMode::INCOGNITO;
id<BrowserInterface> currentInterface =
self.interfaceProvider.currentInterface;
id<BrowserInterface> newInterface =
incognitio ? self.interfaceProvider.incognitoInterface
: self.interfaceProvider.mainInterface;
if (currentInterface && currentInterface == newInterface)
return;
// Update the snapshot before switching another application mode. This
// ensures that the snapshot is correct when links are opened in a different
// application mode.
[self updateActiveWebStateSnapshot];
self.interfaceProvider.currentInterface = newInterface;
if (!_dismissingTabSwitcher)
[self displayCurrentBVCAndFocusOmnibox:NO];
// Tell the BVC that was made current that it can use the web.
[self activateBVCAndMakeCurrentBVCPrimary];
}
#pragma mark - Tab closure handlers
......@@ -1476,7 +1575,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
if ([self.currentTabModel count] == 0U) {
[self showTabSwitcher];
} else {
[self.sceneController setCurrentInterfaceForMode:ApplicationMode::NORMAL];
[self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
}
}
......@@ -1581,14 +1680,14 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
focusOmnibox:(BOOL)focusOmnibox {
DCHECK(tabModel == self.mainTabModel || tabModel == self.otrTabModel);
self.dismissingTabSwitcher = YES;
_dismissingTabSwitcher = YES;
ApplicationMode mode = (tabModel == self.mainTabModel)
? ApplicationMode::NORMAL
: ApplicationMode::INCOGNITO;
[self.sceneController setCurrentInterfaceForMode:mode];
[self setCurrentInterfaceForMode:mode];
// The call to set currentBVC above does not actually display the BVC, because
// self.dismissingTabSwitcher is YES. So: Force the BVC transition to start.
// _dismissingTabSwitcher is YES. So: Force the BVC transition to start.
[self displayCurrentBVCAndFocusOmnibox:focusOmnibox];
}
......@@ -1603,8 +1702,8 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
// user to the tab switcher.
if (self.currentTabModel.count == 0U) {
self.tabSwitcherIsActive = NO;
self.dismissingTabSwitcher = NO;
self.modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
_dismissingTabSwitcher = NO;
_modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
self.NTPActionAfterTabSwitcherDismissal = NO_ACTION;
[self showTabSwitcher];
return;
......@@ -1615,16 +1714,15 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
// animations begin, so it should be the current active VC at this point.
DCHECK_EQ(self.mainCoordinator.activeViewController, self.currentBVC);
if (self.modeToDisplayOnTabSwitcherDismissal ==
if (_modeToDisplayOnTabSwitcherDismissal ==
TabSwitcherDismissalMode::NORMAL) {
[self.sceneController setCurrentInterfaceForMode:ApplicationMode::NORMAL];
} else if (self.modeToDisplayOnTabSwitcherDismissal ==
[self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
} else if (_modeToDisplayOnTabSwitcherDismissal ==
TabSwitcherDismissalMode::INCOGNITO) {
[self.sceneController
setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
[self setCurrentInterfaceForMode:ApplicationMode::INCOGNITO];
}
self.modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
_modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
ProceduralBlock action = [self completionBlockForTriggeringAction:
self.NTPActionAfterTabSwitcherDismissal];
......@@ -1634,10 +1732,11 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
}
self.tabSwitcherIsActive = NO;
self.dismissingTabSwitcher = NO;
_dismissingTabSwitcher = NO;
}
#pragma mark - App Navigation
#pragma mark - Navigation Controllers
- (void)presentSignedInAccountsViewControllerForBrowserState:
(ios::ChromeBrowserState*)browserState {
......@@ -1653,7 +1752,32 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
- (void)closeSettingsAnimated:(BOOL)animated
completion:(ProceduralBlock)completion {
[self.sceneController closeSettingsAnimated:animated completion:completion];
if (self.settingsNavigationController) {
[self.settingsNavigationController cleanUpSettings];
UIViewController* presentingViewController =
[self.settingsNavigationController presentingViewController];
// If presentingViewController is nil it means the VC was already dismissed
// by some other action like swiping down.
DCHECK(presentingViewController);
[presentingViewController dismissViewControllerAnimated:animated
completion:completion];
self.settingsNavigationController = nil;
return;
}
// |self.signinInteractionCoordinator| can also present settings, like
// the advanced sign-in settings navigation controller. If the settings has
// to be cloase, it is thus the responsibility of the main controller to
// dismiss the the advanced sign-in settings by dismssing the settings
// presented by |self.signinInteractionCoordinator|.
// To reproduce this case:
// - open Bookmark view
// - start sign-in
// - tap on "Settings" to open the advanced sign-in settings
// - tap on "Manage Your Google Account"
DCHECK(self.signinInteractionCoordinator.isSettingsViewPresented);
[self.signinInteractionCoordinator
abortAndDismissSettingsViewAnimated:animated
completion:completion];
}
#pragma mark - WebStateListObserving
......@@ -1678,6 +1802,54 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
#pragma mark - Tab opening utility methods.
- (void)openOrReuseTabInMode:(ApplicationMode)targetMode
withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
tabOpenedCompletion:(ProceduralBlock)tabOpenedCompletion {
BrowserViewController* targetBVC =
targetMode == ApplicationMode::NORMAL ? self.mainBVC : self.otrBVC;
web::WebState* currentWebState =
targetBVC.tabModel.webStateList->GetActiveWebState();
// Don't call loadWithParams for chrome://newtab when it's already loaded.
// Note that it's safe to use -GetVisibleURL here, as it doesn't matter if the
// NTP hasn't finished loading.
if (currentWebState && IsURLNtp(currentWebState->GetVisibleURL()) &&
IsURLNtp(urlLoadParams.web_params.url)) {
if (tabOpenedCompletion) {
tabOpenedCompletion();
}
return;
}
// With kBrowserContainerContainsNTP enabled paired with a restored NTP
// session, the NTP may appear committed when it is still loading. For the
// time being, always load within a new tab when this feature is enabled.
// TODO(crbug.com/931284): Revert this change when fixed.
BOOL alwaysInsertNewTab =
base::FeatureList::IsEnabled(kBlockNewTabPagePendingLoad);
// If the current tab isn't an NTP, open a new tab. Be sure to use
// -GetLastCommittedURL incase the NTP is still loading.
if (alwaysInsertNewTab ||
!(currentWebState && IsURLNtp(currentWebState->GetVisibleURL()))) {
[targetBVC appendTabAddedCompletion:tabOpenedCompletion];
UrlLoadParams newTabParams = urlLoadParams;
newTabParams.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
newTabParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
->Load(newTabParams);
return;
}
// Otherwise, load |urlLoadParams| in the current tab.
UrlLoadParams sameTabParams = urlLoadParams;
sameTabParams.disposition = WindowOpenDisposition::CURRENT_TAB;
UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
->Load(sameTabParams);
if (tabOpenedCompletion) {
tabOpenedCompletion();
}
}
- (ProceduralBlock)completionBlockForTriggeringAction:
(NTPTabOpeningPostOpeningAction)action {
switch (action) {
......@@ -1698,6 +1870,164 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
}
}
- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)tabOpeningTargetMode
withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
completion:(ProceduralBlock)completion {
// Update the snapshot before opening a new tab. This ensures that the
// snapshot is correct when tabs are openned via the dispatcher.
[self updateActiveWebStateSnapshot];
ApplicationMode targetMode;
if (tabOpeningTargetMode == ApplicationModeForTabOpening::CURRENT) {
targetMode = self.interfaceProvider.currentInterface.incognito
? ApplicationMode::INCOGNITO
: ApplicationMode::NORMAL;
} else if (tabOpeningTargetMode == ApplicationModeForTabOpening::NORMAL) {
targetMode = ApplicationMode::NORMAL;
} else {
targetMode = ApplicationMode::INCOGNITO;
}
id<BrowserInterface> targetInterface =
targetMode == ApplicationMode::NORMAL
? self.interfaceProvider.mainInterface
: self.interfaceProvider.incognitoInterface;
NSUInteger tabIndex = NSNotFound;
ProceduralBlock startupCompletion =
[self completionBlockForTriggeringAction:[_startupParameters
postOpeningAction]];
// Commands are only allowed on NTP.
DCHECK(IsURLNtp(urlLoadParams.web_params.url) || !startupCompletion);
ProceduralBlock tabOpenedCompletion = nil;
if (startupCompletion && completion) {
tabOpenedCompletion = ^{
// Order is important here. |completion| may do cleaning tasks that will
// invalidate |startupCompletion|.
startupCompletion();
completion();
};
} else if (startupCompletion) {
tabOpenedCompletion = startupCompletion;
} else {
tabOpenedCompletion = completion;
}
if (self.tabSwitcherIsActive) {
// If the tab switcher is already being dismissed, simply add the tab and
// note that when the tab switcher finishes dismissing, the current BVC
// should be switched to be the main BVC if necessary.
if (_dismissingTabSwitcher) {
_modeToDisplayOnTabSwitcherDismissal =
targetMode == ApplicationMode::NORMAL
? TabSwitcherDismissalMode::NORMAL
: TabSwitcherDismissalMode::INCOGNITO;
[targetInterface.bvc appendTabAddedCompletion:tabOpenedCompletion];
UrlLoadParams savedParams = urlLoadParams;
savedParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
UrlLoadingServiceFactory::GetForBrowserState(
[targetInterface.bvc browserState])
->Load(savedParams);
} else {
// Voice search, QRScanner and the omnibox are presented by the BVC.
// They must be started after the BVC view is added in the hierarchy.
self.NTPActionAfterTabSwitcherDismissal =
[_startupParameters postOpeningAction];
[self setStartupParameters:nil];
[_tabSwitcher dismissWithNewTabAnimationToBrowser:targetInterface.browser
withUrlLoadParams:urlLoadParams
atIndex:tabIndex];
}
} else {
if (!self.currentBVC.presentedViewController) {
[targetInterface.bvc expectNewForegroundTab];
}
[self setCurrentInterfaceForMode:targetMode];
[self openOrReuseTabInMode:targetMode
withUrlLoadParams:urlLoadParams
tabOpenedCompletion:tabOpenedCompletion];
}
if (_restoreHelper) {
// Now that all the operations on the tabs have been done, display the
// restore infobar if needed.
dispatch_async(dispatch_get_main_queue(), ^{
TabModel* currentTabModel = [self currentTabModel];
[_restoreHelper
showRestoreIfNeededUsingWebState:currentTabModel.webStateList
->GetActiveWebState()
sessionRestorer:currentTabModel];
_restoreHelper = nil;
});
}
}
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox {
// Immediately hide modals from the provider (alert views, action sheets,
// popovers). They will be ultimately dismissed by their owners, but at least,
// they are not visible.
ios::GetChromeBrowserProvider()->HideModalViewStack();
// ChromeIdentityService is responsible for the dialogs displayed by the
// services it wraps.
ios::GetChromeBrowserProvider()->GetChromeIdentityService()->DismissDialogs();
// MailtoHandlerProvider is responsible for the dialogs displayed by the
// services it wraps.
ios::GetChromeBrowserProvider()
->GetMailtoHandlerProvider()
->DismissAllMailtoHandlerInterfaces();
// Then, depending on what the SSO view controller is presented on, dismiss
// it.
ProceduralBlock completionWithBVC = ^{
DCHECK(self.currentBVC);
DCHECK(!self.tabSwitcherIsActive);
DCHECK(!self.signinInteractionCoordinator.isActive);
// This will dismiss the SSO view controller.
[self.interfaceProvider.currentInterface
clearPresentedStateWithCompletion:completion
dismissOmnibox:dismissOmnibox];
};
ProceduralBlock completionWithoutBVC = ^{
// |self.currentBVC| may exist but tab switcher should be active.
DCHECK(self.tabSwitcherIsActive);
// This will dismiss the SSO view controller.
[self.signinInteractionCoordinator cancelAndDismiss];
// History coordinator can be started on top of the tab grid. This is not
// true of the other tab switchers.
DCHECK(self.mainCoordinator);
[self.mainCoordinator stopChildCoordinatorsWithCompletion:completion];
};
// As a top level rule, if the settings are showing, they need to be
// dismissed. Then, based on whether the BVC is present or not, a different
// completion callback is called.
if (!self.tabSwitcherIsActive && self.isSettingsViewPresented) {
// In this case, the settings are up and the BVC is showing. Close the
// settings then call the BVC completion.
[self closeSettingsAnimated:NO completion:completionWithBVC];
} else if (self.isSettingsViewPresented) {
// In this case, the settings are up but the BVC is not showing. Close the
// settings then call the no-BVC completion.
[self closeSettingsAnimated:NO completion:completionWithoutBVC];
} else if (![self isTabSwitcherActive]) {
// In this case, the settings are not shown but the BVC is showing. Call the
// BVC completion.
[self.signinInteractionCoordinator cancel];
completionWithBVC();
} else {
// In this case, neither the settings nor the BVC are shown. Call the no-BVC
// completion.
completionWithoutBVC();
}
// Verify that no modal views are left presented.
ios::GetChromeBrowserProvider()->LogIfModalViewsArePresented();
}
- (bool)mustShowRestoreInfobar {
if ([self isFirstLaunchAfterUpgrade])
......@@ -1715,6 +2045,18 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
return result;
}
// Asks the respective Snapshot helper to update the snapshot for the active
// WebState.
- (void)updateActiveWebStateSnapshot {
WebStateList* webStateList = self.currentBVC.tabModel.webStateList;
if (webStateList) {
web::WebState* webState = webStateList->GetActiveWebState();
if (webState) {
SnapshotTabHelper::FromWebState(webState)->UpdateSnapshotWithCallback(
nil);
}
}
}
- (void)purgeSnapshots {
NSMutableSet* liveSessions = [self liveSessionsForTabModel:self.mainTabModel];
......@@ -1745,11 +2087,11 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
dismissOmnibox:(BOOL)dismissOmnibox
completion:(ProceduralBlock)completion {
UrlLoadParams copyOfUrlLoadParams = urlLoadParams;
[self.sceneController
[self
dismissModalDialogsWithCompletion:^{
[self.sceneController openSelectedTabInMode:targetMode
withUrlLoadParams:copyOfUrlLoadParams
completion:completion];
[self openSelectedTabInMode:targetMode
withUrlLoadParams:copyOfUrlLoadParams
completion:completion];
}
dismissOmnibox:dismissOmnibox];
}
......@@ -1829,6 +2171,21 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
return [self currentBrowserState] -> IsOffTheRecord();
}
// This method is temporarily both required in the scene controller and here.
- (void)openURLInNewTab:(OpenNewTabCommand*)command {
UrlLoadParams params =
UrlLoadParams::InNewTab(command.URL, command.virtualURL);
params.SetInBackground(command.inBackground);
params.web_params.referrer = command.referrer;
params.in_incognito = command.inIncognito;
params.append_to = command.appendTo;
params.origin_point = command.originPoint;
params.from_chrome = command.fromChrome;
params.user_initiated = command.userInitiated;
params.should_focus_omnibox = command.shouldFocusOmnibox;
self.appURLLoadingService->LoadUrlInNewTab(params);
}
#pragma mark - BrowsingDataCommands
- (void)removeBrowsingDataForBrowserState:(ios::ChromeBrowserState*)browserState
......@@ -1902,12 +2259,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
@implementation MainController (TestingOnly)
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox {
[self.sceneController dismissModalDialogsWithCompletion:completion
dismissOmnibox:dismissOmnibox];
}
- (DeviceSharingManager*)deviceSharingManager {
return [_browserViewWrangler deviceSharingManager];
}
......@@ -1927,9 +2278,13 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
self.tabSwitcherIsActive = active;
}
- (BOOL)dismissingTabSwitcher {
return _dismissingTabSwitcher;
}
- (void)setStartupParametersWithURL:(const GURL&)launchURL {
NSString* sourceApplication = @"Fake App";
self.startupParameters = [ChromeAppStartupParameters
_startupParameters = [ChromeAppStartupParameters
newChromeAppStartupParametersWithURL:net::NSURLWithGURL(launchURL)
fromSourceApplication:sourceApplication];
}
......
......@@ -7,7 +7,6 @@
#import <UIKit/UIKit.h>
#import "ios/chrome/browser/crash_report/crash_restore_helper.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
......@@ -23,11 +22,6 @@ namespace ios {
class ChromeBrowserState;
} // namespace ios
// Used to update the current BVC mode if a new tab is added while the tab
// switcher view is being dismissed. This is different than ApplicationMode in
// that it can be set to |NONE| when not in use.
enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
// TODO(crbug.com/1012697): Remove this protocol when SceneController is
// operational. Move the private internals back into MainController, and pass
// ownership of Scene-related objects to SceneController.
......@@ -60,38 +54,10 @@ enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
SigninInteractionCoordinator* signinInteractionCoordinator;
// If YES, the tab switcher is currently active.
@property(nonatomic, assign, getter=isTabSwitcherActive)
BOOL tabSwitcherIsActive;
// YES while animating the dismissal of tab switcher.
@property(nonatomic, assign) BOOL dismissingTabSwitcher;
// Returns YES if the settings are presented, either from
// self.settingsNavigationController or from SigninInteractionCoordinator.
@property(nonatomic, assign, readonly, getter=isSettingsViewPresented)
BOOL settingsViewPresented;
// If not NONE, the current BVC should be switched to this BVC on completion
// of tab switcher dismissal.
@property(nonatomic, assign)
TabSwitcherDismissalMode modeToDisplayOnTabSwitcherDismissal;
// A property to track whether the QR Scanner should be started upon tab
// switcher dismissal. It can only be YES if the QR Scanner experiment is
// enabled.
@property(nonatomic, readwrite)
NTPTabOpeningPostOpeningAction NTPActionAfterTabSwitcherDismissal;
// Parameters received at startup time when the app is launched from another
// app.
@property(nonatomic, strong) AppStartupParameters* startupParameters;
- (ProceduralBlock)completionBlockForTriggeringAction:
(NTPTabOpeningPostOpeningAction)action;
// Keeps track of the restore state during startup.
@property(nonatomic, strong) CrashRestoreHelper* restoreHelper;
- (id<TabSwitcher>)tabSwitcher;
- (TabModel*)currentTabModel;
- (id<TabSwitcher>)tabSwitcher;
......@@ -104,6 +70,11 @@ enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
- (id<BrowserInterfaceProvider>)interfaceProvider;
- (void)startVoiceSearchInCurrentBVC;
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox;
- (void)closeSettingsAnimated:(BOOL)animated
completion:(ProceduralBlock)completion;
- (void)dismissModalsAndOpenSelectedTabInMode:
(ApplicationModeForTabOpening)targetMode
withUrlLoadParams:
......@@ -124,13 +95,6 @@ enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
// screen and showing the appropriate BVC.
- (void)finishDismissingTabSwitcher;
// Sets |currentBVC| as the root view controller for the window.
- (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox;
// Activates |mainBVC| and |otrBVC| and sets |currentBVC| as primary iff
// |currentBVC| can be made active.
- (void)activateBVCAndMakeCurrentBVCPrimary;
@end
#endif // IOS_CHROME_APP_MAIN_CONTROLLER_GUTS_H_
......@@ -24,7 +24,10 @@ class GURL;
// Presents a promo's navigation controller.
- (void)showPromo:(UIViewController*)promo;
- (BOOL)dismissingTabSwitcher;
// Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is
// NO, then call |completion|.
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox;
@end
......@@ -39,16 +42,12 @@ class GURL;
// Tab switcher state.
@property(nonatomic, getter=isTabSwitcherActive) BOOL tabSwitcherActive;
@property(nonatomic, readonly) BOOL dismissingTabSwitcher;
// Sets the internal startup state to indicate that the launch was triggered
// by an external app opening the given URL.
- (void)setStartupParametersWithURL:(const GURL&)launchURL;
// Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is
// NO, then call |completion|.
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox;
@end
#endif // IOS_CHROME_APP_MAIN_CONTROLLER_PRIVATE_H_
......@@ -4,19 +4,6 @@
import("//ios/build/chrome_build.gni")
source_set("scene_guts") {
sources = [
"scene_controller_guts.h",
]
deps = [
"//ios/chrome/app/application_delegate:application_delegate_internal",
"//ios/chrome/browser:utils",
"//ios/chrome/browser/url_loading",
]
libs = [ "UIKit.framework" ]
}
source_set("scene") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
......@@ -30,18 +17,15 @@ source_set("scene") {
deps = [
":main",
":scene_guts",
"//base",
"//components/signin/public/identity_manager",
"//components/url_formatter",
"//ios/chrome/app:app",
"//ios/chrome/app/application_delegate:application_delegate_internal",
"//ios/chrome/browser",
"//ios/chrome/browser:chrome_url_constants",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/browsing_data",
"//ios/chrome/browser/main",
"//ios/chrome/browser/ntp:features",
"//ios/chrome/browser/signin",
"//ios/chrome/browser/snapshots",
"//ios/chrome/browser/tabs:tabs",
......@@ -55,9 +39,6 @@ source_set("scene") {
"//ios/chrome/browser/ui/util:multiwindow_util",
"//ios/chrome/browser/url_loading",
"//ios/chrome/browser/web_state_list",
"//ios/public/provider/chrome/browser",
"//ios/public/provider/chrome/browser/mailto",
"//ios/public/provider/chrome/browser/signin",
"//ios/public/provider/chrome/browser/user_feedback",
]
......
......@@ -9,20 +9,16 @@
#import "ios/chrome/app/application_delegate/tab_switching.h"
#import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/main/scene_controller_guts.h"
#import "ios/chrome/browser/ui/main/scene_state.h"
#import "ios/chrome/browser/ui/tab_grid/tab_switcher.h"
#import "ios/chrome/browser/url_loading/app_url_loading_service.h"
@protocol MainControllerGuts;
// The controller object for a scene. Reacts to scene state changes.
@interface SceneController : NSObject <AppURLLoadingServiceDelegate,
SceneStateObserver,
@interface SceneController : NSObject <SceneStateObserver,
ApplicationCommands,
TabSwitcherDelegate,
TabSwitching,
SceneControllerGuts>
TabSwitching>
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithSceneState:(SceneState*)sceneState
......
......@@ -19,9 +19,7 @@
#include "ios/chrome/browser/browsing_data/browsing_data_remover.h"
#include "ios/chrome/browser/browsing_data/browsing_data_remover_factory.h"
#include "ios/chrome/browser/chrome_url_constants.h"
#import "ios/chrome/browser/chrome_url_util.h"
#include "ios/chrome/browser/main/browser.h"
#include "ios/chrome/browser/ntp/features.h"
#include "ios/chrome/browser/signin/identity_manager_factory.h"
#import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
#import "ios/chrome/browser/tabs/tab_model.h"
......@@ -39,12 +37,7 @@
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/url_loading/app_url_loading_service.h"
#import "ios/chrome/browser/url_loading/url_loading_params.h"
#import "ios/chrome/browser/url_loading/url_loading_service.h"
#import "ios/chrome/browser/url_loading/url_loading_service_factory.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#include "ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h"
#include "ios/public/provider/chrome/browser/signin/chrome_identity_service.h"
#import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
#import "ios/web/public/web_state.h"
......@@ -122,10 +115,6 @@ enum class EnterTabSwitcherSnapshotResult {
return self.mainController.interfaceProvider.incognitoInterface;
}
- (id<BrowserInterfaceProvider>)interfaceProvider {
return self.mainController.interfaceProvider;
}
#pragma mark - SceneStateObserver
- (void)sceneState:(SceneState*)sceneState
......@@ -144,7 +133,8 @@ enum class EnterTabSwitcherSnapshotResult {
#pragma mark - ApplicationCommands
- (void)dismissModalDialogs {
[self dismissModalDialogsWithCompletion:nil dismissOmnibox:YES];
[self.mainController dismissModalDialogsWithCompletion:nil
dismissOmnibox:YES];
}
- (void)showHistory {
......@@ -165,7 +155,7 @@ enum class EnterTabSwitcherSnapshotResult {
}
- (void)closeSettingsUI {
[self closeSettingsAnimated:YES completion:nullptr];
[self.mainController closeSettingsAnimated:YES completion:nullptr];
}
- (void)prepareTabSwitcher {
......@@ -523,7 +513,7 @@ enum class EnterTabSwitcherSnapshotResult {
dismissOmnibox:YES
completion:nil];
};
[self closeSettingsAnimated:YES completion:completion];
[self.mainController closeSettingsAnimated:YES completion:completion];
}
#pragma mark - UserFeedbackDataSource
......@@ -616,335 +606,4 @@ enum class EnterTabSwitcherSnapshotResult {
return YES;
}
#pragma mark - AppURLLoadingServiceDelegate
// Note that the current tab of |browserCoordinator|'s BVC will normally be
// reloaded by this method. If a new tab is about to be added, call
// expectNewForegroundTab on the BVC first to avoid extra work and possible page
// load side-effects for the tab being replaced.
- (void)setCurrentInterfaceForMode:(ApplicationMode)mode {
DCHECK(self.interfaceProvider);
BOOL incognitio = mode == ApplicationMode::INCOGNITO;
id<BrowserInterface> currentInterface =
self.interfaceProvider.currentInterface;
id<BrowserInterface> newInterface =
incognitio ? self.interfaceProvider.incognitoInterface
: self.interfaceProvider.mainInterface;
if (currentInterface && currentInterface == newInterface)
return;
// Update the snapshot before switching another application mode. This
// ensures that the snapshot is correct when links are opened in a different
// application mode.
[self updateActiveWebStateSnapshot];
self.interfaceProvider.currentInterface = newInterface;
if (!self.mainController.dismissingTabSwitcher)
[self.mainController displayCurrentBVCAndFocusOmnibox:NO];
// Tell the BVC that was made current that it can use the web.
[self.mainController activateBVCAndMakeCurrentBVCPrimary];
}
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox {
// Immediately hide modals from the provider (alert views, action sheets,
// popovers). They will be ultimately dismissed by their owners, but at least,
// they are not visible.
ios::GetChromeBrowserProvider()->HideModalViewStack();
// ChromeIdentityService is responsible for the dialogs displayed by the
// services it wraps.
ios::GetChromeBrowserProvider()->GetChromeIdentityService()->DismissDialogs();
// MailtoHandlerProvider is responsible for the dialogs displayed by the
// services it wraps.
ios::GetChromeBrowserProvider()
->GetMailtoHandlerProvider()
->DismissAllMailtoHandlerInterfaces();
// Then, depending on what the SSO view controller is presented on, dismiss
// it.
ProceduralBlock completionWithBVC = ^{
DCHECK(self.mainController.currentBVC);
DCHECK(!self.mainController.tabSwitcherIsActive);
DCHECK(!self.mainController.signinInteractionCoordinator.isActive);
// This will dismiss the SSO view controller.
[self.interfaceProvider.currentInterface
clearPresentedStateWithCompletion:completion
dismissOmnibox:dismissOmnibox];
};
ProceduralBlock completionWithoutBVC = ^{
// |self.mainController.currentBVC| may exist but tab switcher should be
// active.
DCHECK(self.mainController.tabSwitcherIsActive);
// This will dismiss the SSO view controller.
[self.mainController.signinInteractionCoordinator cancelAndDismiss];
// History coordinator can be started on top of the tab grid. This is not
// true of the other tab switchers.
DCHECK(self.mainController.mainCoordinator);
[self.mainController.mainCoordinator
stopChildCoordinatorsWithCompletion:completion];
};
// As a top level rule, if the settings are showing, they need to be
// dismissed. Then, based on whether the BVC is present or not, a different
// completion callback is called.
if (!self.mainController.tabSwitcherIsActive &&
self.mainController.isSettingsViewPresented) {
// In this case, the settings are up and the BVC is showing. Close the
// settings then call the BVC completion.
[self closeSettingsAnimated:NO completion:completionWithBVC];
} else if (self.mainController.isSettingsViewPresented) {
// In this case, the settings are up but the BVC is not showing. Close the
// settings then call the no-BVC completion.
[self closeSettingsAnimated:NO completion:completionWithoutBVC];
} else if (![self.mainController isTabSwitcherActive]) {
// In this case, the settings are not shown but the BVC is showing. Call the
// BVC completion.
[self.mainController.signinInteractionCoordinator cancel];
completionWithBVC();
} else {
// In this case, neither the settings nor the BVC are shown. Call the no-BVC
// completion.
completionWithoutBVC();
}
// Verify that no modal views are left presented.
ios::GetChromeBrowserProvider()->LogIfModalViewsArePresented();
}
// Opens a tab in the target BVC, and switches to it in a way that's appropriate
// to the current UI, based on the |dismissModals| flag:
// - If a modal dialog is showing and |dismissModals| is NO, the selected tab of
// the main tab model will change in the background, but the view won't change.
// - Otherwise, any modal view will be dismissed, the tab switcher will animate
// out if it is showing, the target BVC will become active, and the new tab will
// be shown.
// If the current tab in |targetMode| is a NTP, it can be reused to open URL.
// |completion| is executed after the tab is opened. After Tab is open the
// virtual URL is set to the pending navigation item.
- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)tabOpeningTargetMode
withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
completion:(ProceduralBlock)completion {
// Update the snapshot before opening a new tab. This ensures that the
// snapshot is correct when tabs are openned via the dispatcher.
[self updateActiveWebStateSnapshot];
ApplicationMode targetMode;
if (tabOpeningTargetMode == ApplicationModeForTabOpening::CURRENT) {
targetMode = self.interfaceProvider.currentInterface.incognito
? ApplicationMode::INCOGNITO
: ApplicationMode::NORMAL;
} else if (tabOpeningTargetMode == ApplicationModeForTabOpening::NORMAL) {
targetMode = ApplicationMode::NORMAL;
} else {
targetMode = ApplicationMode::INCOGNITO;
}
id<BrowserInterface> targetInterface =
targetMode == ApplicationMode::NORMAL
? self.interfaceProvider.mainInterface
: self.interfaceProvider.incognitoInterface;
NSUInteger tabIndex = NSNotFound;
ProceduralBlock startupCompletion = [self.mainController
completionBlockForTriggeringAction:[self.mainController.startupParameters
postOpeningAction]];
// Commands are only allowed on NTP.
DCHECK(IsURLNtp(urlLoadParams.web_params.url) || !startupCompletion);
ProceduralBlock tabOpenedCompletion = nil;
if (startupCompletion && completion) {
tabOpenedCompletion = ^{
// Order is important here. |completion| may do cleaning tasks that will
// invalidate |startupCompletion|.
startupCompletion();
completion();
};
} else if (startupCompletion) {
tabOpenedCompletion = startupCompletion;
} else {
tabOpenedCompletion = completion;
}
if (self.mainController.tabSwitcherIsActive) {
// If the tab switcher is already being dismissed, simply add the tab and
// note that when the tab switcher finishes dismissing, the current BVC
// should be switched to be the main BVC if necessary.
if (self.mainController.dismissingTabSwitcher) {
self.mainController.modeToDisplayOnTabSwitcherDismissal =
targetMode == ApplicationMode::NORMAL
? TabSwitcherDismissalMode::NORMAL
: TabSwitcherDismissalMode::INCOGNITO;
[targetInterface.bvc appendTabAddedCompletion:tabOpenedCompletion];
UrlLoadParams savedParams = urlLoadParams;
savedParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
UrlLoadingServiceFactory::GetForBrowserState(
[targetInterface.bvc browserState])
->Load(savedParams);
} else {
// Voice search, QRScanner and the omnibox are presented by the BVC.
// They must be started after the BVC view is added in the hierarchy.
self.mainController.NTPActionAfterTabSwitcherDismissal =
[self.mainController.startupParameters postOpeningAction];
[self.mainController setStartupParameters:nil];
[self.mainController.tabSwitcher
dismissWithNewTabAnimationToBrowser:targetInterface.browser
withUrlLoadParams:urlLoadParams
atIndex:tabIndex];
}
} else {
if (!self.mainController.currentBVC.presentedViewController) {
[targetInterface.bvc expectNewForegroundTab];
}
[self setCurrentInterfaceForMode:targetMode];
[self openOrReuseTabInMode:targetMode
withUrlLoadParams:urlLoadParams
tabOpenedCompletion:tabOpenedCompletion];
}
if (self.mainController.restoreHelper) {
// Now that all the operations on the tabs have been done, display the
// restore infobar if needed.
dispatch_async(dispatch_get_main_queue(), ^{
TabModel* currentTabModel = [self currentTabModel];
[self.mainController.restoreHelper
showRestoreIfNeededUsingWebState:currentTabModel.webStateList
->GetActiveWebState()
sessionRestorer:currentTabModel];
self.mainController.restoreHelper = nil;
});
}
}
- (void)openURLInNewTabWithCommand:(OpenNewTabCommand*)command {
[self openURLInNewTab:command];
}
- (void)expectNewForegroundTabForMode:(ApplicationMode)targetMode {
id<BrowserInterface> interface =
targetMode == ApplicationMode::INCOGNITO
? self.interfaceProvider.incognitoInterface
: self.interfaceProvider.mainInterface;
DCHECK(interface);
[interface.bvc expectNewForegroundTab];
}
- (void)openNewTabFromOriginPoint:(CGPoint)originPoint
focusOmnibox:(BOOL)focusOmnibox {
[self.mainController.currentBVC openNewTabFromOriginPoint:originPoint
focusOmnibox:focusOmnibox];
}
- (ios::ChromeBrowserState*)currentBrowserState {
return self.mainController.interfaceProvider.currentInterface.browserState;
}
- (TabModel*)currentTabModel {
return self.mainController.interfaceProvider.currentInterface.bvc.tabModel;
}
// Asks the respective Snapshot helper to update the snapshot for the active
// WebState.
- (void)updateActiveWebStateSnapshot {
WebStateList* webStateList =
self.mainController.currentBVC.tabModel.webStateList;
if (webStateList) {
web::WebState* webState = webStateList->GetActiveWebState();
if (webState) {
SnapshotTabHelper::FromWebState(webState)->UpdateSnapshotWithCallback(
nil);
}
}
}
- (void)closeSettingsAnimated:(BOOL)animated
completion:(ProceduralBlock)completion {
if (self.mainController.settingsNavigationController) {
[self.mainController.settingsNavigationController cleanUpSettings];
UIViewController* presentingViewController =
[self.mainController
.settingsNavigationController presentingViewController];
// If presentingViewController is nil it means the VC was already dismissed
// by some other action like swiping down.
DCHECK(presentingViewController);
[presentingViewController dismissViewControllerAnimated:animated
completion:completion];
self.mainController.settingsNavigationController = nil;
return;
}
// |self.signinInteractionCoordinator| can also present settings, like
// the advanced sign-in settings navigation controller. If the settings has
// to be cloase, it is thus the responsibility of the main controller to
// dismiss the the advanced sign-in settings by dismssing the settings
// presented by |self.signinInteractionCoordinator|.
// To reproduce this case:
// - open Bookmark view
// - start sign-in
// - tap on "Settings" to open the advanced sign-in settings
// - tap on "Manage Your Google Account"
DCHECK(
self.mainController.signinInteractionCoordinator.isSettingsViewPresented);
[self.mainController.signinInteractionCoordinator
abortAndDismissSettingsViewAnimated:animated
completion:completion];
}
// Checks the target BVC's current tab's URL. If this URL is chrome://newtab,
// loads |urlLoadParams| in this tab. Otherwise, open |urlLoadParams| in a new
// tab in the target BVC. |tabDisplayedCompletion| will be called on the new tab
// (if not nil).
- (void)openOrReuseTabInMode:(ApplicationMode)targetMode
withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
tabOpenedCompletion:(ProceduralBlock)tabOpenedCompletion {
BrowserViewController* targetBVC =
targetMode == ApplicationMode::NORMAL
? self.mainController.interfaceProvider.mainInterface.bvc
: self.mainController.interfaceProvider.incognitoInterface.bvc;
web::WebState* currentWebState =
targetBVC.tabModel.webStateList->GetActiveWebState();
// Don't call loadWithParams for chrome://newtab when it's already loaded.
// Note that it's safe to use -GetVisibleURL here, as it doesn't matter if the
// NTP hasn't finished loading.
if (currentWebState && IsURLNtp(currentWebState->GetVisibleURL()) &&
IsURLNtp(urlLoadParams.web_params.url)) {
if (tabOpenedCompletion) {
tabOpenedCompletion();
}
return;
}
// With kBrowserContainerContainsNTP enabled paired with a restored NTP
// session, the NTP may appear committed when it is still loading. For the
// time being, always load within a new tab when this feature is enabled.
// TODO(crbug.com/931284): Revert this change when fixed.
BOOL alwaysInsertNewTab =
base::FeatureList::IsEnabled(kBlockNewTabPagePendingLoad);
// If the current tab isn't an NTP, open a new tab. Be sure to use
// -GetLastCommittedURL incase the NTP is still loading.
if (alwaysInsertNewTab ||
!(currentWebState && IsURLNtp(currentWebState->GetVisibleURL()))) {
[targetBVC appendTabAddedCompletion:tabOpenedCompletion];
UrlLoadParams newTabParams = urlLoadParams;
newTabParams.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
newTabParams.in_incognito = targetMode == ApplicationMode::INCOGNITO;
UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
->Load(newTabParams);
return;
}
// Otherwise, load |urlLoadParams| in the current tab.
UrlLoadParams sameTabParams = urlLoadParams;
sameTabParams.disposition = WindowOpenDisposition::CURRENT_TAB;
UrlLoadingServiceFactory::GetForBrowserState([targetBVC browserState])
->Load(sameTabParams);
if (tabOpenedCompletion) {
tabOpenedCompletion();
}
}
@end
// Copyright 2019 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.
#ifndef IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_GUTS_H_
#define IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_GUTS_H_
#import <UIKit/UIKit.h>
#import "ios/chrome/app/application_delegate/tab_opening.h"
#import "ios/chrome/browser/procedural_block_types.h"
#import "ios/chrome/browser/url_loading/url_loading_params.h"
@protocol SceneControllerGuts
- (void)closeSettingsAnimated:(BOOL)animated
completion:(ProceduralBlock)completion;
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox;
- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)tabOpeningTargetMode
withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
completion:(ProceduralBlock)completion;
@end
#endif // IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_GUTS_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment