view_http_cache_job_factory.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/net/view_http_cache_job_factory.h"
6
7#include "base/message_loop.h"
8#include "base/string_util.h"
9#include "chrome/common/url_constants.h"
10#include "net/base/net_errors.h"
11#include "net/url_request/url_request.h"
12#include "net/url_request/url_request_context.h"
13#include "net/url_request/url_request_simple_job.h"
14#include "net/url_request/view_cache_helper.h"
15
16namespace {
17
18// A job subclass that dumps an HTTP cache entry.
19class ViewHttpCacheJob : public URLRequestJob {
20 public:
21  explicit ViewHttpCacheJob(URLRequest* request)
22      : URLRequestJob(request), data_offset_(0), cancel_(false), busy_(false),
23        ALLOW_THIS_IN_INITIALIZER_LIST(
24            callback_(this, &ViewHttpCacheJob::OnIOComplete)) {}
25
26  virtual void Start();
27  virtual void Kill();
28  virtual bool GetMimeType(std::string* mime_type) const;
29  virtual bool GetCharset(std::string* charset);
30  virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
31
32 private:
33  ~ViewHttpCacheJob() {}
34
35  // Called when ViewCacheHelper completes the operation.
36  void OnIOComplete(int result);
37
38  std::string data_;
39  int data_offset_;
40  bool cancel_;
41  bool busy_;
42  net::ViewCacheHelper cache_helper_;
43  net::CompletionCallbackImpl<ViewHttpCacheJob> callback_;
44};
45
46void ViewHttpCacheJob::Start() {
47  if (!request_ || cancel_)
48    return;
49
50  busy_ = true;
51  AddRef();  // Released on OnIOComplete().
52  std::string cache_key =
53      request_->url().spec().substr(strlen(chrome::kNetworkViewCacheURL));
54
55  int rv;
56  if (cache_key.empty()) {
57    rv = cache_helper_.GetContentsHTML(request_->context(),
58                                       chrome::kNetworkViewCacheURL, &data_,
59                                       &callback_);
60  } else {
61    rv = cache_helper_.GetEntryInfoHTML(cache_key, request_->context(),
62                                        &data_, &callback_);
63  }
64
65  if (rv != net::ERR_IO_PENDING) {
66    // Start reading asynchronously so that all error reporting and data
67    // callbacks happen as they would for network requests.
68    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
69        this, &ViewHttpCacheJob::OnIOComplete, rv));
70  }
71}
72
73void ViewHttpCacheJob::Kill() {
74  // We don't want to delete this object while we are busy; we'll do it when it
75  // is safe.
76  cancel_ = true;
77  if (!busy_)
78    URLRequestJob::Kill();
79}
80
81bool ViewHttpCacheJob::GetMimeType(std::string* mime_type) const {
82  mime_type->assign("text/html");
83  return true;
84}
85
86bool ViewHttpCacheJob::GetCharset(std::string* charset) {
87  charset->assign("UTF-8");
88  return true;
89}
90
91bool ViewHttpCacheJob::ReadRawData(net::IOBuffer* buf, int buf_size,
92                                   int* bytes_read) {
93  DCHECK(bytes_read);
94  int remaining = static_cast<int>(data_.size()) - data_offset_;
95  if (buf_size > remaining)
96    buf_size = remaining;
97  memcpy(buf->data(), data_.data() + data_offset_, buf_size);
98  data_offset_ += buf_size;
99  *bytes_read = buf_size;
100  return true;
101}
102
103void ViewHttpCacheJob::OnIOComplete(int result) {
104  // We may be holding the last reference to this job.
105  scoped_refptr<ViewHttpCacheJob> self(this);
106  DCHECK_EQ(net::OK, result);
107  busy_ = false;
108  Release();  // Acquired on Start().
109
110  if (cancel_)
111    return URLRequestJob::Kill();
112
113  // Notify that the headers are complete.
114  NotifyHeadersComplete();
115}
116
117}  // namespace.
118
119// Static.
120bool ViewHttpCacheJobFactory::IsSupportedURL(const GURL& url) {
121  return StartsWithASCII(url.spec(), chrome::kNetworkViewCacheURL,
122                         true /*case_sensitive*/);
123}
124
125// Static.
126URLRequestJob* ViewHttpCacheJobFactory::CreateJobForRequest(
127    URLRequest* request) {
128  return new ViewHttpCacheJob(request);
129}
130