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/browser/renderer_host/render_widget_host_view_base.h"
25 #include "content/common/view_messages.h"
26 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/content_browser_client.h"
28 #include "content/public/browser/devtools_agent_host.h"
29 #include "content/public/browser/javascript_dialog_manager.h"
30 #include "content/public/browser/navigation_controller.h"
31 #include "content/public/browser/navigation_entry.h"
32 #include "content/public/browser/render_process_host.h"
33 #include "content/public/browser/render_view_host.h"
34 #include "content/public/browser/render_widget_host_view.h"
35 #include "content/public/browser/storage_partition.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/browser/web_contents_delegate.h"
38 #include "content/public/common/content_client.h"
39 #include "content/public/common/page_transition_types.h"
40 #include "content/public/common/referrer.h"
41 #include "ipc/ipc_sender.h"
42 #include "net/base/net_util.h"
43 #include "third_party/WebKit/public/web/WebInputEvent.h"
44 #include "ui/gfx/codec/jpeg_codec.h"
45 #include "ui/gfx/codec/png_codec.h"
46 #include "ui/gfx/size_conversions.h"
47 #include "ui/snapshot/snapshot.h"
49 #include "webkit/browser/quota/quota_manager.h"
51 using blink::WebGestureEvent
;
52 using blink::WebInputEvent
;
53 using blink::WebMouseEvent
;
59 static const char kPng
[] = "png";
60 static const char kJpeg
[] = "jpeg";
61 static int kDefaultScreenshotQuality
= 80;
62 static int kFrameRateThresholdMs
= 100;
63 static int kCaptureRetryLimit
= 2;
65 void ParseGenericInputParams(base::DictionaryValue
* params
,
66 WebInputEvent
* event
) {
68 if (params
->GetInteger(devtools::Input::dispatchMouseEvent::kParamModifiers
,
71 event
->modifiers
|= WebInputEvent::AltKey
;
73 event
->modifiers
|= WebInputEvent::ControlKey
;
75 event
->modifiers
|= WebInputEvent::MetaKey
;
77 event
->modifiers
|= WebInputEvent::ShiftKey
;
80 params
->GetDouble(devtools::Input::dispatchMouseEvent::kParamTimestamp
,
81 &event
->timeStampSeconds
);
86 RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost
* agent
)
88 capture_retry_count_(0),
90 RegisterCommandHandler(
91 devtools::DOM::setFileInputFiles::kName
,
93 &RendererOverridesHandler::GrantPermissionsForSetFileInputFiles
,
94 base::Unretained(this)));
95 RegisterCommandHandler(
96 devtools::Network::clearBrowserCache::kName
,
98 &RendererOverridesHandler::ClearBrowserCache
,
99 base::Unretained(this)));
100 RegisterCommandHandler(
101 devtools::Network::clearBrowserCookies::kName
,
103 &RendererOverridesHandler::ClearBrowserCookies
,
104 base::Unretained(this)));
105 RegisterCommandHandler(
106 devtools::Page::disable::kName
,
108 &RendererOverridesHandler::PageDisable
, base::Unretained(this)));
109 RegisterCommandHandler(
110 devtools::Page::handleJavaScriptDialog::kName
,
112 &RendererOverridesHandler::PageHandleJavaScriptDialog
,
113 base::Unretained(this)));
114 RegisterCommandHandler(
115 devtools::Page::navigate::kName
,
117 &RendererOverridesHandler::PageNavigate
,
118 base::Unretained(this)));
119 RegisterCommandHandler(
120 devtools::Page::reload::kName
,
122 &RendererOverridesHandler::PageReload
,
123 base::Unretained(this)));
124 RegisterCommandHandler(
125 devtools::Page::getNavigationHistory::kName
,
127 &RendererOverridesHandler::PageGetNavigationHistory
,
128 base::Unretained(this)));
129 RegisterCommandHandler(
130 devtools::Page::navigateToHistoryEntry::kName
,
132 &RendererOverridesHandler::PageNavigateToHistoryEntry
,
133 base::Unretained(this)));
134 RegisterCommandHandler(
135 devtools::Page::captureScreenshot::kName
,
137 &RendererOverridesHandler::PageCaptureScreenshot
,
138 base::Unretained(this)));
139 RegisterCommandHandler(
140 devtools::Page::canScreencast::kName
,
142 &RendererOverridesHandler::PageCanScreencast
,
143 base::Unretained(this)));
144 RegisterCommandHandler(
145 devtools::Page::startScreencast::kName
,
147 &RendererOverridesHandler::PageStartScreencast
,
148 base::Unretained(this)));
149 RegisterCommandHandler(
150 devtools::Page::stopScreencast::kName
,
152 &RendererOverridesHandler::PageStopScreencast
,
153 base::Unretained(this)));
154 RegisterCommandHandler(
155 devtools::Page::queryUsageAndQuota::kName
,
157 &RendererOverridesHandler::PageQueryUsageAndQuota
,
158 base::Unretained(this)));
159 RegisterCommandHandler(
160 devtools::Input::dispatchMouseEvent::kName
,
162 &RendererOverridesHandler::InputDispatchMouseEvent
,
163 base::Unretained(this)));
164 RegisterCommandHandler(
165 devtools::Input::dispatchGestureEvent::kName
,
167 &RendererOverridesHandler::InputDispatchGestureEvent
,
168 base::Unretained(this)));
171 RendererOverridesHandler::~RendererOverridesHandler() {}
173 void RendererOverridesHandler::OnClientDetached() {
174 screencast_command_
= NULL
;
177 void RendererOverridesHandler::OnSwapCompositorFrame(
178 const cc::CompositorFrameMetadata
& frame_metadata
) {
179 last_compositor_frame_metadata_
= frame_metadata
;
181 if (screencast_command_
)
182 InnerSwapCompositorFrame();
185 void RendererOverridesHandler::OnVisibilityChanged(bool visible
) {
186 if (!screencast_command_
)
188 NotifyScreencastVisibility(visible
);
191 void RendererOverridesHandler::InnerSwapCompositorFrame() {
192 if ((base::TimeTicks::Now() - last_frame_time_
).InMilliseconds() <
193 kFrameRateThresholdMs
) {
197 RenderViewHost
* host
= agent_
->GetRenderViewHost();
198 if (!host
->GetView())
201 last_frame_time_
= base::TimeTicks::Now();
203 int quality
= kDefaultScreenshotQuality
;
205 ParseCaptureParameters(screencast_command_
.get(), &format
, &quality
, &scale
);
207 RenderWidgetHostViewBase
* view
= static_cast<RenderWidgetHostViewBase
*>(
210 gfx::Rect view_bounds
= host
->GetView()->GetViewBounds();
211 gfx::Size snapshot_size
= gfx::ToFlooredSize(
212 gfx::ScaleSize(view_bounds
.size(), scale
));
214 view
->CopyFromCompositingSurface(
215 view_bounds
, snapshot_size
,
216 base::Bind(&RendererOverridesHandler::ScreencastFrameCaptured
,
217 weak_factory_
.GetWeakPtr(),
218 format
, quality
, last_compositor_frame_metadata_
),
219 SkBitmap::kARGB_8888_Config
);
222 void RendererOverridesHandler::ParseCaptureParameters(
223 DevToolsProtocol::Command
* command
,
227 *quality
= kDefaultScreenshotQuality
;
229 double max_width
= -1;
230 double max_height
= -1;
231 base::DictionaryValue
* params
= command
->params();
233 params
->GetString(devtools::Page::startScreencast::kParamFormat
,
235 params
->GetInteger(devtools::Page::startScreencast::kParamQuality
,
237 params
->GetDouble(devtools::Page::startScreencast::kParamMaxWidth
,
239 params
->GetDouble(devtools::Page::startScreencast::kParamMaxHeight
,
243 RenderViewHost
* host
= agent_
->GetRenderViewHost();
244 CHECK(host
->GetView());
245 gfx::Rect view_bounds
= host
->GetView()->GetViewBounds();
247 *scale
= std::min(*scale
, max_width
/ view_bounds
.width());
249 *scale
= std::min(*scale
, max_height
/ view_bounds
.height());
253 if (*quality
< 0 || *quality
> 100)
254 *quality
= kDefaultScreenshotQuality
;
261 base::DictionaryValue
* RendererOverridesHandler::CreateScreenshotResponse(
262 const std::vector
<unsigned char>& png_data
) {
263 std::string base_64_data
;
265 base::StringPiece(reinterpret_cast<const char*>(&png_data
[0]),
269 base::DictionaryValue
* response
= new base::DictionaryValue();
271 devtools::Page::captureScreenshot::kResponseData
, base_64_data
);
275 // DOM agent handlers --------------------------------------------------------
277 scoped_refptr
<DevToolsProtocol::Response
>
278 RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
279 scoped_refptr
<DevToolsProtocol::Command
> command
) {
280 base::DictionaryValue
* params
= command
->params();
281 base::ListValue
* file_list
= NULL
;
283 devtools::DOM::setFileInputFiles::kParamFiles
;
284 if (!params
|| !params
->GetList(param
, &file_list
))
285 return command
->InvalidParamResponse(param
);
286 RenderViewHost
* host
= agent_
->GetRenderViewHost();
290 for (size_t i
= 0; i
< file_list
->GetSize(); ++i
) {
291 base::FilePath::StringType file
;
292 if (!file_list
->GetString(i
, &file
))
293 return command
->InvalidParamResponse(param
);
294 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
295 host
->GetProcess()->GetID(), base::FilePath(file
));
301 // Network agent handlers ----------------------------------------------------
303 scoped_refptr
<DevToolsProtocol::Response
>
304 RendererOverridesHandler::ClearBrowserCache(
305 scoped_refptr
<DevToolsProtocol::Command
> command
) {
306 GetContentClient()->browser()->ClearCache(agent_
->GetRenderViewHost());
307 return command
->SuccessResponse(NULL
);
310 scoped_refptr
<DevToolsProtocol::Response
>
311 RendererOverridesHandler::ClearBrowserCookies(
312 scoped_refptr
<DevToolsProtocol::Command
> command
) {
313 GetContentClient()->browser()->ClearCookies(agent_
->GetRenderViewHost());
314 return command
->SuccessResponse(NULL
);
318 // Page agent handlers -------------------------------------------------------
320 scoped_refptr
<DevToolsProtocol::Response
>
321 RendererOverridesHandler::PageDisable(
322 scoped_refptr
<DevToolsProtocol::Command
> command
) {
323 screencast_command_
= NULL
;
327 scoped_refptr
<DevToolsProtocol::Response
>
328 RendererOverridesHandler::PageHandleJavaScriptDialog(
329 scoped_refptr
<DevToolsProtocol::Command
> command
) {
330 base::DictionaryValue
* params
= command
->params();
331 const char* paramAccept
=
332 devtools::Page::handleJavaScriptDialog::kParamAccept
;
334 if (!params
|| !params
->GetBoolean(paramAccept
, &accept
))
335 return command
->InvalidParamResponse(paramAccept
);
336 base::string16 prompt_override
;
337 base::string16
* prompt_override_ptr
= &prompt_override
;
338 if (!params
|| !params
->GetString(
339 devtools::Page::handleJavaScriptDialog::kParamPromptText
,
340 prompt_override_ptr
)) {
341 prompt_override_ptr
= NULL
;
344 RenderViewHost
* host
= agent_
->GetRenderViewHost();
346 WebContents
* web_contents
= host
->GetDelegate()->GetAsWebContents();
348 JavaScriptDialogManager
* manager
=
349 web_contents
->GetDelegate()->GetJavaScriptDialogManager();
350 if (manager
&& manager
->HandleJavaScriptDialog(
351 web_contents
, accept
, prompt_override_ptr
)) {
352 return command
->SuccessResponse(new base::DictionaryValue());
356 return command
->InternalErrorResponse("No JavaScript dialog to handle");
359 scoped_refptr
<DevToolsProtocol::Response
>
360 RendererOverridesHandler::PageNavigate(
361 scoped_refptr
<DevToolsProtocol::Command
> command
) {
362 base::DictionaryValue
* params
= command
->params();
364 const char* param
= devtools::Page::navigate::kParamUrl
;
365 if (!params
|| !params
->GetString(param
, &url
))
366 return command
->InvalidParamResponse(param
);
368 if (!gurl
.is_valid()) {
369 return command
->InternalErrorResponse("Cannot navigate to invalid URL");
371 RenderViewHost
* host
= agent_
->GetRenderViewHost();
373 WebContents
* web_contents
= host
->GetDelegate()->GetAsWebContents();
375 web_contents
->GetController()
376 .LoadURL(gurl
, Referrer(), PAGE_TRANSITION_TYPED
, std::string());
377 return command
->SuccessResponse(new base::DictionaryValue());
380 return command
->InternalErrorResponse("No WebContents to navigate");
383 scoped_refptr
<DevToolsProtocol::Response
>
384 RendererOverridesHandler::PageReload(
385 scoped_refptr
<DevToolsProtocol::Command
> command
) {
386 RenderViewHost
* host
= agent_
->GetRenderViewHost();
388 WebContents
* web_contents
= host
->GetDelegate()->GetAsWebContents();
390 // Override only if it is crashed.
391 if (!web_contents
->IsCrashed())
394 web_contents
->GetController().Reload(false);
395 return command
->SuccessResponse(NULL
);
398 return command
->InternalErrorResponse("No WebContents to reload");
401 scoped_refptr
<DevToolsProtocol::Response
>
402 RendererOverridesHandler::PageGetNavigationHistory(
403 scoped_refptr
<DevToolsProtocol::Command
> command
) {
404 RenderViewHost
* host
= agent_
->GetRenderViewHost();
406 WebContents
* web_contents
= host
->GetDelegate()->GetAsWebContents();
408 base::DictionaryValue
* result
= new base::DictionaryValue();
409 NavigationController
& controller
= web_contents
->GetController();
411 devtools::Page::getNavigationHistory::kResponseCurrentIndex
,
412 controller
.GetCurrentEntryIndex());
413 base::ListValue
* entries
= new base::ListValue();
414 for (int i
= 0; i
!= controller
.GetEntryCount(); ++i
) {
415 const NavigationEntry
* entry
= controller
.GetEntryAtIndex(i
);
416 base::DictionaryValue
* entry_value
= new base::DictionaryValue();
417 entry_value
->SetInteger(
418 devtools::Page::NavigationEntry::kParamId
,
419 entry
->GetUniqueID());
420 entry_value
->SetString(
421 devtools::Page::NavigationEntry::kParamUrl
,
422 entry
->GetURL().spec());
423 entry_value
->SetString(
424 devtools::Page::NavigationEntry::kParamTitle
,
426 entries
->Append(entry_value
);
429 devtools::Page::getNavigationHistory::kResponseEntries
,
431 return command
->SuccessResponse(result
);
434 return command
->InternalErrorResponse("No WebContents to navigate");
437 scoped_refptr
<DevToolsProtocol::Response
>
438 RendererOverridesHandler::PageNavigateToHistoryEntry(
439 scoped_refptr
<DevToolsProtocol::Command
> command
) {
442 base::DictionaryValue
* params
= command
->params();
443 const char* param
= devtools::Page::navigateToHistoryEntry::kParamEntryId
;
444 if (!params
|| !params
->GetInteger(param
, &entry_id
)) {
445 return command
->InvalidParamResponse(param
);
448 RenderViewHost
* host
= agent_
->GetRenderViewHost();
450 WebContents
* web_contents
= host
->GetDelegate()->GetAsWebContents();
452 NavigationController
& controller
= web_contents
->GetController();
453 for (int i
= 0; i
!= controller
.GetEntryCount(); ++i
) {
454 if (controller
.GetEntryAtIndex(i
)->GetUniqueID() == entry_id
) {
455 controller
.GoToIndex(i
);
456 return command
->SuccessResponse(new base::DictionaryValue());
459 return command
->InvalidParamResponse(param
);
462 return command
->InternalErrorResponse("No WebContents to navigate");
465 scoped_refptr
<DevToolsProtocol::Response
>
466 RendererOverridesHandler::PageCaptureScreenshot(
467 scoped_refptr
<DevToolsProtocol::Command
> command
) {
468 RenderViewHost
* host
= agent_
->GetRenderViewHost();
469 if (!host
->GetView())
470 return command
->InternalErrorResponse("Unable to access the view");
472 gfx::Rect view_bounds
= host
->GetView()->GetViewBounds();
473 gfx::Rect
snapshot_bounds(view_bounds
.size());
474 gfx::Size snapshot_size
= snapshot_bounds
.size();
476 std::vector
<unsigned char> png_data
;
477 if (ui::GrabViewSnapshot(host
->GetView()->GetNativeView(),
481 return command
->SuccessResponse(CreateScreenshotResponse(png_data
));
483 return command
->InternalErrorResponse("Unable to capture screenshot");
486 ui::GrabViewSnapshotAsync(
487 host
->GetView()->GetNativeView(),
489 base::ThreadTaskRunnerHandle::Get(),
490 base::Bind(&RendererOverridesHandler::ScreenshotCaptured
,
491 weak_factory_
.GetWeakPtr(), command
));
492 return command
->AsyncResponsePromise();
495 void RendererOverridesHandler::ScreenshotCaptured(
496 scoped_refptr
<DevToolsProtocol::Command
> command
,
497 scoped_refptr
<base::RefCountedBytes
> png_data
) {
500 command
->SuccessResponse(CreateScreenshotResponse(png_data
->data())));
503 command
->InternalErrorResponse("Unable to capture screenshot"));
507 scoped_refptr
<DevToolsProtocol::Response
>
508 RendererOverridesHandler::PageCanScreencast(
509 scoped_refptr
<DevToolsProtocol::Command
> command
) {
510 base::DictionaryValue
* result
= new base::DictionaryValue();
511 #if defined(OS_ANDROID)
512 result
->SetBoolean(devtools::kResult
, true);
514 result
->SetBoolean(devtools::kResult
, false);
515 #endif // defined(OS_ANDROID)
516 return command
->SuccessResponse(result
);
519 scoped_refptr
<DevToolsProtocol::Response
>
520 RendererOverridesHandler::PageStartScreencast(
521 scoped_refptr
<DevToolsProtocol::Command
> command
) {
522 screencast_command_
= command
;
523 RenderViewHostImpl
* host
= static_cast<RenderViewHostImpl
*>(
524 agent_
->GetRenderViewHost());
525 bool visible
= !host
->is_hidden();
526 NotifyScreencastVisibility(visible
);
528 InnerSwapCompositorFrame();
529 return command
->SuccessResponse(NULL
);
532 scoped_refptr
<DevToolsProtocol::Response
>
533 RendererOverridesHandler::PageStopScreencast(
534 scoped_refptr
<DevToolsProtocol::Command
> command
) {
535 last_frame_time_
= base::TimeTicks();
536 screencast_command_
= NULL
;
537 return command
->SuccessResponse(NULL
);
540 void RendererOverridesHandler::ScreencastFrameCaptured(
541 const std::string
& format
,
543 const cc::CompositorFrameMetadata
& metadata
,
545 const SkBitmap
& bitmap
) {
547 if (capture_retry_count_
) {
548 --capture_retry_count_
;
549 base::MessageLoop::current()->PostDelayedTask(
551 base::Bind(&RendererOverridesHandler::InnerSwapCompositorFrame
,
552 weak_factory_
.GetWeakPtr()),
553 base::TimeDelta::FromMilliseconds(kFrameRateThresholdMs
));
558 std::vector
<unsigned char> data
;
559 SkAutoLockPixels
lock_image(bitmap
);
561 if (format
== kPng
) {
562 encoded
= gfx::PNGCodec::Encode(
563 reinterpret_cast<unsigned char*>(bitmap
.getAddr32(0, 0)),
564 gfx::PNGCodec::FORMAT_SkBitmap
,
565 gfx::Size(bitmap
.width(), bitmap
.height()),
566 bitmap
.width() * bitmap
.bytesPerPixel(),
567 false, std::vector
<gfx::PNGCodec::Comment
>(), &data
);
568 } else if (format
== kJpeg
) {
569 encoded
= gfx::JPEGCodec::Encode(
570 reinterpret_cast<unsigned char*>(bitmap
.getAddr32(0, 0)),
571 gfx::JPEGCodec::FORMAT_SkBitmap
,
574 bitmap
.width() * bitmap
.bytesPerPixel(),
583 std::string base_64_data
;
585 base::StringPiece(reinterpret_cast<char*>(&data
[0]), data
.size()),
588 base::DictionaryValue
* response
= new base::DictionaryValue();
589 response
->SetString(devtools::Page::screencastFrame::kParamData
,
592 // Consider metadata empty in case it has no device scale factor.
593 if (metadata
.device_scale_factor
!= 0) {
594 base::DictionaryValue
* response_metadata
= new base::DictionaryValue();
596 response_metadata
->SetDouble(
597 devtools::Page::ScreencastFrameMetadata::kParamDeviceScaleFactor
,
598 metadata
.device_scale_factor
);
599 response_metadata
->SetDouble(
600 devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactor
,
601 metadata
.page_scale_factor
);
602 response_metadata
->SetDouble(
603 devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMin
,
604 metadata
.min_page_scale_factor
);
605 response_metadata
->SetDouble(
606 devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMax
,
607 metadata
.max_page_scale_factor
);
608 response_metadata
->SetDouble(
609 devtools::Page::ScreencastFrameMetadata::kParamOffsetTop
,
610 metadata
.location_bar_content_translation
.y());
611 response_metadata
->SetDouble(
612 devtools::Page::ScreencastFrameMetadata::kParamOffsetBottom
,
613 metadata
.overdraw_bottom_height
);
615 base::DictionaryValue
* viewport
= new base::DictionaryValue();
616 viewport
->SetDouble(devtools::DOM::Rect::kParamX
,
617 metadata
.root_scroll_offset
.x());
618 viewport
->SetDouble(devtools::DOM::Rect::kParamY
,
619 metadata
.root_scroll_offset
.y());
620 viewport
->SetDouble(devtools::DOM::Rect::kParamWidth
,
621 metadata
.viewport_size
.width());
622 viewport
->SetDouble(devtools::DOM::Rect::kParamHeight
,
623 metadata
.viewport_size
.height());
624 response_metadata
->Set(
625 devtools::Page::ScreencastFrameMetadata::kParamViewport
, viewport
);
627 response
->Set(devtools::Page::screencastFrame::kParamMetadata
,
631 SendNotification(devtools::Page::screencastFrame::kName
, response
);
634 // Quota and Usage ------------------------------------------
638 typedef base::Callback
<void(scoped_ptr
<base::DictionaryValue
>)>
641 void QueryUsageAndQuotaCompletedOnIOThread(
642 scoped_ptr
<base::DictionaryValue
> quota
,
643 scoped_ptr
<base::DictionaryValue
> usage
,
644 ResponseCallback callback
) {
646 scoped_ptr
<base::DictionaryValue
> response_data(new base::DictionaryValue
);
647 response_data
->Set(devtools::Page::queryUsageAndQuota::kResponseQuota
,
649 response_data
->Set(devtools::Page::queryUsageAndQuota::kResponseUsage
,
652 BrowserThread::PostTask(
653 BrowserThread::UI
, FROM_HERE
,
654 base::Bind(callback
, base::Passed(&response_data
)));
657 void DidGetHostUsage(
658 base::ListValue
* list
,
659 const std::string
& client_id
,
660 const base::Closure
& barrier
,
662 base::DictionaryValue
* usage_item
= new base::DictionaryValue
;
663 usage_item
->SetString(devtools::Page::UsageItem::kParamId
, client_id
);
664 usage_item
->SetDouble(devtools::Page::UsageItem::kParamValue
, value
);
665 list
->Append(usage_item
);
669 void DidGetQuotaValue(
670 base::DictionaryValue
* dictionary
,
671 const std::string
& item_name
,
672 const base::Closure
& barrier
,
673 quota::QuotaStatusCode status
,
675 if (status
== quota::kQuotaStatusOk
)
676 dictionary
->SetDouble(item_name
, value
);
680 void DidGetUsageAndQuotaForWebApps(
681 base::DictionaryValue
* quota
,
682 const std::string
& item_name
,
683 const base::Closure
& barrier
,
684 quota::QuotaStatusCode status
,
686 int64 quota_in_bytes
) {
687 if (status
== quota::kQuotaStatusOk
)
688 quota
->SetDouble(item_name
, quota_in_bytes
);
692 std::string
GetStorageTypeName(quota::StorageType type
) {
694 case quota::kStorageTypeTemporary
:
695 return devtools::Page::Usage::kParamTemporary
;
696 case quota::kStorageTypePersistent
:
697 return devtools::Page::Usage::kParamPersistent
;
698 case quota::kStorageTypeSyncable
:
699 return devtools::Page::Usage::kParamSyncable
;
700 case quota::kStorageTypeQuotaNotManaged
:
701 case quota::kStorageTypeUnknown
:
707 std::string
GetQuotaClientName(quota::QuotaClient::ID id
) {
709 case quota::QuotaClient::kFileSystem
:
710 return devtools::Page::UsageItem::Id::kEnumFilesystem
;
711 case quota::QuotaClient::kDatabase
:
712 return devtools::Page::UsageItem::Id::kEnumDatabase
;
713 case quota::QuotaClient::kAppcache
:
714 return devtools::Page::UsageItem::Id::kEnumAppcache
;
715 case quota::QuotaClient::kIndexedDatabase
:
716 return devtools::Page::UsageItem::Id::kEnumIndexeddatabase
;
723 void QueryUsageAndQuotaOnIOThread(
724 scoped_refptr
<quota::QuotaManager
> quota_manager
,
725 const GURL
& security_origin
,
726 const ResponseCallback
& callback
) {
727 scoped_ptr
<base::DictionaryValue
> quota(new base::DictionaryValue
);
728 scoped_ptr
<base::DictionaryValue
> usage(new base::DictionaryValue
);
730 static quota::QuotaClient::ID kQuotaClients
[] = {
731 quota::QuotaClient::kFileSystem
,
732 quota::QuotaClient::kDatabase
,
733 quota::QuotaClient::kAppcache
,
734 quota::QuotaClient::kIndexedDatabase
737 static const size_t kStorageTypeCount
= quota::kStorageTypeUnknown
;
738 std::map
<quota::StorageType
, base::ListValue
*> storage_type_lists
;
740 for (size_t i
= 0; i
!= kStorageTypeCount
; i
++) {
741 const quota::StorageType type
= static_cast<quota::StorageType
>(i
);
742 if (type
== quota::kStorageTypeQuotaNotManaged
)
744 storage_type_lists
[type
] = new base::ListValue
;
745 usage
->Set(GetStorageTypeName(type
), storage_type_lists
[type
]);
748 const int kExpectedResults
=
749 2 + arraysize(kQuotaClients
) * storage_type_lists
.size();
750 base::DictionaryValue
* quota_raw_ptr
= quota
.get();
752 // Takes ownership on usage and quota.
753 base::Closure barrier
= BarrierClosure(
755 base::Bind(&QueryUsageAndQuotaCompletedOnIOThread
,
756 base::Passed("a
),
757 base::Passed(&usage
),
759 std::string host
= net::GetHostOrSpecFromURL(security_origin
);
761 quota_manager
->GetUsageAndQuotaForWebApps(
763 quota::kStorageTypeTemporary
,
764 base::Bind(&DidGetUsageAndQuotaForWebApps
, quota_raw_ptr
,
765 std::string(devtools::Page::Quota::kParamTemporary
), barrier
));
767 quota_manager
->GetPersistentHostQuota(
769 base::Bind(&DidGetQuotaValue
, quota_raw_ptr
,
770 std::string(devtools::Page::Quota::kParamPersistent
),
773 for (size_t i
= 0; i
!= arraysize(kQuotaClients
); i
++) {
774 std::map
<quota::StorageType
, base::ListValue
*>::const_iterator iter
;
775 for (iter
= storage_type_lists
.begin();
776 iter
!= storage_type_lists
.end(); ++iter
) {
777 const quota::StorageType type
= (*iter
).first
;
778 if (!quota_manager
->IsTrackingHostUsage(type
, kQuotaClients
[i
])) {
782 quota_manager
->GetHostUsage(
783 host
, type
, kQuotaClients
[i
],
784 base::Bind(&DidGetHostUsage
, (*iter
).second
,
785 GetQuotaClientName(kQuotaClients
[i
]),
793 scoped_refptr
<DevToolsProtocol::Response
>
794 RendererOverridesHandler::PageQueryUsageAndQuota(
795 scoped_refptr
<DevToolsProtocol::Command
> command
) {
796 base::DictionaryValue
* params
= command
->params();
797 std::string security_origin
;
798 if (!params
|| !params
->GetString(
799 devtools::Page::queryUsageAndQuota::kParamSecurityOrigin
,
801 return command
->InvalidParamResponse(
802 devtools::Page::queryUsageAndQuota::kParamSecurityOrigin
);
805 ResponseCallback callback
= base::Bind(
806 &RendererOverridesHandler::PageQueryUsageAndQuotaCompleted
,
807 weak_factory_
.GetWeakPtr(),
810 scoped_refptr
<quota::QuotaManager
> quota_manager
=
811 agent_
->GetRenderViewHost()->GetProcess()->
812 GetStoragePartition()->GetQuotaManager();
814 BrowserThread::PostTask(
815 BrowserThread::IO
, FROM_HERE
,
817 &QueryUsageAndQuotaOnIOThread
,
819 GURL(security_origin
),
822 return command
->AsyncResponsePromise();
825 void RendererOverridesHandler::PageQueryUsageAndQuotaCompleted(
826 scoped_refptr
<DevToolsProtocol::Command
> command
,
827 scoped_ptr
<base::DictionaryValue
> response_data
) {
828 SendAsyncResponse(command
->SuccessResponse(response_data
.release()));
831 void RendererOverridesHandler::NotifyScreencastVisibility(bool visible
) {
833 capture_retry_count_
= kCaptureRetryLimit
;
834 base::DictionaryValue
* params
= new base::DictionaryValue();
836 devtools::Page::screencastVisibilityChanged::kParamVisible
, visible
);
838 devtools::Page::screencastVisibilityChanged::kName
, params
);
841 // Input agent handlers ------------------------------------------------------
843 scoped_refptr
<DevToolsProtocol::Response
>
844 RendererOverridesHandler::InputDispatchMouseEvent(
845 scoped_refptr
<DevToolsProtocol::Command
> command
) {
846 base::DictionaryValue
* params
= command
->params();
850 bool device_space
= false;
851 if (!params
->GetBoolean(
852 devtools::Input::dispatchMouseEvent::kParamDeviceSpace
,
858 RenderViewHost
* host
= agent_
->GetRenderViewHost();
859 blink::WebMouseEvent mouse_event
;
860 ParseGenericInputParams(params
, &mouse_event
);
863 if (params
->GetString(devtools::Input::dispatchMouseEvent::kParamType
,
866 devtools::Input::dispatchMouseEvent::Type::kEnumMousePressed
)
867 mouse_event
.type
= WebInputEvent::MouseDown
;
869 devtools::Input::dispatchMouseEvent::Type::kEnumMouseReleased
)
870 mouse_event
.type
= WebInputEvent::MouseUp
;
872 devtools::Input::dispatchMouseEvent::Type::kEnumMouseMoved
)
873 mouse_event
.type
= WebInputEvent::MouseMove
;
880 if (!params
->GetInteger(devtools::Input::dispatchMouseEvent::kParamX
,
882 !params
->GetInteger(devtools::Input::dispatchMouseEvent::kParamY
,
887 mouse_event
.windowX
= mouse_event
.x
;
888 mouse_event
.windowY
= mouse_event
.y
;
889 mouse_event
.globalX
= mouse_event
.x
;
890 mouse_event
.globalY
= mouse_event
.y
;
892 params
->GetInteger(devtools::Input::dispatchMouseEvent::kParamClickCount
,
893 &mouse_event
.clickCount
);
896 if (!params
->GetString(devtools::Input::dispatchMouseEvent::kParamButton
,
901 if (button
== "none") {
902 mouse_event
.button
= WebMouseEvent::ButtonNone
;
903 } else if (button
== "left") {
904 mouse_event
.button
= WebMouseEvent::ButtonLeft
;
905 mouse_event
.modifiers
|= WebInputEvent::LeftButtonDown
;
906 } else if (button
== "middle") {
907 mouse_event
.button
= WebMouseEvent::ButtonMiddle
;
908 mouse_event
.modifiers
|= WebInputEvent::MiddleButtonDown
;
909 } else if (button
== "right") {
910 mouse_event
.button
= WebMouseEvent::ButtonRight
;
911 mouse_event
.modifiers
|= WebInputEvent::RightButtonDown
;
916 host
->ForwardMouseEvent(mouse_event
);
917 return command
->SuccessResponse(NULL
);
920 scoped_refptr
<DevToolsProtocol::Response
>
921 RendererOverridesHandler::InputDispatchGestureEvent(
922 scoped_refptr
<DevToolsProtocol::Command
> command
) {
923 base::DictionaryValue
* params
= command
->params();
927 RenderViewHostImpl
* host
= static_cast<RenderViewHostImpl
*>(
928 agent_
->GetRenderViewHost());
929 blink::WebGestureEvent event
;
930 ParseGenericInputParams(params
, &event
);
931 event
.sourceDevice
= WebGestureEvent::Touchscreen
;
934 if (params
->GetString(devtools::Input::dispatchGestureEvent::kParamType
,
937 devtools::Input::dispatchGestureEvent::Type::kEnumScrollBegin
)
938 event
.type
= WebInputEvent::GestureScrollBegin
;
940 devtools::Input::dispatchGestureEvent::Type::kEnumScrollUpdate
)
941 event
.type
= WebInputEvent::GestureScrollUpdate
;
943 devtools::Input::dispatchGestureEvent::Type::kEnumScrollEnd
)
944 event
.type
= WebInputEvent::GestureScrollEnd
;
946 devtools::Input::dispatchGestureEvent::Type::kEnumTapDown
)
947 event
.type
= WebInputEvent::GestureTapDown
;
949 devtools::Input::dispatchGestureEvent::Type::kEnumTap
)
950 event
.type
= WebInputEvent::GestureTap
;
952 devtools::Input::dispatchGestureEvent::Type::kEnumPinchBegin
)
953 event
.type
= WebInputEvent::GesturePinchBegin
;
955 devtools::Input::dispatchGestureEvent::Type::kEnumPinchUpdate
)
956 event
.type
= WebInputEvent::GesturePinchUpdate
;
958 devtools::Input::dispatchGestureEvent::Type::kEnumPinchEnd
)
959 event
.type
= WebInputEvent::GesturePinchEnd
;
966 if (!params
->GetInteger(devtools::Input::dispatchGestureEvent::kParamX
,
968 !params
->GetInteger(devtools::Input::dispatchGestureEvent::kParamY
,
972 event
.globalX
= event
.x
;
973 event
.globalY
= event
.y
;
975 if (type
== "scrollUpdate") {
978 if (!params
->GetInteger(
979 devtools::Input::dispatchGestureEvent::kParamDeltaX
, &dx
) ||
981 devtools::Input::dispatchGestureEvent::kParamDeltaY
, &dy
)) {
984 event
.data
.scrollUpdate
.deltaX
= dx
;
985 event
.data
.scrollUpdate
.deltaY
= dy
;
988 if (type
== "pinchUpdate") {
990 if (!params
->GetDouble(
991 devtools::Input::dispatchGestureEvent::kParamPinchScale
,
995 event
.data
.pinchUpdate
.scale
= static_cast<float>(scale
);
998 host
->ForwardGestureEvent(event
);
999 return command
->SuccessResponse(NULL
);
1002 } // namespace content