Index: content/browser/devtools/renderer_overrides_handler.cc |
diff --git a/content/browser/devtools/renderer_overrides_handler.cc b/content/browser/devtools/renderer_overrides_handler.cc |
index c25adde7619407673d7f4c202dfcede2fb20ddaf..e7a9f59f2aef75c7a4c22053881d6db4c0365c1e 100644 |
--- a/content/browser/devtools/renderer_overrides_handler.cc |
+++ b/content/browser/devtools/renderer_overrides_handler.cc |
@@ -6,6 +6,7 @@ |
#include <string> |
+#include "base/barrier_closure.h" |
#include "base/base64.h" |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
@@ -28,17 +29,20 @@ |
#include "content/public/browser/render_process_host.h" |
#include "content/public/browser/render_view_host.h" |
#include "content/public/browser/render_widget_host_view.h" |
+#include "content/public/browser/storage_partition.h" |
#include "content/public/browser/web_contents.h" |
#include "content/public/browser/web_contents_delegate.h" |
#include "content/public/common/page_transition_types.h" |
#include "content/public/common/referrer.h" |
#include "ipc/ipc_sender.h" |
+#include "net/base/net_util.h" |
#include "third_party/WebKit/public/web/WebInputEvent.h" |
#include "ui/gfx/codec/jpeg_codec.h" |
#include "ui/gfx/codec/png_codec.h" |
#include "ui/gfx/size_conversions.h" |
#include "ui/snapshot/snapshot.h" |
#include "url/gurl.h" |
+#include "webkit/browser/quota/quota_manager.h" |
using WebKit::WebGestureEvent; |
using WebKit::WebInputEvent; |
@@ -127,6 +131,11 @@ RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent) |
&RendererOverridesHandler::PageStopScreencast, |
base::Unretained(this))); |
RegisterCommandHandler( |
+ devtools::Page::queryUsageAndQuota::kName, |
+ base::Bind( |
+ &RendererOverridesHandler::PageQueryUsageAndQuota, |
+ base::Unretained(this))); |
+ RegisterCommandHandler( |
devtools::Input::dispatchMouseEvent::kName, |
base::Bind( |
&RendererOverridesHandler::InputDispatchMouseEvent, |
@@ -559,6 +568,203 @@ void RendererOverridesHandler::ScreenshotCaptured( |
} |
} |
+// Quota and Usage ------------------------------------------ |
+ |
+namespace { |
+ |
+typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)> |
+ ResponseCallback; |
+ |
+void QueryUsageAndQuotaCompletedOnIOThread( |
+ scoped_ptr<base::DictionaryValue> quota, |
+ scoped_ptr<base::DictionaryValue> usage, |
+ ResponseCallback callback) { |
+ |
+ scoped_ptr<base::DictionaryValue> response_data(new base::DictionaryValue); |
+ response_data->Set(devtools::Page::queryUsageAndQuota::kResponseQuota, |
+ quota.release()); |
+ response_data->Set(devtools::Page::queryUsageAndQuota::kResponseUsage, |
+ usage.release()); |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(callback, base::Passed(&response_data))); |
+} |
+ |
+void DidGetHostUsage( |
+ base::ListValue* list, |
+ const std::string& client_id, |
+ const base::Closure& barrier, |
+ int64 value) { |
+ base::DictionaryValue* usage_item = new base::DictionaryValue; |
+ usage_item->SetString(devtools::Page::UsageItem::kItemID, client_id); |
+ usage_item->SetDouble(devtools::Page::UsageItem::kItemValue, value); |
+ list->Append(usage_item); |
+ barrier.Run(); |
+} |
+ |
+void DidGetQuotaValue( |
+ base::DictionaryValue* dictionary, |
+ const std::string& item_name, |
+ const base::Closure& barrier, |
+ quota::QuotaStatusCode status, |
+ int64 value) { |
+ if (status == quota::kQuotaStatusOk) |
+ dictionary->SetDouble(item_name, value); |
+ barrier.Run(); |
+} |
+ |
+void DidGetUsageAndQuotaForWebApps( |
+ base::DictionaryValue* quota, |
+ const std::string& item_name, |
+ const base::Closure& barrier, |
+ quota::QuotaStatusCode status, |
+ int64 used_bytes, |
+ int64 quota_in_bytes) { |
+ if (status == quota::kQuotaStatusOk) |
+ quota->SetDouble(item_name, quota_in_bytes); |
+ barrier.Run(); |
+} |
+ |
+std::string GetStorageTypeName(quota::StorageType type) { |
+ switch (type) { |
+ case quota::kStorageTypeTemporary: |
+ return devtools::Page::Usage::kItemTemporary; |
+ case quota::kStorageTypePersistent: |
+ return devtools::Page::Usage::kItemPersistent; |
+ case quota::kStorageTypeSyncable: |
+ return devtools::Page::Usage::kItemSyncable; |
+ default: |
+ NOTREACHED(); |
+ return ""; |
+ } |
+} |
+ |
+std::string GetQuotaClientName(quota::QuotaClient::ID id) { |
+ switch (id) { |
+ case quota::QuotaClient::kFileSystem: |
+ return devtools::Page::UsageItem::ID::kFilesystem; |
+ case quota::QuotaClient::kDatabase: |
+ return devtools::Page::UsageItem::ID::kDatabase; |
+ case quota::QuotaClient::kAppcache: |
+ return devtools::Page::UsageItem::ID::kAppcache; |
+ case quota::QuotaClient::kIndexedDatabase: |
+ return devtools::Page::UsageItem::ID::kIndexedDatabase; |
+ default: |
+ NOTREACHED(); |
+ return ""; |
+ } |
+} |
+ |
+void QueryUsageAndQuotaOnIOThread( |
+ scoped_refptr<quota::QuotaManager> quota_manager, |
+ const GURL& security_origin, |
+ const ResponseCallback& callback) { |
+ scoped_ptr<base::DictionaryValue> quota(new base::DictionaryValue); |
+ scoped_ptr<base::DictionaryValue> usage(new base::DictionaryValue); |
+ |
+ static quota::QuotaClient::ID kQuotaClients[] = { |
+ quota::QuotaClient::kFileSystem, |
+ quota::QuotaClient::kDatabase, |
+ quota::QuotaClient::kAppcache, |
+ quota::QuotaClient::kIndexedDatabase |
+ }; |
+ |
+ static const size_t kStorageTypeCount = quota::kStorageTypeUnknown; |
+ |
+ base::ListValue* storage_type_lists[kStorageTypeCount]; |
+ |
+ for (size_t i = 0; i != kStorageTypeCount; i++) { |
+ const quota::StorageType type = static_cast<quota::StorageType>(i); |
+ storage_type_lists[i] = new base::ListValue; |
+ usage->Set(GetStorageTypeName(type), storage_type_lists[i]); |
+ } |
+ |
+ COMPILE_ASSERT(kStorageTypeCount == arraysize(storage_type_lists), |
+ inconsistent_storage_type_list); |
+ |
+ int kExpectedResults = 2 + arraysize(kQuotaClients) * kStorageTypeCount; |
+ |
+ base::DictionaryValue* quota_raw_ptr = quota.get(); |
+ |
+ // Takes owneship on usage and quota. |
+ base::Closure barrier = BarrierClosure( |
+ kExpectedResults, |
+ base::Bind(&QueryUsageAndQuotaCompletedOnIOThread, |
+ base::Passed("a), |
+ base::Passed(&usage), |
+ callback)); |
+ std::string host = net::GetHostOrSpecFromURL(security_origin); |
+ |
+ quota_manager->GetUsageAndQuotaForWebApps( |
+ security_origin, |
+ quota::kStorageTypeTemporary, |
+ base::Bind(&DidGetUsageAndQuotaForWebApps, quota_raw_ptr, |
+ std::string(devtools::Page::Quota::kItemTemporary), barrier)); |
+ |
+ quota_manager->GetPersistentHostQuota( |
+ host, |
+ base::Bind(&DidGetQuotaValue, quota_raw_ptr, |
+ std::string(devtools::Page::Quota::kItemPersistent), |
+ barrier)); |
+ |
+ for (size_t i = 0; i != arraysize(kQuotaClients); i++) { |
+ for (size_t j = 0; j != kStorageTypeCount; j++) { |
+ const quota::StorageType type = static_cast<quota::StorageType>(j); |
+ if (!quota_manager->IsTrackingHostUsage(type, |
+ kQuotaClients[i])) { |
+ barrier.Run(); |
+ continue; |
+ } |
+ quota_manager->GetHostUsage(host, type, |
+ kQuotaClients[i], |
+ base::Bind(&DidGetHostUsage, storage_type_lists[j], |
+ GetQuotaClientName(kQuotaClients[i]), |
+ barrier)); |
+ } |
+ } |
+} |
+ |
+} // namespace |
+ |
+scoped_refptr<DevToolsProtocol::Response> |
+RendererOverridesHandler::PageQueryUsageAndQuota( |
+ scoped_refptr<DevToolsProtocol::Command> command) { |
+ base::DictionaryValue* params = command->params(); |
+ std::string security_origin; |
+ if (!params || !params->GetString( |
+ devtools::Page::queryUsageAndQuota::kParamSecurityOrigin, |
+ &security_origin)) { |
+ return command->InvalidParamResponse( |
+ devtools::Page::queryUsageAndQuota::kParamSecurityOrigin); |
+ } |
+ |
+ ResponseCallback callback = base::Bind( |
+ &RendererOverridesHandler::PageQueryUsageAndQuotaCompleted, |
+ weak_factory_.GetWeakPtr(), |
+ command); |
+ |
+ scoped_refptr<quota::QuotaManager> quota_manager = |
+ agent_->GetRenderViewHost()->GetProcess()-> |
+ GetStoragePartition()->GetQuotaManager(); |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind( |
+ &QueryUsageAndQuotaOnIOThread, |
+ quota_manager, |
+ GURL(security_origin), |
+ callback)); |
+ |
+ return command->AsyncResponsePromise(); |
+} |
+ |
+void RendererOverridesHandler::PageQueryUsageAndQuotaCompleted( |
+ scoped_refptr<DevToolsProtocol::Command> command, |
+ scoped_ptr<base::DictionaryValue> response_data) { |
+ SendAsyncResponse(command->SuccessResponse(response_data.release())); |
+} |
+ |
void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) { |
base::DictionaryValue* params = new base::DictionaryValue(); |
params->SetBoolean( |