Remove linux_chromium_gn_dbg from the chromium CQ.
[chromium-blink-merge.git] / net / url_request / view_cache_helper.cc
blob36d3ae5ce0d89d26b8a422b367c2da11900bb232
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
3 // found in the LICENSE file.
5 #include "net/url_request/view_cache_helper.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/strings/stringprintf.h"
10 #include "net/base/escape.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h"
13 #include "net/disk_cache/disk_cache.h"
14 #include "net/http/http_cache.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/http/http_response_info.h"
17 #include "net/url_request/url_request_context.h"
19 #define VIEW_CACHE_HEAD \
20 "<html><meta charset=\"utf-8\">" \
21 "<meta http-equiv=\"Content-Security-Policy\" " \
22 " content=\"object-src 'none'; script-src 'none' 'unsafe-eval'\">" \
23 "<body><table>"
25 #define VIEW_CACHE_TAIL \
26 "</table></body></html>"
28 namespace net {
30 namespace {
32 std::string FormatEntryInfo(disk_cache::Entry* entry,
33 const std::string& url_prefix) {
34 std::string key = entry->GetKey();
35 GURL url = GURL(url_prefix + key);
36 std::string row =
37 "<tr><td><a href=\"" + url.spec() + "\">" + EscapeForHTML(key) +
38 "</a></td></tr>";
39 return row;
42 } // namespace.
44 ViewCacheHelper::ViewCacheHelper()
45 : context_(NULL),
46 disk_cache_(NULL),
47 entry_(NULL),
48 buf_len_(0),
49 index_(0),
50 data_(NULL),
51 next_state_(STATE_NONE),
52 weak_factory_(this) {
55 ViewCacheHelper::~ViewCacheHelper() {
56 if (entry_)
57 entry_->Close();
60 int ViewCacheHelper::GetEntryInfoHTML(const std::string& key,
61 const URLRequestContext* context,
62 std::string* out,
63 const CompletionCallback& callback) {
64 return GetInfoHTML(key, context, std::string(), out, callback);
67 int ViewCacheHelper::GetContentsHTML(const URLRequestContext* context,
68 const std::string& url_prefix,
69 std::string* out,
70 const CompletionCallback& callback) {
71 return GetInfoHTML(std::string(), context, url_prefix, out, callback);
74 // static
75 void ViewCacheHelper::HexDump(const char *buf, size_t buf_len,
76 std::string* result) {
77 const size_t kMaxRows = 16;
78 int offset = 0;
80 const unsigned char *p;
81 while (buf_len) {
82 base::StringAppendF(result, "%08x: ", offset);
83 offset += kMaxRows;
85 p = (const unsigned char *) buf;
87 size_t i;
88 size_t row_max = std::min(kMaxRows, buf_len);
90 // print hex codes:
91 for (i = 0; i < row_max; ++i)
92 base::StringAppendF(result, "%02x ", *p++);
93 for (i = row_max; i < kMaxRows; ++i)
94 result->append(" ");
95 result->append(" ");
97 // print ASCII glyphs if possible:
98 p = (const unsigned char *) buf;
99 for (i = 0; i < row_max; ++i, ++p) {
100 if (*p < 0x7F && *p > 0x1F) {
101 AppendEscapedCharForHTML(*p, result);
102 } else {
103 result->push_back('.');
107 result->push_back('\n');
109 buf += row_max;
110 buf_len -= row_max;
114 //-----------------------------------------------------------------------------
116 int ViewCacheHelper::GetInfoHTML(const std::string& key,
117 const URLRequestContext* context,
118 const std::string& url_prefix,
119 std::string* out,
120 const CompletionCallback& callback) {
121 DCHECK(callback_.is_null());
122 DCHECK(context);
123 key_ = key;
124 context_ = context;
125 url_prefix_ = url_prefix;
126 data_ = out;
127 next_state_ = STATE_GET_BACKEND;
128 int rv = DoLoop(OK);
130 if (rv == ERR_IO_PENDING)
131 callback_ = callback;
133 return rv;
136 void ViewCacheHelper::DoCallback(int rv) {
137 DCHECK_NE(ERR_IO_PENDING, rv);
138 DCHECK(!callback_.is_null());
140 callback_.Run(rv);
141 callback_.Reset();
144 void ViewCacheHelper::HandleResult(int rv) {
145 DCHECK_NE(ERR_IO_PENDING, rv);
146 DCHECK_NE(ERR_FAILED, rv);
147 context_ = NULL;
148 if (!callback_.is_null())
149 DoCallback(rv);
152 int ViewCacheHelper::DoLoop(int result) {
153 DCHECK(next_state_ != STATE_NONE);
155 int rv = result;
156 do {
157 State state = next_state_;
158 next_state_ = STATE_NONE;
159 switch (state) {
160 case STATE_GET_BACKEND:
161 DCHECK_EQ(OK, rv);
162 rv = DoGetBackend();
163 break;
164 case STATE_GET_BACKEND_COMPLETE:
165 rv = DoGetBackendComplete(rv);
166 break;
167 case STATE_OPEN_NEXT_ENTRY:
168 DCHECK_EQ(OK, rv);
169 rv = DoOpenNextEntry();
170 break;
171 case STATE_OPEN_NEXT_ENTRY_COMPLETE:
172 rv = DoOpenNextEntryComplete(rv);
173 break;
174 case STATE_OPEN_ENTRY:
175 DCHECK_EQ(OK, rv);
176 rv = DoOpenEntry();
177 break;
178 case STATE_OPEN_ENTRY_COMPLETE:
179 rv = DoOpenEntryComplete(rv);
180 break;
181 case STATE_READ_RESPONSE:
182 DCHECK_EQ(OK, rv);
183 rv = DoReadResponse();
184 break;
185 case STATE_READ_RESPONSE_COMPLETE:
186 rv = DoReadResponseComplete(rv);
187 break;
188 case STATE_READ_DATA:
189 DCHECK_EQ(OK, rv);
190 rv = DoReadData();
191 break;
192 case STATE_READ_DATA_COMPLETE:
193 rv = DoReadDataComplete(rv);
194 break;
196 default:
197 NOTREACHED() << "bad state";
198 rv = ERR_FAILED;
199 break;
201 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
203 if (rv != ERR_IO_PENDING)
204 HandleResult(rv);
206 return rv;
209 int ViewCacheHelper::DoGetBackend() {
210 next_state_ = STATE_GET_BACKEND_COMPLETE;
212 if (!context_->http_transaction_factory())
213 return ERR_FAILED;
215 HttpCache* http_cache = context_->http_transaction_factory()->GetCache();
216 if (!http_cache)
217 return ERR_FAILED;
219 return http_cache->GetBackend(
220 &disk_cache_, base::Bind(&ViewCacheHelper::OnIOComplete,
221 base::Unretained(this)));
224 int ViewCacheHelper::DoGetBackendComplete(int result) {
225 if (result == ERR_FAILED) {
226 data_->append("no disk cache");
227 return OK;
230 DCHECK_EQ(OK, result);
231 if (key_.empty()) {
232 data_->assign(VIEW_CACHE_HEAD);
233 DCHECK(!iter_);
234 next_state_ = STATE_OPEN_NEXT_ENTRY;
235 return OK;
238 next_state_ = STATE_OPEN_ENTRY;
239 return OK;
242 int ViewCacheHelper::DoOpenNextEntry() {
243 next_state_ = STATE_OPEN_NEXT_ENTRY_COMPLETE;
244 if (!iter_)
245 iter_ = disk_cache_->CreateIterator();
246 return
247 iter_->OpenNextEntry(&entry_, base::Bind(&ViewCacheHelper::OnIOComplete,
248 base::Unretained(this)));
251 int ViewCacheHelper::DoOpenNextEntryComplete(int result) {
252 if (result == ERR_FAILED) {
253 data_->append(VIEW_CACHE_TAIL);
254 return OK;
257 DCHECK_EQ(OK, result);
258 data_->append(FormatEntryInfo(entry_, url_prefix_));
259 entry_->Close();
260 entry_ = NULL;
262 next_state_ = STATE_OPEN_NEXT_ENTRY;
263 return OK;
266 int ViewCacheHelper::DoOpenEntry() {
267 next_state_ = STATE_OPEN_ENTRY_COMPLETE;
268 return disk_cache_->OpenEntry(
269 key_, &entry_,
270 base::Bind(&ViewCacheHelper::OnIOComplete, base::Unretained(this)));
273 int ViewCacheHelper::DoOpenEntryComplete(int result) {
274 if (result == ERR_FAILED) {
275 data_->append("no matching cache entry for: " + EscapeForHTML(key_));
276 return OK;
279 data_->assign(VIEW_CACHE_HEAD);
280 data_->append(EscapeForHTML(entry_->GetKey()));
281 next_state_ = STATE_READ_RESPONSE;
282 return OK;
285 int ViewCacheHelper::DoReadResponse() {
286 next_state_ = STATE_READ_RESPONSE_COMPLETE;
287 buf_len_ = entry_->GetDataSize(0);
288 if (!buf_len_)
289 return buf_len_;
291 buf_ = new IOBuffer(buf_len_);
292 return entry_->ReadData(
295 buf_.get(),
296 buf_len_,
297 base::Bind(&ViewCacheHelper::OnIOComplete, weak_factory_.GetWeakPtr()));
300 int ViewCacheHelper::DoReadResponseComplete(int result) {
301 if (result && result == buf_len_) {
302 HttpResponseInfo response;
303 bool truncated;
304 if (HttpCache::ParseResponseInfo(
305 buf_->data(), buf_len_, &response, &truncated) &&
306 response.headers.get()) {
307 if (truncated)
308 data_->append("<pre>RESPONSE_INFO_TRUNCATED</pre>");
310 data_->append("<hr><pre>");
311 data_->append(EscapeForHTML(response.headers->GetStatusLine()));
312 data_->push_back('\n');
314 void* iter = NULL;
315 std::string name, value;
316 while (response.headers->EnumerateHeaderLines(&iter, &name, &value)) {
317 data_->append(EscapeForHTML(name));
318 data_->append(": ");
319 data_->append(EscapeForHTML(value));
320 data_->push_back('\n');
322 data_->append("</pre>");
326 index_ = 0;
327 next_state_ = STATE_READ_DATA;
328 return OK;
331 int ViewCacheHelper::DoReadData() {
332 data_->append("<hr><pre>");
334 next_state_ = STATE_READ_DATA_COMPLETE;
335 buf_len_ = entry_->GetDataSize(index_);
336 if (!buf_len_)
337 return buf_len_;
339 buf_ = new IOBuffer(buf_len_);
340 return entry_->ReadData(
341 index_,
343 buf_.get(),
344 buf_len_,
345 base::Bind(&ViewCacheHelper::OnIOComplete, weak_factory_.GetWeakPtr()));
348 int ViewCacheHelper::DoReadDataComplete(int result) {
349 if (result && result == buf_len_) {
350 HexDump(buf_->data(), buf_len_, data_);
352 data_->append("</pre>");
353 index_++;
354 if (index_ < HttpCache::kNumCacheEntryDataIndices) {
355 next_state_ = STATE_READ_DATA;
356 } else {
357 data_->append(VIEW_CACHE_TAIL);
358 entry_->Close();
359 entry_ = NULL;
361 return OK;
364 void ViewCacheHelper::OnIOComplete(int result) {
365 DoLoop(result);
368 } // namespace net.