tor-browser

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

Navigation.h (13236B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_dom_Navigation_h___
      8 #define mozilla_dom_Navigation_h___
      9 
     10 #include "mozilla/AlreadyAddRefed.h"
     11 #include "mozilla/DOMEventTargetHelper.h"
     12 #include "mozilla/Maybe.h"
     13 #include "mozilla/RefPtr.h"
     14 #include "mozilla/dom/NavigateEvent.h"
     15 #include "mozilla/dom/NavigationBinding.h"
     16 #include "nsHashtablesFwd.h"
     17 #include "nsStringFwd.h"
     18 
     19 class nsIDHashKey;
     20 
     21 namespace mozilla::dom {
     22 
     23 class FormData;
     24 class NavigationActivation;
     25 class NavigationDestination;
     26 class NavigationHistoryEntry;
     27 struct NavigationNavigateOptions;
     28 struct NavigationOptions;
     29 class NavigationTransition;
     30 struct NavigationUpdateCurrentEntryOptions;
     31 struct NavigationReloadOptions;
     32 struct NavigationResult;
     33 
     34 class SessionHistoryInfo;
     35 
     36 // https://html.spec.whatwg.org/#navigation-api-method-tracker
     37 struct NavigationAPIMethodTracker final : public nsISupports {
     38  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     39  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(NavigationAPIMethodTracker)
     40 
     41  NavigationAPIMethodTracker(Navigation* aNavigationObject,
     42                             const Maybe<nsID> aKey, const JS::Value& aInfo,
     43                             nsIStructuredCloneContainer* aSerializedState,
     44                             NavigationHistoryEntry* aCommittedToEntry,
     45                             Promise* aCommittedPromise,
     46                             Promise* aFinishedPromise, bool aPending = false);
     47 
     48  // Mark this tracker as no longer pending (promoted to ongoing).
     49  void MarkAsNotPending() { mPending = false; }
     50 
     51  void CleanUp();
     52  void NotifyAboutCommittedToEntry(NavigationHistoryEntry* aNHE);
     53  void ResolveFinishedPromise();
     54  void RejectFinishedPromise(JS::Handle<JS::Value> aException);
     55  void CreateResult(JSContext* aCx, NavigationResult& aResult);
     56  void SetSerializedState(nsIStructuredCloneContainer* aSerializedState) {
     57    mSerializedState = aSerializedState;
     58  }
     59 
     60  Promise* CommittedPromise() { return mCommittedPromise; }
     61  Promise* FinishedPromise() { return mFinishedPromise; }
     62 
     63  RefPtr<Navigation> mNavigationObject;
     64  Maybe<nsID> mKey;
     65  JS::Heap<JS::Value> mInfo;
     66 
     67 private:
     68  ~NavigationAPIMethodTracker();
     69 
     70  bool mPending;
     71  RefPtr<nsIStructuredCloneContainer> mSerializedState;
     72  RefPtr<NavigationHistoryEntry> mCommittedToEntry;
     73  RefPtr<Promise> mCommittedPromise;
     74  RefPtr<Promise> mFinishedPromise;
     75 };
     76 
     77 class Navigation final : public DOMEventTargetHelper {
     78 public:
     79  NS_DECL_ISUPPORTS_INHERITED
     80  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Navigation, DOMEventTargetHelper)
     81 
     82  explicit Navigation(nsPIDOMWindowInner* aWindow);
     83 
     84  bool IsNavigation() const override { return true; }
     85 
     86  NS_IMPL_FROMEVENTTARGET_HELPER(Navigation, IsNavigation())
     87 
     88  using EventTarget::EventListenerAdded;
     89  virtual void EventListenerAdded(nsAtom* aType) override;
     90  using EventTarget::EventListenerRemoved;
     91  virtual void EventListenerRemoved(nsAtom* aType) override;
     92 
     93  // Navigation.webidl
     94  void Entries(nsTArray<RefPtr<NavigationHistoryEntry>>& aResult) const;
     95  already_AddRefed<NavigationHistoryEntry> GetCurrentEntry() const;
     96  MOZ_CAN_RUN_SCRIPT
     97  void UpdateCurrentEntry(JSContext* aCx,
     98                          const NavigationUpdateCurrentEntryOptions& aOptions,
     99                          ErrorResult& aRv);
    100  NavigationTransition* GetTransition() const;
    101  NavigationActivation* GetActivation() const;
    102 
    103  bool CanGoBack() {
    104    return !HasEntriesAndEventsDisabled() && mCurrentEntryIndex &&
    105           *mCurrentEntryIndex != 0;
    106  }
    107  bool CanGoForward() {
    108    return !HasEntriesAndEventsDisabled() && mCurrentEntryIndex &&
    109           *mCurrentEntryIndex != mEntries.Length() - 1;
    110  }
    111 
    112  void Navigate(JSContext* aCx, const nsAString& aUrl,
    113                const NavigationNavigateOptions& aOptions,
    114                NavigationResult& aResult);
    115 
    116  MOZ_CAN_RUN_SCRIPT void Reload(JSContext* aCx,
    117                                 const NavigationReloadOptions& aOptions,
    118                                 NavigationResult& aResult);
    119 
    120  void TraverseTo(JSContext* aCx, const nsAString& aKey,
    121                  const NavigationOptions& aOptions, NavigationResult& aResult);
    122  void Back(JSContext* aCx, const NavigationOptions& aOptions,
    123            NavigationResult& aResult);
    124  void Forward(JSContext* aCx, const NavigationOptions& aOptions,
    125               NavigationResult& aResult);
    126 
    127  IMPL_EVENT_HANDLER(navigate);
    128  IMPL_EVENT_HANDLER(navigatesuccess);
    129  IMPL_EVENT_HANDLER(navigateerror);
    130  IMPL_EVENT_HANDLER(currententrychange);
    131 
    132  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#initialize-the-navigation-api-entries-for-a-new-document
    133  void InitializeHistoryEntries(
    134      mozilla::Span<const SessionHistoryInfo> aNewSHInfos,
    135      const SessionHistoryInfo* aInitialSHInfo);
    136 
    137  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-reactivation
    138  MOZ_CAN_RUN_SCRIPT
    139  void UpdateForReactivation(SessionHistoryInfo* aReactivatedEntry);
    140 
    141  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
    142  void UpdateEntriesForSameDocumentNavigation(
    143      SessionHistoryInfo* aDestinationSHE, NavigationType aNavigationType);
    144 
    145  JSObject* WrapObject(JSContext* aCx,
    146                       JS::Handle<JSObject*> aGivenProto) override;
    147 
    148  // The Navigation API is only enabled if both SessionHistoryInParent and
    149  // the dom.navigation.webidl.enabled pref are set.
    150  static bool IsAPIEnabled(JSContext* /* unused */ = nullptr,
    151                           JSObject* /* unused */ = nullptr);
    152 
    153  // Wrapper algorithms for firing the navigate event.
    154  // https://html.spec.whatwg.org/#navigate-event-firing
    155 
    156  MOZ_CAN_RUN_SCRIPT bool FireTraverseNavigateEvent(
    157      JSContext* aCx, const SessionHistoryInfo& aDestinationSessionHistoryInfo,
    158      Maybe<UserNavigationInvolvement> aUserInvolvement);
    159 
    160  MOZ_CAN_RUN_SCRIPT bool FirePushReplaceReloadNavigateEvent(
    161      JSContext* aCx, NavigationType aNavigationType, nsIURI* aDestinationURL,
    162      bool aIsSameDocument, Maybe<UserNavigationInvolvement> aUserInvolvement,
    163      Element* aSourceElement, FormData* aFormDataEntryList,
    164      nsIStructuredCloneContainer* aNavigationAPIState,
    165      nsIStructuredCloneContainer* aClassicHistoryAPIState,
    166      NavigationAPIMethodTracker* aApiMethodTrackerForNavigateOrReload =
    167          nullptr);
    168 
    169  MOZ_CAN_RUN_SCRIPT bool FireDownloadRequestNavigateEvent(
    170      JSContext* aCx, nsIURI* aDestinationURL,
    171      UserNavigationInvolvement aUserInvolvement, Element* aSourceElement,
    172      const nsAString& aFilename);
    173 
    174  bool FocusedChangedDuringOngoingNavigation() const;
    175  void SetFocusedChangedDuringOngoingNavigation(
    176      bool aFocusChangedDuringOngoingNavigation);
    177 
    178  bool HasOngoingNavigateEvent() const;
    179 
    180  MOZ_CAN_RUN_SCRIPT
    181  void InnerInformAboutAbortingNavigation(JSContext* aCx);
    182 
    183  MOZ_CAN_RUN_SCRIPT
    184  void AbortOngoingNavigation(
    185      JSContext* aCx, JS::Handle<JS::Value> aError = JS::UndefinedHandleValue);
    186 
    187  MOZ_CAN_RUN_SCRIPT
    188  void AbortNavigateEvent(JSContext* aCx, NavigateEvent* aEvent,
    189                          JS::Handle<JS::Value> aReason);
    190 
    191  MOZ_CAN_RUN_SCRIPT
    192  void InformAboutChildNavigableDestruction(JSContext* aCx);
    193 
    194  void CreateNavigationActivationFrom(
    195      SessionHistoryInfo* aPreviousEntryForActivation,
    196      NavigationType aNavigationType);
    197 
    198  void SetSerializedStateIntoOngoingAPIMethodTracker(
    199      nsIStructuredCloneContainer* aSerializedState);
    200 
    201 private:
    202  friend struct NavigationAPIMethodTracker;
    203  friend struct NavigationWaitForAllScope;
    204  using UpcomingTraverseAPIMethodTrackers =
    205      nsTHashMap<nsIDHashKey, RefPtr<NavigationAPIMethodTracker>>;
    206 
    207  ~Navigation() = default;
    208 
    209  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#has-entries-and-events-disabled
    210  bool HasEntriesAndEventsDisabled() const;
    211 
    212  MOZ_CAN_RUN_SCRIPT
    213  nsresult FireEvent(const nsAString& aName);
    214 
    215  MOZ_CAN_RUN_SCRIPT
    216  nsresult FireErrorEvent(const nsAString& aName,
    217                          const ErrorEventInit& aEventInitDict);
    218 
    219  // https://html.spec.whatwg.org/#inner-navigate-event-firing-algorithm
    220  MOZ_CAN_RUN_SCRIPT bool InnerFireNavigateEvent(
    221      JSContext* aCx, NavigationType aNavigationType,
    222      NavigationDestination* aDestination,
    223      UserNavigationInvolvement aUserInvolvement, Element* aSourceElement,
    224      FormData* aFormDataEntryList,
    225      nsIStructuredCloneContainer* aClassicHistoryAPIState,
    226      const nsAString& aDownloadRequestFilename,
    227      NavigationAPIMethodTracker* aNavigationAPIMethodTracker = nullptr);
    228 
    229  NavigationHistoryEntry* FindNavigationHistoryEntry(
    230      const SessionHistoryInfo& aSessionHistoryInfo) const;
    231 
    232  RefPtr<NavigationAPIMethodTracker> SetUpNavigateReloadAPIMethodTracker(
    233      JS::Handle<JS::Value> aInfo,
    234      nsIStructuredCloneContainer* aSerializedState);
    235 
    236  RefPtr<NavigationAPIMethodTracker> AddUpcomingTraverseAPIMethodTracker(
    237      const nsID& aKey, JS::Handle<JS::Value> aInfo);
    238 
    239  void SetEarlyErrorResult(JSContext* aCx, NavigationResult& aResult,
    240                           ErrorResult&& aRv) const;
    241 
    242  void SetEarlyStateErrorResult(JSContext* aCx, NavigationResult& aResult,
    243                                const nsACString& aMessage) const;
    244 
    245  bool CheckIfDocumentIsFullyActiveAndMaybeSetEarlyErrorResult(
    246      JSContext* aCx, const Document* aDocument,
    247      NavigationResult& aResult) const;
    248 
    249  bool CheckDocumentUnloadCounterAndMaybeSetEarlyErrorResult(
    250      JSContext* aCx, const Document* aDocument,
    251      NavigationResult& aResult) const;
    252 
    253  already_AddRefed<nsIStructuredCloneContainer>
    254  CreateSerializedStateAndMaybeSetEarlyErrorResult(
    255      JSContext* aCx, const JS::Value& aState, NavigationResult& aResult) const;
    256 
    257  static void CleanUp(NavigationAPIMethodTracker* aNavigationAPIMethodTracker);
    258 
    259  void SetCurrentEntryIndex(const SessionHistoryInfo* aTargetInfo);
    260 
    261  Document* GetAssociatedDocument() const;
    262 
    263  // Update the state managing if we need to dispatch the traverse event or not.
    264  void UpdateNeedsTraverse();
    265 
    266  void LogHistory() const;
    267 
    268  void PerformNavigationTraversal(JSContext* aCx, const nsID& aKey,
    269                                  const NavigationOptions& aOptions,
    270                                  NavigationResult& aResult);
    271 
    272  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-entry-list
    273  nsTArray<RefPtr<NavigationHistoryEntry>> mEntries;
    274 
    275  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigation-current-entry
    276  Maybe<uint64_t> mCurrentEntryIndex;
    277 
    278  // https://html.spec.whatwg.org/#ongoing-navigation-tracking:navigateevent-2
    279  RefPtr<NavigateEvent> mOngoingNavigateEvent;
    280 
    281  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#focus-changed-during-ongoing-navigation
    282  bool mFocusChangedDuringOngoingNavigation = false;
    283 
    284  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#suppress-normal-scroll-restoration-during-ongoing-navigation
    285  bool mSuppressNormalScrollRestorationDuringOngoingNavigation = false;
    286 
    287  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#ongoing-api-method-tracker
    288  RefPtr<NavigationAPIMethodTracker> mOngoingAPIMethodTracker;
    289 
    290  // https://html.spec.whatwg.org/multipage/nav-history-apis.html#upcoming-traverse-api-method-trackers
    291  UpcomingTraverseAPIMethodTrackers mUpcomingTraverseAPIMethodTrackers;
    292 
    293  // https://html.spec.whatwg.org/#concept-navigation-transition
    294  RefPtr<NavigationTransition> mTransition;
    295 
    296  // https://html.spec.whatwg.org/#navigation-activation
    297  RefPtr<NavigationActivation> mActivation;
    298 };
    299 
    300 inline Navigation* EventTarget::GetAsNavigation() {
    301  return IsNavigation() ? AsNavigation() : nullptr;
    302 }
    303 inline const Navigation* EventTarget::GetAsNavigation() const {
    304  return IsNavigation() ? AsNavigation() : nullptr;
    305 }
    306 inline Navigation* EventTarget::AsNavigation() {
    307  MOZ_DIAGNOSTIC_ASSERT(IsNavigation());
    308  return static_cast<Navigation*>(this);
    309 }
    310 inline const Navigation* EventTarget::AsNavigation() const {
    311  MOZ_DIAGNOSTIC_ASSERT(IsNavigation());
    312  return static_cast<const Navigation*>(this);
    313 }
    314 
    315 }  // namespace mozilla::dom
    316 
    317 template <>
    318 struct fmt::formatter<mozilla::dom::NavigationType, char>
    319    : public formatter<nsLiteralCString> {
    320  template <typename FmtContext>
    321  constexpr auto format(const mozilla::dom::NavigationType& aNavigationType,
    322                        FmtContext& aCtx) const {
    323    return formatter<nsLiteralCString>::format(
    324        mozilla::dom::GetEnumString(aNavigationType), aCtx);
    325  }
    326 };
    327 
    328 template <>
    329 struct fmt::formatter<mozilla::dom::NavigationHistoryBehavior, char>
    330    : public formatter<nsLiteralCString> {
    331  template <typename FmtContext>
    332  constexpr auto format(
    333      const mozilla::dom::NavigationHistoryBehavior& aNavigationHistoryBehavior,
    334      FmtContext& aCtx) const {
    335    return formatter<nsLiteralCString>::format(
    336        mozilla::dom::GetEnumString(aNavigationHistoryBehavior), aCtx);
    337  }
    338 };
    339 
    340 #endif  // mozilla_dom_Navigation_h___