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 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 |