Index: content/renderer/history_controller.cc |
diff --git a/content/renderer/history_controller.cc b/content/renderer/history_controller.cc |
deleted file mode 100644 |
index 6369f09354e7ad7c2191745b3c781ff8f074e9cb..0000000000000000000000000000000000000000 |
--- a/content/renderer/history_controller.cc |
+++ /dev/null |
@@ -1,335 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-/* |
- * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
- * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
- * (http://www.torchmobile.com/) |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions |
- * are met: |
- * |
- * 1. Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright |
- * notice, this list of conditions and the following disclaimer in the |
- * documentation and/or other materials provided with the distribution. |
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
- * its contributors may be used to endorse or promote products derived |
- * from this software without specific prior written permission. |
- * |
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#include "content/renderer/history_controller.h" |
- |
-#include <utility> |
- |
-#include "base/memory/ptr_util.h" |
-#include "content/common/navigation_params.h" |
-#include "content/common/site_isolation_policy.h" |
-#include "content/renderer/render_frame_impl.h" |
-#include "content/renderer/render_view_impl.h" |
-#include "third_party/WebKit/public/web/WebFrameLoadType.h" |
-#include "third_party/WebKit/public/web/WebLocalFrame.h" |
- |
-using blink::WebCachePolicy; |
-using blink::WebFrame; |
-using blink::WebHistoryCommitType; |
-using blink::WebHistoryItem; |
-using blink::WebURLRequest; |
- |
-namespace content { |
- |
-HistoryController::HistoryController(RenderViewImpl* render_view) |
- : render_view_(render_view) { |
- // We don't use HistoryController in OOPIF enabled modes. |
- DCHECK(!SiteIsolationPolicy::UseSubframeNavigationEntries()); |
-} |
- |
-HistoryController::~HistoryController() { |
-} |
- |
-bool HistoryController::GoToEntry( |
- blink::WebLocalFrame* main_frame, |
- std::unique_ptr<HistoryEntry> target_entry, |
- std::unique_ptr<NavigationParams> navigation_params, |
- WebCachePolicy cache_policy) { |
- DCHECK(!main_frame->parent()); |
- HistoryFrameLoadVector same_document_loads; |
- HistoryFrameLoadVector different_document_loads; |
- |
- set_provisional_entry(std::move(target_entry)); |
- navigation_params_ = std::move(navigation_params); |
- |
- if (current_entry_) { |
- RecursiveGoToEntry( |
- main_frame, same_document_loads, different_document_loads); |
- } |
- |
- if (same_document_loads.empty() && different_document_loads.empty()) { |
- // If we don't have any frames to navigate at this point, either |
- // (1) there is no previous history entry to compare against, or |
- // (2) we were unable to match any frames by name. In the first case, |
- // doing a different document navigation to the root item is the only valid |
- // thing to do. In the second case, we should have been able to find a |
- // frame to navigate based on names if this were a same document |
- // navigation, so we can safely assume this is the different document case. |
- different_document_loads.push_back( |
- std::make_pair(main_frame, provisional_entry_->root())); |
- } |
- |
- bool has_main_frame_request = false; |
- for (const auto& item : same_document_loads) { |
- WebFrame* frame = item.first; |
- RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame); |
- if (!render_frame) |
- continue; |
- render_frame->SetPendingNavigationParams( |
- base::MakeUnique<NavigationParams>(*navigation_params_.get())); |
- WebURLRequest request = frame->toWebLocalFrame()->requestFromHistoryItem( |
- item.second, cache_policy); |
- frame->toWebLocalFrame()->load( |
- request, blink::WebFrameLoadType::BackForward, item.second, |
- blink::WebHistorySameDocumentLoad); |
- if (frame == main_frame) |
- has_main_frame_request = true; |
- } |
- for (const auto& item : different_document_loads) { |
- WebFrame* frame = item.first; |
- RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame); |
- if (!render_frame) |
- continue; |
- render_frame->SetPendingNavigationParams( |
- base::MakeUnique<NavigationParams>(*navigation_params_.get())); |
- WebURLRequest request = frame->toWebLocalFrame()->requestFromHistoryItem( |
- item.second, cache_policy); |
- frame->toWebLocalFrame()->load( |
- request, blink::WebFrameLoadType::BackForward, item.second, |
- blink::WebHistoryDifferentDocumentLoad); |
- if (frame == main_frame) |
- has_main_frame_request = true; |
- } |
- |
- return has_main_frame_request; |
-} |
- |
-void HistoryController::RecursiveGoToEntry( |
- WebFrame* frame, |
- HistoryFrameLoadVector& same_document_loads, |
- HistoryFrameLoadVector& different_document_loads) { |
- DCHECK(provisional_entry_); |
- DCHECK(current_entry_); |
- RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame); |
- const WebHistoryItem& new_item = |
- provisional_entry_->GetItemForFrame(render_frame); |
- |
- // Use the last committed history item for the frame rather than |
- // current_entry_, since the latter may not accurately reflect which URL is |
- // currently committed in the frame. See https://crbug.com/612713#c12. |
- const WebHistoryItem& old_item = render_frame->current_history_item(); |
- |
- if (new_item.isNull()) |
- return; |
- |
- if (old_item.isNull() || |
- new_item.itemSequenceNumber() != old_item.itemSequenceNumber()) { |
- if (!old_item.isNull() && |
- new_item.documentSequenceNumber() == |
- old_item.documentSequenceNumber()) { |
- same_document_loads.push_back(std::make_pair(frame, new_item)); |
- |
- // Returning here (and omitting child frames which have also changed) is |
- // wrong, but not returning here is worse. See the discussion in |
- // NavigationControllerImpl::FindFramesToNavigate for more information. |
- return; |
- } else { |
- different_document_loads.push_back(std::make_pair(frame, new_item)); |
- // For a different document, the subframes will be destroyed, so there's |
- // no need to consider them. |
- return; |
- } |
- } |
- |
- for (WebFrame* child = frame->firstChild(); child; |
- child = child->nextSibling()) { |
- RecursiveGoToEntry(child, same_document_loads, different_document_loads); |
- } |
-} |
- |
-void HistoryController::UpdateForInitialLoadInChildFrame( |
- RenderFrameImpl* frame, |
- const WebHistoryItem& item) { |
- DCHECK_NE(frame->GetWebFrame()->top(), frame->GetWebFrame()); |
- if (!current_entry_) |
- return; |
- if (HistoryEntry::HistoryNode* existing_node = |
- current_entry_->GetHistoryNodeForFrame(frame)) { |
- // Clear the children and any NavigationParams if this commit isn't for |
- // the same item. Otherwise we might have stale data after a redirect. |
- if (existing_node->item().itemSequenceNumber() != |
- item.itemSequenceNumber()) { |
- existing_node->RemoveChildren(); |
- navigation_params_.reset(); |
- } |
- existing_node->set_item(item); |
- return; |
- } |
- RenderFrameImpl* parent = |
- RenderFrameImpl::FromWebFrame(frame->GetWebFrame()->parent()); |
- if (!parent) |
- return; |
- if (HistoryEntry::HistoryNode* parent_history_node = |
- current_entry_->GetHistoryNodeForFrame(parent)) { |
- parent_history_node->AddChild(item); |
- } |
-} |
- |
-void HistoryController::UpdateForCommit(RenderFrameImpl* frame, |
- const WebHistoryItem& item, |
- WebHistoryCommitType commit_type, |
- bool navigation_within_page) { |
- switch (commit_type) { |
- case blink::WebBackForwardCommit: |
- if (!provisional_entry_) { |
- // The provisional entry may have been discarded due to a navigation in |
- // a different frame. For main frames, it is not safe to leave the |
- // current_entry_ in place, which may have a cross-site page and will be |
- // included in the PageState for this commit. Replace it with a new |
- // HistoryEntry corresponding to the commit, and clear any stale |
- // NavigationParams which might point to the wrong entry. |
- // |
- // This will lack any subframe history items that were in the original |
- // provisional entry, but we don't know what those were after discarding |
- // it. We'll load the default URL in those subframes instead. |
- // |
- // TODO(creis): It's also possible to get here for subframe commits. |
- // We'll leave a stale current_entry_ in that case, but that only causes |
- // an earlier URL to load in the subframe when leaving and coming back, |
- // and only in rare cases. It does not risk a URL spoof, unlike the |
- // main frame case. Since this bug is not present in the new |
- // FrameNavigationEntry-based navigation path (https://crbug.com/236848) |
- // we'll wait for that to fix the subframe case. |
- if (frame->IsMainFrame()) { |
- current_entry_.reset(new HistoryEntry(item)); |
- navigation_params_.reset(); |
- } |
- |
- return; |
- } |
- |
- // If the current entry is null, this must be a main frame commit. |
- DCHECK(current_entry_ || frame->IsMainFrame()); |
- |
- // Commit the provisional entry, but only if it is a plausible transition. |
- // Do not commit it if the navigation is in a subframe and the provisional |
- // entry's main frame item does not match the current entry's main frame, |
- // which can happen if multiple forward navigations occur. In that case, |
- // committing the provisional entry would corrupt it, leading to a URL |
- // spoof. See https://crbug.com/597322. (Note that the race in this bug |
- // does not affect main frame navigations, only navigations in subframes.) |
- // |
- // Note that we cannot compare the provisional entry against |item|, since |
- // |item| may have redirected to a different URL and ISN. We also cannot |
- // compare against the main frame's URL, since that may have changed due |
- // to a replaceState. (Even origin can change on replaceState in certain |
- // modes.) |
- // |
- // It would be safe to additionally check the ISNs of all parent frames |
- // (and not just the root), but that is less critical because it won't |
- // lead to a URL spoof. |
- if (frame->IsMainFrame() || |
- current_entry_->root().itemSequenceNumber() == |
- provisional_entry_->root().itemSequenceNumber()) { |
- current_entry_ = std::move(provisional_entry_); |
- } |
- |
- // We're guaranteed to have a current entry now. |
- DCHECK(current_entry_); |
- |
- if (HistoryEntry::HistoryNode* node = |
- current_entry_->GetHistoryNodeForFrame(frame)) { |
- // Clear the children and any NavigationParams if this commit isn't for |
- // the same item. Otherwise we might have stale data from a race. |
- if (node->item().itemSequenceNumber() != item.itemSequenceNumber()) { |
- node->RemoveChildren(); |
- navigation_params_.reset(); |
- } |
- |
- node->set_item(item); |
- } |
- break; |
- case blink::WebStandardCommit: |
- CreateNewBackForwardItem(frame, item, navigation_within_page); |
- break; |
- case blink::WebInitialCommitInChildFrame: |
- UpdateForInitialLoadInChildFrame(frame, item); |
- break; |
- case blink::WebHistoryInertCommit: |
- // Even for inert commits (e.g., location.replace, client redirects), make |
- // sure the current entry gets updated, if there is one. |
- if (current_entry_) { |
- if (HistoryEntry::HistoryNode* node = |
- current_entry_->GetHistoryNodeForFrame(frame)) { |
- // Inert commits that reset the page without changing the item (e.g., |
- // reloads, location.replace) shouldn't keep the old subtree. |
- if (!navigation_within_page) |
- node->RemoveChildren(); |
- node->set_item(item); |
- } |
- } |
- break; |
- default: |
- NOTREACHED() << "Invalid commit type: " << commit_type; |
- } |
-} |
- |
-HistoryEntry* HistoryController::GetCurrentEntry() { |
- return current_entry_.get(); |
-} |
- |
-WebHistoryItem HistoryController::GetItemForNewChildFrame( |
- RenderFrameImpl* frame) const { |
- if (navigation_params_.get()) { |
- frame->SetPendingNavigationParams( |
- base::MakeUnique<NavigationParams>(*navigation_params_.get())); |
- } |
- |
- if (!current_entry_) |
- return WebHistoryItem(); |
- return current_entry_->GetItemForFrame(frame); |
-} |
- |
-void HistoryController::RemoveChildrenForRedirect(RenderFrameImpl* frame) { |
- if (!provisional_entry_) |
- return; |
- if (HistoryEntry::HistoryNode* node = |
- provisional_entry_->GetHistoryNodeForFrame(frame)) |
- node->RemoveChildren(); |
-} |
- |
-void HistoryController::CreateNewBackForwardItem( |
- RenderFrameImpl* target_frame, |
- const WebHistoryItem& new_item, |
- bool clone_children_of_target) { |
- if (!current_entry_) { |
- current_entry_.reset(new HistoryEntry(new_item)); |
- } else { |
- current_entry_.reset(current_entry_->CloneAndReplace( |
- new_item, clone_children_of_target, target_frame, render_view_)); |
- } |
-} |
- |
-} // namespace content |