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 |
161 void set_deny_xframe_options(bool deny_xframe_options) { | 166 void set_deny_xframe_options(bool deny_xframe_options) { |
162 deny_xframe_options_ = deny_xframe_options; | 167 deny_xframe_options_ = deny_xframe_options; |
163 } | 168 } |
164 | 169 |
165 void set_send_content_type_header(bool send_content_type_header) { | 170 void set_send_content_type_header(bool send_content_type_header) { |
(...skipping 15 matching lines...) Expand all Loading... |
181 // Helper for Start(), to let us start asynchronously. | 186 // Helper for Start(), to let us start asynchronously. |
182 // (This pattern is shared by most net::URLRequestJob implementations.) | 187 // (This pattern is shared by most net::URLRequestJob implementations.) |
183 void StartAsync(bool allowed); | 188 void StartAsync(bool allowed); |
184 | 189 |
185 // Called on the UI thread to check if this request is allowed. | 190 // Called on the UI thread to check if this request is allowed. |
186 static void CheckStoragePartitionMatches( | 191 static void CheckStoragePartitionMatches( |
187 int render_process_id, | 192 int render_process_id, |
188 const GURL& url, | 193 const GURL& url, |
189 const base::WeakPtr<URLRequestChromeJob>& job); | 194 const base::WeakPtr<URLRequestChromeJob>& job); |
190 | 195 |
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|. | 196 // 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 | 197 // Separate from ReadRawData so we can handle async I/O. Returns the number of |
196 // bytes read. | 198 // bytes read. |
197 int CompleteRead(net::IOBuffer* buf, int buf_size); | 199 int CompleteRead(net::IOBuffer* buf, int buf_size); |
198 | 200 |
199 // The actual data we're serving. NULL until it's been fetched. | 201 // The actual data we're serving. NULL until it's been fetched. |
200 scoped_refptr<base::RefCountedMemory> data_; | 202 scoped_refptr<base::RefCountedMemory> data_; |
201 // The current offset into the data that we're handing off to our | 203 // The current offset into the data that we're handing off to our |
202 // callers via the Read interfaces. | 204 // callers via the Read interfaces. |
203 int data_offset_; | 205 int data_offset_; |
204 | 206 |
205 // For async reads, we keep around a pointer to the buffer that | 207 // For async reads, we keep around a pointer to the buffer that |
206 // we're reading into. | 208 // we're reading into. |
207 scoped_refptr<net::IOBuffer> pending_buf_; | 209 scoped_refptr<net::IOBuffer> pending_buf_; |
208 int pending_buf_size_; | 210 int pending_buf_size_; |
209 std::string mime_type_; | 211 std::string mime_type_; |
210 | 212 |
211 // If true, set a header in the response to prevent it from being cached. | 213 // If true, set a header in the response to prevent it from being cached. |
212 bool allow_caching_; | 214 bool allow_caching_; |
213 | 215 |
214 // If true, set the Content Security Policy (CSP) header. | 216 // If true, set the Content Security Policy (CSP) header. |
215 bool add_content_security_policy_; | 217 bool add_content_security_policy_; |
216 | 218 |
217 // These are used with the CSP. | 219 // These are used with the CSP. |
| 220 std::string content_security_policy_script_source_; |
218 std::string content_security_policy_object_source_; | 221 std::string content_security_policy_object_source_; |
219 std::string content_security_policy_frame_source_; | 222 std::string content_security_policy_frame_source_; |
220 | 223 |
221 // If true, sets the "X-Frame-Options: DENY" header. | 224 // If true, sets the "X-Frame-Options: DENY" header. |
222 bool deny_xframe_options_; | 225 bool deny_xframe_options_; |
223 | 226 |
224 // If true, sets the "Content-Type: <mime-type>" header. | 227 // If true, sets the "Content-Type: <mime-type>" header. |
225 bool send_content_type_header_; | 228 bool send_content_type_header_; |
226 | 229 |
227 // If not empty, "Access-Control-Allow-Origin:" is set to the value of this | 230 // If not empty, "Access-Control-Allow-Origin:" is set to the value of this |
(...skipping 13 matching lines...) Expand all Loading... |
241 | 244 |
242 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, | 245 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, |
243 net::NetworkDelegate* network_delegate, | 246 net::NetworkDelegate* network_delegate, |
244 URLDataManagerBackend* backend, | 247 URLDataManagerBackend* backend, |
245 bool is_incognito) | 248 bool is_incognito) |
246 : net::URLRequestJob(request, network_delegate), | 249 : net::URLRequestJob(request, network_delegate), |
247 data_offset_(0), | 250 data_offset_(0), |
248 pending_buf_size_(0), | 251 pending_buf_size_(0), |
249 allow_caching_(true), | 252 allow_caching_(true), |
250 add_content_security_policy_(true), | 253 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), | 254 deny_xframe_options_(true), |
254 send_content_type_header_(false), | 255 send_content_type_header_(false), |
255 is_incognito_(is_incognito), | 256 is_incognito_(is_incognito), |
256 backend_(backend), | 257 backend_(backend), |
257 weak_factory_(this) { | 258 weak_factory_(this) { |
258 DCHECK(backend); | 259 DCHECK(backend); |
259 } | 260 } |
260 | 261 |
261 URLRequestChromeJob::~URLRequestChromeJob() { | 262 URLRequestChromeJob::~URLRequestChromeJob() { |
262 CHECK(!backend_->HasPendingJob(this)); | 263 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 | 320 // 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 | 321 // 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. | 322 // indistiguishable from other error types. Instant relies on getting a 200. |
322 info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); | 323 info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); |
323 | 324 |
324 // Determine the least-privileged content security policy header, if any, | 325 // 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 | 326 // that is compatible with a given WebUI URL, and append it to the existing |
326 // response headers. | 327 // response headers. |
327 if (add_content_security_policy_) { | 328 if (add_content_security_policy_) { |
328 std::string base = kChromeURLContentSecurityPolicyHeaderBase; | 329 std::string base = kChromeURLContentSecurityPolicyHeaderBase; |
329 base.append(RequiresUnsafeEval() ? " 'unsafe-eval'; " : "; "); | 330 base.append(content_security_policy_script_source_); |
330 base.append(content_security_policy_object_source_); | 331 base.append(content_security_policy_object_source_); |
331 base.append(content_security_policy_frame_source_); | 332 base.append(content_security_policy_frame_source_); |
332 info->headers->AddHeader(base); | 333 info->headers->AddHeader(base); |
333 } | 334 } |
334 | 335 |
335 if (deny_xframe_options_) | 336 if (deny_xframe_options_) |
336 info->headers->AddHeader(kChromeURLXFrameOptionsHeader); | 337 info->headers->AddHeader(kChromeURLXFrameOptionsHeader); |
337 | 338 |
338 if (!allow_caching_) | 339 if (!allow_caching_) |
339 info->headers->AddHeader("Cache-Control: no-cache"); | 340 info->headers->AddHeader("Cache-Control: no-cache"); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 void URLRequestChromeJob::StartAsync(bool allowed) { | 432 void URLRequestChromeJob::StartAsync(bool allowed) { |
432 if (!request_) | 433 if (!request_) |
433 return; | 434 return; |
434 | 435 |
435 if (!allowed || !backend_->StartRequest(request_, this)) { | 436 if (!allowed || !backend_->StartRequest(request_, this)) { |
436 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 437 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
437 net::ERR_INVALID_URL)); | 438 net::ERR_INVALID_URL)); |
438 } | 439 } |
439 } | 440 } |
440 | 441 |
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 { | 442 namespace { |
448 | 443 |
449 // Gets mime type for data that is available from |source| by |path|. | 444 // Gets mime type for data that is available from |source| by |path|. |
450 // After that, notifies |job| that mime type is available. This method | 445 // After that, notifies |job| that mime type is available. This method |
451 // should be called on the UI thread, but notification is performed on | 446 // should be called on the UI thread, but notification is performed on |
452 // the IO thread. | 447 // the IO thread. |
453 void GetMimeTypeOnUI(URLDataSourceImpl* source, | 448 void GetMimeTypeOnUI(URLDataSourceImpl* source, |
454 const std::string& path, | 449 const std::string& path, |
455 const base::WeakPtr<URLRequestChromeJob>& job) { | 450 const base::WeakPtr<URLRequestChromeJob>& job) { |
456 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 451 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 URLToRequestPath(request->url(), &path); | 624 URLToRequestPath(request->url(), &path); |
630 source->source()->WillServiceRequest(request, &path); | 625 source->source()->WillServiceRequest(request, &path); |
631 | 626 |
632 // Save this request so we know where to send the data. | 627 // Save this request so we know where to send the data. |
633 RequestID request_id = next_request_id_++; | 628 RequestID request_id = next_request_id_++; |
634 pending_requests_.insert(std::make_pair(request_id, job)); | 629 pending_requests_.insert(std::make_pair(request_id, job)); |
635 | 630 |
636 job->set_allow_caching(source->source()->AllowCaching()); | 631 job->set_allow_caching(source->source()->AllowCaching()); |
637 job->set_add_content_security_policy( | 632 job->set_add_content_security_policy( |
638 source->source()->ShouldAddContentSecurityPolicy()); | 633 source->source()->ShouldAddContentSecurityPolicy()); |
| 634 job->set_content_security_policy_script_source( |
| 635 source->source()->GetContentSecurityPolicyScriptSrc()); |
639 job->set_content_security_policy_object_source( | 636 job->set_content_security_policy_object_source( |
640 source->source()->GetContentSecurityPolicyObjectSrc()); | 637 source->source()->GetContentSecurityPolicyObjectSrc()); |
641 job->set_content_security_policy_frame_source( | 638 job->set_content_security_policy_frame_source( |
642 source->source()->GetContentSecurityPolicyFrameSrc()); | 639 source->source()->GetContentSecurityPolicyFrameSrc()); |
643 job->set_deny_xframe_options( | 640 job->set_deny_xframe_options( |
644 source->source()->ShouldDenyXFrameOptions()); | 641 source->source()->ShouldDenyXFrameOptions()); |
645 job->set_send_content_type_header( | 642 job->set_send_content_type_header( |
646 source->source()->ShouldServeMimeTypeAsContentTypeHeader()); | 643 source->source()->ShouldServeMimeTypeAsContentTypeHeader()); |
647 | 644 |
648 std::string origin = GetOriginHeaderValue(request); | 645 std::string origin = GetOriginHeaderValue(request); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 | 800 |
804 } // namespace | 801 } // namespace |
805 | 802 |
806 net::URLRequestJobFactory::ProtocolHandler* | 803 net::URLRequestJobFactory::ProtocolHandler* |
807 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, | 804 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, |
808 bool is_incognito) { | 805 bool is_incognito) { |
809 return new DevToolsJobFactory(resource_context, is_incognito); | 806 return new DevToolsJobFactory(resource_context, is_incognito); |
810 } | 807 } |
811 | 808 |
812 } // namespace content | 809 } // namespace content |
OLD | NEW |