Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(515)

Side by Side Diff: ios/chrome/browser/tabs/tab_model.mm

Issue 2687303003: Convert some of TabModel logic to WebStateListObservers. (Closed)
Patch Set: Rebase. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ios/chrome/browser/tabs/BUILD.gn ('k') | ios/chrome/browser/tabs/tab_model_observers_bridge.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « ios/chrome/browser/tabs/BUILD.gn ('k') | ios/chrome/browser/tabs/tab_model_observers_bridge.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698