Commit 6023fbff authored by Toni Barzic's avatar Toni Barzic Committed by Commit Bot

first_run: Skip app list tutorial when home button is hidden

The app list step introduces the user to the home button, which might
be confusing if the home button is not shown, which is the case in
tablet mode with kHideShelfControlsInTabletMode feature enabled (the
feature removes home/back/overview buttons from shelf in favor of
gestural navigation).

BUG=1012814

Change-Id: I8621b72a734c08d84774537e962346a74ec3c5d9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2015649Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarAlexander Alekseev <alemate@chromium.org>
Commit-Queue: Toni Baržić <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734640}
parent 91c8933f
...@@ -46,6 +46,9 @@ gfx::Rect FirstRunHelperImpl::GetAppListButtonBounds() { ...@@ -46,6 +46,9 @@ gfx::Rect FirstRunHelperImpl::GetAppListButtonBounds() {
Shelf* shelf = Shelf::ForWindow(Shell::GetPrimaryRootWindow()); Shelf* shelf = Shelf::ForWindow(Shell::GetPrimaryRootWindow());
HomeButton* home_button = HomeButton* home_button =
shelf->shelf_widget()->navigation_widget()->GetHomeButton(); shelf->shelf_widget()->navigation_widget()->GetHomeButton();
if (!home_button)
return gfx::Rect();
return home_button->GetBoundsInScreen(); return home_button->GetBoundsInScreen();
} }
......
...@@ -31,7 +31,7 @@ class ASH_EXPORT FirstRunHelper { ...@@ -31,7 +31,7 @@ class ASH_EXPORT FirstRunHelper {
static std::unique_ptr<FirstRunHelper> Start(base::OnceClosure on_cancelled); static std::unique_ptr<FirstRunHelper> Start(base::OnceClosure on_cancelled);
// Returns the bounds of the home button on the primary display in screen // Returns the bounds of the home button on the primary display in screen
// coordinates. // coordinates. Returns empty bounds if the home button is not shown in shelf.
virtual gfx::Rect GetAppListButtonBounds() = 0; virtual gfx::Rect GetAppListButtonBounds() = 0;
// Opens the system tray bubble menu to show the default view. Does nothing if // Opens the system tray bubble menu to show the default view. Does nothing if
......
...@@ -2,12 +2,16 @@ ...@@ -2,12 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/system_tray_test_api.h" #include "ash/public/cpp/system_tray_test_api.h"
#include "ash/public/cpp/test/shell_test_api.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/chromeos/first_run/first_run.h" #include "chrome/browser/chromeos/first_run/first_run.h"
#include "chrome/browser/chromeos/first_run/first_run_controller.h" #include "chrome/browser/chromeos/first_run/first_run_controller.h"
#include "chrome/browser/chromeos/first_run/step_names.h" #include "chrome/browser/chromeos/first_run/step_names.h"
#include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/browser/chromeos/login/test/js_checker.h"
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/constants/chromeos_features.h"
#include "content/public/test/test_utils.h" #include "content/public/test/test_utils.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/events/event_handler.h" #include "ui/events/event_handler.h"
...@@ -51,17 +55,34 @@ class CountingEventHandler : public ui::EventHandler { ...@@ -51,17 +55,34 @@ class CountingEventHandler : public ui::EventHandler {
} // namespace } // namespace
class FirstRunUIBrowserTest : public InProcessBrowserTest, // The param respectively indicate whether tablet mode and the
public FirstRunActor::Delegate { // kHideShelfControlsInTabletMode feature are enabled.
class FirstRunUIBrowserTest
: public InProcessBrowserTest,
public FirstRunActor::Delegate,
public ::testing::WithParamInterface<std::tuple<bool, bool>> {
public: public:
FirstRunUIBrowserTest() FirstRunUIBrowserTest()
: initialized_(false), : initialized_(false),
finalized_(false) { finalized_(false) {
if (IsHomeButtonHiddenInTabletMode()) {
// kHideShelfControlsInTabletMode is predicated on hotseat being enabled.
scoped_feature_list_.InitWithFeatures(
{ash::features::kHideShelfControlsInTabletMode,
chromeos::features::kShelfHotseat},
{});
} else {
scoped_feature_list_.InitWithFeatures(
{}, {ash::features::kHideShelfControlsInTabletMode});
}
} }
void SetUpOnMainThread() override { void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread(); InProcessBrowserTest::SetUpOnMainThread();
tray_test_api_ = ash::SystemTrayTestApi::Create(); tray_test_api_ = ash::SystemTrayTestApi::Create();
if (InTabletMode())
ash::ShellTestApi().SetTabletModeEnabledForTest(true);
} }
// FirstRunActor::Delegate overrides. // FirstRunActor::Delegate overrides.
...@@ -98,6 +119,16 @@ class FirstRunUIBrowserTest : public InProcessBrowserTest, ...@@ -98,6 +119,16 @@ class FirstRunUIBrowserTest : public InProcessBrowserTest,
void OnActorDestroyed() override { controller()->OnActorDestroyed(); } void OnActorDestroyed() override { controller()->OnActorDestroyed(); }
bool InTabletMode() const { return std::get<0>(GetParam()); }
bool IsHomeButtonHiddenInTabletMode() const {
return std::get<1>(GetParam());
}
bool IsHomeButtonShown() const {
return !InTabletMode() || !IsHomeButtonHiddenInTabletMode();
}
void LaunchTutorial() { void LaunchTutorial() {
chromeos::first_run::LaunchTutorial(); chromeos::first_run::LaunchTutorial();
EXPECT_TRUE(controller() != NULL); EXPECT_TRUE(controller() != NULL);
...@@ -155,19 +186,30 @@ class FirstRunUIBrowserTest : public InProcessBrowserTest, ...@@ -155,19 +186,30 @@ class FirstRunUIBrowserTest : public InProcessBrowserTest,
std::string current_step_name_; std::string current_step_name_;
bool initialized_; bool initialized_;
bool finalized_; bool finalized_;
base::test::ScopedFeatureList scoped_feature_list_;
base::OnceClosure on_initialized_callback_; base::OnceClosure on_initialized_callback_;
base::OnceClosure on_step_shown_callback_; base::OnceClosure on_step_shown_callback_;
base::OnceClosure on_finalized_callback_; base::OnceClosure on_finalized_callback_;
test::JSChecker js_; test::JSChecker js_;
}; };
IN_PROC_BROWSER_TEST_F(FirstRunUIBrowserTest, FirstRunFlow) { INSTANTIATE_TEST_SUITE_P(
All,
FirstRunUIBrowserTest,
::testing::Combine(
::testing::Bool() /*tablet mode*/,
::testing::Bool() /*home button hidden in tablet mode*/));
IN_PROC_BROWSER_TEST_P(FirstRunUIBrowserTest, FirstRunFlow) {
LaunchTutorial(); LaunchTutorial();
WaitForInitialization(); WaitForInitialization();
WaitForStep(first_run::kAppListStep);
EXPECT_FALSE(IsTrayBubbleOpen());
AdvanceStep(); if (IsHomeButtonShown()) {
WaitForStep(first_run::kAppListStep);
EXPECT_FALSE(IsTrayBubbleOpen());
AdvanceStep();
}
WaitForStep(first_run::kTrayStep); WaitForStep(first_run::kTrayStep);
EXPECT_TRUE(IsTrayBubbleOpen()); EXPECT_TRUE(IsTrayBubbleOpen());
...@@ -182,11 +224,12 @@ IN_PROC_BROWSER_TEST_F(FirstRunUIBrowserTest, FirstRunFlow) { ...@@ -182,11 +224,12 @@ IN_PROC_BROWSER_TEST_F(FirstRunUIBrowserTest, FirstRunFlow) {
// window might be open if enterprise policy forces a browser tab to open // window might be open if enterprise policy forces a browser tab to open
// on first login and the web page opens a JavaScript alert. // on first login and the web page opens a JavaScript alert.
// See https://crrev.com/99673003 // See https://crrev.com/99673003
IN_PROC_BROWSER_TEST_F(FirstRunUIBrowserTest, ModalWindowDoesNotBlock) { IN_PROC_BROWSER_TEST_P(FirstRunUIBrowserTest, ModalWindowDoesNotBlock) {
// Start the tutorial. // Start the tutorial.
LaunchTutorial(); LaunchTutorial();
WaitForInitialization(); WaitForInitialization();
WaitForStep(first_run::kAppListStep); WaitForStep(IsHomeButtonShown() ? first_run::kAppListStep
: first_run::kTrayStep);
// Simulate the browser opening a modal dialog. // Simulate the browser opening a modal dialog.
views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget( views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
...@@ -208,12 +251,14 @@ IN_PROC_BROWSER_TEST_F(FirstRunUIBrowserTest, ModalWindowDoesNotBlock) { ...@@ -208,12 +251,14 @@ IN_PROC_BROWSER_TEST_F(FirstRunUIBrowserTest, ModalWindowDoesNotBlock) {
} }
// Tests that the escape key cancels the tutorial. // Tests that the escape key cancels the tutorial.
IN_PROC_BROWSER_TEST_F(FirstRunUIBrowserTest, EscapeCancelsTutorial) { IN_PROC_BROWSER_TEST_P(FirstRunUIBrowserTest, EscapeCancelsTutorial) {
// Run the tutorial for a couple steps, but don't finish it. // Run the tutorial for a couple steps, but don't finish it.
LaunchTutorial(); LaunchTutorial();
WaitForInitialization(); WaitForInitialization();
WaitForStep(first_run::kAppListStep); if (IsHomeButtonShown()) {
AdvanceStep(); WaitForStep(first_run::kAppListStep);
AdvanceStep();
}
WaitForStep(first_run::kTrayStep); WaitForStep(first_run::kTrayStep);
EXPECT_TRUE(IsTrayBubbleOpen()); EXPECT_TRUE(IsTrayBubbleOpen());
......
...@@ -208,7 +208,8 @@ void FirstRunController::ShowNextStep() { ...@@ -208,7 +208,8 @@ void FirstRunController::ShowNextStep() {
RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT); RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
return; return;
} }
GetCurrentStep()->Show(); if (!GetCurrentStep()->Show())
ShowNextStep();
} }
void FirstRunController::AdvanceStep() { void FirstRunController::AdvanceStep() {
......
...@@ -45,9 +45,12 @@ Step::Step(const std::string& name, ...@@ -45,9 +45,12 @@ Step::Step(const std::string& name,
Step::~Step() { RecordCompletion(); } Step::~Step() { RecordCompletion(); }
void Step::Show() { bool Step::Show() {
if (!DoShow())
return false;
show_time_ = base::Time::Now(); show_time_ = base::Time::Now();
DoShow(); return true;
} }
void Step::OnBeforeHide() { void Step::OnBeforeHide() {
......
...@@ -24,8 +24,9 @@ class Step { ...@@ -24,8 +24,9 @@ class Step {
FirstRunActor* actor); FirstRunActor* actor);
virtual ~Step(); virtual ~Step();
// Step shows its content. // Step shows its content. Return whether the step was successfully shown.
void Show(); // Returns false if the step should be skipped.
bool Show();
// Called before hiding step. // Called before hiding step.
void OnBeforeHide(); void OnBeforeHide();
...@@ -39,8 +40,9 @@ class Step { ...@@ -39,8 +40,9 @@ class Step {
FirstRunController* first_run_controller() { return first_run_controller_; } FirstRunController* first_run_controller() { return first_run_controller_; }
FirstRunActor* actor() const { return actor_; } FirstRunActor* actor() const { return actor_; }
// Called from Show method. // Called from Show method. Returns false if the step should be skipped, true
virtual void DoShow() = 0; // otherwise.
virtual bool DoShow() = 0;
// Called from OnBeforeHide. Step implementation could override this method to // Called from OnBeforeHide. Step implementation could override this method to
// react on corresponding event. // react on corresponding event.
......
...@@ -23,13 +23,17 @@ namespace first_run { ...@@ -23,13 +23,17 @@ namespace first_run {
AppListStep::AppListStep(FirstRunController* controller, FirstRunActor* actor) AppListStep::AppListStep(FirstRunController* controller, FirstRunActor* actor)
: Step(kAppListStep, controller, actor) {} : Step(kAppListStep, controller, actor) {}
void AppListStep::DoShow() { bool AppListStep::DoShow() {
// FirstRunController owns this object, so use Unretained. // FirstRunController owns this object, so use Unretained.
gfx::Rect screen_bounds = gfx::Rect screen_bounds =
first_run_controller()->first_run_helper()->GetAppListButtonBounds(); first_run_controller()->first_run_helper()->GetAppListButtonBounds();
if (screen_bounds.IsEmpty())
return false;
gfx::Point center = screen_bounds.CenterPoint(); gfx::Point center = screen_bounds.CenterPoint();
actor()->AddRoundHole(center.x(), center.y(), kCircleRadius); actor()->AddRoundHole(center.x(), center.y(), kCircleRadius);
actor()->ShowStepPointingTo(name(), center.x(), center.y(), kCircleRadius); actor()->ShowStepPointingTo(name(), center.x(), center.y(), kCircleRadius);
return true;
} }
} // namespace first_run } // namespace first_run
......
...@@ -17,7 +17,7 @@ class AppListStep : public Step { ...@@ -17,7 +17,7 @@ class AppListStep : public Step {
private: private:
// Step: // Step:
void DoShow() override; bool DoShow() override;
DISALLOW_COPY_AND_ASSIGN(AppListStep); DISALLOW_COPY_AND_ASSIGN(AppListStep);
}; };
......
...@@ -19,7 +19,7 @@ namespace first_run { ...@@ -19,7 +19,7 @@ namespace first_run {
TrayStep::TrayStep(FirstRunController* controller, FirstRunActor* actor) TrayStep::TrayStep(FirstRunController* controller, FirstRunActor* actor)
: Step(kTrayStep, controller, actor) {} : Step(kTrayStep, controller, actor) {}
void TrayStep::DoShow() { bool TrayStep::DoShow() {
// FirstRunController owns this object, so use Unretained. // FirstRunController owns this object, so use Unretained.
gfx::Rect bounds = gfx::Rect bounds =
first_run_controller()->first_run_helper()->OpenTrayBubble(); first_run_controller()->first_run_helper()->OpenTrayBubble();
...@@ -37,6 +37,7 @@ void TrayStep::DoShow() { ...@@ -37,6 +37,7 @@ void TrayStep::DoShow() {
position.SetLeft(bounds.right()); position.SetLeft(bounds.right());
} }
actor()->ShowStepPositioned(name(), position); actor()->ShowStepPositioned(name(), position);
return true;
} }
} // namespace first_run } // namespace first_run
......
...@@ -17,7 +17,7 @@ class TrayStep : public Step { ...@@ -17,7 +17,7 @@ class TrayStep : public Step {
private: private:
// Step: // Step:
void DoShow() override; bool DoShow() override;
DISALLOW_COPY_AND_ASSIGN(TrayStep); DISALLOW_COPY_AND_ASSIGN(TrayStep);
}; };
......
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