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/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
16 #include "base/memory/ref_counted.h" | 16 #include "base/memory/ref_counted.h" |
17 #include "base/memory/ref_counted_memory.h" | 17 #include "base/memory/ref_counted_memory.h" |
18 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
19 #include "base/message_loop.h" | 19 #include "base/message_loop.h" |
20 #include "base/string_util.h" | 20 #include "base/string_util.h" |
21 #include "content/browser/webui/shared_resources_data_source.h" | 21 #include "content/browser/webui/shared_resources_data_source.h" |
| 22 #include "content/browser/webui/url_data_source_impl.h" |
22 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
23 #include "content/public/common/url_constants.h" | 24 #include "content/public/common/url_constants.h" |
24 #include "googleurl/src/url_util.h" | 25 #include "googleurl/src/url_util.h" |
25 #include "net/base/io_buffer.h" | 26 #include "net/base/io_buffer.h" |
26 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
27 #include "net/http/http_response_headers.h" | 28 #include "net/http/http_response_headers.h" |
28 #include "net/url_request/url_request.h" | 29 #include "net/url_request/url_request.h" |
29 #include "net/url_request/url_request_context.h" | 30 #include "net/url_request/url_request_context.h" |
30 #include "net/url_request/url_request_job.h" | 31 #include "net/url_request/url_request_job.h" |
31 #include "net/url_request/url_request_job_factory.h" | 32 #include "net/url_request/url_request_job_factory.h" |
32 | 33 |
33 using content::BrowserThread; | 34 namespace content { |
34 | 35 |
35 namespace { | 36 namespace { |
36 | 37 |
37 // TODO(tsepez) remove unsafe-eval when bidichecker_packaged.js fixed. | 38 // TODO(tsepez) remove unsafe-eval when bidichecker_packaged.js fixed. |
38 const char kChromeURLContentSecurityPolicyHeaderBase[] = | 39 const char kChromeURLContentSecurityPolicyHeaderBase[] = |
39 "Content-Security-Policy: script-src chrome://resources " | 40 "Content-Security-Policy: script-src chrome://resources " |
40 "'self' 'unsafe-eval'; "; | 41 "'self' 'unsafe-eval'; "; |
41 | 42 |
42 const char kChromeURLXFrameOptionsHeader[] = "X-Frame-Options: DENY"; | 43 const char kChromeURLXFrameOptionsHeader[] = "X-Frame-Options: DENY"; |
43 | 44 |
(...skipping 28 matching lines...) Expand all Loading... |
72 // URLRequestChromeJob is a net::URLRequestJob that manages running | 73 // URLRequestChromeJob is a net::URLRequestJob that manages running |
73 // chrome-internal resource requests asynchronously. | 74 // chrome-internal resource requests asynchronously. |
74 // It hands off URL requests to ChromeURLDataManager, which asynchronously | 75 // It hands off URL requests to ChromeURLDataManager, which asynchronously |
75 // calls back once the data is available. | 76 // calls back once the data is available. |
76 class URLRequestChromeJob : public net::URLRequestJob, | 77 class URLRequestChromeJob : public net::URLRequestJob, |
77 public base::SupportsWeakPtr<URLRequestChromeJob> { | 78 public base::SupportsWeakPtr<URLRequestChromeJob> { |
78 public: | 79 public: |
79 // |is_incognito| set when job is generated from an incognito profile. | 80 // |is_incognito| set when job is generated from an incognito profile. |
80 URLRequestChromeJob(net::URLRequest* request, | 81 URLRequestChromeJob(net::URLRequest* request, |
81 net::NetworkDelegate* network_delegate, | 82 net::NetworkDelegate* network_delegate, |
82 ChromeURLDataManagerBackend* backend, | 83 URLDataManagerBackend* backend, |
83 bool is_incognito); | 84 bool is_incognito); |
84 | 85 |
85 // net::URLRequestJob implementation. | 86 // net::URLRequestJob implementation. |
86 virtual void Start() OVERRIDE; | 87 virtual void Start() OVERRIDE; |
87 virtual void Kill() OVERRIDE; | 88 virtual void Kill() OVERRIDE; |
88 virtual bool ReadRawData(net::IOBuffer* buf, | 89 virtual bool ReadRawData(net::IOBuffer* buf, |
89 int buf_size, | 90 int buf_size, |
90 int* bytes_read) OVERRIDE; | 91 int* bytes_read) OVERRIDE; |
91 virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; | 92 virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; |
92 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE; | 93 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 std::string content_security_policy_object_source_; | 163 std::string content_security_policy_object_source_; |
163 std::string content_security_policy_frame_source_; | 164 std::string content_security_policy_frame_source_; |
164 | 165 |
165 // If true, sets the "X-Frame-Options: DENY" header. | 166 // If true, sets the "X-Frame-Options: DENY" header. |
166 bool deny_xframe_options_; | 167 bool deny_xframe_options_; |
167 | 168 |
168 // True when job is generated from an incognito profile. | 169 // True when job is generated from an incognito profile. |
169 const bool is_incognito_; | 170 const bool is_incognito_; |
170 | 171 |
171 // The backend is owned by ChromeURLRequestContext and always outlives us. | 172 // The backend is owned by ChromeURLRequestContext and always outlives us. |
172 ChromeURLDataManagerBackend* backend_; | 173 URLDataManagerBackend* backend_; |
173 | 174 |
174 base::WeakPtrFactory<URLRequestChromeJob> weak_factory_; | 175 base::WeakPtrFactory<URLRequestChromeJob> weak_factory_; |
175 | 176 |
176 DISALLOW_COPY_AND_ASSIGN(URLRequestChromeJob); | 177 DISALLOW_COPY_AND_ASSIGN(URLRequestChromeJob); |
177 }; | 178 }; |
178 | 179 |
179 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, | 180 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, |
180 net::NetworkDelegate* network_delegate, | 181 net::NetworkDelegate* network_delegate, |
181 ChromeURLDataManagerBackend* backend, | 182 URLDataManagerBackend* backend, |
182 bool is_incognito) | 183 bool is_incognito) |
183 : net::URLRequestJob(request, network_delegate), | 184 : net::URLRequestJob(request, network_delegate), |
184 data_offset_(0), | 185 data_offset_(0), |
185 pending_buf_size_(0), | 186 pending_buf_size_(0), |
186 allow_caching_(true), | 187 allow_caching_(true), |
187 add_content_security_policy_(true), | 188 add_content_security_policy_(true), |
188 content_security_policy_object_source_("object-src 'none';"), | 189 content_security_policy_object_source_("object-src 'none';"), |
189 content_security_policy_frame_source_("frame-src 'none';"), | 190 content_security_policy_frame_source_("frame-src 'none';"), |
190 deny_xframe_options_(true), | 191 deny_xframe_options_(true), |
191 is_incognito_(is_incognito), | 192 is_incognito_(is_incognito), |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 } | 326 } |
326 | 327 |
327 } // namespace | 328 } // namespace |
328 | 329 |
329 namespace { | 330 namespace { |
330 | 331 |
331 class ChromeProtocolHandler | 332 class ChromeProtocolHandler |
332 : public net::URLRequestJobFactory::ProtocolHandler { | 333 : public net::URLRequestJobFactory::ProtocolHandler { |
333 public: | 334 public: |
334 // |is_incognito| should be set for incognito profiles. | 335 // |is_incognito| should be set for incognito profiles. |
335 explicit ChromeProtocolHandler(ChromeURLDataManagerBackend* backend, | 336 explicit ChromeProtocolHandler(URLDataManagerBackend* backend, |
336 bool is_incognito); | 337 bool is_incognito); |
337 ~ChromeProtocolHandler(); | 338 ~ChromeProtocolHandler(); |
338 | 339 |
339 virtual net::URLRequestJob* MaybeCreateJob( | 340 virtual net::URLRequestJob* MaybeCreateJob( |
340 net::URLRequest* request, | 341 net::URLRequest* request, |
341 net::NetworkDelegate* network_delegate) const OVERRIDE; | 342 net::NetworkDelegate* network_delegate) const OVERRIDE; |
342 | 343 |
343 private: | 344 private: |
344 // These members are owned by ProfileIOData, which owns this ProtocolHandler. | 345 // These members are owned by ProfileIOData, which owns this ProtocolHandler. |
345 ChromeURLDataManagerBackend* const backend_; | 346 URLDataManagerBackend* const backend_; |
346 | 347 |
347 // True when generated from an incognito profile. | 348 // True when generated from an incognito profile. |
348 const bool is_incognito_; | 349 const bool is_incognito_; |
349 | 350 |
350 DISALLOW_COPY_AND_ASSIGN(ChromeProtocolHandler); | 351 DISALLOW_COPY_AND_ASSIGN(ChromeProtocolHandler); |
351 }; | 352 }; |
352 | 353 |
353 ChromeProtocolHandler::ChromeProtocolHandler( | 354 ChromeProtocolHandler::ChromeProtocolHandler( |
354 ChromeURLDataManagerBackend* backend, bool is_incognito) | 355 URLDataManagerBackend* backend, bool is_incognito) |
355 : backend_(backend), is_incognito_(is_incognito) {} | 356 : backend_(backend), is_incognito_(is_incognito) {} |
356 | 357 |
357 ChromeProtocolHandler::~ChromeProtocolHandler() {} | 358 ChromeProtocolHandler::~ChromeProtocolHandler() {} |
358 | 359 |
359 net::URLRequestJob* ChromeProtocolHandler::MaybeCreateJob( | 360 net::URLRequestJob* ChromeProtocolHandler::MaybeCreateJob( |
360 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { | 361 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { |
361 DCHECK(request); | 362 DCHECK(request); |
362 | 363 |
363 // Fall back to using a custom handler | 364 // Fall back to using a custom handler |
364 return new URLRequestChromeJob(request, network_delegate, backend_, | 365 return new URLRequestChromeJob(request, network_delegate, backend_, |
365 is_incognito_); | 366 is_incognito_); |
366 } | 367 } |
367 | 368 |
368 } // namespace | 369 } // namespace |
369 | 370 |
370 ChromeURLDataManagerBackend::ChromeURLDataManagerBackend() | 371 URLDataManagerBackend::URLDataManagerBackend() |
371 : next_request_id_(0) { | 372 : next_request_id_(0) { |
372 content::URLDataSource* shared_source = new SharedResourcesDataSource(); | 373 URLDataSource* shared_source = new SharedResourcesDataSource(); |
373 URLDataSourceImpl* source_impl = | 374 URLDataSourceImpl* source_impl = |
374 new URLDataSourceImpl(shared_source->GetSource(), shared_source); | 375 new URLDataSourceImpl(shared_source->GetSource(), shared_source); |
375 AddDataSource(source_impl); | 376 AddDataSource(source_impl); |
376 } | 377 } |
377 | 378 |
378 ChromeURLDataManagerBackend::~ChromeURLDataManagerBackend() { | 379 URLDataManagerBackend::~URLDataManagerBackend() { |
379 for (DataSourceMap::iterator i = data_sources_.begin(); | 380 for (DataSourceMap::iterator i = data_sources_.begin(); |
380 i != data_sources_.end(); ++i) { | 381 i != data_sources_.end(); ++i) { |
381 i->second->backend_ = NULL; | 382 i->second->backend_ = NULL; |
382 } | 383 } |
383 data_sources_.clear(); | 384 data_sources_.clear(); |
384 } | 385 } |
385 | 386 |
386 // static | 387 // static |
387 net::URLRequestJobFactory::ProtocolHandler* | 388 net::URLRequestJobFactory::ProtocolHandler* |
388 ChromeURLDataManagerBackend::CreateProtocolHandler( | 389 URLDataManagerBackend::CreateProtocolHandler( |
389 ChromeURLDataManagerBackend* backend, bool is_incognito) { | 390 URLDataManagerBackend* backend, bool is_incognito) { |
390 DCHECK(backend); | 391 DCHECK(backend); |
391 return new ChromeProtocolHandler(backend, is_incognito); | 392 return new ChromeProtocolHandler(backend, is_incognito); |
392 } | 393 } |
393 | 394 |
394 void ChromeURLDataManagerBackend::AddDataSource( | 395 void URLDataManagerBackend::AddDataSource( |
395 URLDataSourceImpl* source) { | 396 URLDataSourceImpl* source) { |
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
397 DataSourceMap::iterator i = data_sources_.find(source->source_name()); | 398 DataSourceMap::iterator i = data_sources_.find(source->source_name()); |
398 if (i != data_sources_.end()) { | 399 if (i != data_sources_.end()) { |
399 if (!source->source()->ShouldReplaceExistingSource()) | 400 if (!source->source()->ShouldReplaceExistingSource()) |
400 return; | 401 return; |
401 i->second->backend_ = NULL; | 402 i->second->backend_ = NULL; |
402 } | 403 } |
403 data_sources_[source->source_name()] = source; | 404 data_sources_[source->source_name()] = source; |
404 source->backend_ = this; | 405 source->backend_ = this; |
405 } | 406 } |
406 | 407 |
407 bool ChromeURLDataManagerBackend::HasPendingJob( | 408 bool URLDataManagerBackend::HasPendingJob( |
408 URLRequestChromeJob* job) const { | 409 URLRequestChromeJob* job) const { |
409 for (PendingRequestMap::const_iterator i = pending_requests_.begin(); | 410 for (PendingRequestMap::const_iterator i = pending_requests_.begin(); |
410 i != pending_requests_.end(); ++i) { | 411 i != pending_requests_.end(); ++i) { |
411 if (i->second == job) | 412 if (i->second == job) |
412 return true; | 413 return true; |
413 } | 414 } |
414 return false; | 415 return false; |
415 } | 416 } |
416 | 417 |
417 bool ChromeURLDataManagerBackend::StartRequest(const GURL& url, | 418 bool URLDataManagerBackend::StartRequest(const GURL& url, |
418 URLRequestChromeJob* job) { | 419 URLRequestChromeJob* job) { |
419 // Parse the URL into a request for a source and path. | 420 // Parse the URL into a request for a source and path. |
420 std::string source_name; | 421 std::string source_name; |
421 std::string path; | 422 std::string path; |
422 URLToRequest(url, &source_name, &path); | 423 URLToRequest(url, &source_name, &path); |
423 | 424 |
424 // Look up the data source for the request. | 425 // Look up the data source for the request. |
425 DataSourceMap::iterator i = data_sources_.find(source_name); | 426 DataSourceMap::iterator i = data_sources_.find(source_name); |
426 if (i == data_sources_.end()) | 427 if (i == data_sources_.end()) |
427 return false; | 428 return false; |
428 | 429 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 target_message_loop->PostTask( | 466 target_message_loop->PostTask( |
466 FROM_HERE, | 467 FROM_HERE, |
467 base::Bind(&GetMimeTypeOnUI, | 468 base::Bind(&GetMimeTypeOnUI, |
468 scoped_refptr<URLDataSourceImpl>(source), | 469 scoped_refptr<URLDataSourceImpl>(source), |
469 path, job->AsWeakPtr())); | 470 path, job->AsWeakPtr())); |
470 | 471 |
471 // The DataSource wants StartDataRequest to be called on a specific thread, | 472 // The DataSource wants StartDataRequest to be called on a specific thread, |
472 // usually the UI thread, for this path. | 473 // usually the UI thread, for this path. |
473 target_message_loop->PostTask( | 474 target_message_loop->PostTask( |
474 FROM_HERE, | 475 FROM_HERE, |
475 base::Bind(&ChromeURLDataManagerBackend::CallStartRequest, | 476 base::Bind(&URLDataManagerBackend::CallStartRequest, |
476 make_scoped_refptr(source), path, job->is_incognito(), | 477 make_scoped_refptr(source), path, job->is_incognito(), |
477 request_id)); | 478 request_id)); |
478 } | 479 } |
479 return true; | 480 return true; |
480 } | 481 } |
481 | 482 |
482 void ChromeURLDataManagerBackend::CallStartRequest( | 483 void URLDataManagerBackend::CallStartRequest( |
483 scoped_refptr<URLDataSourceImpl> source, | 484 scoped_refptr<URLDataSourceImpl> source, |
484 const std::string& path, | 485 const std::string& path, |
485 bool is_incognito, | 486 bool is_incognito, |
486 int request_id) { | 487 int request_id) { |
487 source->source()->StartDataRequest( | 488 source->source()->StartDataRequest( |
488 path, | 489 path, |
489 is_incognito, | 490 is_incognito, |
490 base::Bind(&URLDataSourceImpl::SendResponse, source, request_id)); | 491 base::Bind(&URLDataSourceImpl::SendResponse, source, request_id)); |
491 } | 492 } |
492 | 493 |
493 void ChromeURLDataManagerBackend::RemoveRequest(URLRequestChromeJob* job) { | 494 void URLDataManagerBackend::RemoveRequest(URLRequestChromeJob* job) { |
494 // Remove the request from our list of pending requests. | 495 // Remove the request from our list of pending requests. |
495 // If/when the source sends the data that was requested, the data will just | 496 // If/when the source sends the data that was requested, the data will just |
496 // be thrown away. | 497 // be thrown away. |
497 for (PendingRequestMap::iterator i = pending_requests_.begin(); | 498 for (PendingRequestMap::iterator i = pending_requests_.begin(); |
498 i != pending_requests_.end(); ++i) { | 499 i != pending_requests_.end(); ++i) { |
499 if (i->second == job) { | 500 if (i->second == job) { |
500 pending_requests_.erase(i); | 501 pending_requests_.erase(i); |
501 return; | 502 return; |
502 } | 503 } |
503 } | 504 } |
504 } | 505 } |
505 | 506 |
506 void ChromeURLDataManagerBackend::DataAvailable(RequestID request_id, | 507 void URLDataManagerBackend::DataAvailable(RequestID request_id, |
507 base::RefCountedMemory* bytes) { | 508 base::RefCountedMemory* bytes) { |
508 // Forward this data on to the pending net::URLRequest, if it exists. | 509 // Forward this data on to the pending net::URLRequest, if it exists. |
509 PendingRequestMap::iterator i = pending_requests_.find(request_id); | 510 PendingRequestMap::iterator i = pending_requests_.find(request_id); |
510 if (i != pending_requests_.end()) { | 511 if (i != pending_requests_.end()) { |
511 URLRequestChromeJob* job(i->second); | 512 URLRequestChromeJob* job(i->second); |
512 pending_requests_.erase(i); | 513 pending_requests_.erase(i); |
513 job->DataAvailable(bytes); | 514 job->DataAvailable(bytes); |
514 } | 515 } |
515 } | 516 } |
516 | 517 |
517 namespace { | 518 namespace { |
518 | 519 |
519 class DevToolsJobFactory | 520 class DevToolsJobFactory |
520 : public net::URLRequestJobFactory::ProtocolHandler { | 521 : public net::URLRequestJobFactory::ProtocolHandler { |
521 public: | 522 public: |
522 // |is_incognito| should be set for incognito profiles. | 523 // |is_incognito| should be set for incognito profiles. |
523 DevToolsJobFactory(ChromeURLDataManagerBackend* backend, | 524 DevToolsJobFactory(URLDataManagerBackend* backend, |
524 bool is_incognito); | 525 bool is_incognito); |
525 virtual ~DevToolsJobFactory(); | 526 virtual ~DevToolsJobFactory(); |
526 | 527 |
527 virtual net::URLRequestJob* MaybeCreateJob( | 528 virtual net::URLRequestJob* MaybeCreateJob( |
528 net::URLRequest* request, | 529 net::URLRequest* request, |
529 net::NetworkDelegate* network_delegate) const OVERRIDE; | 530 net::NetworkDelegate* network_delegate) const OVERRIDE; |
530 | 531 |
531 private: | 532 private: |
532 // |backend_| and |network_delegate_| are owned by ProfileIOData, which owns | 533 // |backend_| and |network_delegate_| are owned by ProfileIOData, which owns |
533 // this ProtocolHandler. | 534 // this ProtocolHandler. |
534 ChromeURLDataManagerBackend* const backend_; | 535 URLDataManagerBackend* const backend_; |
535 | 536 |
536 // True when generated from an incognito profile. | 537 // True when generated from an incognito profile. |
537 const bool is_incognito_; | 538 const bool is_incognito_; |
538 | 539 |
539 DISALLOW_COPY_AND_ASSIGN(DevToolsJobFactory); | 540 DISALLOW_COPY_AND_ASSIGN(DevToolsJobFactory); |
540 }; | 541 }; |
541 | 542 |
542 DevToolsJobFactory::DevToolsJobFactory(ChromeURLDataManagerBackend* backend, | 543 DevToolsJobFactory::DevToolsJobFactory(URLDataManagerBackend* backend, |
543 bool is_incognito) | 544 bool is_incognito) |
544 : backend_(backend), | 545 : backend_(backend), |
545 is_incognito_(is_incognito) { | 546 is_incognito_(is_incognito) { |
546 DCHECK(backend_); | 547 DCHECK(backend_); |
547 } | 548 } |
548 | 549 |
549 DevToolsJobFactory::~DevToolsJobFactory() {} | 550 DevToolsJobFactory::~DevToolsJobFactory() {} |
550 | 551 |
551 net::URLRequestJob* | 552 net::URLRequestJob* |
552 DevToolsJobFactory::MaybeCreateJob( | 553 DevToolsJobFactory::MaybeCreateJob( |
553 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { | 554 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { |
554 return new URLRequestChromeJob(request, network_delegate, backend_, | 555 return new URLRequestChromeJob(request, network_delegate, backend_, |
555 is_incognito_); | 556 is_incognito_); |
556 } | 557 } |
557 | 558 |
558 } // namespace | 559 } // namespace |
559 | 560 |
560 net::URLRequestJobFactory::ProtocolHandler* | 561 net::URLRequestJobFactory::ProtocolHandler* |
561 CreateDevToolsProtocolHandler(ChromeURLDataManagerBackend* backend, | 562 CreateDevToolsProtocolHandler(URLDataManagerBackend* backend, |
562 bool is_incognito) { | 563 bool is_incognito) { |
563 return new DevToolsJobFactory(backend, is_incognito); | 564 return new DevToolsJobFactory(backend, is_incognito); |
564 } | 565 } |
| 566 |
| 567 } // namespace content |
OLD | NEW |