// Copyright (c) 2006-2008 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 "base/string_util.h" #include "net/base/escape.h" #include "net/base/io_buffer.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><body><table>" #define VIEW_CACHE_TAIL \ "</table></body></html>" static void 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) { 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) StringAppendF(result, "%02x ", *p++); for (i = row_max; i < kMaxRows; ++i) 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; } } static 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; } static std::string FormatEntryDetails(disk_cache::Entry* entry, int num_entry_data_indices) { std::string result = EscapeForHTML(entry->GetKey()); net::HttpResponseInfo response; bool truncated; if (net::HttpCache::ReadResponseInfo(entry, &response, &truncated) && response.headers) { if (truncated) result.append("<pre>RESPONSE_INFO_TRUNCATED</pre>"); result.append("<hr><pre>"); result.append(EscapeForHTML(response.headers->GetStatusLine())); result.push_back('\n'); void* iter = NULL; std::string name, value; while (response.headers->EnumerateHeaderLines(&iter, &name, &value)) { result.append(EscapeForHTML(name)); result.append(": "); result.append(EscapeForHTML(value)); result.push_back('\n'); } result.append("</pre>"); } for (int i = 0; i < num_entry_data_indices; ++i) { result.append("<hr><pre>"); int data_size = entry->GetDataSize(i); if (data_size) { scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_size); if (entry->ReadData(i, 0, buffer, data_size, NULL) == data_size) HexDump(buffer->data(), data_size, &result); } result.append("</pre>"); } return result; } static disk_cache::Backend* GetDiskCache(URLRequestContext* context) { if (!context) return NULL; if (!context->http_transaction_factory()) return NULL; net::HttpCache* http_cache = context->http_transaction_factory()->GetCache(); if (!http_cache) return NULL; return http_cache->GetBackend(); } static std::string FormatStatistics(disk_cache::Backend* disk_cache) { std::vector<std::pair<std::string, std::string> > stats; disk_cache->GetStats(&stats); std::string result; for (size_t index = 0; index < stats.size(); index++) { result.append(stats[index].first); result.append(": "); result.append(stats[index].second); result.append("<br/>\n"); } return result; } // static void ViewCacheHelper::GetEntryInfoHTML(const std::string& key, URLRequestContext* context, const std::string& url_prefix, std::string* data) { disk_cache::Backend* disk_cache = GetDiskCache(context); if (!disk_cache) { data->assign("no disk cache"); return; } if (key.empty()) { data->assign(VIEW_CACHE_HEAD); void* iter = NULL; disk_cache::Entry* entry; while (disk_cache->OpenNextEntry(&iter, &entry)) { data->append(FormatEntryInfo(entry, url_prefix)); entry->Close(); } data->append(VIEW_CACHE_TAIL); } else { disk_cache::Entry* entry; if (disk_cache->OpenEntry(key, &entry)) { data->assign(FormatEntryDetails( entry, net::HttpCache::kNumCacheEntryDataIndices)); entry->Close(); } else { data->assign("no matching cache entry for: " + EscapeForHTML(key)); } } } // static void ViewCacheHelper::GetStatisticsHTML(URLRequestContext* context, std::string* data) { disk_cache::Backend* disk_cache = GetDiskCache(context); if (!disk_cache) { data->append("no disk cache"); return; } data->append(FormatStatistics(disk_cache)); }