netwerk/protocol/about/nsAboutCache.cpp

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

mercurial