tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ViewTransition.h (8545B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef mozilla_dom_ViewTransition_h
      6 #define mozilla_dom_ViewTransition_h
      7 
      8 #include "mozilla/Attributes.h"
      9 #include "mozilla/layers/IpcResourceUpdateQueue.h"
     10 #include "nsAtomHashKeys.h"
     11 #include "nsClassHashtable.h"
     12 #include "nsRect.h"
     13 #include "nsRefPtrHashtable.h"
     14 #include "nsWrapperCache.h"
     15 
     16 class nsIGlobalObject;
     17 class nsITimer;
     18 
     19 namespace mozilla {
     20 
     21 class ErrorResult;
     22 struct Keyframe;
     23 struct PseudoStyleRequest;
     24 struct StyleLockedDeclarationBlock;
     25 
     26 namespace layers {
     27 class RenderRootStateManager;
     28 }
     29 
     30 namespace wr {
     31 struct ImageKey;
     32 class IpcResourceUpdateQueue;
     33 }  // namespace wr
     34 
     35 namespace dom {
     36 
     37 class ViewTransitionTypeSet;
     38 extern LazyLogModule gViewTransitionsLog;
     39 
     40 #define VT_LOG(...)                                                    \
     41  MOZ_LOG(mozilla::dom::gViewTransitionsLog, mozilla::LogLevel::Debug, \
     42          (__VA_ARGS__))
     43 
     44 #ifdef DEBUG
     45 #  define VT_LOG_DEBUG(...) VT_LOG(__VA_ARGS__)
     46 #else
     47 #  define VT_LOG_DEBUG(...)
     48 #endif
     49 
     50 class Document;
     51 class Element;
     52 class Promise;
     53 class ViewTransitionUpdateCallback;
     54 
     55 enum class SkipTransitionReason : uint8_t {
     56  JS,
     57  DocumentHidden,
     58  RootRemoved,
     59  ClobberedActiveTransition,
     60  Timeout,
     61  UpdateCallbackRejected,
     62  DuplicateTransitionNameCapturingOldState,
     63  DuplicateTransitionNameCapturingNewState,
     64  PseudoUpdateFailure,
     65  Resize,
     66  PageSwap,
     67  // Can happen due to various recoverable internal errors such as GPU process
     68  // crashes or GPU device resets.
     69  ResetRendering,
     70 };
     71 
     72 // https://drafts.csswg.org/css-view-transitions-1/#viewtransition-phase
     73 enum class ViewTransitionPhase : uint8_t {
     74  PendingCapture = 0,
     75  UpdateCallbackCalled,
     76  Animating,
     77  Done,
     78 };
     79 
     80 class ViewTransition final : public nsISupports, public nsWrapperCache {
     81 public:
     82  using Phase = ViewTransitionPhase;
     83  using TypeList = nsTArray<RefPtr<nsAtom>>;
     84 
     85  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     86  NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ViewTransition)
     87 
     88  ViewTransition(Document&, ViewTransitionUpdateCallback*, TypeList&&);
     89 
     90  Promise* GetUpdateCallbackDone(ErrorResult&);
     91  Promise* GetReady(ErrorResult&);
     92  Promise* GetFinished(ErrorResult&);
     93  ViewTransitionTypeSet* Types();
     94  const TypeList& GetTypeList() const { return mTypeList; }
     95  TypeList& GetTypeList() { return mTypeList; }
     96 
     97  void SkipTransition(SkipTransitionReason = SkipTransitionReason::JS);
     98  MOZ_CAN_RUN_SCRIPT void PerformPendingOperations();
     99 
    100  // Get the snapshot containing block, which is the top-layer for rendering the
    101  // view transition tree.
    102  Element* GetSnapshotContainingBlock() const {
    103    return mSnapshotContainingBlock;
    104  }
    105  // Get ::view-transition pseudo element, which is the view transition tree
    106  // root. We find the pseudo element of this tree from this node.
    107  Element* GetViewTransitionTreeRoot() const;
    108  // Get all currently captured element frames if accessible.
    109  void GetCapturedFrames(nsTArray<nsIFrame*>& aCapturedFrames) const;
    110 
    111  Maybe<nsRect> GetOldInkOverflowRect(nsAtom* aName) const;
    112  Maybe<nsRect> GetNewInkOverflowRect(nsAtom* aName) const;
    113  Maybe<nsSize> GetOldBorderBoxSize(nsAtom* aName) const;
    114  Maybe<nsSize> GetNewBorderBoxSize(nsAtom* aName) const;
    115  Maybe<nsRect> GetOldActiveRect(nsAtom* aName) const;
    116  Maybe<nsRect> GetNewActiveRect(nsAtom* aName) const;
    117  // Use this to generate the old state image key for use in a stacking context.
    118  // Do not use the returned image key in an image display item, use
    119  // ReadOldImageKey instead.
    120  const wr::ImageKey* GetOrCreateOldImageKey(nsAtom* aName,
    121                                             layers::RenderRootStateManager*,
    122                                             wr::IpcResourceUpdateQueue&) const;
    123  // Use this to get the already-created old state image key for use in an image
    124  // display item.
    125  // This marks the old state image key as used which influences the how eagerly
    126  // it can be deleted.
    127  const wr::ImageKey* ReadOldImageKey(nsAtom* aName,
    128                                      layers::RenderRootStateManager*,
    129                                      wr::IpcResourceUpdateQueue&) const;
    130  const wr::ImageKey* GetNewImageKey(nsAtom* aName) const;
    131  const wr::ImageKey* GetImageKeyForCapturedFrame(
    132      nsIFrame* aFrame, layers::RenderRootStateManager*,
    133      wr::IpcResourceUpdateQueue&) const;
    134  void UpdateActiveRectForCapturedFrame(
    135      nsIFrame* capturedFrame, const gfx::MatrixScales& aInheritedScale,
    136      nsRect& aOutCapturedRect);
    137 
    138  Element* FindPseudo(const PseudoStyleRequest&) const;
    139 
    140  const StyleLockedDeclarationBlock* GetDynamicRuleFor(const Element&) const;
    141 
    142  static constexpr nsLiteralString kGroupAnimPrefix =
    143      u"-ua-view-transition-group-anim-"_ns;
    144 
    145  [[nodiscard]] bool GetGroupKeyframes(nsAtom* aAnimationName,
    146                                       const StyleComputedTimingFunction&,
    147                                       nsTArray<Keyframe>&);
    148 
    149  bool MatchClassList(nsAtom*, const nsTArray<StyleAtom>&) const;
    150 
    151  nsIGlobalObject* GetParentObject() const;
    152  JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
    153 
    154  struct CapturedElement;
    155 
    156  static nsRect SnapshotContainingBlockRect(nsPresContext*);
    157  static nsRect CapturedInkOverflowRectForFrame(nsIFrame*, bool aIsRoot);
    158  MOZ_CAN_RUN_SCRIPT void CallUpdateCallback(ErrorResult&);
    159 
    160 private:
    161  MOZ_CAN_RUN_SCRIPT void MaybeScheduleUpdateCallback();
    162  void Activate();
    163 
    164  void ClearActiveTransition(bool aIsDocumentHidden);
    165  void Timeout();
    166  MOZ_CAN_RUN_SCRIPT void Setup();
    167  [[nodiscard]] MOZ_CAN_RUN_SCRIPT Maybe<SkipTransitionReason>
    168  CaptureOldState();
    169  [[nodiscard]] Maybe<SkipTransitionReason> CaptureNewState();
    170  void SetupTransitionPseudoElements();
    171  [[nodiscard]] bool UpdatePseudoElementStyles(bool aNeedsInvalidation);
    172  void ClearNamedElements();
    173  void HandleFrame();
    174  bool CheckForActiveAnimations() const;
    175  void SkipTransition(SkipTransitionReason, JS::Handle<JS::Value>);
    176  void ClearTimeoutTimer();
    177 
    178  nsRect SnapshotContainingBlockRect() const;
    179 
    180  Maybe<uint64_t> GetElementIdentifier(Element* aElement) const;
    181  uint64_t EnsureElementIdentifier(Element* aElement);
    182 
    183  already_AddRefed<nsAtom> DocumentScopedTransitionNameFor(nsIFrame* aFrame);
    184 
    185  ~ViewTransition();
    186 
    187  // Stored for the whole lifetime of the object (until CC).
    188  RefPtr<Document> mDocument;
    189  RefPtr<ViewTransitionUpdateCallback> mUpdateCallback;
    190 
    191  // https://drafts.csswg.org/css-view-transitions/#viewtransition-named-elements
    192  using NamedElements = nsClassHashtable<nsAtomHashKey, CapturedElement>;
    193  NamedElements mNamedElements;
    194  // mNamedElements is an unordered map, we need to keep the tree order. This
    195  // also keeps the strong reference to the view-transition-name which may be
    196  // auto-generated for this view transition.
    197  AutoTArray<RefPtr<nsAtom>, 8> mNames;
    198 
    199  using OldCaptureFramesArray =
    200      AutoTArray<std::pair<nsIFrame*, RefPtr<nsAtom>>, 32>;
    201  // Short lived array pointer used to mark old captures for DL building.
    202  OldCaptureFramesArray* mOldCaptureElements = nullptr;
    203 
    204  // The element identifier for the elements which need the auto-generated
    205  // view-transition-name. The lifetime of those element identifiers is
    206  // element’s node document’s active view transition.
    207  // Note: Use a non-owning element pointer because we never dereference it.
    208  // It is just a key to map an id. The size of this hashmap is fixed after we
    209  // capture the old state and new state,
    210  using ElementIdentifiers = nsTHashMap<Element*, uint64_t>;
    211  ElementIdentifiers mElementIdentifiers;
    212 
    213  // https://drafts.csswg.org/css-view-transitions/#viewtransition-initial-snapshot-containing-block-size
    214  nsSize mInitialSnapshotContainingBlockSize;
    215 
    216  // Allocated lazily, but same object once allocated (again until CC).
    217  RefPtr<Promise> mUpdateCallbackDonePromise;
    218  RefPtr<Promise> mReadyPromise;
    219  RefPtr<Promise> mFinishedPromise;
    220 
    221  TypeList mTypeList;
    222  RefPtr<ViewTransitionTypeSet> mTypes;
    223 
    224  static void TimeoutCallback(nsITimer*, void*);
    225  RefPtr<nsITimer> mTimeoutTimer;
    226 
    227  Phase mPhase = Phase::PendingCapture;
    228  // The wrapper of the pseudo-elements tree, to make sure it is always
    229  // out-of-flow. This is the top-layer for rendering the view transition tree.
    230  // So in general, its child (and only one) is the transition root
    231  // pseudo-element.
    232  RefPtr<Element> mSnapshotContainingBlock;
    233 };
    234 
    235 }  // namespace dom
    236 }  // namespace mozilla
    237 
    238 #endif