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_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 { |
| 231 DCHECK([_observers empty]); | 232 DCHECK([_observers empty]); |
| 232 // browserStateDestroyed should always have been called before destruction. | 233 // browserStateDestroyed should always have been called before destruction. |
| 233 DCHECK(!_browserState); | 234 DCHECK(!_browserState); |
| 234 | 235 |
| 235 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 236 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 236 | 237 |
| 237 // Clear weak pointer to WebStateListMetricsObserver before destroying it. | 238 // Clear weak pointer to WebStateListMetricsObserver before destroying it. |
| 238 _webStateListMetricsObserver = nullptr; | 239 _webStateListMetricsObserver = nullptr; |
| 239 | 240 |
| 240 // Unregister all observers before closing all the tabs. | |
| 241 for (const auto& webStateListObserver : _webStateListObservers) | |
| 242 _webStateList->RemoveObserver(webStateListObserver.get()); | |
| 243 _webStateListObservers.clear(); | |
| 244 | |
| 245 // Make sure the tabs do clean after themselves. It is important for | 241 // Make sure the tabs do clean after themselves. It is important for |
| 246 // removeObserver: to be called first otherwise a lot of unecessary work will | 242 // removeObserver: to be called first otherwise a lot of unecessary work will |
|
rohitrao (ping after 24h)
2017/04/03 17:49:35
This removeObserver comment might be stale now? W
sdefresne
2017/04/04 13:47:56
The comment says that all observer registered with
| |
| 247 // happen on -closeAllTabs. | 243 // happen on -closeAllTabs. |
| 248 [self closeAllTabs]; | 244 [self closeAllTabs]; |
| 249 | 245 |
| 246 // Unregister all observers after closing all the tabs as some of them are | |
|
rohitrao (ping after 24h)
2017/04/03 17:49:35
We used to do this before closing all tabs. Do yo
sdefresne
2017/04/04 13:47:56
As _observers is empty (i.e. there are no TabModel
| |
| 247 // required to properly clean up the Tabs. | |
| 248 for (const auto& webStateListObserver : _webStateListObservers) | |
| 249 _webStateList->RemoveObserver(webStateListObserver.get()); | |
| 250 _webStateListObservers.clear(); | |
| 251 | |
| 250 _clearPoliciesTaskTracker.TryCancelAll(); | 252 _clearPoliciesTaskTracker.TryCancelAll(); |
| 251 | 253 |
| 252 [super dealloc]; | 254 [super dealloc]; |
| 253 } | 255 } |
| 254 | 256 |
| 255 #pragma mark - Public methods | 257 #pragma mark - Public methods |
| 256 | 258 |
| 257 - (Tab*)currentTab { | 259 - (Tab*)currentTab { |
| 258 web::WebState* webState = _webStateList->GetActiveWebState(); | 260 web::WebState* webState = _webStateList->GetActiveWebState(); |
| 259 return webState ? LegacyTabHelper::GetTabForWebState(webState) : nil; | 261 return webState ? LegacyTabHelper::GetTabForWebState(webState) : nil; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 287 } | 289 } |
| 288 | 290 |
| 289 - (WebStateList*)webStateList { | 291 - (WebStateList*)webStateList { |
| 290 return _webStateList.get(); | 292 return _webStateList.get(); |
| 291 } | 293 } |
| 292 | 294 |
| 293 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window | 295 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window |
| 294 sessionService:(SessionServiceIOS*)service | 296 sessionService:(SessionServiceIOS*)service |
| 295 browserState:(ios::ChromeBrowserState*)browserState { | 297 browserState:(ios::ChromeBrowserState*)browserState { |
| 296 if ((self = [super init])) { | 298 if ((self = [super init])) { |
| 297 _tabRetainer.reset([[NSMutableSet alloc] init]); | |
| 298 _observers.reset([[TabModelObservers observers] retain]); | 299 _observers.reset([[TabModelObservers observers] retain]); |
| 299 | 300 |
| 300 _webStateListDelegate = | 301 _webStateListDelegate = |
| 301 base::MakeUnique<TabModelWebStateListDelegate>(self); | 302 base::MakeUnique<TabModelWebStateListDelegate>(self); |
| 302 _webStateList = base::MakeUnique<WebStateList>( | 303 _webStateList = base::MakeUnique<WebStateList>(_webStateListDelegate.get()); |
| 303 _webStateListDelegate.get(), WebStateList::WebStateBorrowed); | |
| 304 | 304 |
| 305 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc] | 305 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc] |
| 306 initWithWebStateList:_webStateList.get() | 306 initWithWebStateList:_webStateList.get() |
| 307 proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]); | 307 proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]); |
| 308 | 308 |
| 309 _browserState = browserState; | 309 _browserState = browserState; |
| 310 DCHECK(_browserState); | 310 DCHECK(_browserState); |
| 311 | 311 |
| 312 // Normal browser states are the only ones to get tab restore. Tab sync | 312 // Normal browser states are the only ones to get tab restore. Tab sync |
| 313 // handles incognito browser states by filtering on profile, so it's | 313 // handles incognito browser states by filtering on profile, so it's |
| 314 // important to the backend code to always have a sync window delegate. | 314 // important to the backend code to always have a sync window delegate. |
| 315 if (!_browserState->IsOffTheRecord()) { | 315 if (!_browserState->IsOffTheRecord()) { |
| 316 // Set up the usage recorder before tabs are created. | 316 // Set up the usage recorder before tabs are created. |
| 317 _tabUsageRecorder = base::MakeUnique<TabUsageRecorder>(self); | 317 _tabUsageRecorder = base::MakeUnique<TabUsageRecorder>(self); |
| 318 } | 318 } |
| 319 _syncedWindowDelegate = | 319 _syncedWindowDelegate = |
| 320 base::MakeUnique<TabModelSyncedWindowDelegate>(self); | 320 base::MakeUnique<TabModelSyncedWindowDelegate>(self); |
| 321 | 321 |
| 322 // There must be a valid session service defined to consume session windows. | 322 // There must be a valid session service defined to consume session windows. |
| 323 DCHECK(service); | 323 DCHECK(service); |
| 324 _sessionService.reset([service retain]); | 324 _sessionService.reset([service retain]); |
| 325 | 325 |
| 326 _webStateListObservers.push_back(base::MakeUnique< | |
| 327 WebStateListObserverBridge>([ | |
| 328 [TabModelClosingWebStateObserver alloc] | |
| 329 initWithTabModel:self | |
| 330 restoreService:IOSChromeTabRestoreServiceFactory::GetForBrowserState( | |
| 331 _browserState)])); | |
| 326 _webStateListObservers.push_back( | 332 _webStateListObservers.push_back( |
| 327 base::MakeUnique<SnapshotCacheWebStateListObserver>( | 333 base::MakeUnique<SnapshotCacheWebStateListObserver>( |
| 328 [SnapshotCache sharedInstance])); | 334 [SnapshotCache sharedInstance])); |
| 329 if (_tabUsageRecorder) { | 335 if (_tabUsageRecorder) { |
| 330 _webStateListObservers.push_back( | 336 _webStateListObservers.push_back( |
| 331 base::MakeUnique<TabUsageRecorderWebStateListObserver>( | 337 base::MakeUnique<TabUsageRecorderWebStateListObserver>( |
| 332 _tabUsageRecorder.get())); | 338 _tabUsageRecorder.get())); |
| 333 } | 339 } |
| 334 _webStateListObservers.push_back(base::MakeUnique<TabParentingObserver>()); | 340 _webStateListObservers.push_back(base::MakeUnique<TabParentingObserver>()); |
| 335 _webStateListObservers.push_back( | 341 _webStateListObservers.push_back( |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 params.referrer = referrer; | 474 params.referrer = referrer; |
| 469 params.transition_type = transition; | 475 params.transition_type = transition; |
| 470 return [self insertTabWithLoadParams:params | 476 return [self insertTabWithLoadParams:params |
| 471 opener:parentTab | 477 opener:parentTab |
| 472 openedByDOM:openedByDOM | 478 openedByDOM:openedByDOM |
| 473 atIndex:index | 479 atIndex:index |
| 474 inBackground:inBackground]; | 480 inBackground:inBackground]; |
| 475 } | 481 } |
| 476 | 482 |
| 477 - (Tab*)insertTabWithLoadParams: | 483 - (Tab*)insertTabWithLoadParams: |
| 478 (const web::NavigationManager::WebLoadParams&)params | 484 (const web::NavigationManager::WebLoadParams&)loadParams |
| 479 opener:(Tab*)parentTab | 485 opener:(Tab*)parentTab |
| 480 openedByDOM:(BOOL)openedByDOM | 486 openedByDOM:(BOOL)openedByDOM |
| 481 atIndex:(NSUInteger)index | 487 atIndex:(NSUInteger)index |
| 482 inBackground:(BOOL)inBackground { | 488 inBackground:(BOOL)inBackground { |
| 483 DCHECK(_browserState); | 489 DCHECK(_browserState); |
| 484 base::scoped_nsobject<Tab> tab([[Tab alloc] initWithBrowserState:_browserState | 490 |
| 485 opener:parentTab | 491 web::WebState::CreateParams createParams(self.browserState); |
| 486 openedByDOM:openedByDOM | 492 createParams.created_with_opener = openedByDOM; |
| 487 model:self]); | 493 std::unique_ptr<web::WebState> webState = web::WebState::Create(createParams); |
| 494 | |
| 495 web::WebState* webStatePtr = webState.get(); | |
| 496 if (index == TabModelConstants::kTabPositionAutomatically) { | |
| 497 _webStateList->AppendWebState(loadParams.transition_type, | |
| 498 std::move(webState), | |
| 499 WebStateOpener(parentTab.webState)); | |
| 500 } else { | |
| 501 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | |
| 502 const int insertion_index = static_cast<int>(index); | |
| 503 _webStateList->InsertWebState(insertion_index, std::move(webState)); | |
| 504 if (parentTab.webState) { | |
| 505 _webStateList->SetOpenerOfWebStateAt(insertion_index, | |
| 506 WebStateOpener(parentTab.webState)); | |
| 507 } | |
| 508 } | |
| 509 | |
| 510 Tab* tab = LegacyTabHelper::GetTabForWebState(webStatePtr); | |
| 511 DCHECK(tab); | |
| 512 | |
| 488 [tab webController].webUsageEnabled = webUsageEnabled_; | 513 [tab webController].webUsageEnabled = webUsageEnabled_; |
| 489 | 514 |
| 490 [self insertTab:tab | |
| 491 atIndex:index | |
| 492 opener:parentTab | |
| 493 transition:params.transition_type]; | |
| 494 | |
| 495 if (!inBackground && _tabUsageRecorder) | 515 if (!inBackground && _tabUsageRecorder) |
| 496 _tabUsageRecorder->TabCreatedForSelection(tab); | 516 _tabUsageRecorder->TabCreatedForSelection(tab); |
| 497 | 517 |
| 498 [[tab webController] loadWithParams:params]; | 518 [[tab webController] loadWithParams:loadParams]; |
| 519 | |
| 499 // Force the page to start loading even if it's in the background. | 520 // Force the page to start loading even if it's in the background. |
| 500 if (webUsageEnabled_) | 521 if (webUsageEnabled_) |
| 501 [[tab webController] triggerPendingLoad]; | 522 [[tab webController] triggerPendingLoad]; |
| 502 NSDictionary* userInfo = @{ | 523 NSDictionary* userInfo = @{ |
| 503 kTabModelTabKey : tab, | 524 kTabModelTabKey : tab, |
| 504 kTabModelOpenInBackgroundKey : @(inBackground), | 525 kTabModelOpenInBackgroundKey : @(inBackground), |
| 505 }; | 526 }; |
| 506 [[NSNotificationCenter defaultCenter] | 527 [[NSNotificationCenter defaultCenter] |
| 507 postNotificationName:kTabModelNewTabWillOpenNotification | 528 postNotificationName:kTabModelNewTabWillOpenNotification |
| 508 object:self | 529 object:self |
| 509 userInfo:userInfo]; | 530 userInfo:userInfo]; |
| 510 | 531 |
| 511 if (!inBackground) | 532 if (!inBackground) |
| 512 [self setCurrentTab:tab]; | 533 [self setCurrentTab:tab]; |
| 513 | 534 |
| 514 return tab; | 535 return tab; |
| 515 } | 536 } |
| 516 | 537 |
| 517 - (Tab*)insertTabWithWebState:(std::unique_ptr<web::WebState>)webState | |
| 518 atIndex:(NSUInteger)index { | |
| 519 DCHECK(_browserState); | |
| 520 DCHECK_EQ(webState->GetBrowserState(), _browserState); | |
| 521 base::scoped_nsobject<Tab> tab( | |
| 522 [[Tab alloc] initWithWebState:std::move(webState) model:self]); | |
| 523 [tab webController].webUsageEnabled = webUsageEnabled_; | |
| 524 [self insertTab:tab atIndex:index]; | |
| 525 return tab; | |
| 526 } | |
| 527 | |
| 528 - (void)insertTab:(Tab*)tab | |
| 529 atIndex:(NSUInteger)index | |
| 530 opener:(Tab*)parentTab | |
| 531 transition:(ui::PageTransition)transition { | |
| 532 DCHECK(tab); | |
| 533 DCHECK(![_tabRetainer containsObject:tab]); | |
| 534 | |
| 535 [_tabRetainer addObject:tab]; | |
| 536 if (index == TabModelConstants::kTabPositionAutomatically) { | |
| 537 _webStateList->AppendWebState( | |
| 538 transition, tab.webState, | |
| 539 WebStateOpener(parentTab.webState, tab.openerNavigationIndex)); | |
| 540 } else { | |
| 541 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | |
| 542 const int insertion_index = static_cast<int>(index); | |
| 543 _webStateList->InsertWebState(insertion_index, tab.webState); | |
| 544 if (parentTab.webState) { | |
| 545 _webStateList->SetOpenerOfWebStateAt( | |
| 546 insertion_index, | |
| 547 WebStateOpener(parentTab.webState, tab.openerNavigationIndex)); | |
| 548 } | |
| 549 } | |
| 550 | |
| 551 // Persist the session due to a new tab being inserted. If this is a | |
| 552 // background tab (will not become active), saving now will capture the | |
| 553 // state properly. If it does eventually become active, another save will | |
| 554 // be triggered to properly capture the end result. | |
| 555 [self saveSessionImmediately:NO]; | |
| 556 } | |
| 557 | |
| 558 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index opener:(Tab*)parentTab { | |
| 559 DCHECK(tab); | |
| 560 DCHECK(![_tabRetainer containsObject:tab]); | |
| 561 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | |
| 562 | |
| 563 [self insertTab:tab | |
| 564 atIndex:index | |
| 565 opener:parentTab | |
| 566 transition:ui::PAGE_TRANSITION_GENERATED]; | |
| 567 } | |
| 568 | |
| 569 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { | |
| 570 DCHECK(tab); | |
| 571 DCHECK(![_tabRetainer containsObject:tab]); | |
| 572 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | |
| 573 | |
| 574 [self insertTab:tab atIndex:index opener:GetOpenerForTab(self, tab)]; | |
| 575 } | |
| 576 | |
| 577 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { | 538 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { |
| 578 DCHECK([_tabRetainer containsObject:tab]); | |
| 579 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX)); | 539 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX)); |
| 580 int fromIndex = _webStateList->GetIndexOfWebState(tab.webState); | 540 int fromIndex = _webStateList->GetIndexOfWebState(tab.webState); |
| 581 _webStateList->MoveWebStateAt(fromIndex, static_cast<int>(toIndex)); | 541 _webStateList->MoveWebStateAt(fromIndex, static_cast<int>(toIndex)); |
| 582 } | 542 } |
| 583 | 543 |
| 584 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { | |
| 585 DCHECK([_tabRetainer containsObject:oldTab]); | |
| 586 DCHECK(![_tabRetainer containsObject:newTab]); | |
| 587 | |
| 588 int index = _webStateList->GetIndexOfWebState(oldTab.webState); | |
| 589 DCHECK_NE(index, WebStateList::kInvalidIndex); | |
| 590 DCHECK_GE(index, 0); | |
| 591 | |
| 592 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); | |
| 593 [_tabRetainer removeObject:oldTab]; | |
| 594 [_tabRetainer addObject:newTab]; | |
| 595 [newTab setParentTabModel:self]; | |
| 596 | |
| 597 // The WebState is owned by the associated Tab, so it is safe to ignore | |
| 598 // the result and won't cause a memory leak. Once the ownership is moved | |
| 599 // to WebStateList, this function will return a std::unique_ptr<> and the | |
| 600 // object destroyed as expected, so it will fine to ignore the result then | |
| 601 // too. See http://crbug.com/546222 for progress of changing the ownership | |
| 602 // of the WebStates. | |
| 603 ignore_result(_webStateList->ReplaceWebStateAt(index, newTab.webState)); | |
| 604 | |
| 605 Tab* parentTab = GetOpenerForTab(self, newTab); | |
| 606 if (parentTab) { | |
| 607 _webStateList->SetOpenerOfWebStateAt( | |
| 608 index, | |
| 609 WebStateOpener(parentTab.webState, newTab.openerNavigationIndex)); | |
| 610 } | |
| 611 | |
| 612 [oldTab setParentTabModel:nil]; | |
| 613 [oldTab close]; | |
| 614 } | |
| 615 | |
| 616 - (void)closeTabAtIndex:(NSUInteger)index { | 544 - (void)closeTabAtIndex:(NSUInteger)index { |
| 617 DCHECK(index < self.count); | 545 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); |
| 618 [self closeTab:[self tabAtIndex:index]]; | 546 _webStateList->CloseWebStateAt(static_cast<int>(index)); |
| 619 } | 547 } |
| 620 | 548 |
| 621 - (void)closeTab:(Tab*)tab { | 549 - (void)closeTab:(Tab*)tab { |
| 622 // Ensure the tab stays alive long enough for us to send out the | 550 [self closeTabAtIndex:[self indexOfTab:tab]]; |
| 623 // notice of its destruction to the delegate. | |
| 624 [_observers tabModel:self willRemoveTab:tab]; | |
| 625 [tab close]; // Note it is not safe to access the tab after 'close'. | |
| 626 } | 551 } |
| 627 | 552 |
| 628 - (void)closeAllTabs { | 553 - (void)closeAllTabs { |
| 629 for (NSInteger i = self.count - 1; i >= 0; --i) | 554 _webStateList->CloseAllWebStates(); |
| 630 [self closeTabAtIndex:i]; | |
| 631 [[NSNotificationCenter defaultCenter] | 555 [[NSNotificationCenter defaultCenter] |
| 632 postNotificationName:kTabModelAllTabsDidCloseNotification | 556 postNotificationName:kTabModelAllTabsDidCloseNotification |
| 633 object:self]; | 557 object:self]; |
| 634 } | 558 } |
| 635 | 559 |
| 636 - (void)haltAllTabs { | 560 - (void)haltAllTabs { |
| 637 for (Tab* tab in self) { | 561 for (Tab* tab in self) { |
| 638 [tab terminateNetworkActivity]; | 562 [tab terminateNetworkActivity]; |
| 639 } | 563 } |
| 640 } | 564 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 718 | 642 |
| 719 // NOTE: This can be called multiple times, so must be robust against that. | 643 // NOTE: This can be called multiple times, so must be robust against that. |
| 720 - (void)browserStateDestroyed { | 644 - (void)browserStateDestroyed { |
| 721 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 645 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 722 if (_browserState) { | 646 if (_browserState) { |
| 723 UnregisterTabModelFromChromeBrowserState(_browserState, self); | 647 UnregisterTabModelFromChromeBrowserState(_browserState, self); |
| 724 } | 648 } |
| 725 _browserState = nullptr; | 649 _browserState = nullptr; |
| 726 } | 650 } |
| 727 | 651 |
| 728 // Called when a tab is closing, but before its CRWWebController is destroyed. | |
| 729 // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel. | |
| 730 - (void)didCloseTab:(Tab*)closedTab { | |
| 731 DCHECK(closedTab); | |
| 732 DCHECK([_tabRetainer containsObject:closedTab]); | |
| 733 int closedTabIndex = _webStateList->GetIndexOfWebState(closedTab.webState); | |
| 734 DCHECK_NE(closedTabIndex, WebStateList::kInvalidIndex); | |
| 735 DCHECK_GE(closedTabIndex, 0); | |
| 736 | |
| 737 // Let the sessions::TabRestoreService know about that new tab. | |
| 738 sessions::TabRestoreService* restoreService = | |
| 739 _browserState | |
| 740 ? IOSChromeTabRestoreServiceFactory::GetForBrowserState(_browserState) | |
| 741 : nullptr; | |
| 742 web::NavigationManager* navigationManager = [closedTab navigationManager]; | |
| 743 DCHECK(navigationManager); | |
| 744 int itemCount = navigationManager->GetItemCount(); | |
| 745 if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) { | |
| 746 restoreService->CreateHistoricalTab( | |
| 747 sessions::IOSLiveTab::GetForWebState(closedTab.webState), | |
| 748 closedTabIndex); | |
| 749 } | |
| 750 | |
| 751 base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]); | |
| 752 | |
| 753 // If a non-current Tab is closed, save the session (it will be saved by | |
| 754 // TabModelObserversBridge if the currentTab has been closed). | |
| 755 BOOL needToSaveSession = (closedTab != self.currentTab); | |
| 756 | |
| 757 DCHECK([_tabRetainer containsObject:closedTab]); | |
| 758 [_tabRetainer removeObject:closedTab]; | |
| 759 | |
| 760 // The WebState is owned by the associated Tab, so it is safe to ignore | |
| 761 // the result and won't cause a memory leak. Once the ownership is moved | |
| 762 // to WebStateList, this function will return a std::unique_ptr<> and the | |
| 763 // object destroyed as expected, so it will fine to ignore the result then | |
| 764 // too. See http://crbug.com/546222 for progress of changing the ownership | |
| 765 // of the WebStates. | |
| 766 ignore_result(_webStateList->DetachWebStateAt(closedTabIndex)); | |
| 767 | |
| 768 if (needToSaveSession) | |
| 769 [self saveSessionImmediately:NO]; | |
| 770 } | |
| 771 | |
| 772 - (void)navigationCommittedInTab:(Tab*)tab | 652 - (void)navigationCommittedInTab:(Tab*)tab |
| 773 previousItem:(web::NavigationItem*)previousItem { | 653 previousItem:(web::NavigationItem*)previousItem { |
| 774 if (self.offTheRecord) | 654 if (self.offTheRecord) |
| 775 return; | 655 return; |
| 776 if (![tab navigationManager]) | 656 if (![tab navigationManager]) |
| 777 return; | 657 return; |
| 778 | 658 |
| 779 // See if the navigation was within a page; if so ignore it. | 659 // See if the navigation was within a page; if so ignore it. |
| 780 if (previousItem) { | 660 if (previousItem) { |
| 781 GURL previousURL = previousItem->GetURL(); | 661 GURL previousURL = previousItem->GetURL(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 821 // fg tab. Do it now. | 701 // fg tab. Do it now. |
| 822 [self.currentTab recordStateInHistory]; | 702 [self.currentTab recordStateInHistory]; |
| 823 | 703 |
| 824 // Build the array of sessions. Copy the session objects as the saving will | 704 // Build the array of sessions. Copy the session objects as the saving will |
| 825 // be done on a separate thread. | 705 // be done on a separate thread. |
| 826 // TODO(crbug.com/661986): This could get expensive especially since this | 706 // TODO(crbug.com/661986): This could get expensive especially since this |
| 827 // window may never be saved (if another call comes in before the delay). | 707 // window may never be saved (if another call comes in before the delay). |
| 828 NSMutableArray<CRWSessionStorage*>* sessions = | 708 NSMutableArray<CRWSessionStorage*>* sessions = |
| 829 [NSMutableArray arrayWithCapacity:[self count]]; | 709 [NSMutableArray arrayWithCapacity:[self count]]; |
| 830 | 710 |
| 831 for (Tab* tab in self) { | 711 for (int index = 0; index < _webStateList->count(); ++index) { |
| 832 DCHECK(tab.webState); | 712 web::WebState* webState = _webStateList->GetWebStateAt(index); |
| 833 [sessions addObject:tab.webState->BuildSessionStorage()]; | 713 web::SerializableUserDataManager* userDataManager = |
| 714 web::SerializableUserDataManager::FromWebState(webState); | |
| 715 | |
| 716 WebStateOpener opener = _webStateList->GetOpenerOfWebStateAt(index); | |
| 717 if (opener.opener) { | |
| 718 Tab* parentTab = LegacyTabHelper::GetTabForWebState(opener.opener); | |
| 719 userDataManager->AddSerializableData(parentTab.tabId, kOpenerIDKey); | |
| 720 userDataManager->AddSerializableData(@(opener.navigation_index), | |
| 721 kOpenerNavigationIndexKey); | |
| 722 } else { | |
| 723 userDataManager->AddSerializableData([NSNull null], kOpenerIDKey); | |
| 724 userDataManager->AddSerializableData([NSNull null], | |
| 725 kOpenerNavigationIndexKey); | |
| 726 } | |
| 727 | |
| 728 [sessions addObject:webState->BuildSessionStorage()]; | |
| 834 } | 729 } |
| 835 | 730 |
| 836 return [[[SessionWindowIOS alloc] | 731 return [[[SessionWindowIOS alloc] |
| 837 initWithSessions:sessions | 732 initWithSessions:sessions |
| 838 selectedIndex:[self indexOfTab:self.currentTab]] autorelease]; | 733 selectedIndex:[self indexOfTab:self.currentTab]] autorelease]; |
| 839 } | 734 } |
| 840 | 735 |
| 841 - (BOOL)isNTPTab:(Tab*)tab { | |
| 842 std::string host = tab.url.host(); | |
| 843 return host == kChromeUINewTabHost || host == kChromeUIBookmarksHost; | |
| 844 } | |
| 845 | |
| 846 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab { | 736 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab { |
| 847 // A scoped_nsobject is used rather than an NSDictionary with static | 737 // A scoped_nsobject is used rather than an NSDictionary with static |
| 848 // initializer dictionaryWithObject, because that approach adds the dictionary | 738 // initializer dictionaryWithObject, because that approach adds the dictionary |
| 849 // to the autorelease pool, which in turn holds Tab alive longer than | 739 // to the autorelease pool, which in turn holds Tab alive longer than |
| 850 // necessary. | 740 // necessary. |
| 851 base::scoped_nsobject<NSDictionary> userInfo( | 741 base::scoped_nsobject<NSDictionary> userInfo( |
| 852 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); | 742 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); |
| 853 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName | 743 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName |
| 854 object:self | 744 object:self |
| 855 userInfo:userInfo]; | 745 userInfo:userInfo]; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 873 | 763 |
| 874 base::scoped_nsobject<NSMutableArray<Tab*>> restoredTabs( | 764 base::scoped_nsobject<NSMutableArray<Tab*>> restoredTabs( |
| 875 [[NSMutableArray alloc] initWithCapacity:sessions.count]); | 765 [[NSMutableArray alloc] initWithCapacity:sessions.count]); |
| 876 | 766 |
| 877 // Recreate all the restored Tabs and add them to the WebStateList without | 767 // Recreate all the restored Tabs and add them to the WebStateList without |
| 878 // any opener-opened relationship (as the n-th restored Tab opener may be | 768 // any opener-opened relationship (as the n-th restored Tab opener may be |
| 879 // at an index larger than n). Then in a second pass fix the openers. | 769 // at an index larger than n). Then in a second pass fix the openers. |
| 880 for (CRWSessionStorage* session in sessions) { | 770 for (CRWSessionStorage* session in sessions) { |
| 881 std::unique_ptr<web::WebState> webState = | 771 std::unique_ptr<web::WebState> webState = |
| 882 web::WebState::CreateWithStorageSession(params, session); | 772 web::WebState::CreateWithStorageSession(params, session); |
| 883 base::scoped_nsobject<Tab> tab( | 773 _webStateList->InsertWebState(_webStateList->count(), std::move(webState)); |
| 884 [[Tab alloc] initWithWebState:std::move(webState) model:self]); | 774 } |
| 885 [tab webController].webUsageEnabled = webUsageEnabled_; | 775 |
| 886 [tab webController].usePlaceholderOverlay = YES; | 776 for (int index = oldCount; index < _webStateList->count(); ++index) { |
| 777 web::WebState* webState = _webStateList->GetWebStateAt(index); | |
| 778 Tab* tab = LegacyTabHelper::GetTabForWebState(webState); | |
| 779 tab.webController.webUsageEnabled = webUsageEnabled_; | |
| 780 tab.webController.usePlaceholderOverlay = YES; | |
| 887 | 781 |
| 888 // Restore the CertificatePolicyCache (note that webState is invalid after | 782 // Restore the CertificatePolicyCache (note that webState is invalid after |
| 889 // passing it via move semantic to -initWithWebState:model:). | 783 // passing it via move semantic to -initWithWebState:model:). |
| 890 UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]); | 784 UpdateCertificatePolicyCacheFromWebState(policyCache, [tab webState]); |
| 891 [self insertTab:tab atIndex:self.count opener:nil]; | 785 [restoredTabs addObject:tab]; |
| 892 [restoredTabs addObject:tab.get()]; | |
| 893 } | 786 } |
| 894 | 787 |
| 895 DCHECK_EQ(sessions.count, [restoredTabs count]); | 788 DCHECK_EQ(sessions.count, [restoredTabs count]); |
| 896 DCHECK_GT(_webStateList->count(), oldCount); | 789 DCHECK_GT(_webStateList->count(), oldCount); |
| 897 | 790 |
| 898 // Fix openers now that all Tabs have been restored. Only look for an opener | 791 // Fix openers now that all Tabs have been restored. Only look for an opener |
| 899 // Tab in the newly restored Tabs and not in the already open Tabs. | 792 // Tab in the newly restored Tabs and not in the already open Tabs. |
| 900 for (int index = oldCount; index < _webStateList->count(); ++index) { | 793 for (int index = oldCount; index < _webStateList->count(); ++index) { |
| 901 DCHECK_GE(index, oldCount); | 794 DCHECK_GE(index, oldCount); |
| 902 NSUInteger tabIndex = static_cast<NSUInteger>(index - oldCount); | 795 NSUInteger tabIndex = static_cast<NSUInteger>(index - oldCount); |
| 903 Tab* tab = [restoredTabs objectAtIndex:tabIndex]; | 796 Tab* tab = [restoredTabs objectAtIndex:tabIndex]; |
| 904 Tab* opener = GetOpenerForTab(restoredTabs.get(), tab); | 797 WebStateOpener opener = GetOpenerForTab(restoredTabs.get(), tab); |
| 905 if (opener) { | 798 if (opener.opener) |
| 906 DCHECK(opener.webState); | 799 _webStateList->SetOpenerOfWebStateAt(index, opener); |
| 907 _webStateList->SetOpenerOfWebStateAt( | |
| 908 index, WebStateOpener(opener.webState, tab.openerNavigationIndex)); | |
| 909 } | |
| 910 } | 800 } |
| 911 | 801 |
| 912 // Update the selected tab if there was a selected Tab in the saved session. | 802 // Update the selected tab if there was a selected Tab in the saved session. |
| 913 if (window.selectedIndex != NSNotFound) { | 803 if (window.selectedIndex != NSNotFound) { |
| 914 NSUInteger selectedIndex = window.selectedIndex + oldCount; | 804 NSUInteger selectedIndex = window.selectedIndex + oldCount; |
| 915 DCHECK_LT(selectedIndex, self.count); | 805 DCHECK_LT(selectedIndex, self.count); |
| 916 DCHECK([self tabAtIndex:selectedIndex]); | 806 DCHECK([self tabAtIndex:selectedIndex]); |
| 917 | 807 |
| 918 if (persistState && self.currentTab) | 808 if (persistState && self.currentTab) |
| 919 [self.currentTab recordStateInHistory]; | 809 [self.currentTab recordStateInHistory]; |
| 920 _webStateList->ActivateWebStateAt(static_cast<int>(selectedIndex)); | 810 _webStateList->ActivateWebStateAt(static_cast<int>(selectedIndex)); |
| 921 } | 811 } |
| 922 | 812 |
| 923 // If there was only one tab and it was the new tab page, clobber it. | 813 // If there was only one tab and it was the new tab page, clobber it. |
| 924 BOOL closedNTPTab = NO; | 814 BOOL closedNTPTab = NO; |
| 925 if (oldCount == 1) { | 815 if (oldCount == 1) { |
| 926 Tab* tab = [self tabAtIndex:0]; | 816 Tab* tab = [self tabAtIndex:0]; |
| 927 if (tab.url == GURL(kChromeUINewTabURL)) { | 817 if (tab.url == GURL(kChromeUINewTabURL)) { |
| 928 [self closeTab:tab]; | 818 [self closeTab:tab]; |
| 929 closedNTPTab = YES; | 819 closedNTPTab = YES; |
| 930 oldCount = 0; | 820 oldCount = 0; |
| 931 } | 821 } |
| 932 } | 822 } |
| 933 if (_tabUsageRecorder) { | 823 if (_tabUsageRecorder) |
| 934 NSMutableArray<Tab*>* restoredTabs = | |
| 935 [NSMutableArray arrayWithCapacity:_webStateList->count() - oldCount]; | |
| 936 for (int index = oldCount; index < _webStateList->count(); ++index) { | |
| 937 web::WebState* webState = _webStateList->GetWebStateAt(index); | |
| 938 [restoredTabs addObject:LegacyTabHelper::GetTabForWebState(webState)]; | |
| 939 } | |
| 940 _tabUsageRecorder->InitialRestoredTabs(self.currentTab, restoredTabs); | 824 _tabUsageRecorder->InitialRestoredTabs(self.currentTab, restoredTabs); |
| 941 } | |
| 942 return closedNTPTab; | 825 return closedNTPTab; |
| 943 } | 826 } |
| 944 | 827 |
| 945 #pragma mark - Notification Handlers | 828 #pragma mark - Notification Handlers |
| 946 | 829 |
| 947 // Called when UIApplicationWillResignActiveNotification is received. | 830 // Called when UIApplicationWillResignActiveNotification is received. |
| 948 - (void)willResignActive:(NSNotification*)notify { | 831 - (void)willResignActive:(NSNotification*)notify { |
| 949 if (webUsageEnabled_ && self.currentTab) { | 832 if (webUsageEnabled_ && self.currentTab) { |
| 950 [[SnapshotCache sharedInstance] | 833 [[SnapshotCache sharedInstance] |
| 951 willBeSavedGreyWhenBackgrounding:self.currentTab.tabId]; | 834 willBeSavedGreyWhenBackgrounding:self.currentTab.tabId]; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 980 } | 863 } |
| 981 | 864 |
| 982 // Called when UIApplicationWillEnterForegroundNotification is received. | 865 // Called when UIApplicationWillEnterForegroundNotification is received. |
| 983 - (void)applicationWillEnterForeground:(NSNotification*)notify { | 866 - (void)applicationWillEnterForeground:(NSNotification*)notify { |
| 984 if (_tabUsageRecorder) { | 867 if (_tabUsageRecorder) { |
| 985 _tabUsageRecorder->AppWillEnterForeground(); | 868 _tabUsageRecorder->AppWillEnterForeground(); |
| 986 } | 869 } |
| 987 } | 870 } |
| 988 | 871 |
| 989 @end | 872 @end |
| OLD | NEW |