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/)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "BackForwardList.h"
31 #include "FrameLoader.h"
32 #include "FrameLoaderClient.h"
33 #include "HistoryItem.h"
36 #include "PageCache.h"
37 #include "SerializedScriptValue.h"
43 static const unsigned DefaultCapacity = 100;
44 static const unsigned NoCurrentItemIndex = UINT_MAX;
46 BackForwardList::BackForwardList(Page* page)
48 , m_current(NoCurrentItemIndex)
49 , m_capacity(DefaultCapacity)
55 BackForwardList::~BackForwardList()
60 void BackForwardList::addItem(PassRefPtr<HistoryItem> prpItem)
63 if (m_capacity == 0 || !m_enabled)
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());
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];
82 m_entryHash.remove(item);
83 pageCache()->remove(item.get());
87 m_entryHash.add(prpItem.get());
88 m_entries.insert(m_current + 1, prpItem);
92 void BackForwardList::goBack()
94 ASSERT(m_current > 0);
100 void BackForwardList::goForward()
102 ASSERT(m_current < m_entries.size() - 1);
103 if (m_current < m_entries.size() - 1) {
108 void BackForwardList::goToItem(HistoryItem* item)
110 if (!m_entries.size() || !item)
113 unsigned int index = 0;
114 for (; index < m_entries.size(); ++index)
115 if (m_entries[index] == item)
117 if (index < m_entries.size()) {
122 HistoryItem* BackForwardList::backItem()
124 if (m_current && m_current != NoCurrentItemIndex)
125 return m_entries[m_current - 1].get();
129 HistoryItem* BackForwardList::currentItem()
131 if (m_current != NoCurrentItemIndex)
132 return m_entries[m_current].get();
136 HistoryItem* BackForwardList::forwardItem()
138 if (m_entries.size() && m_current < m_entries.size() - 1)
139 return m_entries[m_current + 1].get();
143 void BackForwardList::backListWithLimit(int limit, HistoryItemVector& list)
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]);
153 void BackForwardList::forwardListWithLimit(int limit, HistoryItemVector& list)
157 if (!m_entries.size())
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]);
169 int BackForwardList::capacity()
174 void BackForwardList::setCapacity(int size)
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());
184 m_current = NoCurrentItemIndex;
185 else if (m_current > m_entries.size() - 1) {
186 m_current = m_entries.size() - 1;
191 bool BackForwardList::enabled()
196 void BackForwardList::setEnabled(bool enabled)
200 int capacity = m_capacity;
202 setCapacity(capacity);
206 int BackForwardList::backListCount()
208 return m_current == NoCurrentItemIndex ? 0 : m_current;
211 int BackForwardList::forwardListCount()
213 return m_current == NoCurrentItemIndex ? 0 : (int)m_entries.size() - (m_current + 1);
216 HistoryItem* BackForwardList::itemAtIndex(int index)
218 // Do range checks without doing math on index to avoid overflow.
219 if (index < -(int)m_current)
222 if (index > forwardListCount())
225 return m_entries[index + m_current].get();
228 HistoryItemVector& BackForwardList::entries()
233 void BackForwardList::close()
235 int size = m_entries.size();
236 for (int i = 0; i < size; ++i)
237 pageCache()->remove(m_entries[i].get());
244 bool BackForwardList::closed()
249 void BackForwardList::removeItem(HistoryItem* item)
254 for (unsigned i = 0; i < m_entries.size(); ++i)
255 if (m_entries[i] == item) {
257 m_entryHash.remove(item);
258 if (m_current == NoCurrentItemIndex || m_current < i)
263 size_t count = m_entries.size();
264 if (m_current >= count)
265 m_current = count ? count - 1 : NoCurrentItemIndex;
271 bool BackForwardList::containsItem(HistoryItem* entry)
273 return m_entryHash.contains(entry);
276 }; // namespace WebCore