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 |