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/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "net/base/escape.h"
19 #include "net/base/net_errors.h"
20 #include "net/url_request/url_request.h"
21 #include "storage/browser/blob/blob_storage_context.h"
22 #include "storage/common/blob/blob_data.h"
26 const char kEmptyBlobStorageMessage
[] = "No available blob data.";
27 const char kContentType
[] = "Content Type: ";
28 const char kContentDisposition
[] = "Content Disposition: ";
29 const char kCount
[] = "Count: ";
30 const char kIndex
[] = "Index: ";
31 const char kType
[] = "Type: ";
32 const char kPath
[] = "Path: ";
33 const char kURL
[] = "URL: ";
34 const char kModificationTime
[] = "Modification Time: ";
35 const char kOffset
[] = "Offset: ";
36 const char kLength
[] = "Length: ";
37 const char kUUID
[] = "Uuid: ";
38 const char kRefcount
[] = "Refcount: ";
40 void StartHTML(std::string
* out
) {
43 "<html><title>Blob Storage Internals</title>"
44 "<meta http-equiv=\"Content-Security-Policy\""
45 " content=\"object-src 'none'; script-src 'none'\">\n"
47 "body { font-family: sans-serif; font-size: 0.8em; }\n"
48 "tt, code, pre { font-family: WebKitHack, monospace; }\n"
49 "form { display: inline }\n"
50 ".subsection_body { margin: 10px 0 10px 2em; }\n"
51 ".subsection_title { font-weight: bold; }\n"
56 void EndHTML(std::string
* out
) {
57 out
->append("\n</body></html>");
60 void AddHTMLBoldText(const std::string
& text
, std::string
* out
) {
62 out
->append(net::EscapeForHTML(text
));
66 void StartHTMLList(std::string
* out
) {
67 out
->append("\n<ul>");
70 void EndHTMLList(std::string
* out
) {
71 out
->append("</ul>\n");
74 void AddHTMLListItem(const std::string
& element_title
,
75 const std::string
& element_data
,
78 // No need to escape element_title since constant string is passed.
79 out
->append(element_title
);
80 out
->append(net::EscapeForHTML(element_data
));
81 out
->append("</li>\n");
84 void AddHorizontalRule(std::string
* out
) {
85 out
->append("\n<hr>\n");
92 ViewBlobInternalsJob::ViewBlobInternalsJob(
93 net::URLRequest
* request
,
94 net::NetworkDelegate
* network_delegate
,
95 BlobStorageContext
* blob_storage_context
)
96 : net::URLRequestSimpleJob(request
, network_delegate
),
97 blob_storage_context_(blob_storage_context
),
101 ViewBlobInternalsJob::~ViewBlobInternalsJob() {
104 void ViewBlobInternalsJob::Start() {
105 base::MessageLoop::current()->PostTask(
107 base::Bind(&ViewBlobInternalsJob::StartAsync
,
108 weak_factory_
.GetWeakPtr()));
111 bool ViewBlobInternalsJob::IsRedirectResponse(GURL
* location
,
112 int* http_status_code
) {
113 if (request_
->url().has_query()) {
114 // Strip the query parameters.
115 GURL::Replacements replacements
;
116 replacements
.ClearQuery();
117 *location
= request_
->url().ReplaceComponents(replacements
);
118 *http_status_code
= 307;
124 void ViewBlobInternalsJob::Kill() {
125 net::URLRequestSimpleJob::Kill();
126 weak_factory_
.InvalidateWeakPtrs();
129 int ViewBlobInternalsJob::GetData(
130 std::string
* mime_type
,
131 std::string
* charset
,
133 const net::CompletionCallback
& callback
) const {
134 mime_type
->assign("text/html");
135 charset
->assign("UTF-8");
139 if (blob_storage_context_
->blob_map_
.empty())
140 data
->append(kEmptyBlobStorageMessage
);
147 void ViewBlobInternalsJob::GenerateHTML(std::string
* out
) const {
148 for (BlobStorageContext::BlobMap::const_iterator iter
=
149 blob_storage_context_
->blob_map_
.begin();
150 iter
!= blob_storage_context_
->blob_map_
.end();
152 AddHTMLBoldText(iter
->first
, out
);
153 GenerateHTMLForBlobData(*(iter
->second
.data
.get()),
154 iter
->second
.refcount
,
157 if (!blob_storage_context_
->public_blob_urls_
.empty()) {
158 AddHorizontalRule(out
);
159 for (BlobStorageContext::BlobURLMap::const_iterator iter
=
160 blob_storage_context_
->public_blob_urls_
.begin();
161 iter
!= blob_storage_context_
->public_blob_urls_
.end();
163 AddHTMLBoldText(iter
->first
.spec(), out
);
165 AddHTMLListItem(kUUID
, iter
->second
, out
);
171 void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData
& blob_data
,
176 AddHTMLListItem(kRefcount
, base::IntToString(refcount
), out
);
177 if (!blob_data
.content_type().empty())
178 AddHTMLListItem(kContentType
, blob_data
.content_type(), out
);
179 if (!blob_data
.content_disposition().empty())
180 AddHTMLListItem(kContentDisposition
, blob_data
.content_disposition(), out
);
182 bool has_multi_items
= blob_data
.items().size() > 1;
183 if (has_multi_items
) {
184 AddHTMLListItem(kCount
,
185 base::UTF16ToUTF8(base::FormatNumber(blob_data
.items().size())), out
);
188 for (size_t i
= 0; i
< blob_data
.items().size(); ++i
) {
189 if (has_multi_items
) {
190 AddHTMLListItem(kIndex
, base::UTF16ToUTF8(base::FormatNumber(i
)), out
);
193 const BlobData::Item
& item
= blob_data
.items().at(i
);
195 switch (item
.type()) {
196 case BlobData::Item::TYPE_BYTES
:
197 AddHTMLListItem(kType
, "data", out
);
199 case BlobData::Item::TYPE_FILE
:
200 AddHTMLListItem(kType
, "file", out
);
201 AddHTMLListItem(kPath
,
202 net::EscapeForHTML(item
.path().AsUTF8Unsafe()),
204 if (!item
.expected_modification_time().is_null()) {
205 AddHTMLListItem(kModificationTime
, base::UTF16ToUTF8(
206 TimeFormatFriendlyDateAndTime(item
.expected_modification_time())),
210 case BlobData::Item::TYPE_BLOB
:
211 NOTREACHED(); // Should be flattened in the storage context.
213 case BlobData::Item::TYPE_FILE_FILESYSTEM
:
214 AddHTMLListItem(kType
, "filesystem", out
);
215 AddHTMLListItem(kURL
, item
.filesystem_url().spec(), out
);
216 if (!item
.expected_modification_time().is_null()) {
217 AddHTMLListItem(kModificationTime
, base::UTF16ToUTF8(
218 TimeFormatFriendlyDateAndTime(item
.expected_modification_time())),
222 case BlobData::Item::TYPE_UNKNOWN
:
227 AddHTMLListItem(kOffset
, base::UTF16ToUTF8(base::FormatNumber(
228 static_cast<int64
>(item
.offset()))), out
);
230 if (static_cast<int64
>(item
.length()) != -1) {
231 AddHTMLListItem(kLength
, base::UTF16ToUTF8(base::FormatNumber(
232 static_cast<int64
>(item
.length()))), out
);
242 } // namespace storage