2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2009 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
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #ifndef HistoryController_h
31 #define HistoryController_h
33 #include "core/loader/FrameLoaderTypes.h"
34 #include "core/loader/HistoryItem.h"
35 #include "platform/network/ResourceRequest.h"
36 #include "wtf/HashMap.h"
37 #include "wtf/Noncopyable.h"
38 #include "wtf/RefPtr.h"
39 #include "wtf/text/WTFString.h"
48 // A guide to history state in Blink:
50 // HistoryController: Owned by Page, is the entry point for interacting with history.
51 // Handles most of the operations to modify history state, navigate to an existing
52 // back/forward entry, etc.
53 // HistoryEntry: Represents a single entry in the back/forward list, encapsulating
54 // all frames in the page it represents. It provides access to each frame's
55 // state via lookups by frame id or frame name.
56 // HistoryNode: Represents a single frame in a HistoryEntry. Owned by a HistoryEntry. HistoryNodes
57 // form a tree that mirrors the FrameTree in the corresponding page. HistoryNodes represent
58 // the structure of the page, but don't hold any per-frame state except a list of child frames.
59 // HistoryItem (lives in a separate file): The state for a given frame. Can persist across
60 // navigations. HistoryItem is reference counted, and each HistoryNode holds a reference
61 // to its single corresponding HistoryItem. Can be referenced by multiple HistoryNodes and
62 // can therefore exist in multiple HistoryEntry instances.
64 // Suppose we have the following page, foo.com, which embeds foo.com/a in an iframe:
67 // HistoryNode 0_0 (HistoryItem A (url: foo.com))
68 // HistoryNode 0_1: (HistoryItem B (url: foo.com/a))
70 // Now we navigation the top frame to bar.com, which embeds bar.com/b and bar.com/c in iframes,
71 // and bar.com/b in turn embeds bar.com/d. We will create a new HistoryEntry with a tree
72 // containing 4 new HistoryNodes. The state will be:
75 // HistoryNode 1_0 (HistoryItem C (url: bar.com))
76 // HistoryNode 1_1: (HistoryItem D (url: bar.com/b))
77 // HistoryNode 1_3: (HistoryItem F (url: bar.com/d))
78 // HistoryNode 1_2: (HistoryItem E (url: bar.com/c))
81 // Finally, we navigate the first subframe from bar.com/b to bar.com/e, which embeds bar.com/f.
82 // We will create a new HistoryEntry and new HistoryNode for each frame. Any frame that
83 // navigates (bar.com/e and its child, bar.com/f) will receive a new HistoryItem. However,
84 // 2 frames were not navigated (bar.com and bar.com/c), so those two frames will reuse the
85 // existing HistoryItem:
88 // HistoryNode 2_0 (HistoryItem C (url: bar.com)) *REUSED*
89 // HistoryNode 2_1: (HistoryItem G (url: bar.com/e))
90 // HistoryNode 2_3: (HistoryItem H (url: bar.com/f))
91 // HistoryNode 2_2: (HistoryItem E (url: bar.com/c)) *REUSED*
96 static PassOwnPtr<HistoryNode> create(HistoryEntry*, HistoryItem*);
99 HistoryNode* addChild(PassRefPtr<HistoryItem>);
100 PassOwnPtr<HistoryNode> cloneAndReplace(HistoryEntry*, HistoryItem* newItem, bool clipAtTarget, Frame* targetFrame, Frame* currentFrame);
101 HistoryItem* value() { return m_value.get(); }
102 void updateValue(PassRefPtr<HistoryItem> item) { m_value = item; }
103 const Vector<OwnPtr<HistoryNode> >& children() const { return m_children; }
104 void removeChildren();
107 HistoryNode(HistoryEntry*, HistoryItem*);
109 HistoryEntry* m_entry;
110 Vector<OwnPtr<HistoryNode> > m_children;
111 RefPtr<HistoryItem> m_value;
117 static PassOwnPtr<HistoryEntry> create(HistoryItem* root);
118 PassOwnPtr<HistoryEntry> cloneAndReplace(HistoryItem* newItem, bool clipAtTarget, Frame* targetFrame, Page*);
120 HistoryNode* historyNodeForFrame(Frame*);
121 HistoryItem* itemForFrame(Frame*);
122 HistoryItem* root() const { return m_root->value(); }
123 HistoryNode* rootHistoryNode() const { return m_root.get(); }
126 friend class HistoryNode;
129 explicit HistoryEntry(HistoryItem* root);
131 OwnPtr<HistoryNode> m_root;
132 HashMap<uint64_t, HistoryNode*> m_framesToItems;
133 HashMap<String, HistoryNode*> m_uniqueNamesToItems;
136 class HistoryController {
137 WTF_MAKE_NONCOPYABLE(HistoryController);
139 explicit HistoryController(Page*);
140 ~HistoryController();
142 // Should only be called by embedder. To request a back/forward
143 // navigation, call FrameLoaderClient::navigateBackForward().
144 void goToItem(HistoryItem*, ResourceRequestCachePolicy);
146 void updateBackForwardListForFragmentScroll(Frame*, HistoryItem*);
147 void updateForCommit(Frame*, HistoryItem*, HistoryCommitType);
149 PassRefPtr<HistoryItem> currentItemForExport();
150 PassRefPtr<HistoryItem> previousItemForExport();
151 HistoryItem* itemForNewChildFrame(Frame*) const;
152 void removeChildrenForRedirect(Frame*);
154 void setDefersLoading(bool);
157 void goToEntry(PassOwnPtr<HistoryEntry>, ResourceRequestCachePolicy);
158 typedef HashMap<RefPtr<Frame>, RefPtr<HistoryItem> > HistoryFrameLoadSet;
159 void recursiveGoToEntry(Frame*, HistoryFrameLoadSet& sameDocumentLoads, HistoryFrameLoadSet& differentDocumentLoads);
161 void updateForInitialLoadInChildFrame(Frame*, HistoryItem*);
162 void createNewBackForwardItem(Frame*, HistoryItem*, bool doClip);
166 OwnPtr<HistoryEntry> m_currentEntry;
167 OwnPtr<HistoryEntry> m_previousEntry;
168 OwnPtr<HistoryEntry> m_provisionalEntry;
170 bool m_defersLoading;
171 RefPtr<HistoryItem> m_deferredItem;
172 ResourceRequestCachePolicy m_deferredCachePolicy;
175 } // namespace WebCore
177 #endif // HistoryController_h