Home | History | Annotate | Download | only in url_request
      1 // Copyright (c) 2006-2008 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 "net/url_request/view_cache_helper.h"
      6 
      7 #include "base/string_util.h"
      8 #include "net/base/escape.h"
      9 #include "net/base/io_buffer.h"
     10 #include "net/disk_cache/disk_cache.h"
     11 #include "net/http/http_cache.h"
     12 #include "net/http/http_response_headers.h"
     13 #include "net/http/http_response_info.h"
     14 #include "net/url_request/url_request_context.h"
     15 
     16 #define VIEW_CACHE_HEAD \
     17   "<html><body><table>"
     18 
     19 #define VIEW_CACHE_TAIL \
     20   "</table></body></html>"
     21 
     22 static void HexDump(const char *buf, size_t buf_len, std::string* result) {
     23   const size_t kMaxRows = 16;
     24   int offset = 0;
     25 
     26   const unsigned char *p;
     27   while (buf_len) {
     28     StringAppendF(result, "%08x:  ", offset);
     29     offset += kMaxRows;
     30 
     31     p = (const unsigned char *) buf;
     32 
     33     size_t i;
     34     size_t row_max = std::min(kMaxRows, buf_len);
     35 
     36     // print hex codes:
     37     for (i = 0; i < row_max; ++i)
     38       StringAppendF(result, "%02x  ", *p++);
     39     for (i = row_max; i < kMaxRows; ++i)
     40       result->append("    ");
     41 
     42     // print ASCII glyphs if possible:
     43     p = (const unsigned char *) buf;
     44     for (i = 0; i < row_max; ++i, ++p) {
     45       if (*p < 0x7F && *p > 0x1F) {
     46         AppendEscapedCharForHTML(*p, result);
     47       } else {
     48         result->push_back('.');
     49       }
     50     }
     51 
     52     result->push_back('\n');
     53 
     54     buf += row_max;
     55     buf_len -= row_max;
     56   }
     57 }
     58 
     59 static std::string FormatEntryInfo(disk_cache::Entry* entry,
     60                                    const std::string& url_prefix) {
     61   std::string key = entry->GetKey();
     62   GURL url = GURL(url_prefix + key);
     63   std::string row =
     64       "<tr><td><a href=\"" + url.spec() + "\">" + EscapeForHTML(key) +
     65       "</a></td></tr>";
     66   return row;
     67 }
     68 
     69 static std::string FormatEntryDetails(disk_cache::Entry* entry) {
     70   std::string result = EscapeForHTML(entry->GetKey());
     71 
     72   net::HttpResponseInfo response;
     73   bool truncated;
     74   if (net::HttpCache::ReadResponseInfo(entry, &response, &truncated) &&
     75       response.headers) {
     76     if (truncated)
     77       result.append("<pre>RESPONSE_INFO_TRUNCATED</pre>");
     78 
     79     result.append("<hr><pre>");
     80     result.append(EscapeForHTML(response.headers->GetStatusLine()));
     81     result.push_back('\n');
     82 
     83     void* iter = NULL;
     84     std::string name, value;
     85     while (response.headers->EnumerateHeaderLines(&iter, &name, &value)) {
     86       result.append(EscapeForHTML(name));
     87       result.append(": ");
     88       result.append(EscapeForHTML(value));
     89       result.push_back('\n');
     90     }
     91     result.append("</pre>");
     92   }
     93 
     94   for (int i = 0; i < 2; ++i) {
     95     result.append("<hr><pre>");
     96 
     97     int data_size = entry->GetDataSize(i);
     98 
     99     if (data_size) {
    100       scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_size);
    101       if (entry->ReadData(i, 0, buffer, data_size, NULL) == data_size)
    102         HexDump(buffer->data(), data_size, &result);
    103     }
    104 
    105     result.append("</pre>");
    106   }
    107 
    108   return result;
    109 }
    110 
    111 static disk_cache::Backend* GetDiskCache(URLRequestContext* context) {
    112   if (!context)
    113     return NULL;
    114 
    115   if (!context->http_transaction_factory())
    116     return NULL;
    117 
    118   net::HttpCache* http_cache = context->http_transaction_factory()->GetCache();
    119   if (!http_cache)
    120     return NULL;
    121 
    122   return http_cache->GetBackend();
    123 }
    124 
    125 static std::string FormatStatistics(disk_cache::Backend* disk_cache) {
    126   std::vector<std::pair<std::string, std::string> > stats;
    127   disk_cache->GetStats(&stats);
    128   std::string result;
    129 
    130   for (size_t index = 0; index < stats.size(); index++) {
    131     result.append(stats[index].first);
    132     result.append(": ");
    133     result.append(stats[index].second);
    134     result.append("<br/>\n");
    135   }
    136 
    137   return result;
    138 }
    139 
    140 // static
    141 void ViewCacheHelper::GetEntryInfoHTML(const std::string& key,
    142                                        URLRequestContext* context,
    143                                        const std::string& url_prefix,
    144                                        std::string* data) {
    145   disk_cache::Backend* disk_cache = GetDiskCache(context);
    146   if (!disk_cache) {
    147     data->assign("no disk cache");
    148     return;
    149   }
    150 
    151   if (key.empty()) {
    152     data->assign(VIEW_CACHE_HEAD);
    153     void* iter = NULL;
    154     disk_cache::Entry* entry;
    155     while (disk_cache->OpenNextEntry(&iter, &entry)) {
    156       data->append(FormatEntryInfo(entry, url_prefix));
    157       entry->Close();
    158     }
    159     data->append(VIEW_CACHE_TAIL);
    160   } else {
    161     disk_cache::Entry* entry;
    162     if (disk_cache->OpenEntry(key, &entry)) {
    163       data->assign(FormatEntryDetails(entry));
    164       entry->Close();
    165     } else {
    166       data->assign("no matching cache entry for: " + key);
    167     }
    168   }
    169 }
    170 
    171 // static
    172 void ViewCacheHelper::GetStatisticsHTML(URLRequestContext* context,
    173                                         std::string* data) {
    174   disk_cache::Backend* disk_cache = GetDiskCache(context);
    175   if (!disk_cache) {
    176     data->append("no disk cache");
    177     return;
    178   }
    179   data->append(FormatStatistics(disk_cache));
    180 }
    181