// 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 <set>
#include <string>
#include <vector>

#include "ash/app_list/model/app_list_item.h"
#include "ash/app_list/model/app_list_model.h"
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/accelerators.h"
#include "ash/public/cpp/pagination/pagination_model.h"
#include "ash/public/cpp/shelf_model.h"
#include "ash/public/cpp/test/app_list_test_api.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/ash/login/login_manager_test.h"
#include "chrome/browser/ash/login/test/login_manager_mixin.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/app_list/app_list_client_impl.h"
#include "chrome/browser/ui/app_list/app_list_model_updater.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
#include "chrome/browser/ui/app_list/chrome_app_list_item.h"
#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/browser/web_applications/web_app_id_constants.h"
#include "chrome/browser/web_applications/web_app_install_info.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "components/account_id/account_id.h"
#include "components/app_constants/constants.h"
#include "components/session_manager/core/session_manager.h"
#include "components/sync/model/string_ordinal.h"
#include "components/sync/test/model/fake_sync_change_processor.h"
#include "components/sync/test/model/sync_error_factory_mock.h"
#include "content/public/test/browser_test.h"
#include "extensions/browser/extension_system.h"

namespace {

constexpr char kOemAppId[] = "emfkafnhnpcmabnnkckkchdilgeoekbo";

// Gets list of item app IDs in order they appear in shelf model. Only items
// contained in `filter` will be included.
std::vector<std::string> GetOrderedShelfItems(
    const std::set<std::string>& filter) {
  std::vector<std::string> result;
  for (const auto& item : ash::ShelfModel::Get()->items()) {
    if (base::Contains(filter, item.id.app_id))
      result.push_back(item.id.app_id);
  }
  return result;
}

}  // namespace

class OemAppPositionTest : public ash::LoginManagerTest {
 public:
  OemAppPositionTest() { login_mixin_.AppendRegularUsers(1); }
  OemAppPositionTest(const OemAppPositionTest&) = delete;
  OemAppPositionTest& operator=(const OemAppPositionTest&) = delete;
  ~OemAppPositionTest() override = default;

  // LoginManagerTest:
  bool SetUpUserDataDirectory() override {
    // Create test user profile directory and copy extensions and preferences
    // from the test data directory to it.
    base::FilePath user_data_dir;
    base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
    const std::string& email =
        login_mixin_.users()[0].account_id.GetUserEmail();
    const std::string user_id_hash =
        ash::ProfileHelper::GetUserIdHashByUserIdForTesting(email);
    const base::FilePath user_profile_path = user_data_dir.Append(
        ash::ProfileHelper::GetUserProfileDir(user_id_hash));
    base::CreateDirectory(user_profile_path);

    base::FilePath src_dir;
    base::PathService::Get(chrome::DIR_TEST_DATA, &src_dir);
    src_dir = src_dir.AppendASCII("extensions").AppendASCII("app_list_oem");

    base::CopyFile(src_dir.Append(chrome::kPreferencesFilename),
                   user_profile_path.Append(chrome::kPreferencesFilename));
    base::CopyDirectory(src_dir.AppendASCII("Extensions"), user_profile_path,
                        true);
    return true;
  }

  ash::LoginManagerMixin login_mixin_{&mixin_host_};
};

class ChromeAppListModelUpdaterTestBase
    : public extensions::ExtensionBrowserTest {
 public:
  explicit ChromeAppListModelUpdaterTestBase(
      bool enable_productivity_launcher) {
    feature_list_.InitWithFeatureState(ash::features::kProductivityLauncher,
                                       enable_productivity_launcher);
  }
  ~ChromeAppListModelUpdaterTestBase() override = default;
  ChromeAppListModelUpdaterTestBase(
      const ChromeAppListModelUpdaterTestBase& other) = delete;
  ChromeAppListModelUpdaterTestBase& operator=(
      const ChromeAppListModelUpdaterTestBase& other) = delete;

 protected:
  void SetUpOnMainThread() override {
    ExtensionBrowserTest::SetUpOnMainThread();
    AppListClientImpl* client = AppListClientImpl::GetInstance();
    ASSERT_TRUE(client);
    client->UpdateProfile();

    // Ensure async callbacks are run.
    base::RunLoop().RunUntilIdle();
  }

  void ShowAppList() {
    ash::AcceleratorController::Get()->PerformActionIfEnabled(
        ash::TOGGLE_APP_LIST_FULLSCREEN, {});
    if (ash::features::IsProductivityLauncherEnabled()) {
      app_list_test_api_.WaitForBubbleWindow(
          /*wait_for_opening_animation=*/false);
    }
  }

  ash::AppListTestApi app_list_test_api_;

 private:
  base::test::ScopedFeatureList feature_list_;
};

