Skip to content

Commit

Permalink
Issue 2351: Adding WebSocket proxy for Brave shields.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Efremov authored and bridiver committed Aug 26, 2019
1 parent 2574cc5 commit 28d2965
Show file tree
Hide file tree
Showing 11 changed files with 725 additions and 83 deletions.
11 changes: 11 additions & 0 deletions browser/brave_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "brave/browser/brave_browser_process_impl.h"
#include "brave/browser/extensions/brave_tor_client_updater.h"
#include "brave/browser/net/brave_proxying_url_loader_factory.h"
#include "brave/browser/net/brave_proxying_web_socket.h"
#include "brave/browser/tor/buildflags.h"
#include "brave/common/pref_names.h"
#include "brave/common/webui_url_constants.h"
Expand Down Expand Up @@ -296,6 +297,16 @@ bool BraveContentBrowserClient::WillCreateURLLoaderFactory(
return use_proxy;
}

void BraveContentBrowserClient::WillCreateWebSocket(
content::RenderFrameHost* frame,
network::mojom::WebSocketRequest* request,
network::mojom::AuthenticationHandlerPtr* auth_handler,
network::mojom::TrustedHeaderClientPtr* header_client,
uint32_t* options) {
ChromeContentBrowserClient::WillCreateWebSocket(frame, request, auth_handler,
header_client, options);
BraveProxyingWebSocket::ProxyWebSocket(frame, request, auth_handler);
}

