summaryrefslogtreecommitdiffstats
path: root/chrome/browser/net/view_http_cache_job_factory.cc
blob: 839130d532575b77998e64610fcea8dcfa629df5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/net/view_http_cache_job_factory.h"

#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/common/url_constants.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_simple_job.h"
#include "net/url_request/view_cache_helper.h"

namespace {

// A job subclass that dumps an HTTP cache entry.
class ViewHttpCacheJob : public net::URLRequestJob {
 public:
  explicit ViewHttpCacheJob(net::URLRequest* request)
      : net::URLRequestJob(request),
        data_offset_(0),
        cancel_(false),
        busy_(false),
        ALLOW_THIS_IN_INITIALIZER_LIST(
            callback_(this, &ViewHttpCacheJob::OnIOComplete)) {}

  virtual void Start();
  virtual void Kill();
  virtual bool GetMimeType(std::string* mime_type) const;
  virtual bool GetCharset(std::string* charset);
  virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);

 private:
  ~ViewHttpCacheJob() {}

  // Called when ViewCacheHelper completes the operation.
  void OnIOComplete(int result);

  std::string data_;
  int data_offset_;
  bool cancel_;
  bool busy_;
  net::ViewCacheHelper cache_helper_;
  net::CompletionCallbackImpl<ViewHttpCacheJob> callback_;
};

void ViewHttpCacheJob::Start() {
  if (!request_ || cancel_)
    return;

  busy_ = true;
  AddRef();  // Released on OnIOComplete().
  std::string cache_key =
      request_->url().spec().substr(strlen(chrome::kNetworkViewCacheURL));

  int rv;
  if (cache_key.empty()) {
    rv = cache_helper_.GetContentsHTML(request_->context(),
                                       chrome::kNetworkViewCacheURL, &data_,
                                       &callback_);
  } else {
    rv = cache_helper_.GetEntryInfoHTML(cache_key, request_->context(),
                                        &data_, &callback_);
  }

  if (rv != net::ERR_IO_PENDING) {
    // Start reading asynchronously so that all error reporting and data
    // callbacks happen as they would for network requests.
    MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
        this, &ViewHttpCacheJob::OnIOComplete, rv));
  }
}

void ViewHttpCacheJob::Kill() {
  // We don't want to delete this object while we are busy; we'll do it when it
  // is safe.
  cancel_ = true;
  if (!busy_)
    net::URLRequestJob::Kill();
}

bool ViewHttpCacheJob::GetMimeType(std::string* mime_type) const {
  mime_type->assign("text/html");
  return true;
}

bool ViewHttpCacheJob::GetCharset(std::string* charset) {
  charset->assign("UTF-8");
  return true;
}

bool ViewHttpCacheJob::ReadRawData(net::IOBuffer* buf, int buf_size,
                                   int* bytes_read) {
  DCHECK(bytes_read);
  int remaining = static_cast<int>(data_.size()) - data_offset_;
  if (buf_size > remaining)
    buf_size = remaining;
  memcpy(buf->data(), data_.data() + data_offset_, buf_size);
  data_offset_ += buf_size;
  *bytes_read = buf_size;
  return true;
}

void ViewHttpCacheJob::OnIOComplete(int result) {
  // We may be holding the last reference to this job.
  scoped_refptr<ViewHttpCacheJob> self(this);
  DCHECK_EQ(net::OK, result);
  busy_ = false;
  Release();  // Acquired on Start().

  if (cancel_)
    return net::URLRequestJob::Kill();

  // Notify that the headers are complete.
  NotifyHeadersComplete();
}

}  // namespace.

// Static.
bool ViewHttpCacheJobFactory::IsSupportedURL(const GURL& url) {
  return StartsWithASCII(url.spec(), chrome::kNetworkViewCacheURL,
                         true /*case_sensitive*/);
}

// Static.
net::URLRequestJob* ViewHttpCacheJobFactory::CreateJobForRequest(
    net::URLRequest* request) {
  return new ViewHttpCacheJob(request);
}