Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make webRequest work with WebSocket (8-x-y) #22134

Merged
merged 1 commit into from Feb 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/api/web-request.md
Expand Up @@ -146,6 +146,7 @@ response are visible by the time this listener is fired.
* `timestamp` Double
* `statusLine` String
* `statusCode` Integer
* `requestHeaders` Record<string, string>
* `responseHeaders` Record<string, string[]> (optional)
* `callback` Function
* `headersReceivedResponse` Object
Expand Down Expand Up @@ -228,6 +229,7 @@ redirect is about to occur.
* `fromCache` Boolean
* `statusCode` Integer
* `statusLine` String
* `error` String

The `listener` will be called with `listener(details)` when a request is
completed.
Expand Down
3 changes: 3 additions & 0 deletions filenames.gni
Expand Up @@ -238,12 +238,15 @@ filenames = {
"shell/browser/net/node_stream_loader.h",
"shell/browser/net/proxying_url_loader_factory.cc",
"shell/browser/net/proxying_url_loader_factory.h",
"shell/browser/net/proxying_websocket.cc",
"shell/browser/net/proxying_websocket.h",
"shell/browser/net/resolve_proxy_helper.cc",
"shell/browser/net/resolve_proxy_helper.h",
"shell/browser/net/system_network_context_manager.cc",
"shell/browser/net/system_network_context_manager.h",
"shell/browser/net/url_pipe_loader.cc",
"shell/browser/net/url_pipe_loader.h",
"shell/browser/net/web_request_api_interface.h",
"shell/browser/network_hints_handler_impl.cc",
"shell/browser/network_hints_handler_impl.h",
"shell/browser/node_debugger.cc",
Expand Down
10 changes: 5 additions & 5 deletions shell/browser/api/electron_api_web_request_ns.h
Expand Up @@ -13,7 +13,7 @@
#include "gin/arguments.h"
#include "gin/handle.h"
#include "gin/wrappable.h"
#include "shell/browser/net/proxying_url_loader_factory.h"
#include "shell/browser/net/web_request_api_interface.h"

namespace content {
class BrowserContext;
Expand Down Expand Up @@ -50,10 +50,6 @@ class WebRequestNS : public gin::Wrappable<WebRequestNS>, public WebRequestAPI {
v8::Isolate* isolate) override;
const char* GetTypeName() override;

private:
WebRequestNS(v8::Isolate* isolate, content::BrowserContext* browser_context);
~WebRequestNS() override;

// WebRequestAPI:
bool HasListener() const override;
int OnBeforeRequest(extensions::WebRequestInfo* info,
Expand Down Expand Up @@ -87,6 +83,10 @@ class WebRequestNS : public gin::Wrappable<WebRequestNS>, public WebRequestAPI {
int net_error) override;
void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info) override;

private:
WebRequestNS(v8::Isolate* isolate, content::BrowserContext* browser_context);
~WebRequestNS() override;

enum SimpleEvent {
kOnSendHeaders,
kOnBeforeRedirect,
Expand Down
39 changes: 38 additions & 1 deletion shell/browser/electron_browser_client.cc
Expand Up @@ -72,6 +72,7 @@
#include "shell/browser/net/network_context_service.h"
#include "shell/browser/net/network_context_service_factory.h"
#include "shell/browser/net/proxying_url_loader_factory.h"
#include "shell/browser/net/proxying_websocket.h"
#include "shell/browser/net/system_network_context_manager.h"
#include "shell/browser/network_hints_handler_impl.h"
#include "shell/browser/notifications/notification_presenter.h"
Expand Down Expand Up @@ -985,6 +986,42 @@ void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
}
}

bool ElectronBrowserClient::WillInterceptWebSocket(
content::RenderFrameHost* frame) {
if (!frame)
return false;

v8::Isolate* isolate = v8::Isolate::GetCurrent();
auto* browser_context = frame->GetProcess()->GetBrowserContext();
auto web_request = api::WebRequestNS::FromOrCreate(isolate, browser_context);

// NOTE: Some unit test environments do not initialize
// BrowserContextKeyedAPI factories for e.g. WebRequest.
if (!web_request.get())
return false;

return web_request->HasListener();
}

void ElectronBrowserClient::CreateWebSocket(
content::RenderFrameHost* frame,
WebSocketFactory factory,
const GURL& url,
const GURL& site_for_cookies,
const base::Optional<std::string>& user_agent,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
auto* browser_context = frame->GetProcess()->GetBrowserContext();
auto web_request = api::WebRequestNS::FromOrCreate(isolate, browser_context);
DCHECK(web_request.get());
ProxyingWebSocket::StartProxying(
web_request.get(), std::move(factory), url, site_for_cookies, user_agent,
std::move(handshake_client), true, frame->GetProcess()->GetID(),
frame->GetRoutingID(), frame->GetLastCommittedOrigin(), browser_context,
&next_id_);
}

bool ElectronBrowserClient::WillCreateURLLoaderFactory(
content::BrowserContext* browser_context,
content::RenderFrameHost* frame_host,
Expand Down Expand Up @@ -1026,7 +1063,7 @@ bool ElectronBrowserClient::WillCreateURLLoaderFactory(

new ProxyingURLLoaderFactory(
web_request.get(), protocol->intercept_handlers(), browser_context,
render_process_id, std::move(navigation_ui_data),
render_process_id, &next_id_, std::move(navigation_ui_data),
std::move(navigation_id), std::move(proxied_receiver),
std::move(target_factory_remote), std::move(header_client_receiver),
type);
Expand Down
13 changes: 13 additions & 0 deletions shell/browser/electron_browser_client.h
Expand Up @@ -174,6 +174,15 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
int render_process_id,
int render_frame_id,
NonNetworkURLLoaderFactoryMap* factories) override;
void CreateWebSocket(
content::RenderFrameHost* frame,
WebSocketFactory factory,
const GURL& url,
const GURL& site_for_cookies,
const base::Optional<std::string>& user_agent,
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
handshake_client) override;
bool WillInterceptWebSocket(content::RenderFrameHost*) override;
bool WillCreateURLLoaderFactory(
content::BrowserContext* browser_context,
content::RenderFrameHost* frame,
Expand Down Expand Up @@ -285,6 +294,10 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool disable_process_restart_tricks_ = false;
bool disable_process_restart_tricks_is_default_value_ = true;

// Simple shared ID generator, used by ProxyingURLLoaderFactory and
// ProxyingWebSocket classes.
uint64_t next_id_ = 0;

DISALLOW_COPY_AND_ASSIGN(ElectronBrowserClient);
};

Expand Down
11 changes: 3 additions & 8 deletions shell/browser/net/proxying_url_loader_factory.cc
Expand Up @@ -19,13 +19,6 @@
#include "shell/common/options_switches.h"

namespace electron {

namespace {

int64_t g_request_id = 0;

} // namespace

ProxyingURLLoaderFactory::InProgressRequest::FollowRedirectParams::
FollowRedirectParams() = default;
ProxyingURLLoaderFactory::InProgressRequest::FollowRedirectParams::
Expand Down Expand Up @@ -675,6 +668,7 @@ ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
const HandlersMap& intercepted_handlers,
content::BrowserContext* browser_context,
int render_process_id,
uint64_t* request_id_generator,
std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data,
base::Optional<int64_t> navigation_id,
network::mojom::URLLoaderFactoryRequest loader_request,
Expand All @@ -686,6 +680,7 @@ ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
intercepted_handlers_(intercepted_handlers),
browser_context_(browser_context),
render_process_id_(render_process_id),
request_id_generator_(request_id_generator),
navigation_ui_data_(std::move(navigation_ui_data)),
navigation_id_(std::move(navigation_id)),
loader_factory_type_(loader_factory_type) {
Expand Down Expand Up @@ -763,7 +758,7 @@ void ProxyingURLLoaderFactory::CreateLoaderAndStart(
// per-BrowserContext so extensions can make sense of it. Note that
// |network_service_request_id_| by contrast is not necessarily unique, so we
// don't use it for identity here.
const uint64_t web_request_id = ++g_request_id;
const uint64_t web_request_id = ++(*request_id_generator_);

// Notes: Chromium assumes that requests with zero-ID would never use the
// "extraHeaders" code path, however in Electron requests started from
Expand Down
46 changes: 3 additions & 43 deletions shell/browser/net/proxying_url_loader_factory.h
Expand Up @@ -24,52 +24,10 @@
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "shell/browser/net/electron_url_loader_factory.h"
#include "shell/browser/net/web_request_api_interface.h"

namespace electron {

// Defines the interface for WebRequest API, implemented by api::WebRequestNS.
class WebRequestAPI {
public:
virtual ~WebRequestAPI() {}

using BeforeSendHeadersCallback =
base::OnceCallback<void(const std::set<std::string>& removed_headers,
const std::set<std::string>& set_headers,
int error_code)>;

virtual bool HasListener() const = 0;
virtual int OnBeforeRequest(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
GURL* new_url) = 0;
virtual int OnBeforeSendHeaders(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
BeforeSendHeadersCallback callback,
net::HttpRequestHeaders* headers) = 0;
virtual int OnHeadersReceived(
extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
net::CompletionOnceCallback callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) = 0;
virtual void OnSendHeaders(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
const net::HttpRequestHeaders& headers) = 0;
virtual void OnBeforeRedirect(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
const GURL& new_location) = 0;
virtual void OnResponseStarted(extensions::WebRequestInfo* info,
const network::ResourceRequest& request) = 0;
virtual void OnErrorOccurred(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
int net_error) = 0;
virtual void OnCompleted(extensions::WebRequestInfo* info,
const network::ResourceRequest& request,
int net_error) = 0;
virtual void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info) = 0;
};

// This class is responsible for following tasks when NetworkService is enabled:
// 1. handling intercepted protocols;
// 2. implementing webRequest module;
Expand Down Expand Up @@ -210,6 +168,7 @@ class ProxyingURLLoaderFactory
const HandlersMap& intercepted_handlers,
content::BrowserContext* browser_context,
int render_process_id,
uint64_t* request_id_generator,
std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data,
base::Optional<int64_t> navigation_id,
network::mojom::URLLoaderFactoryRequest loader_request,
Expand Down Expand Up @@ -269,6 +228,7 @@ class ProxyingURLLoaderFactory

content::BrowserContext* const browser_context_;
const int render_process_id_;
uint64_t* request_id_generator_; // managed by AtomBrowserClient
std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data_;
base::Optional<int64_t> navigation_id_;
mojo::ReceiverSet<network::mojom::URLLoaderFactory> proxy_receivers_;
Expand Down