1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
9 * (http://www.torchmobile.com/)
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
21 * its contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
25 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "content/renderer/history_entry.h"
38 #include "content/renderer/render_frame_impl.h"
39 #include "content/renderer/render_view_impl.h"
40 #include "third_party/WebKit/public/web/WebFrame.h"
42 using blink::WebFrame
;
43 using blink::WebHistoryItem
;
47 HistoryEntry::HistoryNode
* HistoryEntry::HistoryNode::AddChild(
48 const WebHistoryItem
& item
,
50 children_
->push_back(new HistoryNode(entry_
, item
, frame_id
));
51 return children_
->back();
54 HistoryEntry::HistoryNode
* HistoryEntry::HistoryNode::AddChild() {
55 return AddChild(WebHistoryItem(), kInvalidFrameRoutingID
);
58 HistoryEntry::HistoryNode
* HistoryEntry::HistoryNode::CloneAndReplace(
59 HistoryEntry
* new_entry
,
60 const WebHistoryItem
& new_item
,
61 bool clone_children_of_target
,
62 RenderFrameImpl
* target_frame
,
63 RenderFrameImpl
* current_frame
) {
64 bool is_target_frame
= target_frame
== current_frame
;
65 const WebHistoryItem
& item_for_create
= is_target_frame
? new_item
: item_
;
66 HistoryNode
* new_history_node
= new HistoryNode(
67 new_entry
, item_for_create
, current_frame
->GetRoutingID());
69 if (is_target_frame
&& clone_children_of_target
&& !item_
.isNull()) {
70 new_history_node
->item().setDocumentSequenceNumber(
71 item_
.documentSequenceNumber());
74 if (clone_children_of_target
|| !is_target_frame
) {
75 for (WebFrame
* child
= current_frame
->GetWebFrame()->firstChild(); child
;
76 child
= child
->nextSibling()) {
77 RenderFrameImpl
* child_render_frame
=
78 RenderFrameImpl::FromWebFrame(child
);
79 HistoryNode
* child_history_node
=
80 entry_
->GetHistoryNodeForFrame(child_render_frame
);
81 if (!child_history_node
)
83 HistoryNode
* new_child_node
=
84 child_history_node
->CloneAndReplace(new_entry
,
86 clone_children_of_target
,
89 new_history_node
->children_
->push_back(new_child_node
);
92 return new_history_node
;
95 void HistoryEntry::HistoryNode::set_item(const WebHistoryItem
& item
) {
96 // The previous HistoryItem might not have had a target set, or it might be
97 // different than the current one.
98 entry_
->unique_names_to_items_
[item
.target().utf8()] = this;
102 HistoryEntry::HistoryNode::HistoryNode(HistoryEntry
* entry
,
103 const WebHistoryItem
& item
,
105 : entry_(entry
), item_(item
) {
106 if (frame_id
!= kInvalidFrameRoutingID
)
107 entry_
->frames_to_items_
[frame_id
] = this;
109 entry_
->unique_names_to_items_
[item
.target().utf8()] = this;
110 children_
.reset(new ScopedVector
<HistoryNode
>);
113 HistoryEntry::HistoryNode::~HistoryNode() {
116 void HistoryEntry::HistoryNode::RemoveChildren() {
117 // TODO(japhet): This is inefficient. Figure out a cleaner way to ensure
118 // this HistoryNode isn't cached anywhere.
119 std::vector
<uint64_t> frames_to_remove
;
120 std::vector
<std::string
> unique_names_to_remove
;
121 for (size_t i
= 0; i
< children().size(); i
++) {
122 children().at(i
)->RemoveChildren();
124 HistoryEntry::FramesToItems::iterator frames_end
=
125 entry_
->frames_to_items_
.end();
126 HistoryEntry::UniqueNamesToItems::iterator unique_names_end
=
127 entry_
->unique_names_to_items_
.end();
128 for (HistoryEntry::FramesToItems::iterator it
=
129 entry_
->frames_to_items_
.begin();
132 if (it
->second
== children().at(i
))
133 frames_to_remove
.push_back(it
->first
);
135 for (HistoryEntry::UniqueNamesToItems::iterator it
=
136 entry_
->unique_names_to_items_
.begin();
137 it
!= unique_names_end
;
139 if (it
->second
== children().at(i
))
140 unique_names_to_remove
.push_back(it
->first
);
143 for (unsigned i
= 0; i
< frames_to_remove
.size(); i
++)
144 entry_
->frames_to_items_
.erase(frames_to_remove
[i
]);
145 for (unsigned i
= 0; i
< unique_names_to_remove
.size(); i
++)
146 entry_
->unique_names_to_items_
.erase(unique_names_to_remove
[i
]);
147 children_
.reset(new ScopedVector
<HistoryNode
>);
150 HistoryEntry::HistoryEntry() {
151 root_
.reset(new HistoryNode(this, WebHistoryItem(), kInvalidFrameRoutingID
));
154 HistoryEntry::~HistoryEntry() {
157 HistoryEntry::HistoryEntry(const WebHistoryItem
& root
, int64_t frame_id
) {
158 root_
.reset(new HistoryNode(this, root
, frame_id
));
161 HistoryEntry
* HistoryEntry::CloneAndReplace(const WebHistoryItem
& new_item
,
162 bool clone_children_of_target
,
163 RenderFrameImpl
* target_frame
,
164 RenderViewImpl
* render_view
) {
165 HistoryEntry
* new_entry
= new HistoryEntry();
166 new_entry
->root_
.reset(
167 root_
->CloneAndReplace(new_entry
,
169 clone_children_of_target
,
171 render_view
->main_render_frame()));
175 HistoryEntry::HistoryNode
* HistoryEntry::GetHistoryNodeForFrame(
176 RenderFrameImpl
* frame
) {
177 if (HistoryNode
* history_node
= frames_to_items_
[frame
->GetRoutingID()])
179 return unique_names_to_items_
[frame
->GetWebFrame()->uniqueName().utf8()];
182 WebHistoryItem
HistoryEntry::GetItemForFrame(RenderFrameImpl
* frame
) {
183 if (HistoryNode
* history_node
= GetHistoryNodeForFrame(frame
))
184 return history_node
->item();
185 return WebHistoryItem();
188 } // namespace content