1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 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 /**
8  * ChildSHistory represents a view of session history from a child process. It
9  * exposes getters for some cached history state, and mutators which are
10  * implemented by communicating with the actual history storage.
11  *
12  * NOTE: Currently session history is in transition, meaning that we're still
13  * using the legacy nsSHistory class internally. The API exposed from this class
14  * should be only the API which we expect to expose when this transition is
15  * complete, and special cases will need to call through the LegacySHistory()
16  * getters.
17  */
18 
19 #ifndef mozilla_dom_ChildSHistory_h
20 #define mozilla_dom_ChildSHistory_h
21 
22 #include "nsCOMPtr.h"
23 #include "mozilla/dom/BindingDeclarations.h"
24 #include "nsWrapperCache.h"
25 #include "nsThreadUtils.h"
26 #include "mozilla/ErrorResult.h"
27 #include "mozilla/LinkedList.h"
28 #include "nsID.h"
29 
30 class nsISHEntry;
31 class nsISHistory;
32 
33 namespace mozilla {
34 namespace dom {
35 
36 class BrowsingContext;
37 
38 class ChildSHistory : public nsISupports, public nsWrapperCache {
39  public:
40   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
41   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ChildSHistory)
42   nsISupports* GetParentObject() const;
43   JSObject* WrapObject(JSContext* cx,
44                        JS::Handle<JSObject*> aGivenProto) override;
45 
46   explicit ChildSHistory(BrowsingContext* aBrowsingContext);
47 
48   void SetBrowsingContext(BrowsingContext* aBrowsingContext);
49 
50   // Create or destroy the session history implementation in the child process.
51   // This can be removed once session history is stored exclusively in the
52   // parent process.
53   void SetIsInProcess(bool aIsInProcess);
IsInProcess()54   bool IsInProcess() { return !!mHistory; }
55 
56   int32_t Count();
57   int32_t Index();
58 
59   /**
60    * Reload the current entry in the session history.
61    */
62   void Reload(uint32_t aReloadFlags, ErrorResult& aRv);
63 
64   /**
65    * The CanGo and Go methods are called with an offset from the current index.
66    * Positive numbers go forward in history, while negative numbers go
67    * backwards.
68    */
69   bool CanGo(int32_t aOffset);
70   void Go(int32_t aOffset, bool aRequireUserInteraction, bool aUserActivation,
71           ErrorResult& aRv);
72   void AsyncGo(int32_t aOffset, bool aRequireUserInteraction,
73                bool aUserActivation, CallerType aCallerType, ErrorResult& aRv);
74 
75   // aIndex is the new index, and aOffset is the offset between new and current.
76   void GotoIndex(int32_t aIndex, int32_t aOffset, bool aRequireUserInteraction,
77                  bool aUserActivation, ErrorResult& aRv);
78 
79   void RemovePendingHistoryNavigations();
80 
81   /**
82    * Evicts all content viewers within the current process.
83    */
84   void EvictLocalContentViewers();
85 
86   // GetLegacySHistory and LegacySHistory have been deprecated. Don't
87   // use these, but instead handle the interaction with nsISHistory in
88   // the parent process.
89   nsISHistory* GetLegacySHistory(ErrorResult& aError);
90   nsISHistory* LegacySHistory();
91 
92   void SetIndexAndLength(uint32_t aIndex, uint32_t aLength,
93                          const nsID& aChangeId);
94   nsID AddPendingHistoryChange();
95   nsID AddPendingHistoryChange(int32_t aIndexDelta, int32_t aLengthDelta);
96 
97  private:
98   virtual ~ChildSHistory();
99 
100   class PendingAsyncHistoryNavigation
101       : public Runnable,
102         public mozilla::LinkedListElement<PendingAsyncHistoryNavigation> {
103    public:
PendingAsyncHistoryNavigation(ChildSHistory * aHistory,int32_t aOffset,bool aRequireUserInteraction,bool aUserActivation)104     PendingAsyncHistoryNavigation(ChildSHistory* aHistory, int32_t aOffset,
105                                   bool aRequireUserInteraction,
106                                   bool aUserActivation)
107         : Runnable("PendingAsyncHistoryNavigation"),
108           mHistory(aHistory),
109           mRequireUserInteraction(aRequireUserInteraction),
110           mUserActivation(aUserActivation),
111           mOffset(aOffset) {}
112 
Run()113     NS_IMETHOD Run() override {
114       if (isInList()) {
115         remove();
116         mHistory->Go(mOffset, mRequireUserInteraction, mUserActivation,
117                      IgnoreErrors());
118       }
119       return NS_OK;
120     }
121 
122    private:
123     RefPtr<ChildSHistory> mHistory;
124     bool mRequireUserInteraction;
125     bool mUserActivation;
126     int32_t mOffset;
127   };
128 
129   RefPtr<BrowsingContext> mBrowsingContext;
130   nsCOMPtr<nsISHistory> mHistory;
131   // Can be removed once history-in-parent is the only way
132   mozilla::LinkedList<PendingAsyncHistoryNavigation> mPendingNavigations;
133   int32_t mIndex = -1;
134   int32_t mLength = 0;
135 
136   struct PendingSHistoryChange {
137     nsID mChangeID;
138     int32_t mIndexDelta;
139     int32_t mLengthDelta;
140   };
141   AutoTArray<PendingSHistoryChange, 2> mPendingSHistoryChanges;
142 
143   // Needs to start 1 above default epoch in parent
144   uint64_t mHistoryEpoch = 1;
145   bool mPendingEpoch = false;
146 };
147 
148 }  // namespace dom
149 }  // namespace mozilla
150 
151 #endif /* mozilla_dom_ChildSHistory_h */
152