1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
// Copyright 2013 The Chromium Authors
// 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_network_proxy_host.h"
#include "base/functional/bind.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_proxy_lookup_helper.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/network_isolation_key.h"
#include "net/proxy_resolution/proxy_info.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
namespace content {
namespace {
bool LookUpProxyForURLCallback(
int render_process_host_id,
int render_frame_host_id,
const GURL& url,
mojo::PendingRemote<network::mojom::ProxyLookupClient>
proxy_lookup_client) {
RenderFrameHost* render_frame_host =
RenderFrameHost::FromID(render_process_host_id, render_frame_host_id);
if (!render_frame_host)
return false;
SiteInstance* site_instance = render_frame_host->GetSiteInstance();
StoragePartition* storage_partition =
site_instance->GetBrowserContext()->GetStoragePartition(site_instance);
storage_partition->GetNetworkContext()->LookUpProxyForURL(
url,
render_frame_host->GetIsolationInfoForSubresources()
.network_anonymization_key(),
std::move(proxy_lookup_client));
return true;
}
} // namespace
PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host,
PP_Instance instance,
PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource),
render_process_id_(0),
render_frame_id_(0),
is_allowed_(false),
waiting_for_ui_thread_data_(true) {
host->GetRenderFrameIDsForInstance(instance, &render_process_id_,
&render_frame_id_);
GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&GetUIThreadDataOnUIThread, render_process_id_,
render_frame_id_, host->external_plugin()),
base::BindOnce(&PepperNetworkProxyHost::DidGetUIThreadData,
weak_factory_.GetWeakPtr()));
}
PepperNetworkProxyHost::~PepperNetworkProxyHost() = default;
PepperNetworkProxyHost::UIThreadData::UIThreadData() : is_allowed(false) {}
PepperNetworkProxyHost::UIThreadData::UIThreadData(const UIThreadData& other) =
default;
PepperNetworkProxyHost::UIThreadData::~UIThreadData() {}
// static
PepperNetworkProxyHost::UIThreadData
PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
int render_frame_id,
bool is_external_plugin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PepperNetworkProxyHost::UIThreadData result;
SocketPermissionRequest request(
content::SocketPermissionRequest::RESOLVE_PROXY, std::string(), 0);
result.is_allowed =
pepper_socket_utils::CanUseSocketAPIs(is_external_plugin,
false /* is_private_api */,
&request,
render_process_id,
render_frame_id);
return result;
}
void PepperNetworkProxyHost::DidGetUIThreadData(
const UIThreadData& ui_thread_data) {
is_allowed_ = ui_thread_data.is_allowed;
waiting_for_ui_thread_data_ = false;
TryToSendUnsentRequests();
}
int32_t PepperNetworkProxyHost::OnResourceMessageReceived(
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) {
PPAPI_BEGIN_MESSAGE_MAP(PepperNetworkProxyHost, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_NetworkProxy_GetProxyForURL,
OnMsgGetProxyForURL)
PPAPI_END_MESSAGE_MAP()
return PP_ERROR_FAILED;
}
int32_t PepperNetworkProxyHost::OnMsgGetProxyForURL(
ppapi::host::HostMessageContext* context,
const std::string& url) {
GURL gurl(url);
if (gurl.is_valid()) {
UnsentRequest request = {gurl, context->MakeReplyMessageContext()};
unsent_requests_.push(request);
TryToSendUnsentRequests();
} else {
SendFailureReply(PP_ERROR_BADARGUMENT, context->MakeReplyMessageContext());
}
return PP_OK_COMPLETIONPENDING;
}
void PepperNetworkProxyHost::TryToSendUnsentRequests() {
if (waiting_for_ui_thread_data_)
return;
while (!unsent_requests_.empty()) {
const UnsentRequest& request = unsent_requests_.front();
if (!is_allowed_) {
SendFailureReply(PP_ERROR_NOACCESS, request.reply_context);
} else {
// Everything looks valid, so try to resolve the proxy.
auto lookup_helper = std::make_unique<PepperProxyLookupHelper>();
PepperProxyLookupHelper::LookUpProxyForURLCallback
look_up_proxy_for_url_callback = base::BindOnce(
&LookUpProxyForURLCallback, render_process_id_, render_frame_id_);
PepperProxyLookupHelper::LookUpCompleteCallback
look_up_complete_callback =
base::BindOnce(&PepperNetworkProxyHost::OnResolveProxyCompleted,
weak_factory_.GetWeakPtr(), request.reply_context,
lookup_helper.get());
lookup_helper->Start(request.url,
std::move(look_up_proxy_for_url_callback),
std::move(look_up_complete_callback));
pending_requests_.insert(std::move(lookup_helper));
}
unsent_requests_.pop();
}
}
void PepperNetworkProxyHost::OnResolveProxyCompleted(
ppapi::host::ReplyMessageContext context,
PepperProxyLookupHelper* pending_request,
std::optional<net::ProxyInfo> proxy_info) {
auto it = pending_requests_.find(pending_request);
CHECK(it != pending_requests_.end());
pending_requests_.erase(it);
std::string pac_string;
if (!proxy_info) {
// This can happen in cases of network service crash, shutdown, or when
// the request fails with ERR_MANDATORY_PROXY_CONFIGURATION_FAILED. There's
// really no action a plugin can take, so there's no need to distinguish
// which error occurred.
context.params.set_result(PP_ERROR_FAILED);
} else if (proxy_info->ContainsMultiProxyChain()) {
// Multi-proxy chains cannot be represented as a PAC string.
context.params.set_result(PP_ERROR_FAILED);
} else {
pac_string = proxy_info->ToPacString();
}
host()->SendReply(
context, PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(pac_string));
}
void PepperNetworkProxyHost::SendFailureReply(
int32_t error,
ppapi::host::ReplyMessageContext context) {
context.params.set_result(error);
host()->SendReply(
context, PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(std::string()));
}
} // namespace content
|