1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 /*
7  * container for information saved in session history when the document
8  * is not
9  */
10 
11 #include "nsILayoutHistoryState.h"
12 #include "nsWeakReference.h"
13 #include "nsClassHashtable.h"
14 #include "nsPresState.h"
15 #include "mozilla/Attributes.h"
16 
17 class nsLayoutHistoryState final : public nsILayoutHistoryState,
18                                    public nsSupportsWeakReference
19 {
20 public:
21   nsLayoutHistoryState()
22     : mScrollPositionOnly(false)
23   {
24   }
25 
26   NS_DECL_ISUPPORTS
27 
28   // nsILayoutHistoryState
29   virtual void
30   AddState(const nsCString& aKey, nsPresState* aState) override;
31   virtual nsPresState*
32   GetState(const nsCString& aKey) override;
33   virtual void
34   RemoveState(const nsCString& aKey) override;
35   virtual bool
36   HasStates() const override;
37   virtual void
38   SetScrollPositionOnly(const bool aFlag) override;
39   virtual void
40   ResetScrollState() override;
41 
42 private:
43   ~nsLayoutHistoryState() {}
44   bool mScrollPositionOnly;
45 
46   nsClassHashtable<nsCStringHashKey,nsPresState> mStates;
47 };
48 
49 
50 already_AddRefed<nsILayoutHistoryState>
51 NS_NewLayoutHistoryState()
52 {
53   RefPtr<nsLayoutHistoryState> state = new nsLayoutHistoryState();
54   return state.forget();
55 }
56 
57 NS_IMPL_ISUPPORTS(nsLayoutHistoryState,
58                   nsILayoutHistoryState,
59                   nsISupportsWeakReference)
60 
61 void
62 nsLayoutHistoryState::AddState(const nsCString& aStateKey, nsPresState* aState)
63 {
64   mStates.Put(aStateKey, aState);
65 }
66 
67 nsPresState*
68 nsLayoutHistoryState::GetState(const nsCString& aKey)
69 {
70   nsPresState* state = nullptr;
71   bool entryExists = mStates.Get(aKey, &state);
72 
73   if (entryExists && mScrollPositionOnly) {
74     // Ensure any state that shouldn't be restored is removed
75     state->ClearNonScrollState();
76   }
77 
78   return state;
79 }
80 
81 void
82 nsLayoutHistoryState::RemoveState(const nsCString& aKey)
83 {
84   mStates.Remove(aKey);
85 }
86 
87 bool
88 nsLayoutHistoryState::HasStates() const
89 {
90   return mStates.Count() != 0;
91 }
92 
93 void
94 nsLayoutHistoryState::SetScrollPositionOnly(const bool aFlag)
95 {
96   mScrollPositionOnly = aFlag;
97 }
98 
99 void
100 nsLayoutHistoryState::ResetScrollState()
101 {
102   for (auto iter = mStates.Iter(); !iter.Done(); iter.Next()) {
103     nsPresState* state = iter.UserData();
104     if (state) {
105       state->SetScrollState(nsPoint(0, 0));
106     }
107   }
108 }
109