netwerk/protocol/about/nsAboutCache.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsAboutCache.h"
michael@0 7 #include "nsIInputStream.h"
michael@0 8 #include "nsIStorageStream.h"
michael@0 9 #include "nsIURI.h"
michael@0 10 #include "nsCOMPtr.h"
michael@0 11 #include "nsNetUtil.h"
michael@0 12 #include "nsEscape.h"
michael@0 13 #include "nsAboutProtocolUtils.h"
michael@0 14
michael@0 15 #include "nsICacheService.h"
michael@0 16
michael@0 17 NS_IMPL_ISUPPORTS(nsAboutCache, nsIAboutModule, nsICacheVisitor)
michael@0 18
michael@0 19 NS_IMETHODIMP
michael@0 20 nsAboutCache::NewChannel(nsIURI *aURI, nsIChannel **result)
michael@0 21 {
michael@0 22 NS_ENSURE_ARG_POINTER(aURI);
michael@0 23 nsresult rv;
michael@0 24 uint32_t bytesWritten;
michael@0 25
michael@0 26 *result = nullptr;
michael@0 27 // Get the cache manager service
michael@0 28 nsCOMPtr<nsICacheService> cacheService =
michael@0 29 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
michael@0 30 if (NS_FAILED(rv)) return rv;
michael@0 31
michael@0 32 nsCOMPtr<nsIStorageStream> storageStream;
michael@0 33 nsCOMPtr<nsIOutputStream> outputStream;
michael@0 34
michael@0 35 // Init: (block size, maximum length)
michael@0 36 rv = NS_NewStorageStream(256, (uint32_t)-1, getter_AddRefs(storageStream));
michael@0 37 if (NS_FAILED(rv)) return rv;
michael@0 38
michael@0 39 rv = storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
michael@0 40 if (NS_FAILED(rv)) return rv;
michael@0 41
michael@0 42 mBuffer.AssignLiteral(
michael@0 43 "<!DOCTYPE html>\n"
michael@0 44 "<html>\n"
michael@0 45 "<head>\n"
michael@0 46 " <title>Information about the Cache Service</title>\n"
michael@0 47 " <link rel=\"stylesheet\" "
michael@0 48 "href=\"chrome://global/skin/about.css\" type=\"text/css\"/>\n"
michael@0 49 " <link rel=\"stylesheet\" "
michael@0 50 "href=\"chrome://global/skin/aboutCache.css\" type=\"text/css\"/>\n"
michael@0 51 "</head>\n"
michael@0 52 "<body class=\"aboutPageWideContainer\">\n"
michael@0 53 "<h1>Information about the Cache Service</h1>\n");
michael@0 54
michael@0 55 outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
michael@0 56
michael@0 57 rv = ParseURI(aURI, mDeviceID);
michael@0 58 if (NS_FAILED(rv)) return rv;
michael@0 59
michael@0 60 mStream = outputStream;
michael@0 61
michael@0 62 // nsCacheService::VisitEntries calls nsMemoryCacheDevice::Visit,
michael@0 63 // nsDiskCacheDevice::Visit and nsOfflineCacheDevice::Visit,
michael@0 64 // each of which call
michael@0 65 // 1. VisitDevice (for about:cache),
michael@0 66 // 2. VisitEntry in a loop (for about:cache?device=disk etc.)
michael@0 67 rv = cacheService->VisitEntries(this);
michael@0 68 mBuffer.Truncate();
michael@0 69 if (rv == NS_ERROR_NOT_AVAILABLE) {
michael@0 70 mBuffer.AppendLiteral("<h2>The cache is disabled.</h2>\n");
michael@0 71 }
michael@0 72 else if (NS_FAILED(rv)) {
michael@0 73 return rv;
michael@0 74 }
michael@0 75
michael@0 76 if (!mDeviceID.IsEmpty()) {
michael@0 77 mBuffer.AppendLiteral("</table>\n");
michael@0 78 }
michael@0 79 mBuffer.AppendLiteral("</body>\n"
michael@0 80 "</html>\n");
michael@0 81 outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
michael@0 82
michael@0 83 nsCOMPtr<nsIInputStream> inStr;
michael@0 84
michael@0 85 rv = storageStream->NewInputStream(0, getter_AddRefs(inStr));
michael@0 86 if (NS_FAILED(rv)) return rv;
michael@0 87
michael@0 88 nsCOMPtr<nsIChannel> channel;
michael@0 89 rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, inStr,
michael@0 90 NS_LITERAL_CSTRING("text/html"),
michael@0 91 NS_LITERAL_CSTRING("utf-8"));
michael@0 92 if (NS_FAILED(rv)) return rv;
michael@0 93
michael@0 94 channel.forget(result);
michael@0 95 return rv;
michael@0 96 }
michael@0 97
michael@0 98 NS_IMETHODIMP
michael@0 99 nsAboutCache::GetURIFlags(nsIURI *aURI, uint32_t *result)
michael@0 100 {
michael@0 101 *result = 0;
michael@0 102 return NS_OK;
michael@0 103 }
michael@0 104
michael@0 105 NS_IMETHODIMP
michael@0 106 nsAboutCache::VisitDevice(const char *deviceID,
michael@0 107 nsICacheDeviceInfo *deviceInfo,
michael@0 108 bool *visitEntries)
michael@0 109 {
michael@0 110 uint32_t bytesWritten, value, entryCount;
michael@0 111 nsXPIDLCString str;
michael@0 112
michael@0 113 *visitEntries = false;
michael@0 114
michael@0 115 if (mDeviceID.IsEmpty() || mDeviceID.Equals(deviceID)) {
michael@0 116
michael@0 117 // We need mStream for this
michael@0 118 if (!mStream)
michael@0 119 return NS_ERROR_FAILURE;
michael@0 120
michael@0 121 // Write out the Cache Name
michael@0 122 deviceInfo->GetDescription(getter_Copies(str));
michael@0 123
michael@0 124 mBuffer.AssignLiteral("<h2>");
michael@0 125 mBuffer.Append(str);
michael@0 126 mBuffer.AppendLiteral("</h2>\n"
michael@0 127 "<table id=\"");
michael@0 128 mBuffer.Append(deviceID);
michael@0 129 mBuffer.AppendLiteral("\">\n");
michael@0 130
michael@0 131 // Write out cache info
michael@0 132 // Number of entries
michael@0 133 mBuffer.AppendLiteral(" <tr>\n"
michael@0 134 " <th>Number of entries:</th>\n"
michael@0 135 " <td>");
michael@0 136 entryCount = 0;
michael@0 137 deviceInfo->GetEntryCount(&entryCount);
michael@0 138 mBuffer.AppendInt(entryCount);
michael@0 139 mBuffer.AppendLiteral("</td>\n"
michael@0 140 " </tr>\n");
michael@0 141
michael@0 142 // Maximum storage size
michael@0 143 mBuffer.AppendLiteral(" <tr>\n"
michael@0 144 " <th>Maximum storage size:</th>\n"
michael@0 145 " <td>");
michael@0 146 value = 0;
michael@0 147 deviceInfo->GetMaximumSize(&value);
michael@0 148 mBuffer.AppendInt(value/1024);
michael@0 149 mBuffer.AppendLiteral(" KiB</td>\n"
michael@0 150 " </tr>\n");
michael@0 151
michael@0 152 // Storage in use
michael@0 153 mBuffer.AppendLiteral(" <tr>\n"
michael@0 154 " <th>Storage in use:</th>\n"
michael@0 155 " <td>");
michael@0 156 value = 0;
michael@0 157 deviceInfo->GetTotalSize(&value);
michael@0 158 mBuffer.AppendInt(value/1024);
michael@0 159 mBuffer.AppendLiteral(" KiB</td>\n"
michael@0 160 " </tr>\n");
michael@0 161
michael@0 162 deviceInfo->GetUsageReport(getter_Copies(str));
michael@0 163 mBuffer.Append(str);
michael@0 164
michael@0 165 if (mDeviceID.IsEmpty()) { // The about:cache case
michael@0 166 if (entryCount != 0) { // Add the "List Cache Entries" link
michael@0 167 mBuffer.AppendLiteral(" <tr>\n"
michael@0 168 " <th><a href=\"about:cache?device=");
michael@0 169 mBuffer.Append(deviceID);
michael@0 170 mBuffer.AppendLiteral("\">List Cache Entries</a></th>\n"
michael@0 171 " </tr>\n");
michael@0 172 }
michael@0 173 mBuffer.AppendLiteral("</table>\n");
michael@0 174 } else { // The about:cache?device=disk etc. case
michael@0 175 mBuffer.AppendLiteral("</table>\n");
michael@0 176 if (entryCount != 0) {
michael@0 177 *visitEntries = true;
michael@0 178 mBuffer.AppendLiteral("<hr/>\n"
michael@0 179 "<table id=\"entries\">\n"
michael@0 180 " <colgroup>\n"
michael@0 181 " <col id=\"col-key\">\n"
michael@0 182 " <col id=\"col-dataSize\">\n"
michael@0 183 " <col id=\"col-fetchCount\">\n"
michael@0 184 " <col id=\"col-lastModified\">\n"
michael@0 185 " <col id=\"col-expires\">\n"
michael@0 186 " </colgroup>\n"
michael@0 187 " <thead>\n"
michael@0 188 " <tr>\n"
michael@0 189 " <th>Key</th>\n"
michael@0 190 " <th>Data size</th>\n"
michael@0 191 " <th>Fetch count</th>\n"
michael@0 192 " <th>Last modified</th>\n"
michael@0 193 " <th>Expires</th>\n"
michael@0 194 " </tr>\n"
michael@0 195 " </thead>\n");
michael@0 196 }
michael@0 197 }
michael@0 198
michael@0 199 mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
michael@0 200 }
michael@0 201
michael@0 202 return NS_OK;
michael@0 203 }
michael@0 204
michael@0 205 NS_IMETHODIMP
michael@0 206 nsAboutCache::VisitEntry(const char *deviceID,
michael@0 207 nsICacheEntryInfo *entryInfo,
michael@0 208 bool *visitNext)
michael@0 209 {
michael@0 210 // We need mStream for this
michael@0 211 if (!mStream)
michael@0 212 return NS_ERROR_FAILURE;
michael@0 213
michael@0 214 nsresult rv;
michael@0 215 uint32_t bytesWritten;
michael@0 216 nsAutoCString key;
michael@0 217 nsXPIDLCString clientID;
michael@0 218 bool streamBased;
michael@0 219
michael@0 220 rv = entryInfo->GetKey(key);
michael@0 221 if (NS_FAILED(rv)) return rv;
michael@0 222
michael@0 223 rv = entryInfo->GetClientID(getter_Copies(clientID));
michael@0 224 if (NS_FAILED(rv)) return rv;
michael@0 225
michael@0 226 rv = entryInfo->IsStreamBased(&streamBased);
michael@0 227 if (NS_FAILED(rv)) return rv;
michael@0 228
michael@0 229 // Generate a about:cache-entry URL for this entry...
michael@0 230 nsAutoCString url;
michael@0 231 url.AssignLiteral("about:cache-entry?client=");
michael@0 232 url += clientID;
michael@0 233 url.AppendLiteral("&amp;sb=");
michael@0 234 url += streamBased ? '1' : '0';
michael@0 235 url.AppendLiteral("&amp;key=");
michael@0 236 char* escapedKey = nsEscapeHTML(key.get());
michael@0 237 url += escapedKey; // key
michael@0 238
michael@0 239 // Entry start...
michael@0 240 mBuffer.AssignLiteral(" <tr>\n");
michael@0 241
michael@0 242 // URI
michael@0 243 mBuffer.AppendLiteral(" <td><a href=\"");
michael@0 244 mBuffer.Append(url);
michael@0 245 mBuffer.AppendLiteral("\">");
michael@0 246 mBuffer.Append(escapedKey);
michael@0 247 nsMemory::Free(escapedKey);
michael@0 248 mBuffer.AppendLiteral("</a></td>\n");
michael@0 249
michael@0 250 // Content length
michael@0 251 uint32_t length = 0;
michael@0 252 entryInfo->GetDataSize(&length);
michael@0 253 mBuffer.AppendLiteral(" <td>");
michael@0 254 mBuffer.AppendInt(length);
michael@0 255 mBuffer.AppendLiteral(" bytes</td>\n");
michael@0 256
michael@0 257 // Number of accesses
michael@0 258 int32_t fetchCount = 0;
michael@0 259 entryInfo->GetFetchCount(&fetchCount);
michael@0 260 mBuffer.AppendLiteral(" <td>");
michael@0 261 mBuffer.AppendInt(fetchCount);
michael@0 262 mBuffer.AppendLiteral("</td>\n");
michael@0 263
michael@0 264 // vars for reporting time
michael@0 265 char buf[255];
michael@0 266 uint32_t t;
michael@0 267
michael@0 268 // Last modified time
michael@0 269 mBuffer.AppendLiteral(" <td>");
michael@0 270 entryInfo->GetLastModified(&t);
michael@0 271 if (t) {
michael@0 272 PrintTimeString(buf, sizeof(buf), t);
michael@0 273 mBuffer.Append(buf);
michael@0 274 } else
michael@0 275 mBuffer.AppendLiteral("No last modified time");
michael@0 276 mBuffer.AppendLiteral("</td>\n");
michael@0 277
michael@0 278 // Expires time
michael@0 279 mBuffer.AppendLiteral(" <td>");
michael@0 280 entryInfo->GetExpirationTime(&t);
michael@0 281 if (t < 0xFFFFFFFF) {
michael@0 282 PrintTimeString(buf, sizeof(buf), t);
michael@0 283 mBuffer.Append(buf);
michael@0 284 } else {
michael@0 285 mBuffer.AppendLiteral("No expiration time");
michael@0 286 }
michael@0 287 mBuffer.AppendLiteral("</td>\n");
michael@0 288
michael@0 289 // Entry is done...
michael@0 290 mBuffer.AppendLiteral(" </tr>\n");
michael@0 291
michael@0 292 mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
michael@0 293
michael@0 294 *visitNext = true;
michael@0 295 return NS_OK;
michael@0 296 }
michael@0 297
michael@0 298
michael@0 299 nsresult
michael@0 300 nsAboutCache::ParseURI(nsIURI * uri, nsCString &deviceID)
michael@0 301 {
michael@0 302 //
michael@0 303 // about:cache[?device=string]
michael@0 304 //
michael@0 305 nsresult rv;
michael@0 306
michael@0 307 deviceID.Truncate();
michael@0 308
michael@0 309 nsAutoCString path;
michael@0 310 rv = uri->GetPath(path);
michael@0 311 if (NS_FAILED(rv)) return rv;
michael@0 312
michael@0 313 nsACString::const_iterator start, valueStart, end;
michael@0 314 path.BeginReading(start);
michael@0 315 path.EndReading(end);
michael@0 316
michael@0 317 valueStart = end;
michael@0 318 if (!FindInReadable(NS_LITERAL_CSTRING("?device="), start, valueStart))
michael@0 319 return NS_OK;
michael@0 320
michael@0 321 deviceID.Assign(Substring(valueStart, end));
michael@0 322 return NS_OK;
michael@0 323 }
michael@0 324
michael@0 325
michael@0 326 nsresult
michael@0 327 nsAboutCache::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
michael@0 328 {
michael@0 329 nsAboutCache* about = new nsAboutCache();
michael@0 330 if (about == nullptr)
michael@0 331 return NS_ERROR_OUT_OF_MEMORY;
michael@0 332 NS_ADDREF(about);
michael@0 333 nsresult rv = about->QueryInterface(aIID, aResult);
michael@0 334 NS_RELEASE(about);
michael@0 335 return rv;
michael@0 336 }
michael@0 337
michael@0 338
michael@0 339
michael@0 340 ////////////////////////////////////////////////////////////////////////////////

mercurial