Commit 732a75d5 authored by Peter Boström's avatar Peter Boström Committed by Commit Bot

Loading bar for WebUI-tab-strip mode

This is used in place of the tab-icon loading indicator as the favicon is
not visible when the tab strip is hidden.

Bug: chromium:1027377
Change-Id: I40c6e6b38023bfae4b5e9993bd9c9f4c8b2bbb3e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1959340
Commit-Queue: Peter Boström <pbos@chromium.org>
Reviewed-by: default avatarTaylor Bergquist <tbergquist@chromium.org>
Cr-Commit-Position: refs/heads/master@{#727837}
parent 479abc3c
......@@ -2887,6 +2887,8 @@ jumbo_static_library("ui") {
"views/frame/toolbar_button_provider.h",
"views/frame/top_container_background.cc",
"views/frame/top_container_background.h",
"views/frame/top_container_loading_bar.cc",
"views/frame/top_container_loading_bar.h",
"views/frame/top_container_view.cc",
"views/frame/top_container_view.h",
"views/frame/top_controls_slide_controller.h",
......
......@@ -87,6 +87,7 @@
#include "chrome/browser/ui/views/frame/contents_layout_manager.h"
#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
#include "chrome/browser/ui/views/frame/tab_strip_region_view.h"
#include "chrome/browser/ui/views/frame/top_container_loading_bar.h"
#include "chrome/browser/ui/views/frame/top_container_view.h"
#include "chrome/browser/ui/views/frame/web_contents_close_handler.h"
#include "chrome/browser/ui/views/frame/web_footer_experiment_view.h"
......@@ -898,6 +899,8 @@ void BrowserView::OnActiveTabChanged(content::WebContents* old_contents,
// read out to screen readers, even if focus doesn't actually change.
GetWidget()->GetFocusManager()->ClearFocus();
}
if (loading_bar_)
loading_bar_->SetWebContents(nullptr);
contents_web_view_->SetWebContents(nullptr);
devtools_web_view_->SetWebContents(nullptr);
}
......@@ -939,6 +942,8 @@ void BrowserView::OnActiveTabChanged(content::WebContents* old_contents,
}
web_contents_close_handler_->ActiveTabChanged();
if (loading_bar_)
loading_bar_->SetWebContents(new_contents);
contents_web_view_->SetWebContents(new_contents);
SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(new_contents);
if (sad_tab_helper)
......@@ -968,6 +973,8 @@ void BrowserView::OnTabDetached(content::WebContents* contents,
// freed. This is because the focus manager performs some operations
// on the selected WebContents when it is removed.
web_contents_close_handler_->ActiveTabChanged();
if (loading_bar_)
loading_bar_->SetWebContents(nullptr);
contents_web_view_->SetWebContents(nullptr);
infobar_container_->ChangeInfoBarManager(nullptr);
app_banner_manager_observer_.RemoveAll();
......@@ -1777,6 +1784,9 @@ void BrowserView::OnTabStripModelChanged(
if (selection.selection_changed())
toolbar_->InvalidateLayout();
if (loading_bar_)
loading_bar_->SetWebContents(GetActiveWebContents());
if (change.type() != TabStripModelChange::kInserted)
return;
......@@ -2697,13 +2707,21 @@ void BrowserView::MaybeInitializeWebUITabStrip() {
webui_tab_strip_ = top_container_->AddChildView(
std::make_unique<WebUITabStripContainerView>(browser_.get(),
contents_container_));
loading_bar_ = top_container_->AddChildView(
std::make_unique<TopContainerLoadingBar>());
loading_bar_->SetWebContents(GetActiveWebContents());
}
} else if (webui_tab_strip_) {
top_container_->RemoveChildView(webui_tab_strip_);
delete webui_tab_strip_;
webui_tab_strip_ = nullptr;
top_container_->RemoveChildView(loading_bar_);
delete loading_bar_;
loading_bar_ = nullptr;
}
GetBrowserViewLayout()->set_webui_tab_strip(webui_tab_strip_);
GetBrowserViewLayout()->set_loading_bar(loading_bar_);
if (toolbar_)
toolbar_->UpdateForWebUITabStrip();
#endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
......
......@@ -68,6 +68,7 @@ class TabStrip;
class TabStripRegionView;
class ToolbarButtonProvider;
class ToolbarView;
class TopContainerLoadingBar;
class TopContainerView;
class TopControlsSlideControllerTest;
class WebContentsCloseHandler;
......@@ -753,6 +754,9 @@ class BrowserView : public BrowserWindow,
// Separator between top container and contents.
views::View* contents_separator_ = nullptr;
// Loading bar (part of top container for / WebUI tab strip).
TopContainerLoadingBar* loading_bar_ = nullptr;
// The do-nothing view which controls the z-order of the find bar widget
// relative to views which paint into layers and views with an associated
// NativeView.
......
......@@ -396,9 +396,18 @@ int BrowserViewLayout::LayoutBookmarkAndInfoBars(int top, int browser_view_y) {
contents_separator_->SetBounds(vertical_layout_rect_.x(), top,
vertical_layout_rect_.width(),
separator_height);
if (loading_bar_) {
SetViewVisibility(loading_bar_, true);
loading_bar_->SetBounds(vertical_layout_rect_.x(), top - 2,
vertical_layout_rect_.width(),
separator_height + 2);
top_container_->ReorderChildView(loading_bar_, -1);
}
top += separator_height;
} else {
SetViewVisibility(contents_separator_, false);
if (loading_bar_)
SetViewVisibility(loading_bar_, false);
}
return LayoutInfoBar(top);
......
......@@ -67,6 +67,7 @@ class BrowserViewLayout : public views::LayoutManager {
void set_webui_tab_strip(views::View* webui_tab_strip) {
webui_tab_strip_ = webui_tab_strip;
}
void set_loading_bar(views::View* loading_bar) { loading_bar_ = loading_bar; }
void set_bookmark_bar(BookmarkBarView* bookmark_bar) {
bookmark_bar_ = bookmark_bar;
}
......@@ -154,6 +155,7 @@ class BrowserViewLayout : public views::LayoutManager {
views::View* const contents_separator_;
views::View* webui_tab_strip_ = nullptr;
views::View* loading_bar_ = nullptr;
TabStrip* tab_strip_ = nullptr;
BookmarkBarView* bookmark_bar_ = nullptr;
views::View* download_shelf_ = nullptr;
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/frame/top_container_loading_bar.h"
#include "chrome/browser/favicon/favicon_utils.h"
#include "chrome/browser/ui/tab_ui_helper.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
LoadingBarView::LoadingBarView() {
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
animation_.SetDuration(base::TimeDelta::FromMilliseconds(300));
}
double LoadingBarView::GetDisplayedLoadingProgress() const {
return gfx::Tween::DoubleValueBetween(
gfx::Tween::CalculateValue(gfx::Tween::EASE_OUT,
animation_.GetCurrentValue()),
start_loading_progress_, target_loading_progress_);
}
void LoadingBarView::OnThemeChanged() {
SchedulePaint();
}
void LoadingBarView::AddedToWidget() {
SchedulePaint();
}
void LoadingBarView::HideImmediately() {
is_shown_when_not_animating_ = false;
start_loading_progress_ = 0.0;
target_loading_progress_ = 0.0;
animation_.Stop();
// If we were previously drawn we have to redraw as invisible.
SchedulePaint();
}
void LoadingBarView::Show(double loading_progress) {
is_shown_when_not_animating_ = true;
start_loading_progress_ = loading_progress;
target_loading_progress_ = loading_progress;
animation_.Stop();
SchedulePaint();
}
void LoadingBarView::FinishLoading() {
if (!is_shown_when_not_animating_)
return;
SetLoadingProgress(1.0);
is_shown_when_not_animating_ = false;
}
void LoadingBarView::SetLoadingProgress(double loading_progress) {
if (loading_progress <= target_loading_progress_)
return;
start_loading_progress_ = GetDisplayedLoadingProgress();
target_loading_progress_ = loading_progress;
animation_.SetCurrentValue(0.0);
animation_.Start();
}
void LoadingBarView::OnPaint(gfx::Canvas* canvas) {
if (is_shown_when_not_animating_ || animation_.is_animating()) {
canvas->FillRect(GetLocalBounds(), gfx::kGoogleBlue100);
gfx::Rect progress_bounds(GetLocalBounds());
progress_bounds.set_width(gfx::Tween::IntValueBetween(
GetDisplayedLoadingProgress(), 0, progress_bounds.width()));
canvas->FillRect(progress_bounds, gfx::kGoogleBlue500);
}
}
void LoadingBarView::AnimationEnded(const gfx::Animation* animation) {
SchedulePaint();
}
void LoadingBarView::AnimationProgressed(const gfx::Animation* animation) {
SchedulePaint();
}
TopContainerLoadingBar::TopContainerLoadingBar() = default;
void TopContainerLoadingBar::SetWebContents(
content::WebContents* web_contents) {
Observe(web_contents);
if (!web_contents) {
network_state_ = TabNetworkState::kNone;
HideImmediately();
return;
}
// TODO(pbos): Consider storing one loading bar per tab and have it run (and
// observing) in the background. This would remove the need to reset
// loading-bar state during tab transitions as we'd just swap in the visible
// object. Currently Show(GetLoadingProgress()) can decrease from what was
// previously displayed in that tab.
// Reset network state to update from a clean slate.
network_state_ = TabNetworkState::kNone;
UpdateLoadingProgress();
}
void TopContainerLoadingBar::UpdateLoadingProgress() {
DCHECK(web_contents());
if (!favicon::ShouldDisplayFavicon(web_contents())) {
HideImmediately();
return;
}
TabUIHelper* const tab_ui_helper =
TabUIHelper::FromWebContents(web_contents());
if (tab_ui_helper->ShouldHideThrobber()) {
HideImmediately();
return;
}
const TabNetworkState old_network_state = network_state_;
network_state_ = TabNetworkStateForWebContents(web_contents());
if (old_network_state != network_state_) {
if (network_state_ == TabNetworkState::kWaiting ||
network_state_ == TabNetworkState::kLoading) {
// Reset loading state when we go to waiting or loading.
Show(GetLoadingProgress());
}
}
switch (network_state_) {
case TabNetworkState::kLoading:
SetLoadingProgress(GetLoadingProgress());
break;
case TabNetworkState::kError:
// TODO(pbos): Add a better error indicator (fade-out red?).
HideImmediately();
break;
case TabNetworkState::kWaiting:
break;
case TabNetworkState::kNone:
FinishLoading();
break;
}
}
double TopContainerLoadingBar::GetLoadingProgress() {
DCHECK(web_contents());
return std::min(web_contents()->GetLoadProgress(), 0.9);
}
void TopContainerLoadingBar::LoadProgressChanged(double progress) {
UpdateLoadingProgress();
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_TOP_CONTAINER_LOADING_BAR_H_
#define CHROME_BROWSER_UI_VIEWS_FRAME_TOP_CONTAINER_LOADING_BAR_H_
#include "chrome/browser/ui/tabs/tab_network_state.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/views/view.h"
class LoadingBarView : public views::View, public gfx::AnimationDelegate {
public:
LoadingBarView();
LoadingBarView(const LoadingBarView&) = delete;
LoadingBarView& operator=(const LoadingBarView&) = delete;
void HideImmediately();
void Show(double loading_progress);
void FinishLoading();
void SetLoadingProgress(double loading_progress);
private:
double GetDisplayedLoadingProgress() const;
// views::View:
void OnThemeChanged() override;
void AddedToWidget() override;
void OnPaint(gfx::Canvas* canvas) override;
// gfx::AnimationDelegate:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
gfx::LinearAnimation animation_{this};
bool is_shown_when_not_animating_ = false;
double start_loading_progress_ = 0.0;
double target_loading_progress_ = 0.0;
};
class TopContainerLoadingBar : public LoadingBarView,
public content::WebContentsObserver {
public:
TopContainerLoadingBar();
TopContainerLoadingBar(const TopContainerLoadingBar&) = delete;
TopContainerLoadingBar& operator=(const TopContainerLoadingBar&) = delete;
void SetWebContents(content::WebContents* web_contents);
private:
void UpdateLoadingProgress();
double GetLoadingProgress();
// content::WebContentsObserver:
void LoadProgressChanged(double progress) override;
TabNetworkState network_state_ = TabNetworkState::kNone;
};
#endif // CHROME_BROWSER_UI_VIEWS_FRAME_TOP_CONTAINER_LOADING_BAR_H_
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