summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h')
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h233
1 files changed, 97 insertions, 136 deletions
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
index bd85935bae8..870b662ed60 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -5,18 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DISPLAY_LOCK_DISPLAY_LOCK_CONTEXT_H_
-#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/display_lock/display_lock_budget.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
-class DisplayLockSuspendedHandle;
class Element;
class DisplayLockScopedLogger;
class StyleRecalcChange;
@@ -45,7 +40,8 @@ enum class DisplayLockActivationReason {
// Shorthands
kViewport = static_cast<uint16_t>(kSelection) |
static_cast<uint16_t>(kUserFocus) |
- static_cast<uint16_t>(kViewportIntersection),
+ static_cast<uint16_t>(kViewportIntersection) |
+ static_cast<uint16_t>(kAccessibility),
kAny = static_cast<uint16_t>(kAccessibility) |
static_cast<uint16_t>(kFindInPage) |
static_cast<uint16_t>(kFragmentNavigation) |
@@ -64,47 +60,12 @@ static_assert(static_cast<uint32_t>(DisplayLockActivationReason::kAny) <
std::numeric_limits<uint16_t>::max(),
"DisplayLockActivationReason is too large");
-// Since we currently, and temporarily, support both CSS and attribute version,
-// we need to distinguish the two so that lack of CSS, for example, doesn't
-// unlock the attribute version and vice versa.
-enum class DisplayLockContextCreateMethod { kUnknown, kCSS, kAttribute };
-
class CORE_EXPORT DisplayLockContext final
: public GarbageCollected<DisplayLockContext>,
- public ContextLifecycleObserver,
public LocalFrameView::LifecycleNotificationObserver {
USING_GARBAGE_COLLECTED_MIXIN(DisplayLockContext);
- USING_PRE_FINALIZER(DisplayLockContext, Dispose);
public:
- // Determines what type of budget to use. This can be overridden via
- // DisplayLockContext::SetBudgetType().
- // - kDoNotYield:
- // This will effectively do all of the lifecycle phases when we're
- // committing. That is, this is the "no budget" option.
- // - kStrictYieldBetweenLifecyclePhases:
- // This type always yields between each lifecycle phase, even if that
- // phase was quick (note that it still skips phases that don't need any
- // updates).
- // - kYieldBetweenLifecyclePhases:
- // This type will only yield between lifecycle phases (not in the middle
- // of one). However, if there is sufficient time left (TODO(vmpstr):
- // define this), then it will continue on to the next lifecycle phase.
- enum class BudgetType {
- kDoNotYield,
- kStrictYieldBetweenLifecyclePhases,
- kYieldBetweenLifecyclePhases,
- kDefault = kYieldBetweenLifecyclePhases
- };
-
- // The current state of the lock. Note that the order of these matters.
- enum State {
- kLocked,
- kUpdating,
- kCommitting,
- kUnlocked,
- };
-
// The type of style that was blocked by this display lock.
enum StyleType {
kStyleUpdateNotRequired,
@@ -130,31 +91,18 @@ class CORE_EXPORT DisplayLockContext final
UntracedMember<DisplayLockContext> context_ = nullptr;
};
- DisplayLockContext(Element*, ExecutionContext*);
- ~DisplayLockContext();
+ explicit DisplayLockContext(Element*);
+ ~DisplayLockContext() = default;
- // GC functions.
- void Trace(blink::Visitor*) override;
- void Dispose();
-
- // ContextLifecycleObserver overrides.
- void ContextDestroyed(ExecutionContext*) override;
-
- // Set which reasons activate, as a mask of DisplayLockActivationReason enums.
- void SetActivatable(uint16_t activatable_mask);
-
- // Returns true if this lock has been activated and the activation has not yet
- // been cleared.
- bool IsActivated() const;
- // Clear the activated flag.
- void ClearActivated();
+ // Called by style to update the current state of subtree-visibility.
+ void SetRequestedState(ESubtreeVisibility state);
+ // Called by style to adjust the element's style based on the current state.
+ void AdjustElementStyle(ComputedStyle* style) const;
- // Acquire the lock, should only be called when unlocked.
- void StartAcquire();
- // Initiate a commit.
- void StartCommit();
- // Update rendering of the subtree.
- ScriptPromise UpdateRendering(ScriptState*);
+ // Is called by the intersection observer callback to inform us of the
+ // intersection state.
+ void NotifyIsIntersectingViewport();
+ void NotifyIsNotIntersectingViewport();
// Lifecycle observation / state functions.
bool ShouldStyle(DisplayLockLifecycleTarget) const;
@@ -182,17 +130,14 @@ class CORE_EXPORT DisplayLockContext final
// find-in-page, scrolling, etc.
// This issues a before activate signal with the given element as the
// activated element.
- void CommitForActivationWithSignal(Element* activated_element);
+ // The reason is specified for metrics.
+ void CommitForActivationWithSignal(Element* activated_element,
+ DisplayLockActivationReason reason);
bool ShouldCommitForActivation(DisplayLockActivationReason reason) const;
- // Returns true if this lock is locked. Note from the outside perspective, the
- // lock is locked any time the state is not kUnlocked or kCommitting.
- bool IsLocked() const { return state_ != kUnlocked && state_ != kCommitting; }
-
- // Called when the layout tree is attached. This is used to verify
- // containment.
- void DidAttachLayoutTree();
+ // Returns true if this context is locked.
+ bool IsLocked() const { return is_locked_; }
// Returns a ScopedForcedUpdate object which for the duration of its lifetime
// will allow updates to happen on this element's subtree. For the element
@@ -212,7 +157,6 @@ class CORE_EXPORT DisplayLockContext final
// LifecycleNotificationObserver overrides.
void WillStartLifecycleUpdate(const LocalFrameView&) override;
- void DidFinishLifecycleUpdate(const LocalFrameView&) override;
// Inform the display lock that it prevented a style change. This is used to
// invalidate style when we need to update it in the future.
@@ -244,6 +188,12 @@ class CORE_EXPORT DisplayLockContext final
void ElementDisconnected();
void ElementConnected();
+ void NotifySubtreeLostFocus();
+ void NotifySubtreeGainedFocus();
+
+ void NotifySubtreeLostSelection();
+ void NotifySubtreeGainedSelection();
+
void SetNeedsPrePaintSubtreeWalk(
bool needs_effective_allowed_touch_action_update) {
needs_effective_allowed_touch_action_update_ =
@@ -251,50 +201,47 @@ class CORE_EXPORT DisplayLockContext final
needs_prepaint_subtree_walk_ = true;
}
- void SetMethod(DisplayLockContextCreateMethod method) { method_ = method; }
- DisplayLockContextCreateMethod GetMethod() const {
- DCHECK(method_ != DisplayLockContextCreateMethod::kUnknown);
- return method_;
- }
-
- // Note that this returns true if there is no context at all, so in order to
- // check whether this is strictly an attribute version, as opposed to a null
- // context, one needs to compare context with nullptr first.
- static bool IsAttributeVersion(DisplayLockContext* context) {
- return !context ||
- context->GetMethod() == DisplayLockContextCreateMethod::kAttribute;
- }
-
// This is called by the style recalc code in lieu of
// MarkForStyleRecalcIfNeeded() in order to adjust the child change if we need
// to recalc children nodes here.
StyleRecalcChange AdjustStyleRecalcChangeForChildren(
StyleRecalcChange change);
- private:
- friend class DisplayLockContextTest;
- friend class DisplayLockBudgetTest;
- friend class DisplayLockSuspendedHandle;
- friend class DisplayLockBudget;
+ void DidForceActivatableDisplayLocks() {
+ if (IsLocked() && IsActivatable(DisplayLockActivationReason::kAny)) {
+ MarkForStyleRecalcIfNeeded();
+ MarkForLayoutIfNeeded();
+ }
+ }
- class StateChangeHelper {
- DISALLOW_NEW();
+ // GC functions.
+ void Trace(Visitor*) override;
- public:
- explicit StateChangeHelper(DisplayLockContext*);
+ private:
+ // Test friends.
+ friend class DisplayLockContextRenderingTest;
+ friend class DisplayLockContextTest;
- operator State() const { return state_; }
- StateChangeHelper& operator=(State);
- void UpdateActivationBlockingCount(bool old_activatable,
- bool new_activatable);
+ // Request that this context be locked. Called when style determines that the
+ // subtree rooted at this element should be skipped, unless things like
+ // viewport intersection prevent it from doing so.
+ void RequestLock(uint16_t activation_mask);
+ // Request that this context be unlocked. Called when style determines that
+ // the subtree rooted at this element should be rendered.
+ void RequestUnlock();
+
+ // Records the locked context counts on the document as well as context that
+ // block all activation.
+ void UpdateDocumentBookkeeping(bool was_locked,
+ bool all_activation_was_blocked,
+ bool is_locked,
+ bool all_activation_is_blocked);
- private:
- State state_ = kUnlocked;
- UntracedMember<DisplayLockContext> context_;
- };
+ // Set which reasons activate, as a mask of DisplayLockActivationReason enums.
+ void UpdateActivationMask(uint16_t activatable_mask);
- // Initiate an update.
- void StartUpdateIfNeeded();
+ // Clear the activated flag.
+ void ResetActivation();
// Marks ancestors of elements in |whitespace_reattach_set_| with
// ChildNeedsReattachLayoutTree and clears the set.
@@ -318,26 +265,10 @@ class CORE_EXPORT DisplayLockContext final
// GetScopedForcedUpdate() for more information.
void NotifyForcedUpdateScopeEnded();
- // Creates a new update budget based on the BudgetType::kDefault enum. In
- // other words, it will create a budget of that type.
- // TODO(vmpstr): In tests, we will probably switch the value to test other
- // budgets. As well, this makes it easier to change the budget right in the
- // enum definitions.
- std::unique_ptr<DisplayLockBudget> CreateNewBudget();
-
// Helper to schedule an animation to delay lifecycle updates for the next
// frame.
void ScheduleAnimation();
- // Helper functions to resolve the update/commit promises.
- enum ResolverState { kResolve, kReject, kDetach };
- void MakeResolver(ScriptState*, Member<ScriptPromiseResolver>*);
- bool HasResolver();
- void FinishUpdateResolver(ResolverState, const char* reject_reason = nullptr);
- void FinishResolver(Member<ScriptPromiseResolver>*,
- ResolverState,
- const char* reject_reason);
-
// Checks whether we should force unlock the lock (due to not meeting
// containment/display requirements), returns a string from rejection_names
// if we should, nullptr if not. Note that this can only be called if the
@@ -355,12 +286,6 @@ class CORE_EXPORT DisplayLockContext final
// when acquiring this lock should immediately resolve the acquire promise.
bool ConnectedToView() const;
- bool ShouldPerformUpdatePhase(DisplayLockBudget::Phase phase) const;
-
- // During an attempt to commit, clean up state and reject pending resolver
- // promises if the lock is not connected to the tree.
- bool CleanupAndRejectCommitIfNotConnected();
-
// Registers or unregisters the element for intersection observations in the
// document. This is used to activate on visibily changes. This can be safely
// called even if changes are not required, since it will only act if a
@@ -371,11 +296,28 @@ class CORE_EXPORT DisplayLockContext final
// Scheduled by CommitForActivationWithSignal.
void FireActivationEvent(Element* activated_element);
- std::unique_ptr<DisplayLockBudget> update_budget_;
+ // Determines whether or not we need lifecycle notifications.
+ bool NeedsLifecycleNotifications() const;
+ // Updates the lifecycle notification registration based on whether we need
+ // the notifications.
+ void UpdateLifecycleNotificationRegistration();
+
+ // Locks the context.
+ void Lock();
+ // Unlocks the context.
+ void Unlock();
+
+ // Determines if the subtree has focus. This is a linear walk from the focused
+ // element to its root element.
+ void DetermineIfSubtreeHasFocus();
+
+ // Determines if the subtree has selection. This will walk from each of the
+ // selected notes up to its root looking for `element_`.
+ void DetermineIfSubtreeHasSelection();
- Member<ScriptPromiseResolver> update_resolver_;
WeakMember<Element> element_;
WeakMember<Document> document_;
+ ESubtreeVisibility state_ = ESubtreeVisibility::kVisible;
// See StyleEngine's |whitespace_reattach_set_|.
// Set of elements that had at least one rendered children removed
@@ -386,8 +328,6 @@ class CORE_EXPORT DisplayLockContext final
// style recalc on them.
HeapHashSet<Member<Element>> whitespace_reattach_set_;
- StateChangeHelper state_;
-
bool update_forced_ = false;
StyleType blocked_style_traversal_type_ = kStyleUpdateNotRequired;
@@ -398,7 +338,6 @@ class CORE_EXPORT DisplayLockContext final
bool needs_effective_allowed_touch_action_update_ = false;
bool needs_prepaint_subtree_walk_ = false;
- bool is_horizontal_writing_mode_ = true;
bool needs_graphics_layer_collection_ = false;
bool needs_compositing_requirements_update_ = false;
@@ -415,11 +354,33 @@ class CORE_EXPORT DisplayLockContext final
uint16_t activatable_mask_ =
static_cast<uint16_t>(DisplayLockActivationReason::kAny);
- bool is_activated_ = false;
+ // Is set to true if we are registered for lifecycle notifications.
+ bool is_registered_for_lifecycle_notifications_ = false;
+
+ // This is set to true when we have delayed locking ourselves due to viewport
+ // intersection (or lack thereof) because we were nested in a locked subtree.
+ // In that case, we register for lifecycle notifications and check every time
+ // if we are still nested.
+ bool needs_deferred_not_intersecting_signal_ = false;
+
+ // Lock has been requested.
+ bool is_locked_ = false;
+
+ enum class RenderAffectingState : int {
+ kLockRequested,
+ kIntersectsViewport,
+ kSubtreeHasFocus,
+ kSubtreeHasSelection,
+ kNumRenderAffectingStates
+ };
+ void SetRenderAffectingState(RenderAffectingState state, bool flag);
+ void NotifyRenderAffectingStateChanged();
- DisplayLockContextCreateMethod method_ =
- DisplayLockContextCreateMethod::kUnknown;
+ bool render_affecting_state_[static_cast<int>(
+ RenderAffectingState::kNumRenderAffectingStates)] = {false};
+ // TODO(vmpstr): This is only needed while we're still sending activation
+ // events.
base::WeakPtrFactory<DisplayLockContext> weak_factory_{this};
};