1// Copyright (c) 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#include "base/memory/ref_counted.h"
6#include "base/strings/stringprintf.h"
7#include "chrome/browser/extensions/extension_apitest.h"
8#include "chrome/browser/extensions/extension_service.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/common/chrome_paths.h"
11#include "chrome/test/base/in_process_browser_test.h"
12#include "chrome/test/base/ui_test_utils.h"
13#include "extensions/browser/api/dns/host_resolver_wrapper.h"
14#include "extensions/browser/api/dns/mock_host_resolver_creator.h"
15#include "extensions/browser/api/socket/socket_api.h"
16#include "extensions/test/extension_test_message_listener.h"
17#include "extensions/test/result_catcher.h"
18#include "net/dns/mock_host_resolver.h"
19#include "net/test/spawned_test_server/spawned_test_server.h"
20
21using extensions::Extension;
22using extensions::ResultCatcher;
23
24namespace {
25
26const std::string kHostname = "127.0.0.1";
27const int kPort = 8888;
28
29class SocketApiTest : public ExtensionApiTest {
30 public:
31  SocketApiTest() : resolver_event_(true, false),
32                    resolver_creator_(
33                        new extensions::MockHostResolverCreator()) {
34  }
35
36  virtual void SetUpOnMainThread() OVERRIDE {
37    extensions::HostResolverWrapper::GetInstance()->SetHostResolverForTesting(
38        resolver_creator_->CreateMockHostResolver());
39  }
40
41  virtual void TearDownOnMainThread() OVERRIDE {
42    extensions::HostResolverWrapper::GetInstance()->
43        SetHostResolverForTesting(NULL);
44    resolver_creator_->DeleteMockHostResolver();
45  }
46
47 private:
48  base::WaitableEvent resolver_event_;
49
50  // The MockHostResolver asserts that it's used on the same thread on which
51  // it's created, which is actually a stronger rule than its real counterpart.
52  // But that's fine; it's good practice.
53  scoped_refptr<extensions::MockHostResolverCreator> resolver_creator_;
54};
55
56}  // namespace
57
58IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketUDPExtension) {
59  scoped_ptr<net::SpawnedTestServer> test_server(
60      new net::SpawnedTestServer(
61          net::SpawnedTestServer::TYPE_UDP_ECHO,
62          net::SpawnedTestServer::kLocalhost,
63          base::FilePath(FILE_PATH_LITERAL("net/data"))));
64  EXPECT_TRUE(test_server->Start());
65
66  net::HostPortPair host_port_pair = test_server->host_port_pair();
67  int port = host_port_pair.port();
68  ASSERT_GT(port, 0);
69
70  // Test that sendTo() is properly resolving hostnames.
71  host_port_pair.set_host("LOCALhost");
72
73  ResultCatcher catcher;
74  catcher.RestrictToBrowserContext(browser()->profile());
75
76  ExtensionTestMessageListener listener("info_please", true);
77
78  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api")));
79  EXPECT_TRUE(listener.WaitUntilSatisfied());
80  listener.Reply(
81      base::StringPrintf("udp:%s:%d", host_port_pair.host().c_str(), port));
82
83  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
84}
85
86IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPExtension) {
87  scoped_ptr<net::SpawnedTestServer> test_server(
88      new net::SpawnedTestServer(
89          net::SpawnedTestServer::TYPE_TCP_ECHO,
90          net::SpawnedTestServer::kLocalhost,
91          base::FilePath(FILE_PATH_LITERAL("net/data"))));
92  EXPECT_TRUE(test_server->Start());
93
94  net::HostPortPair host_port_pair = test_server->host_port_pair();
95  int port = host_port_pair.port();
96  ASSERT_GT(port, 0);
97
98  // Test that connect() is properly resolving hostnames.
99  host_port_pair.set_host("lOcAlHoSt");
100
101  ResultCatcher catcher;
102  catcher.RestrictToBrowserContext(browser()->profile());
103
104  ExtensionTestMessageListener listener("info_please", true);
105
106  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api")));
107  EXPECT_TRUE(listener.WaitUntilSatisfied());
108  listener.Reply(
109      base::StringPrintf("tcp:%s:%d", host_port_pair.host().c_str(), port));
110
111  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
112}
113
114IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPServerExtension) {
115  ResultCatcher catcher;
116  catcher.RestrictToBrowserContext(browser()->profile());
117  ExtensionTestMessageListener listener("info_please", true);
118  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api")));
119  EXPECT_TRUE(listener.WaitUntilSatisfied());
120  listener.Reply(
121      base::StringPrintf("tcp_server:%s:%d", kHostname.c_str(), kPort));
122
123  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
124}
125
126IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPServerUnbindOnUnload) {
127  ResultCatcher catcher;
128  const Extension* extension =
129      LoadExtension(test_data_dir_.AppendASCII("socket/unload"));
130  ASSERT_TRUE(extension);
131  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
132
133  UnloadExtension(extension->id());
134
135  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/unload")))
136      << message_;
137  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
138}
139
140IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketMulticast) {
141  ResultCatcher catcher;
142  catcher.RestrictToBrowserContext(browser()->profile());
143  ExtensionTestMessageListener listener("info_please", true);
144  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api")));
145  EXPECT_TRUE(listener.WaitUntilSatisfied());
146  listener.Reply(
147      base::StringPrintf("multicast:%s:%d", kHostname.c_str(), kPort));
148
149  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
150}
151