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/thread_task_runner_handle.h"
17 #include "base/values.h"
18 #include "content/browser/child_process_security_policy_impl.h"
19 #include "content/browser/devtools/devtools_protocol_constants.h"
20 #include "content/browser/devtools/devtools_tracing_handler.h"
21 #include "content/browser/renderer_host/dip_util.h"
22 #include "content/browser/renderer_host/render_view_host_delegate.h"
23 #include "content/browser/renderer_host/render_view_host_impl.h"
24 #include "content/common/view_messages.h"
25 #include "content/port/browser/render_widget_host_view_port.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/devtools_agent_host.h"
28 #include "content/public/browser/javascript_dialog_manager.h"
29 #include "content/public/browser/navigation_controller.h"
30 #include "content/public/browser/navigation_entry.h"
31 #include "content/public/browser/render_process_host.h"
32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/render_widget_host_view.h"
34 #include "content/public/browser/storage_partition.h"
35 #include "content/public/browser/web_contents.h"
36 #include "content/public/browser/web_contents_delegate.h"
37 #include "content/public/common/content_client.h"
38 #include "content/public/common/page_transition_types.h"
39 #include "content/public/common/referrer.h"
40 #include "ipc/ipc_sender.h"
41 #include "net/base/net_util.h"
42 #include "third_party/WebKit/public/web/WebInputEvent.h"
43 #include "ui/gfx/codec/jpeg_codec.h"
44 #include "ui/gfx/codec/png_codec.h"
45 #include "ui/gfx/size_conversions.h"
46 #include "ui/snapshot/snapshot.h"
48 #include "webkit/browser/quota/quota_manager.h"
50 using blink::WebGestureEvent;
51 using blink::WebInputEvent;
52 using blink::WebMouseEvent;
58 static const char kPng[] = "png";
59 static const char kJpeg[] = "jpeg";
60 static int kDefaultScreenshotQuality = 80;
61 static int kFrameRateThresholdMs = 100;
62 static int kCaptureRetryLimit = 2;
64 void ParseGenericInputParams(base::DictionaryValue* params,
65 WebInputEvent* event) {
67 if (params->GetInteger(devtools::Input::dispatchMouseEvent::kParamModifiers,
70 event->modifiers |= WebInputEvent::AltKey;
72 event->modifiers |= WebInputEvent::ControlKey;
74 event->modifiers |= WebInputEvent::MetaKey;
76 event->modifiers |= WebInputEvent::ShiftKey;
79 params->GetDouble(devtools::Input::dispatchMouseEvent::kParamTimestamp,
80 &event->timeStampSeconds);
85 RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
87 capture_retry_count_(0),
89 RegisterCommandHandler(
90 devtools::DOM::setFileInputFiles::kName,
92 &RendererOverridesHandler::GrantPermissionsForSetFileInputFiles,
93 base::Unretained(this)));
94 RegisterCommandHandler(
95 devtools::Page::disable::kName,
97 &RendererOverridesHandler::PageDisable, base::Unretained(this)));
98 RegisterCommandHandler(
99 devtools::Page::handleJavaScriptDialog::kName,
101 &RendererOverridesHandler::PageHandleJavaScriptDialog,
102 base::Unretained(this)));
103 RegisterCommandHandler(
104 devtools::Page::navigate::kName,
106 &RendererOverridesHandler::PageNavigate,
107 base::Unretained(this)));
108 RegisterCommandHandler(
109 devtools::Page::reload::kName,
111 &RendererOverridesHandler::PageReload,
112 base::Unretained(this)));
113 RegisterCommandHandler(
114 devtools::Page::getNavigationHistory::kName,
116 &RendererOverridesHandler::PageGetNavigationHistory,
117 base::Unretained(this)));
118 RegisterCommandHandler(
119 devtools::Page::navigateToHistoryEntry::kName,
121 &RendererOverridesHandler::PageNavigateToHistoryEntry,
122 base::Unretained(this)));
123 RegisterCommandHandler(
124 devtools::Page::captureScreenshot::kName,
126 &RendererOverridesHandler::PageCaptureScreenshot,
127 base::Unretained(this)));
128 RegisterCommandHandler(
129 devtools::Page::canScreencast::kName,
131 &RendererOverridesHandler::PageCanScreencast,
132 base::Unretained(this)));
133 RegisterCommandHandler(
134 devtools::Page::startScreencast::kName,
136 &RendererOverridesHandler::PageStartScreencast,
137 base::Unretained(this)));
138 RegisterCommandHandler(
139 devtools::Page::stopScreencast::kName,
141 &RendererOverridesHandler::PageStopScreencast,
142 base::Unretained(this)));
143 RegisterCommandHandler(
144 devtools::Page::queryUsageAndQuota::kName,
146 &RendererOverridesHandler::PageQueryUsageAndQuota,
147 base::Unretained(this)));
148 RegisterCommandHandler(
149 devtools::Input::dispatchMouseEvent::kName,
151 &RendererOverridesHandler::InputDispatchMouseEvent,
152 base::Unretained(this)));
153 RegisterCommandHandler(
154 devtools::Input::dispatchGestureEvent::kName,
156 &RendererOverridesHandler::InputDispatchGestureEvent,
157 base::Unretained(this)));
160 RendererOverridesHandler::~RendererOverridesHandler() {}
162 void RendererOverridesHandler::OnClientDetached() {
163 screencast_command_ = NULL;
166 void RendererOverridesHandler::OnSwapCompositorFrame(
167 const cc::CompositorFrameMetadata& frame_metadata) {
168 last_compositor_frame_metadata_ = frame_metadata;
170 if (screencast_command_)
171 InnerSwapCompositorFrame();
174 void RendererOverridesHandler::OnVisibilityChanged(bool visible) {
175 if (!screencast_command_)
177 NotifyScreencastVisibility(visible);
180 void RendererOverridesHandler::InnerSwapCompositorFrame() {
181 if ((base::TimeTicks::Now() - last_frame_time_).InMilliseconds() <
182 kFrameRateThresholdMs) {
186 RenderViewHost* host = agent_->GetRenderViewHost();
187 if (!host->GetView())
190 last_frame_time_ = base::TimeTicks::Now();
192 int quality = kDefaultScreenshotQuality;
194 ParseCaptureParameters(screencast_command_.get(), &format, &quality, &scale);
196 RenderWidgetHostViewPort* view_port =
197 RenderWidgetHostViewPort::FromRWHV(host->GetView());
199 gfx::Rect view_bounds = host->GetView()->GetViewBounds();
200 gfx::Size snapshot_size = gfx::ToFlooredSize(
201 gfx::ScaleSize(view_bounds.size(), scale));
203 view_port->CopyFromCompositingSurface(
204 view_bounds, snapshot_size,
205 base::Bind(&RendererOverridesHandler::ScreencastFrameCaptured,
206 weak_factory_.GetWeakPtr(),
207 format, quality, last_compositor_frame_metadata_),
208 SkBitmap::kARGB_8888_Config);
211 void RendererOverridesHandler::ParseCaptureParameters(
212 DevToolsProtocol::Command* command,
216 *quality = kDefaultScreenshotQuality;
218 double max_width = -1;
219 double max_height = -1;
220 base::DictionaryValue* params = command->params();
222 params->GetString(devtools::Page::startScreencast::kParamFormat,
224 params->GetInteger(devtools::Page::startScreencast::kParamQuality,
226 params->GetDouble(devtools::Page::startScreencast::kParamMaxWidth,
228 params->GetDouble(devtools::Page::startScreencast::kParamMaxHeight,
232 RenderViewHost* host = agent_->GetRenderViewHost();
233 CHECK(host->GetView());
234 gfx::Rect view_bounds = host->GetView()->GetViewBounds();
236 *scale = std::min(*scale, max_width / view_bounds.width());
238 *scale = std::min(*scale, max_height / view_bounds.height());
242 if (*quality < 0 || *quality > 100)
243 *quality = kDefaultScreenshotQuality;
250 base::DictionaryValue* RendererOverridesHandler::CreateScreenshotResponse(
251 const std::vector<unsigned char>& png_data) {
252 std::string base_64_data;
254 base::StringPiece(reinterpret_cast<const char*>(&png_data[0]),
258 base::DictionaryValue* response = new base::DictionaryValue();
260 devtools::Page::captureScreenshot::kResponseData, base_64_data);
264 // DOM agent handlers --------------------------------------------------------
266 scoped_refptr<DevToolsProtocol::Response>
267 RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
268 scoped_refptr<DevToolsProtocol::Command> command) {
269 base::DictionaryValue* params = command->params();
270 base::ListValue* file_list = NULL;
272 devtools::DOM::setFileInputFiles::kParamFiles;
273 if (!params || !params->GetList(param, &file_list))
274 return command->InvalidParamResponse(param);
275 RenderViewHost* host = agent_->GetRenderViewHost();
279 for (size_t i = 0; i < file_list->GetSize(); ++i) {
280 base::FilePath::StringType file;
281 if (!file_list->GetString(i, &file))
282 return command->InvalidParamResponse(param);
283 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
284 host->GetProcess()->GetID(), base::FilePath(file));
290 // Page agent handlers -------------------------------------------------------
292 scoped_refptr<DevToolsProtocol::Response>
293 RendererOverridesHandler::PageDisable(
294 scoped_refptr<DevToolsProtocol::Command> command) {
295 screencast_command_ = NULL;
299 scoped_refptr<DevToolsProtocol::Response>
300 RendererOverridesHandler::PageHandleJavaScriptDialog(
301 scoped_refptr<DevToolsProtocol::Command> command) {
302 base::DictionaryValue* params = command->params();
303 const char* paramAccept =
304 devtools::Page::handleJavaScriptDialog::kParamAccept;
306 if (!params || !params->GetBoolean(paramAccept, &accept))
307 return command->InvalidParamResponse(paramAccept);
308 base::string16 prompt_override;
309 base::string16* prompt_override_ptr = &prompt_override;
310 if (!params || !params->GetString(
311 devtools::Page::handleJavaScriptDialog::kParamPromptText,
312 prompt_override_ptr)) {
313 prompt_override_ptr = NULL;
316 RenderViewHost* host = agent_->GetRenderViewHost();
318 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
320 JavaScriptDialogManager* manager =
321 web_contents->GetDelegate()->GetJavaScriptDialogManager();
322 if (manager && manager->HandleJavaScriptDialog(
323 web_contents, accept, prompt_override_ptr)) {
324 return command->SuccessResponse(new base::DictionaryValue());
328 return command->InternalErrorResponse("No JavaScript dialog to handle");
331 scoped_refptr<DevToolsProtocol::Response>
332 RendererOverridesHandler::PageNavigate(
333 scoped_refptr<DevToolsProtocol::Command> command) {
334 base::DictionaryValue* params = command->params();
336 const char* param = devtools::Page::navigate::kParamUrl;
337 if (!params || !params->GetString(param, &url))
338 return command->InvalidParamResponse(param);
340 if (!gurl.is_valid()) {
341 return command->InternalErrorResponse("Cannot navigate to invalid URL");
343 RenderViewHost* host = agent_->GetRenderViewHost();
345 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
347 web_contents->GetController()
348 .LoadURL(gurl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
349 return command->SuccessResponse(new base::DictionaryValue());
352 return command->InternalErrorResponse("No WebContents to navigate");
355 scoped_refptr<DevToolsProtocol::Response>
356 RendererOverridesHandler::PageReload(
357 scoped_refptr<DevToolsProtocol::Command> command) {
358 RenderViewHost* host = agent_->GetRenderViewHost();
360 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
362 // Override only if it is crashed.
363 if (!web_contents->IsCrashed())
366 web_contents->GetController().Reload(false);
367 return command->SuccessResponse(NULL);
370 return command->InternalErrorResponse("No WebContents to reload");
373 scoped_refptr<DevToolsProtocol::Response>
374 RendererOverridesHandler::PageGetNavigationHistory(
375 scoped_refptr<DevToolsProtocol::Command> command) {
376 RenderViewHost* host = agent_->GetRenderViewHost();
378 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
380 base::DictionaryValue* result = new base::DictionaryValue();
381 NavigationController& controller = web_contents->GetController();
383 devtools::Page::getNavigationHistory::kResponseCurrentIndex,
384 controller.GetCurrentEntryIndex());
385 base::ListValue* entries = new base::ListValue();
386 for (int i = 0; i != controller.GetEntryCount(); ++i) {
387 const NavigationEntry* entry = controller.GetEntryAtIndex(i);
388 base::DictionaryValue* entry_value = new base::DictionaryValue();
389 entry_value->SetInteger(
390 devtools::Page::NavigationEntry::kParamId,
391 entry->GetUniqueID());
392 entry_value->SetString(
393 devtools::Page::NavigationEntry::kParamUrl,
394 entry->GetURL().spec());
395 entry_value->SetString(
396 devtools::Page::NavigationEntry::kParamTitle,
398 entries->Append(entry_value);
401 devtools::Page::getNavigationHistory::kResponseEntries,
403 return command->SuccessResponse(result);
406 return command->InternalErrorResponse("No WebContents to navigate");
409 scoped_refptr<DevToolsProtocol::Response>
410 RendererOverridesHandler::PageNavigateToHistoryEntry(
411 scoped_refptr<DevToolsProtocol::Command> command) {
414 base::DictionaryValue* params = command->params();
415 const char* param = devtools::Page::navigateToHistoryEntry::kParamEntryId;
416 if (!params || !params->GetInteger(param, &entry_id)) {
417 return command->InvalidParamResponse(param);
420 RenderViewHost* host = agent_->GetRenderViewHost();
422 WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
424 NavigationController& controller = web_contents->GetController();
425 for (int i = 0; i != controller.GetEntryCount(); ++i) {
426 if (controller.GetEntryAtIndex(i)->GetUniqueID() == entry_id) {
427 controller.GoToIndex(i);
428 return command->SuccessResponse(new base::DictionaryValue());
431 return command->InvalidParamResponse(param);
434 return command->InternalErrorResponse("No WebContents to navigate");
437 scoped_refptr<DevToolsProtocol::Response>
438 RendererOverridesHandler::PageCaptureScreenshot(
439 scoped_refptr<DevToolsProtocol::Command> command) {
440 RenderViewHost* host = agent_->GetRenderViewHost();
441 if (!host->GetView())
442 return command->InternalErrorResponse("Unable to access the view");
444 gfx::Rect view_bounds = host->GetView()->GetViewBounds();
445 gfx::Rect snapshot_bounds(view_bounds.size());
446 gfx::Size snapshot_size = snapshot_bounds.size();
448 std::vector<unsigned char> png_data;
449 if (ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
453 return command->SuccessResponse(CreateScreenshotResponse(png_data));
455 return command->InternalErrorResponse("Unable to capture screenshot");
458 ui::GrabViewSnapshotAsync(
459 host->GetView()->GetNativeView(),
461 base::ThreadTaskRunnerHandle::Get(),
462 base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
463 weak_factory_.GetWeakPtr(), command));
464 return command->AsyncResponsePromise();
467 void RendererOverridesHandler::ScreenshotCaptured(
468 scoped_refptr<DevToolsProtocol::Command> command,
469 scoped_refptr<base::RefCountedBytes> png_data) {
472 command->SuccessResponse(CreateScreenshotResponse(png_data->data())));
475 command->InternalErrorResponse("Unable to capture screenshot"));
479 scoped_refptr<DevToolsProtocol::Response>
480 RendererOverridesHandler::PageCanScreencast(
481 scoped_refptr<DevToolsProtocol::Command> command) {
482 base::DictionaryValue* result = new base::DictionaryValue();
483 #if defined(OS_ANDROID)
484 result->SetBoolean(devtools::kResult, true);
486 result->SetBoolean(devtools::kResult, false);
487 #endif // defined(OS_ANDROID)
488 return command->SuccessResponse(result);
491 scoped_refptr<DevToolsProtocol::Response>
492 RendererOverridesHandler::PageStartScreencast(
493 scoped_refptr<DevToolsProtocol::Command> command) {
494 screencast_command_ = command;
495 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
496 agent_->GetRenderViewHost());
497 bool visible = !host->is_hidden();
498 NotifyScreencastVisibility(visible);
500 InnerSwapCompositorFrame();
501 return command->SuccessResponse(NULL);
504 scoped_refptr<DevToolsProtocol::Response>
505 RendererOverridesHandler::PageStopScreencast(
506 scoped_refptr<DevToolsProtocol::Command> command) {
507 last_frame_time_ = base::TimeTicks();
508 screencast_command_ = NULL;
509 return command->SuccessResponse(NULL);
512 void RendererOverridesHandler::ScreencastFrameCaptured(
513 const std::string& format,
515 const cc::CompositorFrameMetadata& metadata,
517 const SkBitmap& bitmap) {
519 if (capture_retry_count_) {
520 --capture_retry_count_;
521 base::MessageLoop::current()->PostDelayedTask(
523 base::Bind(&RendererOverridesHandler::InnerSwapCompositorFrame,
524 weak_factory_.GetWeakPtr()),
525 base::TimeDelta::FromMilliseconds(kFrameRateThresholdMs));
530 std::vector<unsigned char> data;
531 SkAutoLockPixels lock_image(bitmap);
533 if (format == kPng) {
534 encoded = gfx::PNGCodec::Encode(
535 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
536 gfx::PNGCodec::FORMAT_SkBitmap,
537 gfx::Size(bitmap.width(), bitmap.height()),
538 bitmap.width() * bitmap.bytesPerPixel(),
539 false, std::vector<gfx::PNGCodec::Comment>(), &data);
540 } else if (format == kJpeg) {
541 encoded = gfx::JPEGCodec::Encode(
542 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
543 gfx::JPEGCodec::FORMAT_SkBitmap,
546 bitmap.width() * bitmap.bytesPerPixel(),
555 std::string base_64_data;
557 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()),
560 base::DictionaryValue* response = new base::DictionaryValue();
561 response->SetString(devtools::Page::screencastFrame::kParamData,
564 // Consider metadata empty in case it has no device scale factor.
565 if (metadata.device_scale_factor != 0) {
566 base::DictionaryValue* response_metadata = new base::DictionaryValue();
568 response_metadata->SetDouble(
569 devtools::Page::ScreencastFrameMetadata::kParamDeviceScaleFactor,
570 metadata.device_scale_factor);
571 response_metadata->SetDouble(
572 devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactor,
573 metadata.page_scale_factor);
574 response_metadata->SetDouble(
575 devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMin,
576 metadata.min_page_scale_factor);
577 response_metadata->SetDouble(
578 devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMax,
579 metadata.max_page_scale_factor);
580 response_metadata->SetDouble(
581 devtools::Page::ScreencastFrameMetadata::kParamOffsetTop,
582 metadata.location_bar_content_translation.y());
583 response_metadata->SetDouble(
584 devtools::Page::ScreencastFrameMetadata::kParamOffsetBottom,
585 metadata.overdraw_bottom_height);
587 base::DictionaryValue* viewport = new base::DictionaryValue();
588 viewport->SetDouble(devtools::DOM::Rect::kParamX,
589 metadata.root_scroll_offset.x());
590 viewport->SetDouble(devtools::DOM::Rect::kParamY,
591 metadata.root_scroll_offset.y());
592 viewport->SetDouble(devtools::DOM::Rect::kParamWidth,
593 metadata.viewport_size.width());
594 viewport->SetDouble(devtools::DOM::Rect::kParamHeight,
595 metadata.viewport_size.height());
596 response_metadata->Set(
597 devtools::Page::ScreencastFrameMetadata::kParamViewport, viewport);
599 response->Set(devtools::Page::screencastFrame::kParamMetadata,
603 SendNotification(devtools::Page::screencastFrame::kName, response);
606 // Quota and Usage ------------------------------------------
610 typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)>
613 void QueryUsageAndQuotaCompletedOnIOThread(
614 scoped_ptr<base::DictionaryValue> quota,
615 scoped_ptr<base::DictionaryValue> usage,
616 ResponseCallback callback) {
618 scoped_ptr<base::DictionaryValue> response_data(new base::DictionaryValue);
619 response_data->Set(devtools::Page::queryUsageAndQuota::kResponseQuota,
621 response_data->Set(devtools::Page::queryUsageAndQuota::kResponseUsage,
624 BrowserThread::PostTask(
625 BrowserThread::UI, FROM_HERE,
626 base::Bind(callback, base::Passed(&response_data)));
629 void DidGetHostUsage(
630 base::ListValue* list,
631 const std::string& client_id,
632 const base::Closure& barrier,
634 base::DictionaryValue* usage_item = new base::DictionaryValue;
635 usage_item->SetString(devtools::Page::UsageItem::kParamId, client_id);
636 usage_item->SetDouble(devtools::Page::UsageItem::kParamValue, value);
637 list->Append(usage_item);
641 void DidGetQuotaValue(
642 base::DictionaryValue* dictionary,
643 const std::string& item_name,
644 const base::Closure& barrier,
645 quota::QuotaStatusCode status,
647 if (status == quota::kQuotaStatusOk)
648 dictionary->SetDouble(item_name, value);
652 void DidGetUsageAndQuotaForWebApps(
653 base::DictionaryValue* quota,
654 const std::string& item_name,
655 const base::Closure& barrier,
656 quota::QuotaStatusCode status,
658 int64 quota_in_bytes) {
659 if (status == quota::kQuotaStatusOk)
660 quota->SetDouble(item_name, quota_in_bytes);
664 std::string GetStorageTypeName(quota::StorageType type) {
666 case quota::kStorageTypeTemporary:
667 return devtools::Page::Usage::kParamTemporary;
668 case quota::kStorageTypePersistent:
669 return devtools::Page::Usage::kParamPersistent;
670 case quota::kStorageTypeSyncable:
671 return devtools::Page::Usage::kParamSyncable;
672 case quota::kStorageTypeQuotaNotManaged:
673 case quota::kStorageTypeUnknown:
679 std::string GetQuotaClientName(quota::QuotaClient::ID id) {
681 case quota::QuotaClient::kFileSystem:
682 return devtools::Page::UsageItem::Id::kEnumFilesystem;
683 case quota::QuotaClient::kDatabase:
684 return devtools::Page::UsageItem::Id::kEnumDatabase;
685 case quota::QuotaClient::kAppcache:
686 return devtools::Page::UsageItem::Id::kEnumAppcache;
687 case quota::QuotaClient::kIndexedDatabase:
688 return devtools::Page::UsageItem::Id::kEnumIndexeddatabase;
695 void QueryUsageAndQuotaOnIOThread(
696 scoped_refptr<quota::QuotaManager> quota_manager,
697 const GURL& security_origin,
698 const ResponseCallback& callback) {
699 scoped_ptr<base::DictionaryValue> quota(new base::DictionaryValue);
700 scoped_ptr<base::DictionaryValue> usage(new base::DictionaryValue);
702 static quota::QuotaClient::ID kQuotaClients[] = {
703 quota::QuotaClient::kFileSystem,
704 quota::QuotaClient::kDatabase,
705 quota::QuotaClient::kAppcache,
706 quota::QuotaClient::kIndexedDatabase
709 static const size_t kStorageTypeCount = quota::kStorageTypeUnknown;
710 std::map<quota::StorageType, base::ListValue*> storage_type_lists;
712 for (size_t i = 0; i != kStorageTypeCount; i++) {
713 const quota::StorageType type = static_cast<quota::StorageType>(i);
714 if (type == quota::kStorageTypeQuotaNotManaged)
716 storage_type_lists[type] = new base::ListValue;
717 usage->Set(GetStorageTypeName(type), storage_type_lists[type]);
720 const int kExpectedResults =
721 2 + arraysize(kQuotaClients) * storage_type_lists.size();
722 base::DictionaryValue* quota_raw_ptr = quota.get();
724 // Takes ownership on usage and quota.
725 base::Closure barrier = BarrierClosure(
727 base::Bind(&QueryUsageAndQuotaCompletedOnIOThread,
728 base::Passed("a),
729 base::Passed(&usage),
731 std::string host = net::GetHostOrSpecFromURL(security_origin);
733 quota_manager->GetUsageAndQuotaForWebApps(
735 quota::kStorageTypeTemporary,
736 base::Bind(&DidGetUsageAndQuotaForWebApps, quota_raw_ptr,
737 std::string(devtools::Page::Quota::kParamTemporary), barrier));
739 quota_manager->GetPersistentHostQuota(
741 base::Bind(&DidGetQuotaValue, quota_raw_ptr,
742 std::string(devtools::Page::Quota::kParamPersistent),
745 for (size_t i = 0; i != arraysize(kQuotaClients); i++) {
746 std::map<quota::StorageType, base::ListValue*>::const_iterator iter;
747 for (iter = storage_type_lists.begin();
748 iter != storage_type_lists.end(); ++iter) {
749 const quota::StorageType type = (*iter).first;
750 if (!quota_manager->IsTrackingHostUsage(type, kQuotaClients[i])) {
754 quota_manager->GetHostUsage(
755 host, type, kQuotaClients[i],
756 base::Bind(&DidGetHostUsage, (*iter).second,
757 GetQuotaClientName(kQuotaClients[i]),
765 scoped_refptr<DevToolsProtocol::Response>
766 RendererOverridesHandler::PageQueryUsageAndQuota(
767 scoped_refptr<DevToolsProtocol::Command> command) {
768 base::DictionaryValue* params = command->params();
769 std::string security_origin;
770 if (!params || !params->GetString(
771 devtools::Page::queryUsageAndQuota::kParamSecurityOrigin,
773 return command->InvalidParamResponse(
774 devtools::Page::queryUsageAndQuota::kParamSecurityOrigin);
777 ResponseCallback callback = base::Bind(
778 &RendererOverridesHandler::PageQueryUsageAndQuotaCompleted,
779 weak_factory_.GetWeakPtr(),
782 scoped_refptr<quota::QuotaManager> quota_manager =
783 agent_->GetRenderViewHost()->GetProcess()->
784 GetStoragePartition()->GetQuotaManager();
786 BrowserThread::PostTask(
787 BrowserThread::IO, FROM_HERE,
789 &QueryUsageAndQuotaOnIOThread,
791 GURL(security_origin),
794 return command->AsyncResponsePromise();
797 void RendererOverridesHandler::PageQueryUsageAndQuotaCompleted(
798 scoped_refptr<DevToolsProtocol::Command> command,
799 scoped_ptr<base::DictionaryValue> response_data) {
800 SendAsyncResponse(command->SuccessResponse(response_data.release()));
803 void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) {
805 capture_retry_count_ = kCaptureRetryLimit;
806 base::DictionaryValue* params = new base::DictionaryValue();
808 devtools::Page::screencastVisibilityChanged::kParamVisible, visible);
810 devtools::Page::screencastVisibilityChanged::kName, params);
813 // Input agent handlers ------------------------------------------------------
815 scoped_refptr<DevToolsProtocol::Response>
816 RendererOverridesHandler::InputDispatchMouseEvent(
817 scoped_refptr<DevToolsProtocol::Command> command) {
818 base::DictionaryValue* params = command->params();
822 bool device_space = false;
823 if (!params->GetBoolean(
824 devtools::Input::dispatchMouseEvent::kParamDeviceSpace,
830 RenderViewHost* host = agent_->GetRenderViewHost();
831 blink::WebMouseEvent mouse_event;
832 ParseGenericInputParams(params, &mouse_event);
835 if (params->GetString(devtools::Input::dispatchMouseEvent::kParamType,
838 devtools::Input::dispatchMouseEvent::Type::kEnumMousePressed)
839 mouse_event.type = WebInputEvent::MouseDown;
841 devtools::Input::dispatchMouseEvent::Type::kEnumMouseReleased)
842 mouse_event.type = WebInputEvent::MouseUp;
844 devtools::Input::dispatchMouseEvent::Type::kEnumMouseMoved)
845 mouse_event.type = WebInputEvent::MouseMove;
852 if (!params->GetInteger(devtools::Input::dispatchMouseEvent::kParamX,
854 !params->GetInteger(devtools::Input::dispatchMouseEvent::kParamY,
859 mouse_event.windowX = mouse_event.x;
860 mouse_event.windowY = mouse_event.y;
861 mouse_event.globalX = mouse_event.x;
862 mouse_event.globalY = mouse_event.y;
864 params->GetInteger(devtools::Input::dispatchMouseEvent::kParamClickCount,
865 &mouse_event.clickCount);
868 if (!params->GetString(devtools::Input::dispatchMouseEvent::kParamButton,
873 if (button == "none") {
874 mouse_event.button = WebMouseEvent::ButtonNone;
875 } else if (button == "left") {
876 mouse_event.button = WebMouseEvent::ButtonLeft;
877 mouse_event.modifiers |= WebInputEvent::LeftButtonDown;
878 } else if (button == "middle") {
879 mouse_event.button = WebMouseEvent::ButtonMiddle;
880 mouse_event.modifiers |= WebInputEvent::MiddleButtonDown;
881 } else if (button == "right") {
882 mouse_event.button = WebMouseEvent::ButtonRight;
883 mouse_event.modifiers |= WebInputEvent::RightButtonDown;
888 host->ForwardMouseEvent(mouse_event);
889 return command->SuccessResponse(NULL);
892 scoped_refptr<DevToolsProtocol::Response>
893 RendererOverridesHandler::InputDispatchGestureEvent(
894 scoped_refptr<DevToolsProtocol::Command> command) {
895 base::DictionaryValue* params = command->params();
899 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
900 agent_->GetRenderViewHost());
901 blink::WebGestureEvent event;
902 ParseGenericInputParams(params, &event);
903 event.sourceDevice = WebGestureEvent::Touchscreen;
906 if (params->GetString(devtools::Input::dispatchGestureEvent::kParamType,
909 devtools::Input::dispatchGestureEvent::Type::kEnumScrollBegin)
910 event.type = WebInputEvent::GestureScrollBegin;
912 devtools::Input::dispatchGestureEvent::Type::kEnumScrollUpdate)
913 event.type = WebInputEvent::GestureScrollUpdate;
915 devtools::Input::dispatchGestureEvent::Type::kEnumScrollEnd)
916 event.type = WebInputEvent::GestureScrollEnd;
918 devtools::Input::dispatchGestureEvent::Type::kEnumTapDown)
919 event.type = WebInputEvent::GestureTapDown;
921 devtools::Input::dispatchGestureEvent::Type::kEnumTap)
922 event.type = WebInputEvent::GestureTap;
924 devtools::Input::dispatchGestureEvent::Type::kEnumPinchBegin)
925 event.type = WebInputEvent::GesturePinchBegin;
927 devtools::Input::dispatchGestureEvent::Type::kEnumPinchUpdate)
928 event.type = WebInputEvent::GesturePinchUpdate;
930 devtools::Input::dispatchGestureEvent::Type::kEnumPinchEnd)
931 event.type = WebInputEvent::GesturePinchEnd;
938 if (!params->GetInteger(devtools::Input::dispatchGestureEvent::kParamX,
940 !params->GetInteger(devtools::Input::dispatchGestureEvent::kParamY,
944 event.globalX = event.x;
945 event.globalY = event.y;
947 if (type == "scrollUpdate") {
950 if (!params->GetInteger(
951 devtools::Input::dispatchGestureEvent::kParamDeltaX, &dx) ||
953 devtools::Input::dispatchGestureEvent::kParamDeltaY, &dy)) {
956 event.data.scrollUpdate.deltaX = dx;
957 event.data.scrollUpdate.deltaY = dy;
960 if (type == "pinchUpdate") {
962 if (!params->GetDouble(
963 devtools::Input::dispatchGestureEvent::kParamPinchScale,
967 event.data.pinchUpdate.scale = static_cast<float>(scale);
970 host->ForwardGestureEvent(event);
971 return command->SuccessResponse(NULL);
974 } // namespace content