Index: ios/chrome/browser/tabs/tab_model.mm |
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm |
index 2a344082d667b86259ade56e52b5ad9f66d541aa..6647782cca00545df536dfcc06a70bbd0876de8d 100644 |
--- a/ios/chrome/browser/tabs/tab_model.mm |
+++ b/ios/chrome/browser/tabs/tab_model.mm |
@@ -31,9 +31,12 @@ |
#import "ios/chrome/browser/tabs/legacy_tab_helper.h" |
#import "ios/chrome/browser/tabs/tab.h" |
#import "ios/chrome/browser/tabs/tab_model_list.h" |
+#import "ios/chrome/browser/tabs/tab_model_metrics_observer.h" |
#import "ios/chrome/browser/tabs/tab_model_observers.h" |
#import "ios/chrome/browser/tabs/tab_model_order_controller.h" |
#import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h" |
+#import "ios/chrome/browser/tabs/tab_model_tab_model_observers_bridge.h" |
+#import "ios/chrome/browser/tabs/tab_model_tab_parenting_observer.h" |
#import "ios/chrome/browser/xcallback_parameters.h" |
#import "ios/shared/chrome/browser/tabs/web_state_list.h" |
#import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h" |
@@ -128,6 +131,10 @@ void CleanCertificatePolicyCache( |
// WebState owns the associated Tab. |
base::scoped_nsobject<NSMutableSet<Tab*>> _tabs; |
+ // WebStateListObserver bridges to react to modifications of the model (may |
+ // send notification, translate and forward events, update metrics, ...). |
+ std::vector<std::unique_ptr<WebStateListObserver>> _observerBridges; |
+ |
// Maintains policy for where new tabs go and the selection when a tab |
// is removed. |
base::scoped_nsobject<TabModelOrderController> _orderController; |
@@ -214,6 +221,12 @@ void CleanCertificatePolicyCache( |
DCHECK(!_browserState); |
[[NSNotificationCenter defaultCenter] removeObserver:self]; |
+ |
+ // Unregister all listeners before closing all the tabs. |
+ for (const auto& observerBridge : _observerBridges) |
+ _webStateList.RemoveObserver(observerBridge.get()); |
+ _observerBridges.clear(); |
+ |
// Make sure the tabs do clean after themselves. It is important for |
// removeObserver: to be called first otherwise a lot of unecessary work will |
// happen on -closeAllTabs. |
@@ -273,6 +286,17 @@ void CleanCertificatePolicyCache( |
initWithWebStateList:&_webStateList |
proxyFactory:self]); |
+ _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( |
+ [[TabModelTabParentingObserver alloc] init])); |
+ _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( |
+ [[TabModelTabModelObserversBridge alloc] |
+ initWithTabModel:self |
+ tabModelObservers:_observers.get()])); |
+ _observerBridges.push_back(base::MakeUnique<WebStateListObserverBridge>( |
+ [[TabModelMetricsObserver alloc] init])); |
+ for (const auto& observerBridge : _observerBridges) |
+ _webStateList.AddObserver(observerBridge.get()); |
+ |
_browserState = browserState; |
DCHECK(_browserState); |
@@ -544,15 +568,10 @@ void CleanCertificatePolicyCache( |
- (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index { |
DCHECK(tab); |
DCHECK(![_tabs containsObject:tab]); |
- [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
|
[_tabs addObject:tab]; |
_webStateList.InsertWebState(index, tab.webState); |
- TabParentingGlobalObserver::GetInstance()->OnTabParented(tab.webState); |
- [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO]; |
- [_observers tabModelDidChangeTabCount:self]; |
- base::RecordAction(base::UserMetricsAction("MobileNewTabOpened")); |
// Persist the session due to a new tab being inserted. If this is a |
// background tab (will not become active), saving now will capture the |
// state properly. If it does eventually become active, another save will |
@@ -565,34 +584,27 @@ void CleanCertificatePolicyCache( |
- (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex { |
size_t fromIndex = _webStateList.GetIndexOfWebState(tab.webState); |
_webStateList.MoveWebStateAt(fromIndex, toIndex); |
- [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex]; |
} |
- (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab { |
NSUInteger index = [self indexOfTab:oldTab]; |
DCHECK_NE(NSNotFound, static_cast<NSInteger>(index)); |
+ |
DCHECK([_tabs containsObject:oldTab]); |
DCHECK(![_tabs containsObject:newTab]); |
base::scoped_nsobject<Tab> tabSaver([oldTab retain]); |
- [newTab fetchFavicon]; |
[_tabs removeObject:oldTab]; |
[_tabs addObject:newTab]; |
[newTab setParentTabModel:self]; |
_webStateList.ReplaceWebStateAt(index, newTab.webState); |
- TabParentingGlobalObserver::GetInstance()->OnTabParented(newTab.webState); |
- [_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index]; |
if (self.currentTab == oldTab) |
[self changeSelectedTabFrom:nil to:newTab persistState:NO]; |
[oldTab setParentTabModel:nil]; |
[oldTab close]; |
- |
- // Record a tab clobber, since swapping tabs bypasses the tab code that would |
- // normally log clobbers. |
- base::RecordAction(base::UserMetricsAction("MobileTabClobbered")); |
} |
- (void)closeTabAtIndex:(NSUInteger)index { |
@@ -748,8 +760,6 @@ void CleanCertificatePolicyCache( |
[_tabs removeObject:closedTab]; |
_webStateList.RemoveWebStateAt(closedTabIndex); |
- [_observers tabModel:self didRemoveTab:closedTab atIndex:closedTabIndex]; |
- [_observers tabModelDidChangeTabCount:self]; |
// Current tab has closed, update the selected tab and swap in its |
// contents. There is nothing to do if a non-selected tab is closed as |
@@ -761,7 +771,6 @@ void CleanCertificatePolicyCache( |
} else { |
[self saveSessionImmediately:NO]; |
} |
- base::RecordAction(base::UserMetricsAction("MobileTabClosed")); |
++_closedTabCount; |
} |