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 fe35d3029b3e7c2a18f55c5248e088b94b4ca38c..540d18340cbd37cc87439f082b1aec1c0db540a3 100644 |
--- a/content/browser/devtools/renderer_overrides_handler.cc |
+++ b/content/browser/devtools/renderer_overrides_handler.cc |
@@ -6,10 +6,12 @@ |
#include <string> |
+#include "base/barrier_closure.h" |
#include "base/base64.h" |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
#include "base/files/file_path.h" |
+#include "base/message_loop/message_loop_proxy.h" |
#include "base/strings/string16.h" |
#include "base/values.h" |
#include "content/browser/child_process_security_policy_impl.h" |
@@ -28,17 +30,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; |
@@ -72,6 +77,80 @@ void ParseGenericInputParams(base::DictionaryValue* params, |
&event->timeStampSeconds); |
} |
+typedef base::Callback<void (DevToolsProtocol::Response*)> RespondCallback; |
+ |
+class QuotaTask { |
+ public: |
+ virtual ~QuotaTask() {} |
+ |
+ static void Run(scoped_ptr<QuotaTask> task); |
+ |
+ protected: |
+ QuotaTask(scoped_refptr<DevToolsProtocol::Command> command, |
+ const RespondCallback& callback, |
+ RenderViewHost* render_vew_host, |
+ const std::string& security_origin); |
+ |
+ scoped_refptr<quota::QuotaManager> GetQuotaManager() { |
pfeldman
2013/09/17 15:19:45
These will not be needed.
SeRya
2013/09/17 16:12:13
Done.
|
+ return quota_manager_; |
+ } |
+ |
+ std::string host() const { return net::GetHostOrSpecFromURL(origin_); } |
+ const GURL& origin() const { return origin_; } |
+ |
+ void AddStep(base::Closure const& step) { steps_.push_back(step); } |
+ |
+ void StepDone(); |
+ virtual scoped_ptr<base::DictionaryValue> GetResponseData() = 0; |
+ |
+ private: |
+ scoped_refptr<DevToolsProtocol::Command> command_; |
+ RespondCallback callback_; |
+ |
+ GURL origin_; |
+ scoped_refptr<quota::QuotaManager> quota_manager_; |
+ |
+ scoped_refptr<base::MessageLoopProxy> response_loop_proxy_; |
+ |
+ std::vector<base::Closure> steps_; |
+ base::Closure barrier_; |
+ |
+ // Called on IO thread. |
+ void TaskStart(); |
+ void TaskDone(); |
+ |
+ void RespondOnCallerThread(scoped_ptr<base::DictionaryValue> response); |
+ static void RespondOnCallerThreadAndDelete( |
+ QuotaTask* task, |
+ scoped_ptr<base::DictionaryValue> responseData); |
+}; |
+ |
+class GetUsageAndQuotaTask : public QuotaTask { |
+ public: |
+ GetUsageAndQuotaTask(scoped_refptr<DevToolsProtocol::Command> command, |
+ const RespondCallback& callback, |
+ RenderViewHost* render_vew_host, |
+ const std::string& security_origin); |
+ |
+ private: |
+ scoped_ptr<base::DictionaryValue> quota_; |
+ scoped_ptr<base::DictionaryValue> usage_; |
+ |
+ virtual scoped_ptr<base::DictionaryValue> GetResponseData() OVERRIDE; |
+ void GetHostUsage(quota::StorageType type, |
+ quota::QuotaClient::ID client_id, const char* name); |
+ void DidGetQuota( |
+ const char* name, quota::QuotaStatusCode status, int64 space); |
+ quota::QuotaCallback MakeQuotaCallback(const char* name); |
+ void DidGetUsage(const char* name, int64 usage_value); |
+ void DidGetUsageAndQuotaForWebApps(const char* name, |
+ quota::QuotaStatusCode status, int64 usage, int64 quota); |
+ void AddGetHostUsageStep( |
+ quota::StorageType type, |
+ quota::QuotaClient::ID client_id, |
+ const char* name); |
+}; |
+ |
} // namespace |
RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent) |
@@ -122,6 +201,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, |
@@ -525,6 +609,203 @@ void RendererOverridesHandler::ScreenshotCaptured( |
} |
} |
pfeldman
2013/09/17 15:19:45
}
// QuotaTask ---------------------------------
SeRya
2013/09/17 16:12:13
Done.
|
+// static |
+void QuotaTask::Run(scoped_ptr<QuotaTask> task) { |
+ // Will be deleted when done. |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&QuotaTask::TaskStart, base::Unretained(task.release()))); |
+} |
+ |
+QuotaTask::QuotaTask( |
+ scoped_refptr<DevToolsProtocol::Command> command, |
+ const RespondCallback& callback, |
+ RenderViewHost* render_vew_host, |
+ const std::string& security_origin) |
+ : command_(command), |
+ callback_(callback), |
+ origin_(security_origin), |
+ quota_manager_(render_vew_host->GetProcess()-> |
+ GetStoragePartition()->GetQuotaManager()), |
+ response_loop_proxy_(base::MessageLoopProxy::current()) { |
+} |
+ |
+void QuotaTask::TaskStart() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ barrier_ = base::BarrierClosure( |
+ steps_.size(), |
+ base::Bind(&QuotaTask::TaskDone, base::Unretained(this))); |
+ |
+ for (std::vector<base::Closure>::iterator i = steps_.begin(); |
+ i != steps_.end(); ++i) { |
+ i->Run(); |
+ } |
+} |
+ |
+void QuotaTask::StepDone() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ barrier_.Run(); |
+} |
+ |
+void QuotaTask::TaskDone() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ scoped_ptr<base::DictionaryValue> responseData = GetResponseData(); |
+ |
+ base::MessageLoopProxy* loop = response_loop_proxy_.get(); |
+ loop->PostTask(FROM_HERE, base::Bind( |
+ &QuotaTask::RespondOnCallerThreadAndDelete, |
+ this, base::Passed(&responseData))); |
+} |
+ |
+void QuotaTask::RespondOnCallerThread( |
+ scoped_ptr<base::DictionaryValue> response) { |
+ callback_.Run(command_->SuccessResponse(response.release()).get()); |
+} |
+ |
+// static |
+void QuotaTask::RespondOnCallerThreadAndDelete( |
+ QuotaTask* task, |
+ scoped_ptr<base::DictionaryValue> responseData) { |
+ task->RespondOnCallerThread(responseData.Pass()); |
+ delete task; |
+} |
+ |
+GetUsageAndQuotaTask::GetUsageAndQuotaTask( |
+ scoped_refptr<DevToolsProtocol::Command> command, |
+ const RespondCallback& callback, |
+ RenderViewHost* render_vew_host, |
+ const std::string& security_origin) |
+ : QuotaTask(command, callback, render_vew_host, security_origin), |
+ quota_(new base::DictionaryValue), |
+ usage_(new base::DictionaryValue) { |
+ AddStep(base::Bind("a::QuotaManager::GetAvailableSpace, |
+ GetQuotaManager(), |
+ MakeQuotaCallback("availableSpace"))); |
+ |
+ AddStep(base::Bind( |
+ "a::QuotaManager::GetUsageAndQuotaForWebApps, |
+ GetQuotaManager(), |
+ origin(), |
+ quota::kStorageTypeTemporary, |
+ base::Bind(&GetUsageAndQuotaTask::DidGetUsageAndQuotaForWebApps, |
+ base::Unretained(this), "temporaryHostQuota"))); |
+ |
+ AddStep(base::Bind("a::QuotaManager::GetPersistentHostQuota, |
+ GetQuotaManager(), |
+ host(), |
+ MakeQuotaCallback("persistentHostQuota"))); |
+ |
+ AddGetHostUsageStep( |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kFileSystem, |
+ "temporaryFileSystemUsage"); |
+ |
+ AddGetHostUsageStep( |
+ quota::kStorageTypePersistent, |
+ quota::QuotaClient::kFileSystem, |
+ "persistentFileSystemUsage"); |
+ |
+ AddGetHostUsageStep( |
+ quota::kStorageTypeSyncable, |
+ quota::QuotaClient::kFileSystem, |
+ "syncableFileSystemUsage"); |
+ |
+ AddGetHostUsageStep( |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kDatabase, |
+ "databaseUsage"); |
+ |
+ AddGetHostUsageStep( |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kAppcache, |
+ "appcacheUsage"); |
+ |
+ AddGetHostUsageStep( |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kIndexedDatabase, |
+ "indexedDatabaseUsage"); |
+} |
+ |
+void GetUsageAndQuotaTask::AddGetHostUsageStep( |
+ quota::StorageType type, |
+ quota::QuotaClient::ID client_id, |
+ const char* name) { |
+ AddStep(base::Bind(&GetUsageAndQuotaTask::GetHostUsage, |
pfeldman
2013/09/17 15:19:45
Why do you need to collect steps and not simply ru
SeRya
2013/09/17 16:12:13
BarrierClosure needs to be created before running
|
+ base::Unretained(this), type, client_id, name)); |
+} |
+ |
+scoped_ptr<base::DictionaryValue> GetUsageAndQuotaTask::GetResponseData() { |
+ scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); |
+ result->Set("quota", quota_.release()); |
+ result->Set("usage", usage_.release()); |
+ return result.Pass(); |
+} |
+ |
+void GetUsageAndQuotaTask::GetHostUsage( |
+ quota::StorageType type, |
+ quota::QuotaClient::ID client_id, |
+ const char* name) { |
+ quota::UsageCallback callback = |
+ base::Bind(&GetUsageAndQuotaTask::DidGetUsage, |
+ base::Unretained(this), name); |
+ GetQuotaManager()->GetHostUsage(host(), type, client_id, callback); |
+} |
+ |
+void GetUsageAndQuotaTask::DidGetQuota( |
+ const char* name, |
+ quota::QuotaStatusCode status, |
+ int64 space) { |
+ if (status == quota::kQuotaStatusOk) |
+ quota_->SetDouble(name, space); |
+ StepDone(); |
+} |
+ |
+quota::QuotaCallback GetUsageAndQuotaTask::MakeQuotaCallback(const char* name) { |
+ return base::Bind(&GetUsageAndQuotaTask::DidGetQuota, |
+ base::Unretained(this), name); |
+} |
+ |
+void GetUsageAndQuotaTask::DidGetUsage(const char* name, int64 usage_value) { |
+ usage_->SetDouble(name, usage_value); |
+ StepDone(); |
+} |
+ |
+void GetUsageAndQuotaTask::DidGetUsageAndQuotaForWebApps( |
+ const char* name, |
+ quota::QuotaStatusCode status, |
+ int64 usage, |
+ int64 quota) { |
+ if (status == quota::kQuotaStatusOk) |
+ quota_->SetDouble(name, quota); |
+ StepDone(); |
+} |
+ |
+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); |
+ } |
+ |
+ RespondCallback callback = base::Bind( |
+ &RendererOverridesHandler::AsyncTaskDone, weak_factory_.GetWeakPtr()); |
+ QuotaTask::Run(scoped_ptr<QuotaTask>(new GetUsageAndQuotaTask(command, |
+ callback, agent_->GetRenderViewHost(), security_origin))); |
+ return command->AsyncResponsePromise(); |
+} |
+ |
+void RendererOverridesHandler::AsyncTaskDone( |
+ DevToolsProtocol::Response* response) { |
+ SendRawMessage(response->Serialize()); |
+} |
// Input agent handlers ------------------------------------------------------ |