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

Unified Diff: ios/chrome/browser/ui/tab_switcher/tab_switcher_model.mm

Issue 2588733002: Upstream Chrome on iOS source code [9/11]. (Closed)
Patch Set: Created 4 years 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 side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/tab_switcher/tab_switcher_model.mm
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_model.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_model.mm
new file mode 100644
index 0000000000000000000000000000000000000000..6f1a4e5df90d59c11346724d2d7f21dbb88f08ed
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_model.mm
@@ -0,0 +1,410 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_model.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "components/browser_sync/profile_sync_service.h"
+#include "components/sessions/core/session_id.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/signin/signin_manager_factory.h"
+#include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
+#include "ios/chrome/browser/sync/sync_setup_service.h"
+#include "ios/chrome/browser/sync/sync_setup_service_factory.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+#include "ios/chrome/browser/ui/ntp/recent_tabs/synced_sessions.h"
+#import "ios/chrome/browser/ui/tab_switcher/session_changes.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_model_snapshot.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_cache.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_model_private.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h"
+
+namespace ios_internal {
+
+bool IsLocalSession(SessionType sessionType) {
+ return sessionType == SessionType::OFF_THE_RECORD_SESSION ||
+ sessionType == SessionType::REGULAR_SESSION;
+}
+
+} // namespace ios_internal
+
+namespace {
+
+class TagAndIndex {
+ public:
+ TagAndIndex(std::string const& tag, size_t index)
+ : tag_(tag), index_(index) {}
+ std::string tag_;
+ size_t index_;
+ bool operator<(const TagAndIndex& other) const { return tag_ < other.tag_; }
+};
+
+void FillSetUsingSessions(synced_sessions::SyncedSessions const& sessions,
+ std::set<TagAndIndex>* set) {
+ DCHECK(set);
+ DCHECK(set->empty());
+ for (size_t i = 0; i < sessions.GetSessionCount(); ++i) {
+ set->insert(TagAndIndex(sessions.GetSession(i)->tag, i));
+ }
+}
+
+} // namespace
+
+@interface TabSwitcherModel () {
+ // The browser state.
+ ios::ChromeBrowserState* _browserState; // weak
+ // The tab models.
+ TabModel* _mainTabModel; // weak
+ TabModel* _otrTabModel; // weak
+ // The delegate for event callbacks.
+ id<TabSwitcherModelDelegate> _delegate; // weak, owns us.
+ // The synced sessions. Must never be null.
+ std::unique_ptr<synced_sessions::SyncedSessions> _syncedSessions;
+ // The synced sessions change observer.
+ std::unique_ptr<synced_sessions::SyncedSessionsObserverBridge>
+ _syncedSessionsObserver;
+ // Snapshots of the |_mainTabModel| and |_otrTabModel|.
+ std::unique_ptr<TabModelSnapshot> _mainTabModelSnapshot;
+ std::unique_ptr<TabModelSnapshot> _otrTabModelSnapshot;
+ // The cache holding resized tabs snapshots.
+ base::scoped_nsobject<TabSwitcherCache> _cache;
+}
+
+// Returns the type of the local session corresponding to the given |tabModel|.
+// |tabModel| MUST be equal to either |_mainTabModel|, or |_otrTabModel|.
+- (ios_internal::SessionType)typeOfLocalSessionForTabModel:(TabModel*)tabModel;
+@end
+
+@implementation TabSwitcherModel
+
+@synthesize mainTabModel = _mainTabModel;
+@synthesize otrTabModel = _otrTabModel;
+
+- (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
+ delegate:(id<TabSwitcherModelDelegate>)delegate
+ mainTabModel:(TabModel*)mainTabModel
+ otrTabModel:(TabModel*)otrTabModel
+ withCache:(TabSwitcherCache*)cache {
+ DCHECK(browserState);
+ DCHECK(delegate);
+ // TODO(jif): DCHECK |mainTabModel| and |otrTabModel|.
+ self = [self init];
+ if (self) {
+ _browserState = browserState;
+ _delegate = delegate;
+ _syncedSessions.reset(new synced_sessions::SyncedSessions());
+ _syncedSessionsObserver.reset(
+ new synced_sessions::SyncedSessionsObserverBridge(self, _browserState));
+ _mainTabModel = mainTabModel;
+ _otrTabModel = otrTabModel;
+ _mainTabModelSnapshot.reset(new TabModelSnapshot(mainTabModel));
+ _otrTabModelSnapshot.reset(new TabModelSnapshot(otrTabModel));
+ [_mainTabModel addObserver:self];
+ [_otrTabModel addObserver:self];
+ _cache.reset([cache retain]);
+ }
+ return self;
+}
+
+- (void)setMainTabModel:(TabModel*)mainTabModel
+ otrTabModel:(TabModel*)otrTabModel {
+ [self replaceOldTabModel:&_mainTabModel withTabModel:mainTabModel];
+ [self replaceOldTabModel:&_otrTabModel withTabModel:otrTabModel];
+}
+
+- (void)replaceOldTabModel:(TabModel**)oldTabModel
+ withTabModel:(TabModel*)newTabModel {
+ if (*oldTabModel == newTabModel)
+ return;
+ [*oldTabModel removeObserver:self];
+ *oldTabModel = newTabModel;
+ [newTabModel addObserver:self];
+ // Calling |tabModelChanged:| may trigger an animated refresh of the
+ // Tab Switcher's collection view.
+ // Here in |replaceOldTabModel:withTabModel:| the animation is undesirable.
+ [UIView performWithoutAnimation:^{
+ [self tabModelChanged:newTabModel];
+ }];
+}
+
+- (void)dealloc {
+ [_mainTabModel removeObserver:self];
+ [_otrTabModel removeObserver:self];
+ [super dealloc];
+}
+
+- (NSInteger)sessionCount {
+ const NSInteger mainTabModelSessionCount = 1;
+ const NSInteger otrTabModelSessionCount = 1;
+ return mainTabModelSessionCount + otrTabModelSessionCount +
+ [self distantSessionCount];
+}
+
+- (NSInteger)distantSessionCount {
+ return _syncedSessions->GetSessionCount();
+}
+
+- (ios::ChromeBrowserState*)browserState {
+ return _browserState;
+}
+
+- (TabModel*)tabModelForSessionOfType:(ios_internal::SessionType)type {
+ DCHECK(type == ios_internal::SessionType::OFF_THE_RECORD_SESSION ||
+ type == ios_internal::SessionType::REGULAR_SESSION);
+ return type == ios_internal::SessionType::OFF_THE_RECORD_SESSION
+ ? _otrTabModel
+ : _mainTabModel;
+}
+
+- (NSInteger)numberOfTabsInLocalSessionOfType:(ios_internal::SessionType)type {
+ TabModelSnapshot* tabModelSnapshot = [self tabModelSnapshotForSession:type];
+ return tabModelSnapshot->tabs().size();
+}
+
+- (Tab*)tabAtIndex:(NSUInteger)index
+ inLocalSessionOfType:(ios_internal::SessionType)type {
+ TabModelSnapshot* tabModelSnapshot = [self tabModelSnapshotForSession:type];
+ return tabModelSnapshot->tabs()[index];
+}
+
+- (std::unique_ptr<TabModelSnapshot>)tabModelSnapshotForLocalSession:
+ (ios_internal::SessionType)type {
+ TabModel* tm = nullptr;
+ switch (type) {
+ case ios_internal::SessionType::OFF_THE_RECORD_SESSION:
+ tm = _otrTabModel;
+ break;
+ case ios_internal::SessionType::REGULAR_SESSION:
+ tm = _mainTabModel;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return base::MakeUnique<TabModelSnapshot>(tm);
+}
+
+- (std::unique_ptr<const synced_sessions::DistantSession>)distantSessionForTag:
+ (std::string const&)tag {
+ syncer::SyncService* syncService =
+ IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState);
+ return base::MakeUnique<synced_sessions::DistantSession>(syncService, tag);
+}
+
+- (std::string const&)tagOfDistantSessionAtIndex:(int)index {
+ return _syncedSessions->GetSession(index)->tag;
+}
+
+- (TabSwitcherSignInPanelsType)signInPanelType {
+ TabSwitcherSignInPanelsType panelType = TabSwitcherSignInPanelsType::NO_PANEL;
+ if (![self isSignedIn]) {
+ panelType = TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_OUT;
+ } else {
+ if (![self isSyncTabsEnabled]) {
+ panelType = TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_IN_SYNC_OFF;
+ } else {
+ if (_syncedSessions->GetSessionCount() == 0) {
+ if ([self isFirstSyncCycleCompleted]) {
+ panelType = TabSwitcherSignInPanelsType::
+ PANEL_USER_SIGNED_IN_SYNC_ON_NO_SESSIONS;
+ } else {
+ panelType = TabSwitcherSignInPanelsType::
+ PANEL_USER_SIGNED_IN_SYNC_IN_PROGRESS;
+ }
+ }
+ }
+ }
+ return panelType;
+}
+
+- (void)syncedSessionsChanged {
+ syncer::SyncService* syncService =
+ IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState);
+
+ std::unique_ptr<synced_sessions::SyncedSessions> oldSyncedSessions(
+ new synced_sessions::SyncedSessions(syncService));
+ _syncedSessions.swap(oldSyncedSessions);
+
+ // Notify about change in the sign in panel.
+ TabSwitcherSignInPanelsType panelType = [self signInPanelType];
+ [_delegate signInPanelChangedTo:panelType];
+
+ if (panelType != TabSwitcherSignInPanelsType::NO_PANEL) {
+ // Do not show synced sessions.
+ _syncedSessions.reset(new synced_sessions::SyncedSessions());
+ }
+
+ // Notify about changes in the synced sessions.
+ [TabSwitcherModel notifyDelegate:_delegate
+ aboutChangeFrom:*oldSyncedSessions
+ to:*_syncedSessions];
+}
+
+- (BOOL)isSignedIn {
+ SigninManager* signin_manager =
+ ios::SigninManagerFactory::GetForBrowserState(_browserState);
+ return signin_manager->IsAuthenticated();
+}
+
+- (BOOL)isSyncTabsEnabled {
+ DCHECK([self isSignedIn]);
+ SyncSetupService* service =
+ SyncSetupServiceFactory::GetForBrowserState(_browserState);
+ return !service->UserActionIsRequiredToHaveSyncWork();
+}
+
+- (BOOL)isFirstSyncCycleCompleted {
+ return _syncedSessionsObserver->IsFirstSyncCycleCompleted();
+}
+
++ (void)notifyDelegate:(id<TabSwitcherModelDelegate>)delegate
+ aboutChangeFrom:(synced_sessions::SyncedSessions&)oldSessions
+ to:(synced_sessions::SyncedSessions&)newSessions {
+ // Compute and notify the delegate about removed or inserted sessions.
+ std::set<TagAndIndex> tagsOfOldSessions;
+ std::set<TagAndIndex> tagsOfNewSessions;
+ FillSetUsingSessions(oldSessions, &tagsOfOldSessions);
+ FillSetUsingSessions(newSessions, &tagsOfNewSessions);
+
+ std::set<TagAndIndex> tagsOfRemovedSessions;
+ std::set<TagAndIndex> tagsOfInsertedSessions;
+ std::set_difference(
+ tagsOfOldSessions.begin(), tagsOfOldSessions.end(),
+ tagsOfNewSessions.begin(), tagsOfNewSessions.end(),
+ std::inserter(tagsOfRemovedSessions, tagsOfRemovedSessions.end()));
+ std::set_difference(
+ tagsOfNewSessions.begin(), tagsOfNewSessions.end(),
+ tagsOfOldSessions.begin(), tagsOfOldSessions.end(),
+ std::inserter(tagsOfInsertedSessions, tagsOfInsertedSessions.end()));
+
+ NSArray* removedIndexesSorted = nil;
+ NSArray* insertedIndexesSorted = nil;
+ if (!tagsOfRemovedSessions.empty()) {
+ NSMutableArray* removedIndexes = [NSMutableArray array];
+ for (auto& tagAndIndex : tagsOfRemovedSessions) {
+ [removedIndexes addObject:[NSNumber numberWithInt:tagAndIndex.index_]];
+ }
+ removedIndexesSorted =
+ [removedIndexes sortedArrayUsingSelector:@selector(compare:)];
+ }
+ if (!tagsOfInsertedSessions.empty()) {
+ NSMutableArray* insertedIndexes = [NSMutableArray array];
+ for (auto& tagAndIndex : tagsOfInsertedSessions) {
+ [insertedIndexes addObject:[NSNumber numberWithInt:tagAndIndex.index_]];
+ }
+ insertedIndexesSorted =
+ [insertedIndexes sortedArrayUsingSelector:@selector(compare:)];
+ }
+ if (removedIndexesSorted || insertedIndexesSorted) {
+ [delegate distantSessionsRemovedAtSortedIndexes:removedIndexesSorted
+ insertedAtSortedIndexes:insertedIndexesSorted];
+ }
+ // Compute and notify the delegate about tabs that were removed or inserted
+ // in the sessions that weren't inserted or deleted.
+ std::set<TagAndIndex> tagsOfOtherSessions;
+ std::set_intersection(
+ tagsOfNewSessions.begin(), tagsOfNewSessions.end(),
+ tagsOfOldSessions.begin(), tagsOfOldSessions.end(),
+ std::inserter(tagsOfOtherSessions, tagsOfOtherSessions.end()));
+ for (TagAndIndex const& tagAndIndexOfSession : tagsOfOtherSessions) {
+ [delegate distantSessionMayNeedUpdate:tagAndIndexOfSession.tag_];
+ }
+}
+
+- (ios_internal::SessionType)typeOfLocalSessionForTabModel:(TabModel*)tabModel {
+ DCHECK(tabModel == _mainTabModel || tabModel == _otrTabModel);
+ if (tabModel == _otrTabModel)
+ return ios_internal::SessionType::OFF_THE_RECORD_SESSION;
+ return ios_internal::SessionType::REGULAR_SESSION;
+}
+
+- (TabModelSnapshot*)tabModelSnapshotForSession:
+ (ios_internal::SessionType)type {
+ switch (type) {
+ case ios_internal::SessionType::OFF_THE_RECORD_SESSION:
+ return _otrTabModelSnapshot.get();
+ case ios_internal::SessionType::REGULAR_SESSION:
+ return _mainTabModelSnapshot.get();
+ default:
+ NOTREACHED();
+ return nullptr;
+ break;
+ }
+}
+
+- (void)setTabModelSnapshot:(std::unique_ptr<TabModelSnapshot>)tabModelSnapshot
+ forSession:(ios_internal::SessionType)type {
+ switch (type) {
+ case ios_internal::SessionType::OFF_THE_RECORD_SESSION:
+ _otrTabModelSnapshot = std::move(tabModelSnapshot);
+ break;
+ case ios_internal::SessionType::REGULAR_SESSION:
+ _mainTabModelSnapshot = std::move(tabModelSnapshot);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+- (void)tabModelChanged:(TabModel*)tabModel {
+ ios_internal::SessionType sessionType =
+ [self typeOfLocalSessionForTabModel:tabModel];
+ [_delegate localSessionMayNeedUpdate:sessionType];
+}
+
+#pragma mark - SyncedSessionsObserver
+
+- (void)reloadSessions {
+ [self syncedSessionsChanged];
+}
+
+- (void)onSyncStateChanged {
+ [self syncedSessionsChanged];
+}
+
+#pragma mark - TabModelObserver
+
+- (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab {
+ [self tabModelChanged:model];
+}
+
+- (void)tabModel:(TabModel*)model
+ didInsertTab:(Tab*)tab
+ atIndex:(NSUInteger)index
+ inForeground:(BOOL)fg {
+ [self tabModelChanged:model];
+}
+
+- (void)tabModel:(TabModel*)model
+ didRemoveTab:(Tab*)tab
+ atIndex:(NSUInteger)index {
+ [self tabModelChanged:model];
+}
+
+- (void)tabModel:(TabModel*)model
+ didMoveTab:(Tab*)tab
+ fromIndex:(NSUInteger)fromIndex
+ toIndex:(NSUInteger)toIndex {
+ [self tabModelChanged:model];
+}
+
+- (void)tabModel:(TabModel*)model
+ didReplaceTab:(Tab*)oldTab
+ withTab:(Tab*)newTab
+ atIndex:(NSUInteger)index {
+ [self tabModelChanged:model];
+}
+
+- (void)tabModel:(TabModel*)model
+ didChangeTabSnapshot:(Tab*)tab
+ withImage:(UIImage*)image {
+ [self tabModelChanged:model];
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698