// Parameterized by whether productivity launcher is enabled,
class ChromeAppListModelUpdaterTest
    : public ChromeAppListModelUpdaterTestBase,
      public ::testing::WithParamInterface<bool> {
 public:
  ChromeAppListModelUpdaterTest()
      : ChromeAppListModelUpdaterTestBase(
            /*enable_productivity_launcher=*/GetParam()) {}
  ~ChromeAppListModelUpdaterTest() override = default;
};

INSTANTIATE_TEST_SUITE_P(ProductivityLauncher,
                         ChromeAppListModelUpdaterTest,
                         ::testing::Bool());

// Test cases with productivity launcher enabled.
class ChromeAppListModelUpdaterLegacyLauncherTest
    : public ChromeAppListModelUpdaterTestBase {
 public:
  ChromeAppListModelUpdaterLegacyLauncherTest()
      : ChromeAppListModelUpdaterTestBase(
            /*enable_productivity_launcher=*/false) {}
  ~ChromeAppListModelUpdaterLegacyLauncherTest() override = default;
};

class ChromeAppListModelUpdaterProductivityLauncherTest
    : public ChromeAppListModelUpdaterTestBase {
 public:
  ChromeAppListModelUpdaterProductivityLauncherTest()
      : ChromeAppListModelUpdaterTestBase(
            /*enable_productivity_launcher=*/true) {}
};

// Tests that an Oem app and its folder are created with valid positions after
// sign-in.
IN_PROC_BROWSER_TEST_F(OemAppPositionTest, ValidOemAppPosition) {
  LoginUser(login_mixin_.users()[0].account_id);

  // Ensure apps that are installed upon sign-in are registered with the App
  // Service, resolving any pending messages as a result of running async
  // callbacks.
  Profile* profile = ProfileManager::GetActiveUserProfile();
  auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile);
  proxy->FlushMojoCallsForTesting();

  AppListClientImpl* client = AppListClientImpl::GetInstance();
  ASSERT_TRUE(client);
  client->UpdateProfile();
  AppListModelUpdater* model_updater = test::GetModelUpdater(client);

  // Ensure async callbacks are run.
  base::RunLoop().RunUntilIdle();

  const ChromeAppListItem* oem_app = model_updater->FindItem(kOemAppId);
  ASSERT_TRUE(oem_app);
  EXPECT_TRUE(oem_app->position().IsValid());

  const ChromeAppListItem* oem_folder =
      model_updater->FindItem(ash::kOemFolderId);
  ASSERT_TRUE(oem_folder);
  EXPECT_TRUE(oem_folder->position().IsValid());
}

IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       GetPositionBeforeFirstItemTest) {
  AppListClientImpl* client = AppListClientImpl::GetInstance();
  ASSERT_TRUE(client);
  AppListModelUpdater* model_updater = test::GetModelUpdater(client);

  // Default apps will be present but we add an app to guarantee there will be
  // at least 1 app.
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());

  // Create the app list view and show the apps grid.
  ShowAppList();

  std::vector<std::string> top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();
  syncer::StringOrdinal position_before_first_item =
      model_updater->GetPositionBeforeFirstItem();

  // Check that position is before all items in the list.
  for (const auto& id : top_level_id_list) {
    ChromeAppListItem* item = model_updater->FindItem(id);
    ASSERT_TRUE(position_before_first_item.LessThan(item->position()));
  }

  // Move app to the front.
  app_list_test_api_.MoveItemToPosition(app1_id, 0);

  std::vector<std::string> reordered_top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();
  syncer::StringOrdinal new_position_before_first_item =
      model_updater->GetPositionBeforeFirstItem();

  // Re-check that position is before all items in the list.
  for (const auto& id : reordered_top_level_id_list) {
    ChromeAppListItem* item = model_updater->FindItem(id);
    ASSERT_TRUE(new_position_before_first_item.LessThan(item->position()));
  }
}

IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       PRE_ReorderAppPositionInTopLevelAppList) {
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());
  const std::string app2_id =
      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
  ASSERT_FALSE(app2_id.empty());
  // App3 is the same app as app1 in |test_data_dir_|. Take app4 as the third
  // app in this test.
  const std::string app3_id =
      LoadExtension(test_data_dir_.AppendASCII("app4"))->id();
  ASSERT_FALSE(app3_id.empty());

  // Create the app list view and show the apps grid.
  ShowAppList();

  std::vector<std::string> top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();
  size_t top_level_id_list_size = top_level_id_list.size();

  // This test ignores the default apps and we don't test the exact
  // |top_level_id_list| size here.
  ASSERT_GE(top_level_id_list_size, 3u);

  if (ash::features::IsProductivityLauncherEnabled()) {
    ASSERT_EQ(top_level_id_list[2], app1_id);
    ASSERT_EQ(top_level_id_list[1], app2_id);
    ASSERT_EQ(top_level_id_list[0], app3_id);
  } else {
    ASSERT_EQ(top_level_id_list[top_level_id_list_size - 3], app1_id);
    ASSERT_EQ(top_level_id_list[top_level_id_list_size - 2], app2_id);
    ASSERT_EQ(top_level_id_list[top_level_id_list_size - 1], app3_id);
  }

  // After the move operation, app3 should be at index 0 and app1 should be at
  // index 1. App2 stays at the last position in the item list.
  app_list_test_api_.MoveItemToPosition(app1_id, 0);
  app_list_test_api_.MoveItemToPosition(app3_id, 0);

  std::vector<std::string> reordered_top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();

  EXPECT_EQ(top_level_id_list_size, reordered_top_level_id_list.size());
  EXPECT_EQ(reordered_top_level_id_list[0], app3_id);
  EXPECT_EQ(reordered_top_level_id_list[1], app1_id);
  if (ash::features::IsProductivityLauncherEnabled()) {
    EXPECT_EQ(reordered_top_level_id_list[2], app2_id);
  } else {
    EXPECT_EQ(reordered_top_level_id_list.back(), app2_id);
  }
}

// Tests if the app position changed in the top level persist after the system
// restarts.
IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       ReorderAppPositionInTopLevelAppList) {
  // Create the app list view and show the apps grid.
  ShowAppList();

  const std::string app1_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app1"))
          ->id();
  const std::string app2_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app2"))
          ->id();
  const std::string app3_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app4"))
          ->id();

  std::vector<std::string> reordered_top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();

  // This test ignores the default apps and we don't test the exact
  // |reordered_top_level_id_list| size here.
  ASSERT_GE(reordered_top_level_id_list.size(), 3u);

  EXPECT_EQ(reordered_top_level_id_list[0], app3_id);
  EXPECT_EQ(reordered_top_level_id_list[1], app1_id);
  if (ash::features::IsProductivityLauncherEnabled()) {
    ASSERT_EQ(reordered_top_level_id_list[2], app2_id);
  } else {
    EXPECT_EQ(reordered_top_level_id_list.back(), app2_id);
  }
}

IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       PRE_ReorderAppPositionInFolder) {
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());
  const std::string app2_id =
      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
  ASSERT_FALSE(app2_id.empty());
  // App3 is the same app as app1 in |test_data_dir_|. Take app4 as the third
  // app in this test.
  const std::string app3_id =
      LoadExtension(test_data_dir_.AppendASCII("app4"))->id();
  ASSERT_FALSE(app3_id.empty());

  // Create the app list view and show the apps grid.
  ShowAppList();

  // Create a folder with app1, app2 and app3 in order.
  const std::string folder_id =
      app_list_test_api_.CreateFolderWithApps({app1_id, app2_id, app3_id});

  std::vector<std::string> original_id_list{app1_id, app2_id, app3_id};
  ASSERT_EQ(app_list_test_api_.GetAppIdsInFolder(folder_id), original_id_list);

  // Change an app position in the folder.
  app_list_test_api_.MoveItemToPosition(app1_id, 2);

  std::vector<std::string> reordered_id_list{app2_id, app3_id, app1_id};
  EXPECT_EQ(app_list_test_api_.GetAppIdsInFolder(folder_id), reordered_id_list);
}

