| 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" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/debug/alias.h" | 12 #include "base/debug/alias.h" |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/location.h" | 14 #include "base/location.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
| 17 #include "base/memory/ref_counted.h" | 17 #include "base/memory/ref_counted.h" |
| 18 #include "base/memory/ref_counted_memory.h" | 18 #include "base/memory/ref_counted_memory.h" |
| 19 #include "base/memory/weak_ptr.h" | 19 #include "base/memory/weak_ptr.h" |
| 20 #include "base/profiler/scoped_tracker.h" | 20 #include "base/profiler/scoped_tracker.h" |
| 21 #include "base/single_thread_task_runner.h" | 21 #include "base/single_thread_task_runner.h" |
| 22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
| 24 #include "base/strings/stringprintf.h" | 24 #include "base/strings/stringprintf.h" |
| 25 #include "base/threading/worker_pool.h" | |
| 26 #include "base/trace_event/trace_event.h" | 25 #include "base/trace_event/trace_event.h" |
| 27 #include "content/browser/blob_storage/chrome_blob_storage_context.h" | 26 #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
| 28 #include "content/browser/histogram_internals_request_job.h" | 27 #include "content/browser/histogram_internals_request_job.h" |
| 29 #include "content/browser/net/view_blob_internals_job_factory.h" | 28 #include "content/browser/net/view_blob_internals_job_factory.h" |
| 30 #include "content/browser/net/view_http_cache_job_factory.h" | 29 #include "content/browser/net/view_http_cache_job_factory.h" |
| 31 #include "content/browser/resource_context_impl.h" | 30 #include "content/browser/resource_context_impl.h" |
| 32 #include "content/browser/webui/shared_resources_data_source.h" | 31 #include "content/browser/webui/shared_resources_data_source.h" |
| 33 #include "content/browser/webui/url_data_source_impl.h" | 32 #include "content/browser/webui/url_data_source_impl.h" |
| 34 #include "content/public/browser/browser_context.h" | 33 #include "content/public/browser/browser_context.h" |
| 35 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 std::string result; | 97 std::string result; |
| 99 if (request->extra_request_headers().GetHeader( | 98 if (request->extra_request_headers().GetHeader( |
| 100 net::HttpRequestHeaders::kOrigin, &result)) | 99 net::HttpRequestHeaders::kOrigin, &result)) |
| 101 return result; | 100 return result; |
| 102 net::HttpRequestHeaders headers; | 101 net::HttpRequestHeaders headers; |
| 103 if (request->GetFullRequestHeaders(&headers)) | 102 if (request->GetFullRequestHeaders(&headers)) |
| 104 headers.GetHeader(net::HttpRequestHeaders::kOrigin, &result); | 103 headers.GetHeader(net::HttpRequestHeaders::kOrigin, &result); |
| 105 return result; | 104 return result; |
| 106 } | 105 } |
| 107 | 106 |
| 108 // Copy data from source buffer into IO buffer destination. | |
| 109 // TODO(groby): Very similar to URLRequestSimpleJob, unify at some point. | |
| 110 void CopyData(const scoped_refptr<net::IOBuffer>& buf, | |
| 111 int buf_size, | |
| 112 const scoped_refptr<base::RefCountedMemory>& data, | |
| 113 int64_t data_offset) { | |
| 114 // TODO(pkasting): Remove ScopedTracker below once crbug.com/455423 is | |
| 115 // fixed. | |
| 116 tracked_objects::ScopedTracker tracking_profile( | |
| 117 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 118 "455423 URLRequestChromeJob::CompleteRead memcpy")); | |
| 119 memcpy(buf->data(), data->front() + data_offset, buf_size); | |
| 120 } | |
| 121 | |
| 122 } // namespace | 107 } // namespace |
| 123 | 108 |
| 124 // URLRequestChromeJob is a net::URLRequestJob that manages running | 109 // URLRequestChromeJob is a net::URLRequestJob that manages running |
| 125 // chrome-internal resource requests asynchronously. | 110 // chrome-internal resource requests asynchronously. |
| 126 // It hands off URL requests to ChromeURLDataManager, which asynchronously | 111 // It hands off URL requests to ChromeURLDataManager, which asynchronously |
| 127 // calls back once the data is available. | 112 // calls back once the data is available. |
| 128 class URLRequestChromeJob : public net::URLRequestJob { | 113 class URLRequestChromeJob : public net::URLRequestJob { |
| 129 public: | 114 public: |
| 130 // |is_incognito| set when job is generated from an incognito profile. | 115 // |is_incognito| set when job is generated from an incognito profile. |
| 131 URLRequestChromeJob(net::URLRequest* request, | 116 URLRequestChromeJob(net::URLRequest* request, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 // (This pattern is shared by most net::URLRequestJob implementations.) | 197 // (This pattern is shared by most net::URLRequestJob implementations.) |
| 213 void StartAsync(); | 198 void StartAsync(); |
| 214 | 199 |
| 215 // Due to a race condition, DevTools relies on a legacy thread hop to the UI | 200 // Due to a race condition, DevTools relies on a legacy thread hop to the UI |
| 216 // thread before calling StartAsync. | 201 // thread before calling StartAsync. |
| 217 // TODO(caseq): Fix the race condition and remove this thread hop in | 202 // TODO(caseq): Fix the race condition and remove this thread hop in |
| 218 // https://crbug.com/616641. | 203 // https://crbug.com/616641. |
| 219 static void DelayStartForDevTools( | 204 static void DelayStartForDevTools( |
| 220 const base::WeakPtr<URLRequestChromeJob>& job); | 205 const base::WeakPtr<URLRequestChromeJob>& job); |
| 221 | 206 |
| 222 // Post a task to copy |data_| to |buf_| on a worker thread, to avoid browser | 207 // Do the actual copy from data_ (the data we're serving) into |buf|. |
| 223 // jank. (|data_| might be mem-mapped, so a memcpy can trigger file ops). | 208 // Separate from ReadRawData so we can handle async I/O. Returns the number of |
| 224 int PostReadTask(net::IOBuffer* buf, int buf_size); | 209 // bytes read. |
| 210 int CompleteRead(net::IOBuffer* buf, int buf_size); |
| 225 | 211 |
| 226 // The actual data we're serving. NULL until it's been fetched. | 212 // The actual data we're serving. NULL until it's been fetched. |
| 227 scoped_refptr<base::RefCountedMemory> data_; | 213 scoped_refptr<base::RefCountedMemory> data_; |
| 228 // The current offset into the data that we're handing off to our | 214 // The current offset into the data that we're handing off to our |
| 229 // callers via the Read interfaces. | 215 // callers via the Read interfaces. |
| 230 int data_offset_; | 216 int data_offset_; |
| 231 | 217 |
| 232 // For async reads, we keep around a pointer to the buffer that | 218 // For async reads, we keep around a pointer to the buffer that |
| 233 // we're reading into. | 219 // we're reading into. |
| 234 scoped_refptr<net::IOBuffer> pending_buf_; | 220 scoped_refptr<net::IOBuffer> pending_buf_; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 } | 357 } |
| 372 } | 358 } |
| 373 | 359 |
| 374 void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) { | 360 void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) { |
| 375 set_mime_type(mime_type); | 361 set_mime_type(mime_type); |
| 376 NotifyHeadersComplete(); | 362 NotifyHeadersComplete(); |
| 377 } | 363 } |
| 378 | 364 |
| 379 void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { | 365 void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { |
| 380 TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); | 366 TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); |
| 381 DCHECK(!data_); | 367 if (bytes) { |
| 382 | 368 data_ = bytes; |
| 383 // A passed-in nullptr signals an error. | 369 if (pending_buf_.get()) { |
| 384 if (!bytes) { | 370 CHECK(pending_buf_->data()); |
| 371 int result = CompleteRead(pending_buf_.get(), pending_buf_size_); |
| 372 pending_buf_ = NULL; |
| 373 ReadRawDataComplete(result); |
| 374 } |
| 375 } else { |
| 376 // The request failed. |
| 385 ReadRawDataComplete(net::ERR_FAILED); | 377 ReadRawDataComplete(net::ERR_FAILED); |
| 386 return; | |
| 387 } | |
| 388 | |
| 389 // All further requests will be satisfied from the passed-in data. | |
| 390 data_ = bytes; | |
| 391 | |
| 392 if (pending_buf_) { | |
| 393 int result = PostReadTask(pending_buf_.get(), pending_buf_size_); | |
| 394 if (result != net::ERR_IO_PENDING) | |
| 395 ReadRawDataComplete(result); | |
| 396 pending_buf_ = nullptr; | |
| 397 } | 378 } |
| 398 } | 379 } |
| 399 | 380 |
| 400 base::WeakPtr<URLRequestChromeJob> URLRequestChromeJob::AsWeakPtr() { | 381 base::WeakPtr<URLRequestChromeJob> URLRequestChromeJob::AsWeakPtr() { |
| 401 return weak_factory_.GetWeakPtr(); | 382 return weak_factory_.GetWeakPtr(); |
| 402 } | 383 } |
| 403 | 384 |
| 404 int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { | 385 int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { |
| 405 DCHECK(!pending_buf_.get()); | |
| 406 | |
| 407 // If data isn't available yet, mark this as asynchronous. | |
| 408 if (!data_.get()) { | 386 if (!data_.get()) { |
| 387 DCHECK(!pending_buf_.get()); |
| 388 CHECK(buf->data()); |
| 409 pending_buf_ = buf; | 389 pending_buf_ = buf; |
| 410 pending_buf_size_ = buf_size; | 390 pending_buf_size_ = buf_size; |
| 411 return net::ERR_IO_PENDING; | 391 return net::ERR_IO_PENDING; |
| 412 } | 392 } |
| 413 | 393 |
| 414 return PostReadTask(buf, buf_size); | 394 // Otherwise, the data is available. |
| 395 return CompleteRead(buf, buf_size); |
| 415 } | 396 } |
| 416 | 397 |
| 417 int URLRequestChromeJob::PostReadTask(net::IOBuffer* buf, int buf_size) { | 398 int URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size) { |
| 418 DCHECK(buf); | |
| 419 DCHECK(data_); | |
| 420 CHECK(buf->data()); | |
| 421 | |
| 422 int remaining = data_->size() - data_offset_; | 399 int remaining = data_->size() - data_offset_; |
| 423 if (buf_size > remaining) | 400 if (buf_size > remaining) |
| 424 buf_size = remaining; | 401 buf_size = remaining; |
| 425 | 402 if (buf_size > 0) { |
| 426 if (buf_size == 0) | 403 // TODO(pkasting): Remove ScopedTracker below once crbug.com/455423 is |
| 427 return 0; | 404 // fixed. |
| 428 | 405 tracked_objects::ScopedTracker tracking_profile( |
| 429 base::WorkerPool::GetTaskRunner(false)->PostTaskAndReply( | 406 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 430 FROM_HERE, base::Bind(&CopyData, base::RetainedRef(buf), buf_size, data_, | 407 "455423 URLRequestChromeJob::CompleteRead memcpy")); |
| 431 data_offset_), | 408 memcpy(buf->data(), data_->front() + data_offset_, buf_size); |
| 432 base::Bind(&URLRequestChromeJob::ReadRawDataComplete, AsWeakPtr(), | 409 data_offset_ += buf_size; |
| 433 buf_size)); | 410 } |
| 434 data_offset_ += buf_size; | 411 return buf_size; |
| 435 | |
| 436 return net::ERR_IO_PENDING; | |
| 437 } | 412 } |
| 438 | 413 |
| 439 void URLRequestChromeJob::DelayStartForDevTools( | 414 void URLRequestChromeJob::DelayStartForDevTools( |
| 440 const base::WeakPtr<URLRequestChromeJob>& job) { | 415 const base::WeakPtr<URLRequestChromeJob>& job) { |
| 441 BrowserThread::PostTask( | 416 BrowserThread::PostTask( |
| 442 BrowserThread::IO, | 417 BrowserThread::IO, |
| 443 FROM_HERE, | 418 FROM_HERE, |
| 444 base::Bind(&URLRequestChromeJob::StartAsync, job)); | 419 base::Bind(&URLRequestChromeJob::StartAsync, job)); |
| 445 } | 420 } |
| 446 | 421 |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 | 794 |
| 820 } // namespace | 795 } // namespace |
| 821 | 796 |
| 822 net::URLRequestJobFactory::ProtocolHandler* | 797 net::URLRequestJobFactory::ProtocolHandler* |
| 823 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, | 798 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, |
| 824 bool is_incognito) { | 799 bool is_incognito) { |
| 825 return new DevToolsJobFactory(resource_context, is_incognito); | 800 return new DevToolsJobFactory(resource_context, is_incognito); |
| 826 } | 801 } |
| 827 | 802 |
| 828 } // namespace content | 803 } // namespace content |
| OLD | NEW |