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

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

Issue 2683393003: Refactor TabModel to use WebStateList to store WebStates. (Closed)
Patch Set: Fix TabModelTest.MoveTabs. Created 3 years, 10 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
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 <cstdint>
7 #include <utility> 8 #include <utility>
8 #include <vector> 9 #include <vector>
9 10
10 #include "base/bind.h" 11 #include "base/bind.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #import "base/mac/scoped_nsobject.h" 13 #import "base/mac/scoped_nsobject.h"
13 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
14 #include "base/metrics/user_metrics.h" 15 #include "base/metrics/user_metrics.h"
15 #include "base/metrics/user_metrics_action.h" 16 #include "base/metrics/user_metrics_action.h"
16 #include "base/strings/sys_string_conversions.h" 17 #include "base/strings/sys_string_conversions.h"
17 #include "base/task/cancelable_task_tracker.h" 18 #include "base/task/cancelable_task_tracker.h"
18 #include "components/sessions/core/serialized_navigation_entry.h" 19 #include "components/sessions/core/serialized_navigation_entry.h"
19 #include "components/sessions/core/session_id.h" 20 #include "components/sessions/core/session_id.h"
20 #include "components/sessions/core/tab_restore_service.h" 21 #include "components/sessions/core/tab_restore_service.h"
21 #include "components/sessions/ios/ios_live_tab.h" 22 #include "components/sessions/ios/ios_live_tab.h"
22 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" 23 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
23 #include "ios/chrome/browser/chrome_url_constants.h" 24 #include "ios/chrome/browser/chrome_url_constants.h"
24 #import "ios/chrome/browser/chrome_url_util.h" 25 #import "ios/chrome/browser/chrome_url_util.h"
25 #import "ios/chrome/browser/metrics/tab_usage_recorder.h" 26 #import "ios/chrome/browser/metrics/tab_usage_recorder.h"
26 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" 27 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
27 #import "ios/chrome/browser/sessions/session_service.h" 28 #import "ios/chrome/browser/sessions/session_service.h"
28 #import "ios/chrome/browser/sessions/session_window.h" 29 #import "ios/chrome/browser/sessions/session_window.h"
29 #import "ios/chrome/browser/snapshots/snapshot_cache.h" 30 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
30 #include "ios/chrome/browser/tab_parenting_global_observer.h" 31 #include "ios/chrome/browser/tab_parenting_global_observer.h"
32 #import "ios/chrome/browser/tabs/legacy_tab_helper.h"
31 #import "ios/chrome/browser/tabs/tab.h" 33 #import "ios/chrome/browser/tabs/tab.h"
32 #import "ios/chrome/browser/tabs/tab_model_list.h" 34 #import "ios/chrome/browser/tabs/tab_model_list.h"
33 #import "ios/chrome/browser/tabs/tab_model_observers.h" 35 #import "ios/chrome/browser/tabs/tab_model_observers.h"
34 #import "ios/chrome/browser/tabs/tab_model_order_controller.h" 36 #import "ios/chrome/browser/tabs/tab_model_order_controller.h"
35 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" 37 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
36 #import "ios/chrome/browser/xcallback_parameters.h" 38 #import "ios/chrome/browser/xcallback_parameters.h"
39 #import "ios/shared/chrome/browser/tabs/web_state_list.h"
40 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h "
41 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h"
37 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" 42 #import "ios/web/navigation/crw_session_certificate_policy_manager.h"
38 #import "ios/web/navigation/crw_session_controller.h" 43 #import "ios/web/navigation/crw_session_controller.h"
39 #include "ios/web/public/browser_state.h" 44 #include "ios/web/public/browser_state.h"
40 #include "ios/web/public/certificate_policy_cache.h" 45 #include "ios/web/public/certificate_policy_cache.h"
41 #include "ios/web/public/navigation_item.h" 46 #include "ios/web/public/navigation_item.h"
42 #import "ios/web/public/navigation_manager.h" 47 #import "ios/web/public/navigation_manager.h"
43 #include "ios/web/public/web_thread.h" 48 #include "ios/web/public/web_thread.h"
44 #import "ios/web/web_state/ui/crw_web_controller.h" 49 #import "ios/web/web_state/ui/crw_web_controller.h"
45 #import "ios/web/web_state/web_state_impl.h" 50 #import "ios/web/web_state/web_state_impl.h"
46 #include "url/gurl.h" 51 #include "url/gurl.h"
(...skipping 25 matching lines...) Expand all
72 DCHECK_CURRENTLY_ON(web::WebThread::UI); 77 DCHECK_CURRENTLY_ON(web::WebThread::UI);
73 // TODO(crbug.com/454984): Remove CRWSessionController usage once certificate 78 // TODO(crbug.com/454984): Remove CRWSessionController usage once certificate
74 // policy manager is moved to NavigationManager. 79 // policy manager is moved to NavigationManager.
75 CRWSessionController* controller = static_cast<web::WebStateImpl*>(web_state) 80 CRWSessionController* controller = static_cast<web::WebStateImpl*>(web_state)
76 ->GetNavigationManagerImpl() 81 ->GetNavigationManagerImpl()
77 .GetSessionController(); 82 .GetSessionController();
78 [[controller sessionCertificatePolicyManager] 83 [[controller sessionCertificatePolicyManager]
79 updateCertificatePolicyCache:policy_cache]; 84 updateCertificatePolicyCache:policy_cache];
80 } 85 }
81 86
82 // Populates the certificate policy cache based on the WebStates of |tab_model|. 87 // Populates the certificate policy cache based on the WebStates of
88 // |web_state_list|.
83 void RestoreCertificatePolicyCacheFromModel( 89 void RestoreCertificatePolicyCacheFromModel(
84 const scoped_refptr<web::CertificatePolicyCache>& policy_cache, 90 const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
85 TabModel* tab_model) { 91 WebStateList* web_state_list) {
86 DCHECK_CURRENTLY_ON(web::WebThread::UI); 92 DCHECK_CURRENTLY_ON(web::WebThread::UI);
87 for (Tab* tab in tab_model) 93 for (int index = 0; index < web_state_list->count(); ++index) {
88 UpdateCertificatePolicyCacheFromWebState(policy_cache, tab.webState); 94 UpdateCertificatePolicyCacheFromWebState(
95 policy_cache, web_state_list->GetWebStateAt(index));
96 }
89 } 97 }
90 98
91 // Scrubs the certificate policy cache of all certificates policies except 99 // Scrubs the certificate policy cache of all certificates policies except
92 // those for the current entries in |tab_model|. 100 // those for the current entries in |web_state_list|.
93 void CleanCertificatePolicyCache( 101 void CleanCertificatePolicyCache(
94 base::CancelableTaskTracker* task_tracker, 102 base::CancelableTaskTracker* task_tracker,
95 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 103 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
96 const scoped_refptr<web::CertificatePolicyCache>& policy_cache, 104 const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
97 TabModel* tab_model) { 105 WebStateList* web_state_list) {
98 DCHECK(tab_model);
99 DCHECK(policy_cache); 106 DCHECK(policy_cache);
107 DCHECK(web_state_list);
100 DCHECK_CURRENTLY_ON(web::WebThread::UI); 108 DCHECK_CURRENTLY_ON(web::WebThread::UI);
101 task_tracker->PostTaskAndReply( 109 task_tracker->PostTaskAndReply(
102 task_runner.get(), FROM_HERE, 110 task_runner.get(), FROM_HERE,
103 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies, 111 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies,
104 policy_cache), 112 policy_cache),
105 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache, 113 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache,
106 base::Unretained(tab_model))); 114 base::Unretained(web_state_list)));
107 } 115 }
108 116
109 } // anonymous namespace 117 } // anonymous namespace
110 118
119 @interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory>
120 @end
121
122 @implementation TabModelWebStateProxyFactory
123
124 - (id)proxyForWebState:(web::WebState*)webState {
125 return LegacyTabHelper::GetTabForWebState(webState);
126 }
127
128 @end
129
111 @interface TabModel ()<TabUsageRecorderDelegate> { 130 @interface TabModel ()<TabUsageRecorderDelegate> {
112 // Array of |Tab| objects. 131 // Underlying shared model implementation.
113 base::scoped_nsobject<NSMutableArray> _tabs; 132 WebStateList _webStateList;
133
134 // Helper providing NSFastEnumeration implementation over the WebStateList.
135 base::scoped_nsobject<WebStateListFastEnumerationHelper>
136 _fastEnumerationHelper;
137
138 // Used to keep the Tabs alive while the corresponding WebStates are stored
139 // in the WebStateList (as Tabs currently own their WebState). Remove once
140 // WebState owns the associated Tab.
141 base::scoped_nsobject<NSMutableSet<Tab*>> _tabRetainer;
142
114 // Maintains policy for where new tabs go and the selection when a tab 143 // Maintains policy for where new tabs go and the selection when a tab
115 // is removed. 144 // is removed.
116 base::scoped_nsobject<TabModelOrderController> _orderController; 145 base::scoped_nsobject<TabModelOrderController> _orderController;
117 // The delegate for sync. 146 // The delegate for sync.
118 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; 147 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate;
119 // Currently selected tab. May be nil. 148 // Currently selected tab. May be nil.
120 base::WeakNSObject<Tab> _currentTab; 149 base::WeakNSObject<Tab> _currentTab;
121 150
122 // Counters for metrics. 151 // Counters for metrics.
123 int _openedTabCount; 152 int _openedTabCount;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 [super dealloc]; 236 [super dealloc];
208 } 237 }
209 238
210 #pragma mark - Public methods 239 #pragma mark - Public methods
211 240
212 - (Tab*)currentTab { 241 - (Tab*)currentTab {
213 return _currentTab.get(); 242 return _currentTab.get();
214 } 243 }
215 244
216 - (void)setCurrentTab:(Tab*)newTab { 245 - (void)setCurrentTab:(Tab*)newTab {
217 DCHECK([_tabs containsObject:newTab]); 246 DCHECK_NE([self indexOfTab:newTab], static_cast<NSUInteger>(NSNotFound));
218 if (_currentTab != newTab) { 247 if (_currentTab != newTab) {
219 base::RecordAction(base::UserMetricsAction("MobileTabSwitched")); 248 base::RecordAction(base::UserMetricsAction("MobileTabSwitched"));
220 [self updateSnapshotCache:newTab]; 249 [self updateSnapshotCache:newTab];
221 } 250 }
222 if (_tabUsageRecorder) { 251 if (_tabUsageRecorder) {
223 _tabUsageRecorder->RecordTabSwitched(_currentTab, newTab); 252 _tabUsageRecorder->RecordTabSwitched(_currentTab, newTab);
224 } 253 }
225 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES]; 254 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES];
226 } 255 }
227 256
228 - (TabModelSyncedWindowDelegate*)syncedWindowDelegate { 257 - (TabModelSyncedWindowDelegate*)syncedWindowDelegate {
229 return _syncedWindowDelegate.get(); 258 return _syncedWindowDelegate.get();
230 } 259 }
231 260
232 - (TabUsageRecorder*)tabUsageRecorder { 261 - (TabUsageRecorder*)tabUsageRecorder {
233 return _tabUsageRecorder.get(); 262 return _tabUsageRecorder.get();
234 } 263 }
235 264
236 - (BOOL)isOffTheRecord { 265 - (BOOL)isOffTheRecord {
237 return _browserState && _browserState->IsOffTheRecord(); 266 return _browserState && _browserState->IsOffTheRecord();
238 } 267 }
239 268
240 - (BOOL)isEmpty { 269 - (BOOL)isEmpty {
241 return self.count == 0; 270 return _webStateList.empty();
242 } 271 }
243 272
244 - (NSUInteger)count { 273 - (NSUInteger)count {
245 return [_tabs count]; 274 DCHECK_GE(_webStateList.count(), 0);
275 return static_cast<NSUInteger>(_webStateList.count());
246 } 276 }
247 277
248 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window 278 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window
249 sessionService:(SessionServiceIOS*)service 279 sessionService:(SessionServiceIOS*)service
250 browserState:(ios::ChromeBrowserState*)browserState { 280 browserState:(ios::ChromeBrowserState*)browserState {
251 if ((self = [super init])) { 281 if ((self = [super init])) {
282 _tabRetainer.reset([[NSMutableSet alloc] init]);
252 _observers.reset([[TabModelObservers observers] retain]); 283 _observers.reset([[TabModelObservers observers] retain]);
253 284
285 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc]
286 initWithWebStateList:&_webStateList
287 proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]);
288
254 _browserState = browserState; 289 _browserState = browserState;
255 DCHECK(_browserState); 290 DCHECK(_browserState);
256 291
257 // There must be a valid session service defined to consume session windows. 292 // There must be a valid session service defined to consume session windows.
258 DCHECK(service); 293 DCHECK(service);
259 _sessionService.reset([service retain]); 294 _sessionService.reset([service retain]);
260 295
261 // Normal browser states are the only ones to get tab restore. Tab sync 296 // Normal browser states are the only ones to get tab restore. Tab sync
262 // handles incognito browser states by filtering on profile, so it's 297 // handles incognito browser states by filtering on profile, so it's
263 // important to the backend code to always have a sync window delegate. 298 // important to the backend code to always have a sync window delegate.
264 if (!_browserState->IsOffTheRecord()) { 299 if (!_browserState->IsOffTheRecord()) {
265 // Set up the usage recorder before tabs are created. 300 // Set up the usage recorder before tabs are created.
266 _tabUsageRecorder.reset(new TabUsageRecorder(self)); 301 _tabUsageRecorder.reset(new TabUsageRecorder(self));
267 } 302 }
268 _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self)); 303 _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self));
269 304
270 _tabs.reset([[NSMutableArray alloc] init]);
271 if (window) { 305 if (window) {
272 DCHECK([_observers empty]); 306 DCHECK([_observers empty]);
273 // Restore the session and reset the session metrics (as the event have 307 // Restore the session and reset the session metrics (as the event have
274 // not been generated by the user but by a cold start cycle). 308 // not been generated by the user but by a cold start cycle).
275 [self restoreSessionWindow:window persistState:NO]; 309 [self restoreSessionWindow:window persistState:NO];
276 [self resetSessionMetrics]; 310 [self resetSessionMetrics];
277 } 311 }
278 312
279 _orderController.reset( 313 _orderController.reset(
280 [[TabModelOrderController alloc] initWithTabModel:self]); 314 [[TabModelOrderController alloc] initWithTabModel:self]);
(...skipping 28 matching lines...) Expand all
309 return nil; 343 return nil;
310 } 344 }
311 345
312 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window { 346 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window {
313 return [self restoreSessionWindow:window persistState:YES]; 347 return [self restoreSessionWindow:window persistState:YES];
314 } 348 }
315 349
316 - (void)saveSessionImmediately:(BOOL)immediately { 350 - (void)saveSessionImmediately:(BOOL)immediately {
317 // Do nothing if there are tabs in the model but no selected tab. This is 351 // Do nothing if there are tabs in the model but no selected tab. This is
318 // a transitional state. 352 // a transitional state.
319 if ((!_currentTab && [_tabs count]) || !_browserState) 353 if ((!_currentTab && _webStateList.count()) || !_browserState)
320 return; 354 return;
321 [_sessionService saveWindow:self.windowForSavingSession 355 [_sessionService saveWindow:self.windowForSavingSession
322 forBrowserState:_browserState 356 forBrowserState:_browserState
323 immediately:immediately]; 357 immediately:immediately];
324 } 358 }
325 359
326 - (Tab*)tabAtIndex:(NSUInteger)index { 360 - (Tab*)tabAtIndex:(NSUInteger)index {
327 return [_tabs objectAtIndex:index]; 361 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
362 return LegacyTabHelper::GetTabForWebState(
363 _webStateList.GetWebStateAt(static_cast<int>(index)));
328 } 364 }
329 365
330 - (NSUInteger)indexOfTab:(Tab*)tab { 366 - (NSUInteger)indexOfTab:(Tab*)tab {
331 return [_tabs indexOfObject:tab]; 367 int index = _webStateList.GetIndexOfWebState(tab.webState);
368 if (index == WebStateList::kInvalidIndex)
369 return NSNotFound;
370
371 DCHECK_GE(index, 0);
372 return static_cast<NSUInteger>(index);
332 } 373 }
333 374
334 - (Tab*)tabWithWindowName:(NSString*)windowName { 375 - (Tab*)tabWithWindowName:(NSString*)windowName {
335 if (!windowName) 376 if (!windowName)
336 return nil; 377 return nil;
337 for (Tab* tab in _tabs.get()) { 378 for (Tab* tab in self) {
338 if ([windowName isEqualToString:tab.windowName]) { 379 if ([windowName isEqualToString:tab.windowName]) {
339 return tab; 380 return tab;
340 } 381 }
341 } 382 }
342 return nil; 383 return nil;
343 } 384 }
344 385
345 - (Tab*)nextTabWithOpener:(Tab*)tab afterTab:(Tab*)afterTab { 386 - (Tab*)nextTabWithOpener:(Tab*)tab afterTab:(Tab*)afterTab {
346 NSUInteger startIndex = NSNotFound; 387 NSUInteger startIndex = NSNotFound;
347 // Start looking after |afterTab|. If it's not found, start looking after 388 // Start looking after |afterTab|. If it's not found, start looking after
348 // |tab|. If it's not found either, bail. 389 // |tab|. If it's not found either, bail.
349 if (afterTab) 390 if (afterTab)
350 startIndex = [self indexOfTab:afterTab]; 391 startIndex = [self indexOfTab:afterTab];
351 if (startIndex == NSNotFound) 392 if (startIndex == NSNotFound)
352 startIndex = [self indexOfTab:tab]; 393 startIndex = [self indexOfTab:tab];
353 if (startIndex == NSNotFound) 394 if (startIndex == NSNotFound)
354 return nil; 395 return nil;
355 NSString* parentID = tab.tabId; 396 NSString* parentID = tab.tabId;
356 for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) { 397 for (NSUInteger i = startIndex + 1; i < self.count; ++i) {
357 Tab* current = [_tabs objectAtIndex:i]; 398 Tab* current = [self tabAtIndex:i];
358 DCHECK([current navigationManager]); 399 DCHECK([current navigationManager]);
359 CRWSessionController* sessionController = 400 CRWSessionController* sessionController =
360 [current navigationManager]->GetSessionController(); 401 [current navigationManager]->GetSessionController();
361 if ([sessionController.openerId isEqualToString:parentID]) 402 if ([sessionController.openerId isEqualToString:parentID])
362 return current; 403 return current;
363 } 404 }
364 return nil; 405 return nil;
365 } 406 }
366 407
367 - (Tab*)lastTabWithOpener:(Tab*)tab { 408 - (Tab*)lastTabWithOpener:(Tab*)tab {
368 NSUInteger startIndex = [self indexOfTab:tab]; 409 NSUInteger startIndex = [self indexOfTab:tab];
369 if (startIndex == NSNotFound) 410 if (startIndex == NSNotFound)
370 return nil; 411 return nil;
371 // There is at least one tab in the model, because otherwise the above check 412 // There is at least one tab in the model, because otherwise the above check
372 // would have returned. 413 // would have returned.
373 NSString* parentID = tab.tabId; 414 NSString* parentID = tab.tabId;
374 DCHECK([tab navigationManager]); 415 DCHECK([tab navigationManager]);
375 NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex(); 416 NSInteger parentNavIndex = [tab navigationManager]->GetCurrentItemIndex();
376 417
377 Tab* match = nil; 418 Tab* match = nil;
378 // Find the last tab in the first matching 'group'. A 'group' is a set of 419 // Find the last tab in the first matching 'group'. A 'group' is a set of
379 // tabs whose opener's id and opener's navigation index match. The navigation 420 // tabs whose opener's id and opener's navigation index match. The navigation
380 // index is used in addition to the session id to detect navigations changes 421 // index is used in addition to the session id to detect navigations changes
381 // within the same session. 422 // within the same session.
382 for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) { 423 for (NSUInteger i = startIndex + 1; i < self.count; ++i) {
383 Tab* tabToCheck = [_tabs objectAtIndex:i]; 424 Tab* tabToCheck = [self tabAtIndex:i];
384 DCHECK([tabToCheck navigationManager]); 425 DCHECK([tabToCheck navigationManager]);
385 CRWSessionController* sessionController = 426 CRWSessionController* sessionController =
386 [tabToCheck navigationManager]->GetSessionController(); 427 [tabToCheck navigationManager]->GetSessionController();
387 if ([sessionController.openerId isEqualToString:parentID] && 428 if ([sessionController.openerId isEqualToString:parentID] &&
388 sessionController.openerNavigationIndex == parentNavIndex) { 429 sessionController.openerNavigationIndex == parentNavIndex) {
389 match = tabToCheck; 430 match = tabToCheck;
390 } else if (match) { 431 } else if (match) {
391 break; 432 break;
392 } 433 }
393 } 434 }
394 return match; 435 return match;
395 } 436 }
396 437
397 - (Tab*)openerOfTab:(Tab*)tab { 438 - (Tab*)openerOfTab:(Tab*)tab {
398 if (![tab navigationManager]) 439 if (![tab navigationManager])
399 return nil; 440 return nil;
400 NSString* openerId = [tab navigationManager]->GetSessionController().openerId; 441 NSString* openerId = [tab navigationManager]->GetSessionController().openerId;
401 if (!openerId.length) // Short-circuit if opener is empty. 442 if (!openerId.length) // Short-circuit if opener is empty.
402 return nil; 443 return nil;
403 for (Tab* iteratedTab in _tabs.get()) { 444 for (Tab* iteratedTab in self) {
404 if ([iteratedTab.tabId isEqualToString:openerId]) 445 if ([iteratedTab.tabId isEqualToString:openerId])
405 return iteratedTab; 446 return iteratedTab;
406 } 447 }
407 return nil; 448 return nil;
408 } 449 }
409 450
410 - (Tab*)insertOrUpdateTabWithURL:(const GURL&)URL 451 - (Tab*)insertOrUpdateTabWithURL:(const GURL&)URL
411 referrer:(const web::Referrer&)referrer 452 referrer:(const web::Referrer&)referrer
412 transition:(ui::PageTransition)transition 453 transition:(ui::PageTransition)transition
413 windowName:(NSString*)windowName 454 windowName:(NSString*)windowName
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 DCHECK_EQ(webState->GetBrowserState(), _browserState); 527 DCHECK_EQ(webState->GetBrowserState(), _browserState);
487 base::scoped_nsobject<Tab> tab( 528 base::scoped_nsobject<Tab> tab(
488 [[Tab alloc] initWithWebState:std::move(webState) model:self]); 529 [[Tab alloc] initWithWebState:std::move(webState) model:self]);
489 [tab webController].webUsageEnabled = webUsageEnabled_; 530 [tab webController].webUsageEnabled = webUsageEnabled_;
490 [self insertTab:tab atIndex:index]; 531 [self insertTab:tab atIndex:index];
491 return tab; 532 return tab;
492 } 533 }
493 534
494 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { 535 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index {
495 DCHECK(tab); 536 DCHECK(tab);
496 DCHECK(index <= [_tabs count]); 537 DCHECK(![_tabRetainer containsObject:tab]);
538 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
497 [tab fetchFavicon]; 539 [tab fetchFavicon];
498 [_tabs insertObject:tab atIndex:index];
499 540
541 [_tabRetainer addObject:tab];
542 _webStateList.InsertWebState(static_cast<int>(index), tab.webState);
500 TabParentingGlobalObserver::GetInstance()->OnTabParented(tab.webState); 543 TabParentingGlobalObserver::GetInstance()->OnTabParented(tab.webState);
501 [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO]; 544 [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO];
502 [_observers tabModelDidChangeTabCount:self]; 545 [_observers tabModelDidChangeTabCount:self];
503 546
504 base::RecordAction(base::UserMetricsAction("MobileNewTabOpened")); 547 base::RecordAction(base::UserMetricsAction("MobileNewTabOpened"));
505 // Persist the session due to a new tab being inserted. If this is a 548 // Persist the session due to a new tab being inserted. If this is a
506 // background tab (will not become active), saving now will capture the 549 // background tab (will not become active), saving now will capture the
507 // state properly. If it does eventually become active, another save will 550 // state properly. If it does eventually become active, another save will
508 // be triggered to properly capture the end result. 551 // be triggered to properly capture the end result.
509 [self saveSessionImmediately:NO]; 552 [self saveSessionImmediately:NO];
553
510 ++_newTabCount; 554 ++_newTabCount;
511 } 555 }
512 556
513 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { 557 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex {
514 NSUInteger fromIndex = [self indexOfTab:tab]; 558 if ([self tabAtIndex:toIndex] == tab)
515 DCHECK_NE(NSNotFound, static_cast<NSInteger>(fromIndex));
516 DCHECK_LT(toIndex, self.count);
517 if (fromIndex == NSNotFound || toIndex >= self.count ||
518 fromIndex == toIndex) {
519 return; 559 return;
520 }
521 560
522 base::scoped_nsobject<Tab> tabSaver([tab retain]); 561 DCHECK([_tabRetainer containsObject:tab]);
523 [_tabs removeObject:tab]; 562 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX));
524 [_tabs insertObject:tab atIndex:toIndex]; 563 int fromIndex = _webStateList.GetIndexOfWebState(tab.webState);
525 564 _webStateList.MoveWebStateAt(fromIndex, static_cast<int>(toIndex));
526 [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex]; 565 [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex];
527 } 566 }
528 567
529 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { 568 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab {
530 NSUInteger index = [self indexOfTab:oldTab]; 569 DCHECK([_tabRetainer containsObject:oldTab]);
531 DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); 570 DCHECK(![_tabRetainer containsObject:newTab]);
571
572 int index = _webStateList.GetIndexOfWebState(oldTab.webState);
573 DCHECK_NE(index, WebStateList::kInvalidIndex);
574 DCHECK_GE(index, 0);
532 575
533 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); 576 base::scoped_nsobject<Tab> tabSaver([oldTab retain]);
534 [newTab fetchFavicon]; 577 [newTab fetchFavicon];
535 [_tabs replaceObjectAtIndex:index withObject:newTab]; 578 [_tabRetainer removeObject:oldTab];
579 [_tabRetainer addObject:newTab];
536 [newTab setParentTabModel:self]; 580 [newTab setParentTabModel:self];
537 581
582 _webStateList.ReplaceWebStateAt(index, newTab.webState);
538 TabParentingGlobalObserver::GetInstance()->OnTabParented(newTab.webState); 583 TabParentingGlobalObserver::GetInstance()->OnTabParented(newTab.webState);
539 [_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index]; 584 [_observers tabModel:self
585 didReplaceTab:oldTab
586 withTab:newTab
587 atIndex:static_cast<NSUInteger>(index)];
540 588
541 if (self.currentTab == oldTab) 589 if (self.currentTab == oldTab)
542 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; 590 [self changeSelectedTabFrom:nil to:newTab persistState:NO];
543 591
544 [oldTab setParentTabModel:nil]; 592 [oldTab setParentTabModel:nil];
545 [oldTab close]; 593 [oldTab close];
546 594
547 // Record a tab clobber, since swapping tabs bypasses the tab code that would 595 // Record a tab clobber, since swapping tabs bypasses the tab code that would
548 // normally log clobbers. 596 // normally log clobbers.
549 base::RecordAction(base::UserMetricsAction("MobileTabClobbered")); 597 base::RecordAction(base::UserMetricsAction("MobileTabClobbered"));
550 } 598 }
551 599
552 - (void)closeTabAtIndex:(NSUInteger)index { 600 - (void)closeTabAtIndex:(NSUInteger)index {
553 DCHECK(index < [_tabs count]); 601 DCHECK(index < self.count);
554 [self closeTab:[_tabs objectAtIndex:index]]; 602 [self closeTab:[self tabAtIndex:index]];
555 } 603 }
556 604
557 - (void)closeTab:(Tab*)tab { 605 - (void)closeTab:(Tab*)tab {
558 // Ensure the tab stays alive long enough for us to send out the 606 // Ensure the tab stays alive long enough for us to send out the
559 // notice of its destruction to the delegate. 607 // notice of its destruction to the delegate.
560 [_observers tabModel:self willRemoveTab:tab]; 608 [_observers tabModel:self willRemoveTab:tab];
561 [tab close]; // Note it is not safe to access the tab after 'close'. 609 [tab close]; // Note it is not safe to access the tab after 'close'.
562 } 610 }
563 611
564 - (void)closeAllTabs { 612 - (void)closeAllTabs {
565 // If this changes, _closedTabCount metrics need to be adjusted. 613 // If this changes, _closedTabCount metrics need to be adjusted.
566 for (NSInteger i = self.count - 1; i >= 0; --i) 614 for (NSInteger i = self.count - 1; i >= 0; --i)
567 [self closeTabAtIndex:i]; 615 [self closeTabAtIndex:i];
568 [[NSNotificationCenter defaultCenter] 616 [[NSNotificationCenter defaultCenter]
569 postNotificationName:kTabModelAllTabsDidCloseNotification 617 postNotificationName:kTabModelAllTabsDidCloseNotification
570 object:self]; 618 object:self];
571 } 619 }
572 620
573 - (void)haltAllTabs { 621 - (void)haltAllTabs {
574 for (Tab* tab in _tabs.get()) { 622 for (Tab* tab in self) {
575 [tab terminateNetworkActivity]; 623 [tab terminateNetworkActivity];
576 } 624 }
577 } 625 }
578 626
579 - (void)notifyTabChanged:(Tab*)tab { 627 - (void)notifyTabChanged:(Tab*)tab {
580 [_observers tabModel:self didChangeTab:tab]; 628 [_observers tabModel:self didChangeTab:tab];
581 } 629 }
582 630
583 - (void)addObserver:(id<TabModelObserver>)observer { 631 - (void)addObserver:(id<TabModelObserver>)observer {
584 [_observers addObserver:observer]; 632 [_observers addObserver:observer];
(...skipping 16 matching lines...) Expand all
601 200, 50); 649 200, 50);
602 UMA_HISTOGRAM_CUSTOM_COUNTS("Session.NewTabCounts", _newTabCount, 1, 200, 50); 650 UMA_HISTOGRAM_CUSTOM_COUNTS("Session.NewTabCounts", _newTabCount, 1, 200, 50);
603 } 651 }
604 652
605 - (void)notifyTabSnapshotChanged:(Tab*)tab withImage:(UIImage*)image { 653 - (void)notifyTabSnapshotChanged:(Tab*)tab withImage:(UIImage*)image {
606 DCHECK([NSThread isMainThread]); 654 DCHECK([NSThread isMainThread]);
607 [_observers tabModel:self didChangeTabSnapshot:tab withImage:image]; 655 [_observers tabModel:self didChangeTabSnapshot:tab withImage:image];
608 } 656 }
609 657
610 - (void)resetAllWebViews { 658 - (void)resetAllWebViews {
611 for (Tab* tab in _tabs.get()) { 659 for (Tab* tab in self) {
612 [tab.webController reinitializeWebViewAndReload:(tab == _currentTab)]; 660 [tab.webController reinitializeWebViewAndReload:(tab == _currentTab)];
613 } 661 }
614 } 662 }
615 663
616 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled { 664 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled {
617 if (webUsageEnabled_ == webUsageEnabled) 665 if (webUsageEnabled_ == webUsageEnabled)
618 return; 666 return;
619 webUsageEnabled_ = webUsageEnabled; 667 webUsageEnabled_ = webUsageEnabled;
620 for (Tab* tab in _tabs.get()) { 668 for (Tab* tab in self) {
621 tab.webUsageEnabled = webUsageEnabled; 669 tab.webUsageEnabled = webUsageEnabled;
622 } 670 }
623 } 671 }
624 672
625 - (void)setPrimary:(BOOL)primary { 673 - (void)setPrimary:(BOOL)primary {
626 if (_tabUsageRecorder) 674 if (_tabUsageRecorder)
627 _tabUsageRecorder->RecordPrimaryTabModelChange(primary, _currentTab); 675 _tabUsageRecorder->RecordPrimaryTabModelChange(primary, _currentTab);
628 } 676 }
629 677
630 - (NSSet*)currentlyReferencedExternalFiles { 678 - (NSSet*)currentlyReferencedExternalFiles {
631 NSMutableSet* referencedFiles = [NSMutableSet set]; 679 NSMutableSet* referencedFiles = [NSMutableSet set];
632 if (!_browserState) 680 if (!_browserState)
633 return referencedFiles; 681 return referencedFiles;
634 // Check the currently open tabs for external files. 682 // Check the currently open tabs for external files.
635 for (Tab* tab in _tabs.get()) { 683 for (Tab* tab in self) {
636 if (UrlIsExternalFileReference(tab.url)) { 684 if (UrlIsExternalFileReference(tab.url)) {
637 NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName()); 685 NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName());
638 [referencedFiles addObject:fileName]; 686 [referencedFiles addObject:fileName];
639 } 687 }
640 } 688 }
641 // Do the same for the recently closed tabs. 689 // Do the same for the recently closed tabs.
642 sessions::TabRestoreService* restoreService = 690 sessions::TabRestoreService* restoreService =
643 IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState); 691 IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState);
644 DCHECK(restoreService); 692 DCHECK(restoreService);
645 for (const auto& entry : restoreService->entries()) { 693 for (const auto& entry : restoreService->entries()) {
(...skipping 16 matching lines...) Expand all
662 [[NSNotificationCenter defaultCenter] removeObserver:self]; 710 [[NSNotificationCenter defaultCenter] removeObserver:self];
663 if (_browserState) { 711 if (_browserState) {
664 UnregisterTabModelFromChromeBrowserState(_browserState, self); 712 UnregisterTabModelFromChromeBrowserState(_browserState, self);
665 } 713 }
666 _browserState = nullptr; 714 _browserState = nullptr;
667 } 715 }
668 716
669 // Called when a tab is closing, but before its CRWWebController is destroyed. 717 // Called when a tab is closing, but before its CRWWebController is destroyed.
670 // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel. 718 // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel.
671 - (void)didCloseTab:(Tab*)closedTab { 719 - (void)didCloseTab:(Tab*)closedTab {
672 NSUInteger closedTabIndex = [_tabs indexOfObject:closedTab];
673 DCHECK(closedTab); 720 DCHECK(closedTab);
674 DCHECK(closedTabIndex != NSNotFound); 721 DCHECK([_tabRetainer containsObject:closedTab]);
722 int closedTabIndex = _webStateList.GetIndexOfWebState(closedTab.webState);
723 DCHECK_NE(closedTabIndex, WebStateList::kInvalidIndex);
724 DCHECK_GE(closedTabIndex, 0);
725
675 // Let the sessions::TabRestoreService know about that new tab. 726 // Let the sessions::TabRestoreService know about that new tab.
676 sessions::TabRestoreService* restoreService = 727 sessions::TabRestoreService* restoreService =
677 _browserState 728 _browserState
678 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState) 729 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState)
679 : nullptr; 730 : nullptr;
680 web::NavigationManagerImpl* navigationManager = [closedTab navigationManager]; 731 web::NavigationManagerImpl* navigationManager = [closedTab navigationManager];
681 DCHECK(navigationManager); 732 DCHECK(navigationManager);
682 int itemCount = navigationManager->GetItemCount(); 733 int itemCount = navigationManager->GetItemCount();
683 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) { 734 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) {
684 restoreService->CreateHistoricalTab( 735 restoreService->CreateHistoricalTab(
685 sessions::IOSLiveTab::GetForWebState(closedTab.webState), 736 sessions::IOSLiveTab::GetForWebState(closedTab.webState),
686 static_cast<int>(closedTabIndex)); 737 closedTabIndex);
687 } 738 }
688 // This needs to be called before the tab is removed from the list. 739 // This needs to be called before the tab is removed from the list.
689 Tab* newSelection = 740 Tab* newSelection =
690 [_orderController determineNewSelectedTabFromRemovedTab:closedTab]; 741 [_orderController determineNewSelectedTabFromRemovedTab:closedTab];
742
691 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]); 743 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]);
692 [_tabs removeObject:closedTab];
693 744
694 // If closing the current tab, clear |_currentTab| before sending any 745 // If closing the current tab, clear |_currentTab| before sending any
695 // notification. This avoids various parts of the code getting confused 746 // notification. This avoids various parts of the code getting confused
696 // when the current tab isn't in the tab model. 747 // when the current tab isn't in the tab model.
697 Tab* savedCurrentTab = _currentTab; 748 Tab* savedCurrentTab = _currentTab;
698 if (closedTab == _currentTab) 749 if (closedTab == _currentTab)
699 _currentTab.reset(nil); 750 _currentTab.reset(nil);
700 751
701 [_observers tabModel:self didRemoveTab:closedTab atIndex:closedTabIndex]; 752 DCHECK([_tabRetainer containsObject:closedTab]);
753 [_tabRetainer removeObject:closedTab];
754
755 _webStateList.DetachWebStateAt(closedTabIndex);
756 [_observers tabModel:self
757 didRemoveTab:closedTab
758 atIndex:static_cast<NSUInteger>(closedTabIndex)];
702 [_observers tabModelDidChangeTabCount:self]; 759 [_observers tabModelDidChangeTabCount:self];
703 760
704 // Current tab has closed, update the selected tab and swap in its 761 // Current tab has closed, update the selected tab and swap in its
705 // contents. There is nothing to do if a non-selected tab is closed as 762 // contents. There is nothing to do if a non-selected tab is closed as
706 // the selection isn't index-based, therefore it hasn't changed. 763 // the selection isn't index-based, therefore it hasn't changed.
707 // -changeSelectedTabFrom: will persist the state change, so only do it 764 // -changeSelectedTabFrom: will persist the state change, so only do it
708 // if the selection isn't changing. 765 // if the selection isn't changing.
709 if (closedTab == savedCurrentTab) { 766 if (closedTab == savedCurrentTab) {
710 [self changeSelectedTabFrom:closedTab to:newSelection persistState:NO]; 767 [self changeSelectedTabFrom:closedTab to:newSelection persistState:NO];
711 } else { 768 } else {
(...skipping 26 matching lines...) Expand all
738 795
739 int tabCount = static_cast<int>(self.count); 796 int tabCount = static_cast<int>(self.count);
740 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tabCount, 1, 200, 50); 797 UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tabCount, 1, 200, 50);
741 } 798 }
742 799
743 #pragma mark - NSFastEnumeration 800 #pragma mark - NSFastEnumeration
744 801
745 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state 802 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
746 objects:(id*)objects 803 objects:(id*)objects
747 count:(NSUInteger)count { 804 count:(NSUInteger)count {
748 return [_tabs countByEnumeratingWithState:state objects:objects count:count]; 805 return [_fastEnumerationHelper countByEnumeratingWithState:state
806 objects:objects
807 count:count];
749 } 808 }
750 809
751 #pragma mark - TabUsageRecorderDelegate 810 #pragma mark - TabUsageRecorderDelegate
752 811
753 - (NSUInteger)liveTabsCount { 812 - (NSUInteger)liveTabsCount {
754 NSUInteger count = 0; 813 NSUInteger count = 0;
755 NSArray* tabs = _tabs.get(); 814 for (Tab* tab in self) {
756 for (Tab* tab in tabs) {
757 if ([tab.webController isViewAlive]) 815 if ([tab.webController isViewAlive])
758 count++; 816 count++;
759 } 817 }
760 return count; 818 return count;
761 } 819 }
762 820
763 #pragma mark - Private methods 821 #pragma mark - Private methods
764 822
765 - (SessionWindowIOS*)windowForSavingSession { 823 - (SessionWindowIOS*)windowForSavingSession {
766 // Background tabs will already have their state preserved, but not the 824 // Background tabs will already have their state preserved, but not the
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 975
918 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window 976 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window
919 persistState:(BOOL)persistState { 977 persistState:(BOOL)persistState {
920 DCHECK(_browserState); 978 DCHECK(_browserState);
921 DCHECK(window); 979 DCHECK(window);
922 980
923 NSArray* sessions = window.sessions; 981 NSArray* sessions = window.sessions;
924 if (!sessions.count) 982 if (!sessions.count)
925 return NO; 983 return NO;
926 984
927 size_t oldCount = [_tabs count]; 985 int oldCount = _webStateList.count();
986 DCHECK_GE(oldCount, 0);
987
928 web::WebState::CreateParams params(_browserState); 988 web::WebState::CreateParams params(_browserState);
929 scoped_refptr<web::CertificatePolicyCache> policyCache = 989 scoped_refptr<web::CertificatePolicyCache> policyCache =
930 web::BrowserState::GetCertificatePolicyCache(_browserState); 990 web::BrowserState::GetCertificatePolicyCache(_browserState);
931 991
932 for (CRWSessionStorage* session in sessions) { 992 for (CRWSessionStorage* session in sessions) {
933 std::unique_ptr<web::WebState> webState = 993 std::unique_ptr<web::WebState> webState =
934 web::WebState::Create(params, session); 994 web::WebState::Create(params, session);
935 DCHECK_EQ(webState->GetBrowserState(), _browserState); 995 DCHECK_EQ(webState->GetBrowserState(), _browserState);
936 Tab* tab = 996 Tab* tab =
937 [self insertTabWithWebState:std::move(webState) atIndex:[_tabs count]]; 997 [self insertTabWithWebState:std::move(webState) atIndex:self.count];
938 tab.webController.usePlaceholderOverlay = YES; 998 tab.webController.usePlaceholderOverlay = YES;
939 999
940 // Restore the CertificatePolicyCache (note that webState is invalid after 1000 // Restore the CertificatePolicyCache (note that webState is invalid after
941 // passing it via move semantic to -insertTabWithWebState:atIndex:). 1001 // passing it via move semantic to -insertTabWithWebState:atIndex:).
942 UpdateCertificatePolicyCacheFromWebState(policyCache, tab.webState); 1002 UpdateCertificatePolicyCacheFromWebState(policyCache, tab.webState);
943 } 1003 }
944 DCHECK_GT([_tabs count], oldCount); 1004 DCHECK_GT(_webStateList.count(), oldCount);
945 1005
946 // Update the selected tab if there was a selected Tab in the saved session. 1006 // Update the selected tab if there was a selected Tab in the saved session.
947 if (window.selectedIndex != NSNotFound) { 1007 if (window.selectedIndex != NSNotFound) {
948 NSUInteger selectedIndex = window.selectedIndex + oldCount; 1008 NSUInteger selectedIndex = window.selectedIndex + oldCount;
949 DCHECK_LT(selectedIndex, [_tabs count]); 1009 DCHECK_LT(selectedIndex, self.count);
950 DCHECK([self tabAtIndex:selectedIndex]); 1010 DCHECK([self tabAtIndex:selectedIndex]);
951 [self changeSelectedTabFrom:_currentTab 1011 [self changeSelectedTabFrom:_currentTab
952 to:[self tabAtIndex:selectedIndex] 1012 to:[self tabAtIndex:selectedIndex]
953 persistState:persistState]; 1013 persistState:persistState];
954 } 1014 }
955 1015
956 // If there was only one tab and it was the new tab page, clobber it. 1016 // If there was only one tab and it was the new tab page, clobber it.
957 BOOL closedNTPTab = NO; 1017 BOOL closedNTPTab = NO;
958 if (oldCount == 1) { 1018 if (oldCount == 1) {
959 Tab* tab = [_tabs objectAtIndex:0]; 1019 Tab* tab = [self tabAtIndex:0];
960 if (tab.url == GURL(kChromeUINewTabURL)) { 1020 if (tab.url == GURL(kChromeUINewTabURL)) {
961 [self closeTab:tab]; 1021 [self closeTab:tab];
962 closedNTPTab = YES; 1022 closedNTPTab = YES;
963 oldCount = 0; 1023 oldCount = 0;
964 } 1024 }
965 } 1025 }
966 if (_tabUsageRecorder) { 1026 if (_tabUsageRecorder) {
967 _tabUsageRecorder->InitialRestoredTabs( 1027 NSMutableArray<Tab*>* restoredTabs =
968 _currentTab, 1028 [NSMutableArray arrayWithCapacity:_webStateList.count() - oldCount];
969 [_tabs 1029 for (int index = oldCount; index < _webStateList.count(); ++index) {
970 subarrayWithRange:NSMakeRange(oldCount, [_tabs count] - oldCount)]); 1030 web::WebState* webState = _webStateList.GetWebStateAt(index);
1031 [restoredTabs addObject:LegacyTabHelper::GetTabForWebState(webState)];
1032 }
1033 _tabUsageRecorder->InitialRestoredTabs(_currentTab, restoredTabs);
971 } 1034 }
972 return closedNTPTab; 1035 return closedNTPTab;
973 } 1036 }
974 1037
975 #pragma mark - Notification Handlers 1038 #pragma mark - Notification Handlers
976 1039
977 // Called when UIApplicationWillResignActiveNotification is received. 1040 // Called when UIApplicationWillResignActiveNotification is received.
978 - (void)willResignActive:(NSNotification*)notify { 1041 - (void)willResignActive:(NSNotification*)notify {
979 if (webUsageEnabled_ && _currentTab) { 1042 if (webUsageEnabled_ && _currentTab) {
980 [[SnapshotCache sharedInstance] 1043 [[SnapshotCache sharedInstance]
981 willBeSavedGreyWhenBackgrounding:_currentTab.get().tabId]; 1044 willBeSavedGreyWhenBackgrounding:_currentTab.get().tabId];
982 } 1045 }
983 } 1046 }
984 1047
985 // Called when UIApplicationDidEnterBackgroundNotification is received. 1048 // Called when UIApplicationDidEnterBackgroundNotification is received.
986 - (void)applicationDidEnterBackground:(NSNotification*)notify { 1049 - (void)applicationDidEnterBackground:(NSNotification*)notify {
987 if (!_browserState) 1050 if (!_browserState)
988 return; 1051 return;
989 1052
990 // Evict all the certificate policies except for the current entries of the 1053 // Evict all the certificate policies except for the current entries of the
991 // active sessions. 1054 // active sessions.
992 CleanCertificatePolicyCache( 1055 CleanCertificatePolicyCache(
993 &_clearPoliciesTaskTracker, 1056 &_clearPoliciesTaskTracker,
994 web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), 1057 web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
995 web::BrowserState::GetCertificatePolicyCache(_browserState), self); 1058 web::BrowserState::GetCertificatePolicyCache(_browserState),
1059 &_webStateList);
996 1060
997 if (_tabUsageRecorder) 1061 if (_tabUsageRecorder)
998 _tabUsageRecorder->AppDidEnterBackground(); 1062 _tabUsageRecorder->AppDidEnterBackground();
999 1063
1000 // Normally, the session is saved after some timer expires but since the app 1064 // Normally, the session is saved after some timer expires but since the app
1001 // is about to enter the background send YES to save the session immediately. 1065 // is about to enter the background send YES to save the session immediately.
1002 [self saveSessionImmediately:YES]; 1066 [self saveSessionImmediately:YES];
1003 1067
1004 // Write out a grey version of the current website to disk. 1068 // Write out a grey version of the current website to disk.
1005 if (webUsageEnabled_ && _currentTab) { 1069 if (webUsageEnabled_ && _currentTab) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 web::NavigationManager::WebLoadParams params(URL); 1108 web::NavigationManager::WebLoadParams params(URL);
1045 params.referrer = referrer; 1109 params.referrer = referrer;
1046 params.transition_type = ui::PAGE_TRANSITION_TYPED; 1110 params.transition_type = ui::PAGE_TRANSITION_TYPED;
1047 [[tab webController] loadWithParams:params]; 1111 [[tab webController] loadWithParams:params];
1048 [tab webController].webUsageEnabled = webUsageEnabled_; 1112 [tab webController].webUsageEnabled = webUsageEnabled_;
1049 [self insertTab:tab atIndex:index]; 1113 [self insertTab:tab atIndex:index];
1050 return tab; 1114 return tab;
1051 } 1115 }
1052 1116
1053 @end 1117 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/tabs/BUILD.gn ('k') | ios/chrome/browser/tabs/tab_model_order_controller_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698