Commit 78764069 authored by Emily Stark's avatar Emily Stark Committed by Commit Bot

Simplified domain display: accommodate browser-initiated navigations

In the hide-on-interaction field trial, we were previously handling
navigations only in DidFinishNavigation(). That is, when a navigation
began, we didn’t change the elision state until it commited in
DidFinishNavigation(). This worked well for renderer-initiated
navigations, where the visible URL doesn’t update until the navigation
commits. But it didn’t work for browser-initiated navigations, where
the URL would update at the very beginning of the navigation and
inherit the elision state of the previous navigation until
DidFinishNavigation (see screencast in crbug.com/1111665).

The fix for this is rather tricky and not perfect. For a
browser-initiated navigation, the order of events is as follows:
- URL is updated (triggering EmphasizeURLComponents)
- DidStartNavigation
- DidFinishNavigation
Because the URL is updated at the first step, we need to set the
elision state in EmphasizeURLComponents. Even setting in
DidStartNavigation would be too late, as we could still get a flash of
the new URL with the previous navigation’s elision applied to it. The
problem, though, is that we don’t know if we should elide the URL
until the navigation finishes, because the elision logic depends on
whether the navigation was same-document and if it changed the visible
URL’s path. (In particular, for same-document navigations that only
change the fragment, we ignore those and don’t have them change the
elision state at all.) Therefore, in EmphasizeURLComponents(), we
don’t know for sure whether we should leave the URL elided if it
already is elided, or if we should unelide and reset to the
on-page-load state.

I wasn’t able to think up a perfect solution for this, but the best I
can come up with is to make our best guess how to elide in
EmphasizeURLComponents(), and then fix it up as we get more
information in DidStartNavigation() and
DidFinishNavigation(). Specifically, EmphasizeURLComponents() elides
to the simplified domain if the URL had already been elided, and shows
the full URL otherwise. DidStartNavigation() then fully resets to the
on-page-load state for cross-document navigations, and
DidFinishNavigation() fully resets to the on-page-load state for
same-document navigations that changed the path (which we don't know
until the navigation commits). There remains a weirdness where a
browser-initiated navigation will initially briefly show the
simplified domain of the destination before updating to the full URL
in DidStartNavigation(), but I think this is far better than briefly
showing the destination URL truncated where the previous page’s URL
was truncated.

