diff -r 000000000000 -r 6474c204b198 netwerk/protocol/about/nsAboutCache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/netwerk/protocol/about/nsAboutCache.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,340 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsAboutCache.h" +#include "nsIInputStream.h" +#include "nsIStorageStream.h" +#include "nsIURI.h" +#include "nsCOMPtr.h" +#include "nsNetUtil.h" +#include "nsEscape.h" +#include "nsAboutProtocolUtils.h" + +#include "nsICacheService.h" + +NS_IMPL_ISUPPORTS(nsAboutCache, nsIAboutModule, nsICacheVisitor) + +NS_IMETHODIMP +nsAboutCache::NewChannel(nsIURI *aURI, nsIChannel **result) +{ + NS_ENSURE_ARG_POINTER(aURI); + nsresult rv; + uint32_t bytesWritten; + + *result = nullptr; + // Get the cache manager service + nsCOMPtr cacheService = + do_GetService(NS_CACHESERVICE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr storageStream; + nsCOMPtr outputStream; + + // Init: (block size, maximum length) + rv = NS_NewStorageStream(256, (uint32_t)-1, getter_AddRefs(storageStream)); + if (NS_FAILED(rv)) return rv; + + rv = storageStream->GetOutputStream(0, getter_AddRefs(outputStream)); + if (NS_FAILED(rv)) return rv; + + mBuffer.AssignLiteral( + "\n" + "\n" + "\n" + " Information about the Cache Service\n" + " \n" + " \n" + "\n" + "\n" + "

Information about the Cache Service

\n"); + + outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten); + + rv = ParseURI(aURI, mDeviceID); + if (NS_FAILED(rv)) return rv; + + mStream = outputStream; + + // nsCacheService::VisitEntries calls nsMemoryCacheDevice::Visit, + // nsDiskCacheDevice::Visit and nsOfflineCacheDevice::Visit, + // each of which call + // 1. VisitDevice (for about:cache), + // 2. VisitEntry in a loop (for about:cache?device=disk etc.) + rv = cacheService->VisitEntries(this); + mBuffer.Truncate(); + if (rv == NS_ERROR_NOT_AVAILABLE) { + mBuffer.AppendLiteral("

The cache is disabled.

\n"); + } + else if (NS_FAILED(rv)) { + return rv; + } + + if (!mDeviceID.IsEmpty()) { + mBuffer.AppendLiteral("\n"); + } + mBuffer.AppendLiteral("\n" + "\n"); + outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten); + + nsCOMPtr inStr; + + rv = storageStream->NewInputStream(0, getter_AddRefs(inStr)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr channel; + rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, inStr, + NS_LITERAL_CSTRING("text/html"), + NS_LITERAL_CSTRING("utf-8")); + if (NS_FAILED(rv)) return rv; + + channel.forget(result); + return rv; +} + +NS_IMETHODIMP +nsAboutCache::GetURIFlags(nsIURI *aURI, uint32_t *result) +{ + *result = 0; + return NS_OK; +} + +NS_IMETHODIMP +nsAboutCache::VisitDevice(const char *deviceID, + nsICacheDeviceInfo *deviceInfo, + bool *visitEntries) +{ + uint32_t bytesWritten, value, entryCount; + nsXPIDLCString str; + + *visitEntries = false; + + if (mDeviceID.IsEmpty() || mDeviceID.Equals(deviceID)) { + + // We need mStream for this + if (!mStream) + return NS_ERROR_FAILURE; + + // Write out the Cache Name + deviceInfo->GetDescription(getter_Copies(str)); + + mBuffer.AssignLiteral("

"); + mBuffer.Append(str); + mBuffer.AppendLiteral("

