1// Copyright 2013 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 "content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h" 6 7#include "base/logging.h" 8#include "base/memory/scoped_ptr.h" 9#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h" 10#include "content/browser/renderer_host/pepper/pepper_lookup_request.h" 11#include "content/browser/renderer_host/pepper/pepper_socket_utils.h" 12#include "content/public/browser/browser_context.h" 13#include "content/public/browser/browser_thread.h" 14#include "content/public/browser/render_process_host.h" 15#include "content/public/browser/resource_context.h" 16#include "content/public/common/socket_permission_request.h" 17#include "net/base/address_list.h" 18#include "net/dns/host_resolver.h" 19#include "ppapi/c/pp_errors.h" 20#include "ppapi/c/private/ppb_host_resolver_private.h" 21#include "ppapi/c/private/ppb_net_address_private.h" 22#include "ppapi/host/dispatch_host_message.h" 23#include "ppapi/host/error_conversion.h" 24#include "ppapi/host/host_message_context.h" 25#include "ppapi/proxy/ppapi_messages.h" 26#include "ppapi/shared_impl/private/net_address_private_impl.h" 27 28using ppapi::host::NetErrorToPepperError; 29using ppapi::host::ReplyMessageContext; 30 31namespace content { 32 33namespace { 34 35void PrepareRequestInfo(const PP_HostResolver_Private_Hint& hint, 36 net::HostResolver::RequestInfo* request_info) { 37 DCHECK(request_info); 38 39 net::AddressFamily address_family; 40 switch (hint.family) { 41 case PP_NETADDRESSFAMILY_PRIVATE_IPV4: 42 address_family = net::ADDRESS_FAMILY_IPV4; 43 break; 44 case PP_NETADDRESSFAMILY_PRIVATE_IPV6: 45 address_family = net::ADDRESS_FAMILY_IPV6; 46 break; 47 default: 48 address_family = net::ADDRESS_FAMILY_UNSPECIFIED; 49 } 50 request_info->set_address_family(address_family); 51 52 net::HostResolverFlags host_resolver_flags = 0; 53 if (hint.flags & PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME) 54 host_resolver_flags |= net::HOST_RESOLVER_CANONNAME; 55 if (hint.flags & PP_HOST_RESOLVER_PRIVATE_FLAGS_LOOPBACK_ONLY) 56 host_resolver_flags |= net::HOST_RESOLVER_LOOPBACK_ONLY; 57 request_info->set_host_resolver_flags(host_resolver_flags); 58} 59 60void CreateNetAddressListFromAddressList( 61 const net::AddressList& list, 62 std::vector<PP_NetAddress_Private>* net_address_list) { 63 DCHECK(net_address_list); 64 65 net_address_list->clear(); 66 net_address_list->reserve(list.size()); 67 68 PP_NetAddress_Private address; 69 for (size_t i = 0; i < list.size(); ++i) { 70 if (!ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress( 71 list[i].address(), list[i].port(), &address)) { 72 net_address_list->clear(); 73 return; 74 } 75 net_address_list->push_back(address); 76 } 77} 78 79} // namespace 80 81PepperHostResolverMessageFilter::PepperHostResolverMessageFilter( 82 BrowserPpapiHostImpl* host, 83 PP_Instance instance, 84 bool private_api) 85 : external_plugin_(host->external_plugin()), 86 private_api_(private_api), 87 render_process_id_(0), 88 render_frame_id_(0) { 89 DCHECK(host); 90 91 if (!host->GetRenderFrameIDsForInstance( 92 instance, &render_process_id_, &render_frame_id_)) { 93 NOTREACHED(); 94 } 95} 96 97PepperHostResolverMessageFilter::~PepperHostResolverMessageFilter() {} 98 99scoped_refptr<base::TaskRunner> 100PepperHostResolverMessageFilter::OverrideTaskRunnerForMessage( 101 const IPC::Message& message) { 102 if (message.type() == PpapiHostMsg_HostResolver_Resolve::ID) 103 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 104 return NULL; 105} 106 107int32_t PepperHostResolverMessageFilter::OnResourceMessageReceived( 108 const IPC::Message& msg, 109 ppapi::host::HostMessageContext* context) { 110 PPAPI_BEGIN_MESSAGE_MAP(PepperHostResolverMessageFilter, msg) 111 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_HostResolver_Resolve, 112 OnMsgResolve) 113 PPAPI_END_MESSAGE_MAP() 114 return PP_ERROR_FAILED; 115} 116 117int32_t PepperHostResolverMessageFilter::OnMsgResolve( 118 const ppapi::host::HostMessageContext* context, 119 const ppapi::HostPortPair& host_port, 120 const PP_HostResolver_Private_Hint& hint) { 121 DCHECK_CURRENTLY_ON(BrowserThread::UI); 122 123 // Check plugin permissions. 124 SocketPermissionRequest request( 125 SocketPermissionRequest::RESOLVE_HOST, host_port.host, host_port.port); 126 if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, 127 private_api_, 128 &request, 129 render_process_id_, 130 render_frame_id_)) { 131 return PP_ERROR_NOACCESS; 132 } 133 134 RenderProcessHost* render_process_host = 135 RenderProcessHost::FromID(render_process_id_); 136 if (!render_process_host) 137 return PP_ERROR_FAILED; 138 BrowserContext* browser_context = render_process_host->GetBrowserContext(); 139 if (!browser_context || !browser_context->GetResourceContext()) 140 return PP_ERROR_FAILED; 141 142 BrowserThread::PostTask( 143 BrowserThread::IO, 144 FROM_HERE, 145 base::Bind(&PepperHostResolverMessageFilter::DoResolve, 146 this, 147 context->MakeReplyMessageContext(), 148 host_port, 149 hint, 150 browser_context->GetResourceContext())); 151 return PP_OK_COMPLETIONPENDING; 152} 153 154void PepperHostResolverMessageFilter::DoResolve( 155 const ReplyMessageContext& context, 156 const ppapi::HostPortPair& host_port, 157 const PP_HostResolver_Private_Hint& hint, 158 ResourceContext* resource_context) { 159 DCHECK_CURRENTLY_ON(BrowserThread::IO); 160 161 net::HostResolver* host_resolver = resource_context->GetHostResolver(); 162 if (!host_resolver) { 163 SendResolveError(PP_ERROR_FAILED, context); 164 return; 165 } 166 167 net::HostResolver::RequestInfo request_info( 168 net::HostPortPair(host_port.host, host_port.port)); 169 PrepareRequestInfo(hint, &request_info); 170 171 scoped_ptr<ReplyMessageContext> bound_info(new ReplyMessageContext(context)); 172 173 // The lookup request will delete itself on completion. 174 PepperLookupRequest<ReplyMessageContext>* lookup_request = 175 new PepperLookupRequest<ReplyMessageContext>( 176 host_resolver, 177 request_info, 178 net::DEFAULT_PRIORITY, 179 bound_info.release(), 180 base::Bind(&PepperHostResolverMessageFilter::OnLookupFinished, this)); 181 lookup_request->Start(); 182} 183 184void PepperHostResolverMessageFilter::OnLookupFinished( 185 int net_result, 186 const net::AddressList& addresses, 187 const ReplyMessageContext& context) { 188 if (net_result != net::OK) { 189 SendResolveError(NetErrorToPepperError(net_result), context); 190 } else { 191 const std::string& canonical_name = addresses.canonical_name(); 192 NetAddressList net_address_list; 193 CreateNetAddressListFromAddressList(addresses, &net_address_list); 194 if (net_address_list.empty()) 195 SendResolveError(PP_ERROR_FAILED, context); 196 else 197 SendResolveReply(PP_OK, canonical_name, net_address_list, context); 198 } 199} 200 201void PepperHostResolverMessageFilter::SendResolveReply( 202 int32_t result, 203 const std::string& canonical_name, 204 const NetAddressList& net_address_list, 205 const ReplyMessageContext& context) { 206 ReplyMessageContext reply_context = context; 207 reply_context.params.set_result(result); 208 SendReply(reply_context, 209 PpapiPluginMsg_HostResolver_ResolveReply(canonical_name, 210 net_address_list)); 211} 212 213void PepperHostResolverMessageFilter::SendResolveError( 214 int32_t error, 215 const ReplyMessageContext& context) { 216 SendResolveReply(error, std::string(), NetAddressList(), context); 217} 218 219} // namespace content 220