// Tests if the app position changed in a folder persist after the system
// restarts.
IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       ReorderAppPositionInFolder) {
  const std::string app1_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app1"))
          ->id();
  const std::string app2_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app2"))
          ->id();
  const std::string app3_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app4"))
          ->id();

  std::string folder_id = app_list_test_api_.GetFolderId(app1_id);
  // Check if the three apps are still in the same folder.
  ASSERT_FALSE(folder_id.empty());
  ASSERT_EQ(app_list_test_api_.GetFolderId(app2_id), folder_id);
  ASSERT_EQ(app_list_test_api_.GetFolderId(app3_id), folder_id);

  std::vector<std::string> reordered_id_list{app2_id, app3_id, app1_id};
  EXPECT_EQ(app_list_test_api_.GetAppIdsInFolder(folder_id), reordered_id_list);
}

IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       PRE_UnmergeTwoItemFolder) {
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());
  const std::string app2_id =
      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
  ASSERT_FALSE(app2_id.empty());
  // App3 is the same app as app1 in |test_data_dir_|. Take app4 as the third
  // app in this test.
  const std::string app3_id =
      LoadExtension(test_data_dir_.AppendASCII("app4"))->id();
  ASSERT_FALSE(app3_id.empty());

  // Create the app list view and show the apps grid.
  ShowAppList();

  // Create a folder with app1, app2 and app3 in order.
  const std::string folder_id =
      app_list_test_api_.CreateFolderWithApps({app1_id, app2_id});

  ash::AppListModel* model = app_list_test_api_.GetAppListModel();
  ash::AppListItem* app1_item = model->FindItem(app1_id);
  ASSERT_TRUE(app1_item);

  ash::AppListItem* app2_item = model->FindItem(app2_id);
  ASSERT_TRUE(app2_item);

  ash::AppListItem* app3_item = model->FindItem(app3_id);
  ASSERT_TRUE(app3_item);

  if (ash::features::IsProductivityLauncherEnabled()) {
    model->MoveItemToRootAt(app2_item, app3_item->position().CreateBefore());
  } else {
    model->MoveItemToRootAt(app2_item, app3_item->position().CreateAfter());
  }

  // Get last 3 items (the grid may have default items, in addition to the ones
  // installed by the test).
  std::vector<std::string> top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();
  ASSERT_GT(top_level_id_list.size(), 2u);
  if (ash::features::IsProductivityLauncherEnabled()) {
    EXPECT_TRUE(base::Contains(top_level_id_list, folder_id));
    model->MoveItemToRootAt(app1_item, app2_item->position().CreateBefore());

    top_level_id_list = app_list_test_api_.GetTopLevelViewIdList();
    EXPECT_FALSE(base::Contains(top_level_id_list, folder_id));
  } else {
    EXPECT_FALSE(base::Contains(top_level_id_list, folder_id));
  }

  if (ash::features::IsProductivityLauncherEnabled()) {
    std::vector<std::string> leading_items = {
        top_level_id_list[0],
        top_level_id_list[1],
        top_level_id_list[2],
    };

    EXPECT_EQ(std::vector<std::string>({app1_id, app2_id, app3_id}),
              leading_items);
  } else {
    std::vector<std::string> trailing_items = {
        top_level_id_list[top_level_id_list.size() - 3],
        top_level_id_list[top_level_id_list.size() - 2],
        top_level_id_list[top_level_id_list.size() - 1],
    };

    EXPECT_EQ(std::vector<std::string>({app1_id, app3_id, app2_id}),
              trailing_items);
  }
}

IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest, UnmergeTwoItemFolder) {
  const std::string app1_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app1"))
          ->id();
  const std::string app2_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app2"))
          ->id();
  const std::string app3_id =
      GetExtensionByPath(extension_registry()->enabled_extensions(),
                         test_data_dir_.AppendASCII("app4"))
          ->id();

  // Create the app list view and show the apps grid.
  ShowAppList();

  // Get last 3 items (the grid may have default items, in addition to the ones
  // installed by the test).
  std::vector<std::string> top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();
  ASSERT_GT(top_level_id_list.size(), 2u);

  if (ash::features::IsProductivityLauncherEnabled()) {
    std::vector<std::string> leading_items = {
        top_level_id_list[0],
        top_level_id_list[1],
        top_level_id_list[2],
    };

    EXPECT_EQ(std::vector<std::string>({app1_id, app2_id, app3_id}),
              leading_items);
  } else {
    std::vector<std::string> trailing_items = {
        top_level_id_list[top_level_id_list.size() - 3],
        top_level_id_list[top_level_id_list.size() - 2],
        top_level_id_list[top_level_id_list.size() - 1],
    };

    EXPECT_EQ(std::vector<std::string>({app1_id, app3_id, app2_id}),
              trailing_items);
  }
}

// Tests that session restart before a default pinned preinstalled app is
// correctly positioned in the app list if the session restarts before the app
// installation completes.
IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       PRE_SessionRestartDoesntOverrideDefaultAppListPosition) {
  // Simluate installation of an app pinned to shelf by default:
  // App with web_app::kGmailAppId ID.
  auto gmail_info = std::make_unique<WebAppInstallInfo>();
  gmail_info->start_url =
      GURL("https://mail.google.com/mail/?usp=installed_webapp");
  gmail_info->display_mode = blink::mojom::DisplayMode::kMinimalUi;
  web_app::test::InstallWebApp(profile(), std::move(gmail_info));
  // Flush app service so app installation gets handled.
  apps::AppServiceProxyFactory::GetForProfile(profile())
      ->FlushMojoCallsForTesting();

  std::set<std::string> app_filter({app_constants::kChromeAppId,
                                    web_app::kGmailAppId,
                                    web_app::kMessagesAppId});
  EXPECT_EQ(std::vector<std::string>(
                {app_constants::kChromeAppId, web_app::kGmailAppId}),
            GetOrderedShelfItems(app_filter));
}

IN_PROC_BROWSER_TEST_P(ChromeAppListModelUpdaterTest,
                       SessionRestartDoesntOverrideDefaultAppListPosition) {
  app_list::AppListSyncableService* app_list_syncable_service =
      app_list::AppListSyncableServiceFactory::GetForProfile(profile());
  AppListModelUpdater* app_list_model_updater =
      app_list_syncable_service->GetModelUpdater();
  app_list_model_updater->SetActive(true);

  app_list_syncable_service->MergeDataAndStartSyncing(
      syncer::APP_LIST, syncer::SyncDataList(),
      std::make_unique<syncer::FakeSyncChangeProcessor>(),
      std::make_unique<syncer::SyncErrorFactoryMock>());

  // Simluate installation of an app pinned to shelf by default after initial
  // sync data is merged: app with web_app::kMessagesAppId ID.
  auto messages_info = std::make_unique<WebAppInstallInfo>();
  messages_info->start_url = GURL("https://messages.google.com/web/");
  messages_info->display_mode = blink::mojom::DisplayMode::kMinimalUi;
  web_app::test::InstallWebApp(profile(), std::move(messages_info));

  // Flush app service so app installation gets handled.
  apps::AppServiceProxyFactory::GetForProfile(profile())
      ->FlushMojoCallsForTesting();

  std::set<std::string> app_filter({app_constants::kChromeAppId,
                                    web_app::kGmailAppId,
                                    web_app::kMessagesAppId});
  EXPECT_EQ(
      std::vector<std::string>({app_constants::kChromeAppId,
                                web_app::kGmailAppId, web_app::kMessagesAppId}),
      GetOrderedShelfItems(app_filter));

  // Verify that order of apps in the app list respects default app ordinals
  // (for test apps that have default app list ordinal set).
  ShowAppList();
  std::vector<std::string> top_level_id_list =
      app_list_test_api_.GetTopLevelViewIdList();
  std::vector<std::string> filtered_top_level_id_list;
  for (const auto& item : top_level_id_list) {
    if (base::Contains(app_filter, item))
      filtered_top_level_id_list.push_back(item);
  }

  EXPECT_EQ(
      std::vector<std::string>({app_constants::kChromeAppId,
                                web_app::kGmailAppId, web_app::kMessagesAppId}),
      filtered_top_level_id_list);
}

IN_PROC_BROWSER_TEST_F(ChromeAppListModelUpdaterProductivityLauncherTest,
                       IsNewInstall) {
  AppListClientImpl* client = AppListClientImpl::GetInstance();
  ASSERT_TRUE(client);
  AppListModelUpdater* model_updater = test::GetModelUpdater(client);
  ASSERT_TRUE(model_updater);

  // The built-in "Web Store" app is not a new install.
  ChromeAppListItem* web_store_item =
      model_updater->FindItem(extensions::kWebStoreAppId);
  ASSERT_TRUE(web_store_item);
  EXPECT_FALSE(web_store_item->CloneMetadata()->is_new_install);

  // Install 2 apps.
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());
  const std::string app2_id =
      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
  ASSERT_FALSE(app2_id.empty());

  // Both apps are new installs.
  ChromeAppListItem* item1 = model_updater->FindItem(app1_id);
  ASSERT_TRUE(item1);
  EXPECT_TRUE(item1->CloneMetadata()->is_new_install);

  ChromeAppListItem* item2 = model_updater->FindItem(app2_id);
  ASSERT_TRUE(item2);
  EXPECT_TRUE(item2->CloneMetadata()->is_new_install);

  // Launch the first app.
  item1->Activate(ui::EF_NONE);

  // First app is no longer a new install.
  EXPECT_FALSE(item1->CloneMetadata()->is_new_install);

  // Second app is still a new install.
  EXPECT_TRUE(item2->CloneMetadata()->is_new_install);
}

