Chromium Code Reviews| Index: content/browser/renderer_host/pepper/pepper_host_resolver_private_host.cc |
| diff --git a/content/browser/renderer_host/pepper/pepper_host_resolver_private_host.cc b/content/browser/renderer_host/pepper/pepper_host_resolver_private_host.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6c253154d8d143f9857b91ac7085f9f57c8ddfef |
| --- /dev/null |
| +++ b/content/browser/renderer_host/pepper/pepper_host_resolver_private_host.cc |
| @@ -0,0 +1,246 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/pepper/pepper_host_resolver_private_host.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/time.h" |
| +#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" |
| +#include "content/browser/renderer_host/pepper/pepper_lookup_request.h" |
| +#include "content/browser/renderer_host/pepper/pepper_socket_utils.h" |
| +#include "content/public/browser/browser_context.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "content/public/browser/resource_context.h" |
| +#include "content/public/common/socket_permission_request.h" |
| +#include "net/base/address_list.h" |
| +#include "net/base/host_resolver.h" |
| +#include "ppapi/c/private/ppb_host_resolver_private.h" |
| +#include "ppapi/c/private/ppb_net_address_private.h" |
| +#include "ppapi/host/dispatch_host_message.h" |
| +#include "ppapi/host/ppapi_host.h" |
| +#include "ppapi/proxy/host_resolver_private_resource.h" |
| +#include "ppapi/proxy/ppapi_messages.h" |
| +#include "ppapi/shared_impl/private/net_address_private_impl.h" |
| + |
| +namespace content { |
| + |
| +namespace { |
| + |
| +// Delay for resolve requests until host resolver is ready. |
| +const int kHostResolverWaitingTimeoutMs = 100; |
| + |
| +ResourceContext* GetResourceContext(RenderProcessHost* render_process_host) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + BrowserContext* browser_context = render_process_host->GetBrowserContext(); |
| + if (!browser_context) |
| + return NULL; |
| + return browser_context->GetResourceContext(); |
| +} |
| + |
| +void PrepareRequestInfo(const PP_HostResolver_Private_Hint& hint, |
| + net::HostResolver::RequestInfo* request_info) { |
| + DCHECK(request_info); |
| + |
| + net::AddressFamily address_family; |
| + switch (hint.family) { |
| + case PP_NETADDRESSFAMILY_IPV4: |
| + address_family = net::ADDRESS_FAMILY_IPV4; |
| + break; |
| + case PP_NETADDRESSFAMILY_IPV6: |
| + address_family = net::ADDRESS_FAMILY_IPV6; |
| + break; |
| + default: |
| + address_family = net::ADDRESS_FAMILY_UNSPECIFIED; |
| + } |
| + request_info->set_address_family(address_family); |
| + |
| + net::HostResolverFlags host_resolver_flags = 0; |
| + if (hint.flags & PP_HOST_RESOLVER_FLAGS_CANONNAME) |
| + host_resolver_flags |= net::HOST_RESOLVER_CANONNAME; |
| + if (hint.flags & PP_HOST_RESOLVER_FLAGS_LOOPBACK_ONLY) |
| + host_resolver_flags |= net::HOST_RESOLVER_LOOPBACK_ONLY; |
| + request_info->set_host_resolver_flags(host_resolver_flags); |
| +} |
| + |
| +void CreateNetAddressListFromAddressList( |
| + const net::AddressList& list, |
| + std::vector<PP_NetAddress_Private>* net_address_list) { |
| + DCHECK(net_address_list); |
| + |
| + net_address_list->clear(); |
| + net_address_list->reserve(list.size()); |
| + |
| + PP_NetAddress_Private address; |
| + for (size_t i = 0; i < list.size(); ++i) { |
| + if (!ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(list[i].address(), |
| + list[i].port(), |
| + &address)) { |
| + net_address_list->clear(); |
| + return; |
| + } |
| + net_address_list->push_back(address); |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +PepperHostResolverPrivateHost::PepperHostResolverPrivateHost( |
| + BrowserPpapiHostImpl* host, |
| + PP_Instance instance, |
| + PP_Resource resource) |
| + : ResourceHost(host->GetPpapiHost(), instance, resource), |
| + host_(host), |
| + host_resolver_(NULL), |
| + host_resolver_is_ready_(false), |
| + weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| + DCHECK(host); |
| + |
| + // Request host resolver. |
| + pepper_socket_utils::PostOnUIThreadWithRenderProcessHostAndReply( |
| + host_, |
| + FROM_HERE, |
| + instance, |
| + base::Bind(&GetResourceContext), |
| + base::Bind(&PepperHostResolverPrivateHost::SetHostResolver, |
| + weak_factory_.GetWeakPtr())); |
| +} |
| + |
| +PepperHostResolverPrivateHost::~PepperHostResolverPrivateHost() { |
| +} |
| + |
| +int32_t PepperHostResolverPrivateHost::OnResourceMessageReceived( |
| + const IPC::Message& msg, |
| + ppapi::host::HostMessageContext* context) { |
| + IPC_BEGIN_MESSAGE_MAP(PepperHostResolverPrivateHost, msg) |
| + PPAPI_DISPATCH_HOST_RESOURCE_CALL( |
| + PpapiHostMsg_HostResolverPrivate_Resolve, |
| + OnMsgResolve) |
| + IPC_END_MESSAGE_MAP() |
| + return PP_ERROR_FAILED; |
| +} |
| + |
| +void PepperHostResolverPrivateHost::SetHostResolver( |
| + ResourceContext* resource_context) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + host_resolver_is_ready_ = true; |
|
yzshen1
2013/01/24 18:45:03
nit: |host_resolver_is_ready_| is not very accurat
ygorshenin1
2013/02/05 12:45:31
Done.
|
| + if (resource_context) |
| + host_resolver_ = resource_context->GetHostResolver(); |
| +} |
| + |
| +int32_t PepperHostResolverPrivateHost::OnMsgResolve( |
|
yzshen1
2013/01/24 18:45:03
Now that we have to jump to the UI thread to:
- ge
ygorshenin1
2013/02/05 12:45:31
Great idea. Code is much cleaner now. Thanks!
On
|
| + const ppapi::host::HostMessageContext* context, |
| + const ppapi::HostPortPair& host_port, |
| + const PP_HostResolver_Private_Hint& hint) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + OnResolve(context->MakeReplyMessageContext(), host_port, hint); |
| + return PP_OK_COMPLETIONPENDING; |
| +} |
| + |
| +void PepperHostResolverPrivateHost::OnResolve( |
| + const ppapi::host::ReplyMessageContext& context, |
| + const ppapi::HostPortPair& host_port, |
| + const PP_HostResolver_Private_Hint& hint) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + if (!host_resolver_is_ready()) { |
| + // Delay resolve request until host resolver is ready. |
| + BrowserThread::PostDelayedTask( |
| + BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(&PepperHostResolverPrivateHost::OnResolve, |
| + weak_factory_.GetWeakPtr(), |
| + context, host_port, hint), |
| + base::TimeDelta::FromMilliseconds(kHostResolverWaitingTimeoutMs)); |
| + return; |
| + } |
| + |
| + SocketPermissionRequest request( |
| + content::SocketPermissionRequest::NONE, "", 0); |
| + CheckSocketPermissionsAndReply( |
| + request, |
| + base::Bind(&PepperHostResolverPrivateHost::DoResolve, |
| + weak_factory_.GetWeakPtr(), |
| + context, host_port, hint)); |
| +} |
| + |
| +void PepperHostResolverPrivateHost::DoResolve( |
| + const ppapi::host::ReplyMessageContext& context, |
| + const ppapi::HostPortPair& host_port, |
| + const PP_HostResolver_Private_Hint& hint, |
| + bool allowed) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + if (!allowed || !host_resolver()) { |
| + SendResolveError(context); |
| + return; |
| + } |
| + |
| + net::HostResolver::RequestInfo request_info( |
| + net::HostPortPair(host_port.host, host_port.port)); |
| + PrepareRequestInfo(hint, &request_info); |
| + |
| + scoped_ptr<ReplyMessageContext> bound_info(new ReplyMessageContext(context)); |
| + |
| + // The lookup request will delete itself on completion. |
| + PepperLookupRequest<ReplyMessageContext>* lookup_request = |
| + new PepperLookupRequest<ReplyMessageContext>( |
| + host_resolver(), |
| + request_info, |
| + bound_info.release(), |
| + base::Bind(&PepperHostResolverPrivateHost::OnLookupFinished, |
| + weak_factory_.GetWeakPtr())); |
| + lookup_request->Start(); |
| +} |
| + |
| +void PepperHostResolverPrivateHost::OnLookupFinished( |
| + int result, |
| + const net::AddressList& addresses, |
| + const ReplyMessageContext& context) { |
| + if (result != net::OK) { |
| + SendResolveError(context); |
| + } else { |
| + const std::string& canonical_name = addresses.canonical_name(); |
| + NetAddressList net_address_list; |
| + CreateNetAddressListFromAddressList(addresses, &net_address_list); |
| + if (net_address_list.empty()) |
| + SendResolveError(context); |
| + else |
| + SendResolveReply(true, canonical_name, net_address_list, context); |
| + } |
| +} |
| + |
| +void PepperHostResolverPrivateHost::SendResolveReply( |
| + bool succeeded, |
| + const std::string& canonical_name, |
| + const NetAddressList& net_address_list, |
| + const ReplyMessageContext& context) { |
| + ppapi::host::ReplyMessageContext reply_context = context; |
| + reply_context.params.set_result(succeeded); |
| + host()->SendReply(reply_context, |
| + PpapiPluginMsg_HostResolverPrivate_ResolveReply( |
| + canonical_name, net_address_list)); |
| +} |
| + |
| +void PepperHostResolverPrivateHost::SendResolveError( |
| + const ReplyMessageContext& context) { |
| + SendResolveReply(false, "", NetAddressList(), context); |
| +} |
| + |
| +void PepperHostResolverPrivateHost::CheckSocketPermissionsAndReply( |
| + const SocketPermissionRequest& params, |
| + const PermissionCheckCallback& callback) { |
| + pepper_socket_utils::PostOnUIThreadWithRenderViewHostAndReply( |
| + host_, |
| + FROM_HERE, |
| + pp_instance(), |
| + base::Bind(&pepper_socket_utils::CanUseSocketAPIs, |
| + host_->plugin_process_type(), params), |
| + callback); |
| +} |
| + |
| +} // namespace content |