Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / local_discovery / local_discovery_ui_browsertest.cc
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.
4
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_switches.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/test/base/ui_test_utils.h"
21 #include "chrome/test/base/web_ui_browser_test.h"
22 #include "components/signin/core/browser/profile_oauth2_token_service.h"
23 #include "components/signin/core/browser/signin_manager.h"
24 #include "components/signin/core/browser/signin_manager_base.h"
25 #include "google_apis/gaia/gaia_urls.h"
26 #include "net/http/http_status_code.h"
27 #include "net/url_request/test_url_fetcher_factory.h"
28 #include "net/url_request/url_request_status.h"
29 #include "net/url_request/url_request_test_util.h"
30
31 #if defined(OS_CHROMEOS)
32 #include "base/prefs/pref_service.h"
33 #include "chrome/common/pref_names.h"
34 #endif
35
36 using testing::InvokeWithoutArgs;
37 using testing::Return;
38 using testing::AtLeast;
39 using testing::DoDefault;
40 using testing::DoAll;
41 using testing::InSequence;
42 using testing::StrictMock;
43 using testing::AnyNumber;
44
45 using testing::InvokeWithoutArgs;
46 using testing::Return;
47 using testing::AtLeast;
48
49 namespace local_discovery {
50
51 namespace {
52
53 const uint8 kQueryData[] = {
54   // Header
55   0x00, 0x00,
56   0x00, 0x00,               // Flags not set.
57   0x00, 0x01,               // Set QDCOUNT (question count) to 1, all the
58   // rest are 0 for a query.
59   0x00, 0x00,
60   0x00, 0x00,
61   0x00, 0x00,
62
63   // Question
64   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
65   0x04, '_', 't', 'c', 'p',
66   0x05, 'l', 'o', 'c', 'a', 'l',
67   0x00,
68
69   0x00, 0x0c,               // QTYPE: A query.
70   0x00, 0x01,               // QCLASS: IN class. Unicast bit not set.
71 };
72
73 const uint8 kAnnouncePacket[] = {
74   // Header
75   0x00, 0x00,               // ID is zeroed out
76   0x80, 0x00,               // Standard query response, no error
77   0x00, 0x00,               // No questions (for simplicity)
78   0x00, 0x05,               // 5 RR (answers)
79   0x00, 0x00,               // 0 authority RRs
80   0x00, 0x00,               // 0 additional RRs
81
82   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
83   0x04, '_', 't', 'c', 'p',
84   0x05, 'l', 'o', 'c', 'a', 'l',
85   0x00,
86   0x00, 0x0c,        // TYPE is PTR.
87   0x00, 0x01,        // CLASS is IN.
88   0x00, 0x00,        // TTL (4 bytes) is 32768 second.
89   0x10, 0x00,
90   0x00, 0x0c,        // RDLENGTH is 12 bytes.
91   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
92   0xc0, 0x0c,
93
94   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
95   0xc0, 0x0c,
96   0x00, 0x10,        // TYPE is TXT.
97   0x00, 0x01,        // CLASS is IN.
98   0x00, 0x00,        // TTL (4 bytes) is 32768 seconds.
99   0x01, 0x00,
100   0x00, 0x41,        // RDLENGTH is 69 bytes.
101   0x03, 'i', 'd', '=',
102   0x10, 't', 'y', '=', 'S', 'a', 'm', 'p', 'l', 'e', ' ',
103         'd', 'e', 'v', 'i', 'c', 'e',
104   0x1e, 'n', 'o', 't', 'e', '=',
105         'S', 'a', 'm', 'p', 'l', 'e', ' ', 'd', 'e', 'v', 'i', 'c', 'e', ' ',
106         'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n',
107   0x0c, 't', 'y', 'p', 'e', '=', 'p', 'r', 'i', 'n', 't', 'e', 'r',
108
109   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
110   0xc0, 0x0c,
111   0x00, 0x21,        // Type is SRV
112   0x00, 0x01,        // CLASS is IN
113   0x00, 0x00,        // TTL (4 bytes) is 32768 second.
114   0x10, 0x00,
115   0x00, 0x17,        // RDLENGTH is 23
116   0x00, 0x00,
117   0x00, 0x00,
118   0x22, 0xb8,        // port 8888
119   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
120   0x05, 'l', 'o', 'c', 'a', 'l',
121   0x00,
122
123   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
124   0x05, 'l', 'o', 'c', 'a', 'l',
125   0x00,
126   0x00, 0x01,        // Type is A
127   0x00, 0x01,        // CLASS is IN
128   0x00, 0x00,        // TTL (4 bytes) is 32768 second.
129   0x10, 0x00,
130   0x00, 0x04,        // RDLENGTH is 4
131   0x01, 0x02, 0x03, 0x04,  // 1.2.3.4
132
133   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
134   0x05, 'l', 'o', 'c', 'a', 'l',
135   0x00,
136   0x00, 0x1C,        // Type is AAAA
137   0x00, 0x01,        // CLASS is IN
138   0x00, 0x00,        // TTL (4 bytes) is 32768 second.
139   0x10, 0x00,
140   0x00, 0x10,        // RDLENGTH is 16
141   0x01, 0x02, 0x03, 0x04,  // 1.2.3.4
142   0x01, 0x02, 0x03, 0x04,
143   0x01, 0x02, 0x03, 0x04,
144   0x01, 0x02, 0x03, 0x04,
145 };
146
147
148 const uint8 kGoodbyePacket[] = {
149   // Header
150   0x00, 0x00,               // ID is zeroed out
151   0x80, 0x00,               // Standard query response, RA, no error
152   0x00, 0x00,               // No questions (for simplicity)
153   0x00, 0x02,               // 1 RR (answers)
154   0x00, 0x00,               // 0 authority RRs
155   0x00, 0x00,               // 0 additional RRs
156
157   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
158   0x04, '_', 't', 'c', 'p',
159   0x05, 'l', 'o', 'c', 'a', 'l',
160   0x00,
161   0x00, 0x0c,        // TYPE is PTR.
162   0x00, 0x01,        // CLASS is IN.
163   0x00, 0x00,        // TTL (4 bytes) is 0 seconds.
164   0x00, 0x00,
165   0x00, 0x0c,        // RDLENGTH is 12 bytes.
166   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
167   0xc0, 0x0c,
168
169
170   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
171   0xc0, 0x0c,
172   0x00, 0x21,        // Type is SRV
173   0x00, 0x01,        // CLASS is IN
174   0x00, 0x00,        // TTL (4 bytes) is 0 seconds.
175   0x00, 0x00,
176   0x00, 0x17,        // RDLENGTH is 23
177   0x00, 0x00,
178   0x00, 0x00,
179   0x22, 0xb8,        // port 8888
180   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
181   0x05, 'l', 'o', 'c', 'a', 'l',
182   0x00,
183 };
184
185 const uint8 kAnnouncePacketRegistered[] = {
186   // Header
187   0x00, 0x00,               // ID is zeroed out
188   0x80, 0x00,               // Standard query response, RA, no error
189   0x00, 0x00,               // No questions (for simplicity)
190   0x00, 0x01,               // 1 RR (answers)
191   0x00, 0x00,               // 0 authority RRs
192   0x00, 0x00,               // 0 additional RRs
193
194   0x09, 'm', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e',
195   0x07, '_', 'p', 'r', 'i', 'v', 'e', 't',
196   0x04, '_', 't', 'c', 'p',
197   0x05, 'l', 'o', 'c', 'a', 'l',
198   0x00,
199   0x00, 0x10,        // TYPE is TXT.
200   0x00, 0x01,        // CLASS is IN.
201   0x00, 0x00,        // TTL (4 bytes) is 32768 seconds.
202   0x01, 0x00,
203   0x00, 0x3b,        // RDLENGTH is 76 bytes.
204   0x0a, 'i', 'd', '=', 's', 'o', 'm', 'e', '_', 'i', 'd',
205   0x10, 't', 'y', '=', 'S', 'a', 'm', 'p', 'l', 'e', ' ',
206         'd', 'e', 'v', 'i', 'c', 'e',
207   0x1e, 'n', 'o', 't', 'e', '=',
208         'S', 'a', 'm', 'p', 'l', 'e', ' ', 'd', 'e', 'v', 'i', 'c', 'e', ' ',
209         'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n',
210 };
211
212 const char kResponseInfo[] = "{"
213     "     \"x-privet-token\" : \"MyPrivetToken\""
214     "}";
215
216 const char kResponseInfoWithID[] = "{"
217     "     \"x-privet-token\" : \"MyPrivetToken\","
218     "     \"id\" : \"my_id\""
219     "}";
220
221 const char kResponseRegisterStart[] = "{"
222     "     \"action\": \"start\","
223     "     \"user\": \"user@host.com\""
224     "}";
225
226 const char kResponseRegisterClaimTokenNoConfirm[] = "{"
227     "    \"action\": \"getClaimToken\","
228     "    \"user\": \"user@host.com\","
229     "    \"error\": \"pending_user_action\","
230     "    \"timeout\": 1"
231     "}";
232
233 const char kResponseRegisterClaimTokenConfirm[] = "{"
234     "    \"action\": \"getClaimToken\","
235     "    \"user\": \"user@host.com\","
236     "    \"token\": \"MySampleToken\","
237     "    \"claim_url\": \"http://someurl.com/\""
238     "}";
239
240 const char kResponseCloudPrintConfirm[] = "{ \"success\": true }";
241
242 const char kResponseRegisterComplete[] = "{"
243     "    \"action\": \"complete\","
244     "    \"user\": \"user@host.com\","
245     "    \"device_id\": \"my_id\""
246     "}";
247
248 const char kResponseGaiaToken[] = "{"
249     "  \"access_token\": \"at1\","
250     "  \"expires_in\": 3600,"
251     "  \"token_type\": \"Bearer\""
252     "}";
253
254 const char kResponseGaiaId[] = "{"
255     "  \"id\": \"12345\""
256     "}";
257
258 const char kURLInfo[] = "http://1.2.3.4:8888/privet/info";
259
260 const char kURLRegisterStart[] =
261     "http://1.2.3.4:8888/privet/register?action=start&user=user%40host.com";
262
263 const char kURLRegisterClaimToken[] =
264     "http://1.2.3.4:8888/privet/register?action=getClaimToken&"
265     "user=user%40host.com";
266
267 const char kURLCloudPrintConfirm[] =
268     "https://www.google.com/cloudprint/confirm?token=MySampleToken";
269
270 const char kURLRegisterComplete[] =
271     "http://1.2.3.4:8888/privet/register?action=complete&user=user%40host.com";
272
273 const char kURLGaiaToken[] =
274     "https://accounts.google.com/o/oauth2/token";
275
276 const char kSampleUser[] = "user@host.com";
277
278 class TestMessageLoopCondition {
279  public:
280   TestMessageLoopCondition() : signaled_(false),
281                                waiting_(false) {
282   }
283
284   ~TestMessageLoopCondition() {
285   }
286
287   // Signal a waiting method that it can continue executing.
288   void Signal() {
289     signaled_ = true;
290     if (waiting_)
291       base::MessageLoop::current()->Quit();
292   }
293
294   // Pause execution and recursively run the message loop until |Signal()| is
295   // called. Do not pause if |Signal()| has already been called.
296   void Wait() {
297     while (!signaled_) {
298       waiting_ = true;
299       base::MessageLoop::current()->Run();
300       waiting_ = false;
301     }
302     signaled_ = false;
303   }
304
305  private:
306   bool signaled_;
307   bool waiting_;
308
309   DISALLOW_COPY_AND_ASSIGN(TestMessageLoopCondition);
310 };
311
312 class MockableFakeURLFetcherCreator {
313  public:
314   MockableFakeURLFetcherCreator() {
315   }
316
317   ~MockableFakeURLFetcherCreator() {
318   }
319
320   MOCK_METHOD1(OnCreateFakeURLFetcher, void(const std::string& url));
321
322   scoped_ptr<net::FakeURLFetcher> CreateFakeURLFetcher(
323       const GURL& url,
324       net::URLFetcherDelegate* delegate,
325       const std::string& response_data,
326       net::HttpStatusCode response_code,
327       net::URLRequestStatus::Status status) {
328     OnCreateFakeURLFetcher(url.spec());
329     return scoped_ptr<net::FakeURLFetcher>(new net::FakeURLFetcher(
330         url, delegate, response_data, response_code, status));
331   }
332
333   net::FakeURLFetcherFactory::FakeURLFetcherCreator callback() {
334     return base::Bind(&MockableFakeURLFetcherCreator::CreateFakeURLFetcher,
335                       base::Unretained(this));
336   }
337 };
338
339 class LocalDiscoveryUITest : public WebUIBrowserTest {
340  public:
341   LocalDiscoveryUITest() : fake_fetcher_factory_(
342       &fetcher_impl_factory_,
343       fake_url_fetcher_creator_.callback()) {
344   }
345   virtual ~LocalDiscoveryUITest() {
346   }
347
348   virtual void SetUpOnMainThread() override {
349     WebUIBrowserTest::SetUpOnMainThread();
350
351     test_service_discovery_client_ = new TestServiceDiscoveryClient();
352     test_service_discovery_client_->Start();
353     EXPECT_CALL(
354         *test_service_discovery_client_.get(),
355         OnSendTo(std::string((const char*)kQueryData, sizeof(kQueryData))))
356         .Times(AtLeast(2))
357         .WillOnce(InvokeWithoutArgs(&condition_devices_listed_,
358                                     &TestMessageLoopCondition::Signal))
359         .WillRepeatedly(Return());
360
361     SigninManagerBase* signin_manager =
362         SigninManagerFactory::GetForProfile(browser()->profile());
363
364 #if defined(OS_CHROMEOS)
365     // Chrome OS initializes prefs::kGoogleServicesUsername to "stub user" so
366     // we need to override it as well.
367     browser()->profile()->GetPrefs()->
368         SetString(prefs::kGoogleServicesUsername, kSampleUser);
369 #endif
370     DCHECK(signin_manager);
371     signin_manager->SetAuthenticatedUsername(kSampleUser);
372
373     fake_fetcher_factory().SetFakeResponse(
374         GURL(kURLInfo),
375         kResponseInfo,
376         net::HTTP_OK,
377         net::URLRequestStatus::SUCCESS);
378
379     fake_fetcher_factory().SetFakeResponse(
380         GURL(kURLRegisterStart),
381         kResponseRegisterStart,
382         net::HTTP_OK,
383         net::URLRequestStatus::SUCCESS);
384
385     fake_fetcher_factory().SetFakeResponse(
386         GURL(kURLRegisterClaimToken),
387         kResponseRegisterClaimTokenNoConfirm,
388         net::HTTP_OK,
389         net::URLRequestStatus::SUCCESS);
390
391     fake_fetcher_factory().SetFakeResponse(
392         GURL(kURLCloudPrintConfirm),
393         kResponseCloudPrintConfirm,
394         net::HTTP_OK,
395         net::URLRequestStatus::SUCCESS);
396
397     fake_fetcher_factory().SetFakeResponse(
398         GURL(kURLRegisterComplete),
399         kResponseRegisterComplete,
400         net::HTTP_OK,
401         net::URLRequestStatus::SUCCESS);
402
403     fake_fetcher_factory().SetFakeResponse(
404         GURL(kURLGaiaToken),
405         kResponseGaiaToken,
406         net::HTTP_OK,
407         net::URLRequestStatus::SUCCESS);
408
409     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
410         kURLGaiaToken))
411         .Times(AnyNumber());
412
413     fake_fetcher_factory().SetFakeResponse(
414         GaiaUrls::GetInstance()->oauth_user_info_url(),
415         kResponseGaiaId,
416         net::HTTP_OK,
417         net::URLRequestStatus::SUCCESS);
418
419     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
420         GaiaUrls::GetInstance()->oauth_user_info_url().spec()))
421         .Times(AnyNumber());
422
423     ProfileOAuth2TokenService* token_service =
424         ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile());
425
426     token_service->UpdateCredentials("user@host.com", "MyFakeToken");
427
428     AddLibrary(base::FilePath(FILE_PATH_LITERAL("local_discovery_ui_test.js")));
429   }
430
431   virtual void SetUpCommandLine(CommandLine* command_line) override {
432     WebUIBrowserTest::SetUpCommandLine(command_line);
433   }
434
435   void RunFor(base::TimeDelta time_period) {
436     base::CancelableCallback<void()> callback(base::Bind(
437         &base::MessageLoop::Quit, base::Unretained(
438             base::MessageLoop::current())));
439     base::MessageLoop::current()->PostDelayedTask(
440         FROM_HERE, callback.callback(), time_period);
441
442     base::MessageLoop::current()->Run();
443     callback.Cancel();
444   }
445
446   TestServiceDiscoveryClient* test_service_discovery_client() {
447     return test_service_discovery_client_.get();
448   }
449
450   TestMessageLoopCondition& condition_devices_listed() {
451     return condition_devices_listed_;
452   }
453
454   net::FakeURLFetcherFactory& fake_fetcher_factory() {
455     return fake_fetcher_factory_;
456   }
457
458   MockableFakeURLFetcherCreator& fake_url_fetcher_creator() {
459     return fake_url_fetcher_creator_;
460   }
461
462  private:
463   scoped_refptr<TestServiceDiscoveryClient> test_service_discovery_client_;
464   TestMessageLoopCondition condition_devices_listed_;
465
466   net::URLFetcherImplFactory fetcher_impl_factory_;
467   StrictMock<MockableFakeURLFetcherCreator> fake_url_fetcher_creator_;
468   net::FakeURLFetcherFactory fake_fetcher_factory_;
469
470   DISALLOW_COPY_AND_ASSIGN(LocalDiscoveryUITest);
471 };
472
473 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, EmptyTest) {
474   ui_test_utils::NavigateToURL(browser(), GURL(
475       chrome::kChromeUIDevicesURL));
476   condition_devices_listed().Wait();
477   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkNoDevices"));
478 }
479
480 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, AddRowTest) {
481   ui_test_utils::NavigateToURL(browser(), GURL(
482       chrome::kChromeUIDevicesURL));
483   condition_devices_listed().Wait();
484
485   test_service_discovery_client()->SimulateReceive(
486       kAnnouncePacket, sizeof(kAnnouncePacket));
487
488   base::MessageLoop::current()->RunUntilIdle();
489
490   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkOneDevice"));
491
492   test_service_discovery_client()->SimulateReceive(
493       kGoodbyePacket, sizeof(kGoodbyePacket));
494
495   RunFor(base::TimeDelta::FromMilliseconds(1100));
496
497   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkNoDevices"));
498 }
499
500
501 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, RegisterTest) {
502   TestMessageLoopCondition condition_token_claimed;
503
504   ui_test_utils::NavigateToURL(browser(), GURL(
505       chrome::kChromeUIDevicesURL));
506   condition_devices_listed().Wait();
507
508   test_service_discovery_client()->SimulateReceive(
509       kAnnouncePacket, sizeof(kAnnouncePacket));
510
511   base::MessageLoop::current()->RunUntilIdle();
512
513   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("checkOneDevice"));
514
515   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("registerShowOverlay"));
516
517   {
518     InSequence s;
519     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(kURLInfo));
520     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
521         kURLRegisterStart));
522     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
523         kURLRegisterClaimToken))
524         .WillOnce(InvokeWithoutArgs(&condition_token_claimed,
525                                     &TestMessageLoopCondition::Signal));
526   }
527
528   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("registerBegin"));
529
530   condition_token_claimed.Wait();
531
532   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("expectPageAdding1"));
533
534   fake_fetcher_factory().SetFakeResponse(
535       GURL(kURLRegisterClaimToken),
536       kResponseRegisterClaimTokenConfirm,
537       net::HTTP_OK,
538       net::URLRequestStatus::SUCCESS);
539
540   fake_fetcher_factory().SetFakeResponse(
541       GURL(kURLInfo),
542       kResponseInfoWithID,
543       net::HTTP_OK,
544       net::URLRequestStatus::SUCCESS);
545
546   {
547     InSequence s;
548     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
549         kURLRegisterClaimToken));
550     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
551         kURLCloudPrintConfirm));
552     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(
553         kURLRegisterComplete));
554     EXPECT_CALL(fake_url_fetcher_creator(), OnCreateFakeURLFetcher(kURLInfo))
555         .WillOnce(InvokeWithoutArgs(&condition_token_claimed,
556                                     &TestMessageLoopCondition::Signal));
557   }
558
559   condition_token_claimed.Wait();
560
561   test_service_discovery_client()->SimulateReceive(
562       kAnnouncePacketRegistered, sizeof(kAnnouncePacketRegistered));
563
564   base::MessageLoop::current()->RunUntilIdle();
565
566   EXPECT_TRUE(WebUIBrowserTest::RunJavascriptTest("expectRegisterDone"));
567 }
568
569 }  // namespace
570
571 }  // namespace local_discovery