Bug 1704028 - [devtools] Enable touch simulation in remote frame. r=ochameau,devtools-backward-compat-reviewers.

This patch removes the `setTouchEventsOverride` method on the targetConfigurationCommand,
as we're now enabling the touch simulation from the server, in `BrowsingContextActor#updateTargetConfiguration`.
A new configuration property is added, `reloadOnTouchSimulationToggle`, so the
actor is responsible for reloading the page if the user set the pref.
The `touchSimulator` property is moved from the responsive actor to the browsingContext one
to facilitate managing the touch simulation state.

Differential Revision: https://phabricator.services.mozilla.com/D116103
This commit is contained in:
Nicolas Chevobbe 2021-06-03 11:28:00 +00:00
Родитель aaeff5b146
Коммит a5de5d21cf
9 изменённых файлов: 101 добавлений и 163 удалений

Просмотреть файл

@ -18,13 +18,8 @@ addRDMTask(TEST_URL, async function({ ui, manager }) {
const browser = ui.getViewportBrowser();
for (const mv in [true, false]) {
const reloadNeeded = await ui.updateTouchSimulation(mv);
if (reloadNeeded) {
info("Reload is needed -- waiting for it.");
const reload = waitForViewportLoad(ui);
browser.reload();
await reload;
}
await ui.updateTouchSimulation(mv);
info("Setting focus on the browser.");
browser.focus();

Просмотреть файл

@ -852,16 +852,13 @@ function rotateViewport(ui) {
// Call this to switch between on/off support for meta viewports.
async function setTouchAndMetaViewportSupport(ui, value) {
const reloadNeeded = await ui.updateTouchSimulation(value);
if (reloadNeeded) {
info("Reload is needed -- waiting for it.");
const reload = waitForViewportLoad(ui);
const browser = ui.getViewportBrowser();
browser.reload();
await reload;
await promiseContentReflow(ui);
}
return reloadNeeded;
await ui.updateTouchSimulation(value);
info("Reload so the new configuration applies cleanly to the page");
const reload = waitForViewportLoad(ui);
const browser = ui.getViewportBrowser();
browser.reload();
await reload;
await promiseContentReflow(ui);
}
// This function checks that zoom, layout viewport width and height

Просмотреть файл

@ -307,9 +307,11 @@ class ResponsiveUI {
await this.updateDPPX(null);
reloadNeeded |=
(await this.updateUserAgent()) && this.reloadOnChange("userAgent");
reloadNeeded |=
(await this.updateTouchSimulation()) &&
this.reloadOnChange("touchSimulation");
// Don't reload on the server if we're already doing a reload on the client
const reloadOnTouchSimulationChange =
this.reloadOnChange("touchSimulation") && !reloadNeeded;
await this.updateTouchSimulation(null, reloadOnTouchSimulationChange);
if (reloadNeeded) {
await this.reloadBrowser();
}
@ -489,9 +491,12 @@ class ResponsiveUI {
reloadNeeded |=
(await this.updateUserAgent(userAgent)) &&
this.reloadOnChange("userAgent");
reloadNeeded |=
(await this.updateTouchSimulation(touch)) &&
this.reloadOnChange("touchSimulation");
// Don't reload on the server if we're already doing a reload on the client
const reloadOnTouchSimulationChange =
this.reloadOnChange("touchSimulation") && !reloadNeeded;
await this.updateTouchSimulation(touch, reloadOnTouchSimulationChange);
if (reloadNeeded) {
this.reloadBrowser();
}
@ -516,12 +521,11 @@ class ResponsiveUI {
await this.updateMaxTouchPointsEnabled(enabled);
const reloadNeeded =
(await this.updateTouchSimulation(enabled)) &&
this.reloadOnChange("touchSimulation");
if (reloadNeeded) {
this.reloadBrowser();
}
await this.updateTouchSimulation(
enabled,
this.reloadOnChange("touchSimulation")
);
// Used by tests
this.emit("touch-simulation-changed");
}
@ -547,9 +551,11 @@ class ResponsiveUI {
await this.updateDPPX(null);
reloadNeeded |=
(await this.updateUserAgent()) && this.reloadOnChange("userAgent");
reloadNeeded |=
(await this.updateTouchSimulation()) &&
this.reloadOnChange("touchSimulation");
// Don't reload on the server if we're already doing a reload on the client
const reloadOnTouchSimulationChange =
this.reloadOnChange("touchSimulation") && !reloadNeeded;
await this.updateTouchSimulation(null, reloadOnTouchSimulationChange);
if (reloadNeeded) {
this.reloadBrowser();
}
@ -790,12 +796,11 @@ class ResponsiveUI {
await this.updateScreenOrientation(type, angle);
await this.updateMaxTouchPointsEnabled(touchSimulationEnabled);
let reloadNeeded = false;
if (touchSimulationEnabled) {
reloadNeeded |=
(await this.updateTouchSimulation(touchSimulationEnabled)) &&
this.reloadOnChange("touchSimulation");
await this.updateTouchSimulation(touchSimulationEnabled);
}
let reloadNeeded = false;
if (userAgent) {
reloadNeeded |=
(await this.updateUserAgent(userAgent)) &&
@ -867,32 +872,31 @@ class ResponsiveUI {
* false, this method will clear all touch simulation and meta viewport
* overrides, returning to default behavior for both settings.
*
* @return boolean
* Whether a reload is needed to apply the override change(s).
* @param {boolean} enabled
* @param {boolean} reloadOnTouchSimulationToggle: Set to true to trigger a page reload
* if the touch simulation state changes.
*/
async updateTouchSimulation(enabled) {
let reloadNeeded;
async updateTouchSimulation(enabled, reloadOnTouchSimulationToggle) {
// Call setMetaViewportOverride so the server would be in the expected state when/if
// the document reloads (as part of the call to updateConfiguration).
if (enabled) {
reloadNeeded = await this.commands.targetConfigurationCommand.setTouchEventsOverride(
"enabled"
);
const metaViewportEnabled = Services.prefs.getBoolPref(
"devtools.responsive.metaViewport.enabled",
false
);
if (metaViewportEnabled) {
reloadNeeded |= await this.responsiveFront.setMetaViewportOverride(
await this.responsiveFront.setMetaViewportOverride(
Ci.nsIDocShell.META_VIEWPORT_OVERRIDE_ENABLED
);
}
} else {
reloadNeeded = await this.commands.targetConfigurationCommand.setTouchEventsOverride(
null
);
reloadNeeded |= await this.responsiveFront.clearMetaViewportOverride();
await this.responsiveFront.clearMetaViewportOverride();
}
return reloadNeeded;
await this.commands.targetConfigurationCommand.updateConfiguration({
touchEventsOverride: enabled ? "enabled" : null,
reloadOnTouchSimulationToggle,
});
}
/**

Просмотреть файл

@ -9,13 +9,6 @@ const Services = require("Services");
const protocol = require("devtools/shared/protocol");
const { responsiveSpec } = require("devtools/shared/specs/responsive");
loader.lazyRequireGetter(
this,
"TouchSimulator",
"devtools/server/actors/emulation/touch-simulator",
true
);
const FLOATING_SCROLLBARS_SHEET = Services.io.newURI(
"chrome://devtools/skin/floating-scrollbars-responsive-design.css"
);
@ -46,14 +39,12 @@ const ResponsiveActor = protocol.ActorClassWithSpec(responsiveSpec, {
destroy() {
this.clearNetworkThrottling();
this.toggleTouchSimulator({ enable: false });
this.clearMetaViewportOverride();
this.targetActor.off("window-ready", this.onWindowReady);
this.targetActor = null;
this.docShell = null;
this._touchSimulator = null;
protocol.Actor.prototype.destroy.call(this);
},
@ -75,16 +66,6 @@ const ResponsiveActor = protocol.ActorClassWithSpec(responsiveSpec, {
return this.conn._getOrCreateActor(form.consoleActor);
},
get touchSimulator() {
if (!this._touchSimulator) {
this._touchSimulator = new TouchSimulator(
this.targetActor.chromeEventHandler
);
}
return this._touchSimulator;
},
get win() {
return this.docShell.chromeEventHandler.ownerGlobal;
},
@ -197,33 +178,7 @@ const ResponsiveActor = protocol.ActorClassWithSpec(responsiveSpec, {
* @param {String} pickerType
*/
setElementPickerState(state, pickerType) {
this.touchSimulator.setElementPickerState(state, pickerType);
},
/**
* Start or stop the touch simulator depending on the parameter
*
* @param {Object} options
* @param {Boolean} options.enable: Pass true to start the touch simulator. Any other
* value will stop it. Defaults to false.
* @returns {Boolean} Whether or not any action was done on the touch simulator.
*/
toggleTouchSimulator({ enable = false } = {}) {
if (enable) {
if (this.touchSimulator.enabled) {
return false;
}
this.touchSimulator.start();
return true;
}
if (!this.touchSimulator.enabled) {
return false;
}
this.touchSimulator.stop();
return true;
this.targetActor.touchSimulator.setElementPickerState(state, pickerType);
},
/* Meta viewport override */

Просмотреть файл

@ -36,6 +36,8 @@ const SUPPORTED_OPTIONS = {
rdmPaneMaxTouchPoints: true,
// Page orientation (used in RDM and doesn't apply if RDM isn't enabled)
rdmPaneOrientation: true,
// Reload the page when the touch simulation state changes (only works alongside touchEventsOverride)
reloadOnTouchSimulationToggle: true,
// Restore focus in the page after closing DevTools.
restoreFocus: true,
// Enable service worker testing over HTTP (instead of HTTPS only).

Просмотреть файл

@ -73,6 +73,13 @@ loader.lazyRequireGetter(
true
);
loader.lazyRequireGetter(
this,
"TouchSimulator",
"devtools/server/actors/emulation/touch-simulator",
true
);
function getWindowID(window) {
return window.windowGlobalChild.innerWindowId;
}
@ -600,6 +607,11 @@ const browsingContextTargetPrototype = {
this.threadActor._parentClosed = true;
}
if (this._touchSimulator) {
this._touchSimulator.stop();
this._touchSimulator = null;
}
this._detach();
this.docShell = null;
this._extraActors = null;
@ -1236,16 +1248,34 @@ const browsingContextTargetPrototype = {
return;
}
let reload = false;
if (typeof options.touchEventsOverride !== "undefined") {
const enableTouchSimulator = options.touchEventsOverride === "enabled";
// We want to reload the document if it's a top level target on which the touch
// simulator will be toggled and the user has turned the "reload on touch simulation"
// settings on.
if (
enableTouchSimulator !== this.touchSimulator.enabled &&
options.reloadOnTouchSimulationToggle === true &&
this.isTopLevelTarget
) {
reload = true;
}
if (enableTouchSimulator) {
this.touchSimulator.start();
} else {
this.touchSimulator.stop();
}
}
if (!this.isTopLevelTarget) {
// DevTools target options should only apply to the top target and be
// Following DevTools target options should only apply to the top target and be
// propagated through the browsing context tree via the platform.
return;
}
// Wait a tick so that the response packet can be dispatched before the
// subsequent navigation event packet.
let reload = false;
if (
typeof options.javascriptEnabled !== "undefined" &&
options.javascriptEnabled !== this._getJavascriptEnabled()
@ -1274,6 +1304,14 @@ const browsingContextTargetPrototype = {
}
},
get touchSimulator() {
if (!this._touchSimulator) {
this._touchSimulator = new TouchSimulator(this.chromeEventHandler);
}
return this._touchSimulator;
},
/**
* Opposite of the updateTargetConfiguration method, that resets document
* state when closing the toolbox.

Просмотреть файл

@ -77,35 +77,6 @@ class TargetConfigurationCommand {
return this._commands.targetCommand.targetFront._javascriptEnabled;
}
/**
* Enable or disable touch events simulation
*
* @param {String|null} flag: The value to set for the touchEventsOverride flag.
* Pass null to reset the flag to its original value.
* @returns {Boolean} Returns true if the page needs to be reloaded (so the page can
* acknowledge the new state).
*/
async setTouchEventsOverride(flag) {
// We need to set the flag on the parent process
await this.updateConfiguration({
touchEventsOverride: flag,
});
// And start the touch simulation within the content process.
// Note that this only handle current top-level document. When Fission is enabled, this
// doesn't enable touch simulation in remote iframes (See Bug 1704028).
// This also does not handle further navigation to a different origin (aka target switch),
// which should be fixed in Bug 1704029.
const responsiveFront = await this._commands.targetCommand.targetFront.getFront(
"responsive"
);
const reloadNeeded = await responsiveFront.toggleTouchSimulator({
enable: flag === "enabled",
});
return reloadNeeded;
}
/**
* Change orientation type and angle (that can be accessed through screen.orientation in
* the content page) and simulates the "orientationchange" event when the device screen

Просмотреть файл

@ -11,6 +11,9 @@ add_task(async function() {
// Disable click hold and double tap zooming as it might interfere with the test
await pushPref("ui.click_hold_context_menus", false);
await pushPref("apz.allow_double_tap_zooming", false);
// We turn server-side target switching on so touch simulation is enabled when navigating
// to a different origin (See Bug 1704029).
await pushPref("devtools.target-switching.server.enabled", true);
const tab = await addTab(TEST_URI);
@ -28,13 +31,12 @@ add_task(async function() {
});
info("Enable touch simulation");
await targetConfigurationCommand.setTouchEventsOverride("enabled");
await targetConfigurationCommand.updateConfiguration({
touchEventsOverride: "enabled",
});
await checkTopLevelDocumentTouchSimulation({ enabled: true });
await checkIframeTouchSimulation({
enabled: true,
// touch events are not emitted in remote frame when fission is enabled.
// This should be removed in Bug 1704028.
skipTouchEventsCheck: Services.appinfo.fissionAutostart,
});
info("Reload the page");
@ -59,9 +61,6 @@ add_task(async function() {
);
await checkIframeTouchSimulation({
enabled: true,
// touch events are not emitted in remote frame when fission is enabled.
// This should be removed in Bug 1704028.
skipTouchEventsCheck: Services.appinfo.fissionAutostart,
});
info(
@ -91,9 +90,6 @@ add_task(async function() {
await checkTopLevelDocumentTouchSimulation({ enabled: true });
await checkIframeTouchSimulation({
enabled: true,
// touch events are not emitted in remote frame when fission is enabled.
// This should be removed in Bug 1704028.
skipTouchEventsCheck: Services.appinfo.fissionAutostart,
});
const previousBrowsingContextId = gBrowser.selectedBrowser.browsingContext.id;
@ -124,9 +120,6 @@ add_task(async function() {
);
await checkTopLevelDocumentTouchSimulation({
enabled: true,
// The touch simulator isn't working after a new browsing context is created.
// This should be removed in Bug 1704029.
skipTouchEventsCheck: true,
});
is(
@ -136,10 +129,6 @@ add_task(async function() {
);
await checkIframeTouchSimulation({
enabled: true,
// The touch simulator isn't working after a new browsing context is created,
// and touch events are not emitted in remote frame when fission is enabled.
// This can be removed once Bug 1704029 and Bug 1704028 are resolved.
skipTouchEventsCheck: true,
});
info(
@ -234,10 +223,7 @@ async function isTouchEventEmitted(browserOrBrowsingContext) {
return result !== "TIMEOUT";
}
async function checkTopLevelDocumentTouchSimulation({
enabled,
skipTouchEventsCheck = false,
}) {
async function checkTopLevelDocumentTouchSimulation({ enabled }) {
is(
await matchesCoarsePointer(gBrowser.selectedBrowser),
enabled,
@ -246,10 +232,6 @@ async function checkTopLevelDocumentTouchSimulation({
} on the top level document`
);
if (skipTouchEventsCheck) {
return;
}
is(
await isTouchEventEmitted(gBrowser.selectedBrowser),
enabled,
@ -269,10 +251,7 @@ function getIframeBrowsingContext() {
);
}
async function checkIframeTouchSimulation({
enabled,
skipTouchEventsCheck = false,
}) {
async function checkIframeTouchSimulation({ enabled }) {
const iframeBC = await getIframeBrowsingContext();
is(
await matchesCoarsePointer(iframeBC),
@ -280,10 +259,6 @@ async function checkIframeTouchSimulation({
`The touch simulation is ${enabled ? "enabled" : "disabled"} on the iframe`
);
if (skipTouchEventsCheck) {
return;
}
is(
await isTouchEventEmitted(iframeBC),
enabled,

Просмотреть файл

@ -20,6 +20,7 @@ types.addDictType("target-configuration.configuration", {
paintFlashing: "nullable:boolean",
printSimulationEnabled: "nullable:boolean",
rdmPaneOrientation: "nullable:json",
reloadOnTouchSimulationToggle: "nullable:boolean",
restoreFocus: "nullable:boolean",
serviceWorkersTestingEnabled: "nullable:boolean",
touchEventsOverride: "nullable:string",