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