Back to index

lightning-sunbird  0.9+nobinonly
nsAboutCache.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Alexey Chernyak <alexeyc@bigfoot.com> (XHTML 1.1 conversion)
00024  *   Henrik Gemal <mozilla@gemal.dk>
00025  *   Darin Fisher <darin@netscape.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsAboutCache.h"
00042 #include "nsIIOService.h"
00043 #include "nsIServiceManager.h"
00044 #include "nsIInputStream.h"
00045 #include "nsIStorageStream.h"
00046 #include "nsISimpleEnumerator.h"
00047 #include "nsXPIDLString.h"
00048 #include "nsIURI.h"
00049 #include "nsCOMPtr.h"
00050 #include "nsNetUtil.h"
00051 #include "prtime.h"
00052 #include "nsEscape.h"
00053 
00054 #include "nsICacheService.h"
00055 
00056 static PRTime SecondsToPRTime(PRUint32 t_sec)
00057 {
00058     PRTime t_usec, usec_per_sec;
00059     LL_I2L(t_usec, t_sec);
00060     LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
00061     LL_MUL(t_usec, t_usec, usec_per_sec);
00062     return t_usec;
00063 }
00064 static void PrintTimeString(char *buf, PRUint32 bufsize, PRUint32 t_sec)
00065 {
00066     PRExplodedTime et;
00067     PRTime t_usec = SecondsToPRTime(t_sec);
00068     PR_ExplodeTime(t_usec, PR_LocalTimeParameters, &et);
00069     PR_FormatTime(buf, bufsize, "%Y-%m-%d %H:%M:%S", &et);
00070 }
00071 
00072 
00073 NS_IMPL_ISUPPORTS2(nsAboutCache, nsIAboutModule, nsICacheVisitor)
00074 
00075 NS_IMETHODIMP
00076 nsAboutCache::NewChannel(nsIURI *aURI, nsIChannel **result)
00077 {
00078     NS_ENSURE_ARG_POINTER(aURI);
00079     nsresult rv;
00080     PRUint32 bytesWritten;
00081 
00082     *result = nsnull;
00083 /*
00084     nsXPIDLCString path;
00085     rv = aURI->GetPath(getter_Copies(path));
00086     if (NS_FAILED(rv)) return rv;
00087 
00088     PRBool clear = PR_FALSE;
00089     PRBool leaks = PR_FALSE;
00090 
00091     nsCAutoString p(path);
00092     PRInt32 pos = p.Find("?");
00093     if (pos > 0) {
00094         nsCAutoString param;
00095         (void)p.Right(param, p.Length() - (pos+1));
00096         if (param.Equals("new"))
00097             statType = nsTraceRefcnt::NEW_STATS;
00098         else if (param.Equals("clear"))
00099             clear = PR_TRUE;
00100         else if (param.Equals("leaks"))
00101             leaks = PR_TRUE;
00102     }
00103 */
00104     // Get the cache manager service
00105     nsCOMPtr<nsICacheService> cacheService = 
00106              do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
00107     if (NS_FAILED(rv)) return rv;
00108 
00109     nsCOMPtr<nsIStorageStream> storageStream;
00110     nsCOMPtr<nsIOutputStream> outputStream;
00111 
00112     // Init: (block size, maximum length)
00113     rv = NS_NewStorageStream(256, (PRUint32)-1, getter_AddRefs(storageStream));
00114     if (NS_FAILED(rv)) return rv;
00115 
00116     rv = storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
00117     if (NS_FAILED(rv)) return rv;
00118 
00119     mBuffer.AssignLiteral(
00120                    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00121                    "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n"
00122                    "    \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
00123                    "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
00124                    "<head>\n<title>Information about the Cache Service</title>\n</head>\n"
00125                    "<body>\n<div>\n");
00126 
00127     outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
00128 
00129     rv = ParseURI(aURI, mDeviceID);
00130     if (NS_FAILED(rv)) return rv;
00131 
00132     mStream = outputStream;
00133     rv = cacheService->VisitEntries(this);
00134     if (NS_FAILED(rv)) return rv;
00135 
00136     if (!mDeviceID.IsEmpty()) {
00137         mBuffer.AssignLiteral("</pre>\n");
00138     }
00139     else {
00140         mBuffer.Truncate();
00141     }
00142     mBuffer.AppendLiteral("</div>\n</body>\n</html>\n");
00143     outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
00144         
00145     nsCOMPtr<nsIInputStream> inStr;
00146 
00147     rv = storageStream->NewInputStream(0, getter_AddRefs(inStr));
00148     if (NS_FAILED(rv)) return rv;
00149 
00150     nsIChannel* channel;
00151     rv = NS_NewInputStreamChannel(&channel, aURI, inStr,
00152                                   NS_LITERAL_CSTRING("text/html"),
00153                                   NS_LITERAL_CSTRING("utf-8"));
00154     if (NS_FAILED(rv)) return rv;
00155 
00156     *result = channel;
00157     return rv;
00158 }
00159 
00160 
00161 NS_IMETHODIMP
00162 nsAboutCache::VisitDevice(const char *deviceID,
00163                           nsICacheDeviceInfo *deviceInfo,
00164                           PRBool *visitEntries)
00165 {
00166     PRUint32 bytesWritten, value;
00167     nsXPIDLCString str;
00168 
00169     *visitEntries = PR_FALSE;
00170 
00171     if (mDeviceID.IsEmpty() || mDeviceID.Equals(deviceID)) {
00172 
00173         // We need mStream for this
00174         if (!mStream)
00175           return NS_ERROR_FAILURE;
00176 
00177         // Write out the Cache Name
00178         deviceInfo->GetDescription(getter_Copies(str));
00179 
00180         mBuffer.AssignLiteral("<h2>");
00181         mBuffer.Append(str);
00182         mBuffer.AppendLiteral("</h2>\n<br />\n"
00183                               "<table>\n");
00184 
00185         // Write out cache info
00186 
00187         mBuffer.AppendLiteral("\n<tr>\n<td><b>Number of entries:</b></td>\n");
00188         value = 0;
00189         deviceInfo->GetEntryCount(&value);
00190         mBuffer.AppendLiteral("<td><tt>");
00191         mBuffer.AppendInt(value);
00192         mBuffer.AppendLiteral("</tt></td>\n</tr>\n"
00193                               "\n<tr>\n<td><b>Maximum storage size:</b></td>\n");
00194         value = 0;
00195         deviceInfo->GetMaximumSize(&value);
00196         mBuffer.AppendLiteral("<td><tt>");
00197         mBuffer.AppendInt(value/1024);
00198         mBuffer.AppendLiteral(" KiB</tt></td>\n</tr>\n"
00199                               "\n<tr>\n<td><b>Storage in use:</b></td>\n"
00200                               "<td><tt>");
00201         value = 0;
00202         deviceInfo->GetTotalSize(&value);
00203         mBuffer.AppendInt(value/1024);
00204         mBuffer.AppendLiteral(" KiB</tt></td>\n</tr>\n");
00205 
00206         deviceInfo->GetUsageReport(getter_Copies(str));
00207         mBuffer.Append(str);
00208         mBuffer.AppendLiteral("</table>\n\n<br />");
00209 
00210         if (mDeviceID.IsEmpty()) {
00211             mBuffer.AppendLiteral("\n<a href=\"about:cache?device=");
00212             mBuffer.Append(deviceID);
00213             mBuffer.AppendLiteral("\">List Cache Entries</a>\n"
00214                                   "<hr />\n");
00215         } else {
00216             *visitEntries = PR_TRUE;
00217             mBuffer.AppendLiteral("<hr />\n<pre>\n");
00218         }
00219         
00220         mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
00221     }
00222 
00223     return NS_OK;
00224 }
00225 
00226 NS_IMETHODIMP
00227 nsAboutCache::VisitEntry(const char *deviceID,
00228                          nsICacheEntryInfo *entryInfo,
00229                          PRBool *visitNext)
00230 {
00231     // We need mStream for this
00232     if (!mStream)
00233       return NS_ERROR_FAILURE;
00234 
00235     nsresult        rv;
00236     PRUint32        bytesWritten;
00237     nsCAutoString   key;
00238     nsXPIDLCString  clientID;
00239     PRBool          streamBased;
00240     
00241     rv = entryInfo->GetKey(key);
00242     if (NS_FAILED(rv))  return rv;
00243 
00244     rv = entryInfo->GetClientID(getter_Copies(clientID));
00245     if (NS_FAILED(rv))  return rv;
00246 
00247     rv = entryInfo->IsStreamBased(&streamBased);
00248     if (NS_FAILED(rv)) return rv;
00249 
00250     // Generate a about:cache-entry URL for this entry...
00251     nsCAutoString url;
00252     url.AssignLiteral("about:cache-entry?client=");
00253     url += clientID;
00254     url.AppendLiteral("&amp;sb=");
00255     url += streamBased ? '1' : '0';
00256     url.AppendLiteral("&amp;key=");
00257     char* escapedKey = nsEscapeHTML(key.get());
00258     url += escapedKey; // key
00259 
00260     // Entry start...
00261 
00262     // URI
00263     mBuffer.AssignLiteral("<b>           Key:</b> <a href=\"");
00264     mBuffer.Append(url);
00265     mBuffer.AppendLiteral("\">");
00266     mBuffer.Append(escapedKey);
00267     nsMemory::Free(escapedKey);
00268     mBuffer.AppendLiteral("</a>");
00269 
00270     // Content length
00271     PRUint32 length = 0;
00272     entryInfo->GetDataSize(&length);
00273 
00274     mBuffer.AppendLiteral("\n<b>     Data size:</b> ");
00275     mBuffer.AppendInt(length);
00276     mBuffer.AppendLiteral(" bytes");
00277 
00278     // Number of accesses
00279     PRInt32 fetchCount = 0;
00280     entryInfo->GetFetchCount(&fetchCount);
00281 
00282     mBuffer.AppendLiteral("\n<b>   Fetch count:</b> ");
00283     mBuffer.AppendInt(fetchCount);
00284 
00285     // vars for reporting time
00286     char buf[255];
00287     PRUint32 t;
00288 
00289     // Last modified time
00290     mBuffer.AppendLiteral("\n<b> Last modified:</b> ");
00291     entryInfo->GetLastModified(&t);
00292     if (t) {
00293         PrintTimeString(buf, sizeof(buf), t);
00294         mBuffer.Append(buf);
00295     } else
00296         mBuffer.AppendLiteral("No last modified time");
00297 
00298     // Expires time
00299     mBuffer.AppendLiteral("\n<b>       Expires:</b> ");
00300     entryInfo->GetExpirationTime(&t);
00301     if (t < 0xFFFFFFFF) {
00302         PrintTimeString(buf, sizeof(buf), t);
00303         mBuffer.Append(buf);
00304     } else {
00305         mBuffer.AppendLiteral("No expiration time");
00306     }
00307 
00308     // Entry is done...
00309     mBuffer.AppendLiteral("\n\n");
00310 
00311     mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
00312 
00313     *visitNext = PR_TRUE;
00314     return NS_OK;
00315 }
00316 
00317 
00318 nsresult
00319 nsAboutCache::ParseURI(nsIURI * uri, nsCString &deviceID)
00320 {
00321     //
00322     // about:cache[?device=string]
00323     //
00324     nsresult rv;
00325 
00326     deviceID.Truncate();
00327 
00328     nsCAutoString path;
00329     rv = uri->GetPath(path);
00330     if (NS_FAILED(rv)) return rv;
00331 
00332     nsACString::const_iterator start, valueStart, end;
00333     path.BeginReading(start);
00334     path.EndReading(end);
00335 
00336     valueStart = end;
00337     if (!FindInReadable(NS_LITERAL_CSTRING("?device="), start, valueStart))
00338         return NS_OK;
00339 
00340     deviceID.Assign(Substring(valueStart, end));
00341     return NS_OK;
00342 }
00343 
00344 
00345 NS_METHOD
00346 nsAboutCache::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
00347 {
00348     nsAboutCache* about = new nsAboutCache();
00349     if (about == nsnull)
00350         return NS_ERROR_OUT_OF_MEMORY;
00351     NS_ADDREF(about);
00352     nsresult rv = about->QueryInterface(aIID, aResult);
00353     NS_RELEASE(about);
00354     return rv;
00355 }
00356 
00357 
00358