Index: chrome/browser/ui/webui/quota_internals_ui.cc |
diff --git a/chrome/browser/ui/webui/quota_internals_ui.cc b/chrome/browser/ui/webui/quota_internals_ui.cc |
index 30c68d4ae8aeba74d64f475fe6fcc2c14d4d7182..370fdd3a9a7ea3d193880d4fb6b82aee1055f4f5 100644 |
--- a/chrome/browser/ui/webui/quota_internals_ui.cc |
+++ b/chrome/browser/ui/webui/quota_internals_ui.cc |
@@ -7,15 +7,39 @@ |
#include <algorithm> |
#include <string> |
+#include "base/values.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/common/url_constants.h" |
#include "content/browser/tab_contents/tab_contents.h" |
#include "grit/quota_internals_resources.h" |
+#include "net/base/net_util.h" |
#include "ui/base/resource/resource_bundle.h" |
+namespace { |
+template<typename T> |
+std::string toString(const T& v) { |
kinuko
2011/05/30 10:18:00
style-nit: please start function names with capita
tzik
2011/05/31 04:53:00
Done.
|
+ std::ostringstream out; |
+ out << v; |
+ return out.str(); |
+} |
+ |
+std::string storageTypeToString(quota::StorageType type) { |
kinuko
2011/05/30 10:18:00
ditto
tzik
2011/05/31 04:53:00
Done.
|
+ switch (type) { |
+ case quota::kStorageTypeTemporary: |
+ return "temporary"; |
+ case quota::kStorageTypePersistent: |
+ return "persistent"; |
+ default: |
+ return "unknown"; |
+ } |
+} |
+} |
kinuko
2011/05/30 10:18:00
style-nit: can you add a comment?
} // anonymous
tzik
2011/05/31 04:53:00
Done.
|
+ |
QuotaInternalsUI::QuotaInternalsUI(TabContents* contents) |
: WebUI(contents) { |
- // TODO(tzik): implement and attach message handler |
+ WebUIMessageHandler* handler = |
+ new quota_internals::QuotaInternalsMessageHandler; |
+ AddMessageHandler(handler->Attach(this)); |
contents->profile()->GetChromeURLDataManager()-> |
AddDataSource(new quota_internals::QuotaInternalsHTMLSource); |
} |
@@ -46,4 +70,349 @@ std::string QuotaInternalsHTMLSource::GetMimeType( |
return "text/html"; |
} |
+QuotaInternalsMessageHandler::QuotaInternalsMessageHandler() { |
+} |
+ |
+QuotaInternalsMessageHandler::~QuotaInternalsMessageHandler() { |
+ if (proxy_) |
+ proxy_->handler_ = NULL; |
+} |
+ |
+WebUIMessageHandler* QuotaInternalsMessageHandler::Attach(WebUI* web_ui) { |
+ return WebUIMessageHandler::Attach(web_ui); |
+} |
+ |
+void QuotaInternalsMessageHandler::RegisterMessages() { |
+ DCHECK(web_ui_); |
+ web_ui_->RegisterMessageCallback( |
+ "requestData", |
+ NewCallback(this, &QuotaInternalsMessageHandler::OnRequestData)); |
+} |
+ |
+void QuotaInternalsMessageHandler::ReportAvailableSpace( |
+ int64 available_space) { |
+ scoped_ptr<Value> avail( |
+ Value::CreateStringValue(toString(available_space))); |
+ SendMessage("AvailableSpaceUpdated", *avail.get()); |
+} |
+ |
+void QuotaInternalsMessageHandler::ReportGlobalData(const GlobalData& data) { |
+ DictionaryValue dict; |
+ if (data.type != quota::kStorageTypeUnknown) |
+ dict.SetString("type", storageTypeToString(data.type)); |
+ if (data.usage >= 0) |
+ dict.SetString("usage", toString(data.usage)); |
+ if (data.usage >= 0) |
kinuko
2011/05/30 10:18:00
data.unlimited_usage ?
tzik
2011/05/31 04:53:00
Done.
|
+ dict.SetString("unlimited_usage", toString(data.unlimited_usage)); |
+ if (data.quota >= 0) |
+ dict.SetString("quota", toString(data.quota)); |
kinuko
2011/05/30 10:18:00
Can we show these values even if they are < 0?
Hm
|
+ SendMessage("GlobalDataUpdated", dict); |
+} |
+ |
+void QuotaInternalsMessageHandler::ReportHostData( |
+ const std::vector<HostData>& hosts) { |
+ ListValue hosts_value; |
+ typedef std::vector<HostData>::const_iterator iterator; |
+ for (iterator itr(hosts.begin()), end(hosts.end()); |
+ itr != end; ++itr) { |
+ scoped_ptr<DictionaryValue> dict(new DictionaryValue); |
+ if (!itr->host.empty()) |
+ dict->SetString("host", itr->host); |
+ if (itr->type != quota::kStorageTypeUnknown) |
+ dict->SetString("type", storageTypeToString(itr->type)); |
kinuko
2011/05/30 10:18:00
could we simply show "unknown" for unknown types?
tzik
2011/05/31 04:53:00
Done.
|
+ if (itr->usage >= 0) |
+ dict->SetString("usage", toString(itr->usage)); |
+ if (itr->quota >= 0) |
+ dict->SetString("quota", toString(itr->quota)); |
+ hosts_value.Append(dict.release()); |
+ } |
+ |
+ SendMessage("HostDataUpdated", hosts_value); |
+} |
+ |
+void QuotaInternalsMessageHandler::ReportOriginData( |
+ const std::vector<OriginData>& origins) { |
+ ListValue origins_value; |
+ typedef std::vector<OriginData>::const_iterator iterator; |
+ for (iterator itr(origins.begin()), end(origins.end()); |
+ itr != end; ++itr) { |
+ scoped_ptr<DictionaryValue> dict(new DictionaryValue); |
+ if (!itr->origin.is_empty()) |
+ dict->SetString("origin", itr->origin.spec()); |
+ if (itr->type != quota::kStorageTypeUnknown) |
+ dict->SetString("type", storageTypeToString(itr->type)); |
kinuko
2011/05/30 10:18:00
ditto
tzik
2011/05/31 04:53:00
Done.
|
+ if (!itr->host.empty()) |
+ dict->SetString("host", toString(itr->host)); |
+ if (itr->in_use >= 0) |
+ dict->SetBoolean("in_use", itr->in_use ? true : false); |
+ if (itr->used_count >= 0) |
+ dict->SetInteger("used_count", itr->used_count); |
+ if (!itr->last_access_time.is_null()) |
+ dict->SetDouble("last_access_time", itr->last_access_time.ToDoubleT()); |
+ origins_value.Append(dict.release()); |
+ } |
+ |
+ SendMessage("OriginDataUpdated", origins_value); |
+} |
+ |
+void QuotaInternalsMessageHandler::OnRequestData(const ListValue* list) { |
+ if (!proxy_) |
+ proxy_ = new QuotaInternalsProxy(this); |
+ proxy_->RequestData(web_ui_->GetProfile()->GetQuotaManager()); |
+} |
+ |
+void QuotaInternalsMessageHandler::SendMessage(const std::string& message, |
+ const Value& value) { |
+ scoped_ptr<Value> message_data(Value::CreateStringValue(message)); |
+ web_ui_->CallJavascriptFunction("cr.quota.messageHandler_", |
+ *message_data.get(), |
+ value); |
+} |
+ |
+void QuotaInternalsProxy::RequestData(quota::QuotaManager* quota_manager) { |
+ io_thread_->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod(this, &QuotaInternalsProxy::RunRequestData, |
+ make_scoped_refptr(quota_manager))); |
+} |
+ |
+void QuotaInternalsProxy::Destruct(const QuotaInternalsProxy* proxy) { |
+ if (proxy->io_thread_->BelongsToCurrentThread()) |
+ proxy->io_thread_->DeleteSoon(FROM_HERE, proxy); |
+ else |
+ delete proxy; |
+} |
+ |
+void QuotaInternalsProxy::RunRequestData( |
kinuko
2011/05/30 10:18:00
For better readability can we rename this to Reque
tzik
2011/05/31 04:53:00
Done.
|
+ scoped_refptr<quota::QuotaManager> quota_manager) { |
+ quota_manager_ = quota_manager->AsWeakPtr(); |
+ |
+ quota_manager->GetAvailableSpace( |
+ callback_factory_.NewCallback( |
+ &QuotaInternalsProxy::DidGetAvailableSpace)); |
+ |
+ quota_manager->GetTemporaryGlobalQuota( |
+ callback_factory_.NewCallback( |
+ &QuotaInternalsProxy::DidGetGlobalQuota)); |
+ |
+ quota_manager->GetGlobalUsage( |
+ quota::kStorageTypeTemporary, |
+ callback_factory_.NewCallback( |
+ &QuotaInternalsProxy::DidGetGlobalUsage)); |
+ |
+ quota_manager->GetGlobalUsage( |
+ quota::kStorageTypePersistent, |
+ callback_factory_.NewCallback( |
+ &QuotaInternalsProxy::DidGetGlobalUsage)); |
+ |
+ quota_manager->DumpQuotaTable( |
+ callback_factory_.NewCallback( |
+ &QuotaInternalsProxy::DidDumpQuotaTable)); |
+ |
+ quota_manager->DumpLastAccessTimeTable( |
+ callback_factory_.NewCallback( |
+ &QuotaInternalsProxy::DidDumpLastAccessTimeTable)); |
+} |
+ |
+QuotaInternalsProxy::QuotaInternalsProxy( |
+ QuotaInternalsMessageHandler* handler) |
+ : io_thread_( |
+ BrowserThread::GetMessageLoopProxyForThread( |
+ BrowserThread::IO)), |
+ ui_thread_( |
+ BrowserThread::GetMessageLoopProxyForThread( |
+ BrowserThread::UI)), |
kinuko
2011/05/30 10:18:00
You could use BrowserThread::PostTask(BrowserThrea
tzik
2011/05/31 04:53:00
Done.
|
+ handler_(handler), |
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
+} |
+ |
+void QuotaInternalsProxy::ReportAvailableSpace(int64 available_space) { |
+ ui_thread_->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod( |
+ this, &QuotaInternalsProxy::RunReportAvailableSpace, |
+ available_space)); |
+} |
+ |
+void QuotaInternalsProxy::RunReportAvailableSpace(int64 available_space) { |
+ if (handler_) |
+ handler_->ReportAvailableSpace(available_space); |
+} |
+ |
+void QuotaInternalsProxy::ReportGlobalData(const GlobalData& data) { |
+ ui_thread_->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod( |
+ this, &QuotaInternalsProxy::RunReportGlobalData, |
+ data)); |
+} |
+ |
+void QuotaInternalsProxy::RunReportGlobalData(const GlobalData& data) { |
+ if (handler_) |
+ handler_->ReportGlobalData(data); |
+} |
+ |
+void QuotaInternalsProxy::ReportHostData( |
+ const std::vector<HostData>& hosts) { |
+ ui_thread_->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod( |
+ this, &QuotaInternalsProxy::RunReportHostData, |
+ hosts)); |
+} |
+ |
+void QuotaInternalsProxy::RunReportHostData( |
kinuko
2011/05/30 10:18:00
For better readability can we rename this to Repor
tzik
2011/05/31 04:53:00
Done.
|
+ const std::vector<HostData>& hosts) { |
+ if (handler_) |
+ handler_->ReportHostData(hosts); |
+} |
+ |
+void QuotaInternalsProxy::ReportOriginData( |
+ const std::vector<OriginData>& origins) { |
+ ui_thread_->PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod( |
+ this, &QuotaInternalsProxy::RunReportOriginData, |
+ origins)); |
+} |
+ |
+void QuotaInternalsProxy::RunReportOriginData( |
kinuko
2011/05/30 10:18:00
For better readability can we rename this to Repor
tzik
2011/05/31 04:53:00
Done.
|
+ const std::vector<OriginData>& origins) { |
+ if (handler_) |
+ handler_->ReportOriginData(origins); |
+} |
+ |
+void QuotaInternalsProxy::DidGetAvailableSpace(quota::QuotaStatusCode status, |
+ int64 space) { |
+ if (status == quota::kQuotaStatusOk) |
+ ReportAvailableSpace(space); |
+} |
+ |
+void QuotaInternalsProxy::DidGetGlobalQuota( |
+ quota::QuotaStatusCode status, |
+ quota::StorageType type, |
+ int64 quota) { |
+ if (status == quota::kQuotaStatusOk) |
+ ReportGlobalData((GlobalData) {type, -1, -1, quota}); |
kinuko
2011/05/30 10:18:00
I might make this a constructor.
qq: do they need
tzik
2011/05/31 04:53:00
Done.
|
+} |
+ |
+void QuotaInternalsProxy::DidGetGlobalUsage(quota::StorageType type, |
+ int64 usage, |
+ int64 unlimited_usage) { |
+ ReportGlobalData((GlobalData) {type, usage, unlimited_usage, -1}); |
+ RequestPerOriginData(type); |
+} |
+ |
+void QuotaInternalsProxy::RequestPerOriginData(quota::StorageType type) { |
+ if (!quota_manager_) |
+ return; |
+ |
+ std::set<GURL> origins; |
+ quota_manager_->GetCachedOrigins(type, &origins); |
+ |
+ std::vector<OriginData> origin_data; |
+ origin_data.reserve(origins.size()); |
+ |
+ std::set<std::string> hosts; |
+ std::vector<HostData> host_data; |
+ |
+ for (std::set<GURL>::iterator itr(origins.begin()), end(origins.end()); |
+ itr != end; ++itr) { |
+ std::string host = net::GetHostOrSpecFromURL(*itr); |
+ origin_data.push_back( |
+ (OriginData) { |
+ *itr, |
+ type, |
+ host, |
+ quota_manager_->IsOriginInUse(*itr) ? 1 : 0, |
+ -1, |
+ base::Time(), |
+ }); |
+ if (hosts.insert(host).second) { |
+ host_data.push_back( |
+ (HostData) {host, type, -1, -1}); |
+ VisitHost(host, type); |
+ } |
+ } |
+ ReportOriginData(origin_data); |
+ ReportHostData(host_data); |
+} |
+ |
+void QuotaInternalsProxy::VisitHost(const std::string& host, |
+ quota::StorageType type) { |
+ if (hosts_visited_.insert(std::make_pair(host, type)).second) { |
+ hosts_pending_.insert(std::make_pair(host, type)); |
+ if (hosts_pending_.size() == 1) { |
+ GetHostUsage(host, type); |
+ } |
+ } |
+} |
+ |
+void QuotaInternalsProxy::GetHostUsage(const std::string& host, |
+ quota::StorageType type) { |
+ if (quota_manager_) |
+ quota_manager_->GetHostUsage( |
+ host, type, |
+ callback_factory_.NewCallback( |
+ &QuotaInternalsProxy::DidGetHostUsage)); |
+} |
+ |
+ |
+void QuotaInternalsProxy::DidDumpQuotaTable( |
+ const QuotaTableEntries& entries) { |
+ std::vector<HostData> host_data; |
+ host_data.reserve(entries.size()); |
+ |
+ typedef QuotaTableEntries::const_iterator iterator; |
+ for (iterator itr(entries.begin()), end(entries.end()); |
+ itr != end; ++itr) { |
+ host_data.push_back( |
+ (HostData) { |
+ itr->host, |
+ itr->type, |
+ -1, |
+ itr->quota, |
+ }); |
+ } |
+ ReportHostData(host_data); |
+} |
+ |
+void QuotaInternalsProxy::DidDumpLastAccessTimeTable( |
+ const LastAccessTimeTableEntries& entries) { |
+ std::vector<OriginData> origin_data; |
+ origin_data.reserve(entries.size()); |
+ |
+ typedef LastAccessTimeTableEntries::const_iterator iterator; |
+ for (iterator itr(entries.begin()), end(entries.end()); |
+ itr != end; ++itr) { |
+ origin_data.push_back( |
+ (OriginData) { |
+ itr->origin, |
+ itr->type, |
+ std::string(), |
+ -1, |
+ itr->used_count, |
+ itr->last_access_time, |
+ }); |
+ } |
+ ReportOriginData(origin_data); |
+} |
+ |
+void QuotaInternalsProxy::DidGetHostUsage( |
+ const std::string& host, quota::StorageType type, int64 usage) { |
+ DCHECK(type == quota::kStorageTypeTemporary || |
+ type == quota::kStorageTypePersistent); |
+ |
+ report_pending_.push_back( |
+ (HostData) {host, type, usage, -1}); |
+ hosts_pending_.erase(make_pair(host, type)); |
+ if (report_pending_.size() >= 10 || hosts_pending_.empty()) { |
+ ReportHostData(report_pending_); |
+ report_pending_.clear(); |
+ } |
+ |
+ if (!hosts_pending_.empty()) |
+ GetHostUsage(hosts_pending_.begin()->first, |
+ hosts_pending_.begin()->second); |
+} |
} // namespace quota_internals |