chromium/chrome/browser/ash/file_manager/virtual_tasks/install_isolated_web_app_virtual_task_unittest.cc

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

#include <memory>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/ranges/algorithm.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "chrome/browser/ash/file_manager/app_id.h"
#include "chrome/browser/ash/file_manager/file_tasks.h"
#include "chrome/browser/ash/file_manager/virtual_file_tasks.h"
#include "chrome/browser/ash/file_manager/virtual_tasks/install_isolated_web_app_virtual_task.h"
#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
#include "chrome/browser/web_applications/test/fake_web_app_ui_manager.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/entry_info.h"
#include "storage/browser/file_system/file_system_url.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/gurl.h"

using testing::_;

namespace file_manager::file_tasks {

class MockWebAppUiManager : public web_app::FakeWebAppUiManager {
 public:
  MOCK_METHOD(void,
              LaunchOrFocusIsolatedWebAppInstaller,
              (const base::FilePath&),
              (override));
};

class InstallIsolatedWebAppVirtualTaskTest : public testing::Test {
 public:
  void SetUp() override {
    feature_list_.InitWithFeatures(
        {features::kIsolatedWebApps, features::kIsolatedWebAppUnmanagedInstall},
        {});

    auto ui_manager = std::make_unique<MockWebAppUiManager>();
    ui_manager_ = ui_manager.get();
    web_app::FakeWebAppProvider::Get(&profile_)->SetWebAppUiManager(
        std::move(ui_manager));
    web_app::test::AwaitStartWebAppProviderAndSubsystems(&profile_);

    GetTestVirtualTasks().push_back(&task_);
  }

  void TearDown() override {
    ui_manager_ = nullptr;
    GetTestVirtualTasks().clear();
  }

 protected:
  MockWebAppUiManager& ui_manager() { return *ui_manager_; }

  bool Matches(const std::vector<GURL>& file_urls) {
    std::vector<extensions::EntryInfo> entries;
    base::ranges::transform(
        file_urls, std::back_inserter(entries), [](const GURL& file_url) {
          return extensions::EntryInfo(base::FilePath(file_url.path()),
                                       "application/octet-stream",
                                       /*is_directory=*/false);
        });

    std::vector<FullTaskDescriptor> tasks;
    MatchVirtualTasks(&profile_, entries, file_urls, /*dlp_source_urls=*/{},
                      &tasks);

    return tasks.size() == 1 &&
           tasks[0].task_descriptor.action_id == task_.id();
  }

  bool ExecuteTask(const std::vector<GURL>& file_urls) {
    std::vector<FileSystemURL> file_system_urls;
    auto storage_key =
        blink::StorageKey::CreateFromStringForTesting("https://example.com/");
    base::ranges::transform(file_urls, std::back_inserter(file_system_urls),
                            [&](const GURL& url) {
                              return storage::FileSystemURL::CreateForTest(
                                  storage_key, storage::kFileSystemTypeLocal,
                                  base::FilePath::FromUTF8Unsafe(url.path()));
                            });

    return ExecuteVirtualTask(
        &profile_, {kFileManagerSwaAppId, TASK_TYPE_WEB_APP, task_.id()},
        file_system_urls);
  }

 private:
  content::BrowserTaskEnvironment browser_task_environment_;
  TestingProfile profile_;
  InstallIsolatedWebAppVirtualTask task_;
  raw_ptr<MockWebAppUiManager> ui_manager_ = nullptr;

  base::test::ScopedFeatureList feature_list_;
};

TEST_F(InstallIsolatedWebAppVirtualTaskTest, MatchesSwbnFiles) {
  EXPECT_TRUE(Matches({GURL("file:///bundle.swbn"), GURL("file:///bundle.SWBN"),
                       GURL("file:///bundle.SwBn")}));
}

TEST_F(InstallIsolatedWebAppVirtualTaskTest, DoesNotMatchMultipleExtensions) {
  EXPECT_FALSE(
      Matches({GURL("file:///bundle.swbn"), GURL("file:///bundle.wbn")}));
}

TEST_F(InstallIsolatedWebAppVirtualTaskTest, DoesNotMatchIfIwasDisabled) {
  base::test::ScopedFeatureList disable_feature;
  disable_feature.InitAndDisableFeature(features::kIsolatedWebApps);

  EXPECT_FALSE(Matches({GURL("file:///bundle.swbn")}));
}

TEST_F(InstallIsolatedWebAppVirtualTaskTest,
       DoesNotMatchIfUnmanagedInstallDisabled) {
  base::test::ScopedFeatureList disable_feature;
  disable_feature.InitAndDisableFeature(
      features::kIsolatedWebAppUnmanagedInstall);

  EXPECT_FALSE(Matches({GURL("file:///bundle.swbn")}));
}

TEST_F(InstallIsolatedWebAppVirtualTaskTest, TaskNotRunWhenFeatureDisabled) {
  base::test::ScopedFeatureList disable_feature;
  disable_feature.InitAndDisableFeature(features::kIsolatedWebApps);

  EXPECT_FALSE(ExecuteTask({GURL("file:///bundle.swbn")}));
}

TEST_F(InstallIsolatedWebAppVirtualTaskTest, TaskNotRunIfNoFiles) {
  EXPECT_FALSE(ExecuteTask({}));
}

TEST_F(InstallIsolatedWebAppVirtualTaskTest, SingleFile) {
  EXPECT_CALL(ui_manager(), LaunchOrFocusIsolatedWebAppInstaller(
                                base::FilePath("/bundle.swbn")));

  EXPECT_TRUE(ExecuteTask({GURL("file:///bundle.swbn")}));
}

TEST_F(InstallIsolatedWebAppVirtualTaskTest, MultipleFiles) {
  EXPECT_CALL(ui_manager(), LaunchOrFocusIsolatedWebAppInstaller(
                                base::FilePath("/bundle1.swbn")));
  EXPECT_CALL(ui_manager(), LaunchOrFocusIsolatedWebAppInstaller(
                                base::FilePath("/bundle3.SWBN")));
  EXPECT_CALL(ui_manager(), LaunchOrFocusIsolatedWebAppInstaller(
                                base::FilePath("/bundle4.SwBn")));

  EXPECT_TRUE(ExecuteTask({
      GURL("file:///bundle1.swbn"),
      GURL("file:///bundle3.SWBN"),
      GURL("file:///bundle4.SwBn"),
  }));
}

}  // namespace file_manager::file_tasks