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