OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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. |
| 4 |
| 5 SDK.EmulationModel = class extends SDK.SDKModel { |
| 6 /** |
| 7 * @param {!SDK.Target} target |
| 8 */ |
| 9 constructor(target) { |
| 10 super(target); |
| 11 this._emulationAgent = target.emulationAgent(); |
| 12 this._pageAgent = target.pageAgent(); |
| 13 this._deviceOrientationAgent = target.deviceOrientationAgent(); |
| 14 this._cssModel = target.model(SDK.CSSModel); |
| 15 this._overlayModel = target.model(SDK.OverlayModel); |
| 16 if (this._overlayModel) |
| 17 this._overlayModel.addEventListener(SDK.OverlayModel.Events.InspectModeWil
lBeToggled, this._updateTouch, this); |
| 18 |
| 19 var disableJavascriptSetting = Common.settings.moduleSetting('javaScriptDisa
bled'); |
| 20 disableJavascriptSetting.addChangeListener( |
| 21 () => this._emulationAgent.setScriptExecutionDisabled(disableJavascriptS
etting.get())); |
| 22 if (disableJavascriptSetting.get()) |
| 23 this._emulationAgent.setScriptExecutionDisabled(true); |
| 24 |
| 25 this._touchEnabled = false; |
| 26 this._touchMobile = false; |
| 27 this._customTouchEnabled = false; |
| 28 this._touchConfiguration = {enabled: false, configuration: 'mobile', scriptI
d: ''}; |
| 29 } |
| 30 |
| 31 /** |
| 32 * @return {boolean} |
| 33 */ |
| 34 supportsDeviceEmulation() { |
| 35 return this.target().hasAllCapabilities(SDK.Target.Capability.DeviceEmulatio
n); |
| 36 } |
| 37 |
| 38 /** |
| 39 * @param {?SDK.EmulationModel.Geolocation} geolocation |
| 40 */ |
| 41 emulateGeolocation(geolocation) { |
| 42 if (!geolocation) { |
| 43 this._emulationAgent.clearGeolocationOverride(); |
| 44 return; |
| 45 } |
| 46 |
| 47 if (geolocation.error) { |
| 48 this._emulationAgent.setGeolocationOverride(); |
| 49 } else { |
| 50 this._emulationAgent.setGeolocationOverride( |
| 51 geolocation.latitude, geolocation.longitude, SDK.EmulationModel.Geoloc
ation.DefaultMockAccuracy); |
| 52 } |
| 53 } |
| 54 |
| 55 /** |
| 56 * @param {?SDK.EmulationModel.DeviceOrientation} deviceOrientation |
| 57 */ |
| 58 emulateDeviceOrientation(deviceOrientation) { |
| 59 if (deviceOrientation) { |
| 60 this._deviceOrientationAgent.setDeviceOrientationOverride( |
| 61 deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gam
ma); |
| 62 } else { |
| 63 this._deviceOrientationAgent.clearDeviceOrientationOverride(); |
| 64 } |
| 65 } |
| 66 |
| 67 /** |
| 68 * @param {?string} media |
| 69 */ |
| 70 emulateCSSMedia(media) { |
| 71 this._emulationAgent.setEmulatedMedia(media || ''); |
| 72 if (this._cssModel) |
| 73 this._cssModel.mediaQueryResultChanged(); |
| 74 } |
| 75 |
| 76 /** |
| 77 * @param {number} rate |
| 78 */ |
| 79 setCPUThrottlingRate(rate) { |
| 80 this._emulationAgent.setCPUThrottlingRate(rate); |
| 81 } |
| 82 |
| 83 /** |
| 84 * @param {boolean} enabled |
| 85 * @param {boolean} mobile |
| 86 */ |
| 87 emulateTouch(enabled, mobile) { |
| 88 this._touchEnabled = enabled; |
| 89 this._touchMobile = mobile; |
| 90 this._updateTouch(); |
| 91 } |
| 92 |
| 93 /** |
| 94 * @param {boolean} enabled |
| 95 */ |
| 96 overrideEmulateTouch(enabled) { |
| 97 this._customTouchEnabled = enabled; |
| 98 this._updateTouch(); |
| 99 } |
| 100 |
| 101 _updateTouch() { |
| 102 var configuration = { |
| 103 enabled: this._touchEnabled, |
| 104 configuration: this._touchMobile ? 'mobile' : 'desktop', |
| 105 scriptId: '' |
| 106 }; |
| 107 if (this._customTouchEnabled) |
| 108 configuration = {enabled: true, configuration: 'mobile', scriptId: ''}; |
| 109 |
| 110 if (this._overlayModel && this._overlayModel.inspectModeEnabled()) |
| 111 configuration = {enabled: false, configuration: 'mobile', scriptId: ''}; |
| 112 |
| 113 /** |
| 114 * @suppressGlobalPropertiesCheck |
| 115 */ |
| 116 const injectedFunction = function() { |
| 117 const touchEvents = ['ontouchstart', 'ontouchend', 'ontouchmove', 'ontouch
cancel']; |
| 118 var recepients = [window.__proto__, document.__proto__]; |
| 119 for (var i = 0; i < touchEvents.length; ++i) { |
| 120 for (var j = 0; j < recepients.length; ++j) { |
| 121 if (!(touchEvents[i] in recepients[j])) { |
| 122 Object.defineProperty( |
| 123 recepients[j], touchEvents[i], {value: null, writable: true, con
figurable: true, enumerable: true}); |
| 124 } |
| 125 } |
| 126 } |
| 127 }; |
| 128 |
| 129 if (!this._touchConfiguration.enabled && !configuration.enabled) |
| 130 return; |
| 131 if (this._touchConfiguration.enabled && configuration.enabled && |
| 132 this._touchConfiguration.configuration === configuration.configuration) |
| 133 return; |
| 134 |
| 135 if (this._touchConfiguration.scriptId) |
| 136 this._pageAgent.removeScriptToEvaluateOnLoad(this._touchConfiguration.scri
ptId); |
| 137 this._touchConfiguration = configuration; |
| 138 if (configuration.enabled) { |
| 139 this._pageAgent.addScriptToEvaluateOnLoad('(' + injectedFunction.toString(
) + ')()', (error, scriptId) => { |
| 140 this._touchConfiguration.scriptId = error ? '' : scriptId; |
| 141 }); |
| 142 } |
| 143 |
| 144 this._emulationAgent.setTouchEmulationEnabled(configuration.enabled, configu
ration.configuration); |
| 145 } |
| 146 }; |
| 147 |
| 148 SDK.SDKModel.register(SDK.EmulationModel, SDK.Target.Capability.Emulation, true)
; |
| 149 |
| 150 SDK.EmulationModel.Geolocation = class { |
| 151 /** |
| 152 * @param {number} latitude |
| 153 * @param {number} longitude |
| 154 * @param {boolean} error |
| 155 */ |
| 156 constructor(latitude, longitude, error) { |
| 157 this.latitude = latitude; |
| 158 this.longitude = longitude; |
| 159 this.error = error; |
| 160 } |
| 161 |
| 162 /** |
| 163 * @return {!SDK.EmulationModel.Geolocation} |
| 164 */ |
| 165 static parseSetting(value) { |
| 166 if (value) { |
| 167 var splitError = value.split(':'); |
| 168 if (splitError.length === 2) { |
| 169 var splitPosition = splitError[0].split('@'); |
| 170 if (splitPosition.length === 2) { |
| 171 return new SDK.EmulationModel.Geolocation( |
| 172 parseFloat(splitPosition[0]), parseFloat(splitPosition[1]), splitE
rror[1]); |
| 173 } |
| 174 } |
| 175 } |
| 176 return new SDK.EmulationModel.Geolocation(0, 0, false); |
| 177 } |
| 178 |
| 179 /** |
| 180 * @param {string} latitudeString |
| 181 * @param {string} longitudeString |
| 182 * @param {string} errorStatus |
| 183 * @return {?SDK.EmulationModel.Geolocation} |
| 184 */ |
| 185 static parseUserInput(latitudeString, longitudeString, errorStatus) { |
| 186 if (!latitudeString && !longitudeString) |
| 187 return null; |
| 188 |
| 189 var isLatitudeValid = SDK.EmulationModel.Geolocation.latitudeValidator(latit
udeString); |
| 190 var isLongitudeValid = SDK.EmulationModel.Geolocation.longitudeValidator(lon
gitudeString); |
| 191 |
| 192 if (!isLatitudeValid && !isLongitudeValid) |
| 193 return null; |
| 194 |
| 195 var latitude = isLatitudeValid ? parseFloat(latitudeString) : -1; |
| 196 var longitude = isLongitudeValid ? parseFloat(longitudeString) : -1; |
| 197 return new SDK.EmulationModel.Geolocation(latitude, longitude, !!errorStatus
); |
| 198 } |
| 199 |
| 200 /** |
| 201 * @param {string} value |
| 202 * @return {boolean} |
| 203 */ |
| 204 static latitudeValidator(value) { |
| 205 var numValue = parseFloat(value); |
| 206 return /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value) && numValue >= -90 &&
numValue <= 90; |
| 207 } |
| 208 |
| 209 /** |
| 210 * @param {string} value |
| 211 * @return {boolean} |
| 212 */ |
| 213 static longitudeValidator(value) { |
| 214 var numValue = parseFloat(value); |
| 215 return /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value) && numValue >= -180 &
& numValue <= 180; |
| 216 } |
| 217 |
| 218 /** |
| 219 * @return {string} |
| 220 */ |
| 221 toSetting() { |
| 222 return (typeof this.latitude === 'number' && typeof this.longitude === 'numb
er' && typeof this.error === 'string') ? |
| 223 this.latitude + '@' + this.longitude + ':' + this.error : |
| 224 ''; |
| 225 } |
| 226 }; |
| 227 |
| 228 SDK.EmulationModel.Geolocation.DefaultMockAccuracy = 150; |
| 229 |
| 230 SDK.EmulationModel.DeviceOrientation = class { |
| 231 /** |
| 232 * @param {number} alpha |
| 233 * @param {number} beta |
| 234 * @param {number} gamma |
| 235 */ |
| 236 constructor(alpha, beta, gamma) { |
| 237 this.alpha = alpha; |
| 238 this.beta = beta; |
| 239 this.gamma = gamma; |
| 240 } |
| 241 |
| 242 /** |
| 243 * @return {!SDK.EmulationModel.DeviceOrientation} |
| 244 */ |
| 245 static parseSetting(value) { |
| 246 if (value) { |
| 247 var jsonObject = JSON.parse(value); |
| 248 return new SDK.EmulationModel.DeviceOrientation(jsonObject.alpha, jsonObje
ct.beta, jsonObject.gamma); |
| 249 } |
| 250 return new SDK.EmulationModel.DeviceOrientation(0, 0, 0); |
| 251 } |
| 252 |
| 253 /** |
| 254 * @return {?SDK.EmulationModel.DeviceOrientation} |
| 255 */ |
| 256 static parseUserInput(alphaString, betaString, gammaString) { |
| 257 if (!alphaString && !betaString && !gammaString) |
| 258 return null; |
| 259 |
| 260 var isAlphaValid = SDK.EmulationModel.DeviceOrientation.validator(alphaStrin
g); |
| 261 var isBetaValid = SDK.EmulationModel.DeviceOrientation.validator(betaString)
; |
| 262 var isGammaValid = SDK.EmulationModel.DeviceOrientation.validator(gammaStrin
g); |
| 263 |
| 264 if (!isAlphaValid && !isBetaValid && !isGammaValid) |
| 265 return null; |
| 266 |
| 267 var alpha = isAlphaValid ? parseFloat(alphaString) : -1; |
| 268 var beta = isBetaValid ? parseFloat(betaString) : -1; |
| 269 var gamma = isGammaValid ? parseFloat(gammaString) : -1; |
| 270 |
| 271 return new SDK.EmulationModel.DeviceOrientation(alpha, beta, gamma); |
| 272 } |
| 273 |
| 274 /** |
| 275 * @param {string} value |
| 276 * @return {boolean} |
| 277 */ |
| 278 static validator(value) { |
| 279 return /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value); |
| 280 } |
| 281 |
| 282 /** |
| 283 * @return {string} |
| 284 */ |
| 285 toSetting() { |
| 286 return JSON.stringify(this); |
| 287 } |
| 288 }; |
OLD | NEW |