mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-27 20:25:44 +00:00
efbf4624b2
Only `simulator-core` is used by new RDM via the Emulation actor, so I've moved this server side and renamed it to `touch-simulator`. MozReview-Commit-ID: 5YgpYNDwBvw --HG-- rename : devtools/shared/touch/moz.build => devtools/server/actors/emulation/moz.build rename : devtools/shared/touch/simulator-core.js => devtools/server/actors/emulation/touch-simulator.js extra : rebase_source : d38f3fa09c8e187440be716e993d42c88a10da2a
238 lines
6.6 KiB
JavaScript
238 lines
6.6 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
const { Ci } = require("chrome");
|
|
const protocol = require("devtools/shared/protocol");
|
|
const { emulationSpec } = require("devtools/shared/specs/emulation");
|
|
const { TouchSimulator } = require("devtools/server/actors/emulation/touch-simulator");
|
|
|
|
/**
|
|
* This actor overrides various browser features to simulate different environments to
|
|
* test how pages perform under various conditions.
|
|
*
|
|
* The design below, which saves the previous value of each property before setting, is
|
|
* needed because it's possible to have multiple copies of this actor for a single page.
|
|
* When some instance of this actor changes a property, we want it to be able to restore
|
|
* that property to the way it was found before the change.
|
|
*
|
|
* A subtle aspect of the code below is that all get* methods must return non-undefined
|
|
* values, so that the absence of a previous value can be distinguished from the value for
|
|
* "no override" for each of the properties.
|
|
*/
|
|
let EmulationActor = protocol.ActorClassWithSpec(emulationSpec, {
|
|
|
|
initialize(conn, tabActor) {
|
|
protocol.Actor.prototype.initialize.call(this, conn);
|
|
this.tabActor = tabActor;
|
|
this.docShell = tabActor.docShell;
|
|
this.touchSimulator = new TouchSimulator(tabActor.chromeEventHandler);
|
|
},
|
|
|
|
destroy() {
|
|
this.clearDPPXOverride();
|
|
this.clearNetworkThrottling();
|
|
this.clearTouchEventsOverride();
|
|
this.clearUserAgentOverride();
|
|
this.tabActor = null;
|
|
this.docShell = null;
|
|
this.touchSimulator = null;
|
|
protocol.Actor.prototype.destroy.call(this);
|
|
},
|
|
|
|
/**
|
|
* Retrieve the console actor for this tab. This allows us to expose network throttling
|
|
* as part of emulation settings, even though it's internally connected to the network
|
|
* monitor, which for historical reasons is part of the console actor.
|
|
*/
|
|
get _consoleActor() {
|
|
if (this.tabActor.exited) {
|
|
return null;
|
|
}
|
|
let form = this.tabActor.form();
|
|
return this.conn._getOrCreateActor(form.consoleActor);
|
|
},
|
|
|
|
/* DPPX override */
|
|
|
|
_previousDPPXOverride: undefined,
|
|
|
|
setDPPXOverride(dppx) {
|
|
if (this.getDPPXOverride() === dppx) {
|
|
return false;
|
|
}
|
|
|
|
if (this._previousDPPXOverride === undefined) {
|
|
this._previousDPPXOverride = this.getDPPXOverride();
|
|
}
|
|
|
|
this.docShell.contentViewer.overrideDPPX = dppx;
|
|
|
|
return true;
|
|
},
|
|
|
|
getDPPXOverride() {
|
|
return this.docShell.contentViewer.overrideDPPX;
|
|
},
|
|
|
|
clearDPPXOverride() {
|
|
if (this._previousDPPXOverride !== undefined) {
|
|
return this.setDPPXOverride(this._previousDPPXOverride);
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/* Network Throttling */
|
|
|
|
_previousNetworkThrottling: undefined,
|
|
|
|
/**
|
|
* Transform the RDP format into the internal format and then set network throttling.
|
|
*/
|
|
setNetworkThrottling({ downloadThroughput, uploadThroughput, latency }) {
|
|
let throttleData = {
|
|
latencyMean: latency,
|
|
latencyMax: latency,
|
|
downloadBPSMean: downloadThroughput,
|
|
downloadBPSMax: downloadThroughput,
|
|
uploadBPSMean: uploadThroughput,
|
|
uploadBPSMax: uploadThroughput,
|
|
};
|
|
return this._setNetworkThrottling(throttleData);
|
|
},
|
|
|
|
_setNetworkThrottling(throttleData) {
|
|
let current = this._getNetworkThrottling();
|
|
// Check if they are both objects or both null
|
|
let match = throttleData == current;
|
|
// If both objects, check all entries
|
|
if (match && current && throttleData) {
|
|
match = Object.entries(current).every(([ k, v ]) => {
|
|
return throttleData[k] === v;
|
|
});
|
|
}
|
|
if (match) {
|
|
return false;
|
|
}
|
|
|
|
if (this._previousNetworkThrottling === undefined) {
|
|
this._previousNetworkThrottling = current;
|
|
}
|
|
|
|
let consoleActor = this._consoleActor;
|
|
if (!consoleActor) {
|
|
return false;
|
|
}
|
|
consoleActor.onStartListeners({
|
|
listeners: [ "NetworkActivity" ],
|
|
});
|
|
consoleActor.onSetPreferences({
|
|
preferences: {
|
|
"NetworkMonitor.throttleData": throttleData,
|
|
}
|
|
});
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* Get network throttling and then transform the internal format into the RDP format.
|
|
*/
|
|
getNetworkThrottling() {
|
|
let throttleData = this._getNetworkThrottling();
|
|
if (!throttleData) {
|
|
return null;
|
|
}
|
|
let { downloadBPSMax, uploadBPSMax, latencyMax } = throttleData;
|
|
return {
|
|
downloadThroughput: downloadBPSMax,
|
|
uploadThroughput: uploadBPSMax,
|
|
latency: latencyMax,
|
|
};
|
|
},
|
|
|
|
_getNetworkThrottling() {
|
|
let consoleActor = this._consoleActor;
|
|
if (!consoleActor) {
|
|
return null;
|
|
}
|
|
let prefs = consoleActor.onGetPreferences({
|
|
preferences: [ "NetworkMonitor.throttleData" ],
|
|
});
|
|
return prefs.preferences["NetworkMonitor.throttleData"] || null;
|
|
},
|
|
|
|
clearNetworkThrottling() {
|
|
if (this._previousNetworkThrottling !== undefined) {
|
|
return this._setNetworkThrottling(this._previousNetworkThrottling);
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/* Touch events override */
|
|
|
|
_previousTouchEventsOverride: undefined,
|
|
|
|
setTouchEventsOverride(flag) {
|
|
if (this.getTouchEventsOverride() == flag) {
|
|
return false;
|
|
}
|
|
if (this._previousTouchEventsOverride === undefined) {
|
|
this._previousTouchEventsOverride = this.getTouchEventsOverride();
|
|
}
|
|
|
|
// Start or stop the touch simulator depending on the override flag
|
|
if (flag == Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED) {
|
|
this.touchSimulator.start();
|
|
} else {
|
|
this.touchSimulator.stop();
|
|
}
|
|
|
|
this.docShell.touchEventsOverride = flag;
|
|
return true;
|
|
},
|
|
|
|
getTouchEventsOverride() {
|
|
return this.docShell.touchEventsOverride;
|
|
},
|
|
|
|
clearTouchEventsOverride() {
|
|
if (this._previousTouchEventsOverride !== undefined) {
|
|
return this.setTouchEventsOverride(this._previousTouchEventsOverride);
|
|
}
|
|
return false;
|
|
},
|
|
|
|
/* User agent override */
|
|
|
|
_previousUserAgentOverride: undefined,
|
|
|
|
setUserAgentOverride(userAgent) {
|
|
if (this.getUserAgentOverride() == userAgent) {
|
|
return false;
|
|
}
|
|
if (this._previousUserAgentOverride === undefined) {
|
|
this._previousUserAgentOverride = this.getUserAgentOverride();
|
|
}
|
|
this.docShell.customUserAgent = userAgent;
|
|
return true;
|
|
},
|
|
|
|
getUserAgentOverride() {
|
|
return this.docShell.customUserAgent;
|
|
},
|
|
|
|
clearUserAgentOverride() {
|
|
if (this._previousUserAgentOverride !== undefined) {
|
|
return this.setUserAgentOverride(this._previousUserAgentOverride);
|
|
}
|
|
return false;
|
|
},
|
|
|
|
});
|
|
|
|
exports.EmulationActor = EmulationActor;
|