Commit c9f06c79 authored by Xiaoqian Dai's avatar Xiaoqian Dai Committed by Commit Bot

back gesture contextual nudge showup logic

- The back gesture contextual nudge ui will appear when a user navigates
to the second page within any Chrome apps in tablet mode.

Show frequency:
  * It only shows once per active day for over 3 days per user
  * and the user hasn't been done back gesture successfully for 7 times

Bug: 1009005b
Change-Id: Ide2dbf46be1dfcd0963d4466448f5a6ff5d62f9d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2062917
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742778}
parent 3a586091
......@@ -1195,6 +1195,8 @@ component("ash") {
"wm/gestures/back_gesture/back_gesture_affordance.h",
"wm/gestures/back_gesture/back_gesture_contextual_nudge.cc",
"wm/gestures/back_gesture/back_gesture_contextual_nudge.h",
"wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.cc",
"wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.h",
"wm/gestures/back_gesture/back_gesture_event_handler.cc",
"wm/gestures/back_gesture/back_gesture_event_handler.h",
"wm/gestures/back_gesture/back_gesture_metrics.cc",
......@@ -2379,6 +2381,8 @@ static_library("test_support") {
"wm/cursor_manager_test_api.h",
"wm/desks/desks_test_util.cc",
"wm/desks/desks_test_util.h",
"wm/gestures/back_gesture/test_back_gesture_contextual_nudge_delegate.cc",
"wm/gestures/back_gesture/test_back_gesture_contextual_nudge_delegate.h",
"wm/lock_state_controller_test_api.cc",
"wm/lock_state_controller_test_api.h",
"wm/splitview/multi_display_overview_and_split_view_test.cc",
......
......@@ -83,6 +83,8 @@ component("cpp") {
"assistant/proactive_suggestions_client.h",
"assistant/util/histogram_util.cc",
"assistant/util/histogram_util.h",
"back_gesture_contextual_nudge_controller.h",
"back_gesture_contextual_nudge_delegate.h",
"caption_buttons/caption_button_model.h",
"caption_buttons/frame_back_button.cc",
"caption_buttons/frame_back_button.h",
......
// Copyright 2020 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 ASH_PUBLIC_CPP_BACK_GESTURE_CONTEXTUAL_NUDGE_CONTROLLER_H_
#define ASH_PUBLIC_CPP_BACK_GESTURE_CONTEXTUAL_NUDGE_CONTROLLER_H_
#include "ash/public/cpp/ash_public_export.h"
namespace aura {
class Window;
}
namespace ash {
// Used by Chrome to notify the navigation status change and update back
// gesture contextual nudge Ui in ash.
class ASH_PUBLIC_EXPORT BackGestureContextualNudgeController {
public:
BackGestureContextualNudgeController() = default;
virtual ~BackGestureContextualNudgeController() = default;
// Called when |window|'s navigation entry changed.
virtual void NavigationEntryChanged(aura::Window* window) = 0;
};
} // namespace ash
#endif // ASH_PUBLIC_CPP_BACK_GESTURE_CONTEXTUAL_NUDGE_CONTROLLER_H_
// Copyright 2020 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 ASH_PUBLIC_CPP_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
#define ASH_PUBLIC_CPP_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
#include "ash/public/cpp/ash_public_export.h"
namespace aura {
class Window;
}
namespace ash {
// Used by BackGestureContextualNudgeController to communicate with chrome
// side BackGestureContextualNudgeDelegate.
class ASH_PUBLIC_EXPORT BackGestureContextualNudgeDelegate {
public:
BackGestureContextualNudgeDelegate() = default;
virtual ~BackGestureContextualNudgeDelegate() = default;
// Starts tracking navigation status for |window| if applicable.
virtual void MaybeStartTrackingNavigation(aura::Window* window) = 0;
};
} // namespace ash
#endif // ASH_PUBLIC_CPP_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
......@@ -21,6 +21,10 @@ namespace {
constexpr char kShownCount[] = "shown_count";
constexpr char kLastTimeShown[] = "last_time_shown";
// Keys for tooltip sub-preferences of how many times a gesture has been
// successfully performed by the user.
constexpr char kSuccessCount[] = "success_count";
base::Clock* g_clock_override = nullptr;
base::Time GetTime() {
......@@ -33,6 +37,8 @@ std::string TooltipTypeToString(TooltipType type) {
switch (type) {
case TooltipType::kDragHandle:
return "drag_handle";
case TooltipType::kBackGesture:
return "back_gesture";
}
return "invalid";
}
......@@ -43,13 +49,6 @@ std::string GetPath(TooltipType type, const std::string& sub_pref) {
return base::JoinString({TooltipTypeToString(type), sub_pref}, ".");
}
int GetShownCount(PrefService* prefs, TooltipType type) {
base::Optional<int> shown_count =
prefs->GetDictionary(prefs::kContextualTooltips)
->FindIntPath(GetPath(type, kShownCount));
return shown_count.value_or(0);
}
base::Time GetLastShownTime(PrefService* prefs, TooltipType type) {
const base::Value* last_shown_time =
prefs->GetDictionary(prefs::kContextualTooltips)
......@@ -59,6 +58,13 @@ base::Time GetLastShownTime(PrefService* prefs, TooltipType type) {
return *util::ValueToTime(last_shown_time);
}
int GetSuccessCount(PrefService* prefs, TooltipType type) {
base::Optional<int> success_count =
prefs->GetDictionary(prefs::kContextualTooltips)
->FindIntPath(GetPath(type, kSuccessCount));
return success_count.value_or(0);
}
} // namespace
void RegisterProfilePrefs(PrefRegistrySimple* registry) {
......@@ -70,6 +76,9 @@ bool ShouldShowNudge(PrefService* prefs, TooltipType type) {
if (!features::AreContextualNudgesEnabled())
return false;
if (GetSuccessCount(prefs, type) >= kSuccessLimit)
return false;
const int shown_count = GetShownCount(prefs, type);
if (shown_count >= kNotificationLimit)
return false;
......@@ -87,6 +96,13 @@ base::TimeDelta GetNudgeTimeout(PrefService* prefs, TooltipType type) {
return kNudgeShowDuration;
}
int GetShownCount(PrefService* prefs, TooltipType type) {
base::Optional<int> shown_count =
prefs->GetDictionary(prefs::kContextualTooltips)
->FindIntPath(GetPath(type, kShownCount));
return shown_count.value_or(0);
}
void HandleNudgeShown(PrefService* prefs, TooltipType type) {
const int shown_count = GetShownCount(prefs, type);
DictionaryPrefUpdate update(prefs, prefs::kContextualTooltips);
......@@ -94,6 +110,12 @@ void HandleNudgeShown(PrefService* prefs, TooltipType type) {
update->SetPath(GetPath(type, kLastTimeShown), util::TimeToValue(GetTime()));
}
void HandleGesturePerformed(PrefService* prefs, TooltipType type) {
const int success_count = GetSuccessCount(prefs, type);
DictionaryPrefUpdate update(prefs, prefs::kContextualTooltips);
update->SetIntPath(GetPath(type, kSuccessCount), success_count + 1);
}
void OverrideClockForTesting(base::Clock* test_clock) {
DCHECK(!g_clock_override);
g_clock_override = test_clock;
......
......@@ -17,10 +17,13 @@ namespace contextual_tooltip {
// Enumeration of all contextual tooltips.
enum class TooltipType {
kDragHandle,
kBackGesture,
};
// Maximum number of times a user can be shown a contextual nudge.
// Maximum number of times a user can be shown a contextual nudge if the user
// hasn't performed the gesture |kSuccessLimit| times successfully.
constexpr int kNotificationLimit = 3;
constexpr int kSuccessLimit = 7;
// Minimum time between showing contextual nudges to the user.
constexpr base::TimeDelta kMinInterval = base::TimeDelta::FromDays(1);
......@@ -40,10 +43,18 @@ ASH_EXPORT bool ShouldShowNudge(PrefService* prefs, TooltipType type);
ASH_EXPORT base::TimeDelta GetNudgeTimeout(PrefService* prefs,
TooltipType type);
// Returns the number of counts that |type| nudge has been shown for the user
// with the given |prefs|.
ASH_EXPORT int GetShownCount(PrefService* prefs, TooltipType type);
// Increments the counter tracking the number of times the tooltip has been
// shown. Updates the last shown time for the tooltip.
ASH_EXPORT void HandleNudgeShown(PrefService* prefs, TooltipType type);
// Increments the counter tracking the number of times the tooltip's
// correpsonding gesture has been performed successfully.
ASH_EXPORT void HandleGesturePerformed(PrefService* prefs, TooltipType type);
ASH_EXPORT void OverrideClockForTesting(base::Clock* test_clock);
ASH_EXPORT void ClearClockOverrideForTesting();
......
......@@ -9,12 +9,16 @@
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test_shell_delegate.h"
#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/util/values/values_util.h"
#include "base/values.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "ui/aura/window.h"
#include "ui/wm/core/window_util.h"
namespace ash {
......@@ -114,6 +118,46 @@ TEST_P(ContextualTooltipTest, ShouldShowTimedDragHandleNudge) {
TooltipType::kDragHandle));
}
// Tests that if the user has successfully performed the gesture for at least
// |kSuccessLimit|, the corresponding nudge should not be shown.
TEST_P(ContextualTooltipTest, ShouldNotShowNudgeAfterSuccessLimit) {
EXPECT_TRUE(contextual_tooltip::ShouldShowNudge(GetPrefService(),
TooltipType::kDragHandle));
for (int success_count = 0; success_count < contextual_tooltip::kSuccessLimit;
success_count++) {
contextual_tooltip::HandleGesturePerformed(GetPrefService(),
TooltipType::kDragHandle);
}
EXPECT_FALSE(contextual_tooltip::ShouldShowNudge(GetPrefService(),
TooltipType::kDragHandle));
}
// Contextual nudge logic specific to back gesture.
TEST_P(ContextualTooltipTest, BackGestureContextualNudge) {
std::unique_ptr<aura::Window> window1 = CreateTestWindow();
std::unique_ptr<aura::Window> window2 = CreateTestWindow();
// Only show back gesture nudge in tablet mode.
wm::ActivateWindow(window1.get());
EXPECT_EQ(contextual_tooltip::GetShownCount(GetPrefService(),
TooltipType::kBackGesture),
0);
TabletModeControllerTestApi().EnterTabletMode();
wm::ActivateWindow(window2.get());
EXPECT_EQ(contextual_tooltip::GetShownCount(GetPrefService(),
TooltipType::kBackGesture),
1);
// We can only show back gesture nudge ui on windows that can perform "go
// back" operation.
ash_test_helper()->test_shell_delegate()->SetCanGoBack(false);
clock()->Advance(contextual_tooltip::kMinInterval);
EXPECT_EQ(contextual_tooltip::GetShownCount(GetPrefService(),
TooltipType::kBackGesture),
1);
}
} // namespace contextual_tooltip
} // namespace ash
......@@ -769,6 +769,7 @@ Shell::~Shell() {
accessibility_focus_ring_controller_.reset();
policy_recommendation_restorer_.reset();
ime_controller_.reset();
back_gesture_event_handler_.reset();
// Balances the Install() in Initialize().
views::FocusManagerFactory::Install(nullptr);
......
......@@ -8,6 +8,7 @@
#include "ash/accessibility/default_accessibility_delegate.h"
#include "ash/test_screenshot_delegate.h"
#include "ash/wm/gestures/back_gesture/test_back_gesture_contextual_nudge_delegate.h"
namespace ash {
namespace shell {
......@@ -29,6 +30,12 @@ AccessibilityDelegate* ShellDelegateImpl::CreateAccessibilityDelegate() {
return new DefaultAccessibilityDelegate;
}
std::unique_ptr<BackGestureContextualNudgeDelegate>
ShellDelegateImpl::CreateBackGestureContextualNudgeDelegate(
BackGestureContextualNudgeController* controller) {
return std::make_unique<TestBackGestureContextualNudgeDelegate>(controller);
}
bool ShellDelegateImpl::CanGoBack(gfx::NativeWindow window) const {
return true;
}
......
......@@ -23,6 +23,9 @@ class ShellDelegateImpl : public ShellDelegate {
bool CanShowWindowForUser(const aura::Window* window) const override;
std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override;
AccessibilityDelegate* CreateAccessibilityDelegate() override;
std::unique_ptr<BackGestureContextualNudgeDelegate>
CreateBackGestureContextualNudgeDelegate(
BackGestureContextualNudgeController* controller) override;
bool CanGoBack(gfx::NativeWindow window) const override;
void BindNavigableContentsFactory(
mojo::PendingReceiver<content::mojom::NavigableContentsFactory> receiver)
......
......@@ -27,6 +27,8 @@ namespace ash {
class AccessibilityDelegate;
class ScreenshotDelegate;
class BackGestureContextualNudgeDelegate;
class BackGestureContextualNudgeController;
// Delegate of the Shell.
class ASH_EXPORT ShellDelegate {
......@@ -44,6 +46,11 @@ class ASH_EXPORT ShellDelegate {
// Creates a accessibility delegate. Shell takes ownership of the delegate.
virtual AccessibilityDelegate* CreateAccessibilityDelegate() = 0;
// Creates a back gesture contextual nudge delegate for |controller|.
virtual std::unique_ptr<BackGestureContextualNudgeDelegate>
CreateBackGestureContextualNudgeDelegate(
BackGestureContextualNudgeController* controller) = 0;
// Check whether the current tab of the browser window can go back.
virtual bool CanGoBack(gfx::NativeWindow window) const = 0;
......
......@@ -7,6 +7,7 @@
#include "ash/accessibility/default_accessibility_delegate.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "ash/test_screenshot_delegate.h"
#include "ash/wm/gestures/back_gesture/test_back_gesture_contextual_nudge_delegate.h"
#include "base/logging.h"
#include "ui/gfx/image/image.h"
......@@ -29,6 +30,12 @@ AccessibilityDelegate* TestShellDelegate::CreateAccessibilityDelegate() {
return new DefaultAccessibilityDelegate;
}
std::unique_ptr<BackGestureContextualNudgeDelegate>
TestShellDelegate::CreateBackGestureContextualNudgeDelegate(
BackGestureContextualNudgeController* controller) {
return std::make_unique<TestBackGestureContextualNudgeDelegate>(controller);
}
bool TestShellDelegate::CanGoBack(gfx::NativeWindow window) const {
return can_go_back_;
}
......
......@@ -33,6 +33,9 @@ class TestShellDelegate : public ShellDelegate {
bool CanShowWindowForUser(const aura::Window* window) const override;
std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override;
AccessibilityDelegate* CreateAccessibilityDelegate() override;
std::unique_ptr<BackGestureContextualNudgeDelegate>
CreateBackGestureContextualNudgeDelegate(
BackGestureContextualNudgeController* controller) override;
bool CanGoBack(gfx::NativeWindow window) const override;
void BindNavigableContentsFactory(
mojo::PendingReceiver<content::mojom::NavigableContentsFactory> receiver)
......
......@@ -73,6 +73,7 @@ std::unique_ptr<views::Widget> CreateWidget() {
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
params.z_order = ui::ZOrderLevel::kFloatingWindow;
params.accept_events = false;
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.name = "BackGestureContextualNudge";
params.layer_type = ui::LAYER_NOT_DRAWN;
......
// Copyright 2020 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/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.h"
#include "ash/public/cpp/back_gesture_contextual_nudge_delegate.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/contextual_tooltip.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.h"
#include "ash/wm/window_util.h"
#include "components/prefs/pref_service.h"
#include "ui/wm/public/activation_client.h"
namespace ash {
namespace {
PrefService* GetActivePrefService() {
return Shell::Get()->session_controller()->GetActivePrefService();
}
} // namespace
BackGestureContextualNudgeControllerImpl::
BackGestureContextualNudgeControllerImpl() {
tablet_mode_observer_.Add(Shell::Get()->tablet_mode_controller());
}
BackGestureContextualNudgeControllerImpl::
~BackGestureContextualNudgeControllerImpl() {
if (is_monitoring_windows_) {
nudge_delegate_.reset();
Shell::Get()->activation_client()->RemoveObserver(this);
}
}
void BackGestureContextualNudgeControllerImpl::OnActiveUserSessionChanged(
const AccountId& account_id) {
UpdateWindowMonitoring();
}
void BackGestureContextualNudgeControllerImpl::OnTabletModeStarted() {
UpdateWindowMonitoring();
// If there is an active window at this moment and we should monitor its
// navigation status, start monitoring it.
if (is_monitoring_windows_) {
aura::Window* active_window = window_util::GetActiveWindow();
if (active_window)
nudge_delegate_->MaybeStartTrackingNavigation(active_window);
}
}
void BackGestureContextualNudgeControllerImpl::OnTabletModeEnded() {
UpdateWindowMonitoring();
// TODO: Also cancel in-waiting animation or in-progress animation.
}
void BackGestureContextualNudgeControllerImpl::OnTabletControllerDestroyed() {
tablet_mode_observer_.RemoveAll();
}
void BackGestureContextualNudgeControllerImpl::OnWindowActivated(
ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) {
if (!gained_active)
return;
// TODO: If another window is activated when the nudge is waiting to be shown
// or is currently being shown, cancel the animation.
// Otherwise, start tracking |gained_active|'s navigation status and show the
// contextual nudge ui if applicable.
nudge_delegate_->MaybeStartTrackingNavigation(gained_active);
}
void BackGestureContextualNudgeControllerImpl::NavigationEntryChanged(
aura::Window* window) {
if (Shell::Get()->shell_delegate()->CanGoBack(window) && CanShowNudge())
ShowNudgeUi();
}
bool BackGestureContextualNudgeControllerImpl::CanShowNudge() const {
if (!Shell::Get()->IsInTabletMode())
return false;
return contextual_tooltip::ShouldShowNudge(
GetActivePrefService(), contextual_tooltip::TooltipType::kBackGesture);
}
void BackGestureContextualNudgeControllerImpl::ShowNudgeUi() {
nudge_ = std::make_unique<BackGestureContextualNudge>();
// TODO: Only call HandleNudgeShown after |nudge_| animation is done.
contextual_tooltip::HandleNudgeShown(
GetActivePrefService(), contextual_tooltip::TooltipType::kBackGesture);
UpdateWindowMonitoring();
// Set a timer to monitoring windows and show nudge ui again.
auto_show_timer_.Start(
FROM_HERE, contextual_tooltip::kMinInterval, this,
&BackGestureContextualNudgeControllerImpl::UpdateWindowMonitoring);
}
void BackGestureContextualNudgeControllerImpl::UpdateWindowMonitoring() {
const bool should_monitor = CanShowNudge();
if (is_monitoring_windows_ == should_monitor)
return;
is_monitoring_windows_ = should_monitor;
if (should_monitor) {
// Start monitoring window.
nudge_delegate_ = Shell::Get()
->shell_delegate()
->CreateBackGestureContextualNudgeDelegate(this);
Shell::Get()->activation_client()->AddObserver(this);
return;
}
// Stop monitoring window.
nudge_delegate_.reset();
Shell::Get()->activation_client()->RemoveObserver(this);
}
} // namespace ash
// Copyright 2020 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 ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_CONTEXTUAL_NUDGE_CONTROLLER_IMPL_H_
#define ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_CONTEXTUAL_NUDGE_CONTROLLER_IMPL_H_
#include "ash/ash_export.h"
#include "ash/public/cpp/back_gesture_contextual_nudge_controller.h"
#include "ash/public/cpp/tablet_mode_observer.h"
#include "ash/session/session_observer.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/scoped_observer.h"
#include "base/timer/timer.h"
#include "ui/wm/public/activation_change_observer.h"
namespace aura {
class Window;
}
namespace ash {
class BackGestureContextualNudgeDelegate;
class BackGestureContextualNudge;
// The class to decide when to show/hide back gesture contextual nudge.
class ASH_EXPORT BackGestureContextualNudgeControllerImpl
: public SessionObserver,
public TabletModeObserver,
public wm::ActivationChangeObserver,
public BackGestureContextualNudgeController {
public:
BackGestureContextualNudgeControllerImpl();
BackGestureContextualNudgeControllerImpl(
const BackGestureContextualNudgeControllerImpl&) = delete;
BackGestureContextualNudgeControllerImpl& operator=(
const BackGestureContextualNudgeControllerImpl&) = delete;
~BackGestureContextualNudgeControllerImpl() override;
// SessionObserver:
void OnActiveUserSessionChanged(const AccountId& account_id) override;
// TabletModeObserver:
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
void OnTabletControllerDestroyed() override;
// wm::ActivationChangeObserver:
void OnWindowActivated(ActivationReason reason,
aura::Window* gained_active,
aura::Window* lost_active) override;
// BackGestureContextualNudgeController:
void NavigationEntryChanged(aura::Window* window) override;
private:
// Returns true if we can show back gesture contextual nudge ui in current
// configuration.
bool CanShowNudge() const;
void ShowNudgeUi();
// Starts or stops monitoring windows activation changes to decide if and when
// to show up the contextual nudge ui.
void UpdateWindowMonitoring();
ScopedSessionObserver session_observer_{this};
ScopedObserver<TabletModeController, TabletModeObserver>
tablet_mode_observer_{this};
// The delegate to monitor the current active window's navigation status.
std::unique_ptr<BackGestureContextualNudgeDelegate> nudge_delegate_;
// The nudge widget.
std::unique_ptr<BackGestureContextualNudge> nudge_;
// True if we're currently monitoring window activation changes.
bool is_monitoring_windows_ = false;
// Timer to automatically show nudge ui in 24 hours.
base::OneShotTimer auto_show_timer_;
};
} // namespace ash
#endif // ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_CONTEXTUAL_NUDGE_CONTROLLER_IMPL_H_
......@@ -10,8 +10,10 @@
#include "ash/public/cpp/app_types.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/contextual_tooltip.h"
#include "ash/shell.h"
#include "ash/wm/gestures/back_gesture/back_gesture_affordance.h"
#include "ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/splitview/split_view_divider.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
......@@ -136,6 +138,11 @@ void ActivateUnderneathWindowInSplitViewMode(
BackGestureEventHandler::BackGestureEventHandler()
: gesture_provider_(this, this) {
if (features::AreContextualNudgesEnabled()) {
nudge_controller_ =
std::make_unique<BackGestureContextualNudgeControllerImpl>();
}
display::Screen::GetScreen()->AddObserver(this);
}
......@@ -283,6 +290,11 @@ bool BackGestureEventHandler::MaybeHandleBackGesture(ui::GestureEvent* event,
back_gesture_start_scenario_type_, BackGestureEndType::kBack));
}
back_gesture_affordance_->Complete();
if (features::AreContextualNudgesEnabled()) {
contextual_tooltip::HandleGesturePerformed(
Shell::Get()->session_controller()->GetActivePrefService(),
contextual_tooltip::TooltipType::kBackGesture);
}
} else {
back_gesture_affordance_->Abort();
RecordEndScenarioType(GetEndScenarioType(
......
......@@ -17,6 +17,7 @@ class Window;
namespace ash {
class BackGestureAffordance;
class BackGestureContextualNudgeControllerImpl;
class BackGestureEventHandler : public display::DisplayObserver,
public ui::EventHandler,
......@@ -79,6 +80,9 @@ class BackGestureEventHandler : public display::DisplayObserver,
// previout page.
std::unique_ptr<BackGestureAffordance> back_gesture_affordance_;
// Used to decide when to show/hide the back gesture contextual nudge.
std::unique_ptr<BackGestureContextualNudgeControllerImpl> nudge_controller_;
// True if back gesture dragged from splitview divider.
bool dragged_from_splitview_divider_ = false;
......
// Copyright 2020 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/wm/gestures/back_gesture/test_back_gesture_contextual_nudge_delegate.h"
#include "ash/public/cpp/back_gesture_contextual_nudge_controller.h"
namespace ash {
TestBackGestureContextualNudgeDelegate::TestBackGestureContextualNudgeDelegate(
BackGestureContextualNudgeController* controller)
: controller_(controller) {}
TestBackGestureContextualNudgeDelegate::
~TestBackGestureContextualNudgeDelegate() = default;
void TestBackGestureContextualNudgeDelegate::MaybeStartTrackingNavigation(
aura::Window* window) {
controller_->NavigationEntryChanged(window);
}
} // namespace ash
// Copyright 2020 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 ASH_WM_GESTURES_BACK_GESTURE_TEST_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
#define ASH_WM_GESTURES_BACK_GESTURE_TEST_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
#include "ash/public/cpp/back_gesture_contextual_nudge_delegate.h"
namespace ash {
class BackGestureContextualNudgeController;
class TestBackGestureContextualNudgeDelegate
: public BackGestureContextualNudgeDelegate {
public:
explicit TestBackGestureContextualNudgeDelegate(
BackGestureContextualNudgeController* controller);
TestBackGestureContextualNudgeDelegate(
const TestBackGestureContextualNudgeDelegate&) = delete;
TestBackGestureContextualNudgeDelegate& operator=(
const TestBackGestureContextualNudgeDelegate&) = delete;
~TestBackGestureContextualNudgeDelegate() override;
// BackGestureContextualNudgeDelegate:
void MaybeStartTrackingNavigation(aura::Window* window) override;
private:
BackGestureContextualNudgeController* const controller_;
};
} // namespace ash
#endif // ASH_WM_GESTURES_BACK_GESTURE_TEST_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
......@@ -1542,6 +1542,8 @@ jumbo_static_library("ui") {
"ash/ash_shell_init.h",
"ash/ash_util.cc",
"ash/ash_util.h",
"ash/back_gesture_contextual_nudge_delegate.cc",
"ash/back_gesture_contextual_nudge_delegate.h",
"ash/cast_config_controller_media_router.cc",
"ash/cast_config_controller_media_router.h",
"ash/chrome_accessibility_delegate.cc",
......
// Copyright 2020 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/ash/back_gesture_contextual_nudge_delegate.h"
#include "ash/public/cpp/back_gesture_contextual_nudge_controller.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "content/public/browser/navigation_details.h"
#include "ui/aura/window.h"
BackGestureContextualNudgeDelegate::BackGestureContextualNudgeDelegate(
ash::BackGestureContextualNudgeController* controller)
: controller_(controller) {}
BackGestureContextualNudgeDelegate::~BackGestureContextualNudgeDelegate() {
StopTrackingNavigation();
}
void BackGestureContextualNudgeDelegate::MaybeStartTrackingNavigation(
aura::Window* window) {
if (window == window_)
return;
// Stop tracking the previous window before tracking a new window.
StopTrackingNavigation();
BrowserView* browser_view =
BrowserView::GetBrowserViewForNativeWindow(window);
if (!browser_view)
return;
window_ = window;
window_->AddObserver(this);
TabStripModel* tab_strip_model = browser_view->browser()->tab_strip_model();
tab_strip_model->AddObserver(this);
content::WebContents* contents = tab_strip_model->GetActiveWebContents();
Observe(contents);
}
void BackGestureContextualNudgeDelegate::NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) {
if (window_)
controller_->NavigationEntryChanged(window_);
}
void BackGestureContextualNudgeDelegate::OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) {
const bool active_tab_changed = selection.active_tab_changed();
if (active_tab_changed) {
content::WebContents* contents = tab_strip_model->GetActiveWebContents();
Observe(contents);
}
}
void BackGestureContextualNudgeDelegate::OnWindowDestroying(
aura::Window* window) {
DCHECK_EQ(window_, window);
StopTrackingNavigation();
}
void BackGestureContextualNudgeDelegate::StopTrackingNavigation() {
if (window_) {
BrowserView* browser_view =
BrowserView::GetBrowserViewForNativeWindow(window_);
DCHECK(browser_view);
browser_view->browser()->tab_strip_model()->RemoveObserver(this);
window_->RemoveObserver(this);
window_ = nullptr;
}
Observe(nullptr);
}
// Copyright 2020 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_ASH_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
#define CHROME_BROWSER_UI_ASH_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
#include "ash/public/cpp/back_gesture_contextual_nudge_delegate.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/aura/window_observer.h"
namespace aura {
class Window;
}
namespace ash {
class BackGestureContextualNudgeController;
}
// BackGestureContextualNudgeDelegate observes |window_|'s active webcontent and
// notify when |window_|'s navigation entry changes.
class BackGestureContextualNudgeDelegate
: public ash::BackGestureContextualNudgeDelegate,
public content::WebContentsObserver,
public TabStripModelObserver,
public aura::WindowObserver {
public:
explicit BackGestureContextualNudgeDelegate(
ash::BackGestureContextualNudgeController* controller);
BackGestureContextualNudgeDelegate(
const BackGestureContextualNudgeDelegate&) = delete;
BackGestureContextualNudgeDelegate& operator=(
const BackGestureContextualNudgeDelegate&) = delete;
~BackGestureContextualNudgeDelegate() override;
// ash::BackGestureContextualNudgeDelegate:
void MaybeStartTrackingNavigation(aura::Window* window) override;
// content::WebContentsObserver:
void NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) override;
// TabStripModelObserver:
void OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) override;
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
private:
// Stop tracking the navigation status for |window_|.
void StopTrackingNavigation();
aura::Window* window_ = nullptr; // Current observed window.
ash::BackGestureContextualNudgeController* const controller_; // Not owned.
};
#endif // CHROME_BROWSER_UI_ASH_BACK_GESTURE_CONTEXTUAL_NUDGE_DELEGATE_H_
......@@ -13,6 +13,7 @@
#include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/back_gesture_contextual_nudge_delegate.h"
#include "chrome/browser/ui/ash/chrome_accessibility_delegate.h"
#include "chrome/browser/ui/ash/chrome_screenshot_grabber.h"
#include "chrome/browser/ui/ash/keyboard/chrome_keyboard_ui.h"
......@@ -110,3 +111,8 @@ ChromeShellDelegate::CreateScreenshotDelegate() {
return std::make_unique<ChromeScreenshotGrabber>();
}
std::unique_ptr<ash::BackGestureContextualNudgeDelegate>
ChromeShellDelegate::CreateBackGestureContextualNudgeDelegate(
ash::BackGestureContextualNudgeController* controller) {
return std::make_unique<BackGestureContextualNudgeDelegate>(controller);
}
......@@ -17,6 +17,9 @@ class ChromeShellDelegate : public ash::ShellDelegate {
bool CanShowWindowForUser(const aura::Window* window) const override;
std::unique_ptr<ash::ScreenshotDelegate> CreateScreenshotDelegate() override;
ash::AccessibilityDelegate* CreateAccessibilityDelegate() override;
std::unique_ptr<ash::BackGestureContextualNudgeDelegate>
CreateBackGestureContextualNudgeDelegate(
ash::BackGestureContextualNudgeController* controller) override;
void OpenKeyboardShortcutHelpPage() const override;
bool CanGoBack(gfx::NativeWindow window) const override;
void BindBluetoothSystemFactory(
......
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