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

Side by Side Diff: ios/chrome/browser/tabs/tab_model.mm

Issue 2640093004: WebStateList is an array of web::WebState* wrappers. (Closed)
Patch Set: Fix leaks (caught by unit tests). Created 3 years, 11 months 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
« no previous file with comments | « ios/chrome/browser/tabs/tab_model.h ('k') | ios/chrome/browser/tabs/tab_model_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ios/chrome/browser/tabs/tab_model.h" 5 #import "ios/chrome/browser/tabs/tab_model.h"
6 6
7 #include <list> 7 #include <list>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 @"kTabModelTabDeselectedNotification"; 59 @"kTabModelTabDeselectedNotification";
60 NSString* const kTabModelNewTabWillOpenNotification = 60 NSString* const kTabModelNewTabWillOpenNotification =
61 @"kTabModelNewTabWillOpenNotification"; 61 @"kTabModelNewTabWillOpenNotification";
62 NSString* const kTabModelTabKey = @"tab"; 62 NSString* const kTabModelTabKey = @"tab";
63 NSString* const kTabModelPageLoadSuccess = @"pageLoadSuccess"; 63 NSString* const kTabModelPageLoadSuccess = @"pageLoadSuccess";
64 NSString* const kTabModelOpenInBackgroundKey = @"shouldOpenInBackground"; 64 NSString* const kTabModelOpenInBackgroundKey = @"shouldOpenInBackground";
65 65
66 namespace { 66 namespace {
67 67
68 // Updates CRWSessionCertificatePolicyManager's certificate policy cache. 68 // Updates CRWSessionCertificatePolicyManager's certificate policy cache.
69 void UpdateCertificatePolicyCacheFromWebState(web::WebStateImpl* webState) { 69 void UpdateCertificatePolicyCacheFromWebState(web::WebStateImpl* web_state) {
70 DCHECK([NSThread isMainThread]); 70 DCHECK([NSThread isMainThread]);
71 DCHECK(webState); 71 DCHECK(web_state);
72 scoped_refptr<web::CertificatePolicyCache> policy_cache = 72 scoped_refptr<web::CertificatePolicyCache> policy_cache =
73 web::BrowserState::GetCertificatePolicyCache(webState->GetBrowserState()); 73 web::BrowserState::GetCertificatePolicyCache(
74 web_state->GetBrowserState());
74 CRWSessionController* controller = 75 CRWSessionController* controller =
75 webState->GetNavigationManagerImpl().GetSessionController(); 76 web_state->GetNavigationManagerImpl().GetSessionController();
76 [[controller sessionCertificatePolicyManager] 77 [[controller sessionCertificatePolicyManager]
77 updateCertificatePolicyCache:policy_cache]; 78 updateCertificatePolicyCache:policy_cache];
78 } 79 }
79 80
80 // Populates the certificate policy cache based on the current entries of the 81 // Populates the certificate policy cache based on the current entries of the
81 // given tabs. 82 // given tabs.
82 void RestoreCertificatePolicyCacheFromTabs(NSArray* tabs) { 83 void RestoreCertificatePolicyCacheFromTabs(WebStateList* web_state_list) {
83 DCHECK([NSThread isMainThread]); 84 DCHECK([NSThread isMainThread]);
84 for (Tab* tab in tabs) { 85 for (id<WebStateHandle> web_state in web_state_list) {
85 UpdateCertificatePolicyCacheFromWebState(tab.webStateImpl); 86 UpdateCertificatePolicyCacheFromWebState(web_state.webStateImpl);
86 } 87 }
87 } 88 }
88 89
89 // Scrubs the certificate policy cache of all the certificate policies except 90 // Scrubs the certificate policy cache of all the certificate policies except
90 // those for the current entries of the given tabs. 91 // those for the current entries of the given tabs.
91 void CleanCertificatePolicyCache( 92 void CleanCertificatePolicyCache(
92 scoped_refptr<web::CertificatePolicyCache> policy_cache, 93 scoped_refptr<web::CertificatePolicyCache> policy_cache,
93 NSArray* tabs) { 94 WebStateList* web_state_list) {
94 DCHECK_CURRENTLY_ON(web::WebThread::IO); 95 DCHECK_CURRENTLY_ON(web::WebThread::IO);
95 DCHECK(policy_cache); 96 DCHECK(policy_cache);
96 policy_cache->ClearCertificatePolicies(); 97 policy_cache->ClearCertificatePolicies();
97 web::WebThread::PostTask( 98 web::WebThread::PostTask(
98 web::WebThread::UI, FROM_HERE, 99 web::WebThread::UI, FROM_HERE,
99 base::Bind(&RestoreCertificatePolicyCacheFromTabs, tabs)); 100 base::Bind(&RestoreCertificatePolicyCacheFromTabs, web_state_list));
101 }
102
103 // Creates a NSArray<Tab*>* with elements from |web_state_list| falling into
104 // |range|. This is for compatibility with TabUsageRecorder existing API. That
105 // API will be refactored in later CL and this method removed, see
106 // http://crbug.com/681867 for details.
107 NSArray<Tab*>* GetTabsFromWebStateList(WebStateList* web_state_list,
108 NSRange range) {
109 base::scoped_nsobject<NSMutableArray<Tab*>> mutableArray(
110 [[NSMutableArray alloc] initWithCapacity:range.length]);
111
112 for (NSUInteger ii = range.location; NSLocationInRange(ii, range); ++ii) {
113 [mutableArray addObject:[web_state_list webStateAtIndex:ii]];
114 }
115
116 return [[mutableArray copy] autorelease];
100 } 117 }
101 118
102 } // anonymous namespace 119 } // anonymous namespace
103 120
104 @interface TabModelObservers : CRBProtocolObservers<TabModelObserver> 121 @interface TabModelObservers : CRBProtocolObservers<TabModelObserver>
105 @end 122 @end
106 @implementation TabModelObservers 123 @implementation TabModelObservers
107 @end 124 @end
108 125
109 @interface TabModel ()<TabUsageRecorderDelegate> { 126 @interface TabModel ()<TabUsageRecorderDelegate> {
110 // Array of |Tab| objects.
111 base::scoped_nsobject<NSMutableArray> _tabs;
112 // Maintains policy for where new tabs go and the selection when a tab 127 // Maintains policy for where new tabs go and the selection when a tab
113 // is removed. 128 // is removed.
114 base::scoped_nsobject<TabModelOrderController> _orderController; 129 base::scoped_nsobject<TabModelOrderController> _orderController;
115 // The delegate for sync. 130 // The delegate for sync.
116 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; 131 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate;
117 // Currently selected tab. May be nil. 132 // Currently selected tab. May be nil.
118 base::WeakNSObject<Tab> _currentTab; 133 base::WeakNSObject<Tab> _currentTab;
119 134
120 // Counters for metrics. 135 // Counters for metrics.
121 int _openedTabCount; 136 int _openedTabCount;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 [super dealloc]; 205 [super dealloc];
191 } 206 }
192 207
193 #pragma mark - Public methods 208 #pragma mark - Public methods
194 209
195 - (Tab*)currentTab { 210 - (Tab*)currentTab {
196 return _currentTab.get(); 211 return _currentTab.get();
197 } 212 }
198 213
199 - (void)setCurrentTab:(Tab*)newTab { 214 - (void)setCurrentTab:(Tab*)newTab {
200 DCHECK([_tabs containsObject:newTab]); 215 DCHECK([self containsWebState:newTab]);
201 if (_currentTab != newTab) { 216 if (_currentTab != newTab) {
202 base::RecordAction(base::UserMetricsAction("MobileTabSwitched")); 217 base::RecordAction(base::UserMetricsAction("MobileTabSwitched"));
203 [self updateSnapshotCache:newTab]; 218 [self updateSnapshotCache:newTab];
204 } 219 }
205 if (_tabUsageRecorder) { 220 if (_tabUsageRecorder) {
206 _tabUsageRecorder->RecordTabSwitched(_currentTab, newTab); 221 _tabUsageRecorder->RecordTabSwitched(_currentTab, newTab);
207 } 222 }
208 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES]; 223 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES];
209 } 224 }
210 225
211 - (TabModelSyncedWindowDelegate*)syncedWindowDelegate { 226 - (TabModelSyncedWindowDelegate*)syncedWindowDelegate {
212 return _syncedWindowDelegate.get(); 227 return _syncedWindowDelegate.get();
213 } 228 }
214 229
215 - (TabUsageRecorder*)tabUsageRecorder { 230 - (TabUsageRecorder*)tabUsageRecorder {
216 return _tabUsageRecorder.get(); 231 return _tabUsageRecorder.get();
217 } 232 }
218 233
219 - (BOOL)isOffTheRecord { 234 - (BOOL)isOffTheRecord {
220 return _browserState && _browserState->IsOffTheRecord(); 235 return _browserState && _browserState->IsOffTheRecord();
221 } 236 }
222 237
223 - (BOOL)isEmpty { 238 - (BOOL)isEmpty {
224 return self.count == 0; 239 return self.count == 0;
225 } 240 }
226 241
227 - (NSUInteger)count {
228 return [_tabs count];
229 }
230
231 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window 242 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window
232 sessionService:(SessionServiceIOS*)service 243 sessionService:(SessionServiceIOS*)service
233 browserState:(ios::ChromeBrowserState*)browserState { 244 browserState:(ios::ChromeBrowserState*)browserState {
234 if ((self = [super init])) { 245 if ((self = [super init])) {
235 _observers.reset([[TabModelObservers 246 _observers.reset([[TabModelObservers
236 observersWithProtocol:@protocol(TabModelObserver)] retain]); 247 observersWithProtocol:@protocol(TabModelObserver)] retain]);
237 248
238 _browserState = browserState; 249 _browserState = browserState;
239 DCHECK(_browserState); 250 DCHECK(_browserState);
240 251
241 // There must be a valid session service defined to consume session windows. 252 // There must be a valid session service defined to consume session windows.
242 DCHECK(service); 253 DCHECK(service);
243 _sessionService.reset([service retain]); 254 _sessionService.reset([service retain]);
244 255
245 // Normal browser states are the only ones to get tab restore. Tab sync 256 // Normal browser states are the only ones to get tab restore. Tab sync
246 // handles incognito browser states by filtering on profile, so it's 257 // handles incognito browser states by filtering on profile, so it's
247 // important to the backend code to always have a sync window delegate. 258 // important to the backend code to always have a sync window delegate.
248 if (!_browserState->IsOffTheRecord()) { 259 if (!_browserState->IsOffTheRecord()) {
249 // Set up the usage recorder before tabs are created. 260 // Set up the usage recorder before tabs are created.
250 _tabUsageRecorder.reset(new TabUsageRecorder(self)); 261 _tabUsageRecorder.reset(new TabUsageRecorder(self));
251 } 262 }
252 _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self)); 263 _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self));
253 264
254 _tabs.reset([[NSMutableArray alloc] init]);
255 NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; 265 NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
256 if (window) { 266 if (window) {
257 while (window.unclaimedSessions) { 267 while (window.unclaimedSessions) {
258 std::unique_ptr<web::WebStateImpl> webState = [window nextSession]; 268 std::unique_ptr<web::WebStateImpl> webState = [window nextSession];
259 DCHECK_EQ(webState->GetBrowserState(), _browserState); 269 DCHECK_EQ(webState->GetBrowserState(), _browserState);
260 // Restore the CertificatePolicyCache. 270 // Restore the CertificatePolicyCache.
261 UpdateCertificatePolicyCacheFromWebState(webState.get()); 271 UpdateCertificatePolicyCacheFromWebState(webState.get());
262 // Create a new tab for each entry in the window. Don't send delegate 272 // Create a new tab for each entry in the window. Don't send delegate
263 // notifications for each restored tab, only when all done. 273 // notifications for each restored tab, only when all done.
264 base::scoped_nsobject<Tab> tab( 274 base::scoped_nsobject<Tab> tab(
265 [[Tab alloc] initWithWebState:std::move(webState) model:self]); 275 [[Tab alloc] initWithWebState:std::move(webState) model:self]);
266 [tab webController].usePlaceholderOverlay = YES; 276 [tab webController].usePlaceholderOverlay = YES;
267 [tab fetchFavicon]; 277 [tab fetchFavicon];
268 [_tabs addObject:tab]; 278 [self addWebState:tab];
269 279
270 TabParentingGlobalObserver::GetInstance()->OnTabParented( 280 TabParentingGlobalObserver::GetInstance()->OnTabParented(
271 [tab webStateImpl]); 281 [tab webStateImpl]);
272 } 282 }
273 if ([_tabs count]) { 283 if (self.count) {
274 DCHECK(window.selectedIndex < [_tabs count]); 284 DCHECK(window.selectedIndex < self.count);
275 _currentTab.reset([self tabAtIndex:window.selectedIndex]); 285 _currentTab.reset([self tabAtIndex:window.selectedIndex]);
276 DCHECK(_currentTab); 286 DCHECK(_currentTab);
277 if (_tabUsageRecorder) 287 if (_tabUsageRecorder) {
278 _tabUsageRecorder->InitialRestoredTabs(_currentTab, _tabs); 288 _tabUsageRecorder->InitialRestoredTabs(
289 _currentTab,
290 GetTabsFromWebStateList(self, NSMakeRange(0, self.count)));
291 }
279 // Perform initializations for affiliated objects which update the 292 // Perform initializations for affiliated objects which update the
280 // session information related to the current tab. 293 // session information related to the current tab.
281 [_currentTab updateLastVisitedTimestamp]; 294 [_currentTab updateLastVisitedTimestamp];
282 [self saveSessionImmediately:NO]; 295 [self saveSessionImmediately:NO];
283 } 296 }
284 } 297 }
285 298
286 _orderController.reset( 299 _orderController.reset(
287 [[TabModelOrderController alloc] initWithTabModel:self]); 300 [[TabModelOrderController alloc] initWithTabModel:self]);
288 // Register for resign active notification. 301 // Register for resign active notification.
(...skipping 21 matching lines...) Expand all
310 - (instancetype)init { 323 - (instancetype)init {
311 NOTREACHED(); 324 NOTREACHED();
312 return nil; 325 return nil;
313 } 326 }
314 327
315 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window { 328 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window {
316 DCHECK(_browserState); 329 DCHECK(_browserState);
317 DCHECK(window); 330 DCHECK(window);
318 if (!window.unclaimedSessions) 331 if (!window.unclaimedSessions)
319 return NO; 332 return NO;
320 size_t oldCount = [_tabs count]; 333 size_t oldCount = self.count;
321 size_t index = oldCount; 334 size_t index = oldCount;
322 while (window.unclaimedSessions) { 335 while (window.unclaimedSessions) {
323 std::unique_ptr<web::WebStateImpl> webState = [window nextSession]; 336 std::unique_ptr<web::WebStateImpl> webState = [window nextSession];
324 DCHECK_EQ(webState->GetBrowserState(), _browserState); 337 DCHECK_EQ(webState->GetBrowserState(), _browserState);
325 Tab* tab = [self insertTabWithWebState:std::move(webState) atIndex:index++]; 338 Tab* tab = [self insertTabWithWebState:std::move(webState) atIndex:index++];
326 tab.webController.usePlaceholderOverlay = YES; 339 tab.webController.usePlaceholderOverlay = YES;
327 // Restore the CertificatePolicyCache. Note that after calling Pass() 340 // Restore the CertificatePolicyCache. Note that after calling Pass()
328 // |webState| is invalid, so we need to get the webstate from |tab|. 341 // |webState| is invalid, so we need to get the webstate from |tab|.
329 UpdateCertificatePolicyCacheFromWebState(tab.webStateImpl); 342 UpdateCertificatePolicyCacheFromWebState(tab.webStateImpl);
330 } 343 }
331 DCHECK([_tabs count] > oldCount); 344 DCHECK(self.count > oldCount);
332 // If any tab was restored, the saved selected tab must be selected. 345 // If any tab was restored, the saved selected tab must be selected.
333 if ([_tabs count] > oldCount) { 346 if (self.count > oldCount) {
334 NSUInteger selectedIndex = window.selectedIndex; 347 NSUInteger selectedIndex = window.selectedIndex;
335 if (selectedIndex == NSNotFound) 348 if (selectedIndex == NSNotFound)
336 selectedIndex = oldCount; 349 selectedIndex = oldCount;
337 else 350 else
338 selectedIndex += oldCount; 351 selectedIndex += oldCount;
339 DCHECK(selectedIndex < [_tabs count]); 352 DCHECK(selectedIndex < self.count);
340 Tab* newTab = [self tabAtIndex:selectedIndex]; 353 Tab* newTab = [self tabAtIndex:selectedIndex];
341 DCHECK(newTab); 354 DCHECK(newTab);
342 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES]; 355 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES];
343 356
344 // If there was only one tab and it was the new tab page, clobber it. 357 // If there was only one tab and it was the new tab page, clobber it.
345 if (oldCount == 1) { 358 if (oldCount == 1) {
346 Tab* tab = [_tabs objectAtIndex:0]; 359 Tab* tab = [self firstWebState];
347 if (tab.url == GURL(kChromeUINewTabURL)) { 360 if (tab.url == GURL(kChromeUINewTabURL)) {
348 [self closeTab:tab]; 361 [self closeTab:tab];
349 if (_tabUsageRecorder) 362 if (_tabUsageRecorder) {
350 _tabUsageRecorder->InitialRestoredTabs(_currentTab, _tabs); 363 _tabUsageRecorder->InitialRestoredTabs(
364 _currentTab,
365 GetTabsFromWebStateList(self, NSMakeRange(0, self.count)));
366 }
351 return YES; 367 return YES;
352 } 368 }
353 } 369 }
354 if (_tabUsageRecorder) { 370 if (_tabUsageRecorder) {
355 _tabUsageRecorder->InitialRestoredTabs( 371 _tabUsageRecorder->InitialRestoredTabs(
356 _currentTab, 372 _currentTab, GetTabsFromWebStateList(
357 [_tabs subarrayWithRange:NSMakeRange(oldCount, 373 self, NSMakeRange(oldCount, self.count - oldCount)));
358 [_tabs count] - oldCount)]);
359 } 374 }
360 } 375 }
361 return NO; 376 return NO;
362 } 377 }
363 378
364 - (void)saveSessionImmediately:(BOOL)immediately { 379 - (void)saveSessionImmediately:(BOOL)immediately {
365 // Do nothing if there are tabs in the model but no selected tab. This is 380 // Do nothing if there are tabs in the model but no selected tab. This is
366 // a transitional state. 381 // a transitional state.
367 if ((!_currentTab && [_tabs count]) || !_browserState) 382 if ((!_currentTab && self.count) || !_browserState)
368 return; 383 return;
369 [_sessionService saveWindow:self.windowForSavingSession 384 [_sessionService saveWindow:self.windowForSavingSession
370 forBrowserState:_browserState 385 forBrowserState:_browserState
371 immediately:immediately]; 386 immediately:immediately];
372 } 387 }
373 388
374 - (Tab*)tabAtIndex:(NSUInteger)index { 389 - (Tab*)tabAtIndex:(NSUInteger)index {
375 return [_tabs objectAtIndex:index]; 390 return [self webStateAtIndex:index];
376 } 391 }
377 392
378 - (NSUInteger)indexOfTab:(Tab*)tab { 393 - (NSUInteger)indexOfTab:(Tab*)tab {
379 return [_tabs indexOfObject:tab]; 394 return [self indexOfWebState:tab];
380 } 395 }
381 396
382 - (Tab*)tabWithWindowName:(NSString*)windowName { 397 - (Tab*)tabWithWindowName:(NSString*)windowName {
383 if (!windowName) 398 if (!windowName)
384 return nil; 399 return nil;
385 for (Tab* tab in _tabs.get()) { 400 for (Tab* tab in self) {
386 if ([windowName isEqualToString:tab.windowName]) { 401 if ([windowName isEqualToString:tab.windowName]) {
387 return tab; 402 return tab;
388 } 403 }
389 } 404 }
390 return nil; 405 return nil;
391 } 406 }
392 407
393 - (Tab*)nextTabWithOpener:(Tab*)tab afterTab:(Tab*)afterTab { 408 - (Tab*)nextTabWithOpener:(Tab*)tab afterTab:(Tab*)afterTab {
394 NSUInteger startIndex = NSNotFound; 409 NSUInteger startIndex = NSNotFound;
395 // Start looking after |afterTab|. If it's not found, start looking after 410 // Start looking after |afterTab|. If it's not found, start looking after
396 // |tab|. If it's not found either, bail. 411 // |tab|. If it's not found either, bail.
397 if (afterTab) 412 if (afterTab)
398 startIndex = [self indexOfTab:afterTab]; 413 startIndex = [self indexOfTab:afterTab];
399 if (startIndex == NSNotFound) 414 if (startIndex == NSNotFound)
400 startIndex = [self indexOfTab:tab]; 415 startIndex = [self indexOfTab:tab];
401 if (startIndex == NSNotFound) 416 if (startIndex == NSNotFound)
402 return nil; 417 return nil;
403 NSString* parentID = [tab currentSessionID]; 418 NSString* parentID = [tab currentSessionID];
404 for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) { 419 for (NSUInteger i = startIndex + 1; i < self.count; ++i) {
405 Tab* current = [_tabs objectAtIndex:i]; 420 Tab* current = [self webStateAtIndex:i];
406 DCHECK([current navigationManager]); 421 DCHECK([current navigationManager]);
407 CRWSessionController* sessionController = 422 CRWSessionController* sessionController =
408 [current navigationManager]->GetSessionController(); 423 [current navigationManager]->GetSessionController();
409 if ([sessionController.openerId isEqualToString:parentID]) 424 if ([sessionController.openerId isEqualToString:parentID])
410 return current; 425 return current;
411 } 426 }
412 return nil; 427 return nil;
413 } 428 }
414 429
415 - (Tab*)firstTabWithOpener:(Tab*)tab { 430 - (Tab*)firstTabWithOpener:(Tab*)tab {
416 if (!tab) 431 if (!tab)
417 return nil; 432 return nil;
418 NSUInteger stopIndex = [self indexOfTab:tab]; 433 NSUInteger stopIndex = [self indexOfTab:tab];
419 if (stopIndex == NSNotFound) 434 if (stopIndex == NSNotFound)
420 return nil; 435 return nil;
421 NSString* parentID = [tab currentSessionID]; 436 NSString* parentID = [tab currentSessionID];
422 // Match the navigation index as well as the session id, to better match the 437 // Match the navigation index as well as the session id, to better match the
423 // state of the tab. I.e. two tabs are opened via a link from tab A, and then 438 // state of the tab. I.e. two tabs are opened via a link from tab A, and then
424 // a new url is loaded into tab A, and more tabs opened from that url, the 439 // a new url is loaded into tab A, and more tabs opened from that url, the
425 // latter two tabs should not be grouped with the former two. The navigation 440 // latter two tabs should not be grouped with the former two. The navigation
426 // index is the simplest way to detect navigation changes. 441 // index is the simplest way to detect navigation changes.
427 DCHECK([tab navigationManager]); 442 DCHECK([tab navigationManager]);
428 NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex(); 443 NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex();
429 for (NSUInteger i = 0; i < stopIndex; ++i) { 444 for (NSUInteger i = 0; i < stopIndex; ++i) {
430 Tab* tabToCheck = [_tabs objectAtIndex:i]; 445 Tab* tabToCheck = [self webStateAtIndex:i];
431 DCHECK([tabToCheck navigationManager]); 446 DCHECK([tabToCheck navigationManager]);
432 CRWSessionController* sessionController = 447 CRWSessionController* sessionController =
433 [tabToCheck navigationManager]->GetSessionController(); 448 [tabToCheck navigationManager]->GetSessionController();
434 if ([sessionController.openerId isEqualToString:parentID] && 449 if ([sessionController.openerId isEqualToString:parentID] &&
435 sessionController.openerNavigationIndex == parentNavIndex) { 450 sessionController.openerNavigationIndex == parentNavIndex) {
436 return tabToCheck; 451 return tabToCheck;
437 } 452 }
438 } 453 }
439 return nil; 454 return nil;
440 } 455 }
441 456
442 - (Tab*)lastTabWithOpener:(Tab*)tab { 457 - (Tab*)lastTabWithOpener:(Tab*)tab {
443 NSUInteger startIndex = [self indexOfTab:tab]; 458 NSUInteger startIndex = [self indexOfTab:tab];
444 if (startIndex == NSNotFound) 459 if (startIndex == NSNotFound)
445 return nil; 460 return nil;
446 // There is at least one tab in the model, because otherwise the above check 461 // There is at least one tab in the model, because otherwise the above check
447 // would have returned. 462 // would have returned.
448 NSString* parentID = [tab currentSessionID]; 463 NSString* parentID = [tab currentSessionID];
449 DCHECK([tab navigationManager]); 464 DCHECK([tab navigationManager]);
450 NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex(); 465 NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex();
451 466
452 Tab* match = nil; 467 Tab* match = nil;
453 // Find the last tab in the first matching 'group'. A 'group' is a set of 468 // Find the last tab in the first matching 'group'. A 'group' is a set of
454 // tabs whose opener's id and opener's navigation index match. The navigation 469 // tabs whose opener's id and opener's navigation index match. The navigation
455 // index is used in addition to the session id to detect navigations changes 470 // index is used in addition to the session id to detect navigations changes
456 // within the same session. 471 // within the same session.
457 for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) { 472 for (NSUInteger i = startIndex + 1; i < self.count; ++i) {
458 Tab* tabToCheck = [_tabs objectAtIndex:i]; 473 Tab* tabToCheck = [self webStateAtIndex:i];
459 DCHECK([tabToCheck navigationManager]); 474 DCHECK([tabToCheck navigationManager]);
460 CRWSessionController* sessionController = 475 CRWSessionController* sessionController =
461 [tabToCheck navigationManager]->GetSessionController(); 476 [tabToCheck navigationManager]->GetSessionController();
462 if ([sessionController.openerId isEqualToString:parentID] && 477 if ([sessionController.openerId isEqualToString:parentID] &&
463 sessionController.openerNavigationIndex == parentNavIndex) { 478 sessionController.openerNavigationIndex == parentNavIndex) {
464 match = tabToCheck; 479 match = tabToCheck;
465 } else if (match) { 480 } else if (match) {
466 break; 481 break;
467 } 482 }
468 } 483 }
469 return match; 484 return match;
470 } 485 }
471 486
472 - (Tab*)openerOfTab:(Tab*)tab { 487 - (Tab*)openerOfTab:(Tab*)tab {
473 if (![tab navigationManager]) 488 if (![tab navigationManager])
474 return nil; 489 return nil;
475 NSString* opener = [tab navigationManager]->GetSessionController().openerId; 490 NSString* opener = [tab navigationManager]->GetSessionController().openerId;
476 if (!opener.length) // Short-circuit if opener is empty. 491 if (!opener.length) // Short-circuit if opener is empty.
477 return nil; 492 return nil;
478 for (Tab* iteratedTab in _tabs.get()) { 493 for (Tab* iteratedTab in self) {
479 if ([[iteratedTab currentSessionID] isEqualToString:opener]) 494 if ([[iteratedTab currentSessionID] isEqualToString:opener])
480 return iteratedTab; 495 return iteratedTab;
481 } 496 }
482 return nil; 497 return nil;
483 } 498 }
484 499
485 - (Tab*)insertOrUpdateTabWithURL:(const GURL&)URL 500 - (Tab*)insertOrUpdateTabWithURL:(const GURL&)URL
486 referrer:(const web::Referrer&)referrer 501 referrer:(const web::Referrer&)referrer
487 transition:(ui::PageTransition)transition 502 transition:(ui::PageTransition)transition
488 windowName:(NSString*)windowName 503 windowName:(NSString*)windowName
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 DCHECK_EQ(webState->GetBrowserState(), _browserState); 576 DCHECK_EQ(webState->GetBrowserState(), _browserState);
562 base::scoped_nsobject<Tab> tab( 577 base::scoped_nsobject<Tab> tab(
563 [[Tab alloc] initWithWebState:std::move(webState) model:self]); 578 [[Tab alloc] initWithWebState:std::move(webState) model:self]);
564 [tab webController].webUsageEnabled = webUsageEnabled_; 579 [tab webController].webUsageEnabled = webUsageEnabled_;
565 [self insertTab:tab atIndex:index]; 580 [self insertTab:tab atIndex:index];
566 return tab; 581 return tab;
567 } 582 }
568 583
569 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { 584 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index {
570 DCHECK(tab); 585 DCHECK(tab);
571 DCHECK(index <= [_tabs count]); 586 DCHECK(index <= self.count);
572 [tab fetchFavicon]; 587 [tab fetchFavicon];
573 [_tabs insertObject:tab atIndex:index]; 588 [self insertWebState:tab atIndex:index];
574 589
575 [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO]; 590 [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO];
576 [_observers tabModelDidChangeTabCount:self]; 591 [_observers tabModelDidChangeTabCount:self];
577 592
578 base::RecordAction(base::UserMetricsAction("MobileNewTabOpened")); 593 base::RecordAction(base::UserMetricsAction("MobileNewTabOpened"));
579 // Persist the session due to a new tab being inserted. If this is a 594 // Persist the session due to a new tab being inserted. If this is a
580 // background tab (will not become active), saving now will capture the 595 // background tab (will not become active), saving now will capture the
581 // state properly. If it does eventually become active, another save will 596 // state properly. If it does eventually become active, another save will
582 // be triggered to properly capture the end result. 597 // be triggered to properly capture the end result.
583 [self saveSessionImmediately:NO]; 598 [self saveSessionImmediately:NO];
584 ++_newTabCount; 599 ++_newTabCount;
585 } 600 }
586 601
587 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { 602 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex {
588 NSUInteger fromIndex = [self indexOfTab:tab]; 603 NSUInteger fromIndex = [self indexOfTab:tab];
589 DCHECK_NE(NSNotFound, static_cast<NSInteger>(fromIndex)); 604 DCHECK_NE(NSNotFound, static_cast<NSInteger>(fromIndex));
590 DCHECK_LT(toIndex, self.count); 605 DCHECK_LT(toIndex, self.count);
591 if (fromIndex == NSNotFound || toIndex >= self.count || 606 if (fromIndex == NSNotFound || toIndex >= self.count ||
592 fromIndex == toIndex) { 607 fromIndex == toIndex) {
593 return; 608 return;
594 } 609 }
595 610
596 base::scoped_nsobject<Tab> tabSaver([tab retain]); 611 base::scoped_nsobject<Tab> tabSaver([tab retain]);
597 [_tabs removeObject:tab]; 612 [self removeWebState:tab];
598 [_tabs insertObject:tab atIndex:toIndex]; 613 [self insertWebState:tab atIndex:toIndex];
599 614
600 [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex]; 615 [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex];
601 } 616 }
602 617
603 - (void)replaceTab:(Tab*)oldTab 618 - (void)replaceTab:(Tab*)oldTab
604 withTab:(Tab*)newTab 619 withTab:(Tab*)newTab
605 keepOldTabOpen:(BOOL)keepOldTabOpen { 620 keepOldTabOpen:(BOOL)keepOldTabOpen {
606 NSUInteger index = [self indexOfTab:oldTab]; 621 NSUInteger index = [self indexOfTab:oldTab];
607 DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); 622 DCHECK_NE(NSNotFound, static_cast<NSInteger>(index));
608 623
609 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); 624 base::scoped_nsobject<Tab> tabSaver([oldTab retain]);
610 [newTab fetchFavicon]; 625 [newTab fetchFavicon];
611 [_tabs replaceObjectAtIndex:index withObject:newTab]; 626 [self replaceWebStateAtIndex:index withWebState:newTab];
612 [newTab setParentTabModel:self]; 627 [newTab setParentTabModel:self];
613 628
614 [_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index]; 629 [_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index];
615 630
616 if (self.currentTab == oldTab) 631 if (self.currentTab == oldTab)
617 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; 632 [self changeSelectedTabFrom:nil to:newTab persistState:NO];
618 633
619 [oldTab setParentTabModel:nil]; 634 [oldTab setParentTabModel:nil];
620 if (!keepOldTabOpen) 635 if (!keepOldTabOpen)
621 [oldTab close]; 636 [oldTab close];
622 637
623 // Record a tab clobber, since swapping tabs bypasses the tab code that would 638 // Record a tab clobber, since swapping tabs bypasses the tab code that would
624 // normally log clobbers. 639 // normally log clobbers.
625 base::RecordAction(base::UserMetricsAction("MobileTabClobbered")); 640 base::RecordAction(base::UserMetricsAction("MobileTabClobbered"));
626 } 641 }
627 642
628 - (void)closeTabAtIndex:(NSUInteger)index { 643 - (void)closeTabAtIndex:(NSUInteger)index {
629 DCHECK(index < [_tabs count]); 644 DCHECK(index < self.count);
630 [self closeTab:[_tabs objectAtIndex:index]]; 645 [self closeTab:[self webStateAtIndex:index]];
631 } 646 }
632 647
633 - (void)closeTab:(Tab*)tab { 648 - (void)closeTab:(Tab*)tab {
634 // Ensure the tab stays alive long enough for us to send out the 649 // Ensure the tab stays alive long enough for us to send out the
635 // notice of its destruction to the delegate. 650 // notice of its destruction to the delegate.
636 [_observers tabModel:self willRemoveTab:tab]; 651 [_observers tabModel:self willRemoveTab:tab];
637 [tab close]; // Note it is not safe to access the tab after 'close'. 652 [tab close]; // Note it is not safe to access the tab after 'close'.
638 } 653 }
639 654
640 - (void)closeAllTabs { 655 - (void)closeAllTabs {
641 // If this changes, _closedTabCount metrics need to be adjusted. 656 // If this changes, _closedTabCount metrics need to be adjusted.
642 for (NSInteger i = self.count - 1; i >= 0; --i) 657 for (NSInteger i = self.count - 1; i >= 0; --i)
643 [self closeTabAtIndex:i]; 658 [self closeTabAtIndex:i];
644 [[NSNotificationCenter defaultCenter] 659 [[NSNotificationCenter defaultCenter]
645 postNotificationName:kTabModelAllTabsDidCloseNotification 660 postNotificationName:kTabModelAllTabsDidCloseNotification
646 object:self]; 661 object:self];
647 } 662 }
648 663
649 - (void)haltAllTabs { 664 - (void)haltAllTabs {
650 for (Tab* tab in _tabs.get()) { 665 for (Tab* tab in self) {
651 [tab terminateNetworkActivity]; 666 [tab terminateNetworkActivity];
652 } 667 }
653 } 668 }
654 669
655 - (void)notifyTabChanged:(Tab*)tab { 670 - (void)notifyTabChanged:(Tab*)tab {
656 [_observers tabModel:self didChangeTab:tab]; 671 [_observers tabModel:self didChangeTab:tab];
657 } 672 }
658 673
659 - (void)addObserver:(id<TabModelObserver>)observer { 674 - (void)addObserver:(id<TabModelObserver>)observer {
660 [_observers addObserver:observer]; 675 [_observers addObserver:observer];
(...skipping 16 matching lines...) Expand all
677 200, 50); 692 200, 50);
678 UMA_HISTOGRAM_CUSTOM_COUNTS("Session.NewTabCounts", _newTabCount, 1, 200, 50); 693 UMA_HISTOGRAM_CUSTOM_COUNTS("Session.NewTabCounts", _newTabCount, 1, 200, 50);
679 } 694 }
680 695
681 - (void)notifyTabSnapshotChanged:(Tab*)tab withImage:(UIImage*)image { 696 - (void)notifyTabSnapshotChanged:(Tab*)tab withImage:(UIImage*)image {
682 DCHECK([NSThread isMainThread]); 697 DCHECK([NSThread isMainThread]);
683 [_observers tabModel:self didChangeTabSnapshot:tab withImage:image]; 698 [_observers tabModel:self didChangeTabSnapshot:tab withImage:image];
684 } 699 }
685 700
686 - (void)resetAllWebViews { 701 - (void)resetAllWebViews {
687 for (Tab* tab in _tabs.get()) { 702 for (Tab* tab in self) {
688 [tab.webController reinitializeWebViewAndReload:(tab == _currentTab)]; 703 [tab.webController reinitializeWebViewAndReload:(tab == _currentTab)];
689 } 704 }
690 } 705 }
691 706
692 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled { 707 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled {
693 if (webUsageEnabled_ == webUsageEnabled) 708 if (webUsageEnabled_ == webUsageEnabled)
694 return; 709 return;
695 webUsageEnabled_ = webUsageEnabled; 710 webUsageEnabled_ = webUsageEnabled;
696 for (Tab* tab in _tabs.get()) { 711 for (Tab* tab in self) {
697 tab.webUsageEnabled = webUsageEnabled; 712 tab.webUsageEnabled = webUsageEnabled;
698 } 713 }
699 } 714 }
700 715
701 - (void)setPrimary:(BOOL)primary { 716 - (void)setPrimary:(BOOL)primary {
702 if (_tabUsageRecorder) 717 if (_tabUsageRecorder)
703 _tabUsageRecorder->RecordPrimaryTabModelChange(primary, _currentTab); 718 _tabUsageRecorder->RecordPrimaryTabModelChange(primary, _currentTab);
704 } 719 }
705 720
706 - (NSSet*)currentlyReferencedExternalFiles { 721 - (NSSet*)currentlyReferencedExternalFiles {
707 NSMutableSet* referencedFiles = [NSMutableSet set]; 722 NSMutableSet* referencedFiles = [NSMutableSet set];
708 if (!_browserState) 723 if (!_browserState)
709 return referencedFiles; 724 return referencedFiles;
710 // Check the currently open tabs for external files. 725 // Check the currently open tabs for external files.
711 for (Tab* tab in _tabs.get()) { 726 for (Tab* tab in self) {
712 if (UrlIsExternalFileReference(tab.url)) { 727 if (UrlIsExternalFileReference(tab.url)) {
713 NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName()); 728 NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName());
714 [referencedFiles addObject:fileName]; 729 [referencedFiles addObject:fileName];
715 } 730 }
716 } 731 }
717 // Do the same for the recently closed tabs. 732 // Do the same for the recently closed tabs.
718 sessions::TabRestoreService* restoreService = 733 sessions::TabRestoreService* restoreService =
719 IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState); 734 IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState);
720 DCHECK(restoreService); 735 DCHECK(restoreService);
721 for (const auto& entry : restoreService->entries()) { 736 for (const auto& entry : restoreService->entries()) {
(...skipping 16 matching lines...) Expand all
738 [[NSNotificationCenter defaultCenter] removeObserver:self]; 753 [[NSNotificationCenter defaultCenter] removeObserver:self];
739 if (_browserState) { 754 if (_browserState) {
740 UnregisterTabModelFromChromeBrowserState(_browserState, self); 755 UnregisterTabModelFromChromeBrowserState(_browserState, self);
741 } 756 }
742 _browserState = nullptr; 757 _browserState = nullptr;
743 } 758 }
744 759
745 // Called when a tab is closing, but before its CRWWebController is destroyed. 760 // Called when a tab is closing, but before its CRWWebController is destroyed.
746 // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel. 761 // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel.
747 - (void)didCloseTab:(Tab*)closedTab { 762 - (void)didCloseTab:(Tab*)closedTab {
748 NSUInteger closedTabIndex = [_tabs indexOfObject:closedTab]; 763 NSUInteger closedTabIndex = [self indexOfWebState:closedTab];
749 DCHECK(closedTab); 764 DCHECK(closedTab);
750 DCHECK(closedTabIndex != NSNotFound); 765 DCHECK(closedTabIndex != NSNotFound);
751 // Let the sessions::TabRestoreService know about that new tab. 766 // Let the sessions::TabRestoreService know about that new tab.
752 sessions::TabRestoreService* restoreService = 767 sessions::TabRestoreService* restoreService =
753 _browserState 768 _browserState
754 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState) 769 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState)
755 : nullptr; 770 : nullptr;
756 web::NavigationManagerImpl* navigationManager = [closedTab navigationManager]; 771 web::NavigationManagerImpl* navigationManager = [closedTab navigationManager];
757 DCHECK(navigationManager); 772 DCHECK(navigationManager);
758 int itemCount = navigationManager->GetItemCount(); 773 int itemCount = navigationManager->GetItemCount();
759 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) { 774 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) {
760 restoreService->CreateHistoricalTab( 775 restoreService->CreateHistoricalTab(
761 sessions::IOSLiveTab::GetForWebState(closedTab.webStateImpl), 776 sessions::IOSLiveTab::GetForWebState(closedTab.webStateImpl),
762 static_cast<int>(closedTabIndex)); 777 static_cast<int>(closedTabIndex));
763 } 778 }
764 // This needs to be called before the tab is removed from the list. 779 // This needs to be called before the tab is removed from the list.
765 Tab* newSelection = 780 Tab* newSelection =
766 [_orderController determineNewSelectedTabFromRemovedTab:closedTab]; 781 [_orderController determineNewSelectedTabFromRemovedTab:closedTab];
767 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]); 782 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]);
768 [_tabs removeObject:closedTab]; 783 [self removeWebState:closedTab];
769 784
770 // If closing the current tab, clear |_currentTab| before sending any 785 // If closing the current tab, clear |_currentTab| before sending any
771 // notification. This avoids various parts of the code getting confused 786 // notification. This avoids various parts of the code getting confused
772 // when the current tab isn't in the tab model. 787 // when the current tab isn't in the tab model.
773 Tab* savedCurrentTab = _currentTab; 788 Tab* savedCurrentTab = _currentTab;
774 if (closedTab == _currentTab) 789 if (closedTab == _currentTab)
775 _currentTab.reset(nil); 790 _currentTab.reset(nil);
776 791
777 [_observers tabModel:self didRemoveTab:closedTab atIndex:closedTabIndex]; 792 [_observers tabModel:self didRemoveTab:closedTab atIndex:closedTabIndex];
778 [_observers tabModelDidChangeTabCount:self]; 793 [_observers tabModelDidChangeTabCount:self];
(...skipping 30 matching lines...) Expand all
809 if (previousURL.ReplaceComponents(replacements) == 824 if (previousURL.ReplaceComponents(replacements) ==
810 currentURL.ReplaceComponents(replacements)) { 825 currentURL.ReplaceComponents(replacements)) {
811 return; 826 return;
812 } 827 }
813 } 828 }
814 829
815 int tabCount = static_cast<int>(self.count); 830 int tabCount = static_cast<int>(self.count);
816 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tabCount, 1, 200, 50); 831 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tabCount, 1, 200, 50);
817 } 832 }
818 833
819 #pragma mark - NSFastEnumeration
820
821 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
822 objects:(id*)objects
823 count:(NSUInteger)count {
824 return [_tabs countByEnumeratingWithState:state objects:objects count:count];
825 }
826
827 #pragma mark - TabUsageRecorderDelegate 834 #pragma mark - TabUsageRecorderDelegate
828 835
829 - (NSUInteger)liveTabsCount { 836 - (NSUInteger)liveTabsCount {
830 NSUInteger count = 0; 837 NSUInteger count = 0;
831 NSArray* tabs = _tabs.get(); 838 for (Tab* tab in self) {
832 for (Tab* tab in tabs) {
833 if ([tab.webController isViewAlive]) 839 if ([tab.webController isViewAlive])
834 count++; 840 count++;
835 } 841 }
836 return count; 842 return count;
837 } 843 }
838 844
839 #pragma mark - Private methods 845 #pragma mark - Private methods
840 846
841 - (SessionWindowIOS*)windowForSavingSession { 847 - (SessionWindowIOS*)windowForSavingSession {
842 // Background tabs will already have their state preserved, but not the 848 // Background tabs will already have their state preserved, but not the
843 // fg tab. Do it now. 849 // fg tab. Do it now.
844 [_currentTab recordStateInHistory]; 850 [_currentTab recordStateInHistory];
845 851
846 // Build the array of sessions. Copy the session objects as the saving will 852 // Build the array of sessions. Copy the session objects as the saving will
847 // be done on a separate thread. 853 // be done on a separate thread.
848 // TODO(crbug.com/661986): This could get expensive especially since this 854 // TODO(crbug.com/661986): This could get expensive especially since this
849 // window may never be saved (if another call comes in before the delay). 855 // window may never be saved (if another call comes in before the delay).
850 SessionWindowIOS* window = [[[SessionWindowIOS alloc] init] autorelease]; 856 SessionWindowIOS* window = [[[SessionWindowIOS alloc] init] autorelease];
851 for (Tab* tab in _tabs.get()) { 857 for (Tab* tab in self) {
852 DCHECK(tab.webStateImpl); 858 DCHECK(tab.webStateImpl);
853 std::unique_ptr<web::WebStateImpl> webStateCopy( 859 std::unique_ptr<web::WebStateImpl> webStateCopy(
854 tab.webStateImpl->CopyForSessionWindow()); 860 tab.webStateImpl->CopyForSessionWindow());
855 [window addSession:std::move(webStateCopy)]; 861 [window addSession:std::move(webStateCopy)];
856 } 862 }
857 window.selectedIndex = [self indexOfTab:_currentTab]; 863 window.selectedIndex = [self indexOfTab:_currentTab];
858 return window; 864 return window;
859 } 865 }
860 866
861 - (BOOL)isNTPTab:(Tab*)tab { 867 - (BOOL)isNTPTab:(Tab*)tab {
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 - (void)applicationDidEnterBackground:(NSNotification*)notify { 1012 - (void)applicationDidEnterBackground:(NSNotification*)notify {
1007 if (!_browserState) 1013 if (!_browserState)
1008 return; 1014 return;
1009 // Evict all the certificate policies except for the current entries of the 1015 // Evict all the certificate policies except for the current entries of the
1010 // active sessions. 1016 // active sessions.
1011 scoped_refptr<web::CertificatePolicyCache> policy_cache = 1017 scoped_refptr<web::CertificatePolicyCache> policy_cache =
1012 web::BrowserState::GetCertificatePolicyCache(_browserState); 1018 web::BrowserState::GetCertificatePolicyCache(_browserState);
1013 DCHECK(policy_cache); 1019 DCHECK(policy_cache);
1014 web::WebThread::PostTask( 1020 web::WebThread::PostTask(
1015 web::WebThread::IO, FROM_HERE, 1021 web::WebThread::IO, FROM_HERE,
1016 base::Bind(&CleanCertificatePolicyCache, policy_cache, _tabs)); 1022 base::Bind(&CleanCertificatePolicyCache, policy_cache, self));
1017 1023
1018 if (_tabUsageRecorder) 1024 if (_tabUsageRecorder)
1019 _tabUsageRecorder->AppDidEnterBackground(); 1025 _tabUsageRecorder->AppDidEnterBackground();
1020 1026
1021 // Normally, the session is saved after some timer expires but since the app 1027 // Normally, the session is saved after some timer expires but since the app
1022 // is about to enter the background send YES to save the session immediately. 1028 // is about to enter the background send YES to save the session immediately.
1023 [self saveSessionImmediately:YES]; 1029 [self saveSessionImmediately:YES];
1024 1030
1025 // Write out a grey version of the current website to disk. 1031 // Write out a grey version of the current website to disk.
1026 if (webUsageEnabled_ && _currentTab) { 1032 if (webUsageEnabled_ && _currentTab) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 web::NavigationManager::WebLoadParams params(URL); 1071 web::NavigationManager::WebLoadParams params(URL);
1066 params.referrer = referrer; 1072 params.referrer = referrer;
1067 params.transition_type = ui::PAGE_TRANSITION_TYPED; 1073 params.transition_type = ui::PAGE_TRANSITION_TYPED;
1068 [[tab webController] loadWithParams:params]; 1074 [[tab webController] loadWithParams:params];
1069 [tab webController].webUsageEnabled = webUsageEnabled_; 1075 [tab webController].webUsageEnabled = webUsageEnabled_;
1070 [self insertTab:tab atIndex:index]; 1076 [self insertTab:tab atIndex:index];
1071 return tab; 1077 return tab;
1072 } 1078 }
1073 1079
1074 @end 1080 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/tabs/tab_model.h ('k') | ios/chrome/browser/tabs/tab_model_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698