| 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 <list> | 7 #include <list> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 // The |index| parameter can be set to | 150 // The |index| parameter can be set to |
| 151 // TabModelConstants::kTabPositionAutomatically if the caller doesn't have a | 151 // TabModelConstants::kTabPositionAutomatically if the caller doesn't have a |
| 152 // preference for the position of the tab. | 152 // preference for the position of the tab. |
| 153 - (Tab*)insertTabWithLoadParams: | 153 - (Tab*)insertTabWithLoadParams: |
| 154 (const web::NavigationManager::WebLoadParams&)params | 154 (const web::NavigationManager::WebLoadParams&)params |
| 155 windowName:(NSString*)windowName | 155 windowName:(NSString*)windowName |
| 156 opener:(Tab*)parentTab | 156 opener:(Tab*)parentTab |
| 157 openedByDOM:(BOOL)openedByDOM | 157 openedByDOM:(BOOL)openedByDOM |
| 158 atIndex:(NSUInteger)index | 158 atIndex:(NSUInteger)index |
| 159 inBackground:(BOOL)inBackground; | 159 inBackground:(BOOL)inBackground; |
| 160 |
| 160 // Call to switch the selected tab. Broadcasts about the change in selection. | 161 // Call to switch the selected tab. Broadcasts about the change in selection. |
| 161 // It's ok for |newTab| to be nil in case the last tab is going away. In that | 162 // It's ok for |newTab| to be nil in case the last tab is going away. In that |
| 162 // case, the "tab deselected" notification gets sent, but no corresponding | 163 // case, the "tab deselected" notification gets sent, but no corresponding |
| 163 // "tab selected" notification is sent. |persist| indicates whether or not | 164 // "tab selected" notification is sent. |persist| indicates whether or not |
| 164 // the tab's state should be persisted in history upon switching. | 165 // the tab's state should be persisted in history upon switching. |
| 165 - (void)changeSelectedTabFrom:(Tab*)oldTab | 166 - (void)changeSelectedTabFrom:(Tab*)oldTab |
| 166 to:(Tab*)newTab | 167 to:(Tab*)newTab |
| 167 persistState:(BOOL)persist; | 168 persistState:(BOOL)persist; |
| 169 |
| 168 // Tells the snapshot cache the adjacent tab session ids. | 170 // Tells the snapshot cache the adjacent tab session ids. |
| 169 - (void)updateSnapshotCache:(Tab*)tab; | 171 - (void)updateSnapshotCache:(Tab*)tab; |
| 172 |
| 170 // Helper method that posts a notification with the given name with |tab| | 173 // Helper method that posts a notification with the given name with |tab| |
| 171 // in the userInfo dictionary under the kTabModelTabKey. | 174 // in the userInfo dictionary under the kTabModelTabKey. |
| 172 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab; | 175 - (void)postNotificationName:(NSString*)notificationName withTab:(Tab*)tab; |
| 176 |
| 177 // Helper method to restore a saved session and control if the state should |
| 178 // be persisted or not. Used to implement the public -restoreSessionWindow: |
| 179 // method and restoring session in the initialiser. |
| 180 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window |
| 181 persistState:(BOOL)persistState; |
| 182 |
| 173 @end | 183 @end |
| 174 | 184 |
| 175 @implementation TabModel | 185 @implementation TabModel |
| 176 | 186 |
| 177 @synthesize browserState = _browserState; | 187 @synthesize browserState = _browserState; |
| 178 @synthesize sessionID = _sessionID; | 188 @synthesize sessionID = _sessionID; |
| 179 @synthesize webUsageEnabled = webUsageEnabled_; | 189 @synthesize webUsageEnabled = webUsageEnabled_; |
| 180 | 190 |
| 181 #pragma mark - Overriden | 191 #pragma mark - Overriden |
| 182 | 192 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 // Normal browser states are the only ones to get tab restore. Tab sync | 259 // Normal browser states are the only ones to get tab restore. Tab sync |
| 250 // handles incognito browser states by filtering on profile, so it's | 260 // handles incognito browser states by filtering on profile, so it's |
| 251 // important to the backend code to always have a sync window delegate. | 261 // important to the backend code to always have a sync window delegate. |
| 252 if (!_browserState->IsOffTheRecord()) { | 262 if (!_browserState->IsOffTheRecord()) { |
| 253 // Set up the usage recorder before tabs are created. | 263 // Set up the usage recorder before tabs are created. |
| 254 _tabUsageRecorder.reset(new TabUsageRecorder(self)); | 264 _tabUsageRecorder.reset(new TabUsageRecorder(self)); |
| 255 } | 265 } |
| 256 _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self)); | 266 _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self)); |
| 257 | 267 |
| 258 _tabs.reset([[NSMutableArray alloc] init]); | 268 _tabs.reset([[NSMutableArray alloc] init]); |
| 259 NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; | |
| 260 if (window) { | 269 if (window) { |
| 261 web::WebState::CreateParams params(_browserState); | 270 DCHECK([_observers empty]); |
| 262 for (CRWNavigationManagerStorage* session in window.sessions) { | 271 // Restore the session and reset the session metrics (as the event have |
| 263 std::unique_ptr<web::WebState> webState = | 272 // not been generated by the user but by a cold start cycle). |
| 264 web::WebState::Create(params, session); | 273 [self restoreSessionWindow:window persistState:NO]; |
| 265 DCHECK_EQ(webState->GetBrowserState(), _browserState); | 274 [self resetSessionMetrics]; |
| 266 // Restore the CertificatePolicyCache. | |
| 267 UpdateCertificatePolicyCacheFromWebState(webState.get()); | |
| 268 // Create a new tab for each entry in the window. Don't send delegate | |
| 269 // notifications for each restored tab, only when all done. | |
| 270 base::scoped_nsobject<Tab> tab( | |
| 271 [[Tab alloc] initWithWebState:std::move(webState) model:self]); | |
| 272 [tab webController].usePlaceholderOverlay = YES; | |
| 273 [tab fetchFavicon]; | |
| 274 [_tabs addObject:tab]; | |
| 275 | |
| 276 TabParentingGlobalObserver::GetInstance()->OnTabParented( | |
| 277 tab.get().webState); | |
| 278 } | |
| 279 if ([_tabs count]) { | |
| 280 DCHECK(window.selectedIndex < [_tabs count]); | |
| 281 _currentTab.reset([self tabAtIndex:window.selectedIndex]); | |
| 282 DCHECK(_currentTab); | |
| 283 if (_tabUsageRecorder) | |
| 284 _tabUsageRecorder->InitialRestoredTabs(_currentTab, _tabs); | |
| 285 // Perform initializations for affiliated objects which update the | |
| 286 // session information related to the current tab. | |
| 287 [_currentTab updateLastVisitedTimestamp]; | |
| 288 [self saveSessionImmediately:NO]; | |
| 289 } | |
| 290 } | 275 } |
| 291 | 276 |
| 292 _orderController.reset( | 277 _orderController.reset( |
| 293 [[TabModelOrderController alloc] initWithTabModel:self]); | 278 [[TabModelOrderController alloc] initWithTabModel:self]); |
| 279 |
| 294 // Register for resign active notification. | 280 // Register for resign active notification. |
| 295 [defaultCenter addObserver:self | 281 [[NSNotificationCenter defaultCenter] |
| 296 selector:@selector(willResignActive:) | 282 addObserver:self |
| 297 name:UIApplicationWillResignActiveNotification | 283 selector:@selector(willResignActive:) |
| 298 object:nil]; | 284 name:UIApplicationWillResignActiveNotification |
| 285 object:nil]; |
| 299 // Register for background notification. | 286 // Register for background notification. |
| 300 [defaultCenter addObserver:self | 287 [[NSNotificationCenter defaultCenter] |
| 301 selector:@selector(applicationDidEnterBackground:) | 288 addObserver:self |
| 302 name:UIApplicationDidEnterBackgroundNotification | 289 selector:@selector(applicationDidEnterBackground:) |
| 303 object:nil]; | 290 name:UIApplicationDidEnterBackgroundNotification |
| 291 object:nil]; |
| 304 // Register for foregrounding notification. | 292 // Register for foregrounding notification. |
| 305 [defaultCenter addObserver:self | 293 [[NSNotificationCenter defaultCenter] |
| 306 selector:@selector(applicationWillEnterForeground:) | 294 addObserver:self |
| 307 name:UIApplicationWillEnterForegroundNotification | 295 selector:@selector(applicationWillEnterForeground:) |
| 308 object:nil]; | 296 name:UIApplicationWillEnterForegroundNotification |
| 297 object:nil]; |
| 309 | 298 |
| 310 // Associate with ios::ChromeBrowserState. | 299 // Associate with ios::ChromeBrowserState. |
| 311 RegisterTabModelWithChromeBrowserState(_browserState, self); | 300 RegisterTabModelWithChromeBrowserState(_browserState, self); |
| 312 } | 301 } |
| 313 return self; | 302 return self; |
| 314 } | 303 } |
| 315 | 304 |
| 316 - (instancetype)init { | 305 - (instancetype)init { |
| 317 NOTREACHED(); | 306 NOTREACHED(); |
| 318 return nil; | 307 return nil; |
| 319 } | 308 } |
| 320 | 309 |
| 321 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window { | 310 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window { |
| 322 DCHECK(_browserState); | 311 return [self restoreSessionWindow:window persistState:YES]; |
| 323 DCHECK(window); | |
| 324 NSArray* sessions = window.sessions; | |
| 325 if (!sessions.count) | |
| 326 return NO; | |
| 327 size_t oldCount = [_tabs count]; | |
| 328 size_t index = oldCount; | |
| 329 web::WebState::CreateParams params(_browserState); | |
| 330 for (CRWNavigationManagerStorage* session in sessions) { | |
| 331 std::unique_ptr<web::WebState> webState = | |
| 332 web::WebState::Create(params, session); | |
| 333 DCHECK_EQ(webState->GetBrowserState(), _browserState); | |
| 334 Tab* tab = [self insertTabWithWebState:std::move(webState) atIndex:index++]; | |
| 335 tab.webController.usePlaceholderOverlay = YES; | |
| 336 // Restore the CertificatePolicyCache. Note that after calling Pass() | |
| 337 // |webState| is invalid, so we need to get the webstate from |tab|. | |
| 338 UpdateCertificatePolicyCacheFromWebState(tab.webState); | |
| 339 } | |
| 340 DCHECK([_tabs count] > oldCount); | |
| 341 // If any tab was restored, the saved selected tab must be selected. | |
| 342 if ([_tabs count] > oldCount) { | |
| 343 NSUInteger selectedIndex = window.selectedIndex; | |
| 344 if (selectedIndex == NSNotFound) | |
| 345 selectedIndex = oldCount; | |
| 346 else | |
| 347 selectedIndex += oldCount; | |
| 348 DCHECK(selectedIndex < [_tabs count]); | |
| 349 Tab* newTab = [self tabAtIndex:selectedIndex]; | |
| 350 DCHECK(newTab); | |
| 351 [self changeSelectedTabFrom:_currentTab to:newTab persistState:YES]; | |
| 352 | |
| 353 // If there was only one tab and it was the new tab page, clobber it. | |
| 354 if (oldCount == 1) { | |
| 355 Tab* tab = [_tabs objectAtIndex:0]; | |
| 356 if (tab.url == GURL(kChromeUINewTabURL)) { | |
| 357 [self closeTab:tab]; | |
| 358 if (_tabUsageRecorder) | |
| 359 _tabUsageRecorder->InitialRestoredTabs(_currentTab, _tabs); | |
| 360 return YES; | |
| 361 } | |
| 362 } | |
| 363 if (_tabUsageRecorder) { | |
| 364 _tabUsageRecorder->InitialRestoredTabs( | |
| 365 _currentTab, | |
| 366 [_tabs subarrayWithRange:NSMakeRange(oldCount, | |
| 367 [_tabs count] - oldCount)]); | |
| 368 } | |
| 369 } | |
| 370 return NO; | |
| 371 } | 312 } |
| 372 | 313 |
| 373 - (void)saveSessionImmediately:(BOOL)immediately { | 314 - (void)saveSessionImmediately:(BOOL)immediately { |
| 374 // Do nothing if there are tabs in the model but no selected tab. This is | 315 // Do nothing if there are tabs in the model but no selected tab. This is |
| 375 // a transitional state. | 316 // a transitional state. |
| 376 if ((!_currentTab && [_tabs count]) || !_browserState) | 317 if ((!_currentTab && [_tabs count]) || !_browserState) |
| 377 return; | 318 return; |
| 378 [_sessionService saveWindow:self.windowForSavingSession | 319 [_sessionService saveWindow:self.windowForSavingSession |
| 379 forBrowserState:_browserState | 320 forBrowserState:_browserState |
| 380 immediately:immediately]; | 321 immediately:immediately]; |
| (...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 // initializer dictionaryWithObject, because that approach adds the dictionary | 936 // initializer dictionaryWithObject, because that approach adds the dictionary |
| 996 // to the autorelease pool, which in turn holds Tab alive longer than | 937 // to the autorelease pool, which in turn holds Tab alive longer than |
| 997 // necessary. | 938 // necessary. |
| 998 base::scoped_nsobject<NSDictionary> userInfo( | 939 base::scoped_nsobject<NSDictionary> userInfo( |
| 999 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); | 940 [[NSDictionary alloc] initWithObjectsAndKeys:tab, kTabModelTabKey, nil]); |
| 1000 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName | 941 [[NSNotificationCenter defaultCenter] postNotificationName:notificationName |
| 1001 object:self | 942 object:self |
| 1002 userInfo:userInfo]; | 943 userInfo:userInfo]; |
| 1003 } | 944 } |
| 1004 | 945 |
| 946 - (BOOL)restoreSessionWindow:(SessionWindowIOS*)window |
| 947 persistState:(BOOL)persistState { |
| 948 DCHECK(_browserState); |
| 949 DCHECK(window); |
| 950 |
| 951 NSArray* sessions = window.sessions; |
| 952 if (!sessions.count) |
| 953 return NO; |
| 954 |
| 955 size_t oldCount = [_tabs count]; |
| 956 web::WebState::CreateParams params(_browserState); |
| 957 |
| 958 for (CRWNavigationManagerStorage* session in sessions) { |
| 959 std::unique_ptr<web::WebState> webState = |
| 960 web::WebState::Create(params, session); |
| 961 DCHECK_EQ(webState->GetBrowserState(), _browserState); |
| 962 Tab* tab = |
| 963 [self insertTabWithWebState:std::move(webState) atIndex:[_tabs count]]; |
| 964 tab.webController.usePlaceholderOverlay = YES; |
| 965 |
| 966 // Restore the CertificatePolicyCache (note that webState is invalid after |
| 967 // passing it via move semantic to -insertTabWithWebState:atIndex:). |
| 968 UpdateCertificatePolicyCacheFromWebState(tab.webState); |
| 969 } |
| 970 DCHECK_GT([_tabs count], oldCount); |
| 971 |
| 972 // Update the selected tab if there was a selected Tab in the saved session. |
| 973 if (window.selectedIndex != NSNotFound) { |
| 974 NSUInteger selectedIndex = window.selectedIndex + oldCount; |
| 975 DCHECK_LT(selectedIndex, [_tabs count]); |
| 976 DCHECK([self tabAtIndex:selectedIndex]); |
| 977 [self changeSelectedTabFrom:_currentTab |
| 978 to:[self tabAtIndex:selectedIndex] |
| 979 persistState:persistState]; |
| 980 } |
| 981 |
| 982 // If there was only one tab and it was the new tab page, clobber it. |
| 983 BOOL closedNTPTab = NO; |
| 984 if (oldCount == 1) { |
| 985 Tab* tab = [_tabs objectAtIndex:0]; |
| 986 if (tab.url == GURL(kChromeUINewTabURL)) { |
| 987 [self closeTab:tab]; |
| 988 closedNTPTab = YES; |
| 989 oldCount = 0; |
| 990 } |
| 991 } |
| 992 if (_tabUsageRecorder) { |
| 993 _tabUsageRecorder->InitialRestoredTabs( |
| 994 _currentTab, |
| 995 [_tabs |
| 996 subarrayWithRange:NSMakeRange(oldCount, [_tabs count] - oldCount)]); |
| 997 } |
| 998 return closedNTPTab; |
| 999 } |
| 1000 |
| 1005 #pragma mark - Notification Handlers | 1001 #pragma mark - Notification Handlers |
| 1006 | 1002 |
| 1007 // Called when UIApplicationWillResignActiveNotification is received. | 1003 // Called when UIApplicationWillResignActiveNotification is received. |
| 1008 - (void)willResignActive:(NSNotification*)notify { | 1004 - (void)willResignActive:(NSNotification*)notify { |
| 1009 if (webUsageEnabled_ && _currentTab) { | 1005 if (webUsageEnabled_ && _currentTab) { |
| 1010 [[SnapshotCache sharedInstance] | 1006 [[SnapshotCache sharedInstance] |
| 1011 willBeSavedGreyWhenBackgrounding:_currentTab.get().tabId]; | 1007 willBeSavedGreyWhenBackgrounding:_currentTab.get().tabId]; |
| 1012 } | 1008 } |
| 1013 } | 1009 } |
| 1014 | 1010 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1075 web::NavigationManager::WebLoadParams params(URL); | 1071 web::NavigationManager::WebLoadParams params(URL); |
| 1076 params.referrer = referrer; | 1072 params.referrer = referrer; |
| 1077 params.transition_type = ui::PAGE_TRANSITION_TYPED; | 1073 params.transition_type = ui::PAGE_TRANSITION_TYPED; |
| 1078 [[tab webController] loadWithParams:params]; | 1074 [[tab webController] loadWithParams:params]; |
| 1079 [tab webController].webUsageEnabled = webUsageEnabled_; | 1075 [tab webController].webUsageEnabled = webUsageEnabled_; |
| 1080 [self insertTab:tab atIndex:index]; | 1076 [self insertTab:tab atIndex:index]; |
| 1081 return tab; | 1077 return tab; |
| 1082 } | 1078 } |
| 1083 | 1079 |
| 1084 @end | 1080 @end |
| OLD | NEW |