Index: third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f06668f93542787851cceb839e5b6d80b66343cb |
--- /dev/null |
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js |
@@ -0,0 +1,288 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+SDK.EmulationModel = class extends SDK.SDKModel { |
+ /** |
+ * @param {!SDK.Target} target |
+ */ |
+ constructor(target) { |
+ super(target); |
+ this._emulationAgent = target.emulationAgent(); |
+ this._pageAgent = target.pageAgent(); |
+ this._deviceOrientationAgent = target.deviceOrientationAgent(); |
+ this._cssModel = target.model(SDK.CSSModel); |
+ this._overlayModel = target.model(SDK.OverlayModel); |
+ if (this._overlayModel) |
+ this._overlayModel.addEventListener(SDK.OverlayModel.Events.InspectModeWillBeToggled, this._updateTouch, this); |
+ |
+ var disableJavascriptSetting = Common.settings.moduleSetting('javaScriptDisabled'); |
+ disableJavascriptSetting.addChangeListener( |
+ () => this._emulationAgent.setScriptExecutionDisabled(disableJavascriptSetting.get())); |
+ if (disableJavascriptSetting.get()) |
+ this._emulationAgent.setScriptExecutionDisabled(true); |
+ |
+ this._touchEnabled = false; |
+ this._touchMobile = false; |
+ this._customTouchEnabled = false; |
+ this._touchConfiguration = {enabled: false, configuration: 'mobile', scriptId: ''}; |
+ } |
+ |
+ /** |
+ * @return {boolean} |
+ */ |
+ supportsDeviceEmulation() { |
+ return this.target().hasAllCapabilities(SDK.Target.Capability.DeviceEmulation); |
+ } |
+ |
+ /** |
+ * @param {?SDK.EmulationModel.Geolocation} geolocation |
+ */ |
+ emulateGeolocation(geolocation) { |
+ if (!geolocation) { |
+ this._emulationAgent.clearGeolocationOverride(); |
+ return; |
+ } |
+ |
+ if (geolocation.error) { |
+ this._emulationAgent.setGeolocationOverride(); |
+ } else { |
+ this._emulationAgent.setGeolocationOverride( |
+ geolocation.latitude, geolocation.longitude, SDK.EmulationModel.Geolocation.DefaultMockAccuracy); |
+ } |
+ } |
+ |
+ /** |
+ * @param {?SDK.EmulationModel.DeviceOrientation} deviceOrientation |
+ */ |
+ emulateDeviceOrientation(deviceOrientation) { |
+ if (deviceOrientation) { |
+ this._deviceOrientationAgent.setDeviceOrientationOverride( |
+ deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma); |
+ } else { |
+ this._deviceOrientationAgent.clearDeviceOrientationOverride(); |
+ } |
+ } |
+ |
+ /** |
+ * @param {?string} media |
+ */ |
+ emulateCSSMedia(media) { |
+ this._emulationAgent.setEmulatedMedia(media || ''); |
+ if (this._cssModel) |
+ this._cssModel.mediaQueryResultChanged(); |
+ } |
+ |
+ /** |
+ * @param {number} rate |
+ */ |
+ setCPUThrottlingRate(rate) { |
+ this._emulationAgent.setCPUThrottlingRate(rate); |
+ } |
+ |
+ /** |
+ * @param {boolean} enabled |
+ * @param {boolean} mobile |
+ */ |
+ emulateTouch(enabled, mobile) { |
+ this._touchEnabled = enabled; |
+ this._touchMobile = mobile; |
+ this._updateTouch(); |
+ } |
+ |
+ /** |
+ * @param {boolean} enabled |
+ */ |
+ overrideEmulateTouch(enabled) { |
+ this._customTouchEnabled = enabled; |
+ this._updateTouch(); |
+ } |
+ |
+ _updateTouch() { |
+ var configuration = { |
+ enabled: this._touchEnabled, |
+ configuration: this._touchMobile ? 'mobile' : 'desktop', |
+ scriptId: '' |
+ }; |
+ if (this._customTouchEnabled) |
+ configuration = {enabled: true, configuration: 'mobile', scriptId: ''}; |
+ |
+ if (this._overlayModel && this._overlayModel.inspectModeEnabled()) |
+ configuration = {enabled: false, configuration: 'mobile', scriptId: ''}; |
+ |
+ /** |
+ * @suppressGlobalPropertiesCheck |
+ */ |
+ const injectedFunction = function() { |
+ const touchEvents = ['ontouchstart', 'ontouchend', 'ontouchmove', 'ontouchcancel']; |
+ var recepients = [window.__proto__, document.__proto__]; |
+ for (var i = 0; i < touchEvents.length; ++i) { |
+ for (var j = 0; j < recepients.length; ++j) { |
+ if (!(touchEvents[i] in recepients[j])) { |
+ Object.defineProperty( |
+ recepients[j], touchEvents[i], {value: null, writable: true, configurable: true, enumerable: true}); |
+ } |
+ } |
+ } |
+ }; |
+ |
+ if (!this._touchConfiguration.enabled && !configuration.enabled) |
+ return; |
+ if (this._touchConfiguration.enabled && configuration.enabled && |
+ this._touchConfiguration.configuration === configuration.configuration) |
+ return; |
+ |
+ if (this._touchConfiguration.scriptId) |
+ this._pageAgent.removeScriptToEvaluateOnLoad(this._touchConfiguration.scriptId); |
+ this._touchConfiguration = configuration; |
+ if (configuration.enabled) { |
+ this._pageAgent.addScriptToEvaluateOnLoad('(' + injectedFunction.toString() + ')()', (error, scriptId) => { |
+ this._touchConfiguration.scriptId = error ? '' : scriptId; |
+ }); |
+ } |
+ |
+ this._emulationAgent.setTouchEmulationEnabled(configuration.enabled, configuration.configuration); |
+ } |
+}; |
+ |
+SDK.SDKModel.register(SDK.EmulationModel, SDK.Target.Capability.Emulation, true); |
+ |
+SDK.EmulationModel.Geolocation = class { |
+ /** |
+ * @param {number} latitude |
+ * @param {number} longitude |
+ * @param {boolean} error |
+ */ |
+ constructor(latitude, longitude, error) { |
+ this.latitude = latitude; |
+ this.longitude = longitude; |
+ this.error = error; |
+ } |
+ |
+ /** |
+ * @return {!SDK.EmulationModel.Geolocation} |
+ */ |
+ static parseSetting(value) { |
+ if (value) { |
+ var splitError = value.split(':'); |
+ if (splitError.length === 2) { |
+ var splitPosition = splitError[0].split('@'); |
+ if (splitPosition.length === 2) { |
+ return new SDK.EmulationModel.Geolocation( |
+ parseFloat(splitPosition[0]), parseFloat(splitPosition[1]), splitError[1]); |
+ } |
+ } |
+ } |
+ return new SDK.EmulationModel.Geolocation(0, 0, false); |
+ } |
+ |
+ /** |
+ * @param {string} latitudeString |
+ * @param {string} longitudeString |
+ * @param {string} errorStatus |
+ * @return {?SDK.EmulationModel.Geolocation} |
+ */ |
+ static parseUserInput(latitudeString, longitudeString, errorStatus) { |
+ if (!latitudeString && !longitudeString) |
+ return null; |
+ |
+ var isLatitudeValid = SDK.EmulationModel.Geolocation.latitudeValidator(latitudeString); |
+ var isLongitudeValid = SDK.EmulationModel.Geolocation.longitudeValidator(longitudeString); |
+ |
+ if (!isLatitudeValid && !isLongitudeValid) |
+ return null; |
+ |
+ var latitude = isLatitudeValid ? parseFloat(latitudeString) : -1; |
+ var longitude = isLongitudeValid ? parseFloat(longitudeString) : -1; |
+ return new SDK.EmulationModel.Geolocation(latitude, longitude, !!errorStatus); |
+ } |
+ |
+ /** |
+ * @param {string} value |
+ * @return {boolean} |
+ */ |
+ static latitudeValidator(value) { |
+ var numValue = parseFloat(value); |
+ return /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value) && numValue >= -90 && numValue <= 90; |
+ } |
+ |
+ /** |
+ * @param {string} value |
+ * @return {boolean} |
+ */ |
+ static longitudeValidator(value) { |
+ var numValue = parseFloat(value); |
+ return /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value) && numValue >= -180 && numValue <= 180; |
+ } |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ toSetting() { |
+ return (typeof this.latitude === 'number' && typeof this.longitude === 'number' && typeof this.error === 'string') ? |
+ this.latitude + '@' + this.longitude + ':' + this.error : |
+ ''; |
+ } |
+}; |
+ |
+SDK.EmulationModel.Geolocation.DefaultMockAccuracy = 150; |
+ |
+SDK.EmulationModel.DeviceOrientation = class { |
+ /** |
+ * @param {number} alpha |
+ * @param {number} beta |
+ * @param {number} gamma |
+ */ |
+ constructor(alpha, beta, gamma) { |
+ this.alpha = alpha; |
+ this.beta = beta; |
+ this.gamma = gamma; |
+ } |
+ |
+ /** |
+ * @return {!SDK.EmulationModel.DeviceOrientation} |
+ */ |
+ static parseSetting(value) { |
+ if (value) { |
+ var jsonObject = JSON.parse(value); |
+ return new SDK.EmulationModel.DeviceOrientation(jsonObject.alpha, jsonObject.beta, jsonObject.gamma); |
+ } |
+ return new SDK.EmulationModel.DeviceOrientation(0, 0, 0); |
+ } |
+ |
+ /** |
+ * @return {?SDK.EmulationModel.DeviceOrientation} |
+ */ |
+ static parseUserInput(alphaString, betaString, gammaString) { |
+ if (!alphaString && !betaString && !gammaString) |
+ return null; |
+ |
+ var isAlphaValid = SDK.EmulationModel.DeviceOrientation.validator(alphaString); |
+ var isBetaValid = SDK.EmulationModel.DeviceOrientation.validator(betaString); |
+ var isGammaValid = SDK.EmulationModel.DeviceOrientation.validator(gammaString); |
+ |
+ if (!isAlphaValid && !isBetaValid && !isGammaValid) |
+ return null; |
+ |
+ var alpha = isAlphaValid ? parseFloat(alphaString) : -1; |
+ var beta = isBetaValid ? parseFloat(betaString) : -1; |
+ var gamma = isGammaValid ? parseFloat(gammaString) : -1; |
+ |
+ return new SDK.EmulationModel.DeviceOrientation(alpha, beta, gamma); |
+ } |
+ |
+ /** |
+ * @param {string} value |
+ * @return {boolean} |
+ */ |
+ static validator(value) { |
+ return /^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(value); |
+ } |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ toSetting() { |
+ return JSON.stringify(this); |
+ } |
+}; |