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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_model.h"
6
7 #include <memory>
8
9 #include "base/memory/ptr_util.h"
10 #include "components/browser_sync/profile_sync_service.h"
11 #include "components/sessions/core/session_id.h"
12 #include "components/signin/core/browser/signin_manager.h"
13 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
14 #include "ios/chrome/browser/signin/signin_manager_factory.h"
15 #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
16 #include "ios/chrome/browser/sync/sync_setup_service.h"
17 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
18 #import "ios/chrome/browser/tabs/tab.h"
19 #import "ios/chrome/browser/tabs/tab_model.h"
20 #include "ios/chrome/browser/ui/ntp/recent_tabs/synced_sessions.h"
21 #import "ios/chrome/browser/ui/tab_switcher/session_changes.h"
22 #import "ios/chrome/browser/ui/tab_switcher/tab_model_snapshot.h"
23 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_cache.h"
24 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_model_private.h"
25 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h"
26
27 namespace ios_internal {
28
29 bool IsLocalSession(SessionType sessionType) {
30 return sessionType == SessionType::OFF_THE_RECORD_SESSION ||
31 sessionType == SessionType::REGULAR_SESSION;
32 }
33
34 } // namespace ios_internal
35
36 namespace {
37
38 class TagAndIndex {
39 public:
40 TagAndIndex(std::string const& tag, size_t index)
41 : tag_(tag), index_(index) {}
42 std::string tag_;
43 size_t index_;
44 bool operator<(const TagAndIndex& other) const { return tag_ < other.tag_; }
45 };
46
47 void FillSetUsingSessions(synced_sessions::SyncedSessions const& sessions,
48 std::set<TagAndIndex>* set) {
49 DCHECK(set);
50 DCHECK(set->empty());
51 for (size_t i = 0; i < sessions.GetSessionCount(); ++i) {
52 set->insert(TagAndIndex(sessions.GetSession(i)->tag, i));
53 }
54 }
55
56 } // namespace
57
58 @interface TabSwitcherModel () {
59 // The browser state.
60 ios::ChromeBrowserState* _browserState; // weak
61 // The tab models.
62 TabModel* _mainTabModel; // weak
63 TabModel* _otrTabModel; // weak
64 // The delegate for event callbacks.
65 id<TabSwitcherModelDelegate> _delegate; // weak, owns us.
66 // The synced sessions. Must never be null.
67 std::unique_ptr<synced_sessions::SyncedSessions> _syncedSessions;
68 // The synced sessions change observer.
69 std::unique_ptr<synced_sessions::SyncedSessionsObserverBridge>
70 _syncedSessionsObserver;
71 // Snapshots of the |_mainTabModel| and |_otrTabModel|.
72 std::unique_ptr<TabModelSnapshot> _mainTabModelSnapshot;
73 std::unique_ptr<TabModelSnapshot> _otrTabModelSnapshot;
74 // The cache holding resized tabs snapshots.
75 base::scoped_nsobject<TabSwitcherCache> _cache;
76 }
77
78 // Returns the type of the local session corresponding to the given |tabModel|.
79 // |tabModel| MUST be equal to either |_mainTabModel|, or |_otrTabModel|.
80 - (ios_internal::SessionType)typeOfLocalSessionForTabModel:(TabModel*)tabModel;
81 @end
82
83 @implementation TabSwitcherModel
84
85 @synthesize mainTabModel = _mainTabModel;
86 @synthesize otrTabModel = _otrTabModel;
87
88 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
89 delegate:(id<TabSwitcherModelDelegate>)delegate
90 mainTabModel:(TabModel*)mainTabModel
91 otrTabModel:(TabModel*)otrTabModel
92 withCache:(TabSwitcherCache*)cache {
93 DCHECK(browserState);
94 DCHECK(delegate);
95 // TODO(jif): DCHECK |mainTabModel| and |otrTabModel|.
96 self = [self init];
97 if (self) {
98 _browserState = browserState;
99 _delegate = delegate;
100 _syncedSessions.reset(new synced_sessions::SyncedSessions());
101 _syncedSessionsObserver.reset(
102 new synced_sessions::SyncedSessionsObserverBridge(self, _browserState));
103 _mainTabModel = mainTabModel;
104 _otrTabModel = otrTabModel;
105 _mainTabModelSnapshot.reset(new TabModelSnapshot(mainTabModel));
106 _otrTabModelSnapshot.reset(new TabModelSnapshot(otrTabModel));
107 [_mainTabModel addObserver:self];
108 [_otrTabModel addObserver:self];
109 _cache.reset([cache retain]);
110 }
111 return self;
112 }
113
114 - (void)setMainTabModel:(TabModel*)mainTabModel
115 otrTabModel:(TabModel*)otrTabModel {
116 [self replaceOldTabModel:&_mainTabModel withTabModel:mainTabModel];
117 [self replaceOldTabModel:&_otrTabModel withTabModel:otrTabModel];
118 }
119
120 - (void)replaceOldTabModel:(TabModel**)oldTabModel
121 withTabModel:(TabModel*)newTabModel {
122 if (*oldTabModel == newTabModel)
123 return;
124 [*oldTabModel removeObserver:self];
125 *oldTabModel = newTabModel;
126 [newTabModel addObserver:self];
127 // Calling |tabModelChanged:| may trigger an animated refresh of the
128 // Tab Switcher's collection view.
129 // Here in |replaceOldTabModel:withTabModel:| the animation is undesirable.
130 [UIView performWithoutAnimation:^{
131 [self tabModelChanged:newTabModel];
132 }];
133 }
134
135 - (void)dealloc {
136 [_mainTabModel removeObserver:self];
137 [_otrTabModel removeObserver:self];
138 [super dealloc];
139 }
140
141 - (NSInteger)sessionCount {
142 const NSInteger mainTabModelSessionCount = 1;
143 const NSInteger otrTabModelSessionCount = 1;
144 return mainTabModelSessionCount + otrTabModelSessionCount +
145 [self distantSessionCount];
146 }
147
148 - (NSInteger)distantSessionCount {
149 return _syncedSessions->GetSessionCount();
150 }
151
152 - (ios::ChromeBrowserState*)browserState {
153 return _browserState;
154 }
155
156 - (TabModel*)tabModelForSessionOfType:(ios_internal::SessionType)type {
157 DCHECK(type == ios_internal::SessionType::OFF_THE_RECORD_SESSION ||
158 type == ios_internal::SessionType::REGULAR_SESSION);
159 return type == ios_internal::SessionType::OFF_THE_RECORD_SESSION
160 ? _otrTabModel
161 : _mainTabModel;
162 }
163
164 - (NSInteger)numberOfTabsInLocalSessionOfType:(ios_internal::SessionType)type {
165 TabModelSnapshot* tabModelSnapshot = [self tabModelSnapshotForSession:type];
166 return tabModelSnapshot->tabs().size();
167 }
168
169 - (Tab*)tabAtIndex:(NSUInteger)index
170 inLocalSessionOfType:(ios_internal::SessionType)type {
171 TabModelSnapshot* tabModelSnapshot = [self tabModelSnapshotForSession:type];
172 return tabModelSnapshot->tabs()[index];
173 }
174
175 - (std::unique_ptr<TabModelSnapshot>)tabModelSnapshotForLocalSession:
176 (ios_internal::SessionType)type {
177 TabModel* tm = nullptr;
178 switch (type) {
179 case ios_internal::SessionType::OFF_THE_RECORD_SESSION:
180 tm = _otrTabModel;
181 break;
182 case ios_internal::SessionType::REGULAR_SESSION:
183 tm = _mainTabModel;
184 break;
185 default:
186 NOTREACHED();
187 break;
188 }
189 return base::MakeUnique<TabModelSnapshot>(tm);
190 }
191
192 - (std::unique_ptr<const synced_sessions::DistantSession>)distantSessionForTag:
193 (std::string const&)tag {
194 syncer::SyncService* syncService =
195 IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState);
196 return base::MakeUnique<synced_sessions::DistantSession>(syncService, tag);
197 }
198
199 - (std::string const&)tagOfDistantSessionAtIndex:(int)index {
200 return _syncedSessions->GetSession(index)->tag;
201 }
202
203 - (TabSwitcherSignInPanelsType)signInPanelType {
204 TabSwitcherSignInPanelsType panelType = TabSwitcherSignInPanelsType::NO_PANEL;
205 if (![self isSignedIn]) {
206 panelType = TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_OUT;
207 } else {
208 if (![self isSyncTabsEnabled]) {
209 panelType = TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_IN_SYNC_OFF;
210 } else {
211 if (_syncedSessions->GetSessionCount() == 0) {
212 if ([self isFirstSyncCycleCompleted]) {
213 panelType = TabSwitcherSignInPanelsType::
214 PANEL_USER_SIGNED_IN_SYNC_ON_NO_SESSIONS;
215 } else {
216 panelType = TabSwitcherSignInPanelsType::
217 PANEL_USER_SIGNED_IN_SYNC_IN_PROGRESS;
218 }
219 }
220 }
221 }
222 return panelType;
223 }
224
225 - (void)syncedSessionsChanged {
226 syncer::SyncService* syncService =
227 IOSChromeProfileSyncServiceFactory::GetForBrowserState(_browserState);
228
229 std::unique_ptr<synced_sessions::SyncedSessions> oldSyncedSessions(
230 new synced_sessions::SyncedSessions(syncService));
231 _syncedSessions.swap(oldSyncedSessions);
232
233 // Notify about change in the sign in panel.
234 TabSwitcherSignInPanelsType panelType = [self signInPanelType];
235 [_delegate signInPanelChangedTo:panelType];
236
237 if (panelType != TabSwitcherSignInPanelsType::NO_PANEL) {
238 // Do not show synced sessions.
239 _syncedSessions.reset(new synced_sessions::SyncedSessions());
240 }
241
242 // Notify about changes in the synced sessions.
243 [TabSwitcherModel notifyDelegate:_delegate
244 aboutChangeFrom:*oldSyncedSessions
245 to:*_syncedSessions];
246 }
247
248 - (BOOL)isSignedIn {
249 SigninManager* signin_manager =
250 ios::SigninManagerFactory::GetForBrowserState(_browserState);
251 return signin_manager->IsAuthenticated();
252 }
253
254 - (BOOL)isSyncTabsEnabled {
255 DCHECK([self isSignedIn]);
256 SyncSetupService* service =
257 SyncSetupServiceFactory::GetForBrowserState(_browserState);
258 return !service->UserActionIsRequiredToHaveSyncWork();
259 }
260
261 - (BOOL)isFirstSyncCycleCompleted {
262 return _syncedSessionsObserver->IsFirstSyncCycleCompleted();
263 }
264
265 + (void)notifyDelegate:(id<TabSwitcherModelDelegate>)delegate
266 aboutChangeFrom:(synced_sessions::SyncedSessions&)oldSessions
267 to:(synced_sessions::SyncedSessions&)newSessions {
268 // Compute and notify the delegate about removed or inserted sessions.
269 std::set<TagAndIndex> tagsOfOldSessions;
270 std::set<TagAndIndex> tagsOfNewSessions;
271 FillSetUsingSessions(oldSessions, &tagsOfOldSessions);
272 FillSetUsingSessions(newSessions, &tagsOfNewSessions);
273
274 std::set<TagAndIndex> tagsOfRemovedSessions;
275 std::set<TagAndIndex> tagsOfInsertedSessions;
276 std::set_difference(
277 tagsOfOldSessions.begin(), tagsOfOldSessions.end(),
278 tagsOfNewSessions.begin(), tagsOfNewSessions.end(),
279 std::inserter(tagsOfRemovedSessions, tagsOfRemovedSessions.end()));
280 std::set_difference(
281 tagsOfNewSessions.begin(), tagsOfNewSessions.end(),
282 tagsOfOldSessions.begin(), tagsOfOldSessions.end(),
283 std::inserter(tagsOfInsertedSessions, tagsOfInsertedSessions.end()));
284
285 NSArray* removedIndexesSorted = nil;
286 NSArray* insertedIndexesSorted = nil;
287 if (!tagsOfRemovedSessions.empty()) {
288 NSMutableArray* removedIndexes = [NSMutableArray array];
289 for (auto& tagAndIndex : tagsOfRemovedSessions) {
290 [removedIndexes addObject:[NSNumber numberWithInt:tagAndIndex.index_]];
291 }
292 removedIndexesSorted =
293 [removedIndexes sortedArrayUsingSelector:@selector(compare:)];
294 }
295 if (!tagsOfInsertedSessions.empty()) {
296 NSMutableArray* insertedIndexes = [NSMutableArray array];
297 for (auto& tagAndIndex : tagsOfInsertedSessions) {
298 [insertedIndexes addObject:[NSNumber numberWithInt:tagAndIndex.index_]];
299 }
300 insertedIndexesSorted =
301 [insertedIndexes sortedArrayUsingSelector:@selector(compare:)];
302 }
303 if (removedIndexesSorted || insertedIndexesSorted) {
304 [delegate distantSessionsRemovedAtSortedIndexes:removedIndexesSorted
305 insertedAtSortedIndexes:insertedIndexesSorted];
306 }
307 // Compute and notify the delegate about tabs that were removed or inserted
308 // in the sessions that weren't inserted or deleted.
309 std::set<TagAndIndex> tagsOfOtherSessions;
310 std::set_intersection(
311 tagsOfNewSessions.begin(), tagsOfNewSessions.end(),
312 tagsOfOldSessions.begin(), tagsOfOldSessions.end(),
313 std::inserter(tagsOfOtherSessions, tagsOfOtherSessions.end()));
314 for (TagAndIndex const& tagAndIndexOfSession : tagsOfOtherSessions) {
315 [delegate distantSessionMayNeedUpdate:tagAndIndexOfSession.tag_];
316 }
317 }
318
319 - (ios_internal::SessionType)typeOfLocalSessionForTabModel:(TabModel*)tabModel {
320 DCHECK(tabModel == _mainTabModel || tabModel == _otrTabModel);
321 if (tabModel == _otrTabModel)
322 return ios_internal::SessionType::OFF_THE_RECORD_SESSION;
323 return ios_internal::SessionType::REGULAR_SESSION;
324 }
325
326 - (TabModelSnapshot*)tabModelSnapshotForSession:
327 (ios_internal::SessionType)type {
328 switch (type) {
329 case ios_internal::SessionType::OFF_THE_RECORD_SESSION:
330 return _otrTabModelSnapshot.get();
331 case ios_internal::SessionType::REGULAR_SESSION:
332 return _mainTabModelSnapshot.get();
333 default:
334 NOTREACHED();
335 return nullptr;
336 break;
337 }
338 }
339
340 - (void)setTabModelSnapshot:(std::unique_ptr<TabModelSnapshot>)tabModelSnapshot
341 forSession:(ios_internal::SessionType)type {
342 switch (type) {
343 case ios_internal::SessionType::OFF_THE_RECORD_SESSION:
344 _otrTabModelSnapshot = std::move(tabModelSnapshot);
345 break;
346 case ios_internal::SessionType::REGULAR_SESSION:
347 _mainTabModelSnapshot = std::move(tabModelSnapshot);
348 break;
349 default:
350 NOTREACHED();
351 break;
352 }
353 }
354
355 - (void)tabModelChanged:(TabModel*)tabModel {
356 ios_internal::SessionType sessionType =
357 [self typeOfLocalSessionForTabModel:tabModel];
358 [_delegate localSessionMayNeedUpdate:sessionType];
359 }
360
361 #pragma mark - SyncedSessionsObserver
362
363 - (void)reloadSessions {
364 [self syncedSessionsChanged];
365 }
366
367 - (void)onSyncStateChanged {
368 [self syncedSessionsChanged];
369 }
370
371 #pragma mark - TabModelObserver
372
373 - (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab {
374 [self tabModelChanged:model];
375 }
376
377 - (void)tabModel:(TabModel*)model
378 didInsertTab:(Tab*)tab
379 atIndex:(NSUInteger)index
380 inForeground:(BOOL)fg {
381 [self tabModelChanged:model];
382 }
383
384 - (void)tabModel:(TabModel*)model
385 didRemoveTab:(Tab*)tab
386 atIndex:(NSUInteger)index {
387 [self tabModelChanged:model];
388 }
389
390 - (void)tabModel:(TabModel*)model
391 didMoveTab:(Tab*)tab
392 fromIndex:(NSUInteger)fromIndex
393 toIndex:(NSUInteger)toIndex {
394 [self tabModelChanged:model];
395 }
396
397 - (void)tabModel:(TabModel*)model
398 didReplaceTab:(Tab*)oldTab
399 withTab:(Tab*)newTab
400 atIndex:(NSUInteger)index {
401 [self tabModelChanged:model];
402 }
403
404 - (void)tabModel:(TabModel*)model
405 didChangeTabSnapshot:(Tab*)tab
406 withImage:(UIImage*)image {
407 [self tabModelChanged:model];
408 }
409
410 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698