Commit b6aae4aa authored by Stepan Khapugin's avatar Stepan Khapugin Committed by Commit Bot

[iOS][multiball] Move WebStateList observation to Scene level.

MainController observes WSL to know when the last {normal|incognito}
tab is closed. Conceptually, this seems like a Scene-level concern.
However, clearing browsing data might be an App-level concept, so I
keep the logic in MainController for now.

Bug: none
Change-Id: I0b3453518f4f0390a34f77ce27817f4af1f4d650
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2003135
Commit-Queue: Stepan Khapugin <stkhapugin@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#733390}
parent a660f380
...@@ -276,8 +276,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -276,8 +276,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
} // namespace } // namespace
@interface MainController () <BrowserStateStorageSwitching, @interface MainController () <BrowserStateStorageSwitching,
PrefObserverDelegate, PrefObserverDelegate> {
WebStateListObserving> {
IBOutlet UIWindow* _window; IBOutlet UIWindow* _window;
// Weak; owned by the ChromeBrowserProvider. // Weak; owned by the ChromeBrowserProvider.
...@@ -346,14 +345,8 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -346,14 +345,8 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
// browser has started up to the FOREGROUND stage. // browser has started up to the FOREGROUND stage.
@property(nonatomic, readonly) TabGridCoordinator* mainCoordinator; @property(nonatomic, readonly) TabGridCoordinator* mainCoordinator;
// Shows the tab switcher UI.
- (void)showTabSwitcher;
// Starts a voice search on the current BVC. // Starts a voice search on the current BVC.
- (void)startVoiceSearchInCurrentBVC; - (void)startVoiceSearchInCurrentBVC;
// Called when the last incognito tab was closed.
- (void)lastIncognitoTabClosed;
// Called when the last regular tab was closed.
- (void)lastRegularTabClosed;
// Returns whether the restore infobar should be displayed. // Returns whether the restore infobar should be displayed.
- (bool)mustShowRestoreInfobar; - (bool)mustShowRestoreInfobar;
// Switch all global states for the given mode (normal or incognito). // Switch all global states for the given mode (normal or incognito).
...@@ -412,11 +405,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -412,11 +405,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
- (void)scheduleShowPromo; - (void)scheduleShowPromo;
// Crashes the application if requested. // Crashes the application if requested.
- (void)crashIfRequested; - (void)crashIfRequested;
// Clears incognito data that is specific to iOS and won't be cleared by
// deleting the browser state.
- (void)clearIOSSpecificIncognitoData;
// Destroys and rebuilds the incognito browser state.
- (void)destroyAndRebuildIncognitoBrowserState;
// Handles the notification that first run modal dialog UI is about to complete. // Handles the notification that first run modal dialog UI is about to complete.
- (void)handleFirstRunUIWillFinish; - (void)handleFirstRunUIWillFinish;
// Handles the notification that first run modal dialog UI completed. // Handles the notification that first run modal dialog UI completed.
...@@ -603,7 +591,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -603,7 +591,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
[self.browserViewWrangler shutdown]; [self.browserViewWrangler shutdown];
self.browserViewWrangler = [[BrowserViewWrangler alloc] self.browserViewWrangler = [[BrowserViewWrangler alloc]
initWithBrowserState:self.mainBrowserState initWithBrowserState:self.mainBrowserState
webStateListObserver:self webStateListObserver:self.sceneController
applicationCommandEndpoint:self.sceneController applicationCommandEndpoint:self.sceneController
browsingDataCommandEndpoint:self browsingDataCommandEndpoint:self
appURLLoadingService:self.appURLLoadingService appURLLoadingService:self.appURLLoadingService
...@@ -640,7 +628,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -640,7 +628,7 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
BOOL switchFromIncognito = startInIncognito && ![self canLaunchInIncognito]; BOOL switchFromIncognito = startInIncognito && ![self canLaunchInIncognito];
if (postCrashLaunch || switchFromIncognito) { if (postCrashLaunch || switchFromIncognito) {
[self clearIOSSpecificIncognitoData]; [self.sceneController clearIOSSpecificIncognitoData];
if (switchFromIncognito) if (switchFromIncognito)
[self switchGlobalStateToMode:ApplicationMode::NORMAL]; [self switchGlobalStateToMode:ApplicationMode::NORMAL];
} }
...@@ -739,54 +727,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -739,54 +727,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
triggerSystemPromptForNewUser:YES]; triggerSystemPromptForNewUser:YES];
} }
- (void)clearIOSSpecificIncognitoData {
DCHECK(self.mainBrowserState->HasOffTheRecordChromeBrowserState());
ios::ChromeBrowserState* otrBrowserState =
self.mainBrowserState->GetOffTheRecordChromeBrowserState();
[self removeBrowsingDataForBrowserState:otrBrowserState
timePeriod:browsing_data::TimePeriod::ALL_TIME
removeMask:BrowsingDataRemoveMask::REMOVE_ALL
completionBlock:^{
[self activateBVCAndMakeCurrentBVCPrimary];
}];
}
- (void)destroyAndRebuildIncognitoBrowserState {
BOOL otrBVCIsCurrent = (self.currentBVC == self.otrBVC);
// Clear the OTR tab model and notify the _tabSwitcher that its otrBVC will
// be destroyed.
[_tabSwitcher setOtrBrowser:nil];
[self.browserViewWrangler destroyAndRebuildIncognitoBrowser];
if (otrBVCIsCurrent) {
[self activateBVCAndMakeCurrentBVCPrimary];
}
// Always set the new otr browser for the tablet or grid switcher.
// Notify the _tabSwitcher with the new otrBVC.
[_tabSwitcher setOtrBrowser:self.mainBrowser];
// This seems the best place to deem the destroying and rebuilding the
// incognito browser state to be completed.
breakpad_helper::SetDestroyingAndRebuildingIncognitoBrowserState(
/*in_progress=*/false);
}
- (void)activateBVCAndMakeCurrentBVCPrimary {
// If there are pending removal operations, the activation will be deferred
// until the callback is received.
BrowsingDataRemover* browsingDataRemover =
BrowsingDataRemoverFactory::GetForBrowserStateIfExists(
self.currentBrowserState);
if (browsingDataRemover && browsingDataRemover->IsRemoving())
return;
self.interfaceProvider.mainInterface.userInteractionEnabled = YES;
self.interfaceProvider.incognitoInterface.userInteractionEnabled = YES;
[self.currentBVC setPrimary:YES];
}
#pragma mark - Property implementation. #pragma mark - Property implementation.
...@@ -1452,54 +1392,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -1452,54 +1392,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
#pragma mark - Tab closure handlers
- (void)lastIncognitoTabClosed {
// This seems the best place to mark the start of destroying the incognito
// browser state.
breakpad_helper::SetDestroyingAndRebuildingIncognitoBrowserState(
/*in_progress=*/true);
DCHECK(self.mainBrowserState->HasOffTheRecordChromeBrowserState());
[self clearIOSSpecificIncognitoData];
// OffTheRecordProfileIOData cannot be deleted before all the requests are
// deleted. Queue browser state recreation on IO thread.
base::PostTaskAndReply(FROM_HERE, {web::WebThread::IO}, base::DoNothing(),
base::BindRepeating(^{
[self destroyAndRebuildIncognitoBrowserState];
}));
// a) The first condition can happen when the last incognito tab is closed
// from the tab switcher.
// b) The second condition can happen if some other code (like JS) triggers
// closure of tabs from the otr tab model when it's not current.
// Nothing to do here. The next user action (like clicking on an existing
// regular tab or creating a new incognito tab from the settings menu) will
// take care of the logic to mode switch.
if (self.tabSwitcherIsActive || ![self.currentTabModel isOffTheRecord]) {
return;
}
if ([self.currentTabModel count] == 0U) {
[self showTabSwitcher];
} else {
[self.sceneController setCurrentInterfaceForMode:ApplicationMode::NORMAL];
}
}
- (void)lastRegularTabClosed {
// a) The first condition can happen when the last regular tab is closed from
// the tab switcher.
// b) The second condition can happen if some other code (like JS) triggers
// closure of tabs from the main tab model when the main tab model is not
// current.
// Nothing to do here.
if (self.tabSwitcherIsActive || [self.currentTabModel isOffTheRecord]) {
return;
}
[self showTabSwitcher];
}
#pragma mark - Mode Switching #pragma mark - Mode Switching
...@@ -1542,39 +1434,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData( ...@@ -1542,39 +1434,6 @@ void MainControllerAuthenticationServiceDelegate::ClearBrowsingData(
return self.currentBVC.browserState; return self.currentBVC.browserState;
} }
- (void)showTabSwitcher {
DCHECK(_tabSwitcher);
// Tab switcher implementations may need to rebuild state before being
// displayed.
[_tabSwitcher restoreInternalStateWithMainTabModel:self.mainTabModel
otrTabModel:self.otrTabModel
activeTabModel:self.currentTabModel];
self.tabSwitcherIsActive = YES;
[_tabSwitcher setDelegate:self.sceneController];
[self.mainCoordinator showTabSwitcher:_tabSwitcher];
}
#pragma mark - WebStateListObserving
// Called when a WebState is removed. Triggers the switcher view when the last
// WebState is closed on a device that uses the switcher.
- (void)webStateList:(WebStateList*)notifiedWebStateList
didDetachWebState:(web::WebState*)webState
atIndex:(int)atIndex {
// Do nothing on initialization.
if (![self currentTabModel].webStateList)
return;
if (notifiedWebStateList->empty()) {
if (webState->GetBrowserState()->IsOffTheRecord()) {
[self lastIncognitoTabClosed];
} else {
[self lastRegularTabClosed];
}
}
}
#pragma mark - Tab opening utility methods. #pragma mark - Tab opening utility methods.
- (ProceduralBlock)completionBlockForTriggeringAction: - (ProceduralBlock)completionBlockForTriggeringAction:
......
...@@ -7,12 +7,16 @@ ...@@ -7,12 +7,16 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "base/ios/block_types.h"
#include "components/browsing_data/core/browsing_data_utils.h"
#include "ios/chrome/app/startup/chrome_app_startup_parameters.h" #include "ios/chrome/app/startup/chrome_app_startup_parameters.h"
#include "ios/chrome/browser/browsing_data/browsing_data_remove_mask.h"
#import "ios/chrome/browser/crash_report/crash_restore_helper.h" #import "ios/chrome/browser/crash_report/crash_restore_helper.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h" #import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
@class BrowserViewController; @class BrowserViewController;
@class BrowserViewWrangler;
@class HistoryCoordinator; @class HistoryCoordinator;
@class SigninInteractionCoordinator; @class SigninInteractionCoordinator;
@class TabGridCoordinator; @class TabGridCoordinator;
...@@ -91,9 +95,9 @@ enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO }; ...@@ -91,9 +95,9 @@ enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
// Keeps track of the restore state during startup. // Keeps track of the restore state during startup.
@property(nonatomic, strong) CrashRestoreHelper* restoreHelper; @property(nonatomic, strong) CrashRestoreHelper* restoreHelper;
- (BrowserViewWrangler*)browserViewWrangler;
- (id<TabSwitcher>)tabSwitcher; - (id<TabSwitcher>)tabSwitcher;
- (TabModel*)currentTabModel; - (TabModel*)currentTabModel;
- (id<TabSwitcher>)tabSwitcher;
- (ios::ChromeBrowserState*)mainBrowserState; - (ios::ChromeBrowserState*)mainBrowserState;
- (ios::ChromeBrowserState*)currentBrowserState; - (ios::ChromeBrowserState*)currentBrowserState;
- (BrowserViewController*)currentBVC; - (BrowserViewController*)currentBVC;
...@@ -102,14 +106,14 @@ enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO }; ...@@ -102,14 +106,14 @@ enum class TabSwitcherDismissalMode { NONE, NORMAL, INCOGNITO };
- (TabGridCoordinator*)mainCoordinator; - (TabGridCoordinator*)mainCoordinator;
- (id<BrowserInterfaceProvider>)interfaceProvider; - (id<BrowserInterfaceProvider>)interfaceProvider;
- (void)startVoiceSearchInCurrentBVC; - (void)startVoiceSearchInCurrentBVC;
- (void)showTabSwitcher;
// Sets |currentBVC| as the root view controller for the window. // Sets |currentBVC| as the root view controller for the window.
- (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox; - (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox;
// Activates |mainBVC| and |otrBVC| and sets |currentBVC| as primary iff - (void)removeBrowsingDataForBrowserState:(ios::ChromeBrowserState*)browserState
// |currentBVC| can be made active. timePeriod:(browsing_data::TimePeriod)timePeriod
- (void)activateBVCAndMakeCurrentBVCPrimary; removeMask:(BrowsingDataRemoveMask)removeMask
completionBlock:(ProceduralBlock)completionBlock;
@end @end
......
...@@ -10,6 +10,7 @@ source_set("scene_guts") { ...@@ -10,6 +10,7 @@ source_set("scene_guts") {
"//ios/chrome/app/application_delegate:application_delegate_internal", "//ios/chrome/app/application_delegate:application_delegate_internal",
"//ios/chrome/browser:utils", "//ios/chrome/browser:utils",
"//ios/chrome/browser/url_loading", "//ios/chrome/browser/url_loading",
"//ios/chrome/browser/web_state_list",
] ]
libs = [ "UIKit.framework" ] libs = [ "UIKit.framework" ]
...@@ -39,6 +40,7 @@ source_set("scene") { ...@@ -39,6 +40,7 @@ source_set("scene") {
"//ios/chrome/browser:chrome_url_constants", "//ios/chrome/browser:chrome_url_constants",
"//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state",
"//ios/chrome/browser/browsing_data", "//ios/chrome/browser/browsing_data",
"//ios/chrome/browser/crash_report",
"//ios/chrome/browser/main", "//ios/chrome/browser/main",
"//ios/chrome/browser/ntp:features", "//ios/chrome/browser/ntp:features",
"//ios/chrome/browser/payments", "//ios/chrome/browser/payments",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "components/payments/core/features.h" #include "components/payments/core/features.h"
#include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_manager.h"
#include "components/url_formatter/url_formatter.h" #include "components/url_formatter/url_formatter.h"
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
#include "ios/chrome/browser/browsing_data/browsing_data_remover_factory.h" #include "ios/chrome/browser/browsing_data/browsing_data_remover_factory.h"
#include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/chrome_url_constants.h"
#import "ios/chrome/browser/chrome_url_util.h" #import "ios/chrome/browser/chrome_url_util.h"
#include "ios/chrome/browser/crash_report/breakpad_helper.h"
#include "ios/chrome/browser/main/browser.h" #include "ios/chrome/browser/main/browser.h"
#include "ios/chrome/browser/ntp/features.h" #include "ios/chrome/browser/ntp/features.h"
#include "ios/chrome/browser/payments/ios_payment_instrument_launcher.h" #include "ios/chrome/browser/payments/ios_payment_instrument_launcher.h"
...@@ -39,6 +41,7 @@ ...@@ -39,6 +41,7 @@
#import "ios/chrome/browser/ui/commands/show_signin_command.h" #import "ios/chrome/browser/ui/commands/show_signin_command.h"
#include "ios/chrome/browser/ui/history/history_coordinator.h" #include "ios/chrome/browser/ui/history/history_coordinator.h"
#import "ios/chrome/browser/ui/main/browser_interface_provider.h" #import "ios/chrome/browser/ui/main/browser_interface_provider.h"
#import "ios/chrome/browser/ui/main/browser_view_wrangler.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#import "ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.h" #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.h"
#include "ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h" #include "ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h"
...@@ -50,10 +53,12 @@ ...@@ -50,10 +53,12 @@
#import "ios/chrome/browser/url_loading/url_loading_service.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/url_loading/url_loading_service_factory.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.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/mailto/mailto_handler_provider.h"
#include "ios/public/provider/chrome/browser/signin/chrome_identity_service.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/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
#include "ios/web/public/thread/web_task_traits.h"
#import "ios/web/public/web_state.h" #import "ios/web/public/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -90,7 +95,8 @@ enum class EnterTabSwitcherSnapshotResult { ...@@ -90,7 +95,8 @@ enum class EnterTabSwitcherSnapshotResult {
} // namespace } // namespace
@interface SceneController () <UserFeedbackDataSource, @interface SceneController () <UserFeedbackDataSource,
SettingsNavigationControllerDelegate> SettingsNavigationControllerDelegate,
WebStateListObserving>
// A flag that keeps track of the UI initialization for the controlled scene. // A flag that keeps track of the UI initialization for the controlled scene.
@property(nonatomic, assign) BOOL hasInitializedUI; @property(nonatomic, assign) BOOL hasInitializedUI;
...@@ -217,7 +223,7 @@ enum class EnterTabSwitcherSnapshotResult { ...@@ -217,7 +223,7 @@ enum class EnterTabSwitcherSnapshotResult {
DCHECK(!self.mainController.isTabSwitcherActive); DCHECK(!self.mainController.isTabSwitcherActive);
if (!self.mainController.isProcessingVoiceSearchCommand) { if (!self.mainController.isProcessingVoiceSearchCommand) {
[self.mainController.currentBVC userEnteredTabSwitcher]; [self.mainController.currentBVC userEnteredTabSwitcher];
[self.mainController showTabSwitcher]; [self showTabSwitcher];
self.mainController.isProcessingTabSwitcherCommand = YES; self.mainController.isProcessingTabSwitcherCommand = YES;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
kExpectedTransitionDurationInNanoSeconds), kExpectedTransitionDurationInNanoSeconds),
...@@ -635,7 +641,7 @@ enum class EnterTabSwitcherSnapshotResult { ...@@ -635,7 +641,7 @@ enum class EnterTabSwitcherSnapshotResult {
self.mainController.modeToDisplayOnTabSwitcherDismissal = self.mainController.modeToDisplayOnTabSwitcherDismissal =
TabSwitcherDismissalMode::NONE; TabSwitcherDismissalMode::NONE;
self.mainController.NTPActionAfterTabSwitcherDismissal = NO_ACTION; self.mainController.NTPActionAfterTabSwitcherDismissal = NO_ACTION;
[self.mainController showTabSwitcher]; [self showTabSwitcher];
return; return;
} }
...@@ -827,7 +833,7 @@ enum class EnterTabSwitcherSnapshotResult { ...@@ -827,7 +833,7 @@ enum class EnterTabSwitcherSnapshotResult {
[self.mainController displayCurrentBVCAndFocusOmnibox:NO]; [self.mainController displayCurrentBVCAndFocusOmnibox:NO];
// Tell the BVC that was made current that it can use the web. // Tell the BVC that was made current that it can use the web.
[self.mainController activateBVCAndMakeCurrentBVCPrimary]; [self activateBVCAndMakeCurrentBVCPrimary];
} }
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion - (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
...@@ -1151,4 +1157,144 @@ enum class EnterTabSwitcherSnapshotResult { ...@@ -1151,4 +1157,144 @@ enum class EnterTabSwitcherSnapshotResult {
self.mainController.mainCoordinator.viewController); self.mainController.mainCoordinator.viewController);
} }
#pragma mark - WebStateListObserving
// Called when a WebState is removed. Triggers the switcher view when the last
// WebState is closed on a device that uses the switcher.
- (void)webStateList:(WebStateList*)notifiedWebStateList
didDetachWebState:(web::WebState*)webState
atIndex:(int)atIndex {
// Do nothing on initialization.
if (![self currentTabModel].webStateList)
return;
if (notifiedWebStateList->empty()) {
if (webState->GetBrowserState()->IsOffTheRecord()) {
[self lastIncognitoTabClosed];
} else {
[self lastRegularTabClosed];
}
}
}
// Called when the last incognito tab was closed.
- (void)lastIncognitoTabClosed {
// This seems the best place to mark the start of destroying the incognito
// browser state.
breakpad_helper::SetDestroyingAndRebuildingIncognitoBrowserState(
/*in_progress=*/true);
DCHECK(self.mainController.mainBrowserState
->HasOffTheRecordChromeBrowserState());
[self clearIOSSpecificIncognitoData];
// OffTheRecordProfileIOData cannot be deleted before all the requests are
// deleted. Queue browser state recreation on IO thread.
base::PostTaskAndReply(FROM_HERE, {web::WebThread::IO}, base::DoNothing(),
base::BindRepeating(^{
[self destroyAndRebuildIncognitoBrowserState];
}));
// a) The first condition can happen when the last incognito tab is closed
// from the tab switcher.
// b) The second condition can happen if some other code (like JS) triggers
// closure of tabs from the otr tab model when it's not current.
// Nothing to do here. The next user action (like clicking on an existing
// regular tab or creating a new incognito tab from the settings menu) will
// take care of the logic to mode switch.
if (self.mainController.tabSwitcherIsActive ||
![self.mainController.currentTabModel isOffTheRecord]) {
return;
}
if ([self.mainController.currentTabModel count] == 0U) {
[self showTabSwitcher];
} else {
[self setCurrentInterfaceForMode:ApplicationMode::NORMAL];
}
}
// Called when the last regular tab was closed.
- (void)lastRegularTabClosed {
// a) The first condition can happen when the last regular tab is closed from
// the tab switcher.
// b) The second condition can happen if some other code (like JS) triggers
// closure of tabs from the main tab model when the main tab model is not
// current.
// Nothing to do here.
if (self.mainController.tabSwitcherIsActive ||
[self.mainController.currentTabModel isOffTheRecord]) {
return;
}
[self showTabSwitcher];
}
- (void)clearIOSSpecificIncognitoData {
DCHECK(self.mainController.mainBrowserState
->HasOffTheRecordChromeBrowserState());
ios::ChromeBrowserState* otrBrowserState =
self.mainController.mainBrowserState->GetOffTheRecordChromeBrowserState();
[self.mainController
removeBrowsingDataForBrowserState:otrBrowserState
timePeriod:browsing_data::TimePeriod::ALL_TIME
removeMask:BrowsingDataRemoveMask::REMOVE_ALL
completionBlock:^{
[self activateBVCAndMakeCurrentBVCPrimary];
}];
}
- (void)activateBVCAndMakeCurrentBVCPrimary {
// If there are pending removal operations, the activation will be deferred
// until the callback is received.
BrowsingDataRemover* browsingDataRemover =
BrowsingDataRemoverFactory::GetForBrowserStateIfExists(
self.currentBrowserState);
if (browsingDataRemover && browsingDataRemover->IsRemoving())
return;
self.interfaceProvider.mainInterface.userInteractionEnabled = YES;
self.interfaceProvider.incognitoInterface.userInteractionEnabled = YES;
[self.mainController.currentBVC setPrimary:YES];
}
- (void)showTabSwitcher {
DCHECK(self.mainController.tabSwitcher);
// Tab switcher implementations may need to rebuild state before being
// displayed.
[self.mainController.tabSwitcher
restoreInternalStateWithMainTabModel:self.mainInterface.tabModel
otrTabModel:self.incognitoInterface.tabModel
activeTabModel:self.currentTabModel];
self.mainController.tabSwitcherIsActive = YES;
[self.mainController.tabSwitcher setDelegate:self];
[self.mainController.mainCoordinator
showTabSwitcher:self.mainController.tabSwitcher];
}
// Destroys and rebuilds the incognito browser state.
- (void)destroyAndRebuildIncognitoBrowserState {
BOOL otrBVCIsCurrent = (self.interfaceProvider.mainInterface.bvc ==
self.interfaceProvider.incognitoInterface.bvc);
// Clear the OTR tab model and notify the _tabSwitcher that its otrBVC will
// be destroyed.
[self.mainController.tabSwitcher setOtrBrowser:nil];
[self.mainController.browserViewWrangler destroyAndRebuildIncognitoBrowser];
if (otrBVCIsCurrent) {
[self activateBVCAndMakeCurrentBVCPrimary];
}
// Always set the new otr tab model for the tablet or grid switcher.
// Notify the _tabSwitcher with the new otrBVC.
[self.mainController.tabSwitcher setOtrBrowser:self.mainInterface.browser];
// This seems the best place to deem the destroying and rebuilding the
// incognito browser state to be completed.
breakpad_helper::SetDestroyingAndRebuildingIncognitoBrowserState(
/*in_progress=*/false);
}
@end @end
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#import "ios/chrome/app/application_delegate/tab_opening.h" #import "ios/chrome/app/application_delegate/tab_opening.h"
#import "ios/chrome/browser/procedural_block_types.h" #import "ios/chrome/browser/procedural_block_types.h"
#import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/url_loading/url_loading_params.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
@class TabModel; @class TabModel;
...@@ -18,7 +19,7 @@ namespace ios { ...@@ -18,7 +19,7 @@ namespace ios {
class ChromeBrowserState; class ChromeBrowserState;
} // namespace ios } // namespace ios
@protocol SceneControllerGuts @protocol SceneControllerGuts <WebStateListObserving>
- (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion - (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
dismissOmnibox:(BOOL)dismissOmnibox; dismissOmnibox:(BOOL)dismissOmnibox;
...@@ -62,6 +63,12 @@ class ChromeBrowserState; ...@@ -62,6 +63,12 @@ class ChromeBrowserState;
// Returns YES if the settings navigation controller exists. // Returns YES if the settings navigation controller exists.
- (BOOL)hasSettingsNavigationController; - (BOOL)hasSettingsNavigationController;
// Clears incognito data that is specific to iOS and won't be cleared by
// deleting the browser state.
- (void)clearIOSSpecificIncognitoData;
- (void)activateBVCAndMakeCurrentBVCPrimary;
@end @end
#endif // IOS_CHROME_BROWSER_UI_MAIN_SCENE_CONTROLLER_GUTS_H_ #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