Bug 1873330 - Part 2: Add UserActivation::Modifiers and UserActivation::StateAndModifiers. r=smaug

Associate modifier keys to user activation, in order to use the modifiers
in `window.open` initiated by the user activation.

Depends on D197859

Differential Revision: https://phabricator.services.mozilla.com/D197860
This commit is contained in:
Tooru Fujisawa 2024-01-11 17:24:01 +00:00
Родитель 7eb60cfbdc
Коммит aeb2eac8f0
3 изменённых файлов: 94 добавлений и 11 удалений

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

@ -364,11 +364,11 @@ void WindowContext::DidSet(FieldIndex<IDX_SHEntryHasUserInteraction>,
}
}
void WindowContext::DidSet(FieldIndex<IDX_UserActivationState>) {
void WindowContext::DidSet(FieldIndex<IDX_UserActivationStateAndModifiers>) {
MOZ_ASSERT_IF(!IsInProcess(), mUserGestureStart.IsNull());
USER_ACTIVATION_LOG("Set user gesture activation %" PRIu8
USER_ACTIVATION_LOG("Set user gesture activation 0x%02" PRIu8
" for %s browsing context 0x%08" PRIx64,
static_cast<uint8_t>(GetUserActivationState()),
GetUserActivationStateAndModifiers(),
XRE_IsParentProcess() ? "Parent" : "Child", Id());
if (IsInProcess()) {
USER_ACTIVATION_LOG(
@ -484,11 +484,15 @@ void WindowContext::AddSecurityState(uint32_t aStateFlags) {
}
void WindowContext::NotifyUserGestureActivation() {
Unused << SetUserActivationState(UserActivation::State::FullActivated);
UserActivation::StateAndModifiers stateAndModifiers;
stateAndModifiers.SetState(UserActivation::State::FullActivated);
Unused << SetUserActivationStateAndModifiers(stateAndModifiers.GetRawData());
}
void WindowContext::NotifyResetUserGestureActivation() {
Unused << SetUserActivationState(UserActivation::State::None);
UserActivation::StateAndModifiers stateAndModifiers;
stateAndModifiers.SetState(UserActivation::State::None);
Unused << SetUserActivationStateAndModifiers(stateAndModifiers.GetRawData());
}
bool WindowContext::HasBeenUserGestureActivated() {
@ -534,8 +538,11 @@ bool WindowContext::ConsumeTransientUserGestureActivation() {
WindowContext* windowContext = aBrowsingContext->GetCurrentWindowContext();
if (windowContext && windowContext->GetUserActivationState() ==
UserActivation::State::FullActivated) {
Unused << windowContext->SetUserActivationState(
UserActivation::State::HasBeenActivated);
auto stateAndModifiers = UserActivation::StateAndModifiers(
GetUserActivationStateAndModifiers());
stateAndModifiers.SetState(UserActivation::State::HasBeenActivated);
Unused << windowContext->SetUserActivationStateAndModifiers(
stateAndModifiers.GetRawData());
}
});

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

@ -69,7 +69,8 @@ class BrowsingContextGroup;
FIELD(HasBeforeUnload, bool) \
/* Controls whether the WindowContext is currently considered to be \
* activated by a gesture */ \
FIELD(UserActivationState, UserActivation::State) \
FIELD(UserActivationStateAndModifiers, \
UserActivation::StateAndModifiers::DataT) \
FIELD(EmbedderPolicy, nsILoadInfo::CrossOriginEmbedderPolicy) \
/* True if this document tree contained at least a HTMLMediaElement. \
* This should only be set on top level context. */ \
@ -194,6 +195,12 @@ class WindowContext : public nsISupports, public nsWrapperCache {
// 'MIXED' state flags, and should only be called on the top window context.
void AddSecurityState(uint32_t aStateFlags);
UserActivation::State GetUserActivationState() const {
return UserActivation::StateAndModifiers(
GetUserActivationStateAndModifiers())
.GetState();
}
// This function would be called when its corresponding window is activated
// by user gesture.
void NotifyUserGestureActivation();
@ -310,8 +317,9 @@ class WindowContext : public nsISupports, public nsWrapperCache {
bool CanSet(FieldIndex<IDX_DelegatedExactHostMatchPermissions>,
const PermissionDelegateHandler::DelegatedPermissionList& aValue,
ContentParent* aSource);
bool CanSet(FieldIndex<IDX_UserActivationState>,
const UserActivation::State& aUserActivationState,
bool CanSet(FieldIndex<IDX_UserActivationStateAndModifiers>,
const UserActivation::StateAndModifiers::DataT&
aUserActivationStateAndModifiers,
ContentParent* aSource) {
return true;
}
@ -344,7 +352,7 @@ class WindowContext : public nsISupports, public nsWrapperCache {
void DidSet(FieldIndex<I>) {}
template <size_t I, typename T>
void DidSet(FieldIndex<I>, T&& aOldValue) {}
void DidSet(FieldIndex<IDX_UserActivationState>);
void DidSet(FieldIndex<IDX_UserActivationStateAndModifiers>);
// Recomputes whether we can execute scripts in this WindowContext based on
// the value of AllowJavascript() and whether scripts are allowed in the

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

@ -7,6 +7,7 @@
#ifndef mozilla_dom_UserActivation_h
#define mozilla_dom_UserActivation_h
#include "mozilla/Assertions.h"
#include "mozilla/EventForwards.h"
#include "mozilla/TimeStamp.h"
#include "nsCycleCollectionParticipant.h"
@ -44,6 +45,73 @@ class UserActivation final : public nsISupports, public nsWrapperCache {
EndGuard_
};
class StateAndModifiers;
// Modifier keys held while the user activation.
class Modifiers {
public:
static constexpr uint8_t Shift = 0x10;
static constexpr uint8_t Meta = 0x20;
static constexpr uint8_t Control = 0x40;
static constexpr uint8_t Alt = 0x80;
static constexpr uint8_t Mask = 0xF0;
constexpr Modifiers() = default;
explicit constexpr Modifiers(uint8_t aModifiers) : mModifiers(aModifiers) {}
static constexpr Modifiers None() { return Modifiers(0); }
uint8_t GetRawData() const { return mModifiers; }
void SetShift() { mModifiers |= Shift; }
void SetMeta() { mModifiers |= Meta; }
void SetControl() { mModifiers |= Control; }
void SetAlt() { mModifiers |= Alt; }
bool IsShift() const { return mModifiers & Shift; }
bool IsMeta() const { return mModifiers & Meta; }
bool IsControl() const { return mModifiers & Control; }
bool IsAlt() const { return mModifiers & Alt; }
private:
uint8_t mModifiers = 0;
friend class StateAndModifiers;
};
// State and Modifiers encoded into single data, for WindowContext field.
class StateAndModifiers {
public:
using DataT = uint8_t;
constexpr StateAndModifiers() = default;
explicit constexpr StateAndModifiers(DataT aStateAndModifiers)
: mStateAndModifiers(aStateAndModifiers) {}
DataT GetRawData() const { return mStateAndModifiers; }
State GetState() const { return State(RawState()); }
void SetState(State aState) {
MOZ_ASSERT((uint8_t(aState) & Modifiers::Mask) == 0);
mStateAndModifiers = uint8_t(aState) | RawModifiers();
}
Modifiers GetModifiers() const { return Modifiers(RawModifiers()); }
void SetModifiers(Modifiers aModifiers) {
mStateAndModifiers = RawState() | aModifiers.mModifiers;
}
private:
uint8_t RawState() const { return mStateAndModifiers & ~Modifiers::Mask; }
uint8_t RawModifiers() const {
return mStateAndModifiers & Modifiers::Mask;
}
uint8_t mStateAndModifiers = 0;
};
/**
* Returns true if the current code is being executed as a result of
* user input or keyboard input. The former includes anything that is