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/path_service.h" 7 #include "base/strings/stringprintf.h" 8 #include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h" 9 #include "chrome/browser/extensions/api/dns/mock_host_resolver_creator.h" 10 #include "chrome/browser/extensions/api/socket/socket_api.h" 11 #include "chrome/browser/extensions/extension_apitest.h" 12 #include "chrome/browser/extensions/extension_function_test_utils.h" 13 #include "chrome/browser/extensions/extension_service.h" 14 #include "chrome/browser/extensions/extension_test_message_listener.h" 15 #include "chrome/browser/ui/browser.h" 16 #include "chrome/browser/ui/extensions/application_launch.h" 17 #include "chrome/common/chrome_paths.h" 18 #include "chrome/test/base/in_process_browser_test.h" 19 #include "chrome/test/base/ui_test_utils.h" 20 #include "net/dns/mock_host_resolver.h" 21 #include "net/test/spawned_test_server/spawned_test_server.h" 22 23 using extensions::Extension; 24 25 namespace utils = extension_function_test_utils; 26 27 namespace { 28 29 // TODO(jschuh): Hanging plugin tests. crbug.com/244653 30 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64) 31 #define MAYBE(x) DISABLED_##x 32 #else 33 #define MAYBE(x) x 34 #endif 35 36 const std::string kHostname = "127.0.0.1"; 37 const int kPort = 8888; 38 39 class SocketApiTest : public ExtensionApiTest { 40 public: 41 SocketApiTest() : resolver_event_(true, false), 42 resolver_creator_( 43 new extensions::MockHostResolverCreator()) { 44 } 45 46 virtual void SetUpOnMainThread() OVERRIDE { 47 extensions::HostResolverWrapper::GetInstance()->SetHostResolverForTesting( 48 resolver_creator_->CreateMockHostResolver()); 49 } 50 51 virtual void CleanUpOnMainThread() OVERRIDE { 52 extensions::HostResolverWrapper::GetInstance()-> 53 SetHostResolverForTesting(NULL); 54 resolver_creator_->DeleteMockHostResolver(); 55 } 56 57 private: 58 base::WaitableEvent resolver_event_; 59 60 // The MockHostResolver asserts that it's used on the same thread on which 61 // it's created, which is actually a stronger rule than its real counterpart. 62 // But that's fine; it's good practice. 63 scoped_refptr<extensions::MockHostResolverCreator> resolver_creator_; 64 }; 65 66 #if !defined(DISABLE_NACL) 67 // TODO(yzshen): Build testing framework for all extensions APIs in Pepper. And 68 // move these Pepper API tests there. 69 class SocketPpapiTest : public SocketApiTest { 70 public: 71 SocketPpapiTest() { 72 } 73 virtual ~SocketPpapiTest() { 74 } 75 76 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 77 SocketApiTest::SetUpCommandLine(command_line); 78 // TODO(yzshen): It is better to use switches::kEnablePepperTesting. 79 // However, that requires adding a new DEPS entry. Considering that we are 80 // going to move the Pepper API tests to a new place, use a string literal 81 // for now. 82 command_line->AppendSwitch("enable-pepper-testing"); 83 84 PathService::Get(chrome::DIR_GEN_TEST_DATA, &app_dir_); 85 app_dir_ = app_dir_.AppendASCII( 86 "chrome/test/data/extensions/api_test/socket/ppapi/newlib"); 87 } 88 89 protected: 90 void LaunchTestingApp() { 91 const Extension* extension = LoadExtension(app_dir_); 92 ASSERT_TRUE(extension); 93 94 chrome::AppLaunchParams params(browser()->profile(), extension, 95 extension_misc::LAUNCH_NONE, 96 NEW_WINDOW); 97 params.command_line = CommandLine::ForCurrentProcess(); 98 chrome::OpenApplication(params); 99 } 100 101 private: 102 base::FilePath app_dir_; 103 }; 104 #endif 105 106 } // namespace 107 108 IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketUDPCreateGood) { 109 scoped_refptr<extensions::SocketCreateFunction> socket_create_function( 110 new extensions::SocketCreateFunction()); 111 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 112 113 socket_create_function->set_extension(empty_extension.get()); 114 socket_create_function->set_has_callback(true); 115 116 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 117 socket_create_function.get(), "[\"udp\"]", browser(), utils::NONE)); 118 ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType()); 119 base::DictionaryValue *value = 120 static_cast<base::DictionaryValue*>(result.get()); 121 int socketId = -1; 122 EXPECT_TRUE(value->GetInteger("socketId", &socketId)); 123 EXPECT_TRUE(socketId > 0); 124 } 125 126 IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPCreateGood) { 127 scoped_refptr<extensions::SocketCreateFunction> socket_create_function( 128 new extensions::SocketCreateFunction()); 129 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 130 131 socket_create_function->set_extension(empty_extension.get()); 132 socket_create_function->set_has_callback(true); 133 134 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 135 socket_create_function.get(), "[\"tcp\"]", browser(), utils::NONE)); 136 ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType()); 137 base::DictionaryValue *value = 138 static_cast<base::DictionaryValue*>(result.get()); 139 int socketId = -1; 140 EXPECT_TRUE(value->GetInteger("socketId", &socketId)); 141 ASSERT_TRUE(socketId > 0); 142 } 143 144 IN_PROC_BROWSER_TEST_F(SocketApiTest, GetNetworkList) { 145 scoped_refptr<extensions::SocketGetNetworkListFunction> socket_function( 146 new extensions::SocketGetNetworkListFunction()); 147 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 148 149 socket_function->set_extension(empty_extension.get()); 150 socket_function->set_has_callback(true); 151 152 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 153 socket_function.get(), "[]", browser(), utils::NONE)); 154 ASSERT_EQ(base::Value::TYPE_LIST, result->GetType()); 155 156 // If we're invoking socket tests, all we can confirm is that we have at 157 // least one address, but not what it is. 158 base::ListValue *value = static_cast<base::ListValue*>(result.get()); 159 ASSERT_TRUE(value->GetSize() > 0); 160 } 161 162 IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketUDPExtension) { 163 scoped_ptr<net::SpawnedTestServer> test_server( 164 new net::SpawnedTestServer( 165 net::SpawnedTestServer::TYPE_UDP_ECHO, 166 net::SpawnedTestServer::kLocalhost, 167 base::FilePath(FILE_PATH_LITERAL("net/data")))); 168 EXPECT_TRUE(test_server->Start()); 169 170 net::HostPortPair host_port_pair = test_server->host_port_pair(); 171 int port = host_port_pair.port(); 172 ASSERT_TRUE(port > 0); 173 174 // Test that sendTo() is properly resolving hostnames. 175 host_port_pair.set_host("LOCALhost"); 176 177 ResultCatcher catcher; 178 catcher.RestrictToProfile(browser()->profile()); 179 180 ExtensionTestMessageListener listener("info_please", true); 181 182 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 183 EXPECT_TRUE(listener.WaitUntilSatisfied()); 184 listener.Reply( 185 base::StringPrintf("udp:%s:%d", host_port_pair.host().c_str(), port)); 186 187 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 188 } 189 190 IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPExtension) { 191 scoped_ptr<net::SpawnedTestServer> test_server( 192 new net::SpawnedTestServer( 193 net::SpawnedTestServer::TYPE_TCP_ECHO, 194 net::SpawnedTestServer::kLocalhost, 195 base::FilePath(FILE_PATH_LITERAL("net/data")))); 196 EXPECT_TRUE(test_server->Start()); 197 198 net::HostPortPair host_port_pair = test_server->host_port_pair(); 199 int port = host_port_pair.port(); 200 ASSERT_TRUE(port > 0); 201 202 // Test that connect() is properly resolving hostnames. 203 host_port_pair.set_host("lOcAlHoSt"); 204 205 ResultCatcher catcher; 206 catcher.RestrictToProfile(browser()->profile()); 207 208 ExtensionTestMessageListener listener("info_please", true); 209 210 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 211 EXPECT_TRUE(listener.WaitUntilSatisfied()); 212 listener.Reply( 213 base::StringPrintf("tcp:%s:%d", host_port_pair.host().c_str(), port)); 214 215 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 216 } 217 218 IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPServerExtension) { 219 ResultCatcher catcher; 220 catcher.RestrictToProfile(browser()->profile()); 221 ExtensionTestMessageListener listener("info_please", true); 222 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 223 EXPECT_TRUE(listener.WaitUntilSatisfied()); 224 listener.Reply( 225 base::StringPrintf("tcp_server:%s:%d", kHostname.c_str(), kPort)); 226 227 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 228 } 229 230 IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPServerUnbindOnUnload) { 231 ResultCatcher catcher; 232 const Extension* extension = 233 LoadExtension(test_data_dir_.AppendASCII("socket/unload")); 234 ASSERT_TRUE(extension); 235 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 236 237 UnloadExtension(extension->id()); 238 239 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/unload"))) 240 << message_; 241 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 242 } 243 244 IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketMulticast) { 245 ResultCatcher catcher; 246 catcher.RestrictToProfile(browser()->profile()); 247 ExtensionTestMessageListener listener("info_please", true); 248 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 249 EXPECT_TRUE(listener.WaitUntilSatisfied()); 250 listener.Reply( 251 base::StringPrintf("multicast:%s:%d", kHostname.c_str(), kPort)); 252 253 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 254 } 255 256 #if !defined(DISABLE_NACL) 257 IN_PROC_BROWSER_TEST_F(SocketPpapiTest, MAYBE(UDP)) { 258 scoped_ptr<net::SpawnedTestServer> test_server( 259 new net::SpawnedTestServer( 260 net::SpawnedTestServer::TYPE_UDP_ECHO, 261 net::SpawnedTestServer::kLocalhost, 262 base::FilePath(FILE_PATH_LITERAL("net/data")))); 263 EXPECT_TRUE(test_server->Start()); 264 265 net::HostPortPair host_port_pair = test_server->host_port_pair(); 266 int port = host_port_pair.port(); 267 ASSERT_TRUE(port > 0); 268 269 // Test that sendTo() is properly resolving hostnames. 270 host_port_pair.set_host("LOCALhost"); 271 272 ResultCatcher catcher; 273 catcher.RestrictToProfile(browser()->profile()); 274 275 ExtensionTestMessageListener listener("info_please", true); 276 277 LaunchTestingApp(); 278 279 EXPECT_TRUE(listener.WaitUntilSatisfied()); 280 listener.Reply( 281 base::StringPrintf("udp:%s:%d", host_port_pair.host().c_str(), port)); 282 283 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 284 } 285 286 IN_PROC_BROWSER_TEST_F(SocketPpapiTest, MAYBE(TCP)) { 287 scoped_ptr<net::SpawnedTestServer> test_server( 288 new net::SpawnedTestServer( 289 net::SpawnedTestServer::TYPE_TCP_ECHO, 290 net::SpawnedTestServer::kLocalhost, 291 base::FilePath(FILE_PATH_LITERAL("net/data")))); 292 EXPECT_TRUE(test_server->Start()); 293 294 net::HostPortPair host_port_pair = test_server->host_port_pair(); 295 int port = host_port_pair.port(); 296 ASSERT_TRUE(port > 0); 297 298 // Test that connect() is properly resolving hostnames. 299 host_port_pair.set_host("lOcAlHoSt"); 300 301 ResultCatcher catcher; 302 catcher.RestrictToProfile(browser()->profile()); 303 304 ExtensionTestMessageListener listener("info_please", true); 305 306 LaunchTestingApp(); 307 308 EXPECT_TRUE(listener.WaitUntilSatisfied()); 309 listener.Reply( 310 base::StringPrintf("tcp:%s:%d", host_port_pair.host().c_str(), port)); 311 312 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 313 } 314 315 IN_PROC_BROWSER_TEST_F(SocketPpapiTest, MAYBE(TCPServer)) { 316 ResultCatcher catcher; 317 catcher.RestrictToProfile(browser()->profile()); 318 ExtensionTestMessageListener listener("info_please", true); 319 320 LaunchTestingApp(); 321 322 EXPECT_TRUE(listener.WaitUntilSatisfied()); 323 listener.Reply( 324 base::StringPrintf("tcp_server:%s:%d", kHostname.c_str(), kPort)); 325 326 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 327 } 328 329 IN_PROC_BROWSER_TEST_F(SocketPpapiTest, MAYBE(Multicast)) { 330 ResultCatcher catcher; 331 catcher.RestrictToProfile(browser()->profile()); 332 ExtensionTestMessageListener listener("info_please", true); 333 334 LaunchTestingApp(); 335 336 EXPECT_TRUE(listener.WaitUntilSatisfied()); 337 listener.Reply( 338 base::StringPrintf("multicast:%s:%d", kHostname.c_str(), kPort)); 339 340 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 341 } 342 #endif 343