| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/webui/url_data_manager_backend.h" | 5 #include "content/browser/webui/url_data_manager_backend.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 #include "net/url_request/url_request_error_job.h" | 46 #include "net/url_request/url_request_error_job.h" |
| 47 #include "net/url_request/url_request_job.h" | 47 #include "net/url_request/url_request_job.h" |
| 48 #include "net/url_request/url_request_job_factory.h" | 48 #include "net/url_request/url_request_job_factory.h" |
| 49 #include "url/url_util.h" | 49 #include "url/url_util.h" |
| 50 | 50 |
| 51 namespace content { | 51 namespace content { |
| 52 | 52 |
| 53 namespace { | 53 namespace { |
| 54 | 54 |
| 55 const char kChromeURLContentSecurityPolicyHeaderBase[] = | 55 const char kChromeURLContentSecurityPolicyHeaderBase[] = |
| 56 "Content-Security-Policy: script-src chrome://resources 'self'"; | 56 "Content-Security-Policy: "; |
| 57 | 57 |
| 58 const char kChromeURLXFrameOptionsHeader[] = "X-Frame-Options: DENY"; | 58 const char kChromeURLXFrameOptionsHeader[] = "X-Frame-Options: DENY"; |
| 59 static const char kNetworkErrorKey[] = "netError"; | 59 static const char kNetworkErrorKey[] = "netError"; |
| 60 | 60 |
| 61 bool SchemeIsInSchemes(const std::string& scheme, | 61 bool SchemeIsInSchemes(const std::string& scheme, |
| 62 const std::vector<std::string>& schemes) { | 62 const std::vector<std::string>& schemes) { |
| 63 return std::find(schemes.begin(), schemes.end(), scheme) != schemes.end(); | 63 return std::find(schemes.begin(), schemes.end(), scheme) != schemes.end(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 // Returns whether |url| passes some sanity checks and is a valid GURL. | 66 // Returns whether |url| passes some sanity checks and is a valid GURL. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 | 146 |
| 147 void set_add_content_security_policy(bool add_content_security_policy) { | 147 void set_add_content_security_policy(bool add_content_security_policy) { |
| 148 add_content_security_policy_ = add_content_security_policy; | 148 add_content_security_policy_ = add_content_security_policy; |
| 149 } | 149 } |
| 150 | 150 |
| 151 void set_content_security_policy_object_source( | 151 void set_content_security_policy_object_source( |
| 152 const std::string& data) { | 152 const std::string& data) { |
| 153 content_security_policy_object_source_ = data; | 153 content_security_policy_object_source_ = data; |
| 154 } | 154 } |
| 155 | 155 |
| 156 void set_content_security_policy_script_source( |
| 157 const std::string& data) { |
| 158 content_security_policy_script_source_ = data; |
| 159 } |
| 160 |
| 156 void set_content_security_policy_frame_source( | 161 void set_content_security_policy_frame_source( |
| 157 const std::string& data) { | 162 const std::string& data) { |
| 158 content_security_policy_frame_source_ = data; | 163 content_security_policy_frame_source_ = data; |
| 159 } | 164 } |
| 160 | 165 |
| 166 void set_content_security_policy_style_source( |
| 167 const std::string& data) { |
| 168 content_security_policy_style_source_ = data; |
| 169 } |
| 170 |
| 171 void set_content_security_policy_image_source( |
| 172 const std::string& data) { |
| 173 content_security_policy_image_source_ = data; |
| 174 } |
| 175 |
| 161 void set_deny_xframe_options(bool deny_xframe_options) { | 176 void set_deny_xframe_options(bool deny_xframe_options) { |
| 162 deny_xframe_options_ = deny_xframe_options; | 177 deny_xframe_options_ = deny_xframe_options; |
| 163 } | 178 } |
| 164 | 179 |
| 165 void set_send_content_type_header(bool send_content_type_header) { | 180 void set_send_content_type_header(bool send_content_type_header) { |
| 166 send_content_type_header_ = send_content_type_header; | 181 send_content_type_header_ = send_content_type_header; |
| 167 } | 182 } |
| 168 | 183 |
| 169 void set_access_control_allow_origin(const std::string& value) { | 184 void set_access_control_allow_origin(const std::string& value) { |
| 170 access_control_allow_origin_ = value; | 185 access_control_allow_origin_ = value; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 181 // Helper for Start(), to let us start asynchronously. | 196 // Helper for Start(), to let us start asynchronously. |
| 182 // (This pattern is shared by most net::URLRequestJob implementations.) | 197 // (This pattern is shared by most net::URLRequestJob implementations.) |
| 183 void StartAsync(bool allowed); | 198 void StartAsync(bool allowed); |
| 184 | 199 |
| 185 // Called on the UI thread to check if this request is allowed. | 200 // Called on the UI thread to check if this request is allowed. |
| 186 static void CheckStoragePartitionMatches( | 201 static void CheckStoragePartitionMatches( |
| 187 int render_process_id, | 202 int render_process_id, |
| 188 const GURL& url, | 203 const GURL& url, |
| 189 const base::WeakPtr<URLRequestChromeJob>& job); | 204 const base::WeakPtr<URLRequestChromeJob>& job); |
| 190 | 205 |
| 191 // Specific resources require unsafe-eval in the Content Security Policy. | |
| 192 bool RequiresUnsafeEval() const; | |
| 193 | |
| 194 // Do the actual copy from data_ (the data we're serving) into |buf|. | 206 // Do the actual copy from data_ (the data we're serving) into |buf|. |
| 195 // Separate from ReadRawData so we can handle async I/O. Returns the number of | 207 // Separate from ReadRawData so we can handle async I/O. Returns the number of |
| 196 // bytes read. | 208 // bytes read. |
| 197 int CompleteRead(net::IOBuffer* buf, int buf_size); | 209 int CompleteRead(net::IOBuffer* buf, int buf_size); |
| 198 | 210 |
| 199 // The actual data we're serving. NULL until it's been fetched. | 211 // The actual data we're serving. NULL until it's been fetched. |
| 200 scoped_refptr<base::RefCountedMemory> data_; | 212 scoped_refptr<base::RefCountedMemory> data_; |
| 201 // The current offset into the data that we're handing off to our | 213 // The current offset into the data that we're handing off to our |
| 202 // callers via the Read interfaces. | 214 // callers via the Read interfaces. |
| 203 int data_offset_; | 215 int data_offset_; |
| 204 | 216 |
| 205 // For async reads, we keep around a pointer to the buffer that | 217 // For async reads, we keep around a pointer to the buffer that |
| 206 // we're reading into. | 218 // we're reading into. |
| 207 scoped_refptr<net::IOBuffer> pending_buf_; | 219 scoped_refptr<net::IOBuffer> pending_buf_; |
| 208 int pending_buf_size_; | 220 int pending_buf_size_; |
| 209 std::string mime_type_; | 221 std::string mime_type_; |
| 210 | 222 |
| 211 // If true, set a header in the response to prevent it from being cached. | 223 // If true, set a header in the response to prevent it from being cached. |
| 212 bool allow_caching_; | 224 bool allow_caching_; |
| 213 | 225 |
| 214 // If true, set the Content Security Policy (CSP) header. | 226 // If true, set the Content Security Policy (CSP) header. |
| 215 bool add_content_security_policy_; | 227 bool add_content_security_policy_; |
| 216 | 228 |
| 217 // These are used with the CSP. | 229 // These are used with the CSP. |
| 230 std::string content_security_policy_script_source_; |
| 218 std::string content_security_policy_object_source_; | 231 std::string content_security_policy_object_source_; |
| 219 std::string content_security_policy_frame_source_; | 232 std::string content_security_policy_frame_source_; |
| 233 std::string content_security_policy_style_source_; |
| 234 std::string content_security_policy_image_source_; |
| 220 | 235 |
| 221 // If true, sets the "X-Frame-Options: DENY" header. | 236 // If true, sets the "X-Frame-Options: DENY" header. |
| 222 bool deny_xframe_options_; | 237 bool deny_xframe_options_; |
| 223 | 238 |
| 224 // If true, sets the "Content-Type: <mime-type>" header. | 239 // If true, sets the "Content-Type: <mime-type>" header. |
| 225 bool send_content_type_header_; | 240 bool send_content_type_header_; |
| 226 | 241 |
| 227 // If not empty, "Access-Control-Allow-Origin:" is set to the value of this | 242 // If not empty, "Access-Control-Allow-Origin:" is set to the value of this |
| 228 // string. | 243 // string. |
| 229 std::string access_control_allow_origin_; | 244 std::string access_control_allow_origin_; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 241 | 256 |
| 242 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, | 257 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, |
| 243 net::NetworkDelegate* network_delegate, | 258 net::NetworkDelegate* network_delegate, |
| 244 URLDataManagerBackend* backend, | 259 URLDataManagerBackend* backend, |
| 245 bool is_incognito) | 260 bool is_incognito) |
| 246 : net::URLRequestJob(request, network_delegate), | 261 : net::URLRequestJob(request, network_delegate), |
| 247 data_offset_(0), | 262 data_offset_(0), |
| 248 pending_buf_size_(0), | 263 pending_buf_size_(0), |
| 249 allow_caching_(true), | 264 allow_caching_(true), |
| 250 add_content_security_policy_(true), | 265 add_content_security_policy_(true), |
| 251 content_security_policy_object_source_("object-src 'none';"), | |
| 252 content_security_policy_frame_source_("frame-src 'none';"), | |
| 253 deny_xframe_options_(true), | 266 deny_xframe_options_(true), |
| 254 send_content_type_header_(false), | 267 send_content_type_header_(false), |
| 255 is_incognito_(is_incognito), | 268 is_incognito_(is_incognito), |
| 256 backend_(backend), | 269 backend_(backend), |
| 257 weak_factory_(this) { | 270 weak_factory_(this) { |
| 258 DCHECK(backend); | 271 DCHECK(backend); |
| 259 } | 272 } |
| 260 | 273 |
| 261 URLRequestChromeJob::~URLRequestChromeJob() { | 274 URLRequestChromeJob::~URLRequestChromeJob() { |
| 262 CHECK(!backend_->HasPendingJob(this)); | 275 CHECK(!backend_->HasPendingJob(this)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 // Set the headers so that requests serviced by ChromeURLDataManager return a | 332 // Set the headers so that requests serviced by ChromeURLDataManager return a |
| 320 // status code of 200. Without this they return a 0, which makes the status | 333 // status code of 200. Without this they return a 0, which makes the status |
| 321 // indistiguishable from other error types. Instant relies on getting a 200. | 334 // indistiguishable from other error types. Instant relies on getting a 200. |
| 322 info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); | 335 info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); |
| 323 | 336 |
| 324 // Determine the least-privileged content security policy header, if any, | 337 // Determine the least-privileged content security policy header, if any, |
| 325 // that is compatible with a given WebUI URL, and append it to the existing | 338 // that is compatible with a given WebUI URL, and append it to the existing |
| 326 // response headers. | 339 // response headers. |
| 327 if (add_content_security_policy_) { | 340 if (add_content_security_policy_) { |
| 328 std::string base = kChromeURLContentSecurityPolicyHeaderBase; | 341 std::string base = kChromeURLContentSecurityPolicyHeaderBase; |
| 329 base.append(RequiresUnsafeEval() ? " 'unsafe-eval'; " : "; "); | 342 base.append(content_security_policy_script_source_); |
| 330 base.append(content_security_policy_object_source_); | 343 base.append(content_security_policy_object_source_); |
| 331 base.append(content_security_policy_frame_source_); | 344 base.append(content_security_policy_frame_source_); |
| 345 base.append(content_security_policy_style_source_); |
| 346 base.append(content_security_policy_image_source_); |
| 332 info->headers->AddHeader(base); | 347 info->headers->AddHeader(base); |
| 333 } | 348 } |
| 334 | 349 |
| 335 if (deny_xframe_options_) | 350 if (deny_xframe_options_) |
| 336 info->headers->AddHeader(kChromeURLXFrameOptionsHeader); | 351 info->headers->AddHeader(kChromeURLXFrameOptionsHeader); |
| 337 | 352 |
| 338 if (!allow_caching_) | 353 if (!allow_caching_) |
| 339 info->headers->AddHeader("Cache-Control: no-cache"); | 354 info->headers->AddHeader("Cache-Control: no-cache"); |
| 340 | 355 |
| 341 if (send_content_type_header_ && !mime_type_.empty()) { | 356 if (send_content_type_header_ && !mime_type_.empty()) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 void URLRequestChromeJob::StartAsync(bool allowed) { | 446 void URLRequestChromeJob::StartAsync(bool allowed) { |
| 432 if (!request_) | 447 if (!request_) |
| 433 return; | 448 return; |
| 434 | 449 |
| 435 if (!allowed || !backend_->StartRequest(request_, this)) { | 450 if (!allowed || !backend_->StartRequest(request_, this)) { |
| 436 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 451 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 437 net::ERR_INVALID_URL)); | 452 net::ERR_INVALID_URL)); |
| 438 } | 453 } |
| 439 } | 454 } |
| 440 | 455 |
| 441 // TODO(tsepez,mfoltz): Refine this method when tests have been fixed to not use | |
| 442 // eval()/new Function(). http://crbug.com/525224 | |
| 443 bool URLRequestChromeJob::RequiresUnsafeEval() const { | |
| 444 return true; | |
| 445 } | |
| 446 | |
| 447 namespace { | 456 namespace { |
| 448 | 457 |
| 449 // Gets mime type for data that is available from |source| by |path|. | 458 // Gets mime type for data that is available from |source| by |path|. |
| 450 // After that, notifies |job| that mime type is available. This method | 459 // After that, notifies |job| that mime type is available. This method |
| 451 // should be called on the UI thread, but notification is performed on | 460 // should be called on the UI thread, but notification is performed on |
| 452 // the IO thread. | 461 // the IO thread. |
| 453 void GetMimeTypeOnUI(URLDataSourceImpl* source, | 462 void GetMimeTypeOnUI(URLDataSourceImpl* source, |
| 454 const std::string& path, | 463 const std::string& path, |
| 455 const base::WeakPtr<URLRequestChromeJob>& job) { | 464 const base::WeakPtr<URLRequestChromeJob>& job) { |
| 456 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 465 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 URLToRequestPath(request->url(), &path); | 638 URLToRequestPath(request->url(), &path); |
| 630 source->source()->WillServiceRequest(request, &path); | 639 source->source()->WillServiceRequest(request, &path); |
| 631 | 640 |
| 632 // Save this request so we know where to send the data. | 641 // Save this request so we know where to send the data. |
| 633 RequestID request_id = next_request_id_++; | 642 RequestID request_id = next_request_id_++; |
| 634 pending_requests_.insert(std::make_pair(request_id, job)); | 643 pending_requests_.insert(std::make_pair(request_id, job)); |
| 635 | 644 |
| 636 job->set_allow_caching(source->source()->AllowCaching()); | 645 job->set_allow_caching(source->source()->AllowCaching()); |
| 637 job->set_add_content_security_policy( | 646 job->set_add_content_security_policy( |
| 638 source->source()->ShouldAddContentSecurityPolicy()); | 647 source->source()->ShouldAddContentSecurityPolicy()); |
| 648 job->set_content_security_policy_script_source( |
| 649 source->source()->GetContentSecurityPolicyScriptSrc()); |
| 639 job->set_content_security_policy_object_source( | 650 job->set_content_security_policy_object_source( |
| 640 source->source()->GetContentSecurityPolicyObjectSrc()); | 651 source->source()->GetContentSecurityPolicyObjectSrc()); |
| 641 job->set_content_security_policy_frame_source( | 652 job->set_content_security_policy_frame_source( |
| 642 source->source()->GetContentSecurityPolicyFrameSrc()); | 653 source->source()->GetContentSecurityPolicyFrameSrc()); |
| 654 job->set_content_security_policy_style_source( |
| 655 source->source()->GetContentSecurityPolicyStyleSrc()); |
| 656 job->set_content_security_policy_image_source( |
| 657 source->source()->GetContentSecurityPolicyImgSrc()); |
| 643 job->set_deny_xframe_options( | 658 job->set_deny_xframe_options( |
| 644 source->source()->ShouldDenyXFrameOptions()); | 659 source->source()->ShouldDenyXFrameOptions()); |
| 645 job->set_send_content_type_header( | 660 job->set_send_content_type_header( |
| 646 source->source()->ShouldServeMimeTypeAsContentTypeHeader()); | 661 source->source()->ShouldServeMimeTypeAsContentTypeHeader()); |
| 647 | 662 |
| 648 std::string origin = GetOriginHeaderValue(request); | 663 std::string origin = GetOriginHeaderValue(request); |
| 649 if (!origin.empty()) { | 664 if (!origin.empty()) { |
| 650 std::string header = | 665 std::string header = |
| 651 source->source()->GetAccessControlAllowOriginForOrigin(origin); | 666 source->source()->GetAccessControlAllowOriginForOrigin(origin); |
| 652 DCHECK(header.empty() || header == origin || header == "*" || | 667 DCHECK(header.empty() || header == origin || header == "*" || |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 | 818 |
| 804 } // namespace | 819 } // namespace |
| 805 | 820 |
| 806 net::URLRequestJobFactory::ProtocolHandler* | 821 net::URLRequestJobFactory::ProtocolHandler* |
| 807 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, | 822 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, |
| 808 bool is_incognito) { | 823 bool is_incognito) { |
| 809 return new DevToolsJobFactory(resource_context, is_incognito); | 824 return new DevToolsJobFactory(resource_context, is_incognito); |
| 810 } | 825 } |
| 811 | 826 |
| 812 } // namespace content | 827 } // namespace content |
| OLD | NEW |