Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: chrome/browser/ui/views/tabs/tab.cc

Issue 2217273002: Desaturate the favicon shown in the tab when a network error is encountered (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added change for pinned tabs, reused NetworkState enum for net errors Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/tabs/tab.h" 5 #include "chrome/browser/ui/views/tabs/tab.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <limits> 8 #include <limits>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 13 matching lines...) Expand all
24 #include "chrome/browser/ui/views/touch_uma/touch_uma.h" 24 #include "chrome/browser/ui/views/touch_uma/touch_uma.h"
25 #include "chrome/common/chrome_switches.h" 25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/url_constants.h" 26 #include "chrome/common/url_constants.h"
27 #include "chrome/grit/generated_resources.h" 27 #include "chrome/grit/generated_resources.h"
28 #include "content/public/browser/user_metrics.h" 28 #include "content/public/browser/user_metrics.h"
29 #include "content/public/common/url_constants.h" 29 #include "content/public/common/url_constants.h"
30 #include "grit/components_scaled_resources.h" 30 #include "grit/components_scaled_resources.h"
31 #include "grit/components_strings.h" 31 #include "grit/components_strings.h"
32 #include "grit/theme_resources.h" 32 #include "grit/theme_resources.h"
33 #include "third_party/skia/include/effects/SkGradientShader.h" 33 #include "third_party/skia/include/effects/SkGradientShader.h"
34 #include "third_party/skia/include/effects/SkLumaColorFilter.h"
34 #include "third_party/skia/include/pathops/SkPathOps.h" 35 #include "third_party/skia/include/pathops/SkPathOps.h"
35 #include "ui/accessibility/ax_view_state.h" 36 #include "ui/accessibility/ax_view_state.h"
36 #include "ui/base/l10n/l10n_util.h" 37 #include "ui/base/l10n/l10n_util.h"
37 #include "ui/base/material_design/material_design_controller.h" 38 #include "ui/base/material_design/material_design_controller.h"
38 #include "ui/base/models/list_selection_model.h" 39 #include "ui/base/models/list_selection_model.h"
39 #include "ui/base/resource/resource_bundle.h" 40 #include "ui/base/resource/resource_bundle.h"
40 #include "ui/base/theme_provider.h" 41 #include "ui/base/theme_provider.h"
41 #include "ui/gfx/animation/animation_container.h" 42 #include "ui/gfx/animation/animation_container.h"
42 #include "ui/gfx/animation/throb_animation.h" 43 #include "ui/gfx/animation/throb_animation.h"
43 #include "ui/gfx/canvas.h" 44 #include "ui/gfx/canvas.h"
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 canvas->DrawImageInt(*stroke_images->image_l, 0, 0); 572 canvas->DrawImageInt(*stroke_images->image_l, 0, 0);
572 canvas->TileImageInt( 573 canvas->TileImageInt(
573 *stroke_images->image_c, stroke_images->l_width, 0, 574 *stroke_images->image_c, stroke_images->l_width, 0,
574 rect.width() - stroke_images->l_width - stroke_images->r_width, 575 rect.width() - stroke_images->l_width - stroke_images->r_width,
575 rect.height()); 576 rect.height());
576 canvas->DrawImageInt(*stroke_images->image_r, 577 canvas->DrawImageInt(*stroke_images->image_r,
577 rect.width() - stroke_images->r_width, 0); 578 rect.width() - stroke_images->r_width, 0);
578 } 579 }
579 } 580 }
580 581
582 // Destaurates the favicon. Should only be used for when a tab encounters a
583 // network error state.
584 void PaintDesaturatedFavIcon(gfx::Canvas* canvas,
585 gfx::ImageSkia& favicon,
586 gfx::Rect bounds) {
sky 2016/08/12 15:29:25 const gfx::Rect&
edwardjung 2016/08/12 19:29:25 Done.
587 SkPaint paint;
588 paint.setStyle(SkPaint::kFill_Style);
589 paint.setAntiAlias(true);
590 SkScalar desaturate[20] = {0.3086f, 0.6094f, 0.0820f, 0.0f, 0.0f,
sky 2016/08/12 15:29:25 These constants look rather magical. Are they defi
edwardjung 2016/08/12 19:29:25 I've switched to use CreateHSLShiftedImage which h
591 0.3086f, 0.6094f, 0.0820f, 0.0f, 0.0f,
592 0.3086f, 0.6094f, 0.0820f, 0.0f, 0.0f,
593 0.0f, 0.0f, 0.0f, 0.8f, 0.0f};
594 paint.setColorFilter(SkColorFilter::MakeMatrixFilterRowMajor255(desaturate));
595 if (!bounds.IsEmpty()) {
596 canvas->DrawImageInt(favicon, 0, 0, bounds.width(), bounds.height(),
597 bounds.x(), bounds.y(), bounds.width(),
598 bounds.height(), false, paint);
599 } else {
600 canvas->DrawImageInt(favicon, 0, 0, paint);
601 }
602 }
603
581 } // namespace 604 } // namespace
582 605
583 //////////////////////////////////////////////////////////////////////////////// 606 ////////////////////////////////////////////////////////////////////////////////
584 // FaviconCrashAnimation 607 // FaviconCrashAnimation
585 // 608 //
586 // A custom animation subclass to manage the favicon crash animation. 609 // A custom animation subclass to manage the favicon crash animation.
587 class Tab::FaviconCrashAnimation : public gfx::LinearAnimation, 610 class Tab::FaviconCrashAnimation : public gfx::LinearAnimation,
588 public gfx::AnimationDelegate { 611 public gfx::AnimationDelegate {
589 public: 612 public:
590 explicit FaviconCrashAnimation(Tab* target) 613 explicit FaviconCrashAnimation(Tab* target)
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 loading_start_time_ = base::TimeTicks(); 775 loading_start_time_ = base::TimeTicks();
753 waiting_state_ = gfx::ThrobberWaitingState(); 776 waiting_state_ = gfx::ThrobberWaitingState();
754 } 777 }
755 778
756 bool Tab::ThrobberView::CanProcessEventsWithinSubtree() const { 779 bool Tab::ThrobberView::CanProcessEventsWithinSubtree() const {
757 return false; 780 return false;
758 } 781 }
759 782
760 void Tab::ThrobberView::OnPaint(gfx::Canvas* canvas) { 783 void Tab::ThrobberView::OnPaint(gfx::Canvas* canvas) {
761 const TabRendererData::NetworkState state = owner_->data().network_state; 784 const TabRendererData::NetworkState state = owner_->data().network_state;
762 if (state == TabRendererData::NETWORK_STATE_NONE) 785 if (state == TabRendererData::NETWORK_STATE_NONE ||
786 state == TabRendererData::NETWORK_STATE_ERROR)
763 return; 787 return;
764 788
765 const ui::ThemeProvider* tp = GetThemeProvider(); 789 const ui::ThemeProvider* tp = GetThemeProvider();
766 const gfx::Rect bounds = GetLocalBounds(); 790 const gfx::Rect bounds = GetLocalBounds();
767 if (state == TabRendererData::NETWORK_STATE_WAITING) { 791 if (state == TabRendererData::NETWORK_STATE_WAITING) {
768 if (waiting_start_time_ == base::TimeTicks()) 792 if (waiting_start_time_ == base::TimeTicks())
769 waiting_start_time_ = base::TimeTicks::Now(); 793 waiting_start_time_ = base::TimeTicks::Now();
770 794
771 waiting_state_.elapsed_time = base::TimeTicks::Now() - waiting_start_time_; 795 waiting_state_.elapsed_time = base::TimeTicks::Now() - waiting_start_time_;
772 gfx::PaintThrobberWaiting( 796 gfx::PaintThrobberWaiting(
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 void Tab::AlertStateChanged() { 914 void Tab::AlertStateChanged() {
891 Layout(); 915 Layout();
892 } 916 }
893 917
894 bool Tab::IsSelected() const { 918 bool Tab::IsSelected() const {
895 return controller_->IsTabSelected(this); 919 return controller_->IsTabSelected(this);
896 } 920 }
897 921
898 void Tab::SetData(const TabRendererData& data) { 922 void Tab::SetData(const TabRendererData& data) {
899 DCHECK(GetWidget()); 923 DCHECK(GetWidget());
900
901 if (data_.Equals(data)) 924 if (data_.Equals(data))
902 return; 925 return;
903 926
904 TabRendererData old(data_); 927 TabRendererData old(data_);
905 UpdateLoadingAnimation(data.network_state); 928 UpdateLoadingAnimation(data.network_state);
906 data_ = data; 929 data_ = data;
907 930
908 base::string16 title = data_.title; 931 base::string16 title = data_.title;
909 if (title.empty()) { 932 if (title.empty()) {
910 title = data_.loading ? 933 title = data_.loading ?
(...skipping 21 matching lines...) Expand all
932 showing_pinned_tab_title_changed_indicator_ = false; 955 showing_pinned_tab_title_changed_indicator_ = false;
933 956
934 DataChanged(old); 957 DataChanged(old);
935 958
936 Layout(); 959 Layout();
937 SchedulePaint(); 960 SchedulePaint();
938 } 961 }
939 962
940 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { 963 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) {
941 if (state == data_.network_state && 964 if (state == data_.network_state &&
942 state == TabRendererData::NETWORK_STATE_NONE) { 965 (state == TabRendererData::NETWORK_STATE_NONE ||
966 state == TabRendererData::NETWORK_STATE_ERROR)) {
943 // If the network state is none and hasn't changed, do nothing. Otherwise we 967 // If the network state is none and hasn't changed, do nothing. Otherwise we
sky 2016/08/12 15:29:25 update comment
edwardjung 2016/08/12 19:29:25 Done.
944 // need to advance the animation frame. 968 // need to advance the animation frame.
945 return; 969 return;
946 } 970 }
947 971
948 data_.network_state = state; 972 data_.network_state = state;
949 AdvanceLoadingAnimation(); 973 AdvanceLoadingAnimation();
950 } 974 }
951 975
952 void Tab::StartPulse() { 976 void Tab::StartPulse() {
953 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); 977 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 const gfx::Rect& favicon_draw_bounds) { 1611 const gfx::Rect& favicon_draw_bounds) {
1588 // The pinned tab title changed indicator consists of two parts: 1612 // The pinned tab title changed indicator consists of two parts:
1589 // . a clear (totally transparent) part over the bottom right (or left in rtl) 1613 // . a clear (totally transparent) part over the bottom right (or left in rtl)
1590 // of the favicon. This is done by drawing the favicon to a canvas, then 1614 // of the favicon. This is done by drawing the favicon to a canvas, then
1591 // drawing the clear part on top of the favicon. 1615 // drawing the clear part on top of the favicon.
1592 // . a circle in the bottom right (or left in rtl) of the favicon. 1616 // . a circle in the bottom right (or left in rtl) of the favicon.
1593 if (!favicon_.isNull()) { 1617 if (!favicon_.isNull()) {
1594 const float kIndicatorCropRadius = 4.5; 1618 const float kIndicatorCropRadius = 4.5;
1595 gfx::Canvas icon_canvas(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize), 1619 gfx::Canvas icon_canvas(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize),
1596 canvas->image_scale(), false); 1620 canvas->image_scale(), false);
1597 icon_canvas.DrawImageInt(favicon_, 0, 0); 1621
1622 if (data().network_state == TabRendererData::NETWORK_STATE_ERROR)
1623 PaintDesaturatedFavIcon(&icon_canvas, favicon_, gfx::Rect());
1624 else
1625 icon_canvas.DrawImageInt(favicon_, 0, 0);
1626
1598 SkPaint clear_paint; 1627 SkPaint clear_paint;
1599 clear_paint.setAntiAlias(true); 1628 clear_paint.setAntiAlias(true);
1600 clear_paint.setXfermodeMode(SkXfermode::kClear_Mode); 1629 clear_paint.setXfermodeMode(SkXfermode::kClear_Mode);
1601 const int circle_x = base::i18n::IsRTL() ? 0 : gfx::kFaviconSize; 1630 const int circle_x = base::i18n::IsRTL() ? 0 : gfx::kFaviconSize;
1602 icon_canvas.DrawCircle(gfx::PointF(circle_x, gfx::kFaviconSize), 1631 icon_canvas.DrawCircle(gfx::PointF(circle_x, gfx::kFaviconSize),
1603 kIndicatorCropRadius, clear_paint); 1632 kIndicatorCropRadius, clear_paint);
1604 canvas->DrawImageInt(gfx::ImageSkia(icon_canvas.ExtractImageRep()), 0, 0, 1633 canvas->DrawImageInt(gfx::ImageSkia(icon_canvas.ExtractImageRep()), 0, 0,
1605 favicon_draw_bounds.width(), 1634 favicon_draw_bounds.width(),
1606 favicon_draw_bounds.height(), favicon_draw_bounds.x(), 1635 favicon_draw_bounds.height(), favicon_draw_bounds.x(),
1607 favicon_draw_bounds.y(), favicon_draw_bounds.width(), 1636 favicon_draw_bounds.y(), favicon_draw_bounds.width(),
(...skipping 16 matching lines...) Expand all
1624 1653
1625 void Tab::PaintIcon(gfx::Canvas* canvas) { 1654 void Tab::PaintIcon(gfx::Canvas* canvas) {
1626 gfx::Rect bounds = favicon_bounds_; 1655 gfx::Rect bounds = favicon_bounds_;
1627 bounds.set_x(GetMirroredXForRect(bounds)); 1656 bounds.set_x(GetMirroredXForRect(bounds));
1628 bounds.Offset(0, favicon_hiding_offset_); 1657 bounds.Offset(0, favicon_hiding_offset_);
1629 bounds.Intersect(GetContentsBounds()); 1658 bounds.Intersect(GetContentsBounds());
1630 if (bounds.IsEmpty()) 1659 if (bounds.IsEmpty())
1631 return; 1660 return;
1632 1661
1633 // Throbber will do its own painting. 1662 // Throbber will do its own painting.
1634 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) 1663 if (data().network_state != TabRendererData::NETWORK_STATE_NONE &&
1664 data().network_state != TabRendererData::NETWORK_STATE_ERROR)
1635 return; 1665 return;
1636 1666
1637 // Ensure that |favicon_| is created. 1667 // Ensure that |favicon_| is created.
1638 if (favicon_.isNull()) { 1668 if (favicon_.isNull()) {
1639 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); 1669 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
1640 favicon_ = should_display_crashed_favicon_ 1670 favicon_ = should_display_crashed_favicon_
1641 ? *rb->GetImageSkiaNamed(IDR_CRASH_SAD_FAVICON) 1671 ? *rb->GetImageSkiaNamed(IDR_CRASH_SAD_FAVICON)
1642 : data().favicon; 1672 : data().favicon;
1643 // Themify the icon if it's a chrome:// page or if it's the sadtab favicon. 1673 // Themify the icon if it's a chrome:// page or if it's the sadtab favicon.
1644 // This ensures chrome:// pages are visible over the tab background. This is 1674 // This ensures chrome:// pages are visible over the tab background. This is
1645 // similar to code in the bookmarks bar. 1675 // similar to code in the bookmarks bar.
1646 if (!favicon_.isNull() && 1676 if (!favicon_.isNull() &&
1647 (should_display_crashed_favicon_ || 1677 (should_display_crashed_favicon_ ||
1648 favicon_.BackedBySameObjectAs( 1678 favicon_.BackedBySameObjectAs(
1649 *rb->GetImageSkiaNamed(IDR_DEFAULT_FAVICON)) || 1679 *rb->GetImageSkiaNamed(IDR_DEFAULT_FAVICON)) ||
1650 ShouldThemifyFaviconForUrl(data().url))) { 1680 ShouldThemifyFaviconForUrl(data().url))) {
1651 favicon_ = gfx::ImageSkiaOperations::CreateHSLShiftedImage( 1681 favicon_ = gfx::ImageSkiaOperations::CreateHSLShiftedImage(
1652 favicon_, GetThemeProvider()->GetTint(ThemeProperties::TINT_BUTTONS)); 1682 favicon_, GetThemeProvider()->GetTint(ThemeProperties::TINT_BUTTONS));
1653 } 1683 }
1654 } 1684 }
1655 1685
1656 if (showing_pinned_tab_title_changed_indicator_ && 1686 if (showing_pinned_tab_title_changed_indicator_ &&
1657 !should_display_crashed_favicon_) { 1687 !should_display_crashed_favicon_) {
1658 PaintPinnedTabTitleChangedIndicatorAndIcon(canvas, bounds); 1688 PaintPinnedTabTitleChangedIndicatorAndIcon(canvas, bounds);
1659 } else if (!favicon_.isNull()) { 1689 } else if (!favicon_.isNull()) {
1660 canvas->DrawImageInt(favicon_, 0, 0, bounds.width(), bounds.height(), 1690 // Desaturate favicons of tabs with network errors.
1661 bounds.x(), bounds.y(), bounds.width(), 1691 if (data().network_state == TabRendererData::NETWORK_STATE_ERROR) {
1662 bounds.height(), false); 1692 PaintDesaturatedFavIcon(canvas, favicon_, bounds);
1693 } else {
1694 canvas->DrawImageInt(favicon_, 0, 0, bounds.width(), bounds.height(),
1695 bounds.x(), bounds.y(), bounds.width(),
1696 bounds.height(), false);
1697 }
1663 } 1698 }
1664 } 1699 }
1665 1700
1666 void Tab::AdvanceLoadingAnimation() { 1701 void Tab::AdvanceLoadingAnimation() {
1667 const TabRendererData::NetworkState state = data().network_state; 1702 const TabRendererData::NetworkState state = data().network_state;
1668 if (controller_->IsImmersiveStyle()) { 1703 if (controller_->IsImmersiveStyle()) {
1669 throbber_->SetVisible(false); 1704 throbber_->SetVisible(false);
1670 if (state == TabRendererData::NETWORK_STATE_WAITING) { 1705 if (state == TabRendererData::NETWORK_STATE_WAITING) {
1671 // Waiting steps backwards. 1706 // Waiting steps backwards.
1672 immersive_loading_step_ = 1707 immersive_loading_step_ =
1673 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % 1708 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) %
1674 kImmersiveLoadingStepCount; 1709 kImmersiveLoadingStepCount;
1675 } else if (state == TabRendererData::NETWORK_STATE_LOADING) { 1710 } else if (state == TabRendererData::NETWORK_STATE_LOADING) {
1676 immersive_loading_step_ = 1711 immersive_loading_step_ =
1677 (immersive_loading_step_ + 1) % kImmersiveLoadingStepCount; 1712 (immersive_loading_step_ + 1) % kImmersiveLoadingStepCount;
1678 } else { 1713 } else {
1679 immersive_loading_step_ = 0; 1714 immersive_loading_step_ = 0;
1680 } 1715 }
1681 1716
1682 SchedulePaintInRect(GetImmersiveBarRect()); 1717 SchedulePaintInRect(GetImmersiveBarRect());
1683 return; 1718 return;
1684 } 1719 }
1685 1720
1686 if (state == TabRendererData::NETWORK_STATE_NONE) { 1721 if (state == TabRendererData::NETWORK_STATE_NONE ||
1722 state == TabRendererData::NETWORK_STATE_ERROR) {
1687 throbber_->ResetStartTimes(); 1723 throbber_->ResetStartTimes();
1688 throbber_->SetVisible(false); 1724 throbber_->SetVisible(false);
1689 ScheduleIconPaint(); 1725 ScheduleIconPaint();
1690 return; 1726 return;
1691 } 1727 }
1692 1728
1693 // Since the throbber can animate for a long time, paint to a separate layer 1729 // Since the throbber can animate for a long time, paint to a separate layer
1694 // when possible to reduce repaint overhead. 1730 // when possible to reduce repaint overhead.
1695 const bool paint_to_layer = controller_->CanPaintThrobberToLayer(); 1731 const bool paint_to_layer = controller_->CanPaintThrobberToLayer();
1696 if (paint_to_layer != !!throbber_->layer()) { 1732 if (paint_to_layer != !!throbber_->layer()) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1821 gfx::Rect Tab::GetImmersiveBarRect() const { 1857 gfx::Rect Tab::GetImmersiveBarRect() const {
1822 // The main bar is as wide as the normal tab's horizontal top line. 1858 // The main bar is as wide as the normal tab's horizontal top line.
1823 // This top line of the tab extends a few pixels left and right of the 1859 // This top line of the tab extends a few pixels left and right of the
1824 // center image due to pixels in the rounded corner images. 1860 // center image due to pixels in the rounded corner images.
1825 const int kBarPadding = 1; 1861 const int kBarPadding = 1;
1826 int main_bar_left = g_active_images.l_width - kBarPadding; 1862 int main_bar_left = g_active_images.l_width - kBarPadding;
1827 int main_bar_right = width() - g_active_images.r_width + kBarPadding; 1863 int main_bar_right = width() - g_active_images.r_width + kBarPadding;
1828 return gfx::Rect( 1864 return gfx::Rect(
1829 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); 1865 main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight);
1830 } 1866 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698