Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / emulation / OverridesSupport.js
blob6ef155147b4b82de30e9320af28459c2405b996a
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /**
32 * @constructor
33 * @extends {WebInspector.Object}
35 WebInspector.OverridesSupport = function()
37 this._touchEmulationSuspended = false;
38 this._emulateMobileEnabled = false;
39 this._userAgent = "";
40 this._pageResizer = null;
41 this._deviceScale = 1;
42 this._fixedDeviceScale = false;
43 this._initialized = false;
44 this._deviceMetricsThrottler = new WebInspector.Throttler(0);
46 this.settings = {};
47 this.settings._emulationEnabled = WebInspector.settings.createSetting("emulationEnabled", false);
49 this.settings.userAgent = WebInspector.settings.createSetting("userAgent", "");
51 this.settings.emulateResolution = WebInspector.settings.createSetting("emulateResolution", true);
52 this.settings.deviceWidth = WebInspector.settings.createSetting("deviceWidth", 360);
53 this.settings.deviceHeight = WebInspector.settings.createSetting("deviceHeight", 640);
54 this.settings.deviceScaleFactor = WebInspector.settings.createSetting("deviceScaleFactor", 0);
55 this.settings.deviceFitWindow = WebInspector.settings.createSetting("deviceFitWindow", true);
56 this.settings.emulateMobile = WebInspector.settings.createSetting("emulateMobile", false);
58 this.settings.emulateTouch = WebInspector.settings.createSetting("emulateTouch", false);
60 this.settings.overrideGeolocation = WebInspector.settings.createSetting("overrideGeolocation", false);
61 this.settings.geolocationOverride = WebInspector.settings.createSetting("geolocationOverride", "");
63 this.settings.overrideDeviceOrientation = WebInspector.settings.createSetting("overrideDeviceOrientation", false);
64 this.settings.deviceOrientationOverride = WebInspector.settings.createSetting("deviceOrientationOverride", "");
66 this.settings.screenOrientationOverride = WebInspector.settings.createSetting("screenOrientationOverride", "");
68 this.settings.overrideCSSMedia = WebInspector.settings.createSetting("overrideCSSMedia", false);
69 this.settings.emulatedCSSMedia = WebInspector.settings.createSetting("emulatedCSSMedia", "print");
71 this.settings.javaScriptDisabled = WebInspector.moduleSetting("javaScriptDisabled");
74 WebInspector.OverridesSupport.Events = {
75 OverridesWarningUpdated: "OverridesWarningUpdated",
76 EmulationStateChanged: "EmulationStateChanged"
79 WebInspector.OverridesSupport.MaxDeviceSize = 9999;
81 /**
82 * @interface
83 * @extends {WebInspector.EventTarget}
85 WebInspector.OverridesSupport.PageResizer = function()
89 WebInspector.OverridesSupport.PageResizer.Events = {
90 AvailableSizeChanged: "AvailableSizeChanged",
91 ResizeRequested: "ResizeRequested",
92 FixedScaleRequested: "FixedScaleRequested",
93 InsetsChanged: "InsetsChanged"
96 WebInspector.OverridesSupport.PageResizer.prototype = {
97 /**
98 * Zero width and height mean default size.
99 * Scale should be applied to page-scale-dependent UI bits. Zero means no scale.
100 * @param {number} dipWidth
101 * @param {number} dipHeight
102 * @param {number} scale
104 update: function(dipWidth, dipHeight, scale) { }
107 /** @typedef {{width: number, height: number, deviceScaleFactor: number, userAgent: string, touch: boolean, mobile: boolean}} */
108 WebInspector.OverridesSupport.Device = {};
111 * @constructor
112 * @param {number} latitude
113 * @param {number} longitude
114 * @param {string} error
116 WebInspector.OverridesSupport.GeolocationPosition = function(latitude, longitude, error)
118 this.latitude = latitude;
119 this.longitude = longitude;
120 this.error = error;
123 WebInspector.OverridesSupport.GeolocationPosition.prototype = {
125 * @return {string}
127 toSetting: function()
129 return (typeof this.latitude === "number" && typeof this.longitude === "number" && typeof this.error === "string") ? this.latitude + "@" + this.longitude + ":" + this.error : "";
134 * @return {!WebInspector.OverridesSupport.GeolocationPosition}
136 WebInspector.OverridesSupport.GeolocationPosition.parseSetting = function(value)
138 if (value) {
139 var splitError = value.split(":");
140 if (splitError.length === 2) {
141 var splitPosition = splitError[0].split("@");
142 if (splitPosition.length === 2)
143 return new WebInspector.OverridesSupport.GeolocationPosition(parseFloat(splitPosition[0]), parseFloat(splitPosition[1]), splitError[1]);
146 return new WebInspector.OverridesSupport.GeolocationPosition(0, 0, "");
150 * @return {?WebInspector.OverridesSupport.GeolocationPosition}
152 WebInspector.OverridesSupport.GeolocationPosition.parseUserInput = function(latitudeString, longitudeString, errorStatus)
154 function isUserInputValid(value)
156 if (!value)
157 return true;
158 return /^[-]?[0-9]*[.]?[0-9]*$/.test(value);
161 if (!latitudeString && !longitudeString)
162 return null;
164 var isLatitudeValid = isUserInputValid(latitudeString);
165 var isLongitudeValid = isUserInputValid(longitudeString);
167 if (!isLatitudeValid && !isLongitudeValid)
168 return null;
170 var latitude = isLatitudeValid ? parseFloat(latitudeString) : -1;
171 var longitude = isLongitudeValid ? parseFloat(longitudeString) : -1;
173 return new WebInspector.OverridesSupport.GeolocationPosition(latitude, longitude, errorStatus ? "PositionUnavailable" : "");
177 * @constructor
178 * @param {number} alpha
179 * @param {number} beta
180 * @param {number} gamma
182 WebInspector.OverridesSupport.DeviceOrientation = function(alpha, beta, gamma)
184 this.alpha = alpha;
185 this.beta = beta;
186 this.gamma = gamma;
189 WebInspector.OverridesSupport.DeviceOrientation.prototype = {
191 * @return {string}
193 toSetting: function()
195 return JSON.stringify(this);
200 * @return {!WebInspector.OverridesSupport.DeviceOrientation}
202 WebInspector.OverridesSupport.DeviceOrientation.parseSetting = function(value)
204 if (value) {
205 var jsonObject = JSON.parse(value);
206 return new WebInspector.OverridesSupport.DeviceOrientation(jsonObject.alpha, jsonObject.beta, jsonObject.gamma);
208 return new WebInspector.OverridesSupport.DeviceOrientation(0, 0, 0);
212 * @return {?WebInspector.OverridesSupport.DeviceOrientation}
214 WebInspector.OverridesSupport.DeviceOrientation.parseUserInput = function(alphaString, betaString, gammaString)
216 function isUserInputValid(value)
218 if (!value)
219 return true;
220 return /^[-]?[0-9]*[.]?[0-9]*$/.test(value);
223 if (!alphaString && !betaString && !gammaString)
224 return null;
226 var isAlphaValid = isUserInputValid(alphaString);
227 var isBetaValid = isUserInputValid(betaString);
228 var isGammaValid = isUserInputValid(gammaString);
230 if (!isAlphaValid && !isBetaValid && !isGammaValid)
231 return null;
233 var alpha = isAlphaValid ? parseFloat(alphaString) : -1;
234 var beta = isBetaValid ? parseFloat(betaString) : -1;
235 var gamma = isGammaValid ? parseFloat(gammaString) : -1;
237 return new WebInspector.OverridesSupport.DeviceOrientation(alpha, beta, gamma);
241 * @param {string} value
242 * @return {string}
244 WebInspector.OverridesSupport.deviceSizeValidator = function(value)
246 if (!value || (/^[\d]+$/.test(value) && value >= 0 && value <= WebInspector.OverridesSupport.MaxDeviceSize))
247 return "";
248 return WebInspector.UIString("Value must be non-negative integer");
252 * @param {string} value
253 * @return {string}
255 WebInspector.OverridesSupport.deviceScaleFactorValidator = function(value)
257 if (!value || (/^[\d]+(\.\d+)?|\.\d+$/.test(value) && value >= 0 && value <= 10))
258 return "";
259 return WebInspector.UIString("Value must be non-negative float");
262 WebInspector.OverridesSupport._touchEventsScriptIdSymbol = Symbol("OverridesSupport.touchEventsScriptIdSymbol");
264 WebInspector.OverridesSupport.prototype = {
266 * @return {boolean}
268 canEmulate: function()
270 return !!this._target && this._targetCanEmulate;
274 * @return {boolean}
276 emulationEnabled: function()
278 return this.canEmulate() && this.settings._emulationEnabled.get();
282 * @param {boolean} enabled
284 setEmulationEnabled: function(enabled)
286 if (this.canEmulate()) {
287 this.settings._emulationEnabled.set(enabled);
288 this.dispatchEventToListeners(WebInspector.OverridesSupport.Events.EmulationStateChanged);
289 if (enabled && this.settings.emulateResolution.get())
290 this._target.emulationAgent().resetScrollAndPageScaleFactor();
295 * @param {!WebInspector.Target} target
296 * @param {function()} callback
298 init: function(target, callback)
300 if (target.isPage())
301 target.emulationAgent().canEmulate(canEmulateCallback.bind(this));
302 else
303 canEmulateCallback.call(this, null, false);
306 * @param {?Protocol.Error} error
307 * @param {boolean} canEmulate
308 * @this {WebInspector.OverridesSupport}
310 function canEmulateCallback(error, canEmulate)
312 this._target = target;
313 this._targetCanEmulate = !error && canEmulate;
314 this._initialized = true;
316 if (this.canEmulate()) {
317 target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this);
318 var domModel = WebInspector.DOMModel.fromTarget(this._target);
319 if (domModel)
320 domModel.addEventListener(WebInspector.DOMModel.Events.InspectModeWillBeToggled, this._inspectModeWillBeToggled, this);
321 this._applyInitialOverrides();
324 this.dispatchEventToListeners(WebInspector.OverridesSupport.Events.EmulationStateChanged);
326 callback();
331 * @param {?WebInspector.OverridesSupport.PageResizer} pageResizer
332 * @param {!Size} availableSize
333 * @param {!Insets} insets
335 setPageResizer: function(pageResizer, availableSize, insets)
337 if (pageResizer === this._pageResizer)
338 return;
340 if (this._pageResizer) {
341 this._pageResizer.removeEventListener(WebInspector.OverridesSupport.PageResizer.Events.AvailableSizeChanged, this._onPageResizerAvailableSizeChanged, this);
342 this._pageResizer.removeEventListener(WebInspector.OverridesSupport.PageResizer.Events.ResizeRequested, this._onPageResizerResizeRequested, this);
343 this._pageResizer.removeEventListener(WebInspector.OverridesSupport.PageResizer.Events.FixedScaleRequested, this._onPageResizerFixedScaleRequested, this);
344 this._pageResizer.removeEventListener(WebInspector.OverridesSupport.PageResizer.Events.InsetsChanged, this._onPageResizerInsetsChanged, this);
346 this._pageResizer = pageResizer;
347 this._pageResizerAvailableSize = availableSize;
348 this._pageResizerInsets = insets;
349 if (this._pageResizer) {
350 this._pageResizer.addEventListener(WebInspector.OverridesSupport.PageResizer.Events.AvailableSizeChanged, this._onPageResizerAvailableSizeChanged, this);
351 this._pageResizer.addEventListener(WebInspector.OverridesSupport.PageResizer.Events.ResizeRequested, this._onPageResizerResizeRequested, this);
352 this._pageResizer.addEventListener(WebInspector.OverridesSupport.PageResizer.Events.FixedScaleRequested, this._onPageResizerFixedScaleRequested, this);
353 this._pageResizer.addEventListener(WebInspector.OverridesSupport.PageResizer.Events.InsetsChanged, this._onPageResizerInsetsChanged, this);
355 this._deviceMetricsChanged(false);
359 * @param {!WebInspector.OverridesSupport.Device} device
361 emulateDevice: function(device)
363 this._deviceMetricsChangedListenerMuted = true;
364 this._userAgentChangedListenerMuted = true;
365 this.settings.userAgent.set(device.userAgent);
366 this.settings.emulateResolution.set(true);
367 this.settings.deviceWidth.set(device.width);
368 this.settings.deviceHeight.set(device.height);
369 this.settings.deviceScaleFactor.set(device.deviceScaleFactor);
370 this.settings.emulateTouch.set(device.touch);
371 this.settings.emulateMobile.set(device.mobile);
372 delete this._deviceMetricsChangedListenerMuted;
373 delete this._userAgentChangedListenerMuted;
375 if (this._initialized) {
376 this._deviceMetricsChanged(true);
377 this._userAgentChanged();
381 reset: function()
383 this._deviceMetricsChangedListenerMuted = true;
384 this._userAgentChangedListenerMuted = true;
385 this.settings.userAgent.set("");
386 this.settings.emulateResolution.set(false);
387 this.settings.deviceScaleFactor.set(0);
388 this.settings.emulateTouch.set(false);
389 this.settings.emulateMobile.set(false);
390 this.settings.overrideDeviceOrientation.set(false);
391 this.settings.screenOrientationOverride.set("");
392 this.settings.overrideGeolocation.set(false);
393 this.settings.overrideCSSMedia.set(false);
394 delete this._deviceMetricsChangedListenerMuted;
395 delete this._userAgentChangedListenerMuted;
397 if (this._initialized) {
398 this._deviceMetricsChanged(false);
399 this._userAgentChanged();
404 * @param {!WebInspector.OverridesSupport.Device} device
405 * @return {boolean}
407 isEmulatingDevice: function(device)
409 var sameResolution = this.settings.emulateResolution.get() ?
410 (this.settings.deviceWidth.get() === device.width && this.settings.deviceHeight.get() === device.height && this.settings.deviceScaleFactor.get() === device.deviceScaleFactor) :
411 (!device.width && !device.height && !device.deviceScaleFactor);
412 return this.settings.userAgent.get() === device.userAgent
413 && this.settings.emulateTouch.get() === device.touch
414 && this.settings.emulateMobile.get() === device.mobile
415 && sameResolution;
419 * @param {!WebInspector.Event} event
421 _inspectModeWillBeToggled: function(event)
423 var inspectModeEnabled = /** @type {boolean} */ (event.data);
424 this._touchEmulationSuspended = inspectModeEnabled;
425 this._emulateTouchEventsChanged();
428 _applyInitialOverrides: function()
430 this.settings._emulationEnabled.addChangeListener(this._userAgentChanged, this);
431 this.settings.userAgent.addChangeListener(this._userAgentChanged, this);
433 this.settings._emulationEnabled.addChangeListener(this._deviceMetricsChanged.bind(this, false));
434 this.settings.emulateResolution.addChangeListener(this._deviceMetricsChanged.bind(this, false));
435 this.settings.deviceWidth.addChangeListener(this._deviceMetricsChanged.bind(this, false));
436 this.settings.deviceHeight.addChangeListener(this._deviceMetricsChanged.bind(this, false));
437 this.settings.deviceScaleFactor.addChangeListener(this._deviceMetricsChanged.bind(this, false));
438 this.settings.emulateMobile.addChangeListener(this._deviceMetricsChanged.bind(this, false));
439 this.settings.deviceFitWindow.addChangeListener(this._deviceMetricsChanged.bind(this, false));
441 this.settings._emulationEnabled.addChangeListener(this._geolocationPositionChanged, this);
442 this.settings.overrideGeolocation.addChangeListener(this._geolocationPositionChanged, this);
443 this.settings.geolocationOverride.addChangeListener(this._geolocationPositionChanged, this);
445 this.settings._emulationEnabled.addChangeListener(this._deviceOrientationChanged, this);
446 this.settings.overrideDeviceOrientation.addChangeListener(this._deviceOrientationChanged, this);
447 this.settings.deviceOrientationOverride.addChangeListener(this._deviceOrientationChanged, this);
449 this.settings._emulationEnabled.addChangeListener(this._screenOrientationChanged, this);
450 this.settings.screenOrientationOverride.addChangeListener(this._screenOrientationChanged, this);
452 this.settings._emulationEnabled.addChangeListener(this._emulateTouchEventsChanged, this);
453 this.settings.emulateTouch.addChangeListener(this._emulateTouchEventsChanged, this);
455 this.settings._emulationEnabled.addChangeListener(this._cssMediaChanged, this);
456 this.settings.overrideCSSMedia.addChangeListener(this._cssMediaChanged, this);
457 this.settings.emulatedCSSMedia.addChangeListener(this._cssMediaChanged, this);
459 this.settings.javaScriptDisabled.addChangeListener(this._javaScriptDisabledChanged, this);
460 this._javaScriptDisabledChanged();
462 this.settings._emulationEnabled.addChangeListener(this._showRulersChanged, this);
463 WebInspector.moduleSetting("showMetricsRulers").addChangeListener(this._showRulersChanged, this);
464 this._showRulersChanged();
466 if (this.emulationEnabled()) {
467 if (this.settings.overrideDeviceOrientation.get())
468 this._deviceOrientationChanged();
470 if (this.settings.screenOrientationOverride.get())
471 this._screenOrientationChanged();
473 if (this.settings.overrideGeolocation.get())
474 this._geolocationPositionChanged();
476 if (this.settings.emulateTouch.get())
477 this._emulateTouchEventsChanged();
479 if (this.settings.overrideCSSMedia.get())
480 this._cssMediaChanged();
482 this._deviceMetricsChanged(true);
484 this._userAgentChanged();
488 _userAgentChanged: function()
490 if (this._userAgentChangedListenerMuted)
491 return;
492 var userAgent = this.emulationEnabled() ? this.settings.userAgent.get() : "";
493 WebInspector.multitargetNetworkManager.setUserAgentOverride(userAgent);
494 if (this._userAgent !== userAgent)
495 this._updateUserAgentWarningMessage(WebInspector.UIString("You might need to reload the page for proper user agent spoofing and viewport rendering."));
496 this._userAgent = userAgent;
500 * @param {!WebInspector.Event} event
502 _onPageResizerAvailableSizeChanged: function(event)
504 this._pageResizerAvailableSize = /** @type {!Size} */ (event.data.size);
505 this._pageResizerInsets = /** @type {!Insets} */ (event.data.insets);
506 this._deviceMetricsChanged(false);
510 * @param {!WebInspector.Event} event
512 _onPageResizerInsetsChanged: function(event)
514 this._pageResizerInsets = /** @type {!Insets} */ (event.data);
518 * @param {!WebInspector.Event} event
520 _onPageResizerResizeRequested: function(event)
522 if (typeof event.data.width !== "undefined") {
523 var width = /** @type {number} */ (event.data.width);
524 if (width !== this.settings.deviceWidth.get())
525 this.settings.deviceWidth.set(width);
527 if (typeof event.data.height !== "undefined") {
528 var height = /** @type {number} */ (event.data.height);
529 if (height !== this.settings.deviceHeight.get())
530 this.settings.deviceHeight.set(height);
535 * @param {!WebInspector.Event} event
537 _onPageResizerFixedScaleRequested: function(event)
539 this._fixedDeviceScale = /** @type {boolean} */ (event.data);
540 this._deviceMetricsChanged(false);
544 * @param {boolean} resetScrollAndPageScale
546 _deviceMetricsChanged: function(resetScrollAndPageScale)
548 if (!this._initialized)
549 return;
551 this._showRulersChanged();
553 if (this._deviceMetricsChangedListenerMuted)
554 return;
556 if (!this.emulationEnabled()) {
557 this._deviceMetricsThrottler.schedule(clearDeviceMetricsOverride.bind(this));
558 if (this._pageResizer)
559 this._pageResizer.update(0, 0, 1);
560 return;
563 var dipWidth = this.settings.emulateResolution.get() ? this.settings.deviceWidth.get() : 0;
564 var dipHeight = this.settings.emulateResolution.get() ? this.settings.deviceHeight.get() : 0;
566 var overrideWidth = dipWidth;
567 var overrideHeight = dipHeight;
568 var screenWidth = dipWidth;
569 var screenHeight = dipHeight;
570 var positionX = 0;
571 var positionY = 0;
572 var scale = 1;
573 if (this._pageResizer) {
574 var available = this._pageResizerAvailableSize;
575 var insets = this._pageResizerInsets;
576 if (this.settings.deviceFitWindow.get()) {
577 if (this._fixedDeviceScale) {
578 scale = this._deviceScale;
579 } else {
580 scale = 1;
581 while (available.width < (dipWidth + insets.left + insets.right) * scale || available.height < (dipHeight + insets.top + insets.bottom) * scale)
582 scale *= 0.8;
586 this._pageResizer.update(Math.min(dipWidth * scale, available.width - insets.left * scale), Math.min(dipHeight * scale, available.height - insets.top * scale), scale);
587 if (scale === 1 && available.width >= dipWidth && available.height >= dipHeight) {
588 // When we have enough space, no page size override is required. This will speed things up and remove lag.
589 overrideWidth = 0;
590 overrideHeight = 0;
592 if (dipWidth === 0 && dipHeight !== 0)
593 overrideWidth = Math.round(available.width / scale);
594 if (dipHeight === 0 && dipWidth !== 0)
595 overrideHeight = Math.round(available.height / scale);
596 screenWidth = dipWidth + insets.left + insets.right;
597 screenHeight = dipHeight + insets.top + insets.bottom;
598 positionX = insets.left;
599 positionY = insets.top;
601 this._deviceScale = scale;
603 this._deviceMetricsThrottler.schedule(setDeviceMetricsOverride.bind(this));
606 * @this {WebInspector.OverridesSupport}
607 * @return {!Promise.<?>}
609 function setDeviceMetricsOverride()
611 var setDevicePromise = this._target.emulationAgent().setDeviceMetricsOverride(
612 overrideWidth, overrideHeight, this.settings.emulateResolution.get() ? this.settings.deviceScaleFactor.get() : 0,
613 this.settings.emulateMobile.get(), this._pageResizer ? false : this.settings.deviceFitWindow.get(), scale, 0, 0,
614 screenWidth, screenHeight, positionX, positionY, apiCallback.bind(this))
615 var allPromises = [ setDevicePromise ];
616 if (resetScrollAndPageScale)
617 allPromises.push(this._target.emulationAgent().resetScrollAndPageScaleFactor());
618 return Promise.all(allPromises);
622 * @this {WebInspector.OverridesSupport}
623 * @return {!Promise.<?>}
625 function clearDeviceMetricsOverride()
627 return this._target.emulationAgent().clearDeviceMetricsOverride(apiCallback.bind(this))
631 * @param {?Protocol.Error} error
632 * @this {WebInspector.OverridesSupport}
634 function apiCallback(error)
636 if (error) {
637 this._updateDeviceMetricsWarningMessage(WebInspector.UIString("Screen emulation is not available on this page."));
638 this._deviceMetricsOverrideAppliedForTest();
639 return;
642 var mobileEnabled = this.emulationEnabled() && this.settings.emulateMobile.get();
643 if (this._emulateMobileEnabled !== mobileEnabled)
644 this._updateDeviceMetricsWarningMessage(WebInspector.UIString("You might need to reload the page for proper user agent spoofing and viewport rendering."));
645 this._emulateMobileEnabled = mobileEnabled;
646 this._deviceMetricsOverrideAppliedForTest();
650 _deviceMetricsOverrideAppliedForTest: function()
652 // Used for sniffing in tests.
655 _geolocationPositionChanged: function()
657 if (!this.emulationEnabled() || !this.settings.overrideGeolocation.get()) {
658 this._target.emulationAgent().clearGeolocationOverride();
659 return;
661 var geolocation = WebInspector.OverridesSupport.GeolocationPosition.parseSetting(this.settings.geolocationOverride.get());
662 if (geolocation.error)
663 this._target.emulationAgent().setGeolocationOverride();
664 else
665 this._target.emulationAgent().setGeolocationOverride(geolocation.latitude, geolocation.longitude, 150);
668 _deviceOrientationChanged: function()
670 if (!this.emulationEnabled() || !this.settings.overrideDeviceOrientation.get()) {
671 this._target.deviceOrientationAgent().clearDeviceOrientationOverride();
672 return;
675 var deviceOrientation = WebInspector.OverridesSupport.DeviceOrientation.parseSetting(this.settings.deviceOrientationOverride.get());
676 this._target.deviceOrientationAgent().setDeviceOrientationOverride(deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma);
679 _screenOrientationChanged: function()
681 if (!this.emulationEnabled() || !this.settings.screenOrientationOverride.get()) {
682 this._target.screenOrientationAgent().clearScreenOrientationOverride();
683 return;
686 var screenOrientation = this.settings.screenOrientationOverride.get();
687 this._target.screenOrientationAgent().setScreenOrientationOverride(screenOrientation === "landscapePrimary" ? 90 : 0, screenOrientation);
690 _emulateTouchEventsChanged: function()
692 var emulationEnabled = this.emulationEnabled() && this.settings.emulateTouch.get() && !this._touchEmulationSuspended;
693 var configuration = this.settings.emulateMobile.get() ? "mobile" : "desktop";
694 var target = this._target;
697 * @suppressGlobalPropertiesCheck
699 const injectedFunction = function() {
700 const touchEvents = ["ontouchstart", "ontouchend", "ontouchmove", "ontouchcancel"];
701 var recepients = [window.__proto__, document.__proto__];
702 for (var i = 0; i < touchEvents.length; ++i) {
703 for (var j = 0; j < recepients.length; ++j) {
704 if (!(touchEvents[i] in recepients[j]))
705 Object.defineProperty(recepients[j], touchEvents[i], { value: null, writable: true, configurable: true, enumerable: true });
710 var symbol = WebInspector.OverridesSupport._touchEventsScriptIdSymbol;
712 if (typeof target[symbol] !== "undefined") {
713 target.pageAgent().removeScriptToEvaluateOnLoad(target[symbol]);
714 delete target[symbol];
717 if (emulationEnabled)
718 target.pageAgent().addScriptToEvaluateOnLoad("(" + injectedFunction.toString() + ")()", scriptAddedCallback);
721 * @param {?Protocol.Error} error
722 * @param {string} scriptId
724 function scriptAddedCallback(error, scriptId)
726 if (error)
727 delete target[symbol];
728 else
729 target[symbol] = scriptId;
732 target.emulationAgent().setTouchEmulationEnabled(emulationEnabled, configuration);
735 _cssMediaChanged: function()
737 var enabled = this.emulationEnabled() && this.settings.overrideCSSMedia.get();
738 this._target.emulationAgent().setEmulatedMedia(enabled ? this.settings.emulatedCSSMedia.get() : "");
739 var cssModel = WebInspector.CSSStyleModel.fromTarget(this._target);
740 if (cssModel)
741 cssModel.mediaQueryResultChanged();
744 _javaScriptDisabledChanged: function()
746 this._target.emulationAgent().setScriptExecutionDisabled(this.settings.javaScriptDisabled.get());
749 _pageResizerActive: function()
751 return this._pageResizer && this.emulationEnabled();
754 _showRulersChanged: function()
756 var showRulersValue = WebInspector.moduleSetting("showMetricsRulers").get();
757 for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) {
758 target.pageAgent().setShowViewportSizeOnResize(!this._pageResizerActive(), showRulersValue);
759 var domModel = WebInspector.DOMModel.fromTarget(target);
760 if (domModel)
761 domModel.setHighlightSettings(showRulersValue && !this._pageResizerActive(), showRulersValue);
765 _onMainFrameNavigated: function()
767 this._deviceMetricsChanged(false);
768 this._updateUserAgentWarningMessage("");
769 this._updateDeviceMetricsWarningMessage("");
772 _dispatchWarningChanged: function()
774 this.dispatchEventToListeners(WebInspector.OverridesSupport.Events.OverridesWarningUpdated);
778 * @param {string} warningMessage
780 _updateDeviceMetricsWarningMessage: function(warningMessage)
782 this._deviceMetricsWarningMessage = warningMessage;
783 this._dispatchWarningChanged();
787 * @param {string} warningMessage
789 _updateUserAgentWarningMessage: function(warningMessage)
791 this._userAgentWarningMessage = warningMessage;
792 this._dispatchWarningChanged();
796 * @return {string}
798 warningMessage: function()
800 return this._deviceMetricsWarningMessage || this._userAgentWarningMessage || "";
803 clearWarningMessage: function()
805 this._deviceMetricsWarningMessage = "";
806 this._userAgentWarningMessage = "";
807 this._dispatchWarningChanged();
810 swapDimensions: function()
812 var width = WebInspector.overridesSupport.settings.deviceWidth.get();
813 var height = WebInspector.overridesSupport.settings.deviceHeight.get();
814 WebInspector.overridesSupport.settings.deviceWidth.set(height);
815 WebInspector.overridesSupport.settings.deviceHeight.set(width);
818 __proto__: WebInspector.Object.prototype
823 * @type {!WebInspector.OverridesSupport}
825 WebInspector.overridesSupport;