chromium/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_environment.h"
#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.h"
#include "chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/app_constants/constants.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension_urls.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/views/controls/link.h"
#include "ui/views/test/scoped_views_test_helper.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/views/window/dialog_delegate.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/public/cpp/shelf_model.h"  // nogncheck
#include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ash/app_list/arc/arc_app_test.h"
#include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
#include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
#include "chrome/browser/ui/ash/shelf/shelf_controller_helper.h"
#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
namespace {

std::vector<arc::mojom::AppInfoPtr> GetArcSettingsAppInfo() {
  std::vector<arc::mojom::AppInfoPtr> apps;
  arc::mojom::AppInfoPtr app(arc::mojom::AppInfo::New());
  app->name = "settings";
  app->package_name = "com.android.settings";
  app->activity = "com.android.settings.Settings";
  app->sticky = false;
  apps.push_back(std::move(app));
  return apps;
}

}  // namespace
#endif

namespace test {

class AppInfoDialogTestApi {};

}  // namespace test

namespace {

const char kTestExtensionId[] =;
const char kTestOtherExtensionId[] =;

}  // namespace

class AppInfoDialogViewsTest : public BrowserWithTestWindowTest,
                               public views::WidgetObserver {};

// Tests that the dialog closes when the current app is uninstalled.
TEST_F(AppInfoDialogViewsTest, UninstallingAppClosesDialog) {}

// Tests that the dialog does not close when a different app is uninstalled.
TEST_F(AppInfoDialogViewsTest, UninstallingOtherAppDoesNotCloseDialog) {}

// Tests that the dialog closes when the current profile is destroyed.
TEST_F(AppInfoDialogViewsTest, DestroyedProfileClosesDialog) {}

// Tests that the dialog does not close when a different profile is destroyed.
TEST_F(AppInfoDialogViewsTest, DestroyedOtherProfileDoesNotCloseDialog) {}

// Tests that clicking the View in Store link opens a browser tab and closes the
// dialog cleanly.
TEST_F(AppInfoDialogViewsTest, ViewInStore) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(AppInfoDialogViewsTest, ArcAppInfoLinks) {
  ShowAppInfo(app_constants::kChromeAppId);
  EXPECT_FALSE(widget_->IsClosed());
  // App Info should not have ARC App info links section because ARC Settings
  // app is not available yet.
  EXPECT_FALSE(dialog_->arc_app_info_links_for_test());

  // Re-show App Info but with ARC Settings app enabled.
  CloseAppInfo();
  ArcAppListPrefs* arc_prefs =
      ArcAppListPrefs::Get(extension_environment_.profile());
  ASSERT_TRUE(arc_prefs);
  arc::mojom::AppHost* app_host = arc_prefs;
  app_host->OnAppListRefreshed(GetArcSettingsAppInfo());
  EXPECT_TRUE(arc_prefs->IsRegistered(arc::kSettingsAppId));
  ShowAppInfo(app_constants::kChromeAppId);
  EXPECT_FALSE(widget_->IsClosed());
  EXPECT_TRUE(dialog_->arc_app_info_links_for_test());

  // Re-show App Info but for non-primary profile.
  CloseAppInfo();
  std::unique_ptr<TestingProfile> other_profile =
      std::make_unique<TestingProfile>();
  extension_environment_.CreateExtensionServiceForProfile(other_profile.get());
  // We're adding the extension to the second profile, so don't install it
  // automatically in the profile from `extension_environment_`.
  const bool install = false;
  scoped_refptr<const extensions::Extension> other_app =
      extension_environment_.MakePackagedApp(app_constants::kChromeAppId,
                                             install);
  extensions::ExtensionSystem::Get(other_profile.get())
      ->extension_service()
      ->AddExtension(other_app.get());
  ShowAppInfoForProfile(app_constants::kChromeAppId, other_profile.get());
  EXPECT_FALSE(widget_->IsClosed());
  // The ARC App info links are not available if ARC is not allowed for
  // secondary profile.
  EXPECT_FALSE(dialog_->arc_app_info_links_for_test());
}

// Tests that the pin/unpin button is focused after unpinning/pinning. This is
// to verify regression in crbug.com/428704 is fixed.
TEST_F(AppInfoDialogViewsTest, PinButtonsAreFocusedAfterPinUnpin) {
  ShowAppInfo(kTestExtensionId);
  AppInfoFooterPanel* dialog_footer =
      static_cast<AppInfoFooterPanel*>(dialog_->dialog_footer_);
  views::View* pin_button = dialog_footer->pin_to_shelf_button_;
  views::View* unpin_button = dialog_footer->unpin_from_shelf_button_;

  pin_button->RequestFocus();
  EXPECT_TRUE(pin_button->GetVisible());
  EXPECT_FALSE(unpin_button->GetVisible());
  EXPECT_TRUE(pin_button->HasFocus());

  // Avoid attempting to use sync, it's not initialized in this test.
  auto sync_disabler = chrome_shelf_controller_->GetScopedPinSyncDisabler();

  dialog_footer->SetPinnedToShelf(true);
  EXPECT_FALSE(pin_button->GetVisible());
  EXPECT_TRUE(unpin_button->GetVisible());
  EXPECT_TRUE(unpin_button->HasFocus());

  dialog_footer->SetPinnedToShelf(false);
  EXPECT_TRUE(pin_button->GetVisible());
  EXPECT_FALSE(unpin_button->GetVisible());
  EXPECT_TRUE(pin_button->HasFocus());
}
#endif