Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / gcd_private / gcd_private_apitest.cc
1 // Copyright 2014 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/bind.h"
6 #include "base/command_line.h"
7 #include "base/json/json_reader.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "chrome/browser/extensions/api/gcd_private/gcd_private_api.h"
10 #include "chrome/browser/extensions/extension_apitest.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/local_discovery/gcd_api_flow.h"
13 #include "chrome/browser/local_discovery/wifi/mock_wifi_manager.h"
14 #include "chrome/common/extensions/api/mdns.h"
15 #include "extensions/common/switches.h"
16 #include "net/url_request/test_url_fetcher_factory.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18
19 #if defined(ENABLE_MDNS)
20 #include "chrome/browser/local_discovery/test_service_discovery_client.h"
21 #endif  // ENABLE_MDNS
22
23 namespace api = extensions::api;
24
25 using testing::Invoke;
26
27 namespace {
28
29 const char kCloudPrintResponse[] =
30     "{"
31     "   \"success\": true,"
32     "   \"printers\": ["
33     "     {\"id\" : \"someCloudPrintID\","
34     "      \"displayName\": \"someCloudPrintDisplayName\","
35     "      \"description\": \"someCloudPrintDescription\"}"
36     "    ]"
37     "}";
38
39 const char kGCDResponse[] =
40     "{"
41     "\"kind\": \"clouddevices#devicesListResponse\","
42     "\"devices\": [{"
43     "  \"kind\": \"clouddevices#device\","
44     "  \"id\": \"someGCDID\","
45     "  \"deviceKind\": \"someType\","
46     "  \"creationTimeMs\": \"123\","
47     "  \"systemName\": \"someGCDDisplayName\","
48     "  \"owner\": \"user@domain.com\","
49     "  \"description\": \"someGCDDescription\","
50     "  \"state\": {"
51     "  \"base\": {"
52     "    \"connectionStatus\": \"offline\""
53     "   }"
54     "  },"
55     "  \"channel\": {"
56     "  \"supportedType\": \"xmpp\""
57     "  },"
58     "  \"personalizedInfo\": {"
59     "   \"maxRole\": \"owner\""
60     "  }}]}";
61
62 const char kPrivetInfoResponse[] =
63     "{"
64     "\"x-privet-token\": \"sample\""
65     "}";
66
67 const char kPrivetPingResponse[] =
68     "{"
69     "\"response\": \"pong\""
70     "}";
71
72 #if defined(ENABLE_MDNS)
73
74 const uint8 kAnnouncePacket[] = {
75     // Header
76     0x00, 0x00,  // ID is zeroed out
77     0x80, 0x00,  // Standard query response, no error
78     0x00, 0x00,  // No questions (for simplicity)
79     0x00, 0x05,  // 5 RR (answers)
80     0x00, 0x00,  // 0 authority RRs
81     0x00, 0x00,  // 0 additional RRs
82     0x07, '_',  'p',  'r',  'i',  'v',  'e',  't',  0x04, '_',
83     't',  'c',  'p',  0x05, 'l',  'o',  'c',  'a',  'l',  0x00,
84     0x00, 0x0c,              // TYPE is PTR.
85     0x00, 0x01,              // CLASS is IN.
86     0x00, 0x00,              // TTL (4 bytes) is 32768 second.
87     0x10, 0x00, 0x00, 0x0c,  // RDLENGTH is 12 bytes.
88     0x09, 'm',  'y',  'S',  'e',  'r',  'v',  'i',  'c',  'e',
89     0xc0, 0x0c, 0x09, 'm',  'y',  'S',  'e',  'r',  'v',  'i',
90     'c',  'e',  0xc0, 0x0c, 0x00, 0x10,  // TYPE is TXT.
91     0x00, 0x01,                          // CLASS is IN.
92     0x00, 0x00,                          // TTL (4 bytes) is 32768 seconds.
93     0x01, 0x00, 0x00, 0x41,              // RDLENGTH is 69 bytes.
94     0x03, 'i',  'd',  '=',  0x10, 't',  'y',  '=',  'S',  'a',
95     'm',  'p',  'l',  'e',  ' ',  'd',  'e',  'v',  'i',  'c',
96     'e',  0x1e, 'n',  'o',  't',  'e',  '=',  'S',  'a',  'm',
97     'p',  'l',  'e',  ' ',  'd',  'e',  'v',  'i',  'c',  'e',
98     ' ',  'd',  'e',  's',  'c',  'r',  'i',  'p',  't',  'i',
99     'o',  'n',  0x0c, 't',  'y',  'p',  'e',  '=',  'p',  'r',
100     'i',  'n',  't',  'e',  'r',  0x09, 'm',  'y',  'S',  'e',
101     'r',  'v',  'i',  'c',  'e',  0xc0, 0x0c, 0x00, 0x21,  // Type is SRV
102     0x00, 0x01,                                            // CLASS is IN
103     0x00, 0x00,                          // TTL (4 bytes) is 32768 second.
104     0x10, 0x00, 0x00, 0x17,              // RDLENGTH is 23
105     0x00, 0x00, 0x00, 0x00, 0x22, 0xb8,  // port 8888
106     0x09, 'm',  'y',  'S',  'e',  'r',  'v',  'i',  'c',  'e',
107     0x05, 'l',  'o',  'c',  'a',  'l',  0x00, 0x09, 'm',  'y',
108     'S',  'e',  'r',  'v',  'i',  'c',  'e',  0x05, 'l',  'o',
109     'c',  'a',  'l',  0x00, 0x00, 0x01,  // Type is A
110     0x00, 0x01,                          // CLASS is IN
111     0x00, 0x00,                          // TTL (4 bytes) is 32768 second.
112     0x10, 0x00, 0x00, 0x04,              // RDLENGTH is 4
113     0x01, 0x02, 0x03, 0x04,              // 1.2.3.4
114     0x09, 'm',  'y',  'S',  'e',  'r',  'v',  'i',  'c',  'e',
115     0x05, 'l',  'o',  'c',  'a',  'l',  0x00, 0x00, 0x1C,  // Type is AAAA
116     0x00, 0x01,                                            // CLASS is IN
117     0x00, 0x00,              // TTL (4 bytes) is 32768 second.
118     0x10, 0x00, 0x00, 0x10,  // RDLENGTH is 16
119     0x01, 0x02, 0x03, 0x04,  // 1.2.3.4
120     0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02,
121     0x03, 0x04,
122 };
123
124 const uint8 kGoodbyePacket[] = {
125     // Header
126     0x00, 0x00,  // ID is zeroed out
127     0x80, 0x00,  // Standard query response, RA, no error
128     0x00, 0x00,  // No questions (for simplicity)
129     0x00, 0x02,  // 1 RR (answers)
130     0x00, 0x00,  // 0 authority RRs
131     0x00, 0x00,  // 0 additional RRs
132     0x07, '_',  'p',  'r',  'i',  'v',  'e', 't',  0x04, '_',  't',  'c',
133     'p',  0x05, 'l',  'o',  'c',  'a',  'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
134     0x00, 0x01,                                                 // CLASS is IN.
135     0x00, 0x00,              // TTL (4 bytes) is 0 seconds.
136     0x00, 0x00, 0x00, 0x0c,  // RDLENGTH is 12 bytes.
137     0x09, 'm',  'y',  'S',  'e',  'r',  'v', 'i',  'c',  'e',  0xc0, 0x0c,
138     0x09, 'm',  'y',  'S',  'e',  'r',  'v', 'i',  'c',  'e',  0xc0, 0x0c,
139     0x00, 0x21,                          // Type is SRV
140     0x00, 0x01,                          // CLASS is IN
141     0x00, 0x00,                          // TTL (4 bytes) is 0 seconds.
142     0x00, 0x00, 0x00, 0x17,              // RDLENGTH is 23
143     0x00, 0x00, 0x00, 0x00, 0x22, 0xb8,  // port 8888
144     0x09, 'm',  'y',  'S',  'e',  'r',  'v', 'i',  'c',  'e',  0x05, 'l',
145     'o',  'c',  'a',  'l',  0x00,
146 };
147
148 const uint8 kQueryPacket[] = {
149     // Header
150     0x00, 0x00,  // ID is zeroed out
151     0x00, 0x00,  // No flags.
152     0x00, 0x01,  // One question.
153     0x00, 0x00,  // 0 RRs (answers)
154     0x00, 0x00,  // 0 authority RRs
155     0x00, 0x00,  // 0 additional RRs
156
157     // Question
158     // This part is echoed back from the respective query.
159     0x07, '_',  'p', 'r', 'i', 'v', 'e', 't',  0x04, '_',  't', 'c',
160     'p',  0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0x00, 0x0c,  // TYPE is PTR.
161     0x00, 0x01,                                             // CLASS is IN.
162 };
163
164 #endif  // ENABLE_MDNS
165
166 // Sentinel value to signify the request should fail.
167 const char kResponseValueFailure[] = "FAILURE";
168
169 class FakeGCDApiFlowFactory
170     : public extensions::GcdPrivateAPI::GCDApiFlowFactoryForTests {
171  public:
172   FakeGCDApiFlowFactory() {
173     extensions::GcdPrivateAPI::SetGCDApiFlowFactoryForTests(this);
174   }
175
176   ~FakeGCDApiFlowFactory() override {
177     extensions::GcdPrivateAPI::SetGCDApiFlowFactoryForTests(NULL);
178   }
179
180   scoped_ptr<local_discovery::GCDApiFlow> CreateGCDApiFlow() override {
181     return scoped_ptr<local_discovery::GCDApiFlow>(new FakeGCDApiFlow(this));
182   }
183
184   void SetResponse(const GURL& url, const std::string& response) {
185     responses_[url] = response;
186   }
187
188  private:
189   class FakeGCDApiFlow : public local_discovery::GCDApiFlow {
190    public:
191     explicit FakeGCDApiFlow(FakeGCDApiFlowFactory* factory)
192         : factory_(factory) {}
193
194     ~FakeGCDApiFlow() override {}
195
196     void Start(scoped_ptr<Request> request) override {
197       std::string response_str = factory_->responses_[request->GetURL()];
198
199       if (response_str == kResponseValueFailure) {
200         request->OnGCDAPIFlowError(
201             local_discovery::GCDApiFlow::ERROR_MALFORMED_RESPONSE);
202         return;
203       }
204
205       scoped_ptr<base::Value> response(base::JSONReader::Read(response_str));
206       ASSERT_TRUE(response);
207
208       base::DictionaryValue* response_dict;
209       ASSERT_TRUE(response->GetAsDictionary(&response_dict));
210
211       request->OnGCDAPIFlowComplete(*response_dict);
212     }
213
214    private:
215     FakeGCDApiFlowFactory* factory_;
216   };
217
218   std::map<GURL /*request url*/, std::string /*response json*/> responses_;
219 };
220
221 class GcdPrivateAPITest : public ExtensionApiTest {
222  public:
223   GcdPrivateAPITest() : url_fetcher_factory_(&url_fetcher_impl_factory_) {
224 #if defined(ENABLE_MDNS)
225     test_service_discovery_client_ =
226         new local_discovery::TestServiceDiscoveryClient();
227     test_service_discovery_client_->Start();
228 #endif  // ENABLE_MDNS
229   }
230
231   void SetUpCommandLine(CommandLine* command_line) override {
232     ExtensionApiTest::SetUpCommandLine(command_line);
233     command_line->AppendSwitchASCII(
234         extensions::switches::kWhitelistedExtensionID,
235         "ddchlicdkolnonkihahngkmmmjnjlkkf");
236   }
237
238 #if defined(ENABLE_WIFI_BOOTSTRAPPING)
239   virtual void OnCreateWifiManager() {
240     wifi_manager_ = wifi_manager_factory_.GetLastCreatedWifiManager();
241
242     EXPECT_CALL(*wifi_manager_, Start());
243
244     EXPECT_CALL(*wifi_manager_,
245                 RequestNetworkCredentialsInternal("SuccessNetwork"))
246         .WillOnce(Invoke(this, &GcdPrivateAPITest::RespondToNetwork));
247
248     EXPECT_CALL(*wifi_manager_,
249                 RequestNetworkCredentialsInternal("FailureNetwork"))
250         .WillOnce(Invoke(this, &GcdPrivateAPITest::RespondToNetwork));
251   }
252
253   void RespondToNetwork(const std::string& network) {
254     bool success = (network == "SuccessNetwork");
255
256     wifi_manager_->CallRequestNetworkCredentialsCallback(
257         success, network, success ? "SuccessPass" : "");
258   }
259 #endif
260
261  protected:
262   FakeGCDApiFlowFactory api_flow_factory_;
263   net::URLFetcherImplFactory url_fetcher_impl_factory_;
264   net::FakeURLFetcherFactory url_fetcher_factory_;
265
266 #if defined(ENABLE_MDNS)
267   scoped_refptr<local_discovery::TestServiceDiscoveryClient>
268       test_service_discovery_client_;
269 #endif  // ENABLE_MDNS
270
271 #if defined(ENABLE_WIFI_BOOTSTRAPPING)
272   local_discovery::wifi::MockWifiManagerFactory wifi_manager_factory_;
273   local_discovery::wifi::MockWifiManager* wifi_manager_;
274 #endif
275 };
276
277 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, GetCloudList) {
278   api_flow_factory_.SetResponse(
279       GURL("https://www.google.com/cloudprint/search"), kCloudPrintResponse);
280
281   api_flow_factory_.SetResponse(
282       GURL("https://www.googleapis.com/clouddevices/v1/devices"), kGCDResponse);
283
284   EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "get_cloud_list.html"));
285 }
286
287 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, Session) {
288   url_fetcher_factory_.SetFakeResponse(GURL("http://1.2.3.4:9090/privet/info"),
289                                        kPrivetInfoResponse,
290                                        net::HTTP_OK,
291                                        net::URLRequestStatus::SUCCESS);
292
293   url_fetcher_factory_.SetFakeResponse(GURL("http://1.2.3.4:9090/privet/ping"),
294                                        kPrivetPingResponse,
295                                        net::HTTP_OK,
296                                        net::URLRequestStatus::SUCCESS);
297
298   EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "session.html"));
299 }
300
301 #if defined(ENABLE_MDNS)
302
303 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, AddBefore) {
304   test_service_discovery_client_->SimulateReceive(kAnnouncePacket,
305                                                   sizeof(kAnnouncePacket));
306
307   EXPECT_TRUE(
308       RunExtensionSubtest("gcd_private/api", "receive_new_device.html"));
309 }
310
311 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, AddAfter) {
312   base::MessageLoopProxy::current()->PostDelayedTask(
313       FROM_HERE,
314       base::Bind(&local_discovery::TestServiceDiscoveryClient::SimulateReceive,
315                  test_service_discovery_client_,
316                  kAnnouncePacket,
317                  sizeof(kAnnouncePacket)),
318       base::TimeDelta::FromSeconds(1));
319
320   EXPECT_TRUE(
321       RunExtensionSubtest("gcd_private/api", "receive_new_device.html"));
322 }
323
324 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, AddRemove) {
325   test_service_discovery_client_->SimulateReceive(kAnnouncePacket,
326                                                   sizeof(kAnnouncePacket));
327
328   base::MessageLoopProxy::current()->PostDelayedTask(
329       FROM_HERE,
330       base::Bind(&local_discovery::TestServiceDiscoveryClient::SimulateReceive,
331                  test_service_discovery_client_,
332                  kGoodbyePacket,
333                  sizeof(kGoodbyePacket)),
334       base::TimeDelta::FromSeconds(1));
335
336   EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "remove_device.html"));
337 }
338
339 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, SendQuery) {
340 // TODO(noamsml): Win Dbg has a workaround that makes RunExtensionSubtest
341 // always return true without actually running the test. Remove when fixed.
342 // See http://crbug.com/177163 for details.
343 #if !defined(OS_WIN) || defined(NDEBUG)
344   EXPECT_CALL(*test_service_discovery_client_.get(),
345               OnSendTo(std::string(reinterpret_cast<const char*>(kQueryPacket),
346                                    sizeof(kQueryPacket)))).Times(2);
347 #endif
348   EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "send_query.html"));
349 }
350
351 #endif  // ENABLE_MDNS
352
353 #if defined(ENABLE_WIFI_BOOTSTRAPPING)
354
355 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, WifiMessage) {
356   EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "wifi_message.html"));
357 }
358
359 IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, WifiPasswords) {
360 // TODO(noamsml): Win Dbg has a workaround that makes RunExtensionSubtest
361 // always return true without actually running the test. Remove when fixed.
362 // See http://crbug.com/177163 for details.
363 #if !defined(OS_WIN) || defined(NDEBUG)
364   EXPECT_CALL(wifi_manager_factory_, WifiManagerCreated())
365       .WillOnce(Invoke(this, &GcdPrivateAPITest::OnCreateWifiManager));
366 #endif
367
368   EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "wifi_password.html"));
369 }
370
371 #endif  // ENABLE_WIFI_BOOTSTRAPPING
372
373 }  // namespace