Commit fd3b257a authored by dzhioev's avatar dzhioev Committed by Commit bot

URLDataSource can specify the value for 'Access-Control-Allow-Origin' response...

URLDataSource can specify the value for 'Access-Control-Allow-Origin' response header based on 'Origin' request header.

SharedResourcesDataSource allows access for all 'chrome://*' origins.

BUG=418199

Review URL: https://codereview.chromium.org/613733002

Cr-Commit-Position: refs/heads/master@{#299153}
parent 736a6299
...@@ -400,23 +400,22 @@ void ChromeContentRendererClient::RenderThreadStarted() { ...@@ -400,23 +400,22 @@ void ChromeContentRendererClient::RenderThreadStarted() {
WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs( WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
chrome_search_scheme); chrome_search_scheme);
// chrome:, chrome-search:, and chrome-extension: resources shouldn't trigger // chrome:, chrome-search:, chrome-extension:, and chrome-extension-resource:
// insecure content warnings. // resources shouldn't trigger insecure content warnings.
WebSecurityPolicy::registerURLSchemeAsSecure(chrome_ui_scheme); WebSecurityPolicy::registerURLSchemeAsSecure(chrome_ui_scheme);
WebSecurityPolicy::registerURLSchemeAsSecure(chrome_search_scheme); WebSecurityPolicy::registerURLSchemeAsSecure(chrome_search_scheme);
WebString extension_scheme(ASCIIToUTF16(extensions::kExtensionScheme)); WebString extension_scheme(ASCIIToUTF16(extensions::kExtensionScheme));
WebSecurityPolicy::registerURLSchemeAsSecure(extension_scheme); WebSecurityPolicy::registerURLSchemeAsSecure(extension_scheme);
// chrome-extension: resources should be allowed to receive CORS requests.
WebSecurityPolicy::registerURLSchemeAsCORSEnabled(extension_scheme);
WebString extension_resource_scheme( WebString extension_resource_scheme(
ASCIIToUTF16(extensions::kExtensionResourceScheme)); ASCIIToUTF16(extensions::kExtensionResourceScheme));
WebSecurityPolicy::registerURLSchemeAsSecure(extension_resource_scheme); WebSecurityPolicy::registerURLSchemeAsSecure(extension_resource_scheme);
// chrome-extension-resource: resources should be allowed to receive CORS // chrome:, chrome-extension:, chrome-extension-resource: resources should be
// requests. // allowed to receive CORS requests.
WebSecurityPolicy::registerURLSchemeAsCORSEnabled(chrome_ui_scheme);
WebSecurityPolicy::registerURLSchemeAsCORSEnabled(extension_scheme);
WebSecurityPolicy::registerURLSchemeAsCORSEnabled(extension_resource_scheme); WebSecurityPolicy::registerURLSchemeAsCORSEnabled(extension_resource_scheme);
// chrome-extension: resources should bypass Content Security Policy checks // chrome-extension: resources should bypass Content Security Policy checks
......
...@@ -89,3 +89,17 @@ std::string SharedResourcesDataSource::GetMimeType( ...@@ -89,3 +89,17 @@ std::string SharedResourcesDataSource::GetMimeType(
net::GetMimeTypeFromFile(base::FilePath().AppendASCII(path), &mime_type); net::GetMimeTypeFromFile(base::FilePath().AppendASCII(path), &mime_type);
return mime_type; return mime_type;
} }
std::string
SharedResourcesDataSource::GetAccessControlAllowOriginForOrigin(
const std::string& origin) const {
// For now we give access only for "chrome://*" origins.
// According to CORS spec, Access-Control-Allow-Origin header doesn't support
// wildcards, so we need to set its value explicitly by passing the |origin|
// back.
std::string allowed_origin_prefix = content::kChromeUIScheme;
allowed_origin_prefix += "://";
if (origin.find(allowed_origin_prefix) != 0)
return "none";
return origin;
}
...@@ -22,6 +22,8 @@ class SharedResourcesDataSource : public content::URLDataSource { ...@@ -22,6 +22,8 @@ class SharedResourcesDataSource : public content::URLDataSource {
int render_frame_id, int render_frame_id,
const content::URLDataSource::GotDataCallback& callback) override; const content::URLDataSource::GotDataCallback& callback) override;
virtual std::string GetMimeType(const std::string&) const override; virtual std::string GetMimeType(const std::string&) const override;
virtual std::string GetAccessControlAllowOriginForOrigin(
const std::string& origin) const override;
private: private:
virtual ~SharedResourcesDataSource(); virtual ~SharedResourcesDataSource();
......
...@@ -90,6 +90,19 @@ void URLToRequestPath(const GURL& url, std::string* path) { ...@@ -90,6 +90,19 @@ void URLToRequestPath(const GURL& url, std::string* path) {
path->assign(spec.substr(offset)); 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) {
std::string result;
if (request->extra_request_headers().GetHeader(
net::HttpRequestHeaders::kOrigin, &result))
return result;
net::HttpRequestHeaders headers;
if (request->GetFullRequestHeaders(&headers))
headers.GetHeader(net::HttpRequestHeaders::kOrigin, &result);
return result;
}
} // namespace } // namespace
// URLRequestChromeJob is a net::URLRequestJob that manages running // URLRequestChromeJob is a net::URLRequestJob that manages running
...@@ -152,6 +165,10 @@ class URLRequestChromeJob : public net::URLRequestJob, ...@@ -152,6 +165,10 @@ class URLRequestChromeJob : public net::URLRequestJob,
send_content_type_header_ = 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;
}
// Returns true when job was generated from an incognito profile. // Returns true when job was generated from an incognito profile.
bool is_incognito() const { bool is_incognito() const {
return is_incognito_; return is_incognito_;
...@@ -202,6 +219,10 @@ class URLRequestChromeJob : public net::URLRequestJob, ...@@ -202,6 +219,10 @@ class URLRequestChromeJob : public net::URLRequestJob,
// If true, sets the "Content-Type: <mime-type>" header. // If true, sets the "Content-Type: <mime-type>" header.
bool send_content_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. // True when job is generated from an incognito profile.
const bool is_incognito_; const bool is_incognito_;
...@@ -293,6 +314,12 @@ void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) { ...@@ -293,6 +314,12 @@ void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
mime_type_.c_str()); mime_type_.c_str());
info->headers->AddHeader(content_type); 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");
}
} }
void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) { void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) {
...@@ -578,6 +605,15 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request, ...@@ -578,6 +605,15 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
job->set_send_content_type_header( job->set_send_content_type_header(
source->source()->ShouldServeMimeTypeAsContentTypeHeader()); source->source()->ShouldServeMimeTypeAsContentTypeHeader());
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);
}
// Look up additional request info to pass down. // Look up additional request info to pass down.
int render_process_id = -1; int render_process_id = -1;
int render_frame_id = -1; int render_frame_id = -1;
......
...@@ -56,4 +56,9 @@ bool URLDataSource::ShouldServeMimeTypeAsContentTypeHeader() const { ...@@ -56,4 +56,9 @@ bool URLDataSource::ShouldServeMimeTypeAsContentTypeHeader() const {
return false; return false;
} }
std::string URLDataSource::GetAccessControlAllowOriginForOrigin(
const std::string& origin) const {
return std::string();
}
} // namespace content } // namespace content
...@@ -119,6 +119,15 @@ class CONTENT_EXPORT URLDataSource { ...@@ -119,6 +119,15 @@ class CONTENT_EXPORT URLDataSource {
// is for chrome-devtools. // is for chrome-devtools.
virtual bool ShouldServeMimeTypeAsContentTypeHeader() const; virtual bool ShouldServeMimeTypeAsContentTypeHeader() const;
// This method is called when the request contains "Origin:" header. The value
// of the header is passed in |origin| parameter. If the returned value is not
// empty, it is used as a value for "Access-Control-Allow-Origin:" response
// header, otherwise the header is not set. This method should return either
// |origin|, or "*", or "none", or empty string.
// Default implementation returns an empty string.
virtual std::string GetAccessControlAllowOriginForOrigin(
const std::string& origin) const;
// Called to inform the source that StartDataRequest() will be called soon. // Called to inform the source that StartDataRequest() will be called soon.
// Gives the source an opportunity to rewrite |path| to incorporate extra // Gives the source an opportunity to rewrite |path| to incorporate extra
// information from the URLRequest prior to serving. // information from the URLRequest prior to serving.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment