Index: content/renderer/history_entry.cc |
diff --git a/content/renderer/history_entry.cc b/content/renderer/history_entry.cc |
index 63c1ea0f1d3d588bde9a13ecb150b71065a2f955..67806342bed91d4f25e709f0783735a5200f571b 100644 |
--- a/content/renderer/history_entry.cc |
+++ b/content/renderer/history_entry.cc |
@@ -44,6 +44,16 @@ using blink::WebHistoryItem; |
namespace content { |
+// Frame routing ids are not safe to serialize, so instead create a mapping |
+// from routing ids to frame sequence numbers. The sequence numbers can be |
+// benignly serialized with limited risk of collision in a different process. |
+// FrameMap is a singleton per-process. |
+typedef base::hash_map<uint64_t, uint64_t> FrameMap; |
+static FrameMap& GetFrameMap() { |
+ CR_DEFINE_STATIC_LOCAL(FrameMap, routing_ids_to_internal_frame_ids, ()); |
+ return routing_ids_to_internal_frame_ids; |
+} |
+ |
HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::AddChild( |
const WebHistoryItem& item, |
int64_t frame_id) { |
@@ -96,6 +106,7 @@ void HistoryEntry::HistoryNode::set_item(const WebHistoryItem& item) { |
// The previous HistoryItem might not have had a target set, or it might be |
// different than the current one. |
entry_->unique_names_to_items_[item.target().utf8()] = this; |
+ entry_->frames_to_items_[item.frameSequenceNumber()] = this; |
item_ = item; |
} |
@@ -103,10 +114,20 @@ HistoryEntry::HistoryNode::HistoryNode(HistoryEntry* entry, |
const WebHistoryItem& item, |
int64_t frame_id) |
: entry_(entry), item_(item) { |
- if (frame_id != kInvalidFrameRoutingID) |
- entry_->frames_to_items_[frame_id] = this; |
- if (!item.isNull()) |
- entry_->unique_names_to_items_[item.target().utf8()] = this; |
+ if (frame_id != kInvalidFrameRoutingID) { |
+ // Each history item is given a frame sequence number on creation. |
+ // If we've already mapped this frame id to a sequence number, standardize |
+ // this item to that sequence number. Otherwise, map the frame id to this |
+ // item's existing sequence number. |
+ if (GetFrameMap()[frame_id] == 0) |
+ GetFrameMap()[frame_id] = item_.frameSequenceNumber(); |
+ else if (!item_.isNull()) |
+ item_.setFrameSequenceNumber(GetFrameMap()[frame_id]); |
+ entry_->frames_to_items_[GetFrameMap()[frame_id]] = this; |
+ } |
+ |
+ if (!item_.isNull()) |
+ entry_->unique_names_to_items_[item_.target().utf8()] = this; |
children_.reset(new ScopedVector<HistoryNode>); |
} |
@@ -130,7 +151,7 @@ void HistoryEntry::HistoryNode::RemoveChildren() { |
it != frames_end; |
++it) { |
if (it->second == children().at(i)) |
- frames_to_remove.push_back(it->first); |
+ frames_to_remove.push_back(GetFrameMap()[it->first]); |
} |
for (HistoryEntry::UniqueNamesToItems::iterator it = |
entry_->unique_names_to_items_.begin(); |
@@ -174,7 +195,8 @@ HistoryEntry* HistoryEntry::CloneAndReplace(const WebHistoryItem& new_item, |
HistoryEntry::HistoryNode* HistoryEntry::GetHistoryNodeForFrame( |
RenderFrameImpl* frame) { |
- if (HistoryNode* history_node = frames_to_items_[frame->GetRoutingID()]) |
+ if (HistoryNode* history_node = |
+ frames_to_items_[GetFrameMap()[frame->GetRoutingID()]]) |
return history_node; |
return unique_names_to_items_[frame->GetWebFrame()->uniqueName().utf8()]; |
} |