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 <utility> | 7 #include <utility> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #import "ios/chrome/browser/chrome_url_util.h" | 24 #import "ios/chrome/browser/chrome_url_util.h" |
| 25 #import "ios/chrome/browser/metrics/tab_usage_recorder.h" | 25 #import "ios/chrome/browser/metrics/tab_usage_recorder.h" |
| 26 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" | 26 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" |
| 27 #import "ios/chrome/browser/sessions/session_service.h" | 27 #import "ios/chrome/browser/sessions/session_service.h" |
| 28 #import "ios/chrome/browser/sessions/session_window.h" | 28 #import "ios/chrome/browser/sessions/session_window.h" |
| 29 #import "ios/chrome/browser/snapshots/snapshot_cache.h" | 29 #import "ios/chrome/browser/snapshots/snapshot_cache.h" |
| 30 #include "ios/chrome/browser/tab_parenting_global_observer.h" | 30 #include "ios/chrome/browser/tab_parenting_global_observer.h" |
| 31 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" | 31 #import "ios/chrome/browser/tabs/legacy_tab_helper.h" |
| 32 #import "ios/chrome/browser/tabs/tab.h" | 32 #import "ios/chrome/browser/tabs/tab.h" |
| 33 #import "ios/chrome/browser/tabs/tab_model_list.h" | 33 #import "ios/chrome/browser/tabs/tab_model_list.h" |
| 34 #import "ios/chrome/browser/tabs/tab_model_metrics_observer.h" | |
| 34 #import "ios/chrome/browser/tabs/tab_model_observers.h" | 35 #import "ios/chrome/browser/tabs/tab_model_observers.h" |
| 35 #import "ios/chrome/browser/tabs/tab_model_order_controller.h" | 36 #import "ios/chrome/browser/tabs/tab_model_order_controller.h" |
| 36 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" | 37 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" |
| 38 #import "ios/chrome/browser/tabs/tab_model_tab_model_observers_bridge.h" | |
| 39 #import "ios/chrome/browser/tabs/tab_model_tab_parenting_observer.h" | |
| 37 #import "ios/chrome/browser/xcallback_parameters.h" | 40 #import "ios/chrome/browser/xcallback_parameters.h" |
| 38 #import "ios/shared/chrome/browser/tabs/web_state_list.h" | 41 #import "ios/shared/chrome/browser/tabs/web_state_list.h" |
| 39 #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 " |
| 40 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" | 43 #import "ios/shared/chrome/browser/tabs/web_state_list_observer.h" |
| 41 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" | 44 #import "ios/web/navigation/crw_session_certificate_policy_manager.h" |
| 42 #import "ios/web/navigation/crw_session_controller.h" | 45 #import "ios/web/navigation/crw_session_controller.h" |
| 43 #include "ios/web/public/browser_state.h" | 46 #include "ios/web/public/browser_state.h" |
| 44 #include "ios/web/public/certificate_policy_cache.h" | 47 #include "ios/web/public/certificate_policy_cache.h" |
| 45 #include "ios/web/public/navigation_item.h" | 48 #include "ios/web/public/navigation_item.h" |
| 46 #import "ios/web/public/navigation_manager.h" | 49 #import "ios/web/public/navigation_manager.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 | 124 |
| 122 // Helper providing NSFastEnumeration implementation over the WebStateList. | 125 // Helper providing NSFastEnumeration implementation over the WebStateList. |
| 123 base::scoped_nsobject<WebStateListFastEnumerationHelper> | 126 base::scoped_nsobject<WebStateListFastEnumerationHelper> |
| 124 _fastEnumerationHelper; | 127 _fastEnumerationHelper; |
| 125 | 128 |
| 126 // Used to keep the Tabs alive while the corresponding WebStates are stored | 129 // Used to keep the Tabs alive while the corresponding WebStates are stored |
| 127 // in the WebStateList (as Tabs currently owns their WebState). Remove once | 130 // in the WebStateList (as Tabs currently owns their WebState). Remove once |
| 128 // WebState owns the associated Tab. | 131 // WebState owns the associated Tab. |
| 129 base::scoped_nsobject<NSMutableSet<Tab*>> _tabs; | 132 base::scoped_nsobject<NSMutableSet<Tab*>> _tabs; |
| 130 | 133 |
| 134 // WebStateListObserver bridges to react to modifications of the model (may | |
| 135 // send notification, translate and forward events, update metrics, ...). | |
| 136 std::vector<std::unique_ptr<WebStateListObserver>> _observerBridges; | |
| 137 | |
| 131 // Maintains policy for where new tabs go and the selection when a tab | 138 // Maintains policy for where new tabs go and the selection when a tab |
| 132 // is removed. | 139 // is removed. |
| 133 base::scoped_nsobject<TabModelOrderController> _orderController; | 140 base::scoped_nsobject<TabModelOrderController> _orderController; |
| 134 // The delegate for sync. | 141 // The delegate for sync. |
| 135 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; | 142 std::unique_ptr<TabModelSyncedWindowDelegate> _syncedWindowDelegate; |
| 136 // Currently selected tab. May be nil. | 143 // Currently selected tab. May be nil. |
| 137 base::WeakNSObject<Tab> _currentTab; | 144 base::WeakNSObject<Tab> _currentTab; |
| 138 | 145 |
| 139 // Counters for metrics. | 146 // Counters for metrics. |
| 140 int _openedTabCount; | 147 int _openedTabCount; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 @synthesize webUsageEnabled = webUsageEnabled_; | 214 @synthesize webUsageEnabled = webUsageEnabled_; |
| 208 | 215 |
| 209 #pragma mark - Overriden | 216 #pragma mark - Overriden |
| 210 | 217 |
| 211 - (void)dealloc { | 218 - (void)dealloc { |
| 212 DCHECK([_observers empty]); | 219 DCHECK([_observers empty]); |
| 213 // browserStateDestroyed should always have been called before destruction. | 220 // browserStateDestroyed should always have been called before destruction. |
| 214 DCHECK(!_browserState); | 221 DCHECK(!_browserState); |
| 215 | 222 |
| 216 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 223 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 224 | |
| 225 // Unregister all listeners before closing all the tabs. | |
| 226 for (const auto& observerBridge : _observerBridges) | |
| 227 _webStateList.RemoveObserver(observerBridge.get()); | |
| 228 _observerBridges.clear(); | |
| 229 | |
| 217 // Make sure the tabs do clean after themselves. It is important for | 230 // Make sure the tabs do clean after themselves. It is important for |
| 218 // removeObserver: to be called first otherwise a lot of unecessary work will | 231 // removeObserver: to be called first otherwise a lot of unecessary work will |
| 219 // happen on -closeAllTabs. | 232 // happen on -closeAllTabs. |
| 220 [self closeAllTabs]; | 233 [self closeAllTabs]; |
| 221 | 234 |
| 222 _clearPoliciesTaskTracker.TryCancelAll(); | 235 _clearPoliciesTaskTracker.TryCancelAll(); |
| 223 | 236 |
| 224 [super dealloc]; | 237 [super dealloc]; |
| 225 } | 238 } |
| 226 | 239 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 sessionService:(SessionServiceIOS*)service | 279 sessionService:(SessionServiceIOS*)service |
| 267 browserState:(ios::ChromeBrowserState*)browserState { | 280 browserState:(ios::ChromeBrowserState*)browserState { |
| 268 if ((self = [super init])) { | 281 if ((self = [super init])) { |
| 269 _tabs.reset([[NSMutableSet alloc] init]); | 282 _tabs.reset([[NSMutableSet alloc] init]); |
| 270 _observers.reset([[TabModelObservers observers] retain]); | 283 _observers.reset([[TabModelObservers observers] retain]); |
| 271 | 284 |
| 272 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc] | 285 _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc] |
| 273 initWithWebStateList:&_webStateList | 286 initWithWebStateList:&_webStateList |
| 274 proxyFactory:self]); | 287 proxyFactory:self]); |
| 275 | 288 |
| 289 _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( | |
| 290 [[TabModelTabParentingObserver alloc] init])); | |
| 291 _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( | |
| 292 [[TabModelTabModelObserversBridge alloc] | |
| 293 initWithTabModel:self | |
| 294 tabModelObservers:_observers.get()])); | |
| 295 _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( | |
| 296 [[TabModelMetricsObserver alloc] init])); | |
| 297 for (const auto& observerBridge : _observerBridges) | |
| 298 _webStateList.AddObserver(observerBridge.get()); | |
| 299 | |
| 276 _browserState = browserState; | 300 _browserState = browserState; |
| 277 DCHECK(_browserState); | 301 DCHECK(_browserState); |
| 278 | 302 |
| 279 // There must be a valid session service defined to consume session windows. | 303 // There must be a valid session service defined to consume session windows. |
| 280 DCHECK(service); | 304 DCHECK(service); |
| 281 _sessionService.reset([service retain]); | 305 _sessionService.reset([service retain]); |
| 282 | 306 |
| 283 // Normal browser states are the only ones to get tab restore. Tab sync | 307 // Normal browser states are the only ones to get tab restore. Tab sync |
| 284 // handles incognito browser states by filtering on profile, so it's | 308 // handles incognito browser states by filtering on profile, so it's |
| 285 // important to the backend code to always have a sync window delegate. | 309 // important to the backend code to always have a sync window delegate. |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 base::scoped_nsobject<Tab> tab( | 561 base::scoped_nsobject<Tab> tab( |
| 538 [[Tab alloc] initWithWebState:std::move(webState) model:self]); | 562 [[Tab alloc] initWithWebState:std::move(webState) model:self]); |
| 539 [tab webController].webUsageEnabled = webUsageEnabled_; | 563 [tab webController].webUsageEnabled = webUsageEnabled_; |
| 540 [self insertTab:tab atIndex:index]; | 564 [self insertTab:tab atIndex:index]; |
| 541 return tab; | 565 return tab; |
| 542 } | 566 } |
| 543 | 567 |
| 544 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { | 568 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { |
| 545 DCHECK(tab); | 569 DCHECK(tab); |
| 546 DCHECK(![_tabs containsObject:tab]); | 570 DCHECK(![_tabs containsObject:tab]); |
| 547 [tab fetchFavicon]; | |
|
marq (ping after 24h)
2017/02/13 17:06:54
Any idea why [tab setParentTabModel:self] isn't ca
sdefresne
2017/02/13 17:13:39
Yes, this is because this method is only ever call
| |
| 548 | 571 |
| 549 [_tabs addObject:tab]; | 572 [_tabs addObject:tab]; |
| 550 _webStateList.InsertWebState(index, tab.webState); | 573 _webStateList.InsertWebState(index, tab.webState); |
| 551 TabParentingGlobalObserver::GetInstance()->OnTabParented(tab.webState); | |
| 552 [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO]; | |
| 553 [_observers tabModelDidChangeTabCount:self]; | |
| 554 | 574 |
| 555 base::RecordAction(base::UserMetricsAction("MobileNewTabOpened")); | |
| 556 // Persist the session due to a new tab being inserted. If this is a | 575 // Persist the session due to a new tab being inserted. If this is a |
| 557 // background tab (will not become active), saving now will capture the | 576 // background tab (will not become active), saving now will capture the |
| 558 // state properly. If it does eventually become active, another save will | 577 // state properly. If it does eventually become active, another save will |
| 559 // be triggered to properly capture the end result. | 578 // be triggered to properly capture the end result. |
| 560 [self saveSessionImmediately:NO]; | 579 [self saveSessionImmediately:NO]; |
| 561 | 580 |
| 562 ++_newTabCount; | 581 ++_newTabCount; |
| 563 } | 582 } |
| 564 | 583 |
| 565 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { | 584 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { |
| 566 size_t fromIndex = _webStateList.GetIndexOfWebState(tab.webState); | 585 size_t fromIndex = _webStateList.GetIndexOfWebState(tab.webState); |
| 567 _webStateList.MoveWebStateAt(fromIndex, toIndex); | 586 _webStateList.MoveWebStateAt(fromIndex, toIndex); |
| 568 [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex]; | |
| 569 } | 587 } |
| 570 | 588 |
| 571 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { | 589 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { |
| 572 NSUInteger index = [self indexOfTab:oldTab]; | 590 NSUInteger index = [self indexOfTab:oldTab]; |
| 573 DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); | 591 DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); |
| 592 | |
| 574 DCHECK([_tabs containsObject:oldTab]); | 593 DCHECK([_tabs containsObject:oldTab]); |
| 575 DCHECK(![_tabs containsObject:newTab]); | 594 DCHECK(![_tabs containsObject:newTab]); |
| 576 | 595 |
| 577 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); | 596 base::scoped_nsobject<Tab> tabSaver([oldTab retain]); |
| 578 [newTab fetchFavicon]; | |
| 579 [_tabs removeObject:oldTab]; | 597 [_tabs removeObject:oldTab]; |
| 580 [_tabs addObject:newTab]; | 598 [_tabs addObject:newTab]; |
| 581 [newTab setParentTabModel:self]; | 599 [newTab setParentTabModel:self]; |
| 582 | 600 |
| 583 _webStateList.ReplaceWebStateAt(index, newTab.webState); | 601 _webStateList.ReplaceWebStateAt(index, newTab.webState); |
| 584 TabParentingGlobalObserver::GetInstance()->OnTabParented(newTab.webState); | |
| 585 [_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index]; | |
| 586 | 602 |
| 587 if (self.currentTab == oldTab) | 603 if (self.currentTab == oldTab) |
| 588 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; | 604 [self changeSelectedTabFrom:nil to:newTab persistState:NO]; |
| 589 | 605 |
| 590 [oldTab setParentTabModel:nil]; | 606 [oldTab setParentTabModel:nil]; |
| 591 [oldTab close]; | 607 [oldTab close]; |
| 592 | |
| 593 // Record a tab clobber, since swapping tabs bypasses the tab code that would | |
| 594 // normally log clobbers. | |
| 595 base::RecordAction(base::UserMetricsAction("MobileTabClobbered")); | |
| 596 } | 608 } |
| 597 | 609 |
| 598 - (void)closeTabAtIndex:(NSUInteger)index { | 610 - (void)closeTabAtIndex:(NSUInteger)index { |
| 599 DCHECK(index < _webStateList.count()); | 611 DCHECK(index < _webStateList.count()); |
| 600 [self closeTab:[self tabAtIndex:index]]; | 612 [self closeTab:[self tabAtIndex:index]]; |
| 601 } | 613 } |
| 602 | 614 |
| 603 - (void)closeTab:(Tab*)tab { | 615 - (void)closeTab:(Tab*)tab { |
| 604 // Ensure the tab stays alive long enough for us to send out the | 616 // Ensure the tab stays alive long enough for us to send out the |
| 605 // notice of its destruction to the delegate. | 617 // notice of its destruction to the delegate. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 741 // notification. This avoids various parts of the code getting confused | 753 // notification. This avoids various parts of the code getting confused |
| 742 // when the current tab isn't in the tab model. | 754 // when the current tab isn't in the tab model. |
| 743 Tab* savedCurrentTab = _currentTab; | 755 Tab* savedCurrentTab = _currentTab; |
| 744 if (closedTab == _currentTab) | 756 if (closedTab == _currentTab) |
| 745 _currentTab.reset(nil); | 757 _currentTab.reset(nil); |
| 746 | 758 |
| 747 DCHECK([_tabs containsObject:closedTab]); | 759 DCHECK([_tabs containsObject:closedTab]); |
| 748 [_tabs removeObject:closedTab]; | 760 [_tabs removeObject:closedTab]; |
| 749 | 761 |
| 750 _webStateList.RemoveWebStateAt(closedTabIndex); | 762 _webStateList.RemoveWebStateAt(closedTabIndex); |
| 751 [_observers tabModel:self didRemoveTab:closedTab atIndex:closedTabIndex]; | |
| 752 [_observers tabModelDidChangeTabCount:self]; | |
| 753 | 763 |
| 754 // Current tab has closed, update the selected tab and swap in its | 764 // Current tab has closed, update the selected tab and swap in its |
| 755 // contents. There is nothing to do if a non-selected tab is closed as | 765 // contents. There is nothing to do if a non-selected tab is closed as |
| 756 // the selection isn't index-based, therefore it hasn't changed. | 766 // the selection isn't index-based, therefore it hasn't changed. |
| 757 // -changeSelectedTabFrom: will persist the state change, so only do it | 767 // -changeSelectedTabFrom: will persist the state change, so only do it |
| 758 // if the selection isn't changing. | 768 // if the selection isn't changing. |
| 759 if (closedTab == savedCurrentTab) { | 769 if (closedTab == savedCurrentTab) { |
| 760 [self changeSelectedTabFrom:closedTab to:newSelection persistState:NO]; | 770 [self changeSelectedTabFrom:closedTab to:newSelection persistState:NO]; |
| 761 } else { | 771 } else { |
| 762 [self saveSessionImmediately:NO]; | 772 [self saveSessionImmediately:NO]; |
| 763 } | 773 } |
| 764 base::RecordAction(base::UserMetricsAction("MobileTabClosed")); | |
| 765 ++_closedTabCount; | 774 ++_closedTabCount; |
| 766 } | 775 } |
| 767 | 776 |
| 768 - (void)navigationCommittedInTab:(Tab*)tab { | 777 - (void)navigationCommittedInTab:(Tab*)tab { |
| 769 if (self.offTheRecord) | 778 if (self.offTheRecord) |
| 770 return; | 779 return; |
| 771 if (![tab navigationManager]) | 780 if (![tab navigationManager]) |
| 772 return; | 781 return; |
| 773 | 782 |
| 774 // See if the navigation was within a page; if so ignore it. | 783 // See if the navigation was within a page; if so ignore it. |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1104 web::NavigationManager::WebLoadParams params(URL); | 1113 web::NavigationManager::WebLoadParams params(URL); |
| 1105 params.referrer = referrer; | 1114 params.referrer = referrer; |
| 1106 params.transition_type = ui::PAGE_TRANSITION_TYPED; | 1115 params.transition_type = ui::PAGE_TRANSITION_TYPED; |
| 1107 [[tab webController] loadWithParams:params]; | 1116 [[tab webController] loadWithParams:params]; |
| 1108 [tab webController].webUsageEnabled = webUsageEnabled_; | 1117 [tab webController].webUsageEnabled = webUsageEnabled_; |
| 1109 [self insertTab:tab atIndex:index]; | 1118 [self insertTab:tab atIndex:index]; |
| 1110 return tab; | 1119 return tab; |
| 1111 } | 1120 } |
| 1112 | 1121 |
| 1113 @end | 1122 @end |
| OLD | NEW |