1 // Copyright 2015 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/protocol/emulation_handler.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "content/browser/frame_host/render_frame_host_impl.h"
9 #include "content/browser/geolocation/geolocation_service_context.h"
10 #include "content/browser/renderer_host/render_widget_host_impl.h"
11 #include "content/browser/web_contents/web_contents_impl.h"
12 #include "content/common/view_messages.h"
13 #include "content/public/common/url_constants.h"
19 using Response
= DevToolsProtocolClient::Response
;
23 ui::GestureProviderConfigType
TouchEmulationConfigurationToType(
24 const std::string
& protocol_value
) {
25 ui::GestureProviderConfigType result
=
26 ui::GestureProviderConfigType::CURRENT_PLATFORM
;
28 set_touch_emulation_enabled::kConfigurationMobile
) {
29 result
= ui::GestureProviderConfigType::GENERIC_MOBILE
;
32 set_touch_emulation_enabled::kConfigurationDesktop
) {
33 result
= ui::GestureProviderConfigType::GENERIC_DESKTOP
;
40 EmulationHandler::EmulationHandler(page::PageHandler
* page_handler
)
41 : touch_emulation_enabled_(false),
42 device_emulation_enabled_(false),
43 page_handler_(page_handler
),
46 page_handler
->SetScreencastListener(this);
49 EmulationHandler::~EmulationHandler() {
52 void EmulationHandler::ScreencastEnabledChanged() {
53 UpdateTouchEventEmulationState();
56 void EmulationHandler::SetRenderFrameHost(RenderFrameHostImpl
* host
) {
61 UpdateTouchEventEmulationState();
62 UpdateDeviceEmulationState();
65 void EmulationHandler::Detached() {
66 touch_emulation_enabled_
= false;
67 device_emulation_enabled_
= false;
68 UpdateTouchEventEmulationState();
69 UpdateDeviceEmulationState();
72 Response
EmulationHandler::SetGeolocationOverride(
73 double* latitude
, double* longitude
, double* accuracy
) {
74 if (!GetWebContents())
75 return Response::InternalError("Could not connect to view");
77 GeolocationServiceContext
* geolocation_context
=
78 GetWebContents()->GetGeolocationServiceContext();
79 scoped_ptr
<Geoposition
> geoposition(new Geoposition());
80 if (latitude
&& longitude
&& accuracy
) {
81 geoposition
->latitude
= *latitude
;
82 geoposition
->longitude
= *longitude
;
83 geoposition
->accuracy
= *accuracy
;
84 geoposition
->timestamp
= base::Time::Now();
85 if (!geoposition
->Validate()) {
86 return Response::InternalError("Invalid geolocation");
89 geoposition
->error_code
= Geoposition::ERROR_CODE_POSITION_UNAVAILABLE
;
91 geolocation_context
->SetOverride(geoposition
.Pass());
92 return Response::OK();
95 Response
EmulationHandler::ClearGeolocationOverride() {
96 if (!GetWebContents())
97 return Response::InternalError("Could not connect to view");
99 GeolocationServiceContext
* geolocation_context
=
100 GetWebContents()->GetGeolocationServiceContext();
101 geolocation_context
->ClearOverride();
102 return Response::OK();
105 Response
EmulationHandler::SetTouchEmulationEnabled(
106 bool enabled
, const std::string
* configuration
) {
107 touch_emulation_enabled_
= enabled
;
108 touch_emulation_configuration_
=
109 configuration
? *configuration
: std::string();
110 UpdateTouchEventEmulationState();
111 return Response::FallThrough();
114 Response
EmulationHandler::CanEmulate(bool* result
) {
115 #if defined(OS_ANDROID)
119 if (WebContentsImpl
* web_contents
= GetWebContents())
120 *result
&= !web_contents
->GetVisibleURL().SchemeIs(kChromeDevToolsScheme
);
121 #endif // defined(OS_ANDROID)
122 return Response::OK();
125 Response
EmulationHandler::SetDeviceMetricsOverride(
126 int width
, int height
, double device_scale_factor
, bool mobile
,
127 bool fit_window
, const double* optional_scale
,
128 const double* optional_offset_x
, const double* optional_offset_y
) {
129 const static int max_size
= 10000000;
130 const static double max_scale
= 10;
133 return Response::InternalError("Could not connect to view");
135 if (width
< 0 || height
< 0 || width
> max_size
|| height
> max_size
) {
136 return Response::InvalidParams(
137 "Width and height values must be positive, not greater than " +
138 base::IntToString(max_size
));
141 if (device_scale_factor
< 0)
142 return Response::InvalidParams("deviceScaleFactor must be non-negative");
144 if (optional_scale
&& (*optional_scale
<= 0 || *optional_scale
> max_scale
)) {
145 return Response::InvalidParams(
146 "scale must be positive, not greater than " +
147 base::IntToString(max_scale
));
150 blink::WebDeviceEmulationParams params
;
151 params
.screenPosition
= mobile
? blink::WebDeviceEmulationParams::Mobile
:
152 blink::WebDeviceEmulationParams::Desktop
;
153 params
.deviceScaleFactor
= device_scale_factor
;
154 params
.viewSize
= blink::WebSize(width
, height
);
155 params
.fitToView
= fit_window
;
156 params
.scale
= optional_scale
? *optional_scale
: 1;
157 params
.offset
= blink::WebFloatPoint(
158 optional_offset_x
? *optional_offset_x
: 0.f
,
159 optional_offset_y
? *optional_offset_y
: 0.f
);
161 if (device_emulation_enabled_
&& params
== device_emulation_params_
)
162 return Response::OK();
164 device_emulation_enabled_
= true;
165 device_emulation_params_
= params
;
166 UpdateDeviceEmulationState();
167 return Response::OK();
170 Response
EmulationHandler::ClearDeviceMetricsOverride() {
171 if (!device_emulation_enabled_
)
172 return Response::OK();
174 device_emulation_enabled_
= false;
175 UpdateDeviceEmulationState();
176 return Response::OK();
179 WebContentsImpl
* EmulationHandler::GetWebContents() {
181 static_cast<WebContentsImpl
*>(WebContents::FromRenderFrameHost(host_
)) :
185 void EmulationHandler::UpdateTouchEventEmulationState() {
186 RenderWidgetHostImpl
* widget_host
=
187 host_
? host_
->GetRenderWidgetHost() : nullptr;
190 bool enabled
= touch_emulation_enabled_
||
191 page_handler_
->screencast_enabled();
192 ui::GestureProviderConfigType config_type
=
193 TouchEmulationConfigurationToType(touch_emulation_configuration_
);
194 widget_host
->SetTouchEventEmulationEnabled(enabled
, config_type
);
195 if (GetWebContents())
196 GetWebContents()->SetForceDisableOverscrollContent(enabled
);
199 void EmulationHandler::UpdateDeviceEmulationState() {
200 RenderWidgetHostImpl
* widget_host
=
201 host_
? host_
->GetRenderWidgetHost() : nullptr;
204 if (device_emulation_enabled_
) {
205 widget_host
->Send(new ViewMsg_EnableDeviceEmulation(
206 widget_host
->GetRoutingID(), device_emulation_params_
));
208 widget_host
->Send(new ViewMsg_DisableDeviceEmulation(
209 widget_host
->GetRoutingID()));
213 } // namespace emulation
214 } // namespace devtools
215 } // namespace content