| OLD | NEW |
| 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 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/debug/alias.h" | 12 #include "base/debug/alias.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "build/build_config.h" | 15 #include "build/build_config.h" |
| 16 #include "chrome/browser/themes/theme_properties.h" | 16 #include "chrome/browser/themes/theme_properties.h" |
| 17 #include "chrome/browser/ui/browser.h" | 17 #include "chrome/browser/ui/browser.h" |
| 18 #include "chrome/browser/ui/layout_constants.h" | 18 #include "chrome/browser/ui/layout_constants.h" |
| 19 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" | 19 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" |
| 20 #include "chrome/browser/ui/tabs/tab_utils.h" | 20 #include "chrome/browser/ui/tabs/tab_utils.h" |
| 21 #include "chrome/browser/ui/view_ids.h" | 21 #include "chrome/browser/ui/view_ids.h" |
| 22 #include "chrome/browser/ui/views/tabs/alert_indicator_button.h" | 22 #include "chrome/browser/ui/views/tabs/alert_indicator_button.h" |
| 23 #include "chrome/browser/ui/views/tabs/tab_controller.h" | 23 #include "chrome/browser/ui/views/tabs/tab_controller.h" |
| 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/grit/generated_resources.h" | 26 #include "chrome/grit/generated_resources.h" |
| 27 #include "content/public/browser/user_metrics.h" | 27 #include "content/public/browser/user_metrics.h" |
| 28 #include "content/public/common/url_constants.h" |
| 28 #include "grit/components_scaled_resources.h" | 29 #include "grit/components_scaled_resources.h" |
| 29 #include "grit/components_strings.h" | 30 #include "grit/components_strings.h" |
| 30 #include "grit/theme_resources.h" | 31 #include "grit/theme_resources.h" |
| 31 #include "third_party/skia/include/effects/SkGradientShader.h" | 32 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 32 #include "third_party/skia/include/pathops/SkPathOps.h" | 33 #include "third_party/skia/include/pathops/SkPathOps.h" |
| 33 #include "ui/accessibility/ax_view_state.h" | 34 #include "ui/accessibility/ax_view_state.h" |
| 34 #include "ui/base/l10n/l10n_util.h" | 35 #include "ui/base/l10n/l10n_util.h" |
| 35 #include "ui/base/material_design/material_design_controller.h" | 36 #include "ui/base/material_design/material_design_controller.h" |
| 36 #include "ui/base/models/list_selection_model.h" | 37 #include "ui/base/models/list_selection_model.h" |
| 37 #include "ui/base/resource/resource_bundle.h" | 38 #include "ui/base/resource/resource_bundle.h" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 void AnimateToState(double state) override { | 163 void AnimateToState(double state) override { |
| 163 const double kHidingOffset = | 164 const double kHidingOffset = |
| 164 Tab::GetMinimumInactiveSize().height() - GetLayoutInsets(TAB).height(); | 165 Tab::GetMinimumInactiveSize().height() - GetLayoutInsets(TAB).height(); |
| 165 | 166 |
| 166 if (state < .5) { | 167 if (state < .5) { |
| 167 // Animate the normal icon down. | 168 // Animate the normal icon down. |
| 168 target_->SetFaviconHidingOffset( | 169 target_->SetFaviconHidingOffset( |
| 169 static_cast<int>(floor(kHidingOffset * 2.0 * state))); | 170 static_cast<int>(floor(kHidingOffset * 2.0 * state))); |
| 170 } else { | 171 } else { |
| 171 // Animate the crashed icon up. | 172 // Animate the crashed icon up. |
| 172 target_->set_should_display_crashed_favicon(); | 173 target_->SetShouldDisplayCrashedFavicon(true); |
| 173 target_->SetFaviconHidingOffset( | 174 target_->SetFaviconHidingOffset( |
| 174 static_cast<int>( | 175 static_cast<int>( |
| 175 floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); | 176 floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); |
| 176 } | 177 } |
| 177 } | 178 } |
| 178 | 179 |
| 179 private: | 180 private: |
| 180 Tab* target_; | 181 Tab* target_; |
| 181 | 182 |
| 182 DISALLOW_COPY_AND_ASSIGN(FaviconCrashAnimation); | 183 DISALLOW_COPY_AND_ASSIGN(FaviconCrashAnimation); |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 title = data_.loading ? | 634 title = data_.loading ? |
| 634 l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : | 635 l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : |
| 635 CoreTabHelper::GetDefaultTitle(); | 636 CoreTabHelper::GetDefaultTitle(); |
| 636 } else { | 637 } else { |
| 637 Browser::FormatTitleForDisplay(&title); | 638 Browser::FormatTitleForDisplay(&title); |
| 638 } | 639 } |
| 639 title_->SetText(title); | 640 title_->SetText(title); |
| 640 | 641 |
| 641 if (!data_.IsCrashed()) { | 642 if (!data_.IsCrashed()) { |
| 642 crash_icon_animation_->Stop(); | 643 crash_icon_animation_->Stop(); |
| 643 should_display_crashed_favicon_ = false; | 644 SetShouldDisplayCrashedFavicon(false); |
| 644 favicon_hiding_offset_ = 0; | 645 favicon_hiding_offset_ = 0; |
| 645 } else if (!should_display_crashed_favicon_ && | 646 } else if (!should_display_crashed_favicon_ && |
| 646 !crash_icon_animation_->is_animating()) { | 647 !crash_icon_animation_->is_animating()) { |
| 647 data_.alert_state = TabAlertState::NONE; | 648 data_.alert_state = TabAlertState::NONE; |
| 648 crash_icon_animation_->Start(); | 649 crash_icon_animation_->Start(); |
| 649 } | 650 } |
| 650 | 651 |
| 651 if (data_.alert_state != old.alert_state) | 652 if (data_.alert_state != old.alert_state) |
| 652 alert_indicator_button_->TransitionToAlertState(data_.alert_state); | 653 alert_indicator_button_->TransitionToAlertState(data_.alert_state); |
| 653 | 654 |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 // provided vertical space. | 1005 // provided vertical space. |
| 1005 title_->SetBoundsRect( | 1006 title_->SetBoundsRect( |
| 1006 gfx::Rect(title_left, lb.y(), std::max(title_width, 0), lb.height())); | 1007 gfx::Rect(title_left, lb.y(), std::max(title_width, 0), lb.height())); |
| 1007 } | 1008 } |
| 1008 title_->SetVisible(show_title); | 1009 title_->SetVisible(show_title); |
| 1009 } | 1010 } |
| 1010 | 1011 |
| 1011 void Tab::OnThemeChanged() { | 1012 void Tab::OnThemeChanged() { |
| 1012 LoadTabImages(); | 1013 LoadTabImages(); |
| 1013 OnButtonColorMaybeChanged(); | 1014 OnButtonColorMaybeChanged(); |
| 1015 favicon_ = gfx::ImageSkia(); |
| 1014 } | 1016 } |
| 1015 | 1017 |
| 1016 const char* Tab::GetClassName() const { | 1018 const char* Tab::GetClassName() const { |
| 1017 return kViewClassName; | 1019 return kViewClassName; |
| 1018 } | 1020 } |
| 1019 | 1021 |
| 1020 bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { | 1022 bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { |
| 1021 // Note: Anything that affects the tooltip text should be accounted for when | 1023 // Note: Anything that affects the tooltip text should be accounted for when |
| 1022 // calling TooltipTextChanged() from Tab::DataChanged(). | 1024 // calling TooltipTextChanged() from Tab::DataChanged(). |
| 1023 *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.alert_state); | 1025 *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.alert_state); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 const int ideal_delta = width() - GetPinnedWidth(); | 1188 const int ideal_delta = width() - GetPinnedWidth(); |
| 1187 const int ideal_x = (GetPinnedWidth() - bounds->width()) / 2; | 1189 const int ideal_x = (GetPinnedWidth() - bounds->width()) / 2; |
| 1188 bounds->set_x( | 1190 bounds->set_x( |
| 1189 bounds->x() + static_cast<int>( | 1191 bounds->x() + static_cast<int>( |
| 1190 (1 - static_cast<float>(ideal_delta) / | 1192 (1 - static_cast<float>(ideal_delta) / |
| 1191 static_cast<float>(kPinnedTabExtraWidthToRenderAsNormal)) * | 1193 static_cast<float>(kPinnedTabExtraWidthToRenderAsNormal)) * |
| 1192 (ideal_x - bounds->x()))); | 1194 (ideal_x - bounds->x()))); |
| 1193 } | 1195 } |
| 1194 | 1196 |
| 1195 void Tab::DataChanged(const TabRendererData& old) { | 1197 void Tab::DataChanged(const TabRendererData& old) { |
| 1198 // Clear the cached themed favicon except in the case of about:crash, which |
| 1199 // should go on using the old icon, whatever it was. |
| 1200 if (data().url != GURL(content::kChromeUICrashURL)) |
| 1201 favicon_ = gfx::ImageSkia(); |
| 1202 |
| 1196 if (data().alert_state != old.alert_state || data().title != old.title) | 1203 if (data().alert_state != old.alert_state || data().title != old.title) |
| 1197 TooltipTextChanged(); | 1204 TooltipTextChanged(); |
| 1198 | 1205 |
| 1199 if (data().blocked == old.blocked) | 1206 if (data().blocked == old.blocked) |
| 1200 return; | 1207 return; |
| 1201 | 1208 |
| 1202 if (data().blocked) | 1209 if (data().blocked) |
| 1203 StartPulse(); | 1210 StartPulse(); |
| 1204 else | 1211 else |
| 1205 StopPulse(); | 1212 StopPulse(); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1493 } | 1500 } |
| 1494 | 1501 |
| 1495 void Tab::PaintIcon(gfx::Canvas* canvas) { | 1502 void Tab::PaintIcon(gfx::Canvas* canvas) { |
| 1496 gfx::Rect bounds = favicon_bounds_; | 1503 gfx::Rect bounds = favicon_bounds_; |
| 1497 bounds.set_x(GetMirroredXForRect(bounds)); | 1504 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1498 bounds.Offset(0, favicon_hiding_offset_); | 1505 bounds.Offset(0, favicon_hiding_offset_); |
| 1499 bounds.Intersect(GetContentsBounds()); | 1506 bounds.Intersect(GetContentsBounds()); |
| 1500 if (bounds.IsEmpty()) | 1507 if (bounds.IsEmpty()) |
| 1501 return; | 1508 return; |
| 1502 | 1509 |
| 1503 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { | 1510 // Throbber will do its own painting. |
| 1504 // Throbber will do its own painting. | 1511 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) |
| 1505 } else { | 1512 return; |
| 1506 const gfx::ImageSkia& favicon = should_display_crashed_favicon_ ? | 1513 |
| 1507 *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | 1514 if (favicon_.isNull()) { |
| 1508 IDR_CRASH_SAD_FAVICON) : | 1515 favicon_ = should_display_crashed_favicon_ |
| 1509 data().favicon; | 1516 ? *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| 1510 if (!favicon.isNull()) { | 1517 IDR_CRASH_SAD_FAVICON) |
| 1511 canvas->DrawImageInt(favicon, 0, 0, bounds.width(), bounds.height(), | 1518 : data().favicon; |
| 1512 bounds.x(), bounds.y(), bounds.width(), | 1519 // Theme the icon if it's a chrome:// page or if it's the sadtab favicon. |
| 1513 bounds.height(), false); | 1520 if (!favicon_.isNull() && |
| 1521 (should_display_crashed_favicon_ || |
| 1522 (data().url.SchemeIs(content::kChromeUIScheme)))) { |
| 1523 color_utils::HSL icon_shift = |
| 1524 GetThemeProvider()->GetTint(ThemeProperties::TINT_BUTTONS); |
| 1525 favicon_ = |
| 1526 gfx::ImageSkiaOperations::CreateHSLShiftedImage(favicon_, icon_shift); |
| 1514 } | 1527 } |
| 1515 } | 1528 } |
| 1529 |
| 1530 if (!favicon_.isNull()) { |
| 1531 canvas->DrawImageInt(favicon_, 0, 0, bounds.width(), bounds.height(), |
| 1532 bounds.x(), bounds.y(), bounds.width(), |
| 1533 bounds.height(), false); |
| 1534 } |
| 1516 } | 1535 } |
| 1517 | 1536 |
| 1518 void Tab::AdvanceLoadingAnimation() { | 1537 void Tab::AdvanceLoadingAnimation() { |
| 1519 const TabRendererData::NetworkState state = data().network_state; | 1538 const TabRendererData::NetworkState state = data().network_state; |
| 1520 if (controller_->IsImmersiveStyle()) { | 1539 if (controller_->IsImmersiveStyle()) { |
| 1521 throbber_->SetVisible(false); | 1540 throbber_->SetVisible(false); |
| 1522 if (state == TabRendererData::NETWORK_STATE_WAITING) { | 1541 if (state == TabRendererData::NETWORK_STATE_WAITING) { |
| 1523 // Waiting steps backwards. | 1542 // Waiting steps backwards. |
| 1524 immersive_loading_step_ = | 1543 immersive_loading_step_ = |
| 1525 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % | 1544 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1620 // much. | 1639 // much. |
| 1621 if (pulse_animation_->is_animating() && | 1640 if (pulse_animation_->is_animating() && |
| 1622 !pinned_title_change_animation_->is_animating()) { | 1641 !pinned_title_change_animation_->is_animating()) { |
| 1623 val += pulse_animation_->GetCurrentValue() * offset; | 1642 val += pulse_animation_->GetCurrentValue() * offset; |
| 1624 } else if (hover_controller_.ShouldDraw()) { | 1643 } else if (hover_controller_.ShouldDraw()) { |
| 1625 val += hover_controller_.GetAnimationValue() * offset; | 1644 val += hover_controller_.GetAnimationValue() * offset; |
| 1626 } | 1645 } |
| 1627 return val; | 1646 return val; |
| 1628 } | 1647 } |
| 1629 | 1648 |
| 1649 void Tab::SetShouldDisplayCrashedFavicon(bool value) { |
| 1650 if (value == should_display_crashed_favicon_) |
| 1651 return; |
| 1652 |
| 1653 should_display_crashed_favicon_ = value; |
| 1654 favicon_ = gfx::ImageSkia(); |
| 1655 } |
| 1656 |
| 1630 void Tab::SetFaviconHidingOffset(int offset) { | 1657 void Tab::SetFaviconHidingOffset(int offset) { |
| 1631 favicon_hiding_offset_ = offset; | 1658 favicon_hiding_offset_ = offset; |
| 1632 ScheduleIconPaint(); | 1659 ScheduleIconPaint(); |
| 1633 } | 1660 } |
| 1634 | 1661 |
| 1635 void Tab::OnButtonColorMaybeChanged() { | 1662 void Tab::OnButtonColorMaybeChanged() { |
| 1636 // The theme provider may be null if we're not currently in a widget | 1663 // The theme provider may be null if we're not currently in a widget |
| 1637 // hierarchy. | 1664 // hierarchy. |
| 1638 const ui::ThemeProvider* theme_provider = GetThemeProvider(); | 1665 const ui::ThemeProvider* theme_provider = GetThemeProvider(); |
| 1639 if (!theme_provider) | 1666 if (!theme_provider) |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 inactive_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); | 1801 inactive_images_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); |
| 1775 inactive_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); | 1802 inactive_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); |
| 1776 inactive_images_.l_width = inactive_images_.image_l->width(); | 1803 inactive_images_.l_width = inactive_images_.image_l->width(); |
| 1777 inactive_images_.r_width = inactive_images_.image_r->width(); | 1804 inactive_images_.r_width = inactive_images_.image_r->width(); |
| 1778 | 1805 |
| 1779 mask_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); | 1806 mask_images_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); |
| 1780 mask_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); | 1807 mask_images_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); |
| 1781 mask_images_.l_width = mask_images_.image_l->width(); | 1808 mask_images_.l_width = mask_images_.image_l->width(); |
| 1782 mask_images_.r_width = mask_images_.image_r->width(); | 1809 mask_images_.r_width = mask_images_.image_r->width(); |
| 1783 } | 1810 } |
| OLD | NEW |