blob: 14d234e6969754dfaddba56fc38ba985ee252a51 [file] [log] [blame]
// 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 "chrome/browser/signin/chrome_signin_url_loader_throttle.h"
#include "chrome/browser/signin/chrome_signin_helper.h"
#include "chrome/browser/signin/header_modification_delegate.h"
#include "components/signin/core/browser/signin_header_helper.h"
namespace signin {
class URLLoaderThrottle::ThrottleRequestAdapter : public ChromeRequestAdapter {
public:
ThrottleRequestAdapter(URLLoaderThrottle* throttle,
const net::HttpRequestHeaders& original_headers,
net::HttpRequestHeaders* modified_headers,
std::vector<std::string>* headers_to_remove)
: ChromeRequestAdapter(nullptr),
throttle_(throttle),
original_headers_(original_headers),
modified_headers_(modified_headers),
headers_to_remove_(headers_to_remove) {}
~ThrottleRequestAdapter() override = default;
// ChromeRequestAdapter
bool IsMainRequestContext(ProfileIOData* io_data) override {
// The <webview> check in URLLoaderThrottle::MaybeCreate means this is
// always true.
return true;
}
content::ResourceRequestInfo::WebContentsGetter GetWebContentsGetter()
const override {
return throttle_->web_contents_getter_;
}
content::ResourceType GetResourceType() const override {
return throttle_->request_resource_type_;
}
GURL GetReferrerOrigin() const override {
return throttle_->request_referrer_.GetOrigin();
}
void SetDestructionCallback(base::OnceClosure closure) override {
if (!throttle_->destruction_callback_)
throttle_->destruction_callback_ = std::move(closure);
}
// RequestAdapter
const GURL& GetUrl() override { return throttle_->request_url_; }
bool HasHeader(const std::string& name) override {
return (original_headers_.HasHeader(name) ||
modified_headers_->HasHeader(name)) &&
!base::ContainsValue(*headers_to_remove_, name);
}
void RemoveRequestHeaderByName(const std::string& name) override {
if (!base::ContainsValue(*headers_to_remove_, name))
headers_to_remove_->push_back(name);
}
void SetExtraHeaderByName(const std::string& name,
const std::string& value) override {
modified_headers_->SetHeader(name, value);
auto it =
std::find(headers_to_remove_->begin(), headers_to_remove_->end(), name);
if (it != headers_to_remove_->end())
headers_to_remove_->erase(it);
}
private:
URLLoaderThrottle* const throttle_;
const net::HttpRequestHeaders& original_headers_;
net::HttpRequestHeaders* const modified_headers_;
std::vector<std::string>* const headers_to_remove_;
DISALLOW_COPY_AND_ASSIGN(ThrottleRequestAdapter);
};
class URLLoaderThrottle::ThrottleResponseAdapter : public ResponseAdapter {
public:
ThrottleResponseAdapter(URLLoaderThrottle* throttle,
net::HttpResponseHeaders* headers)
: ResponseAdapter(nullptr), throttle_(throttle), headers_(headers) {}
~ThrottleResponseAdapter() override = default;
// ResponseAdapter
content::ResourceRequestInfo::WebContentsGetter GetWebContentsGetter()
const override {
return throttle_->web_contents_getter_;
}
bool IsMainFrame() const override { return throttle_->is_main_frame_; }
GURL GetOrigin() const override {
return throttle_->request_url_.GetOrigin();
}
const net::HttpResponseHeaders* GetHeaders() const override {
return headers_;
}
void RemoveHeader(const std::string& name) override {
headers_->RemoveHeader(name);
}
private:
URLLoaderThrottle* const throttle_;
net::HttpResponseHeaders* headers_;
DISALLOW_COPY_AND_ASSIGN(ThrottleResponseAdapter);
};
// static
std::unique_ptr<URLLoaderThrottle> URLLoaderThrottle::MaybeCreate(
std::unique_ptr<HeaderModificationDelegate> delegate,
content::NavigationUIData* navigation_ui_data,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter) {
if (!delegate->ShouldInterceptNavigation(navigation_ui_data))
return nullptr;
return base::WrapUnique(new URLLoaderThrottle(
std::move(delegate), std::move(web_contents_getter)));
}
URLLoaderThrottle::~URLLoaderThrottle() {
if (destruction_callback_)
std::move(destruction_callback_).Run();
}
void URLLoaderThrottle::WillStartRequest(network::ResourceRequest* request,
bool* defer) {
request_url_ = request->url;
request_referrer_ = request->referrer;
request_resource_type_ =
static_cast<content::ResourceType>(request->resource_type);
is_main_frame_ = request->is_main_frame;
net::HttpRequestHeaders modified_request_headers;
std::vector<std::string> to_be_removed_request_headers;
ThrottleRequestAdapter adapter(this, request->headers,
&modified_request_headers,
&to_be_removed_request_headers);
delegate_->ProcessRequest(&adapter, GURL() /* redirect_url */);
request->headers.MergeFrom(modified_request_headers);
for (const std::string& name : to_be_removed_request_headers)
request->headers.RemoveHeader(name);
// We need to keep a full copy of the request headers for later calls to
// FixAccountConsistencyRequestHeader. Perhaps this could be replaced with
// more specific per-request state.
request_headers_.CopyFrom(request->headers);
}
void URLLoaderThrottle::WillRedirectRequest(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head,
bool* /* defer */,
std::vector<std::string>* to_be_removed_request_headers,
net::HttpRequestHeaders* modified_request_headers) {
ThrottleRequestAdapter request_adapter(this, request_headers_,
modified_request_headers,
to_be_removed_request_headers);
delegate_->ProcessRequest(&request_adapter, redirect_info.new_url);
request_headers_.MergeFrom(*modified_request_headers);
for (const std::string& name : *to_be_removed_request_headers)
request_headers_.RemoveHeader(name);
// Modifications to |response_head.headers| will be passed to the
// URLLoaderClient even though |response_head| is const.
ThrottleResponseAdapter response_adapter(this, response_head.headers.get());
delegate_->ProcessResponse(&response_adapter, redirect_info.new_url);
request_url_ = redirect_info.new_url;
request_referrer_ = GURL(redirect_info.new_referrer);
}
void URLLoaderThrottle::WillProcessResponse(
const GURL& response_url,
network::ResourceResponseHead* response_head,
bool* defer) {
ThrottleResponseAdapter adapter(this, response_head->headers.get());
delegate_->ProcessResponse(&adapter, GURL() /* redirect_url */);
}
URLLoaderThrottle::URLLoaderThrottle(
std::unique_ptr<HeaderModificationDelegate> delegate,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter)
: delegate_(std::move(delegate)),
web_contents_getter_(std::move(web_contents_getter)) {}
} // namespace signin