Commit c0f6e41d authored by mfomitchev's avatar mfomitchev Committed by Commit bot

Use entry URLs instead of entry IDs to determine when to dismiss the overscroll overlay.

This is a band-aid fix for crbug.com/415167, which I'd like to try to get into M38.
Apparently it's possible to have "temporary" entry IDs set as pending and then
thrown away. This confuses OverscrollNavigationOverlay into thinking that the
page was never loaded and the overlay never gets dismissed as a result, which
makes the webpage unusable.
Using URLs is not as reliable avoids this problem. It can introduce false
positives in some corner cases, however a false positive doesn't have severe
consequences - we simply dismiss the overlay too soon, and the use may see an
empty page or a flicker.

BUG=415167

Review URL: https://codereview.chromium.org/575203002

Cr-Commit-Position: refs/heads/master@{#295811}
parent 25deaa9e
...@@ -21,6 +21,24 @@ ...@@ -21,6 +21,24 @@
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
namespace content { namespace content {
namespace {
// Returns true if the entry's URL or any of the URLs in entry's redirect chain
// match |url|.
bool DoesEntryMatchURL(NavigationEntry* entry, const GURL& url) {
if (entry->GetURL() == url)
return true;
const std::vector<GURL>& redirect_chain = entry->GetRedirectChain();
for (std::vector<GURL>::const_iterator it = redirect_chain.begin();
it != redirect_chain.end();
it++) {
if (*it == url)
return true;
}
return false;
}
} // namespace
// A LayerDelegate that paints an image for the layer. // A LayerDelegate that paints an image for the layer.
class ImageLayerDelegate : public ui::LayerDelegate { class ImageLayerDelegate : public ui::LayerDelegate {
...@@ -119,7 +137,6 @@ OverscrollNavigationOverlay::OverscrollNavigationOverlay( ...@@ -119,7 +137,6 @@ OverscrollNavigationOverlay::OverscrollNavigationOverlay(
image_delegate_(NULL), image_delegate_(NULL),
loading_complete_(false), loading_complete_(false),
received_paint_update_(false), received_paint_update_(false),
pending_entry_id_(0),
slide_direction_(SLIDE_UNKNOWN) { slide_direction_(SLIDE_UNKNOWN) {
} }
...@@ -130,7 +147,6 @@ void OverscrollNavigationOverlay::StartObserving() { ...@@ -130,7 +147,6 @@ void OverscrollNavigationOverlay::StartObserving() {
loading_complete_ = false; loading_complete_ = false;
received_paint_update_ = false; received_paint_update_ = false;
overlay_dismiss_layer_.reset(); overlay_dismiss_layer_.reset();
pending_entry_id_ = 0;
Observe(web_contents_); Observe(web_contents_);
// Make sure the overlay window is on top. // Make sure the overlay window is on top.
...@@ -140,10 +156,10 @@ void OverscrollNavigationOverlay::StartObserving() { ...@@ -140,10 +156,10 @@ void OverscrollNavigationOverlay::StartObserving() {
// Assumes the navigation has been initiated. // Assumes the navigation has been initiated.
NavigationEntry* pending_entry = NavigationEntry* pending_entry =
web_contents_->GetController().GetPendingEntry(); web_contents_->GetController().GetPendingEntry();
// Save id of the pending entry to identify when it loads and paints later. // Save url of the pending entry to identify when it loads and paints later.
// Under some circumstances navigation can leave a null pending entry - // Under some circumstances navigation can leave a null pending entry -
// see comments in NavigationControllerImpl::NavigateToPendingEntry(). // see comments in NavigationControllerImpl::NavigateToPendingEntry().
pending_entry_id_ = pending_entry ? pending_entry->GetUniqueID() : 0; pending_entry_url_ = pending_entry ? pending_entry->GetURL() : GURL();
} }
void OverscrollNavigationOverlay::SetOverlayWindow( void OverscrollNavigationOverlay::SetOverlayWindow(
...@@ -282,23 +298,21 @@ void OverscrollNavigationOverlay::OnWindowSliderDestroyed() { ...@@ -282,23 +298,21 @@ void OverscrollNavigationOverlay::OnWindowSliderDestroyed() {
} }
void OverscrollNavigationOverlay::DidFirstVisuallyNonEmptyPaint() { void OverscrollNavigationOverlay::DidFirstVisuallyNonEmptyPaint() {
int visible_entry_id = NavigationEntry* visible_entry =
web_contents_->GetController().GetVisibleEntry()->GetUniqueID(); web_contents_->GetController().GetVisibleEntry();
if (visible_entry_id == pending_entry_id_ || !pending_entry_id_) { if (pending_entry_url_.is_empty() ||
DoesEntryMatchURL(visible_entry, pending_entry_url_)) {
received_paint_update_ = true; received_paint_update_ = true;
StopObservingIfDone(); StopObservingIfDone();
} }
} }
void OverscrollNavigationOverlay::DidStopLoading(RenderViewHost* host) { void OverscrollNavigationOverlay::DidStopLoading(RenderViewHost* host) {
// Use the last committed entry rather than the active one, in case a // Don't compare URLs in this case - it's possible they won't match if
// pending entry has been created. // a gesture-nav initiated navigation was interrupted by some other in-site
int committed_entry_id = // navigation ((e.g., from a script, or from a bookmark).
web_contents_->GetController().GetLastCommittedEntry()->GetUniqueID(); loading_complete_ = true;
if (committed_entry_id == pending_entry_id_ || !pending_entry_id_) { StopObservingIfDone();
loading_complete_ = true;
StopObservingIfDone();
}
} }
} // namespace content } // namespace content
...@@ -101,10 +101,10 @@ class CONTENT_EXPORT OverscrollNavigationOverlay ...@@ -101,10 +101,10 @@ class CONTENT_EXPORT OverscrollNavigationOverlay
bool loading_complete_; bool loading_complete_;
bool received_paint_update_; bool received_paint_update_;
// Unique ID of the NavigationEntry we are navigating to. This is needed to // URL of the NavigationEntry we are navigating to. This is needed to
// filter on WebContentsObserver callbacks and is used to dismiss the overlay // filter on WebContentsObserver callbacks and is used to dismiss the overlay
// when the relevant page loads and paints. // when the relevant page loads and paints.
int pending_entry_id_; GURL pending_entry_url_;
// The |WindowSlider| that allows sliding history layers while the page is // The |WindowSlider| that allows sliding history layers while the page is
// being reloaded. // being reloaded.
......
...@@ -157,7 +157,7 @@ TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_PaintUpdate) { ...@@ -157,7 +157,7 @@ TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_PaintUpdate) {
EXPECT_FALSE(GetOverlay()->received_paint_update_); EXPECT_FALSE(GetOverlay()->received_paint_update_);
ReceivePaintUpdate(); ReceivePaintUpdate();
// Paint updates until the navigation is committed represent updates // Paint updates until the navigation is committed typically represent updates
// for the previous page, so they shouldn't affect the flag. // for the previous page, so they shouldn't affect the flag.
EXPECT_FALSE(GetOverlay()->received_paint_update_); EXPECT_FALSE(GetOverlay()->received_paint_update_);
...@@ -179,17 +179,13 @@ TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_LoadingUpdate) { ...@@ -179,17 +179,13 @@ TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_LoadingUpdate) {
// Navigation was started, so the loading status flag should be reset. // Navigation was started, so the loading status flag should be reset.
EXPECT_FALSE(GetOverlay()->loading_complete_); EXPECT_FALSE(GetOverlay()->loading_complete_);
// Load updates until the navigation is committed represent updates for the // DidStopLoading for any navigation should always reset the load flag and
// previous page, so they shouldn't affect the flag. // dismiss the overlay even if the pending navigation wasn't committed -
// 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(true);
contents()->TestSetIsLoading(false); contents()->TestSetIsLoading(false);
EXPECT_FALSE(GetOverlay()->loading_complete_);
contents()->CommitPendingNavigation();
contents()->TestSetIsLoading(true);
contents()->TestSetIsLoading(false);
// Navigation was committed and the load update was received - the flag
// should now be updated.
EXPECT_TRUE(GetOverlay()->loading_complete_); EXPECT_TRUE(GetOverlay()->loading_complete_);
EXPECT_FALSE(GetOverlay()->web_contents()); EXPECT_FALSE(GetOverlay()->web_contents());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment