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

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

Issue 2775623002: [ios] WebStateList owns all WebState it manages. (Closed)
Patch Set: Remove Tab -willClose method (Tab implements CRWWebControllerObserver protocol). Created 3 years, 8 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 <cstdint>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #import "base/mac/foundation_util.h"
13 #import "base/mac/scoped_nsobject.h" 14 #import "base/mac/scoped_nsobject.h"
14 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.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 #import "ios/chrome/browser/metrics/tab_usage_recorder_web_state_list_observer.h " 27 #import "ios/chrome/browser/metrics/tab_usage_recorder_web_state_list_observer.h "
27 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" 28 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
28 #import "ios/chrome/browser/sessions/session_service.h" 29 #import "ios/chrome/browser/sessions/session_service.h"
29 #import "ios/chrome/browser/sessions/session_window_ios.h" 30 #import "ios/chrome/browser/sessions/session_window_ios.h"
30 #import "ios/chrome/browser/snapshots/snapshot_cache.h" 31 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
31 #import "ios/chrome/browser/snapshots/snapshot_cache_web_state_list_observer.h" 32 #import "ios/chrome/browser/snapshots/snapshot_cache_web_state_list_observer.h"
32 #include "ios/chrome/browser/tab_parenting_global_observer.h" 33 #include "ios/chrome/browser/tab_parenting_global_observer.h"
33 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" 34 #import "ios/chrome/browser/tabs/legacy_tab_helper.h"
34 #import "ios/chrome/browser/tabs/tab.h" 35 #import "ios/chrome/browser/tabs/tab.h"
36 #import "ios/chrome/browser/tabs/tab_model_closing_web_state_observer.h"
35 #import "ios/chrome/browser/tabs/tab_model_list.h" 37 #import "ios/chrome/browser/tabs/tab_model_list.h"
36 #import "ios/chrome/browser/tabs/tab_model_observers.h" 38 #import "ios/chrome/browser/tabs/tab_model_observers.h"
37 #import "ios/chrome/browser/tabs/tab_model_observers_bridge.h" 39 #import "ios/chrome/browser/tabs/tab_model_observers_bridge.h"
38 #import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h" 40 #import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h"
39 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" 41 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
40 #import "ios/chrome/browser/tabs/tab_model_web_state_list_delegate.h" 42 #import "ios/chrome/browser/tabs/tab_model_web_state_list_delegate.h"
41 #import "ios/chrome/browser/tabs/tab_parenting_observer.h" 43 #import "ios/chrome/browser/tabs/tab_parenting_observer.h"
42 #import "ios/chrome/browser/xcallback_parameters.h" 44 #import "ios/chrome/browser/xcallback_parameters.h"
43 #import "ios/shared/chrome/browser/tabs/web_state_list.h" 45 #import "ios/shared/chrome/browser/tabs/web_state_list.h"
44 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h " 46 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h "
45 #import "ios/shared/chrome/browser/tabs/web_state_list_metrics_observer.h" 47 #import "ios/shared/chrome/browser/tabs/web_state_list_metrics_observer.h"
46 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" 48 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h"
47 #import "ios/shared/chrome/browser/tabs/web_state_opener.h" 49 #import "ios/shared/chrome/browser/tabs/web_state_opener.h"
48 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" 50 #import "ios/web/navigation/crw_session_certificate_policy_manager.h"
49 #import "ios/web/navigation/crw_session_controller.h" 51 #import "ios/web/navigation/crw_session_controller.h"
50 #include "ios/web/public/browser_state.h" 52 #include "ios/web/public/browser_state.h"
51 #include "ios/web/public/certificate_policy_cache.h" 53 #include "ios/web/public/certificate_policy_cache.h"
52 #include "ios/web/public/navigation_item.h" 54 #include "ios/web/public/navigation_item.h"
53 #import "ios/web/public/navigation_manager.h" 55 #import "ios/web/public/navigation_manager.h"
56 #import "ios/web/public/serializable_user_data_manager.h"
54 #include "ios/web/public/web_thread.h" 57 #include "ios/web/public/web_thread.h"
55 #import "ios/web/web_state/ui/crw_web_controller.h" 58 #import "ios/web/web_state/ui/crw_web_controller.h"
56 #import "ios/web/web_state/web_state_impl.h" 59 #import "ios/web/web_state/web_state_impl.h"
57 #include "url/gurl.h" 60 #include "url/gurl.h"
58 61
59 NSString* const kTabModelTabWillStartLoadingNotification = 62 NSString* const kTabModelTabWillStartLoadingNotification =
60 @"kTabModelTabWillStartLoadingNotification"; 63 @"kTabModelTabWillStartLoadingNotification";
61 NSString* const kTabModelTabDidStartLoadingNotification = 64 NSString* const kTabModelTabDidStartLoadingNotification =
62 @"kTabModelTabDidStartLoadingNotification"; 65 @"kTabModelTabDidStartLoadingNotification";
63 NSString* const kTabModelTabDidFinishLoadingNotification = 66 NSString* const kTabModelTabDidFinishLoadingNotification =
64 @"kTabModelTabDidFinishLoadingNotification"; 67 @"kTabModelTabDidFinishLoadingNotification";
65 NSString* const kTabModelAllTabsDidCloseNotification = 68 NSString* const kTabModelAllTabsDidCloseNotification =
66 @"kTabModelAllTabsDidCloseNotification"; 69 @"kTabModelAllTabsDidCloseNotification";
67 NSString* const kTabModelTabDeselectedNotification = 70 NSString* const kTabModelTabDeselectedNotification =
68 @"kTabModelTabDeselectedNotification"; 71 @"kTabModelTabDeselectedNotification";
69 NSString* const kTabModelNewTabWillOpenNotification = 72 NSString* const kTabModelNewTabWillOpenNotification =
70 @"kTabModelNewTabWillOpenNotification"; 73 @"kTabModelNewTabWillOpenNotification";
71 NSString* const kTabModelTabKey = @"tab"; 74 NSString* const kTabModelTabKey = @"tab";
72 NSString* const kTabModelPageLoadSuccess = @"pageLoadSuccess"; 75 NSString* const kTabModelPageLoadSuccess = @"pageLoadSuccess";
73 NSString* const kTabModelOpenInBackgroundKey = @"shouldOpenInBackground"; 76 NSString* const kTabModelOpenInBackgroundKey = @"shouldOpenInBackground";
74 77
75 namespace { 78 namespace {
76 79
80 // The key under which the opener Tab ID is stored in the WebState's
81 // serializable user data.
82 NSString* const kOpenerIDKey = @"OpenerID";
83
84 // The key under which the opener navigation index is stored in the WebState's
85 // serializable user data.
86 NSString* const kOpenerNavigationIndexKey = @"OpenerNavigationIndex";
87
77 // Updates CRWSessionCertificatePolicyManager's certificate policy cache. 88 // Updates CRWSessionCertificatePolicyManager's certificate policy cache.
78 void UpdateCertificatePolicyCacheFromWebState( 89 void UpdateCertificatePolicyCacheFromWebState(
79 const scoped_refptr<web::CertificatePolicyCache>& policy_cache, 90 const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
80 web::WebState* web_state) { 91 web::WebState* web_state) {
81 DCHECK(web_state); 92 DCHECK(web_state);
82 DCHECK_CURRENTLY_ON(web::WebThread::UI); 93 DCHECK_CURRENTLY_ON(web::WebThread::UI);
83 // TODO(crbug.com/454984): Remove CRWSessionController usage once certificate 94 // TODO(crbug.com/454984): Remove CRWSessionController usage once certificate
84 // policy manager is moved to NavigationManager. 95 // policy manager is moved to NavigationManager.
85 CRWSessionController* controller = static_cast<web::WebStateImpl*>(web_state) 96 CRWSessionController* controller = static_cast<web::WebStateImpl*>(web_state)
86 ->GetNavigationManagerImpl() 97 ->GetNavigationManagerImpl()
(...skipping 28 matching lines...) Expand all
115 task_runner.get(), FROM_HERE, 126 task_runner.get(), FROM_HERE,
116 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies, 127 base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies,
117 policy_cache), 128 policy_cache),
118 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache, 129 base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache,
119 base::Unretained(web_state_list))); 130 base::Unretained(web_state_list)));
120 } 131 }
121 132
122 // Internal helper function returning the opener for a given Tab by 133 // Internal helper function returning the opener for a given Tab by
123 // checking the associated Tab tabId (should be removed once the opener 134 // checking the associated Tab tabId (should be removed once the opener
124 // is passed to the insertTab:atIndex: and replaceTab:withTab: methods). 135 // is passed to the insertTab:atIndex: and replaceTab:withTab: methods).
125 Tab* GetOpenerForTab(id<NSFastEnumeration> tabs, Tab* tab) { 136 WebStateOpener GetOpenerForTab(id<NSFastEnumeration> tabs, Tab* tab) {
126 if (!tab.openerID) 137 web::SerializableUserDataManager* user_data_manager =
127 return nullptr; 138 web::SerializableUserDataManager::FromWebState(tab.webState);
128 139
129 for (Tab* currentTab in tabs) { 140 NSString* opener_id = base::mac::ObjCCast<NSString>(
130 if ([tab.openerID isEqualToString:currentTab.tabId]) 141 user_data_manager->GetValueForSerializationKey(kOpenerIDKey));
131 return currentTab; 142 if (!opener_id || ![opener_id length])
143 return WebStateOpener(nullptr);
144
145 NSNumber* boxed_opener_navigation_index = base::mac::ObjCCast<NSNumber>(
146 user_data_manager->GetValueForSerializationKey(
147 kOpenerNavigationIndexKey));
148 if (!boxed_opener_navigation_index)
149 return WebStateOpener(nullptr);
150
151 for (Tab* current_tab in tabs) {
152 if ([opener_id isEqualToString:current_tab.tabId]) {
153 return WebStateOpener(current_tab.webState,
154 [boxed_opener_navigation_index intValue]);
155 }
132 } 156 }
133 157
134 return nullptr; 158 return WebStateOpener(nullptr);
135 } 159 }
136 160
137 } // anonymous namespace 161 } // anonymous namespace
138 162
139 @interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory> 163 @interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory>
140 @end 164 @end
141 165
142 @implementation TabModelWebStateProxyFactory 166 @implementation TabModelWebStateProxyFactory
143 167
144 - (id)proxyForWebState:(web::WebState*)webState { 168 - (id)proxyForWebState:(web::WebState*)webState {
145 return LegacyTabHelper::GetTabForWebState(webState); 169 return LegacyTabHelper::GetTabForWebState(webState);
146 } 170 }
147 171
148 @end 172 @end
149 173
150 @interface TabModel ()<TabUsageRecorderDelegate> { 174 @interface TabModel ()<TabUsageRecorderDelegate> {
151 // Delegate for the WebStateList. 175 // Delegate for the WebStateList.
152 std::unique_ptr<WebStateListDelegate> _webStateListDelegate; 176 std::unique_ptr<WebStateListDelegate> _webStateListDelegate;
153 177
154 // Underlying shared model implementation. 178 // Underlying shared model implementation.
155 std::unique_ptr<WebStateList> _webStateList; 179 std::unique_ptr<WebStateList> _webStateList;
156 180
157 // Helper providing NSFastEnumeration implementation over the WebStateList. 181 // Helper providing NSFastEnumeration implementation over the WebStateList.
158 base::scoped_nsobject<WebStateListFastEnumerationHelper> 182 base::scoped_nsobject<WebStateListFastEnumerationHelper>
159 _fastEnumerationHelper; 183 _fastEnumerationHelper;
160 184
161 // Used to keep the Tabs alive while the corresponding WebStates are stored
162 // in the WebStateList (as Tabs currently own their WebState). Remove once
163 // WebState owns the associated Tab.
164 base::scoped_nsobject<NSMutableSet<Tab*>> _tabRetainer;
165
166 // WebStateListObservers reacting to modifications of the model (may send 185 // WebStateListObservers reacting to modifications of the model (may send
167 // notification, translate and forward events, update metrics, ...). 186 // notification, translate and forward events, update metrics, ...).
168 std::vector<std::unique_ptr<WebStateListObserver>> _webStateListObservers; 187 std::vector<std::unique_ptr<WebStateListObserver>> _webStateListObservers;
169 188
170 // The delegate for sync. 189 // The delegate for sync.
171 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; 190 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate;
172 191
173 // Counters for metrics. 192 // Counters for metrics.
174 WebStateListMetricsObserver* _webStateListMetricsObserver; 193 WebStateListMetricsObserver* _webStateListMetricsObserver;
175 194
176 // Backs up property with the same name. 195 // Backs up property with the same name.
177 std::unique_ptr<TabUsageRecorder> _tabUsageRecorder; 196 std::unique_ptr<TabUsageRecorder> _tabUsageRecorder;
178 // Backs up property with the same name. 197 // Backs up property with the same name.
179 const SessionID _sessionID; 198 const SessionID _sessionID;
180 // Saves session's state. 199 // Saves session's state.
181 base::scoped_nsobject<SessionServiceIOS> _sessionService; 200 base::scoped_nsobject<SessionServiceIOS> _sessionService;
182 // List of TabModelObservers. 201 // List of TabModelObservers.
183 base::scoped_nsobject<TabModelObservers> _observers; 202 base::scoped_nsobject<TabModelObservers> _observers;
184 203
185 // Used to ensure thread-safety of the certificate policy management code. 204 // Used to ensure thread-safety of the certificate policy management code.
186 base::CancelableTaskTracker _clearPoliciesTaskTracker; 205 base::CancelableTaskTracker _clearPoliciesTaskTracker;
187 } 206 }
188 207
189 // Session window for the contents of the tab model. 208 // Session window for the contents of the tab model.
190 @property(nonatomic, readonly) SessionWindowIOS* windowForSavingSession; 209 @property(nonatomic, readonly) SessionWindowIOS* windowForSavingSession;
191 210
192 // Returns YES if tab URL host indicates that tab is an NTP tab.
193 - (BOOL)isNTPTab:(Tab*)tab;
194
195 // Helper method that posts a notification with the given name with |tab| 211 // Helper method that posts a notification with the given name with |tab|
196 // in the userInfo dictionary under the kTabModelTabKey. 212 // in the userInfo dictionary under the kTabModelTabKey.
197 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab; 213 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab;
198 214
199 // Helper method to restore a saved session and control if the state should 215 // Helper method to restore a saved session and control if the state should
200 // be persisted or not. Used to implement the public -restoreSessionWindow: 216 // be persisted or not. Used to implement the public -restoreSessionWindow:
201 // method and restoring session in the initialiser. 217 // method and restoring session in the initialiser.
202 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window 218 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window
203 persistState:(BOOL)persistState; 219 persistState:(BOOL)persistState;
204 220
205 // Helper method to insert |tab| at the given |index| recording |parentTab| as
206 // the opener. Broadcasts the proper notifications about the change. The
207 // receiver should be set as the parentTabModel for |tab|; this method doesn't
208 // check that.
209 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index opener:(Tab*)parentTab;
210
211 // Helper method to insert |tab| at the given |index| recording |parentTab| as
212 // the opener. Broadcasts the proper notifications about the change. The
213 // receiver should be set as the parentTabModel for |tab|; this method doesn't
214 // check that.
215 - (void)insertTab:(Tab*)tab
216 atIndex:(NSUInteger)index
217 opener:(Tab*)parentTab
218 transition:(ui::PageTransition)transition;
219
220 @end 221 @end
221 222
222 @implementation TabModel 223 @implementation TabModel
223 224
224 @synthesize browserState = _browserState; 225 @synthesize browserState = _browserState;
225 @synthesize sessionID = _sessionID; 226 @synthesize sessionID = _sessionID;
226 @synthesize webUsageEnabled = webUsageEnabled_; 227 @synthesize webUsageEnabled = webUsageEnabled_;
227 228
228 #pragma mark - Overriden 229 #pragma mark - Overriden
229 230
230 - (void)dealloc { 231 - (void)dealloc {
231 DCHECK([_observers empty]); 232 DCHECK([_observers empty]);
232 // browserStateDestroyed should always have been called before destruction. 233 // browserStateDestroyed should always have been called before destruction.
233 DCHECK(!_browserState); 234 DCHECK(!_browserState);
234 235
235 [[NSNotificationCenter defaultCenter] removeObserver:self]; 236 [[NSNotificationCenter defaultCenter] removeObserver:self];
236 237
237 // Clear weak pointer to WebStateListMetricsObserver before destroying it. 238 // Clear weak pointer to WebStateListMetricsObserver before destroying it.
238 _webStateListMetricsObserver = nullptr; 239 _webStateListMetricsObserver = nullptr;
239 240
240 // Unregister all observers before closing all the tabs.
241 for (const auto& webStateListObserver : _webStateListObservers)
242 _webStateList->RemoveObserver(webStateListObserver.get());
243 _webStateListObservers.clear();
244
245 // Make sure the tabs do clean after themselves. It is important for 241 // Make sure the tabs do clean after themselves. It is important for
246 // removeObserver: to be called first otherwise a lot of unecessary work will 242 // removeObserver: to be called first otherwise a lot of unecessary work will
rohitrao (ping after 24h) 2017/04/03 17:49:35 This removeObserver comment might be stale now? W
sdefresne 2017/04/04 13:47:56 The comment says that all observer registered with
247 // happen on -closeAllTabs. 243 // happen on -closeAllTabs.
248 [self closeAllTabs]; 244 [self closeAllTabs];
249 245
246 // Unregister all observers after closing all the tabs as some of them are
rohitrao (ping after 24h) 2017/04/03 17:49:35 We used to do this before closing all tabs. Do yo
sdefresne 2017/04/04 13:47:56 As _observers is empty (i.e. there are no TabModel
247 // required to properly clean up the Tabs.
248 for (const auto& webStateListObserver : _webStateListObservers)
249 _webStateList->RemoveObserver(webStateListObserver.get());
250 _webStateListObservers.clear();
251
250 _clearPoliciesTaskTracker.TryCancelAll(); 252 _clearPoliciesTaskTracker.TryCancelAll();
251 253
252 [super dealloc]; 254 [super dealloc];
253 } 255 }
254 256
255 #pragma mark - Public methods 257 #pragma mark - Public methods
256 258
257 - (Tab*)currentTab { 259 - (Tab*)currentTab {
258 web::WebState* webState = _webStateList->GetActiveWebState(); 260 web::WebState* webState = _webStateList->GetActiveWebState();
259 return webState ? LegacyTabHelper::GetTabForWebState(webState) : nil; 261 return webState ? LegacyTabHelper::GetTabForWebState(webState) : nil;
(...skipping 27 matching lines...) Expand all
287 } 289 }
288 290
289 - (WebStateList*)webStateList { 291 - (WebStateList*)webStateList {
290 return _webStateList.get(); 292 return _webStateList.get();
291 } 293 }
292 294
293 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window 295 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window
294 sessionService:(SessionServiceIOS*)service 296 sessionService:(SessionServiceIOS*)service
295 browserState:(ios::ChromeBrowserState*)browserState { 297 browserState:(ios::ChromeBrowserState*)browserState {
296 if ((self = [super init])) { 298 if ((self = [super init])) {
297 _tabRetainer.reset([[NSMutableSet alloc] init]);
298 _observers.reset([[TabModelObservers observers] retain]); 299 _observers.reset([[TabModelObservers observers] retain]);
299 300
300 _webStateListDelegate = 301 _webStateListDelegate =
301 base::MakeUnique<TabModelWebStateListDelegate>(self); 302 base::MakeUnique<TabModelWebStateListDelegate>(self);
302 _webStateList = base::MakeUnique<WebStateList>( 303 _webStateList = base::MakeUnique<WebStateList>(_webStateListDelegate.get());
303 _webStateListDelegate.get(), WebStateList::WebStateBorrowed);
304 304
305 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc] 305 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc]
306 initWithWebStateList:_webStateList.get() 306 initWithWebStateList:_webStateList.get()
307 proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]); 307 proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]);
308 308
309 _browserState = browserState; 309 _browserState = browserState;
310 DCHECK(_browserState); 310 DCHECK(_browserState);
311 311
312 // Normal browser states are the only ones to get tab restore. Tab sync 312 // Normal browser states are the only ones to get tab restore. Tab sync
313 // handles incognito browser states by filtering on profile, so it's 313 // handles incognito browser states by filtering on profile, so it's
314 // important to the backend code to always have a sync window delegate. 314 // important to the backend code to always have a sync window delegate.
315 if (!_browserState->IsOffTheRecord()) { 315 if (!_browserState->IsOffTheRecord()) {
316 // Set up the usage recorder before tabs are created. 316 // Set up the usage recorder before tabs are created.
317 _tabUsageRecorder = base::MakeUnique<TabUsageRecorder>(self); 317 _tabUsageRecorder = base::MakeUnique<TabUsageRecorder>(self);
318 } 318 }
319 _syncedWindowDelegate = 319 _syncedWindowDelegate =
320 base::MakeUnique<TabModelSyncedWindowDelegate>(self); 320 base::MakeUnique<TabModelSyncedWindowDelegate>(self);
321 321
322 // There must be a valid session service defined to consume session windows. 322 // There must be a valid session service defined to consume session windows.
323 DCHECK(service); 323 DCHECK(service);
324 _sessionService.reset([service retain]); 324 _sessionService.reset([service retain]);
325 325
326 _webStateListObservers.push_back(base::MakeUnique<
327 WebStateListObserverBridge>([
328 [TabModelClosingWebStateObserver alloc]
329 initWithTabModel:self
330 restoreService:IOSChromeTabRestoreServiceFactory::GetForBrowserState(
331 _browserState)]));
326 _webStateListObservers.push_back( 332 _webStateListObservers.push_back(
327 base::MakeUnique<SnapshotCacheWebStateListObserver>( 333 base::MakeUnique<SnapshotCacheWebStateListObserver>(
328 [SnapshotCache sharedInstance])); 334 [SnapshotCache sharedInstance]));
329 if (_tabUsageRecorder) { 335 if (_tabUsageRecorder) {
330 _webStateListObservers.push_back( 336 _webStateListObservers.push_back(
331 base::MakeUnique<TabUsageRecorderWebStateListObserver>( 337 base::MakeUnique<TabUsageRecorderWebStateListObserver>(
332 _tabUsageRecorder.get())); 338 _tabUsageRecorder.get()));
333 } 339 }
334 _webStateListObservers.push_back(base::MakeUnique<TabParentingObserver>()); 340 _webStateListObservers.push_back(base::MakeUnique<TabParentingObserver>());
335 _webStateListObservers.push_back( 341 _webStateListObservers.push_back(
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 params.referrer = referrer; 474 params.referrer = referrer;
469 params.transition_type = transition; 475 params.transition_type = transition;
470 return [self insertTabWithLoadParams:params 476 return [self insertTabWithLoadParams:params
471 opener:parentTab 477 opener:parentTab
472 openedByDOM:openedByDOM 478 openedByDOM:openedByDOM
473 atIndex:index 479 atIndex:index
474 inBackground:inBackground]; 480 inBackground:inBackground];
475 } 481 }
476 482
477 - (Tab*)insertTabWithLoadParams: 483 - (Tab*)insertTabWithLoadParams:
478 (const web::NavigationManager::WebLoadParams&)params 484 (const web::NavigationManager::WebLoadParams&)loadParams
479 opener:(Tab*)parentTab 485 opener:(Tab*)parentTab
480 openedByDOM:(BOOL)openedByDOM 486 openedByDOM:(BOOL)openedByDOM
481 atIndex:(NSUInteger)index 487 atIndex:(NSUInteger)index
482 inBackground:(BOOL)inBackground { 488 inBackground:(BOOL)inBackground {
483 DCHECK(_browserState); 489 DCHECK(_browserState);
484 base::scoped_nsobject<Tab> tab([[Tab alloc] initWithBrowserState:_browserState 490
485 opener:parentTab 491 web::WebState::CreateParams createParams(self.browserState);
486 openedByDOM:openedByDOM 492 createParams.created_with_opener = openedByDOM;
487 model:self]); 493 std::unique_ptr<web::WebState> webState = web::WebState::Create(createParams);
494
495 web::WebState* webStatePtr = webState.get();
496 if (index == TabModelConstants::kTabPositionAutomatically) {
497 _webStateList->AppendWebState(loadParams.transition_type,
498 std::move(webState),
499 WebStateOpener(parentTab.webState));
500 } else {
501 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
502 const int insertion_index = static_cast<int>(index);
503 _webStateList->InsertWebState(insertion_index, std::move(webState));
504 if (parentTab.webState) {
505 _webStateList->SetOpenerOfWebStateAt(insertion_index,
506 WebStateOpener(parentTab.webState));
507 }
508 }
509
510 Tab* tab = LegacyTabHelper::GetTabForWebState(webStatePtr);
511 DCHECK(tab);
512
488 [tab webController].webUsageEnabled = webUsageEnabled_; 513 [tab webController].webUsageEnabled = webUsageEnabled_;
489 514
490 [self insertTab:tab
491 atIndex:index
492 opener:parentTab
493 transition:params.transition_type];
494
495 if (!inBackground && _tabUsageRecorder) 515 if (!inBackground && _tabUsageRecorder)
496 _tabUsageRecorder->TabCreatedForSelection(tab); 516 _tabUsageRecorder->TabCreatedForSelection(tab);
497 517
498 [[tab webController] loadWithParams:params]; 518 [[tab webController] loadWithParams:loadParams];
519
499 // Force the page to start loading even if it's in the background. 520 // Force the page to start loading even if it's in the background.
500 if (webUsageEnabled_) 521 if (webUsageEnabled_)
501 [[tab webController] triggerPendingLoad]; 522 [[tab webController] triggerPendingLoad];
502 NSDictionary* userInfo = @{ 523 NSDictionary* userInfo = @{
503 kTabModelTabKey : tab, 524 kTabModelTabKey : tab,
504 kTabModelOpenInBackgroundKey : @(inBackground), 525 kTabModelOpenInBackgroundKey : @(inBackground),
505 }; 526 };
506 [[NSNotificationCenter defaultCenter] 527 [[NSNotificationCenter defaultCenter]
507 postNotificationName:kTabModelNewTabWillOpenNotification 528 postNotificationName:kTabModelNewTabWillOpenNotification
508 object:self 529 object:self
509 userInfo:userInfo]; 530 userInfo:userInfo];
510 531
511 if (!inBackground) 532 if (!inBackground)
512 [self setCurrentTab:tab]; 533 [self setCurrentTab:tab];
513 534
514 return tab; 535 return tab;
515 } 536 }
516 537
517 - (Tab*)insertTabWithWebState:(std::unique_ptr<web::WebState>)webState
518 atIndex:(NSUInteger)index {
519 DCHECK(_browserState);
520 DCHECK_EQ(webState->GetBrowserState(), _browserState);
521 base::scoped_nsobject<Tab> tab(
522 [[Tab alloc] initWithWebState:std::move(webState) model:self]);
523 [tab webController].webUsageEnabled = webUsageEnabled_;
524 [self insertTab:tab atIndex:index];
525 return tab;
526 }
527
528 - (void)insertTab:(Tab*)tab
529 atIndex:(NSUInteger)index
530 opener:(Tab*)parentTab
531 transition:(ui::PageTransition)transition {
532 DCHECK(tab);
533 DCHECK(![_tabRetainer containsObject:tab]);
534
535 [_tabRetainer addObject:tab];
536 if (index == TabModelConstants::kTabPositionAutomatically) {
537 _webStateList->AppendWebState(
538 transition, tab.webState,
539 WebStateOpener(parentTab.webState, tab.openerNavigationIndex));
540 } else {
541 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
542 const int insertion_index = static_cast<int>(index);
543 _webStateList->InsertWebState(insertion_index, tab.webState);
544 if (parentTab.webState) {
545 _webStateList->SetOpenerOfWebStateAt(
546 insertion_index,
547 WebStateOpener(parentTab.webState, tab.openerNavigationIndex));
548 }
549 }
550
551 // Persist the session due to a new tab being inserted. If this is a
552 // background tab (will not become active), saving now will capture the
553 // state properly. If it does eventually become active, another save will
554 // be triggered to properly capture the end result.
555 [self saveSessionImmediately:NO];
556 }
557
558 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index opener:(Tab*)parentTab {
559 DCHECK(tab);
560 DCHECK(![_tabRetainer containsObject:tab]);
561 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
562
563 [self insertTab:tab
564 atIndex:index
565 opener:parentTab
566 transition:ui::PAGE_TRANSITION_GENERATED];
567 }
568
569 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index {
570 DCHECK(tab);
571 DCHECK(![_tabRetainer containsObject:tab]);
572 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
573
574 [self insertTab:tab atIndex:index opener:GetOpenerForTab(self, tab)];
575 }
576
577 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { 538 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex {
578 DCHECK([_tabRetainer containsObject:tab]);
579 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX)); 539 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX));
580 int fromIndex = _webStateList->GetIndexOfWebState(tab.webState); 540 int fromIndex = _webStateList->GetIndexOfWebState(tab.webState);
581 _webStateList->MoveWebStateAt(fromIndex, static_cast<int>(toIndex)); 541 _webStateList->MoveWebStateAt(fromIndex, static_cast<int>(toIndex));
582 } 542 }
583 543
584 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab {
585 DCHECK([_tabRetainer containsObject:oldTab]);
586 DCHECK(![_tabRetainer containsObject:newTab]);
587
588 int index = _webStateList->GetIndexOfWebState(oldTab.webState);
589 DCHECK_NE(index, WebStateList::kInvalidIndex);
590 DCHECK_GE(index, 0);
591
592 base::scoped_nsobject<Tab> tabSaver([oldTab retain]);
593 [_tabRetainer removeObject:oldTab];
594 [_tabRetainer addObject:newTab];
595 [newTab setParentTabModel:self];
596
597 // The WebState is owned by the associated Tab, so it is safe to ignore
598 // the result and won't cause a memory leak. Once the ownership is moved
599 // to WebStateList, this function will return a std::unique_ptr<> and the
600 // object destroyed as expected, so it will fine to ignore the result then
601 // too. See http://crbug.com/546222 for progress of changing the ownership
602 // of the WebStates.
603 ignore_result(_webStateList->ReplaceWebStateAt(index, newTab.webState));
604
605 Tab* parentTab = GetOpenerForTab(self, newTab);
606 if (parentTab) {
607 _webStateList->SetOpenerOfWebStateAt(
608 index,
609 WebStateOpener(parentTab.webState, newTab.openerNavigationIndex));
610 }
611
612 [oldTab setParentTabModel:nil];
613 [oldTab close];
614 }
615
616 - (void)closeTabAtIndex:(NSUInteger)index { 544 - (void)closeTabAtIndex:(NSUInteger)index {
617 DCHECK(index < self.count); 545 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
618 [self closeTab:[self tabAtIndex:index]]; 546 _webStateList->CloseWebStateAt(static_cast<int>(index));
619 } 547 }
620 548
621 - (void)closeTab:(Tab*)tab { 549 - (void)closeTab:(Tab*)tab {
622 // Ensure the tab stays alive long enough for us to send out the 550 [self closeTabAtIndex:[self indexOfTab:tab]];
623 // notice of its destruction to the delegate.
624 [_observers tabModel:self willRemoveTab:tab];
625 [tab close]; // Note it is not safe to access the tab after 'close'.
626 } 551 }
627 552
628 - (void)closeAllTabs { 553 - (void)closeAllTabs {
629 for (NSInteger i = self.count - 1; i >= 0; --i) 554 _webStateList->CloseAllWebStates();
630 [self closeTabAtIndex:i];
631 [[NSNotificationCenter defaultCenter] 555 [[NSNotificationCenter defaultCenter]
632 postNotificationName:kTabModelAllTabsDidCloseNotification 556 postNotificationName:kTabModelAllTabsDidCloseNotification
633 object:self]; 557 object:self];
634 } 558 }
635 559
636 - (void)haltAllTabs { 560 - (void)haltAllTabs {
637 for (Tab* tab in self) { 561 for (Tab* tab in self) {
638 [tab terminateNetworkActivity]; 562 [tab terminateNetworkActivity];
639 } 563 }
640 } 564 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 642
719 // NOTE: This can be called multiple times, so must be robust against that. 643 // NOTE: This can be called multiple times, so must be robust against that.
720 - (void)browserStateDestroyed { 644 - (void)browserStateDestroyed {
721 [[NSNotificationCenter defaultCenter] removeObserver:self]; 645 [[NSNotificationCenter defaultCenter] removeObserver:self];
722 if (_browserState) { 646 if (_browserState) {
723 UnregisterTabModelFromChromeBrowserState(_browserState, self); 647 UnregisterTabModelFromChromeBrowserState(_browserState, self);
724 } 648 }
725 _browserState = nullptr; 649 _browserState = nullptr;
726 } 650 }
727 651
728 // Called when a tab is closing, but before its CRWWebController is destroyed.
729 // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel.
730 - (void)didCloseTab:(Tab*)closedTab {
731 DCHECK(closedTab);
732 DCHECK([_tabRetainer containsObject:closedTab]);
733 int closedTabIndex = _webStateList->GetIndexOfWebState(closedTab.webState);
734 DCHECK_NE(closedTabIndex, WebStateList::kInvalidIndex);
735 DCHECK_GE(closedTabIndex, 0);
736
737 // Let the sessions::TabRestoreService know about that new tab.
738 sessions::TabRestoreService* restoreService =
739 _browserState
740 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState)
741 : nullptr;
742 web::NavigationManager* navigationManager = [closedTab navigationManager];
743 DCHECK(navigationManager);
744 int itemCount = navigationManager->GetItemCount();
745 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) {
746 restoreService->CreateHistoricalTab(
747 sessions::IOSLiveTab::GetForWebState(closedTab.webState),
748 closedTabIndex);
749 }
750
751 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]);
752
753 // If a non-current Tab is closed, save the session (it will be saved by
754 // TabModelObserversBridge if the currentTab has been closed).
755 BOOL needToSaveSession = (closedTab != self.currentTab);
756
757 DCHECK([_tabRetainer containsObject:closedTab]);
758 [_tabRetainer removeObject:closedTab];
759
760 // The WebState is owned by the associated Tab, so it is safe to ignore
761 // the result and won't cause a memory leak. Once the ownership is moved
762 // to WebStateList, this function will return a std::unique_ptr<> and the
763 // object destroyed as expected, so it will fine to ignore the result then
764 // too. See http://crbug.com/546222 for progress of changing the ownership
765 // of the WebStates.
766 ignore_result(_webStateList->DetachWebStateAt(closedTabIndex));
767
768 if (needToSaveSession)
769 [self saveSessionImmediately:NO];
770 }
771
772 - (void)navigationCommittedInTab:(Tab*)tab 652 - (void)navigationCommittedInTab:(Tab*)tab
773 previousItem:(web::NavigationItem*)previousItem { 653 previousItem:(web::NavigationItem*)previousItem {
774 if (self.offTheRecord) 654 if (self.offTheRecord)
775 return; 655 return;
776 if (![tab navigationManager]) 656 if (![tab navigationManager])
777 return; 657 return;
778 658
779 // See if the navigation was within a page; if so ignore it. 659 // See if the navigation was within a page; if so ignore it.
780 if (previousItem) { 660 if (previousItem) {
781 GURL previousURL = previousItem->GetURL(); 661 GURL previousURL = previousItem->GetURL();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 // fg tab. Do it now. 701 // fg tab. Do it now.
822 [self.currentTab recordStateInHistory]; 702 [self.currentTab recordStateInHistory];
823 703
824 // Build the array of sessions. Copy the session objects as the saving will 704 // Build the array of sessions. Copy the session objects as the saving will
825 // be done on a separate thread. 705 // be done on a separate thread.
826 // TODO(crbug.com/661986): This could get expensive especially since this 706 // TODO(crbug.com/661986): This could get expensive especially since this
827 // window may never be saved (if another call comes in before the delay). 707 // window may never be saved (if another call comes in before the delay).
828 NSMutableArray<CRWSessionStorage*>* sessions = 708 NSMutableArray<CRWSessionStorage*>* sessions =
829 [NSMutableArray arrayWithCapacity:[self count]]; 709 [NSMutableArray arrayWithCapacity:[self count]];
830 710
831 for (Tab* tab in self) { 711 for (int index = 0; index < _webStateList->count(); ++index) {
832 DCHECK(tab.webState); 712 web::WebState* webState = _webStateList->GetWebStateAt(index);
833 [sessions addObject:tab.webState->BuildSessionStorage()]; 713 web::SerializableUserDataManager* userDataManager =
714 web::SerializableUserDataManager::FromWebState(webState);
715
716 WebStateOpener opener = _webStateList->GetOpenerOfWebStateAt(index);
717 if (opener.opener) {
718 Tab* parentTab = LegacyTabHelper::GetTabForWebState(opener.opener);
719 userDataManager->AddSerializableData(parentTab.tabId, kOpenerIDKey);
720 userDataManager->AddSerializableData(@(opener.navigation_index),
721 kOpenerNavigationIndexKey);
722 } else {
723 userDataManager->AddSerializableData([NSNull null], kOpenerIDKey);
724 userDataManager->AddSerializableData([NSNull null],
725 kOpenerNavigationIndexKey);
726 }
727
728 [sessions addObject:webState->BuildSessionStorage()];
834 } 729 }
835 730
836 return [[[SessionWindowIOS alloc] 731 return [[[SessionWindowIOS alloc]
837 initWithSessions:sessions 732 initWithSessions:sessions
838 selectedIndex:[self indexOfTab:self.currentTab]] autorelease]; 733 selectedIndex:[self indexOfTab:self.currentTab]] autorelease];
839 } 734 }
840 735
841 - (BOOL)isNTPTab:(Tab*)tab {
842 std::string host = tab.url.host();
843 return host == kChromeUINewTabHost || host == kChromeUIBookmarksHost;
844 }
845
846 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab { 736 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab {
847 // A scoped_nsobject is used rather than an NSDictionary with static 737 // A scoped_nsobject is used rather than an NSDictionary with static
848 // initializer dictionaryWithObject, because that approach adds the dictionary 738 // initializer dictionaryWithObject, because that approach adds the dictionary
849 // to the autorelease pool, which in turn holds Tab alive longer than 739 // to the autorelease pool, which in turn holds Tab alive longer than
850 // necessary. 740 // necessary.
851 base::scoped_nsobject<NSDictionary> userInfo( 741 base::scoped_nsobject<NSDictionary> userInfo(
852 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); 742 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]);
853 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName 743 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName
854 object:self 744 object:self
855 userInfo:userInfo]; 745 userInfo:userInfo];
(...skipping 17 matching lines...) Expand all
873 763
874 base::scoped_nsobject<NSMutableArray<Tab*>> restoredTabs( 764 base::scoped_nsobject<NSMutableArray<Tab*>> restoredTabs(
875 [[NSMutableArray alloc] initWithCapacity:sessions.count]); 765 [[NSMutableArray alloc] initWithCapacity:sessions.count]);
876 766
877 // Recreate all the restored Tabs and add them to the WebStateList without 767 // Recreate all the restored Tabs and add them to the WebStateList without
878 // any opener-opened relationship (as the n-th restored Tab opener may be 768 // any opener-opened relationship (as the n-th restored Tab opener may be
879 // at an index larger than n). Then in a second pass fix the openers. 769 // at an index larger than n). Then in a second pass fix the openers.
880 for (CRWSessionStorage* session in sessions) { 770 for (CRWSessionStorage* session in sessions) {
881 std::unique_ptr<web::WebState> webState = 771 std::unique_ptr<web::WebState> webState =
882 web::WebState::CreateWithStorageSession(params, session); 772 web::WebState::CreateWithStorageSession(params, session);
883 base::scoped_nsobject<Tab> tab( 773 _webStateList->InsertWebState(_webStateList->count(), std::move(webState));
884 [[Tab alloc] initWithWebState:std::move(webState) model:self]); 774 }
885 [tab webController].webUsageEnabled = webUsageEnabled_; 775
886 [tab webController].usePlaceholderOverlay = YES; 776 for (int index = oldCount; index < _webStateList->count(); ++index) {
777 web::WebState* webState = _webStateList->GetWebStateAt(index);
778 Tab* tab = LegacyTabHelper::GetTabForWebState(webState);
779 tab.webController.webUsageEnabled = webUsageEnabled_;
780 tab.webController.usePlaceholderOverlay = YES;
887 781
888 // Restore the CertificatePolicyCache (note that webState is invalid after 782 // Restore the CertificatePolicyCache (note that webState is invalid after
889 // passing it via move semantic to -initWithWebState:model:). 783 // passing it via move semantic to -initWithWebState:model:).
890 UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]); 784 UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]);
891 [self insertTab:tab atIndex:self.count opener:nil]; 785 [restoredTabs addObject:tab];
892 [restoredTabs addObject:tab.get()];
893 } 786 }
894 787
895 DCHECK_EQ(sessions.count, [restoredTabs count]); 788 DCHECK_EQ(sessions.count, [restoredTabs count]);
896 DCHECK_GT(_webStateList->count(), oldCount); 789 DCHECK_GT(_webStateList->count(), oldCount);
897 790
898 // Fix openers now that all Tabs have been restored. Only look for an opener 791 // Fix openers now that all Tabs have been restored. Only look for an opener
899 // Tab in the newly restored Tabs and not in the already open Tabs. 792 // Tab in the newly restored Tabs and not in the already open Tabs.
900 for (int index = oldCount; index < _webStateList->count(); ++index) { 793 for (int index = oldCount; index < _webStateList->count(); ++index) {
901 DCHECK_GE(index, oldCount); 794 DCHECK_GE(index, oldCount);
902 NSUInteger tabIndex = static_cast<NSUInteger>(index - oldCount); 795 NSUInteger tabIndex = static_cast<NSUInteger>(index - oldCount);
903 Tab* tab = [restoredTabs objectAtIndex:tabIndex]; 796 Tab* tab = [restoredTabs objectAtIndex:tabIndex];
904 Tab* opener = GetOpenerForTab(restoredTabs.get(), tab); 797 WebStateOpener opener = GetOpenerForTab(restoredTabs.get(), tab);
905 if (opener) { 798 if (opener.opener)
906 DCHECK(opener.webState); 799 _webStateList->SetOpenerOfWebStateAt(index, opener);
907 _webStateList->SetOpenerOfWebStateAt(
908 index, WebStateOpener(opener.webState, tab.openerNavigationIndex));
909 }
910 } 800 }
911 801
912 // Update the selected tab if there was a selected Tab in the saved session. 802 // Update the selected tab if there was a selected Tab in the saved session.
913 if (window.selectedIndex != NSNotFound) { 803 if (window.selectedIndex != NSNotFound) {
914 NSUInteger selectedIndex = window.selectedIndex + oldCount; 804 NSUInteger selectedIndex = window.selectedIndex + oldCount;
915 DCHECK_LT(selectedIndex, self.count); 805 DCHECK_LT(selectedIndex, self.count);
916 DCHECK([self tabAtIndex:selectedIndex]); 806 DCHECK([self tabAtIndex:selectedIndex]);
917 807
918 if (persistState && self.currentTab) 808 if (persistState && self.currentTab)
919 [self.currentTab recordStateInHistory]; 809 [self.currentTab recordStateInHistory];
920 _webStateList->ActivateWebStateAt(static_cast<int>(selectedIndex)); 810 _webStateList->ActivateWebStateAt(static_cast<int>(selectedIndex));
921 } 811 }
922 812
923 // If there was only one tab and it was the new tab page, clobber it. 813 // If there was only one tab and it was the new tab page, clobber it.
924 BOOL closedNTPTab = NO; 814 BOOL closedNTPTab = NO;
925 if (oldCount == 1) { 815 if (oldCount == 1) {
926 Tab* tab = [self tabAtIndex:0]; 816 Tab* tab = [self tabAtIndex:0];
927 if (tab.url == GURL(kChromeUINewTabURL)) { 817 if (tab.url == GURL(kChromeUINewTabURL)) {
928 [self closeTab:tab]; 818 [self closeTab:tab];
929 closedNTPTab = YES; 819 closedNTPTab = YES;
930 oldCount = 0; 820 oldCount = 0;
931 } 821 }
932 } 822 }
933 if (_tabUsageRecorder) { 823 if (_tabUsageRecorder)
934 NSMutableArray<Tab*>* restoredTabs =
935 [NSMutableArray arrayWithCapacity:_webStateList->count() - oldCount];
936 for (int index = oldCount; index < _webStateList->count(); ++index) {
937 web::WebState* webState = _webStateList->GetWebStateAt(index);
938 [restoredTabs addObject:LegacyTabHelper::GetTabForWebState(webState)];
939 }
940 _tabUsageRecorder->InitialRestoredTabs(self.currentTab, restoredTabs); 824 _tabUsageRecorder->InitialRestoredTabs(self.currentTab, restoredTabs);
941 }
942 return closedNTPTab; 825 return closedNTPTab;
943 } 826 }
944 827
945 #pragma mark - Notification Handlers 828 #pragma mark - Notification Handlers
946 829
947 // Called when UIApplicationWillResignActiveNotification is received. 830 // Called when UIApplicationWillResignActiveNotification is received.
948 - (void)willResignActive:(NSNotification*)notify { 831 - (void)willResignActive:(NSNotification*)notify {
949 if (webUsageEnabled_ && self.currentTab) { 832 if (webUsageEnabled_ && self.currentTab) {
950 [[SnapshotCache sharedInstance] 833 [[SnapshotCache sharedInstance]
951 willBeSavedGreyWhenBackgrounding:self.currentTab.tabId]; 834 willBeSavedGreyWhenBackgrounding:self.currentTab.tabId];
(...skipping 28 matching lines...) Expand all
980 } 863 }
981 864
982 // Called when UIApplicationWillEnterForegroundNotification is received. 865 // Called when UIApplicationWillEnterForegroundNotification is received.
983 - (void)applicationWillEnterForeground:(NSNotification*)notify { 866 - (void)applicationWillEnterForeground:(NSNotification*)notify {
984 if (_tabUsageRecorder) { 867 if (_tabUsageRecorder) {
985 _tabUsageRecorder->AppWillEnterForeground(); 868 _tabUsageRecorder->AppWillEnterForeground();
986 } 869 }
987 } 870 }
988 871
989 @end 872 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698