chromium/chrome/browser/lacros/lacros_extension_apps_controller_browsertest.cc

// Copyright 2021 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/lacros/lacros_extension_apps_controller.h"

#include "base/containers/contains.h"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_keeplist_chromeos.h"
#include "chrome/browser/lacros/lacros_extensions_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/services/app_service/public/cpp/app_types.h"
#include "components/services/app_service/public/cpp/icon_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace {

class LacrosExtensionAppsControllerTest
    : public extensions::ExtensionBrowserTest {
 public:
  void SetUp() override {
    // Since the browser tests run without Ash, Lacros won't get the Ash
    // extension keeplist data from Ash (passed via crosapi). Therefore,
    // set empty ash keeplist for test.
    extensions::SetEmptyAshKeeplistForTest();
    ExtensionBrowserTest::SetUp();
  }

  content::WebContents* GetActiveWebContents() {
    Browser* browser =
        chrome::FindTabbedBrowser(profile(), /*match_original_profiles=*/false);
    return browser->tab_strip_model()->GetActiveWebContents();
  }
};

// Test opening native settings for the app.
IN_PROC_BROWSER_TEST_F(LacrosExtensionAppsControllerTest, OpenNativeSettings) {
  const extensions::Extension* extension =
      LoadExtension(test_data_dir_.AppendASCII("platform_apps/minimal"));

  // It doesn't matter what the URL is, it shouldn't be related to the
  // extension.
  ASSERT_FALSE(base::Contains(GetActiveWebContents()->GetVisibleURL().spec(),
                              extension->id()));

  // Send the message to open native settings.
  std::unique_ptr<LacrosExtensionAppsController> controller =
      LacrosExtensionAppsController::MakeForChromeApps();
  controller->OpenNativeSettings(extension->id());

  // Now the URL should be on a settings page that has the extension id.
  ASSERT_TRUE(base::Contains(GetActiveWebContents()->GetVisibleURL().spec(),
                             extension->id()));
}

// Test uninstalling an app.
IN_PROC_BROWSER_TEST_F(LacrosExtensionAppsControllerTest, Uninstall) {
  const extensions::Extension* extension =
      LoadExtension(test_data_dir_.AppendASCII("platform_apps/minimal"));

  // Store the extension id since it will be uninstalled.
  std::string extension_id = extension->id();

  // Check that the app is installed.
  {
    const extensions::Extension* installed_extension =
        lacros_extensions_util::MaybeGetExtension(profile(), extension_id);
    EXPECT_TRUE(installed_extension && installed_extension->is_platform_app());
  }

  // Uninstall the extension.
  std::unique_ptr<LacrosExtensionAppsController> controller =
      LacrosExtensionAppsController::MakeForChromeApps();
  controller->Uninstall(extension->id(), apps::UninstallSource::kAppList,
                        /*clear_site_data=*/true,
                        /*report_abuse=*/true);

  // Check that the app is no longer installed.
  EXPECT_FALSE(
      lacros_extensions_util::MaybeGetExtension(profile(), extension_id));
}

// Test loading an icon
IN_PROC_BROWSER_TEST_F(LacrosExtensionAppsControllerTest, GetCompressedIcon) {
  const extensions::Extension* extension_minimal =
      LoadExtension(test_data_dir_.AppendASCII("platform_apps/minimal"));
  const extensions::Extension* extension_with_icon =
      LoadExtension(test_data_dir_.AppendASCII("platform_apps/app_icon"));

  // For loop is much easier to set up then a doubly parameterized test.
  for (int i = 0; i <= 1; ++i) {
    // Regardless of whether we use an extension with an custom icon or not, an
    // icon should always load.
    const extensions::Extension* extension =
        (i == 0) ? extension_minimal : extension_with_icon;

    // Check that the compressed images load correctly.

    // Set up the LoadIconCallback which quits the nested run loop and
    // populates |output|.
    apps::IconValuePtr output;
    base::RunLoop run_loop;
    apps::LoadIconCallback callback = base::BindOnce(
        [](base::RunLoop* run_loop, apps::IconValuePtr* output,
           apps::IconValuePtr input) {
          *output = std::move(input);
          run_loop->QuitClosure().Run();
        },
        &run_loop, &output);

    // Load the icon
    std::unique_ptr<LacrosExtensionAppsController> controller =
        LacrosExtensionAppsController::MakeForChromeApps();
    controller->GetCompressedIcon(extension->id(), /*size_in_dip=*/1,
                                  ui::ResourceScaleFactor::k100Percent,
                                  std::move(callback));
    run_loop.Run();

    EXPECT_FALSE(output->compressed.empty());
  }
}

}  // namespace