OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/webui/quota_internals_ui.h" | 5 #include "chrome/browser/ui/webui/quota_internals_ui.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/values.h" | |
10 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
11 #include "chrome/common/url_constants.h" | 12 #include "chrome/common/url_constants.h" |
12 #include "content/browser/tab_contents/tab_contents.h" | 13 #include "content/browser/tab_contents/tab_contents.h" |
13 #include "grit/quota_internals_resources.h" | 14 #include "grit/quota_internals_resources.h" |
15 #include "net/base/net_util.h" | |
14 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
15 | 17 |
18 namespace { | |
Evan Stade
2011/06/01 01:15:04
insert blank line
tzik
2011/06/03 16:01:19
Done.
| |
19 template<typename T> | |
20 std::string ToString(const T& v) { | |
21 std::ostringstream out; | |
22 out << v; | |
23 return out.str(); | |
24 } | |
25 | |
26 std::string StorageTypeToString(quota::StorageType type) { | |
27 switch (type) { | |
28 case quota::kStorageTypeTemporary: | |
29 return "temporary"; | |
30 case quota::kStorageTypePersistent: | |
31 return "persistent"; | |
32 default: | |
33 return "unknown"; | |
34 } | |
35 } | |
Evan Stade
2011/06/01 01:15:04
insert blank line
tzik
2011/06/03 16:01:19
Done.
| |
36 } // anonymous namespace | |
37 | |
38 namespace quota_internals { | |
39 | |
40 class GlobalData { | |
41 public: | |
42 GlobalData(quota::StorageType type, | |
43 int64 usage, | |
44 int64 unlimited_usage, | |
45 int64 quota) | |
46 : type_(type), | |
47 usage_(usage), | |
48 unlimited_usage_(unlimited_usage), | |
49 quota_(quota) { | |
50 } | |
51 | |
52 Value* NewValue() const { | |
53 scoped_ptr<DictionaryValue> dict(new DictionaryValue); | |
54 dict->SetString("type", StorageTypeToString(type_)); | |
55 if (usage_ >= 0) | |
56 dict->SetString("usage", ToString(usage_)); | |
57 if (unlimited_usage_ >= 0) | |
58 dict->SetString("unlimited_usage", ToString(unlimited_usage_)); | |
59 if (quota_ >= 0) | |
60 dict->SetString("quota", ToString(quota_)); | |
61 return dict.release(); | |
62 } | |
63 | |
64 private: | |
65 quota::StorageType type_; | |
66 int64 usage_; | |
67 int64 unlimited_usage_; | |
68 int64 quota_; | |
69 }; | |
70 | |
71 class HostData { | |
72 public: | |
73 HostData(const std::string& host, | |
74 quota::StorageType type, | |
75 int64 usage, | |
76 int64 quota) | |
77 : host_(host), | |
78 type_(type), | |
79 usage_(usage), | |
80 quota_(quota) { | |
81 } | |
82 | |
83 Value* NewValue() const { | |
84 scoped_ptr<DictionaryValue> dict(new DictionaryValue); | |
85 DCHECK(!host_.empty()); | |
86 dict->SetString("host", host_); | |
87 dict->SetString("type", StorageTypeToString(type_)); | |
88 if (usage_ >= 0) | |
89 dict->SetString("usage", ToString(usage_)); | |
90 if (quota_ >= 0) | |
91 dict->SetString("quota", ToString(quota_)); | |
92 return dict.release(); | |
93 } | |
94 | |
95 private: | |
96 std::string host_; | |
97 quota::StorageType type_; | |
98 int64 usage_; | |
99 int64 quota_; | |
100 }; | |
101 | |
102 struct OriginData { | |
103 public: | |
104 OriginData(const GURL& origin, | |
105 quota::StorageType type, | |
106 int in_use, | |
107 int used_count, | |
108 base::Time last_access_time) | |
109 : origin_(origin), | |
110 type_(type), | |
111 host_(net::GetHostOrSpecFromURL(origin)), | |
112 in_use_(in_use), | |
113 used_count_(used_count), | |
114 last_access_time_(last_access_time) { | |
115 } | |
116 | |
117 Value* NewValue() const { | |
118 scoped_ptr<DictionaryValue> dict(new DictionaryValue); | |
119 DCHECK(!origin_.is_empty()); | |
120 DCHECK(!host_.empty()); | |
121 dict->SetString("origin", origin_.spec()); | |
122 dict->SetString("type", StorageTypeToString(type_)); | |
123 dict->SetString("host", ToString(host_)); | |
124 if (in_use_ >= 0) | |
125 dict->SetBoolean("in_use", in_use_ ? true : false); | |
126 if (used_count_ >= 0) | |
127 dict->SetInteger("used_count", used_count_); | |
128 if (!last_access_time_.is_null()) | |
129 dict->SetDouble("last_access_time", last_access_time_.ToDoubleT()); | |
130 return dict.release(); | |
131 } | |
132 | |
133 private: | |
134 GURL origin_; | |
135 quota::StorageType type_; | |
136 std::string host_; | |
137 int in_use_; | |
138 int used_count_; | |
139 base::Time last_access_time_; | |
140 }; | |
141 | |
142 typedef std::map<std::string, std::string> Statistics; | |
143 | |
144 class QuotaInternalsProxy; | |
145 | |
146 class QuotaInternalsHTMLSource : public ChromeURLDataManager::DataSource { | |
147 public: | |
148 QuotaInternalsHTMLSource() | |
149 : DataSource(chrome::kChromeUIQuotaInternalsHost, | |
150 MessageLoop::current()) { | |
151 } | |
152 | |
153 virtual void StartDataRequest(const std::string& path, | |
154 bool is_incognito, | |
155 int request_id) OVERRIDE { | |
156 base::StringPiece html( | |
157 ResourceBundle::GetSharedInstance().GetRawDataResource( | |
158 IDR_QUOTA_INTERNALS_INDEX_HTML)); | |
159 | |
160 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); | |
161 html_bytes->data.resize(html.size()); | |
162 std::copy(html.data(), html.data() + html.size(), | |
163 html_bytes->data.begin()); | |
164 SendResponse(request_id, html_bytes); | |
165 return; | |
166 } | |
167 | |
168 virtual std::string GetMimeType(const std::string&) const OVERRIDE { | |
169 return "text/html"; | |
170 } | |
171 | |
172 private: | |
173 virtual ~QuotaInternalsHTMLSource() {} | |
174 DISALLOW_COPY_AND_ASSIGN(QuotaInternalsHTMLSource); | |
175 }; | |
176 | |
177 class QuotaInternalsMessageHandler : public WebUIMessageHandler { | |
Evan Stade
2011/06/01 01:15:04
this class needs to go in its own file
tzik
2011/06/03 16:01:19
Done. Should I move QuotaInternalsProxy to another
| |
178 public: | |
179 QuotaInternalsMessageHandler() {} | |
180 | |
181 virtual ~QuotaInternalsMessageHandler(); | |
182 | |
183 virtual void RegisterMessages() OVERRIDE { | |
184 DCHECK(web_ui_); | |
185 web_ui_->RegisterMessageCallback( | |
186 "requestData", | |
187 NewCallback(this, &QuotaInternalsMessageHandler::OnRequestData)); | |
188 } | |
189 | |
190 void ReportAvailableSpace(int64 available_space) { | |
191 scoped_ptr<Value> avail( | |
192 Value::CreateStringValue(ToString(available_space))); | |
193 SendMessage("AvailableSpaceUpdated", *avail.get()); | |
194 } | |
195 | |
196 void ReportGlobalData(const GlobalData& data) { | |
197 scoped_ptr<Value> value(data.NewValue()); | |
198 SendMessage("GlobalDataUpdated", *value); | |
199 } | |
200 | |
201 void ReportHostData(const std::vector<HostData>& hosts) { | |
202 ListValue values; | |
203 typedef std::vector<HostData>::const_iterator iterator; | |
204 for (iterator itr(hosts.begin()), end(hosts.end()); | |
205 itr != end; ++itr) | |
Evan Stade
2011/06/01 01:15:04
need curlies
tzik
2011/06/03 16:01:19
Done.
| |
206 values.Append(itr->NewValue()); | |
Evan Stade
2011/06/01 01:15:04
newline
tzik
2011/06/03 16:01:19
Done.
| |
207 SendMessage("HostDataUpdated", values); | |
208 } | |
209 | |
210 void ReportOriginData(const std::vector<OriginData>& origins) { | |
211 ListValue origins_value; | |
212 typedef std::vector<OriginData>::const_iterator iterator; | |
213 for (iterator itr(origins.begin()), end(origins.end()); | |
214 itr != end; ++itr) | |
Evan Stade
2011/06/01 01:15:04
need curlies
tzik
2011/06/03 16:01:19
Done.
| |
215 origins_value.Append(itr->NewValue()); | |
216 | |
217 SendMessage("OriginDataUpdated", origins_value); | |
218 } | |
219 | |
220 void ReportStatistics(const Statistics& stats) { | |
221 DictionaryValue dict; | |
222 typedef Statistics::const_iterator iterator; | |
223 for (iterator itr(stats.begin()), end(stats.end()); | |
224 itr != end; ++itr) | |
Evan Stade
2011/06/01 01:15:04
need curlies
tzik
2011/06/03 16:01:19
Done.
| |
225 dict.SetString(itr->first, itr->second); | |
Evan Stade
2011/06/01 01:15:04
newline
tzik
2011/06/03 16:01:19
Done.
| |
226 SendMessage("StatisticsUpdated", dict); | |
227 } | |
228 | |
229 private: | |
230 void OnRequestData(const ListValue*); | |
231 | |
232 void SendMessage(const std::string& message, const Value& value) { | |
233 scoped_ptr<Value> message_data(Value::CreateStringValue(message)); | |
234 web_ui_->CallJavascriptFunction("cr.quota.messageHandler_", | |
235 *message_data.get(), | |
236 value); | |
237 } | |
238 | |
239 scoped_refptr<QuotaInternalsProxy> proxy_; | |
240 | |
241 DISALLOW_COPY_AND_ASSIGN(QuotaInternalsMessageHandler); | |
242 }; | |
243 | |
244 typedef QuotaInternalsProxy QuotaInternalsProxyDeleter; | |
michaeln
2011/06/01 01:09:32
doesn't look used anywhere
tzik
2011/06/03 16:01:19
Done.
| |
245 | |
246 class QuotaInternalsProxy | |
247 : public base::RefCountedThreadSafe<QuotaInternalsProxy, | |
248 BrowserThread::DeleteOnIOThread> { | |
michaeln
2011/06/01 01:09:32
Extending the life of the QM shouldn't be an issue
tzik
2011/06/03 16:01:19
I see. Done.
| |
249 public: | |
250 explicit QuotaInternalsProxy(QuotaInternalsMessageHandler* handler) | |
251 : handler_(handler), | |
252 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
253 } | |
254 | |
255 // Called on IO Thread. | |
256 void ReportAvailableSpace(int64 available_space) { | |
257 BrowserThread::PostTask( | |
258 BrowserThread::UI, FROM_HERE, | |
259 NewRunnableMethod( | |
260 this, &QuotaInternalsProxy::RunReportAvailableSpaceOnUIThread, | |
261 available_space)); | |
262 } | |
263 | |
264 void ReportGlobalData(const GlobalData& data) { | |
265 BrowserThread::PostTask( | |
266 BrowserThread::UI, FROM_HERE, | |
267 NewRunnableMethod( | |
268 this, &QuotaInternalsProxy::RunReportGlobalDataOnUIThread, | |
269 data)); | |
270 } | |
271 | |
272 void ReportHostData(const std::vector<HostData>& hosts) { | |
273 BrowserThread::PostTask( | |
274 BrowserThread::UI, FROM_HERE, | |
275 NewRunnableMethod( | |
276 this, &QuotaInternalsProxy::RunReportHostDataOnUIThread, | |
277 hosts)); | |
278 } | |
279 | |
280 void ReportOriginData(const std::vector<OriginData>& origins) { | |
281 BrowserThread::PostTask( | |
282 BrowserThread::UI, FROM_HERE, | |
283 NewRunnableMethod( | |
284 this, &QuotaInternalsProxy::RunReportOriginDataOnUIThread, | |
285 origins)); | |
286 } | |
287 | |
288 void ReportStatistics(const Statistics& stats) { | |
289 BrowserThread::PostTask( | |
290 BrowserThread::UI, FROM_HERE, | |
291 NewRunnableMethod( | |
292 this, &QuotaInternalsProxy::RunReportStatisticsOnUIThread, | |
293 stats)); | |
294 } | |
295 | |
296 // Called on UI Thread. | |
297 void RequestData(quota::QuotaManager* quota_manager) { | |
298 BrowserThread::PostTask( | |
299 BrowserThread::IO, FROM_HERE, | |
300 NewRunnableMethod(this, &QuotaInternalsProxy::RunRequestDataOnIOThread, | |
301 make_scoped_refptr(quota_manager))); | |
302 } | |
303 | |
304 private: | |
305 typedef quota::QuotaManager::QuotaTableEntry QuotaTableEntry; | |
306 typedef quota::QuotaManager::LastAccessTimeTableEntry | |
307 LastAccessTimeTableEntry; | |
308 typedef quota::QuotaManager::QuotaTableEntries QuotaTableEntries; | |
309 typedef quota::QuotaManager::LastAccessTimeTableEntries | |
310 LastAccessTimeTableEntries; | |
311 | |
312 // Called on UI Thread. | |
313 void RunReportAvailableSpaceOnUIThread(int64 available_space) { | |
314 if (handler_) | |
315 handler_->ReportAvailableSpace(available_space); | |
316 } | |
317 | |
318 void RunReportGlobalDataOnUIThread(const GlobalData& data) { | |
319 if (handler_) | |
320 handler_->ReportGlobalData(data); | |
321 } | |
322 | |
323 void RunReportHostDataOnUIThread(const std::vector<HostData>& hosts) { | |
324 if (handler_) | |
325 handler_->ReportHostData(hosts); | |
326 } | |
327 | |
328 void RunReportOriginDataOnUIThread(const std::vector<OriginData>& origins) { | |
329 if (handler_) | |
330 handler_->ReportOriginData(origins); | |
331 } | |
332 | |
333 void RunReportStatisticsOnUIThread(const Statistics& stats) { | |
334 if (handler_) | |
335 handler_->ReportStatistics(stats); | |
336 } | |
337 | |
338 // Called on IO Thread. | |
339 void RunRequestDataOnIOThread( | |
340 scoped_refptr<quota::QuotaManager> quota_manager) { | |
341 quota_manager_ = quota_manager->AsWeakPtr(); | |
342 | |
343 quota_manager->GetAvailableSpace( | |
344 callback_factory_.NewCallback( | |
345 &QuotaInternalsProxy::DidGetAvailableSpace)); | |
346 | |
347 quota_manager->GetTemporaryGlobalQuota( | |
348 callback_factory_.NewCallback( | |
349 &QuotaInternalsProxy::DidGetGlobalQuota)); | |
350 | |
351 quota_manager->GetGlobalUsage( | |
352 quota::kStorageTypeTemporary, | |
353 callback_factory_.NewCallback( | |
354 &QuotaInternalsProxy::DidGetGlobalUsage)); | |
355 | |
356 quota_manager->GetGlobalUsage( | |
357 quota::kStorageTypePersistent, | |
358 callback_factory_.NewCallback( | |
359 &QuotaInternalsProxy::DidGetGlobalUsage)); | |
360 | |
361 quota_manager->DumpQuotaTable( | |
362 callback_factory_.NewCallback( | |
363 &QuotaInternalsProxy::DidDumpQuotaTable)); | |
364 | |
365 quota_manager->DumpLastAccessTimeTable( | |
366 callback_factory_.NewCallback( | |
367 &QuotaInternalsProxy::DidDumpLastAccessTimeTable)); | |
368 | |
369 // TODO(tzik): | |
370 // Call QuotaManager::GetStatistics() (to be implemented.) | |
371 } | |
372 | |
373 // Called on IO Thread by QuotaManager as callback. | |
374 void DidGetAvailableSpace(quota::QuotaStatusCode status, int64 space) { | |
375 if (status == quota::kQuotaStatusOk) | |
376 ReportAvailableSpace(space); | |
377 } | |
378 | |
379 void DidGetGlobalQuota(quota::QuotaStatusCode status, | |
380 quota::StorageType type, | |
381 int64 quota) { | |
382 if (status == quota::kQuotaStatusOk) | |
383 ReportGlobalData(GlobalData(type, -1, -1, quota)); | |
384 } | |
385 | |
386 void DidGetGlobalUsage(quota::StorageType type, | |
387 int64 usage, | |
388 int64 unlimited_usage) { | |
389 ReportGlobalData(GlobalData(type, usage, unlimited_usage, -1)); | |
390 RequestPerOriginData(type); | |
391 } | |
392 | |
393 void DidDumpQuotaTable(const QuotaTableEntries& entries) { | |
394 std::vector<HostData> host_data; | |
395 host_data.reserve(entries.size()); | |
396 | |
397 typedef QuotaTableEntries::const_iterator iterator; | |
398 for (iterator itr(entries.begin()), end(entries.end()); | |
399 itr != end; ++itr) | |
400 host_data.push_back(HostData(itr->host, itr->type, -1, itr->quota)); | |
401 ReportHostData(host_data); | |
402 } | |
403 | |
404 void DidDumpLastAccessTimeTable(const LastAccessTimeTableEntries& entries) { | |
405 std::vector<OriginData> origin_data; | |
406 origin_data.reserve(entries.size()); | |
407 | |
408 typedef LastAccessTimeTableEntries::const_iterator iterator; | |
409 for (iterator itr(entries.begin()), end(entries.end()); | |
410 itr != end; ++itr) | |
411 origin_data.push_back( | |
412 OriginData(itr->origin, itr->type, | |
413 -1, itr->used_count, itr->last_access_time)); | |
414 ReportOriginData(origin_data); | |
415 } | |
416 | |
417 void DidGetHostUsage(const std::string& host, | |
418 quota::StorageType type, | |
419 int64 usage) { | |
420 DCHECK(type == quota::kStorageTypeTemporary || | |
421 type == quota::kStorageTypePersistent); | |
422 | |
423 report_pending_.push_back( | |
424 (HostData) {host, type, usage, -1}); | |
michaeln
2011/06/01 01:09:32
use the ctor here instead
tzik
2011/06/03 16:01:19
Done.
| |
425 hosts_pending_.erase(make_pair(host, type)); | |
426 if (report_pending_.size() >= 10 || hosts_pending_.empty()) { | |
427 ReportHostData(report_pending_); | |
428 report_pending_.clear(); | |
429 } | |
430 | |
431 if (!hosts_pending_.empty()) | |
432 GetHostUsage(hosts_pending_.begin()->first, | |
433 hosts_pending_.begin()->second); | |
434 } | |
435 | |
436 // Helper. Called on IO Thread. | |
437 void RequestPerOriginData(quota::StorageType type); | |
438 | |
439 void VisitHost(const std::string& host, quota::StorageType type) { | |
440 if (hosts_visited_.insert(std::make_pair(host, type)).second) { | |
441 hosts_pending_.insert(std::make_pair(host, type)); | |
442 if (hosts_pending_.size() == 1) { | |
443 GetHostUsage(host, type); | |
444 } | |
445 } | |
446 } | |
447 | |
448 void GetHostUsage(const std::string& host, quota::StorageType type) { | |
449 if (quota_manager_) | |
450 quota_manager_->GetHostUsage( | |
451 host, type, | |
452 callback_factory_.NewCallback( | |
453 &QuotaInternalsProxy::DidGetHostUsage)); | |
454 } | |
455 | |
456 // Used on UI Thread. | |
457 QuotaInternalsMessageHandler* handler_; | |
458 | |
459 // Used on IO Thread. | |
460 base::ScopedCallbackFactory<QuotaInternalsProxy> callback_factory_; | |
461 base::WeakPtr<quota::QuotaManager> quota_manager_; | |
michaeln
2011/05/30 19:36:57
can this be a scoped_refptr<>
tzik
2011/06/03 16:01:19
Done.
| |
462 std::set<std::pair<std::string, quota::StorageType> > | |
463 hosts_visited_, hosts_pending_; | |
464 std::vector<HostData> report_pending_; | |
465 | |
466 friend class QuotaInternalsMessageHandler; | |
467 friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; | |
468 friend class DeleteTask<QuotaInternalsProxy>; | |
469 | |
470 virtual ~QuotaInternalsProxy() {} | |
471 }; | |
472 | |
473 void QuotaInternalsMessageHandler::OnRequestData(const ListValue*) { | |
michaeln
2011/06/01 01:09:32
I'd move this method definition next to the other
tzik
2011/06/03 16:01:19
Done.
| |
474 if (!proxy_) | |
475 proxy_ = new QuotaInternalsProxy(this); | |
476 proxy_->RequestData(web_ui_->GetProfile()->GetQuotaManager()); | |
477 } | |
478 | |
479 void QuotaInternalsProxy::RequestPerOriginData(quota::StorageType type) { | |
480 if (!quota_manager_) | |
481 return; | |
482 | |
483 std::set<GURL> origins; | |
484 quota_manager_->GetCachedOrigins(type, &origins); | |
485 | |
486 std::vector<OriginData> origin_data; | |
487 origin_data.reserve(origins.size()); | |
488 | |
489 std::set<std::string> hosts; | |
490 std::vector<HostData> host_data; | |
491 | |
492 for (std::set<GURL>::iterator itr(origins.begin()), end(origins.end()); | |
Evan Stade
2011/06/01 01:15:04
it's confusing to define a variable here that's no
tzik
2011/06/03 16:01:19
Done.
| |
493 itr != end; ++itr) { | |
494 origin_data.push_back( | |
495 OriginData(*itr, type, | |
496 quota_manager_->IsOriginInUse(*itr) ? 1 : 0, -1, | |
497 base::Time())); | |
498 | |
499 std::string host(net::GetHostOrSpecFromURL(*itr)); | |
500 if (hosts.insert(host).second) { | |
501 host_data.push_back(HostData(host, type, -1, -1)); | |
502 VisitHost(host, type); | |
503 } | |
504 } | |
505 ReportOriginData(origin_data); | |
506 ReportHostData(host_data); | |
507 } | |
508 | |
509 QuotaInternalsMessageHandler::~QuotaInternalsMessageHandler() { | |
510 if (proxy_) | |
511 proxy_->handler_ = NULL; | |
512 } | |
513 } // namespace quota_internals | |
514 | |
16 QuotaInternalsUI::QuotaInternalsUI(TabContents* contents) | 515 QuotaInternalsUI::QuotaInternalsUI(TabContents* contents) |
17 : WebUI(contents) { | 516 : WebUI(contents) { |
18 // TODO(tzik): implement and attach message handler | 517 WebUIMessageHandler* handler = |
518 new quota_internals::QuotaInternalsMessageHandler; | |
519 AddMessageHandler(handler->Attach(this)); | |
19 contents->profile()->GetChromeURLDataManager()-> | 520 contents->profile()->GetChromeURLDataManager()-> |
20 AddDataSource(new quota_internals::QuotaInternalsHTMLSource); | 521 AddDataSource(new quota_internals::QuotaInternalsHTMLSource); |
michaeln
2011/05/30 19:36:57
When is this data source removed? It looks like a
tzik
2011/05/31 04:53:01
Yes, we add DataSource in each quota-internals tab
michaeln
2011/06/01 01:09:32
I see, any old DataSource under this ones name is
| |
21 } | 522 } |
22 | |
23 namespace quota_internals { | |
24 | |
25 QuotaInternalsHTMLSource::QuotaInternalsHTMLSource() | |
26 : DataSource(chrome::kChromeUIQuotaInternalsHost, | |
27 MessageLoop::current()) { | |
28 } | |
29 | |
30 void QuotaInternalsHTMLSource::StartDataRequest(const std::string& path, | |
31 bool is_incognito, | |
32 int request_id) OVERRIDE { | |
33 base::StringPiece html( | |
34 ResourceBundle::GetSharedInstance().GetRawDataResource( | |
35 IDR_QUOTA_INTERNALS_INDEX_HTML)); | |
36 | |
37 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); | |
38 html_bytes->data.resize(html.size()); | |
39 std::copy(html.data(), html.data() + html.size(), html_bytes->data.begin()); | |
40 SendResponse(request_id, html_bytes); | |
41 return; | |
42 } | |
43 | |
44 std::string QuotaInternalsHTMLSource::GetMimeType( | |
45 const std::string& path_unused) const { | |
46 return "text/html"; | |
47 } | |
48 | |
49 } // namespace quota_internals | |
OLD | NEW |