• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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/)
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  *
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.
17  *
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.
28  */
29 
30 #ifndef HistoryController_h
31 #define HistoryController_h
32 
33 #include "core/history/HistoryItem.h"
34 #include "core/loader/FrameLoaderTypes.h"
35 #include "wtf/HashMap.h"
36 #include "wtf/Noncopyable.h"
37 #include "wtf/RefPtr.h"
38 #include "wtf/text/WTFString.h"
39 
40 namespace WebCore {
41 
42 class Frame;
43 class HistoryEntry;
44 class Page;
45 
46 
47 // A guide to history state in Blink:
48 //
49 // HistoryController: Owned by Page, is the entry point for interacting with history.
50 //     Handles most of the operations to modify history state, navigate to an existing
51 //     back/forward entry, etc.
52 // HistoryEntry: Represents a single entry in the back/forward list, encapsulating
53 //     all frames in the page it represents. It provides access to each frame's
54 //     state via lookups by frame id or frame name.
55 // HistoryNode: Represents a single frame in a HistoryEntry. Owned by a HistoryEntry. HistoryNodes
56 // form a tree that mirrors the FrameTree in the corresponding page. HistoryNodes represent
57 // the structure of the page, but don't hold any per-frame state except a list of child frames.
58 // HistoryItem (lives in a separate file): The state for a given frame. Can persist across
59 //     navigations. HistoryItem is reference counted, and each HistoryNode holds a reference
60 //     to its single corresponding HistoryItem. Can be referenced by multiple HistoryNodes and
61 //     can therefore exist in multiple HistoryEntry instances.
62 //
63 // Suppose we have the following page, foo.com, which embeds foo.com/a in an iframe:
64 //
65 // HistoryEntry 0:
66 //     HistoryNode 0_0 (HistoryItem A (url: foo.com))
67 //         HistoryNode 0_1: (HistoryItem B (url: foo.com/a))
68 //
69 // Now we navigation the top frame to bar.com, which embeds bar.com/b and bar.com/c in iframes,
70 // and bar.com/b in turn embeds bar.com/d. We will create a new HistoryEntry with a tree
71 // containing 4 new HistoryNodes. The state will be:
72 //
73 // HistoryEntry 1:
74 //     HistoryNode 1_0 (HistoryItem C (url: bar.com))
75 //         HistoryNode 1_1: (HistoryItem D (url: bar.com/b))
76 //             HistoryNode 1_3: (HistoryItem F (url: bar.com/d))
77 //         HistoryNode 1_2: (HistoryItem E (url: bar.com/c))
78 //
79 //
80 // Finally, we navigate the first subframe from bar.com/b to bar.com/e, which embeds bar.com/f.
81 // We will create a new HistoryEntry and new HistoryNode for each frame. Any frame that
82 // navigates (bar.com/e and its child, bar.com/f) will receive a new HistoryItem. However,
83 // 2 frames were not navigated (bar.com and bar.com/c), so those two frames will reuse the
84 // existing HistoryItem:
85 //
86 // HistoryEntry 2:
87 //     HistoryNode 2_0 (HistoryItem C (url: bar.com))  *REUSED*
88 //         HistoryNode 2_1: (HistoryItem G (url: bar.com/e))
89 //            HistoryNode 2_3: (HistoryItem H (url: bar.com/f))
90 //         HistoryNode 2_2: (HistoryItem E (url: bar.com/c)) *REUSED*
91 //
92 
93 class HistoryNode {
94 public:
95     static PassOwnPtr<HistoryNode> create(HistoryEntry*, HistoryItem*);
~HistoryNode()96     ~HistoryNode() { }
97 
98     HistoryNode* addChild(PassRefPtr<HistoryItem>);
99     PassOwnPtr<HistoryNode> cloneAndReplace(HistoryEntry*, HistoryItem* newItem, bool clipAtTarget, Frame* targetFrame, Frame* currentFrame);
value()100     HistoryItem* value() { return m_value.get(); }
updateValue(PassRefPtr<HistoryItem> item)101     void updateValue(PassRefPtr<HistoryItem> item) { m_value = item; }
children()102     const Vector<OwnPtr<HistoryNode> >& children() const { return m_children; }
103     void removeChildren();
104 
105 private:
106     HistoryNode(HistoryEntry*, HistoryItem*);
107 
108     HistoryEntry* m_entry;
109     Vector<OwnPtr<HistoryNode> > m_children;
110     RefPtr<HistoryItem> m_value;
111 };
112 
113 class HistoryEntry {
114 public:
115     static PassOwnPtr<HistoryEntry> create(HistoryItem* root);
116     PassOwnPtr<HistoryEntry> cloneAndReplace(HistoryItem* newItem, bool clipAtTarget, Frame* targetFrame, Page*);
117 
118     HistoryNode* historyNodeForFrame(Frame*);
119     HistoryItem* itemForFrame(Frame*);
root()120     HistoryItem* root() const { return m_root->value(); }
rootHistoryNode()121     HistoryNode* rootHistoryNode() const { return m_root.get(); }
122 
123 private:
124     friend class HistoryNode;
125 
HistoryEntry()126     HistoryEntry() { }
127     explicit HistoryEntry(HistoryItem* root);
128 
129     OwnPtr<HistoryNode> m_root;
130     HashMap<uint64_t, HistoryNode*> m_framesToItems;
131     HashMap<String, HistoryNode*> m_uniqueNamesToItems;
132 };
133 
134 class HistoryController {
135     WTF_MAKE_NONCOPYABLE(HistoryController);
136 public:
137     explicit HistoryController(Page*);
138     ~HistoryController();
139 
140     // Should only be called by embedder. To request a back/forward
141     // navigation, call FrameLoaderClient::navigateBackForward().
142     void goToItem(HistoryItem*);
143 
144     void updateBackForwardListForFragmentScroll(Frame*, HistoryItem*);
145     void updateForCommit(Frame*, HistoryItem*);
146 
147     PassRefPtr<HistoryItem> currentItemForExport();
148     PassRefPtr<HistoryItem> previousItemForExport();
149     PassRefPtr<HistoryItem> provisionalItemForExport();
150     HistoryItem* itemForNewChildFrame(Frame*) const;
151     void removeChildrenForRedirect(Frame*);
152 
inSameDocumentLoad()153     bool inSameDocumentLoad() const { return !m_sameDocumentLoadsInProgress.isEmpty() && m_differentDocumentLoadsInProgress.isEmpty(); }
154 
155     void setDefersLoading(bool);
156 
157 private:
158     void goToEntry(PassOwnPtr<HistoryEntry>);
159     void recursiveGoToEntry(Frame*);
160 
161     void updateForInitialLoadInChildFrame(Frame*, HistoryItem*);
162     void createNewBackForwardItem(Frame*, HistoryItem*, bool doClip);
163 
164     Page* m_page;
165 
166     OwnPtr<HistoryEntry> m_currentEntry;
167     OwnPtr<HistoryEntry> m_previousEntry;
168     OwnPtr<HistoryEntry> m_provisionalEntry;
169 
170     typedef HashMap<Frame*, RefPtr<HistoryItem> > HistoryFrameLoadSet;
171     HistoryFrameLoadSet m_sameDocumentLoadsInProgress;
172     HistoryFrameLoadSet m_differentDocumentLoadsInProgress;
173 
174     bool m_defersLoading;
175     RefPtr<HistoryItem> m_deferredItem;
176 };
177 
178 } // namespace WebCore
179 
180 #endif // HistoryController_h
181