| 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 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #import "ios/chrome/browser/metrics/tab_usage_recorder.h" | 26 #import "ios/chrome/browser/metrics/tab_usage_recorder.h" |
| 27 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" | 27 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" |
| 28 #import "ios/chrome/browser/sessions/session_service.h" | 28 #import "ios/chrome/browser/sessions/session_service.h" |
| 29 #import "ios/chrome/browser/sessions/session_window.h" | 29 #import "ios/chrome/browser/sessions/session_window.h" |
| 30 #import "ios/chrome/browser/snapshots/snapshot_cache.h" | 30 #import "ios/chrome/browser/snapshots/snapshot_cache.h" |
| 31 #include "ios/chrome/browser/tab_parenting_global_observer.h" | 31 #include "ios/chrome/browser/tab_parenting_global_observer.h" |
| 32 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" | 32 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" |
| 33 #import "ios/chrome/browser/tabs/tab.h" | 33 #import "ios/chrome/browser/tabs/tab.h" |
| 34 #import "ios/chrome/browser/tabs/tab_model_list.h" | 34 #import "ios/chrome/browser/tabs/tab_model_list.h" |
| 35 #import "ios/chrome/browser/tabs/tab_model_observers.h" | 35 #import "ios/chrome/browser/tabs/tab_model_observers.h" |
| 36 #import "ios/chrome/browser/tabs/tab_model_observers_bridge.h" |
| 36 #import "ios/chrome/browser/tabs/tab_model_order_controller.h" | 37 #import "ios/chrome/browser/tabs/tab_model_order_controller.h" |
| 37 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" | 38 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" |
| 39 #import "ios/chrome/browser/tabs/tab_parenting_observer.h" |
| 38 #import "ios/chrome/browser/xcallback_parameters.h" | 40 #import "ios/chrome/browser/xcallback_parameters.h" |
| 39 #import "ios/shared/chrome/browser/tabs/web_state_list.h" | 41 #import "ios/shared/chrome/browser/tabs/web_state_list.h" |
| 40 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h
" | 42 #import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h
" |
| 43 #import "ios/shared/chrome/browser/tabs/web_state_list_metrics_observer.h" |
| 41 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" | 44 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" |
| 42 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" | 45 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" |
| 43 #import "ios/web/navigation/crw_session_controller.h" | 46 #import "ios/web/navigation/crw_session_controller.h" |
| 44 #include "ios/web/public/browser_state.h" | 47 #include "ios/web/public/browser_state.h" |
| 45 #include "ios/web/public/certificate_policy_cache.h" | 48 #include "ios/web/public/certificate_policy_cache.h" |
| 46 #include "ios/web/public/navigation_item.h" | 49 #include "ios/web/public/navigation_item.h" |
| 47 #import "ios/web/public/navigation_manager.h" | 50 #import "ios/web/public/navigation_manager.h" |
| 48 #include "ios/web/public/web_thread.h" | 51 #include "ios/web/public/web_thread.h" |
| 49 #import "ios/web/web_state/ui/crw_web_controller.h" | 52 #import "ios/web/web_state/ui/crw_web_controller.h" |
| 50 #import "ios/web/web_state/web_state_impl.h" | 53 #import "ios/web/web_state/web_state_impl.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 | 136 |
| 134 // Helper providing NSFastEnumeration implementation over the WebStateList. | 137 // Helper providing NSFastEnumeration implementation over the WebStateList. |
| 135 base::scoped_nsobject<WebStateListFastEnumerationHelper> | 138 base::scoped_nsobject<WebStateListFastEnumerationHelper> |
| 136 _fastEnumerationHelper; | 139 _fastEnumerationHelper; |
| 137 | 140 |
| 138 // Used to keep the Tabs alive while the corresponding WebStates are stored | 141 // Used to keep the Tabs alive while the corresponding WebStates are stored |
| 139 // in the WebStateList (as Tabs currently own their WebState). Remove once | 142 // in the WebStateList (as Tabs currently own their WebState). Remove once |
| 140 // WebState owns the associated Tab. | 143 // WebState owns the associated Tab. |
| 141 base::scoped_nsobject<NSMutableSet<Tab*>> _tabRetainer; | 144 base::scoped_nsobject<NSMutableSet<Tab*>> _tabRetainer; |
| 142 | 145 |
| 146 // WebStateListObserver bridges to react to modifications of the model (may |
| 147 // send notification, translate and forward events, update metrics, ...). |
| 148 std::vector<std::unique_ptr<WebStateListObserver>> _observerBridges; |
| 149 |
| 143 // Maintains policy for where new tabs go and the selection when a tab | 150 // Maintains policy for where new tabs go and the selection when a tab |
| 144 // is removed. | 151 // is removed. |
| 145 base::scoped_nsobject<TabModelOrderController> _orderController; | 152 base::scoped_nsobject<TabModelOrderController> _orderController; |
| 146 // The delegate for sync. | 153 // The delegate for sync. |
| 147 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; | 154 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; |
| 148 // Currently selected tab. May be nil. | 155 // Currently selected tab. May be nil. |
| 149 base::WeakNSObject<Tab> _currentTab; | 156 base::WeakNSObject<Tab> _currentTab; |
| 150 | 157 |
| 151 // Counters for metrics. | 158 // Counters for metrics. |
| 152 int _openedTabCount; | 159 int _openedTabCount; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 @synthesize webUsageEnabled = webUsageEnabled_; | 226 @synthesize webUsageEnabled = webUsageEnabled_; |
| 220 | 227 |
| 221 #pragma mark - Overriden | 228 #pragma mark - Overriden |
| 222 | 229 |
| 223 - (void)dealloc { | 230 - (void)dealloc { |
| 224 DCHECK([_observers empty]); | 231 DCHECK([_observers empty]); |
| 225 // browserStateDestroyed should always have been called before destruction. | 232 // browserStateDestroyed should always have been called before destruction. |
| 226 DCHECK(!_browserState); | 233 DCHECK(!_browserState); |
| 227 | 234 |
| 228 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 235 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 236 |
| 237 // Unregister all listeners before closing all the tabs. |
| 238 for (const auto& observerBridge : _observerBridges) |
| 239 _webStateList.RemoveObserver(observerBridge.get()); |
| 240 _observerBridges.clear(); |
| 241 |
| 229 // Make sure the tabs do clean after themselves. It is important for | 242 // Make sure the tabs do clean after themselves. It is important for |
| 230 // removeObserver: to be called first otherwise a lot of unecessary work will | 243 // removeObserver: to be called first otherwise a lot of unecessary work will |
| 231 // happen on -closeAllTabs. | 244 // happen on -closeAllTabs. |
| 232 [self closeAllTabs]; | 245 [self closeAllTabs]; |
| 233 | 246 |
| 234 _clearPoliciesTaskTracker.TryCancelAll(); | 247 _clearPoliciesTaskTracker.TryCancelAll(); |
| 235 | 248 |
| 236 [super dealloc]; | 249 [super dealloc]; |
| 237 } | 250 } |
| 238 | 251 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 sessionService:(SessionServiceIOS*)service | 292 sessionService:(SessionServiceIOS*)service |
| 280 browserState:(ios::ChromeBrowserState*)browserState { | 293 browserState:(ios::ChromeBrowserState*)browserState { |
| 281 if ((self = [super init])) { | 294 if ((self = [super init])) { |
| 282 _tabRetainer.reset([[NSMutableSet alloc] init]); | 295 _tabRetainer.reset([[NSMutableSet alloc] init]); |
| 283 _observers.reset([[TabModelObservers observers] retain]); | 296 _observers.reset([[TabModelObservers observers] retain]); |
| 284 | 297 |
| 285 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc] | 298 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc] |
| 286 initWithWebStateList:&_webStateList | 299 initWithWebStateList:&_webStateList |
| 287 proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]); | 300 proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]); |
| 288 | 301 |
| 302 _observerBridges.push_back(base::MakeUnique<TabParentingObserver>()); |
| 303 _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( |
| 304 [[TabModelObserversBridge alloc] initWithTabModel:self |
| 305 tabModelObservers:_observers.get()])); |
| 306 _observerBridges.push_back(base::MakeUnique<WebStateListMetricsObserver>()); |
| 307 for (const auto& observerBridge : _observerBridges) |
| 308 _webStateList.AddObserver(observerBridge.get()); |
| 309 |
| 289 _browserState = browserState; | 310 _browserState = browserState; |
| 290 DCHECK(_browserState); | 311 DCHECK(_browserState); |
| 291 | 312 |
| 292 // There must be a valid session service defined to consume session windows. | 313 // There must be a valid session service defined to consume session windows. |
| 293 DCHECK(service); | 314 DCHECK(service); |
| 294 _sessionService.reset([service retain]); | 315 _sessionService.reset([service retain]); |
| 295 | 316 |
| 296 // Normal browser states are the only ones to get tab restore. Tab sync | 317 // Normal browser states are the only ones to get tab restore. Tab sync |
| 297 // handles incognito browser states by filtering on profile, so it's | 318 // handles incognito browser states by filtering on profile, so it's |
| 298 // important to the backend code to always have a sync window delegate. | 319 // important to the backend code to always have a sync window delegate. |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 [[Tab alloc] initWithWebState:std::move(webState) model:self]); | 550 [[Tab alloc] initWithWebState:std::move(webState) model:self]); |
| 530 [tab webController].webUsageEnabled = webUsageEnabled_; | 551 [tab webController].webUsageEnabled = webUsageEnabled_; |
| 531 [self insertTab:tab atIndex:index]; | 552 [self insertTab:tab atIndex:index]; |
| 532 return tab; | 553 return tab; |
| 533 } | 554 } |
| 534 | 555 |
| 535 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { | 556 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { |
| 536 DCHECK(tab); | 557 DCHECK(tab); |
| 537 DCHECK(![_tabRetainer containsObject:tab]); | 558 DCHECK(![_tabRetainer containsObject:tab]); |
| 538 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); | 559 DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX)); |
| 539 [tab fetchFavicon]; | |
| 540 | 560 |
| 541 [_tabRetainer addObject:tab]; | 561 [_tabRetainer addObject:tab]; |
| 542 _webStateList.InsertWebState(static_cast<int>(index), tab.webState); | 562 _webStateList.InsertWebState(static_cast<int>(index), tab.webState); |
| 543 TabParentingGlobalObserver::GetInstance()->OnTabParented(tab.webState); | |
| 544 [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO]; | |
| 545 [_observers tabModelDidChangeTabCount:self]; | |
| 546 | 563 |
| 547 base::RecordAction(base::UserMetricsAction("MobileNewTabOpened")); | |
| 548 // Persist the session due to a new tab being inserted. If this is a | 564 // Persist the session due to a new tab being inserted. If this is a |
| 549 // background tab (will not become active), saving now will capture the | 565 // background tab (will not become active), saving now will capture the |
| 550 // state properly. If it does eventually become active, another save will | 566 // state properly. If it does eventually become active, another save will |
| 551 // be triggered to properly capture the end result. | 567 // be triggered to properly capture the end result. |
| 552 [self saveSessionImmediately:NO]; | 568 [self saveSessionImmediately:NO]; |
| 553 | 569 |
| 554 ++_newTabCount; | 570 ++_newTabCount; |
| 555 } | 571 } |
| 556 | 572 |
| 557 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { | 573 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { |
| 558 if ([self tabAtIndex:toIndex] == tab) | |
| 559 return; | |
| 560 | |
| 561 DCHECK([_tabRetainer containsObject:tab]); | 574 DCHECK([_tabRetainer containsObject:tab]); |
| 562 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX)); | 575 DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX)); |
| 563 int fromIndex = _webStateList.GetIndexOfWebState(tab.webState); | 576 int fromIndex = _webStateList.GetIndexOfWebState(tab.webState); |
| 564 _webStateList.MoveWebStateAt(fromIndex, static_cast<int>(toIndex)); | 577 _webStateList.MoveWebStateAt(fromIndex, static_cast<int>(toIndex)); |
| 565 [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex]; | |
| 566 } | 578 } |
| 567 | 579 |
| 568 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { | 580 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { |
| 569 DCHECK([_tabRetainer containsObject:oldTab]); | 581 DCHECK([_tabRetainer containsObject:oldTab]); |
| 570 DCHECK(![_tabRetainer containsObject:newTab]); | 582 DCHECK(![_tabRetainer containsObject:newTab]); |
| 571 | 583 |
| 572 int index = _webStateList.GetIndexOfWebState(oldTab.webState); | 584 int index = _webStateList.GetIndexOfWebState(oldTab.webState); |
| 573 DCHECK_NE(index, WebStateList::kInvalidIndex); | 585 DCHECK_NE(index, WebStateList::kInvalidIndex); |
| 574 DCHECK_GE(index, 0); | 586 DCHECK_GE(index, 0); |
| 575 | 587 |
| 576 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); | 588 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); |
| 577 [newTab fetchFavicon]; | |
| 578 [_tabRetainer removeObject:oldTab]; | 589 [_tabRetainer removeObject:oldTab]; |
| 579 [_tabRetainer addObject:newTab]; | 590 [_tabRetainer addObject:newTab]; |
| 580 [newTab setParentTabModel:self]; | 591 [newTab setParentTabModel:self]; |
| 581 | 592 |
| 582 _webStateList.ReplaceWebStateAt(index, newTab.webState); | 593 _webStateList.ReplaceWebStateAt(index, newTab.webState); |
| 583 TabParentingGlobalObserver::GetInstance()->OnTabParented(newTab.webState); | |
| 584 [_observers tabModel:self | |
| 585 didReplaceTab:oldTab | |
| 586 withTab:newTab | |
| 587 atIndex:static_cast<NSUInteger>(index)]; | |
| 588 | 594 |
| 589 if (self.currentTab == oldTab) | 595 if (self.currentTab == oldTab) |
| 590 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; | 596 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; |
| 591 | 597 |
| 592 [oldTab setParentTabModel:nil]; | 598 [oldTab setParentTabModel:nil]; |
| 593 [oldTab close]; | 599 [oldTab close]; |
| 594 | |
| 595 // Record a tab clobber, since swapping tabs bypasses the tab code that would | |
| 596 // normally log clobbers. | |
| 597 base::RecordAction(base::UserMetricsAction("MobileTabClobbered")); | |
| 598 } | 600 } |
| 599 | 601 |
| 600 - (void)closeTabAtIndex:(NSUInteger)index { | 602 - (void)closeTabAtIndex:(NSUInteger)index { |
| 601 DCHECK(index < self.count); | 603 DCHECK(index < self.count); |
| 602 [self closeTab:[self tabAtIndex:index]]; | 604 [self closeTab:[self tabAtIndex:index]]; |
| 603 } | 605 } |
| 604 | 606 |
| 605 - (void)closeTab:(Tab*)tab { | 607 - (void)closeTab:(Tab*)tab { |
| 606 // Ensure the tab stays alive long enough for us to send out the | 608 // Ensure the tab stays alive long enough for us to send out the |
| 607 // notice of its destruction to the delegate. | 609 // notice of its destruction to the delegate. |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 // notification. This avoids various parts of the code getting confused | 748 // notification. This avoids various parts of the code getting confused |
| 747 // when the current tab isn't in the tab model. | 749 // when the current tab isn't in the tab model. |
| 748 Tab* savedCurrentTab = _currentTab; | 750 Tab* savedCurrentTab = _currentTab; |
| 749 if (closedTab == _currentTab) | 751 if (closedTab == _currentTab) |
| 750 _currentTab.reset(nil); | 752 _currentTab.reset(nil); |
| 751 | 753 |
| 752 DCHECK([_tabRetainer containsObject:closedTab]); | 754 DCHECK([_tabRetainer containsObject:closedTab]); |
| 753 [_tabRetainer removeObject:closedTab]; | 755 [_tabRetainer removeObject:closedTab]; |
| 754 | 756 |
| 755 _webStateList.DetachWebStateAt(closedTabIndex); | 757 _webStateList.DetachWebStateAt(closedTabIndex); |
| 756 [_observers tabModel:self | |
| 757 didRemoveTab:closedTab | |
| 758 atIndex:static_cast<NSUInteger>(closedTabIndex)]; | |
| 759 [_observers tabModelDidChangeTabCount:self]; | |
| 760 | 758 |
| 761 // Current tab has closed, update the selected tab and swap in its | 759 // Current tab has closed, update the selected tab and swap in its |
| 762 // contents. There is nothing to do if a non-selected tab is closed as | 760 // contents. There is nothing to do if a non-selected tab is closed as |
| 763 // the selection isn't index-based, therefore it hasn't changed. | 761 // the selection isn't index-based, therefore it hasn't changed. |
| 764 // -changeSelectedTabFrom: will persist the state change, so only do it | 762 // -changeSelectedTabFrom: will persist the state change, so only do it |
| 765 // if the selection isn't changing. | 763 // if the selection isn't changing. |
| 766 if (closedTab == savedCurrentTab) { | 764 if (closedTab == savedCurrentTab) { |
| 767 [self changeSelectedTabFrom:closedTab to:newSelection persistState:NO]; | 765 [self changeSelectedTabFrom:closedTab to:newSelection persistState:NO]; |
| 768 } else { | 766 } else { |
| 769 [self saveSessionImmediately:NO]; | 767 [self saveSessionImmediately:NO]; |
| 770 } | 768 } |
| 771 base::RecordAction(base::UserMetricsAction("MobileTabClosed")); | |
| 772 ++_closedTabCount; | 769 ++_closedTabCount; |
| 773 } | 770 } |
| 774 | 771 |
| 775 - (void)navigationCommittedInTab:(Tab*)tab { | 772 - (void)navigationCommittedInTab:(Tab*)tab { |
| 776 if (self.offTheRecord) | 773 if (self.offTheRecord) |
| 777 return; | 774 return; |
| 778 if (![tab navigationManager]) | 775 if (![tab navigationManager]) |
| 779 return; | 776 return; |
| 780 | 777 |
| 781 // See if the navigation was within a page; if so ignore it. | 778 // See if the navigation was within a page; if so ignore it. |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 web::NavigationManager::WebLoadParams params(URL); | 1105 web::NavigationManager::WebLoadParams params(URL); |
| 1109 params.referrer = referrer; | 1106 params.referrer = referrer; |
| 1110 params.transition_type = ui::PAGE_TRANSITION_TYPED; | 1107 params.transition_type = ui::PAGE_TRANSITION_TYPED; |
| 1111 [[tab webController] loadWithParams:params]; | 1108 [[tab webController] loadWithParams:params]; |
| 1112 [tab webController].webUsageEnabled = webUsageEnabled_; | 1109 [tab webController].webUsageEnabled = webUsageEnabled_; |
| 1113 [self insertTab:tab atIndex:index]; | 1110 [self insertTab:tab atIndex:index]; |
| 1114 return tab; | 1111 return tab; |
| 1115 } | 1112 } |
| 1116 | 1113 |
| 1117 @end | 1114 @end |
| OLD | NEW |