Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / netwerk / protocol / about / src / nsAboutCache.cpp
bloba69a75f957f3e4f47ea3dc28ec0f01a3a15a0fd9
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Alexey Chernyak <alexeyc@bigfoot.com> (XHTML 1.1 conversion)
24 * Henrik Gemal <mozilla@gemal.dk>
25 * Darin Fisher <darin@netscape.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "nsAboutCache.h"
42 #include "nsIIOService.h"
43 #include "nsIServiceManager.h"
44 #include "nsIInputStream.h"
45 #include "nsIStorageStream.h"
46 #include "nsISimpleEnumerator.h"
47 #include "nsXPIDLString.h"
48 #include "nsIURI.h"
49 #include "nsCOMPtr.h"
50 #include "nsNetUtil.h"
51 #include "prtime.h"
52 #include "nsEscape.h"
54 #include "nsICacheService.h"
56 static PRTime SecondsToPRTime(PRUint32 t_sec)
58 PRTime t_usec, usec_per_sec;
59 LL_I2L(t_usec, t_sec);
60 LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
61 LL_MUL(t_usec, t_usec, usec_per_sec);
62 return t_usec;
64 static void PrintTimeString(char *buf, PRUint32 bufsize, PRUint32 t_sec)
66 PRExplodedTime et;
67 PRTime t_usec = SecondsToPRTime(t_sec);
68 PR_ExplodeTime(t_usec, PR_LocalTimeParameters, &et);
69 PR_FormatTime(buf, bufsize, "%Y-%m-%d %H:%M:%S", &et);
73 NS_IMPL_ISUPPORTS2(nsAboutCache, nsIAboutModule, nsICacheVisitor)
75 NS_IMETHODIMP
76 nsAboutCache::NewChannel(nsIURI *aURI, nsIChannel **result)
78 NS_ENSURE_ARG_POINTER(aURI);
79 nsresult rv;
80 PRUint32 bytesWritten;
82 *result = nsnull;
83 // Get the cache manager service
84 nsCOMPtr<nsICacheService> cacheService =
85 do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
86 if (NS_FAILED(rv)) return rv;
88 nsCOMPtr<nsIStorageStream> storageStream;
89 nsCOMPtr<nsIOutputStream> outputStream;
91 // Init: (block size, maximum length)
92 rv = NS_NewStorageStream(256, (PRUint32)-1, getter_AddRefs(storageStream));
93 if (NS_FAILED(rv)) return rv;
95 rv = storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
96 if (NS_FAILED(rv)) return rv;
98 mBuffer.AssignLiteral(
99 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
100 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n"
101 " \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
102 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
103 "<head>\n<title>Information about the Cache Service</title>\n</head>\n"
104 "<body>\n<div>\n");
106 outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
108 rv = ParseURI(aURI, mDeviceID);
109 if (NS_FAILED(rv)) return rv;
111 mStream = outputStream;
112 rv = cacheService->VisitEntries(this);
113 mBuffer.Truncate();
114 if (rv == NS_ERROR_NOT_AVAILABLE) {
115 mBuffer.AppendLiteral("<h2>The cache is disabled.</h2>\n");
117 else if (NS_FAILED(rv)) {
118 return rv;
121 if (!mDeviceID.IsEmpty()) {
122 mBuffer.AppendLiteral("</pre>\n");
124 mBuffer.AppendLiteral("</div>\n</body>\n</html>\n");
125 outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
127 nsCOMPtr<nsIInputStream> inStr;
129 rv = storageStream->NewInputStream(0, getter_AddRefs(inStr));
130 if (NS_FAILED(rv)) return rv;
132 nsIChannel* channel;
133 rv = NS_NewInputStreamChannel(&channel, aURI, inStr,
134 NS_LITERAL_CSTRING("text/html"),
135 NS_LITERAL_CSTRING("utf-8"));
136 if (NS_FAILED(rv)) return rv;
138 *result = channel;
139 return rv;
142 NS_IMETHODIMP
143 nsAboutCache::GetURIFlags(nsIURI *aURI, PRUint32 *result)
145 *result = 0;
146 return NS_OK;
149 NS_IMETHODIMP
150 nsAboutCache::VisitDevice(const char *deviceID,
151 nsICacheDeviceInfo *deviceInfo,
152 PRBool *visitEntries)
154 PRUint32 bytesWritten, value;
155 nsXPIDLCString str;
157 *visitEntries = PR_FALSE;
159 if (mDeviceID.IsEmpty() || mDeviceID.Equals(deviceID)) {
161 // We need mStream for this
162 if (!mStream)
163 return NS_ERROR_FAILURE;
165 // Write out the Cache Name
166 deviceInfo->GetDescription(getter_Copies(str));
168 mBuffer.AssignLiteral("<h2>");
169 mBuffer.Append(str);
170 mBuffer.AppendLiteral("</h2>\n<br />\n"
171 "<table>\n");
173 // Write out cache info
175 mBuffer.AppendLiteral("\n<tr>\n<td><b>Number of entries:</b></td>\n");
176 value = 0;
177 deviceInfo->GetEntryCount(&value);
178 mBuffer.AppendLiteral("<td><tt>");
179 mBuffer.AppendInt(value);
180 mBuffer.AppendLiteral("</tt></td>\n</tr>\n"
181 "\n<tr>\n<td><b>Maximum storage size:</b></td>\n");
182 value = 0;
183 deviceInfo->GetMaximumSize(&value);
184 mBuffer.AppendLiteral("<td><tt>");
185 mBuffer.AppendInt(value/1024);
186 mBuffer.AppendLiteral(" KiB</tt></td>\n</tr>\n"
187 "\n<tr>\n<td><b>Storage in use:</b></td>\n"
188 "<td><tt>");
189 value = 0;
190 deviceInfo->GetTotalSize(&value);
191 mBuffer.AppendInt(value/1024);
192 mBuffer.AppendLiteral(" KiB</tt></td>\n</tr>\n");
194 deviceInfo->GetUsageReport(getter_Copies(str));
195 mBuffer.Append(str);
196 mBuffer.AppendLiteral("</table>\n\n<br />");
198 if (mDeviceID.IsEmpty()) {
199 mBuffer.AppendLiteral("\n<a href=\"about:cache?device=");
200 mBuffer.Append(deviceID);
201 mBuffer.AppendLiteral("\">List Cache Entries</a>\n"
202 "<hr />\n");
203 } else {
204 *visitEntries = PR_TRUE;
205 mBuffer.AppendLiteral("<hr />\n<pre>\n");
208 mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
211 return NS_OK;
214 NS_IMETHODIMP
215 nsAboutCache::VisitEntry(const char *deviceID,
216 nsICacheEntryInfo *entryInfo,
217 PRBool *visitNext)
219 // We need mStream for this
220 if (!mStream)
221 return NS_ERROR_FAILURE;
223 nsresult rv;
224 PRUint32 bytesWritten;
225 nsCAutoString key;
226 nsXPIDLCString clientID;
227 PRBool streamBased;
229 rv = entryInfo->GetKey(key);
230 if (NS_FAILED(rv)) return rv;
232 rv = entryInfo->GetClientID(getter_Copies(clientID));
233 if (NS_FAILED(rv)) return rv;
235 rv = entryInfo->IsStreamBased(&streamBased);
236 if (NS_FAILED(rv)) return rv;
238 // Generate a about:cache-entry URL for this entry...
239 nsCAutoString url;
240 url.AssignLiteral("about:cache-entry?client=");
241 url += clientID;
242 url.AppendLiteral("&amp;sb=");
243 url += streamBased ? '1' : '0';
244 url.AppendLiteral("&amp;key=");
245 char* escapedKey = nsEscapeHTML(key.get());
246 url += escapedKey; // key
248 // Entry start...
250 // URI
251 mBuffer.AssignLiteral("<b> Key:</b> <a href=\"");
252 mBuffer.Append(url);
253 mBuffer.AppendLiteral("\">");
254 mBuffer.Append(escapedKey);
255 nsMemory::Free(escapedKey);
256 mBuffer.AppendLiteral("</a>");
258 // Content length
259 PRUint32 length = 0;
260 entryInfo->GetDataSize(&length);
262 mBuffer.AppendLiteral("\n<b> Data size:</b> ");
263 mBuffer.AppendInt(length);
264 mBuffer.AppendLiteral(" bytes");
266 // Number of accesses
267 PRInt32 fetchCount = 0;
268 entryInfo->GetFetchCount(&fetchCount);
270 mBuffer.AppendLiteral("\n<b> Fetch count:</b> ");
271 mBuffer.AppendInt(fetchCount);
273 // vars for reporting time
274 char buf[255];
275 PRUint32 t;
277 // Last modified time
278 mBuffer.AppendLiteral("\n<b> Last modified:</b> ");
279 entryInfo->GetLastModified(&t);
280 if (t) {
281 PrintTimeString(buf, sizeof(buf), t);
282 mBuffer.Append(buf);
283 } else
284 mBuffer.AppendLiteral("No last modified time");
286 // Expires time
287 mBuffer.AppendLiteral("\n<b> Expires:</b> ");
288 entryInfo->GetExpirationTime(&t);
289 if (t < 0xFFFFFFFF) {
290 PrintTimeString(buf, sizeof(buf), t);
291 mBuffer.Append(buf);
292 } else {
293 mBuffer.AppendLiteral("No expiration time");
296 // Entry is done...
297 mBuffer.AppendLiteral("\n\n");
299 mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
301 *visitNext = PR_TRUE;
302 return NS_OK;
306 nsresult
307 nsAboutCache::ParseURI(nsIURI * uri, nsCString &deviceID)
310 // about:cache[?device=string]
312 nsresult rv;
314 deviceID.Truncate();
316 nsCAutoString path;
317 rv = uri->GetPath(path);
318 if (NS_FAILED(rv)) return rv;
320 nsACString::const_iterator start, valueStart, end;
321 path.BeginReading(start);
322 path.EndReading(end);
324 valueStart = end;
325 if (!FindInReadable(NS_LITERAL_CSTRING("?device="), start, valueStart))
326 return NS_OK;
328 deviceID.Assign(Substring(valueStart, end));
329 return NS_OK;
333 NS_METHOD
334 nsAboutCache::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
336 nsAboutCache* about = new nsAboutCache();
337 if (about == nsnull)
338 return NS_ERROR_OUT_OF_MEMORY;
339 NS_ADDREF(about);
340 nsresult rv = about->QueryInterface(aIID, aResult);
341 NS_RELEASE(about);
342 return rv;
347 ////////////////////////////////////////////////////////////////////////////////