1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/devtools/renderer_overrides_handler.h"
10 #include "base/barrier_closure.h"
11 #include "base/base64.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/files/file_path.h"
15 #include "base/strings/string16.h"
16 #include "base/values.h"
17 #include "content/browser/child_process_security_policy_impl.h"
18 #include "content/browser/devtools/devtools_protocol_constants.h"
19 #include "content/browser/devtools/devtools_tracing_handler.h"
20 #include "content/browser/renderer_host/dip_util.h"
21 #include "content/browser/renderer_host/render_view_host_delegate.h"
22 #include "content/browser/renderer_host/render_view_host_impl.h"
23 #include "content/common/view_messages.h"
24 #include "content/port/browser/render_widget_host_view_port.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/devtools_agent_host.h"
27 #include "content/public/browser/javascript_dialog_manager.h"
28 #include "content/public/browser/navigation_controller.h"
29 #include "content/public/browser/navigation_entry.h"
30 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/render_view_host.h"
32 #include "content/public/browser/render_widget_host_view.h"
33 #include "content/public/browser/storage_partition.h"
34 #include "content/public/browser/web_contents.h"
35 #include "content/public/browser/web_contents_delegate.h"
36 #include "content/public/common/page_transition_types.h"
37 #include "content/public/common/referrer.h"
38 #include "ipc/ipc_sender.h"
39 #include "net/base/net_util.h"
40 #include "third_party/WebKit/public/web/WebInputEvent.h"
41 #include "ui/gfx/codec/jpeg_codec.h"
42 #include "ui/gfx/codec/png_codec.h"
43 #include "ui/gfx/size_conversions.h"
44 #include "ui/snapshot/snapshot.h"
46 #include "webkit/browser/quota/quota_manager.h"
48 using WebKit::WebGestureEvent;
49 using WebKit::WebInputEvent;
50 using WebKit::WebMouseEvent;
56 static const char kPng[] = "png";
57 static const char kJpeg[] = "jpeg";
58 static int kDefaultScreenshotQuality = 80;
59 static int kFrameRateThresholdMs = 100;
60 static int kCaptureRetryLimit = 2;
62 void ParseGenericInputParams(base::DictionaryValue* params,
63 WebInputEvent* event) {
65 if (params->GetInteger(devtools::Input::kParamModifiers,
68 event->modifiers |= WebInputEvent::AltKey;
70 event->modifiers |= WebInputEvent::ControlKey;
72 event->modifiers |= WebInputEvent::MetaKey;
74 event->modifiers |= WebInputEvent::ShiftKey;
77 params->GetDouble(devtools::Input::kParamTimestamp,
78 &event->timeStampSeconds);
83 RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
85 capture_retry_count_(0),
87 RegisterCommandHandler(
88 devtools::DOM::setFileInputFiles::kName,
90 &RendererOverridesHandler::GrantPermissionsForSetFileInputFiles,
91 base::Unretained(this)));
92 RegisterCommandHandler(
93 devtools::Page::disable::kName,
95 &RendererOverridesHandler::PageDisable, base::Unretained(this)));
96 RegisterCommandHandler(
97 devtools::Page::handleJavaScriptDialog::kName,
99 &RendererOverridesHandler::PageHandleJavaScriptDialog,
100 base::Unretained(this)));
101 RegisterCommandHandler(
102 devtools::Page::navigate::kName,
104 &RendererOverridesHandler::PageNavigate,
105 base::Unretained(this)));
106 RegisterCommandHandler(
107 devtools::Page::reload::kName,
109 &RendererOverridesHandler::PageReload,
110 base::Unretained(this)));
111 RegisterCommandHandler(
112 devtools::Page::getNavigationHistory::kName,
114 &RendererOverridesHandler::PageGetNavigationHistory,
115 base::Unretained(this)));
116 RegisterCommandHandler(
117 devtools::Page::navigateToHistoryEntry::kName,
119 &RendererOverridesHandler::PageNavigateToHistoryEntry,
120 base::Unretained(this)));
121 RegisterCommandHandler(
122 devtools::Page::captureScreenshot::kName,
124 &RendererOverridesHandler::PageCaptureScreenshot,
125 base::Unretained(this)));
126 RegisterCommandHandler(
127 devtools::Page::canScreencast::kName,
129 &RendererOverridesHandler::PageCanScreencast,
130 base::Unretained(this)));
131 RegisterCommandHandler(
132 devtools::Page::startScreencast::kName,
134 &RendererOverridesHandler::PageStartScreencast,
135 base::Unretained(this)));
136 RegisterCommandHandler(
137 devtools::Page::stopScreencast::kName,
139 &RendererOverridesHandler::PageStopScreencast,
140 base::Unretained(this)));
141 RegisterCommandHandler(
142 devtools::Page::queryUsageAndQuota::kName,
144 &RendererOverridesHandler::PageQueryUsageAndQuota,
145 base::Unretained(this)));
146 RegisterCommandHandler(
147 devtools::Input::dispatchMouseEvent::kName,
149 &RendererOverridesHandler::InputDispatchMouseEvent,
150 base::Unretained(this)));
151 RegisterCommandHandler(
152 devtools::Input::dispatchGestureEvent::kName,
154 &RendererOverridesHandler::InputDispatchGestureEvent,
155 base::Unretained(this)));
158 RendererOverridesHandler::~RendererOverridesHandler() {}
160 void RendererOverridesHandler::OnClientDetached() {
161 screencast_command_ = NULL;
164 void RendererOverridesHandler::OnSwapCompositorFrame(
165 const IPC::Message& message) {
166 ViewHostMsg_SwapCompositorFrame::Param param;
167 if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m))
169 last_compositor_frame_metadata_ = param.b.metadata;
171 if (screencast_command_)
172 InnerSwapCompositorFrame();
175 void RendererOverridesHandler::OnVisibilityChanged(bool visible) {
176 if (!screencast_command_)
178 NotifyScreencastVisibility(visible);
181 void RendererOverridesHandler::InnerSwapCompositorFrame() {
182 if ((base::TimeTicks::Now() - last_frame_time_).InMilliseconds() <
183 kFrameRateThresholdMs) {
187 RenderViewHost* host = agent_->GetRenderViewHost();
188 if (!host->GetView())
191 last_frame_time_ = base::TimeTicks::Now();
193 int quality = kDefaultScreenshotQuality;
195 ParseCaptureParameters(screencast_command_.get(), &format, &quality, &scale);
197 RenderWidgetHostViewPort* view_port =
198 RenderWidgetHostViewPort::FromRWHV(host->GetView());
200 gfx::Rect view_bounds = host->GetView()->GetViewBounds();
201 gfx::Size snapshot_size = gfx::ToFlooredSize(
202 gfx::ScaleSize(view_bounds.size(), scale));
204 view_port->CopyFromCompositingSurface(
205 view_bounds, snapshot_size,
206 base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
207 weak_factory_.GetWeakPtr(),
208 scoped_refptr<DevToolsProtocol::Command>(), format, quality,
209 last_compositor_frame_metadata_));
212 void RendererOverridesHandler::ParseCaptureParameters(
213 DevToolsProtocol::Command* command,
217 *quality = kDefaultScreenshotQuality;
219 double max_width = -1;
220 double max_height = -1;
221 base::DictionaryValue* params = command->params();
223 params->GetString(devtools::Page::captureScreenshot::kParamFormat,
225 params->GetInteger(devtools::Page::captureScreenshot::kParamQuality,
227 params->GetDouble(devtools::Page::captureScreenshot::kParamMaxWidth,
229 params->GetDouble(devtools::Page::captureScreenshot::kParamMaxHeight,
233 RenderViewHost* host = agent_->GetRenderViewHost();
234 CHECK(host->GetView());
235 gfx::Rect view_bounds = host->GetView()->GetViewBounds();
236 float device_sf = last_compositor_frame_metadata_.device_scale_factor;
238 *scale = std::min(*scale, max_width / view_bounds.width() / device_sf);
240 *scale = std::min(*scale, max_height / view_bounds.height() / device_sf);
244 if (*quality < 0 || *quality > 100)
245 *quality = kDefaultScreenshotQuality;
252 // DOM agent handlers --------------------------------------------------------
254 scoped_refptr<DevToolsProtocol::Response>
255 RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
256 scoped_refptr<DevToolsProtocol::Command> command) {
257 base::DictionaryValue* params = command->params();
258 base::ListValue* file_list = NULL;
260 devtools::DOM::setFileInputFiles::kParamFiles;
261 if (!params || !params->GetList(param, &file_list))
262 return command->InvalidParamResponse(param);
263 RenderViewHost* host = agent_->GetRenderViewHost();
267 for (size_t i = 0; i < file_list->GetSize(); ++i) {
268 base::FilePath::StringType file;
269 if (!file_list->GetString(i, &file))
270 return command->InvalidParamResponse(param);
271 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
272 host->GetProcess()->GetID(), base::FilePath(file));
278 // Page agent handlers -------------------------------------------------------
280 scoped_refptr<DevToolsProtocol::Response>
281 RendererOverridesHandler::PageDisable(
282 scoped_refptr<DevToolsProtocol::Command> command) {
283 screencast_command_ = NULL;
287 scoped_refptr<DevToolsProtocol::Response>
288 RendererOverridesHandler::PageHandleJavaScriptDialog(
289 scoped_refptr<DevToolsProtocol::Command> command) {
290 base::DictionaryValue* params = command->params();
291 const char* paramAccept =
292 devtools::Page::handleJavaScriptDialog::kParamAccept;
294 if (!params || !params->GetBoolean(paramAccept, &accept))
295 return command->InvalidParamResponse(paramAccept);
296 string16 prompt_override;
297 string16* prompt_override_ptr = &prompt_override;
298 if (!params || !params->GetString(
299 devtools::Page::handleJavaScriptDialog::kParamPromptText,
300 prompt_override_ptr)) {
301 prompt_override_ptr = NULL;
304 RenderViewHost* host = agent_->GetRenderViewHost();
306 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
308 JavaScriptDialogManager* manager =
309 web_contents->GetDelegate()->GetJavaScriptDialogManager();
310 if (manager && manager->HandleJavaScriptDialog(
311 web_contents, accept, prompt_override_ptr)) {
316 return command->InternalErrorResponse("No JavaScript dialog to handle");
319 scoped_refptr<DevToolsProtocol::Response>
320 RendererOverridesHandler::PageNavigate(
321 scoped_refptr<DevToolsProtocol::Command> command) {
322 base::DictionaryValue* params = command->params();
324 const char* param = devtools::Page::navigate::kParamUrl;
325 if (!params || !params->GetString(param, &url))
326 return command->InvalidParamResponse(param);
328 if (!gurl.is_valid()) {
329 return command->InternalErrorResponse("Cannot navigate to invalid URL");
331 RenderViewHost* host = agent_->GetRenderViewHost();
333 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
335 web_contents->GetController()
336 .LoadURL(gurl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
337 return command->SuccessResponse(new base::DictionaryValue());
340 return command->InternalErrorResponse("No WebContents to navigate");
343 scoped_refptr<DevToolsProtocol::Response>
344 RendererOverridesHandler::PageReload(
345 scoped_refptr<DevToolsProtocol::Command> command) {
346 RenderViewHost* host = agent_->GetRenderViewHost();
348 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
350 // Override only if it is crashed.
351 if (!web_contents->IsCrashed())
354 web_contents->GetController().Reload(false);
355 return command->SuccessResponse(NULL);
358 return command->InternalErrorResponse("No WebContents to reload");
361 scoped_refptr<DevToolsProtocol::Response>
362 RendererOverridesHandler::PageGetNavigationHistory(
363 scoped_refptr<DevToolsProtocol::Command> command) {
364 RenderViewHost* host = agent_->GetRenderViewHost();
366 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
368 base::DictionaryValue* result = new base::DictionaryValue();
369 NavigationController& controller = web_contents->GetController();
371 devtools::Page::getNavigationHistory::kResponseCurrentIndex,
372 controller.GetCurrentEntryIndex());
373 ListValue* entries = new ListValue();
374 for (int i = 0; i != controller.GetEntryCount(); ++i) {
375 const NavigationEntry* entry = controller.GetEntryAtIndex(i);
376 base::DictionaryValue* entry_value = new base::DictionaryValue();
377 entry_value->SetInteger(
378 devtools::Page::getNavigationHistory::kResponseEntryId,
379 entry->GetUniqueID());
380 entry_value->SetString(
381 devtools::Page::getNavigationHistory::kResponseEntryURL,
382 entry->GetURL().spec());
383 entry_value->SetString(
384 devtools::Page::getNavigationHistory::kResponseEntryTitle,
386 entries->Append(entry_value);
389 devtools::Page::getNavigationHistory::kResponseEntries,
391 return command->SuccessResponse(result);
394 return command->InternalErrorResponse("No WebContents to navigate");
397 scoped_refptr<DevToolsProtocol::Response>
398 RendererOverridesHandler::PageNavigateToHistoryEntry(
399 scoped_refptr<DevToolsProtocol::Command> command) {
402 base::DictionaryValue* params = command->params();
403 const char* param = devtools::Page::navigateToHistoryEntry::kParamEntryId;
404 if (!params || !params->GetInteger(param, &entry_id)) {
405 return command->InvalidParamResponse(param);
408 RenderViewHost* host = agent_->GetRenderViewHost();
410 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
412 NavigationController& controller = web_contents->GetController();
413 for (int i = 0; i != controller.GetEntryCount(); ++i) {
414 if (controller.GetEntryAtIndex(i)->GetUniqueID() == entry_id) {
415 controller.GoToIndex(i);
416 return command->SuccessResponse(new base::DictionaryValue());
419 return command->InvalidParamResponse(param);
422 return command->InternalErrorResponse("No WebContents to navigate");
425 scoped_refptr<DevToolsProtocol::Response>
426 RendererOverridesHandler::PageCaptureScreenshot(
427 scoped_refptr<DevToolsProtocol::Command> command) {
428 RenderViewHost* host = agent_->GetRenderViewHost();
429 if (!host->GetView())
430 return command->InternalErrorResponse("Unable to access the view");
433 int quality = kDefaultScreenshotQuality;
435 ParseCaptureParameters(command.get(), &format, &quality, &scale);
437 gfx::Rect view_bounds = host->GetView()->GetViewBounds();
438 gfx::Size snapshot_size = gfx::ToFlooredSize(
439 gfx::ScaleSize(view_bounds.size(), scale));
441 // Grab screen pixels if available for current platform.
442 // TODO(pfeldman): support format, scale and quality in ui::GrabViewSnapshot.
443 std::vector<unsigned char> png;
444 bool is_unscaled_png = scale == 1 && format == kPng;
445 if (is_unscaled_png && ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
447 gfx::Rect(snapshot_size))) {
448 std::string base64_data;
449 bool success = base::Base64Encode(
450 base::StringPiece(reinterpret_cast<char*>(&*png.begin()), png.size()),
453 base::DictionaryValue* result = new base::DictionaryValue();
455 devtools::Page::kData, base64_data);
456 return command->SuccessResponse(result);
458 return command->InternalErrorResponse("Unable to base64encode screenshot");
461 // Fallback to copying from compositing surface.
462 RenderWidgetHostViewPort* view_port =
463 RenderWidgetHostViewPort::FromRWHV(host->GetView());
465 view_port->CopyFromCompositingSurface(
466 view_bounds, snapshot_size,
467 base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
468 weak_factory_.GetWeakPtr(), command, format, quality,
469 last_compositor_frame_metadata_));
470 return command->AsyncResponsePromise();
473 scoped_refptr<DevToolsProtocol::Response>
474 RendererOverridesHandler::PageCanScreencast(
475 scoped_refptr<DevToolsProtocol::Command> command) {
476 base::DictionaryValue* result = new base::DictionaryValue();
477 #if defined(OS_ANDROID)
478 result->SetBoolean(devtools::kResult, true);
480 result->SetBoolean(devtools::kResult, false);
481 #endif // defined(OS_ANDROID)
482 return command->SuccessResponse(result);
485 scoped_refptr<DevToolsProtocol::Response>
486 RendererOverridesHandler::PageStartScreencast(
487 scoped_refptr<DevToolsProtocol::Command> command) {
488 screencast_command_ = command;
489 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
490 agent_->GetRenderViewHost());
491 bool visible = !host->is_hidden();
492 NotifyScreencastVisibility(visible);
494 InnerSwapCompositorFrame();
495 return command->SuccessResponse(NULL);
498 scoped_refptr<DevToolsProtocol::Response>
499 RendererOverridesHandler::PageStopScreencast(
500 scoped_refptr<DevToolsProtocol::Command> command) {
501 last_frame_time_ = base::TimeTicks();
502 screencast_command_ = NULL;
503 return command->SuccessResponse(NULL);
506 void RendererOverridesHandler::ScreenshotCaptured(
507 scoped_refptr<DevToolsProtocol::Command> command,
508 const std::string& format,
510 const cc::CompositorFrameMetadata& metadata,
512 const SkBitmap& bitmap) {
516 command->InternalErrorResponse("Unable to capture screenshot"));
517 } else if (capture_retry_count_) {
518 --capture_retry_count_;
519 base::MessageLoop::current()->PostDelayedTask(
521 base::Bind(&RendererOverridesHandler::InnerSwapCompositorFrame,
522 weak_factory_.GetWeakPtr()),
523 base::TimeDelta::FromMilliseconds(kFrameRateThresholdMs));
528 std::vector<unsigned char> data;
529 SkAutoLockPixels lock_image(bitmap);
531 if (format == kPng) {
532 encoded = gfx::PNGCodec::Encode(
533 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
534 gfx::PNGCodec::FORMAT_SkBitmap,
535 gfx::Size(bitmap.width(), bitmap.height()),
536 bitmap.width() * bitmap.bytesPerPixel(),
537 false, std::vector<gfx::PNGCodec::Comment>(), &data);
538 } else if (format == kJpeg) {
539 encoded = gfx::JPEGCodec::Encode(
540 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
541 gfx::JPEGCodec::FORMAT_SkBitmap,
544 bitmap.width() * bitmap.bytesPerPixel(),
553 command->InternalErrorResponse("Unable to encode screenshot"));
558 std::string base_64_data;
559 if (!base::Base64Encode(base::StringPiece(
560 reinterpret_cast<char*>(&data[0]),
565 command->InternalErrorResponse("Unable to base64 encode"));
570 base::DictionaryValue* response = new base::DictionaryValue();
571 response->SetString(devtools::Page::kData, base_64_data);
573 // Consider metadata empty in case it has no device scale factor.
574 if (metadata.device_scale_factor != 0) {
575 response->SetDouble(devtools::Page::kParamDeviceScaleFactor,
576 metadata.device_scale_factor);
577 response->SetDouble(devtools::Page::kParamPageScaleFactor,
578 metadata.page_scale_factor);
579 response->SetDouble(devtools::Page::kParamPageScaleFactorMin,
580 metadata.min_page_scale_factor);
581 response->SetDouble(devtools::Page::kParamPageScaleFactorMax,
582 metadata.max_page_scale_factor);
583 response->SetDouble(devtools::Page::kParamOffsetTop,
584 metadata.location_bar_content_translation.y());
585 response->SetDouble(devtools::Page::kParamOffsetBottom,
586 metadata.overdraw_bottom_height);
588 base::DictionaryValue* viewport = new base::DictionaryValue();
589 viewport->SetDouble(devtools::kParamX, metadata.root_scroll_offset.x());
590 viewport->SetDouble(devtools::kParamY, metadata.root_scroll_offset.y());
591 viewport->SetDouble(devtools::kParamWidth, metadata.viewport_size.width());
592 viewport->SetDouble(devtools::kParamHeight,
593 metadata.viewport_size.height());
594 response->Set(devtools::Page::kParamViewport, viewport);
598 SendAsyncResponse(command->SuccessResponse(response));
600 SendNotification(devtools::Page::screencastFrame::kName, response);
604 // Quota and Usage ------------------------------------------
608 typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)>
611 void QueryUsageAndQuotaCompletedOnIOThread(
612 scoped_ptr<base::DictionaryValue> quota,
613 scoped_ptr<base::DictionaryValue> usage,
614 ResponseCallback callback) {
616 scoped_ptr<base::DictionaryValue> response_data(new base::DictionaryValue);
617 response_data->Set(devtools::Page::queryUsageAndQuota::kResponseQuota,
619 response_data->Set(devtools::Page::queryUsageAndQuota::kResponseUsage,
622 BrowserThread::PostTask(
623 BrowserThread::UI, FROM_HERE,
624 base::Bind(callback, base::Passed(&response_data)));
627 void DidGetHostUsage(
628 base::ListValue* list,
629 const std::string& client_id,
630 const base::Closure& barrier,
632 base::DictionaryValue* usage_item = new base::DictionaryValue;
633 usage_item->SetString(devtools::Page::UsageItem::kItemID, client_id);
634 usage_item->SetDouble(devtools::Page::UsageItem::kItemValue, value);
635 list->Append(usage_item);
639 void DidGetQuotaValue(
640 base::DictionaryValue* dictionary,
641 const std::string& item_name,
642 const base::Closure& barrier,
643 quota::QuotaStatusCode status,
645 if (status == quota::kQuotaStatusOk)
646 dictionary->SetDouble(item_name, value);
650 void DidGetUsageAndQuotaForWebApps(
651 base::DictionaryValue* quota,
652 const std::string& item_name,
653 const base::Closure& barrier,
654 quota::QuotaStatusCode status,
656 int64 quota_in_bytes) {
657 if (status == quota::kQuotaStatusOk)
658 quota->SetDouble(item_name, quota_in_bytes);
662 std::string GetStorageTypeName(quota::StorageType type) {
664 case quota::kStorageTypeTemporary:
665 return devtools::Page::Usage::kItemTemporary;
666 case quota::kStorageTypePersistent:
667 return devtools::Page::Usage::kItemPersistent;
668 case quota::kStorageTypeSyncable:
669 return devtools::Page::Usage::kItemSyncable;
670 case quota::kStorageTypeQuotaNotManaged:
671 case quota::kStorageTypeUnknown:
677 std::string GetQuotaClientName(quota::QuotaClient::ID id) {
679 case quota::QuotaClient::kFileSystem:
680 return devtools::Page::UsageItem::ID::kFilesystem;
681 case quota::QuotaClient::kDatabase:
682 return devtools::Page::UsageItem::ID::kDatabase;
683 case quota::QuotaClient::kAppcache:
684 return devtools::Page::UsageItem::ID::kAppcache;
685 case quota::QuotaClient::kIndexedDatabase:
686 return devtools::Page::UsageItem::ID::kIndexedDatabase;
693 void QueryUsageAndQuotaOnIOThread(
694 scoped_refptr<quota::QuotaManager> quota_manager,
695 const GURL& security_origin,
696 const ResponseCallback& callback) {
697 scoped_ptr<base::DictionaryValue> quota(new base::DictionaryValue);
698 scoped_ptr<base::DictionaryValue> usage(new base::DictionaryValue);
700 static quota::QuotaClient::ID kQuotaClients[] = {
701 quota::QuotaClient::kFileSystem,
702 quota::QuotaClient::kDatabase,
703 quota::QuotaClient::kAppcache,
704 quota::QuotaClient::kIndexedDatabase
707 static const size_t kStorageTypeCount = quota::kStorageTypeUnknown;
708 std::map<quota::StorageType, base::ListValue*> storage_type_lists;
710 for (size_t i = 0; i != kStorageTypeCount; i++) {
711 const quota::StorageType type = static_cast<quota::StorageType>(i);
712 if (type == quota::kStorageTypeQuotaNotManaged)
714 storage_type_lists[type] = new base::ListValue;
715 usage->Set(GetStorageTypeName(type), storage_type_lists[type]);
718 const int kExpectedResults =
719 2 + arraysize(kQuotaClients) * storage_type_lists.size();
720 base::DictionaryValue* quota_raw_ptr = quota.get();
722 // Takes ownership on usage and quota.
723 base::Closure barrier = BarrierClosure(
725 base::Bind(&QueryUsageAndQuotaCompletedOnIOThread,
726 base::Passed("a),
727 base::Passed(&usage),
729 std::string host = net::GetHostOrSpecFromURL(security_origin);
731 quota_manager->GetUsageAndQuotaForWebApps(
733 quota::kStorageTypeTemporary,
734 base::Bind(&DidGetUsageAndQuotaForWebApps, quota_raw_ptr,
735 std::string(devtools::Page::Quota::kItemTemporary), barrier));
737 quota_manager->GetPersistentHostQuota(
739 base::Bind(&DidGetQuotaValue, quota_raw_ptr,
740 std::string(devtools::Page::Quota::kItemPersistent),
743 for (size_t i = 0; i != arraysize(kQuotaClients); i++) {
744 std::map<quota::StorageType, base::ListValue*>::const_iterator iter;
745 for (iter = storage_type_lists.begin();
746 iter != storage_type_lists.end(); ++iter) {
747 const quota::StorageType type = (*iter).first;
748 if (!quota_manager->IsTrackingHostUsage(type, kQuotaClients[i])) {
752 quota_manager->GetHostUsage(
753 host, type, kQuotaClients[i],
754 base::Bind(&DidGetHostUsage, (*iter).second,
755 GetQuotaClientName(kQuotaClients[i]),
763 scoped_refptr<DevToolsProtocol::Response>
764 RendererOverridesHandler::PageQueryUsageAndQuota(
765 scoped_refptr<DevToolsProtocol::Command> command) {
766 base::DictionaryValue* params = command->params();
767 std::string security_origin;
768 if (!params || !params->GetString(
769 devtools::Page::queryUsageAndQuota::kParamSecurityOrigin,
771 return command->InvalidParamResponse(
772 devtools::Page::queryUsageAndQuota::kParamSecurityOrigin);
775 ResponseCallback callback = base::Bind(
776 &RendererOverridesHandler::PageQueryUsageAndQuotaCompleted,
777 weak_factory_.GetWeakPtr(),
780 scoped_refptr<quota::QuotaManager> quota_manager =
781 agent_->GetRenderViewHost()->GetProcess()->
782 GetStoragePartition()->GetQuotaManager();
784 BrowserThread::PostTask(
785 BrowserThread::IO, FROM_HERE,
787 &QueryUsageAndQuotaOnIOThread,
789 GURL(security_origin),
792 return command->AsyncResponsePromise();
795 void RendererOverridesHandler::PageQueryUsageAndQuotaCompleted(
796 scoped_refptr<DevToolsProtocol::Command> command,
797 scoped_ptr<base::DictionaryValue> response_data) {
798 SendAsyncResponse(command->SuccessResponse(response_data.release()));
801 void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) {
803 capture_retry_count_ = kCaptureRetryLimit;
804 base::DictionaryValue* params = new base::DictionaryValue();
806 devtools::Page::screencastVisibilityChanged::kParamVisible, visible);
808 devtools::Page::screencastVisibilityChanged::kName, params);
811 // Input agent handlers ------------------------------------------------------
813 scoped_refptr<DevToolsProtocol::Response>
814 RendererOverridesHandler::InputDispatchMouseEvent(
815 scoped_refptr<DevToolsProtocol::Command> command) {
816 base::DictionaryValue* params = command->params();
820 bool device_space = false;
821 if (!params->GetBoolean(devtools::Input::kParamDeviceSpace,
827 RenderViewHost* host = agent_->GetRenderViewHost();
828 WebKit::WebMouseEvent mouse_event;
829 ParseGenericInputParams(params, &mouse_event);
832 if (params->GetString(devtools::Input::kParamType,
834 if (type == "mousePressed")
835 mouse_event.type = WebInputEvent::MouseDown;
836 else if (type == "mouseReleased")
837 mouse_event.type = WebInputEvent::MouseUp;
838 else if (type == "mouseMoved")
839 mouse_event.type = WebInputEvent::MouseMove;
846 if (!params->GetInteger(devtools::kParamX, &mouse_event.x) ||
847 !params->GetInteger(devtools::kParamY, &mouse_event.y)) {
851 mouse_event.windowX = mouse_event.x;
852 mouse_event.windowY = mouse_event.y;
853 mouse_event.globalX = mouse_event.x;
854 mouse_event.globalY = mouse_event.y;
856 params->GetInteger(devtools::Input::dispatchMouseEvent::kParamClickCount,
857 &mouse_event.clickCount);
860 if (!params->GetString(devtools::Input::dispatchMouseEvent::kParamButton,
865 if (button == "none") {
866 mouse_event.button = WebMouseEvent::ButtonNone;
867 } else if (button == "left") {
868 mouse_event.button = WebMouseEvent::ButtonLeft;
869 mouse_event.modifiers |= WebInputEvent::LeftButtonDown;
870 } else if (button == "middle") {
871 mouse_event.button = WebMouseEvent::ButtonMiddle;
872 mouse_event.modifiers |= WebInputEvent::MiddleButtonDown;
873 } else if (button == "right") {
874 mouse_event.button = WebMouseEvent::ButtonRight;
875 mouse_event.modifiers |= WebInputEvent::RightButtonDown;
880 host->ForwardMouseEvent(mouse_event);
881 return command->SuccessResponse(NULL);
884 scoped_refptr<DevToolsProtocol::Response>
885 RendererOverridesHandler::InputDispatchGestureEvent(
886 scoped_refptr<DevToolsProtocol::Command> command) {
887 base::DictionaryValue* params = command->params();
891 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
892 agent_->GetRenderViewHost());
893 WebKit::WebGestureEvent event;
894 ParseGenericInputParams(params, &event);
897 if (params->GetString(devtools::Input::kParamType,
899 if (type == "scrollBegin")
900 event.type = WebInputEvent::GestureScrollBegin;
901 else if (type == "scrollUpdate")
902 event.type = WebInputEvent::GestureScrollUpdate;
903 else if (type == "scrollEnd")
904 event.type = WebInputEvent::GestureScrollEnd;
905 else if (type == "tapDown")
906 event.type = WebInputEvent::GestureTapDown;
907 else if (type == "tap")
908 event.type = WebInputEvent::GestureTap;
909 else if (type == "pinchBegin")
910 event.type = WebInputEvent::GesturePinchBegin;
911 else if (type == "pinchUpdate")
912 event.type = WebInputEvent::GesturePinchUpdate;
913 else if (type == "pinchEnd")
914 event.type = WebInputEvent::GesturePinchEnd;
921 if (!params->GetInteger(devtools::kParamX, &event.x) ||
922 !params->GetInteger(devtools::kParamY, &event.y)) {
925 event.globalX = event.x;
926 event.globalY = event.y;
928 if (type == "scrollUpdate") {
931 if (!params->GetInteger(
932 devtools::Input::dispatchGestureEvent::kParamDeltaX, &dx) ||
934 devtools::Input::dispatchGestureEvent::kParamDeltaY, &dy)) {
937 event.data.scrollUpdate.deltaX = dx;
938 event.data.scrollUpdate.deltaY = dy;
941 if (type == "pinchUpdate") {
943 if (!params->GetDouble(
944 devtools::Input::dispatchGestureEvent::kParamPinchScale,
948 event.data.pinchUpdate.scale = static_cast<float>(scale);
951 host->ForwardGestureEvent(event);
952 return command->SuccessResponse(NULL);
955 } // namespace content