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