Chromium Code Reviews| 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 |