Missed one BackForwardListImpl.h in the last commit.
[WebKit-https.git] / Source / WebCore / history / BackForwardList.cpp
1 /*
2  * Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "BackForwardList.h"
29
30 #include "Frame.h"
31 #include "FrameLoader.h"
32 #include "FrameLoaderClient.h"
33 #include "HistoryItem.h"
34 #include "Logging.h"
35 #include "Page.h"
36 #include "PageCache.h"
37 #include "SerializedScriptValue.h"
38
39 using namespace std;
40
41 namespace WebCore {
42
43 static const unsigned DefaultCapacity = 100;
44 static const unsigned NoCurrentItemIndex = UINT_MAX;
45
46 BackForwardList::BackForwardList(Page* page)
47     : m_page(page)
48     , m_current(NoCurrentItemIndex)
49     , m_capacity(DefaultCapacity)
50     , m_closed(true)
51     , m_enabled(true)
52 {
53 }
54
55 BackForwardList::~BackForwardList()
56 {
57     ASSERT(m_closed);
58 }
59
60 void BackForwardList::addItem(PassRefPtr<HistoryItem> prpItem)
61 {
62     ASSERT(prpItem);
63     if (m_capacity == 0 || !m_enabled)
64         return;
65     
66     // Toss anything in the forward list    
67     if (m_current != NoCurrentItemIndex) {
68         unsigned targetSize = m_current + 1;
69         while (m_entries.size() > targetSize) {
70             RefPtr<HistoryItem> item = m_entries.last();
71             m_entries.removeLast();
72             m_entryHash.remove(item);
73             pageCache()->remove(item.get());
74         }
75     }
76
77     // Toss the first item if the list is getting too big, as long as we're not using it
78     // (or even if we are, if we only want 1 entry).
79     if (m_entries.size() == m_capacity && (m_current != 0 || m_capacity == 1)) {
80         RefPtr<HistoryItem> item = m_entries[0];
81         m_entries.remove(0);
82         m_entryHash.remove(item);
83         pageCache()->remove(item.get());
84         m_current--;
85     }
86
87     m_entryHash.add(prpItem.get());
88     m_entries.insert(m_current + 1, prpItem);
89     m_current++;
90 }
91
92 void BackForwardList::goBack()
93 {
94     ASSERT(m_current > 0);
95     if (m_current > 0) {
96         m_current--;
97     }
98 }
99
100 void BackForwardList::goForward()
101 {
102     ASSERT(m_current < m_entries.size() - 1);
103     if (m_current < m_entries.size() - 1) {
104         m_current++;
105     }
106 }
107
108 void BackForwardList::goToItem(HistoryItem* item)
109 {
110     if (!m_entries.size() || !item)
111         return;
112         
113     unsigned int index = 0;
114     for (; index < m_entries.size(); ++index)
115         if (m_entries[index] == item)
116             break;
117     if (index < m_entries.size()) {
118         m_current = index;
119     }
120 }
121
122 HistoryItem* BackForwardList::backItem()
123 {
124     if (m_current && m_current != NoCurrentItemIndex)
125         return m_entries[m_current - 1].get();
126     return 0;
127 }
128
129 HistoryItem* BackForwardList::currentItem()
130 {
131     if (m_current != NoCurrentItemIndex)
132         return m_entries[m_current].get();
133     return 0;
134 }
135
136 HistoryItem* BackForwardList::forwardItem()
137 {
138     if (m_entries.size() && m_current < m_entries.size() - 1)
139         return m_entries[m_current + 1].get();
140     return 0;
141 }
142
143 void BackForwardList::backListWithLimit(int limit, HistoryItemVector& list)
144 {
145     list.clear();
146     if (m_current != NoCurrentItemIndex) {
147         unsigned first = max((int)m_current - limit, 0);
148         for (; first < m_current; ++first)
149             list.append(m_entries[first]);
150     }
151 }
152
153 void BackForwardList::forwardListWithLimit(int limit, HistoryItemVector& list)
154 {
155     ASSERT(limit > -1);
156     list.clear();
157     if (!m_entries.size())
158         return;
159         
160     unsigned lastEntry = m_entries.size() - 1;
161     if (m_current < lastEntry) {
162         int last = min(m_current + limit, lastEntry);
163         limit = m_current + 1;
164         for (; limit <= last; ++limit)
165             list.append(m_entries[limit]);
166     }
167 }
168
169 int BackForwardList::capacity()
170 {
171     return m_capacity;
172 }
173
174 void BackForwardList::setCapacity(int size)
175 {    
176     while (size < (int)m_entries.size()) {
177         RefPtr<HistoryItem> item = m_entries.last();
178         m_entries.removeLast();
179         m_entryHash.remove(item);
180         pageCache()->remove(item.get());
181     }
182
183     if (!size)
184         m_current = NoCurrentItemIndex;
185     else if (m_current > m_entries.size() - 1) {
186         m_current = m_entries.size() - 1;
187     }
188     m_capacity = size;
189 }
190
191 bool BackForwardList::enabled()
192 {
193     return m_enabled;
194 }
195
196 void BackForwardList::setEnabled(bool enabled)
197 {
198     m_enabled = enabled;
199     if (!enabled) {
200         int capacity = m_capacity;
201         setCapacity(0);
202         setCapacity(capacity);
203     }
204 }
205
206 int BackForwardList::backListCount()
207 {
208     return m_current == NoCurrentItemIndex ? 0 : m_current;
209 }
210
211 int BackForwardList::forwardListCount()
212 {
213     return m_current == NoCurrentItemIndex ? 0 : (int)m_entries.size() - (m_current + 1);
214 }
215
216 HistoryItem* BackForwardList::itemAtIndex(int index)
217 {
218     // Do range checks without doing math on index to avoid overflow.
219     if (index < -(int)m_current)
220         return 0;
221     
222     if (index > forwardListCount())
223         return 0;
224         
225     return m_entries[index + m_current].get();
226 }
227
228 HistoryItemVector& BackForwardList::entries()
229 {
230     return m_entries;
231 }
232
233 void BackForwardList::close()
234 {
235     int size = m_entries.size();
236     for (int i = 0; i < size; ++i)
237         pageCache()->remove(m_entries[i].get());
238     m_entries.clear();
239     m_entryHash.clear();
240     m_page = 0;
241     m_closed = true;
242 }
243
244 bool BackForwardList::closed()
245 {
246     return m_closed;
247 }
248
249 void BackForwardList::removeItem(HistoryItem* item)
250 {
251     if (!item)
252         return;
253     
254     for (unsigned i = 0; i < m_entries.size(); ++i)
255         if (m_entries[i] == item) {
256             m_entries.remove(i);
257             m_entryHash.remove(item);
258             if (m_current == NoCurrentItemIndex || m_current < i)
259                 break;
260             if (m_current > i)
261                 m_current--;
262             else {
263                 size_t count = m_entries.size();
264                 if (m_current >= count)
265                     m_current = count ? count - 1 : NoCurrentItemIndex;
266             }
267             break;
268         }
269 }
270
271 bool BackForwardList::containsItem(HistoryItem* entry)
272 {
273     return m_entryHash.contains(entry);
274 }
275
276 }; // namespace WebCore