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 "chrome/browser/ui/webui/chrome_url_data_manager_backend.h" | 5 #include "chrome/browser/ui/webui/chrome_url_data_manager_backend.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 16 #include "base/memory/ref_counted.h" |
16 #include "base/memory/ref_counted_memory.h" | 17 #include "base/memory/ref_counted_memory.h" |
17 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
18 #include "base/message_loop.h" | 19 #include "base/message_loop.h" |
19 #include "base/path_service.h" | 20 #include "base/path_service.h" |
20 #include "base/string_util.h" | 21 #include "base/string_util.h" |
21 #include "chrome/browser/net/chrome_url_request_context.h" | 22 #include "chrome/browser/net/chrome_url_request_context.h" |
22 #include "chrome/browser/ui/webui/shared_resources_data_source.h" | 23 #include "chrome/browser/ui/webui/shared_resources_data_source.h" |
23 #include "chrome/common/chrome_paths.h" | 24 #include "chrome/common/chrome_paths.h" |
24 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
25 #include "chrome/common/url_constants.h" | 26 #include "chrome/common/url_constants.h" |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 | 164 |
164 // net::URLRequestJob implementation. | 165 // net::URLRequestJob implementation. |
165 virtual void Start() OVERRIDE; | 166 virtual void Start() OVERRIDE; |
166 virtual void Kill() OVERRIDE; | 167 virtual void Kill() OVERRIDE; |
167 virtual bool ReadRawData(net::IOBuffer* buf, | 168 virtual bool ReadRawData(net::IOBuffer* buf, |
168 int buf_size, | 169 int buf_size, |
169 int* bytes_read) OVERRIDE; | 170 int* bytes_read) OVERRIDE; |
170 virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; | 171 virtual bool GetMimeType(std::string* mime_type) const OVERRIDE; |
171 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE; | 172 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE; |
172 | 173 |
| 174 // Used to notify that the requested data's |mime_type| is ready. |
| 175 void MimeTypeAvailable(const std::string& mime_type); |
| 176 |
173 // Called by ChromeURLDataManager to notify us that the data blob is ready | 177 // Called by ChromeURLDataManager to notify us that the data blob is ready |
174 // for us. | 178 // for us. |
175 void DataAvailable(base::RefCountedMemory* bytes); | 179 void DataAvailable(base::RefCountedMemory* bytes); |
176 | 180 |
177 void set_mime_type(const std::string& mime_type) { | 181 void set_mime_type(const std::string& mime_type) { |
178 mime_type_ = mime_type; | 182 mime_type_ = mime_type; |
179 } | 183 } |
180 | 184 |
181 void set_allow_caching(bool allow_caching) { | 185 void set_allow_caching(bool allow_caching) { |
182 allow_caching_ = allow_caching; | 186 allow_caching_ = allow_caching; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 DCHECK(!info->headers); | 260 DCHECK(!info->headers); |
257 // Set the headers so that requests serviced by ChromeURLDataManager return a | 261 // Set the headers so that requests serviced by ChromeURLDataManager return a |
258 // status code of 200. Without this they return a 0, which makes the status | 262 // status code of 200. Without this they return a 0, which makes the status |
259 // indistiguishable from other error types. Instant relies on getting a 200. | 263 // indistiguishable from other error types. Instant relies on getting a 200. |
260 info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); | 264 info->headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); |
261 AddContentSecurityPolicyHeader(request_->url(), info->headers); | 265 AddContentSecurityPolicyHeader(request_->url(), info->headers); |
262 if (!allow_caching_) | 266 if (!allow_caching_) |
263 info->headers->AddHeader("Cache-Control: no-cache"); | 267 info->headers->AddHeader("Cache-Control: no-cache"); |
264 } | 268 } |
265 | 269 |
| 270 void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) { |
| 271 set_mime_type(mime_type); |
| 272 NotifyHeadersComplete(); |
| 273 } |
| 274 |
266 void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { | 275 void URLRequestChromeJob::DataAvailable(base::RefCountedMemory* bytes) { |
267 TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); | 276 TRACE_EVENT_ASYNC_END0("browser", "DataManager:Request", this); |
268 if (bytes) { | 277 if (bytes) { |
269 // The request completed, and we have all the data. | 278 // The request completed, and we have all the data. |
270 // Clear any IO pending status. | 279 // Clear any IO pending status. |
271 SetStatus(net::URLRequestStatus()); | 280 SetStatus(net::URLRequestStatus()); |
272 | 281 |
273 data_ = bytes; | 282 data_ = bytes; |
274 int bytes_read; | 283 int bytes_read; |
275 if (pending_buf_.get()) { | 284 if (pending_buf_.get()) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 memcpy(buf->data(), data_->front() + data_offset_, buf_size); | 319 memcpy(buf->data(), data_->front() + data_offset_, buf_size); |
311 data_offset_ += buf_size; | 320 data_offset_ += buf_size; |
312 } | 321 } |
313 *bytes_read = buf_size; | 322 *bytes_read = buf_size; |
314 } | 323 } |
315 | 324 |
316 void URLRequestChromeJob::StartAsync() { | 325 void URLRequestChromeJob::StartAsync() { |
317 if (!request_) | 326 if (!request_) |
318 return; | 327 return; |
319 | 328 |
320 if (backend_->StartRequest(request_->url(), this)) { | 329 if (!backend_->StartRequest(request_->url(), this)) { |
321 NotifyHeadersComplete(); | |
322 } else { | |
323 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 330 NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
324 net::ERR_INVALID_URL)); | 331 net::ERR_INVALID_URL)); |
325 } | 332 } |
326 } | 333 } |
327 | 334 |
328 namespace { | 335 namespace { |
329 | 336 |
| 337 // Gets mime type for data that is available from |source| by |path|. |
| 338 // After that, notifies |job| that mime type is available. This method |
| 339 // should be called on the UI thread, but notification is performed on |
| 340 // the IO thread. |
| 341 void GetMimeTypeOnUI(ChromeURLDataManager::DataSource* source, |
| 342 const std::string& path, |
| 343 URLRequestChromeJob* job) { |
| 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 345 std::string mime_type = source->GetMimeType(path); |
| 346 BrowserThread::PostTask( |
| 347 BrowserThread::IO, FROM_HERE, |
| 348 base::Bind(&URLRequestChromeJob::MimeTypeAvailable, job, mime_type)); |
| 349 } |
| 350 |
| 351 } // namespace |
| 352 |
| 353 namespace { |
| 354 |
330 class ChromeProtocolHandler | 355 class ChromeProtocolHandler |
331 : public net::URLRequestJobFactory::ProtocolHandler { | 356 : public net::URLRequestJobFactory::ProtocolHandler { |
332 public: | 357 public: |
333 explicit ChromeProtocolHandler(ChromeURLDataManagerBackend* backend); | 358 explicit ChromeProtocolHandler(ChromeURLDataManagerBackend* backend); |
334 ~ChromeProtocolHandler(); | 359 ~ChromeProtocolHandler(); |
335 | 360 |
336 virtual net::URLRequestJob* MaybeCreateJob( | 361 virtual net::URLRequestJob* MaybeCreateJob( |
337 net::URLRequest* request) const OVERRIDE; | 362 net::URLRequest* request) const OVERRIDE; |
338 | 363 |
339 private: | 364 private: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 DataSourceMap::iterator i = data_sources_.find(source_name); | 439 DataSourceMap::iterator i = data_sources_.find(source_name); |
415 if (i == data_sources_.end()) | 440 if (i == data_sources_.end()) |
416 return false; | 441 return false; |
417 | 442 |
418 ChromeURLDataManager::DataSource* source = i->second; | 443 ChromeURLDataManager::DataSource* source = i->second; |
419 | 444 |
420 // Save this request so we know where to send the data. | 445 // Save this request so we know where to send the data. |
421 RequestID request_id = next_request_id_++; | 446 RequestID request_id = next_request_id_++; |
422 pending_requests_.insert(std::make_pair(request_id, job)); | 447 pending_requests_.insert(std::make_pair(request_id, job)); |
423 | 448 |
424 // TODO(eroman): would be nicer if the mimetype were set at the same time | |
425 // as the data blob. For now do it here, since NotifyHeadersComplete() is | |
426 // going to get called once we return. | |
427 job->set_mime_type(source->GetMimeType(path)); | |
428 job->set_allow_caching(source->AllowCaching()); | 449 job->set_allow_caching(source->AllowCaching()); |
429 | 450 |
430 const ChromeURLRequestContext* context = | 451 const ChromeURLRequestContext* context = |
431 static_cast<const ChromeURLRequestContext*>(job->request()->context()); | 452 static_cast<const ChromeURLRequestContext*>(job->request()->context()); |
432 | 453 |
433 // Forward along the request to the data source. | 454 // Forward along the request to the data source. |
434 MessageLoop* target_message_loop = source->MessageLoopForRequestPath(path); | 455 MessageLoop* target_message_loop = source->MessageLoopForRequestPath(path); |
435 if (!target_message_loop) { | 456 if (!target_message_loop) { |
| 457 job->MimeTypeAvailable(source->GetMimeType(path)); |
| 458 |
436 // The DataSource is agnostic to which thread StartDataRequest is called | 459 // The DataSource is agnostic to which thread StartDataRequest is called |
437 // on for this path. Call directly into it from this thread, the IO | 460 // on for this path. Call directly into it from this thread, the IO |
438 // thread. | 461 // thread. |
439 source->StartDataRequest(path, context->is_incognito(), request_id); | 462 source->StartDataRequest(path, context->is_incognito(), request_id); |
440 } else { | 463 } else { |
| 464 // URLRequestChromeJob should receive mime type before data. This |
| 465 // is guaranteed because request for mime type is placed in the |
| 466 // message loop before request for data. And correspondingly their |
| 467 // replies are put on the IO thread in the same order. |
| 468 target_message_loop->PostTask( |
| 469 FROM_HERE, |
| 470 base::Bind(&GetMimeTypeOnUI, |
| 471 scoped_refptr<ChromeURLDataManager::DataSource>(source), |
| 472 path, |
| 473 scoped_refptr<URLRequestChromeJob>(job))); |
| 474 |
441 // The DataSource wants StartDataRequest to be called on a specific thread, | 475 // The DataSource wants StartDataRequest to be called on a specific thread, |
442 // usually the UI thread, for this path. | 476 // usually the UI thread, for this path. |
443 target_message_loop->PostTask( | 477 target_message_loop->PostTask( |
444 FROM_HERE, | 478 FROM_HERE, |
445 base::Bind(&ChromeURLDataManager::DataSource::StartDataRequest, source, | 479 base::Bind(&ChromeURLDataManager::DataSource::StartDataRequest, source, |
446 path, context->is_incognito(), request_id)); | 480 path, context->is_incognito(), request_id)); |
447 } | 481 } |
448 return true; | 482 return true; |
449 } | 483 } |
450 | 484 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 | 597 |
564 return new URLRequestChromeJob(request, backend_); | 598 return new URLRequestChromeJob(request, backend_); |
565 } | 599 } |
566 | 600 |
567 } // namespace | 601 } // namespace |
568 | 602 |
569 net::URLRequestJobFactory::ProtocolHandler* | 603 net::URLRequestJobFactory::ProtocolHandler* |
570 CreateDevToolsProtocolHandler(ChromeURLDataManagerBackend* backend) { | 604 CreateDevToolsProtocolHandler(ChromeURLDataManagerBackend* backend) { |
571 return new DevToolsJobFactory(backend); | 605 return new DevToolsJobFactory(backend); |
572 } | 606 } |
OLD | NEW |