blob: 4aa86939aa2b5821058a83b2a413cb4a0ecd84b1 [file] [log] [blame]
// 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/send_tab_to_self/send_tab_to_self_sub_menu_model.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h"
#include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h"
#include "chrome/grit/generated_resources.h"
#include "components/send_tab_to_self/send_tab_to_self_model.h"
#include "components/send_tab_to_self/send_tab_to_self_sync_service.h"
#include "components/send_tab_to_self/target_device_info.h"
#include "content/public/browser/web_contents.h"
namespace send_tab_to_self {
namespace {
// Each item of submenu has its unique command id. These ids should not be same
// with the command ids of items in the menumodel. The range of all command
// ID's used in SendTabToSelfSubMenuModel must be equal or larger than
// |SendTabToSelfSubMenuModel::kMinCommandId| and less than
// |SendTabToSelfSubMenuModel::kMaxCommandId|.
// We assume that the user doesn't have more than 10 devices, if someone has,
// then the device list will only show the first 10 lines.
const int kMaxDevicesShown = 10;
const int kShareTabCommandId = SendTabToSelfSubMenuModel::kMinCommandId;
const int kShareLinkCommandId = 2010;
static_assert(
kShareLinkCommandId - kShareTabCommandId == kMaxDevicesShown,
"The range of command id for sharing tab should be no more than 10.");
const int kMaxCommandId = SendTabToSelfSubMenuModel::kMaxCommandId;
static_assert(
kMaxCommandId - kShareLinkCommandId == kMaxDevicesShown,
"The range of command id for sharing link should be no more than 10.");
// Returns true if the command id identifies a non-link contextual menu item.
bool IsShareTabCommandId(int command_id) {
return command_id >= kShareTabCommandId && command_id < kShareLinkCommandId;
}
// Returns true if the command id identifies a link contextual menu item.
bool IsShareLinkCommandId(int command_id) {
return command_id >= kShareLinkCommandId && command_id < kMaxCommandId;
}
// Converts |command_id| of menu item to index in |valid_device_items_|.
int CommandIdToVectorIndex(int command_id) {
if (IsShareTabCommandId(command_id)) {
return command_id - kShareTabCommandId;
}
if (IsShareLinkCommandId(command_id)) {
return command_id - kShareLinkCommandId;
}
return -1;
}
// Converts menu type to string.
const std::string MenuTypeToString(SendTabToSelfMenuType menu_type) {
switch (menu_type) {
case SendTabToSelfMenuType::kTab:
return kTabMenu;
case SendTabToSelfMenuType::kContent:
return kContentMenu;
case SendTabToSelfMenuType::kOmnibox:
return kOmniboxMenu;
case SendTabToSelfMenuType::kLink:
return kLinkMenu;
default:
NOTREACHED();
}
}
} // namespace
struct SendTabToSelfSubMenuModel::ValidDeviceItem {
ValidDeviceItem(const std::string& device_name, const std::string& cache_guid)
: device_name(device_name), cache_guid(cache_guid) {}
std::string device_name;
std::string cache_guid;
};
SendTabToSelfSubMenuModel::SendTabToSelfSubMenuModel(
content::WebContents* tab,
SendTabToSelfMenuType menu_type)
: SendTabToSelfSubMenuModel(tab, menu_type, GURL()) {}
SendTabToSelfSubMenuModel::SendTabToSelfSubMenuModel(
content::WebContents* tab,
SendTabToSelfMenuType menu_type,
const GURL& link_url)
: ui::SimpleMenuModel(this),
tab_(tab),
menu_type_(menu_type),
link_url_(link_url) {
Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext());
Build(profile);
}
SendTabToSelfSubMenuModel::~SendTabToSelfSubMenuModel() {}
bool SendTabToSelfSubMenuModel::IsCommandIdEnabled(int command_id) const {
// Only valid device names are shown, so all items are enabled.
return true;
}
void SendTabToSelfSubMenuModel::ExecuteCommand(int command_id,
int event_flags) {
int vector_index = CommandIdToVectorIndex(command_id);
if (vector_index == -1) {
return;
}
const ValidDeviceItem& item = valid_device_items_[vector_index];
if (menu_type_ == SendTabToSelfMenuType::kLink) {
// Is sharing a link from link menu.
CreateNewEntry(tab_, item.device_name, item.cache_guid, link_url_);
} else {
// Is sharing a tab from tab menu, content menu or omnibox menu.
CreateNewEntry(tab_, item.device_name, item.cache_guid);
}
RecordSendTabToSelfClickResult(MenuTypeToString(menu_type_),
SendTabToSelfClickResult::kClickItem);
return;
}
void SendTabToSelfSubMenuModel::OnMenuWillShow(ui::SimpleMenuModel* source) {
RecordSendTabToSelfClickResult(MenuTypeToString(menu_type_),
SendTabToSelfClickResult::kShowDeviceList);
RecordSendTabToSelfDeviceCount(MenuTypeToString(menu_type_),
valid_device_items_.size());
}
void SendTabToSelfSubMenuModel::Build(Profile* profile) {
SendTabToSelfSyncService* service =
SendTabToSelfSyncServiceFactory::GetForProfile(profile);
DCHECK(service);
SendTabToSelfModel* model = service->GetSendTabToSelfModel();
DCHECK(model);
std::vector<TargetDeviceInfo> devices =
model->GetTargetDeviceInfoSortedList();
if (!devices.empty()) {
int index = 0;
for (const auto& item : devices) {
if (index == kMaxDevicesShown) {
return;
}
BuildDeviceItem(item.device_name, item.cache_guid, index++);
}
}
return;
}
void SendTabToSelfSubMenuModel::BuildDeviceItem(const std::string& device_name,
const std::string& cache_guid,
int index) {
ValidDeviceItem item(device_name, cache_guid);
int command_id =
((menu_type_ == kTab) ? kShareTabCommandId : kShareLinkCommandId) + index;
InsertItemAt(index, command_id, base::UTF8ToUTF16(device_name));
valid_device_items_.push_back(item);
}
} // namespace send_tab_to_self