Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Unified Diff: ios/chrome/browser/ui/main/browser_view_wrangler.mm

Issue 2590473002: Upstream Chrome on iOS source code [5/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/main/browser_view_wrangler.mm
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
new file mode 100644
index 0000000000000000000000000000000000000000..b16f003a763a24dc5fc9bb5235248e5e9d06885b
--- /dev/null
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -0,0 +1,346 @@
+// 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/browser/ui/main/browser_view_wrangler.h"
+
+#include "base/mac/objc_property_releaser.h"
+#import "base/mac/scoped_nsobject.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/browsing_data/browsing_data_removal_controller.h"
+#include "ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h"
+#include "ios/chrome/browser/crash_report/crash_report_helper.h"
+#import "ios/chrome/browser/device_sharing/device_sharing_manager.h"
+#import "ios/chrome/browser/physical_web/start_physical_web_discovery.h"
+#import "ios/chrome/browser/sessions/session_service.h"
+#import "ios/chrome/browser/sessions/session_window.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/tabs/tab_model_observer.h"
+#import "ios/chrome/browser/ui/browser_view_controller.h"
+#import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h"
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
+
+@interface BrowserViewWrangler ()<TabModelObserver> {
+ ios::ChromeBrowserState* _browserState;
+ __unsafe_unretained id<TabModelObserver> _tabModelObserver;
+
+ base::mac::ObjCPropertyReleaser _propertyReleaser_BrowserViewWrangler;
+}
+
+// Responsible for maintaining all state related to sharing to other devices.
+// Redeclared readwrite from the readonly declaration in the Testing interface.
+@property(nonatomic, retain, readwrite)
+ DeviceSharingManager* deviceSharingManager;
+
+// Creates a new autoreleased tab model for |browserState|; if |empty| is NO,
+// then any existing tabs that have been saved for |browserState| will be
+// loaded; otherwise, the tab model will be created empty.
+- (TabModel*)tabModelForBrowserState:(ios::ChromeBrowserState*)browserState
+ empty:(BOOL)empty;
+
+// Creates a new off-the-record ("incognito") browser state for |_browserState|,
+// then calls -tabModelForBrowserState:empty: and returns the (autoreleased)
+// result.
+- (TabModel*)buildOtrTabModel:(BOOL)empty;
+
+// Creates the correct BrowserViewController for the corresponding browser state
+// and tab model.
+- (BrowserViewController*)bvcForBrowserState:
+ (ios::ChromeBrowserState*)browserState
+ tabModel:(TabModel*)tabModel;
+@end
+
+@implementation BrowserViewWrangler
+
+// Properties defined in the BrowserViewInformation protocol.
+@synthesize mainBVC = _mainBVC;
+@synthesize mainTabModel = _mainTabModel;
+@synthesize otrBVC = _otrBVC;
+@synthesize otrTabModel = _otrTabModel;
+@synthesize currentBVC = _currentBVC;
+// Private properies.
+@synthesize deviceSharingManager = _deviceSharingManager;
+
+- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
+ tabModelObserver:(id<TabModelObserver>)tabModelObserver {
+ if ((self = [super init])) {
+ _propertyReleaser_BrowserViewWrangler.Init(self,
+ [BrowserViewWrangler class]);
+ _browserState = browserState;
+ _tabModelObserver = tabModelObserver;
+ }
+ return self;
+}
+
+- (instancetype)init {
+ NOTREACHED();
+ return nil;
+}
+
+- (void)dealloc {
+ if (_tabModelObserver) {
+ [_mainTabModel removeObserver:_tabModelObserver];
+ [_otrTabModel removeObserver:_tabModelObserver];
+ }
+ [_mainTabModel removeObserver:self];
+ [_otrTabModel removeObserver:self];
+
+ // Stop URL monitoring of the main tab model.
+ ios_internal::breakpad::StopMonitoringURLsForTabModel(_mainTabModel);
+
+ // Stop Breakpad state monitoring of both tab models (if necessary).
+ ios_internal::breakpad::StopMonitoringTabStateForTabModel(_mainTabModel);
+ ios_internal::breakpad::StopMonitoringTabStateForTabModel(_otrTabModel);
+
+ // Normally other objects will take care of unhooking the tab models from
+ // the browser state, but this code should ensure that it happens regardless.
+ [_mainTabModel browserStateDestroyed];
+ [_otrTabModel browserStateDestroyed];
+
+ [super dealloc];
+}
+
+#pragma mark - BrowserViewInformation property implementations
+
+- (BrowserViewController*)mainBVC {
+ if (!_mainBVC) {
+ // |_browserState| should always be set before trying to create
+ // |_mainBVC|.
+ DCHECK(_browserState);
+ self.mainBVC =
+ [self bvcForBrowserState:_browserState tabModel:self.mainTabModel];
+ DCHECK(_mainBVC);
+ }
+ return _mainBVC;
+}
+
+- (TabModel*)mainTabModel {
+ if (!_mainTabModel) {
+ self.mainTabModel = [self tabModelForBrowserState:_browserState empty:NO];
+ // Follow loaded URLs in the main tab model to send those in case of
+ // crashes.
+ ios_internal::breakpad::MonitorURLsForTabModel(_mainTabModel);
+ ios::GetChromeBrowserProvider()->InitializeCastService(_mainTabModel);
+ }
+ return _mainTabModel;
+}
+
+- (BrowserViewController*)otrBVC {
+ if (!_otrBVC) {
+ // |_browserState| should always be set before trying to create
+ // |_otrBVC|.
+ DCHECK(_browserState);
+ ios::ChromeBrowserState* otrBrowserState =
+ _browserState->GetOffTheRecordChromeBrowserState();
+ DCHECK(otrBrowserState);
+ self.otrBVC =
+ [self bvcForBrowserState:otrBrowserState tabModel:self.otrTabModel];
+ DCHECK(_otrBVC);
+ }
+ return _otrBVC;
+}
+
+- (TabModel*)otrTabModel {
+ if (!_otrTabModel) {
+ self.otrTabModel = [self buildOtrTabModel:NO];
+ }
+ return _otrTabModel;
+}
+
+- (void)setCurrentBVC:(BrowserViewController*)bvc
+ storageSwitcher:(id<BrowserStateStorageSwitching>)storageSwitcher {
+ DCHECK(bvc != nil);
+ // |bvc| should be one of the BrowserViewControllers this class already owns.
+ DCHECK(_mainBVC == bvc || _otrBVC == bvc);
+ if (self.currentBVC == bvc) {
+ return;
+ }
+
+ if (self.currentBVC) {
+ // Tell the current BVC it moved to the background.
+ [self.currentBVC setPrimary:NO];
+
+ // Data storage for the browser is always owned by the current BVC, so it
+ // must be updated when switching between BVCs.
+ [storageSwitcher changeStorageFromBrowserState:self.currentBVC.browserState
+ toBrowserState:bvc.browserState];
+ }
+
+ self.currentBVC = bvc;
+
+ // The internal state of the Handoff Manager depends on the current BVC.
+ [self updateDeviceSharingManager];
+
+ // By default, Physical Web discovery will not be started if the browser
+ // launches into an Incognito tab. On switching modes, check if discovery
+ // should be started.
+ StartPhysicalWebDiscovery(GetApplicationContext()->GetLocalState(),
+ [self currentBrowserState]);
+}
+
+#pragma mark - BrowserViewInformation methods
+
+- (TabModel*)currentTabModel {
+ return self.currentBVC.tabModel;
+}
+
+- (ios::ChromeBrowserState*)currentBrowserState {
+ return self.currentBVC.browserState;
+}
+
+- (void)haltAllTabs {
+ [self.mainTabModel haltAllTabs];
+ [self.otrTabModel haltAllTabs];
+}
+
+- (void)cleanDeviceSharingManager {
+ [self.deviceSharingManager updateBrowserState:NULL];
+}
+
+#pragma mark - TabModelObserver
+
+- (void)tabModel:(TabModel*)model
+ didChangeActiveTab:(Tab*)newTab
+ previousTab:(Tab*)previousTab
+ atIndex:(NSUInteger)index {
+ [self updateDeviceSharingManager];
+}
+
+- (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab {
+ [self updateDeviceSharingManager];
+}
+
+// Called when the number of tabs changes. Updates the switcher button
+// visibility in the various modes on tablet.
+- (void)tabModelDidChangeTabCount:(TabModel*)notifiedTabModel {
+ // If in tablet, update the mode switcher icon based on the number of tabs
+ // in the incognito tab strip. Doing this all the time simplifies a lot
+ // of the state transition logic and setting the property to the same value
+ // incurs no re-layout penalty.
+ [self updateModeToggle];
+}
+
+#pragma mark - Other public methods
+
+- (void)updateDeviceSharingManager {
+ if (!self.deviceSharingManager) {
+ self.deviceSharingManager = [[DeviceSharingManager alloc] init];
+ }
+ [self.deviceSharingManager updateBrowserState:_browserState];
+
+ GURL activeURL;
+ Tab* currentTab = [self.currentBVC tabModel].currentTab;
+ // Set the active URL if there's a current tab and the current BVC is not OTR.
+ if (currentTab && self.currentBVC != self.otrBVC) {
+ activeURL = currentTab.url;
+ }
+ [self.deviceSharingManager updateActiveURL:activeURL];
+}
+
+- (void)deleteIncognitoTabModelState:
+ (BrowsingDataRemovalController*)removalController {
+ // It is theoretically possible that a Tab has been added to |_otrTabModel|
+ // since the deletion has been scheduled. It is unlikely to happen for real
+ // because it would require superhuman speed.
+ DCHECK(![_otrTabModel count]);
+ DCHECK(_browserState);
+
+ // Stop watching the OTR tab model's state for crashes.
+ ios_internal::breakpad::StopMonitoringTabStateForTabModel(self.otrTabModel);
+
+ // At this stage, a new OTR BVC shouldn't be lazily constructed by calling the
+ // .otrBVC property getter. Instead, the ivar is accessed directly through the
+ // following code.
+ BOOL otrBVCIsCurrent = self.currentBVC == _otrBVC;
+ @autoreleasepool {
+ ios::ChromeBrowserState* otrBrowserState =
+ _browserState->GetOffTheRecordChromeBrowserState();
+ [removalController browserStateDestroyed:otrBrowserState];
+ [_otrBVC browserStateDestroyed];
+ [_otrBVC release];
+ _otrBVC = nil;
+ // There's no guarantee the tab model was ever added to the BVC (or even
+ // that the BVC was created), so ensure the tab model gets notified.
+ [_otrTabModel browserStateDestroyed];
+ if (_tabModelObserver) {
+ [_otrTabModel removeObserver:_tabModelObserver];
+ }
+ [_otrTabModel removeObserver:self];
+ [_otrTabModel release];
+ _otrTabModel = nil;
+ if (otrBVCIsCurrent) {
+ _currentBVC = nil;
+ }
+ }
+
+ _browserState->DestroyOffTheRecordChromeBrowserState();
+
+ // An empty _otrTabModel must be created at this point, because it is then
+ // possible to prevent the tabChanged notification being sent. Otherwise,
+ // when it is created, a notification with no tabs will be sent, and it will
+ // be immediately deleted.
+ self.otrTabModel = [self buildOtrTabModel:YES];
+ DCHECK(![self.otrTabModel count]);
+ DCHECK(_browserState->HasOffTheRecordChromeBrowserState());
+
+ if (otrBVCIsCurrent) {
+ _currentBVC = self.otrBVC;
+ }
+}
+
+- (void)updateModeToggle {
+ if (IsIPadIdiom()) {
+ self.mainBVC.hasModeToggleSwitch = self.otrTabModel.count ? YES : NO;
+ self.otrBVC.hasModeToggleSwitch = YES;
+ }
+}
+
+#pragma mark - Internal methods
+
+- (TabModel*)buildOtrTabModel:(BOOL)empty {
+ DCHECK(_browserState);
+ // Ensure that the OTR ChromeBrowserState is created.
+ ios::ChromeBrowserState* otrBrowserState =
+ _browserState->GetOffTheRecordChromeBrowserState();
+ DCHECK(otrBrowserState);
+ return [self tabModelForBrowserState:otrBrowserState empty:empty];
+}
+
+- (TabModel*)tabModelForBrowserState:(ios::ChromeBrowserState*)browserState
+ empty:(BOOL)empty {
+ SessionWindowIOS* sessionWindow = nil;
+ if (!empty) {
+ // Load existing saved tab model state.
+ sessionWindow = [[SessionServiceIOS sharedService]
+ loadWindowForBrowserState:browserState];
+ }
+
+ // Create tab model from saved session (nil is ok).
+ TabModel* tabModel =
+ [[[TabModel alloc] initWithSessionWindow:sessionWindow
+ sessionService:[SessionServiceIOS sharedService]
+ browserState:browserState] autorelease];
+ // Add observers.
+ if (_tabModelObserver) {
+ [tabModel addObserver:_tabModelObserver];
+ [tabModel addObserver:self];
+ }
+ ios_internal::breakpad::MonitorTabStateForTabModel(tabModel);
+
+ return tabModel;
+}
+
+- (BrowserViewController*)bvcForBrowserState:
+ (ios::ChromeBrowserState*)browserState
+ tabModel:(TabModel*)tabModel {
+ base::scoped_nsobject<BrowserViewControllerDependencyFactory> factory(
+ [[BrowserViewControllerDependencyFactory alloc]
+ initWithBrowserState:browserState]);
+ return [[[BrowserViewController alloc] initWithTabModel:tabModel
+ browserState:browserState
+ dependencyFactory:factory] autorelease];
+}
+
+@end
« no previous file with comments | « ios/chrome/browser/ui/main/browser_view_wrangler.h ('k') | ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698