nsresult nsAboutCacheEntry::Channel::WriteCacheEntryDescription(nsICacheEntry *entry) { nsresult rv; nsCString buffer; uint32_t n; nsAutoCString str; rv = entry->GetKey(str); if (NS_FAILED(rv)) return rv; buffer.SetCapacity(4096); buffer.AssignLiteral("<table>\n" " <tr>\n" " <th>key:</th>\n" " <td id=\"td-key\">"); // Test if the key is actually a URI nsCOMPtr<nsIURI> uri; bool isJS = false; bool isData = false; rv = NS_NewURI(getter_AddRefs(uri), str); // javascript: and data: URLs should not be linkified // since clicking them can cause scripts to run - bug 162584 if (NS_SUCCEEDED(rv)) { uri->SchemeIs("javascript", &isJS); uri->SchemeIs("data", &isData); } char* escapedStr = nsEscapeHTML(str.get()); if (NS_SUCCEEDED(rv) && !(isJS || isData)) { buffer.AppendLiteral("<a href=\""); buffer.Append(escapedStr); buffer.AppendLiteral("\">"); buffer.Append(escapedStr); buffer.AppendLiteral("</a>"); uri = 0; } else { buffer.Append(escapedStr); } free(escapedStr); buffer.AppendLiteral("</td>\n" " </tr>\n"); // temp vars for reporting char timeBuf[255]; uint32_t u = 0; int32_t i = 0; nsAutoCString s; // Fetch Count s.Truncate(); entry->GetFetchCount(&i); s.AppendInt(i); APPEND_ROW("fetch count", s); // Last Fetched entry->GetLastFetched(&u); if (u) { PrintTimeString(timeBuf, sizeof(timeBuf), u); APPEND_ROW("last fetched", timeBuf); } else { APPEND_ROW("last fetched", "No last fetch time (bug 1000338)"); } // Last Modified entry->GetLastModified(&u); if (u) { PrintTimeString(timeBuf, sizeof(timeBuf), u); APPEND_ROW("last modified", timeBuf); } else { APPEND_ROW("last modified", "No last modified time (bug 1000338)"); } // Expiration Time entry->GetExpirationTime(&u); if (u < 0xFFFFFFFF) { PrintTimeString(timeBuf, sizeof(timeBuf), u); APPEND_ROW("expires", timeBuf); } else { APPEND_ROW("expires", "No expiration time"); } // Data Size s.Truncate(); uint32_t dataSize; if (NS_FAILED(entry->GetStorageDataSize(&dataSize))) dataSize = 0; s.AppendInt((int32_t)dataSize); // XXX nsICacheEntryInfo interfaces should be fixed. s.AppendLiteral(" B"); APPEND_ROW("Data size", s); // TODO - mayhemer // Here used to be a link to the disk file (in the old cache for entries that // did not fit any of the block files, in the new cache every time). // I'd rather have a small set of buttons here to action on the entry: // 1. save the content // 2. save as a complete HTTP response (response head, headers, content) // 3. doom the entry // A new bug(s) should be filed here. // Security Info nsCOMPtr<nsISupports> securityInfo; entry->GetSecurityInfo(getter_AddRefs(securityInfo)); if (securityInfo) { APPEND_ROW("Security", "This is a secure document."); } else { APPEND_ROW("Security", "This document does not have any security info associated with it."); } buffer.AppendLiteral("</table>\n" "<hr/>\n" "<table>\n"); mBuffer = &buffer; // make it available for OnMetaDataElement(). entry->VisitMetaData(this); mBuffer = nullptr; buffer.AppendLiteral("</table>\n"); mOutputStream->Write(buffer.get(), buffer.Length(), &n); buffer.Truncate(); // Provide a hexdump of the data if (!dataSize) { return NS_OK; } nsCOMPtr<nsIInputStream> stream; entry->OpenInputStream(0, getter_AddRefs(stream)); if (!stream) { return NS_OK; } RefPtr<nsInputStreamPump> pump; rv = nsInputStreamPump::Create(getter_AddRefs(pump), stream); if (NS_FAILED(rv)) { return NS_OK; // just ignore } rv = pump->AsyncRead(this, nullptr); if (NS_FAILED(rv)) { return NS_OK; // just ignore } mWaitingForData = true; return NS_OK; }