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/api/dns/mock_host_resolver_creator.h" 8#include "chrome/browser/extensions/extension_apitest.h" 9#include "chrome/browser/extensions/extension_function_test_utils.h" 10#include "chrome/browser/extensions/extension_service.h" 11#include "chrome/browser/extensions/extension_test_message_listener.h" 12#include "chrome/browser/ui/browser.h" 13#include "chrome/common/chrome_paths.h" 14#include "chrome/test/base/in_process_browser_test.h" 15#include "chrome/test/base/ui_test_utils.h" 16#include "extensions/browser/api/dns/host_resolver_wrapper.h" 17#include "extensions/browser/api/socket/socket_api.h" 18#include "net/dns/mock_host_resolver.h" 19#include "net/test/spawned_test_server/spawned_test_server.h" 20 21using extensions::Extension; 22 23namespace utils = extension_function_test_utils; 24 25namespace { 26 27const std::string kHostname = "127.0.0.1"; 28const int kPort = 8888; 29 30class SocketApiTest : public ExtensionApiTest { 31 public: 32 SocketApiTest() : resolver_event_(true, false), 33 resolver_creator_( 34 new extensions::MockHostResolverCreator()) { 35 } 36 37 virtual void SetUpOnMainThread() OVERRIDE { 38 extensions::HostResolverWrapper::GetInstance()->SetHostResolverForTesting( 39 resolver_creator_->CreateMockHostResolver()); 40 } 41 42 virtual void CleanUpOnMainThread() OVERRIDE { 43 extensions::HostResolverWrapper::GetInstance()-> 44 SetHostResolverForTesting(NULL); 45 resolver_creator_->DeleteMockHostResolver(); 46 } 47 48 private: 49 base::WaitableEvent resolver_event_; 50 51 // The MockHostResolver asserts that it's used on the same thread on which 52 // it's created, which is actually a stronger rule than its real counterpart. 53 // But that's fine; it's good practice. 54 scoped_refptr<extensions::MockHostResolverCreator> resolver_creator_; 55}; 56 57} // namespace 58 59IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketUDPCreateGood) { 60 scoped_refptr<extensions::SocketCreateFunction> socket_create_function( 61 new extensions::SocketCreateFunction()); 62 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 63 64 socket_create_function->set_extension(empty_extension.get()); 65 socket_create_function->set_has_callback(true); 66 67 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 68 socket_create_function.get(), "[\"udp\"]", browser(), utils::NONE)); 69 ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType()); 70 base::DictionaryValue *value = 71 static_cast<base::DictionaryValue*>(result.get()); 72 int socket_id = -1; 73 EXPECT_TRUE(value->GetInteger("socketId", &socket_id)); 74 EXPECT_GT(socket_id, 0); 75} 76 77IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPCreateGood) { 78 scoped_refptr<extensions::SocketCreateFunction> socket_create_function( 79 new extensions::SocketCreateFunction()); 80 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 81 82 socket_create_function->set_extension(empty_extension.get()); 83 socket_create_function->set_has_callback(true); 84 85 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 86 socket_create_function.get(), "[\"tcp\"]", browser(), utils::NONE)); 87 ASSERT_EQ(base::Value::TYPE_DICTIONARY, result->GetType()); 88 base::DictionaryValue *value = 89 static_cast<base::DictionaryValue*>(result.get()); 90 int socket_id = -1; 91 EXPECT_TRUE(value->GetInteger("socketId", &socket_id)); 92 ASSERT_GT(socket_id, 0); 93} 94 95IN_PROC_BROWSER_TEST_F(SocketApiTest, GetNetworkList) { 96 scoped_refptr<extensions::SocketGetNetworkListFunction> socket_function( 97 new extensions::SocketGetNetworkListFunction()); 98 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension()); 99 100 socket_function->set_extension(empty_extension.get()); 101 socket_function->set_has_callback(true); 102 103 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( 104 socket_function.get(), "[]", browser(), utils::NONE)); 105 ASSERT_EQ(base::Value::TYPE_LIST, result->GetType()); 106 107 // If we're invoking socket tests, all we can confirm is that we have at 108 // least one address, but not what it is. 109 base::ListValue *value = static_cast<base::ListValue*>(result.get()); 110 ASSERT_GT(value->GetSize(), 0U); 111} 112 113IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketUDPExtension) { 114 scoped_ptr<net::SpawnedTestServer> test_server( 115 new net::SpawnedTestServer( 116 net::SpawnedTestServer::TYPE_UDP_ECHO, 117 net::SpawnedTestServer::kLocalhost, 118 base::FilePath(FILE_PATH_LITERAL("net/data")))); 119 EXPECT_TRUE(test_server->Start()); 120 121 net::HostPortPair host_port_pair = test_server->host_port_pair(); 122 int port = host_port_pair.port(); 123 ASSERT_GT(port, 0); 124 125 // Test that sendTo() is properly resolving hostnames. 126 host_port_pair.set_host("LOCALhost"); 127 128 ResultCatcher catcher; 129 catcher.RestrictToProfile(browser()->profile()); 130 131 ExtensionTestMessageListener listener("info_please", true); 132 133 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 134 EXPECT_TRUE(listener.WaitUntilSatisfied()); 135 listener.Reply( 136 base::StringPrintf("udp:%s:%d", host_port_pair.host().c_str(), port)); 137 138 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 139} 140 141IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPExtension) { 142 scoped_ptr<net::SpawnedTestServer> test_server( 143 new net::SpawnedTestServer( 144 net::SpawnedTestServer::TYPE_TCP_ECHO, 145 net::SpawnedTestServer::kLocalhost, 146 base::FilePath(FILE_PATH_LITERAL("net/data")))); 147 EXPECT_TRUE(test_server->Start()); 148 149 net::HostPortPair host_port_pair = test_server->host_port_pair(); 150 int port = host_port_pair.port(); 151 ASSERT_GT(port, 0); 152 153 // Test that connect() is properly resolving hostnames. 154 host_port_pair.set_host("lOcAlHoSt"); 155 156 ResultCatcher catcher; 157 catcher.RestrictToProfile(browser()->profile()); 158 159 ExtensionTestMessageListener listener("info_please", true); 160 161 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 162 EXPECT_TRUE(listener.WaitUntilSatisfied()); 163 listener.Reply( 164 base::StringPrintf("tcp:%s:%d", host_port_pair.host().c_str(), port)); 165 166 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 167} 168 169IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPServerExtension) { 170 ResultCatcher catcher; 171 catcher.RestrictToProfile(browser()->profile()); 172 ExtensionTestMessageListener listener("info_please", true); 173 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 174 EXPECT_TRUE(listener.WaitUntilSatisfied()); 175 listener.Reply( 176 base::StringPrintf("tcp_server:%s:%d", kHostname.c_str(), kPort)); 177 178 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 179} 180 181IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPServerUnbindOnUnload) { 182 ResultCatcher catcher; 183 const Extension* extension = 184 LoadExtension(test_data_dir_.AppendASCII("socket/unload")); 185 ASSERT_TRUE(extension); 186 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 187 188 UnloadExtension(extension->id()); 189 190 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/unload"))) 191 << message_; 192 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 193} 194 195IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketMulticast) { 196 ResultCatcher catcher; 197 catcher.RestrictToProfile(browser()->profile()); 198 ExtensionTestMessageListener listener("info_please", true); 199 ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api"))); 200 EXPECT_TRUE(listener.WaitUntilSatisfied()); 201 listener.Reply( 202 base::StringPrintf("multicast:%s:%d", kHostname.c_str(), kPort)); 203 204 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 205} 206