Commit 4dfa217e authored by Matt Menke's avatar Matt Menke Committed by Commit Bot

Add proxy look up API to NetworkContexts, convert PPAPI consumers.

The only code outside of net/ / services/network that does direct proxy
resolutions appears to be the two PPAPI consumers. This CL updates them
both to use the new API.

Bug: 810950
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: I643605dfe2d8b67626ea8b84ee793b2c88b66e12
Reviewed-on: https://chromium-review.googlesource.com/1136875Reviewed-by: default avatarEric Roman <eroman@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarRaymes Khoury <raymes@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Commit-Queue: Matt Menke <mmenke@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580195}
parent 5f93c62c
...@@ -2022,6 +2022,8 @@ jumbo_source_set("browser") { ...@@ -2022,6 +2022,8 @@ jumbo_source_set("browser") {
"renderer_host/pepper/pepper_print_settings_manager.h", "renderer_host/pepper/pepper_print_settings_manager.h",
"renderer_host/pepper/pepper_printing_host.cc", "renderer_host/pepper/pepper_printing_host.cc",
"renderer_host/pepper/pepper_printing_host.h", "renderer_host/pepper/pepper_printing_host.h",
"renderer_host/pepper/pepper_proxy_lookup_helper.cc",
"renderer_host/pepper/pepper_proxy_lookup_helper.h",
"renderer_host/pepper/pepper_renderer_connection.cc", "renderer_host/pepper/pepper_renderer_connection.cc",
"renderer_host/pepper/pepper_renderer_connection.h", "renderer_host/pepper/pepper_renderer_connection.h",
"renderer_host/pepper/pepper_security_helper.cc", "renderer_host/pepper/pepper_security_helper.cc",
......
...@@ -6,44 +6,65 @@ ...@@ -6,44 +6,65 @@
#include "base/bind.h" #include "base/bind.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.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/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.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/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "content/public/common/socket_permission_request.h" #include "content/public/common/socket_permission_request.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_info.h" #include "net/proxy_resolution/proxy_info.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/c/pp_errors.h" #include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h" #include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h" #include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.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 content {
namespace {
bool LookUpProxyForURLCallback(
int render_process_host_id,
int render_frame_host_id,
const GURL& url,
network::mojom::ProxyLookupClientPtr 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 = BrowserContext::GetStoragePartition(
site_instance->GetBrowserContext(), site_instance);
storage_partition->GetNetworkContext()->LookUpProxyForURL(
url, std::move(proxy_lookup_client));
return true;
}
} // namespace
PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host, PepperNetworkProxyHost::PepperNetworkProxyHost(BrowserPpapiHostImpl* host,
PP_Instance instance, PP_Instance instance,
PP_Resource resource) PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource), : ResourceHost(host->GetPpapiHost(), instance, resource),
proxy_resolution_service_(nullptr), render_process_id_(0),
render_frame_id_(0),
is_allowed_(false), is_allowed_(false),
waiting_for_ui_thread_data_(true), waiting_for_ui_thread_data_(true),
weak_factory_(this) { weak_factory_(this) {
int render_process_id(0), render_frame_id(0); host->GetRenderFrameIDsForInstance(instance, &render_process_id_,
host->GetRenderFrameIDsForInstance( &render_frame_id_);
instance, &render_process_id, &render_frame_id);
BrowserThread::PostTaskAndReplyWithResult( BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::UI, BrowserThread::UI, FROM_HERE,
FROM_HERE, base::BindOnce(&GetUIThreadDataOnUIThread, render_process_id_,
base::Bind(&GetUIThreadDataOnUIThread, render_frame_id_, host->external_plugin()),
render_process_id, base::BindOnce(&PepperNetworkProxyHost::DidGetUIThreadData,
render_frame_id, weak_factory_.GetWeakPtr()));
host->external_plugin()),
base::Bind(&PepperNetworkProxyHost::DidGetUIThreadData,
weak_factory_.GetWeakPtr()));
} }
PepperNetworkProxyHost::~PepperNetworkProxyHost() = default; PepperNetworkProxyHost::~PepperNetworkProxyHost() = default;
...@@ -62,9 +83,6 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id, ...@@ -62,9 +83,6 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
bool is_external_plugin) { bool is_external_plugin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
PepperNetworkProxyHost::UIThreadData result; PepperNetworkProxyHost::UIThreadData result;
RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
if (rph)
result.context_getter = rph->GetStoragePartition()->GetURLRequestContext();
SocketPermissionRequest request( SocketPermissionRequest request(
content::SocketPermissionRequest::RESOLVE_PROXY, std::string(), 0); content::SocketPermissionRequest::RESOLVE_PROXY, std::string(), 0);
...@@ -80,16 +98,7 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id, ...@@ -80,16 +98,7 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
void PepperNetworkProxyHost::DidGetUIThreadData( void PepperNetworkProxyHost::DidGetUIThreadData(
const UIThreadData& ui_thread_data) { const UIThreadData& ui_thread_data) {
is_allowed_ = ui_thread_data.is_allowed; is_allowed_ = ui_thread_data.is_allowed;
if (ui_thread_data.context_getter.get() &&
ui_thread_data.context_getter->GetURLRequestContext()) {
proxy_resolution_service_ =
ui_thread_data.context_getter->GetURLRequestContext()->proxy_resolution_service();
}
waiting_for_ui_thread_data_ = false; waiting_for_ui_thread_data_ = false;
if (!proxy_resolution_service_) {
DLOG_IF(WARNING, proxy_resolution_service_)
<< "Failed to find a ProxyResolutionService for Pepper plugin.";
}
TryToSendUnsentRequests(); TryToSendUnsentRequests();
} }
...@@ -123,27 +132,23 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() { ...@@ -123,27 +132,23 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() {
while (!unsent_requests_.empty()) { while (!unsent_requests_.empty()) {
const UnsentRequest& request = unsent_requests_.front(); const UnsentRequest& request = unsent_requests_.front();
if (!proxy_resolution_service_) { if (!is_allowed_) {
SendFailureReply(PP_ERROR_FAILED, request.reply_context);
} else if (!is_allowed_) {
SendFailureReply(PP_ERROR_NOACCESS, request.reply_context); SendFailureReply(PP_ERROR_NOACCESS, request.reply_context);
} else { } else {
// Everything looks valid, so try to resolve the proxy. // Everything looks valid, so try to resolve the proxy.
net::ProxyInfo* proxy_info = new net::ProxyInfo; auto lookup_helper = std::make_unique<PepperProxyLookupHelper>();
std::unique_ptr<net::ProxyResolutionService::Request> pending_request; PepperProxyLookupHelper::LookUpProxyForURLCallback
base::Callback<void(int)> callback = look_up_proxy_for_url_callback = base::BindOnce(
base::Bind(&PepperNetworkProxyHost::OnResolveProxyCompleted, &LookUpProxyForURLCallback, render_process_id_, render_frame_id_);
weak_factory_.GetWeakPtr(), PepperProxyLookupHelper::LookUpCompleteCallback
request.reply_context, look_up_complete_callback =
base::Owned(proxy_info)); base::BindOnce(&PepperNetworkProxyHost::OnResolveProxyCompleted,
int result = proxy_resolution_service_->ResolveProxy( weak_factory_.GetWeakPtr(), request.reply_context,
request.url, std::string(), proxy_info, callback, &pending_request, lookup_helper.get());
nullptr, net::NetLogWithSource()); lookup_helper->Start(request.url,
pending_requests_.push(std::move(pending_request)); std::move(look_up_proxy_for_url_callback),
// If it was handled synchronously, we must run the callback now; std::move(look_up_complete_callback));
// proxy_resolution_service_ won't run it for us in this case. pending_requests_.insert(std::move(lookup_helper));
if (result != net::ERR_IO_PENDING)
std::move(callback).Run(result);
} }
unsent_requests_.pop(); unsent_requests_.pop();
} }
...@@ -151,20 +156,24 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() { ...@@ -151,20 +156,24 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() {
void PepperNetworkProxyHost::OnResolveProxyCompleted( void PepperNetworkProxyHost::OnResolveProxyCompleted(
ppapi::host::ReplyMessageContext context, ppapi::host::ReplyMessageContext context,
net::ProxyInfo* proxy_info, PepperProxyLookupHelper* pending_request,
int result) { base::Optional<net::ProxyInfo> proxy_info) {
pending_requests_.pop(); auto it = pending_requests_.find(pending_request);
DCHECK(it != pending_requests_.end());
if (result != net::OK) { pending_requests_.erase(it);
// Currently, the only proxy-specific error we could get is
// MANDATORY_PROXY_CONFIGURATION_FAILED. There's really no action a plugin std::string pac_string;
// can take in this case, so there's no need to distinguish it from other if (!proxy_info) {
// failures. // 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); context.params.set_result(PP_ERROR_FAILED);
} else {
pac_string = proxy_info->ToPacString();
} }
host()->SendReply(context, host()->SendReply(
PpapiPluginMsg_NetworkProxy_GetProxyForURLReply( context, PpapiPluginMsg_NetworkProxy_GetProxyForURLReply(pac_string));
proxy_info->ToPacString()));
} }
void PepperNetworkProxyHost::SendFailureReply( void PepperNetworkProxyHost::SendFailureReply(
......
...@@ -8,20 +8,22 @@ ...@@ -8,20 +8,22 @@
#include <stdint.h> #include <stdint.h>
#include <queue> #include <queue>
#include <set>
#include <string> #include <string>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/containers/queue.h" #include "base/containers/queue.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "ppapi/host/host_message_context.h" #include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h" #include "ppapi/host/resource_host.h"
#include "url/gurl.h"
namespace net { namespace net {
class ProxyInfo; class ProxyInfo;
class URLRequestContextGetter;
} }
namespace ppapi { namespace ppapi {
...@@ -33,6 +35,7 @@ struct ReplyMessageContext; ...@@ -33,6 +35,7 @@ struct ReplyMessageContext;
namespace content { namespace content {
class BrowserPpapiHostImpl; class BrowserPpapiHostImpl;
class PepperProxyLookupHelper;
// The host for PPB_NetworkProxy. This class lives on the IO thread. // The host for PPB_NetworkProxy. This class lives on the IO thread.
class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost { class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
...@@ -44,15 +47,14 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost { ...@@ -44,15 +47,14 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
~PepperNetworkProxyHost() override; ~PepperNetworkProxyHost() override;
private: private:
// We retrieve the appropriate URLRequestContextGetter and whether this API // We retrieve whether this API is allowed for the instance on the UI thread
// is allowed for the instance on the UI thread and pass those to // and pass it to DidGetUIThreadData, which sets allowed_.
// DidGetUIThreadData, which sets allowed_ and proxy_resolution_service_.
struct UIThreadData { struct UIThreadData {
UIThreadData(); UIThreadData();
UIThreadData(const UIThreadData& other); UIThreadData(const UIThreadData& other);
~UIThreadData(); ~UIThreadData();
bool is_allowed; bool is_allowed;
scoped_refptr<net::URLRequestContextGetter> context_getter;
}; };
static UIThreadData GetUIThreadDataOnUIThread(int render_process_id, static UIThreadData GetUIThreadDataOnUIThread(int render_process_id,
int render_frame_id, int render_frame_id,
...@@ -67,39 +69,38 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost { ...@@ -67,39 +69,38 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
int32_t OnMsgGetProxyForURL(ppapi::host::HostMessageContext* context, int32_t OnMsgGetProxyForURL(ppapi::host::HostMessageContext* context,
const std::string& url); const std::string& url);
// If we have a valid proxy_resolution_service_, send all messages in // Send all messages in |unsent_requests_|.
// unsent_requests_.
void TryToSendUnsentRequests(); void TryToSendUnsentRequests();
void OnResolveProxyCompleted(ppapi::host::ReplyMessageContext context, void OnResolveProxyCompleted(ppapi::host::ReplyMessageContext context,
net::ProxyInfo* proxy_info, PepperProxyLookupHelper* pending_request,
int result); base::Optional<net::ProxyInfo> proxy_info);
void SendFailureReply(int32_t error, void SendFailureReply(int32_t error,
ppapi::host::ReplyMessageContext context); ppapi::host::ReplyMessageContext context);
// The following two members are invalid until we get some information from // Used to find correct NetworkContext to perform proxy lookups.
// the UI thread. However, these are only ever set or accessed on the IO int render_process_id_;
// thread. int render_frame_id_;
net::ProxyResolutionService* proxy_resolution_service_;
// The following member is invalid until we get some information from the UI
// thread. However, it is only ever set or accessed on the IO thread.
bool is_allowed_; bool is_allowed_;
// True initially, but set to false once the values for // True initially, but set to false once is_allowed_ has been set.
// proxy_resolution_service_ and is_allowed_ have been set.
bool waiting_for_ui_thread_data_; bool waiting_for_ui_thread_data_;
// We have to get the URLRequestContextGetter from the UI thread before we // We have to get is_allowed_ from the UI thread before we can start a
// can retrieve proxy_resolution_service_. If we receive any calls for // request. If we receive any calls for GetProxyForURL before is_allowed_ is
// GetProxyForURL before proxy_resolution_service_ is available, we save them // available, we save them in unsent_requests_.
// in unsent_requests_.
struct UnsentRequest { struct UnsentRequest {
GURL url; GURL url;
ppapi::host::ReplyMessageContext reply_context; ppapi::host::ReplyMessageContext reply_context;
}; };
base::queue<UnsentRequest> unsent_requests_; base::queue<UnsentRequest> unsent_requests_;
// Requests awaiting a response from ProxyResolutionService. We need to store // Requests awaiting a response from the network service. We need to store
// these so that we can cancel them if we get destroyed. // these so that we can cancel them if we get destroyed.
base::queue<std::unique_ptr<net::ProxyResolutionService::Request>> std::set<std::unique_ptr<PepperProxyLookupHelper>, base::UniquePtrComparator>
pending_requests_; pending_requests_;
base::WeakPtrFactory<PepperNetworkProxyHost> weak_factory_; base::WeakPtrFactory<PepperNetworkProxyHost> weak_factory_;
......
// Copyright 2018 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_proxy_lookup_helper.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "url/gurl.h"
namespace content {
// Runs the proxy lookup on the UI thread. Created on the
// PepperProxyLookupHelper's thread, but then does all work on the UI thread,
// and is deleted there by a task posted by the PepperProxyLookupHelper.
class PepperProxyLookupHelper::UIThreadHelper
: public network::mojom::ProxyLookupClient {
public:
UIThreadHelper(const GURL& url,
LookUpProxyForURLCallback look_up_proxy_for_url_callback,
LookUpCompleteCallback look_up_complete_callback)
: binding_(this),
look_up_complete_callback_(std::move(look_up_complete_callback)),
callback_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&UIThreadHelper::StartLookup, base::Unretained(this),
url, std::move(look_up_proxy_for_url_callback)));
}
~UIThreadHelper() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
private:
void StartLookup(const GURL& url,
LookUpProxyForURLCallback look_up_proxy_for_url_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
network::mojom::ProxyLookupClientPtr proxy_lookup_client;
binding_.Bind(mojo::MakeRequest(&proxy_lookup_client));
binding_.set_connection_error_handler(
base::BindOnce(&UIThreadHelper::OnProxyLookupComplete,
base::Unretained(this), base::nullopt));
if (!std::move(look_up_proxy_for_url_callback)
.Run(url, std::move(proxy_lookup_client))) {
OnProxyLookupComplete(base::nullopt);
}
}
void OnProxyLookupComplete(
const base::Optional<net::ProxyInfo>& proxy_info) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
binding_.Close();
callback_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(look_up_complete_callback_), proxy_info));
}
mojo::Binding<network::mojom::ProxyLookupClient> binding_;
LookUpCompleteCallback look_up_complete_callback_;
scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
DISALLOW_COPY_AND_ASSIGN(UIThreadHelper);
};
PepperProxyLookupHelper::PepperProxyLookupHelper() : weak_factory_(this) {}
PepperProxyLookupHelper::~PepperProxyLookupHelper() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
std::move(ui_thread_helper_));
}
void PepperProxyLookupHelper::Start(
const GURL& url,
LookUpProxyForURLCallback look_up_proxy_for_url_callback,
LookUpCompleteCallback look_up_complete_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!look_up_complete_callback_);
DCHECK(!ui_thread_helper_);
look_up_complete_callback_ = std::move(look_up_complete_callback);
ui_thread_helper_ = std::make_unique<UIThreadHelper>(
url, std::move(look_up_proxy_for_url_callback),
base::BindOnce(&PepperProxyLookupHelper::OnProxyLookupComplete,
weak_factory_.GetWeakPtr()));
}
void PepperProxyLookupHelper::OnProxyLookupComplete(
base::Optional<net::ProxyInfo> proxy_info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(look_up_complete_callback_).Run(std::move(proxy_info));
}
} // namespace content
// Copyright 2018 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.
#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_PROXY_LOOKUP_HELPER_H_
#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_PROXY_LOOKUP_HELPER_H_
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "content/common/content_export.h"
#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
class GURL;
namespace net {
class ProxyInfo;
}
namespace content {
// Class that runs a single proxy resolution on the UI thread. Lives on the
// thread its created on, and uses a helper to run tasks off-thread. Can be
// destroyed at any time.
class CONTENT_EXPORT PepperProxyLookupHelper {
public:
// Callback to call LookUpProxyForURL. Called on the UI thread. Needed for
// testing. Returns false if unable to make the call, for whatever reason.
using LookUpProxyForURLCallback = base::OnceCallback<bool(
const GURL& url,
network::mojom::ProxyLookupClientPtr proxy_lookup_client)>;
// Callback to invoke when complete. Invoked on thread the
// PepperProxyLookupHelper was created on.
using LookUpCompleteCallback =
base::OnceCallback<void(base::Optional<net::ProxyInfo> proxy_info)>;
PepperProxyLookupHelper();
~PepperProxyLookupHelper();
// Starts a lookup for |url| on the UI thread. Invokes
// |look_up_proxy_for_url_callback| on the UI thread to start the lookup, and
// calls |look_up_complete_callback| on the thread Start() was called on when
// complete. May only be invoked once.
void Start(const GURL& url,
LookUpProxyForURLCallback look_up_proxy_for_url_callback,
LookUpCompleteCallback look_up_complete_callback);
private:
class UIThreadHelper;
void OnProxyLookupComplete(base::Optional<net::ProxyInfo> proxy_info);
LookUpCompleteCallback look_up_complete_callback_;
std::unique_ptr<UIThreadHelper> ui_thread_helper_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<PepperProxyLookupHelper> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PepperProxyLookupHelper);
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_PROXY_LOOKUP_HELPER_H_
// Copyright 2018 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_proxy_lookup_helper.h"
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/proxy_resolution/proxy_info.h"
#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
namespace {
constexpr char kTestURL[] = "http://foo/";
class PepperProxyLookupHelperTest : public testing::Test {
public:
PepperProxyLookupHelperTest() = default;
~PepperProxyLookupHelperTest() override = default;
// Initializes |lookup_helper_| on the IO thread, and starts it there. Returns
// once it has called into LookUpProxyForURLOnUIThread on the UI thread.
void StartLookup() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RunLoop run_loop;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&PepperProxyLookupHelperTest::StartLookupOnIOThread,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
EXPECT_TRUE(lookup_helper_);
if (!fail_to_start_request_)
EXPECT_TRUE(proxy_lookup_client_);
}
// Takes the |ProxyLookupClientPtr| passed by |lookup_helper_| to
// LookUpProxyForURLOnUIThread(). May only be called after |lookup_helper_|
// has successfully called into LookUpProxyForURLOnUIThread().
network::mojom::ProxyLookupClientPtr ClaimProxyLookupClient() {
EXPECT_TRUE(proxy_lookup_client_);
return std::move(proxy_lookup_client_);
}
void DestroyLookupHelper() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::RunLoop run_loop;
BrowserThread::PostTaskAndReply(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&PepperProxyLookupHelperTest::DestroyLookupHelperOnIOThread,
base::Unretained(this)),
run_loop.QuitClosure());
run_loop.Run();
}
// Waits for |lookup_helper_| to call into OnLookupCompleteOnIOThread(),
// signally proxy lookup completion.
void WaitForLookupCompletion() {
EXPECT_TRUE(lookup_helper_);
lookup_complete_run_loop_.Run();
}
// Get the proxy information passed into OnLookupCompleteOnIOThread().
const base::Optional<net::ProxyInfo>& proxy_info() const {
return proxy_info_;
}
// Setting this to true will make LookUpProxyForURLOnUIThread, the callback
// invoked to start looking up the proxy, return false.
void set_fail_to_start_request(bool fail_to_start_request) {
fail_to_start_request_ = fail_to_start_request;
}
private:
// Must be called on the IO thread. Initializes |lookup_helper_| and starts a
// proxy lookup. Invokes |closure| on the UI thread once the |lookup_helper_|
// has invoked LookUpProxyForURLOnUIThread on the UI thread.
void StartLookupOnIOThread(base::OnceClosure closure) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!lookup_helper_);
lookup_helper_ = std::make_unique<PepperProxyLookupHelper>();
lookup_helper_->Start(
GURL(kTestURL),
base::BindOnce(
&PepperProxyLookupHelperTest::LookUpProxyForURLOnUIThread,
base::Unretained(this), std::move(closure)),
base::BindOnce(&PepperProxyLookupHelperTest::OnLookupCompleteOnIOThread,
base::Unretained(this)));
}
// Callback passed to |lookup_helper_| to start the proxy lookup.
bool LookUpProxyForURLOnUIThread(
base::OnceClosure closure,
const GURL& url,
network::mojom::ProxyLookupClientPtr proxy_lookup_client) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::move(closure).Run();
if (fail_to_start_request_)
return false;
EXPECT_EQ(GURL(kTestURL), url);
proxy_lookup_client_ = std::move(proxy_lookup_client);
return true;
}
// Invoked by |lookup_helper_| on the IO thread once the proxy lookup has
// completed.
void OnLookupCompleteOnIOThread(base::Optional<net::ProxyInfo> proxy_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
proxy_info_ = std::move(proxy_info);
lookup_helper_.reset();
lookup_complete_run_loop_.Quit();
}
void DestroyLookupHelperOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
lookup_helper_.reset();
}
TestBrowserThreadBundle test_browser_thread_bundle_;
bool fail_to_start_request_ = false;
std::unique_ptr<PepperProxyLookupHelper> lookup_helper_;
base::Optional<net::ProxyInfo> proxy_info_;
network::mojom::ProxyLookupClientPtr proxy_lookup_client_;
base::RunLoop lookup_complete_run_loop_;
};
TEST_F(PepperProxyLookupHelperTest, Success) {
StartLookup();
net::ProxyInfo proxy_info_response;
proxy_info_response.UseNamedProxy("result:80");
ClaimProxyLookupClient()->OnProxyLookupComplete(proxy_info_response);
WaitForLookupCompletion();
ASSERT_TRUE(proxy_info());
EXPECT_EQ("PROXY result:80", proxy_info()->ToPacString());
}
// Basic failure case - an error is passed to the PepperProxyLookupHelper
// through the ProxyLookupClient API.
TEST_F(PepperProxyLookupHelperTest, Failure) {
StartLookup();
ClaimProxyLookupClient()->OnProxyLookupComplete(base::nullopt);
WaitForLookupCompletion();
EXPECT_FALSE(proxy_info());
}
// The mojo pipe is closed before the PepperProxyLookupHelper's callback is
// invoked.
TEST_F(PepperProxyLookupHelperTest, PipeClosed) {
StartLookup();
ClaimProxyLookupClient().reset();
WaitForLookupCompletion();
EXPECT_FALSE(proxy_info());
}
// The proxy lookup fails to start - instead, the callback to start the lookup
// returns false.
TEST_F(PepperProxyLookupHelperTest, FailToStartRequest) {
set_fail_to_start_request(true);
StartLookup();
WaitForLookupCompletion();
EXPECT_FALSE(proxy_info());
}
// Destroy the helper before it completes a lookup. Make sure it cancels the
// connection, and memory tools don't detect a leak.
TEST_F(PepperProxyLookupHelperTest, DestroyBeforeComplete) {
StartLookup();
base::RunLoop run_loop;
network::mojom::ProxyLookupClientPtr proxy_lookup_client =
ClaimProxyLookupClient();
proxy_lookup_client.set_connection_error_handler(run_loop.QuitClosure());
DestroyLookupHelper();
run_loop.Run();
}
} // namespace
} // namespace content
...@@ -1859,7 +1859,7 @@ void RenderProcessHostImpl::CreateMessageFilters() { ...@@ -1859,7 +1859,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(p2p_socket_dispatcher_host_.get()); AddFilter(p2p_socket_dispatcher_host_.get());
AddFilter(new TraceMessageFilter(GetID())); AddFilter(new TraceMessageFilter(GetID()));
AddFilter(new ResolveProxyMsgHelper(request_context.get())); AddFilter(new ResolveProxyMsgHelper(GetID()));
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context( scoped_refptr<ServiceWorkerContextWrapper> service_worker_context(
static_cast<ServiceWorkerContextWrapper*>( static_cast<ServiceWorkerContextWrapper*>(
......
...@@ -5,25 +5,33 @@ ...@@ -5,25 +5,33 @@
#include "content/browser/resolve_proxy_msg_helper.h" #include "content/browser/resolve_proxy_msg_helper.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "content/common/view_messages.h" #include "content/common/view_messages.h"
#include "net/base/net_errors.h" #include "content/public/browser/browser_thread.h"
#include "net/log/net_log_with_source.h" #include "content/public/browser/render_process_host.h"
#include "net/url_request/url_request_context.h" #include "content/public/browser/storage_partition.h"
#include "net/url_request/url_request_context_getter.h" #include "mojo/public/cpp/bindings/interface_request.h"
#include "net/proxy_resolution/proxy_info.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace content { namespace content {
ResolveProxyMsgHelper::ResolveProxyMsgHelper( ResolveProxyMsgHelper::ResolveProxyMsgHelper(int render_process_host_id)
net::URLRequestContextGetter* getter)
: BrowserMessageFilter(ViewMsgStart), : BrowserMessageFilter(ViewMsgStart),
context_getter_(getter), render_process_host_id_(render_process_host_id),
proxy_resolution_service_(nullptr) {} binding_(this) {}
ResolveProxyMsgHelper::ResolveProxyMsgHelper( void ResolveProxyMsgHelper::OnDestruct() const {
net::ProxyResolutionService* proxy_resolution_service) // Have to delete on the UI thread, since Mojo objects aren't threadsafe.
: BrowserMessageFilter(ViewMsgStart), proxy_resolution_service_(proxy_resolution_service) {} BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
}
void ResolveProxyMsgHelper::OverrideThreadForMessage(
const IPC::Message& message,
BrowserThread::ID* thread) {
if (message.type() == ViewHostMsg_ResolveProxy::ID)
*thread = BrowserThread::UI;
}
bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) { bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) {
bool handled = true; bool handled = true;
...@@ -36,26 +44,67 @@ bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) { ...@@ -36,26 +44,67 @@ bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message) {
void ResolveProxyMsgHelper::OnResolveProxy(const GURL& url, void ResolveProxyMsgHelper::OnResolveProxy(const GURL& url,
IPC::Message* reply_msg) { IPC::Message* reply_msg) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Enqueue the pending request. // Enqueue the pending request.
pending_requests_.push_back(PendingRequest(url, reply_msg)); pending_requests_.push_back(PendingRequest(url, reply_msg));
// If nothing is in progress, start. // If nothing is in progress, start.
if (pending_requests_.size() == 1) if (!binding_.is_bound()) {
DCHECK_EQ(1u, pending_requests_.size());
StartPendingRequest(); StartPendingRequest();
}
} }
ResolveProxyMsgHelper::~ResolveProxyMsgHelper() = default; ResolveProxyMsgHelper::~ResolveProxyMsgHelper() = default;
void ResolveProxyMsgHelper::OnResolveProxyCompleted(int result) { void ResolveProxyMsgHelper::StartPendingRequest() {
CHECK(!pending_requests_.empty()); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!binding_.is_bound());
DCHECK(!pending_requests_.empty());
// Start the request.
network::mojom::ProxyLookupClientPtr proxy_lookup_client;
binding_.Bind(mojo::MakeRequest(&proxy_lookup_client));
binding_.set_connection_error_handler(
base::BindOnce(&ResolveProxyMsgHelper::OnProxyLookupComplete,
base::Unretained(this), base::nullopt));
if (!SendRequestToNetworkService(pending_requests_.front().url,
std::move(proxy_lookup_client))) {
OnProxyLookupComplete(base::nullopt);
}
}
bool ResolveProxyMsgHelper::SendRequestToNetworkService(
const GURL& url,
network::mojom::ProxyLookupClientPtr proxy_lookup_client) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* render_process_host =
RenderProcessHost::FromID(render_process_host_id_);
// Fail the request if there's no such RenderProcessHost;
if (!render_process_host)
return false;
render_process_host->GetStoragePartition()
->GetNetworkContext()
->LookUpProxyForURL(url, std::move(proxy_lookup_client));
return true;
}
void ResolveProxyMsgHelper::OnProxyLookupComplete(
const base::Optional<net::ProxyInfo>& proxy_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!pending_requests_.empty());
binding_.Close();
// Clear the current (completed) request. // Clear the current (completed) request.
PendingRequest completed_req = std::move(pending_requests_.front()); PendingRequest completed_req = std::move(pending_requests_.front());
pending_requests_.pop_front(); pending_requests_.pop_front();
ViewHostMsg_ResolveProxy::WriteReplyParams(completed_req.reply_msg.get(), ViewHostMsg_ResolveProxy::WriteReplyParams(
result == net::OK, completed_req.reply_msg.get(), !!proxy_info,
proxy_info_.ToPacString()); proxy_info ? proxy_info->ToPacString() : std::string());
Send(completed_req.reply_msg.release()); Send(completed_req.reply_msg.release());
// Start the next request. // Start the next request.
...@@ -63,27 +112,6 @@ void ResolveProxyMsgHelper::OnResolveProxyCompleted(int result) { ...@@ -63,27 +112,6 @@ void ResolveProxyMsgHelper::OnResolveProxyCompleted(int result) {
StartPendingRequest(); StartPendingRequest();
} }
void ResolveProxyMsgHelper::StartPendingRequest() {
// Verify the request wasn't started yet.
DCHECK(nullptr == pending_requests_.front().request);
if (context_getter_.get()) {
proxy_resolution_service_ = context_getter_->GetURLRequestContext()->proxy_resolution_service();
context_getter_ = nullptr;
}
// Start the request.
int result = proxy_resolution_service_->ResolveProxy(
pending_requests_.front().url, std::string(), &proxy_info_,
base::BindOnce(&ResolveProxyMsgHelper::OnResolveProxyCompleted,
base::Unretained(this)),
&pending_requests_.front().request, nullptr, net::NetLogWithSource());
// Completed synchronously.
if (result != net::ERR_IO_PENDING)
OnResolveProxyCompleted(result);
}
ResolveProxyMsgHelper::PendingRequest::PendingRequest(const GURL& url, ResolveProxyMsgHelper::PendingRequest::PendingRequest(const GURL& url,
IPC::Message* reply_msg) IPC::Message* reply_msg)
: url(url), reply_msg(reply_msg) {} : url(url), reply_msg(reply_msg) {}
......
...@@ -8,21 +8,24 @@ ...@@ -8,21 +8,24 @@
#include <string> #include <string>
#include "base/containers/circular_deque.h" #include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h" #include "content/public/browser/browser_message_filter.h"
#include "net/base/completion_callback.h" #include "mojo/public/cpp/bindings/binding.h"
#include "net/proxy_resolution/proxy_resolution_service.h" #include "services/network/public/mojom/proxy_lookup_client.mojom.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace net { namespace net {
class URLRequestContextGetter; class ProxyInfo;
} }
namespace content { namespace content {
// Responds to ChildProcessHostMsg_ResolveProxy, kicking off a ProxyResolve // Responds to ChildProcessHostMsg_ResolveProxy, kicking off a proxy lookup
// request on the IO thread using the specified proxy service. Completion is // request on the UI thread using the specified proxy service. Completion is
// notified through the delegate. If multiple requests are started at the same // notified through the delegate. If multiple requests are started at the same
// time, they will run in FIFO order, with only 1 being outstanding at a time. // time, they will run in FIFO order, with only 1 being outstanding at a time.
// //
...@@ -30,15 +33,16 @@ namespace content { ...@@ -30,15 +33,16 @@ namespace content {
// outstanding proxy resolve requests with the proxy service. It also deletes // outstanding proxy resolve requests with the proxy service. It also deletes
// the stored IPC::Message pointers for pending requests. // the stored IPC::Message pointers for pending requests.
// //
// This object is expected to live on the IO thread. // This object does most of its work, and destroys itself, on the UI thread.
class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter { class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter,
network::mojom::ProxyLookupClient {
public: public:
explicit ResolveProxyMsgHelper(net::URLRequestContextGetter* getter); explicit ResolveProxyMsgHelper(int render_process_host_id);
// Constructor used by unittests.
explicit ResolveProxyMsgHelper(
net::ProxyResolutionService* proxy_resolution_service);
// BrowserMessageFilter implementation // BrowserMessageFilter implementation
void OnDestruct() const override;
void OverrideThreadForMessage(const IPC::Message& message,
BrowserThread::ID* thread) override;
bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message) override;
void OnResolveProxy(const GURL& url, IPC::Message* reply_msg); void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
...@@ -49,12 +53,22 @@ class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter { ...@@ -49,12 +53,22 @@ class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter {
~ResolveProxyMsgHelper() override; ~ResolveProxyMsgHelper() override;
private: private:
// Callback for the ProxyResolutionService (bound to |callback_|). // Used to destroy the |ResolveProxyMsgHelper| on the UI thread.
void OnResolveProxyCompleted(int result); friend class base::DeleteHelper<ResolveProxyMsgHelper>;
// Starts the first pending request. // Starts the first pending request.
void StartPendingRequest(); void StartPendingRequest();
// Virtual for testing. Returns false if unable to get a network service, due
// to the RenderProcessHost no longer existing.
virtual bool SendRequestToNetworkService(
const GURL& url,
network::mojom::ProxyLookupClientPtr proxy_lookup_client);
// network::mojom::ProxyLookupClient implementation.
void OnProxyLookupComplete(
const base::Optional<net::ProxyInfo>& proxy_info) override;
// A PendingRequest is a resolve request that is in progress, or queued. // A PendingRequest is a resolve request that is in progress, or queued.
struct PendingRequest { struct PendingRequest {
public: public:
...@@ -70,22 +84,20 @@ class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter { ...@@ -70,22 +84,20 @@ class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter {
// Data to pass back to the delegate on completion (we own it until then). // Data to pass back to the delegate on completion (we own it until then).
std::unique_ptr<IPC::Message> reply_msg; std::unique_ptr<IPC::Message> reply_msg;
// Handle for cancelling the current request if it has started (else NULL).
std::unique_ptr<net::ProxyResolutionService::Request> request;
private: private:
DISALLOW_COPY_AND_ASSIGN(PendingRequest); DISALLOW_COPY_AND_ASSIGN(PendingRequest);
}; };
// Info about the current outstanding proxy request. const int render_process_host_id_;
net::ProxyInfo proxy_info_;
// FIFO queue of pending requests. The first entry is always the current one. // FIFO queue of pending requests. The first entry is always the current one.
using PendingRequestList = base::circular_deque<PendingRequest>; using PendingRequestList = base::circular_deque<PendingRequest>;
PendingRequestList pending_requests_; PendingRequestList pending_requests_;
scoped_refptr<net::URLRequestContextGetter> context_getter_; // Binding for the currently in-progress request, if any.
net::ProxyResolutionService* proxy_resolution_service_; mojo::Binding<network::mojom::ProxyLookupClient> binding_;
DISALLOW_COPY_AND_ASSIGN(ResolveProxyMsgHelper);
}; };
} // namespace content } // namespace content
......
...@@ -1922,6 +1922,7 @@ test("content_unittests") { ...@@ -1922,6 +1922,7 @@ test("content_unittests") {
"../browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc", "../browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc",
"../browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc", "../browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc",
"../browser/renderer_host/pepper/pepper_printing_host_unittest.cc", "../browser/renderer_host/pepper/pepper_printing_host_unittest.cc",
"../browser/renderer_host/pepper/pepper_proxy_lookup_helper_unittest.cc",
"../browser/renderer_host/pepper/quota_reservation_unittest.cc", "../browser/renderer_host/pepper/quota_reservation_unittest.cc",
"../renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc", "../renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc",
"../renderer/media/pepper/video_track_to_pepper_adapter_unittest.cc", "../renderer/media/pepper/video_track_to_pepper_adapter_unittest.cc",
......
...@@ -64,6 +64,8 @@ component("network_service") { ...@@ -64,6 +64,8 @@ component("network_service") {
"network_usage_accumulator.h", "network_usage_accumulator.h",
"proxy_config_service_mojo.cc", "proxy_config_service_mojo.cc",
"proxy_config_service_mojo.h", "proxy_config_service_mojo.h",
"proxy_lookup_request.cc",
"proxy_lookup_request.h",
"proxy_resolving_client_socket.cc", "proxy_resolving_client_socket.cc",
"proxy_resolving_client_socket.h", "proxy_resolving_client_socket.h",
"proxy_resolving_client_socket_factory.cc", "proxy_resolving_client_socket_factory.cc",
......
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
#include "services/network/network_service.h" #include "services/network/network_service.h"
#include "services/network/network_service_network_delegate.h" #include "services/network/network_service_network_delegate.h"
#include "services/network/proxy_config_service_mojo.h" #include "services/network/proxy_config_service_mojo.h"
#include "services/network/proxy_lookup_request.h"
#include "services/network/proxy_resolving_socket_factory_mojo.h" #include "services/network/proxy_resolving_socket_factory_mojo.h"
#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h" #include "services/network/public/cpp/network_switches.h"
...@@ -498,6 +499,13 @@ void NetworkContext::GetRestrictedCookieManager( ...@@ -498,6 +499,13 @@ void NetworkContext::GetRestrictedCookieManager(
std::move(request)); std::move(request));
} }
void NetworkContext::OnProxyLookupComplete(
ProxyLookupRequest* proxy_lookup_request) {
auto it = proxy_lookup_requests_.find(proxy_lookup_request);
DCHECK(it != proxy_lookup_requests_.end());
proxy_lookup_requests_.erase(it);
}
void NetworkContext::DisableQuic() { void NetworkContext::DisableQuic() {
url_request_context_->http_transaction_factory()->GetSession()->DisableQuic(); url_request_context_->http_transaction_factory()->GetSession()->DisableQuic();
} }
...@@ -768,6 +776,18 @@ void NetworkContext::CreateWebSocket( ...@@ -768,6 +776,18 @@ void NetworkContext::CreateWebSocket(
#endif // !defined(OS_IOS) #endif // !defined(OS_IOS)
} }
void NetworkContext::LookUpProxyForURL(
const GURL& url,
mojom::ProxyLookupClientPtr proxy_lookup_client) {
DCHECK(proxy_lookup_client);
std::unique_ptr<ProxyLookupRequest> proxy_lookup_request(
std::make_unique<ProxyLookupRequest>(std::move(proxy_lookup_client),
this));
ProxyLookupRequest* proxy_lookup_request_ptr = proxy_lookup_request.get();
proxy_lookup_requests_.insert(std::move(proxy_lookup_request));
proxy_lookup_request_ptr->Start(url);
}
void NetworkContext::CreateNetLogExporter( void NetworkContext::CreateNetLogExporter(
mojom::NetLogExporterRequest request) { mojom::NetLogExporterRequest request) {
net_log_exporter_bindings_.AddBinding(std::make_unique<NetLogExporter>(this), net_log_exporter_bindings_.AddBinding(std::make_unique<NetLogExporter>(this),
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "services/network/http_cache_data_counter.h" #include "services/network/http_cache_data_counter.h"
#include "services/network/http_cache_data_remover.h" #include "services/network/http_cache_data_remover.h"
#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
#include "services/network/public/mojom/proxy_resolving_socket.mojom.h" #include "services/network/public/mojom/proxy_resolving_socket.mojom.h"
#include "services/network/public/mojom/restricted_cookie_manager.mojom.h" #include "services/network/public/mojom/restricted_cookie_manager.mojom.h"
#include "services/network/public/mojom/tcp_socket.mojom.h" #include "services/network/public/mojom/tcp_socket.mojom.h"
...@@ -53,6 +54,7 @@ namespace network { ...@@ -53,6 +54,7 @@ namespace network {
class CookieManager; class CookieManager;
class ExpectCTReporter; class ExpectCTReporter;
class NetworkService; class NetworkService;
class ProxyLookupRequest;
class ResourceScheduler; class ResourceScheduler;
class ResourceSchedulerClient; class ResourceSchedulerClient;
class URLRequestContextBuilderMojo; class URLRequestContextBuilderMojo;
...@@ -196,6 +198,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -196,6 +198,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
int32_t render_frame_id, int32_t render_frame_id,
const url::Origin& origin, const url::Origin& origin,
mojom::AuthenticationHandlerPtr auth_handler) override; mojom::AuthenticationHandlerPtr auth_handler) override;
void LookUpProxyForURL(
const GURL& url,
mojom::ProxyLookupClientPtr proxy_lookup_client) override;
void CreateNetLogExporter(mojom::NetLogExporterRequest request) override; void CreateNetLogExporter(mojom::NetLogExporterRequest request) override;
void AddHSTSForTesting(const std::string& host, void AddHSTSForTesting(const std::string& host,
base::Time expiry, base::Time expiry,
...@@ -210,6 +215,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -210,6 +215,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
bool privacy_mode_enabled) override; bool privacy_mode_enabled) override;
void ResetURLLoaderFactories() override; void ResetURLLoaderFactories() override;
// Destroys |request| when a proxy lookup completes.
void OnProxyLookupComplete(ProxyLookupRequest* proxy_lookup_request);
// Disables use of QUIC by the NetworkContext. // Disables use of QUIC by the NetworkContext.
void DisableQuic(); void DisableQuic();
...@@ -217,6 +225,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -217,6 +225,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// no open pipes. // no open pipes.
void DestroyURLLoaderFactory(cors::CORSURLLoaderFactory* url_loader_factory); void DestroyURLLoaderFactory(cors::CORSURLLoaderFactory* url_loader_factory);
size_t pending_proxy_lookup_requests_for_testing() const {
return proxy_lookup_requests_.size();
}
private: private:
class ContextNetworkDelegate; class ContextNetworkDelegate;
...@@ -275,8 +287,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -275,8 +287,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
std::unique_ptr<WebSocketFactory> websocket_factory_; std::unique_ptr<WebSocketFactory> websocket_factory_;
#endif // !defined(OS_IOS) #endif // !defined(OS_IOS)
// These must be below the URLRequestContext, so they're destroyed before it
// is.
std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_; std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_;
std::vector<std::unique_ptr<HttpCacheDataCounter>> http_cache_data_counters_; std::vector<std::unique_ptr<HttpCacheDataCounter>> http_cache_data_counters_;
std::set<std::unique_ptr<ProxyLookupRequest>, base::UniquePtrComparator>
proxy_lookup_requests_;
// This must be below |url_request_context_| so that the URLRequestContext // This must be below |url_request_context_| so that the URLRequestContext
// outlives all the URLLoaderFactories and URLLoaders that depend on it. // outlives all the URLLoaderFactories and URLLoaders that depend on it.
......
// Copyright 2018 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 "services/network/proxy_lookup_request.h"
#include <string>
#include "base/bind.h"
#include "base/optional.h"
#include "net/base/net_errors.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/log/net_log_with_source.h"
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
#include "url/gurl.h"
namespace network {
ProxyLookupRequest::ProxyLookupRequest(
mojom::ProxyLookupClientPtr proxy_lookup_client,
NetworkContext* network_context)
: network_context_(network_context),
proxy_lookup_client_(std::move(proxy_lookup_client)) {
DCHECK(proxy_lookup_client_);
}
ProxyLookupRequest::~ProxyLookupRequest() {
// |request_| should be non-null only when the network service is being torn
// down.
if (request_)
proxy_lookup_client_->OnProxyLookupComplete(base::nullopt);
}
void ProxyLookupRequest::Start(const GURL& url) {
proxy_lookup_client_.set_connection_error_handler(
base::BindOnce(&ProxyLookupRequest::DestroySelf, base::Unretained(this)));
net::ProxyDelegate* proxy_delegate = network_context_->url_request_context()
->http_transaction_factory()
->GetSession()
->context()
.proxy_delegate;
// TODO(mmenke): The NetLogWithSource() means nothing is logged. Fix that.
int result =
network_context_->url_request_context()
->proxy_resolution_service()
->ResolveProxy(url, std::string(), &proxy_info_,
base::BindOnce(&ProxyLookupRequest::OnResolveComplete,
base::Unretained(this)),
&request_, proxy_delegate, net::NetLogWithSource());
if (result != net::ERR_IO_PENDING)
OnResolveComplete(result);
}
void ProxyLookupRequest::OnResolveComplete(int result) {
proxy_lookup_client_->OnProxyLookupComplete(
result == net::OK ? base::Optional<net::ProxyInfo>(std::move(proxy_info_))
: base::nullopt);
DestroySelf();
}
void ProxyLookupRequest::DestroySelf() {
request_.reset();
network_context_->OnProxyLookupComplete(this);
}
} // namespace network
// Copyright 2018 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.
#ifndef SERVICES_NETWORK_PROXY_LOOKUP_REQUEST_H_
#define SERVICES_NETWORK_PROXY_LOOKUP_REQUEST_H_
#include <stdint.h>
#include <memory>
#include "base/component_export.h"
#include "base/macros.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "services/network/public/mojom/proxy_lookup_client.mojom.h"
#include "url/gurl.h"
namespace network {
class NetworkContext;
// Single-use object to manage a proxy lookup.
class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyLookupRequest {
public:
ProxyLookupRequest(mojom::ProxyLookupClientPtr proxy_lookup_client,
NetworkContext* network_context);
~ProxyLookupRequest();
// Starts looking up what proxy to use for |url|. On completion, will inform
// both the ProxyLookupClient and the NetworkContext that it has completed.
// On synchronous completion, will inform the NetworkContext of completion
// re-entrantly. If destroyed before the lookup completes, informs the client
// that the lookup was aborted.
void Start(const GURL& url);
private:
void OnResolveComplete(int result);
// Cancels |request_| and tells |network_context_| to delete |this|.
void DestroySelf();
NetworkContext* const network_context_;
mojom::ProxyLookupClientPtr proxy_lookup_client_;
net::ProxyInfo proxy_info_;
std::unique_ptr<net::ProxyResolutionService::Request> request_;
DISALLOW_COPY_AND_ASSIGN(ProxyLookupRequest);
};
} // namespace network
#endif // SERVICES_NETWORK_PROXY_LOOKUP_REQUEST_H_
...@@ -88,6 +88,7 @@ mojom("mojom") { ...@@ -88,6 +88,7 @@ mojom("mojom") {
"network_types.mojom", "network_types.mojom",
"proxy_config.mojom", "proxy_config.mojom",
"proxy_config_with_annotation.mojom", "proxy_config_with_annotation.mojom",
"proxy_lookup_client.mojom",
"proxy_resolving_socket.mojom", "proxy_resolving_socket.mojom",
"request_context_frame_type.mojom", "request_context_frame_type.mojom",
"restricted_cookie_manager.mojom", "restricted_cookie_manager.mojom",
......
...@@ -16,6 +16,7 @@ import "services/network/public/mojom/ct_log_info.mojom"; ...@@ -16,6 +16,7 @@ import "services/network/public/mojom/ct_log_info.mojom";
import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom"; import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom";
import "services/network/public/mojom/proxy_config.mojom"; import "services/network/public/mojom/proxy_config.mojom";
import "services/network/public/mojom/proxy_config_with_annotation.mojom"; import "services/network/public/mojom/proxy_config_with_annotation.mojom";
import "services/network/public/mojom/proxy_lookup_client.mojom";
import "services/network/public/mojom/proxy_resolving_socket.mojom"; import "services/network/public/mojom/proxy_resolving_socket.mojom";
import "services/network/public/mojom/restricted_cookie_manager.mojom"; import "services/network/public/mojom/restricted_cookie_manager.mojom";
import "services/network/public/mojom/ssl_config.mojom"; import "services/network/public/mojom/ssl_config.mojom";
...@@ -507,6 +508,10 @@ interface NetworkContext { ...@@ -507,6 +508,10 @@ interface NetworkContext {
url.mojom.Origin origin, url.mojom.Origin origin,
AuthenticationHandler? auth_handler); AuthenticationHandler? auth_handler);
// Looks up what proxy to use for a particular URL.
LookUpProxyForURL(url.mojom.Url url,
ProxyLookupClient proxy_lookup_client);
// Create a NetLogExporter, which helps export NetLog to an existing file. // Create a NetLogExporter, which helps export NetLog to an existing file.
// Note that the log is generally global, including all NetworkContexts // Note that the log is generally global, including all NetworkContexts
// managed by the same NetworkService. The particular NetworkContext this is // managed by the same NetworkService. The particular NetworkContext this is
......
// Copyright 2018 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.
module network.mojom;
import "url/mojom/url.mojom";
import "services/proxy_resolver/public/mojom/proxy_resolver.mojom";
// Interface for getting the result of a proxy lookup from a NetworkContext.
// Not to be confused with ProxyResolverRequestClient, which is the interface
// between the ProxyResolver service, which executes PAC scripts, and the
// NetworkService.
//
// Closing the ProxyLookUpClient pipe before the request is complete will cancel
// the proxy lookup.
interface ProxyLookupClient {
// Called with the results of a proxy lookup when it is complete. Invoked only
// once per proxy lookup. |proxy_info| is null if the lookup failed, or if the
// NetworkContext was destroyed.
OnProxyLookupComplete(proxy_resolver.mojom.ProxyInfo? proxy_info);
};
...@@ -100,6 +100,9 @@ class TestNetworkContext : public mojom::NetworkContext { ...@@ -100,6 +100,9 @@ class TestNetworkContext : public mojom::NetworkContext {
int32_t render_frame_id, int32_t render_frame_id,
const url::Origin& origin, const url::Origin& origin,
mojom::AuthenticationHandlerPtr auth_handler) override {} mojom::AuthenticationHandlerPtr auth_handler) override {}
void LookUpProxyForURL(
const GURL& url,
::network::mojom::ProxyLookupClientPtr proxy_lookup_client) override {}
void CreateNetLogExporter(mojom::NetLogExporterRequest exporter) override {} void CreateNetLogExporter(mojom::NetLogExporterRequest exporter) override {}
void AddHSTSForTesting(const std::string& host, void AddHSTSForTesting(const std::string& host,
base::Time expiry, base::Time expiry,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment