1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "storage/browser/blob/view_blob_internals_job.h"
8 #include "base/compiler_specific.h"
9 #include "base/format_macros.h"
10 #include "base/i18n/number_formatting.h"
11 #include "base/i18n/time_formatting.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/profiler/scoped_tracker.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "net/base/escape.h"
20 #include "net/base/net_errors.h"
21 #include "net/url_request/url_request.h"
22 #include "storage/browser/blob/blob_storage_context.h"
23 #include "storage/common/blob/blob_data.h"
27 const char kEmptyBlobStorageMessage[] = "No available blob data.";
28 const char kContentType[] = "Content Type: ";
29 const char kContentDisposition[] = "Content Disposition: ";
30 const char kCount[] = "Count: ";
31 const char kIndex[] = "Index: ";
32 const char kType[] = "Type: ";
33 const char kPath[] = "Path: ";
34 const char kURL[] = "URL: ";
35 const char kModificationTime[] = "Modification Time: ";
36 const char kOffset[] = "Offset: ";
37 const char kLength[] = "Length: ";
38 const char kUUID[] = "Uuid: ";
39 const char kRefcount[] = "Refcount: ";
41 void StartHTML(std::string* out) {
44 "<html><title>Blob Storage Internals</title>"
45 "<meta http-equiv=\"Content-Security-Policy\""
46 " content=\"object-src 'none'; script-src 'none'\">\n"
48 "body { font-family: sans-serif; font-size: 0.8em; }\n"
49 "tt, code, pre { font-family: WebKitHack, monospace; }\n"
50 "form { display: inline }\n"
51 ".subsection_body { margin: 10px 0 10px 2em; }\n"
52 ".subsection_title { font-weight: bold; }\n"
57 void EndHTML(std::string* out) {
58 out->append("\n</body></html>");
61 void AddHTMLBoldText(const std::string& text, std::string* out) {
63 out->append(net::EscapeForHTML(text));
67 void StartHTMLList(std::string* out) {
68 out->append("\n<ul>");
71 void EndHTMLList(std::string* out) {
72 out->append("</ul>\n");
75 void AddHTMLListItem(const std::string& element_title,
76 const std::string& element_data,
79 // No need to escape element_title since constant string is passed.
80 out->append(element_title);
81 out->append(net::EscapeForHTML(element_data));
82 out->append("</li>\n");
85 void AddHorizontalRule(std::string* out) {
86 out->append("\n<hr>\n");
93 ViewBlobInternalsJob::ViewBlobInternalsJob(
94 net::URLRequest* request,
95 net::NetworkDelegate* network_delegate,
96 BlobStorageContext* blob_storage_context)
97 : net::URLRequestSimpleJob(request, network_delegate),
98 blob_storage_context_(blob_storage_context),
102 ViewBlobInternalsJob::~ViewBlobInternalsJob() {
105 void ViewBlobInternalsJob::Start() {
106 base::MessageLoop::current()->PostTask(
108 base::Bind(&ViewBlobInternalsJob::StartAsync,
109 weak_factory_.GetWeakPtr()));
112 bool ViewBlobInternalsJob::IsRedirectResponse(GURL* location,
113 int* http_status_code) {
114 if (request_->url().has_query()) {
115 // Strip the query parameters.
116 GURL::Replacements replacements;
117 replacements.ClearQuery();
118 *location = request_->url().ReplaceComponents(replacements);
119 *http_status_code = 307;
125 void ViewBlobInternalsJob::Kill() {
126 net::URLRequestSimpleJob::Kill();
127 weak_factory_.InvalidateWeakPtrs();
130 int ViewBlobInternalsJob::GetData(
131 std::string* mime_type,
132 std::string* charset,
134 const net::CompletionCallback& callback) const {
135 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
136 tracked_objects::ScopedTracker tracking_profile(
137 FROM_HERE_WITH_EXPLICIT_FUNCTION("422489 ViewBlobInternalsJob::GetData"));
139 mime_type->assign("text/html");
140 charset->assign("UTF-8");
144 if (blob_storage_context_->blob_map_.empty())
145 data->append(kEmptyBlobStorageMessage);
152 void ViewBlobInternalsJob::GenerateHTML(std::string* out) const {
153 for (BlobStorageContext::BlobMap::const_iterator iter =
154 blob_storage_context_->blob_map_.begin();
155 iter != blob_storage_context_->blob_map_.end();
157 AddHTMLBoldText(iter->first, out);
158 GenerateHTMLForBlobData(*(iter->second.data.get()),
159 iter->second.refcount,
162 if (!blob_storage_context_->public_blob_urls_.empty()) {
163 AddHorizontalRule(out);
164 for (BlobStorageContext::BlobURLMap::const_iterator iter =
165 blob_storage_context_->public_blob_urls_.begin();
166 iter != blob_storage_context_->public_blob_urls_.end();
168 AddHTMLBoldText(iter->first.spec(), out);
170 AddHTMLListItem(kUUID, iter->second, out);
176 void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data,
181 AddHTMLListItem(kRefcount, base::IntToString(refcount), out);
182 if (!blob_data.content_type().empty())
183 AddHTMLListItem(kContentType, blob_data.content_type(), out);
184 if (!blob_data.content_disposition().empty())
185 AddHTMLListItem(kContentDisposition, blob_data.content_disposition(), out);
187 bool has_multi_items = blob_data.items().size() > 1;
188 if (has_multi_items) {
189 AddHTMLListItem(kCount,
190 base::UTF16ToUTF8(base::FormatNumber(blob_data.items().size())), out);
193 for (size_t i = 0; i < blob_data.items().size(); ++i) {
194 if (has_multi_items) {
195 AddHTMLListItem(kIndex, base::UTF16ToUTF8(base::FormatNumber(i)), out);
198 const BlobData::Item& item = blob_data.items().at(i);
200 switch (item.type()) {
201 case BlobData::Item::TYPE_BYTES:
202 AddHTMLListItem(kType, "data", out);
204 case BlobData::Item::TYPE_FILE:
205 AddHTMLListItem(kType, "file", out);
206 AddHTMLListItem(kPath,
207 net::EscapeForHTML(item.path().AsUTF8Unsafe()),
209 if (!item.expected_modification_time().is_null()) {
210 AddHTMLListItem(kModificationTime, base::UTF16ToUTF8(
211 TimeFormatFriendlyDateAndTime(item.expected_modification_time())),
215 case BlobData::Item::TYPE_BLOB:
216 NOTREACHED(); // Should be flattened in the storage context.
218 case BlobData::Item::TYPE_FILE_FILESYSTEM:
219 AddHTMLListItem(kType, "filesystem", out);
220 AddHTMLListItem(kURL, item.filesystem_url().spec(), out);
221 if (!item.expected_modification_time().is_null()) {
222 AddHTMLListItem(kModificationTime, base::UTF16ToUTF8(
223 TimeFormatFriendlyDateAndTime(item.expected_modification_time())),
227 case BlobData::Item::TYPE_UNKNOWN:
232 AddHTMLListItem(kOffset, base::UTF16ToUTF8(base::FormatNumber(
233 static_cast<int64>(item.offset()))), out);
235 if (static_cast<int64>(item.length()) != -1) {
236 AddHTMLListItem(kLength, base::UTF16ToUTF8(base::FormatNumber(
237 static_cast<int64>(item.length()))), out);
247 } // namespace storage