mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 06:16:30 +03:00
372 lines
9.5 KiB
C++
372 lines
9.5 KiB
C++
// Copyright (c) 2012 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 "net/url_request/view_cache_helper.h"
|
|
|
|
#include <utility>
|
|
|
|
#include "base/bind.h"
|
|
#include "base/bind_helpers.h"
|
|
#include "base/strings/stringprintf.h"
|
|
#include "net/base/escape.h"
|
|
#include "net/base/io_buffer.h"
|
|
#include "net/base/net_errors.h"
|
|
#include "net/base/request_priority.h"
|
|
#include "net/disk_cache/disk_cache.h"
|
|
#include "net/http/http_cache.h"
|
|
#include "net/http/http_response_headers.h"
|
|
#include "net/http/http_response_info.h"
|
|
#include "net/url_request/url_request_context.h"
|
|
|
|
#define VIEW_CACHE_HEAD \
|
|
"<html><meta charset=\"utf-8\">" \
|
|
"<meta http-equiv=\"Content-Security-Policy\" " \
|
|
" content=\"object-src 'none'; script-src 'none'\">" \
|
|
"<body><table>"
|
|
|
|
#define VIEW_CACHE_TAIL \
|
|
"</table></body></html>"
|
|
|
|
namespace net {
|
|
|
|
namespace {
|
|
|
|
std::string FormatEntryInfo(disk_cache::Entry* entry,
|
|
const std::string& url_prefix) {
|
|
std::string key = entry->GetKey();
|
|
GURL url = GURL(url_prefix + key);
|
|
std::string row =
|
|
"<tr><td><a href=\"" + url.spec() + "\">" + EscapeForHTML(key) +
|
|
"</a></td></tr>";
|
|
return row;
|
|
}
|
|
|
|
} // namespace.
|
|
|
|
ViewCacheHelper::ViewCacheHelper()
|
|
: context_(NULL),
|
|
disk_cache_(NULL),
|
|
entry_(NULL),
|
|
buf_len_(0),
|
|
index_(0),
|
|
data_(NULL),
|
|
next_state_(STATE_NONE),
|
|
weak_factory_(this) {
|
|
}
|
|
|
|
ViewCacheHelper::~ViewCacheHelper() {
|
|
if (entry_)
|
|
entry_->Close();
|
|
}
|
|
|
|
int ViewCacheHelper::GetEntryInfoHTML(const std::string& key,
|
|
const URLRequestContext* context,
|
|
std::string* out,
|
|
CompletionOnceCallback callback) {
|
|
return GetInfoHTML(key, context, std::string(), out, std::move(callback));
|
|
}
|
|
|
|
int ViewCacheHelper::GetContentsHTML(const URLRequestContext* context,
|
|
const std::string& url_prefix,
|
|
std::string* out,
|
|
CompletionOnceCallback callback) {
|
|
return GetInfoHTML(std::string(), context, url_prefix, out,
|
|
std::move(callback));
|
|
}
|
|
|
|
// static
|
|
void ViewCacheHelper::HexDump(const char *buf, size_t buf_len,
|
|
std::string* result) {
|
|
const size_t kMaxRows = 16;
|
|
int offset = 0;
|
|
|
|
const unsigned char *p;
|
|
while (buf_len) {
|
|
base::StringAppendF(result, "%08x: ", offset);
|
|
offset += kMaxRows;
|
|
|
|
p = (const unsigned char *) buf;
|
|
|
|
size_t i;
|
|
size_t row_max = std::min(kMaxRows, buf_len);
|
|
|
|
// print hex codes:
|
|
for (i = 0; i < row_max; ++i)
|
|
base::StringAppendF(result, "%02x ", *p++);
|
|
for (i = row_max; i < kMaxRows; ++i)
|
|
result->append(" ");
|
|
result->append(" ");
|
|
|
|
// print ASCII glyphs if possible:
|
|
p = (const unsigned char *) buf;
|
|
for (i = 0; i < row_max; ++i, ++p) {
|
|
if (*p < 0x7F && *p > 0x1F) {
|
|
AppendEscapedCharForHTML(*p, result);
|
|
} else {
|
|
result->push_back('.');
|
|
}
|
|
}
|
|
|
|
result->push_back('\n');
|
|
|
|
buf += row_max;
|
|
buf_len -= row_max;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int ViewCacheHelper::GetInfoHTML(const std::string& key,
|
|
const URLRequestContext* context,
|
|
const std::string& url_prefix,
|
|
std::string* out,
|
|
CompletionOnceCallback callback) {
|
|
DCHECK(callback_.is_null());
|
|
DCHECK(context);
|
|
key_ = key;
|
|
context_ = context;
|
|
url_prefix_ = url_prefix;
|
|
data_ = out;
|
|
next_state_ = STATE_GET_BACKEND;
|
|
int rv = DoLoop(OK);
|
|
|
|
if (rv == ERR_IO_PENDING)
|
|
callback_ = std::move(callback);
|
|
|
|
return rv;
|
|
}
|
|
|
|
void ViewCacheHelper::DoCallback(int rv) {
|
|
DCHECK_NE(ERR_IO_PENDING, rv);
|
|
DCHECK(!callback_.is_null());
|
|
|
|
std::move(callback_).Run(rv);
|
|
}
|
|
|
|
void ViewCacheHelper::HandleResult(int rv) {
|
|
DCHECK_NE(ERR_IO_PENDING, rv);
|
|
DCHECK_NE(ERR_FAILED, rv);
|
|
context_ = NULL;
|
|
if (!callback_.is_null())
|
|
DoCallback(rv);
|
|
}
|
|
|
|
int ViewCacheHelper::DoLoop(int result) {
|
|
DCHECK(next_state_ != STATE_NONE);
|
|
|
|
int rv = result;
|
|
do {
|
|
State state = next_state_;
|
|
next_state_ = STATE_NONE;
|
|
switch (state) {
|
|
case STATE_GET_BACKEND:
|
|
DCHECK_EQ(OK, rv);
|
|
rv = DoGetBackend();
|
|
break;
|
|
case STATE_GET_BACKEND_COMPLETE:
|
|
rv = DoGetBackendComplete(rv);
|
|
break;
|
|
case STATE_OPEN_NEXT_ENTRY:
|
|
DCHECK_EQ(OK, rv);
|
|
rv = DoOpenNextEntry();
|
|
break;
|
|
case STATE_OPEN_NEXT_ENTRY_COMPLETE:
|
|
rv = DoOpenNextEntryComplete(rv);
|
|
break;
|
|
case STATE_OPEN_ENTRY:
|
|
DCHECK_EQ(OK, rv);
|
|
rv = DoOpenEntry();
|
|
break;
|
|
case STATE_OPEN_ENTRY_COMPLETE:
|
|
rv = DoOpenEntryComplete(rv);
|
|
break;
|
|
case STATE_READ_RESPONSE:
|
|
DCHECK_EQ(OK, rv);
|
|
rv = DoReadResponse();
|
|
break;
|
|
case STATE_READ_RESPONSE_COMPLETE:
|
|
rv = DoReadResponseComplete(rv);
|
|
break;
|
|
case STATE_READ_DATA:
|
|
DCHECK_EQ(OK, rv);
|
|
rv = DoReadData();
|
|
break;
|
|
case STATE_READ_DATA_COMPLETE:
|
|
rv = DoReadDataComplete(rv);
|
|
break;
|
|
|
|
default:
|
|
NOTREACHED() << "bad state";
|
|
rv = ERR_FAILED;
|
|
break;
|
|
}
|
|
} while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
|
|
|
|
if (rv != ERR_IO_PENDING)
|
|
HandleResult(rv);
|
|
|
|
return rv;
|
|
}
|
|
|
|
int ViewCacheHelper::DoGetBackend() {
|
|
next_state_ = STATE_GET_BACKEND_COMPLETE;
|
|
|
|
if (!context_->http_transaction_factory())
|
|
return ERR_FAILED;
|
|
|
|
HttpCache* http_cache = context_->http_transaction_factory()->GetCache();
|
|
if (!http_cache)
|
|
return ERR_FAILED;
|
|
|
|
return http_cache->GetBackend(
|
|
&disk_cache_,
|
|
base::BindOnce(&ViewCacheHelper::OnIOComplete, base::Unretained(this)));
|
|
}
|
|
|
|
int ViewCacheHelper::DoGetBackendComplete(int result) {
|
|
if (result == ERR_FAILED) {
|
|
data_->append("no disk cache");
|
|
return OK;
|
|
}
|
|
|
|
DCHECK_EQ(OK, result);
|
|
if (key_.empty()) {
|
|
data_->assign(VIEW_CACHE_HEAD);
|
|
DCHECK(!iter_);
|
|
next_state_ = STATE_OPEN_NEXT_ENTRY;
|
|
return OK;
|
|
}
|
|
|
|
next_state_ = STATE_OPEN_ENTRY;
|
|
return OK;
|
|
}
|
|
|
|
int ViewCacheHelper::DoOpenNextEntry() {
|
|
next_state_ = STATE_OPEN_NEXT_ENTRY_COMPLETE;
|
|
if (!iter_)
|
|
iter_ = disk_cache_->CreateIterator();
|
|
return
|
|
iter_->OpenNextEntry(&entry_, base::Bind(&ViewCacheHelper::OnIOComplete,
|
|
base::Unretained(this)));
|
|
}
|
|
|
|
int ViewCacheHelper::DoOpenNextEntryComplete(int result) {
|
|
if (result == ERR_FAILED) {
|
|
data_->append(VIEW_CACHE_TAIL);
|
|
return OK;
|
|
}
|
|
|
|
DCHECK_EQ(OK, result);
|
|
data_->append(FormatEntryInfo(entry_, url_prefix_));
|
|
entry_->Close();
|
|
entry_ = NULL;
|
|
|
|
next_state_ = STATE_OPEN_NEXT_ENTRY;
|
|
return OK;
|
|
}
|
|
|
|
int ViewCacheHelper::DoOpenEntry() {
|
|
next_state_ = STATE_OPEN_ENTRY_COMPLETE;
|
|
return disk_cache_->OpenEntry(
|
|
key_, net::HIGHEST, &entry_,
|
|
base::Bind(&ViewCacheHelper::OnIOComplete, base::Unretained(this)));
|
|
}
|
|
|
|
int ViewCacheHelper::DoOpenEntryComplete(int result) {
|
|
if (result == ERR_FAILED) {
|
|
data_->append("no matching cache entry for: " + EscapeForHTML(key_));
|
|
return OK;
|
|
}
|
|
|
|
data_->assign(VIEW_CACHE_HEAD);
|
|
data_->append(EscapeForHTML(entry_->GetKey()));
|
|
next_state_ = STATE_READ_RESPONSE;
|
|
return OK;
|
|
}
|
|
|
|
int ViewCacheHelper::DoReadResponse() {
|
|
next_state_ = STATE_READ_RESPONSE_COMPLETE;
|
|
buf_len_ = entry_->GetDataSize(0);
|
|
if (!buf_len_)
|
|
return buf_len_;
|
|
|
|
buf_ = base::MakeRefCounted<IOBuffer>(buf_len_);
|
|
return entry_->ReadData(
|
|
0,
|
|
0,
|
|
buf_.get(),
|
|
buf_len_,
|
|
base::Bind(&ViewCacheHelper::OnIOComplete, weak_factory_.GetWeakPtr()));
|
|
}
|
|
|
|
int ViewCacheHelper::DoReadResponseComplete(int result) {
|
|
if (result && result == buf_len_) {
|
|
HttpResponseInfo response;
|
|
bool truncated;
|
|
if (HttpCache::ParseResponseInfo(
|
|
buf_->data(), buf_len_, &response, &truncated) &&
|
|
response.headers.get()) {
|
|
if (truncated)
|
|
data_->append("<pre>RESPONSE_INFO_TRUNCATED</pre>");
|
|
|
|
data_->append("<hr><pre>");
|
|
data_->append(EscapeForHTML(response.headers->GetStatusLine()));
|
|
data_->push_back('\n');
|
|
|
|
size_t iter = 0;
|
|
std::string name, value;
|
|
while (response.headers->EnumerateHeaderLines(&iter, &name, &value)) {
|
|
data_->append(EscapeForHTML(name));
|
|
data_->append(": ");
|
|
data_->append(EscapeForHTML(value));
|
|
data_->push_back('\n');
|
|
}
|
|
data_->append("</pre>");
|
|
}
|
|
}
|
|
|
|
index_ = 0;
|
|
next_state_ = STATE_READ_DATA;
|
|
return OK;
|
|
}
|
|
|
|
int ViewCacheHelper::DoReadData() {
|
|
data_->append("<hr><pre>");
|
|
|
|
next_state_ = STATE_READ_DATA_COMPLETE;
|
|
buf_len_ = entry_->GetDataSize(index_);
|
|
if (!buf_len_)
|
|
return buf_len_;
|
|
|
|
buf_ = base::MakeRefCounted<IOBuffer>(buf_len_);
|
|
return entry_->ReadData(
|
|
index_,
|
|
0,
|
|
buf_.get(),
|
|
buf_len_,
|
|
base::Bind(&ViewCacheHelper::OnIOComplete, weak_factory_.GetWeakPtr()));
|
|
}
|
|
|
|
int ViewCacheHelper::DoReadDataComplete(int result) {
|
|
if (result && result == buf_len_) {
|
|
HexDump(buf_->data(), buf_len_, data_);
|
|
}
|
|
data_->append("</pre>");
|
|
index_++;
|
|
if (index_ < HttpCache::kNumCacheEntryDataIndices) {
|
|
next_state_ = STATE_READ_DATA;
|
|
} else {
|
|
data_->append(VIEW_CACHE_TAIL);
|
|
entry_->Close();
|
|
entry_ = NULL;
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
void ViewCacheHelper::OnIOComplete(int result) {
|
|
DoLoop(result);
|
|
}
|
|
|
|
} // namespace net.
|