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"
40 #include "content/renderer/render_frame_impl.h"
41 #include "content/renderer/render_view_impl.h"
42 #include "third_party/WebKit/public/web/WebFrame.h"
44 using blink::WebFrame
;
45 using blink::WebHistoryItem
;
49 HistoryEntry::HistoryNode
* HistoryEntry::HistoryNode::AddChild(
50 const WebHistoryItem
& item
,
52 children_
->push_back(new HistoryNode(entry_
, item
, frame_id
));
53 return children_
->back();
56 HistoryEntry::HistoryNode
* HistoryEntry::HistoryNode::CloneAndReplace(
57 HistoryEntry
* new_entry
,
58 const WebHistoryItem
& new_item
,
59 bool clone_children_of_target
,
60 RenderFrameImpl
* target_frame
,
61 RenderFrameImpl
* current_frame
) {
62 bool is_target_frame
= target_frame
== current_frame
;
63 const WebHistoryItem
& item_for_create
= is_target_frame
? new_item
: item_
;
64 HistoryNode
* new_history_node
= new HistoryNode(
65 new_entry
, item_for_create
, current_frame
->GetRoutingID());
67 if (is_target_frame
&& clone_children_of_target
&& !item_
.isNull()) {
68 new_history_node
->item().setDocumentSequenceNumber(
69 item_
.documentSequenceNumber());
72 if (clone_children_of_target
|| !is_target_frame
) {
73 for (WebFrame
* child
= current_frame
->GetWebFrame()->firstChild(); child
;
74 child
= child
->nextSibling()) {
75 RenderFrameImpl
* child_render_frame
=
76 RenderFrameImpl::FromWebFrame(child
);
77 HistoryNode
* child_history_node
=
78 entry_
->GetHistoryNodeForFrame(child_render_frame
);
79 if (!child_history_node
)
81 HistoryNode
* new_child_node
=
82 child_history_node
->CloneAndReplace(new_entry
,
84 clone_children_of_target
,
87 new_history_node
->children_
->push_back(new_child_node
);
90 return new_history_node
;
93 HistoryEntry::HistoryNode::HistoryNode(HistoryEntry
* entry
,
94 const WebHistoryItem
& item
,
96 : entry_(entry
), item_(item
) {
97 if (frame_id
!= kInvalidFrameRoutingID
)
98 entry_
->frames_to_items_
[frame_id
] = this;
99 entry_
->unique_names_to_items_
[item
.target().utf8()] = this;
100 children_
.reset(new ScopedVector
<HistoryNode
>);
103 HistoryEntry::HistoryNode::~HistoryNode() {
106 void HistoryEntry::HistoryNode::RemoveChildren() {
107 // TODO(japhet): This is inefficient. Figure out a cleaner way to ensure
108 // this HistoryNode isn't cached anywhere.
109 std::vector
<uint64_t> frames_to_remove
;
110 std::vector
<std::string
> unique_names_to_remove
;
111 for (size_t i
= 0; i
< children().size(); i
++) {
112 children().at(i
)->RemoveChildren();
114 HistoryEntry::FramesToItems::iterator frames_end
=
115 entry_
->frames_to_items_
.end();
116 HistoryEntry::UniqueNamesToItems::iterator unique_names_end
=
117 entry_
->unique_names_to_items_
.end();
118 for (HistoryEntry::FramesToItems::iterator it
=
119 entry_
->frames_to_items_
.begin();
122 if (it
->second
== children().at(i
))
123 frames_to_remove
.push_back(it
->first
);
125 for (HistoryEntry::UniqueNamesToItems::iterator it
=
126 entry_
->unique_names_to_items_
.begin();
127 it
!= unique_names_end
;
129 if (it
->second
== children().at(i
))
130 unique_names_to_remove
.push_back(it
->first
);
133 for (unsigned i
= 0; i
< frames_to_remove
.size(); i
++)
134 entry_
->frames_to_items_
.erase(frames_to_remove
[i
]);
135 for (unsigned i
= 0; i
< unique_names_to_remove
.size(); i
++)
136 entry_
->unique_names_to_items_
.erase(unique_names_to_remove
[i
]);
137 children_
.reset(new ScopedVector
<HistoryNode
>);
140 HistoryEntry::HistoryEntry() {
143 HistoryEntry::~HistoryEntry() {
146 HistoryEntry::HistoryEntry(const WebHistoryItem
& root
, int64_t frame_id
) {
147 root_
.reset(new HistoryNode(this, root
, frame_id
));
150 HistoryEntry
* HistoryEntry::CloneAndReplace(const WebHistoryItem
& new_item
,
151 bool clone_children_of_target
,
152 RenderFrameImpl
* target_frame
,
153 RenderViewImpl
* render_view
) {
154 HistoryEntry
* new_entry
= new HistoryEntry();
155 new_entry
->root_
.reset(
156 root_
->CloneAndReplace(new_entry
,
158 clone_children_of_target
,
160 render_view
->main_render_frame()));
164 HistoryEntry::HistoryNode
* HistoryEntry::GetHistoryNodeForFrame(
165 RenderFrameImpl
* frame
) {
166 if (HistoryNode
* history_node
= frames_to_items_
[frame
->GetRoutingID()])
168 return unique_names_to_items_
[frame
->GetWebFrame()->uniqueName().utf8()];
171 WebHistoryItem
HistoryEntry::GetItemForFrame(RenderFrameImpl
* frame
) {
172 if (HistoryNode
* history_node
= GetHistoryNodeForFrame(frame
))
173 return history_node
->item();
174 return WebHistoryItem();
177 } // namespace content