1/*
2 * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
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#ifndef HistoryItem_h
28#define HistoryItem_h
29
30#include "IntPoint.h"
31#include "SerializedScriptValue.h"
32#include <wtf/HashMap.h>
33#include <wtf/OwnPtr.h>
34#include <wtf/PassOwnPtr.h>
35#include <wtf/RefCounted.h>
36#include <wtf/text/WTFString.h>
37
38#if PLATFORM(MAC)
39#import <wtf/RetainPtr.h>
40typedef struct objc_object* id;
41#endif
42
43#if PLATFORM(QT)
44#include <QVariant>
45#include <QByteArray>
46#include <QDataStream>
47#endif
48
49#if PLATFORM(BLACKBERRY)
50#include "HistoryItemViewState.h"
51#endif
52
53namespace WebCore {
54
55class CachedPage;
56class Document;
57class FormData;
58class HistoryItem;
59class Image;
60class KURL;
61class ResourceRequest;
62
63typedef Vector<RefPtr<HistoryItem> > HistoryItemVector;
64
65extern void (*notifyHistoryItemChanged)(HistoryItem*);
66
67enum VisitCountBehavior {
68    IncreaseVisitCount,
69    DoNotIncreaseVisitCount
70};
71
72class HistoryItem : public RefCounted<HistoryItem> {
73    friend class PageCache;
74
75public:
76    static PassRefPtr<HistoryItem> create() { return adoptRef(new HistoryItem); }
77    static PassRefPtr<HistoryItem> create(const String& urlString, const String& title, double lastVisited)
78    {
79        return adoptRef(new HistoryItem(urlString, title, lastVisited));
80    }
81    static PassRefPtr<HistoryItem> create(const String& urlString, const String& title, const String& alternateTitle, double lastVisited)
82    {
83        return adoptRef(new HistoryItem(urlString, title, alternateTitle, lastVisited));
84    }
85    static PassRefPtr<HistoryItem> create(const KURL& url, const String& target, const String& parent, const String& title)
86    {
87        return adoptRef(new HistoryItem(url, target, parent, title));
88    }
89
90    ~HistoryItem();
91
92    PassRefPtr<HistoryItem> copy() const;
93
94    // Resets the HistoryItem to its initial state, as returned by create().
95    void reset();
96
97    void encodeBackForwardTree(Encoder&) const;
98    static PassRefPtr<HistoryItem> decodeBackForwardTree(const String& urlString, const String& title, const String& originalURLString, Decoder&);
99
100    const String& originalURLString() const;
101    const String& urlString() const;
102    const String& title() const;
103
104    bool isInPageCache() const { return m_cachedPage; }
105    bool hasCachedPageExpired() const;
106
107    double lastVisitedTime() const;
108
109    void setAlternateTitle(const String& alternateTitle);
110    const String& alternateTitle() const;
111
112    const String& parent() const;
113    KURL url() const;
114    KURL originalURL() const;
115    const String& referrer() const;
116    const String& target() const;
117    bool isTargetItem() const;
118
119    FormData* formData();
120    String formContentType() const;
121
122    int visitCount() const;
123    bool lastVisitWasFailure() const { return m_lastVisitWasFailure; }
124    bool lastVisitWasHTTPNonGet() const { return m_lastVisitWasHTTPNonGet; }
125
126    void mergeAutoCompleteHints(HistoryItem* otherItem);
127
128    const IntPoint& scrollPoint() const;
129    void setScrollPoint(const IntPoint&);
130    void clearScrollPoint();
131
132    float pageScaleFactor() const;
133    void setPageScaleFactor(float);
134
135    const Vector<String>& documentState() const;
136    void setDocumentState(const Vector<String>&);
137    void clearDocumentState();
138
139    void setURL(const KURL&);
140    void setURLString(const String&);
141    void setOriginalURLString(const String&);
142    void setReferrer(const String&);
143    void setTarget(const String&);
144    void setParent(const String&);
145    void setTitle(const String&);
146    void setIsTargetItem(bool);
147
148    void setStateObject(PassRefPtr<SerializedScriptValue> object);
149    PassRefPtr<SerializedScriptValue> stateObject() const { return m_stateObject; }
150
151    void setItemSequenceNumber(long long number) { m_itemSequenceNumber = number; }
152    long long itemSequenceNumber() const { return m_itemSequenceNumber; }
153
154    void setDocumentSequenceNumber(long long number) { m_documentSequenceNumber = number; }
155    long long documentSequenceNumber() const { return m_documentSequenceNumber; }
156
157    void setFormInfoFromRequest(const ResourceRequest&);
158    void setFormData(PassRefPtr<FormData>);
159    void setFormContentType(const String&);
160
161    void recordInitialVisit();
162
163    void setVisitCount(int);
164    void setLastVisitWasFailure(bool wasFailure) { m_lastVisitWasFailure = wasFailure; }
165    void setLastVisitWasHTTPNonGet(bool wasNotGet) { m_lastVisitWasHTTPNonGet = wasNotGet; }
166
167    void addChildItem(PassRefPtr<HistoryItem>);
168    void setChildItem(PassRefPtr<HistoryItem>);
169    HistoryItem* childItemWithTarget(const String&) const;
170    HistoryItem* childItemWithDocumentSequenceNumber(long long number) const;
171    HistoryItem* targetItem();
172    const HistoryItemVector& children() const;
173    bool hasChildren() const;
174    void clearChildren();
175    bool isAncestorOf(const HistoryItem*) const;
176
177    bool shouldDoSameDocumentNavigationTo(HistoryItem* otherItem) const;
178    bool hasSameFrames(HistoryItem* otherItem) const;
179
180    // This should not be called directly for HistoryItems that are already included
181    // in GlobalHistory. The WebKit api for this is to use -[WebHistory setLastVisitedTimeInterval:forItem:] instead.
182    void setLastVisitedTime(double);
183    void visited(const String& title, double time, VisitCountBehavior);
184
185    void addRedirectURL(const String&);
186    Vector<String>* redirectURLs() const;
187    void setRedirectURLs(PassOwnPtr<Vector<String> >);
188
189    bool isCurrentDocument(Document*) const;
190
191#if PLATFORM(MAC)
192    id viewState() const;
193    void setViewState(id);
194
195    // Transient properties may be of any ObjC type.  They are intended to be used to store state per back/forward list entry.
196    // The properties will not be persisted; when the history item is removed, the properties will be lost.
197    id getTransientProperty(const String&) const;
198    void setTransientProperty(const String&, id);
199#endif
200
201#if PLATFORM(QT)
202    QVariant userData() const { return m_userData; }
203    void setUserData(const QVariant& userData) { m_userData = userData; }
204
205    static PassRefPtr<HistoryItem> restoreState(QDataStream& buffer, int version);
206    QDataStream& saveState(QDataStream& out, int version) const;
207#endif
208
209#if PLATFORM(BLACKBERRY)
210    HistoryItemViewState& viewState() { return m_viewState; }
211#endif
212
213#ifndef NDEBUG
214    int showTree() const;
215    int showTreeWithIndent(unsigned indentLevel) const;
216#endif
217
218    void adoptVisitCounts(Vector<int>& dailyCounts, Vector<int>& weeklyCounts);
219    const Vector<int>& dailyVisitCounts() const { return m_dailyVisitCounts; }
220    const Vector<int>& weeklyVisitCounts() const { return m_weeklyVisitCounts; }
221
222private:
223    HistoryItem();
224    HistoryItem(const String& urlString, const String& title, double lastVisited);
225    HistoryItem(const String& urlString, const String& title, const String& alternateTitle, double lastVisited);
226    HistoryItem(const KURL& url, const String& frameName, const String& parent, const String& title);
227
228    explicit HistoryItem(const HistoryItem&);
229
230    void padDailyCountsForNewVisit(double time);
231    void collapseDailyVisitsToWeekly();
232    void recordVisitAtTime(double, VisitCountBehavior = IncreaseVisitCount);
233
234    bool hasSameDocumentTree(HistoryItem* otherItem) const;
235
236    HistoryItem* findTargetItem();
237
238    void encodeBackForwardTreeNode(Encoder&) const;
239
240    /* When adding new member variables to this class, please notify the Qt team.
241     * qt/HistoryItemQt.cpp contains code to serialize history items.
242     */
243
244    String m_urlString;
245    String m_originalURLString;
246    String m_referrer;
247    String m_target;
248    String m_parent;
249    String m_title;
250    String m_displayTitle;
251
252    double m_lastVisitedTime;
253    bool m_lastVisitWasHTTPNonGet;
254
255    IntPoint m_scrollPoint;
256    float m_pageScaleFactor;
257    Vector<String> m_documentState;
258
259    HistoryItemVector m_children;
260
261    bool m_lastVisitWasFailure;
262    bool m_isTargetItem;
263    int m_visitCount;
264    Vector<int> m_dailyVisitCounts;
265    Vector<int> m_weeklyVisitCounts;
266
267    OwnPtr<Vector<String> > m_redirectURLs;
268
269    // If two HistoryItems have the same item sequence number, then they are
270    // clones of one another.  Traversing history from one such HistoryItem to
271    // another is a no-op.  HistoryItem clones are created for parent and
272    // sibling frames when only a subframe navigates.
273    int64_t m_itemSequenceNumber;
274
275    // If two HistoryItems have the same document sequence number, then they
276    // refer to the same instance of a document.  Traversing history from one
277    // such HistoryItem to another preserves the document.
278    int64_t m_documentSequenceNumber;
279
280    // Support for HTML5 History
281    RefPtr<SerializedScriptValue> m_stateObject;
282
283    // info used to repost form data
284    RefPtr<FormData> m_formData;
285    String m_formContentType;
286
287    // PageCache controls these fields.
288    HistoryItem* m_next;
289    HistoryItem* m_prev;
290    RefPtr<CachedPage> m_cachedPage;
291
292#if PLATFORM(MAC)
293    RetainPtr<id> m_viewState;
294    OwnPtr<HashMap<String, RetainPtr<id> > > m_transientProperties;
295#endif
296
297#if PLATFORM(QT)
298    QVariant m_userData;
299#endif
300
301#if PLATFORM(BLACKBERRY)
302    HistoryItemViewState m_viewState;
303#endif
304}; //class HistoryItem
305
306} //namespace WebCore
307
308#ifndef NDEBUG
309// Outside the WebCore namespace for ease of invocation from gdb.
310extern "C" int showTree(const WebCore::HistoryItem*);
311#endif
312
313#endif // HISTORYITEM_H
314