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