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 3b75e98c7b4563932cf7e1ec312e9c55624f50b1..b884990ade625ccd8f4662850e63700242f6039e 100644 |
--- a/content/browser/devtools/renderer_overrides_handler.cc |
+++ b/content/browser/devtools/renderer_overrides_handler.cc |
@@ -10,6 +10,7 @@ |
#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" |
@@ -25,16 +26,19 @@ |
#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 "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; |
@@ -130,6 +134,11 @@ RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent) |
&RendererOverridesHandler::PageStopScreencast, |
base::Unretained(this))); |
RegisterCommandHandler( |
+ devtools::Quota::queryUsageAndQuota::kName, |
+ base::Bind( |
+ &RendererOverridesHandler::QuotaQueryUsageAndQuota, |
+ base::Unretained(this))); |
+ RegisterCommandHandler( |
devtools::Input::dispatchMouseEvent::kName, |
base::Bind( |
&RendererOverridesHandler::InputDispatchMouseEvent, |
@@ -386,6 +395,231 @@ void RendererOverridesHandler::ScreenshotCaptured( |
} |
} |
+namespace { |
Vladislav Kaznacheev
2013/08/28 10:46:14
This namespace is 200 lines of very task-specific
SeRya
2013/08/29 14:24:16
Only 60 likes are quite generic (QuotaTask), 120 l
|
+ |
+typedef base::Callback<void (DevToolsProtocol::Response*)> RespondCallback; |
+ |
+class QuotaTask { |
+ public: |
+ virtual ~QuotaTask() {} |
+ |
+ static void Run(scoped_ptr<QuotaTask> task) { |
+ // Will be deleted when done. |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&QuotaTask::Start, base::Unretained(task.release()))); |
+ } |
+ |
+ protected: |
+ QuotaTask(scoped_refptr<DevToolsProtocol::Command> command, |
+ const RespondCallback& callback, |
+ RenderViewHost* render_vew_host, |
+ const std::string& security_origin) |
+ : command_(command), |
+ callback_(callback), |
+ host_(net::GetHostOrSpecFromURL(GURL(security_origin))), |
+ quota_manager_(render_vew_host->GetProcess()-> |
+ GetStoragePartition()->GetQuotaManager()), |
+ response_loop_proxy_(base::MessageLoopProxy::current()) { |
Vladislav Kaznacheev
2013/08/28 10:46:14
Looks a bit over-engineered. I assume that the cal
SeRya
2013/08/29 14:24:16
I'm a bit hesitate to introduce first thread depen
|
+ |
+ } |
+ |
+ // Called on IO thread. |
+ virtual void Start() = 0; |
+ |
+ void Done(scoped_ptr<base::DictionaryValue> responseData) { |
+ base::MessageLoopProxy* loop = response_loop_proxy_.get(); |
+ loop->PostTask(FROM_HERE, base::Bind( |
+ &QuotaTask::ResponseOnCallerThreadAndDelete, |
+ this, base::Passed(&responseData))); |
+ } |
+ |
+ quota::QuotaManager* GetQuotaManager() { return quota_manager_.get(); } |
+ const std::string& host() const { return host_; } |
+ |
+ private: |
+ scoped_refptr<DevToolsProtocol::Command> command_; |
+ RespondCallback callback_; |
+ |
+ std::string host_; |
+ scoped_refptr<quota::QuotaManager> quota_manager_; |
+ |
+ scoped_refptr<base::MessageLoopProxy> response_loop_proxy_; |
+ |
+ void ResponseOnCallerThread(scoped_ptr<base::DictionaryValue> response) { |
Vladislav Kaznacheev
2013/08/28 10:46:14
RespondOnCallerThread is better English
SeRya
2013/08/29 14:24:16
Done.
|
+ callback_.Run(command_->SuccessResponse(response.release()).get()); |
+ } |
+ |
+ static void ResponseOnCallerThreadAndDelete(QuotaTask* task, |
Vladislav Kaznacheev
2013/08/28 10:46:14
RespondOnCallerThreadAndDelete is better English
SeRya
2013/08/29 14:24:16
Done.
|
+ scoped_ptr<base::DictionaryValue> responseData) { |
+ task->ResponseOnCallerThread(responseData.Pass()); |
+ delete task; |
+ } |
+}; |
+ |
+class GetUsageAndQuotaTask : public QuotaTask { |
+ public: |
+ 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) { |
+ } |
+ |
+ protected: |
+ virtual void Start() OVERRIDE { |
+ step_ = 0; |
+ readyToNextStep_ = true; |
Vladislav Kaznacheev
2013/08/28 10:46:14
readyForNextStep
SeRya
2013/08/29 14:24:16
Done.
|
+ stepDone_ = true; |
+ DoStep(); |
+ } |
+ |
+ private: |
+ scoped_ptr<base::DictionaryValue> quota_; |
+ scoped_ptr<base::DictionaryValue> usage_; |
+ bool readyToNextStep_; |
+ bool stepDone_; |
+ int step_; |
+ |
+ void DoStep() { |
+ DCHECK(readyToNextStep_); |
+ DCHECK(stepDone_); |
+ readyToNextStep_ = false; |
+ stepDone_ = false; |
+ int startStep = step_; |
+ |
+ switch (step_) { |
Vladislav Kaznacheev
2013/08/28 10:46:14
This switch makes me sad. Please consider replacin
SeRya
2013/08/29 14:24:16
Done.
|
+ case 0: |
+ GetQuotaManager()->GetAvailableSpace( |
+ MakeQuotaCallback("availableSpace")); |
+ break; |
+ |
+ case 1: |
+ GetQuotaManager()->GetTemporaryGlobalQuota( |
+ MakeQuotaCallback("temporaryGlobalQuota")); |
+ break; |
+ |
+ case 2: |
+ GetQuotaManager()->GetPersistentHostQuota(host(), |
+ MakeQuotaCallback("persistentHostQuota")); |
+ break; |
+ |
+ case 3: |
+ GetQuotaManager()->GetHostUsage(host(), |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kFileSystem, |
+ MakeUsageCallback("temporaryFileSystemUsage")); |
+ break; |
+ |
+ case 4: |
+ GetQuotaManager()->GetHostUsage(host(), |
+ quota::kStorageTypePersistent, |
+ quota::QuotaClient::kFileSystem, |
+ MakeUsageCallback("persistentFileSystemUsage")); |
+ break; |
+ |
+ case 5: |
+ GetQuotaManager()->GetHostUsage(host(), |
+ quota::kStorageTypeSyncable, |
+ quota::QuotaClient::kFileSystem, |
+ MakeUsageCallback("syncableFileSystemUsage")); |
+ break; |
+ |
+ case 6: |
+ GetQuotaManager()->GetHostUsage(host(), |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kDatabase, |
+ MakeUsageCallback("databaseUsage")); |
+ break; |
+ |
+ case 7: |
+ GetQuotaManager()->GetHostUsage(host(), |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kAppcache, |
+ MakeUsageCallback("appcacheUsage")); |
+ break; |
+ |
+ case 8: |
+ GetQuotaManager()->GetHostUsage(host(), |
+ quota::kStorageTypeTemporary, |
+ quota::QuotaClient::kIndexedDatabase, |
+ MakeUsageCallback("indexedDatabaseUsage")); |
+ break; |
+ |
+ case 9: { |
+ scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue); |
+ result->Set("quota", quota_.release()); |
+ result->Set("usage", usage_.release()); |
+ Done(result.Pass()); |
+ } |
+ } |
+ |
+ readyToNextStep_ = true; |
+ if (stepDone_) { |
+ DCHECK(step_ == startStep + 1); |
+ DoStep(); |
+ } |
+ } |
+ |
+ void StepDone() { |
+ DCHECK(!stepDone_); |
+ step_++; |
+ stepDone_ = true; |
+ if (readyToNextStep_) |
+ DoStep(); |
+ } |
+ |
+ void DidGetQuota(const char* name, |
+ quota::QuotaStatusCode status, |
+ int64 space) { |
+ if (status == quota::kQuotaStatusOk) |
+ quota_->SetDouble(name, space); |
+ StepDone(); |
+ } |
+ |
+ quota::QuotaCallback MakeQuotaCallback(const char* name) { |
+ return base::Bind(&GetUsageAndQuotaTask::DidGetQuota, |
+ base::Unretained(this), name); |
+ } |
+ |
+ void DidGetUsage(const char* name, int64 usage_value) { |
+ usage_->SetDouble(name, usage_value); |
+ StepDone(); |
+ } |
+ |
+ quota::UsageCallback MakeUsageCallback(const char* name) { |
+ return base::Bind(&GetUsageAndQuotaTask::DidGetUsage, |
+ base::Unretained(this), name); |
+ } |
+}; |
+ |
+} // namespace |
+ |
+scoped_refptr<DevToolsProtocol::Response> |
+RendererOverridesHandler::QuotaQueryUsageAndQuota( |
+ scoped_refptr<DevToolsProtocol::Command> command) { |
+ base::DictionaryValue* params = command->params(); |
+ std::string security_origin; |
+ if (!params || !params->GetString( |
+ devtools::Quota::queryUsageAndQuota::kParamSecurityOrigin, |
+ &security_origin)) { |
+ return command->InvalidParamResponse( |
+ devtools::Quota::queryUsageAndQuota::kParamSecurityOrigin); |
+ } |
+ |
+ RespondCallback callback = base::Bind( |
+ &RendererOverridesHandler::AsyncTaskDone, base::Unretained(this)); |
Vladislav Kaznacheev
2013/08/28 10:46:14
base::Unretained allows this to be deleted before
SeRya
2013/08/29 14:24:16
Good catch. Thanks.
|
+ 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 ------------------------------------------------------ |