Chromium Code Reviews| Index: chrome/utility/local_discovery/service_discovery_message_handler.cc |
| diff --git a/chrome/utility/local_discovery/service_discovery_message_handler.cc b/chrome/utility/local_discovery/service_discovery_message_handler.cc |
| index 074dabca4d1ed62743c668ff1b65f0c7f27a0dc9..64bcef5a7a7245ab474f2a68fc584896129b1e0e 100644 |
| --- a/chrome/utility/local_discovery/service_discovery_message_handler.cc |
| +++ b/chrome/utility/local_discovery/service_discovery_message_handler.cc |
| @@ -4,10 +4,118 @@ |
| #include "chrome/utility/local_discovery/service_discovery_message_handler.h" |
| +#include "base/command_line.h" |
| #include "chrome/common/local_discovery/local_discovery_messages.h" |
| #include "chrome/utility/local_discovery/service_discovery_client_impl.h" |
| +#include "content/public/common/content_switches.h" |
| #include "content/public/utility/utility_thread.h" |
| +#if defined(OS_WIN) |
| + |
| +#include "base/lazy_instance.h" |
| +#include "net/base/winsock_init.h" |
| +#include "net/base/winsock_util.h" |
| + |
| +#endif // OS_WIN |
| + |
| +namespace { |
| + |
| +bool NeedsSockets() { |
| + return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox) && |
| + CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kUtilityProcessEnableMDns); |
| +} |
| + |
| +#if defined(OS_WIN) |
| + |
| +class SocketFactory : public net::PlatformSocketFactory { |
| + public: |
| + SocketFactory() |
| + : socket_v4_(NULL), |
| + socket_v6_(NULL) { |
| + net::EnsureWinsockInit(); |
| + socket_v4_ = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, |
| + WSA_FLAG_OVERLAPPED); |
| + socket_v6_ = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, |
| + WSA_FLAG_OVERLAPPED); |
| + } |
| + |
| + void Reset() { |
| + if (socket_v4_ != INVALID_SOCKET) { |
| + closesocket(socket_v4_); |
| + socket_v4_ = INVALID_SOCKET; |
| + } |
| + if (socket_v6_ != INVALID_SOCKET) { |
| + closesocket(socket_v6_); |
| + socket_v6_ = INVALID_SOCKET; |
| + } |
| + } |
| + |
| + virtual ~SocketFactory() { |
| + Reset(); |
| + } |
| + |
| + virtual SOCKET CreateSocket(int family, int type, int protocol) OVERRIDE { |
| + SOCKET result = INVALID_SOCKET; |
| + if (type != SOCK_DGRAM && protocol != IPPROTO_UDP) { |
| + NOTREACHED(); |
| + } else if (family == AF_INET) { |
| + std::swap(result, socket_v4_); |
| + } else if (family == AF_INET6) { |
| + std::swap(result, socket_v6_); |
| + } |
| + return result; |
| + } |
| + |
| + SOCKET socket_v4_; |
| + SOCKET socket_v6_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SocketFactory); |
| +}; |
| + |
| +base::LazyInstance<SocketFactory> |
| + g_local_discovery_socket_factory = LAZY_INSTANCE_INITIALIZER; |
| + |
| +class ScopedSocketFactorySetter { |
| + public: |
| + ScopedSocketFactorySetter() { |
| + if (NeedsSockets()) { |
| + net::PlatformSocketFactory::SetInstance( |
| + &g_local_discovery_socket_factory.Get()); |
| + } |
| + } |
| + |
| + ~ScopedSocketFactorySetter() { |
| + if (NeedsSockets()) { |
| + net::PlatformSocketFactory::SetInstance(NULL); |
| + g_local_discovery_socket_factory.Get().Reset(); |
| + } |
| + } |
| + |
| + static void Initialize() { |
| + if (NeedsSockets()) { |
| + g_local_discovery_socket_factory.Get(); |
| + } |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ScopedSocketFactorySetter); |
| +}; |
| + |
| +#elif // OS_WIN |
| + |
| +class ScopedSocketFactorySetter { |
| + static void Initialize() { |
| + // TODO(vitalybuka) : implement socket access from sandbox for other |
| + // platforms. |
| + DCHECK(!NeedsSockets()); |
| + } |
| +}; |
| + |
| +#endif // OS_WIN |
| + |
| +} // namespace |
| + |
| namespace local_discovery { |
| ServiceDiscoveryMessageHandler::ServiceDiscoveryMessageHandler() { |
| @@ -16,13 +124,28 @@ ServiceDiscoveryMessageHandler::ServiceDiscoveryMessageHandler() { |
| ServiceDiscoveryMessageHandler::~ServiceDiscoveryMessageHandler() { |
| } |
| -void ServiceDiscoveryMessageHandler::Initialize() { |
| - if (!service_discovery_client_) { |
| - mdns_client_ = net::MDnsClient::CreateDefault(); |
| - mdns_client_->StartListening(); |
| - service_discovery_client_.reset( |
| - new local_discovery::ServiceDiscoveryClientImpl(mdns_client_.get())); |
| +void ServiceDiscoveryMessageHandler::PreSandboxStartup() { |
| + ScopedSocketFactorySetter::Initialize(); |
| +} |
| + |
| +bool ServiceDiscoveryMessageHandler::Initialize() { |
| + if (service_discovery_client_) |
| + return true; |
| + |
| + if (mdns_client_) // We tried but failed before. |
| + false; |
|
gene
2013/07/18 08:55:28
return false?
Vitaly Buka (NO REVIEWS)
2013/07/18 18:16:16
yes. here we have mdns_client_!=NULL and service_d
Vitaly Buka (NO REVIEWS)
2013/07/18 18:18:38
I see :-)
Vitaly Buka (NO REVIEWS)
2013/07/18 18:20:42
Done.
|
| + |
| + mdns_client_ = net::MDnsClient::CreateDefault(); |
| + { |
| + // Temporarily redirect network code to use pre-created sockets. |
| + ScopedSocketFactorySetter socket_factory_setter; |
| + if (!mdns_client_->StartListening()) |
| + return false; |
| } |
| + |
| + service_discovery_client_.reset( |
| + new local_discovery::ServiceDiscoveryClientImpl(mdns_client_.get())); |
| + return true; |
| } |
| bool ServiceDiscoveryMessageHandler::OnMessageReceived( |
| @@ -42,7 +165,8 @@ bool ServiceDiscoveryMessageHandler::OnMessageReceived( |
| void ServiceDiscoveryMessageHandler::OnStartWatcher( |
| uint64 id, |
| const std::string& service_type) { |
| - Initialize(); |
| + if (!Initialize()) |
| + return; |
| DCHECK(service_watchers_.find(id) == service_watchers_.end()); |
| scoped_ptr<ServiceWatcher> watcher( |
| service_discovery_client_->CreateServiceWatcher( |
| @@ -69,7 +193,8 @@ void ServiceDiscoveryMessageHandler::OnDestroyWatcher(uint64 id) { |
| void ServiceDiscoveryMessageHandler::OnResolveService( |
| uint64 id, |
| const std::string& service_name) { |
| - Initialize(); |
| + if (!Initialize()) |
| + return; |
| DCHECK(service_resolvers_.find(id) == service_resolvers_.end()); |
| scoped_ptr<ServiceResolver> resolver( |
| service_discovery_client_->CreateServiceResolver( |