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 28 using ppapi::host::NetErrorToPepperError; 29 using ppapi::host::ReplyMessageContext; 30 31 namespace content { 32 33 namespace { 34 35 void 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 60 void 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(list[i].address(), 71 list[i].port(), 72 &address)) { 73 net_address_list->clear(); 74 return; 75 } 76 net_address_list->push_back(address); 77 } 78 } 79 80 } // namespace 81 82 PepperHostResolverMessageFilter::PepperHostResolverMessageFilter( 83 BrowserPpapiHostImpl* host, 84 PP_Instance instance, 85 bool private_api) 86 : external_plugin_(host->external_plugin()), 87 private_api_(private_api), 88 render_process_id_(0), 89 render_view_id_(0) { 90 DCHECK(host); 91 92 if (!host->GetRenderViewIDsForInstance( 93 instance, 94 &render_process_id_, 95 &render_view_id_)) { 96 NOTREACHED(); 97 } 98 } 99 100 PepperHostResolverMessageFilter::~PepperHostResolverMessageFilter() { 101 } 102 103 scoped_refptr<base::TaskRunner> 104 PepperHostResolverMessageFilter::OverrideTaskRunnerForMessage( 105 const IPC::Message& message) { 106 if (message.type() == PpapiHostMsg_HostResolver_Resolve::ID) 107 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 108 return NULL; 109 } 110 111 int32_t PepperHostResolverMessageFilter::OnResourceMessageReceived( 112 const IPC::Message& msg, 113 ppapi::host::HostMessageContext* context) { 114 IPC_BEGIN_MESSAGE_MAP(PepperHostResolverMessageFilter, msg) 115 PPAPI_DISPATCH_HOST_RESOURCE_CALL( 116 PpapiHostMsg_HostResolver_Resolve, OnMsgResolve) 117 IPC_END_MESSAGE_MAP() 118 return PP_ERROR_FAILED; 119 } 120 121 int32_t PepperHostResolverMessageFilter::OnMsgResolve( 122 const ppapi::host::HostMessageContext* context, 123 const ppapi::HostPortPair& host_port, 124 const PP_HostResolver_Private_Hint& hint) { 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 126 127 // Check plugin permissions. 128 SocketPermissionRequest request( 129 SocketPermissionRequest::RESOLVE_HOST, host_port.host, host_port.port); 130 RenderViewHost* render_view_host = 131 RenderViewHost::FromID(render_process_id_, render_view_id_); 132 if (!render_view_host || 133 !pepper_socket_utils::CanUseSocketAPIs(external_plugin_, 134 private_api_, 135 &request, 136 render_view_host)) { 137 return PP_ERROR_NOACCESS; 138 } 139 140 RenderProcessHost* render_process_host = 141 RenderProcessHost::FromID(render_process_id_); 142 if (!render_process_host) 143 return PP_ERROR_FAILED; 144 BrowserContext* browser_context = render_process_host->GetBrowserContext(); 145 if (!browser_context || !browser_context->GetResourceContext()) 146 return PP_ERROR_FAILED; 147 148 BrowserThread::PostTask( 149 BrowserThread::IO, FROM_HERE, 150 base::Bind(&PepperHostResolverMessageFilter::DoResolve, this, 151 context->MakeReplyMessageContext(), 152 host_port, 153 hint, 154 browser_context->GetResourceContext())); 155 return PP_OK_COMPLETIONPENDING; 156 } 157 158 void PepperHostResolverMessageFilter::DoResolve( 159 const ReplyMessageContext& context, 160 const ppapi::HostPortPair& host_port, 161 const PP_HostResolver_Private_Hint& hint, 162 ResourceContext* resource_context) { 163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 164 165 net::HostResolver* host_resolver = resource_context->GetHostResolver(); 166 if (!host_resolver) { 167 SendResolveError(PP_ERROR_FAILED, context); 168 return; 169 } 170 171 net::HostResolver::RequestInfo request_info( 172 net::HostPortPair(host_port.host, host_port.port)); 173 PrepareRequestInfo(hint, &request_info); 174 175 scoped_ptr<ReplyMessageContext> bound_info(new ReplyMessageContext(context)); 176 177 // The lookup request will delete itself on completion. 178 PepperLookupRequest<ReplyMessageContext>* lookup_request = 179 new PepperLookupRequest<ReplyMessageContext>( 180 host_resolver, 181 request_info, 182 net::DEFAULT_PRIORITY, 183 bound_info.release(), 184 base::Bind(&PepperHostResolverMessageFilter::OnLookupFinished, this)); 185 lookup_request->Start(); 186 } 187 188 void PepperHostResolverMessageFilter::OnLookupFinished( 189 int net_result, 190 const net::AddressList& addresses, 191 const ReplyMessageContext& context) { 192 if (net_result != net::OK) { 193 SendResolveError(NetErrorToPepperError(net_result), context); 194 } else { 195 const std::string& canonical_name = addresses.canonical_name(); 196 NetAddressList net_address_list; 197 CreateNetAddressListFromAddressList(addresses, &net_address_list); 198 if (net_address_list.empty()) 199 SendResolveError(PP_ERROR_FAILED, context); 200 else 201 SendResolveReply(PP_OK, canonical_name, net_address_list, context); 202 } 203 } 204 205 void PepperHostResolverMessageFilter::SendResolveReply( 206 int32_t result, 207 const std::string& canonical_name, 208 const NetAddressList& net_address_list, 209 const ReplyMessageContext& context) { 210 ReplyMessageContext reply_context = context; 211 reply_context.params.set_result(result); 212 SendReply(reply_context, 213 PpapiPluginMsg_HostResolver_ResolveReply( 214 canonical_name, net_address_list)); 215 } 216 217 void PepperHostResolverMessageFilter::SendResolveError( 218 int32_t error, 219 const ReplyMessageContext& context) { 220 SendResolveReply(error, std::string(), NetAddressList(), context); 221 } 222 223 } // namespace content 224