diff options
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.h | 233 |
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}; }; |