Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / local_discovery / local_discovery_ui_browsertest.cc
blob049c95a47d50e3103e6a6d559377bfb607e98adb
1 // Copyright 2013 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.
5 #include "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "chrome/browser/local_discovery/test_service_discovery_client.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
18 #include "chrome/common/chrome_constants.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "chrome/test/base/web_ui_browser_test.h"
23 #include "components/signin/core/browser/profile_oauth2_token_service.h"
24 #include "components/signin/core/browser/signin_manager.h"
25 #include "components/signin/core/browser/signin_manager_base.h"
26 #include "google_apis/gaia/gaia_urls.h"
27 #include "net/http/http_status_code.h"
28 #include "net/url_request/test_url_fetcher_factory.h"
29 #include "net/url_request/url_request_status.h"
30 #include "net/url_request/url_request_test_util.h"
32 #if defined(OS_CHROMEOS)
33 #include "base/prefs/pref_service.h"
34 #include "chrome/common/pref_names.h"
35 #include "chromeos/chromeos_switches.h"
36 #endif
38 using testing::InvokeWithoutArgs;
39 using testing::Return;
40 using testing::AtLeast;
41 using testing::DoDefault;
42 using testing::DoAll;
43 using testing::InSequence;
44 using testing::StrictMock;
45 using testing::AnyNumber;
47 using testing::InvokeWithoutArgs;
48 using testing::Return;
49 using testing::AtLeast;
51 namespace local_discovery {
53 namespace {
55 const uint8 kQueryData[] = {
56 // Header
57 0x00, 0x00,
58 0x00, 0x00, // Flags not set.
59 0x00, 0x01, // Set QDCOUNT (question count) to 1, all the
60 // rest are 0 for a query.
61 0x00, 0x00,
62 0x00, 0x00,
63 0x00, 0x00,
65 // Question
66 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
67 0x04, '_', 't', 'c', 'p',
68 0x05, 'l', 'o', 'c', 'a', 'l',
69 0x00,
71 0x00, 0x0c, // QTYPE: A query.
72 0x00, 0x01, // QCLASS: IN class. Unicast bit not set.
75 const uint8 kAnnouncePacket[] = {
76 // Header
77 0x00, 0x00, // ID is zeroed out
78 0x80, 0x00, // Standard query response, no error
79 0x00, 0x00, // No questions (for simplicity)
80 0x00, 0x05, // 5 RR (answers)
81 0x00, 0x00, // 0 authority RRs
82 0x00, 0x00, // 0 additional RRs
84 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
85 0x04, '_', 't', 'c', 'p',
86 0x05, 'l', 'o', 'c', 'a', 'l',
87 0x00,
88 0x00, 0x0c, // TYPE is PTR.
89 0x00, 0x01, // CLASS is IN.
90 0x00, 0x00, // TTL (4 bytes) is 32768 second.
91 0x10, 0x00,
92 0x00, 0x0c, // RDLENGTH is 12 bytes.
93 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
94 0xc0, 0x0c,
96 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
97 0xc0, 0x0c,
98 0x00, 0x10, // TYPE is TXT.
99 0x00, 0x01, // CLASS is IN.
100 0x00, 0x00, // TTL (4 bytes) is 32768 seconds.
101 0x01, 0x00,
102 0x00, 0x41, // RDLENGTH is 69 bytes.
103 0x03, 'i', 'd', '=',
104 0x10, 't', 'y', '=', 'S', 'a', 'm', 'p', 'l', 'e', ' ',
105 'd', 'e', 'v', 'i', 'c', 'e',
106 0x1e, 'n', 'o', 't', 'e', '=',
107 'S', 'a', 'm', 'p', 'l', 'e', ' ', 'd', 'e', 'v', 'i', 'c', 'e', ' ',
108 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n',
109 0x0c, 't', 'y', 'p', 'e', '=', 'p', 'r', 'i', 'n', 't', 'e', 'r',
111 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
112 0xc0, 0x0c,
113 0x00, 0x21, // Type is SRV
114 0x00, 0x01, // CLASS is IN
115 0x00, 0x00, // TTL (4 bytes) is 32768 second.
116 0x10, 0x00,
117 0x00, 0x17, // RDLENGTH is 23
118 0x00, 0x00,
119 0x00, 0x00,
120 0x22, 0xb8, // port 8888
121 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
122 0x05, 'l', 'o', 'c', 'a', 'l',
123 0x00,
125 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
126 0x05, 'l', 'o', 'c', 'a', 'l',
127 0x00,
128 0x00, 0x01, // Type is A
129 0x00, 0x01, // CLASS is IN
130 0x00, 0x00, // TTL (4 bytes) is 32768 second.
131 0x10, 0x00,
132 0x00, 0x04, // RDLENGTH is 4
133 0x01, 0x02, 0x03, 0x04, // 1.2.3.4
135 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
136 0x05, 'l', 'o', 'c', 'a', 'l',
137 0x00,
138 0x00, 0x1C, // Type is AAAA
139 0x00, 0x01, // CLASS is IN
140 0x00, 0x00, // TTL (4 bytes) is 32768 second.
141 0x10, 0x00,
142 0x00, 0x10, // RDLENGTH is 16
143 0x01, 0x02, 0x03, 0x04, // 1.2.3.4
144 0x01, 0x02, 0x03, 0x04,
145 0x01, 0x02, 0x03, 0x04,
146 0x01, 0x02, 0x03, 0x04,
150 const uint8 kGoodbyePacket[] = {
151 // Header
152 0x00, 0x00, // ID is zeroed out
153 0x80, 0x00, // Standard query response, RA, no error
154 0x00, 0x00, // No questions (for simplicity)
155 0x00, 0x02, // 1 RR (answers)
156 0x00, 0x00, // 0 authority RRs
157 0x00, 0x00, // 0 additional RRs
159 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
160 0x04, '_', 't', 'c', 'p',
161 0x05, 'l', 'o', 'c', 'a', 'l',
162 0x00,
163 0x00, 0x0c, // TYPE is PTR.
164 0x00, 0x01, // CLASS is IN.
165 0x00, 0x00, // TTL (4 bytes) is 0 seconds.
166 0x00, 0x00,
167 0x00, 0x0c, // RDLENGTH is 12 bytes.
168 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
169 0xc0, 0x0c,
172 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
173 0xc0, 0x0c,
174 0x00, 0x21, // Type is SRV
175 0x00, 0x01, // CLASS is IN
176 0x00, 0x00, // TTL (4 bytes) is 0 seconds.
177 0x00, 0x00,
178 0x00, 0x17, // RDLENGTH is 23
179 0x00, 0x00,
180 0x00, 0x00,
181 0x22, 0xb8, // port 8888
182 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
183 0x05, 'l', 'o', 'c', 'a', 'l',
184 0x00,
187 const uint8 kAnnouncePacketRegistered[] = {
188 // Header
189 0x00, 0x00, // ID is zeroed out
190 0x80, 0x00, // Standard query response, RA, no error
191 0x00, 0x00, // No questions (for simplicity)
192 0x00, 0x01, // 1 RR (answers)
193 0x00, 0x00, // 0 authority RRs
194 0x00, 0x00, // 0 additional RRs
196 0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
197 0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
198 0x04, '_', 't', 'c', 'p',
199 0x05, 'l', 'o', 'c', 'a', 'l',
200 0x00,
201 0x00, 0x10, // TYPE is TXT.
202 0x00, 0x01, // CLASS is IN.
203 0x00, 0x00, // TTL (4 bytes) is 32768 seconds.
204 0x01, 0x00,
205 0x00, 0x3b, // RDLENGTH is 76 bytes.
206 0x0a, 'i', 'd', '=', 's', 'o', 'm', 'e', '_', 'i', 'd',
207 0x10, 't', 'y', '=', 'S', 'a', 'm', 'p', 'l', 'e', ' ',
208 'd', 'e', 'v', 'i', 'c', 'e',
209 0x1e, 'n', 'o', 't', 'e', '=',
210 'S', 'a', 'm', 'p', 'l', 'e', ' ', 'd', 'e', 'v', 'i', 'c', 'e', ' ',
211 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n',
214 const char kResponseInfo[] = "{"
215 " \"x-privet-token\" : \"MyPrivetToken\""
216 "}";
218 const char kResponseInfoWithID[] = "{"
219 " \"x-privet-token\" : \"MyPrivetToken\","
220 " \"id\" : \"my_id\""
221 "}";
223 const char kResponseRegisterStart[] = "{"
224 " \"action\": \"start\","
225 " \"user\": \"user@host.com\""
226 "}";
228 const char kResponseRegisterClaimTokenNoConfirm[] = "{"
229 " \"action\": \"getClaimToken\","
230 " \"user\": \"user@host.com\","
231 " \"error\": \"pending_user_action\","
232 " \"timeout\": 1"
233 "}";
235 const char kResponseRegisterClaimTokenConfirm[] = "{"
236 " \"action\": \"getClaimToken\","
237 " \"user\": \"user@host.com\","
238 " \"token\": \"MySampleToken\","
239 " \"claim_url\": \"http://someurl.com/\""
240 "}";
242 const char kResponseCloudPrintConfirm[] = "{ \"success\": true }";
244 const char kResponseRegisterComplete[] = "{"
245 " \"action\": \"complete\","
246 " \"user\": \"user@host.com\","
247 " \"device_id\": \"my_id\""
248 "}";
250 const char kResponseGaiaToken[] = "{"
251 " \"access_token\": \"at1\","
252 " \"expires_in\": 3600,"
253 " \"token_type\": \"Bearer\""
254 "}";
256 const char kResponseGaiaId[] = "{"
257 " \"id\": \"12345\""
258 "}";
260 const char kURLInfo[] = "http://1.2.3.4:8888/privet/info";
262 const char kURLRegisterStart[] =
263 "http://1.2.3.4:8888/privet/register?action=start&user=user%40host.com";
265 const char kURLRegisterClaimToken[] =
266 "http://1.2.3.4:8888/privet/register?action=getClaimToken&"
267 "user=user%40host.com";
269 const char kURLCloudPrintConfirm[] =
270 "https://www.google.com/cloudprint/confirm?token=MySampleToken";
272 const char kURLRegisterComplete[] =
273 "http://1.2.3.4:8888/privet/register?action=complete&user=user%40host.com";
275 const char kURLGaiaToken[] =
276 "https://accounts.google.com/o/oauth2/token";
278 const char kSampleGaiaId[] = "12345";
279 const char kSampleUser[] = "user@host.com";
281 class TestMessageLoopCondition {
282 public:
283 TestMessageLoopCondition() : signaled_(false),
284 waiting_(false) {
287 ~TestMessageLoopCondition() {
290 // Signal a waiting method that it can continue executing.
291 void Signal() {
292 signaled_ = true;
293 if (waiting_)
294 base::MessageLoop::current()->Quit();
297 // Pause execution and recursively run the message loop until |Signal()| is
298 // called. Do not pause if |Signal()| has already been called.
299 void Wait() {
300 while (!signaled_) {
301 waiting_ = true;
302 base::MessageLoop::current()->Run();
303 waiting_ = false;
305 signaled_ = false;
308 private:
309 bool signaled_;
310 bool waiting_;
312 DISALLOW_COPY_AND_ASSIGN(TestMessageLoopCondition);
315 class MockableFakeURLFetcherCreator {
316 public:
317 MockableFakeURLFetcherCreator() {
320 ~MockableFakeURLFetcherCreator() {
323 MOCK_METHOD1(OnCreateFakeURLFetcher, void(const std::string& url));
325 scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
326 const GURL& url,
327 net::URLFetcherDelegate* delegate,
328 const std::string& response_data,
329 net::HttpStatusCode response_code,
330 net::URLRequestStatus::Status status) {
331 OnCreateFakeURLFetcher(url.spec());
332 return scoped_ptr<net::FakeURLFetcher>(new net::FakeURLFetcher(
333 url, delegate, response_data, response_code, status));
336 net::FakeURLFetcherFactory::FakeURLFetcherCreator callback() {
337 return base::Bind(&MockableFakeURLFetcherCreator::CreateFakeURLFetcher,
338 base::Unretained(this));
342 class LocalDiscoveryUITest : public WebUIBrowserTest {
343 public:
344 LocalDiscoveryUITest() : fake_fetcher_factory_(
345 &fetcher_impl_factory_,
346 fake_url_fetcher_creator_.callback()) {
348 ~LocalDiscoveryUITest() override {
351 void SetUpOnMainThread() override {
352 WebUIBrowserTest::SetUpOnMainThread();
354 test_service_discovery_client_ = new TestServiceDiscoveryClient();
355 test_service_discovery_client_->Start();
356 EXPECT_CALL(
357 *test_service_discovery_client_.get(),
358 OnSendTo(std::string((const char*)kQueryData, sizeof(kQueryData))))
359 .Times(AtLeast(2))
360 .WillOnce(InvokeWithoutArgs(&condition_devices_listed_,
361 &TestMessageLoopCondition::Signal))
362 .WillRepeatedly(Return());
364 SigninManagerBase* signin_manager =
365 SigninManagerFactory::GetForProfile(browser()->profile());
367 DCHECK(signin_manager);
368 signin_manager->SetAuthenticatedAccountInfo(kSampleGaiaId, kSampleUser);
370 fake_fetcher_factory().SetFakeResponse(
371 GURL(kURLInfo),
372 kResponseInfo,
373 net::HTTP_OK,
374 net::URLRequestStatus::SUCCESS);
376 fake_fetcher_factory().SetFakeResponse(
377 GURL(kURLRegisterStart),
378 kResponseRegisterStart,
379 net::HTTP_OK,
380 net::URLRequestStatus::SUCCESS);
382 fake_fetcher_factory().SetFakeResponse(
383 GURL(kURLRegisterClaimToken),
384 kResponseRegisterClaimTokenNoConfirm,
385 net::HTTP_OK,
386 net::URLRequestStatus::SUCCESS);
388 fake_fetcher_factory().SetFakeResponse(
389 GURL(kURLCloudPrintConfirm),
390 kResponseCloudPrintConfirm,
391 net::HTTP_OK,
392 net::URLRequestStatus::SUCCESS);
394 fake_fetcher_factory().SetFakeResponse(
395 GURL(kURLRegisterComplete),
396 kResponseRegisterComplete,
397 net::HTTP_OK,
398 net::URLRequestStatus::SUCCESS);
400 fake_fetcher_factory().SetFakeResponse(
401 GURL(kURLGaiaToken),
402 kResponseGaiaToken,
403 net::HTTP_OK,
404 net::URLRequestStatus::SUCCESS);
406 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
407 kURLGaiaToken))
408 .Times(AnyNumber());
410 fake_fetcher_factory().SetFakeResponse(
411 GaiaUrls::GetInstance()->oauth_user_info_url(),
412 kResponseGaiaId,
413 net::HTTP_OK,
414 net::URLRequestStatus::SUCCESS);
416 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
417 GaiaUrls::GetInstance()->oauth_user_info_url().spec()))
418 .Times(AnyNumber());
420 ProfileOAuth2TokenService* token_service =
421 ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile());
423 token_service->UpdateCredentials("user@host.com", "MyFakeToken");
425 AddLibrary(base::FilePath(FILE_PATH_LITERAL("local_discovery_ui_test.js")));
428 void SetUpCommandLine(base::CommandLine* command_line) override {
429 #if defined(OS_CHROMEOS)
430 // On chromeos, don't sign in with the stub-user automatically. Use the
431 // kLoginUser instead.
432 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
433 kSampleUser);
434 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
435 chrome::kTestUserProfileDir);
436 #endif
437 WebUIBrowserTest::SetUpCommandLine(command_line);
440 void RunFor(base::TimeDelta time_period) {
441 base::CancelableCallback<void()> callback(base::Bind(
442 &base::MessageLoop::Quit, base::Unretained(
443 base::MessageLoop::current())));
444 base::MessageLoop::current()->PostDelayedTask(
445 FROM_HERE, callback.callback(), time_period);
447 base::MessageLoop::current()->Run();
448 callback.Cancel();
451 TestServiceDiscoveryClient* test_service_discovery_client() {
452 return test_service_discovery_client_.get();
455 TestMessageLoopCondition& condition_devices_listed() {
456 return condition_devices_listed_;
459 net::FakeURLFetcherFactory& fake_fetcher_factory() {
460 return fake_fetcher_factory_;
463 MockableFakeURLFetcherCreator& fake_url_fetcher_creator() {
464 return fake_url_fetcher_creator_;
467 private:
468 scoped_refptr<TestServiceDiscoveryClient> test_service_discovery_client_;
469 TestMessageLoopCondition condition_devices_listed_;
471 net::URLFetcherImplFactory fetcher_impl_factory_;
472 StrictMock<MockableFakeURLFetcherCreator> fake_url_fetcher_creator_;
473 net::FakeURLFetcherFactory fake_fetcher_factory_;
475 DISALLOW_COPY_AND_ASSIGN(LocalDiscoveryUITest);
478 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, EmptyTest) {
479 ui_test_utils::NavigateToURL(browser(), GURL(
480 chrome::kChromeUIDevicesURL));
481 condition_devices_listed().Wait();
482 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkNoDevices"));
485 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, AddRowTest) {
486 ui_test_utils::NavigateToURL(browser(), GURL(
487 chrome::kChromeUIDevicesURL));
488 condition_devices_listed().Wait();
490 test_service_discovery_client()->SimulateReceive(
491 kAnnouncePacket, sizeof(kAnnouncePacket));
493 base::MessageLoop::current()->RunUntilIdle();
495 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkOneDevice"));
497 test_service_discovery_client()->SimulateReceive(
498 kGoodbyePacket, sizeof(kGoodbyePacket));
500 RunFor(base::TimeDelta::FromMilliseconds(1100));
502 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkNoDevices"));
506 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, RegisterTest) {
507 TestMessageLoopCondition condition_token_claimed;
509 ui_test_utils::NavigateToURL(browser(), GURL(
510 chrome::kChromeUIDevicesURL));
511 condition_devices_listed().Wait();
513 test_service_discovery_client()->SimulateReceive(
514 kAnnouncePacket, sizeof(kAnnouncePacket));
516 base::MessageLoop::current()->RunUntilIdle();
518 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkOneDevice"));
520 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("registerShowOverlay"));
523 InSequence s;
524 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(kURLInfo));
525 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
526 kURLRegisterStart));
527 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
528 kURLRegisterClaimToken))
529 .WillOnce(InvokeWithoutArgs(&condition_token_claimed,
530 &TestMessageLoopCondition::Signal));
533 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("registerBegin"));
535 condition_token_claimed.Wait();
537 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("expectPageAdding1"));
539 fake_fetcher_factory().SetFakeResponse(
540 GURL(kURLRegisterClaimToken),
541 kResponseRegisterClaimTokenConfirm,
542 net::HTTP_OK,
543 net::URLRequestStatus::SUCCESS);
545 fake_fetcher_factory().SetFakeResponse(
546 GURL(kURLInfo),
547 kResponseInfoWithID,
548 net::HTTP_OK,
549 net::URLRequestStatus::SUCCESS);
552 InSequence s;
553 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
554 kURLRegisterClaimToken));
555 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
556 kURLCloudPrintConfirm));
557 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
558 kURLRegisterComplete));
559 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(kURLInfo))
560 .WillOnce(InvokeWithoutArgs(&condition_token_claimed,
561 &TestMessageLoopCondition::Signal));
564 condition_token_claimed.Wait();
566 test_service_discovery_client()->SimulateReceive(
567 kAnnouncePacketRegistered, sizeof(kAnnouncePacketRegistered));
569 base::MessageLoop::current()->RunUntilIdle();
571 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("expectRegisterDone"));
574 } // namespace
576 } // namespace local_discovery