ProfilePolicyConnectorFactory: Refactoring from Profile to BrowserContext.
[chromium-blink-merge.git] / chrome / browser / ui / webui / local_discovery / local_discovery_ui_browsertest.cc
blobfb995454b5970210ae57ffa1e8fcb9e2820c34f1
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 "chromeos/chromeos_switches.h"
24 #include "components/signin/core/browser/profile_oauth2_token_service.h"
25 #include "components/signin/core/browser/signin_manager.h"
26 #include "components/signin/core/browser/signin_manager_base.h"
27 #include "google_apis/gaia/gaia_urls.h"
28 #include "net/http/http_status_code.h"
29 #include "net/url_request/test_url_fetcher_factory.h"
30 #include "net/url_request/url_request_status.h"
31 #include "net/url_request/url_request_test_util.h"
33 #if defined(OS_CHROMEOS)
34 #include "base/prefs/pref_service.h"
35 #include "chrome/common/pref_names.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 kSampleUser[] = "user@host.com";
280 class TestMessageLoopCondition {
281 public:
282 TestMessageLoopCondition() : signaled_(false),
283 waiting_(false) {
286 ~TestMessageLoopCondition() {
289 // Signal a waiting method that it can continue executing.
290 void Signal() {
291 signaled_ = true;
292 if (waiting_)
293 base::MessageLoop::current()->Quit();
296 // Pause execution and recursively run the message loop until |Signal()| is
297 // called. Do not pause if |Signal()| has already been called.
298 void Wait() {
299 while (!signaled_) {
300 waiting_ = true;
301 base::MessageLoop::current()->Run();
302 waiting_ = false;
304 signaled_ = false;
307 private:
308 bool signaled_;
309 bool waiting_;
311 DISALLOW_COPY_AND_ASSIGN(TestMessageLoopCondition);
314 class MockableFakeURLFetcherCreator {
315 public:
316 MockableFakeURLFetcherCreator() {
319 ~MockableFakeURLFetcherCreator() {
322 MOCK_METHOD1(OnCreateFakeURLFetcher, void(const std::string& url));
324 scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
325 const GURL& url,
326 net::URLFetcherDelegate* delegate,
327 const std::string& response_data,
328 net::HttpStatusCode response_code,
329 net::URLRequestStatus::Status status) {
330 OnCreateFakeURLFetcher(url.spec());
331 return scoped_ptr<net::FakeURLFetcher>(new net::FakeURLFetcher(
332 url, delegate, response_data, response_code, status));
335 net::FakeURLFetcherFactory::FakeURLFetcherCreator callback() {
336 return base::Bind(&MockableFakeURLFetcherCreator::CreateFakeURLFetcher,
337 base::Unretained(this));
341 class LocalDiscoveryUITest : public WebUIBrowserTest {
342 public:
343 LocalDiscoveryUITest() : fake_fetcher_factory_(
344 &fetcher_impl_factory_,
345 fake_url_fetcher_creator_.callback()) {
347 virtual ~LocalDiscoveryUITest() {
350 virtual void SetUpOnMainThread() override {
351 WebUIBrowserTest::SetUpOnMainThread();
353 test_service_discovery_client_ = new TestServiceDiscoveryClient();
354 test_service_discovery_client_->Start();
355 EXPECT_CALL(
356 *test_service_discovery_client_.get(),
357 OnSendTo(std::string((const char*)kQueryData, sizeof(kQueryData))))
358 .Times(AtLeast(2))
359 .WillOnce(InvokeWithoutArgs(&condition_devices_listed_,
360 &TestMessageLoopCondition::Signal))
361 .WillRepeatedly(Return());
363 SigninManagerBase* signin_manager =
364 SigninManagerFactory::GetForProfile(browser()->profile());
366 DCHECK(signin_manager);
367 signin_manager->SetAuthenticatedUsername(kSampleUser);
369 fake_fetcher_factory().SetFakeResponse(
370 GURL(kURLInfo),
371 kResponseInfo,
372 net::HTTP_OK,
373 net::URLRequestStatus::SUCCESS);
375 fake_fetcher_factory().SetFakeResponse(
376 GURL(kURLRegisterStart),
377 kResponseRegisterStart,
378 net::HTTP_OK,
379 net::URLRequestStatus::SUCCESS);
381 fake_fetcher_factory().SetFakeResponse(
382 GURL(kURLRegisterClaimToken),
383 kResponseRegisterClaimTokenNoConfirm,
384 net::HTTP_OK,
385 net::URLRequestStatus::SUCCESS);
387 fake_fetcher_factory().SetFakeResponse(
388 GURL(kURLCloudPrintConfirm),
389 kResponseCloudPrintConfirm,
390 net::HTTP_OK,
391 net::URLRequestStatus::SUCCESS);
393 fake_fetcher_factory().SetFakeResponse(
394 GURL(kURLRegisterComplete),
395 kResponseRegisterComplete,
396 net::HTTP_OK,
397 net::URLRequestStatus::SUCCESS);
399 fake_fetcher_factory().SetFakeResponse(
400 GURL(kURLGaiaToken),
401 kResponseGaiaToken,
402 net::HTTP_OK,
403 net::URLRequestStatus::SUCCESS);
405 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
406 kURLGaiaToken))
407 .Times(AnyNumber());
409 fake_fetcher_factory().SetFakeResponse(
410 GaiaUrls::GetInstance()->oauth_user_info_url(),
411 kResponseGaiaId,
412 net::HTTP_OK,
413 net::URLRequestStatus::SUCCESS);
415 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
416 GaiaUrls::GetInstance()->oauth_user_info_url().spec()))
417 .Times(AnyNumber());
419 ProfileOAuth2TokenService* token_service =
420 ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile());
422 token_service->UpdateCredentials("user@host.com", "MyFakeToken");
424 AddLibrary(base::FilePath(FILE_PATH_LITERAL("local_discovery_ui_test.js")));
427 virtual void SetUpCommandLine(base::CommandLine* command_line) override {
428 #if defined(OS_CHROMEOS)
429 // On chromeos, don't sign in with the stub-user automatically. Use the
430 // kLoginUser instead.
431 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
432 kSampleUser);
433 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
434 chrome::kTestUserProfileDir);
435 #endif
436 WebUIBrowserTest::SetUpCommandLine(command_line);
439 void RunFor(base::TimeDelta time_period) {
440 base::CancelableCallback<void()> callback(base::Bind(
441 &base::MessageLoop::Quit, base::Unretained(
442 base::MessageLoop::current())));
443 base::MessageLoop::current()->PostDelayedTask(
444 FROM_HERE, callback.callback(), time_period);
446 base::MessageLoop::current()->Run();
447 callback.Cancel();
450 TestServiceDiscoveryClient* test_service_discovery_client() {
451 return test_service_discovery_client_.get();
454 TestMessageLoopCondition& condition_devices_listed() {
455 return condition_devices_listed_;
458 net::FakeURLFetcherFactory& fake_fetcher_factory() {
459 return fake_fetcher_factory_;
462 MockableFakeURLFetcherCreator& fake_url_fetcher_creator() {
463 return fake_url_fetcher_creator_;
466 private:
467 scoped_refptr<TestServiceDiscoveryClient> test_service_discovery_client_;
468 TestMessageLoopCondition condition_devices_listed_;
470 net::URLFetcherImplFactory fetcher_impl_factory_;
471 StrictMock<MockableFakeURLFetcherCreator> fake_url_fetcher_creator_;
472 net::FakeURLFetcherFactory fake_fetcher_factory_;
474 DISALLOW_COPY_AND_ASSIGN(LocalDiscoveryUITest);
477 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, EmptyTest) {
478 ui_test_utils::NavigateToURL(browser(), GURL(
479 chrome::kChromeUIDevicesURL));
480 condition_devices_listed().Wait();
481 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkNoDevices"));
484 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, AddRowTest) {
485 ui_test_utils::NavigateToURL(browser(), GURL(
486 chrome::kChromeUIDevicesURL));
487 condition_devices_listed().Wait();
489 test_service_discovery_client()->SimulateReceive(
490 kAnnouncePacket, sizeof(kAnnouncePacket));
492 base::MessageLoop::current()->RunUntilIdle();
494 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkOneDevice"));
496 test_service_discovery_client()->SimulateReceive(
497 kGoodbyePacket, sizeof(kGoodbyePacket));
499 RunFor(base::TimeDelta::FromMilliseconds(1100));
501 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkNoDevices"));
505 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, RegisterTest) {
506 TestMessageLoopCondition condition_token_claimed;
508 ui_test_utils::NavigateToURL(browser(), GURL(
509 chrome::kChromeUIDevicesURL));
510 condition_devices_listed().Wait();
512 test_service_discovery_client()->SimulateReceive(
513 kAnnouncePacket, sizeof(kAnnouncePacket));
515 base::MessageLoop::current()->RunUntilIdle();
517 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkOneDevice"));
519 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("registerShowOverlay"));
522 InSequence s;
523 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(kURLInfo));
524 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
525 kURLRegisterStart));
526 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
527 kURLRegisterClaimToken))
528 .WillOnce(InvokeWithoutArgs(&condition_token_claimed,
529 &TestMessageLoopCondition::Signal));
532 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("registerBegin"));
534 condition_token_claimed.Wait();
536 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("expectPageAdding1"));
538 fake_fetcher_factory().SetFakeResponse(
539 GURL(kURLRegisterClaimToken),
540 kResponseRegisterClaimTokenConfirm,
541 net::HTTP_OK,
542 net::URLRequestStatus::SUCCESS);
544 fake_fetcher_factory().SetFakeResponse(
545 GURL(kURLInfo),
546 kResponseInfoWithID,
547 net::HTTP_OK,
548 net::URLRequestStatus::SUCCESS);
551 InSequence s;
552 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
553 kURLRegisterClaimToken));
554 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
555 kURLCloudPrintConfirm));
556 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
557 kURLRegisterComplete));
558 EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(kURLInfo))
559 .WillOnce(InvokeWithoutArgs(&condition_token_claimed,
560 &TestMessageLoopCondition::Signal));
563 condition_token_claimed.Wait();
565 test_service_discovery_client()->SimulateReceive(
566 kAnnouncePacketRegistered, sizeof(kAnnouncePacketRegistered));
568 base::MessageLoop::current()->RunUntilIdle();
570 EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("expectRegisterDone"));
573 } // namespace
575 } // namespace local_discovery