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

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

Issue 2585233003: Upstream Chrome on iOS source code [2/11]. (Closed)
Patch Set: Created 3 years, 12 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import <objc/runtime.h>
6
7 #include "base/mac/scoped_nsautorelease_pool.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/run_loop.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
12 #include "ios/chrome/browser/chrome_url_constants.h"
13 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
14 #import "ios/chrome/browser/sessions/session_window.h"
15 #import "ios/chrome/browser/sessions/test_session_service.h"
16 #import "ios/chrome/browser/tabs/tab.h"
17 #import "ios/chrome/browser/tabs/tab_model.h"
18 #import "ios/chrome/browser/tabs/tab_model_observer.h"
19 #import "ios/chrome/browser/tabs/tab_private.h"
20 #import "ios/chrome/browser/web/chrome_web_client.h"
21 #import "ios/web/navigation/crw_session_controller.h"
22 #import "ios/web/navigation/navigation_manager_impl.h"
23 #import "ios/web/public/navigation_manager.h"
24 #include "ios/web/public/referrer.h"
25 #include "ios/web/public/test/scoped_testing_web_client.h"
26 #include "ios/web/public/test/test_web_thread_bundle.h"
27 #include "ios/web/public/web_thread.h"
28 #import "ios/web/web_state/ui/crw_web_controller.h"
29 #import "ios/web/web_state/web_state_impl.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "testing/gtest_mac.h"
32 #include "testing/platform_test.h"
33 #import "third_party/ocmock/OCMock/OCMock.h"
34 #include "third_party/ocmock/gtest_support.h"
35
36 using web::WebStateImpl;
37
38 // For some of the unit tests, we need to make sure the session is saved
39 // immediately so we can read it back in to verify various attributes. This
40 // is not a situation we normally expect to be in because we never
41 // want the session being saved on the main thread in the production app.
42 // We could expose this as part of the service's public API, but again that
43 // might encourage use where we don't want it. As a result, just use the
44 // known private-for-testing method directly.
45 @interface SessionServiceIOS (Testing)
46 - (void)performSaveWindow:(SessionWindowIOS*)window
47 toDirectory:(NSString*)directory;
48 @end
49
50 // Trivial objective C class whose unique aim is to be a wrapper of C++
51 // classes.
52 @interface ClassesWrapper : NSObject {
53 @public
54 std::unique_ptr<WebStateImpl> _webStateImpl;
55 }
56 @end
57
58 @implementation ClassesWrapper
59 @end
60
61 @interface TabTest : Tab
62
63 - (instancetype)initWithWindowName:(NSString*)windowName
64 lastVisitedTimestamp:(double)lastVisitedTimestamp
65 browserState:(ios::ChromeBrowserState*)browserState
66 tabModel:(TabModel*)tabModel;
67 @end
68
69 @implementation TabTest
70
71 - (instancetype)initWithWindowName:(NSString*)windowName
72 lastVisitedTimestamp:(double)lastVisitedTimestamp
73 browserState:(ios::ChromeBrowserState*)browserState
74 tabModel:(TabModel*)tabModel {
75 self = [super initWithWindowName:windowName
76 opener:nil
77 openedByDOM:NO
78 model:tabModel
79 browserState:browserState];
80 if (self) {
81 id webControllerMock =
82 [OCMockObject niceMockForClass:[CRWWebController class]];
83
84 std::unique_ptr<WebStateImpl> webStateImpl(new WebStateImpl(browserState));
85 webStateImpl->SetWebController(webControllerMock);
86 webStateImpl->GetNavigationManagerImpl().InitializeSession(
87 windowName, @"opener", NO, -1);
88 [webStateImpl->GetNavigationManagerImpl().GetSessionController()
89 setLastVisitedTimestamp:lastVisitedTimestamp];
90
91 WebStateImpl* webStateImplPtr = webStateImpl.get();
92 [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(webStateImplPtr)]
93 webStateImpl];
94 BOOL yes = YES;
95 [[[webControllerMock stub] andReturnValue:OCMOCK_VALUE(yes)] isViewAlive];
96
97 [self replaceWebStateImpl:std::move(webStateImpl)];
98 }
99 return self;
100 }
101
102 @end
103
104 @interface TabModel (VisibleForTesting)
105 - (SessionWindowIOS*)windowForSavingSession;
106 @end
107
108 // Defines a TabModelObserver for use in unittests. This class can be used to
109 // test if an observer method was called or not.
110 @interface TabModelObserverPong : NSObject<TabModelObserver> {
111 // TODO(crbug.com/661989): Add tests for the other observer methods.
112 BOOL tabMovedWasCalled_;
113 }
114 @property(nonatomic, assign) BOOL tabMovedWasCalled;
115 @end
116
117 @implementation TabModelObserverPong
118 @synthesize tabMovedWasCalled = tabMovedWasCalled_;
119
120 - (void)tabModel:(TabModel*)model
121 didMoveTab:(Tab*)tab
122 fromIndex:(NSUInteger)fromIndex
123 toIndex:(NSUInteger)toIndex {
124 tabMovedWasCalled_ = YES;
125 }
126
127 @end
128
129 namespace {
130
131 const GURL kURL("https://www.some.url.com");
132 const web::Referrer kEmptyReferrer;
133 const web::Referrer kReferrer(GURL("https//www.some.referer.com"),
134 web::ReferrerPolicyDefault);
135 const web::Referrer kReferrer2(GURL("https//www.some.referer2.com"),
136 web::ReferrerPolicyDefault);
137
138 class TabModelTest : public PlatformTest {
139 public:
140 TabModelTest() : web_client_(base::MakeUnique<ChromeWebClient>()) {}
141
142 protected:
143 void SetUp() override {
144 DCHECK_CURRENTLY_ON(web::WebThread::UI);
145 PlatformTest::SetUp();
146
147 TestChromeBrowserState::Builder test_cbs_builder;
148 chrome_browser_state_ = test_cbs_builder.Build();
149
150 sessionWindow_.reset([[SessionWindowIOS new] retain]);
151 // Create tab model with just a dummy session service so the async state
152 // saving doesn't trigger unless actually wanted.
153 base::scoped_nsobject<TestSessionService> test_service(
154 [[TestSessionService alloc] init]);
155 tabModel_.reset([[TabModel alloc]
156 initWithSessionWindow:sessionWindow_.get()
157 sessionService:test_service
158 browserState:chrome_browser_state_.get()]);
159 [tabModel_ setWebUsageEnabled:YES];
160 [tabModel_ setPrimary:YES];
161 tabModelObserver_.reset([[TabModelObserverPong alloc] init]);
162 [tabModel_ addObserver:tabModelObserver_];
163 }
164
165 void TearDown() override {
166 [tabModel_ removeObserver:tabModelObserver_];
167 [tabModel_ browserStateDestroyed];
168 PlatformTest::TearDown();
169 }
170
171 Tab* CreateTab(NSString* windowName,
172 double lastVisitedTimestamp) NS_RETURNS_RETAINED {
173 return [[TabTest alloc] initWithWindowName:windowName
174 lastVisitedTimestamp:lastVisitedTimestamp
175 browserState:chrome_browser_state_.get()
176 tabModel:tabModel_.get()];
177 }
178
179 std::unique_ptr<WebStateImpl> CreateWebState(NSString* windowName,
180 NSString* opener,
181 NSInteger index) {
182 std::unique_ptr<WebStateImpl> webState(
183 new WebStateImpl(chrome_browser_state_.get()));
184 webState->GetNavigationManagerImpl().InitializeSession(windowName, opener,
185 NO, index);
186 return webState;
187 }
188
189 std::unique_ptr<WebStateImpl> CreateWebState(NSString* windowName) {
190 return CreateWebState(windowName, @"", -1);
191 }
192
193 std::unique_ptr<WebStateImpl> CreateChildWebState(Tab* parent) {
194 return CreateWebState([parent windowName], [parent currentSessionID], -1);
195 }
196
197 void RestoreSession(SessionWindowIOS* window) {
198 [tabModel_ restoreSessionWindow:window];
199 }
200
201 // Creates a session window with |entries| entries and a |selectedIndex| of 1.
202 SessionWindowIOS* CreateSessionWindow(int entries) {
203 SessionWindowIOS* window = [[SessionWindowIOS alloc] init];
204 for (int i = 0; i < entries; i++) {
205 NSString* windowName = [NSString stringWithFormat:@"window %d", i + 1];
206 [window addSession:CreateWebState(windowName)];
207 }
208 if (entries)
209 [window setSelectedIndex:1];
210 return window;
211 }
212
213 web::TestWebThreadBundle thread_bundle_;
214 web::ScopedTestingWebClient web_client_;
215 base::scoped_nsobject<SessionWindowIOS> sessionWindow_;
216 std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
217 base::scoped_nsobject<TabModel> tabModel_;
218 base::scoped_nsobject<TabModelObserverPong> tabModelObserver_;
219 base::mac::ScopedNSAutoreleasePool pool_;
220 };
221
222 TEST_F(TabModelTest, IsStoredAsUserData) {
223 EXPECT_EQ(tabModel_,
224 [TabModel tabModelForBrowserState:chrome_browser_state_.get()]);
225 [tabModel_ browserStateDestroyed];
226 EXPECT_EQ(nil,
227 [TabModel tabModelForBrowserState:chrome_browser_state_.get()]);
228 // Verify that a null browser state doesn't break +tabModelForBrowserState.
229 EXPECT_EQ(nil, [TabModel tabModelForBrowserState:nullptr]);
230 }
231
232 TEST_F(TabModelTest, IsEmpty) {
233 EXPECT_EQ([tabModel_ count], 0U);
234 EXPECT_TRUE([tabModel_ isEmpty]);
235 [tabModel_ insertTabWithURL:kURL
236 referrer:kReferrer
237 windowName:@"window 1"
238 opener:nil
239 atIndex:0];
240 ASSERT_EQ(1U, [tabModel_ count]);
241 EXPECT_FALSE([tabModel_ isEmpty]);
242 }
243
244 TEST_F(TabModelTest, InsertUrlSingle) {
245 [tabModel_ insertTabWithURL:kURL
246 referrer:kReferrer
247 windowName:@"window 1"
248 opener:nil
249 atIndex:0];
250 ASSERT_EQ(1U, [tabModel_ count]);
251 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
252 }
253
254 TEST_F(TabModelTest, InsertUrlMultiple) {
255 [tabModel_ insertTabWithURL:kURL
256 referrer:kReferrer
257 windowName:@"window 1"
258 opener:nil
259 atIndex:0];
260 [tabModel_ insertTabWithURL:kURL
261 referrer:kReferrer
262 windowName:@"window 2"
263 opener:nil
264 atIndex:0];
265 [tabModel_ insertTabWithURL:kURL
266 referrer:kReferrer
267 windowName:@"window 3"
268 opener:nil
269 atIndex:1];
270
271 ASSERT_EQ(3U, [tabModel_ count]);
272 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
273 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
274 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
275 }
276
277 TEST_F(TabModelTest, AppendUrlSingle) {
278 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
279 ASSERT_EQ(1U, [tabModel_ count]);
280 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
281 }
282
283 TEST_F(TabModelTest, AppendUrlMultiple) {
284 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
285 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
286 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
287
288 ASSERT_EQ(3U, [tabModel_ count]);
289 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
290 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
291 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
292 }
293
294 TEST_F(TabModelTest, CloseTabAtIndexBeginning) {
295 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
296 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
297 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
298
299 [tabModel_ closeTabAtIndex:0];
300
301 ASSERT_EQ(2U, [tabModel_ count]);
302 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
303 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
304 }
305
306 TEST_F(TabModelTest, CloseTabAtIndexMiddle) {
307 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
308 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
309 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
310
311 [tabModel_ closeTabAtIndex:1];
312
313 ASSERT_EQ(2U, [tabModel_ count]);
314 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
315 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
316 }
317
318 TEST_F(TabModelTest, CloseTabAtIndexLast) {
319 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
320 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
321 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
322
323 [tabModel_ closeTabAtIndex:2];
324
325 ASSERT_EQ(2U, [tabModel_ count]);
326 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
327 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
328 }
329
330 TEST_F(TabModelTest, CloseTabAtIndexOnlyOne) {
331 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
332
333 [tabModel_ closeTabAtIndex:0];
334
335 EXPECT_EQ(0U, [tabModel_ count]);
336 }
337
338 TEST_F(TabModelTest, RestoreSessionOnNTPTest) {
339 [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
340 referrer:kEmptyReferrer
341 windowName:@"old window"
342 opener:nil
343 atIndex:0];
344 base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
345
346 RestoreSession(window.get());
347 ASSERT_EQ(3U, [tabModel_ count]);
348 EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
349 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
350 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
351 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
352 }
353
354 TEST_F(TabModelTest, RestoreSessionOn2NtpTest) {
355 [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
356 referrer:kEmptyReferrer
357 windowName:@"old window 1"
358 opener:nil
359 atIndex:0];
360 [tabModel_ insertTabWithURL:GURL(kChromeUINewTabURL)
361 referrer:kEmptyReferrer
362 windowName:@"old window 2"
363 opener:nil
364 atIndex:1];
365 base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
366
367 RestoreSession(window.get());
368 ASSERT_EQ(5U, [tabModel_ count]);
369 EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
370 EXPECT_NSEQ(@"old window 1", [[tabModel_ tabAtIndex:0] windowName]);
371 EXPECT_NSEQ(@"old window 2", [[tabModel_ tabAtIndex:1] windowName]);
372 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
373 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:3] windowName]);
374 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:4] windowName]);
375 }
376
377 TEST_F(TabModelTest, RestoreSessionOnAnyTest) {
378 [tabModel_ insertTabWithURL:kURL
379 referrer:kEmptyReferrer
380 windowName:@"old window 1"
381 opener:nil
382 atIndex:0];
383 base::scoped_nsobject<SessionWindowIOS> window(CreateSessionWindow(3));
384
385 RestoreSession(window.get());
386 ASSERT_EQ(4U, [tabModel_ count]);
387 EXPECT_NSEQ(@"window 2", [[tabModel_ currentTab] windowName]);
388 EXPECT_NSEQ(@"old window 1", [[tabModel_ tabAtIndex:0] windowName]);
389 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
390 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:2] windowName]);
391 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:3] windowName]);
392 }
393
394 TEST_F(TabModelTest, TabForWindowName) {
395 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
396 [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
397 referrer:kReferrer2
398 windowName:@"window 2"];
399 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
400
401 Tab* tab = [tabModel_ tabWithWindowName:@"window 2"];
402
403 EXPECT_NSEQ([tab windowName], @"window 2");
404 EXPECT_EQ(tab.url, GURL("https://www.some.url2.com/"));
405 }
406
407 TEST_F(TabModelTest, TabForWindowNameNotFound) {
408 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
409 [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
410 referrer:kReferrer2
411 windowName:@"window 2"];
412 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
413
414 Tab* tab = [tabModel_ tabWithWindowName:@"window not found"];
415
416 EXPECT_EQ(nil, tab);
417 }
418
419 TEST_F(TabModelTest, CloseAllTabs) {
420 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
421 [tabModel_ addTabWithURL:GURL("https://www.some.url2.com")
422 referrer:kReferrer2
423 windowName:@"window 2"];
424 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
425
426 [tabModel_ closeAllTabs];
427
428 EXPECT_EQ(0U, [tabModel_ count]);
429 }
430
431 TEST_F(TabModelTest, CloseAllTabsWithNoTabs) {
432 [tabModel_ closeAllTabs];
433
434 EXPECT_EQ(0U, [tabModel_ count]);
435 }
436
437 TEST_F(TabModelTest, InsertWithSessionController) {
438 EXPECT_EQ([tabModel_ count], 0U);
439 EXPECT_TRUE([tabModel_ isEmpty]);
440
441 Tab* new_tab =
442 [tabModel_ insertTabWithWebState:CreateWebState(@"window", @"opener", -1)
443 atIndex:0];
444 EXPECT_EQ([tabModel_ count], 1U);
445 [tabModel_ setCurrentTab:new_tab];
446 Tab* current_tab = [tabModel_ currentTab];
447 EXPECT_TRUE(current_tab);
448 }
449
450 TEST_F(TabModelTest, OpenerOfTab) {
451 // Start off with a couple tabs.
452 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
453 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
454 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
455
456 // Create parent tab.
457 Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
458 atIndex:[tabModel_ count]];
459 // Create child tab.
460 Tab* child_tab =
461 [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
462 atIndex:[tabModel_ count]];
463 // Create another unrelated tab.
464 Tab* another_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
465 atIndex:[tabModel_ count]];
466
467 // Create another child of the first tab.
468 Tab* child_tab2 =
469 [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
470 atIndex:[tabModel_ count]];
471
472 EXPECT_FALSE([tabModel_ openerOfTab:parent_tab]);
473 EXPECT_FALSE([tabModel_ openerOfTab:another_tab]);
474 EXPECT_EQ(parent_tab, [tabModel_ openerOfTab:child_tab]);
475 EXPECT_EQ(parent_tab, [tabModel_ openerOfTab:child_tab2]);
476 }
477
478 TEST_F(TabModelTest, OpenerOfTabEmptyModel) {
479 EXPECT_FALSE([tabModel_ openerOfTab:nil]);
480 }
481
482 TEST_F(TabModelTest, OpenersEmptyModel) {
483 // Empty model.
484 EXPECT_TRUE([tabModel_ isEmpty]);
485 EXPECT_FALSE([tabModel_ nextTabWithOpener:nil afterTab:nil]);
486 EXPECT_FALSE([tabModel_ lastTabWithOpener:nil]);
487 EXPECT_FALSE([tabModel_ firstTabWithOpener:nil]);
488 }
489
490 TEST_F(TabModelTest, OpenersNothingOpenedGeneral) {
491 // Start with a few tabs.
492 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
493 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
494
495 Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
496 atIndex:[tabModel_ count]];
497
498 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
499 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
500
501 // All should fail since this hasn't opened anything else.
502 EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
503 EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
504 EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
505
506 // Add more items to the tab, expect the same results.
507 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
508 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
509 EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
510 EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
511 EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
512 }
513
514 TEST_F(TabModelTest, OpenersNothingOpenedFirst) {
515 // Our tab is first.
516 Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
517 atIndex:[tabModel_ count]];
518
519 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
520 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
521
522 // All should fail since this hasn't opened anything else.
523 EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
524 EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
525 EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
526 }
527
528 TEST_F(TabModelTest, OpenersNothingOpenedLast) {
529 // Our tab is last.
530 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
531 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
532 Tab* tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
533 atIndex:[tabModel_ count]];
534
535 // All should fail since this hasn't opened anything else.
536 EXPECT_FALSE([tabModel_ nextTabWithOpener:tab afterTab:nil]);
537 EXPECT_FALSE([tabModel_ lastTabWithOpener:tab]);
538 EXPECT_FALSE([tabModel_ firstTabWithOpener:tab]);
539 }
540
541 TEST_F(TabModelTest, OpenersChildTabBeforeOpener) {
542 Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
543 atIndex:[tabModel_ count]];
544 // Insert child at start
545 Tab* child_tab =
546 [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
547 atIndex:0];
548
549 // Insert a few more between them.
550 [tabModel_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
551 [tabModel_ insertTabWithWebState:CreateWebState(@"window") atIndex:1];
552
553 EXPECT_FALSE([tabModel_ nextTabWithOpener:parent_tab afterTab:nil]);
554 EXPECT_FALSE([tabModel_ lastTabWithOpener:parent_tab]);
555 EXPECT_EQ([tabModel_ firstTabWithOpener:parent_tab], child_tab);
556 }
557
558 TEST_F(TabModelTest, OpenersChildTabAfterOpener) {
559 Tab* parent_tab = [tabModel_ insertTabWithWebState:CreateWebState(@"window")
560 atIndex:[tabModel_ count]];
561
562 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
563 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
564 // Insert two children at end.
565 Tab* child_tab1 =
566 [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
567 atIndex:[tabModel_ count]];
568 Tab* child_tab2 =
569 [tabModel_ insertTabWithWebState:CreateChildWebState(parent_tab)
570 atIndex:[tabModel_ count]];
571
572 EXPECT_EQ([tabModel_ nextTabWithOpener:parent_tab afterTab:nil], child_tab1);
573 EXPECT_EQ([tabModel_ nextTabWithOpener:parent_tab afterTab:child_tab1],
574 child_tab2);
575 EXPECT_EQ([tabModel_ lastTabWithOpener:parent_tab], child_tab2);
576 EXPECT_FALSE([tabModel_ firstTabWithOpener:parent_tab]);
577 }
578
579 TEST_F(TabModelTest, AddWithOrderController) {
580 // Create a few tabs with the controller at the front.
581 Tab* parent =
582 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
583 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
584 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
585
586 // Add a new tab, it should be added behind the parent.
587 Tab* child = [tabModel_
588 insertOrUpdateTabWithURL:kURL
589 referrer:kEmptyReferrer
590 transition:ui::PAGE_TRANSITION_LINK
591 windowName:nil
592 opener:parent
593 openedByDOM:NO
594 atIndex:TabModelConstants::kTabPositionAutomatically
595 inBackground:NO];
596 EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
597 EXPECT_EQ([tabModel_ indexOfTab:child], 1U);
598
599 // Add another new tab without a parent, should go at the end.
600 Tab* tab = [tabModel_
601 insertOrUpdateTabWithURL:kURL
602 referrer:kEmptyReferrer
603 transition:ui::PAGE_TRANSITION_LINK
604 windowName:nil
605 opener:nil
606 openedByDOM:NO
607 atIndex:TabModelConstants::kTabPositionAutomatically
608 inBackground:NO];
609 EXPECT_EQ([tabModel_ indexOfTab:tab], [tabModel_ count] - 1);
610
611 // Same for a tab that's not opened via a LINK transition.
612 Tab* tab2 = [tabModel_ insertOrUpdateTabWithURL:kURL
613 referrer:kEmptyReferrer
614 transition:ui::PAGE_TRANSITION_TYPED
615 windowName:nil
616 opener:nil
617 openedByDOM:NO
618 atIndex:[tabModel_ count]
619 inBackground:NO];
620 EXPECT_EQ([tabModel_ indexOfTab:tab2], [tabModel_ count] - 1);
621
622 // Add a tab in the background. It should appear behind the opening tab.
623 Tab* tab3 = [tabModel_
624 insertOrUpdateTabWithURL:kURL
625 referrer:kEmptyReferrer
626 transition:ui::PAGE_TRANSITION_LINK
627 windowName:nil
628 opener:tab
629 openedByDOM:NO
630 atIndex:TabModelConstants::kTabPositionAutomatically
631 inBackground:YES];
632 EXPECT_EQ([tabModel_ indexOfTab:tab3], [tabModel_ indexOfTab:tab] + 1);
633
634 // Add another background tab behind the one we just opened.
635 Tab* tab4 = [tabModel_
636 insertOrUpdateTabWithURL:kURL
637 referrer:kEmptyReferrer
638 transition:ui::PAGE_TRANSITION_LINK
639 windowName:nil
640 opener:tab3
641 openedByDOM:NO
642 atIndex:TabModelConstants::kTabPositionAutomatically
643 inBackground:YES];
644 EXPECT_EQ([tabModel_ indexOfTab:tab4], [tabModel_ indexOfTab:tab3] + 1);
645 }
646
647 TEST_F(TabModelTest, AddWithOrderControllerAndGrouping) {
648 // Create a few tabs with the controller at the front.
649 Tab* parent =
650 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
651 // Force the history to update, as it is used to determine grouping.
652 ASSERT_TRUE([parent navigationManager]);
653 [[parent navigationManager]->GetSessionController() commitPendingEntry];
654 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
655 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
656
657 ASSERT_TRUE(chrome_browser_state_->CreateHistoryService(true));
658
659 // Add a new tab, it should be added behind the parent.
660 Tab* child1 = [tabModel_
661 insertOrUpdateTabWithURL:kURL
662 referrer:kEmptyReferrer
663 transition:ui::PAGE_TRANSITION_LINK
664 windowName:nil
665 opener:parent
666 openedByDOM:NO
667 atIndex:TabModelConstants::kTabPositionAutomatically
668 inBackground:NO];
669 EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
670 EXPECT_EQ([tabModel_ indexOfTab:child1], 1U);
671
672 // Add a second child tab in the background. It should be added behind the
673 // first child.
674 Tab* child2 = [tabModel_
675 insertOrUpdateTabWithURL:kURL
676 referrer:kEmptyReferrer
677 transition:ui::PAGE_TRANSITION_LINK
678 windowName:nil
679 opener:parent
680 openedByDOM:NO
681 atIndex:TabModelConstants::kTabPositionAutomatically
682 inBackground:YES];
683 EXPECT_EQ([tabModel_ indexOfTab:child2], 2U);
684
685 // Navigate the parent tab to a new URL. It should not change any ordering.
686 web::NavigationManager::WebLoadParams parent_params(
687 GURL("http://www.espn.com"));
688 parent_params.transition_type = ui::PAGE_TRANSITION_TYPED;
689 [[parent webController] loadWithParams:parent_params];
690 ASSERT_TRUE([parent navigationManager]);
691 [[parent navigationManager]->GetSessionController() commitPendingEntry];
692 EXPECT_EQ([tabModel_ indexOfTab:parent], 0U);
693
694 // Add a new tab. It should be added behind the parent. It should not be added
695 // after the previous two children.
696 Tab* child3 = [tabModel_
697 insertOrUpdateTabWithURL:kURL
698 referrer:kEmptyReferrer
699 transition:ui::PAGE_TRANSITION_LINK
700 windowName:nil
701 opener:parent
702 openedByDOM:NO
703 atIndex:TabModelConstants::kTabPositionAutomatically
704 inBackground:NO];
705 EXPECT_EQ([tabModel_ indexOfTab:child3], 1U);
706
707 // Add a fourt child tab in the background. It should be added behind the
708 // third child.
709 Tab* child4 = [tabModel_
710 insertOrUpdateTabWithURL:kURL
711 referrer:kEmptyReferrer
712 transition:ui::PAGE_TRANSITION_LINK
713 windowName:nil
714 opener:parent
715 openedByDOM:NO
716 atIndex:TabModelConstants::kTabPositionAutomatically
717 inBackground:YES];
718 EXPECT_EQ([tabModel_ indexOfTab:child4], 2U);
719
720 // The first two children should have been moved to the right.
721 EXPECT_EQ([tabModel_ indexOfTab:child1], 3U);
722 EXPECT_EQ([tabModel_ indexOfTab:child2], 4U);
723
724 // Now add a non-owned tab and make sure it is added at the end.
725 Tab* nonChild =
726 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
727 EXPECT_EQ([tabModel_ indexOfTab:nonChild], [tabModel_ count] - 1);
728 }
729
730 TEST_F(TabModelTest, AddWithLinkTransitionAndIndex) {
731 // Create a few tabs with the controller at the front.
732 Tab* parent =
733 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
734 // Force the history to update, as it is used to determine grouping.
735 ASSERT_TRUE([parent navigationManager]);
736 [[parent navigationManager]->GetSessionController() commitPendingEntry];
737 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
738 [tabModel_ addTabWithURL:kURL referrer:kEmptyReferrer windowName:nil];
739
740 ASSERT_TRUE(chrome_browser_state_->CreateHistoryService(true));
741
742 // Add a new tab, it should be added before the parent since the index
743 // parameter has been specified with a valid value.
744 Tab* child1 = [tabModel_ insertOrUpdateTabWithURL:kURL
745 referrer:kEmptyReferrer
746 transition:ui::PAGE_TRANSITION_LINK
747 windowName:nil
748 opener:parent
749 openedByDOM:NO
750 atIndex:0
751 inBackground:NO];
752 EXPECT_EQ([tabModel_ indexOfTab:parent], 1U);
753 EXPECT_EQ([tabModel_ indexOfTab:child1], 0U);
754
755 // Add a new tab, it should be added at the beginning of the stack because
756 // the index parameter has been specified with a valid value.
757 Tab* child2 = [tabModel_ insertOrUpdateTabWithURL:kURL
758 referrer:kEmptyReferrer
759 transition:ui::PAGE_TRANSITION_LINK
760 windowName:nil
761 opener:parent
762 openedByDOM:NO
763 atIndex:0
764 inBackground:NO];
765 EXPECT_EQ([tabModel_ indexOfTab:parent], 2U);
766 EXPECT_EQ([tabModel_ indexOfTab:child1], 1U);
767 EXPECT_EQ([tabModel_ indexOfTab:child2], 0U);
768
769 // Add a new tab, it should be added at position 1 because the index parameter
770 // has been specified with a valid value.
771 Tab* child3 = [tabModel_ insertOrUpdateTabWithURL:kURL
772 referrer:kEmptyReferrer
773 transition:ui::PAGE_TRANSITION_LINK
774 windowName:nil
775 opener:parent
776 openedByDOM:NO
777 atIndex:1
778 inBackground:NO];
779 EXPECT_EQ([tabModel_ indexOfTab:parent], 3U);
780 EXPECT_EQ([tabModel_ indexOfTab:child1], 2U);
781 EXPECT_EQ([tabModel_ indexOfTab:child3], 1U);
782 EXPECT_EQ([tabModel_ indexOfTab:child2], 0U);
783 }
784
785 TEST_F(TabModelTest, MoveTabs) {
786 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
787 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
788 [tabModel_ addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
789
790 // Basic sanity checks before moving on.
791 ASSERT_EQ(3U, [tabModel_ count]);
792 ASSERT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:0] windowName]);
793 ASSERT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:1] windowName]);
794 ASSERT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
795
796 // Move a tab from index 1 to index 0 (move tab left by one).
797 [tabModelObserver_ setTabMovedWasCalled:NO];
798 [tabModel_ moveTab:[tabModel_ tabAtIndex:1] toIndex:0];
799 ASSERT_EQ(3U, [tabModel_ count]);
800 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
801 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
802 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:2] windowName]);
803 EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
804
805 // Move a tab from index 1 to index 2 (move tab right by one).
806 [tabModelObserver_ setTabMovedWasCalled:NO];
807 [tabModel_ moveTab:[tabModel_ tabAtIndex:1] toIndex:2];
808 ASSERT_EQ(3U, [tabModel_ count]);
809 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
810 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
811 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
812 EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
813
814 // Move a tab from index 0 to index 2 (move tab right by more than one).
815 [tabModelObserver_ setTabMovedWasCalled:NO];
816 [tabModel_ moveTab:[tabModel_ tabAtIndex:0] toIndex:2];
817 ASSERT_EQ(3U, [tabModel_ count]);
818 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:0] windowName]);
819 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:1] windowName]);
820 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:2] windowName]);
821 EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
822
823 // Move a tab from index 2 to index 0 (move tab left by more than one).
824 [tabModelObserver_ setTabMovedWasCalled:NO];
825 [tabModel_ moveTab:[tabModel_ tabAtIndex:2] toIndex:0];
826 ASSERT_EQ(3U, [tabModel_ count]);
827 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
828 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
829 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
830 EXPECT_TRUE([tabModelObserver_ tabMovedWasCalled]);
831
832 // Move a tab from index 2 to index 2 (move tab to the same index).
833 [tabModelObserver_ setTabMovedWasCalled:NO];
834 [tabModel_ moveTab:[tabModel_ tabAtIndex:2] toIndex:2];
835 ASSERT_EQ(3U, [tabModel_ count]);
836 EXPECT_NSEQ(@"window 2", [[tabModel_ tabAtIndex:0] windowName]);
837 EXPECT_NSEQ(@"window 3", [[tabModel_ tabAtIndex:1] windowName]);
838 EXPECT_NSEQ(@"window 1", [[tabModel_ tabAtIndex:2] windowName]);
839 EXPECT_FALSE([tabModelObserver_ tabMovedWasCalled]);
840 }
841
842 TEST_F(TabModelTest, SetParentModel) {
843 // Create a tab without a parent model and make sure it doesn't crash. Then
844 // set its parent TabModel and make sure that works as well.
845 base::scoped_nsobject<TabTest> tab([[TabTest alloc]
846 initWithWindowName:@"parentless"
847 lastVisitedTimestamp:100
848 browserState:chrome_browser_state_.get()
849 tabModel:nil]);
850 EXPECT_TRUE([tab parentTabModel] == nil);
851 [tabModel_ insertTab:tab atIndex:0];
852 [tab setParentTabModel:tabModel_.get()];
853 EXPECT_FALSE([tab parentTabModel] == nil);
854 [tabModel_ closeTabAtIndex:0];
855 }
856
857 TEST_F(TabModelTest, PersistSelectionChange) {
858 NSString* stashPath =
859 base::SysUTF8ToNSString(chrome_browser_state_->GetStatePath().value());
860
861 base::scoped_nsobject<TabModel> model([[TabModel alloc]
862 initWithSessionWindow:sessionWindow_.get()
863 sessionService:[SessionServiceIOS sharedService]
864 browserState:chrome_browser_state_.get()]);
865
866 [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 1"];
867 [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 2"];
868 [model addTabWithURL:kURL referrer:kReferrer windowName:@"window 3"];
869
870 ASSERT_EQ(3U, [model count]);
871 model.get().currentTab = [model tabAtIndex:1];
872 // Force state to flush to disk on the main thread so it can be immediately
873 // tested below.
874 SessionWindowIOS* window = [model windowForSavingSession];
875 [[SessionServiceIOS sharedService] performSaveWindow:window
876 toDirectory:stashPath];
877 [model browserStateDestroyed];
878 model.reset();
879 base::RunLoop().RunUntilIdle();
880
881 SessionWindowIOS* sessionWindow = [[SessionServiceIOS sharedService]
882 loadWindowForBrowserState:chrome_browser_state_.get()];
883
884 // Create tab model from saved session.
885 base::scoped_nsobject<TestSessionService> test_service(
886 [[TestSessionService alloc] init]);
887
888 model.reset([[TabModel alloc]
889 initWithSessionWindow:sessionWindow
890 sessionService:test_service
891 browserState:chrome_browser_state_.get()]);
892 EXPECT_EQ(model.get().currentTab, [model tabAtIndex:1]);
893 [model browserStateDestroyed];
894
895 // Clean up.
896 EXPECT_TRUE([[NSFileManager defaultManager] removeItemAtPath:stashPath
897 error:nullptr]);
898 }
899
900 } // anonymous namespace
OLDNEW
« no previous file with comments | « ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm ('k') | ios/chrome/browser/tabs/tab_private.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698