\n" + "\n"); + + // Write out cache info + // Number of entries + mBuffer.AppendLiteral(" \n" + " \n" + " \n" + " \n"); + + // Maximum storage size + mBuffer.AppendLiteral(" \n" + " \n" + " \n" + " \n"); + + // Storage in use + mBuffer.AppendLiteral(" \n" + " \n" + " \n" + " \n"); + + deviceInfo->GetUsageReport(getter_Copies(str)); + mBuffer.Append(str); + + if (mDeviceID.IsEmpty()) { // The about:cache case + if (entryCount != 0) { // Add the "List Cache Entries" link + mBuffer.AppendLiteral(" \n" + " \n" + " \n"); + } + mBuffer.AppendLiteral("
Number of entries:"); + entryCount = 0; + deviceInfo->GetEntryCount(&entryCount); + mBuffer.AppendInt(entryCount); + mBuffer.AppendLiteral("
Maximum storage size:"); + value = 0; + deviceInfo->GetMaximumSize(&value); + mBuffer.AppendInt(value/1024); + mBuffer.AppendLiteral(" KiB
Storage in use:"); + value = 0; + deviceInfo->GetTotalSize(&value); + mBuffer.AppendInt(value/1024); + mBuffer.AppendLiteral(" KiB
List Cache Entries
\n"); + } else { // The about:cache?device=disk etc. case + mBuffer.AppendLiteral("\n"); + if (entryCount != 0) { + *visitEntries = true; + mBuffer.AppendLiteral("
\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n"); + } + } + + mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsAboutCache::VisitEntry(const char *deviceID, + nsICacheEntryInfo *entryInfo, + bool *visitNext) +{ + // We need mStream for this + if (!mStream) + return NS_ERROR_FAILURE; + + nsresult rv; + uint32_t bytesWritten; + nsAutoCString key; + nsXPIDLCString clientID; + bool streamBased; + + rv = entryInfo->GetKey(key); + if (NS_FAILED(rv)) return rv; + + rv = entryInfo->GetClientID(getter_Copies(clientID)); + if (NS_FAILED(rv)) return rv; + + rv = entryInfo->IsStreamBased(&streamBased); + if (NS_FAILED(rv)) return rv; + + // Generate a about:cache-entry URL for this entry... + nsAutoCString url; + url.AssignLiteral("about:cache-entry?client="); + url += clientID; + url.AppendLiteral("&sb="); + url += streamBased ? '1' : '0'; + url.AppendLiteral("&key="); + char* escapedKey = nsEscapeHTML(key.get()); + url += escapedKey; // key + + // Entry start... + mBuffer.AssignLiteral(" \n"); + + // URI + mBuffer.AppendLiteral(" \n"); + + // Content length + uint32_t length = 0; + entryInfo->GetDataSize(&length); + mBuffer.AppendLiteral(" \n"); + + // Number of accesses + int32_t fetchCount = 0; + entryInfo->GetFetchCount(&fetchCount); + mBuffer.AppendLiteral(" \n"); + + // vars for reporting time + char buf[255]; + uint32_t t; + + // Last modified time + mBuffer.AppendLiteral(" \n"); + + // Expires time + mBuffer.AppendLiteral(" \n"); + + // Entry is done... + mBuffer.AppendLiteral(" \n"); + + mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten); + + *visitNext = true; + return NS_OK; +} + + +nsresult +nsAboutCache::ParseURI(nsIURI * uri, nsCString &deviceID) +{ + // + // about:cache[?device=string] + // + nsresult rv; + + deviceID.Truncate(); + + nsAutoCString path; + rv = uri->GetPath(path); + if (NS_FAILED(rv)) return rv; + + nsACString::const_iterator start, valueStart, end; + path.BeginReading(start); + path.EndReading(end); + + valueStart = end; + if (!FindInReadable(NS_LITERAL_CSTRING("?device="), start, valueStart)) + return NS_OK; + + deviceID.Assign(Substring(valueStart, end)); + return NS_OK; +} + + +nsresult +nsAboutCache::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + nsAboutCache* about = new nsAboutCache(); + if (about == nullptr) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(about); + nsresult rv = about->QueryInterface(aIID, aResult); + NS_RELEASE(about); + return rv; +} + + + +////////////////////////////////////////////////////////////////////////////////
KeyData sizeFetch countLast modifiedExpires
"); + mBuffer.Append(escapedKey); + nsMemory::Free(escapedKey); + mBuffer.AppendLiteral(""); + mBuffer.AppendInt(length); + mBuffer.AppendLiteral(" bytes"); + mBuffer.AppendInt(fetchCount); + mBuffer.AppendLiteral(""); + entryInfo->GetLastModified(&t); + if (t) { + PrintTimeString(buf, sizeof(buf), t); + mBuffer.Append(buf); + } else + mBuffer.AppendLiteral("No last modified time"); + mBuffer.AppendLiteral(""); + entryInfo->GetExpirationTime(&t); + if (t < 0xFFFFFFFF) { + PrintTimeString(buf, sizeof(buf), t); + mBuffer.Append(buf); + } else { + mBuffer.AppendLiteral("No expiration time"); + } + mBuffer.AppendLiteral("