Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(467)

Side by Side Diff: content/renderer/history_entry.cc

Issue 1138543002: Better remove HistoryNodes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove frame sequence numbers from serialization Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/renderer/history_entry.h ('k') | content/renderer/history_serialization.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /* 5 /*
6 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 6 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 7 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
9 * (http://www.torchmobile.com/) 9 * (http://www.torchmobile.com/)
10 * 10 *
(...skipping 26 matching lines...) Expand all
37 37
38 #include "content/renderer/render_frame_impl.h" 38 #include "content/renderer/render_frame_impl.h"
39 #include "content/renderer/render_view_impl.h" 39 #include "content/renderer/render_view_impl.h"
40 #include "third_party/WebKit/public/web/WebLocalFrame.h" 40 #include "third_party/WebKit/public/web/WebLocalFrame.h"
41 41
42 using blink::WebFrame; 42 using blink::WebFrame;
43 using blink::WebHistoryItem; 43 using blink::WebHistoryItem;
44 44
45 namespace content { 45 namespace content {
46 46
47 // Frame routing ids are not safe to serialize, so instead create a mapping
48 // from routing ids to frame sequence numbers. The sequence numbers can be
49 // benignly serialized with limited risk of collision in a different process.
50 // FrameMap is a singleton per-process.
51 typedef base::hash_map<uint64_t, uint64_t> FrameMap;
52 static FrameMap& GetFrameMap() {
53 CR_DEFINE_STATIC_LOCAL(FrameMap, routing_ids_to_internal_frame_ids, ());
54 return routing_ids_to_internal_frame_ids;
55 }
56
57 HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::AddChild( 47 HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::AddChild(
58 const WebHistoryItem& item, 48 const WebHistoryItem& item) {
59 int64_t frame_id) { 49 children_->push_back(new HistoryNode(entry_, item));
60 children_->push_back(new HistoryNode(entry_, item, frame_id));
61 return children_->back(); 50 return children_->back();
62 } 51 }
63 52
64 HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::AddChild() { 53 HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::AddChild() {
65 return AddChild(WebHistoryItem(), kInvalidFrameRoutingID); 54 return AddChild(WebHistoryItem());
66 } 55 }
67 56
68 HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::CloneAndReplace( 57 HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::CloneAndReplace(
69 HistoryEntry* new_entry, 58 const base::WeakPtr<HistoryEntry>& new_entry,
70 const WebHistoryItem& new_item, 59 const WebHistoryItem& new_item,
71 bool clone_children_of_target, 60 bool clone_children_of_target,
72 RenderFrameImpl* target_frame, 61 RenderFrameImpl* target_frame,
73 RenderFrameImpl* current_frame) { 62 RenderFrameImpl* current_frame) {
74 bool is_target_frame = target_frame == current_frame; 63 bool is_target_frame = target_frame == current_frame;
75 const WebHistoryItem& item_for_create = is_target_frame ? new_item : item_; 64 const WebHistoryItem& item_for_create = is_target_frame ? new_item : item_;
76 HistoryNode* new_history_node = new HistoryNode( 65 HistoryNode* new_history_node = new HistoryNode(new_entry, item_for_create);
77 new_entry, item_for_create, current_frame->GetRoutingID());
78 66
79 if (is_target_frame && clone_children_of_target && !item_.isNull()) { 67 if (is_target_frame && clone_children_of_target && !item_.isNull()) {
80 new_history_node->item().setDocumentSequenceNumber( 68 new_history_node->item().setDocumentSequenceNumber(
81 item_.documentSequenceNumber()); 69 item_.documentSequenceNumber());
82 } 70 }
83 71
84 if (clone_children_of_target || !is_target_frame) { 72 if (clone_children_of_target || !is_target_frame) {
85 for (WebFrame* child = current_frame->GetWebFrame()->firstChild(); child; 73 for (WebFrame* child = current_frame->GetWebFrame()->firstChild(); child;
86 child = child->nextSibling()) { 74 child = child->nextSibling()) {
87 RenderFrameImpl* child_render_frame = 75 RenderFrameImpl* child_render_frame =
(...skipping 13 matching lines...) Expand all
101 clone_children_of_target, 89 clone_children_of_target,
102 target_frame, 90 target_frame,
103 child_render_frame); 91 child_render_frame);
104 new_history_node->children_->push_back(new_child_node); 92 new_history_node->children_->push_back(new_child_node);
105 } 93 }
106 } 94 }
107 return new_history_node; 95 return new_history_node;
108 } 96 }
109 97
110 void HistoryEntry::HistoryNode::set_item(const WebHistoryItem& item) { 98 void HistoryEntry::HistoryNode::set_item(const WebHistoryItem& item) {
111 // The previous HistoryItem might not have had a target set, or it might be 99 DCHECK(!item.isNull());
112 // different than the current one.
113 entry_->unique_names_to_items_[item.target().utf8()] = this; 100 entry_->unique_names_to_items_[item.target().utf8()] = this;
114 entry_->frames_to_items_[item.frameSequenceNumber()] = this; 101 unique_names_.push_back(item.target().utf8());
115 item_ = item; 102 item_ = item;
116 } 103 }
117 104
118 HistoryEntry::HistoryNode::HistoryNode(HistoryEntry* entry, 105 HistoryEntry::HistoryNode::HistoryNode(const base::WeakPtr<HistoryEntry>& entry,
119 const WebHistoryItem& item, 106 const WebHistoryItem& item)
120 int64_t frame_id) 107 : entry_(entry) {
121 : entry_(entry), item_(item) { 108 if (!item.isNull())
122 if (frame_id != kInvalidFrameRoutingID) { 109 set_item(item);
123 // Each history item is given a frame sequence number on creation.
124 // If we've already mapped this frame id to a sequence number, standardize
125 // this item to that sequence number. Otherwise, map the frame id to this
126 // item's existing sequence number.
127 if (GetFrameMap()[frame_id] == 0)
128 GetFrameMap()[frame_id] = item_.frameSequenceNumber();
129 else if (!item_.isNull())
130 item_.setFrameSequenceNumber(GetFrameMap()[frame_id]);
131 entry_->frames_to_items_[GetFrameMap()[frame_id]] = this;
132 }
133
134 if (!item_.isNull())
135 entry_->unique_names_to_items_[item_.target().utf8()] = this;
136 children_.reset(new ScopedVector<HistoryNode>); 110 children_.reset(new ScopedVector<HistoryNode>);
137 } 111 }
138 112
139 HistoryEntry::HistoryNode::~HistoryNode() { 113 HistoryEntry::HistoryNode::~HistoryNode() {
114 if (!entry_ || item_.isNull())
115 return;
116
117 for (std::string name : unique_names_) {
118 if (entry_->unique_names_to_items_[name] == this)
119 entry_->unique_names_to_items_.erase(name);
120 }
140 } 121 }
141 122
142 void HistoryEntry::HistoryNode::RemoveChildren() { 123 void HistoryEntry::HistoryNode::RemoveChildren() {
143 // TODO(japhet): This is inefficient. Figure out a cleaner way to ensure
144 // this HistoryNode isn't cached anywhere.
145 std::vector<uint64_t> frames_to_remove;
146 std::vector<std::string> unique_names_to_remove;
147 for (size_t i = 0; i < children().size(); i++) {
148 children().at(i)->RemoveChildren();
149
150 HistoryEntry::FramesToItems::iterator frames_end =
151 entry_->frames_to_items_.end();
152 HistoryEntry::UniqueNamesToItems::iterator unique_names_end =
153 entry_->unique_names_to_items_.end();
154 for (HistoryEntry::FramesToItems::iterator it =
155 entry_->frames_to_items_.begin();
156 it != frames_end;
157 ++it) {
158 if (it->second == children().at(i))
159 frames_to_remove.push_back(GetFrameMap()[it->first]);
160 }
161 for (HistoryEntry::UniqueNamesToItems::iterator it =
162 entry_->unique_names_to_items_.begin();
163 it != unique_names_end;
164 ++it) {
165 if (it->second == children().at(i))
166 unique_names_to_remove.push_back(it->first);
167 }
168 }
169 for (unsigned i = 0; i < frames_to_remove.size(); i++)
170 entry_->frames_to_items_.erase(frames_to_remove[i]);
171 for (unsigned i = 0; i < unique_names_to_remove.size(); i++)
172 entry_->unique_names_to_items_.erase(unique_names_to_remove[i]);
173 children_.reset(new ScopedVector<HistoryNode>); 124 children_.reset(new ScopedVector<HistoryNode>);
174 } 125 }
175 126
176 HistoryEntry::HistoryEntry() { 127 HistoryEntry::HistoryEntry() : weak_ptr_factory_(this) {
177 root_.reset(new HistoryNode(this, WebHistoryItem(), kInvalidFrameRoutingID)); 128 root_.reset(
129 new HistoryNode(weak_ptr_factory_.GetWeakPtr(), WebHistoryItem()));
178 } 130 }
179 131
180 HistoryEntry::~HistoryEntry() { 132 HistoryEntry::~HistoryEntry() {
181 } 133 }
182 134
183 HistoryEntry::HistoryEntry(const WebHistoryItem& root, int64_t frame_id) { 135 HistoryEntry::HistoryEntry(const WebHistoryItem& root)
184 root_.reset(new HistoryNode(this, root, frame_id)); 136 : weak_ptr_factory_(this) {
137 root_.reset(new HistoryNode(weak_ptr_factory_.GetWeakPtr(), root));
185 } 138 }
186 139
187 HistoryEntry* HistoryEntry::CloneAndReplace(const WebHistoryItem& new_item, 140 HistoryEntry* HistoryEntry::CloneAndReplace(const WebHistoryItem& new_item,
188 bool clone_children_of_target, 141 bool clone_children_of_target,
189 RenderFrameImpl* target_frame, 142 RenderFrameImpl* target_frame,
190 RenderViewImpl* render_view) { 143 RenderViewImpl* render_view) {
191 HistoryEntry* new_entry = new HistoryEntry(); 144 HistoryEntry* new_entry = new HistoryEntry();
192 new_entry->root_.reset( 145 new_entry->root_.reset(
193 root_->CloneAndReplace(new_entry, 146 root_->CloneAndReplace(new_entry->weak_ptr_factory_.GetWeakPtr(),
194 new_item, 147 new_item, clone_children_of_target, target_frame,
195 clone_children_of_target,
196 target_frame,
197 render_view->GetMainRenderFrame())); 148 render_view->GetMainRenderFrame()));
198 return new_entry; 149 return new_entry;
199 } 150 }
200 151
201 HistoryEntry::HistoryNode* HistoryEntry::GetHistoryNodeForFrame( 152 HistoryEntry::HistoryNode* HistoryEntry::GetHistoryNodeForFrame(
202 RenderFrameImpl* frame) { 153 RenderFrameImpl* frame) {
203 if (HistoryNode* history_node = 154 if (!frame->GetWebFrame()->parent())
204 frames_to_items_[GetFrameMap()[frame->GetRoutingID()]]) 155 return root_history_node();
205 return history_node;
206 return unique_names_to_items_[frame->GetWebFrame()->uniqueName().utf8()]; 156 return unique_names_to_items_[frame->GetWebFrame()->uniqueName().utf8()];
207 } 157 }
208 158
209 WebHistoryItem HistoryEntry::GetItemForFrame(RenderFrameImpl* frame) { 159 WebHistoryItem HistoryEntry::GetItemForFrame(RenderFrameImpl* frame) {
210 if (HistoryNode* history_node = GetHistoryNodeForFrame(frame)) 160 if (HistoryNode* history_node = GetHistoryNodeForFrame(frame))
211 return history_node->item(); 161 return history_node->item();
212 return WebHistoryItem(); 162 return WebHistoryItem();
213 } 163 }
214 164
215 } // namespace content 165 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/history_entry.h ('k') | content/renderer/history_serialization.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698