| Index: content/browser/webui/url_data_manager_backend.cc
|
| diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc
|
| index ff6ccb12de770736b0fd74837e3a3561450040f9..861261846dd40bea82ad27dd6746a429dbb738f8 100644
|
| --- a/content/browser/webui/url_data_manager_backend.cc
|
| +++ b/content/browser/webui/url_data_manager_backend.cc
|
| @@ -45,7 +45,6 @@
|
| #include "net/base/net_errors.h"
|
| #include "net/filter/gzip_source_stream.h"
|
| #include "net/filter/source_stream.h"
|
| -#include "net/http/http_response_headers.h"
|
| #include "net/http/http_status_code.h"
|
| #include "net/log/net_log_util.h"
|
| #include "net/url_request/url_request.h"
|
| @@ -71,34 +70,6 @@ bool SchemeIsInSchemes(const std::string& scheme,
|
| return std::find(schemes.begin(), schemes.end(), scheme) != schemes.end();
|
| }
|
|
|
| -// Returns whether |url| passes some sanity checks and is a valid GURL.
|
| -bool CheckURLIsValid(const GURL& url) {
|
| - std::vector<std::string> additional_schemes;
|
| - DCHECK(url.SchemeIs(kChromeDevToolsScheme) || url.SchemeIs(kChromeUIScheme) ||
|
| - (GetContentClient()->browser()->GetAdditionalWebUISchemes(
|
| - &additional_schemes),
|
| - SchemeIsInSchemes(url.scheme(), additional_schemes)));
|
| -
|
| - if (!url.is_valid()) {
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// Parse |url| to get the path which will be used to resolve the request. The
|
| -// path is the remaining portion after the scheme and hostname.
|
| -void URLToRequestPath(const GURL& url, std::string* path) {
|
| - const std::string& spec = url.possibly_invalid_spec();
|
| - const url::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
|
| - // + 1 to skip the slash at the beginning of the path.
|
| - int offset = parsed.CountCharactersBefore(url::Parsed::PATH, false) + 1;
|
| -
|
| - if (offset < static_cast<int>(spec.size()))
|
| - path->assign(spec.substr(offset));
|
| -}
|
| -
|
| // Returns a value of 'Origin:' header for the |request| if the header is set.
|
| // Otherwise returns an empty string.
|
| std::string GetOriginHeaderValue(const net::URLRequest* request) {
|
| @@ -134,11 +105,9 @@ void CopyData(const scoped_refptr<net::IOBuffer>& buf,
|
| // calls back once the data is available.
|
| class URLRequestChromeJob : public net::URLRequestJob {
|
| public:
|
| - // |is_incognito| set when job is generated from an incognito profile.
|
| URLRequestChromeJob(net::URLRequest* request,
|
| net::NetworkDelegate* network_delegate,
|
| - URLDataManagerBackend* backend,
|
| - bool is_incognito);
|
| + URLDataManagerBackend* backend);
|
|
|
| // net::URLRequestJob implementation.
|
| void Start() override;
|
| @@ -155,58 +124,6 @@ class URLRequestChromeJob : public net::URLRequestJob {
|
| // for us. |bytes| may be null, indicating an error.
|
| void DataAvailable(base::RefCountedMemory* bytes);
|
|
|
| - // Returns a weak pointer to the job.
|
| - base::WeakPtr<URLRequestChromeJob> AsWeakPtr();
|
| -
|
| - void set_mime_type(const std::string& mime_type) {
|
| - mime_type_ = mime_type;
|
| - }
|
| -
|
| - void set_allow_caching(bool allow_caching) {
|
| - allow_caching_ = allow_caching;
|
| - }
|
| -
|
| - void set_add_content_security_policy(bool add_content_security_policy) {
|
| - add_content_security_policy_ = add_content_security_policy;
|
| - }
|
| -
|
| - void set_content_security_policy_object_source(
|
| - const std::string& data) {
|
| - content_security_policy_object_source_ = data;
|
| - }
|
| -
|
| - void set_content_security_policy_script_source(
|
| - const std::string& data) {
|
| - content_security_policy_script_source_ = data;
|
| - }
|
| -
|
| - void set_content_security_policy_child_source(
|
| - const std::string& data) {
|
| - content_security_policy_child_source_ = data;
|
| - }
|
| -
|
| - void set_content_security_policy_style_source(
|
| - const std::string& data) {
|
| - content_security_policy_style_source_ = data;
|
| - }
|
| -
|
| - void set_content_security_policy_image_source(
|
| - const std::string& data) {
|
| - content_security_policy_image_source_ = data;
|
| - }
|
| -
|
| - void set_deny_xframe_options(bool deny_xframe_options) {
|
| - deny_xframe_options_ = deny_xframe_options;
|
| - }
|
| -
|
| - void set_send_content_type_header(bool send_content_type_header) {
|
| - send_content_type_header_ = send_content_type_header;
|
| - }
|
| -
|
| - void set_access_control_allow_origin(const std::string& value) {
|
| - access_control_allow_origin_ = value;
|
| - }
|
| -
|
| void set_is_gzipped(bool is_gzipped) {
|
| is_gzipped_ = is_gzipped;
|
| }
|
| @@ -215,11 +132,6 @@ class URLRequestChromeJob : public net::URLRequestJob {
|
| replacements_ = replacements;
|
| }
|
|
|
| - // Returns true when job was generated from an incognito profile.
|
| - bool is_incognito() const {
|
| - return is_incognito_;
|
| - }
|
| -
|
| private:
|
| ~URLRequestChromeJob() override;
|
|
|
| @@ -255,32 +167,6 @@ class URLRequestChromeJob : public net::URLRequestJob {
|
| int pending_buf_size_;
|
| std::string mime_type_;
|
|
|
| - // If true, set a header in the response to prevent it from being cached.
|
| - bool allow_caching_;
|
| -
|
| - // If true, set the Content Security Policy (CSP) header.
|
| - bool add_content_security_policy_;
|
| -
|
| - // These are used with the CSP.
|
| - std::string content_security_policy_script_source_;
|
| - std::string content_security_policy_object_source_;
|
| - std::string content_security_policy_child_source_;
|
| - std::string content_security_policy_style_source_;
|
| - std::string content_security_policy_image_source_;
|
| -
|
| - // If true, sets the "X-Frame-Options: DENY" header.
|
| - bool deny_xframe_options_;
|
| -
|
| - // If true, sets the "Content-Type: <mime-type>" header.
|
| - bool send_content_type_header_;
|
| -
|
| - // If not empty, "Access-Control-Allow-Origin:" is set to the value of this
|
| - // string.
|
| - std::string access_control_allow_origin_;
|
| -
|
| - // True when job is generated from an incognito profile.
|
| - const bool is_incognito_;
|
| -
|
| // True when gzip encoding should be used. NOTE: this requires the original
|
| // resources in resources.pak use compress="gzip".
|
| bool is_gzipped_;
|
| @@ -298,17 +184,11 @@ class URLRequestChromeJob : public net::URLRequestJob {
|
|
|
| URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request,
|
| net::NetworkDelegate* network_delegate,
|
| - URLDataManagerBackend* backend,
|
| - bool is_incognito)
|
| + URLDataManagerBackend* backend)
|
| : net::URLRequestJob(request, network_delegate),
|
| data_offset_(0),
|
| data_available_status_(net::OK),
|
| pending_buf_size_(0),
|
| - allow_caching_(true),
|
| - add_content_security_policy_(true),
|
| - deny_xframe_options_(true),
|
| - send_content_type_header_(false),
|
| - is_incognito_(is_incognito),
|
| is_gzipped_(false),
|
| replacements_(nullptr),
|
| backend_(backend),
|
| @@ -359,43 +239,11 @@ bool URLRequestChromeJob::GetMimeType(std::string* mime_type) const {
|
|
|
| void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
|
| DCHECK(!info->headers.get());
|
| - // Set the headers so that requests serviced by ChromeURLDataManager return a
|
| - // status code of 200. Without this they return a 0, which makes the status
|
| - // indistiguishable from other error types. Instant relies on getting a 200.
|
| - info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK");
|
| -
|
| - // Determine the least-privileged content security policy header, if any,
|
| - // that is compatible with a given WebUI URL, and append it to the existing
|
| - // response headers.
|
| - if (add_content_security_policy_) {
|
| - std::string base = kChromeURLContentSecurityPolicyHeaderBase;
|
| - base.append(content_security_policy_script_source_);
|
| - base.append(content_security_policy_object_source_);
|
| - base.append(content_security_policy_child_source_);
|
| - base.append(content_security_policy_style_source_);
|
| - base.append(content_security_policy_image_source_);
|
| - info->headers->AddHeader(base);
|
| - }
|
| -
|
| - if (deny_xframe_options_)
|
| - info->headers->AddHeader(kChromeURLXFrameOptionsHeader);
|
| -
|
| - if (!allow_caching_)
|
| - info->headers->AddHeader("Cache-Control: no-cache");
|
| -
|
| - if (send_content_type_header_ && !mime_type_.empty()) {
|
| - std::string content_type =
|
| - base::StringPrintf("%s:%s", net::HttpRequestHeaders::kContentType,
|
| - mime_type_.c_str());
|
| - info->headers->AddHeader(content_type);
|
| - }
|
| -
|
| - if (!access_control_allow_origin_.empty()) {
|
| - info->headers->AddHeader("Access-Control-Allow-Origin: " +
|
| - access_control_allow_origin_);
|
| - info->headers->AddHeader("Vary: Origin");
|
| - }
|
| -
|
| + URLDataSourceImpl* source = backend_->GetDataSourceFromURL(request()->url());
|
| + std::string path;
|
| + URLDataManagerBackend::URLToRequestPath(request()->url(), &path);
|
| + info->headers = URLDataManagerBackend::GetHeaders(
|
| + source, path, GetOriginHeaderValue(request()));
|
| if (is_gzipped_)
|
| info->headers->AddHeader("Content-Encoding: gzip");
|
| }
|
| @@ -410,7 +258,7 @@ std::unique_ptr<net::SourceStream> URLRequestChromeJob::SetUpSourceStream() {
|
| }
|
|
|
| if (replacements_) {
|
| - source_stream = content::I18nSourceStream::Create(
|
| + source_stream = I18nSourceStream::Create(
|
| std::move(source_stream), net::SourceStream::TYPE_NONE, replacements_);
|
| }
|
|
|
| @@ -418,7 +266,7 @@ std::unique_ptr<net::SourceStream> URLRequestChromeJob::SetUpSourceStream() {
|
| }
|
|
|
| void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) {
|
| - set_mime_type(mime_type);
|
| + mime_type_ = mime_type;
|
| NotifyHeadersComplete();
|
| }
|
|
|
| @@ -441,10 +289,6 @@ void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) {
|
| }
|
| }
|
|
|
| -base::WeakPtr<URLRequestChromeJob> URLRequestChromeJob::AsWeakPtr() {
|
| - return weak_factory_.GetWeakPtr();
|
| -}
|
| -
|
| int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) {
|
| DCHECK(!pending_buf_.get());
|
|
|
| @@ -477,8 +321,8 @@ int URLRequestChromeJob::PostReadTask(scoped_refptr<net::IOBuffer> buf,
|
| FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
| base::Bind(&CopyData, base::RetainedRef(buf), buf_size, data_,
|
| data_offset_),
|
| - base::Bind(&URLRequestChromeJob::ReadRawDataComplete, AsWeakPtr(),
|
| - buf_size));
|
| + base::Bind(&URLRequestChromeJob::ReadRawDataComplete,
|
| + weak_factory_.GetWeakPtr(), buf_size));
|
| data_offset_ += buf_size;
|
|
|
| return net::ERR_IO_PENDING;
|
| @@ -531,12 +375,9 @@ bool IsValidNetworkErrorCode(int error_code) {
|
| class ChromeProtocolHandler
|
| : public net::URLRequestJobFactory::ProtocolHandler {
|
| public:
|
| - // |is_incognito| should be set for incognito profiles.
|
| ChromeProtocolHandler(ResourceContext* resource_context,
|
| - bool is_incognito,
|
| ChromeBlobStorageContext* blob_storage_context)
|
| : resource_context_(resource_context),
|
| - is_incognito_(is_incognito),
|
| blob_storage_context_(blob_storage_context) {}
|
| ~ChromeProtocolHandler() override {}
|
|
|
| @@ -590,7 +431,7 @@ class ChromeProtocolHandler
|
| // Fall back to using a custom handler
|
| return new URLRequestChromeJob(
|
| request, network_delegate,
|
| - GetURLDataManagerForResourceContext(resource_context_), is_incognito_);
|
| + GetURLDataManagerForResourceContext(resource_context_));
|
| }
|
|
|
| bool IsSafeRedirectTarget(const GURL& location) const override {
|
| @@ -601,8 +442,6 @@ class ChromeProtocolHandler
|
| // These members are owned by ProfileIOData, which owns this ProtocolHandler.
|
| ResourceContext* const resource_context_;
|
|
|
| - // True when generated from an incognito profile.
|
| - const bool is_incognito_;
|
| ChromeBlobStorageContext* blob_storage_context_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ChromeProtocolHandler);
|
| @@ -628,10 +467,9 @@ URLDataManagerBackend::~URLDataManagerBackend() {
|
| std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
|
| URLDataManagerBackend::CreateProtocolHandler(
|
| ResourceContext* resource_context,
|
| - bool is_incognito,
|
| ChromeBlobStorageContext* blob_storage_context) {
|
| DCHECK(resource_context);
|
| - return base::MakeUnique<ChromeProtocolHandler>(resource_context, is_incognito,
|
| + return base::MakeUnique<ChromeProtocolHandler>(resource_context,
|
| blob_storage_context);
|
| }
|
|
|
| @@ -672,6 +510,7 @@ bool URLDataManagerBackend::HasPendingJob(
|
|
|
| bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
|
| URLRequestChromeJob* job) {
|
| + // NOTE: this duplicates code in web_ui_url_loader_factory.cc's URLLoaderImpl.
|
| if (!CheckURLIsValid(request->url()))
|
| return false;
|
|
|
| @@ -679,8 +518,7 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
|
| if (!source)
|
| return false;
|
|
|
| - const content::ResourceRequestInfo* info =
|
| - content::ResourceRequestInfo::ForRequest(request);
|
| + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
|
| if (!source->source()->ShouldServiceRequest(
|
| request->url(), info ? info->GetContext() : nullptr,
|
| info ? info->GetChildID() : -1)) {
|
| @@ -694,23 +532,6 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
|
| RequestID request_id = next_request_id_++;
|
| pending_requests_.insert(std::make_pair(request_id, job));
|
|
|
| - job->set_allow_caching(source->source()->AllowCaching());
|
| - job->set_add_content_security_policy(
|
| - source->source()->ShouldAddContentSecurityPolicy());
|
| - job->set_content_security_policy_script_source(
|
| - source->source()->GetContentSecurityPolicyScriptSrc());
|
| - job->set_content_security_policy_object_source(
|
| - source->source()->GetContentSecurityPolicyObjectSrc());
|
| - job->set_content_security_policy_child_source(
|
| - source->source()->GetContentSecurityPolicyChildSrc());
|
| - job->set_content_security_policy_style_source(
|
| - source->source()->GetContentSecurityPolicyStyleSrc());
|
| - job->set_content_security_policy_image_source(
|
| - source->source()->GetContentSecurityPolicyImgSrc());
|
| - job->set_deny_xframe_options(
|
| - source->source()->ShouldDenyXFrameOptions());
|
| - job->set_send_content_type_header(
|
| - source->source()->ShouldServeMimeTypeAsContentTypeHeader());
|
| job->set_is_gzipped(source->source()->IsGzipped(path));
|
|
|
| // TODO(dschuyler): improve filtering of which resource to run template
|
| @@ -719,15 +540,6 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
|
| if (mime_type == "text/html")
|
| job->SetReplacements(source->GetReplacements());
|
|
|
| - std::string origin = GetOriginHeaderValue(request);
|
| - if (!origin.empty()) {
|
| - std::string header =
|
| - source->source()->GetAccessControlAllowOriginForOrigin(origin);
|
| - DCHECK(header.empty() || header == origin || header == "*" ||
|
| - header == "null");
|
| - job->set_access_control_allow_origin(header);
|
| - }
|
| -
|
| // Also notifies that the headers are complete.
|
| job->MimeTypeAvailable(mime_type);
|
|
|
| @@ -810,13 +622,90 @@ void URLDataManagerBackend::DataAvailable(RequestID request_id,
|
| }
|
| }
|
|
|
| +scoped_refptr<net::HttpResponseHeaders> URLDataManagerBackend::GetHeaders(
|
| + URLDataSourceImpl* source_impl,
|
| + const std::string& path,
|
| + const std::string& origin) {
|
| + // Set the headers so that requests serviced by ChromeURLDataManager return a
|
| + // status code of 200. Without this they return a 0, which makes the status
|
| + // indistiguishable from other error types. Instant relies on getting a 200.
|
| + scoped_refptr<net::HttpResponseHeaders> headers(
|
| + new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
|
| + if (!source_impl)
|
| + return headers;
|
| +
|
| + URLDataSource* source = source_impl->source();
|
| + // Determine the least-privileged content security policy header, if any,
|
| + // that is compatible with a given WebUI URL, and append it to the existing
|
| + // response headers.
|
| + if (source->ShouldAddContentSecurityPolicy()) {
|
| + std::string base = kChromeURLContentSecurityPolicyHeaderBase;
|
| + base.append(source->GetContentSecurityPolicyScriptSrc());
|
| + base.append(source->GetContentSecurityPolicyObjectSrc());
|
| + base.append(source->GetContentSecurityPolicyChildSrc());
|
| + base.append(source->GetContentSecurityPolicyStyleSrc());
|
| + base.append(source->GetContentSecurityPolicyImgSrc());
|
| + headers->AddHeader(base);
|
| + }
|
| +
|
| + if (source->ShouldDenyXFrameOptions())
|
| + headers->AddHeader(kChromeURLXFrameOptionsHeader);
|
| +
|
| + if (!source->AllowCaching())
|
| + headers->AddHeader("Cache-Control: no-cache");
|
| +
|
| + std::string mime_type = source->GetMimeType(path);
|
| + if (source->ShouldServeMimeTypeAsContentTypeHeader() && !mime_type.empty()) {
|
| + std::string content_type = base::StringPrintf(
|
| + "%s:%s", net::HttpRequestHeaders::kContentType, mime_type.c_str());
|
| + headers->AddHeader(content_type);
|
| + }
|
| +
|
| + if (!origin.empty()) {
|
| + std::string header = source->GetAccessControlAllowOriginForOrigin(origin);
|
| + DCHECK(header.empty() || header == origin || header == "*" ||
|
| + header == "null");
|
| + if (!header.empty()) {
|
| + headers->AddHeader("Access-Control-Allow-Origin: " + header);
|
| + headers->AddHeader("Vary: Origin");
|
| + }
|
| + }
|
| +
|
| + return headers;
|
| +}
|
| +
|
| +bool URLDataManagerBackend::CheckURLIsValid(const GURL& url) {
|
| + std::vector<std::string> additional_schemes;
|
| + DCHECK(url.SchemeIs(kChromeDevToolsScheme) || url.SchemeIs(kChromeUIScheme) ||
|
| + (GetContentClient()->browser()->GetAdditionalWebUISchemes(
|
| + &additional_schemes),
|
| + SchemeIsInSchemes(url.scheme(), additional_schemes)));
|
| +
|
| + if (!url.is_valid()) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void URLDataManagerBackend::URLToRequestPath(const GURL& url,
|
| + std::string* path) {
|
| + const std::string& spec = url.possibly_invalid_spec();
|
| + const url::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
|
| + // + 1 to skip the slash at the beginning of the path.
|
| + int offset = parsed.CountCharactersBefore(url::Parsed::PATH, false) + 1;
|
| +
|
| + if (offset < static_cast<int>(spec.size()))
|
| + path->assign(spec.substr(offset));
|
| +}
|
| +
|
| namespace {
|
|
|
| class DevToolsJobFactory
|
| : public net::URLRequestJobFactory::ProtocolHandler {
|
| public:
|
| - // |is_incognito| should be set for incognito profiles.
|
| - DevToolsJobFactory(ResourceContext* resource_context, bool is_incognito);
|
| + explicit DevToolsJobFactory(ResourceContext* resource_context);
|
| ~DevToolsJobFactory() override;
|
|
|
| net::URLRequestJob* MaybeCreateJob(
|
| @@ -828,15 +717,11 @@ class DevToolsJobFactory
|
| // which owns this ProtocolHandler.
|
| ResourceContext* const resource_context_;
|
|
|
| - // True when generated from an incognito profile.
|
| - const bool is_incognito_;
|
| -
|
| DISALLOW_COPY_AND_ASSIGN(DevToolsJobFactory);
|
| };
|
|
|
| -DevToolsJobFactory::DevToolsJobFactory(ResourceContext* resource_context,
|
| - bool is_incognito)
|
| - : resource_context_(resource_context), is_incognito_(is_incognito) {
|
| +DevToolsJobFactory::DevToolsJobFactory(ResourceContext* resource_context)
|
| + : resource_context_(resource_context) {
|
| DCHECK(resource_context_);
|
| }
|
|
|
| @@ -847,15 +732,14 @@ DevToolsJobFactory::MaybeCreateJob(
|
| net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
|
| return new URLRequestChromeJob(
|
| request, network_delegate,
|
| - GetURLDataManagerForResourceContext(resource_context_), is_incognito_);
|
| + GetURLDataManagerForResourceContext(resource_context_));
|
| }
|
|
|
| } // namespace
|
|
|
| net::URLRequestJobFactory::ProtocolHandler* CreateDevToolsProtocolHandler(
|
| - ResourceContext* resource_context,
|
| - bool is_incognito) {
|
| - return new DevToolsJobFactory(resource_context, is_incognito);
|
| + ResourceContext* resource_context) {
|
| + return new DevToolsJobFactory(resource_context);
|
| }
|
|
|
| } // namespace content
|
|
|