| OLD | NEW |
| 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/scoped_nsobject.h" | 13 #import "base/mac/scoped_nsobject.h" |
| 14 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 15 #include "base/metrics/user_metrics.h" | 15 #include "base/metrics/user_metrics.h" |
| 16 #include "base/metrics/user_metrics_action.h" | 16 #include "base/metrics/user_metrics_action.h" |
| 17 #include "base/strings/sys_string_conversions.h" | 17 #include "base/strings/sys_string_conversions.h" |
| 18 #include "base/task/cancelable_task_tracker.h" | 18 #include "base/task/cancelable_task_tracker.h" |
| 19 #include "components/sessions/core/serialized_navigation_entry.h" | 19 #include "components/sessions/core/serialized_navigation_entry.h" |
| 20 #include "components/sessions/core/session_id.h" | 20 #include "components/sessions/core/session_id.h" |
| 21 #include "components/sessions/core/tab_restore_service.h" | 21 #include "components/sessions/core/tab_restore_service.h" |
| 22 #include "components/sessions/ios/ios_live_tab.h" | 22 #include "components/sessions/ios/ios_live_tab.h" |
| 23 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 23 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 24 #include "ios/chrome/browser/chrome_url_constants.h" | 24 #include "ios/chrome/browser/chrome_url_constants.h" |
| 25 #import "ios/chrome/browser/chrome_url_util.h" | 25 #import "ios/chrome/browser/chrome_url_util.h" |
| 26 #import "ios/chrome/browser/metrics/tab_usage_recorder.h" | 26 #import "ios/chrome/browser/metrics/tab_usage_recorder.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.h" | 30 #import "ios/chrome/browser/sessions/session_window.h" |
| 30 #import "ios/chrome/browser/snapshots/snapshot_cache.h" | 31 #import "ios/chrome/browser/snapshots/snapshot_cache.h" |
| 32 #import "ios/chrome/browser/snapshots/snapshot_cache_web_state_list_observer.h" |
| 31 #include "ios/chrome/browser/tab_parenting_global_observer.h" | 33 #include "ios/chrome/browser/tab_parenting_global_observer.h" |
| 32 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" | 34 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" |
| 33 #import "ios/chrome/browser/tabs/tab.h" | 35 #import "ios/chrome/browser/tabs/tab.h" |
| 34 #import "ios/chrome/browser/tabs/tab_model_list.h" | 36 #import "ios/chrome/browser/tabs/tab_model_list.h" |
| 35 #import "ios/chrome/browser/tabs/tab_model_observers.h" | 37 #import "ios/chrome/browser/tabs/tab_model_observers.h" |
| 36 #import "ios/chrome/browser/tabs/tab_model_observers_bridge.h" | 38 #import "ios/chrome/browser/tabs/tab_model_observers_bridge.h" |
| 37 #import "ios/chrome/browser/tabs/tab_model_order_controller.h" | 39 #import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h" |
| 38 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" | 40 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" |
| 39 #import "ios/chrome/browser/tabs/tab_parenting_observer.h" | 41 #import "ios/chrome/browser/tabs/tab_parenting_observer.h" |
| 40 #import "ios/chrome/browser/xcallback_parameters.h" | 42 #import "ios/chrome/browser/xcallback_parameters.h" |
| 41 #import "ios/shared/chrome/browser/tabs/web_state_list.h" | 43 #import "ios/shared/chrome/browser/tabs/web_state_list.h" |
| 42 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h
" | 44 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h
" |
| 43 #import "ios/shared/chrome/browser/tabs/web_state_list_metrics_observer.h" | 45 #import "ios/shared/chrome/browser/tabs/web_state_list_metrics_observer.h" |
| 44 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" | 46 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" |
| 45 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" | 47 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" |
| 46 #import "ios/web/navigation/crw_session_controller.h" | 48 #import "ios/web/navigation/crw_session_controller.h" |
| 47 #include "ios/web/public/browser_state.h" | 49 #include "ios/web/public/browser_state.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 | 157 |
| 156 // Used to keep the Tabs alive while the corresponding WebStates are stored | 158 // Used to keep the Tabs alive while the corresponding WebStates are stored |
| 157 // in the WebStateList (as Tabs currently own their WebState). Remove once | 159 // in the WebStateList (as Tabs currently own their WebState). Remove once |
| 158 // WebState owns the associated Tab. | 160 // WebState owns the associated Tab. |
| 159 base::scoped_nsobject<NSMutableSet<Tab*>> _tabRetainer; | 161 base::scoped_nsobject<NSMutableSet<Tab*>> _tabRetainer; |
| 160 | 162 |
| 161 // WebStateListObserver bridges to react to modifications of the model (may | 163 // WebStateListObserver bridges to react to modifications of the model (may |
| 162 // send notification, translate and forward events, update metrics, ...). | 164 // send notification, translate and forward events, update metrics, ...). |
| 163 std::vector<std::unique_ptr<WebStateListObserver>> _observerBridges; | 165 std::vector<std::unique_ptr<WebStateListObserver>> _observerBridges; |
| 164 | 166 |
| 165 // Maintains policy for where new tabs go and the selection when a tab | |
| 166 // is removed. | |
| 167 base::scoped_nsobject<TabModelOrderController> _orderController; | |
| 168 // The delegate for sync. | 167 // The delegate for sync. |
| 169 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; | 168 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; |
| 170 // Currently selected tab. May be nil. | |
| 171 base::WeakNSObject<Tab> _currentTab; | |
| 172 | 169 |
| 173 // Counters for metrics. | 170 // Counters for metrics. |
| 174 int _openedTabCount; | 171 WebStateListMetricsObserver* _webStateListMetricsObserver; |
| 175 int _closedTabCount; | |
| 176 int _newTabCount; | |
| 177 | 172 |
| 178 // Backs up property with the same name. | 173 // Backs up property with the same name. |
| 179 std::unique_ptr<TabUsageRecorder> _tabUsageRecorder; | 174 std::unique_ptr<TabUsageRecorder> _tabUsageRecorder; |
| 180 // Backs up property with the same name. | 175 // Backs up property with the same name. |
| 181 const SessionID _sessionID; | 176 const SessionID _sessionID; |
| 182 // Saves session's state. | 177 // Saves session's state. |
| 183 base::scoped_nsobject<SessionServiceIOS> _sessionService; | 178 base::scoped_nsobject<SessionServiceIOS> _sessionService; |
| 184 // List of TabModelObservers. | 179 // List of TabModelObservers. |
| 185 base::scoped_nsobject<TabModelObservers> _observers; | 180 base::scoped_nsobject<TabModelObservers> _observers; |
| 186 | 181 |
| 187 // Used to ensure thread-safety of the certificate policy management code. | 182 // Used to ensure thread-safety of the certificate policy management code. |
| 188 base::CancelableTaskTracker _clearPoliciesTaskTracker; | 183 base::CancelableTaskTracker _clearPoliciesTaskTracker; |
| 189 } | 184 } |
| 190 | 185 |
| 191 // Session window for the contents of the tab model. | 186 // Session window for the contents of the tab model. |
| 192 @property(nonatomic, readonly) SessionWindowIOS* windowForSavingSession; | 187 @property(nonatomic, readonly) SessionWindowIOS* windowForSavingSession; |
| 193 | 188 |
| 194 // Returns YES if tab URL host indicates that tab is an NTP tab. | 189 // Returns YES if tab URL host indicates that tab is an NTP tab. |
| 195 - (BOOL)isNTPTab:(Tab*)tab; | 190 - (BOOL)isNTPTab:(Tab*)tab; |
| 196 | 191 |
| 197 // Call to switch the selected tab. Broadcasts about the change in selection. | |
| 198 // It's ok for |newTab| to be nil in case the last tab is going away. In that | |
| 199 // case, the "tab deselected" notification gets sent, but no corresponding | |
| 200 // "tab selected" notification is sent. |persist| indicates whether or not | |
| 201 // the tab's state should be persisted in history upon switching. | |
| 202 - (void)changeSelectedTabFrom:(Tab*)oldTab | |
| 203 to:(Tab*)newTab | |
| 204 persistState:(BOOL)persist; | |
| 205 | |
| 206 // Tells the snapshot cache the adjacent tab session ids. | |
| 207 - (void)updateSnapshotCache:(Tab*)tab; | |
| 208 | |
| 209 // Helper method that posts a notification with the given name with |tab| | 192 // Helper method that posts a notification with the given name with |tab| |
| 210 // in the userInfo dictionary under the kTabModelTabKey. | 193 // in the userInfo dictionary under the kTabModelTabKey. |
| 211 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab; | 194 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab; |
| 212 | 195 |
| 213 // Helper method to restore a saved session and control if the state should | 196 // Helper method to restore a saved session and control if the state should |
| 214 // be persisted or not. Used to implement the public -restoreSessionWindow: | 197 // be persisted or not. Used to implement the public -restoreSessionWindow: |
| 215 // method and restoring session in the initialiser. | 198 // method and restoring session in the initialiser. |
| 216 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window | 199 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window |
| 217 persistState:(BOOL)persistState; | 200 persistState:(BOOL)persistState; |
| 218 | 201 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 241 | 224 |
| 242 #pragma mark - Overriden | 225 #pragma mark - Overriden |
| 243 | 226 |
| 244 - (void)dealloc { | 227 - (void)dealloc { |
| 245 DCHECK([_observers empty]); | 228 DCHECK([_observers empty]); |
| 246 // browserStateDestroyed should always have been called before destruction. | 229 // browserStateDestroyed should always have been called before destruction. |
| 247 DCHECK(!_browserState); | 230 DCHECK(!_browserState); |
| 248 | 231 |
| 249 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 232 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 250 | 233 |
| 234 // Clear weak pointer to WebStateListMetricsObserver before destroying it. |
| 235 _webStateListMetricsObserver = nullptr; |
| 236 |
| 251 // Unregister all listeners before closing all the tabs. | 237 // Unregister all listeners before closing all the tabs. |
| 252 for (const auto& observerBridge : _observerBridges) | 238 for (const auto& observerBridge : _observerBridges) |
| 253 _webStateList.RemoveObserver(observerBridge.get()); | 239 _webStateList.RemoveObserver(observerBridge.get()); |
| 254 _observerBridges.clear(); | 240 _observerBridges.clear(); |
| 255 | 241 |
| 256 // Make sure the tabs do clean after themselves. It is important for | 242 // Make sure the tabs do clean after themselves. It is important for |
| 257 // removeObserver: to be called first otherwise a lot of unecessary work will | 243 // removeObserver: to be called first otherwise a lot of unecessary work will |
| 258 // happen on -closeAllTabs. | 244 // happen on -closeAllTabs. |
| 259 [self closeAllTabs]; | 245 [self closeAllTabs]; |
| 260 | 246 |
| 261 _clearPoliciesTaskTracker.TryCancelAll(); | 247 _clearPoliciesTaskTracker.TryCancelAll(); |
| 262 | 248 |
| 263 [super dealloc]; | 249 [super dealloc]; |
| 264 } | 250 } |
| 265 | 251 |
| 266 #pragma mark - Public methods | 252 #pragma mark - Public methods |
| 267 | 253 |
| 268 - (Tab*)currentTab { | 254 - (Tab*)currentTab { |
| 269 return _currentTab.get(); | 255 web::WebState* webState = _webStateList.GetActiveWebState(); |
| 256 return webState ? LegacyTabHelper::GetTabForWebState(webState) : nil; |
| 270 } | 257 } |
| 271 | 258 |
| 272 - (void)setCurrentTab:(Tab*)newTab { | 259 - (void)setCurrentTab:(Tab*)newTab { |
| 273 DCHECK_NE([self indexOfTab:newTab], static_cast<NSUInteger>(NSNotFound)); | 260 int indexOfTab = _webStateList.GetIndexOfWebState(newTab.webState); |
| 274 if (_currentTab != newTab) { | 261 DCHECK_NE(indexOfTab, WebStateList::kInvalidIndex); |
| 275 base::RecordAction(base::UserMetricsAction("MobileTabSwitched")); | 262 _webStateList.ActivateWebStateAt(indexOfTab); |
| 276 [self updateSnapshotCache:newTab]; | |
| 277 } | |
| 278 if (_tabUsageRecorder) { | |
| 279 _tabUsageRecorder->RecordTabSwitched(_currentTab, newTab); | |
| 280 } | |
| 281 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES]; | |
| 282 } | 263 } |
| 283 | 264 |
| 284 - (TabModelSyncedWindowDelegate*)syncedWindowDelegate { | 265 - (TabModelSyncedWindowDelegate*)syncedWindowDelegate { |
| 285 return _syncedWindowDelegate.get(); | 266 return _syncedWindowDelegate.get(); |
| 286 } | 267 } |
| 287 | 268 |
| 288 - (TabUsageRecorder*)tabUsageRecorder { | 269 - (TabUsageRecorder*)tabUsageRecorder { |
| 289 return _tabUsageRecorder.get(); | 270 return _tabUsageRecorder.get(); |
| 290 } | 271 } |
| 291 | 272 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 // Set up the usage recorder before tabs are created. | 304 // Set up the usage recorder before tabs are created. |
| 324 _tabUsageRecorder = base::MakeUnique<TabUsageRecorder>(self); | 305 _tabUsageRecorder = base::MakeUnique<TabUsageRecorder>(self); |
| 325 } | 306 } |
| 326 _syncedWindowDelegate = | 307 _syncedWindowDelegate = |
| 327 base::MakeUnique<TabModelSyncedWindowDelegate>(self); | 308 base::MakeUnique<TabModelSyncedWindowDelegate>(self); |
| 328 | 309 |
| 329 // There must be a valid session service defined to consume session windows. | 310 // There must be a valid session service defined to consume session windows. |
| 330 DCHECK(service); | 311 DCHECK(service); |
| 331 _sessionService.reset([service retain]); | 312 _sessionService.reset([service retain]); |
| 332 | 313 |
| 314 _observerBridges.push_back( |
| 315 base::MakeUnique<SnapshotCacheWebStateListObserver>( |
| 316 [SnapshotCache sharedInstance])); |
| 317 if (_tabUsageRecorder) { |
| 318 _observerBridges.push_back( |
| 319 base::MakeUnique<TabUsageRecorderWebStateListObserver>( |
| 320 _tabUsageRecorder.get())); |
| 321 } |
| 333 _observerBridges.push_back(base::MakeUnique<TabParentingObserver>()); | 322 _observerBridges.push_back(base::MakeUnique<TabParentingObserver>()); |
| 334 _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( | 323 _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( |
| 324 [[TabModelSelectedTabObserver alloc] initWithTabModel:self])); |
| 325 _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( |
| 335 [[TabModelObserversBridge alloc] initWithTabModel:self | 326 [[TabModelObserversBridge alloc] initWithTabModel:self |
| 336 tabModelObservers:_observers.get()])); | 327 tabModelObservers:_observers.get()])); |
| 337 _observerBridges.push_back(base::MakeUnique<WebStateListMetricsObserver>()); | 328 |
| 329 auto webStateListMetricsObserver = |
| 330 base::MakeUnique<WebStateListMetricsObserver>(); |
| 331 _webStateListMetricsObserver = webStateListMetricsObserver.get(); |
| 332 _observerBridges.push_back(std::move(webStateListMetricsObserver)); |
| 338 | 333 |
| 339 for (const auto& observerBridge : _observerBridges) | 334 for (const auto& observerBridge : _observerBridges) |
| 340 _webStateList.AddObserver(observerBridge.get()); | 335 _webStateList.AddObserver(observerBridge.get()); |
| 341 | 336 |
| 342 if (window) { | 337 if (window) { |
| 343 DCHECK([_observers empty]); | 338 DCHECK([_observers empty]); |
| 344 // Restore the session and reset the session metrics (as the event have | 339 // Restore the session and reset the session metrics (as the event have |
| 345 // not been generated by the user but by a cold start cycle). | 340 // not been generated by the user but by a cold start cycle). |
| 346 [self restoreSessionWindow:window persistState:NO]; | 341 [self restoreSessionWindow:window persistState:NO]; |
| 347 [self resetSessionMetrics]; | 342 [self resetSessionMetrics]; |
| 348 } | 343 } |
| 349 | 344 |
| 350 _orderController.reset( | |
| 351 [[TabModelOrderController alloc] initWithTabModel:self]); | |
| 352 | |
| 353 // Register for resign active notification. | 345 // Register for resign active notification. |
| 354 [[NSNotificationCenter defaultCenter] | 346 [[NSNotificationCenter defaultCenter] |
| 355 addObserver:self | 347 addObserver:self |
| 356 selector:@selector(willResignActive:) | 348 selector:@selector(willResignActive:) |
| 357 name:UIApplicationWillResignActiveNotification | 349 name:UIApplicationWillResignActiveNotification |
| 358 object:nil]; | 350 object:nil]; |
| 359 // Register for background notification. | 351 // Register for background notification. |
| 360 [[NSNotificationCenter defaultCenter] | 352 [[NSNotificationCenter defaultCenter] |
| 361 addObserver:self | 353 addObserver:self |
| 362 selector:@selector(applicationDidEnterBackground:) | 354 selector:@selector(applicationDidEnterBackground:) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 380 return nil; | 372 return nil; |
| 381 } | 373 } |
| 382 | 374 |
| 383 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window { | 375 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window { |
| 384 return [self restoreSessionWindow:window persistState:YES]; | 376 return [self restoreSessionWindow:window persistState:YES]; |
| 385 } | 377 } |
| 386 | 378 |
| 387 - (void)saveSessionImmediately:(BOOL)immediately { | 379 - (void)saveSessionImmediately:(BOOL)immediately { |
| 388 // Do nothing if there are tabs in the model but no selected tab. This is | 380 // Do nothing if there are tabs in the model but no selected tab. This is |
| 389 // a transitional state. | 381 // a transitional state. |
| 390 if ((!_currentTab && _webStateList.count()) || !_browserState) | 382 if ((!self.currentTab && _webStateList.count()) || !_browserState) |
| 391 return; | 383 return; |
| 392 [_sessionService saveWindow:self.windowForSavingSession | 384 [_sessionService saveWindow:self.windowForSavingSession |
| 393 forBrowserState:_browserState | 385 forBrowserState:_browserState |
| 394 immediately:immediately]; | 386 immediately:immediately]; |
| 395 } | 387 } |
| 396 | 388 |
| 397 - (Tab*)tabAtIndex:(NSUInteger)index { | 389 - (Tab*)tabAtIndex:(NSUInteger)index { |
| 398 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | 390 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); |
| 399 return LegacyTabHelper::GetTabForWebState( | 391 return LegacyTabHelper::GetTabForWebState( |
| 400 _webStateList.GetWebStateAt(static_cast<int>(index))); | 392 _webStateList.GetWebStateAt(static_cast<int>(index))); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 const int insertion_index = static_cast<int>(index); | 541 const int insertion_index = static_cast<int>(index); |
| 550 _webStateList.InsertWebState(insertion_index, tab.webState, | 542 _webStateList.InsertWebState(insertion_index, tab.webState, |
| 551 parentTab.webState); | 543 parentTab.webState); |
| 552 } | 544 } |
| 553 | 545 |
| 554 // Persist the session due to a new tab being inserted. If this is a | 546 // Persist the session due to a new tab being inserted. If this is a |
| 555 // background tab (will not become active), saving now will capture the | 547 // background tab (will not become active), saving now will capture the |
| 556 // state properly. If it does eventually become active, another save will | 548 // state properly. If it does eventually become active, another save will |
| 557 // be triggered to properly capture the end result. | 549 // be triggered to properly capture the end result. |
| 558 [self saveSessionImmediately:NO]; | 550 [self saveSessionImmediately:NO]; |
| 559 | |
| 560 ++_newTabCount; | |
| 561 } | 551 } |
| 562 | 552 |
| 563 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index opener:(Tab*)parentTab { | 553 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index opener:(Tab*)parentTab { |
| 564 DCHECK(tab); | 554 DCHECK(tab); |
| 565 DCHECK(![_tabRetainer containsObject:tab]); | 555 DCHECK(![_tabRetainer containsObject:tab]); |
| 566 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | 556 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); |
| 567 | 557 |
| 568 [self insertTab:tab | 558 [self insertTab:tab |
| 569 atIndex:index | 559 atIndex:index |
| 570 opener:parentTab | 560 opener:parentTab |
| (...skipping 30 matching lines...) Expand all Loading... |
| 601 | 591 |
| 602 // The WebState is owned by the associated Tab, so it is safe to ignore | 592 // The WebState is owned by the associated Tab, so it is safe to ignore |
| 603 // the result and won't cause a memory leak. Once the ownership is moved | 593 // the result and won't cause a memory leak. Once the ownership is moved |
| 604 // to WebStateList, this function will return a std::unique_ptr<> and the | 594 // to WebStateList, this function will return a std::unique_ptr<> and the |
| 605 // object destroyed as expected, so it will fine to ignore the result then | 595 // object destroyed as expected, so it will fine to ignore the result then |
| 606 // too. See http://crbug.com/546222 for progress of changing the ownership | 596 // too. See http://crbug.com/546222 for progress of changing the ownership |
| 607 // of the WebStates. | 597 // of the WebStates. |
| 608 ignore_result(_webStateList.ReplaceWebStateAt( | 598 ignore_result(_webStateList.ReplaceWebStateAt( |
| 609 index, newTab.webState, GetOpenerForTab(self, newTab).webState)); | 599 index, newTab.webState, GetOpenerForTab(self, newTab).webState)); |
| 610 | 600 |
| 611 if (self.currentTab == oldTab) | |
| 612 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; | |
| 613 | |
| 614 [oldTab setParentTabModel:nil]; | 601 [oldTab setParentTabModel:nil]; |
| 615 [oldTab close]; | 602 [oldTab close]; |
| 616 } | 603 } |
| 617 | 604 |
| 618 - (void)closeTabAtIndex:(NSUInteger)index { | 605 - (void)closeTabAtIndex:(NSUInteger)index { |
| 619 DCHECK(index < self.count); | 606 DCHECK(index < self.count); |
| 620 [self closeTab:[self tabAtIndex:index]]; | 607 [self closeTab:[self tabAtIndex:index]]; |
| 621 } | 608 } |
| 622 | 609 |
| 623 - (void)closeTab:(Tab*)tab { | 610 - (void)closeTab:(Tab*)tab { |
| 624 // Ensure the tab stays alive long enough for us to send out the | 611 // Ensure the tab stays alive long enough for us to send out the |
| 625 // notice of its destruction to the delegate. | 612 // notice of its destruction to the delegate. |
| 626 [_observers tabModel:self willRemoveTab:tab]; | 613 [_observers tabModel:self willRemoveTab:tab]; |
| 627 [tab close]; // Note it is not safe to access the tab after 'close'. | 614 [tab close]; // Note it is not safe to access the tab after 'close'. |
| 628 } | 615 } |
| 629 | 616 |
| 630 - (void)closeAllTabs { | 617 - (void)closeAllTabs { |
| 631 // If this changes, _closedTabCount metrics need to be adjusted. | |
| 632 for (NSInteger i = self.count - 1; i >= 0; --i) | 618 for (NSInteger i = self.count - 1; i >= 0; --i) |
| 633 [self closeTabAtIndex:i]; | 619 [self closeTabAtIndex:i]; |
| 634 [[NSNotificationCenter defaultCenter] | 620 [[NSNotificationCenter defaultCenter] |
| 635 postNotificationName:kTabModelAllTabsDidCloseNotification | 621 postNotificationName:kTabModelAllTabsDidCloseNotification |
| 636 object:self]; | 622 object:self]; |
| 637 } | 623 } |
| 638 | 624 |
| 639 - (void)haltAllTabs { | 625 - (void)haltAllTabs { |
| 640 for (Tab* tab in self) { | 626 for (Tab* tab in self) { |
| 641 [tab terminateNetworkActivity]; | 627 [tab terminateNetworkActivity]; |
| 642 } | 628 } |
| 643 } | 629 } |
| 644 | 630 |
| 645 - (void)notifyTabChanged:(Tab*)tab { | 631 - (void)notifyTabChanged:(Tab*)tab { |
| 646 [_observers tabModel:self didChangeTab:tab]; | 632 [_observers tabModel:self didChangeTab:tab]; |
| 647 } | 633 } |
| 648 | 634 |
| 649 - (void)addObserver:(id<TabModelObserver>)observer { | 635 - (void)addObserver:(id<TabModelObserver>)observer { |
| 650 [_observers addObserver:observer]; | 636 [_observers addObserver:observer]; |
| 651 } | 637 } |
| 652 | 638 |
| 653 - (void)removeObserver:(id<TabModelObserver>)observer { | 639 - (void)removeObserver:(id<TabModelObserver>)observer { |
| 654 [_observers removeObserver:observer]; | 640 [_observers removeObserver:observer]; |
| 655 } | 641 } |
| 656 | 642 |
| 657 - (void)resetSessionMetrics { | 643 - (void)resetSessionMetrics { |
| 658 _closedTabCount = 0; | 644 if (_webStateListMetricsObserver) |
| 659 _openedTabCount = 0; | 645 _webStateListMetricsObserver->ResetSessionMetrics(); |
| 660 _newTabCount = 0; | |
| 661 } | 646 } |
| 662 | 647 |
| 663 - (void)recordSessionMetrics { | 648 - (void)recordSessionMetrics { |
| 664 UMA_HISTOGRAM_CUSTOM_COUNTS("Session.ClosedTabCounts", _closedTabCount, 1, | 649 if (_webStateListMetricsObserver) |
| 665 200, 50); | 650 _webStateListMetricsObserver->RecordSessionMetrics(); |
| 666 UMA_HISTOGRAM_CUSTOM_COUNTS("Session.OpenedTabCounts", _openedTabCount, 1, | |
| 667 200, 50); | |
| 668 UMA_HISTOGRAM_CUSTOM_COUNTS("Session.NewTabCounts", _newTabCount, 1, 200, 50); | |
| 669 } | 651 } |
| 670 | 652 |
| 671 - (void)notifyTabSnapshotChanged:(Tab*)tab withImage:(UIImage*)image { | 653 - (void)notifyTabSnapshotChanged:(Tab*)tab withImage:(UIImage*)image { |
| 672 DCHECK([NSThread isMainThread]); | 654 DCHECK([NSThread isMainThread]); |
| 673 [_observers tabModel:self didChangeTabSnapshot:tab withImage:image]; | 655 [_observers tabModel:self didChangeTabSnapshot:tab withImage:image]; |
| 674 } | 656 } |
| 675 | 657 |
| 676 - (void)resetAllWebViews { | 658 - (void)resetAllWebViews { |
| 677 for (Tab* tab in self) { | 659 for (Tab* tab in self) { |
| 678 [tab.webController reinitializeWebViewAndReload:(tab == _currentTab)]; | 660 [tab.webController reinitializeWebViewAndReload:(tab == self.currentTab)]; |
| 679 } | 661 } |
| 680 } | 662 } |
| 681 | 663 |
| 682 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled { | 664 - (void)setWebUsageEnabled:(BOOL)webUsageEnabled { |
| 683 if (webUsageEnabled_ == webUsageEnabled) | 665 if (webUsageEnabled_ == webUsageEnabled) |
| 684 return; | 666 return; |
| 685 webUsageEnabled_ = webUsageEnabled; | 667 webUsageEnabled_ = webUsageEnabled; |
| 686 for (Tab* tab in self) { | 668 for (Tab* tab in self) { |
| 687 tab.webUsageEnabled = webUsageEnabled; | 669 tab.webUsageEnabled = webUsageEnabled; |
| 688 } | 670 } |
| 689 } | 671 } |
| 690 | 672 |
| 691 - (void)setPrimary:(BOOL)primary { | 673 - (void)setPrimary:(BOOL)primary { |
| 692 if (_tabUsageRecorder) | 674 if (_tabUsageRecorder) |
| 693 _tabUsageRecorder->RecordPrimaryTabModelChange(primary, _currentTab); | 675 _tabUsageRecorder->RecordPrimaryTabModelChange(primary, self.currentTab); |
| 694 } | 676 } |
| 695 | 677 |
| 696 - (NSSet*)currentlyReferencedExternalFiles { | 678 - (NSSet*)currentlyReferencedExternalFiles { |
| 697 NSMutableSet* referencedFiles = [NSMutableSet set]; | 679 NSMutableSet* referencedFiles = [NSMutableSet set]; |
| 698 if (!_browserState) | 680 if (!_browserState) |
| 699 return referencedFiles; | 681 return referencedFiles; |
| 700 // Check the currently open tabs for external files. | 682 // Check the currently open tabs for external files. |
| 701 for (Tab* tab in self) { | 683 for (Tab* tab in self) { |
| 702 if (UrlIsExternalFileReference(tab.url)) { | 684 if (UrlIsExternalFileReference(tab.url)) { |
| 703 NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName()); | 685 NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState) | 729 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState) |
| 748 : nullptr; | 730 : nullptr; |
| 749 web::NavigationManager* navigationManager = [closedTab navigationManager]; | 731 web::NavigationManager* navigationManager = [closedTab navigationManager]; |
| 750 DCHECK(navigationManager); | 732 DCHECK(navigationManager); |
| 751 int itemCount = navigationManager->GetItemCount(); | 733 int itemCount = navigationManager->GetItemCount(); |
| 752 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) { | 734 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) { |
| 753 restoreService->CreateHistoricalTab( | 735 restoreService->CreateHistoricalTab( |
| 754 sessions::IOSLiveTab::GetForWebState(closedTab.webState), | 736 sessions::IOSLiveTab::GetForWebState(closedTab.webState), |
| 755 closedTabIndex); | 737 closedTabIndex); |
| 756 } | 738 } |
| 757 // This needs to be called before the tab is removed from the list. | |
| 758 Tab* newSelection = | |
| 759 [_orderController determineNewSelectedTabFromRemovedTab:closedTab]; | |
| 760 | 739 |
| 761 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]); | 740 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]); |
| 762 | 741 |
| 763 // If closing the current tab, clear |_currentTab| before sending any | 742 // If a non-current Tab is closed, save the session (it will be saved by |
| 764 // notification. This avoids various parts of the code getting confused | 743 // TabModelObserversBridge if the currentTab has been closed). |
| 765 // when the current tab isn't in the tab model. | 744 BOOL needToSaveSession = (closedTab != self.currentTab); |
| 766 Tab* savedCurrentTab = _currentTab; | |
| 767 if (closedTab == _currentTab) | |
| 768 _currentTab.reset(nil); | |
| 769 | 745 |
| 770 DCHECK([_tabRetainer containsObject:closedTab]); | 746 DCHECK([_tabRetainer containsObject:closedTab]); |
| 771 [_tabRetainer removeObject:closedTab]; | 747 [_tabRetainer removeObject:closedTab]; |
| 772 | 748 |
| 773 // The WebState is owned by the associated Tab, so it is safe to ignore | 749 // The WebState is owned by the associated Tab, so it is safe to ignore |
| 774 // the result and won't cause a memory leak. Once the ownership is moved | 750 // the result and won't cause a memory leak. Once the ownership is moved |
| 775 // to WebStateList, this function will return a std::unique_ptr<> and the | 751 // to WebStateList, this function will return a std::unique_ptr<> and the |
| 776 // object destroyed as expected, so it will fine to ignore the result then | 752 // object destroyed as expected, so it will fine to ignore the result then |
| 777 // too. See http://crbug.com/546222 for progress of changing the ownership | 753 // too. See http://crbug.com/546222 for progress of changing the ownership |
| 778 // of the WebStates. | 754 // of the WebStates. |
| 779 ignore_result(_webStateList.DetachWebStateAt(closedTabIndex)); | 755 ignore_result(_webStateList.DetachWebStateAt(closedTabIndex)); |
| 780 | 756 |
| 781 // Current tab has closed, update the selected tab and swap in its | 757 if (needToSaveSession) |
| 782 // contents. There is nothing to do if a non-selected tab is closed as | |
| 783 // the selection isn't index-based, therefore it hasn't changed. | |
| 784 // -changeSelectedTabFrom: will persist the state change, so only do it | |
| 785 // if the selection isn't changing. | |
| 786 if (closedTab == savedCurrentTab) { | |
| 787 [self changeSelectedTabFrom:closedTab to:newSelection persistState:NO]; | |
| 788 } else { | |
| 789 [self saveSessionImmediately:NO]; | 758 [self saveSessionImmediately:NO]; |
| 790 } | |
| 791 ++_closedTabCount; | |
| 792 } | 759 } |
| 793 | 760 |
| 794 - (void)navigationCommittedInTab:(Tab*)tab { | 761 - (void)navigationCommittedInTab:(Tab*)tab { |
| 795 if (self.offTheRecord) | 762 if (self.offTheRecord) |
| 796 return; | 763 return; |
| 797 if (![tab navigationManager]) | 764 if (![tab navigationManager]) |
| 798 return; | 765 return; |
| 799 | 766 |
| 800 // See if the navigation was within a page; if so ignore it. | 767 // See if the navigation was within a page; if so ignore it. |
| 801 web::NavigationItem* previousItem = | 768 web::NavigationItem* previousItem = |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 count++; | 802 count++; |
| 836 } | 803 } |
| 837 return count; | 804 return count; |
| 838 } | 805 } |
| 839 | 806 |
| 840 #pragma mark - Private methods | 807 #pragma mark - Private methods |
| 841 | 808 |
| 842 - (SessionWindowIOS*)windowForSavingSession { | 809 - (SessionWindowIOS*)windowForSavingSession { |
| 843 // Background tabs will already have their state preserved, but not the | 810 // Background tabs will already have their state preserved, but not the |
| 844 // fg tab. Do it now. | 811 // fg tab. Do it now. |
| 845 [_currentTab recordStateInHistory]; | 812 [self.currentTab recordStateInHistory]; |
| 846 | 813 |
| 847 // Build the array of sessions. Copy the session objects as the saving will | 814 // Build the array of sessions. Copy the session objects as the saving will |
| 848 // be done on a separate thread. | 815 // be done on a separate thread. |
| 849 // TODO(crbug.com/661986): This could get expensive especially since this | 816 // TODO(crbug.com/661986): This could get expensive especially since this |
| 850 // window may never be saved (if another call comes in before the delay). | 817 // window may never be saved (if another call comes in before the delay). |
| 851 SessionWindowIOS* window = [[[SessionWindowIOS alloc] init] autorelease]; | 818 SessionWindowIOS* window = [[[SessionWindowIOS alloc] init] autorelease]; |
| 852 for (Tab* tab in self) { | 819 for (Tab* tab in self) { |
| 853 web::WebState* webState = tab.webState; | 820 web::WebState* webState = tab.webState; |
| 854 DCHECK(webState); | 821 DCHECK(webState); |
| 855 [window addSerializedSessionStorage:webState->BuildSessionStorage()]; | 822 [window addSerializedSessionStorage:webState->BuildSessionStorage()]; |
| 856 } | 823 } |
| 857 window.selectedIndex = [self indexOfTab:_currentTab]; | 824 window.selectedIndex = [self indexOfTab:self.currentTab]; |
| 858 return window; | 825 return window; |
| 859 } | 826 } |
| 860 | 827 |
| 861 - (BOOL)isNTPTab:(Tab*)tab { | 828 - (BOOL)isNTPTab:(Tab*)tab { |
| 862 std::string host = tab.url.host(); | 829 std::string host = tab.url.host(); |
| 863 return host == kChromeUINewTabHost || host == kChromeUIBookmarksHost; | 830 return host == kChromeUINewTabHost || host == kChromeUIBookmarksHost; |
| 864 } | 831 } |
| 865 | 832 |
| 866 - (void)changeSelectedTabFrom:(Tab*)oldTab | |
| 867 to:(Tab*)newTab | |
| 868 persistState:(BOOL)persist { | |
| 869 if (oldTab) { | |
| 870 // Save state, such as scroll position, before switching tabs. | |
| 871 if (oldTab != newTab && persist) | |
| 872 [oldTab recordStateInHistory]; | |
| 873 [self postNotificationName:kTabModelTabDeselectedNotification | |
| 874 withTab:oldTab]; | |
| 875 } | |
| 876 | |
| 877 // No Tab to select (e.g. the last Tab has been closed). | |
| 878 if ([self indexOfTab:newTab] == NSNotFound) | |
| 879 return; | |
| 880 | |
| 881 _currentTab.reset(newTab); | |
| 882 if (newTab) { | |
| 883 [_observers tabModel:self | |
| 884 didChangeActiveTab:newTab | |
| 885 previousTab:oldTab | |
| 886 atIndex:[self indexOfTab:newTab]]; | |
| 887 [newTab updateLastVisitedTimestamp]; | |
| 888 ++_openedTabCount; | |
| 889 } | |
| 890 BOOL loadingFinished = [newTab.webController loadPhase] == web::PAGE_LOADED; | |
| 891 if (loadingFinished) { | |
| 892 // Persist the session state. | |
| 893 [self saveSessionImmediately:NO]; | |
| 894 } | |
| 895 } | |
| 896 | |
| 897 - (void)updateSnapshotCache:(Tab*)tab { | |
| 898 NSMutableSet* set = [NSMutableSet set]; | |
| 899 NSUInteger index = [self indexOfTab:tab]; | |
| 900 if (index > 0) { | |
| 901 Tab* previousTab = [self tabAtIndex:(index - 1)]; | |
| 902 [set addObject:previousTab.tabId]; | |
| 903 } | |
| 904 if (index < self.count - 1) { | |
| 905 Tab* nextTab = [self tabAtIndex:(index + 1)]; | |
| 906 [set addObject:nextTab.tabId]; | |
| 907 } | |
| 908 [SnapshotCache sharedInstance].pinnedIDs = set; | |
| 909 } | |
| 910 | |
| 911 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab { | 833 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab { |
| 912 // A scoped_nsobject is used rather than an NSDictionary with static | 834 // A scoped_nsobject is used rather than an NSDictionary with static |
| 913 // initializer dictionaryWithObject, because that approach adds the dictionary | 835 // initializer dictionaryWithObject, because that approach adds the dictionary |
| 914 // to the autorelease pool, which in turn holds Tab alive longer than | 836 // to the autorelease pool, which in turn holds Tab alive longer than |
| 915 // necessary. | 837 // necessary. |
| 916 base::scoped_nsobject<NSDictionary> userInfo( | 838 base::scoped_nsobject<NSDictionary> userInfo( |
| 917 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); | 839 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); |
| 918 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName | 840 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName |
| 919 object:self | 841 object:self |
| 920 userInfo:userInfo]; | 842 userInfo:userInfo]; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 971 DCHECK(opener.webState); | 893 DCHECK(opener.webState); |
| 972 _webStateList.SetOpenerOfWebStateAt(index, opener.webState); | 894 _webStateList.SetOpenerOfWebStateAt(index, opener.webState); |
| 973 } | 895 } |
| 974 } | 896 } |
| 975 | 897 |
| 976 // Update the selected tab if there was a selected Tab in the saved session. | 898 // Update the selected tab if there was a selected Tab in the saved session. |
| 977 if (window.selectedIndex != NSNotFound) { | 899 if (window.selectedIndex != NSNotFound) { |
| 978 NSUInteger selectedIndex = window.selectedIndex + oldCount; | 900 NSUInteger selectedIndex = window.selectedIndex + oldCount; |
| 979 DCHECK_LT(selectedIndex, self.count); | 901 DCHECK_LT(selectedIndex, self.count); |
| 980 DCHECK([self tabAtIndex:selectedIndex]); | 902 DCHECK([self tabAtIndex:selectedIndex]); |
| 981 [self changeSelectedTabFrom:_currentTab | 903 |
| 982 to:[self tabAtIndex:selectedIndex] | 904 if (persistState && self.currentTab) |
| 983 persistState:persistState]; | 905 [self.currentTab recordStateInHistory]; |
| 906 _webStateList.ActivateWebStateAt(static_cast<int>(selectedIndex)); |
| 984 } | 907 } |
| 985 | 908 |
| 986 // If there was only one tab and it was the new tab page, clobber it. | 909 // If there was only one tab and it was the new tab page, clobber it. |
| 987 BOOL closedNTPTab = NO; | 910 BOOL closedNTPTab = NO; |
| 988 if (oldCount == 1) { | 911 if (oldCount == 1) { |
| 989 Tab* tab = [self tabAtIndex:0]; | 912 Tab* tab = [self tabAtIndex:0]; |
| 990 if (tab.url == GURL(kChromeUINewTabURL)) { | 913 if (tab.url == GURL(kChromeUINewTabURL)) { |
| 991 [self closeTab:tab]; | 914 [self closeTab:tab]; |
| 992 closedNTPTab = YES; | 915 closedNTPTab = YES; |
| 993 oldCount = 0; | 916 oldCount = 0; |
| 994 } | 917 } |
| 995 } | 918 } |
| 996 if (_tabUsageRecorder) { | 919 if (_tabUsageRecorder) { |
| 997 NSMutableArray<Tab*>* restoredTabs = | 920 NSMutableArray<Tab*>* restoredTabs = |
| 998 [NSMutableArray arrayWithCapacity:_webStateList.count() - oldCount]; | 921 [NSMutableArray arrayWithCapacity:_webStateList.count() - oldCount]; |
| 999 for (int index = oldCount; index < _webStateList.count(); ++index) { | 922 for (int index = oldCount; index < _webStateList.count(); ++index) { |
| 1000 web::WebState* webState = _webStateList.GetWebStateAt(index); | 923 web::WebState* webState = _webStateList.GetWebStateAt(index); |
| 1001 [restoredTabs addObject:LegacyTabHelper::GetTabForWebState(webState)]; | 924 [restoredTabs addObject:LegacyTabHelper::GetTabForWebState(webState)]; |
| 1002 } | 925 } |
| 1003 _tabUsageRecorder->InitialRestoredTabs(_currentTab, restoredTabs); | 926 _tabUsageRecorder->InitialRestoredTabs(self.currentTab, restoredTabs); |
| 1004 } | 927 } |
| 1005 return closedNTPTab; | 928 return closedNTPTab; |
| 1006 } | 929 } |
| 1007 | 930 |
| 1008 #pragma mark - Notification Handlers | 931 #pragma mark - Notification Handlers |
| 1009 | 932 |
| 1010 // Called when UIApplicationWillResignActiveNotification is received. | 933 // Called when UIApplicationWillResignActiveNotification is received. |
| 1011 - (void)willResignActive:(NSNotification*)notify { | 934 - (void)willResignActive:(NSNotification*)notify { |
| 1012 if (webUsageEnabled_ && _currentTab) { | 935 if (webUsageEnabled_ && self.currentTab) { |
| 1013 [[SnapshotCache sharedInstance] | 936 [[SnapshotCache sharedInstance] |
| 1014 willBeSavedGreyWhenBackgrounding:_currentTab.get().tabId]; | 937 willBeSavedGreyWhenBackgrounding:self.currentTab.tabId]; |
| 1015 } | 938 } |
| 1016 } | 939 } |
| 1017 | 940 |
| 1018 // Called when UIApplicationDidEnterBackgroundNotification is received. | 941 // Called when UIApplicationDidEnterBackgroundNotification is received. |
| 1019 - (void)applicationDidEnterBackground:(NSNotification*)notify { | 942 - (void)applicationDidEnterBackground:(NSNotification*)notify { |
| 1020 if (!_browserState) | 943 if (!_browserState) |
| 1021 return; | 944 return; |
| 1022 | 945 |
| 1023 // Evict all the certificate policies except for the current entries of the | 946 // Evict all the certificate policies except for the current entries of the |
| 1024 // active sessions. | 947 // active sessions. |
| 1025 CleanCertificatePolicyCache( | 948 CleanCertificatePolicyCache( |
| 1026 &_clearPoliciesTaskTracker, | 949 &_clearPoliciesTaskTracker, |
| 1027 web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), | 950 web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), |
| 1028 web::BrowserState::GetCertificatePolicyCache(_browserState), | 951 web::BrowserState::GetCertificatePolicyCache(_browserState), |
| 1029 &_webStateList); | 952 &_webStateList); |
| 1030 | 953 |
| 1031 if (_tabUsageRecorder) | 954 if (_tabUsageRecorder) |
| 1032 _tabUsageRecorder->AppDidEnterBackground(); | 955 _tabUsageRecorder->AppDidEnterBackground(); |
| 1033 | 956 |
| 1034 // Normally, the session is saved after some timer expires but since the app | 957 // Normally, the session is saved after some timer expires but since the app |
| 1035 // is about to enter the background send YES to save the session immediately. | 958 // is about to enter the background send YES to save the session immediately. |
| 1036 [self saveSessionImmediately:YES]; | 959 [self saveSessionImmediately:YES]; |
| 1037 | 960 |
| 1038 // Write out a grey version of the current website to disk. | 961 // Write out a grey version of the current website to disk. |
| 1039 if (webUsageEnabled_ && _currentTab) { | 962 if (webUsageEnabled_ && self.currentTab) { |
| 1040 [[SnapshotCache sharedInstance] | 963 [[SnapshotCache sharedInstance] |
| 1041 saveGreyInBackgroundForSessionID:_currentTab.get().tabId]; | 964 saveGreyInBackgroundForSessionID:self.currentTab.tabId]; |
| 1042 } | 965 } |
| 1043 } | 966 } |
| 1044 | 967 |
| 1045 // Called when UIApplicationWillEnterForegroundNotification is received. | 968 // Called when UIApplicationWillEnterForegroundNotification is received. |
| 1046 - (void)applicationWillEnterForeground:(NSNotification*)notify { | 969 - (void)applicationWillEnterForeground:(NSNotification*)notify { |
| 1047 if (_tabUsageRecorder) { | 970 if (_tabUsageRecorder) { |
| 1048 _tabUsageRecorder->AppWillEnterForeground(); | 971 _tabUsageRecorder->AppWillEnterForeground(); |
| 1049 } | 972 } |
| 1050 } | 973 } |
| 1051 | 974 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1072 web::NavigationManager::WebLoadParams params(URL); | 995 web::NavigationManager::WebLoadParams params(URL); |
| 1073 params.referrer = referrer; | 996 params.referrer = referrer; |
| 1074 params.transition_type = ui::PAGE_TRANSITION_TYPED; | 997 params.transition_type = ui::PAGE_TRANSITION_TYPED; |
| 1075 [[tab webController] loadWithParams:params]; | 998 [[tab webController] loadWithParams:params]; |
| 1076 [tab webController].webUsageEnabled = webUsageEnabled_; | 999 [tab webController].webUsageEnabled = webUsageEnabled_; |
| 1077 [self insertTab:tab atIndex:index opener:parentTab]; | 1000 [self insertTab:tab atIndex:index opener:parentTab]; |
| 1078 return tab; | 1001 return tab; |
| 1079 } | 1002 } |
| 1080 | 1003 |
| 1081 @end | 1004 @end |
| OLD | NEW |