void BraveContentBrowserClient::MaybeHideReferrer(
content::BrowserContext* browser_context,
Expand Down
7 changes: 7 additions & 0 deletions browser/brave_content_browser_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ class BraveContentBrowserClient : public ChromeContentBrowserClient {
network::mojom::TrustedURLLoaderHeaderClientPtrInfo* header_client,
bool* bypass_redirect_checks) override;

void WillCreateWebSocket(
content::RenderFrameHost* frame,
network::mojom::WebSocketRequest* request,
network::mojom::AuthenticationHandlerPtr* auth_handler,
network::mojom::TrustedHeaderClientPtr* header_client,
uint32_t* options) override;

void MaybeHideReferrer(content::BrowserContext* browser_context,
const GURL& request_url,
const GURL& document_url,
Expand Down
4 changes: 4 additions & 0 deletions browser/net/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ source_set("net") {
"brave_profile_network_delegate.h",
"brave_proxying_url_loader_factory.cc",
"brave_proxying_url_loader_factory.h",
"brave_proxying_utils.cc",
"brave_proxying_utils.h",
"brave_proxying_web_socket.cc",
"brave_proxying_web_socket.h",
"brave_request_handler.cc",
"brave_request_handler.h",
"brave_site_hacks_network_delegate_helper.cc",
Expand Down
61 changes: 1 addition & 60 deletions browser/net/brave_proxying_url_loader_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "brave/components/brave_shields/browser/adblock_stub_response.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/resource_context.h"
#include "content/public/common/url_utils.h"
Expand All @@ -26,66 +27,6 @@

namespace {

// User data key for ResourceContextData.
const void* const kResourceContextUserDataKey = &kResourceContextUserDataKey;

class ResourceContextData : public base::SupportsUserData::Data {
public:
~ResourceContextData() override {}

static void StartProxying(
content::ResourceContext* resource_context,
int render_process_id,
int frame_tree_node_id,
network::mojom::URLLoaderFactoryRequest request,
network::mojom::URLLoaderFactoryPtrInfo target_factory) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

auto* self = static_cast<ResourceContextData*>(
resource_context->GetUserData(kResourceContextUserDataKey));
if (!self) {
self = new ResourceContextData();
resource_context->SetUserData(kResourceContextUserDataKey,
base::WrapUnique(self));
}

if (!self->request_handler_) {
self->request_handler_.reset(new BraveRequestHandler);
}

auto proxy = std::make_unique<BraveProxyingURLLoaderFactory>(
self->request_handler_.get(), resource_context, render_process_id,
frame_tree_node_id, std::move(request), std::move(target_factory),
self->request_id_generator_,
base::BindOnce(&ResourceContextData::RemoveProxy,
self->weak_factory_.GetWeakPtr()));

self->proxies_.emplace(std::move(proxy));
}

void RemoveProxy(BraveProxyingURLLoaderFactory* proxy) {
auto it = proxies_.find(proxy);
DCHECK(it != proxies_.end());
proxies_.erase(it);
}

private:
ResourceContextData()
: request_id_generator_(base::MakeRefCounted<RequestIDGenerator>()),
weak_factory_(this) {}

std::unique_ptr<BraveRequestHandler> request_handler_;
scoped_refptr<RequestIDGenerator> request_id_generator_;

std::set<std::unique_ptr<BraveProxyingURLLoaderFactory>,
base::UniquePtrComparator>
proxies_;

base::WeakPtrFactory<ResourceContextData> weak_factory_;

DISALLOW_COPY_AND_ASSIGN(ResourceContextData);
};

// Helper struct for crafting responses.
struct WriteData {
// Wek ref. |client| destroys itself in |OnComplete()|.
Expand Down
25 changes: 2 additions & 23 deletions browser/net/brave_proxying_url_loader_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@
#include "base/callback.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "brave/browser/net/brave_proxying_utils.h"
#include "brave/browser/net/url_context.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "net/base/completion_once_callback.h"
Expand All @@ -40,26 +39,6 @@ class RenderFrameHost;
class ResourceContext;
} // namespace content

class RequestIDGenerator
: public base::RefCountedThreadSafe<RequestIDGenerator> {
public:
RequestIDGenerator() = default;
int64_t Generate() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
return ++id_;
}

private:
friend class base::RefCountedThreadSafe<RequestIDGenerator>;
~RequestIDGenerator() {}

// Although this initialization can be done in a thread other than the IO
// thread, we expect at least one memory barrier before actually calling
// Generate in the IO thread, so we don't protect the variable with a lock.
int64_t id_ = 0;
DISALLOW_COPY_AND_ASSIGN(RequestIDGenerator);
};

// Cargoculted from WebRequestProxyingURLLoaderFactory and
// signin::ProxyingURLLoaderFactory
class BraveProxyingURLLoaderFactory
Expand Down Expand Up @@ -220,7 +199,7 @@ class BraveProxyingURLLoaderFactory

void MaybeRemoveProxy();

BraveRequestHandler* request_handler_;
BraveRequestHandler* const request_handler_;
content::ResourceContext* resource_context_;
const int render_process_id_;
const int frame_tree_node_id_;
Expand Down
102 changes: 102 additions & 0 deletions browser/net/brave_proxying_utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* Copyright 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "brave/browser/net/brave_proxying_utils.h"

#include <utility>

#include "brave/browser/net/brave_proxying_url_loader_factory.h"
#include "brave/browser/net/brave_proxying_web_socket.h"
#include "brave/browser/net/brave_request_handler.h"
#include "content/public/browser/resource_context.h"

// User data key for ResourceContextData.
const void* const kResourceContextUserDataKey = &kResourceContextUserDataKey;

ResourceContextData::ResourceContextData()
: request_id_generator_(base::MakeRefCounted<RequestIDGenerator>()),
weak_factory_(this) {}

ResourceContextData::~ResourceContextData() = default;

// static
void ResourceContextData::StartProxying(
content::ResourceContext* resource_context,
int render_process_id,
int frame_tree_node_id,
network::mojom::URLLoaderFactoryRequest request,
network::mojom::URLLoaderFactoryPtrInfo target_factory) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

auto* self = static_cast<ResourceContextData*>(
resource_context->GetUserData(kResourceContextUserDataKey));
if (!self) {
self = new ResourceContextData();
resource_context->SetUserData(kResourceContextUserDataKey,
base::WrapUnique(self));
}

if (!self->request_handler_) {
self->request_handler_.reset(new BraveRequestHandler);
}

auto proxy = std::make_unique<BraveProxyingURLLoaderFactory>(
self->request_handler_.get(), resource_context, render_process_id,
frame_tree_node_id, std::move(request), std::move(target_factory),
self->request_id_generator_,
base::BindOnce(&ResourceContextData::RemoveProxy,
self->weak_factory_.GetWeakPtr()));

self->proxies_.emplace(std::move(proxy));
}

// static
void ResourceContextData::StartProxyingWebSocket(
content::ResourceContext* resource_context,
int render_process_id,
int frame_id,
int frame_tree_node_id,
const url::Origin& origin,
network::mojom::WebSocketPtrInfo proxied_socket_ptr_info,
network::mojom::WebSocketRequest proxied_request) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

auto* self = static_cast<ResourceContextData*>(
resource_context->GetUserData(kResourceContextUserDataKey));
if (!self) {
self = new ResourceContextData();
resource_context->SetUserData(kResourceContextUserDataKey,
base::WrapUnique(self));
}

if (!self->request_handler_) {
self->request_handler_.reset(new BraveRequestHandler);
}

auto proxy = std::make_unique<BraveProxyingWebSocket>(
self->request_handler_.get(), resource_context, render_process_id,
frame_id, frame_tree_node_id, origin,
self->request_id_generator_,
network::mojom::WebSocketPtr(std::move(proxied_socket_ptr_info)),
std::move(proxied_request),
base::BindOnce(&ResourceContextData::RemoveProxyWebSocket,
self->weak_factory_.GetWeakPtr()));

self->websocket_proxies_.emplace(std::move(proxy));
}


