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