Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / storage / browser / blob / view_blob_internals_job.cc
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.
4
5 #include "storage/browser/blob/view_blob_internals_job.h"
6
7 #include "base/bind.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"
24
25 namespace {
26
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: ";
40
41 void StartHTML(std::string* out) {
42   out->append(
43       "<!DOCTYPE HTML>"
44       "<html><title>Blob Storage Internals</title>"
45       "<meta http-equiv=\"Content-Security-Policy\""
46       "  content=\"object-src 'none'; script-src 'none'\">\n"
47       "<style>\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"
53       "</style>\n"
54       "</head><body>\n\n");
55 }
56
57 void EndHTML(std::string* out) {
58   out->append("\n</body></html>");
59 }
60
61 void AddHTMLBoldText(const std::string& text, std::string* out) {
62   out->append("<b>");
63   out->append(net::EscapeForHTML(text));
64   out->append("</b>");
65 }
66
67 void StartHTMLList(std::string* out) {
68   out->append("\n<ul>");
69 }
70
71 void EndHTMLList(std::string* out) {
72   out->append("</ul>\n");
73 }
74
75 void AddHTMLListItem(const std::string& element_title,
76                      const std::string& element_data,
77                      std::string* out) {
78   out->append("<li>");
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");
83 }
84
85 void AddHorizontalRule(std::string* out) {
86   out->append("\n<hr>\n");
87 }
88
89 }  // namespace
90
91 namespace storage {
92
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),
99       weak_factory_(this) {
100 }
101
102 ViewBlobInternalsJob::~ViewBlobInternalsJob() {
103 }
104
105 void ViewBlobInternalsJob::Start() {
106   base::MessageLoop::current()->PostTask(
107       FROM_HERE,
108       base::Bind(&ViewBlobInternalsJob::StartAsync,
109                  weak_factory_.GetWeakPtr()));
110 }
111
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;
120     return true;
121   }
122   return false;
123 }
124
125 void ViewBlobInternalsJob::Kill() {
126   net::URLRequestSimpleJob::Kill();
127   weak_factory_.InvalidateWeakPtrs();
128 }
129
130 int ViewBlobInternalsJob::GetData(
131     std::string* mime_type,
132     std::string* charset,
133     std::string* data,
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"));
138
139   mime_type->assign("text/html");
140   charset->assign("UTF-8");
141
142   data->clear();
143   StartHTML(data);
144   if (blob_storage_context_->blob_map_.empty())
145     data->append(kEmptyBlobStorageMessage);
146   else
147     GenerateHTML(data);
148   EndHTML(data);
149   return net::OK;
150 }
151
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();
156        ++iter) {
157     AddHTMLBoldText(iter->first, out);
158     GenerateHTMLForBlobData(*(iter->second.data.get()),
159                             iter->second.refcount,
160                             out);
161   }
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();
167          ++iter) {
168       AddHTMLBoldText(iter->first.spec(), out);
169       StartHTMLList(out);
170       AddHTMLListItem(kUUID, iter->second, out);
171       EndHTMLList(out);
172     }
173   }
174 }
175
176 void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data,
177                                                    int refcount,
178                                                    std::string* out) {
179   StartHTMLList(out);
180
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);
186
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);
191   }
192
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);
196       StartHTMLList(out);
197     }
198     const BlobData::Item& item = blob_data.items().at(i);
199
200     switch (item.type()) {
201       case BlobData::Item::TYPE_BYTES:
202         AddHTMLListItem(kType, "data", out);
203         break;
204       case BlobData::Item::TYPE_FILE:
205         AddHTMLListItem(kType, "file", out);
206         AddHTMLListItem(kPath,
207                  net::EscapeForHTML(item.path().AsUTF8Unsafe()),
208                  out);
209         if (!item.expected_modification_time().is_null()) {
210           AddHTMLListItem(kModificationTime, base::UTF16ToUTF8(
211               TimeFormatFriendlyDateAndTime(item.expected_modification_time())),
212               out);
213         }
214         break;
215       case BlobData::Item::TYPE_BLOB:
216         NOTREACHED();   // Should be flattened in the storage context.
217         break;
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())),
224               out);
225         }
226         break;
227       case BlobData::Item::TYPE_UNKNOWN:
228         NOTREACHED();
229         break;
230     }
231     if (item.offset()) {
232       AddHTMLListItem(kOffset, base::UTF16ToUTF8(base::FormatNumber(
233           static_cast<int64>(item.offset()))), out);
234     }
235     if (static_cast<int64>(item.length()) != -1) {
236       AddHTMLListItem(kLength, base::UTF16ToUTF8(base::FormatNumber(
237           static_cast<int64>(item.length()))), out);
238     }
239
240     if (has_multi_items)
241       EndHTMLList(out);
242   }
243
244   EndHTMLList(out);
245 }
246
247 }  // namespace storage