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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/ui/main/browser_view_wrangler.h"
6
7 #include "base/mac/objc_property_releaser.h"
8 #import "base/mac/scoped_nsobject.h"
9 #include "ios/chrome/browser/application_context.h"
10 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
11 #import "ios/chrome/browser/browsing_data/browsing_data_removal_controller.h"
12 #include "ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h"
13 #include "ios/chrome/browser/crash_report/crash_report_helper.h"
14 #import "ios/chrome/browser/device_sharing/device_sharing_manager.h"
15 #import "ios/chrome/browser/physical_web/start_physical_web_discovery.h"
16 #import "ios/chrome/browser/sessions/session_service.h"
17 #import "ios/chrome/browser/sessions/session_window.h"
18 #import "ios/chrome/browser/tabs/tab.h"
19 #import "ios/chrome/browser/tabs/tab_model.h"
20 #import "ios/chrome/browser/tabs/tab_model_observer.h"
21 #import "ios/chrome/browser/ui/browser_view_controller.h"
22 #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h"
23 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
24
25 @interface BrowserViewWrangler ()<TabModelObserver> {
26 ios::ChromeBrowserState* _browserState;
27 __unsafe_unretained id<TabModelObserver> _tabModelObserver;
28
29 base::mac::ObjCPropertyReleaser _propertyReleaser_BrowserViewWrangler;
30 }
31
32 // Responsible for maintaining all state related to sharing to other devices.
33 // Redeclared readwrite from the readonly declaration in the Testing interface.
34 @property(nonatomic, retain, readwrite)
35 DeviceSharingManager* deviceSharingManager;
36
37 // Creates a new autoreleased tab model for |browserState|; if |empty| is NO,
38 // then any existing tabs that have been saved for |browserState| will be
39 // loaded; otherwise, the tab model will be created empty.
40 - (TabModel*)tabModelForBrowserState:(ios::ChromeBrowserState*)browserState
41 empty:(BOOL)empty;
42
43 // Creates a new off-the-record ("incognito") browser state for |_browserState|,
44 // then calls -tabModelForBrowserState:empty: and returns the (autoreleased)
45 // result.
46 - (TabModel*)buildOtrTabModel:(BOOL)empty;
47
48 // Creates the correct BrowserViewController for the corresponding browser state
49 // and tab model.
50 - (BrowserViewController*)bvcForBrowserState:
51 (ios::ChromeBrowserState*)browserState
52 tabModel:(TabModel*)tabModel;
53 @end
54
55 @implementation BrowserViewWrangler
56
57 // Properties defined in the BrowserViewInformation protocol.
58 @synthesize mainBVC = _mainBVC;
59 @synthesize mainTabModel = _mainTabModel;
60 @synthesize otrBVC = _otrBVC;
61 @synthesize otrTabModel = _otrTabModel;
62 @synthesize currentBVC = _currentBVC;
63 // Private properies.
64 @synthesize deviceSharingManager = _deviceSharingManager;
65
66 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
67 tabModelObserver:(id<TabModelObserver>)tabModelObserver {
68 if ((self = [super init])) {
69 _propertyReleaser_BrowserViewWrangler.Init(self,
70 [BrowserViewWrangler class]);
71 _browserState = browserState;
72 _tabModelObserver = tabModelObserver;
73 }
74 return self;
75 }
76
77 - (instancetype)init {
78 NOTREACHED();
79 return nil;
80 }
81
82 - (void)dealloc {
83 if (_tabModelObserver) {
84 [_mainTabModel removeObserver:_tabModelObserver];
85 [_otrTabModel removeObserver:_tabModelObserver];
86 }
87 [_mainTabModel removeObserver:self];
88 [_otrTabModel removeObserver:self];
89
90 // Stop URL monitoring of the main tab model.
91 ios_internal::breakpad::StopMonitoringURLsForTabModel(_mainTabModel);
92
93 // Stop Breakpad state monitoring of both tab models (if necessary).
94 ios_internal::breakpad::StopMonitoringTabStateForTabModel(_mainTabModel);
95 ios_internal::breakpad::StopMonitoringTabStateForTabModel(_otrTabModel);
96
97 // Normally other objects will take care of unhooking the tab models from
98 // the browser state, but this code should ensure that it happens regardless.
99 [_mainTabModel browserStateDestroyed];
100 [_otrTabModel browserStateDestroyed];
101
102 [super dealloc];
103 }
104
105 #pragma mark - BrowserViewInformation property implementations
106
107 - (BrowserViewController*)mainBVC {
108 if (!_mainBVC) {
109 // |_browserState| should always be set before trying to create
110 // |_mainBVC|.
111 DCHECK(_browserState);
112 self.mainBVC =
113 [self bvcForBrowserState:_browserState tabModel:self.mainTabModel];
114 DCHECK(_mainBVC);
115 }
116 return _mainBVC;
117 }
118
119 - (TabModel*)mainTabModel {
120 if (!_mainTabModel) {
121 self.mainTabModel = [self tabModelForBrowserState:_browserState empty:NO];
122 // Follow loaded URLs in the main tab model to send those in case of
123 // crashes.
124 ios_internal::breakpad::MonitorURLsForTabModel(_mainTabModel);
125 ios::GetChromeBrowserProvider()->InitializeCastService(_mainTabModel);
126 }
127 return _mainTabModel;
128 }
129
130 - (BrowserViewController*)otrBVC {
131 if (!_otrBVC) {
132 // |_browserState| should always be set before trying to create
133 // |_otrBVC|.
134 DCHECK(_browserState);
135 ios::ChromeBrowserState* otrBrowserState =
136 _browserState->GetOffTheRecordChromeBrowserState();
137 DCHECK(otrBrowserState);
138 self.otrBVC =
139 [self bvcForBrowserState:otrBrowserState tabModel:self.otrTabModel];
140 DCHECK(_otrBVC);
141 }
142 return _otrBVC;
143 }
144
145 - (TabModel*)otrTabModel {
146 if (!_otrTabModel) {
147 self.otrTabModel = [self buildOtrTabModel:NO];
148 }
149 return _otrTabModel;
150 }
151
152 - (void)setCurrentBVC:(BrowserViewController*)bvc
153 storageSwitcher:(id<BrowserStateStorageSwitching>)storageSwitcher {
154 DCHECK(bvc != nil);
155 // |bvc| should be one of the BrowserViewControllers this class already owns.
156 DCHECK(_mainBVC == bvc || _otrBVC == bvc);
157 if (self.currentBVC == bvc) {
158 return;
159 }
160
161 if (self.currentBVC) {
162 // Tell the current BVC it moved to the background.
163 [self.currentBVC setPrimary:NO];
164
165 // Data storage for the browser is always owned by the current BVC, so it
166 // must be updated when switching between BVCs.
167 [storageSwitcher changeStorageFromBrowserState:self.currentBVC.browserState
168 toBrowserState:bvc.browserState];
169 }
170
171 self.currentBVC = bvc;
172
173 // The internal state of the Handoff Manager depends on the current BVC.
174 [self updateDeviceSharingManager];
175
176 // By default, Physical Web discovery will not be started if the browser
177 // launches into an Incognito tab. On switching modes, check if discovery
178 // should be started.
179 StartPhysicalWebDiscovery(GetApplicationContext()->GetLocalState(),
180 [self currentBrowserState]);
181 }
182
183 #pragma mark - BrowserViewInformation methods
184
185 - (TabModel*)currentTabModel {
186 return self.currentBVC.tabModel;
187 }
188
189 - (ios::ChromeBrowserState*)currentBrowserState {
190 return self.currentBVC.browserState;
191 }
192
193 - (void)haltAllTabs {
194 [self.mainTabModel haltAllTabs];
195 [self.otrTabModel haltAllTabs];
196 }
197
198 - (void)cleanDeviceSharingManager {
199 [self.deviceSharingManager updateBrowserState:NULL];
200 }
201
202 #pragma mark - TabModelObserver
203
204 - (void)tabModel:(TabModel*)model
205 didChangeActiveTab:(Tab*)newTab
206 previousTab:(Tab*)previousTab
207 atIndex:(NSUInteger)index {
208 [self updateDeviceSharingManager];
209 }
210
211 - (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab {
212 [self updateDeviceSharingManager];
213 }
214
215 // Called when the number of tabs changes. Updates the switcher button
216 // visibility in the various modes on tablet.
217 - (void)tabModelDidChangeTabCount:(TabModel*)notifiedTabModel {
218 // If in tablet, update the mode switcher icon based on the number of tabs
219 // in the incognito tab strip. Doing this all the time simplifies a lot
220 // of the state transition logic and setting the property to the same value
221 // incurs no re-layout penalty.
222 [self updateModeToggle];
223 }
224
225 #pragma mark - Other public methods
226
227 - (void)updateDeviceSharingManager {
228 if (!self.deviceSharingManager) {
229 self.deviceSharingManager = [[DeviceSharingManager alloc] init];
230 }
231 [self.deviceSharingManager updateBrowserState:_browserState];
232
233 GURL activeURL;
234 Tab* currentTab = [self.currentBVC tabModel].currentTab;
235 // Set the active URL if there's a current tab and the current BVC is not OTR.
236 if (currentTab && self.currentBVC != self.otrBVC) {
237 activeURL = currentTab.url;
238 }
239 [self.deviceSharingManager updateActiveURL:activeURL];
240 }
241
242 - (void)deleteIncognitoTabModelState:
243 (BrowsingDataRemovalController*)removalController {
244 // It is theoretically possible that a Tab has been added to |_otrTabModel|
245 // since the deletion has been scheduled. It is unlikely to happen for real
246 // because it would require superhuman speed.
247 DCHECK(![_otrTabModel count]);
248 DCHECK(_browserState);
249
250 // Stop watching the OTR tab model's state for crashes.
251 ios_internal::breakpad::StopMonitoringTabStateForTabModel(self.otrTabModel);
252
253 // At this stage, a new OTR BVC shouldn't be lazily constructed by calling the
254 // .otrBVC property getter. Instead, the ivar is accessed directly through the
255 // following code.
256 BOOL otrBVCIsCurrent = self.currentBVC == _otrBVC;
257 @autoreleasepool {
258 ios::ChromeBrowserState* otrBrowserState =
259 _browserState->GetOffTheRecordChromeBrowserState();
260 [removalController browserStateDestroyed:otrBrowserState];
261 [_otrBVC browserStateDestroyed];
262 [_otrBVC release];
263 _otrBVC = nil;
264 // There's no guarantee the tab model was ever added to the BVC (or even
265 // that the BVC was created), so ensure the tab model gets notified.
266 [_otrTabModel browserStateDestroyed];
267 if (_tabModelObserver) {
268 [_otrTabModel removeObserver:_tabModelObserver];
269 }
270 [_otrTabModel removeObserver:self];
271 [_otrTabModel release];
272 _otrTabModel = nil;
273 if (otrBVCIsCurrent) {
274 _currentBVC = nil;
275 }
276 }
277
278 _browserState->DestroyOffTheRecordChromeBrowserState();
279
280 // An empty _otrTabModel must be created at this point, because it is then
281 // possible to prevent the tabChanged notification being sent. Otherwise,
282 // when it is created, a notification with no tabs will be sent, and it will
283 // be immediately deleted.
284 self.otrTabModel = [self buildOtrTabModel:YES];
285 DCHECK(![self.otrTabModel count]);
286 DCHECK(_browserState->HasOffTheRecordChromeBrowserState());
287
288 if (otrBVCIsCurrent) {
289 _currentBVC = self.otrBVC;
290 }
291 }
292
293 - (void)updateModeToggle {
294 if (IsIPadIdiom()) {
295 self.mainBVC.hasModeToggleSwitch = self.otrTabModel.count ? YES : NO;
296 self.otrBVC.hasModeToggleSwitch = YES;
297 }
298 }
299
300 #pragma mark - Internal methods
301
302 - (TabModel*)buildOtrTabModel:(BOOL)empty {
303 DCHECK(_browserState);
304 // Ensure that the OTR ChromeBrowserState is created.
305 ios::ChromeBrowserState* otrBrowserState =
306 _browserState->GetOffTheRecordChromeBrowserState();
307 DCHECK(otrBrowserState);
308 return [self tabModelForBrowserState:otrBrowserState empty:empty];
309 }
310
311 - (TabModel*)tabModelForBrowserState:(ios::ChromeBrowserState*)browserState
312 empty:(BOOL)empty {
313 SessionWindowIOS* sessionWindow = nil;
314 if (!empty) {
315 // Load existing saved tab model state.
316 sessionWindow = [[SessionServiceIOS sharedService]
317 loadWindowForBrowserState:browserState];
318 }
319
320 // Create tab model from saved session (nil is ok).
321 TabModel* tabModel =
322 [[[TabModel alloc] initWithSessionWindow:sessionWindow
323 sessionService:[SessionServiceIOS sharedService]
324 browserState:browserState] autorelease];
325 // Add observers.
326 if (_tabModelObserver) {
327 [tabModel addObserver:_tabModelObserver];
328 [tabModel addObserver:self];
329 }
330 ios_internal::breakpad::MonitorTabStateForTabModel(tabModel);
331
332 return tabModel;
333 }
334
335 - (BrowserViewController*)bvcForBrowserState:
336 (ios::ChromeBrowserState*)browserState
337 tabModel:(TabModel*)tabModel {
338 base::scoped_nsobject<BrowserViewControllerDependencyFactory> factory(
339 [[BrowserViewControllerDependencyFactory alloc]
340 initWithBrowserState:browserState]);
341 return [[[BrowserViewController alloc] initWithTabModel:tabModel
342 browserState:browserState
343 dependencyFactory:factory] autorelease];
344 }
345
346 @end
OLDNEW
« 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