| 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/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/memory/ref_counted_memory.h" | 16 #include "base/memory/ref_counted_memory.h" |
| 17 #include "base/memory/weak_ptr.h" | 17 #include "base/memory/weak_ptr.h" |
| 18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
| 19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 20 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 21 #include "content/browser/fileapi/chrome_blob_storage_context.h" | 21 #include "content/browser/fileapi/chrome_blob_storage_context.h" |
| 22 #include "content/browser/histogram_internals_request_job.h" | 22 #include "content/browser/histogram_internals_request_job.h" |
| 23 #include "content/browser/net/view_blob_internals_job_factory.h" | 23 #include "content/browser/net/view_blob_internals_job_factory.h" |
| 24 #include "content/browser/net/view_http_cache_job_factory.h" | 24 #include "content/browser/net/view_http_cache_job_factory.h" |
| 25 #include "content/browser/resource_context_impl.h" | 25 #include "content/browser/resource_context_impl.h" |
| 26 #include "content/browser/tcmalloc_internals_request_job.h" | 26 #include "content/browser/tcmalloc_internals_request_job.h" |
| 27 #include "content/browser/webui/shared_resources_data_source.h" | 27 #include "content/browser/webui/shared_resources_data_source.h" |
| 28 #include "content/browser/webui/url_data_source_impl.h" | 28 #include "content/browser/webui/url_data_source_impl.h" |
| 29 #include "content/public/browser/browser_context.h" | |
| 30 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 31 #include "content/public/browser/content_browser_client.h" | 30 #include "content/public/browser/content_browser_client.h" |
| 32 #include "content/public/browser/render_process_host.h" | 31 #include "content/public/browser/render_process_host.h" |
| 33 #include "content/public/browser/resource_request_info.h" | 32 #include "content/public/browser/resource_request_info.h" |
| 34 #include "content/public/common/url_constants.h" | 33 #include "content/public/common/url_constants.h" |
| 35 #include "net/base/io_buffer.h" | 34 #include "net/base/io_buffer.h" |
| 36 #include "net/base/net_errors.h" | 35 #include "net/base/net_errors.h" |
| 37 #include "net/http/http_response_headers.h" | 36 #include "net/http/http_response_headers.h" |
| 38 #include "net/http/http_status_code.h" | 37 #include "net/http/http_status_code.h" |
| 39 #include "net/url_request/url_request.h" | 38 #include "net/url_request/url_request.h" |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 // Returns true when job was generated from an incognito profile. | 153 // Returns true when job was generated from an incognito profile. |
| 155 bool is_incognito() const { | 154 bool is_incognito() const { |
| 156 return is_incognito_; | 155 return is_incognito_; |
| 157 } | 156 } |
| 158 | 157 |
| 159 private: | 158 private: |
| 160 virtual ~URLRequestChromeJob(); | 159 virtual ~URLRequestChromeJob(); |
| 161 | 160 |
| 162 // Helper for Start(), to let us start asynchronously. | 161 // Helper for Start(), to let us start asynchronously. |
| 163 // (This pattern is shared by most net::URLRequestJob implementations.) | 162 // (This pattern is shared by most net::URLRequestJob implementations.) |
| 164 void StartAsync(bool allowed); | 163 void StartAsync(); |
| 165 | |
| 166 // Called on the UI thread to check if this request is allowed. | |
| 167 static void CheckStoragePartitionMatches( | |
| 168 int render_process_id, | |
| 169 const GURL& url, | |
| 170 const base::WeakPtr<URLRequestChromeJob>& job); | |
| 171 | 164 |
| 172 // Do the actual copy from data_ (the data we're serving) into |buf|. | 165 // Do the actual copy from data_ (the data we're serving) into |buf|. |
| 173 // Separate from ReadRawData so we can handle async I/O. | 166 // Separate from ReadRawData so we can handle async I/O. |
| 174 void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read); | 167 void CompleteRead(net::IOBuffer* buf, int buf_size, int* bytes_read); |
| 175 | 168 |
| 176 // The actual data we're serving. NULL until it's been fetched. | 169 // The actual data we're serving. NULL until it's been fetched. |
| 177 scoped_refptr<base::RefCountedMemory> data_; | 170 scoped_refptr<base::RefCountedMemory> data_; |
| 178 // The current offset into the data that we're handing off to our | 171 // The current offset into the data that we're handing off to our |
| 179 // callers via the Read interfaces. | 172 // callers via the Read interfaces. |
| 180 int data_offset_; | 173 int data_offset_; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 backend_(backend), | 222 backend_(backend), |
| 230 weak_factory_(this) { | 223 weak_factory_(this) { |
| 231 DCHECK(backend); | 224 DCHECK(backend); |
| 232 } | 225 } |
| 233 | 226 |
| 234 URLRequestChromeJob::~URLRequestChromeJob() { | 227 URLRequestChromeJob::~URLRequestChromeJob() { |
| 235 CHECK(!backend_->HasPendingJob(this)); | 228 CHECK(!backend_->HasPendingJob(this)); |
| 236 } | 229 } |
| 237 | 230 |
| 238 void URLRequestChromeJob::Start() { | 231 void URLRequestChromeJob::Start() { |
| 239 int render_process_id, unused; | 232 // Start reading asynchronously so that all error reporting and data |
| 240 ResourceRequestInfo::GetRenderFrameForRequest( | 233 // callbacks happen as they would for network requests. |
| 241 request_, &render_process_id, &unused); | 234 base::MessageLoop::current()->PostTask( |
| 242 BrowserThread::PostTask( | |
| 243 BrowserThread::UI, | |
| 244 FROM_HERE, | 235 FROM_HERE, |
| 245 base::Bind(&URLRequestChromeJob::CheckStoragePartitionMatches, | 236 base::Bind(&URLRequestChromeJob::StartAsync, weak_factory_.GetWeakPtr())); |
| 246 render_process_id, request_->url(), AsWeakPtr())); | 237 |
| 247 TRACE_EVENT_ASYNC_BEGIN1("browser", "DataManager:Request", this, "URL", | 238 TRACE_EVENT_ASYNC_BEGIN1("browser", "DataManager:Request", this, "URL", |
| 248 request_->url().possibly_invalid_spec()); | 239 request_->url().possibly_invalid_spec()); |
| 249 } | 240 } |
| 250 | 241 |
| 251 void URLRequestChromeJob::Kill() { | 242 void URLRequestChromeJob::Kill() { |
| 252 backend_->RemoveRequest(this); | 243 backend_->RemoveRequest(this); |
| 253 } | 244 } |
| 254 | 245 |
| 255 bool URLRequestChromeJob::GetMimeType(std::string* mime_type) const { | 246 bool URLRequestChromeJob::GetMimeType(std::string* mime_type) const { |
| 256 *mime_type = mime_type_; | 247 *mime_type = mime_type_; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 int remaining = static_cast<int>(data_->size()) - data_offset_; | 331 int remaining = static_cast<int>(data_->size()) - data_offset_; |
| 341 if (buf_size > remaining) | 332 if (buf_size > remaining) |
| 342 buf_size = remaining; | 333 buf_size = remaining; |
| 343 if (buf_size > 0) { | 334 if (buf_size > 0) { |
| 344 memcpy(buf->data(), data_->front() + data_offset_, buf_size); | 335 memcpy(buf->data(), data_->front() + data_offset_, buf_size); |
| 345 data_offset_ += buf_size; | 336 data_offset_ += buf_size; |
| 346 } | 337 } |
| 347 *bytes_read = buf_size; | 338 *bytes_read = buf_size; |
| 348 } | 339 } |
| 349 | 340 |
| 350 void URLRequestChromeJob::CheckStoragePartitionMatches( | 341 void URLRequestChromeJob::StartAsync() { |
| 351 int render_process_id, | |
| 352 const GURL& url, | |
| 353 const base::WeakPtr<URLRequestChromeJob>& job) { | |
| 354 // The embedder could put some webui pages in separate storage partition. | |
| 355 // RenderProcessHostImpl::IsSuitableHost would guard against top level pages | |
| 356 // being in the same process. We do an extra check to guard against an | |
| 357 // exploited renderer pretending to add them as a subframe. We skip this check | |
| 358 // for resources. | |
| 359 bool allowed = false; | |
| 360 if (url.SchemeIs(kChromeUIScheme) && url.host() == kChromeUIResourcesHost) { | |
| 361 allowed = true; | |
| 362 } else { | |
| 363 RenderProcessHost* process = RenderProcessHost::FromID(render_process_id); | |
| 364 if (process) { | |
| 365 StoragePartition* partition = BrowserContext::GetStoragePartitionForSite( | |
| 366 process->GetBrowserContext(), url); | |
| 367 allowed = partition == process->GetStoragePartition(); | |
| 368 } | |
| 369 } | |
| 370 | |
| 371 BrowserThread::PostTask( | |
| 372 BrowserThread::IO, | |
| 373 FROM_HERE, | |
| 374 base::Bind(&URLRequestChromeJob::StartAsync, job, allowed)); | |
| 375 } | |
| 376 | |
| 377 void URLRequestChromeJob::StartAsync(bool allowed) { | |
| 378 if (!request_) | 342 if (!request_) |
| 379 return; | 343 return; |
| 380 | 344 |
| 381 if (!allowed || !backend_->StartRequest(request_, this)) { | 345 if (!backend_->StartRequest(request_, this)) { |
| 382 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 346 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 383 net::ERR_INVALID_URL)); | 347 net::ERR_INVALID_URL)); |
| 384 } | 348 } |
| 385 } | 349 } |
| 386 | 350 |
| 387 namespace { | 351 namespace { |
| 388 | 352 |
| 389 // Gets mime type for data that is available from |source| by |path|. | 353 // Gets mime type for data that is available from |source| by |path|. |
| 390 // After that, notifies |job| that mime type is available. This method | 354 // After that, notifies |job| that mime type is available. This method |
| 391 // should be called on the UI thread, but notification is performed on | 355 // should be called on the UI thread, but notification is performed on |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 | 678 |
| 715 } // namespace | 679 } // namespace |
| 716 | 680 |
| 717 net::URLRequestJobFactory::ProtocolHandler* | 681 net::URLRequestJobFactory::ProtocolHandler* |
| 718 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, | 682 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, |
| 719 bool is_incognito) { | 683 bool is_incognito) { |
| 720 return new DevToolsJobFactory(resource_context, is_incognito); | 684 return new DevToolsJobFactory(resource_context, is_incognito); |
| 721 } | 685 } |
| 722 | 686 |
| 723 } // namespace content | 687 } // namespace content |
| OLD | NEW |