Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / renderer_host / pepper / pepper_network_proxy_host.cc
blobb47c931d56361568a047a50e5e64a9d09539d12e
1 // Copyright (c) 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.
5 #include "content/browser/renderer_host/pepper/pepper_network_proxy_host.h"
7 #include "base/bind.h"
8 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
9 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
10 #include "content/public/browser/browser_context.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "content/public/common/socket_permission_request.h"
14 #include "net/base/net_errors.h"
15 #include "net/proxy/proxy_info.h"
16 #include "net/url_request/url_request_context.h"
17 #include "net/url_request/url_request_context_getter.h"
18 #include "ppapi/c/pp_errors.h"
19 #include "ppapi/host/dispatch_host_message.h"
20 #include "ppapi/host/ppapi_host.h"
21 #include "ppapi/proxy/ppapi_messages.h"
23 namespace content {
25 PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host,
26 PP_Instance instance,
27 PP_Resource resource)
28 : ResourceHost(host->GetPpapiHost(), instance, resource),
29 proxy_service_(NULL),
30 is_allowed_(false),
31 waiting_for_ui_thread_data_(true),
32 weak_factory_(this) {
33 int render_process_id(0), render_frame_id(0);
34 host->GetRenderFrameIDsForInstance(
35 instance, &render_process_id, &render_frame_id);
36 BrowserThread::PostTaskAndReplyWithResult(
37 BrowserThread::UI,
38 FROM_HERE,
39 base::Bind(&GetUIThreadDataOnUIThread,
40 render_process_id,
41 render_frame_id,
42 host->external_plugin()),
43 base::Bind(&PepperNetworkProxyHost::DidGetUIThreadData,
44 weak_factory_.GetWeakPtr()));
47 PepperNetworkProxyHost::~PepperNetworkProxyHost() {
48 while (!pending_requests_.empty()) {
49 // If the proxy_service_ is NULL, we shouldn't have any outstanding
50 // requests.
51 DCHECK(proxy_service_);
52 net::ProxyService::PacRequest* request = pending_requests_.front();
53 proxy_service_->CancelPacRequest(request);
54 pending_requests_.pop();
58 PepperNetworkProxyHost::UIThreadData::UIThreadData() : is_allowed(false) {}
60 PepperNetworkProxyHost::UIThreadData::~UIThreadData() {}
62 // static
63 PepperNetworkProxyHost::UIThreadData
64 PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
65 int render_frame_id,
66 bool is_external_plugin) {
67 DCHECK_CURRENTLY_ON(BrowserThread::UI);
68 PepperNetworkProxyHost::UIThreadData result;
69 RenderProcessHost* render_process_host =
70 RenderProcessHost::FromID(render_process_id);
71 if (render_process_host && render_process_host->GetBrowserContext()) {
72 result.context_getter =
73 render_process_host->GetBrowserContext()
74 ->GetRequestContextForRenderProcess(render_process_id);
77 SocketPermissionRequest request(
78 content::SocketPermissionRequest::RESOLVE_PROXY, std::string(), 0);
79 result.is_allowed =
80 pepper_socket_utils::CanUseSocketAPIs(is_external_plugin,
81 false /* is_private_api */,
82 &request,
83 render_process_id,
84 render_frame_id);
85 return result;
88 void PepperNetworkProxyHost::DidGetUIThreadData(
89 const UIThreadData& ui_thread_data) {
90 is_allowed_ = ui_thread_data.is_allowed;
91 if (ui_thread_data.context_getter.get() &&
92 ui_thread_data.context_getter->GetURLRequestContext()) {
93 proxy_service_ =
94 ui_thread_data.context_getter->GetURLRequestContext()->proxy_service();
96 waiting_for_ui_thread_data_ = false;
97 if (!proxy_service_) {
98 DLOG_IF(WARNING, proxy_service_)
99 << "Failed to find a ProxyService for Pepper plugin.";
101 TryToSendUnsentRequests();
104 int32_t PepperNetworkProxyHost::OnResourceMessageReceived(
105 const IPC::Message& msg,
106 ppapi::host::HostMessageContext* context) {
107 IPC_BEGIN_MESSAGE_MAP(PepperNetworkProxyHost, msg)
108 PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_NetworkProxy_GetProxyForURL,
109 OnMsgGetProxyForURL)
110 IPC_END_MESSAGE_MAP()
111 return PP_ERROR_FAILED;
114 int32_t PepperNetworkProxyHost::OnMsgGetProxyForURL(
115 ppapi::host::HostMessageContext* context,
116 const std::string& url) {
117 GURL gurl(url);
118 if (gurl.is_valid()) {
119 UnsentRequest request = {gurl, context->MakeReplyMessageContext()};
120 unsent_requests_.push(request);
121 TryToSendUnsentRequests();
122 } else {
123 SendFailureReply(PP_ERROR_BADARGUMENT, context->MakeReplyMessageContext());
125 return PP_OK_COMPLETIONPENDING;
128 void PepperNetworkProxyHost::TryToSendUnsentRequests() {
129 if (waiting_for_ui_thread_data_)
130 return;
132 while (!unsent_requests_.empty()) {
133 const UnsentRequest& request = unsent_requests_.front();
134 if (!proxy_service_) {
135 SendFailureReply(PP_ERROR_FAILED, request.reply_context);
136 } else if (!is_allowed_) {
137 SendFailureReply(PP_ERROR_NOACCESS, request.reply_context);
138 } else {
139 // Everything looks valid, so try to resolve the proxy.
140 net::ProxyInfo* proxy_info = new net::ProxyInfo;
141 net::ProxyService::PacRequest* pending_request = NULL;
142 base::Callback<void(int)> callback =
143 base::Bind(&PepperNetworkProxyHost::OnResolveProxyCompleted,
144 weak_factory_.GetWeakPtr(),
145 request.reply_context,
146 base::Owned(proxy_info));
147 int result = proxy_service_->ResolveProxy(request.url,
148 proxy_info,
149 callback,
150 &pending_request,
151 net::BoundNetLog());
152 pending_requests_.push(pending_request);
153 // If it was handled synchronously, we must run the callback now;
154 // proxy_service_ won't run it for us in this case.
155 if (result != net::ERR_IO_PENDING)
156 callback.Run(result);
158 unsent_requests_.pop();
162 void PepperNetworkProxyHost::OnResolveProxyCompleted(
163 ppapi::host::ReplyMessageContext context,
164 net::ProxyInfo* proxy_info,
165 int result) {
166 pending_requests_.pop();
168 if (result != net::OK) {
169 // Currently, the only proxy-specific error we could get is
170 // MANDATORY_PROXY_CONFIGURATION_FAILED. There's really no action a plugin
171 // can take in this case, so there's no need to distinguish it from other
172 // failures.
173 context.params.set_result(PP_ERROR_FAILED);
175 host()->SendReply(context,
176 PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(
177 proxy_info->ToPacString()));
180 void PepperNetworkProxyHost::SendFailureReply(
181 int32_t error,
182 ppapi::host::ReplyMessageContext context) {
183 context.params.set_result(error);
184 host()->SendReply(
185 context, PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(std::string()));
188 } // namespace content