blob: 9b2ab864549031573c508020df183f047539a455 [file] [log] [blame]
// Copyright 2018 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 "ash/app_menu/app_menu_model_adapter.h"
#include "ash/app_menu/notification_menu_controller.h"
#include "ash/public/cpp/shelf_model.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/base/ui_base_features.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
namespace ash {
namespace {
// The UMA histogram that logs the commands which are executed on non-app
// context menus.
constexpr char kNonAppContextMenuExecuteCommand[] =
"Apps.ContextMenuExecuteCommand.NotFromApp";
constexpr char kNonAppContextMenuExecuteCommandInTablet[] =
"Apps.ContextMenuExecuteCommand.NotFromApp.TabletMode";
constexpr char kNonAppContextMenuExecuteCommandInClamshell[] =
"Apps.ContextMenuExecuteCommand.NotFromApp.ClamshellMode";
// The UMA histogram that logs the commands which are executed on app context
// menus.
constexpr char kAppContextMenuExecuteCommand[] =
"Apps.ContextMenuExecuteCommand.FromApp";
constexpr char kAppContextMenuExecuteCommandInTablet[] =
"Apps.ContextMenuExecuteCommand.FromApp.TabletMode";
constexpr char kAppContextMenuExecuteCommandInClamshell[] =
"Apps.ContextMenuExecuteCommand.FromApp.ClamshellMode";
} // namespace
AppMenuModelAdapter::AppMenuModelAdapter(
const std::string& app_id,
std::unique_ptr<ui::SimpleMenuModel> model,
views::Widget* widget_owner,
ui::MenuSourceType source_type,
base::OnceClosure on_menu_closed_callback,
bool is_tablet_mode)
: views::MenuModelAdapter(model.get()),
app_id_(app_id),
model_(std::move(model)),
widget_owner_(widget_owner),
source_type_(source_type),
on_menu_closed_callback_(std::move(on_menu_closed_callback)),
is_tablet_mode_(is_tablet_mode) {}
AppMenuModelAdapter::~AppMenuModelAdapter() = default;
void AppMenuModelAdapter::Run(const gfx::Rect& menu_anchor_rect,
views::MenuAnchorPosition menu_anchor_position,
int run_types) {
DCHECK(!root_);
DCHECK(model_);
menu_open_time_ = base::TimeTicks::Now();
root_ = CreateMenu();
if (features::IsNotificationIndicatorEnabled()) {
notification_menu_controller_ =
std::make_unique<NotificationMenuController>(app_id_, root_, this);
}
menu_runner_ = std::make_unique<views::MenuRunner>(root_, run_types);
menu_runner_->RunMenuAt(widget_owner_, nullptr /* MenuButtonController */,
menu_anchor_rect, menu_anchor_position, source_type_);
}
bool AppMenuModelAdapter::IsShowingMenu() const {
return menu_runner_ && menu_runner_->IsRunning();
}
void AppMenuModelAdapter::Cancel() {
if (!IsShowingMenu())
return;
menu_runner_->Cancel();
}
base::TimeTicks AppMenuModelAdapter::GetClosingEventTime() {
DCHECK(menu_runner_);
return menu_runner_->closing_event_time();
}
void AppMenuModelAdapter::ExecuteCommand(int id, int mouse_event_flags) {
views::MenuModelAdapter::ExecuteCommand(id, mouse_event_flags);
RecordExecuteCommandHistogram(id);
}
void AppMenuModelAdapter::OnMenuClosed(views::MenuItemView* menu) {
DCHECK_NE(base::TimeTicks(), menu_open_time_);
RecordHistogramOnMenuClosed();
if (on_menu_closed_callback_)
std::move(on_menu_closed_callback_).Run();
}
void AppMenuModelAdapter::RecordExecuteCommandHistogram(int command_id) {
const bool is_not_from_app = app_id().empty();
base::UmaHistogramSparse(is_not_from_app ? kNonAppContextMenuExecuteCommand
: kAppContextMenuExecuteCommand,
command_id);
if (is_tablet_mode_) {
base::UmaHistogramSparse(is_not_from_app
? kNonAppContextMenuExecuteCommandInTablet
: kAppContextMenuExecuteCommandInTablet,
command_id);
} else {
base::UmaHistogramSparse(is_not_from_app
? kNonAppContextMenuExecuteCommandInClamshell
: kAppContextMenuExecuteCommandInClamshell,
command_id);
}
}
} // namespace ash