Skip to content

Commit

Permalink
Context menu observer for Shared Clipboard.
Browse files Browse the repository at this point in the history
Bug: 992355
Change-Id: I9a61e2f21d7d0492763d444d228c13090d0d4262
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1751982
Reviewed-by: Michael van Ouwerkerk <mvanouwerkerk@chromium.org>
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Nico Weber <thakis@chromium.org>
Commit-Queue: Yasmin Molazadeh <yasmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686464}
  • Loading branch information
Yasmin authored and Commit Bot committed Aug 13, 2019
1 parent a21285f commit ece0791
Show file tree
Hide file tree
Showing 6 changed files with 512 additions and 0 deletions.
2 changes: 2 additions & 0 deletions chrome/app/chrome_command_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@
// Context menu items for Sharing
#define IDC_CONTENT_CONTEXT_SHARING_CLICK_TO_CALL_SINGLE_DEVICE 51030
#define IDC_CONTENT_CONTEXT_SHARING_CLICK_TO_CALL_MULTIPLE_DEVICES 51031
#define IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE 51032
#define IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES 51033

// Context menu items in the status tray
#define IDC_STATUS_TRAY_KEEP_CHROME_RUNNING_IN_BACKGROUND 51100
Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -3367,6 +3367,8 @@ jumbo_split_static_library("browser") {
"sharing/click_to_call/click_to_call_ui_controller.h",
"sharing/click_to_call/click_to_call_utils.cc",
"sharing/click_to_call/click_to_call_utils.h",
"sharing/shared_clipboard/shared_clipboard_context_menu_observer.cc",
"sharing/shared_clipboard/shared_clipboard_context_menu_observer.h",
"sharing/shared_clipboard/shared_clipboard_ui_controller.cc",
"sharing/shared_clipboard/shared_clipboard_ui_controller.h",
"sharing/sharing_dialog.h",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// 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/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h"

#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
#include "chrome/browser/sharing/shared_clipboard/feature_flags.h"
#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h"
#include "chrome/browser/sharing/sharing_constants.h"
#include "chrome/browser/sharing/sharing_metrics.h"
#include "chrome/browser/sharing/sharing_service.h"
#include "chrome/browser/sharing/sharing_service_factory.h"
#include "chrome/grit/generated_resources.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/native_theme/native_theme.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/views/controls/menu/menu_config.h"

SharedClipboardContextMenuObserver::SubMenuDelegate::SubMenuDelegate(
SharedClipboardContextMenuObserver* parent)
: parent_(parent) {}

SharedClipboardContextMenuObserver::SubMenuDelegate::~SubMenuDelegate() =
default;

bool SharedClipboardContextMenuObserver::SubMenuDelegate::IsCommandIdEnabled(
int command_id) const {
// All supported commands are enabled in sub menu.
return true;
}

void SharedClipboardContextMenuObserver::SubMenuDelegate::ExecuteCommand(
int command_id,
int event_flags) {
if (command_id < kSubMenuFirstDeviceCommandId ||
command_id > kSubMenuLastDeviceCommandId)
return;
int device_index = command_id - kSubMenuFirstDeviceCommandId;
parent_->SendSharedClipboardMessage(device_index);
}

SharedClipboardContextMenuObserver::SharedClipboardContextMenuObserver(
RenderViewContextMenuProxy* proxy)
: proxy_(proxy),
sharing_service_(SharingServiceFactory::GetForBrowserContext(
proxy_->GetBrowserContext())) {}

SharedClipboardContextMenuObserver::~SharedClipboardContextMenuObserver() =
default;

void SharedClipboardContextMenuObserver::InitMenu(
const content::ContextMenuParams& params) {
text_ = params.selection_text;
devices_ = sharing_service_->GetDeviceCandidates(
static_cast<int>(SharingDeviceCapability::kNone));
// TODO(yasmo): add logging

if (devices_.empty())
return;

proxy_->AddSeparator();
if (devices_.size() == 1) {
#if defined(OS_MACOSX)
proxy_->AddMenuItem(
IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE,
l10n_util::GetStringFUTF16(
IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET,
devices_[0].human_readable_name()));
#else
proxy_->AddMenuItemWithIcon(
IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE,
l10n_util::GetStringFUTF16(
IDS_CONTEXT_MENU_SEND_TAB_TO_SELF_SINGLE_TARGET,
devices_[0].human_readable_name()),
GetContextMenuIcon());
#endif
} else {
BuildSubMenu();
#if defined(OS_MACOSX)
proxy_->AddSubMenu(
IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES,
l10n_util::GetStringUTF16(IDS_CONTEXT_MENU_SEND_TAB_TO_SELF),
sub_menu_model_.get());
#else
proxy_->AddSubMenuWithStringIdAndIcon(
IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES,
IDS_CONTEXT_MENU_SEND_TAB_TO_SELF, sub_menu_model_.get(),
GetContextMenuIcon());
#endif
}
}

void SharedClipboardContextMenuObserver::BuildSubMenu() {
sub_menu_model_ = std::make_unique<ui::SimpleMenuModel>(&sub_menu_delegate_);

int command_id = kSubMenuFirstDeviceCommandId;
for (const auto& device : devices_) {
if (command_id > kSubMenuLastDeviceCommandId)
break;
sub_menu_model_->AddItem(command_id++, device.human_readable_name());
}
}

bool SharedClipboardContextMenuObserver::IsCommandIdSupported(int command_id) {
if (devices_.empty())
return false;

if (devices_.size() == 1) {
return command_id ==
IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE;
} else {
return command_id ==
IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES;
}
}

bool SharedClipboardContextMenuObserver::IsCommandIdEnabled(int command_id) {
// All supported commands are enabled.
return true;
}

void SharedClipboardContextMenuObserver::ExecuteCommand(int command_id) {
if (command_id ==
IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE) {
DCHECK(devices_.size() == 1);
SendSharedClipboardMessage(0);
}
}

void SharedClipboardContextMenuObserver::SendSharedClipboardMessage(
int chosen_device_index) {
if (chosen_device_index >= static_cast<int>(devices_.size()))
return;

// TODO(yasmo): Add logging

SharedClipboardUiController::DeviceSelected(proxy_->GetWebContents(), text_,
devices_[chosen_device_index]);
}

gfx::ImageSkia SharedClipboardContextMenuObserver::GetContextMenuIcon() const {
const ui::NativeTheme* native_theme =
ui::NativeTheme::GetInstanceForNativeUi();
bool is_dark = native_theme && native_theme->ShouldUseDarkColors();
int resource_id = is_dark ? IDR_SEND_TAB_TO_SELF_ICON_DARK
: IDR_SEND_TAB_TO_SELF_ICON_LIGHT;
return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
resource_id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// 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_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_CONTEXT_MENU_OBSERVER_H_
#define CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_CONTEXT_MENU_OBSERVER_H_

#include <memory>
#include <string>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/optional.h"
#include "chrome/browser/sharing/sharing_device_info.h"
#include "components/renderer_context_menu/render_view_context_menu_observer.h"
#include "ui/base/models/simple_menu_model.h"

namespace gfx {
class ImageSkia;
}

class RenderViewContextMenuProxy;

class SharingService;

class SharedClipboardContextMenuObserver
: public RenderViewContextMenuObserver {
public:
class SubMenuDelegate : public ui::SimpleMenuModel::Delegate {
public:
explicit SubMenuDelegate(SharedClipboardContextMenuObserver* parent);
~SubMenuDelegate() override;

bool IsCommandIdEnabled(int command_id) const override;
void ExecuteCommand(int command_id, int event_flags) override;

private:
SharedClipboardContextMenuObserver* const parent_;

DISALLOW_COPY_AND_ASSIGN(SubMenuDelegate);
};

explicit SharedClipboardContextMenuObserver(
RenderViewContextMenuProxy* proxy);
~SharedClipboardContextMenuObserver() override;

// RenderViewContextMenuObserver implementation.
void InitMenu(const content::ContextMenuParams& params) override;
bool IsCommandIdSupported(int command_id) override;
bool IsCommandIdEnabled(int command_id) override;
void ExecuteCommand(int command_id) override;

private:
FRIEND_TEST_ALL_PREFIXES(SharedClipboardContextMenuObserverTest,
SingleDevice_ShowMenu);
FRIEND_TEST_ALL_PREFIXES(SharedClipboardContextMenuObserverTest,
MultipleDevices_ShowMenu);
FRIEND_TEST_ALL_PREFIXES(SharedClipboardContextMenuObserverTest,
MultipleDevices_MoreThanMax_ShowMenu);

void BuildSubMenu();

void SendSharedClipboardMessage(int chosen_device_index);

gfx::ImageSkia GetContextMenuIcon() const;

RenderViewContextMenuProxy* proxy_ = nullptr;

SharingService* sharing_service_ = nullptr;

SubMenuDelegate sub_menu_delegate_{this};

base::string16 text_;

std::vector<SharingDeviceInfo> devices_;

std::unique_ptr<ui::SimpleMenuModel> sub_menu_model_;

DISALLOW_COPY_AND_ASSIGN(SharedClipboardContextMenuObserver);
};

#endif // CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_CONTEXT_MENU_OBSERVER_H_

0 comments on commit ece0791

Please sign in to comment.