feat: migrate webRequest module to NetworkService (Part 5) (#19714)
* Pass WebRequest to ProxyingURLLoaderFactory * Call WebRequestAPI in InProgressRequest * Store the listeners * Pass the request and response * Add stub to handle the events * Use extensions::WebRequestInfo * Make sure webRequest is managed by Session * chore: make creation of WebRequestNS more clear * fix: check WebContents for service workers
This commit is contained in:
parent
9713fa09e7
commit
69eac0d9d2
7 changed files with 365 additions and 46 deletions
|
@ -206,8 +206,10 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||||
Session::~Session() {
|
Session::~Session() {
|
||||||
content::BrowserContext::GetDownloadManager(browser_context())
|
content::BrowserContext::GetDownloadManager(browser_context())
|
||||||
->RemoveObserver(this);
|
->RemoveObserver(this);
|
||||||
|
// TODO(zcbenz): Now since URLRequestContextGetter is gone, is this still
|
||||||
|
// needed?
|
||||||
|
// Refs https://github.com/electron/electron/pull/12305.
|
||||||
DestroyGlobalHandle(isolate(), cookies_);
|
DestroyGlobalHandle(isolate(), cookies_);
|
||||||
DestroyGlobalHandle(isolate(), web_request_);
|
|
||||||
DestroyGlobalHandle(isolate(), protocol_);
|
DestroyGlobalHandle(isolate(), protocol_);
|
||||||
DestroyGlobalHandle(isolate(), net_log_);
|
DestroyGlobalHandle(isolate(), net_log_);
|
||||||
g_sessions.erase(weak_map_id());
|
g_sessions.erase(weak_map_id());
|
||||||
|
|
|
@ -100,12 +100,14 @@ class Session : public mate::TrackableObject<Session>,
|
||||||
download::DownloadItem* item) override;
|
download::DownloadItem* item) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Cached object.
|
// Cached mate::Wrappable objects.
|
||||||
v8::Global<v8::Value> cookies_;
|
v8::Global<v8::Value> cookies_;
|
||||||
v8::Global<v8::Value> protocol_;
|
v8::Global<v8::Value> protocol_;
|
||||||
v8::Global<v8::Value> web_request_;
|
|
||||||
v8::Global<v8::Value> net_log_;
|
v8::Global<v8::Value> net_log_;
|
||||||
|
|
||||||
|
// Cached object.
|
||||||
|
v8::Global<v8::Value> web_request_;
|
||||||
|
|
||||||
// The client id to enable the network throttler.
|
// The client id to enable the network throttler.
|
||||||
base::UnguessableToken network_emulation_token_;
|
base::UnguessableToken network_emulation_token_;
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
|
|
||||||
#include "shell/browser/api/atom_api_web_request_ns.h"
|
#include "shell/browser/api/atom_api_web_request_ns.h"
|
||||||
|
|
||||||
#include <set>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "extensions/common/url_pattern.h"
|
|
||||||
#include "gin/converter.h"
|
#include "gin/converter.h"
|
||||||
#include "gin/dictionary.h"
|
#include "gin/dictionary.h"
|
||||||
#include "gin/object_template_builder.h"
|
#include "gin/object_template_builder.h"
|
||||||
|
#include "shell/browser/api/atom_api_session.h"
|
||||||
#include "shell/browser/atom_browser_context.h"
|
#include "shell/browser/atom_browser_context.h"
|
||||||
#include "shell/common/gin_converters/callback_converter_gin_adapter.h"
|
#include "shell/common/gin_converters/callback_converter_gin_adapter.h"
|
||||||
#include "shell/common/gin_converters/std_converter.h"
|
#include "shell/common/gin_converters/std_converter.h"
|
||||||
|
@ -37,12 +38,56 @@ namespace electron {
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char* kUserDataKey = "WebRequestNS";
|
||||||
|
|
||||||
|
// BrowserContext <=> WebRequestNS relationship.
|
||||||
|
struct UserData : public base::SupportsUserData::Data {
|
||||||
|
explicit UserData(WebRequestNS* data) : data(data) {}
|
||||||
|
WebRequestNS* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test whether the URL of |request| matches |patterns|.
|
||||||
|
bool MatchesFilterCondition(extensions::WebRequestInfo* request,
|
||||||
|
const std::set<URLPattern>& patterns) {
|
||||||
|
if (patterns.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (const auto& pattern : patterns) {
|
||||||
|
if (pattern.MatchesURL(request->url))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
gin::WrapperInfo WebRequestNS::kWrapperInfo = {gin::kEmbedderNativeGin};
|
gin::WrapperInfo WebRequestNS::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||||
|
|
||||||
WebRequestNS::WebRequestNS(v8::Isolate* isolate,
|
WebRequestNS::SimpleListenerInfo::SimpleListenerInfo(
|
||||||
AtomBrowserContext* browser_context) {}
|
std::set<URLPattern> patterns_,
|
||||||
|
SimpleListener listener_)
|
||||||
|
: url_patterns(std::move(patterns_)), listener(listener_) {}
|
||||||
|
WebRequestNS::SimpleListenerInfo::SimpleListenerInfo() = default;
|
||||||
|
WebRequestNS::SimpleListenerInfo::~SimpleListenerInfo() = default;
|
||||||
|
|
||||||
WebRequestNS::~WebRequestNS() = default;
|
WebRequestNS::ResponseListenerInfo::ResponseListenerInfo(
|
||||||
|
std::set<URLPattern> patterns_,
|
||||||
|
ResponseListener listener_)
|
||||||
|
: url_patterns(std::move(patterns_)), listener(listener_) {}
|
||||||
|
WebRequestNS::ResponseListenerInfo::ResponseListenerInfo() = default;
|
||||||
|
WebRequestNS::ResponseListenerInfo::~ResponseListenerInfo() = default;
|
||||||
|
|
||||||
|
WebRequestNS::WebRequestNS(v8::Isolate* isolate,
|
||||||
|
content::BrowserContext* browser_context)
|
||||||
|
: browser_context_(browser_context) {
|
||||||
|
browser_context_->SetUserData(kUserDataKey, std::make_unique<UserData>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRequestNS::~WebRequestNS() {
|
||||||
|
browser_context_->RemoveUserData(kUserDataKey);
|
||||||
|
}
|
||||||
|
|
||||||
gin::ObjectTemplateBuilder WebRequestNS::GetObjectTemplateBuilder(
|
gin::ObjectTemplateBuilder WebRequestNS::GetObjectTemplateBuilder(
|
||||||
v8::Isolate* isolate) {
|
v8::Isolate* isolate) {
|
||||||
|
@ -68,18 +113,70 @@ const char* WebRequestNS::GetTypeName() {
|
||||||
return "WebRequest";
|
return "WebRequest";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WebRequestNS::OnBeforeRequest(extensions::WebRequestInfo* request,
|
||||||
|
net::CompletionOnceCallback callback,
|
||||||
|
GURL* new_url) {
|
||||||
|
return HandleResponseEvent(kOnBeforeRequest, request, std::move(callback),
|
||||||
|
new_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRequestNS::OnBeforeSendHeaders(extensions::WebRequestInfo* request,
|
||||||
|
BeforeSendHeadersCallback callback,
|
||||||
|
net::HttpRequestHeaders* headers) {
|
||||||
|
// TODO(zcbenz): Figure out how to handle this generally.
|
||||||
|
return net::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebRequestNS::OnHeadersReceived(
|
||||||
|
extensions::WebRequestInfo* request,
|
||||||
|
net::CompletionOnceCallback callback,
|
||||||
|
const net::HttpResponseHeaders* original_response_headers,
|
||||||
|
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
|
||||||
|
GURL* allowed_unsafe_redirect_url) {
|
||||||
|
return HandleResponseEvent(kOnHeadersReceived, request, std::move(callback),
|
||||||
|
original_response_headers,
|
||||||
|
override_response_headers,
|
||||||
|
allowed_unsafe_redirect_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRequestNS::OnSendHeaders(extensions::WebRequestInfo* request,
|
||||||
|
const net::HttpRequestHeaders& headers) {
|
||||||
|
HandleSimpleEvent(kOnSendHeaders, request, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRequestNS::OnBeforeRedirect(extensions::WebRequestInfo* request,
|
||||||
|
const GURL& new_location) {
|
||||||
|
HandleSimpleEvent(kOnBeforeRedirect, request, new_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRequestNS::OnResponseStarted(extensions::WebRequestInfo* request) {
|
||||||
|
HandleSimpleEvent(kOnResponseStarted, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRequestNS::OnErrorOccurred(extensions::WebRequestInfo* request,
|
||||||
|
int net_error) {
|
||||||
|
HandleSimpleEvent(kOnErrorOccurred, request, net_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebRequestNS::OnCompleted(extensions::WebRequestInfo* request,
|
||||||
|
int net_error) {
|
||||||
|
HandleSimpleEvent(kOnCompleted, request, net_error);
|
||||||
|
}
|
||||||
|
|
||||||
template <WebRequestNS::SimpleEvent event>
|
template <WebRequestNS::SimpleEvent event>
|
||||||
void WebRequestNS::SetSimpleListener(gin::Arguments* args) {
|
void WebRequestNS::SetSimpleListener(gin::Arguments* args) {
|
||||||
SetListener<SimpleListener, SimpleEvent>(event, args);
|
SetListener<SimpleListener>(event, &simple_listeners_, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <WebRequestNS::ResponseEvent event>
|
template <WebRequestNS::ResponseEvent event>
|
||||||
void WebRequestNS::SetResponseListener(gin::Arguments* args) {
|
void WebRequestNS::SetResponseListener(gin::Arguments* args) {
|
||||||
SetListener<ResponseListener, ResponseEvent>(event, args);
|
SetListener<ResponseListener>(event, &response_listeners_, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Listener, typename Event>
|
template <typename Listener, typename Listeners, typename Event>
|
||||||
void WebRequestNS::SetListener(Event event, gin::Arguments* args) {
|
void WebRequestNS::SetListener(Event event,
|
||||||
|
Listeners* listeners,
|
||||||
|
gin::Arguments* args) {
|
||||||
// { urls }.
|
// { urls }.
|
||||||
std::set<URLPattern> patterns;
|
std::set<URLPattern> patterns;
|
||||||
gin::Dictionary dict(args->isolate());
|
gin::Dictionary dict(args->isolate());
|
||||||
|
@ -94,17 +191,76 @@ void WebRequestNS::SetListener(Event event, gin::Arguments* args) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(zcbenz): Actually set the listeners.
|
if (listener.is_null())
|
||||||
args->ThrowTypeError("This API is not implemented yet");
|
listeners->erase(event);
|
||||||
|
else
|
||||||
|
(*listeners)[event] = {std::move(patterns), std::move(listener)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void WebRequestNS::HandleSimpleEvent(SimpleEvent event,
|
||||||
|
extensions::WebRequestInfo* request,
|
||||||
|
Args... args) {
|
||||||
|
const auto& info = simple_listeners_[event];
|
||||||
|
if (!MatchesFilterCondition(request, info.url_patterns))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO(zcbenz): Invoke the listener.
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Out, typename... Args>
|
||||||
|
int WebRequestNS::HandleResponseEvent(ResponseEvent event,
|
||||||
|
extensions::WebRequestInfo* request,
|
||||||
|
net::CompletionOnceCallback callback,
|
||||||
|
Out out,
|
||||||
|
Args... args) {
|
||||||
|
const auto& info = response_listeners_[event];
|
||||||
|
if (!MatchesFilterCondition(request, info.url_patterns))
|
||||||
|
return net::OK;
|
||||||
|
|
||||||
|
// TODO(zcbenz): Invoke the listener.
|
||||||
|
return net::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
gin::Handle<WebRequestNS> WebRequestNS::FromOrCreate(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
content::BrowserContext* browser_context) {
|
||||||
|
gin::Handle<WebRequestNS> handle = From(isolate, browser_context);
|
||||||
|
if (handle.IsEmpty()) {
|
||||||
|
// Make sure the |Session| object has the |webRequest| property created.
|
||||||
|
v8::Local<v8::Value> web_request =
|
||||||
|
Session::CreateFrom(isolate,
|
||||||
|
static_cast<AtomBrowserContext*>(browser_context))
|
||||||
|
->WebRequest(isolate);
|
||||||
|
gin::ConvertFromV8(isolate, web_request, &handle);
|
||||||
|
}
|
||||||
|
DCHECK(!handle.IsEmpty());
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
gin::Handle<WebRequestNS> WebRequestNS::Create(
|
gin::Handle<WebRequestNS> WebRequestNS::Create(
|
||||||
v8::Isolate* isolate,
|
v8::Isolate* isolate,
|
||||||
AtomBrowserContext* browser_context) {
|
content::BrowserContext* browser_context) {
|
||||||
|
DCHECK(From(isolate, browser_context).IsEmpty())
|
||||||
|
<< "WebRequestNS already created";
|
||||||
return gin::CreateHandle(isolate, new WebRequestNS(isolate, browser_context));
|
return gin::CreateHandle(isolate, new WebRequestNS(isolate, browser_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
gin::Handle<WebRequestNS> WebRequestNS::From(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
content::BrowserContext* browser_context) {
|
||||||
|
if (!browser_context)
|
||||||
|
return gin::Handle<WebRequestNS>();
|
||||||
|
auto* user_data =
|
||||||
|
static_cast<UserData*>(browser_context->GetUserData(kUserDataKey));
|
||||||
|
if (!user_data)
|
||||||
|
return gin::Handle<WebRequestNS>();
|
||||||
|
return gin::CreateHandle(isolate, user_data->data);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -5,25 +5,47 @@
|
||||||
#ifndef SHELL_BROWSER_API_ATOM_API_WEB_REQUEST_NS_H_
|
#ifndef SHELL_BROWSER_API_ATOM_API_WEB_REQUEST_NS_H_
|
||||||
#define SHELL_BROWSER_API_ATOM_API_WEB_REQUEST_NS_H_
|
#define SHELL_BROWSER_API_ATOM_API_WEB_REQUEST_NS_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "base/values.h"
|
#include "base/values.h"
|
||||||
|
#include "extensions/common/url_pattern.h"
|
||||||
#include "gin/arguments.h"
|
#include "gin/arguments.h"
|
||||||
#include "gin/handle.h"
|
#include "gin/handle.h"
|
||||||
#include "gin/wrappable.h"
|
#include "gin/wrappable.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
#include "native_mate/handle.h"
|
#include "native_mate/handle.h"
|
||||||
|
#include "shell/browser/net/proxying_url_loader_factory.h"
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
class BrowserContext;
|
||||||
|
}
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
class AtomBrowserContext;
|
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
class WebRequestNS : public gin::Wrappable<WebRequestNS> {
|
class WebRequestNS : public gin::Wrappable<WebRequestNS>, public WebRequestAPI {
|
||||||
public:
|
public:
|
||||||
static gin::WrapperInfo kWrapperInfo;
|
static gin::WrapperInfo kWrapperInfo;
|
||||||
|
|
||||||
static gin::Handle<WebRequestNS> Create(v8::Isolate* isolate,
|
// Return the WebRequest object attached to |browser_context|, create if there
|
||||||
AtomBrowserContext* browser_context);
|
// is no one.
|
||||||
|
// Note that the lifetime of WebRequest object is managed by Session, instead
|
||||||
|
// of the caller.
|
||||||
|
static gin::Handle<WebRequestNS> FromOrCreate(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
content::BrowserContext* browser_context);
|
||||||
|
|
||||||
|
// Return a new WebRequest object, this should only be called by Session.
|
||||||
|
static gin::Handle<WebRequestNS> Create(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
content::BrowserContext* browser_context);
|
||||||
|
|
||||||
|
// Find the WebRequest object attached to |browser_context|.
|
||||||
|
static gin::Handle<WebRequestNS> From(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
content::BrowserContext* browser_context);
|
||||||
|
|
||||||
// gin::Wrappable:
|
// gin::Wrappable:
|
||||||
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||||
|
@ -31,9 +53,31 @@ class WebRequestNS : public gin::Wrappable<WebRequestNS> {
|
||||||
const char* GetTypeName() override;
|
const char* GetTypeName() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WebRequestNS(v8::Isolate* isolate, AtomBrowserContext* browser_context);
|
WebRequestNS(v8::Isolate* isolate, content::BrowserContext* browser_context);
|
||||||
~WebRequestNS() override;
|
~WebRequestNS() override;
|
||||||
|
|
||||||
|
// WebRequestAPI:
|
||||||
|
int OnBeforeRequest(extensions::WebRequestInfo* request,
|
||||||
|
net::CompletionOnceCallback callback,
|
||||||
|
GURL* new_url) override;
|
||||||
|
int OnBeforeSendHeaders(extensions::WebRequestInfo* request,
|
||||||
|
BeforeSendHeadersCallback callback,
|
||||||
|
net::HttpRequestHeaders* headers) override;
|
||||||
|
int OnHeadersReceived(
|
||||||
|
extensions::WebRequestInfo* request,
|
||||||
|
net::CompletionOnceCallback callback,
|
||||||
|
const net::HttpResponseHeaders* original_response_headers,
|
||||||
|
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
|
||||||
|
GURL* allowed_unsafe_redirect_url) override;
|
||||||
|
void OnSendHeaders(extensions::WebRequestInfo* request,
|
||||||
|
const net::HttpRequestHeaders& headers) override;
|
||||||
|
void OnBeforeRedirect(extensions::WebRequestInfo* request,
|
||||||
|
const GURL& new_location) override;
|
||||||
|
void OnResponseStarted(extensions::WebRequestInfo* request) override;
|
||||||
|
void OnErrorOccurred(extensions::WebRequestInfo* request,
|
||||||
|
int net_error) override;
|
||||||
|
void OnCompleted(extensions::WebRequestInfo* request, int net_error) override;
|
||||||
|
|
||||||
enum SimpleEvent {
|
enum SimpleEvent {
|
||||||
kOnSendHeaders,
|
kOnSendHeaders,
|
||||||
kOnBeforeRedirect,
|
kOnBeforeRedirect,
|
||||||
|
@ -56,8 +100,44 @@ class WebRequestNS : public gin::Wrappable<WebRequestNS> {
|
||||||
void SetSimpleListener(gin::Arguments* args);
|
void SetSimpleListener(gin::Arguments* args);
|
||||||
template <ResponseEvent event>
|
template <ResponseEvent event>
|
||||||
void SetResponseListener(gin::Arguments* args);
|
void SetResponseListener(gin::Arguments* args);
|
||||||
template <typename Listener, typename Event>
|
template <typename Listener, typename Listeners, typename Event>
|
||||||
void SetListener(Event event, gin::Arguments* args);
|
void SetListener(Event event, Listeners* listeners, gin::Arguments* args);
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void HandleSimpleEvent(SimpleEvent event,
|
||||||
|
extensions::WebRequestInfo* request,
|
||||||
|
Args... args);
|
||||||
|
template <typename Out, typename... Args>
|
||||||
|
int HandleResponseEvent(ResponseEvent event,
|
||||||
|
extensions::WebRequestInfo* request,
|
||||||
|
net::CompletionOnceCallback callback,
|
||||||
|
Out out,
|
||||||
|
Args... args);
|
||||||
|
|
||||||
|
struct SimpleListenerInfo {
|
||||||
|
std::set<URLPattern> url_patterns;
|
||||||
|
SimpleListener listener;
|
||||||
|
|
||||||
|
SimpleListenerInfo(std::set<URLPattern>, SimpleListener);
|
||||||
|
SimpleListenerInfo();
|
||||||
|
~SimpleListenerInfo();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResponseListenerInfo {
|
||||||
|
std::set<URLPattern> url_patterns;
|
||||||
|
ResponseListener listener;
|
||||||
|
|
||||||
|
ResponseListenerInfo(std::set<URLPattern>, ResponseListener);
|
||||||
|
ResponseListenerInfo();
|
||||||
|
~ResponseListenerInfo();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<SimpleEvent, SimpleListenerInfo> simple_listeners_;
|
||||||
|
std::map<ResponseEvent, ResponseListenerInfo> response_listeners_;
|
||||||
|
std::map<uint64_t, net::CompletionOnceCallback> callbacks_;
|
||||||
|
|
||||||
|
// Weak-ref, it manages us.
|
||||||
|
content::BrowserContext* browser_context_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "shell/browser/api/atom_api_app.h"
|
#include "shell/browser/api/atom_api_app.h"
|
||||||
#include "shell/browser/api/atom_api_protocol_ns.h"
|
#include "shell/browser/api/atom_api_protocol_ns.h"
|
||||||
#include "shell/browser/api/atom_api_web_contents.h"
|
#include "shell/browser/api/atom_api_web_contents.h"
|
||||||
|
#include "shell/browser/api/atom_api_web_request_ns.h"
|
||||||
#include "shell/browser/atom_browser_context.h"
|
#include "shell/browser/atom_browser_context.h"
|
||||||
#include "shell/browser/atom_browser_main_parts.h"
|
#include "shell/browser/atom_browser_main_parts.h"
|
||||||
#include "shell/browser/atom_navigation_throttle.h"
|
#include "shell/browser/atom_navigation_throttle.h"
|
||||||
|
@ -979,13 +980,17 @@ bool AtomBrowserClient::WillCreateURLLoaderFactory(
|
||||||
bool* bypass_redirect_checks) {
|
bool* bypass_redirect_checks) {
|
||||||
content::WebContents* web_contents =
|
content::WebContents* web_contents =
|
||||||
content::WebContents::FromRenderFrameHost(frame_host);
|
content::WebContents::FromRenderFrameHost(frame_host);
|
||||||
if (!web_contents) {
|
// For service workers there might be no WebContents.
|
||||||
|
if (!web_contents)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||||
api::ProtocolNS* protocol = api::ProtocolNS::FromWrappedClass(
|
api::ProtocolNS* protocol = api::ProtocolNS::FromWrappedClass(
|
||||||
v8::Isolate::GetCurrent(), web_contents->GetBrowserContext());
|
isolate, web_contents->GetBrowserContext());
|
||||||
if (!protocol)
|
DCHECK(protocol);
|
||||||
return false;
|
auto web_request = api::WebRequestNS::FromOrCreate(
|
||||||
|
isolate, web_contents->GetBrowserContext());
|
||||||
|
DCHECK(web_request.get());
|
||||||
|
|
||||||
auto proxied_receiver = std::move(*factory_receiver);
|
auto proxied_receiver = std::move(*factory_receiver);
|
||||||
network::mojom::URLLoaderFactoryPtrInfo target_factory_info;
|
network::mojom::URLLoaderFactoryPtrInfo target_factory_info;
|
||||||
|
@ -996,8 +1001,9 @@ bool AtomBrowserClient::WillCreateURLLoaderFactory(
|
||||||
header_client_request = mojo::MakeRequest(header_client);
|
header_client_request = mojo::MakeRequest(header_client);
|
||||||
|
|
||||||
new ProxyingURLLoaderFactory(
|
new ProxyingURLLoaderFactory(
|
||||||
protocol->intercept_handlers(), std::move(proxied_receiver),
|
web_request.get(), protocol->intercept_handlers(), render_process_id,
|
||||||
std::move(target_factory_info), std::move(header_client_request));
|
std::move(proxied_receiver), std::move(target_factory_info),
|
||||||
|
std::move(header_client_request));
|
||||||
|
|
||||||
if (bypass_redirect_checks)
|
if (bypass_redirect_checks)
|
||||||
*bypass_redirect_checks = true;
|
*bypass_redirect_checks = true;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "extensions/browser/extension_navigation_ui_data.h"
|
||||||
#include "mojo/public/cpp/bindings/binding.h"
|
#include "mojo/public/cpp/bindings/binding.h"
|
||||||
#include "net/base/completion_repeating_callback.h"
|
#include "net/base/completion_repeating_callback.h"
|
||||||
#include "net/http/http_util.h"
|
#include "net/http/http_util.h"
|
||||||
|
@ -57,7 +58,9 @@ ProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
|
||||||
network::URLLoaderCompletionStatus(net::ERR_ABORTED)));
|
network::URLLoaderCompletionStatus(net::ERR_ABORTED)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyingURLLoaderFactory::InProgressRequest::~InProgressRequest() {}
|
ProxyingURLLoaderFactory::InProgressRequest::~InProgressRequest() {
|
||||||
|
// TODO(zcbenz): Do cleanup here.
|
||||||
|
}
|
||||||
|
|
||||||
void ProxyingURLLoaderFactory::InProgressRequest::Restart() {
|
void ProxyingURLLoaderFactory::InProgressRequest::Restart() {
|
||||||
UpdateRequestInfo();
|
UpdateRequestInfo();
|
||||||
|
@ -65,13 +68,27 @@ void ProxyingURLLoaderFactory::InProgressRequest::Restart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyingURLLoaderFactory::InProgressRequest::UpdateRequestInfo() {
|
void ProxyingURLLoaderFactory::InProgressRequest::UpdateRequestInfo() {
|
||||||
|
// Derive a new WebRequestInfo value any time |Restart()| is called, because
|
||||||
|
// the details in |request_| may have changed e.g. if we've been redirected.
|
||||||
|
// |request_initiator| can be modified on redirects, but we keep the original
|
||||||
|
// for |initiator| in the event. See also
|
||||||
|
// https://developer.chrome.com/extensions/webRequest#event-onBeforeRequest.
|
||||||
|
network::ResourceRequest request_for_info = request_;
|
||||||
|
request_for_info.request_initiator = original_initiator_;
|
||||||
|
info_.emplace(extensions::WebRequestInfoInitParams(
|
||||||
|
request_id_, factory_->render_process_id_, request_.render_frame_id,
|
||||||
|
nullptr, routing_id_, request_for_info, false,
|
||||||
|
!(options_ & network::mojom::kURLLoadOptionSynchronous)));
|
||||||
|
|
||||||
current_request_uses_header_client_ =
|
current_request_uses_header_client_ =
|
||||||
factory_->url_loader_header_client_binding_ &&
|
factory_->url_loader_header_client_binding_ &&
|
||||||
network_service_request_id_ != 0 &&
|
network_service_request_id_ != 0 &&
|
||||||
false /* HasExtraHeadersListenerForRequest */;
|
false /* TODO(zcbenz): HasExtraHeadersListenerForRequest */;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
|
void ProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
|
||||||
|
DCHECK_EQ(info_->url, request_.url)
|
||||||
|
<< "UpdateRequestInfo must have been called first";
|
||||||
request_completed_ = false;
|
request_completed_ = false;
|
||||||
|
|
||||||
// If the header client will be used, we start the request immediately, and
|
// If the header client will be used, we start the request immediately, and
|
||||||
|
@ -87,8 +104,8 @@ void ProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
|
||||||
weak_factory_.GetWeakPtr());
|
weak_factory_.GetWeakPtr());
|
||||||
}
|
}
|
||||||
redirect_url_ = GURL();
|
redirect_url_ = GURL();
|
||||||
// TODO(zcbenz): Call webRequest.onBeforeRequest.
|
int result = factory_->web_request_api()->OnBeforeRequest(
|
||||||
int result = net::OK;
|
&info_.value(), continuation, &redirect_url_);
|
||||||
if (result == net::ERR_BLOCKED_BY_CLIENT) {
|
if (result == net::ERR_BLOCKED_BY_CLIENT) {
|
||||||
// The request was cancelled synchronously. Dispatch an error notification
|
// The request was cancelled synchronously. Dispatch an error notification
|
||||||
// and terminate the request.
|
// and terminate the request.
|
||||||
|
@ -242,7 +259,7 @@ void ProxyingURLLoaderFactory::InProgressRequest::OnComplete(
|
||||||
}
|
}
|
||||||
|
|
||||||
target_client_->OnComplete(status);
|
target_client_->OnComplete(status);
|
||||||
// TODO(zcbenz): Call webRequest.onCompleted.
|
factory_->web_request_api()->OnCompleted(&info_.value(), status.error_code);
|
||||||
|
|
||||||
// Deletes |this|.
|
// Deletes |this|.
|
||||||
factory_->RemoveRequest(network_service_request_id_, request_id_);
|
factory_->RemoveRequest(network_service_request_id_, request_id_);
|
||||||
|
@ -300,8 +317,8 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToBeforeSendHeaders(
|
||||||
auto continuation = base::BindRepeating(
|
auto continuation = base::BindRepeating(
|
||||||
&InProgressRequest::ContinueToSendHeaders, weak_factory_.GetWeakPtr());
|
&InProgressRequest::ContinueToSendHeaders, weak_factory_.GetWeakPtr());
|
||||||
// Note: In Electron onBeforeSendHeaders is called for all protocols.
|
// Note: In Electron onBeforeSendHeaders is called for all protocols.
|
||||||
// TODO(zcbenz): Call webRequest.onBeforeSendHeaders.
|
int result = factory_->web_request_api()->OnBeforeSendHeaders(
|
||||||
int result = net::OK;
|
&info_.value(), continuation, &request_.headers);
|
||||||
|
|
||||||
if (result == net::ERR_BLOCKED_BY_CLIENT) {
|
if (result == net::ERR_BLOCKED_BY_CLIENT) {
|
||||||
// The request was cancelled synchronously. Dispatch an error notification
|
// The request was cancelled synchronously. Dispatch an error notification
|
||||||
|
@ -368,7 +385,7 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToSendHeaders(
|
||||||
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
|
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
|
||||||
|
|
||||||
// Note: In Electron onSendHeaders is called for all protocols.
|
// Note: In Electron onSendHeaders is called for all protocols.
|
||||||
// TODO(zcbenz): Call webRequest.onSendHeaders.
|
factory_->web_request_api()->OnSendHeaders(&info_.value(), request_.headers);
|
||||||
|
|
||||||
if (!current_request_uses_header_client_)
|
if (!current_request_uses_header_client_)
|
||||||
ContinueToStartRequest(net::OK);
|
ContinueToStartRequest(net::OK);
|
||||||
|
@ -477,9 +494,11 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToResponseStarted(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info_->AddResponseInfoFromResourceResponse(current_response_);
|
||||||
|
|
||||||
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
|
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
|
||||||
|
|
||||||
// TODO(zcbenz): Call webRequest.onResponseStarted.
|
factory_->web_request_api()->OnResponseStarted(&info_.value());
|
||||||
target_client_->OnReceiveResponse(current_response_);
|
target_client_->OnReceiveResponse(current_response_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,10 +510,13 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToBeforeRedirect(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info_->AddResponseInfoFromResourceResponse(current_response_);
|
||||||
|
|
||||||
if (proxied_client_binding_.is_bound())
|
if (proxied_client_binding_.is_bound())
|
||||||
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
|
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
|
||||||
|
|
||||||
// TODO(zcbenz): Call WebRequest.onBeforeRedirect.
|
factory_->web_request_api()->OnBeforeRedirect(&info_.value(),
|
||||||
|
redirect_info.new_url);
|
||||||
target_client_->OnReceiveRedirect(redirect_info, current_response_);
|
target_client_->OnReceiveRedirect(redirect_info, current_response_);
|
||||||
request_.url = redirect_info.new_url;
|
request_.url = redirect_info.new_url;
|
||||||
request_.method = redirect_info.new_method;
|
request_.method = redirect_info.new_method;
|
||||||
|
@ -586,8 +608,10 @@ void ProxyingURLLoaderFactory::InProgressRequest::
|
||||||
|
|
||||||
net::CompletionRepeatingCallback copyable_callback =
|
net::CompletionRepeatingCallback copyable_callback =
|
||||||
base::AdaptCallbackForRepeating(std::move(continuation));
|
base::AdaptCallbackForRepeating(std::move(continuation));
|
||||||
// TODO(zcbenz): Call webRequest.onHeadersReceived.
|
DCHECK(info_.has_value());
|
||||||
int result = net::OK;
|
int result = factory_->web_request_api()->OnHeadersReceived(
|
||||||
|
&info_.value(), copyable_callback, current_response_.headers.get(),
|
||||||
|
&override_headers_, &redirect_url_);
|
||||||
if (result == net::ERR_BLOCKED_BY_CLIENT) {
|
if (result == net::ERR_BLOCKED_BY_CLIENT) {
|
||||||
OnRequestError(network::URLLoaderCompletionStatus(result));
|
OnRequestError(network::URLLoaderCompletionStatus(result));
|
||||||
return;
|
return;
|
||||||
|
@ -612,19 +636,24 @@ void ProxyingURLLoaderFactory::InProgressRequest::OnRequestError(
|
||||||
const network::URLLoaderCompletionStatus& status) {
|
const network::URLLoaderCompletionStatus& status) {
|
||||||
if (!request_completed_) {
|
if (!request_completed_) {
|
||||||
target_client_->OnComplete(status);
|
target_client_->OnComplete(status);
|
||||||
// TODO(zcbenz): Call webRequest.onErrorOccurred.
|
factory_->web_request_api()->OnErrorOccurred(&info_.value(),
|
||||||
|
status.error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(zcbenz): Disassociate from factory.
|
// Deletes |this|.
|
||||||
delete this;
|
factory_->RemoveRequest(network_service_request_id_, request_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
|
ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
|
||||||
|
WebRequestAPI* web_request_api,
|
||||||
const HandlersMap& intercepted_handlers,
|
const HandlersMap& intercepted_handlers,
|
||||||
|
int render_process_id,
|
||||||
network::mojom::URLLoaderFactoryRequest loader_request,
|
network::mojom::URLLoaderFactoryRequest loader_request,
|
||||||
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
|
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
|
||||||
network::mojom::TrustedURLLoaderHeaderClientRequest header_client_request)
|
network::mojom::TrustedURLLoaderHeaderClientRequest header_client_request)
|
||||||
: intercepted_handlers_(intercepted_handlers),
|
: web_request_api_(web_request_api),
|
||||||
|
intercepted_handlers_(intercepted_handlers),
|
||||||
|
render_process_id_(render_process_id),
|
||||||
url_loader_header_client_binding_(this) {
|
url_loader_header_client_binding_(this) {
|
||||||
target_factory_.Bind(std::move(target_factory_info));
|
target_factory_.Bind(std::move(target_factory_info));
|
||||||
target_factory_.set_connection_error_handler(base::BindOnce(
|
target_factory_.set_connection_error_handler(base::BindOnce(
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/optional.h"
|
#include "base/optional.h"
|
||||||
|
#include "extensions/browser/api/web_request/web_request_info.h"
|
||||||
#include "services/network/public/cpp/resource_request.h"
|
#include "services/network/public/cpp/resource_request.h"
|
||||||
#include "services/network/public/cpp/resource_response.h"
|
#include "services/network/public/cpp/resource_response.h"
|
||||||
#include "services/network/public/mojom/network_context.mojom.h"
|
#include "services/network/public/mojom/network_context.mojom.h"
|
||||||
|
@ -20,6 +21,39 @@
|
||||||
|
|
||||||
namespace electron {
|
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 int OnBeforeRequest(extensions::WebRequestInfo* request,
|
||||||
|
net::CompletionOnceCallback callback,
|
||||||
|
GURL* new_url) = 0;
|
||||||
|
virtual int OnBeforeSendHeaders(extensions::WebRequestInfo* request,
|
||||||
|
BeforeSendHeadersCallback callback,
|
||||||
|
net::HttpRequestHeaders* headers) = 0;
|
||||||
|
virtual int OnHeadersReceived(
|
||||||
|
extensions::WebRequestInfo* 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* request,
|
||||||
|
const net::HttpRequestHeaders& headers) = 0;
|
||||||
|
virtual void OnBeforeRedirect(extensions::WebRequestInfo* request,
|
||||||
|
const GURL& new_location) = 0;
|
||||||
|
virtual void OnResponseStarted(extensions::WebRequestInfo* request) = 0;
|
||||||
|
virtual void OnErrorOccurred(extensions::WebRequestInfo* request,
|
||||||
|
int net_error) = 0;
|
||||||
|
virtual void OnCompleted(extensions::WebRequestInfo* request,
|
||||||
|
int net_error) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// This class is responsible for following tasks when NetworkService is enabled:
|
// This class is responsible for following tasks when NetworkService is enabled:
|
||||||
// 1. handling intercepted protocols;
|
// 1. handling intercepted protocols;
|
||||||
// 2. implementing webRequest module;
|
// 2. implementing webRequest module;
|
||||||
|
@ -108,6 +142,8 @@ class ProxyingURLLoaderFactory
|
||||||
mojo::Binding<network::mojom::URLLoader> proxied_loader_binding_;
|
mojo::Binding<network::mojom::URLLoader> proxied_loader_binding_;
|
||||||
network::mojom::URLLoaderClientPtr target_client_;
|
network::mojom::URLLoaderClientPtr target_client_;
|
||||||
|
|
||||||
|
base::Optional<extensions::WebRequestInfo> info_;
|
||||||
|
|
||||||
network::ResourceResponseHead current_response_;
|
network::ResourceResponseHead current_response_;
|
||||||
scoped_refptr<net::HttpResponseHeaders> override_headers_;
|
scoped_refptr<net::HttpResponseHeaders> override_headers_;
|
||||||
GURL redirect_url_;
|
GURL redirect_url_;
|
||||||
|
@ -150,7 +186,9 @@ class ProxyingURLLoaderFactory
|
||||||
};
|
};
|
||||||
|
|
||||||
ProxyingURLLoaderFactory(
|
ProxyingURLLoaderFactory(
|
||||||
|
WebRequestAPI* web_request_api,
|
||||||
const HandlersMap& intercepted_handlers,
|
const HandlersMap& intercepted_handlers,
|
||||||
|
int render_process_id,
|
||||||
network::mojom::URLLoaderFactoryRequest loader_request,
|
network::mojom::URLLoaderFactoryRequest loader_request,
|
||||||
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
|
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
|
||||||
network::mojom::TrustedURLLoaderHeaderClientRequest
|
network::mojom::TrustedURLLoaderHeaderClientRequest
|
||||||
|
@ -173,12 +211,17 @@ class ProxyingURLLoaderFactory
|
||||||
int32_t request_id,
|
int32_t request_id,
|
||||||
network::mojom::TrustedHeaderClientRequest request) override;
|
network::mojom::TrustedHeaderClientRequest request) override;
|
||||||
|
|
||||||
|
WebRequestAPI* web_request_api() { return web_request_api_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnTargetFactoryError();
|
void OnTargetFactoryError();
|
||||||
void OnProxyBindingError();
|
void OnProxyBindingError();
|
||||||
void RemoveRequest(int32_t network_service_request_id, uint64_t request_id);
|
void RemoveRequest(int32_t network_service_request_id, uint64_t request_id);
|
||||||
void MaybeDeleteThis();
|
void MaybeDeleteThis();
|
||||||
|
|
||||||
|
// Passed from api::WebRequestNS.
|
||||||
|
WebRequestAPI* web_request_api_;
|
||||||
|
|
||||||
// This is passed from api::ProtocolNS.
|
// This is passed from api::ProtocolNS.
|
||||||
//
|
//
|
||||||
// The ProtocolNS instance lives through the lifetime of BrowserContenxt,
|
// The ProtocolNS instance lives through the lifetime of BrowserContenxt,
|
||||||
|
@ -188,6 +231,7 @@ class ProxyingURLLoaderFactory
|
||||||
// In this way we can avoid using code from api namespace in this file.
|
// In this way we can avoid using code from api namespace in this file.
|
||||||
const HandlersMap& intercepted_handlers_;
|
const HandlersMap& intercepted_handlers_;
|
||||||
|
|
||||||
|
const int render_process_id_;
|
||||||
mojo::BindingSet<network::mojom::URLLoaderFactory> proxy_bindings_;
|
mojo::BindingSet<network::mojom::URLLoaderFactory> proxy_bindings_;
|
||||||
network::mojom::URLLoaderFactoryPtr target_factory_;
|
network::mojom::URLLoaderFactoryPtr target_factory_;
|
||||||
mojo::Binding<network::mojom::TrustedURLLoaderHeaderClient>
|
mojo::Binding<network::mojom::TrustedURLLoaderHeaderClient>
|
||||||
|
|
Loading…
Reference in a new issue