| 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 17 matching lines...) Expand all Loading... |
| 28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 34 */ | 34 */ |
| 35 | 35 |
| 36 #include "content/renderer/history_controller.h" | 36 #include "content/renderer/history_controller.h" |
| 37 | 37 |
| 38 #include <deque> | |
| 39 | |
| 40 #include "content/renderer/render_frame_impl.h" | 38 #include "content/renderer/render_frame_impl.h" |
| 41 #include "content/renderer/render_view_impl.h" | 39 #include "content/renderer/render_view_impl.h" |
| 42 #include "third_party/WebKit/public/platform/WebVector.h" | |
| 43 #include "third_party/WebKit/public/web/WebFrame.h" | 40 #include "third_party/WebKit/public/web/WebFrame.h" |
| 44 | 41 |
| 45 using blink::WebFrame; | 42 using blink::WebFrame; |
| 46 using blink::WebHistoryCommitType; | 43 using blink::WebHistoryCommitType; |
| 47 using blink::WebHistoryItem; | 44 using blink::WebHistoryItem; |
| 48 using blink::WebURLRequest; | 45 using blink::WebURLRequest; |
| 49 using blink::WebVector; | |
| 50 | 46 |
| 51 namespace content { | 47 namespace content { |
| 52 | 48 |
| 53 HistoryController::HistoryController(RenderViewImpl* render_view) | 49 HistoryController::HistoryController(RenderViewImpl* render_view) |
| 54 : render_view_(render_view) { | 50 : render_view_(render_view) { |
| 55 } | 51 } |
| 56 | 52 |
| 57 HistoryController::~HistoryController() { | 53 HistoryController::~HistoryController() { |
| 58 } | 54 } |
| 59 | 55 |
| 60 void HistoryController::GoToEntry(HistoryEntry* target_entry, | 56 void HistoryController::GoToEntry(HistoryEntry* target_entry, |
| 61 WebURLRequest::CachePolicy cache_policy) { | 57 WebURLRequest::CachePolicy cache_policy) { |
| 62 HistoryFrameLoadVector same_document_loads; | 58 HistoryFrameLoadVector same_document_loads; |
| 63 HistoryFrameLoadVector different_document_loads; | 59 HistoryFrameLoadVector different_document_loads; |
| 64 | 60 |
| 65 provisional_entry_.reset(target_entry); | 61 provisional_entry_.reset(target_entry); |
| 66 | 62 |
| 67 WebFrame* main_frame = render_view_->main_render_frame()->GetWebFrame(); | 63 WebFrame* main_frame = render_view_->main_render_frame()->GetWebFrame(); |
| 68 if (current_entry_) { | 64 if (current_entry_) { |
| 69 RecursiveGoToEntry( | 65 RecursiveGoToEntry( |
| 70 main_frame, same_document_loads, different_document_loads); | 66 main_frame, same_document_loads, different_document_loads); |
| 71 } else { | |
| 72 different_document_loads.push_back( | |
| 73 std::make_pair(main_frame, provisional_entry_->root())); | |
| 74 } | 67 } |
| 75 | 68 |
| 76 if (same_document_loads.empty() && different_document_loads.empty()) { | 69 if (same_document_loads.empty() && different_document_loads.empty()) { |
| 77 same_document_loads.push_back( | 70 // If we don't have any frames to navigate at this point, either |
| 71 // (1) there is no previous history entry to compare against, or |
| 72 // (2) we were unable to match any frames by name. In the first case, |
| 73 // doing a different document navigation to the root item is the only valid |
| 74 // thing to do. In the second case, we should have been able to find a |
| 75 // frame to navigate based on names if this were a same document |
| 76 // navigation, so we can safely assume this is the different document case. |
| 77 different_document_loads.push_back( |
| 78 std::make_pair(main_frame, provisional_entry_->root())); | 78 std::make_pair(main_frame, provisional_entry_->root())); |
| 79 } | 79 } else if (different_document_loads.empty()) { |
| 80 | 80 // If we have only same document navigations to perform, immediately |
| 81 if (different_document_loads.empty()) { | 81 // declare the load "committed" by updating the current entry. |
| 82 // TODO(japhet): This is a historical quirk, because same-document |
| 83 // history navigations call UpdateForCommit() with commit type |
| 84 // HistoryInertCommit. If that is fixed, we can remove this block. |
| 82 previous_entry_.reset(current_entry_.release()); | 85 previous_entry_.reset(current_entry_.release()); |
| 83 current_entry_.reset(provisional_entry_.release()); | 86 current_entry_.reset(provisional_entry_.release()); |
| 84 } | 87 } |
| 85 | 88 |
| 86 for (size_t i = 0; i < same_document_loads.size(); ++i) { | 89 for (size_t i = 0; i < same_document_loads.size(); ++i) { |
| 87 WebFrame* frame = same_document_loads[i].first; | 90 WebFrame* frame = same_document_loads[i].first; |
| 88 if (!RenderFrameImpl::FromWebFrame(frame)) | 91 if (!RenderFrameImpl::FromWebFrame(frame)) |
| 89 continue; | 92 continue; |
| 90 frame->loadHistoryItem(same_document_loads[i].second, | 93 frame->loadHistoryItem(same_document_loads[i].second, |
| 91 blink::WebHistorySameDocumentLoad, | 94 blink::WebHistorySameDocumentLoad, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 different_document_loads.push_back(std::make_pair(frame, new_item)); | 127 different_document_loads.push_back(std::make_pair(frame, new_item)); |
| 125 return; | 128 return; |
| 126 } | 129 } |
| 127 | 130 |
| 128 for (WebFrame* child = frame->firstChild(); child; | 131 for (WebFrame* child = frame->firstChild(); child; |
| 129 child = child->nextSibling()) { | 132 child = child->nextSibling()) { |
| 130 RecursiveGoToEntry(child, same_document_loads, different_document_loads); | 133 RecursiveGoToEntry(child, same_document_loads, different_document_loads); |
| 131 } | 134 } |
| 132 } | 135 } |
| 133 | 136 |
| 134 void HistoryController::GoToItem(const WebHistoryItem& target_item, | |
| 135 WebURLRequest::CachePolicy cache_policy) { | |
| 136 // We don't have enough information to set a correct frame id here. This | |
| 137 // might be a restore from disk, and the frame ids might not match up if the | |
| 138 // state was saved from a different process. Ensure the HistoryEntry's main | |
| 139 // frame id matches the actual main frame id. Its subframe ids are invalid to | |
| 140 // ensure they don't accidentally match a potentially random frame. | |
| 141 HistoryEntry* new_entry = new HistoryEntry( | |
| 142 target_item, render_view_->main_render_frame()->GetRoutingID()); | |
| 143 std::deque<HistoryEntry::HistoryNode*> history_nodes; | |
| 144 history_nodes.push_back(new_entry->root_history_node()); | |
| 145 while (!history_nodes.empty()) { | |
| 146 // For each item, read the children (if any) off the WebHistoryItem, | |
| 147 // create a new HistoryNode for each child and attach it, | |
| 148 // then clear the children on the WebHistoryItem. | |
| 149 HistoryEntry::HistoryNode* history_node = history_nodes.front(); | |
| 150 history_nodes.pop_front(); | |
| 151 | |
| 152 WebVector<WebHistoryItem> children = history_node->item().children(); | |
| 153 for (size_t i = 0; i < children.size(); i++) { | |
| 154 HistoryEntry::HistoryNode* child_history_node = | |
| 155 history_node->AddChild(children[i], kInvalidFrameRoutingID); | |
| 156 history_nodes.push_back(child_history_node); | |
| 157 } | |
| 158 history_node->item().setChildren(WebVector<WebHistoryItem>()); | |
| 159 } | |
| 160 GoToEntry(new_entry, cache_policy); | |
| 161 } | |
| 162 | |
| 163 void HistoryController::UpdateForInitialLoadInChildFrame( | 137 void HistoryController::UpdateForInitialLoadInChildFrame( |
| 164 RenderFrameImpl* frame, | 138 RenderFrameImpl* frame, |
| 165 const WebHistoryItem& item) { | 139 const WebHistoryItem& item) { |
| 166 DCHECK_NE(frame->GetWebFrame()->top(), frame->GetWebFrame()); | 140 DCHECK_NE(frame->GetWebFrame()->top(), frame->GetWebFrame()); |
| 167 if (!current_entry_) | 141 if (!current_entry_) |
| 168 return; | 142 return; |
| 169 if (HistoryEntry::HistoryNode* existing_node = | 143 if (HistoryEntry::HistoryNode* existing_node = |
| 170 current_entry_->GetHistoryNodeForFrame(frame)) { | 144 current_entry_->GetHistoryNodeForFrame(frame)) { |
| 171 existing_node->set_item(item); | 145 existing_node->set_item(item); |
| 172 return; | 146 return; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 188 return; | 162 return; |
| 189 previous_entry_.reset(current_entry_.release()); | 163 previous_entry_.reset(current_entry_.release()); |
| 190 current_entry_.reset(provisional_entry_.release()); | 164 current_entry_.reset(provisional_entry_.release()); |
| 191 } else if (commit_type == blink::WebStandardCommit) { | 165 } else if (commit_type == blink::WebStandardCommit) { |
| 192 CreateNewBackForwardItem(frame, item, navigation_within_page); | 166 CreateNewBackForwardItem(frame, item, navigation_within_page); |
| 193 } else if (commit_type == blink::WebInitialCommitInChildFrame) { | 167 } else if (commit_type == blink::WebInitialCommitInChildFrame) { |
| 194 UpdateForInitialLoadInChildFrame(frame, item); | 168 UpdateForInitialLoadInChildFrame(frame, item); |
| 195 } | 169 } |
| 196 } | 170 } |
| 197 | 171 |
| 198 static WebHistoryItem ItemForExport(HistoryEntry::HistoryNode* history_node) { | 172 HistoryEntry* HistoryController::GetCurrentEntry() { |
| 199 DCHECK(history_node); | 173 return current_entry_.get(); |
| 200 WebHistoryItem item = history_node->item(); | |
| 201 item.setChildren(WebVector<WebHistoryItem>()); | |
| 202 std::vector<HistoryEntry::HistoryNode*>& child_nodes = | |
| 203 history_node->children(); | |
| 204 for (size_t i = 0; i < child_nodes.size(); i++) | |
| 205 item.appendToChildren(ItemForExport(child_nodes.at(i))); | |
| 206 return item; | |
| 207 } | 174 } |
| 208 | 175 |
| 209 WebHistoryItem HistoryController::GetCurrentItemForExport() { | 176 HistoryEntry* HistoryController::GetPreviousEntry() { |
| 210 if (!current_entry_) | 177 return previous_entry_.get(); |
| 211 return WebHistoryItem(); | |
| 212 return ItemForExport(current_entry_->root_history_node()); | |
| 213 } | |
| 214 | |
| 215 WebHistoryItem HistoryController::GetPreviousItemForExport() { | |
| 216 if (!previous_entry_) | |
| 217 return WebHistoryItem(); | |
| 218 return ItemForExport(previous_entry_->root_history_node()); | |
| 219 } | 178 } |
| 220 | 179 |
| 221 WebHistoryItem HistoryController::GetItemForNewChildFrame( | 180 WebHistoryItem HistoryController::GetItemForNewChildFrame( |
| 222 RenderFrameImpl* frame) const { | 181 RenderFrameImpl* frame) const { |
| 223 if (!current_entry_) | 182 if (!current_entry_) |
| 224 return WebHistoryItem(); | 183 return WebHistoryItem(); |
| 225 return current_entry_->GetItemForFrame(frame); | 184 return current_entry_->GetItemForFrame(frame); |
| 226 } | 185 } |
| 227 | 186 |
| 228 void HistoryController::RemoveChildrenForRedirect(RenderFrameImpl* frame) { | 187 void HistoryController::RemoveChildrenForRedirect(RenderFrameImpl* frame) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 241 current_entry_.reset( | 200 current_entry_.reset( |
| 242 new HistoryEntry(new_item, target_frame->GetRoutingID())); | 201 new HistoryEntry(new_item, target_frame->GetRoutingID())); |
| 243 } else { | 202 } else { |
| 244 previous_entry_.reset(current_entry_.release()); | 203 previous_entry_.reset(current_entry_.release()); |
| 245 current_entry_.reset(previous_entry_->CloneAndReplace( | 204 current_entry_.reset(previous_entry_->CloneAndReplace( |
| 246 new_item, clone_children_of_target, target_frame, render_view_)); | 205 new_item, clone_children_of_target, target_frame, render_view_)); |
| 247 } | 206 } |
| 248 } | 207 } |
| 249 | 208 |
| 250 } // namespace content | 209 } // namespace content |
| OLD | NEW |