Revert of Remove the is_loading_ field from WebContentsImpl (patchset #24 id:460001 of https://codereview.chromium.org/1545973002/ )
Reason for revert:
CHECK(is_loading_) appears to fail (flakily?) on Linux ChromiumOS Tests (1). More details in the bug.
Original issue's description:
> Remove the is_loading_ field from WebContentsImpl
>
> This CL removes the is_loading_ field from WebContents, in favor of only
> tracking the loading state through the FrameTree. Currently the loading state
> is tracked in both, leading to more complexity in the code.
>
> BUG=571887, 298193
> CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_site_isolation
>
> Committed: https://crrev.com/db73eb6cf1e59e753fb53e8c744620b00606ccd5
> Cr-Commit-Position: refs/heads/master@{#374651}
[email protected],[email protected],[email protected],[email protected],[email protected]
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=571887, 298193
Review URL: https://codereview.chromium.org/1690633002
Cr-Commit-Position: refs/heads/master@{#374680}
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc
index 2fadc12..5e8b2c1 100644
--- a/content/browser/frame_host/frame_tree.cc
+++ b/content/browser/frame_host/frame_tree.cc
@@ -80,44 +80,6 @@
FrameTree::NodeRange::NodeRange(FrameTree* tree, FrameTreeNode* node_to_skip)
: tree_(tree), node_to_skip_(node_to_skip) {}
-FrameTree::ConstNodeIterator::~ConstNodeIterator() {}
-
-FrameTree::ConstNodeIterator& FrameTree::ConstNodeIterator::operator++() {
- for (size_t i = 0; i < current_node_->child_count(); ++i) {
- const FrameTreeNode* child = current_node_->child_at(i);
- queue_.push(child);
- }
-
- if (!queue_.empty()) {
- current_node_ = queue_.front();
- queue_.pop();
- } else {
- current_node_ = nullptr;
- }
-
- return *this;
-}
-
-bool FrameTree::ConstNodeIterator::operator==(
- const ConstNodeIterator& rhs) const {
- return current_node_ == rhs.current_node_;
-}
-
-FrameTree::ConstNodeIterator::ConstNodeIterator(
- const FrameTreeNode* starting_node)
- : current_node_(starting_node) {}
-
-FrameTree::ConstNodeIterator FrameTree::ConstNodeRange::begin() {
- return ConstNodeIterator(tree_->root());
-}
-
-FrameTree::ConstNodeIterator FrameTree::ConstNodeRange::end() {
- return ConstNodeIterator(nullptr);
-}
-
-FrameTree::ConstNodeRange::ConstNodeRange(const FrameTree* tree)
- : tree_(tree) {}
-
FrameTree::FrameTree(Navigator* navigator,
RenderFrameHostDelegate* render_frame_delegate,
RenderViewHostDelegate* render_view_delegate,
@@ -194,10 +156,6 @@
return NodeRange(this, node_to_skip);
}
-FrameTree::ConstNodeRange FrameTree::ConstNodes() const {
- return ConstNodeRange(this);
-}
-
bool FrameTree::AddFrame(
FrameTreeNode* parent,
int process_id,
@@ -467,8 +425,8 @@
load_progress_ = 0.0;
}
-bool FrameTree::IsLoading() const {
- for (const FrameTreeNode* node : ConstNodes()) {
+bool FrameTree::IsLoading() {
+ for (FrameTreeNode* node : Nodes()) {
if (node->IsLoading())
return true;
}
diff --git a/content/browser/frame_host/frame_tree.h b/content/browser/frame_host/frame_tree.h
index c8596d62..81282c0e 100644
--- a/content/browser/frame_host/frame_tree.h
+++ b/content/browser/frame_host/frame_tree.h
@@ -41,7 +41,6 @@
class CONTENT_EXPORT FrameTree {
public:
class NodeRange;
- class ConstNodeRange;
class CONTENT_EXPORT NodeIterator {
public:
@@ -78,41 +77,6 @@
FrameTreeNode* const node_to_skip_;
};
- class CONTENT_EXPORT ConstNodeIterator {
- public:
- ~ConstNodeIterator();
-
- ConstNodeIterator& operator++();
-
- bool operator==(const ConstNodeIterator& rhs) const;
- bool operator!=(const ConstNodeIterator& rhs) const {
- return !(*this == rhs);
- }
-
- const FrameTreeNode* operator*() { return current_node_; }
-
- private:
- friend class ConstNodeRange;
-
- ConstNodeIterator(const FrameTreeNode* starting_node);
-
- const FrameTreeNode* current_node_;
- std::queue<const FrameTreeNode*> queue_;
- };
-
- class CONTENT_EXPORT ConstNodeRange {
- public:
- ConstNodeIterator begin();
- ConstNodeIterator end();
-
- private:
- friend class FrameTree;
-
- ConstNodeRange(const FrameTree* tree);
-
- const FrameTree* const tree_;
- };
-
// Each FrameTreeNode will default to using the given |navigator| for
// navigation tasks in the frame.
// A set of delegates are remembered here so that we can create
@@ -145,10 +109,6 @@
// breadth-first traversal order.
NodeRange Nodes();
- // Returns a range to iterate over all FrameTreeNodes in the frame tree in
- // breadth-first traversal order. All FrameTreeNodes returned will be const.
- ConstNodeRange ConstNodes() const;
-
// Adds a new child frame to the frame tree. |process_id| is required to
// disambiguate |new_routing_id|, and it must match the process of the
// |parent| node. Otherwise no child is added and this method returns false.
@@ -227,7 +187,7 @@
void ResetLoadProgress();
// Returns true if at least one of the nodes in this FrameTree is loading.
- bool IsLoading() const;
+ bool IsLoading();
// Set page-level focus in all SiteInstances involved in rendering
// this FrameTree, not including the current main frame's
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index b8415a7..cccb3ff1 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -287,26 +287,24 @@
scoped_ptr<NavigationRequest> navigation_request) {
CHECK(IsBrowserSideNavigationEnabled());
- bool was_previously_loading = frame_tree()->IsLoading();
-
// There's no need to reset the state: there's still an ongoing load, and the
// RenderFrameHostManager will take care of updates to the speculative
// RenderFrameHost in DidCreateNavigationRequest below.
- if (was_previously_loading)
- ResetNavigationRequest(true);
-
- navigation_request_ = std::move(navigation_request);
- render_manager()->DidCreateNavigationRequest(*navigation_request_);
+ ResetNavigationRequest(true);
// Force the throbber to start to keep it in sync with what is happening in
// the UI. Blink doesn't send throb notifications for JavaScript URLs, so it
// is not done here either.
- if (!navigation_request_->common_params().url.SchemeIs(
+ if (!navigation_request->common_params().url.SchemeIs(
url::kJavaScriptScheme)) {
// TODO(fdegans): Check if this is a same-document navigation and set the
// proper argument.
- DidStartLoading(true, was_previously_loading);
+ DidStartLoading(true);
}
+
+ navigation_request_ = std::move(navigation_request);
+
+ render_manager()->DidCreateNavigationRequest(*navigation_request_);
}
void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
@@ -332,8 +330,7 @@
loading_progress_ = kLoadingProgressNotStarted;
}
-void FrameTreeNode::DidStartLoading(bool to_different_document,
- bool was_previously_loading) {
+void FrameTreeNode::DidStartLoading(bool to_different_document) {
// Any main frame load to a new document should reset the load progress since
// it will replace the current page and any frames. The WebContents will
// be notified when DidChangeLoadProgress is called.
@@ -341,7 +338,7 @@
frame_tree_->ResetLoadProgress();
// Notify the WebContents.
- if (!was_previously_loading)
+ if (!frame_tree_->IsLoading())
navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
// Set initial load progress and update overall progress. This will notify
@@ -408,26 +405,4 @@
FOR_EACH_OBSERVER(Observer, observers_, OnFrameTreeNodeFocused(this));
}
-void FrameTreeNode::BeforeUnloadCanceled() {
- if (!IsMainFrame())
- return;
-
- RenderFrameHostImpl* current_frame_host =
- render_manager_.current_frame_host();
- DCHECK(current_frame_host);
- current_frame_host->ResetLoadingState();
-
- if (IsBrowserSideNavigationEnabled()) {
- RenderFrameHostImpl* speculative_frame_host =
- render_manager_.speculative_frame_host();
- if (speculative_frame_host)
- speculative_frame_host->ResetLoadingState();
- } else {
- RenderFrameHostImpl* pending_frame_host =
- render_manager_.pending_frame_host();
- if (pending_frame_host)
- pending_frame_host->ResetLoadingState();
- }
-}
-
} // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h
index 4ea61235..eac4977 100644
--- a/content/browser/frame_host/frame_tree_node.h
+++ b/content/browser/frame_host/frame_tree_node.h
@@ -235,11 +235,7 @@
// A RenderFrameHost in this node started loading.
// |to_different_document| will be true unless the load is a fragment
// navigation, or triggered by history.pushState/replaceState.
- // |was_previously_loading| is false if the FrameTree was not loading before.
- // The caller is required to provide this boolean as the delegate should only
- // be called if the FrameTree went from non-loading to loading state.
- // However, when it is called, the FrameTree should be in a loading state.
- void DidStartLoading(bool to_different_document, bool was_previously_loading);
+ void DidStartLoading(bool to_different_document);
// A RenderFrameHost in this node stopped loading.
void DidStopLoading();
@@ -261,10 +257,6 @@
// time and notifies observers.
void DidFocus();
- // Called when the user closed the modal dialogue for BeforeUnload and
- // cancelled the navigation. This should stop the loads.
- void BeforeUnloadCanceled();
-
private:
class OpenerDestroyedObserver;
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc
index 962f5f3..1ad4907b 100644
--- a/content/browser/frame_host/interstitial_page_impl.cc
+++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -164,6 +164,7 @@
original_child_id_(web_contents->GetRenderProcessHost()->GetID()),
original_rvh_id_(web_contents->GetRenderViewHost()->GetRoutingID()),
should_revert_web_contents_title_(false),
+ web_contents_was_loading_(false),
resource_dispatcher_host_notified_(false),
rvh_delegate_view_(new InterstitialPageRVHDelegateView(this)),
create_view_(true),
@@ -517,6 +518,14 @@
// Hide the original RVH since we're showing the interstitial instead.
rwh_view->Hide();
}
+
+ // Notify the tab we are not loading so the throbber is stopped. It also
+ // causes a WebContentsObserver::DidStopLoading callback that the
+ // AutomationProvider (used by the UI tests) expects to consider a navigation
+ // as complete. Without this, navigating in a UI test to a URL that triggers
+ // an interstitial would hang.
+ web_contents_was_loading_ = controller_->delegate()->IsLoading();
+ controller_->delegate()->SetIsLoading(false, true, NULL);
}
RendererPreferences InterstitialPageImpl::GetRendererPrefs(
@@ -625,7 +634,9 @@
Disable();
action_taken_ = PROCEED_ACTION;
- controller_->delegate()->DidProceedOnInterstitial();
+ // Resumes the throbber, if applicable.
+ if (web_contents_was_loading_)
+ controller_->delegate()->SetIsLoading(true, true, NULL);
// If this is a new navigation, the old page is going away, so we cancel any
// blocked requests for it. If it is not a new navigation, then it means the
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h
index c03792d..32361e8 100644
--- a/content/browser/frame_host/interstitial_page_impl.h
+++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -271,6 +271,10 @@
// revert it to its original value).
bool should_revert_web_contents_title_;
+ // Whether or not the contents was loading resources when the interstitial was
+ // shown. We restore this state if the user proceeds from the interstitial.
+ bool web_contents_was_loading_;
+
// Whether the ResourceDispatcherHost has been notified to cancel/resume the
// resource requests blocked for the RenderViewHost.
bool resource_dispatcher_host_notified_;
diff --git a/content/browser/frame_host/navigation_controller_delegate.h b/content/browser/frame_host/navigation_controller_delegate.h
index 8a20e2b..9922ac5 100644
--- a/content/browser/frame_host/navigation_controller_delegate.h
+++ b/content/browser/frame_host/navigation_controller_delegate.h
@@ -42,6 +42,7 @@
virtual void Stop() = 0;
virtual int32_t GetMaxPageID() = 0;
virtual int32_t GetMaxPageIDForSiteInstance(SiteInstance* site_instance) = 0;
+ virtual bool IsLoading() const = 0;
virtual bool IsBeingDestroyed() const = 0;
virtual bool CanOverscrollContent() const = 0;
@@ -70,8 +71,10 @@
RenderFrameHost* render_frame_host) = 0;
virtual void AttachInterstitialPage(
InterstitialPageImpl* interstitial_page) = 0;
- virtual void DidProceedOnInterstitial() = 0;
virtual void DetachInterstitialPage() = 0;
+ virtual void SetIsLoading(bool is_loading,
+ bool to_different_document,
+ LoadNotificationDetails* details) = 0;
};
} // namespace content
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 4065902..e0f6144 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -3467,19 +3467,14 @@
// Suppose it aborts before committing, if it's a 204 or download or due to a
// stop or a new navigation from the user. The URL should remain visible.
- if (IsBrowserSideNavigationEnabled()) {
- static_cast<NavigatorImpl*>(main_test_rfh()->frame_tree_node()->navigator())
- ->CancelNavigation(main_test_rfh()->frame_tree_node());
- } else {
- FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
- params.error_code = net::ERR_ABORTED;
- params.error_description = base::string16();
- params.url = url;
- params.showing_repost_interstitial = false;
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidFailProvisionalLoadWithError(0, params));
- main_test_rfh()->OnMessageReceived(FrameHostMsg_DidStopLoading(0));
- }
+ FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
+ params.error_code = net::ERR_ABORTED;
+ params.error_description = base::string16();
+ params.url = url;
+ params.showing_repost_interstitial = false;
+ main_test_rfh()->OnMessageReceived(
+ FrameHostMsg_DidFailProvisionalLoadWithError(0, params));
+ contents()->SetIsLoading(false, true, NULL);
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
// If something else later modifies the contents of the about:blank page, then
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 9e67f2d..7457ed9d 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -338,24 +338,14 @@
// Double check that here.
CheckWebUIRendererDoesNotDisplayNormalURL(dest_render_frame_host, dest_url);
- // In the case of a transfer navigation, set the destination RenderFrameHost
- // as loading. This ensures that the RenderFrameHost gets in a loading state
- // without emitting a spurrious DidStartLoading notification at the
- // FrameTreeNode level (since the FrameTreeNode was already loading). Note
- // that this works both for a transfer to a different RenderFrameHost and in
- // the rare case where the navigation is transferred back to the same
- // RenderFrameHost.
- bool is_transfer = entry.transferred_global_request_id().child_id != -1;
- if (is_transfer)
- dest_render_frame_host->set_is_loading(true);
-
// Navigate in the desired RenderFrameHost.
// We can skip this step in the rare case that this is a transfer navigation
// which began in the chosen RenderFrameHost, since the request has already
// been issued. In that case, simply resume the response.
- bool is_transfer_to_same = is_transfer &&
- entry.transferred_global_request_id().child_id ==
- dest_render_frame_host->GetProcess()->GetID();
+ bool is_transfer_to_same =
+ entry.transferred_global_request_id().child_id != -1 &&
+ entry.transferred_global_request_id().child_id ==
+ dest_render_frame_host->GetProcess()->GetID();
if (!is_transfer_to_same) {
navigation_data_.reset(new NavigationMetricsData(navigation_start, dest_url,
entry.restore_type()));
@@ -381,7 +371,6 @@
controller_->GetEntryCount()));
} else {
// No need to navigate again. Just resume the deferred request.
- // Also sets the RenderFrameHost back to a loading state again.
dest_render_frame_host->GetProcess()->ResumeDeferredNavigation(
entry.transferred_global_request_id());
}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 4b2a6f6..e8a8038 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -214,7 +214,6 @@
g_routing_id_frame_map.Get().insert(std::make_pair(
RenderFrameHostID(GetProcess()->GetID(), routing_id_),
this));
- site_instance_->AddObserver(this);
if (is_swapped_out) {
rfh_state_ = STATE_SWAPPED_OUT;
@@ -263,8 +262,6 @@
g_routing_id_frame_map.Get().erase(
RenderFrameHostID(GetProcess()->GetID(), routing_id_));
- site_instance_->RemoveObserver(this);
-
if (delegate_ && render_frame_created_)
delegate_->RenderFrameDeleted(this);
@@ -520,6 +517,7 @@
OnDidFailLoadWithError)
IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_DidCommitProvisionalLoad,
OnDidCommitProvisionalLoad(msg))
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DidDropNavigation, OnDidDropNavigation)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateState, OnUpdateState)
IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_DocumentOnLoadCompleted,
@@ -692,13 +690,6 @@
return NULL;
}
-void RenderFrameHostImpl::RenderProcessGone(SiteInstanceImpl* site_instance) {
- DCHECK(site_instance == site_instance_.get());
-
- // The render process is gone, this frame can no longer be loading.
- ResetLoadingState();
-}
-
bool RenderFrameHostImpl::CreateRenderFrame(int proxy_routing_id,
int opener_routing_id,
int parent_routing_id,
@@ -1051,6 +1042,15 @@
pending_commit_ = false;
}
+void RenderFrameHostImpl::OnDidDropNavigation() {
+ // At the end of Navigate(), the FrameTreeNode's DidStartLoading is called to
+ // force the spinner to start, even if the renderer didn't yet begin the load.
+ // If it turns out that the renderer dropped the navigation, the spinner needs
+ // to be turned off.
+ frame_tree_node_->DidStopLoading();
+ navigation_handle_.reset();
+}
+
void RenderFrameHostImpl::OnUpdateState(const PageState& state) {
// TODO(creis): Verify the state's ISN matches the last committed FNE.
@@ -1316,8 +1316,6 @@
return;
}
- ResetLoadingState();
-
// If this RFH wasn't pending deletion, then it is now swapped out.
SetState(RenderFrameHostImpl::STATE_SWAPPED_OUT);
}
@@ -1703,10 +1701,23 @@
}
void RenderFrameHostImpl::OnDidStartLoading(bool to_different_document) {
- bool was_previously_loading = frame_tree_node_->frame_tree()->IsLoading();
+ // Any main frame load to a new document should reset the load since it will
+ // replace the current page and any frames.
+ if (to_different_document && !GetParent())
+ is_loading_ = false;
+
+ // This method should never be called when the frame is loading.
+ // Unfortunately, it can happen if a history navigation happens during a
+ // BeforeUnload or Unload event.
+ // TODO(fdegans): Change this to a DCHECK after LoadEventProgress has been
+ // refactored in Blink. See crbug.com/466089
+ if (is_loading_) {
+ LOG(WARNING) << "OnDidStartLoading was called twice.";
+ return;
+ }
+
+ frame_tree_node_->DidStartLoading(to_different_document);
is_loading_ = true;
- frame_tree_node_->DidStartLoading(to_different_document,
- was_previously_loading);
}
void RenderFrameHostImpl::OnDidStopLoading() {
@@ -1902,7 +1913,7 @@
// Blink doesn't send throb notifications for JavaScript URLs, so it is not
// done here either.
if (!common_params.url.SchemeIs(url::kJavaScriptScheme))
- OnDidStartLoading(true);
+ frame_tree_node_->DidStartLoading(true);
}
void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
@@ -2241,18 +2252,6 @@
return mojo_image_downloader_;
}
-void RenderFrameHostImpl::ResetLoadingState() {
- if (is_loading()) {
- // When pending deletion, just set the loading state to not loading.
- // Otherwise, OnDidStopLoading will take care of that, as well as sending
- // notification to the FrameTreeNode about the change in loading state.
- if (rfh_state_ != STATE_DEFAULT)
- is_loading_ = false;
- else
- OnDidStopLoading();
- }
-}
-
bool RenderFrameHostImpl::IsSameSiteInstance(
RenderFrameHostImpl* other_render_frame_host) {
// As a sanity check, make sure the frame belongs to the same BrowserContext.
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index a4ba3a46..9767a4a 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -96,9 +96,9 @@
CREATE_RF_HIDDEN = 1 << 1,
};
-class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
- public BrowserAccessibilityDelegate,
- public SiteInstanceImpl::Observer {
+class CONTENT_EXPORT RenderFrameHostImpl
+ : public RenderFrameHost,
+ public BrowserAccessibilityDelegate {
public:
using AXTreeSnapshotCallback =
base::Callback<void(
@@ -207,9 +207,6 @@
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
- // SiteInstanceImpl::Observer
- void RenderProcessGone(SiteInstanceImpl* site_instance) override;
-
// Creates a RenderFrame in the renderer process.
bool CreateRenderFrame(int proxy_routing_id,
int opener_routing_id,
@@ -250,12 +247,6 @@
// call FrameTreeNode::IsLoading.
bool is_loading() const { return is_loading_; }
- // Sets this RenderFrameHost loading state. This is only used in the case of
- // transfer navigations, where no DidStart/DidStopLoading notifications
- // should be sent during the transfer.
- // TODO(clamy): Remove this once PlzNavigate ships.
- void set_is_loading(bool is_loading) { is_loading_ = is_loading; }
-
// This returns the RenderFrameHost's owned RenderWidgetHost if it has one,
// or else it returns nullptr.
// If the RenderFrameHost is the page's main frame, this returns instead a
@@ -536,10 +527,6 @@
// Returns the Mojo ImageDownloader service.
const image_downloader::ImageDownloaderPtr& GetMojoImageDownloader();
- // Resets the loading state. Following this call, the RenderFrameHost will be
- // in a non-loading state.
- void ResetLoadingState();
-
protected:
friend class RenderFrameHostFactory;
@@ -585,6 +572,7 @@
const base::string16& error_description,
bool was_ignored_by_handler);
void OnDidCommitProvisionalLoad(const IPC::Message& msg);
+ void OnDidDropNavigation();
void OnUpdateState(const PageState& state);
void OnBeforeUnloadACK(
bool proceed,
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 766e968..cd1684b 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -437,7 +437,6 @@
// should probably cancel the request in that case.
DCHECK(pending_render_frame_host == pending_render_frame_host_.get() ||
pending_render_frame_host == render_frame_host_.get());
- DCHECK(frame_tree_node_->IsLoading());
// Store the transferring request so that we can release it if the transfer
// navigation matches.
@@ -449,11 +448,6 @@
pending_render_frame_host->PassNavigationHandleOwnership();
DCHECK(transfer_navigation_handle_);
- // Set the transferring RenderFrameHost as not loading, so that it does not
- // emit a DidStopLoading notification if it is destroyed when creating the
- // new navigating RenderFrameHost.
- pending_render_frame_host->set_is_loading(false);
-
// Sanity check that the params are for the correct frame and process.
// These should match the RenderFrameHost that made the request.
// If it started as a cross-process navigation via OpenURL, this is the
@@ -486,11 +480,6 @@
// If the navigation continued, the NavigationHandle should have been
// transfered to a RenderFrameHost. In the other cases, it should be cleared.
transfer_navigation_handle_.reset();
-
- // If the navigation in the new renderer did not start, inform the
- // FrameTreeNode that it stopped loading.
- if (!frame_tree_node_->IsLoading())
- frame_tree_node_->DidStopLoading();
}
void RenderFrameHostManager::DidNavigateFrame(
@@ -923,12 +912,8 @@
void RenderFrameHostManager::CleanUpNavigation() {
CHECK(IsBrowserSideNavigationEnabled());
render_frame_host_->ClearPendingWebUI();
- if (speculative_render_frame_host_) {
- bool was_loading = speculative_render_frame_host_->is_loading();
+ if (speculative_render_frame_host_)
DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
- if (was_loading)
- frame_tree_node_->DidStopLoading();
- }
}
// PlzNavigate
@@ -2017,7 +2002,6 @@
// now to make sure the sad tab shows up, etc.
DCHECK(!render_frame_host_->IsRenderFrameLive());
DCHECK(!render_frame_host_->render_view_host()->IsRenderViewLive());
- render_frame_host_->ResetLoadingState();
delegate_->RenderProcessGoneFromRenderManager(
render_frame_host_->render_view_host());
}
@@ -2269,11 +2253,7 @@
TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending",
"FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
render_frame_host_->ClearPendingWebUI();
-
- bool pending_was_loading = pending_render_frame_host_->is_loading();
DiscardUnusedFrame(UnsetPendingRenderFrameHost());
- if (pending_was_loading)
- frame_tree_node_->DidStopLoading();
}
scoped_ptr<RenderFrameHostImpl>
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index 81967cf..b54de7f 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -23,11 +23,11 @@
class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
public RenderProcessHostObserver {
public:
- class CONTENT_EXPORT Observer {
+ class Observer {
public:
// Called when this SiteInstance transitions to having no active frames,
// as measured by active_frame_count().
- virtual void ActiveFrameCountIsZero(SiteInstanceImpl* site_instance) {}
+ virtual void ActiveFrameCountIsZero(SiteInstanceImpl* site_instance) = 0;
// Called when the renderer process of this SiteInstance has exited.
virtual void RenderProcessGone(SiteInstanceImpl* site_instance) = 0;
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index 25694d7..4649e8c6 100644
--- a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -307,6 +307,7 @@
// this is a "safety net" in case we mis-identify the destination webpage
// (which can happen if a new navigation is performed while while a GestureNav
// navigation is in progress).
+ contents()->TestSetIsLoading(true);
contents()->TestSetIsLoading(false);
EXPECT_FALSE(GetOverlay()->web_contents());
NavigationEntry* pending = contents()->GetController().GetPendingEntry();
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 20db239..d4f6bec 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -338,6 +338,7 @@
this,
this,
this),
+ is_loading_(false),
is_load_to_different_document_(false),
crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
crashed_error_code_(0),
@@ -346,7 +347,6 @@
upload_size_(0),
upload_position_(0),
is_resume_pending_(false),
- paused_throbber_for_interstitial_(false),
displayed_insecure_content_(false),
has_accessed_initial_document_(false),
theme_color_(SK_ColorTRANSPARENT),
@@ -371,8 +371,8 @@
force_disable_overscroll_content_(false),
last_dialog_suppressed_(false),
geolocation_service_context_(new GeolocationServiceContext()),
- accessibility_mode_(BrowserAccessibilityStateImpl::GetInstance()
- ->accessibility_mode()),
+ accessibility_mode_(
+ BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
audio_stream_monitor_(this),
virtual_keyboard_requested_(false),
page_scale_factor_is_one_(true),
@@ -896,7 +896,7 @@
// Reload the page if a load is currently in progress to avoid having
// different parts of the page loaded using different user agents.
NavigationEntry* entry = controller_.GetVisibleEntry();
- if (IsLoading() && entry != NULL && entry->GetIsOverridingUserAgent())
+ if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent())
controller_.ReloadIgnoringCache(true);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
@@ -1036,11 +1036,11 @@
}
bool WebContentsImpl::IsLoading() const {
- return frame_tree_.IsLoading() && !paused_throbber_for_interstitial_;
+ return is_loading_;
}
bool WebContentsImpl::IsLoadingToDifferentDocument() const {
- return IsLoading() && is_load_to_different_document_;
+ return is_loading_ && is_load_to_different_document_;
}
bool WebContentsImpl::IsWaitingForResponse() const {
@@ -2309,18 +2309,6 @@
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidAttachInterstitialPage());
-
- // Stop the throbber if needed while the interstitial page is shown.
- if (IsLoading())
- LoadingStateChanged(false, true, true, nullptr);
-}
-
-void WebContentsImpl::DidProceedOnInterstitial() {
- // Restart the throbber now that the interstitial page is going away.
- if (paused_throbber_for_interstitial_) {
- if (frame_tree_.IsLoading())
- LoadingStateChanged(true, true, false, nullptr);
- }
}
void WebContentsImpl::DetachInterstitialPage() {
@@ -2328,11 +2316,6 @@
GetRenderManager()->remove_interstitial_page();
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidDetachInterstitialPage());
- // Restart the throbber now that the interstitial page is going away.
- if (paused_throbber_for_interstitial_) {
- if (frame_tree_.IsLoading())
- LoadingStateChanged(true, true, false, nullptr);
- }
}
void WebContentsImpl::SetHistoryOffsetAndLength(int history_offset,
@@ -3605,17 +3588,12 @@
// Notifies the RenderWidgetHost instance about the fact that the page is
// loading, or done loading.
-void WebContentsImpl::LoadingStateChanged(bool is_loading,
- bool to_different_document,
- bool pause_throbber_for_interstitial,
- LoadNotificationDetails* details) {
- // Do not send notifications about loading while the interstitial is showing.
- if (paused_throbber_for_interstitial_ && pause_throbber_for_interstitial)
+void WebContentsImpl::SetIsLoading(bool is_loading,
+ bool to_different_document,
+ LoadNotificationDetails* details) {
+ if (is_loading == is_loading_)
return;
- // Update whether the interstitial state.
- paused_throbber_for_interstitial_ = pause_throbber_for_interstitial;
-
if (!is_loading) {
load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
base::string16());
@@ -3626,6 +3604,7 @@
GetRenderManager()->SetIsLoading(is_loading);
+ is_loading_ = is_loading;
waiting_for_response_ = is_loading;
is_load_to_different_document_ = to_different_document;
@@ -3978,13 +3957,15 @@
if (delegate_)
delegate_->HideValidationMessage(this);
+ SetIsLoading(false, true, nullptr);
+ NotifyDisconnected();
+ SetIsCrashed(status, error_code);
+
// Reset the loading progress. TODO(avi): What does it mean to have a
// "renderer crash" when there is more than one renderer process serving a
// webpage? Once this function is called at a more granular frame level, we
// probably will need to more granularly reset the state here.
ResetLoadProgressState();
- NotifyDisconnected();
- SetIsCrashed(status, error_code);
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
@@ -4078,8 +4059,7 @@
void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node,
bool to_different_document) {
- LoadingStateChanged(true, to_different_document,
- paused_throbber_for_interstitial_, nullptr);
+ SetIsLoading(true, to_different_document, nullptr);
// Notify accessibility that the user is navigating away from the
// current document.
@@ -4113,8 +4093,7 @@
controller_.GetCurrentEntryIndex()));
}
- LoadingStateChanged(false, true, paused_throbber_for_interstitial_,
- details.get());
+ SetIsLoading(false, true, details.get());
}
void WebContentsImpl::DidChangeLoadProgress() {
@@ -4651,8 +4630,10 @@
last_dialog_suppressed_ = dialog_was_suppressed;
if (is_showing_before_unload_dialog_ && !success) {
+ // If a beforeunload dialog is canceled, we need to stop the throbber from
+ // spinning, since we forced it to start spinning in Navigate.
if (rfh)
- rfh->frame_tree_node()->BeforeUnloadCanceled();
+ DidStopLoading();
controller_.DiscardNonCommittedEntries();
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 6fdc6877..6a5ba60 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -706,8 +706,12 @@
// Unsets the currently showing interstitial.
void DetachInterstitialPage() override;
- // Unpause the throbber if it was paused.
- void DidProceedOnInterstitial() override;
+ // Changes the IsLoading state and notifies the delegate as needed.
+ // |details| is used to provide details on the load that just finished
+ // (but can be null if not applicable).
+ void SetIsLoading(bool is_loading,
+ bool to_different_document,
+ LoadNotificationDetails* details) override;
typedef base::Callback<void(WebContents*)> CreatedCallback;
@@ -1012,16 +1016,6 @@
// the main frame if empty).
WebUI* CreateWebUI(const GURL& url, const std::string& frame_name);
- // Notifies the delegate of a change in loading state.
- // |details| is used to provide details on the load that just finished
- // (but can be null if not applicable).
- // |pause_throbber_for_interstitial_| will be used to update
- // pause_throbber_for_interstitial_.
- void LoadingStateChanged(bool is_loading,
- bool to_different_document,
- bool pause_throbber_for_interstitial,
- LoadNotificationDetails* details);
-
// Data for core operation ---------------------------------------------------
// Delegate for notifying our owner about stuff. Not owned by us.
@@ -1079,6 +1073,9 @@
// Data for loading state ----------------------------------------------------
+ // Indicates whether we're currently loading a resource.
+ bool is_loading_;
+
// Indicates whether the current load is to a different document. Only valid
// if is_loading_ is true.
bool is_load_to_different_document_;
@@ -1112,10 +1109,6 @@
// See ResumeLoadingCreatedWebContents.
bool is_resume_pending_;
- // Whether the throbber is suspended while an interstial page is showing.
- // This is set to false when the user proceeds in the interstitial.
- bool paused_throbber_for_interstitial_;
-
// Data for current page -----------------------------------------------------
// When a title cannot be taken from any entry, this title will be used.
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index e6c5bb89..532cf01 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -108,13 +108,8 @@
const LoadCommittedDetails& load_details) override {
if (!done_) {
done_ = true;
- shell_->LoadURL(url_);
-
- // There should be a pending entry.
- CHECK(shell_->web_contents()->GetController().GetPendingEntry());
-
- // Now that there is a pending entry, stop the load.
shell_->Stop();
+ shell_->LoadURL(url_);
}
}
@@ -194,8 +189,16 @@
int loadingStateToDifferentDocumentCount_;
};
+// See: http://crbug.com/298193
+#if defined(OS_WIN) || defined(OS_LINUX)
+#define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
+#else
+#define MAYBE_DidStopLoadingDetails DidStopLoadingDetails
+#endif
+
// Test that DidStopLoading includes the correct URL in the details.
-IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) {
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ MAYBE_DidStopLoadingDetails) {
ASSERT_TRUE(embedded_test_server()->Start());
LoadStopNotificationObserver load_observer(
@@ -209,15 +212,20 @@
load_observer.controller_);
}
+// See: http://crbug.com/298193
+#if defined(OS_WIN) || defined(OS_LINUX)
+#define MAYBE_DidStopLoadingDetailsWithPending \
+ DISABLED_DidStopLoadingDetailsWithPending
+#else
+#define MAYBE_DidStopLoadingDetailsWithPending DidStopLoadingDetailsWithPending
+#endif
+
// Test that DidStopLoading includes the correct URL in the details when a
// pending entry is present.
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
- DidStopLoadingDetailsWithPending) {
+ MAYBE_DidStopLoadingDetailsWithPending) {
ASSERT_TRUE(embedded_test_server()->Start());
- // TODO(clamy): Add a cross-process navigation case as well once
- // crbug.com/581024 is fixed.
- GURL url1 = embedded_test_server()->GetURL("/title1.html");
- GURL url2 = embedded_test_server()->GetURL("/title2.html");
+ GURL url("data:text/html,<div>test</div>");
// Listen for the first load to stop.
LoadStopNotificationObserver load_observer(
@@ -226,11 +234,11 @@
// We will hear a DidStopLoading from the first load as the new load
// is started.
NavigateOnCommitObserver commit_observer(
- shell(), url2);
- NavigateToURL(shell(), url1);
+ shell(), embedded_test_server()->GetURL("/title2.html"));
+ NavigateToURL(shell(), url);
load_observer.Wait();
- EXPECT_EQ(url1, load_observer.url_);
+ EXPECT_EQ(url, load_observer.url_);
EXPECT_EQ(0, load_observer.session_index_);
EXPECT_EQ(&shell()->web_contents()->GetController(),
load_observer.controller_);