Commit 6914e751 authored by Richard Knoll's avatar Richard Knoll Committed by Commit Bot

Add omnibox icon for Click to Call bubble.

This adds an icon in the omnibox via PageActionIconView. This is the
ancher point of the Click to Call bubble dialog.

Bug: 972059
Change-Id: I69aeb6bfcfd47082ad1a3460d58c2dd107746353
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1695551Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Commit-Queue: Richard Knoll <knollr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#678261}
parent 9ed93eaa
......@@ -2974,6 +2974,8 @@ jumbo_split_static_library("ui") {
"views/session_crashed_bubble_view.h",
"views/sharing/click_to_call/click_to_call_dialog_view.cc",
"views/sharing/click_to_call/click_to_call_dialog_view.h",
"views/sharing/click_to_call/click_to_call_icon_view.cc",
"views/sharing/click_to_call/click_to_call_icon_view.h",
"views/simple_message_box_views.cc",
"views/simple_message_box_views.h",
"views/status_bubble_views.cc",
......
......@@ -54,6 +54,7 @@ void UpdatePageActionIcon(PageActionIconType icon_type,
->GetOmniboxPageActionIconContainer()
->UpdatePageActionIcon(icon_type);
break;
case PageActionIconType::kClickToCall:
case PageActionIconType::kFind:
case PageActionIconType::kIntentPicker:
case PageActionIconType::kNativeFileSystemAccess:
......
......@@ -19,6 +19,7 @@ enum class PageActionIconType {
kTranslate,
kZoom,
kNativeFileSystemAccess,
kClickToCall,
};
class PageActionIconContainer {
......
......@@ -26,6 +26,7 @@
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h"
#include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h"
#include "chrome/browser/sharing/click_to_call/feature.h"
#include "chrome/browser/ssl/security_state_tab_helper.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service.h"
......@@ -229,6 +230,8 @@ void LocationBarView::Init() {
// the left most icon.
if (send_tab_to_self::IsSendingEnabled())
params.types_enabled.push_back(PageActionIconType::kSendTabToSelf);
if (base::FeatureList::IsEnabled(kClickToCallUI))
params.types_enabled.push_back(PageActionIconType::kClickToCall);
if (!base::FeatureList::IsEnabled(
autofill::features::kAutofillEnableToolbarStatusChip)) {
params.types_enabled.push_back(PageActionIconType::kManagePasswords);
......
......@@ -15,6 +15,7 @@
#include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h"
#include "chrome/browser/ui/views/reader_mode/reader_mode_icon_view.h"
#include "chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.h"
#include "chrome/browser/ui/views/sharing/click_to_call/click_to_call_icon_view.h"
#include "chrome/browser/ui/views/translate/translate_icon_view.h"
#include "ui/views/layout/box_layout.h"
......@@ -86,6 +87,11 @@ OmniboxPageActionIconContainerView::OmniboxPageActionIconContainerView(
params.page_action_icon_delegate);
page_action_icons_.push_back(native_file_system_icon_);
break;
case PageActionIconType::kClickToCall:
click_to_call_icon_view_ =
new ClickToCallIconView(params.page_action_icon_delegate);
page_action_icons_.push_back(click_to_call_icon_view_);
break;
case PageActionIconType::kLocalCardMigration:
case PageActionIconType::kSaveCard:
NOTREACHED();
......@@ -132,6 +138,8 @@ PageActionIconView* OmniboxPageActionIconContainerView::GetPageActionIconView(
return send_tab_to_self_icon_view_;
case PageActionIconType::kNativeFileSystemAccess:
return native_file_system_icon_;
case PageActionIconType::kClickToCall:
return click_to_call_icon_view_;
case PageActionIconType::kLocalCardMigration:
case PageActionIconType::kSaveCard:
NOTREACHED();
......
......@@ -16,6 +16,7 @@
#include "ui/views/view.h"
class Browser;
class ClickToCallIconView;
class CommandUpdater;
class FindBarIcon;
class IntentPickerView;
......@@ -92,6 +93,7 @@ class OmniboxPageActionIconContainerView
TranslateIconView* translate_icon_ = nullptr;
NativeFileSystemAccessIconView* native_file_system_icon_ = nullptr;
ReaderModeIconView* reader_mode_icon_ = nullptr;
ClickToCallIconView* click_to_call_icon_view_ = nullptr;
std::vector<PageActionIconView*> page_action_icons_;
ScopedObserver<zoom::ZoomEventManager, zoom::ZoomEventManagerObserver>
......
......@@ -5,7 +5,12 @@
#include "chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/hover_button.h"
#include "chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
......@@ -13,6 +18,9 @@
#include "base/logging.h"
namespace {
// Global instance of the bubble view.
ClickToCallDialogView* g_bubble_ = nullptr;
// Icon sizes in DIP.
// TODO: Confirm the number with the team designer.
constexpr int kPrimaryIconSize = 20;
......@@ -44,6 +52,35 @@ std::unique_ptr<views::ImageView> CreateDeviceIcon(
} // namespace
// static
ClickToCallDialogView* ClickToCallDialogView::GetBubbleView() {
return g_bubble_;
}
// static
void ClickToCallDialogView::Show(
content::WebContents* web_contents,
std::unique_ptr<ClickToCallSharingDialogController> controller) {
Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
if (g_bubble_ || !browser)
return;
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
views::View* anchor_view =
browser_view->toolbar_button_provider()->GetAnchorView();
PageActionIconView* icon =
browser_view->toolbar_button_provider()
->GetOmniboxPageActionIconContainerView()
->GetPageActionIconView(PageActionIconType::kClickToCall);
g_bubble_ = new ClickToCallDialogView(anchor_view, icon, web_contents,
std::move(controller));
views::BubbleDialogDelegateView::CreateBubble(g_bubble_)->Show();
icon->Update();
DCHECK(icon->GetVisible());
}
ClickToCallDialogView::ClickToCallDialogView(
views::View* anchor_view,
PageActionIconView* icon_view,
......@@ -143,3 +180,9 @@ bool ClickToCallDialogView::ShouldShowCloseButton() const {
base::string16 ClickToCallDialogView::GetWindowTitle() const {
return base::UTF8ToUTF16(controller_->GetTitle());
}
void ClickToCallDialogView::WindowClosing() {
DCHECK_EQ(g_bubble_, this);
g_bubble_ = nullptr;
icon_view_->Update();
}
......@@ -6,28 +6,28 @@
#define CHROME_BROWSER_UI_VIEWS_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_DIALOG_VIEW_H_
#include <memory>
#include <string>
#include <vector>
#include "chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h"
#include "chrome/browser/sharing/sharing_device_info.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/hover_button.h"
#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
#include "chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h"
#include "ui/views/controls/button/button.h"
namespace views {
class View;
} // namespace views
class HoverButton;
class PageActionIconView;
class ClickToCallDialogView : public views::ButtonListener,
public LocationBarBubbleDelegateView {
public:
static ClickToCallDialogView* GetBubbleView();
static void Show(
content::WebContents* web_contents,
std::unique_ptr<ClickToCallSharingDialogController> controller);
// Bubble will be anchored to |anchor_view|.
ClickToCallDialogView(
views::View* anchor_view,
......@@ -40,6 +40,7 @@ class ClickToCallDialogView : public views::ButtonListener,
// views::WidgetDelegateView:
bool ShouldShowCloseButton() const override;
base::string16 GetWindowTitle() const override;
void WindowClosing() override;
// views::DialogDelegate:
int GetDialogButtons() const override;
......
......@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/simple_test_clock.h"
#include "chrome/browser/ui/views/hover_button.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/views/chrome_views_test_base.h"
#include "components/send_tab_to_self/target_device_info.h"
......
// 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/sharing/click_to_call/click_to_call_icon_view.h"
#include <algorithm>
#include "base/memory/ptr_util.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/animation/ink_drop.h"
namespace {
// Height of the loader bar in DIP.
constexpr float kLoaderHeight = 4.0f;
// Width of the loader bar in percent of its range.
constexpr float kLoaderWidth = 0.2f;
} // namespace
ClickToCallIconView::ClickToCallIconView(PageActionIconView::Delegate* delegate)
: PageActionIconView(/*command_updater=*/nullptr,
/*command_id=*/0,
delegate) {
SetVisible(false);
UpdateLoaderColor();
}
ClickToCallIconView::~ClickToCallIconView() = default;
views::BubbleDialogDelegateView* ClickToCallIconView::GetBubble() const {
return ClickToCallDialogView::GetBubbleView();
}
bool ClickToCallIconView::Update() {
const bool is_bubble_showing = IsBubbleShowing();
const bool is_visible = is_bubble_showing || loading_animation_;
const bool visibility_changed = GetVisible() != is_visible;
SetVisible(is_visible);
UpdateInkDrop(is_bubble_showing);
return visibility_changed;
}
void ClickToCallIconView::StartLoadingAnimation() {
if (loading_animation_)
return;
loading_animation_ = std::make_unique<gfx::ThrobAnimation>(this);
loading_animation_->SetTweenType(gfx::Tween::LINEAR);
loading_animation_->SetThrobDuration(750);
loading_animation_->StartThrobbing(-1);
SchedulePaint();
}
void ClickToCallIconView::StopLoadingAnimation() {
if (!loading_animation_)
return;
loading_animation_.reset();
SchedulePaint();
}
void ClickToCallIconView::PaintButtonContents(gfx::Canvas* canvas) {
PageActionIconView::PaintButtonContents(canvas);
if (!loading_animation_)
return;
// TODO(knollr): Add support for this animation to PageActionIconView if other
// features need it as well.
gfx::ScopedCanvas scoped_canvas(canvas);
const float scale = canvas->UndoDeviceScaleFactor();
const gfx::Rect icon_bounds =
gfx::ScaleToEnclosedRect(image()->bounds(), scale);
const float progress = loading_animation_->GetCurrentValue();
const float range = icon_bounds.width();
const float offset = icon_bounds.x();
// Calculate start and end in percent of range.
float start = std::max(0.0f, (progress - kLoaderWidth) / (1 - kLoaderWidth));
float end = std::min(1.0f, progress / (1 - kLoaderWidth));
// Convert percentages to actual location.
start = start * (range - kLoaderHeight);
end = end * (range - kLoaderHeight) + kLoaderHeight;
gfx::RectF bounds(start + offset, icon_bounds.bottom() - kLoaderHeight,
end - start, kLoaderHeight);
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(loader_color_);
canvas->DrawRoundRect(bounds, bounds.height() / 2, flags);
}
void ClickToCallIconView::AnimationProgressed(const gfx::Animation* animation) {
if (animation != loading_animation_.get())
return PageActionIconView::AnimationProgressed(animation);
SchedulePaint();
}
void ClickToCallIconView::OnThemeChanged() {
PageActionIconView::OnThemeChanged();
UpdateLoaderColor();
}
void ClickToCallIconView::UpdateInkDrop(bool activate) {
auto target_state =
activate ? views::InkDropState::ACTIVATED : views::InkDropState::HIDDEN;
if (GetInkDrop()->GetTargetInkDropState() != target_state)
AnimateInkDrop(target_state, /*event=*/nullptr);
}
void ClickToCallIconView::UpdateLoaderColor() {
loader_color_ = GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ProminentButtonColor);
}
bool ClickToCallIconView::IsTriggerableEvent(const ui::Event& event) {
// We do nothing when the icon is clicked.
return false;
}
void ClickToCallIconView::OnExecuting(
PageActionIconView::ExecuteSource execute_source) {}
const gfx::VectorIcon& ClickToCallIconView::GetVectorIcon() const {
// TODO(crbug.com/972059): Should we have our own icon?
return kSendTabToSelfIcon;
}
base::string16 ClickToCallIconView::GetTextForTooltipAndAccessibleName() const {
return l10n_util::GetStringUTF16(
IDS_BROWSER_SHARING_CLICK_TO_CALL_DIALOG_TITLE_LABEL);
}
// 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_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_ICON_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_ICON_VIEW_H_
#include <memory>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/vector_icon_types.h"
namespace gfx {
class Canvas;
class ThrobAnimation;
} // namespace gfx
namespace ui {
class Event;
} // namespace ui
// The location bar icon to show the click to call bubble where the user can
// choose to send a phone number to a target device or use an OS handler app.
class ClickToCallIconView : public PageActionIconView {
public:
explicit ClickToCallIconView(PageActionIconView::Delegate* delegate);
~ClickToCallIconView() override;
// PageActionIconView:
views::BubbleDialogDelegateView* GetBubble() const override;
bool Update() override;
base::string16 GetTextForTooltipAndAccessibleName() const override;
// views::Button:
void PaintButtonContents(gfx::Canvas* canvas) override;
// views::View:
void OnThemeChanged() override;
void StartLoadingAnimation();
void StopLoadingAnimation();
protected:
// PageActionIconView:
void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
const gfx::VectorIcon& GetVectorIcon() const override;
bool IsTriggerableEvent(const ui::Event& event) override;
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
private:
void UpdateInkDrop(bool activate);
void UpdateLoaderColor();
SkColor loader_color_;
std::unique_ptr<gfx::ThrobAnimation> loading_animation_;
DISALLOW_COPY_AND_ASSIGN(ClickToCallIconView);
};
#endif // CHROME_BROWSER_UI_VIEWS_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_ICON_VIEW_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