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 * container for information saved in session history when the document
9 * is not
10 */
11
12 #include "nsILayoutHistoryState.h"
13 #include "nsWeakReference.h"
14 #include "nsClassHashtable.h"
15 #include "nsPresState.h"
16 #include "mozilla/Attributes.h"
17
18 class nsLayoutHistoryState final : public nsILayoutHistoryState,
19 public nsSupportsWeakReference {
20 public:
nsLayoutHistoryState()21 nsLayoutHistoryState() : mScrollPositionOnly(false) {}
22
23 NS_DECL_ISUPPORTS
24 NS_DECL_NSILAYOUTHISTORYSTATE
25
26 private:
~nsLayoutHistoryState()27 ~nsLayoutHistoryState() {}
28 bool mScrollPositionOnly;
29
30 nsClassHashtable<nsCStringHashKey, nsPresState> mStates;
31 };
32
NS_NewLayoutHistoryState()33 already_AddRefed<nsILayoutHistoryState> NS_NewLayoutHistoryState() {
34 RefPtr<nsLayoutHistoryState> state = new nsLayoutHistoryState();
35 return state.forget();
36 }
37
NS_IMPL_ISUPPORTS(nsLayoutHistoryState,nsILayoutHistoryState,nsISupportsWeakReference)38 NS_IMPL_ISUPPORTS(nsLayoutHistoryState, nsILayoutHistoryState,
39 nsISupportsWeakReference)
40
41 NS_IMETHODIMP
42 nsLayoutHistoryState::GetHasStates(bool* aHasStates) {
43 *aHasStates = HasStates();
44 return NS_OK;
45 }
46
47 NS_IMETHODIMP
GetKeys(uint32_t * aCount,char *** aKeys)48 nsLayoutHistoryState::GetKeys(uint32_t* aCount, char*** aKeys) {
49 if (!HasStates()) {
50 return NS_ERROR_FAILURE;
51 }
52
53 char** keys =
54 static_cast<char**>(moz_xmalloc(sizeof(char*) * mStates.Count()));
55 *aCount = mStates.Count();
56 *aKeys = keys;
57
58 for (auto iter = mStates.Iter(); !iter.Done(); iter.Next()) {
59 *keys = ToNewCString(iter.Key());
60 keys++;
61 }
62
63 return NS_OK;
64 }
65
66 NS_IMETHODIMP
GetPresState(const nsACString & aKey,float * aScrollX,float * aScrollY,bool * aAllowScrollOriginDowngrade,float * aRes,bool * aScaleToRes)67 nsLayoutHistoryState::GetPresState(const nsACString& aKey, float* aScrollX,
68 float* aScrollY,
69 bool* aAllowScrollOriginDowngrade,
70 float* aRes, bool* aScaleToRes) {
71 nsPresState* state = GetState(nsCString(aKey));
72
73 if (!state) {
74 return NS_ERROR_FAILURE;
75 }
76
77 *aScrollX = state->GetScrollPosition().x;
78 *aScrollY = state->GetScrollPosition().y;
79 *aAllowScrollOriginDowngrade = state->GetAllowScrollOriginDowngrade();
80 *aRes = state->GetResolution();
81 *aScaleToRes = state->GetScaleToResolution();
82
83 return NS_OK;
84 }
85
86 NS_IMETHODIMP
AddNewPresState(const nsACString & aKey,float aScrollX,float aScrollY,bool aAllowScrollOriginDowngrade,float aRes,bool aScaleToRes)87 nsLayoutHistoryState::AddNewPresState(const nsACString& aKey, float aScrollX,
88 float aScrollY,
89 bool aAllowScrollOriginDowngrade,
90 float aRes, bool aScaleToRes) {
91 nsPresState* newState = new nsPresState();
92 newState->SetScrollState(nsPoint(aScrollX, aScrollY));
93 newState->SetAllowScrollOriginDowngrade(aAllowScrollOriginDowngrade);
94 newState->SetResolution(aRes);
95 newState->SetScaleToResolution(aScaleToRes);
96
97 mStates.Put(nsCString(aKey), newState);
98
99 return NS_OK;
100 }
101
AddState(const nsCString & aStateKey,nsPresState * aState)102 void nsLayoutHistoryState::AddState(const nsCString& aStateKey,
103 nsPresState* aState) {
104 mStates.Put(aStateKey, aState);
105 }
106
GetState(const nsCString & aKey)107 nsPresState* nsLayoutHistoryState::GetState(const nsCString& aKey) {
108 nsPresState* state = nullptr;
109 bool entryExists = mStates.Get(aKey, &state);
110
111 if (entryExists && mScrollPositionOnly) {
112 // Ensure any state that shouldn't be restored is removed
113 state->ClearNonScrollState();
114 }
115
116 return state;
117 }
118
RemoveState(const nsCString & aKey)119 void nsLayoutHistoryState::RemoveState(const nsCString& aKey) {
120 mStates.Remove(aKey);
121 }
122
HasStates()123 bool nsLayoutHistoryState::HasStates() { return mStates.Count() != 0; }
124
SetScrollPositionOnly(const bool aFlag)125 void nsLayoutHistoryState::SetScrollPositionOnly(const bool aFlag) {
126 mScrollPositionOnly = aFlag;
127 }
128
ResetScrollState()129 void nsLayoutHistoryState::ResetScrollState() {
130 for (auto iter = mStates.Iter(); !iter.Done(); iter.Next()) {
131 nsPresState* state = iter.UserData();
132 if (state) {
133 state->SetScrollState(nsPoint(0, 0));
134 }
135 }
136 }
137