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 if (buf_size > 0) { | |
Dan Beam
2016/07/19 23:27:33
when will this ever be == 0?
groby-ooo-7-16
2016/07/20 01:01:40
It used to be possible in a previous iteration of
| |
115 // TODO(pkasting): Remove ScopedTracker below once crbug.com/455423 is | |
116 // fixed. | |
117 tracked_objects::ScopedTracker tracking_profile( | |
118 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
119 "455423 URLRequestChromeJob::CompleteRead memcpy")); | |
120 memcpy(buf->data(), data->front() + data_offset, buf_size); | |
121 } | |
122 } | |
123 | |
107 } // namespace | 124 } // namespace |
108 | 125 |
109 // URLRequestChromeJob is a net::URLRequestJob that manages running | 126 // URLRequestChromeJob is a net::URLRequestJob that manages running |
110 // chrome-internal resource requests asynchronously. | 127 // chrome-internal resource requests asynchronously. |
111 // It hands off URL requests to ChromeURLDataManager, which asynchronously | 128 // It hands off URL requests to ChromeURLDataManager, which asynchronously |
112 // calls back once the data is available. | 129 // calls back once the data is available. |
113 class URLRequestChromeJob : public net::URLRequestJob { | 130 class URLRequestChromeJob : public net::URLRequestJob { |
114 public: | 131 public: |
115 // |is_incognito| set when job is generated from an incognito profile. | 132 // |is_incognito| set when job is generated from an incognito profile. |
116 URLRequestChromeJob(net::URLRequest* request, | 133 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.) | 214 // (This pattern is shared by most net::URLRequestJob implementations.) |
198 void StartAsync(); | 215 void StartAsync(); |
199 | 216 |
200 // Due to a race condition, DevTools relies on a legacy thread hop to the UI | 217 // Due to a race condition, DevTools relies on a legacy thread hop to the UI |
201 // thread before calling StartAsync. | 218 // thread before calling StartAsync. |
202 // TODO(caseq): Fix the race condition and remove this thread hop in | 219 // TODO(caseq): Fix the race condition and remove this thread hop in |
203 // https://crbug.com/616641. | 220 // https://crbug.com/616641. |
204 static void DelayStartForDevTools( | 221 static void DelayStartForDevTools( |
205 const base::WeakPtr<URLRequestChromeJob>& job); | 222 const base::WeakPtr<URLRequestChromeJob>& job); |
206 | 223 |
207 // Do the actual copy from data_ (the data we're serving) into |buf|. | 224 // 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 | 225 // jank. (|data_| might be mem-mapped, so a memcpy can trigger file ops). |
209 // bytes read. | 226 int PostReadTask(net::IOBuffer* buf, int buf_size); |
210 int CompleteRead(net::IOBuffer* buf, int buf_size); | |
211 | 227 |
212 // The actual data we're serving. NULL until it's been fetched. | 228 // The actual data we're serving. NULL until it's been fetched. |
213 scoped_refptr<base::RefCountedMemory> data_; | 229 scoped_refptr<base::RefCountedMemory> data_; |
214 // The current offset into the data that we're handing off to our | 230 // The current offset into the data that we're handing off to our |
215 // callers via the Read interfaces. | 231 // callers via the Read interfaces. |
216 int data_offset_; | 232 int data_offset_; |
217 | 233 |
218 // For async reads, we keep around a pointer to the buffer that | 234 // For async reads, we keep around a pointer to the buffer that |
219 // we're reading into. | 235 // we're reading into. |
220 scoped_refptr<net::IOBuffer> pending_buf_; | 236 scoped_refptr<net::IOBuffer> pending_buf_; |
(...skipping 22 matching lines...) Expand all Loading... | |
243 // If not empty, "Access-Control-Allow-Origin:" is set to the value of this | 259 // If not empty, "Access-Control-Allow-Origin:" is set to the value of this |
244 // string. | 260 // string. |
245 std::string access_control_allow_origin_; | 261 std::string access_control_allow_origin_; |
246 | 262 |
247 // True when job is generated from an incognito profile. | 263 // True when job is generated from an incognito profile. |
248 const bool is_incognito_; | 264 const bool is_incognito_; |
249 | 265 |
250 // The backend is owned by net::URLRequestContext and always outlives us. | 266 // The backend is owned by net::URLRequestContext and always outlives us. |
251 URLDataManagerBackend* backend_; | 267 URLDataManagerBackend* backend_; |
252 | 268 |
269 scoped_refptr<base::TaskRunner> task_runner_; | |
253 base::WeakPtrFactory<URLRequestChromeJob> weak_factory_; | 270 base::WeakPtrFactory<URLRequestChromeJob> weak_factory_; |
254 | 271 |
255 DISALLOW_COPY_AND_ASSIGN(URLRequestChromeJob); | 272 DISALLOW_COPY_AND_ASSIGN(URLRequestChromeJob); |
256 }; | 273 }; |
257 | 274 |
258 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, | 275 URLRequestChromeJob::URLRequestChromeJob(net::URLRequest* request, |
259 net::NetworkDelegate* network_delegate, | 276 net::NetworkDelegate* network_delegate, |
260 URLDataManagerBackend* backend, | 277 URLDataManagerBackend* backend, |
261 bool is_incognito) | 278 bool is_incognito) |
262 : net::URLRequestJob(request, network_delegate), | 279 : net::URLRequestJob(request, network_delegate), |
263 data_offset_(0), | 280 data_offset_(0), |
264 pending_buf_size_(0), | 281 pending_buf_size_(0), |
265 allow_caching_(true), | 282 allow_caching_(true), |
266 add_content_security_policy_(true), | 283 add_content_security_policy_(true), |
267 deny_xframe_options_(true), | 284 deny_xframe_options_(true), |
268 send_content_type_header_(false), | 285 send_content_type_header_(false), |
269 is_incognito_(is_incognito), | 286 is_incognito_(is_incognito), |
270 backend_(backend), | 287 backend_(backend), |
288 task_runner_(base::WorkerPool::GetTaskRunner(false)), | |
Dan Beam
2016/07/19 23:27:33
do we want to ref the workerpool the whole time th
groby-ooo-7-16
2016/07/20 01:01:40
We'll need it at the very least until all read req
mmenke
2016/07/20 16:47:58
You don't need to hold onto it - it's a leaked glo
groby-ooo-7-16
2016/07/20 18:10:11
Sounds good.
| |
271 weak_factory_(this) { | 289 weak_factory_(this) { |
272 DCHECK(backend); | 290 DCHECK(backend); |
273 } | 291 } |
274 | 292 |
275 URLRequestChromeJob::~URLRequestChromeJob() { | 293 URLRequestChromeJob::~URLRequestChromeJob() { |
276 CHECK(!backend_->HasPendingJob(this)); | 294 CHECK(!backend_->HasPendingJob(this)); |
277 } | 295 } |
278 | 296 |
279 void URLRequestChromeJob::Start() { | 297 void URLRequestChromeJob::Start() { |
280 const GURL url = request_->url(); | 298 const GURL url = request_->url(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
357 } | 375 } |
358 } | 376 } |
359 | 377 |
360 void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) { | 378 void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) { |
361 set_mime_type(mime_type); | 379 set_mime_type(mime_type); |
362 NotifyHeadersComplete(); | 380 NotifyHeadersComplete(); |
363 } | 381 } |
364 | 382 |
365 void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { | 383 void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { |
366 TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); | 384 TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); |
367 if (bytes) { | 385 DCHECK(!data_); |
368 data_ = bytes; | 386 |
369 if (pending_buf_.get()) { | 387 // If we don't have data, signal an error. |
mmenke
2016/07/20 16:47:58
Here and below, some people hold pretty strongly t
groby-ooo-7-16
2016/07/20 18:10:12
Clearly, it's the royal "we" ;) Fixed
| |
370 CHECK(pending_buf_->data()); | 388 if (!bytes) { |
371 int result = CompleteRead(pending_buf_.get(), pending_buf_size_); | 389 ReadRawDataComplete(net::ERR_FAILED); |
372 pending_buf_ = NULL; | 390 return; |
391 } | |
392 | |
393 // We have data, let's try to satisfy the request. | |
394 data_ = bytes; | |
395 | |
396 if (pending_buf_.get()) { | |
mmenke
2016/07/20 16:47:58
optioanl nit: .get() not needed. (I feel if it's
groby-ooo-7-16
2016/07/20 18:10:12
Thanks for flagging, fixed.
| |
397 int result = PostReadTask(pending_buf_.get(), pending_buf_size_); | |
398 if (result != net::ERR_IO_PENDING) | |
373 ReadRawDataComplete(result); | 399 ReadRawDataComplete(result); |
374 } | 400 pending_buf_ = nullptr; |
375 } else { | |
376 // The request failed. | |
377 ReadRawDataComplete(net::ERR_FAILED); | |
378 } | 401 } |
379 } | 402 } |
380 | 403 |
381 base::WeakPtr<URLRequestChromeJob> URLRequestChromeJob::AsWeakPtr() { | 404 base::WeakPtr<URLRequestChromeJob> URLRequestChromeJob::AsWeakPtr() { |
382 return weak_factory_.GetWeakPtr(); | 405 return weak_factory_.GetWeakPtr(); |
383 } | 406 } |
384 | 407 |
385 int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { | 408 int URLRequestChromeJob::ReadRawData(net::IOBuffer* buf, int buf_size) { |
409 DCHECK(!pending_buf_.get()); | |
410 | |
411 // If data isn't available yet, mark this as asynchronous. | |
386 if (!data_.get()) { | 412 if (!data_.get()) { |
387 DCHECK(!pending_buf_.get()); | |
388 CHECK(buf->data()); | |
389 pending_buf_ = buf; | 413 pending_buf_ = buf; |
390 pending_buf_size_ = buf_size; | 414 pending_buf_size_ = buf_size; |
391 return net::ERR_IO_PENDING; | 415 return net::ERR_IO_PENDING; |
392 } | 416 } |
393 | 417 |
394 // Otherwise, the data is available. | 418 return PostReadTask(buf, buf_size); |
395 return CompleteRead(buf, buf_size); | |
396 } | 419 } |
397 | 420 |
398 int URLRequestChromeJob::CompleteRead(net::IOBuffer* buf, int buf_size) { | 421 int URLRequestChromeJob::PostReadTask(net::IOBuffer* buf, int buf_size) { |
mmenke
2016/07/20 16:47:58
Seems a little weird to take bug and buf_size as a
groby-ooo-7-16
2016/07/20 18:10:11
That was my original solution - I switched to this
mmenke
2016/07/20 18:19:43
I don't have a particularly strong opinion here, j
groby-ooo-7-16
2016/07/26 02:37:45
Acknowledged.
| |
422 DCHECK(buf && data_); | |
mmenke
2016/07/20 16:47:58
Should split this into two DCHECKs, so if one fail
groby-ooo-7-16
2016/07/20 18:10:12
Done.
| |
423 CHECK(buf->data()); | |
424 | |
399 int remaining = data_->size() - data_offset_; | 425 int remaining = data_->size() - data_offset_; |
400 if (buf_size > remaining) | 426 if (buf_size > remaining) |
401 buf_size = remaining; | 427 buf_size = remaining; |
402 if (buf_size > 0) { | 428 |
403 // TODO(pkasting): Remove ScopedTracker below once crbug.com/455423 is | 429 if (buf_size == 0) |
404 // fixed. | 430 return 0; |
405 tracked_objects::ScopedTracker tracking_profile( | 431 |
Dan Beam
2016/07/19 23:27:33
can we just do
if (buf_size == 0) {
task_runner
groby-ooo-7-16
2016/07/20 01:01:40
We could - but there's no benefit to it. See above
| |
406 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 432 task_runner_->PostTaskAndReply( |
mmenke
2016/07/20 16:47:58
Could just use WorkerPool::PostTaskAndReply, and g
groby-ooo-7-16
2016/07/20 18:10:11
I looked at it, but it creates two additional obje
mmenke
2016/07/20 18:19:43
Code size generally matters more, and the single c
groby-ooo-7-16
2016/07/26 02:37:45
Digging deeper, the relay is necessary anyways, an
| |
407 "455423 URLRequestChromeJob::CompleteRead memcpy")); | 433 FROM_HERE, base::Bind(&CopyData, base::RetainedRef(buf), buf_size, data_, |
408 memcpy(buf->data(), data_->front() + data_offset_, buf_size); | 434 data_offset_), |
409 data_offset_ += buf_size; | 435 base::Bind(&URLRequestChromeJob::ReadRawDataComplete, AsWeakPtr(), |
410 } | 436 buf_size)); |
411 return buf_size; | 437 data_offset_ += buf_size; |
438 | |
439 return net::ERR_IO_PENDING; | |
412 } | 440 } |
413 | 441 |
414 void URLRequestChromeJob::DelayStartForDevTools( | 442 void URLRequestChromeJob::DelayStartForDevTools( |
415 const base::WeakPtr<URLRequestChromeJob>& job) { | 443 const base::WeakPtr<URLRequestChromeJob>& job) { |
416 BrowserThread::PostTask( | 444 BrowserThread::PostTask( |
417 BrowserThread::IO, | 445 BrowserThread::IO, |
418 FROM_HERE, | 446 FROM_HERE, |
419 base::Bind(&URLRequestChromeJob::StartAsync, job)); | 447 base::Bind(&URLRequestChromeJob::StartAsync, job)); |
420 } | 448 } |
421 | 449 |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
794 | 822 |
795 } // namespace | 823 } // namespace |
796 | 824 |
797 net::URLRequestJobFactory::ProtocolHandler* | 825 net::URLRequestJobFactory::ProtocolHandler* |
798 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, | 826 CreateDevToolsProtocolHandler(content::ResourceContext* resource_context, |
799 bool is_incognito) { | 827 bool is_incognito) { |
800 return new DevToolsJobFactory(resource_context, is_incognito); | 828 return new DevToolsJobFactory(resource_context, is_incognito); |
801 } | 829 } |
802 | 830 |
803 } // namespace content | 831 } // namespace content |
OLD | NEW |