void ResourceContextData::RemoveProxy(BraveProxyingURLLoaderFactory* proxy) {
auto it = proxies_.find(proxy);
DCHECK(it != proxies_.end());
proxies_.erase(it);
}

void ResourceContextData::RemoveProxyWebSocket(BraveProxyingWebSocket* proxy) {
auto it = websocket_proxies_.find(proxy);
DCHECK(it != websocket_proxies_.end());
websocket_proxies_.erase(it);
}

94 changes: 94 additions & 0 deletions browser/net/brave_proxying_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* Copyright 2019 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_BROWSER_NET_BRAVE_PROXYING_UTILS_H_
#define BRAVE_BROWSER_NET_BRAVE_PROXYING_UTILS_H_

#include <cstdint>
#include <memory>
#include <set>

#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/supports_user_data.h"
#include "content/public/browser/browser_thread.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/websocket.mojom.h"

class BraveProxyingURLLoaderFactory;
class BraveProxyingWebSocket;
class BraveRequestHandler;

namespace content {
class ResourceContext;
}

// Used for both URLLoaders and WebSocket proxies.
class RequestIDGenerator
: public base::RefCountedThreadSafe<RequestIDGenerator> {
public:
RequestIDGenerator() = default;
int64_t Generate() {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
return ++id_;
}

private:
friend class base::RefCountedThreadSafe<RequestIDGenerator>;
~RequestIDGenerator() {}

// Although this initialization can be done in a thread other than the IO
// thread, we expect at least one memory barrier before actually calling
// Generate in the IO thread, so we don't protect the variable with a lock.
int64_t id_ = 0;
DISALLOW_COPY_AND_ASSIGN(RequestIDGenerator);
};

// Owns proxying factories for URLLoaders and websocket proxies. There is
// one |ResourceContextData| per profile.
class ResourceContextData : public base::SupportsUserData::Data {
public:
~ResourceContextData() override;

static void StartProxying(
content::ResourceContext* resource_context,
int render_process_id,
int frame_tree_node_id,
network::mojom::URLLoaderFactoryRequest request,
network::mojom::URLLoaderFactoryPtrInfo target_factory);

static void StartProxyingWebSocket(
content::ResourceContext* resource_context,
int render_process_id,
int frame_id,
int frame_tree_node_id,
const url::Origin& origin,
network::mojom::WebSocketPtrInfo proxied_socket_ptr_info,
network::mojom::WebSocketRequest proxied_request);

void RemoveProxy(BraveProxyingURLLoaderFactory* proxy);
void RemoveProxyWebSocket(BraveProxyingWebSocket* proxy);

private:
ResourceContextData();

std::unique_ptr<BraveRequestHandler> request_handler_;
scoped_refptr<RequestIDGenerator> request_id_generator_;

std::set<std::unique_ptr<BraveProxyingURLLoaderFactory>,
base::UniquePtrComparator>
proxies_;

std::set<std::unique_ptr<BraveProxyingWebSocket>,
base::UniquePtrComparator>
websocket_proxies_;

base::WeakPtrFactory<ResourceContextData> weak_factory_;

DISALLOW_COPY_AND_ASSIGN(ResourceContextData);
};

#endif // BRAVE_BROWSER_NET_BRAVE_PROXYING_UTILS_H_
Loading

0 comments on commit 28d2965

Please sign in to comment.