| Index: chrome/browser/ui/views/download/download_item_view_md.cc
|
| diff --git a/chrome/browser/ui/views/download/download_item_view_md.cc b/chrome/browser/ui/views/download/download_item_view_md.cc
|
| deleted file mode 100644
|
| index f6ab819e9590bde25692233cfd7d62d45c1412d9..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/views/download/download_item_view_md.cc
|
| +++ /dev/null
|
| @@ -1,1132 +0,0 @@
|
| -// Copyright (c) 2012 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/download/download_item_view_md.h"
|
| -
|
| -#include <stddef.h>
|
| -
|
| -#include <algorithm>
|
| -#include <vector>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/callback.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/i18n/break_iterator.h"
|
| -#include "base/i18n/rtl.h"
|
| -#include "base/location.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/metrics/histogram_macros.h"
|
| -#include "base/single_thread_task_runner.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/strings/sys_string_conversions.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "base/threading/thread_task_runner_handle.h"
|
| -#include "chrome/browser/browser_process.h"
|
| -#include "chrome/browser/download/chrome_download_manager_delegate.h"
|
| -#include "chrome/browser/download/download_item_model.h"
|
| -#include "chrome/browser/download/download_stats.h"
|
| -#include "chrome/browser/download/drag_download_item.h"
|
| -#include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h"
|
| -#include "chrome/browser/profiles/profile.h"
|
| -#include "chrome/browser/safe_browsing/download_feedback_service.h"
|
| -#include "chrome/browser/safe_browsing/download_protection_service.h"
|
| -#include "chrome/browser/safe_browsing/safe_browsing_service.h"
|
| -#include "chrome/browser/themes/theme_properties.h"
|
| -#include "chrome/browser/ui/views/download/download_feedback_dialog_view.h"
|
| -#include "chrome/browser/ui/views/download/download_shelf_context_menu_view.h"
|
| -#include "chrome/browser/ui/views/download/download_shelf_view.h"
|
| -#include "chrome/browser/ui/views/frame/browser_view.h"
|
| -#include "chrome/common/pref_names.h"
|
| -#include "chrome/grit/generated_resources.h"
|
| -#include "components/prefs/pref_service.h"
|
| -#include "content/public/browser/download_danger_type.h"
|
| -#include "third_party/icu/source/common/unicode/uchar.h"
|
| -#include "ui/accessibility/ax_view_state.h"
|
| -#include "ui/base/l10n/l10n_util.h"
|
| -#include "ui/base/material_design/material_design_controller.h"
|
| -#include "ui/base/resource/resource_bundle.h"
|
| -#include "ui/base/theme_provider.h"
|
| -#include "ui/events/event.h"
|
| -#include "ui/gfx/animation/slide_animation.h"
|
| -#include "ui/gfx/canvas.h"
|
| -#include "ui/gfx/color_palette.h"
|
| -#include "ui/gfx/color_utils.h"
|
| -#include "ui/gfx/image/image.h"
|
| -#include "ui/gfx/paint_vector_icon.h"
|
| -#include "ui/gfx/text_elider.h"
|
| -#include "ui/gfx/text_utils.h"
|
| -#include "ui/gfx/vector_icons_public.h"
|
| -#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
|
| -#include "ui/views/animation/ink_drop_highlight.h"
|
| -#include "ui/views/border.h"
|
| -#include "ui/views/controls/button/image_button.h"
|
| -#include "ui/views/controls/button/md_text_button.h"
|
| -#include "ui/views/controls/button/vector_icon_button.h"
|
| -#include "ui/views/controls/focusable_border.h"
|
| -#include "ui/views/controls/label.h"
|
| -#include "ui/views/mouse_constants.h"
|
| -#include "ui/views/widget/root_view.h"
|
| -#include "ui/views/widget/widget.h"
|
| -
|
| -using content::DownloadItem;
|
| -using extensions::ExperienceSamplingEvent;
|
| -
|
| -namespace {
|
| -
|
| -// All values in dp.
|
| -const int kTextWidth = 140;
|
| -const int kDangerousTextWidth = 200;
|
| -
|
| -// The normal height of the item which may be exceeded if text is large.
|
| -const int kDefaultHeight = 48;
|
| -
|
| -// The vertical distance between the item's visual upper bound (as delineated by
|
| -// the separator on the right) and the edge of the shelf.
|
| -const int kTopBottomPadding = 6;
|
| -
|
| -// The minimum vertical padding above and below contents of the download item.
|
| -// This is only used when the text size is large.
|
| -const int kMinimumVerticalPadding = 2 + kTopBottomPadding;
|
| -
|
| -// Vertical padding between filename and status text.
|
| -const int kVerticalTextPadding = 1;
|
| -
|
| -const int kTooltipMaxWidth = 800;
|
| -
|
| -// Padding before the icon and at end of the item.
|
| -const int kStartPadding = 12;
|
| -const int kEndPadding = 6;
|
| -
|
| -// Horizontal padding between progress indicator and filename/status text.
|
| -const int kProgressTextPadding = 8;
|
| -
|
| -// The space between the Save and Discard buttons when prompting for a dangerous
|
| -// download.
|
| -const int kButtonPadding = 5;
|
| -
|
| -// The touchable space around the dropdown button's icon.
|
| -const int kDropdownBorderWidth = 10;
|
| -
|
| -// The space on the right side of the dangerous download label.
|
| -const int kLabelPadding = 8;
|
| -
|
| -// Height/width of the warning icon, also in dp.
|
| -const int kWarningIconSize = 24;
|
| -
|
| -// How long the 'download complete' animation should last for.
|
| -const int kCompleteAnimationDurationMs = 2500;
|
| -
|
| -// How long the 'download interrupted' animation should last for.
|
| -const int kInterruptedAnimationDurationMs = 2500;
|
| -
|
| -// How long we keep the item disabled after the user clicked it to open the
|
| -// downloaded item.
|
| -const int kDisabledOnOpenDuration = 3000;
|
| -
|
| -// The separator is drawn as a border. It's one dp wide.
|
| -class SeparatorBorder : public views::FocusableBorder {
|
| - public:
|
| - explicit SeparatorBorder(SkColor color) : color_(color) {}
|
| - ~SeparatorBorder() override {}
|
| -
|
| - void Paint(const views::View& view, gfx::Canvas* canvas) override {
|
| - if (view.HasFocus())
|
| - return FocusableBorder::Paint(view, canvas);
|
| -
|
| - int end_x = base::i18n::IsRTL() ? 0 : view.width() - 1;
|
| - canvas->DrawLine(gfx::Point(end_x, kTopBottomPadding),
|
| - gfx::Point(end_x, view.height() - kTopBottomPadding),
|
| - color_);
|
| - }
|
| -
|
| - gfx::Insets GetInsets() const override { return gfx::Insets(0, 0, 0, 1); }
|
| -
|
| - gfx::Size GetMinimumSize() const override {
|
| - return gfx::Size(1, 2 * kTopBottomPadding + 1);
|
| - }
|
| -
|
| - private:
|
| - SkColor color_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(SeparatorBorder);
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -// Allows the DownloadItemViewMd to control the InkDrop on the drop down button.
|
| -class DownloadItemViewMd::DropDownButton : public views::VectorIconButton {
|
| - public:
|
| - explicit DropDownButton(views::VectorIconButtonDelegate* delegate)
|
| - : views::VectorIconButton(delegate) {}
|
| - ~DropDownButton() override {}
|
| -
|
| - // Promoted visibility to public.
|
| - void AnimateInkDrop(views::InkDropState state) {
|
| - // TODO(bruthig): Plumb in the proper Event.
|
| - views::VectorIconButton::AnimateInkDrop(state, nullptr /* event */);
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(DropDownButton);
|
| -};
|
| -
|
| -DownloadItemViewMd::DownloadItemViewMd(DownloadItem* download_item,
|
| - DownloadShelfView* parent)
|
| - : shelf_(parent),
|
| - status_text_(l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)),
|
| - dropdown_state_(NORMAL),
|
| - mode_(NORMAL_MODE),
|
| - dragging_(false),
|
| - starting_drag_(false),
|
| - model_(download_item),
|
| - save_button_(nullptr),
|
| - discard_button_(nullptr),
|
| - dropdown_button_(new DropDownButton(this)),
|
| - dangerous_download_label_(nullptr),
|
| - dangerous_download_label_sized_(false),
|
| - disabled_while_opening_(false),
|
| - creation_time_(base::Time::Now()),
|
| - time_download_warning_shown_(base::Time()),
|
| - weak_ptr_factory_(this) {
|
| - SetInkDropMode(InkDropMode::ON);
|
| - DCHECK(download());
|
| - DCHECK(ui::MaterialDesignController::IsModeMaterial());
|
| - download()->AddObserver(this);
|
| - set_context_menu_controller(this);
|
| -
|
| - dropdown_button_->SetBorder(
|
| - views::Border::CreateEmptyBorder(gfx::Insets(kDropdownBorderWidth)));
|
| - dropdown_button_->set_ink_drop_size(gfx::Size(32, 32));
|
| - AddChildView(dropdown_button_);
|
| -
|
| - LoadIcon();
|
| -
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - font_list_ =
|
| - rb.GetFontList(ui::ResourceBundle::BaseFont).DeriveWithSizeDelta(1);
|
| - status_font_list_ =
|
| - rb.GetFontList(ui::ResourceBundle::BaseFont).DeriveWithSizeDelta(-2);
|
| -
|
| - SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
|
| -
|
| - OnDownloadUpdated(download());
|
| -
|
| - SetDropdownState(NORMAL);
|
| - UpdateColorsFromTheme();
|
| -}
|
| -
|
| -DownloadItemViewMd::~DownloadItemViewMd() {
|
| - StopDownloadProgress();
|
| - download()->RemoveObserver(this);
|
| -
|
| - // ExperienceSampling: If the user took no action to remove the warning
|
| - // before it disappeared, then the user effectively dismissed the download
|
| - // without keeping it.
|
| - if (sampling_event_.get())
|
| - sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kIgnore);
|
| -}
|
| -
|
| -// Progress animation handlers.
|
| -
|
| -void DownloadItemViewMd::StartDownloadProgress() {
|
| - if (progress_timer_.IsRunning())
|
| - return;
|
| - progress_start_time_ = base::TimeTicks::Now();
|
| - progress_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
|
| - DownloadShelf::kProgressRateMs),
|
| - base::Bind(&DownloadItemViewMd::ProgressTimerFired,
|
| - base::Unretained(this)));
|
| -}
|
| -
|
| -void DownloadItemViewMd::StopDownloadProgress() {
|
| - if (!progress_timer_.IsRunning())
|
| - return;
|
| - previous_progress_elapsed_ += base::TimeTicks::Now() - progress_start_time_;
|
| - progress_start_time_ = base::TimeTicks();
|
| - progress_timer_.Stop();
|
| -}
|
| -
|
| -// static
|
| -SkColor DownloadItemViewMd::GetTextColorForThemeProvider(
|
| - const ui::ThemeProvider* theme) {
|
| - return theme ? theme->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT)
|
| - : gfx::kPlaceholderColor;
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnExtractIconComplete(gfx::Image* icon_bitmap) {
|
| - if (icon_bitmap)
|
| - shelf_->SchedulePaint();
|
| -}
|
| -
|
| -// DownloadObserver interface.
|
| -
|
| -// Update the progress graphic on the icon and our text status label
|
| -// to reflect our current bytes downloaded, time remaining.
|
| -void DownloadItemViewMd::OnDownloadUpdated(DownloadItem* download_item) {
|
| - DCHECK_EQ(download(), download_item);
|
| -
|
| - if (!model_.ShouldShowInShelf()) {
|
| - shelf_->RemoveDownloadView(this); // This will delete us!
|
| - return;
|
| - }
|
| -
|
| - if (IsShowingWarningDialog() != model_.IsDangerous()) {
|
| - ToggleWarningDialog();
|
| - } else {
|
| - switch (download()->GetState()) {
|
| - case DownloadItem::IN_PROGRESS:
|
| - download()->IsPaused() ? StopDownloadProgress()
|
| - : StartDownloadProgress();
|
| - LoadIconIfItemPathChanged();
|
| - break;
|
| - case DownloadItem::INTERRUPTED:
|
| - StopDownloadProgress();
|
| - complete_animation_.reset(new gfx::SlideAnimation(this));
|
| - complete_animation_->SetSlideDuration(kInterruptedAnimationDurationMs);
|
| - complete_animation_->SetTweenType(gfx::Tween::LINEAR);
|
| - complete_animation_->Show();
|
| - LoadIcon();
|
| - break;
|
| - case DownloadItem::COMPLETE:
|
| - if (model_.ShouldRemoveFromShelfWhenComplete()) {
|
| - shelf_->RemoveDownloadView(this); // This will delete us!
|
| - return;
|
| - }
|
| - StopDownloadProgress();
|
| - complete_animation_.reset(new gfx::SlideAnimation(this));
|
| - complete_animation_->SetSlideDuration(kCompleteAnimationDurationMs);
|
| - complete_animation_->SetTweenType(gfx::Tween::LINEAR);
|
| - complete_animation_->Show();
|
| - LoadIcon();
|
| - break;
|
| - case DownloadItem::CANCELLED:
|
| - StopDownloadProgress();
|
| - if (complete_animation_)
|
| - complete_animation_->Stop();
|
| - LoadIcon();
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| - status_text_ = model_.GetStatusText();
|
| - SchedulePaint();
|
| - }
|
| -
|
| - base::string16 new_tip = model_.GetTooltipText(font_list_, kTooltipMaxWidth);
|
| - if (new_tip != tooltip_text_) {
|
| - tooltip_text_ = new_tip;
|
| - TooltipTextChanged();
|
| - }
|
| -
|
| - UpdateAccessibleName();
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnDownloadDestroyed(DownloadItem* download) {
|
| - shelf_->RemoveDownloadView(this); // This will delete us!
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnDownloadOpened(DownloadItem* download) {
|
| - disabled_while_opening_ = true;
|
| - SetEnabled(false);
|
| - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&DownloadItemViewMd::Reenable, weak_ptr_factory_.GetWeakPtr()),
|
| - base::TimeDelta::FromMilliseconds(kDisabledOnOpenDuration));
|
| -
|
| - // Notify our parent.
|
| - shelf_->OpenedDownload();
|
| -}
|
| -
|
| -// View overrides
|
| -
|
| -// In dangerous mode we have to layout our buttons.
|
| -void DownloadItemViewMd::Layout() {
|
| - UpdateColorsFromTheme();
|
| -
|
| - if (IsShowingWarningDialog()) {
|
| - gfx::Point child_origin(
|
| - kStartPadding + kWarningIconSize + kStartPadding,
|
| - (height() - dangerous_download_label_->height()) / 2);
|
| - dangerous_download_label_->SetPosition(child_origin);
|
| -
|
| - child_origin.Offset(dangerous_download_label_->width() + kLabelPadding, 0);
|
| - gfx::Size button_size = GetButtonSize();
|
| - child_origin.set_y((height() - button_size.height()) / 2);
|
| - if (save_button_) {
|
| - save_button_->SetBoundsRect(gfx::Rect(child_origin, button_size));
|
| - child_origin.Offset(button_size.width() + kButtonPadding, 0);
|
| - }
|
| - discard_button_->SetBoundsRect(gfx::Rect(child_origin, button_size));
|
| - }
|
| -
|
| - if (mode_ != DANGEROUS_MODE) {
|
| - dropdown_button_->SizeToPreferredSize();
|
| - dropdown_button_->SetPosition(
|
| - gfx::Point(width() - dropdown_button_->width() - kEndPadding,
|
| - (height() - dropdown_button_->height()) / 2));
|
| - }
|
| -}
|
| -
|
| -gfx::Size DownloadItemViewMd::GetPreferredSize() const {
|
| - int width = 0;
|
| - // We set the height to the height of two rows or text plus margins.
|
| - int child_height = font_list_.GetBaseline() + kVerticalTextPadding +
|
| - status_font_list_.GetHeight();
|
| -
|
| - if (IsShowingWarningDialog()) {
|
| - // Width.
|
| - width = kStartPadding + kWarningIconSize + kStartPadding +
|
| - dangerous_download_label_->width() + kLabelPadding;
|
| - gfx::Size button_size = GetButtonSize();
|
| - if (save_button_)
|
| - width += button_size.width() + kButtonPadding;
|
| - width += button_size.width() + kEndPadding;
|
| -
|
| - // Height: make sure the button fits and the warning icon fits.
|
| - child_height =
|
| - std::max({child_height, button_size.height(), kWarningIconSize});
|
| - } else {
|
| - width = kStartPadding + DownloadShelf::kProgressIndicatorSize +
|
| - kProgressTextPadding + kTextWidth + kEndPadding;
|
| - }
|
| -
|
| - if (mode_ != DANGEROUS_MODE)
|
| - width += dropdown_button_->GetPreferredSize().width();
|
| -
|
| - return gfx::Size(width, std::max(kDefaultHeight,
|
| - 2 * kMinimumVerticalPadding + child_height));
|
| -}
|
| -
|
| -bool DownloadItemViewMd::OnMousePressed(const ui::MouseEvent& event) {
|
| - HandlePressEvent(event, event.IsOnlyLeftMouseButton());
|
| - return true;
|
| -}
|
| -
|
| -// Handle drag (file copy) operations.
|
| -bool DownloadItemViewMd::OnMouseDragged(const ui::MouseEvent& event) {
|
| - // Mouse should not activate us in dangerous mode.
|
| - if (IsShowingWarningDialog())
|
| - return true;
|
| -
|
| - if (!starting_drag_) {
|
| - starting_drag_ = true;
|
| - drag_start_point_ = event.location();
|
| - AnimateInkDrop(views::InkDropState::HIDDEN, &event);
|
| - }
|
| - if (dragging_) {
|
| - if (download()->GetState() == DownloadItem::COMPLETE) {
|
| - IconManager* im = g_browser_process->icon_manager();
|
| - gfx::Image* icon = im->LookupIconFromFilepath(
|
| - download()->GetTargetFilePath(), IconLoader::SMALL);
|
| - views::Widget* widget = GetWidget();
|
| - DragDownloadItem(download(), icon,
|
| - widget ? widget->GetNativeView() : NULL);
|
| - }
|
| - } else if (ExceededDragThreshold(event.location() - drag_start_point_)) {
|
| - dragging_ = true;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnMouseReleased(const ui::MouseEvent& event) {
|
| - HandleClickEvent(event, event.IsOnlyLeftMouseButton());
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnMouseCaptureLost() {
|
| - // Mouse should not activate us in dangerous mode.
|
| - if (mode_ != NORMAL_MODE)
|
| - return;
|
| -
|
| - if (dragging_) {
|
| - // Starting a drag results in a MouseCaptureLost.
|
| - dragging_ = false;
|
| - starting_drag_ = false;
|
| - }
|
| -}
|
| -
|
| -bool DownloadItemViewMd::OnKeyPressed(const ui::KeyEvent& event) {
|
| - // Key press should not activate us in dangerous mode.
|
| - if (IsShowingWarningDialog())
|
| - return true;
|
| -
|
| - if (event.key_code() == ui::VKEY_SPACE ||
|
| - event.key_code() == ui::VKEY_RETURN) {
|
| - AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, nullptr /* &event */);
|
| - // OpenDownload may delete this, so don't add any code after this line.
|
| - OpenDownload();
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool DownloadItemViewMd::GetTooltipText(const gfx::Point& p,
|
| - base::string16* tooltip) const {
|
| - if (IsShowingWarningDialog()) {
|
| - tooltip->clear();
|
| - return false;
|
| - }
|
| -
|
| - tooltip->assign(tooltip_text_);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void DownloadItemViewMd::GetAccessibleState(ui::AXViewState* state) {
|
| - state->name = accessible_name_;
|
| - state->role = ui::AX_ROLE_BUTTON;
|
| - if (model_.IsDangerous())
|
| - state->AddStateFlag(ui::AX_STATE_DISABLED);
|
| - else
|
| - state->AddStateFlag(ui::AX_STATE_HASPOPUP);
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnThemeChanged() {
|
| - UpdateColorsFromTheme();
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void DownloadItemViewMd::AddInkDropLayer(ui::Layer* ink_drop_layer) {
|
| - InkDropHostView::AddInkDropLayer(ink_drop_layer);
|
| - // The layer that's added to host the ink drop layer must mask to bounds
|
| - // so the hover effect is clipped while animating open.
|
| - layer()->SetMasksToBounds(true);
|
| -}
|
| -
|
| -std::unique_ptr<views::InkDropRipple> DownloadItemViewMd::CreateInkDropRipple()
|
| - const {
|
| - return base::MakeUnique<views::FloodFillInkDropRipple>(
|
| - GetLocalBounds(), GetInkDropCenterBasedOnLastEvent(),
|
| - color_utils::DeriveDefaultIconColor(GetTextColor()),
|
| - ink_drop_visible_opacity());
|
| -}
|
| -
|
| -std::unique_ptr<views::InkDropHighlight>
|
| -DownloadItemViewMd::CreateInkDropHighlight() const {
|
| - if (IsShowingWarningDialog())
|
| - return nullptr;
|
| -
|
| - gfx::Size size = GetPreferredSize();
|
| - return base::MakeUnique<views::InkDropHighlight>(
|
| - size, kInkDropSmallCornerRadius,
|
| - gfx::RectF(gfx::SizeF(size)).CenterPoint(),
|
| - color_utils::DeriveDefaultIconColor(GetTextColor()));
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnGestureEvent(ui::GestureEvent* event) {
|
| - if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
|
| - HandlePressEvent(*event, true);
|
| - event->SetHandled();
|
| - return;
|
| - }
|
| -
|
| - if (event->type() == ui::ET_GESTURE_TAP) {
|
| - HandleClickEvent(*event, true);
|
| - event->SetHandled();
|
| - return;
|
| - }
|
| -
|
| - views::View::OnGestureEvent(event);
|
| -}
|
| -
|
| -void DownloadItemViewMd::ShowContextMenuForView(
|
| - View* source,
|
| - const gfx::Point& point,
|
| - ui::MenuSourceType source_type) {
|
| - ShowContextMenuImpl(gfx::Rect(point, gfx::Size()), source_type);
|
| -}
|
| -
|
| -void DownloadItemViewMd::ButtonPressed(views::Button* sender,
|
| - const ui::Event& event) {
|
| - if (sender == dropdown_button_) {
|
| - // TODO(estade): this is copied from ToolbarActionView but should be shared
|
| - // one way or another.
|
| - ui::MenuSourceType type = ui::MENU_SOURCE_NONE;
|
| - if (event.IsMouseEvent())
|
| - type = ui::MENU_SOURCE_MOUSE;
|
| - else if (event.IsKeyEvent())
|
| - type = ui::MENU_SOURCE_KEYBOARD;
|
| - else if (event.IsGestureEvent())
|
| - type = ui::MENU_SOURCE_TOUCH;
|
| - SetDropdownState(PUSHED);
|
| - ShowContextMenuImpl(dropdown_button_->GetBoundsInScreen(), type);
|
| - return;
|
| - }
|
| -
|
| - base::TimeDelta warning_duration;
|
| - if (!time_download_warning_shown_.is_null())
|
| - warning_duration = base::Time::Now() - time_download_warning_shown_;
|
| -
|
| - if (save_button_ && sender == save_button_) {
|
| - // The user has confirmed a dangerous download. We'd record how quickly the
|
| - // user did this to detect whether we're being clickjacked.
|
| - UMA_HISTOGRAM_LONG_TIMES("clickjacking.save_download", warning_duration);
|
| - // ExperienceSampling: User chose to proceed with a dangerous download.
|
| - if (sampling_event_.get()) {
|
| - sampling_event_->CreateUserDecisionEvent(
|
| - ExperienceSamplingEvent::kProceed);
|
| - sampling_event_.reset(NULL);
|
| - }
|
| - // This will change the state and notify us.
|
| - download()->ValidateDangerousDownload();
|
| - return;
|
| - }
|
| -
|
| - // WARNING: all end states after this point delete |this|.
|
| - DCHECK_EQ(discard_button_, sender);
|
| - UMA_HISTOGRAM_LONG_TIMES("clickjacking.discard_download", warning_duration);
|
| - if (!model_.IsMalicious() && model_.ShouldAllowDownloadFeedback() &&
|
| - !shelf_->browser()->profile()->IsOffTheRecord()) {
|
| - if (!shelf_->browser()->profile()->GetPrefs()->HasPrefPath(
|
| - prefs::kSafeBrowsingExtendedReportingEnabled)) {
|
| - // Show dialog, because the dialog hasn't been shown before.
|
| - DownloadFeedbackDialogView::Show(
|
| - shelf_->get_parent()->GetNativeWindow(), shelf_->browser()->profile(),
|
| - shelf_->GetNavigator(),
|
| - base::Bind(
|
| - &DownloadItemViewMd::PossiblySubmitDownloadToFeedbackService,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| - } else {
|
| - PossiblySubmitDownloadToFeedbackService(
|
| - shelf_->browser()->profile()->GetPrefs()->GetBoolean(
|
| - prefs::kSafeBrowsingExtendedReportingEnabled));
|
| - }
|
| - return;
|
| - }
|
| - download()->Remove();
|
| -}
|
| -
|
| -SkColor DownloadItemViewMd::GetVectorIconBaseColor() const {
|
| - return GetTextColor();
|
| -}
|
| -
|
| -void DownloadItemViewMd::AnimationProgressed(const gfx::Animation* animation) {
|
| - // We don't care if what animation (body button/drop button/complete),
|
| - // is calling back, as they all have to go through the same paint call.
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnPaint(gfx::Canvas* canvas) {
|
| - // Make sure to draw |this| opaquely. Since the toolbar color can be partially
|
| - // transparent, start with a black backdrop (which is the default initialized
|
| - // color for opaque canvases).
|
| - canvas->DrawColor(SK_ColorBLACK);
|
| - canvas->DrawColor(
|
| - GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR));
|
| -
|
| - DrawStatusText(canvas);
|
| - DrawFilename(canvas);
|
| - DrawIcon(canvas);
|
| - OnPaintBorder(canvas);
|
| -}
|
| -
|
| -int DownloadItemViewMd::GetYForFilenameText() const {
|
| - int text_height = font_list_.GetBaseline();
|
| - if (!status_text_.empty())
|
| - text_height += kVerticalTextPadding + status_font_list_.GetBaseline();
|
| - return (height() - text_height) / 2;
|
| -}
|
| -
|
| -void DownloadItemViewMd::DrawStatusText(gfx::Canvas* canvas) {
|
| - if (status_text_.empty() || IsShowingWarningDialog())
|
| - return;
|
| -
|
| - int mirrored_x = GetMirroredXWithWidthInView(
|
| - kStartPadding + DownloadShelf::kProgressIndicatorSize +
|
| - kProgressTextPadding,
|
| - kTextWidth);
|
| - int y =
|
| - GetYForFilenameText() + font_list_.GetBaseline() + kVerticalTextPadding;
|
| - canvas->DrawStringRect(
|
| - status_text_, status_font_list_, GetDimmedTextColor(),
|
| - gfx::Rect(mirrored_x, y, kTextWidth, status_font_list_.GetHeight()));
|
| -}
|
| -
|
| -void DownloadItemViewMd::DrawFilename(gfx::Canvas* canvas) {
|
| - if (IsShowingWarningDialog())
|
| - return;
|
| -
|
| - // Print the text, left aligned and always print the file extension.
|
| - // Last value of x was the end of the right image, just before the button.
|
| - // Note that in dangerous mode we use a label (as the text is multi-line).
|
| - base::string16 filename;
|
| - if (!disabled_while_opening_) {
|
| - filename = gfx::ElideFilename(download()->GetFileNameToReportUser(),
|
| - font_list_, kTextWidth);
|
| - } else {
|
| - // First, Calculate the download status opening string width.
|
| - base::string16 status_string = l10n_util::GetStringFUTF16(
|
| - IDS_DOWNLOAD_STATUS_OPENING, base::string16());
|
| - int status_string_width = gfx::GetStringWidth(status_string, font_list_);
|
| - // Then, elide the file name.
|
| - base::string16 filename_string =
|
| - gfx::ElideFilename(download()->GetFileNameToReportUser(), font_list_,
|
| - kTextWidth - status_string_width);
|
| - // Last, concat the whole string.
|
| - filename = l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING,
|
| - filename_string);
|
| - }
|
| -
|
| - int mirrored_x = GetMirroredXWithWidthInView(
|
| - kStartPadding + DownloadShelf::kProgressIndicatorSize +
|
| - kProgressTextPadding,
|
| - kTextWidth);
|
| - canvas->DrawStringRect(filename, font_list_,
|
| - enabled() ? GetTextColor() : GetDimmedTextColor(),
|
| - gfx::Rect(mirrored_x, GetYForFilenameText(),
|
| - kTextWidth, font_list_.GetHeight()));
|
| -}
|
| -
|
| -void DownloadItemViewMd::DrawIcon(gfx::Canvas* canvas) {
|
| - if (IsShowingWarningDialog()) {
|
| - int icon_x = base::i18n::IsRTL()
|
| - ? width() - kWarningIconSize - kStartPadding
|
| - : kStartPadding;
|
| - int icon_y = (height() - kWarningIconSize) / 2;
|
| - canvas->DrawImageInt(GetWarningIcon(), icon_x, icon_y);
|
| - return;
|
| - }
|
| -
|
| - // Paint download progress.
|
| - DownloadItem::DownloadState state = download()->GetState();
|
| - canvas->Save();
|
| - int progress_x =
|
| - base::i18n::IsRTL()
|
| - ? width() - kStartPadding - DownloadShelf::kProgressIndicatorSize
|
| - : kStartPadding;
|
| - int progress_y = (height() - DownloadShelf::kProgressIndicatorSize) / 2;
|
| - canvas->Translate(gfx::Vector2d(progress_x, progress_y));
|
| -
|
| - if (state == DownloadItem::IN_PROGRESS) {
|
| - base::TimeDelta progress_time = previous_progress_elapsed_;
|
| - if (!download()->IsPaused())
|
| - progress_time += base::TimeTicks::Now() - progress_start_time_;
|
| - DownloadShelf::PaintDownloadProgress(
|
| - canvas, *GetThemeProvider(), progress_time, model_.PercentComplete());
|
| - } else if (complete_animation_.get() && complete_animation_->is_animating()) {
|
| - if (state == DownloadItem::INTERRUPTED) {
|
| - DownloadShelf::PaintDownloadInterrupted(
|
| - canvas, *GetThemeProvider(), complete_animation_->GetCurrentValue());
|
| - } else {
|
| - DCHECK_EQ(DownloadItem::COMPLETE, state);
|
| - DownloadShelf::PaintDownloadComplete(
|
| - canvas, *GetThemeProvider(), complete_animation_->GetCurrentValue());
|
| - }
|
| - }
|
| - canvas->Restore();
|
| -
|
| - // Fetch the already-loaded icon.
|
| - IconManager* im = g_browser_process->icon_manager();
|
| - gfx::Image* icon = im->LookupIconFromFilepath(download()->GetTargetFilePath(),
|
| - IconLoader::SMALL);
|
| - if (!icon)
|
| - return;
|
| -
|
| - // Draw the icon image.
|
| - int icon_x = progress_x + DownloadShelf::kFiletypeIconOffset;
|
| - int icon_y = progress_y + DownloadShelf::kFiletypeIconOffset;
|
| - SkPaint paint;
|
| - // Use an alpha to make the image look disabled.
|
| - if (!enabled())
|
| - paint.setAlpha(120);
|
| - canvas->DrawImageInt(*icon->ToImageSkia(), icon_x, icon_y, paint);
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnFocus() {
|
| - View::OnFocus();
|
| - // We render differently when focused.
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void DownloadItemViewMd::OnBlur() {
|
| - View::OnBlur();
|
| - // We render differently when focused.
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void DownloadItemViewMd::OpenDownload() {
|
| - DCHECK(!IsShowingWarningDialog());
|
| - // We're interested in how long it takes users to open downloads. If they
|
| - // open downloads super quickly, we should be concerned about clickjacking.
|
| - UMA_HISTOGRAM_LONG_TIMES("clickjacking.open_download",
|
| - base::Time::Now() - creation_time_);
|
| -
|
| - UpdateAccessibleName();
|
| -
|
| - // Calling download()->OpenDownload may delete this, so this must be
|
| - // the last thing we do.
|
| - download()->OpenDownload();
|
| -}
|
| -
|
| -bool DownloadItemViewMd::SubmitDownloadToFeedbackService() {
|
| -#if defined(FULL_SAFE_BROWSING)
|
| - safe_browsing::SafeBrowsingService* sb_service =
|
| - g_browser_process->safe_browsing_service();
|
| - if (!sb_service)
|
| - return false;
|
| - safe_browsing::DownloadProtectionService* download_protection_service =
|
| - sb_service->download_protection_service();
|
| - if (!download_protection_service)
|
| - return false;
|
| - download_protection_service->feedback_service()->BeginFeedbackForDownload(
|
| - download());
|
| - // WARNING: we are deleted at this point. Don't access 'this'.
|
| - return true;
|
| -#else
|
| - NOTREACHED();
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -void DownloadItemViewMd::PossiblySubmitDownloadToFeedbackService(bool enabled) {
|
| - if (!enabled || !SubmitDownloadToFeedbackService())
|
| - download()->Remove();
|
| - // WARNING: 'this' is deleted at this point. Don't access 'this'.
|
| -}
|
| -
|
| -void DownloadItemViewMd::LoadIcon() {
|
| - IconManager* im = g_browser_process->icon_manager();
|
| - last_download_item_path_ = download()->GetTargetFilePath();
|
| - im->LoadIcon(last_download_item_path_, IconLoader::SMALL,
|
| - base::Bind(&DownloadItemViewMd::OnExtractIconComplete,
|
| - base::Unretained(this)),
|
| - &cancelable_task_tracker_);
|
| -}
|
| -
|
| -void DownloadItemViewMd::LoadIconIfItemPathChanged() {
|
| - base::FilePath current_download_path = download()->GetTargetFilePath();
|
| - if (last_download_item_path_ == current_download_path)
|
| - return;
|
| -
|
| - LoadIcon();
|
| -}
|
| -
|
| -void DownloadItemViewMd::UpdateColorsFromTheme() {
|
| - if (!GetThemeProvider())
|
| - return;
|
| -
|
| - SetBorder(base::MakeUnique<SeparatorBorder>(GetThemeProvider()->GetColor(
|
| - ThemeProperties::COLOR_TOOLBAR_VERTICAL_SEPARATOR)));
|
| -
|
| - SkColor text_color = GetTextColor();
|
| - if (dangerous_download_label_)
|
| - dangerous_download_label_->SetEnabledColor(text_color);
|
| - if (save_button_)
|
| - save_button_->SetEnabledTextColors(text_color);
|
| - if (discard_button_)
|
| - discard_button_->SetEnabledTextColors(text_color);
|
| -}
|
| -
|
| -void DownloadItemViewMd::ShowContextMenuImpl(const gfx::Rect& rect,
|
| - ui::MenuSourceType source_type) {
|
| - // Similar hack as in MenuButton.
|
| - // We're about to show the menu from a mouse press. By showing from the
|
| - // mouse press event we block RootView in mouse dispatching. This also
|
| - // appears to cause RootView to get a mouse pressed BEFORE the mouse
|
| - // release is seen, which means RootView sends us another mouse press no
|
| - // matter where the user pressed. To force RootView to recalculate the
|
| - // mouse target during the mouse press we explicitly set the mouse handler
|
| - // to NULL.
|
| - static_cast<views::internal::RootView*>(GetWidget()->GetRootView())
|
| - ->SetMouseHandler(NULL);
|
| -
|
| - if (!context_menu_.get())
|
| - context_menu_.reset(new DownloadShelfContextMenuView(download()));
|
| - context_menu_->Run(GetWidget()->GetTopLevelWidget(), rect, source_type,
|
| - base::Bind(&DownloadItemViewMd::ReleaseDropdown,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| -}
|
| -
|
| -void DownloadItemViewMd::HandlePressEvent(const ui::LocatedEvent& event,
|
| - bool active_event) {
|
| - // The event should not activate us in dangerous/malicious mode.
|
| - if (IsShowingWarningDialog())
|
| - return;
|
| -
|
| - // Stop any completion animation.
|
| - if (complete_animation_.get() && complete_animation_->is_animating())
|
| - complete_animation_->End();
|
| -
|
| - // Don't show the ripple for right clicks.
|
| - if (!active_event)
|
| - return;
|
| -
|
| - AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
|
| -}
|
| -
|
| -void DownloadItemViewMd::HandleClickEvent(const ui::LocatedEvent& event,
|
| - bool active_event) {
|
| - // The event should not activate us in dangerous/malicious mode.
|
| - if (!active_event || IsShowingWarningDialog())
|
| - return;
|
| -
|
| - AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, &event);
|
| -
|
| - // OpenDownload may delete this, so don't add any code after this line.
|
| - OpenDownload();
|
| -}
|
| -
|
| -void DownloadItemViewMd::SetDropdownState(State new_state) {
|
| - // Avoid extra SchedulePaint()s if the state is going to be the same and
|
| - // |dropdown_button_| has already been initialized.
|
| - if (dropdown_state_ == new_state &&
|
| - !dropdown_button_->GetImage(views::CustomButton::STATE_NORMAL).isNull())
|
| - return;
|
| -
|
| - dropdown_button_->SetIcon(new_state == PUSHED ? gfx::VectorIconId::FIND_NEXT
|
| - : gfx::VectorIconId::FIND_PREV);
|
| - if (new_state != dropdown_state_) {
|
| - dropdown_button_->AnimateInkDrop(new_state == PUSHED
|
| - ? views::InkDropState::ACTIVATED
|
| - : views::InkDropState::DEACTIVATED);
|
| - }
|
| - dropdown_button_->OnThemeChanged();
|
| - dropdown_state_ = new_state;
|
| - SchedulePaint();
|
| -}
|
| -
|
| -void DownloadItemViewMd::ToggleWarningDialog() {
|
| - if (model_.IsDangerous())
|
| - ShowWarningDialog();
|
| - else
|
| - ClearWarningDialog();
|
| -
|
| - // We need to load the icon now that the download has the real path.
|
| - LoadIcon();
|
| -
|
| - // Force the shelf to layout again as our size has changed.
|
| - shelf_->Layout();
|
| - shelf_->SchedulePaint();
|
| -}
|
| -
|
| -void DownloadItemViewMd::ClearWarningDialog() {
|
| - DCHECK(download()->GetDangerType() ==
|
| - content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED);
|
| - DCHECK(IsShowingWarningDialog());
|
| -
|
| - mode_ = NORMAL_MODE;
|
| - dropdown_state_ = NORMAL;
|
| -
|
| - // ExperienceSampling: User proceeded through the warning.
|
| - if (sampling_event_.get()) {
|
| - sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed);
|
| - sampling_event_.reset(NULL);
|
| - }
|
| - // Remove the views used by the warning dialog.
|
| - if (save_button_) {
|
| - RemoveChildView(save_button_);
|
| - delete save_button_;
|
| - save_button_ = NULL;
|
| - }
|
| - RemoveChildView(discard_button_);
|
| - delete discard_button_;
|
| - discard_button_ = NULL;
|
| - RemoveChildView(dangerous_download_label_);
|
| - delete dangerous_download_label_;
|
| - dangerous_download_label_ = NULL;
|
| - dangerous_download_label_sized_ = false;
|
| -
|
| - // We need to load the icon now that the download has the real path.
|
| - LoadIcon();
|
| -
|
| - dropdown_button_->SetVisible(true);
|
| -}
|
| -
|
| -void DownloadItemViewMd::ShowWarningDialog() {
|
| - DCHECK(mode_ != DANGEROUS_MODE && mode_ != MALICIOUS_MODE);
|
| - time_download_warning_shown_ = base::Time::Now();
|
| - content::DownloadDangerType danger_type = download()->GetDangerType();
|
| - RecordDangerousDownloadWarningShown(danger_type);
|
| -#if defined(FULL_SAFE_BROWSING)
|
| - if (model_.ShouldAllowDownloadFeedback()) {
|
| - safe_browsing::DownloadFeedbackService::RecordEligibleDownloadShown(
|
| - danger_type);
|
| - }
|
| -#endif
|
| - mode_ = model_.MightBeMalicious() ? MALICIOUS_MODE : DANGEROUS_MODE;
|
| -
|
| - // ExperienceSampling: Dangerous or malicious download warning is being shown
|
| - // to the user, so we start a new SamplingEvent and track it.
|
| - std::string event_name = model_.MightBeMalicious()
|
| - ? ExperienceSamplingEvent::kMaliciousDownload
|
| - : ExperienceSamplingEvent::kDangerousDownload;
|
| - sampling_event_.reset(new ExperienceSamplingEvent(
|
| - event_name, download()->GetURL(), download()->GetReferrerUrl(),
|
| - download()->GetBrowserContext()));
|
| -
|
| - dropdown_state_ = NORMAL;
|
| - if (mode_ == DANGEROUS_MODE) {
|
| - save_button_ =
|
| - views::MdTextButton::Create(this, model_.GetWarningConfirmButtonText());
|
| - AddChildView(save_button_);
|
| - }
|
| - discard_button_ = views::MdTextButton::Create(
|
| - this, l10n_util::GetStringUTF16(IDS_DISCARD_DOWNLOAD));
|
| - AddChildView(discard_button_);
|
| -
|
| - base::string16 dangerous_label =
|
| - model_.GetWarningText(font_list_, kTextWidth);
|
| - dangerous_download_label_ = new views::Label(dangerous_label);
|
| - dangerous_download_label_->SetMultiLine(true);
|
| - dangerous_download_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
|
| - dangerous_download_label_->SetAutoColorReadabilityEnabled(false);
|
| - AddChildView(dangerous_download_label_);
|
| - SizeLabelToMinWidth();
|
| -
|
| - dropdown_button_->SetVisible(mode_ == MALICIOUS_MODE);
|
| -}
|
| -
|
| -gfx::ImageSkia DownloadItemViewMd::GetWarningIcon() {
|
| - switch (download()->GetDangerType()) {
|
| - case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
|
| - case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
|
| - case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
|
| - case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
|
| - case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
|
| - return gfx::CreateVectorIcon(gfx::VectorIconId::REMOVE_CIRCLE,
|
| - kWarningIconSize,
|
| - gfx::kGoogleRed700);
|
| -
|
| - case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
|
| - case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
|
| - case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
|
| - case content::DOWNLOAD_DANGER_TYPE_MAX:
|
| - NOTREACHED();
|
| - break;
|
| -
|
| - case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
|
| - return gfx::CreateVectorIcon(gfx::VectorIconId::WARNING,
|
| - kWarningIconSize,
|
| - gfx::kGoogleYellow700);
|
| - }
|
| - return gfx::ImageSkia();
|
| -}
|
| -
|
| -gfx::Size DownloadItemViewMd::GetButtonSize() const {
|
| - DCHECK(discard_button_ && (mode_ == MALICIOUS_MODE || save_button_));
|
| - gfx::Size size = discard_button_->GetPreferredSize();
|
| - if (save_button_)
|
| - size.SetToMax(save_button_->GetPreferredSize());
|
| - return size;
|
| -}
|
| -
|
| -// This method computes the minimum width of the label for displaying its text
|
| -// on 2 lines. It just breaks the string in 2 lines on the spaces and keeps the
|
| -// configuration with minimum width.
|
| -void DownloadItemViewMd::SizeLabelToMinWidth() {
|
| - if (dangerous_download_label_sized_)
|
| - return;
|
| -
|
| - base::string16 label_text = dangerous_download_label_->text();
|
| - base::TrimWhitespace(label_text, base::TRIM_ALL, &label_text);
|
| - DCHECK_EQ(base::string16::npos, label_text.find('\n'));
|
| -
|
| - // Make the label big so that GetPreferredSize() is not constrained by the
|
| - // current width.
|
| - dangerous_download_label_->SetBounds(0, 0, 1000, 1000);
|
| -
|
| - // Use a const string from here. BreakIterator requies that text.data() not
|
| - // change during its lifetime.
|
| - const base::string16 original_text(label_text);
|
| - // Using BREAK_WORD can work in most cases, but it can also break
|
| - // lines where it should not. Using BREAK_LINE is safer although
|
| - // slower for Chinese/Japanese. This is not perf-critical at all, though.
|
| - base::i18n::BreakIterator iter(original_text,
|
| - base::i18n::BreakIterator::BREAK_LINE);
|
| - bool status = iter.Init();
|
| - DCHECK(status);
|
| -
|
| - base::string16 prev_text = original_text;
|
| - gfx::Size size = dangerous_download_label_->GetPreferredSize();
|
| - int min_width = size.width();
|
| -
|
| - // Go through the string and try each line break (starting with no line break)
|
| - // searching for the optimal line break position. Stop if we find one that
|
| - // yields one that is less than kDangerousTextWidth wide. This is to prevent
|
| - // a short string (e.g.: "This file is malicious") from being broken up
|
| - // unnecessarily.
|
| - while (iter.Advance() && min_width > kDangerousTextWidth) {
|
| - size_t pos = iter.pos();
|
| - if (pos >= original_text.length())
|
| - break;
|
| - base::string16 current_text = original_text;
|
| - // This can be a low surrogate codepoint, but u_isUWhiteSpace will
|
| - // return false and inserting a new line after a surrogate pair
|
| - // is perfectly ok.
|
| - base::char16 line_end_char = current_text[pos - 1];
|
| - if (u_isUWhiteSpace(line_end_char))
|
| - current_text.replace(pos - 1, 1, 1, base::char16('\n'));
|
| - else
|
| - current_text.insert(pos, 1, base::char16('\n'));
|
| - dangerous_download_label_->SetText(current_text);
|
| - size = dangerous_download_label_->GetPreferredSize();
|
| -
|
| - // If the width is growing again, it means we passed the optimal width spot.
|
| - if (size.width() > min_width) {
|
| - dangerous_download_label_->SetText(prev_text);
|
| - break;
|
| - } else {
|
| - min_width = size.width();
|
| - }
|
| - prev_text = current_text;
|
| - }
|
| -
|
| - dangerous_download_label_->SetSize(size);
|
| - dangerous_download_label_sized_ = true;
|
| -}
|
| -
|
| -void DownloadItemViewMd::Reenable() {
|
| - disabled_while_opening_ = false;
|
| - SetEnabled(true); // Triggers a repaint.
|
| -}
|
| -
|
| -void DownloadItemViewMd::ReleaseDropdown() {
|
| - SetDropdownState(NORMAL);
|
| -}
|
| -
|
| -void DownloadItemViewMd::UpdateAccessibleName() {
|
| - base::string16 new_name;
|
| - if (IsShowingWarningDialog()) {
|
| - new_name = dangerous_download_label_->text();
|
| - } else {
|
| - new_name = status_text_ + base::char16(' ') +
|
| - download()->GetFileNameToReportUser().LossyDisplayName();
|
| - }
|
| -
|
| - // If the name has changed, notify assistive technology that the name
|
| - // has changed so they can announce it immediately.
|
| - if (new_name != accessible_name_) {
|
| - accessible_name_ = new_name;
|
| - NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
|
| - }
|
| -}
|
| -
|
| -void DownloadItemViewMd::AnimateStateTransition(
|
| - State from,
|
| - State to,
|
| - gfx::SlideAnimation* animation) {
|
| - if (from == NORMAL && to == HOT) {
|
| - animation->Show();
|
| - } else if (from == HOT && to == NORMAL) {
|
| - animation->Hide();
|
| - } else if (from != to) {
|
| - animation->Reset((to == HOT) ? 1.0 : 0.0);
|
| - }
|
| -}
|
| -
|
| -void DownloadItemViewMd::ProgressTimerFired() {
|
| - // Only repaint for the indeterminate size case. Otherwise, we'll repaint only
|
| - // when there's an update notified via OnDownloadUpdated().
|
| - if (model_.PercentComplete() < 0)
|
| - SchedulePaint();
|
| -}
|
| -
|
| -SkColor DownloadItemViewMd::GetTextColor() const {
|
| - return GetTextColorForThemeProvider(GetThemeProvider());
|
| -}
|
| -
|
| -SkColor DownloadItemViewMd::GetDimmedTextColor() const {
|
| - return SkColorSetA(GetTextColor(), 0xC7);
|
| -}
|
|
|