Bug: 1111665, 1109778
Change-Id: Ia1528254b8203dee93bd0964666b76d4b15bfd46
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2360803
Commit-Queue: Emily Stark <estark@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarJustin Donnelly <jdonnelly@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799914}
parent 4c4d81cf
...@@ -177,6 +177,188 @@ bool TextRangeOverflowsView(OmniboxViewViews* omnibox_view, ...@@ -177,6 +177,188 @@ bool TextRangeOverflowsView(OmniboxViewViews* omnibox_view,
} // namespace } // namespace
OmniboxViewViews::ElideAnimation::ElideAnimation(OmniboxViewViews* view,
gfx::RenderText* render_text)
: AnimationDelegateViews(view), view_(view), render_text_(render_text) {
DCHECK(view_);
DCHECK(render_text_);
}
OmniboxViewViews::ElideAnimation::~ElideAnimation() = default;
// TODO(estark): this code doesn't work for URLs with RTL components. Will need
// to figure out another animation or just skip the animation entirely on URLs
// with RTL components.
void OmniboxViewViews::ElideAnimation::Start(
const gfx::Range& elide_to_bounds,
uint32_t delay_ms,
const std::vector<gfx::Range>& ranges_surrounding_simplified_domain,
SkColor starting_color,
SkColor ending_color) {
DCHECK(ranges_surrounding_simplified_domain.size() == 1 ||
ranges_surrounding_simplified_domain.size() == 2);
ranges_surrounding_simplified_domain_ = ranges_surrounding_simplified_domain;
starting_color_ = starting_color;
ending_color_ = ending_color;
// simplified_domain_bounds_ will be set to a rectangle surrounding the part
// of the URL that is never elided, on its original position before any
// animation runs. If ranges_surrounding_simplified_domain_ only contains one
// range it means we are not eliding on the right side, so we use the right
// side of elide_to_bounds as the range as it will always be the right limit
// of the simplified section.
gfx::Range simplified_domain_range(
ranges_surrounding_simplified_domain_[0].end(),
ranges_surrounding_simplified_domain_.size() == 2
? ranges_surrounding_simplified_domain_[1].start()
: elide_to_bounds.end());
for (auto rect : render_text_->GetSubstringBounds(simplified_domain_range)) {
simplified_domain_bounds_.Union(rect - render_text_->GetLineOffset(0));
}
// After computing |elide_to_rect_| below, |elide_to_bounds| aren't actually
// need anymore for the animation. However, the bounds provide a convenient
// way for the animation consumer to check if an animation is currently in
// progress to a specific range, so that the consumer can avoid starting a
// duplicate animation (to avoid flicker). So we save the bounds so that
// consumers can query them.
elide_to_bounds_ = elide_to_bounds;
animation_ = std::make_unique<gfx::MultiAnimation>(
gfx::MultiAnimation::Parts({
gfx::MultiAnimation::Part(base::TimeDelta::FromMilliseconds(delay_ms),
gfx::Tween::ZERO),
gfx::MultiAnimation::Part(base::TimeDelta::FromMilliseconds(300),
gfx::Tween::FAST_OUT_SLOW_IN),
}),
gfx::MultiAnimation::kDefaultTimerInterval);
animation_->set_delegate(this);
animation_->set_continuous(false);
elide_from_rect_ = render_text_->display_rect();
elide_to_rect_ = gfx::Rect();
for (const auto& rect : render_text_->GetSubstringBounds(elide_to_bounds))
elide_to_rect_.Union(rect);
// The URL should never shift vertically while eliding to/from simplified
// domain.
elide_to_rect_.set_y(elide_from_rect_.y());
elide_to_rect_.set_height(elide_from_rect_.height());
// There is nothing to animate in this case, so return without starting.
if (elide_from_rect_ == elide_to_rect_ && starting_color_ == ending_color_)
return;
starting_display_offset_ = render_text_->GetUpdatedDisplayOffset().x();
// Shift the text to where |elide_to_bounds| starts, relative to the current
// display rect.
if (base::i18n::IsRTL()) {
ending_display_offset_ = starting_display_offset_ +
elide_from_rect_.right() - elide_to_rect_.right();
} else {
ending_display_offset_ =
starting_display_offset_ - (elide_to_rect_.x() - elide_from_rect_.x());
}
animation_->Start();
}
void OmniboxViewViews::ElideAnimation::Stop() {
// Reset the smoothing rectangles whenever the animation stops to prevent
// stale rectangles from showing at the start of the next animation.
view_->elide_animation_smoothing_rect_left_ = gfx::Rect();
view_->elide_animation_smoothing_rect_right_ = gfx::Rect();
if (animation_)
animation_->Stop();
}
bool OmniboxViewViews::ElideAnimation::IsAnimating() {
return animation_ && animation_->is_animating();
}
const gfx::Range& OmniboxViewViews::ElideAnimation::GetElideToBounds() const {
return elide_to_bounds_;
}
SkColor OmniboxViewViews::ElideAnimation::GetCurrentColor() const {
return animation_
? gfx::Tween::ColorValueBetween(animation_->GetCurrentValue(),
starting_color_, ending_color_)
: gfx::kPlaceholderColor;
}
gfx::MultiAnimation*
OmniboxViewViews::ElideAnimation::GetAnimationForTesting() {
return animation_.get();
}
void OmniboxViewViews::ElideAnimation::AnimationProgressed(
const gfx::Animation* animation) {
DCHECK(!view_->model()->user_input_in_progress());
DCHECK_EQ(animation, animation_.get());
if (animation->GetCurrentValue() == 0)
return;
// |bounds| contains the interpolated substring to show for this frame. Shift
// it to line up with the x position of the previous frame (|old_bounds|),
// because the animation should gradually bring the desired string into view
// at the leading edge. The y/height values shouldn't change because
// |elide_to_rect_| is set to have the same y and height values as
// |elide_to_rect_|.
gfx::Rect old_bounds = render_text_->display_rect();
gfx::Rect bounds = gfx::Tween::RectValueBetween(
animation->GetCurrentValue(), elide_from_rect_, elide_to_rect_);
DCHECK_EQ(bounds.y(), old_bounds.y());
DCHECK_EQ(bounds.height(), old_bounds.height());
gfx::Rect shifted_bounds(base::i18n::IsRTL()
? old_bounds.right() - bounds.width()
: old_bounds.x(),
old_bounds.y(), bounds.width(), old_bounds.height());
render_text_->SetDisplayRect(shifted_bounds);
current_offset_ = gfx::Tween::IntValueBetween(animation->GetCurrentValue(),
starting_display_offset_,
ending_display_offset_);
render_text_->SetDisplayOffset(current_offset_);
for (const auto& range : ranges_surrounding_simplified_domain_) {
view_->ApplyColor(GetCurrentColor(), range);
}
// TODO(crbug.com/1101472): The smoothing gradient mask is not yet implemented
// correctly for RTL UI.
if (base::i18n::IsRTL()) {
view_->SchedulePaint();
return;
}
// The gradient mask should be a fixed width, except if that width would
// cause it to mask the unelided section. In that case we set it to the
// maximum width possible that won't cover the unelided section.
int unelided_left_bound = simplified_domain_bounds_.x() + current_offset_;
int unelided_right_bound =
unelided_left_bound + simplified_domain_bounds_.width();
// GetSubstringBounds rounds up when calculating unelided_left_bound and
// unelided_right_bound, we subtract 1 pixel from the gradient widths to make
// sure they never overlap with the always visible part of the URL.
// gfx::Rect() switches negative values to 0, so this doesn't affect
// rectangles that were originally size 0.
int left_gradient_width = kSmoothingGradientMaxWidth < unelided_left_bound
? kSmoothingGradientMaxWidth - 1
: unelided_left_bound - 1;
int right_gradient_width =
shifted_bounds.right() - kSmoothingGradientMaxWidth > unelided_right_bound
? kSmoothingGradientMaxWidth - 1
: shifted_bounds.right() - unelided_right_bound - 1;
view_->elide_animation_smoothing_rect_left_ = gfx::Rect(
old_bounds.x(), old_bounds.y(), left_gradient_width, old_bounds.height());
view_->elide_animation_smoothing_rect_right_ =
gfx::Rect(shifted_bounds.right() - right_gradient_width, old_bounds.y(),
right_gradient_width, old_bounds.height());
view_->SchedulePaint();
}
// OmniboxViewViews ----------------------------------------------------------- // OmniboxViewViews -----------------------------------------------------------
// static // static
...@@ -358,21 +540,54 @@ void OmniboxViewViews::EmphasizeURLComponents() { ...@@ -358,21 +540,54 @@ void OmniboxViewViews::EmphasizeURLComponents() {
base::string16 text = GetText(); base::string16 text = GetText();
UpdateTextStyle(text, text_is_url, model()->client()->GetSchemeClassifier()); UpdateTextStyle(text, text_is_url, model()->client()->GetSchemeClassifier());
if (OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover() && if (model()->ShouldPreventElision())
!OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() && return;
!model()->ShouldPreventElision()) {
// If reveal-on-hover is enabled and hide-on-interaction is disabled, elide // If the text isn't eligible to be elided to a simplified domain, and
// to the simplified domain now. We don't animate because we don't want this // simplified domain field trials are enabled, then ensure that as much of the
// to be a user-visible transformation; in this variation, we want to always // text as will fit is visible.
// show just the simplified domain until the user specifically interacts if (!IsURLEligibleForSimplifiedDomainEliding() &&
// with the omnibox by hovering over it. (OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() ||
if (IsURLEligibleForSimplifiedDomainEliding()) { OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover())) {
FitToLocalBounds();
return;
}
// In the simplified domain field trials, elide or unelide according to the
// current state and field trial configuration. These elisions are not
// animated because we often don't want this to be a user-visible
// transformation; for example, a navigation should just show the URL in the
// desired state without drawing additional attention from the user.
if (OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction()) {
// In the hide-on-interaction field trial, elide or unelide the URL to the
// simplified domain depending on whether the user has already interacted
// with the page or not. This is a best guess at the correct elision state,
// which we don't really know for sure until a navigation has committed
// (because the elision behavior depends on whether the navigation is
// same-document and if it changes the path). We elide here based on the
// current elision setting; we'll then update the elision state as we get
// more information about the navigation in DidStartNavigation and
// DidFinishNavigation.
if (elide_after_web_contents_interaction_animation_) {
// This can cause a slight quirk in browser-initiated navigations that
// occur after the user interacts with the previous page. In this case,
// the simplified domain will be shown briefly before we show the full URL
// in DidStartNavigation().
ElideURL(); ElideURL();
} else { } else {
// If the text isn't eligible to be elided to a simplified domain, then // Note that here we are only adjusting the display of the URL, not
// ensure that as much of it is visible as will fit. // resetting any state associated with the animations (in particular, we
FitToLocalBounds(); // are not calling ResetToHideOnInteraction()). This is, as above, because
// we don't know exactly how to set state until we know what kind of
// navigation is happening. Thus here we are only adjusting the display so
// things look right mid-navigation, and the final state will be set
// appropriately in DidFinishNavigation().
ShowFullURLWithoutSchemeAndTrivialSubdomain();
} }
} else if (OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
// If reveal-on-hover is enabled and hide-on-interaction is disabled, elide
// to the simplified domain now.
ElideURL();
} }
} }
...@@ -614,6 +829,45 @@ void OmniboxViewViews::RemovedFromWidget() { ...@@ -614,6 +829,45 @@ void OmniboxViewViews::RemovedFromWidget() {
scoped_compositor_observer_.RemoveAll(); scoped_compositor_observer_.RemoveAll();
} }
OmniboxViewViews::ElideAnimation*
OmniboxViewViews::GetHoverElideOrUnelideAnimationForTesting() {
return hover_elide_or_unelide_animation_.get();
}
OmniboxViewViews::ElideAnimation*
OmniboxViewViews::GetElideAfterInteractionAnimationForTesting() {
return elide_after_web_contents_interaction_animation_.get();
}
void OmniboxViewViews::OnThemeChanged() {
views::Textfield::OnThemeChanged();
const SkColor dimmed_text_color = GetOmniboxColor(
GetThemeProvider(), OmniboxPart::LOCATION_BAR_TEXT_DIMMED);
set_placeholder_text_color(dimmed_text_color);
if (!model()->ShouldPreventElision() &&
OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
hover_elide_or_unelide_animation_ =
std::make_unique<ElideAnimation>(this, GetRenderText());
}
EmphasizeURLComponents();
}
bool OmniboxViewViews::IsDropCursorForInsertion() const {
// Dragging text from within omnibox itself will behave like text input
// editor, showing insertion-style drop cursor as usual;
// but dragging text from outside omnibox will replace entire contents with
// paste-and-go behavior, so returning false in that case prevents the
// confusing insertion-style drop cursor.
return HasTextBeingDragged();
}
void OmniboxViewViews::ApplyColor(SkColor color, const gfx::Range& range) {
Textfield::ApplyColor(color, range);
}
void OmniboxViewViews::SetTextAndSelectedRanges( void OmniboxViewViews::SetTextAndSelectedRanges(
const base::string16& text, const base::string16& text,
const std::vector<gfx::Range>& ranges) { const std::vector<gfx::Range>& ranges) {
...@@ -1688,6 +1942,23 @@ bool OmniboxViewViews::IsCommandIdEnabled(int command_id) const { ...@@ -1688,6 +1942,23 @@ bool OmniboxViewViews::IsCommandIdEnabled(int command_id) const {
location_bar_view_->command_updater()->IsCommandEnabled(command_id); location_bar_view_->command_updater()->IsCommandEnabled(command_id);
} }
void OmniboxViewViews::DidStartNavigation(
content::NavigationHandle* navigation) {
if (!OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() ||
model()->ShouldPreventElision()) {
return;
}
// If navigating to a different page in a browser-initiated navigation, the
// new URL should be shown unelided while the navigation is in progress. For
// renderer-initiated navigations, the URL isn't displayed until the
// navigation commits, so there's no need to elide/unelide it now.
if (navigation->IsInMainFrame() && !navigation->IsSameDocument() &&
!navigation->IsRendererInitiated()) {
ResetToHideOnInteraction();
}
}
void OmniboxViewViews::DidFinishNavigation( void OmniboxViewViews::DidFinishNavigation(
content::NavigationHandle* navigation) { content::NavigationHandle* navigation) {
if (!OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() || if (!OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() ||
...@@ -1700,48 +1971,16 @@ void OmniboxViewViews::DidFinishNavigation( ...@@ -1700,48 +1971,16 @@ void OmniboxViewViews::DidFinishNavigation(
if (!navigation->IsInMainFrame()) if (!navigation->IsInMainFrame())
return; return;
// Same-document navigations should be treated with the following // Once a navigation finishes that changes the visible URL (besides just the
// considerations: // ref), unelide and reset state so that we'll show the simplified domain on
// - If the same-document navigation was triggered by a fragment navigation, // interaction. Same-document navigations that only change the ref are treated
// the current elision/unelision state shouldn't be altered, since it always // specially and don't cause the elision/unelision state to be altered. This
// remains in the same page, keeping location.pathname // is to avoid frequent eliding/uneliding within single-page apps that do
// - If the same-document navigation was triggered by the use of history // frequent fragment navigations.
// pushState/replaceState API, we should unelide and reset state to support if (!navigation->IsSameDocument() ||
// the same behaviour in websites that rely on same-document navigation to !navigation->GetPreviousURL().EqualsIgnoringRef(navigation->GetURL())) {
// render different views as if it were 'normal' navigation
if (navigation->IsSameDocument() &&
navigation->GetPreviousURL().EqualsIgnoringRef(navigation->GetURL())) {
if (!IsURLEligibleForSimplifiedDomainEliding())
return;
// Handling same-document navigations is a bit tricky because they shouldn't
// change the current elision/unelision state:
// - If the user interacted with the page, and we have already finished
// animating to the simplified domain, then make sure we stay in the elided
// state, showing only the simplified domain. This is an abrupt elision,
// rather than an animation, because we don't want there to be any visible
// change in the URL from the user's perspective.
// - If the user interacted with the page, and we are currently animating to
// the simplified domain as a result, we want to let the animation run
// undisturbed, eventually ending up in the elided state.
// - If the user hadn't interacted with the previous page, then we need to
// ensure the full URL (without scheme and trivial subdomain) is showing;
// this is done by falling through to ResetToHideOnInteraction() below.
//
// |elide_after_web_contents_interaction_animation_| is only created after
// the user interacts with the page (in DidGetUserInteraction()), so we use
// its existence to determine whether the user has interacted with the page
// yet or not.
if (elide_after_web_contents_interaction_animation_) {
if (!elide_after_web_contents_interaction_animation_->IsAnimating())
ElideURL();
return;
}
}
// Once a navigation finishes, unelide and reset state so
// that we'll show the simplified domain on interaction.
ResetToHideOnInteraction(); ResetToHideOnInteraction();
}
} }
void OmniboxViewViews::DidGetUserInteraction( void OmniboxViewViews::DidGetUserInteraction(
...@@ -1770,227 +2009,6 @@ void OmniboxViewViews::OnFocusChangedInPage( ...@@ -1770,227 +2009,6 @@ void OmniboxViewViews::OnFocusChangedInPage(
MaybeElideURLWithAnimationFromInteraction(); MaybeElideURLWithAnimationFromInteraction();
} }
OmniboxViewViews::ElideAnimation::ElideAnimation(OmniboxViewViews* view,
gfx::RenderText* render_text)
: AnimationDelegateViews(view), view_(view), render_text_(render_text) {
DCHECK(view_);
DCHECK(render_text_);
}
OmniboxViewViews::ElideAnimation::~ElideAnimation() = default;
// TODO(estark): this code doesn't work for URLs with RTL components. Will need
// to figure out another animation or just skip the animation entirely on URLs
// with RTL components.
void OmniboxViewViews::ElideAnimation::Start(
const gfx::Range& elide_to_bounds,
uint32_t delay_ms,
const std::vector<gfx::Range>& ranges_surrounding_simplified_domain,
SkColor starting_color,
SkColor ending_color) {
DCHECK(ranges_surrounding_simplified_domain.size() == 1 ||
ranges_surrounding_simplified_domain.size() == 2);
ranges_surrounding_simplified_domain_ = ranges_surrounding_simplified_domain;
starting_color_ = starting_color;
ending_color_ = ending_color;
// simplified_domain_bounds_ will be set to a rectangle surrounding the part
// of the URL that is never elided, on its original position before any
// animation runs. If ranges_surrounding_simplified_domain_ only contains one
// range it means we are not eliding on the right side, so we use the right
// side of elide_to_bounds as the range as it will always be the right limit
// of the simplified section.
gfx::Range simplified_domain_range(
ranges_surrounding_simplified_domain_[0].end(),
ranges_surrounding_simplified_domain_.size() == 2
? ranges_surrounding_simplified_domain_[1].start()
: elide_to_bounds.end());
for (auto rect : render_text_->GetSubstringBounds(simplified_domain_range)) {
simplified_domain_bounds_.Union(rect - render_text_->GetLineOffset(0));
}
// After computing |elide_to_rect_| below, |elide_to_bounds| aren't actually
// need anymore for the animation. However, the bounds provide a convenient
// way for the animation consumer to check if an animation is currently in
// progress to a specific range, so that the consumer can avoid starting a
// duplicate animation (to avoid flicker). So we save the bounds so that
// consumers can query them.
elide_to_bounds_ = elide_to_bounds;
animation_ = std::make_unique<gfx::MultiAnimation>(
gfx::MultiAnimation::Parts({
gfx::MultiAnimation::Part(base::TimeDelta::FromMilliseconds(delay_ms),
gfx::Tween::ZERO),
gfx::MultiAnimation::Part(base::TimeDelta::FromMilliseconds(300),
gfx::Tween::FAST_OUT_SLOW_IN),
}),
gfx::MultiAnimation::kDefaultTimerInterval);
animation_->set_delegate(this);
animation_->set_continuous(false);
elide_from_rect_ = render_text_->display_rect();
elide_to_rect_ = gfx::Rect();
for (const auto& rect : render_text_->GetSubstringBounds(elide_to_bounds))
elide_to_rect_.Union(rect);
// The URL should never shift vertically while eliding to/from simplified
// domain.
elide_to_rect_.set_y(elide_from_rect_.y());
elide_to_rect_.set_height(elide_from_rect_.height());
// There is nothing to animate in this case, so return without starting.
if (elide_from_rect_ == elide_to_rect_ && starting_color_ == ending_color_)
return;
starting_display_offset_ = render_text_->GetUpdatedDisplayOffset().x();
// Shift the text to where |elide_to_bounds| starts, relative to the current
// display rect.
if (base::i18n::IsRTL()) {
ending_display_offset_ = starting_display_offset_ +
elide_from_rect_.right() - elide_to_rect_.right();
} else {
ending_display_offset_ =
starting_display_offset_ - (elide_to_rect_.x() - elide_from_rect_.x());
}
animation_->Start();
}
void OmniboxViewViews::ElideAnimation::Stop() {
// Reset the smoothing rectangles whenever the animation stops to prevent
// stale rectangles from showing at the start of the next animation.
view_->elide_animation_smoothing_rect_left_ = gfx::Rect();
view_->elide_animation_smoothing_rect_right_ = gfx::Rect();
if (animation_)
animation_->Stop();
}
bool OmniboxViewViews::ElideAnimation::IsAnimating() {
return animation_ && animation_->is_animating();
}
const gfx::Range& OmniboxViewViews::ElideAnimation::GetElideToBounds() const {
return elide_to_bounds_;
}
SkColor OmniboxViewViews::ElideAnimation::GetCurrentColor() const {
return animation_
? gfx::Tween::ColorValueBetween(animation_->GetCurrentValue(),
starting_color_, ending_color_)
: gfx::kPlaceholderColor;
}
gfx::MultiAnimation*
OmniboxViewViews::ElideAnimation::GetAnimationForTesting() {
return animation_.get();
}
void OmniboxViewViews::ElideAnimation::AnimationProgressed(
const gfx::Animation* animation) {
DCHECK(!view_->model()->user_input_in_progress());
DCHECK_EQ(animation, animation_.get());
if (animation->GetCurrentValue() == 0)
return;
// |bounds| contains the interpolated substring to show for this frame. Shift
// it to line up with the x position of the previous frame (|old_bounds|),
// because the animation should gradually bring the desired string into view
// at the leading edge. The y/height values shouldn't change because
// |elide_to_rect_| is set to have the same y and height values as
// |elide_to_rect_|.
gfx::Rect old_bounds = render_text_->display_rect();
gfx::Rect bounds = gfx::Tween::RectValueBetween(
animation->GetCurrentValue(), elide_from_rect_, elide_to_rect_);
DCHECK_EQ(bounds.y(), old_bounds.y());
DCHECK_EQ(bounds.height(), old_bounds.height());
gfx::Rect shifted_bounds(base::i18n::IsRTL()
? old_bounds.right() - bounds.width()
: old_bounds.x(),
old_bounds.y(), bounds.width(), old_bounds.height());
render_text_->SetDisplayRect(shifted_bounds);
current_offset_ = gfx::Tween::IntValueBetween(animation->GetCurrentValue(),
starting_display_offset_,
ending_display_offset_);
render_text_->SetDisplayOffset(current_offset_);
for (const auto& range : ranges_surrounding_simplified_domain_) {
view_->ApplyColor(GetCurrentColor(), range);
}
// TODO(crbug.com/1101472): The smoothing gradient mask is not yet implemented
// correctly for RTL UI.
if (base::i18n::IsRTL()) {
view_->SchedulePaint();
return;
}
// The gradient mask should be a fixed width, except if that width would
// cause it to mask the unelided section. In that case we set it to the
// maximum width possible that won't cover the unelided section.
int unelided_left_bound = simplified_domain_bounds_.x() + current_offset_;
int unelided_right_bound =
unelided_left_bound + simplified_domain_bounds_.width();
// GetSubstringBounds rounds up when calculating unelided_left_bound and
// unelided_right_bound, we subtract 1 pixel from the gradient widths to make
// sure they never overlap with the always visible part of the URL.
// gfx::Rect() switches negative values to 0, so this doesn't affect
// rectangles that were originally size 0.
int left_gradient_width = kSmoothingGradientMaxWidth < unelided_left_bound
? kSmoothingGradientMaxWidth - 1
: unelided_left_bound - 1;
int right_gradient_width =
shifted_bounds.right() - kSmoothingGradientMaxWidth > unelided_right_bound
? kSmoothingGradientMaxWidth - 1
: shifted_bounds.right() - unelided_right_bound - 1;
view_->elide_animation_smoothing_rect_left_ = gfx::Rect(
old_bounds.x(), old_bounds.y(), left_gradient_width, old_bounds.height());
view_->elide_animation_smoothing_rect_right_ =
gfx::Rect(shifted_bounds.right() - right_gradient_width, old_bounds.y(),
right_gradient_width, old_bounds.height());
view_->SchedulePaint();
}
OmniboxViewViews::ElideAnimation*
OmniboxViewViews::GetHoverElideOrUnelideAnimationForTesting() {
return hover_elide_or_unelide_animation_.get();
}
OmniboxViewViews::ElideAnimation*
OmniboxViewViews::GetElideAfterInteractionAnimationForTesting() {
return elide_after_web_contents_interaction_animation_.get();
}
void OmniboxViewViews::OnThemeChanged() {
views::Textfield::OnThemeChanged();
const SkColor dimmed_text_color = GetOmniboxColor(
GetThemeProvider(), OmniboxPart::LOCATION_BAR_TEXT_DIMMED);
set_placeholder_text_color(dimmed_text_color);
if (!model()->ShouldPreventElision() &&
OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
hover_elide_or_unelide_animation_ =
std::make_unique<ElideAnimation>(this, GetRenderText());
}
EmphasizeURLComponents();
}
bool OmniboxViewViews::IsDropCursorForInsertion() const {
// Dragging text from within omnibox itself will behave like text input
// editor, showing insertion-style drop cursor as usual;
// but dragging text from outside omnibox will replace entire contents with
// paste-and-go behavior, so returning false in that case prevents the
// confusing insertion-style drop cursor.
return HasTextBeingDragged();
}
void OmniboxViewViews::ApplyColor(SkColor color, const gfx::Range& range) {
Textfield::ApplyColor(color, range);
}
base::string16 OmniboxViewViews::GetSelectionClipboardText() const { base::string16 OmniboxViewViews::GetSelectionClipboardText() const {
return SanitizeTextForPaste(Textfield::GetSelectionClipboardText()); return SanitizeTextForPaste(Textfield::GetSelectionClipboardText());
} }
...@@ -2769,4 +2787,3 @@ url::Component OmniboxViewViews::GetHostComponentAfterTrivialSubdomain() { ...@@ -2769,4 +2787,3 @@ url::Component OmniboxViewViews::GetHostComponentAfterTrivialSubdomain() {
url_formatter::StripWWWFromHostComponent(base::UTF16ToUTF8(text), &host); url_formatter::StripWWWFromHostComponent(base::UTF16ToUTF8(text), &host);
return host; return host;
} }
...@@ -160,6 +160,7 @@ class OmniboxViewViews : public OmniboxView, ...@@ -160,6 +160,7 @@ class OmniboxViewViews : public OmniboxView,
bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override;
// content::WebContentsObserver: // content::WebContentsObserver:
void DidStartNavigation(content::NavigationHandle* navigation) override;
void DidFinishNavigation(content::NavigationHandle* navigation) override; void DidFinishNavigation(content::NavigationHandle* navigation) override;
void DidGetUserInteraction(const blink::WebInputEvent& event) override; void DidGetUserInteraction(const blink::WebInputEvent& event) override;
void OnFocusChangedInPage(content::FocusedNodeDetails* details) override; void OnFocusChangedInPage(content::FocusedNodeDetails* details) override;
...@@ -282,6 +283,9 @@ class OmniboxViewViews : public OmniboxView, ...@@ -282,6 +283,9 @@ class OmniboxViewViews : public OmniboxView,
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExit); FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExit);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExitIDN); FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, HoverAndExitIDN);
FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, PrivateRegistry); FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, PrivateRegistry);
FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
BrowserInitiatedNavigation);
FRIEND_TEST_ALL_PREFIXES( FRIEND_TEST_ALL_PREFIXES(
OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
UserInteractionAndHover); UserInteractionAndHover);
......
...@@ -82,6 +82,7 @@ void ExpectUnelidedFromSimplifiedDomain(gfx::RenderText* render_text, ...@@ -82,6 +82,7 @@ void ExpectUnelidedFromSimplifiedDomain(gfx::RenderText* render_text,
class TestingOmniboxView : public OmniboxViewViews { class TestingOmniboxView : public OmniboxViewViews {
public: public:
TestingOmniboxView(OmniboxEditController* controller, TestingOmniboxView(OmniboxEditController* controller,
TestLocationBarModel* location_bar_model,
std::unique_ptr<OmniboxClient> client); std::unique_ptr<OmniboxClient> client);
using views::Textfield::GetRenderText; using views::Textfield::GetRenderText;
...@@ -113,7 +114,9 @@ class TestingOmniboxView : public OmniboxViewViews { ...@@ -113,7 +114,9 @@ class TestingOmniboxView : public OmniboxViewViews {
void StepSimplifiedDomainInteractionAnimation(int64_t step_ms); void StepSimplifiedDomainInteractionAnimation(int64_t step_ms);
// Simulates a navigation and checks that the URL is elided to the simplified // Simulates a navigation and checks that the URL is elided to the simplified
// domain afterwards. // domain afterwards. This simulates a renderer-initiated navigation, in which
// the display URL is updated between DidStartNavigation() and
// DidFinishNavigation() calls.
void NavigateAndExpectElided(const GURL& url, void NavigateAndExpectElided(const GURL& url,
bool is_same_document, bool is_same_document,
const GURL& previous_url, const GURL& previous_url,
...@@ -123,8 +126,10 @@ class TestingOmniboxView : public OmniboxViewViews { ...@@ -123,8 +126,10 @@ class TestingOmniboxView : public OmniboxViewViews {
const base::string16& path, const base::string16& path,
bool should_elide_to_registrable_domain); bool should_elide_to_registrable_domain);
// Simulates a navigation and checks that the URL is unelided from the // Simluates a navigation and checks that the URL is unelided from the
// simplified domain afterwards. // simplified domain afterwards. This simulates a renderer-initiated
// navigation, in which the display URL is updated between
// DidStartNavigation() and DidFinishNavigation() calls.
void NavigateAndExpectUnelided(const base::string16& url, void NavigateAndExpectUnelided(const base::string16& url,
bool is_same_document, bool is_same_document,
const GURL& previous_url, const GURL& previous_url,
...@@ -156,6 +161,8 @@ class TestingOmniboxView : public OmniboxViewViews { ...@@ -156,6 +161,8 @@ class TestingOmniboxView : public OmniboxViewViews {
// order. // order.
std::vector<std::pair<SkColor, gfx::Range>> range_colors_; std::vector<std::pair<SkColor, gfx::Range>> range_colors_;
TestLocationBarModel* location_bar_model_;
// SetEmphasis() logs whether the base color of the text is emphasized. // SetEmphasis() logs whether the base color of the text is emphasized.
bool base_text_emphasis_; bool base_text_emphasis_;
...@@ -163,12 +170,14 @@ class TestingOmniboxView : public OmniboxViewViews { ...@@ -163,12 +170,14 @@ class TestingOmniboxView : public OmniboxViewViews {
}; };
TestingOmniboxView::TestingOmniboxView(OmniboxEditController* controller, TestingOmniboxView::TestingOmniboxView(OmniboxEditController* controller,
TestLocationBarModel* location_bar_model,
std::unique_ptr<OmniboxClient> client) std::unique_ptr<OmniboxClient> client)
: OmniboxViewViews(controller, : OmniboxViewViews(controller,
std::move(client), std::move(client),
false, false,
nullptr, nullptr,
gfx::FontList()) {} gfx::FontList()),
location_bar_model_(location_bar_model) {}
void TestingOmniboxView::ResetEmphasisTestState() { void TestingOmniboxView::ResetEmphasisTestState() {
base_text_emphasis_ = false; base_text_emphasis_ = false;
...@@ -278,6 +287,11 @@ void TestingOmniboxView::NavigateAndExpectElided( ...@@ -278,6 +287,11 @@ void TestingOmniboxView::NavigateAndExpectElided(
navigation.set_is_same_document(is_same_document); navigation.set_is_same_document(is_same_document);
navigation.set_url(url); navigation.set_url(url);
navigation.set_previous_url(previous_url); navigation.set_previous_url(previous_url);
DidStartNavigation(&navigation);
location_bar_model_->set_url(url);
location_bar_model_->set_url_for_display(base::ASCIIToUTF16(url.spec()));
model()->ResetDisplayTexts();
RevertAll();
DidFinishNavigation(&navigation); DidFinishNavigation(&navigation);
ExpectElidedToSimplifiedDomain(this, scheme, subdomain, hostname_and_scheme, ExpectElidedToSimplifiedDomain(this, scheme, subdomain, hostname_and_scheme,
path, should_elide_to_registrable_domain); path, should_elide_to_registrable_domain);
...@@ -292,6 +306,11 @@ void TestingOmniboxView::NavigateAndExpectUnelided( ...@@ -292,6 +306,11 @@ void TestingOmniboxView::NavigateAndExpectUnelided(
navigation.set_is_same_document(is_same_document); navigation.set_is_same_document(is_same_document);
navigation.set_url(GURL(url)); navigation.set_url(GURL(url));
navigation.set_previous_url(previous_url); navigation.set_previous_url(previous_url);
DidStartNavigation(&navigation);
location_bar_model_->set_url(GURL(url));
location_bar_model_->set_url_for_display(url);
model()->ResetDisplayTexts();
RevertAll();
DidFinishNavigation(&navigation); DidFinishNavigation(&navigation);
ExpectUnelidedFromSimplifiedDomain(this->GetRenderText(), ExpectUnelidedFromSimplifiedDomain(this->GetRenderText(),
gfx::Range(scheme.size(), url.size())); gfx::Range(scheme.size(), url.size()));
...@@ -606,7 +625,7 @@ void OmniboxViewViewsTest::SetUp() { ...@@ -606,7 +625,7 @@ void OmniboxViewViewsTest::SetUp() {
profile_.get(), profile_.get(),
base::BindRepeating(&AutocompleteClassifierFactory::BuildInstanceFor)); base::BindRepeating(&AutocompleteClassifierFactory::BuildInstanceFor));
auto omnibox_view = std::make_unique<TestingOmniboxView>( auto omnibox_view = std::make_unique<TestingOmniboxView>(
&omnibox_edit_controller_, &omnibox_edit_controller_, location_bar_model(),
std::make_unique<ChromeOmniboxClient>(&omnibox_edit_controller_, std::make_unique<ChromeOmniboxClient>(&omnibox_edit_controller_,
profile_.get())); profile_.get()));
test_api_ = std::make_unique<views::TextfieldTestApi>(omnibox_view.get()); test_api_ = std::make_unique<views::TextfieldTestApi>(omnibox_view.get());
...@@ -2039,6 +2058,104 @@ TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, ...@@ -2039,6 +2058,104 @@ TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
0, kSimplifiedDomainDisplayUrlSubdomainAndScheme.size()))); 0, kSimplifiedDomainDisplayUrlSubdomainAndScheme.size())));
} }
// Tests that the hide-on-interaction simplified domain field trial handles
// intermediate states during a navigation properly. This test simulates a
// browser-initiated navigation in which the URL updates before the navigation
// commits.
TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
BrowserInitiatedNavigation) {
SetUpSimplifiedDomainTest();
ASSERT_NO_FATAL_FAILURE(omnibox_view()->NavigateAndExpectUnelided(
kSimplifiedDomainDisplayUrl,
/*is_same_document=*/false, GURL(), kSimplifiedDomainDisplayUrlScheme));
// Before a user interaction triggers elision, a browser-initiated navigation
// should show the full URL (minus scheme and trivial subdomain) throughout
// the navigation.
// Set a longer URL to ensure that the full URL stays visible even if it's
// longer than the previous URL.
const base::string16 kUrlSuffix = base::ASCIIToUTF16("/foobar");
UpdateDisplayURL(kSimplifiedDomainDisplayUrl + kUrlSuffix);
ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
omnibox_view()->GetRenderText(),
gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
kSimplifiedDomainDisplayUrl.size() + kUrlSuffix.size())));
{
// In this test, we create MockNavigationHandles here instead of using the
// NavigateAndExpect* helpers because those helpers simulate
// renderer-initiated navigations, where the display URL isn't updated until
// just before DidFinishNavigation.
content::MockNavigationHandle navigation;
navigation.set_is_renderer_initiated(false);
omnibox_view()->DidStartNavigation(&navigation);
ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
omnibox_view()->GetRenderText(),
gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
kSimplifiedDomainDisplayUrl.size() + kUrlSuffix.size())));
omnibox_view()->DidFinishNavigation(&navigation);
ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
omnibox_view()->GetRenderText(),
gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
kSimplifiedDomainDisplayUrl.size() + kUrlSuffix.size())));
OmniboxViewViews::ElideAnimation* elide_animation =
omnibox_view()->GetElideAfterInteractionAnimationForTesting();
EXPECT_FALSE(elide_animation);
}
// Simulate a user interaction and advance all the way through the animation
// until the URL is elided to the simplified domain.
omnibox_view()->DidGetUserInteraction(blink::WebKeyboardEvent());
ASSERT_NO_FATAL_FAILURE(
omnibox_view()->StepSimplifiedDomainInteractionAnimation(
/*step_ms=*/1000));
ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
omnibox_view(), kSimplifiedDomainDisplayUrlScheme,
kSimplifiedDomainDisplayUrlSubdomain,
kSimplifiedDomainDisplayUrlHostnameAndScheme,
kSimplifiedDomainDisplayUrlPath + kUrlSuffix,
ShouldElideToRegistrableDomain()));
// Begin simulating a browser-initiated navigation, in which the URL is
// updated before DidStartNavigation() runs.
UpdateDisplayURL(kSimplifiedDomainDisplayUrl + kUrlSuffix);
// Ideally we would actually be unelided at this point, when a
// browser-initiated navigation has begun. But EmphasizeURLComponents()
// doesn't know which type of navigation is in progress, so this is the best
// we can do.
ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
omnibox_view(), kSimplifiedDomainDisplayUrlScheme,
kSimplifiedDomainDisplayUrlSubdomain,
kSimplifiedDomainDisplayUrlHostnameAndScheme,
kSimplifiedDomainDisplayUrlPath + kUrlSuffix,
ShouldElideToRegistrableDomain()));
{
content::MockNavigationHandle navigation;
navigation.set_is_renderer_initiated(false);
// Once the navigation starts and we know that it's a cross-document
// navigation, the URL should be unelided.
omnibox_view()->DidStartNavigation(&navigation);
ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
omnibox_view()->GetRenderText(),
gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
kSimplifiedDomainDisplayUrl.size() + kUrlSuffix.size())));
omnibox_view()->DidFinishNavigation(&navigation);
ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
omnibox_view()->GetRenderText(),
gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
kSimplifiedDomainDisplayUrl.size() + kUrlSuffix.size())));
OmniboxViewViews::ElideAnimation* elide_animation =
omnibox_view()->GetElideAfterInteractionAnimationForTesting();
EXPECT_FALSE(elide_animation);
}
}
// Tests that mouse clicks do not count as user interactions and do not elide // Tests that mouse clicks do not count as user interactions and do not elide
// the URL. // the URL.
TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, MouseClick) { TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, MouseClick) {
...@@ -2631,12 +2748,11 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) { ...@@ -2631,12 +2748,11 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) {
const base::string16 kUrlSuffix = base::ASCIIToUTF16("/foobar"); const base::string16 kUrlSuffix = base::ASCIIToUTF16("/foobar");
// On a same-document navigation before the URL has been simplified, the URL // On a same-document navigation before the URL has been simplified, the URL
// should remain unsimplified. // should remain unsimplified after the navigation finishes.
{ {
// Set a longer URL to ensure that the full URL stays visible even if it's // Set a longer URL to ensure that the full URL stays visible even if it's
// longer than the previous URL. // longer than the previous URL.
UpdateDisplayURL(kSimplifiedDomainDisplayUrl + kUrlSuffix);
omnibox_view()->NavigateAndExpectUnelided( omnibox_view()->NavigateAndExpectUnelided(
kSimplifiedDomainDisplayUrl + kUrlSuffix, /*is_same_document=*/true, kSimplifiedDomainDisplayUrl + kUrlSuffix, /*is_same_document=*/true,
GURL(), kSimplifiedDomainDisplayUrlScheme); GURL(), kSimplifiedDomainDisplayUrlScheme);
...@@ -2655,7 +2771,6 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) { ...@@ -2655,7 +2771,6 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) {
// On a cross-document main-frame navigation, the unsimplified URL should // On a cross-document main-frame navigation, the unsimplified URL should
// remain visible. // remain visible.
{ {
UpdateDisplayURL(kSimplifiedDomainDisplayUrl);
omnibox_view()->NavigateAndExpectUnelided( omnibox_view()->NavigateAndExpectUnelided(
kSimplifiedDomainDisplayUrl, /*is_same_document=*/false, GURL(), kSimplifiedDomainDisplayUrl, /*is_same_document=*/false, GURL(),
kSimplifiedDomainDisplayUrlScheme); kSimplifiedDomainDisplayUrlScheme);
...@@ -2684,7 +2799,8 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) { ...@@ -2684,7 +2799,8 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) {
/*is_same_document=*/true, GURL(kSimplifiedDomainDisplayUrl), /*is_same_document=*/true, GURL(kSimplifiedDomainDisplayUrl),
kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain, kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain,
kSimplifiedDomainDisplayUrlHostnameAndScheme, kSimplifiedDomainDisplayUrlHostnameAndScheme,
kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain()); kSimplifiedDomainDisplayUrlPath + base::ASCIIToUTF16("#foobar"),
ShouldElideToRegistrableDomain());
OmniboxViewViews::ElideAnimation* elide_animation = OmniboxViewViews::ElideAnimation* elide_animation =
omnibox_view()->GetElideAfterInteractionAnimationForTesting(); omnibox_view()->GetElideAfterInteractionAnimationForTesting();
ASSERT_TRUE(elide_animation); ASSERT_TRUE(elide_animation);
...@@ -2694,7 +2810,6 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) { ...@@ -2694,7 +2810,6 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) {
// On same-document main-frame non-fragment navigation, the URL shouldn't // On same-document main-frame non-fragment navigation, the URL shouldn't
// remain elided to the simplified domain. // remain elided to the simplified domain.
{ {
UpdateDisplayURL(kSimplifiedDomainDisplayUrl + kUrlSuffix);
omnibox_view()->NavigateAndExpectUnelided( omnibox_view()->NavigateAndExpectUnelided(
kSimplifiedDomainDisplayUrl + kUrlSuffix, /*is_same_document=*/true, kSimplifiedDomainDisplayUrl + kUrlSuffix, /*is_same_document=*/true,
GURL(kSimplifiedDomainDisplayUrl), kSimplifiedDomainDisplayUrlScheme); GURL(kSimplifiedDomainDisplayUrl), kSimplifiedDomainDisplayUrlScheme);
...@@ -2705,7 +2820,8 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) { ...@@ -2705,7 +2820,8 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SameDocNavigations) {
} }
// Tests that in the hide-on-interaction field trial, a same-document navigation // Tests that in the hide-on-interaction field trial, a same-document navigation
// does not interfere with an animation that is currently running. // cancels a currently-running animation and goes straight to the end state
// (elided to the simplified domain).
TEST_P(OmniboxViewViewsHideOnInteractionTest, TEST_P(OmniboxViewViewsHideOnInteractionTest,
SameDocNavigationDuringAnimation) { SameDocNavigationDuringAnimation) {
SetUpSimplifiedDomainTest(); SetUpSimplifiedDomainTest();
...@@ -2723,10 +2839,10 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, ...@@ -2723,10 +2839,10 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest,
// Advance the clock by 1ms until the full URL is no longer showing, but we // Advance the clock by 1ms until the full URL is no longer showing, but we
// haven't finished eliding to the simplified domain yet. After a // haven't finished eliding to the simplified domain yet. After a
// same-document navigation, we check that the URL is still in the same state // same-document navigation, we check that the URL has gone straight to the
// (midway through elision) and that the animation is still running // end state. In other words, a same-document navigation will cancel a
// undisturbed. In other words, a same-document navigation shouldn't change // currently-running animation but should end up where the animation was
// anything when an animation is in progress. // targeting.
bool is_midway_through_elision = false; bool is_midway_through_elision = false;
uint32_t step_ms = 1; uint32_t step_ms = 1;
while (!is_midway_through_elision) { while (!is_midway_through_elision) {
...@@ -2735,26 +2851,18 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, ...@@ -2735,26 +2851,18 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest,
is_midway_through_elision = IsPartlyThroughSimplifiedDomainElision( is_midway_through_elision = IsPartlyThroughSimplifiedDomainElision(
render_text, kSimplifiedDomainDisplayUrl, path_bounds); render_text, kSimplifiedDomainDisplayUrl, path_bounds);
} }
double animation_value = omnibox_view()
->GetElideAfterInteractionAnimationForTesting()
->GetAnimationForTesting()
->GetCurrentValue();
omnibox_view()->NavigateAndExpectUnelided( omnibox_view()->NavigateAndExpectElided(
kSimplifiedDomainDisplayUrl, /*is_same_document=*/true, GURL(kSimplifiedDomainDisplayUrl),
GURL(kSimplifiedDomainDisplayUrl), kSimplifiedDomainDisplayUrlScheme); /*is_same_document=*/true, GURL(kSimplifiedDomainDisplayUrl),
kSimplifiedDomainDisplayUrlScheme, kSimplifiedDomainDisplayUrlSubdomain,
kSimplifiedDomainDisplayUrlHostnameAndScheme,
kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain());
OmniboxViewViews::ElideAnimation* elide_animation = OmniboxViewViews::ElideAnimation* elide_animation =
omnibox_view()->GetElideAfterInteractionAnimationForTesting(); omnibox_view()->GetElideAfterInteractionAnimationForTesting();
ASSERT_TRUE(elide_animation); ASSERT_TRUE(elide_animation);
EXPECT_TRUE(elide_animation->IsAnimating()); EXPECT_FALSE(elide_animation->IsAnimating());
EXPECT_EQ(animation_value,
elide_animation->GetAnimationForTesting()->GetCurrentValue());
// The current display text should reflect that the animation in progress: the
// full display URL shouldn't be still visible, but we haven't necessarily
// reached the end state (just the simplified domain visible) yet.
EXPECT_TRUE(IsPartlyThroughSimplifiedDomainElision(
render_text, kSimplifiedDomainDisplayUrl, path_bounds));
} }
// Tests that gradient mask is set correctly. // Tests that gradient mask is set correctly.
...@@ -2933,6 +3041,12 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SubframeNavigations) { ...@@ -2933,6 +3041,12 @@ TEST_P(OmniboxViewViewsHideOnInteractionTest, SubframeNavigations) {
content::RenderFrameHostTester::For(web_contents->GetMainFrame()) content::RenderFrameHostTester::For(web_contents->GetMainFrame())
->AppendChild("subframe"); ->AppendChild("subframe");
navigation.set_render_frame_host(subframe); navigation.set_render_frame_host(subframe);
omnibox_view()->DidStartNavigation(&navigation);
ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
omnibox_view(), kSimplifiedDomainDisplayUrlScheme,
kSimplifiedDomainDisplayUrlSubdomain,
kSimplifiedDomainDisplayUrlHostnameAndScheme,
kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain()));
omnibox_view()->DidFinishNavigation(&navigation); omnibox_view()->DidFinishNavigation(&navigation);
ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain( ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
omnibox_view(), kSimplifiedDomainDisplayUrlScheme, omnibox_view(), kSimplifiedDomainDisplayUrlScheme,
......
...@@ -39,7 +39,8 @@ class MockNavigationHandle : public NavigationHandle { ...@@ -39,7 +39,8 @@ class MockNavigationHandle : public NavigationHandle {
return render_frame_host_ ? !render_frame_host_->GetParent() : true; return render_frame_host_ ? !render_frame_host_->GetParent() : true;
} }
MOCK_METHOD0(IsParentMainFrame, bool()); MOCK_METHOD0(IsParentMainFrame, bool());
bool IsRendererInitiated() override { return true; } // By default, MockNavigationHandles are renderer-initiated navigations.
bool IsRendererInitiated() override { return is_renderer_initiated_; }
MOCK_METHOD0(GetFrameTreeNodeId, int()); MOCK_METHOD0(GetFrameTreeNodeId, int());
MOCK_METHOD0(GetPreviousRenderFrameHostId, GlobalFrameRoutingId()); MOCK_METHOD0(GetPreviousRenderFrameHostId, GlobalFrameRoutingId());
bool IsServedFromBackForwardCache() override { return false; } bool IsServedFromBackForwardCache() override { return false; }
...@@ -152,6 +153,9 @@ class MockNavigationHandle : public NavigationHandle { ...@@ -152,6 +153,9 @@ class MockNavigationHandle : public NavigationHandle {
void set_is_same_document(bool is_same_document) { void set_is_same_document(bool is_same_document) {
is_same_document_ = is_same_document; is_same_document_ = is_same_document;
} }
void set_is_renderer_initiated(bool is_renderer_initiated) {
is_renderer_initiated_ = is_renderer_initiated;
}
void set_redirect_chain(const std::vector<GURL>& redirect_chain) { void set_redirect_chain(const std::vector<GURL>& redirect_chain) {
redirect_chain_ = redirect_chain; redirect_chain_ = redirect_chain;
} }
...@@ -201,6 +205,7 @@ class MockNavigationHandle : public NavigationHandle { ...@@ -201,6 +205,7 @@ class MockNavigationHandle : public NavigationHandle {
net::Error net_error_code_ = net::OK; net::Error net_error_code_ = net::OK;
RenderFrameHost* render_frame_host_ = nullptr; RenderFrameHost* render_frame_host_ = nullptr;
bool is_same_document_ = false; bool is_same_document_ = false;
bool is_renderer_initiated_ = true;
std::vector<GURL> redirect_chain_; std::vector<GURL> redirect_chain_;
bool has_committed_ = false; bool has_committed_ = false;
bool is_error_page_ = false; bool is_error_page_ = false;
......
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