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:
Cheng Zhao 2019-08-13 14:47:35 +09:00 committed by GitHub
parent 9713fa09e7
commit 69eac0d9d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 365 additions and 46 deletions

View file

@ -6,6 +6,7 @@
#include <utility>
#include "extensions/browser/extension_navigation_ui_data.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/base/completion_repeating_callback.h"
#include "net/http/http_util.h"
@ -57,7 +58,9 @@ ProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
network::URLLoaderCompletionStatus(net::ERR_ABORTED)));
}
ProxyingURLLoaderFactory::InProgressRequest::~InProgressRequest() {}
ProxyingURLLoaderFactory::InProgressRequest::~InProgressRequest() {
// TODO(zcbenz): Do cleanup here.
}
void ProxyingURLLoaderFactory::InProgressRequest::Restart() {
UpdateRequestInfo();
@ -65,13 +68,27 @@ void ProxyingURLLoaderFactory::InProgressRequest::Restart() {
}
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_ =
factory_->url_loader_header_client_binding_ &&
network_service_request_id_ != 0 &&
false /* HasExtraHeadersListenerForRequest */;
false /* TODO(zcbenz): HasExtraHeadersListenerForRequest */;
}
void ProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
DCHECK_EQ(info_->url, request_.url)
<< "UpdateRequestInfo must have been called first";
request_completed_ = false;
// If the header client will be used, we start the request immediately, and
@ -87,8 +104,8 @@ void ProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
weak_factory_.GetWeakPtr());
}
redirect_url_ = GURL();
// TODO(zcbenz): Call webRequest.onBeforeRequest.
int result = net::OK;
int result = factory_->web_request_api()->OnBeforeRequest(
&info_.value(), continuation, &redirect_url_);
if (result == net::ERR_BLOCKED_BY_CLIENT) {
// The request was cancelled synchronously. Dispatch an error notification
// and terminate the request.
@ -242,7 +259,7 @@ void ProxyingURLLoaderFactory::InProgressRequest::OnComplete(
}
target_client_->OnComplete(status);
// TODO(zcbenz): Call webRequest.onCompleted.
factory_->web_request_api()->OnCompleted(&info_.value(), status.error_code);
// Deletes |this|.
factory_->RemoveRequest(network_service_request_id_, request_id_);
@ -300,8 +317,8 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToBeforeSendHeaders(
auto continuation = base::BindRepeating(
&InProgressRequest::ContinueToSendHeaders, weak_factory_.GetWeakPtr());
// Note: In Electron onBeforeSendHeaders is called for all protocols.
// TODO(zcbenz): Call webRequest.onBeforeSendHeaders.
int result = net::OK;
int result = factory_->web_request_api()->OnBeforeSendHeaders(
&info_.value(), continuation, &request_.headers);
if (result == net::ERR_BLOCKED_BY_CLIENT) {
// The request was cancelled synchronously. Dispatch an error notification
@ -368,7 +385,7 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToSendHeaders(
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
// 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_)
ContinueToStartRequest(net::OK);
@ -477,9 +494,11 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToResponseStarted(
return;
}
info_->AddResponseInfoFromResourceResponse(current_response_);
proxied_client_binding_.ResumeIncomingMethodCallProcessing();
// TODO(zcbenz): Call webRequest.onResponseStarted.
factory_->web_request_api()->OnResponseStarted(&info_.value());
target_client_->OnReceiveResponse(current_response_);
}
@ -491,10 +510,13 @@ void ProxyingURLLoaderFactory::InProgressRequest::ContinueToBeforeRedirect(
return;
}
info_->AddResponseInfoFromResourceResponse(current_response_);
if (proxied_client_binding_.is_bound())
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_);
request_.url = redirect_info.new_url;
request_.method = redirect_info.new_method;
@ -586,8 +608,10 @@ void ProxyingURLLoaderFactory::InProgressRequest::
net::CompletionRepeatingCallback copyable_callback =
base::AdaptCallbackForRepeating(std::move(continuation));
// TODO(zcbenz): Call webRequest.onHeadersReceived.
int result = net::OK;
DCHECK(info_.has_value());
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) {
OnRequestError(network::URLLoaderCompletionStatus(result));
return;
@ -612,19 +636,24 @@ void ProxyingURLLoaderFactory::InProgressRequest::OnRequestError(
const network::URLLoaderCompletionStatus& status) {
if (!request_completed_) {
target_client_->OnComplete(status);
// TODO(zcbenz): Call webRequest.onErrorOccurred.
factory_->web_request_api()->OnErrorOccurred(&info_.value(),
status.error_code);
}
// TODO(zcbenz): Disassociate from factory.
delete this;
// Deletes |this|.
factory_->RemoveRequest(network_service_request_id_, request_id_);
}
ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
WebRequestAPI* web_request_api,
const HandlersMap& intercepted_handlers,
int render_process_id,
network::mojom::URLLoaderFactoryRequest loader_request,
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
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) {
target_factory_.Bind(std::move(target_factory_info));
target_factory_.set_connection_error_handler(base::BindOnce(

View file

@ -12,6 +12,7 @@
#include <vector>
#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_response.h"
#include "services/network/public/mojom/network_context.mojom.h"
@ -20,6 +21,39 @@
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:
// 1. handling intercepted protocols;
// 2. implementing webRequest module;
@ -108,6 +142,8 @@ class ProxyingURLLoaderFactory
mojo::Binding<network::mojom::URLLoader> proxied_loader_binding_;
network::mojom::URLLoaderClientPtr target_client_;
base::Optional<extensions::WebRequestInfo> info_;
network::ResourceResponseHead current_response_;
scoped_refptr<net::HttpResponseHeaders> override_headers_;
GURL redirect_url_;
@ -150,7 +186,9 @@ class ProxyingURLLoaderFactory
};
ProxyingURLLoaderFactory(
WebRequestAPI* web_request_api,
const HandlersMap& intercepted_handlers,
int render_process_id,
network::mojom::URLLoaderFactoryRequest loader_request,
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
network::mojom::TrustedURLLoaderHeaderClientRequest
@ -173,12 +211,17 @@ class ProxyingURLLoaderFactory
int32_t request_id,
network::mojom::TrustedHeaderClientRequest request) override;
WebRequestAPI* web_request_api() { return web_request_api_; }
private:
void OnTargetFactoryError();
void OnProxyBindingError();
void RemoveRequest(int32_t network_service_request_id, uint64_t request_id);
void MaybeDeleteThis();
// Passed from api::WebRequestNS.
WebRequestAPI* web_request_api_;
// This is passed from api::ProtocolNS.
//
// 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.
const HandlersMap& intercepted_handlers_;
const int render_process_id_;
mojo::BindingSet<network::mojom::URLLoaderFactory> proxy_bindings_;
network::mojom::URLLoaderFactoryPtr target_factory_;
mojo::Binding<network::mojom::TrustedURLLoaderHeaderClient>