IN_PROC_BROWSER_TEST_F(ChromeAppListModelUpdaterProductivityLauncherTest,
                       IsNewInstallInFolder) {
  AppListClientImpl* client = AppListClientImpl::GetInstance();
  ASSERT_TRUE(client);
  AppListModelUpdater* model_updater = test::GetModelUpdater(client);
  ASSERT_TRUE(model_updater);

  // Install 2 apps.
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());
  const std::string app2_id =
      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
  ASSERT_FALSE(app2_id.empty());

  ShowAppList();

  // Put the apps in a folder.
  const std::string folder_id =
      app_list_test_api_.CreateFolderWithApps({app1_id, app2_id});

  // Both apps are new installs.
  ash::AppListModel* model = app_list_test_api_.GetAppListModel();
  ash::AppListItem* app1_item = model->FindItem(app1_id);
  ASSERT_TRUE(app1_item);
  EXPECT_TRUE(app1_item->is_new_install());

  ash::AppListItem* app2_item = model->FindItem(app2_id);
  ASSERT_TRUE(app2_item);
  EXPECT_TRUE(app2_item->is_new_install());

  // The folder is considered a "new install" because it contains an item that
  // is a new install.
  ash::AppListItem* folder_item = model->FindItem(folder_id);
  ASSERT_TRUE(folder_item);
  EXPECT_TRUE(folder_item->is_new_install());

  // Launching one item clears its new install status, but the folder still
  // contains a new install.
  model_updater->FindItem(app1_id)->Activate(ui::EF_NONE);
  EXPECT_FALSE(app1_item->is_new_install());
  EXPECT_TRUE(app2_item->is_new_install());
  EXPECT_TRUE(folder_item->is_new_install());

  // Launching them other item clears its new install status, and the folder
  // no longer contains a new install.
  model_updater->FindItem(app2_id)->Activate(ui::EF_NONE);
  EXPECT_FALSE(app1_item->is_new_install());
  EXPECT_FALSE(app2_item->is_new_install());
  EXPECT_FALSE(folder_item->is_new_install());
}

IN_PROC_BROWSER_TEST_F(ChromeAppListModelUpdaterLegacyLauncherTest,
                       PRE_PersistTrailingUserCreatedPage) {
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());
  const std::string app2_id =
      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
  ASSERT_FALSE(app2_id.empty());

  // Create the app list view and show the apps grid.
  ash::AcceleratorController::Get()->PerformActionIfEnabled(
      ash::TOGGLE_APP_LIST_FULLSCREEN, {});
  ASSERT_EQ(1, app_list_test_api_.GetPaginationModel()->total_pages());

  app_list_test_api_.GetLastItemInAppsGridView()->RequestFocus();

  ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
      nullptr, ui::VKEY_DOWN, /*control=*/true, /*shift=*/false,
      /*alt=*/false, /*command=*/false));
  EXPECT_EQ(2, app_list_test_api_.GetPaginationModel()->total_pages());
}

IN_PROC_BROWSER_TEST_F(ChromeAppListModelUpdaterLegacyLauncherTest,
                       PersistTrailingUserCreatedPage) {
  const std::string app1_id =
      LoadExtension(test_data_dir_.AppendASCII("app1"))->id();
  ASSERT_FALSE(app1_id.empty());
  const std::string app2_id =
      LoadExtension(test_data_dir_.AppendASCII("app2"))->id();
  ASSERT_FALSE(app2_id.empty());

  // Verify that the app list still has 2 pages after session restart.
  ash::AcceleratorController::Get()->PerformActionIfEnabled(
      ash::TOGGLE_APP_LIST_FULLSCREEN, {});
  EXPECT_EQ(2, app_list_test_api_.GetPaginationModel()->total_pages());
}
