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