Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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(); |
|
Charlie Reis
2015/05/18 22:48:00
Won't removing FSNs cause a regression of https://
Nate Chapin
2015/05/28 21:31:50
All of the bugs I can find are a failure to correc
| |
| 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 |
| OLD | NEW |