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" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 "Content-Security-Policy: script-src chrome://resources " | 53 "Content-Security-Policy: script-src chrome://resources " |
54 "'self' 'unsafe-eval'; "; | 54 "'self' 'unsafe-eval'; "; |
55 | 55 |
56 const char kChromeURLXFrameOptionsHeader[] = "X-Frame-Options: DENY"; | 56 const char kChromeURLXFrameOptionsHeader[] = "X-Frame-Options: DENY"; |
57 | 57 |
58 bool SchemeIsInSchemes(const std::string& scheme, | 58 bool SchemeIsInSchemes(const std::string& scheme, |
59 const std::vector<std::string>& schemes) { | 59 const std::vector<std::string>& schemes) { |
60 return std::find(schemes.begin(), schemes.end(), scheme) != schemes.end(); | 60 return std::find(schemes.begin(), schemes.end(), scheme) != schemes.end(); |
61 } | 61 } |
62 | 62 |
63 // Parse a URL into the components used to resolve its request. |source_name| | 63 // Returns whether |url| passes some sanity checks and is a valid GURL. |
64 // is the hostname and |path| is the remaining portion of the URL. | 64 bool CheckURLIsValid(const GURL& url) { |
65 void URLToRequest(const GURL& url, std::string* source_name, | |
66 std::string* path) { | |
67 std::vector<std::string> additional_schemes; | 65 std::vector<std::string> additional_schemes; |
68 DCHECK(url.SchemeIs(chrome::kChromeDevToolsScheme) || | 66 DCHECK(url.SchemeIs(chrome::kChromeDevToolsScheme) || |
69 url.SchemeIs(chrome::kChromeUIScheme) || | 67 url.SchemeIs(chrome::kChromeUIScheme) || |
70 (GetContentClient()->browser()->GetAdditionalWebUISchemes( | 68 (GetContentClient()->browser()->GetAdditionalWebUISchemes( |
71 &additional_schemes), | 69 &additional_schemes), |
72 SchemeIsInSchemes(url.scheme(), additional_schemes))); | 70 SchemeIsInSchemes(url.scheme(), additional_schemes))); |
73 | 71 |
74 if (!url.is_valid()) { | 72 if (!url.is_valid()) { |
75 NOTREACHED(); | 73 NOTREACHED(); |
76 return; | 74 return false; |
77 } | 75 } |
78 | 76 |
79 // Our input looks like: chrome://source_name/extra_bits?foo . | 77 return true; |
80 // So the url's "host" is our source, and everything after the host is | 78 } |
81 // the path. | |
82 source_name->assign(url.host()); | |
83 | 79 |
| 80 // Parse |url| to get the path which will be used to resolve the request. The |
| 81 // path is the remaining portion after the scheme and hostname. |
| 82 void URLToRequestPath(const GURL& url, std::string* path) { |
84 const std::string& spec = url.possibly_invalid_spec(); | 83 const std::string& spec = url.possibly_invalid_spec(); |
85 const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec(); | 84 const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec(); |
86 // + 1 to skip the slash at the beginning of the path. | 85 // + 1 to skip the slash at the beginning of the path. |
87 int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false) + 1; | 86 int offset = parsed.CountCharactersBefore(url_parse::Parsed::PATH, false) + 1; |
88 | 87 |
89 if (offset < static_cast<int>(spec.size())) | 88 if (offset < static_cast<int>(spec.size())) |
90 path->assign(spec.substr(offset)); | 89 path->assign(spec.substr(offset)); |
91 } | 90 } |
92 | 91 |
93 } // namespace | 92 } // namespace |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 for (PendingRequestMap::const_iterator i = pending_requests_.begin(); | 490 for (PendingRequestMap::const_iterator i = pending_requests_.begin(); |
492 i != pending_requests_.end(); ++i) { | 491 i != pending_requests_.end(); ++i) { |
493 if (i->second == job) | 492 if (i->second == job) |
494 return true; | 493 return true; |
495 } | 494 } |
496 return false; | 495 return false; |
497 } | 496 } |
498 | 497 |
499 bool URLDataManagerBackend::StartRequest(const net::URLRequest* request, | 498 bool URLDataManagerBackend::StartRequest(const net::URLRequest* request, |
500 URLRequestChromeJob* job) { | 499 URLRequestChromeJob* job) { |
501 // Parse the URL into a request for a source and path. | 500 if (!CheckURLIsValid(request->url())) |
502 std::string source_name; | |
503 std::string path; | |
504 URLToRequest(request->url(), &source_name, &path); | |
505 | |
506 // Look up the data source for the request. | |
507 DataSourceMap::iterator i = data_sources_.find(source_name); | |
508 if (i == data_sources_.end()) | |
509 return false; | 501 return false; |
510 | 502 |
511 URLDataSourceImpl* source = i->second.get(); | 503 URLDataSourceImpl* source = GetDataSourceFromURL(request->url()); |
| 504 if (!source) |
| 505 return false; |
512 | 506 |
513 if (!source->source()->ShouldServiceRequest(request)) | 507 if (!source->source()->ShouldServiceRequest(request)) |
514 return false; | 508 return false; |
| 509 |
| 510 std::string path; |
| 511 URLToRequestPath(request->url(), &path); |
515 source->source()->WillServiceRequest(request, &path); | 512 source->source()->WillServiceRequest(request, &path); |
516 | 513 |
517 // Save this request so we know where to send the data. | 514 // Save this request so we know where to send the data. |
518 RequestID request_id = next_request_id_++; | 515 RequestID request_id = next_request_id_++; |
519 pending_requests_.insert(std::make_pair(request_id, job)); | 516 pending_requests_.insert(std::make_pair(request_id, job)); |
520 | 517 |
521 job->set_allow_caching(source->source()->AllowCaching()); | 518 job->set_allow_caching(source->source()->AllowCaching()); |
522 job->set_add_content_security_policy( | 519 job->set_add_content_security_policy( |
523 source->source()->ShouldAddContentSecurityPolicy()); | 520 source->source()->ShouldAddContentSecurityPolicy()); |
524 job->set_content_security_policy_object_source( | 521 job->set_content_security_policy_object_source( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 // usually the UI thread, for this path. | 563 // usually the UI thread, for this path. |
567 target_message_loop->PostTask( | 564 target_message_loop->PostTask( |
568 FROM_HERE, | 565 FROM_HERE, |
569 base::Bind(&URLDataManagerBackend::CallStartRequest, | 566 base::Bind(&URLDataManagerBackend::CallStartRequest, |
570 make_scoped_refptr(source), path, render_process_id, | 567 make_scoped_refptr(source), path, render_process_id, |
571 render_frame_id, request_id)); | 568 render_frame_id, request_id)); |
572 } | 569 } |
573 return true; | 570 return true; |
574 } | 571 } |
575 | 572 |
| 573 URLDataSourceImpl* URLDataManagerBackend::GetDataSourceFromURL( |
| 574 const GURL& url) { |
| 575 // The input usually looks like: chrome://source_name/extra_bits?foo |
| 576 // so do a lookup using the host of the URL. |
| 577 DataSourceMap::iterator i = data_sources_.find(url.host()); |
| 578 if (i != data_sources_.end()) |
| 579 return i->second.get(); |
| 580 |
| 581 // No match using the host of the URL, so do a lookup using the scheme for |
| 582 // URLs on the form source_name://extra_bits/foo . |
| 583 i = data_sources_.find(url.scheme()); |
| 584 if (i != data_sources_.end()) |
| 585 return i->second.get(); |
| 586 |
| 587 // No matches found, so give up. |
| 588 return NULL; |
| 589 } |
| 590 |
576 void URLDataManagerBackend::CallStartRequest( | 591 void URLDataManagerBackend::CallStartRequest( |
577 scoped_refptr<URLDataSourceImpl> source, | 592 scoped_refptr<URLDataSourceImpl> source, |
578 const std::string& path, | 593 const std::string& path, |
579 int render_process_id, | 594 int render_process_id, |
580 int render_frame_id, | 595 int render_frame_id, |
581 int request_id) { | 596 int request_id) { |
582 if (BrowserThread::CurrentlyOn(BrowserThread::UI) && | 597 if (BrowserThread::CurrentlyOn(BrowserThread::UI) && |
583 render_process_id != -1 && | 598 render_process_id != -1 && |
584 !RenderProcessHost::FromID(render_process_id)) { | 599 !RenderProcessHost::FromID(render_process_id)) { |
585 // Make the request fail if its initiating renderer is no longer valid. | 600 // Make the request fail if its initiating renderer is no longer valid. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 | 679 |
665 } // namespace | 680 } // namespace |
666 | 681 |
667 net::URLRequestJobFactory::ProtocolHandler* | 682 net::URLRequestJobFactory::ProtocolHandler* |
668 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, | 683 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, |
669 bool is_incognito) { | 684 bool is_incognito) { |
670 return new DevToolsJobFactory(resource_context, is_incognito); | 685 return new DevToolsJobFactory(resource_context, is_incognito); |
671 } | 686 } |
672 | 687 |
673 } // namespace content | 688 } // namespace content |
OLD | NEW |