Bug 1606061 - move TouchEventsOverride to BrowsingContext. r=farre,devtools-backward-compat-reviewers

This change removes docshell's `mTouchEventsOverride` and replaces it
with a new `BrowsingContext` field `TouchEventsOverrideInternal`.
All uses of the old field have been replaced and an override should
now work under fission when there are cross-origin descendent frames.

Differential Revision: https://phabricator.services.mozilla.com/D96414
This commit is contained in:
Steven MacLeod 2020-11-10 15:57:30 +00:00
Родитель d90a483bd2
Коммит 971103bdd5
16 изменённых файлов: 123 добавлений и 102 удалений

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

@ -635,7 +635,7 @@ async function testTouchEventsOverride(ui, expected) {
const flag = await ui.responsiveFront.getTouchEventsOverride();
is(
flag === Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED,
flag === "enabled",
expected,
`Touch events override should be ${expected ? "enabled" : "disabled"}`
);

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

@ -859,7 +859,7 @@ class ResponsiveUI {
);
reloadNeeded = await this.responsiveFront.setTouchEventsOverride(
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED
"enabled"
);
if (metaViewportEnabled) {

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

@ -257,18 +257,19 @@ const ResponsiveActor = protocol.ActorClassWithSpec(responsiveSpec, {
}
// Start or stop the touch simulator depending on the override flag
if (flag == Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED) {
// See BrowsingContext.webidl `TouchEventsOverride` enum for values.
if (flag == "enabled") {
this.touchSimulator.start();
} else {
this.touchSimulator.stop();
}
this.docShell.touchEventsOverride = flag;
this.docShell.browsingContext.touchEventsOverride = flag;
return true;
},
getTouchEventsOverride() {
return this.docShell.touchEventsOverride;
return this.docShell.browsingContext.touchEventsOverride;
},
clearTouchEventsOverride() {

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

@ -57,7 +57,7 @@ const responsiveSpec = generateActorSpec({
setTouchEventsOverride: {
request: {
flag: Arg(0, "number"),
flag: Arg(0, "string"),
},
response: {
valueChanged: RetVal("boolean"),
@ -67,7 +67,7 @@ const responsiveSpec = generateActorSpec({
getTouchEventsOverride: {
request: {},
response: {
flag: RetVal("number"),
flag: RetVal("string"),
},
},

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

@ -85,6 +85,13 @@ struct ParamTraits<mozilla::dom::DisplayMode>
mozilla::dom::DisplayMode::Browser,
mozilla::dom::DisplayMode::EndGuard_> {};
// Allow serialization and deserialization of TouchEventsOverride over IPC
template <>
struct ParamTraits<mozilla::dom::TouchEventsOverride>
: public ContiguousEnumSerializer<
mozilla::dom::TouchEventsOverride,
mozilla::dom::TouchEventsOverride::Disabled,
mozilla::dom::TouchEventsOverride::EndGuard_> {};
} // namespace IPC
namespace mozilla {
@ -344,6 +351,8 @@ already_AddRefed<BrowsingContext> BrowsingContext::CreateDetached(
fields.mUseErrorPages = true;
fields.mTouchEventsOverrideInternal = TouchEventsOverride::None;
RefPtr<BrowsingContext> context;
if (XRE_IsParentProcess()) {
context = new CanonicalBrowsingContext(parentWC, group, id,
@ -2193,6 +2202,13 @@ bool BrowsingContext::InactiveForSuspend() const {
return !GetIsActive() && !GetHasMainMediaController();
}
bool BrowsingContext::CanSet(
FieldIndex<IDX_TouchEventsOverrideInternal>,
const enum TouchEventsOverride& aTouchEventsOverride,
ContentParent* aSource) {
return CheckOnlyOwningProcessCanSet(aSource);
}
bool BrowsingContext::CanSet(FieldIndex<IDX_DisplayMode>,
const enum DisplayMode& aDisplayMOde,
ContentParent* aSource) {
@ -2319,6 +2335,46 @@ bool BrowsingContext::CanSet(FieldIndex<IDX_UseErrorPages>,
return CheckOnlyEmbedderCanSet(aSource);
}
mozilla::dom::TouchEventsOverride BrowsingContext::TouchEventsOverride() {
BrowsingContext* bc = this;
while (bc) {
mozilla::dom::TouchEventsOverride tev =
bc->GetTouchEventsOverrideInternal();
if (tev != mozilla::dom::TouchEventsOverride::None) {
return tev;
}
bc = bc->GetParent();
}
return mozilla::dom::TouchEventsOverride::None;
}
void BrowsingContext::SetTouchEventsOverride(
const enum TouchEventsOverride aTouchEventsOverride, ErrorResult& aRv) {
// Clear overrides from descendents first.
for (BrowsingContext* child : Children()) {
child->PreOrderWalk([](BrowsingContext* aContext) {
if (aContext->GetTouchEventsOverrideInternal() !=
mozilla::dom::TouchEventsOverride::None) {
// Ignore failed sets because the override of a discarded
// descendent shouldn't matter.
Unused << aContext->SetTouchEventsOverrideInternal(
mozilla::dom::TouchEventsOverride::None);
}
});
}
SetTouchEventsOverrideInternal(aTouchEventsOverride, aRv);
}
nsresult BrowsingContext::SetTouchEventsOverride(
const enum TouchEventsOverride aTouchEventsOverride) {
ErrorResult rv;
SetTouchEventsOverride(aTouchEventsOverride, rv);
return rv.StealNSResult();
}
// We map `watchedByDevTools` WebIDL attribute to `watchedByDevToolsInternal`
// BC field. And we map it to the top level BrowsingContext.
bool BrowsingContext::WatchedByDevTools() {

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

@ -152,6 +152,7 @@ class WindowProxyHolder;
FIELD(CurrentOrientationType, mozilla::dom::OrientationType) \
FIELD(OrientationLock, mozilla::hal::ScreenOrientation) \
FIELD(UserAgentOverride, nsString) \
FIELD(TouchEventsOverrideInternal, mozilla::dom::TouchEventsOverride) \
FIELD(EmbedderElementType, Maybe<nsString>) \
FIELD(MessageManagerGroup, nsString) \
FIELD(MaxTouchPointsOverride, uint8_t) \
@ -462,6 +463,12 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
bool WatchedByDevTools();
void SetWatchedByDevTools(bool aWatchedByDevTools, ErrorResult& aRv);
mozilla::dom::TouchEventsOverride TouchEventsOverride();
void SetTouchEventsOverride(
const enum TouchEventsOverride aTouchEventsOverride, ErrorResult& aRv);
MOZ_MUST_USE nsresult
SetTouchEventsOverride(const enum TouchEventsOverride aTouchEventsOverride);
bool FullscreenAllowed() const;
float FullZoom() const { return GetFullZoom(); }
@ -834,6 +841,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return IsTop();
}
bool CanSet(FieldIndex<IDX_TouchEventsOverrideInternal>,
const enum TouchEventsOverride& aTouchEventsOverride,
ContentParent* aSource);
bool CanSet(FieldIndex<IDX_DisplayMode>, const enum DisplayMode& aDisplayMode,
ContentParent* aSource);
void DidSet(FieldIndex<IDX_DisplayMode>, enum DisplayMode aOldValue);

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

@ -376,7 +376,6 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
mLoadType(0),
mFailedLoadType(0),
mJSRunToCompletionDepth(0),
mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE),
mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE),
mCreatingDocument(false),
#ifdef DEBUG
@ -2340,34 +2339,6 @@ nsDocShell::ClearCachedUserAgent() {
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetTouchEventsOverride(TouchEventsOverride* aTouchEventsOverride) {
*aTouchEventsOverride = mTouchEventsOverride;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetTouchEventsOverride(TouchEventsOverride aTouchEventsOverride) {
// We don't have a way to verify this coming from Javascript, so this check is
// still needed.
if (!(aTouchEventsOverride == TOUCHEVENTS_OVERRIDE_NONE ||
aTouchEventsOverride == TOUCHEVENTS_OVERRIDE_ENABLED ||
aTouchEventsOverride == TOUCHEVENTS_OVERRIDE_DISABLED)) {
return NS_ERROR_INVALID_ARG;
}
mTouchEventsOverride = aTouchEventsOverride;
uint32_t childCount = mChildList.Length();
for (uint32_t i = 0; i < childCount; ++i) {
nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(ChildAt(i));
if (childShell) {
childShell->SetTouchEventsOverride(aTouchEventsOverride);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetMetaViewportOverride(
MetaViewportOverride* aMetaViewportOverride) {
@ -2627,8 +2598,6 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
SetAffectPrivateSessionLifetime(
parentAsDocShell->GetAffectPrivateSessionLifetime());
SetTouchEventsOverride(parentAsDocShell->GetTouchEventsOverride());
// We don't need to inherit metaViewportOverride, because the viewport
// is only relevant for the outermost nsDocShell, not for any iframes
// like this that might be embedded within it.

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

@ -1239,10 +1239,6 @@ class nsDocShell final : public nsDocLoader,
// has been called without a matching NotifyRunToCompletionStop.
uint32_t mJSRunToCompletionDepth;
// Whether or not touch events are overridden. Possible values are defined
// as constants in the nsIDocShell.idl file.
TouchEventsOverride mTouchEventsOverride;
// Whether or not handling of the <meta name="viewport"> tag is overridden.
// Possible values are defined as constants in nsIDocShell.idl.
MetaViewportOverride mMetaViewportOverride;

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

@ -787,27 +787,6 @@ interface nsIDocShell : nsIDocShellTreeItem
[noscript,nostdcall,notxpcom] nsCommandManager GetCommandManager();
cenum TouchEventsOverride: 8 {
/**
* Override platform/pref default behaviour and force-disable touch events.
*/
TOUCHEVENTS_OVERRIDE_DISABLED = 0,
/**
* Override platform/pref default behaviour and force-enable touch events.
*/
TOUCHEVENTS_OVERRIDE_ENABLED = 1,
/**
* Don't override the platform/pref default behaviour for touch events.
*/
TOUCHEVENTS_OVERRIDE_NONE = 2,
};
/**
* This allows chrome to override the default choice of whether touch events
* are available on a specific docshell. Possible values are listed below.
*/
[infallible] attribute nsIDocShell_TouchEventsOverride touchEventsOverride;
cenum MetaViewportOverride: 8 {
/**
* Override platform/pref default behaviour and force-disable support for

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

@ -14,26 +14,26 @@ add_task(async function() {
});
async function test_body() {
let docshell = docShell;
let bc = content.browsingContext;
is(
docshell.touchEventsOverride,
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_NONE,
bc.touchEventsOverride,
"none",
"touchEventsOverride flag should be initially set to NONE"
);
docshell.touchEventsOverride = Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED;
bc.touchEventsOverride = "disabled";
is(
docshell.touchEventsOverride,
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
bc.touchEventsOverride,
"disabled",
"touchEventsOverride flag should be changed to DISABLED"
);
let frameWin = content.document.querySelector("#test-iframe").contentWindow;
docshell = frameWin.docShell;
bc = frameWin.browsingContext;
is(
docshell.touchEventsOverride,
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
bc.touchEventsOverride,
"disabled",
"touchEventsOverride flag should be passed on to frames."
);
@ -41,20 +41,20 @@ async function test_body() {
content.document.body.appendChild(newFrame);
let newFrameWin = newFrame.contentWindow;
docshell = newFrameWin.docShell;
bc = newFrameWin.browsingContext;
is(
docshell.touchEventsOverride,
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
bc.touchEventsOverride,
"disabled",
"Newly created frames should use the new touchEventsOverride flag"
);
newFrameWin.location.reload();
await ContentTaskUtils.waitForEvent(newFrameWin, "load");
docshell = newFrameWin.docShell;
bc = newFrameWin.browsingContext;
is(
docshell.touchEventsOverride,
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_DISABLED,
bc.touchEventsOverride,
"disabled",
"New touchEventsOverride flag should persist across reloads"
);
}

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

@ -9905,11 +9905,8 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
// value after setting it, above.
if (maxWidth == nsViewportInfo::Auto && !mValidScaleFloat) {
BrowsingContext* bc = GetBrowsingContext();
nsIDocShell* docShell = GetDocShell();
if (docShell &&
docShell->GetTouchEventsOverride() ==
nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED &&
bc && bc->InRDMPane()) {
if (bc && bc->TouchEventsOverride() == TouchEventsOverride::Enabled &&
bc->InRDMPane()) {
// If RDM and touch simulation are active, then use the simulated
// screen width to accomodate for cases where the screen width is
// larger than the desktop viewport default.

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

@ -41,6 +41,15 @@ enum DisplayMode {
"fullscreen",
};
/**
* Allowed overrides of platform/pref default behaviour for touch events.
*/
enum TouchEventsOverride {
"disabled", // Force-disable touch events.
"enabled", // Force-enable touch events.
"none", // Don't override behaviour for touch events.
};
[Exposed=Window, ChromeOnly]
interface BrowsingContext {
static BrowsingContext? get(unsigned long long aId);
@ -146,6 +155,12 @@ interface BrowsingContext {
[SetterThrows] attribute DisplayMode displayMode;
/**
* This allows chrome to override the default choice of whether touch events
* are available in a specific BrowsingContext and its descendents.
*/
[SetterThrows] attribute TouchEventsOverride touchEventsOverride;
/**
* The nsID of the browsing context in the session history.
*/

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

@ -574,15 +574,9 @@ void PointerEventHandler::DispatchPointerFromMouseOrTouch(
return;
}
nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
if (!docShell) {
return;
}
BrowsingContext* bc = doc->GetBrowsingContext();
if (docShell->GetTouchEventsOverride() ==
nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED &&
bc && bc->InRDMPane()) {
if (bc && bc->TouchEventsOverride() == TouchEventsOverride::Enabled &&
bc->InRDMPane()) {
return;
}

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

@ -223,16 +223,18 @@ bool TouchEvent::PlatformSupportsTouch() {
bool TouchEvent::PrefEnabled(nsIDocShell* aDocShell) {
MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
auto touchEventsOverride = nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE;
auto touchEventsOverride = mozilla::dom::TouchEventsOverride::None;
if (aDocShell) {
touchEventsOverride = aDocShell->GetTouchEventsOverride();
if (BrowsingContext* bc = aDocShell->GetBrowsingContext()) {
touchEventsOverride = bc->TouchEventsOverride();
}
}
bool enabled = false;
if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED) {
if (touchEventsOverride == mozilla::dom::TouchEventsOverride::Enabled) {
enabled = true;
} else if (touchEventsOverride ==
nsIDocShell::TOUCHEVENTS_OVERRIDE_DISABLED) {
mozilla::dom::TouchEventsOverride::Disabled) {
enabled = false;
} else {
const int32_t prefValue = StaticPrefs::dom_w3c_touch_events_enabled();
@ -289,8 +291,9 @@ bool TouchEvent::LegacyAPIEnabled(nsIDocShell* aDocShell,
bool aCallerIsSystem) {
return (aCallerIsSystem ||
StaticPrefs::dom_w3c_touch_events_legacy_apis_enabled() ||
(aDocShell && aDocShell->GetTouchEventsOverride() ==
nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED)) &&
(aDocShell && aDocShell->GetBrowsingContext() &&
aDocShell->GetBrowsingContext()->TouchEventsOverride() ==
mozilla::dom::TouchEventsOverride::Enabled)) &&
PrefEnabled(aDocShell);
}

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

@ -8306,8 +8306,8 @@ ScrollMetadata nsLayoutUtils::ComputeScrollMetadata(
nsIDocShell* docShell = presContext->GetDocShell();
BrowsingContext* bc = docShell ? docShell->GetBrowsingContext() : nullptr;
bool isTouchEventsEnabled =
docShell && docShell->GetTouchEventsOverride() ==
nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED;
bc &&
bc->TouchEventsOverride() == mozilla::dom::TouchEventsOverride::Enabled;
if (bc && bc->InRDMPane() && isTouchEventsEnabled) {
metadata.SetIsRDMTouchSimulationActive(true);

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

@ -293,11 +293,11 @@ static PointerCapabilities GetPointerCapabilities(const Document* aDocument,
aID == LookAndFeel::IntID::AllPointerCapabilities);
MOZ_ASSERT(aDocument);
if (nsIDocShell* docShell = aDocument->GetDocShell()) {
if (BrowsingContext* bc = aDocument->GetBrowsingContext()) {
// The touch-events-override happens only for the Responsive Design Mode so
// that we don't need to care about ResistFingerprinting.
if (docShell->GetTouchEventsOverride() ==
nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED) {
if (bc->TouchEventsOverride() ==
mozilla::dom::TouchEventsOverride::Enabled) {
return PointerCapabilities::Coarse;
}
}