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 |