chromium/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.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 <unistd.h>
#include <algorithm>
#include <cstddef>
#include <string>
#include <string_view>

#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.h"

#include "ash/constants/ash_features.h"
#include "ash/constants/ash_switches.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_parser.h"
#include "base/json/json_reader.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/ash/file_manager/app_id.h"
#include "chrome/browser/ash/file_manager/file_manager_test_util.h"
#include "chrome/browser/ash/file_manager/file_tasks.h"
#include "chrome/browser/ash/file_manager/fileapi_util.h"
#include "chrome/browser/ash/file_manager/office_file_tasks.h"
#include "chrome/browser/ash/file_manager/open_util.h"
#include "chrome/browser/ash/file_manager/path_util.h"
#include "chrome/browser/ash/file_manager/url_util.h"
#include "chrome/browser/ash/file_manager/volume_manager.h"
#include "chrome/browser/ash/file_system_provider/fake_extension_provider.h"
#include "chrome/browser/ash/file_system_provider/service.h"
#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
#include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate.h"
#include "chrome/browser/chromeos/upload_office_to_cloud/upload_office_to_cloud.h"
#include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.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/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/crosapi/mojom/volume_manager.mojom.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "extensions/common/constants.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/native_widget_types.h"

namespace ash::cloud_upload {

namespace {

namespace fm_tasks = ::file_manager::file_tasks;

using chromeos::cloud_upload::kCloudUploadPolicyAllowed;
using chromeos::cloud_upload::kCloudUploadPolicyAutomated;
using chromeos::cloud_upload::kCloudUploadPolicyDisallowed;

// The mime type and file_extension must be matching for
// `CreateFakeWebApps()`.
const char kDocFileExtension[] = ".doc";
const char kDocMimeType[] = "application/msword";
const char kDocxFileExtension[] = ".docx";
const char kDocxMimeType[] =
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
const char kPptFileExtension[] = ".ppt";
const char kPptMimeType[] = "application/vnd.ms-powerpoint";
const char kPptxFileExtension[] = ".pptx";
const char kPptxMimeType[] =
    "application/vnd.openxmlformats-officedocument.presentationml.presentation";
const char kXlsxFileExtension[] = ".xlsx";
const char kXlsxMimeType[] =
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

// Create `n` fake web apps that open any files with the `file_extensions` and
// matching `mime_types`. The apps can be identified by a unique `app_id`
// and launched by file_manager::file_tasks::ExecuteFileTask() which can be
// observed by the unique `url`. Store the info of the created tasks in `urls`
// and `tasks`.
void CreateFakeWebApps(
    Profile* profile,
    std::vector<std::string>* urls,
    std::vector<file_manager::file_tasks::TaskDescriptor>* tasks,
    const std::vector<std::string>& file_extensions,
    const std::vector<std::string>& mime_types,
    int n) {
  ASSERT_EQ(file_extensions.size(), mime_types.size());
  for (int i = 0; i < n; ++i) {
    std::string start_url =
        "https://www.example" + base::NumberToString(i) + ".com";
    auto web_app_info =
        web_app::WebAppInstallInfo::CreateWithStartUrlForTesting(
            GURL(start_url));
    web_app_info->scope = GURL(start_url);
    apps::FileHandler handler;
    std::string url = start_url + "/handle_file";
    handler.action = GURL(url);
    handler.display_name = u"activity name";
    for (size_t j = 0; j < file_extensions.size(); j++) {
      apps::FileHandler::AcceptEntry accept_entry;
      accept_entry.file_extensions.insert(file_extensions[j]);
      accept_entry.mime_type = mime_types[j];
      handler.accept.push_back(accept_entry);
    }
    web_app_info->file_handlers.push_back(std::move(handler));

    // Install a PWA in ash.
    std::string app_id =
        web_app::test::InstallWebApp(profile, std::move(web_app_info));
    // Skip past the permission dialog.
    web_app::WebAppProvider::GetForTest(profile)
        ->sync_bridge_unsafe()
        .SetAppFileHandlerApprovalState(app_id,
                                        web_app::ApiApprovalState::kAllowed);

    file_manager::file_tasks::TaskDescriptor task_descriptor(
        app_id, file_manager::file_tasks::TaskType::TASK_TYPE_WEB_APP, url);

    urls->push_back(url);
    tasks->push_back(task_descriptor);
  }
}

// Returns the position of `elt` in `list`. If `list` does not contain `elt`,
// return -1.
int PositionInList(base::Value::List& list, const std::string& elt) {
  for (size_t i = 0; i < list.size(); i++) {
    if (elt == list[i]) {
      return i;
    }
  }
  return -1;
}

// Get web contents of chrome://cloud-upload.
content::WebContents* GetWebContentsFromCloudUploadDialog() {
  ash::SystemWebDialogDelegate* dialog =
      ash::SystemWebDialogDelegate::FindInstance(
          chrome::kChromeUICloudUploadURL);
  EXPECT_TRUE(dialog);
  content::WebUI* webui = dialog->GetWebUIForTest();
  EXPECT_TRUE(webui);
  content::WebContents* web_contents = webui->GetWebContents();
  EXPECT_TRUE(web_contents);
  return web_contents;
}

// Call `CloudOpenTask::Execute()` with the arguments provided and expect that
// dialog will appear at chrome://cloud-upload. Wait until chrome://cloud-upload
// opens.
void LaunchCloudUploadDialog(
    Profile* profile,
    const std::vector<storage::FileSystemURL>& file_urls,
    const CloudProvider cloud_provider,
    std::unique_ptr<CloudOpenMetrics> cloud_open_metrics) {
  // Watch for dialog URL chrome://cloud-upload.
  content::TestNavigationObserver navigation_observer_dialog(
      (GURL(chrome::kChromeUICloudUploadURL)));
  navigation_observer_dialog.StartWatchingNewWebContents();

  // Launch dialog.
  EXPECT_TRUE(CloudOpenTask::Execute(
      profile, file_urls, file_manager::file_tasks::TaskDescriptor(),
      cloud_provider, std::move(cloud_open_metrics)));

  // Wait for chrome://cloud-upload to open.
  navigation_observer_dialog.Wait();
  EXPECT_TRUE(navigation_observer_dialog.last_navigation_succeeded());
}

// Wait until the provided JS `script` returns true when executed on the
// `web_contents`.
void WaitUntilJsReturnsTrue(content::WebContents* web_contents,
                            std::string script) {
  EXPECT_TRUE(base::test::RunUntil(
      [&] { return content::EvalJs(web_contents, script).ExtractBool(); }));
}

// Wait until the `document` element with `element_name` exists on the
// `web_contents`.
void WaitUntilElementExists(content::WebContents* web_contents,
                            std::string element_name) {
  WaitUntilJsReturnsTrue(web_contents,
                         "!!document.querySelector('" + element_name + "')");
}

// Expect that calling `CloudOpenTask::Execute()` with the provided arguments
// will launch a cloud upload dialog at chrome://cloud-upload. Wait until the
// DOM element with `dialog_name` exists at chrome://cloud-upload and return the
// web contents at chrome://cloud-upload.
content::WebContents* LaunchCloudUploadDialogAndGetWebContentsForDialog(
    Profile* profile,
    const std::vector<storage::FileSystemURL>& file_urls,
    const CloudProvider cloud_provider,
    std::unique_ptr<CloudOpenMetrics> cloud_open_metrics,
    std::string dialog_name) {
  LaunchCloudUploadDialog(profile, file_urls, cloud_provider,
                          std::move(cloud_open_metrics));

  // Get the web contents of chrome://cloud-upload to be able to check that the
  // dialog exists.
  content::WebContents* web_contents = GetWebContentsFromCloudUploadDialog();

  // Wait until the DOM element actually exists at chrome://cloud-upload.
  WaitUntilElementExists(web_contents, dialog_name);

  return web_contents;
}

// Set email (using a domain from |kNonManagedDomainPatterns|) to login a
// non-managed user. Intended to be used in the override of |SetUpCommandLine|
// from |InProcessBrowserTest| to ensure
// |IsEligibleAndEnabledUploadOfficeToCloud| returns the result of
// |IsUploadOfficeToCloudEnabled| in browser tests.
void SetUpCommandLineForNonManagedUser(base::CommandLine* command_line) {
  command_line->AppendSwitchASCII(switches::kLoginUser, "[email protected]");
  command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
}

// A matcher to verify that std::optional<TaskDescriptor> corresponds to a Web
// Drive Office Task.
auto IsWebDriveOfficeTask() {
  return testing::Optional(testing::ResultOf(
      &file_manager::file_tasks::IsWebDriveOfficeTask, testing::Eq(true)));
}

// A matcher to verify that std::optional<TaskDescriptor> corresponds to an
// Open in Office Task.
auto IsOpenInOfficeTask() {
  return testing::Optional(testing::ResultOf(
      &file_manager::file_tasks::IsOpenInOfficeTask, testing::Eq(true)));
}

}  // namespace

// Tests the `kFileHandlerDialog` dialog page of the `CloudUploadDialog`.
// Ensures that fake local file tasks are all found and passed to the JS side of
// the dialog - the `FileHandlerPageElement`. Ensures that a local file task
// selected on the JS side gets executed.
class FileHandlerDialogBrowserTest : public InProcessBrowserTest {
 public:
  FileHandlerDialogBrowserTest() {
    feature_list_.InitWithFeatures(
        {chromeos::features::kUploadOfficeToCloud,
         chromeos::features::kUploadOfficeToCloudForEnterprise},
        {});
  }

  explicit FileHandlerDialogBrowserTest(int num_tasks)
      : FileHandlerDialogBrowserTest() {
    num_tasks_ = num_tasks;
  }

  FileHandlerDialogBrowserTest(const FileHandlerDialogBrowserTest&) = delete;
  FileHandlerDialogBrowserTest& operator=(const FileHandlerDialogBrowserTest&) =
      delete;

  Profile* profile() { return browser()->profile(); }

  void SetUpOnMainThread() override {
    InProcessBrowserTest::SetUpOnMainThread();

    // Needed to check that Files app was launched as the dialog's modal parent.
    ash::SystemWebAppManager::GetForTest(browser()->profile())
        ->InstallSystemAppsForTesting();

    SetUpTasksAndFiles();
  }

  // Create test office files and store in `files_` and create `num_tasks_` fake
  // web apps for all office file types.
  void SetUpTasksAndFiles() {
    // Create `num_tasks_` fake web apps for office files with the Doc extension
    // and store the created `urls_` and `tasks_`.
    CreateFakeWebApps(
        profile(), &urls_, &tasks_,
        {kDocxFileExtension, kPptxFileExtension, kXlsxFileExtension},
        {kDocxMimeType, kPptxMimeType, kXlsxMimeType}, num_tasks_);

    files_ = file_manager::test::CopyTestFilesIntoMyFiles(
        profile(), {"text.docx", "presentation.pptx"});
  }

 protected:
  // Use a non-managed user in this browser test to ensure
  // |IsEligibleAndEnabledUploadOfficeToCloud| returns the result of
  // |IsUploadOfficeToCloudEnabled|.
  void SetUpCommandLine(base::CommandLine* command_line) override {
    SetUpCommandLineForNonManagedUser(command_line);
  }

  int num_tasks_ = 3;
  std::vector<std::string> urls_;
  std::vector<file_manager::file_tasks::TaskDescriptor> tasks_;
  std::vector<storage::FileSystemURL> files_;
  base::HistogramTester histogram_;

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

// Tests that a new Files app window is created if no Files app window exists.
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest, NewModalParentCreated) {
  file_manager::test::AddDefaultComponentExtensionsOnMainThread(profile());

  Browser* browser =
      FindSystemWebAppBrowser(profile(), SystemWebAppType::FILE_MANAGER);
  ASSERT_EQ(nullptr, browser);

  // Launch File Handler dialog.
  LaunchCloudUploadDialog(
      profile(), files_, CloudProvider::kGoogleDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kGoogleDrive,
                                         /*file_count=*/1));

  browser = FindSystemWebAppBrowser(profile(), SystemWebAppType::FILE_MANAGER);
  ASSERT_NE(nullptr, browser);
}

// Tests that a new Files app window is not created when there is a Files app
// window already open.
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest,
                       ExistingWindowUsedAsModalParent) {
  file_manager::test::AddDefaultComponentExtensionsOnMainThread(profile());

  Browser* browser =
      FindSystemWebAppBrowser(profile(), SystemWebAppType::FILE_MANAGER);
  ASSERT_EQ(nullptr, browser);

  // Open a files app window.
  ui_test_utils::BrowserChangeObserver browser_added_observer(
      nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded);
  base::test::TestFuture<platform_util::OpenOperationResult> future;
  file_manager::util::ShowItemInFolder(profile(), files_.at(0).path(),
                                       future.GetCallback());
  EXPECT_EQ(future.Get(), platform_util::OpenOperationResult::OPEN_SUCCEEDED);
  browser_added_observer.Wait();

  browser = FindSystemWebAppBrowser(profile(), SystemWebAppType::FILE_MANAGER);
  ASSERT_NE(nullptr, browser);

  // Launch File Handler dialog.
  LaunchCloudUploadDialog(
      profile(), files_, CloudProvider::kGoogleDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kGoogleDrive,
                                         /*file_count=*/1));

  // Check that the existing Files app window was used.
  ASSERT_EQ(browser,
            FindSystemWebAppBrowser(profile(), SystemWebAppType::FILE_MANAGER));
}

// Test which launches a `CloudUploadDialog` which in turn creates a
// `FileHandlerPageElement`. Tests that the cancel button works and a Cancel
// TaskResult is logged.
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest, CancelFileHandlerDialog) {
  auto cloud_open_metrics = std::make_unique<CloudOpenMetrics>(
      CloudProvider::kGoogleDrive, /*file_count=*/1);
  auto cloud_open_metrics_weak_ptr = cloud_open_metrics->GetWeakPtr();

  // Check that the Setup flow has never run and so the File Handler dialog will
  // be launched when CloudOpenTask::Execute() is called.
  ASSERT_FALSE(file_manager::file_tasks::HasExplicitDefaultFileHandler(
      profile(), ".docx"));

  // Launch File Handler dialog and get the web contents of the dialog to be
  // able to query `FileHandlerPageElement`.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, CloudProvider::kGoogleDrive,
          std::move(cloud_open_metrics), "file-handler-page");

  // Click the close button and wait for the dialog to close.
  content::WebContentsDestroyedWatcher watcher(web_contents);
  EXPECT_TRUE(content::ExecJs(web_contents,
                              "document.querySelector('file-handler-page')"
                              ".$('.cancel-button').click()"));
  watcher.Wait();

  // Expect a kCancelledAtSetup TaskResult.
  histogram_.ExpectUniqueSample(
      ash::cloud_upload::kGoogleDriveTaskResultMetricName,
      ash::cloud_upload::OfficeTaskResult::kCancelledAtSetup, 1);

  // cloud_open_metrics should have been destroyed by the end of the test.
  ASSERT_TRUE(cloud_open_metrics_weak_ptr.WasInvalidated());
}

// Test which launches a `CloudUploadDialog` which in turn creates a
// `FileHandlerPageElement`. Tests that closing the Files app the dialog is
// modal to also closes the dialog and a Cancel TaskResult is logged.
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest,
                       ClosingFilesAppCancelsDialog) {
  auto cloud_open_metrics = std::make_unique<CloudOpenMetrics>(
      CloudProvider::kGoogleDrive, /*file_count=*/1);
  auto cloud_open_metrics_weak_ptr = cloud_open_metrics->GetWeakPtr();

  // Check that the Setup flow has never run and so the File Handler dialog will
  // be launched when CloudOpenTask::Execute() is called.
  ASSERT_FALSE(file_manager::file_tasks::HasExplicitDefaultFileHandler(
      profile(), ".docx"));

  // Launch File Handler dialog and get the web contents of the dialog.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, CloudProvider::kGoogleDrive,
          std::move(cloud_open_metrics), "file-handler-page");

  // Close the Files app and wait for the dialog to close.
  content::WebContentsDestroyedWatcher watcher(web_contents);
  Browser* files_app_browser =
      FindSystemWebAppBrowser(profile(), SystemWebAppType::FILE_MANAGER);
  files_app_browser->window()->Close();
  watcher.Wait();

  // Expect a kCancelledAtSetup TaskResult.
  histogram_.ExpectUniqueSample(
      ash::cloud_upload::kGoogleDriveTaskResultMetricName,
      ash::cloud_upload::OfficeTaskResult::kCancelledAtSetup, 1);

  // cloud_open_metrics should have been destroyed by the end of the test.
  ASSERT_TRUE(cloud_open_metrics_weak_ptr.WasInvalidated());
}

// Test which launches a `CloudUploadDialog` which in turn creates a
// `FileHandlerPageElement`. Tests that when the dialog closes unexpectedly, a
// Cancel TaskResult is logged.
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest, DialogClosedUnexpectedly) {
  auto cloud_open_metrics = std::make_unique<CloudOpenMetrics>(
      CloudProvider::kGoogleDrive, /*file_count=*/1);
  auto cloud_open_metrics_weak_ptr = cloud_open_metrics->GetWeakPtr();

  // Check that the Setup flow has never run and so the File Handler dialog will
  // be launched when CloudOpenTask::Execute() is called.
  ASSERT_FALSE(file_manager::file_tasks::HasExplicitDefaultFileHandler(
      profile(), ".docx"));

  // Launch File Handler dialog and get the web contents of the dialog.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, CloudProvider::kGoogleDrive,
          std::move(cloud_open_metrics), "file-handler-page");

  // Close the dialog with no user response and wait for the dialog to close.
  content::WebContentsDestroyedWatcher watcher(web_contents);
  ash::SystemWebDialogDelegate* dialog =
      ash::SystemWebDialogDelegate::FindInstance(
          chrome::kChromeUICloudUploadURL);
  EXPECT_TRUE(dialog);
  dialog->Close();

  watcher.Wait();

  // Expect a kCancelledAtSetup TaskResult.
  histogram_.ExpectUniqueSample(
      ash::cloud_upload::kGoogleDriveTaskResultMetricName,
      ash::cloud_upload::OfficeTaskResult::kCancelledAtSetup, 1);

  // cloud_open_metrics should have been destroyed by the end of the test.
  ASSERT_TRUE(cloud_open_metrics_weak_ptr.WasInvalidated());
}

// Test which launches a `CloudUploadDialog` which in turn creates a
// `FileHandlerPageElement`. Tests that the `FileHandlerPageElement` observes
// all of the fake file tasks and that a file task can be launched by clicking
// on its button before clicking the open button. Tests that the correct
// TaskResult is logged
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest, OpenFileTaskFromDialog) {
  // Install QuickOffice.
  file_manager::test::AddDefaultComponentExtensionsOnMainThread(profile());

  auto cloud_open_metrics = std::make_unique<CloudOpenMetrics>(
      CloudProvider::kGoogleDrive, /*file_count=*/1);
  auto cloud_open_metrics_weak_ptr = cloud_open_metrics->GetWeakPtr();

  // Check that the Setup flow has never run and so the File Handler dialog will
  // be launched when CloudOpenTask::Execute() is called.
  ASSERT_FALSE(file_manager::file_tasks::HasExplicitDefaultFileHandler(
      profile(), ".docx"));

  // Launch File Handler dialog and get the web contents of the dialog to be
  // able to query `FileHandlerPageElement`.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, CloudProvider::kGoogleDrive,
          std::move(cloud_open_metrics), "file-handler-page");

  // Get the `tasks` member from the `FileHandlerPageElement` which are all of
  // the observed local file tasks.
  base::Value::List observed_app_ids;
  ASSERT_TRUE(base::test::RunUntil([&] {
    // It is possible that the `FileHandlerPageElement` element still hasn't
    // been initiated yet. It is completed when the `localTasks` member is
    // non-empty.
    content::EvalJsResult eval_result =
        content::EvalJs(web_contents,
                        "document.querySelector('file-handler-page')"
                        ".localTasks.map(task => task.appId)");
    if (!eval_result.error.empty()) {
      return false;
    }
    observed_app_ids = eval_result.ExtractList().TakeList();
    return !observed_app_ids.empty();
  }));

// Check QuickOffice was observed by the dialog as it should always be shown.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  ASSERT_TRUE(file_manager::file_tasks::IsQuickOfficeInstalled(profile()));
  ASSERT_GE(PositionInList(observed_app_ids,
                           extension_misc::kQuickOfficeComponentExtensionId),
            0);
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)

  // Position (in the `tasks_` and `urls_` vector) of the selected file
  // task to be opened. Use this to find the `selected_task_position` and to
  // watch for the appropriate url in `urls_` to open.
  size_t selected_task = 1;
  // Position of the selected task in dialog's localTasks array - this is not
  // necessarily the same as the `tasks_` vector. Its position is its id
  // so use this to click the task's button.
  size_t selected_task_position;

  // Check that each local file task was observed in the dialog.
  for (size_t i = 0; i < tasks_.size(); i++) {
    int position = PositionInList(observed_app_ids, tasks_[i].app_id);
    ASSERT_GE(position, 0);
    // Record the `selected_task_position`.
    if (i == selected_task) {
      selected_task_position = position;
    }
  }

  // Watch for the selected task to open.
  content::TestNavigationObserver navigation_observer_task(
      (GURL(urls_[selected_task])));
  navigation_observer_task.StartWatchingNewWebContents();

  // Check that there is not a default task for doc files.
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kDocxMimeType, kDocxFileExtension));

  // Check that there is not a default task for pptx files.
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kPptxMimeType, kPptxFileExtension));

  // Expand local tasks accordion.
  EXPECT_TRUE(content::ExecJs(
      web_contents,
      "document.querySelector('file-handler-page').$('#accordion').click()"));

  // Click the selected task.
  std::string position_string = base::NumberToString(selected_task_position);
  EXPECT_TRUE(content::ExecJs(
      web_contents, "document.querySelector('file-handler-page').$('#id" +
                        position_string + "').click()"));

  // Click the open button.
  EXPECT_TRUE(content::ExecJs(web_contents,
                              "document.querySelector('file-handler-page')"
                              ".$('.action-button').click()"));

  // Wait for selected task to open.
  navigation_observer_task.Wait();

  // Check that the Setup flow has been marked complete.
  ASSERT_TRUE(file_manager::file_tasks::HasExplicitDefaultFileHandler(profile(),
                                                                      ".docx"));

  // Check that the selected task has been made the default for doc files.
  ASSERT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                *profile()->GetPrefs(), kDocxMimeType, kDocxFileExtension),
            tasks_[selected_task]);

  // Check that the selected task has been made the default for pptx files.
  ASSERT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                *profile()->GetPrefs(), kPptxMimeType, kPptxFileExtension),
            tasks_[selected_task]);

  // Check that the selected task has not been made the default for xlsx files
  // because there was not an xlsx file selected by the user, even though the
  // task supports xlsx files.
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kXlsxMimeType, kXlsxFileExtension));

  histogram_.ExpectUniqueSample(
      ash::cloud_upload::kGoogleDriveTaskResultMetricName,
      ash::cloud_upload::OfficeTaskResult::kLocalFileTask, 1);

  // cloud_open_metrics should have been destroyed by the end of the test.
  ASSERT_TRUE(cloud_open_metrics_weak_ptr.WasInvalidated());
}

IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest, DefaultSetForDocsOnly) {
  // Check that the Setup flow has never run and so the File
  // Handler dialog will be launched when CloudOpenTask::Execute() is
  // called.
  ASSERT_FALSE(file_manager::file_tasks::HasExplicitDefaultFileHandler(
      profile(), ".docx"));

  // Launch File Handler dialog and get the web contents of the dialog to be
  // able to query `FileHandlerPageElement`.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, CloudProvider::kGoogleDrive,
          std::make_unique<CloudOpenMetrics>(CloudProvider::kGoogleDrive,
                                             /*file_count=*/1),
          "file-handler-page");

  // Wait for local tasks to be filled in, which indicates the dialog is ready.
  ASSERT_TRUE(base::test::RunUntil([&] {
    // It is possible that the `FileHandlerPageElement` element still hasn't
    // been initiated yet. It is completed when the `localTasks` member is
    // non-empty.
    content::EvalJsResult eval_result =
        content::EvalJs(web_contents,
                        "document.querySelector('file-handler-page')"
                        ".localTasks.map(task => task.appId)");
    if (!eval_result.error.empty()) {
      return false;
    }
    return !eval_result.ExtractList().TakeList().empty();
  }));

  // Check that there is not a default task for doc/x files.
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kDocMimeType, kDocFileExtension));
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kDocxMimeType, kDocxFileExtension));

  // Check that there is not a default task for ppt/x files.
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kPptMimeType, kPptFileExtension));
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kPptxMimeType, kPptxFileExtension));

  // Click the Docs task.
  EXPECT_TRUE(content::ExecJs(
      web_contents,
      "document.querySelector('file-handler-page').$('#drive').click()"));

  content::TestNavigationObserver navigation_observer_move_page(
      (GURL(chrome::kChromeUICloudUploadURL)));
  navigation_observer_move_page.StartWatchingNewWebContents();

  // Click the open button.
  EXPECT_TRUE(content::ExecJs(web_contents,
                              "document.querySelector('file-handler-page')"
                              ".$('.action-button').click()"));

  // Wait for the move confirmation dialog to open, so we know that the File
  // Handler dialog closed.
  navigation_observer_move_page.Wait();
  ASSERT_TRUE(navigation_observer_move_page.last_navigation_succeeded());

  // Check that the Setup flow has been marked complete.
  ASSERT_TRUE(file_manager::file_tasks::HasExplicitDefaultFileHandler(profile(),
                                                                      ".docx"));

  // Check that the Docs/Slides task has been made the default for doc/x and
  // ppt/x files, but the Sheets task has not been made default for xlsx files,
  // because there was not an xlsx file selected by the user.
  ASSERT_THAT(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                  *profile()->GetPrefs(), kDocMimeType, kDocFileExtension),
              IsWebDriveOfficeTask());
  ASSERT_THAT(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                  *profile()->GetPrefs(), kDocxMimeType, kDocxFileExtension),
              IsWebDriveOfficeTask());
  ASSERT_THAT(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                  *profile()->GetPrefs(), kPptMimeType, kPptFileExtension),
              IsWebDriveOfficeTask());
  ASSERT_THAT(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                  *profile()->GetPrefs(), kPptxMimeType, kPptxFileExtension),
              IsWebDriveOfficeTask());

  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kXlsxMimeType, kXlsxFileExtension));
}

// Helper to launch Files app and return its NativeWindow.
gfx::NativeWindow LaunchFilesAppAndWait(Profile* profile) {
  GURL files_swa_url = file_manager::util::GetFileManagerMainPageUrlWithParams(
      ui::SelectFileDialog::SELECT_NONE, /*title=*/std::u16string(),
      /*current_directory_url=*/{},
      /*selection_url=*/GURL(),
      /*target_name=*/{}, /*file_types=*/{},
      /*file_type_index=*/0,
      /*search_query=*/{},
      /*show_android_picker_apps=*/false,
      /*volume_filter=*/{});
  ash::SystemAppLaunchParams params;
  params.url = files_swa_url;
  ash::LaunchSystemWebAppAsync(profile, ash::SystemWebAppType::FILE_MANAGER,
                               params);
  Browser* files_app = ui_test_utils::WaitForBrowserToOpen();
  return files_app->window()->GetNativeWindow();
}

class CloudUploadDialogNoTasksBrowserTest
    : public FileHandlerDialogBrowserTest {
 public:
  CloudUploadDialogNoTasksBrowserTest()
      : FileHandlerDialogBrowserTest(/*num_tasks=*/0) {}
};

class CloudUploadDialogHandlerDisabledBrowserTest
    : public CloudUploadDialogNoTasksBrowserTest,
      public testing::WithParamInterface<bool> {};

// Suite with `true` means that `prefs::GoogleWorkspaceCloudUpload` is `allowed`
// and `prefs::MicrosoftOfficeCloudUpload` is `disallowed`. Suite with `false`
// means that `prefs::GoogleWorkspaceCloudUpload` is `disallowed` and
// `prefs::MicrosoftOfficeCloudUpload` is `allowed`.
// Tests that when only one handler is available (Google or Microsoft) in
// absence of local tasks, the user is brought directly to the move confirmation
// page instead of file handling dialog.
IN_PROC_BROWSER_TEST_P(CloudUploadDialogHandlerDisabledBrowserTest,
                       FileHandlingDialogSkipped) {
  const bool google_workspace_test = GetParam();
  auto* prefs = profile()->GetPrefs();
  if (google_workspace_test) {
    // Disable Microsoft365.
    prefs->SetString(prefs::kGoogleWorkspaceCloudUpload,
                     chromeos::cloud_upload::kCloudUploadPolicyAllowed);
    prefs->SetString(prefs::kMicrosoftOfficeCloudUpload,
                     chromeos::cloud_upload::kCloudUploadPolicyDisallowed);
  } else {
    // Disable Google Workspace.
    prefs->SetString(prefs::kGoogleWorkspaceCloudUpload,
                     chromeos::cloud_upload::kCloudUploadPolicyDisallowed);
    prefs->SetString(prefs::kMicrosoftOfficeCloudUpload,
                     chromeos::cloud_upload::kCloudUploadPolicyAllowed);

    // Perform the necessary OneDrive & Microsoft365 setup.
    file_manager::test::MountFakeProvidedFileSystemOneDrive(profile());
    file_manager::test::AddFakeWebApp(
        web_app::kMicrosoft365AppId, kDocMimeType, kDocFileExtension, "", true,
        apps::AppServiceProxyFactory::GetForProfile(profile()));
  }

  const auto& doc_file = files_[0];
  ASSERT_EQ(doc_file.path().Extension(), ".docx");

  const CloudProvider cloud_provider = google_workspace_test
                                           ? CloudProvider::kGoogleDrive
                                           : CloudProvider::kOneDrive;
  // Launch move confirmation dialog and get the web contents of the dialog to
  // be able to query `MoveConfirmationPageElement`.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), {doc_file}, cloud_provider,
          std::make_unique<CloudOpenMetrics>(cloud_provider, /*file_count=*/1),
          "move-confirmation-page");

  constexpr char kGetProviderNameScript[] = R"(
    (async () => {
      const page = document.querySelector('move-confirmation-page');
      return page.getProviderName(page.cloudProvider);
    })();
  )";

  // Validate that the confirmation page is displayed for the correct drive.
  ASSERT_EQ(content::EvalJs(web_contents, kGetProviderNameScript),
            l10n_util::GetStringUTF8(
                google_workspace_test ? IDS_OFFICE_CLOUD_PROVIDER_GOOGLE_DRIVE
                                      : IDS_OFFICE_CLOUD_PROVIDER_ONEDRIVE));
}

INSTANTIATE_TEST_SUITE_P(/**/,
                         CloudUploadDialogHandlerDisabledBrowserTest,
                         testing::Bool());

// Tests that when only Microsoft365 is available in absence of local tasks and
// the fixup flow is required, the user is brought to the M365 setup page.
IN_PROC_BROWSER_TEST_F(
    CloudUploadDialogNoTasksBrowserTest,
    OneDriveSetupDialogShownWhenFixupFlowIsNecessaryForMicrosoft365) {
  auto* prefs = profile()->GetPrefs();
  prefs->SetString(prefs::kGoogleWorkspaceCloudUpload,
                   chromeos::cloud_upload::kCloudUploadPolicyDisallowed);
  prefs->SetString(prefs::kMicrosoftOfficeCloudUpload,
                   chromeos::cloud_upload::kCloudUploadPolicyAllowed);

  const auto& doc_file = files_[0];
  ASSERT_EQ(doc_file.path().Extension(), ".docx");

  // ODFS and O365 App are not installed, so fixup will be required.

  // Launch setup dialog. This returns once the CloudUploadElement (setup page)
  // exists.
  LaunchCloudUploadDialogAndGetWebContentsForDialog(
      profile(), {doc_file}, CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1),
      "cloud-upload");
}

// Runs each test in four configurations (Google And Microsoft prefs
// respectively):
//   * `automated` and `allowed`
//   * `automated` and `disallowed`
//   * `allowed` and `automated`
//   * `disallowed` and `automated`
class FileHandlerDialogBrowserTestWithAutomatedFlow
    : public FileHandlerDialogBrowserTest,
      public testing::WithParamInterface<
          std::tuple<std::string_view, std::string_view>> {
 protected:
  // Tests that there are no explicit file handlers set for office extensions &
  // mime types.
  bool ExplicitFileHandlersForOfficeExtensionsAndMimeTypesNotSet() {
    return ExplicitFileHandlersForExtensionsAndMimeTypesNotSet(
               fm_tasks::WordGroupExtensions(),
               fm_tasks::WordGroupMimeTypes()) &&
           ExplicitFileHandlersForExtensionsAndMimeTypesNotSet(
               fm_tasks::ExcelGroupExtensions(),
               fm_tasks::ExcelGroupMimeTypes()) &&
           ExplicitFileHandlersForExtensionsAndMimeTypesNotSet(
               fm_tasks::PowerPointGroupExtensions(),
               fm_tasks::PowerPointGroupMimeTypes());
  }

  // Tests that there are no explicit file handlers set for the given extensions
  // and mime types.
  bool ExplicitFileHandlersForExtensionsAndMimeTypesNotSet(
      const std::set<std::string>& extensions,
      const std::set<std::string>& mime_types) {
    const auto& prefs = *profile()->GetPrefs();
    for (const auto& extension : extensions) {
      if (fm_tasks::GetDefaultTaskFromPrefs(prefs,
                                            /*mime_type=*/{}, extension)) {
        return false;
      }
    }
    for (const auto& mime_type : mime_types) {
      fm_tasks::TaskDescriptor default_task;
      if (fm_tasks::GetDefaultTaskFromPrefs(prefs, mime_type,
                                            /*suffix=*/{})) {
        return false;
      }
    }
    return true;
  }

  // Tests that explicit file handlers for office extensions & mime types are
  // set to the correct handler (Google Workspace or Microsoft Office depending
  // on the test configuration).
  bool ExplicitFileHandlersForOfficeExtensionsAndMimeTypesSet() {
    const bool google_workspace_test =
        chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(
            profile());
    return ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
               fm_tasks::WordGroupExtensions(), fm_tasks::WordGroupMimeTypes(),
               google_workspace_test ? fm_tasks::kActionIdWebDriveOfficeWord
                                     : fm_tasks::kActionIdOpenInOffice) &&
           ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
               fm_tasks::ExcelGroupExtensions(),
               fm_tasks::ExcelGroupMimeTypes(),
               google_workspace_test ? fm_tasks::kActionIdWebDriveOfficeExcel
                                     : fm_tasks::kActionIdOpenInOffice) &&
           ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
               fm_tasks::PowerPointGroupExtensions(),
               fm_tasks::PowerPointGroupMimeTypes(),
               google_workspace_test
                   ? fm_tasks::kActionIdWebDriveOfficePowerPoint
                   : fm_tasks::kActionIdOpenInOffice);
  }

  // Tests that there are no explicit file handlers set for the given extensions
  // and mime types are set to a task with a given |action_id|.
  bool ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      const std::set<std::string>& extensions,
      const std::set<std::string>& mime_types,
      std::string_view action_id) {
    return ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
        extensions, mime_types,
        /*task=*/
        fm_tasks::TaskDescriptor(file_manager::kFileManagerSwaAppId,
                                 fm_tasks::TASK_TYPE_WEB_APP,
                                 fm_tasks::ToSwaActionId(action_id)));
  }

  // Tests that there are no explicit file handlers set for the given extensions
  // and mime types are set to a particular |task|.
  bool ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      const std::set<std::string>& extensions,
      const std::set<std::string>& mime_types,
      const fm_tasks::TaskDescriptor& task) {
    const auto& prefs = *profile()->GetPrefs();
    for (const auto& extension : extensions) {
      if (fm_tasks::GetDefaultTaskFromPrefs(prefs,
                                            /*mime_type=*/{},
                                            extension) != task) {
        return false;
      }
    }
    for (const auto& mime_type : mime_types) {
      if (fm_tasks::GetDefaultTaskFromPrefs(prefs, mime_type, /*suffix=*/{}) !=
          task) {
        return false;
      }
    }
    return true;
  }

  // Assigns Google & Microsoft prefs to param values for this test.
  void AssignClippyPrefs() {
    auto [google_workspace_cloud_upload, microsoft_office_cloud_upload] =
        GetParam();
    auto* prefs = profile()->GetPrefs();
    prefs->SetString(prefs::kGoogleWorkspaceCloudUpload,
                     google_workspace_cloud_upload);
    prefs->SetString(prefs::kMicrosoftOneDriveMount,
                     microsoft_office_cloud_upload);
    prefs->SetString(prefs::kMicrosoftOfficeCloudUpload,
                     microsoft_office_cloud_upload);
  }
};

// Tests that when one handler is automated, the user is brought directly to the
// move confirmation page instead of file handling dialog.
IN_PROC_BROWSER_TEST_P(FileHandlerDialogBrowserTestWithAutomatedFlow,
                       AutomatedClippyFlow) {
  EXPECT_TRUE(ExplicitFileHandlersForOfficeExtensionsAndMimeTypesNotSet());

  AssignClippyPrefs();

  if (chromeos::cloud_upload::IsMicrosoftOfficeCloudUploadAutomated(
          profile())) {
    // Perform the necessary OneDrive & Microsoft365 setup.
    file_manager::test::MountFakeProvidedFileSystemOneDrive(profile());
    file_manager::test::AddFakeWebApp(
        web_app::kMicrosoft365AppId, kDocMimeType, kDocFileExtension, "", true,
        apps::AppServiceProxyFactory::GetForProfile(profile()));
  }

  EXPECT_TRUE(ExplicitFileHandlersForOfficeExtensionsAndMimeTypesSet());

  const CloudProvider cloud_provider =
      chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(profile())
          ? CloudProvider::kGoogleDrive
          : CloudProvider::kOneDrive;
  // Launch move confirmation dialog and get the web contents of the dialog to
  // be able to query `MoveConfirmationPageElement`.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, cloud_provider,
          std::make_unique<CloudOpenMetrics>(cloud_provider, /*file_count=*/1),
          "move-confirmation-page");

  constexpr char kGetProviderNameScript[] = R"(
    (async () => {
      const page = document.querySelector('move-confirmation-page');
      return page.getProviderName(page.cloudProvider);
    })();
  )";

  // Validate that the confirmation page is displayed for the correct drive.
  ASSERT_EQ(content::EvalJs(web_contents, kGetProviderNameScript),
            l10n_util::GetStringUTF8(
                chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(
                    profile())
                    ? IDS_OFFICE_CLOUD_PROVIDER_GOOGLE_DRIVE
                    : IDS_OFFICE_CLOUD_PROVIDER_ONEDRIVE));
}

// Tests that toggling the pref to `automated` and then back to `disallowed`
// first assigns and then reset office file handlers.
IN_PROC_BROWSER_TEST_P(FileHandlerDialogBrowserTestWithAutomatedFlow,
                       InvertFileHandlers) {
  // Initially no handlers should be set.
  EXPECT_TRUE(ExplicitFileHandlersForOfficeExtensionsAndMimeTypesNotSet());

  AssignClippyPrefs();

  // Now all office handlers are set to either Google or Microsoft (depending on
  // the test param).
  EXPECT_TRUE(ExplicitFileHandlersForOfficeExtensionsAndMimeTypesSet());

  // Now toggle the automated policy to disallowed.
  profile()->GetPrefs()->SetString(
      chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(profile())
          ? prefs::kGoogleWorkspaceCloudUpload
          : prefs::kMicrosoftOfficeCloudUpload,
      kCloudUploadPolicyDisallowed);

  // All handlers are reset.
  EXPECT_TRUE(ExplicitFileHandlersForOfficeExtensionsAndMimeTypesNotSet());
}

// Tests that toggling the pref to `automated` and then back to `disallowed`
// respects existing user prefs if they're set to other handlers for selected
// office extensions or mime types.
IN_PROC_BROWSER_TEST_P(FileHandlerDialogBrowserTestWithAutomatedFlow,
                       PreexistingFileHandlersAreNotOverwritten) {
  std::set<std::string> test_extensions({".docx", ".pptx", ".xslx"});
  std::set<std::string> test_mime_types({"application/msword",
                                         "application/vnd.ms-excel",
                                         "application/vnd.ms-excel"});

  // Create sets of office extensions excluding the ones reserved for testing.
  std::set<std::string> word_extensions(fm_tasks::WordGroupExtensions());
  std::set<std::string> excel_extensions(fm_tasks::ExcelGroupExtensions());
  std::set<std::string> power_point_extensions(
      fm_tasks::PowerPointGroupExtensions());
  for (const auto& extension : test_extensions) {
    word_extensions.erase(extension);
    excel_extensions.erase(extension);
    power_point_extensions.erase(extension);
  }

  // Create sets of office mime types excluding the ones reserved for testing.
  std::set<std::string> word_mime_types(fm_tasks::WordGroupMimeTypes());
  std::set<std::string> excel_mime_types(fm_tasks::ExcelGroupMimeTypes());
  std::set<std::string> power_point_mime_types(
      fm_tasks::PowerPointGroupMimeTypes());
  for (const auto& mime_type : test_mime_types) {
    word_mime_types.erase(mime_type);
    excel_mime_types.erase(mime_type);
    power_point_mime_types.erase(mime_type);
  }

  // Initially no handlers should be set.
  EXPECT_TRUE(ExplicitFileHandlersForOfficeExtensionsAndMimeTypesNotSet());

  constexpr char kAppId[] = "app_id";
  constexpr char kActionId[] = "action_id";
  const fm_tasks::TaskDescriptor descriptor(
      kAppId, fm_tasks::TASK_TYPE_FILE_HANDLER, kActionId);
  // Imitate a user setting default preferences for selected extensions & mime
  // types.
  fm_tasks::UpdateDefaultTask(profile(), descriptor, test_extensions,
                              test_mime_types);

  // Check that the handlers have been propagated.
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      test_extensions, test_mime_types, descriptor));

  AssignClippyPrefs();

  // Check that user-selected handlers remain unchanged on `automated`.
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      test_extensions, test_mime_types, descriptor));

  // Check that other office extensions & mime types are set to Google or
  // Microsoft.
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      word_extensions, word_mime_types,
      chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(profile())
          ? fm_tasks::kActionIdWebDriveOfficeWord
          : fm_tasks::kActionIdOpenInOffice));
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      excel_extensions, excel_mime_types,
      chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(profile())
          ? fm_tasks::kActionIdWebDriveOfficeExcel
          : fm_tasks::kActionIdOpenInOffice));
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      power_point_extensions, power_point_mime_types,
      chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(profile())
          ? fm_tasks::kActionIdWebDriveOfficePowerPoint
          : fm_tasks::kActionIdOpenInOffice));

  // Now toggle the automated policy to disallowed.
  profile()->GetPrefs()->SetString(
      chromeos::cloud_upload::IsGoogleWorkspaceCloudUploadAutomated(profile())
          ? prefs::kGoogleWorkspaceCloudUpload
          : prefs::kMicrosoftOfficeCloudUpload,
      kCloudUploadPolicyDisallowed);

  // Check that user-selected handlers remain unchanged on `disallowed`.
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesSetTo(
      test_extensions, test_mime_types, descriptor));

  // Check that other office extensions & mime types are reset.
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesNotSet(
      word_extensions, word_mime_types));
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesNotSet(
      excel_extensions, excel_mime_types));
  EXPECT_TRUE(ExplicitFileHandlersForExtensionsAndMimeTypesNotSet(
      power_point_extensions, power_point_mime_types));
}

INSTANTIATE_TEST_SUITE_P(
    /**/,
    FileHandlerDialogBrowserTestWithAutomatedFlow,
    testing::ValuesIn(
        std::vector<std::tuple<std::string_view, std::string_view>>(
            {{kCloudUploadPolicyAutomated, kCloudUploadPolicyAllowed},
             {kCloudUploadPolicyAutomated, kCloudUploadPolicyDisallowed},
             {kCloudUploadPolicyAllowed, kCloudUploadPolicyAutomated},
             {kCloudUploadPolicyDisallowed, kCloudUploadPolicyAutomated}})));

IN_PROC_BROWSER_TEST_F(
    FileHandlerDialogBrowserTest,
    ShowConnectOneDriveDialogWithModalParent_OpensAndClosesDialog) {
  // Watch for the Connect OneDrive dialog URL chrome://cloud-upload.
  content::TestNavigationObserver navigation_observer_dialog(
      (GURL(chrome::kChromeUICloudUploadURL)));
  navigation_observer_dialog.StartWatchingNewWebContents();

  // Launch the Connect OneDrive dialog on top of a files app.
  gfx::NativeWindow modal_parent = LaunchFilesAppAndWait(browser()->profile());
  ASSERT_TRUE(ShowConnectOneDriveDialog(modal_parent));

  // Wait for chrome://cloud-upload to open.
  navigation_observer_dialog.Wait();
  ASSERT_TRUE(navigation_observer_dialog.last_navigation_succeeded());

  // Check that we have the right DOM element (Connect OneDrive).
  content::WebContents* web_contents = GetWebContentsFromCloudUploadDialog();
  WaitUntilElementExists(web_contents, "connect-onedrive");

  // Click the close button and wait for the dialog to close.
  content::WebContentsDestroyedWatcher watcher(web_contents);
  EXPECT_TRUE(content::ExecJs(web_contents,
                              "document.querySelector('connect-onedrive')"
                              ".$('.cancel-button').click()"));
  watcher.Wait();
}

IN_PROC_BROWSER_TEST_F(
    FileHandlerDialogBrowserTest,
    ShowConnectOneDriveDialogWithoutModalParent_OpensAndClosesDialog) {
  // Watch for the Connect OneDrive dialog URL chrome://cloud-upload.
  content::TestNavigationObserver navigation_observer_dialog(
      (GURL(chrome::kChromeUICloudUploadURL)));
  navigation_observer_dialog.StartWatchingNewWebContents();

  // Launch the Connect OneDrive dialog without a modal parent.
  ASSERT_TRUE(ShowConnectOneDriveDialog(nullptr));

  // Wait for chrome://cloud-upload to open.
  navigation_observer_dialog.Wait();
  ASSERT_TRUE(navigation_observer_dialog.last_navigation_succeeded());

  // Check that we have the right DOM element (Connect OneDrive).
  content::WebContents* web_contents = GetWebContentsFromCloudUploadDialog();
  WaitUntilElementExists(web_contents, "connect-onedrive");

  // Click the close button and wait for the dialog to close.
  content::WebContentsDestroyedWatcher watcher(web_contents);
  EXPECT_TRUE(content::ExecJs(web_contents,
                              "document.querySelector('connect-onedrive')"
                              ".$('.cancel-button').click()"));
  watcher.Wait();
}

// Tests that OnSetupDialogComplete() opens the specified fake file task.
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest,
                       OnSetupDialogCompleteOpensFileTasks) {
  auto cloud_open_metrics = std::make_unique<CloudOpenMetrics>(
      CloudProvider::kGoogleDrive, /*file_count=*/1);
  auto cloud_open_metrics_weak_ptr = cloud_open_metrics->GetWeakPtr();
  {
    file_manager::file_tasks::TaskDescriptor default_task;

    auto cloud_open_task = base::WrapRefCounted(new CloudOpenTask(
        profile(), files_, file_manager::file_tasks::TaskDescriptor(),
        CloudProvider::kGoogleDrive, std::move(cloud_open_metrics)));
    cloud_open_task->SetTasksForTest(tasks_);

    for (int selected_task = 0; selected_task < num_tasks_; selected_task++) {
      std::string user_response = base::NumberToString(selected_task);
      // Watch for the selected task to open.
      content::TestNavigationObserver navigation_observer_task(
          (GURL(urls_[selected_task])));
      navigation_observer_task.StartWatchingNewWebContents();

      // Simulate user selecting this task.
      cloud_open_task->OnSetupDialogComplete(user_response);

      // Wait for the selected task to open.
      navigation_observer_task.Wait();

      // Check that the selected task has been made the default.
      ASSERT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                    *profile()->GetPrefs(), kPptxMimeType, kPptxFileExtension),
                tasks_[selected_task]);
    }
  }
  // cloud_open_metrics should have been destroyed by the end of the test.
  ASSERT_TRUE(cloud_open_metrics_weak_ptr.WasInvalidated());
}

// Tests that OnSetupDialogComplete() doesn't crash when the specified selected
// task doesn't exist.
IN_PROC_BROWSER_TEST_F(FileHandlerDialogBrowserTest,
                       OnSetupDialogCompleteNoCrash) {
  auto cloud_open_metrics = std::make_unique<CloudOpenMetrics>(
      CloudProvider::kGoogleDrive, /*file_count=*/1);
  auto cloud_open_metrics_weak_ptr = cloud_open_metrics->GetWeakPtr();
  {
    auto cloud_open_task = base::WrapRefCounted(new CloudOpenTask(
        profile(), files_, file_manager::file_tasks::TaskDescriptor(),
        CloudProvider::kGoogleDrive, std::move(cloud_open_metrics)));
    cloud_open_task->SetTasksForTest(tasks_);

    int out_of_range_task = num_tasks_;
    std::string user_response = base::NumberToString(out_of_range_task);

    // Simulate user selecting a nonexistent selected task.
    cloud_open_task->OnSetupDialogComplete(user_response);
  }
  // cloud_open_metrics should have been destroyed by the end of the test.
  ASSERT_TRUE(cloud_open_metrics_weak_ptr.WasInvalidated());
}

// Tests the Fixup flow. Ensures that it is run when the conditions are met: the
// Setup flow has completed, ODFS is not mounted or the Office PWA is not
// installed and OneDrive is selected as the cloud provider. Ensures that it
// cannot change the default task set.
class FixUpFlowBrowserTest : public InProcessBrowserTest {
 public:
  FixUpFlowBrowserTest() {
    feature_list_.InitAndEnableFeature(
        chromeos::features::kUploadOfficeToCloud);
  }

  FixUpFlowBrowserTest(const FixUpFlowBrowserTest&) = delete;
  FixUpFlowBrowserTest& operator=(const FixUpFlowBrowserTest&) = delete;

  Profile* profile() { return browser()->profile(); }

  void SetUpOnMainThread() override {
    // Needed to check that Files app was launched as the dialog's modal parent.
    ash::SystemWebAppManager::GetForTest(browser()->profile())
        ->InstallSystemAppsForTesting();
  }

  // Add a doc test file.
  void SetUpFiles() {
    base::FilePath file =
        file_manager::util::GetMyFilesFolderForProfile(profile()).AppendASCII(
            "foo.doc");
    files_.push_back(FilePathToFileSystemURL(
        profile(),
        file_manager::util::GetFileManagerFileSystemContext(profile()), file));
  }

  void AddFakeODFS() {
    file_manager::test::MountFakeProvidedFileSystemOneDrive(profile());
  }

  void AddFakeOfficePWA() {
    file_manager::test::AddFakeWebApp(
        web_app::kMicrosoft365AppId, kDocMimeType, kDocFileExtension, "", true,
        apps::AppServiceProxyFactory::GetForProfile(profile()));
  }

 protected:
  // Use a non-managed user in this browser test to ensure
  // |IsEligibleAndEnabledUploadOfficeToCloud| returns the result of
  // |IsUploadOfficeToCloudEnabled|.
  void SetUpCommandLine(base::CommandLine* command_line) override {
    SetUpCommandLineForNonManagedUser(command_line);
  }
  std::vector<storage::FileSystemURL> files_;

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

using file_manager::file_tasks::kActionIdWebDriveOfficeWord;
using file_manager::file_tasks::SetWordFileHandlerToFilesSWA;

// Tests that the Fixup flow is entered when OneDrive is selected as the cloud
// provider but ODFS is not mounted and the Setup flow has already completed.
// Checks that the ODFS Sign In Page is reachable.
IN_PROC_BROWSER_TEST_F(FixUpFlowBrowserTest, FixUpFlowWhenODFSNotMounted) {
  // Simulate prefs where the setup flow has already run.
  SetWordFileHandlerToFilesSWA(profile(), kActionIdWebDriveOfficeWord);

  SetUpFiles();
  AddFakeOfficePWA();

  // ODFS is not mounted, expect that the Fixup flow will need to run.
  ASSERT_TRUE(ShouldFixUpOffice(profile(), CloudProvider::kOneDrive));

  LaunchFilesAppAndWait(browser()->profile());

  // Launch setup and get the web contents of the dialog to be able to
  // query `CloudUploadElement`.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, CloudProvider::kOneDrive,
          std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                             /*file_count=*/1),
          "cloud-upload");

  // Wait until the "cloud-upload" DOM element is properly initialised.
  WaitUntilJsReturnsTrue(
      web_contents,
      "!!document.querySelector('cloud-upload').$('welcome-page')");

  // Click through the Welcome Page.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('welcome-page')"
      ".querySelector('.action-button').click()")) {
  }

  // Wait for the ODFS Sign In Page.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('sign-in-page')"
      ".querySelector('.action-button')")) {
  }
}

// Tests that the Fixup flow is entered when OneDrive is selected as the cloud
// provider but the Office PWA is not installed and the Setup flow has already
// completed. Checks that the Office PWA Install Page is reachable.
IN_PROC_BROWSER_TEST_F(FixUpFlowBrowserTest,
                       FixUpFlowWhenOfficePWANotInstalled) {
  // Simulate prefs where the setup flow has already run.
  SetWordFileHandlerToFilesSWA(profile(), kActionIdWebDriveOfficeWord);

  SetUpFiles();
  AddFakeODFS();

  // Office PWA is not installed, expect that the Fixup flow will need to run.
  ASSERT_TRUE(ShouldFixUpOffice(profile(), CloudProvider::kOneDrive));

  LaunchFilesAppAndWait(browser()->profile());

  // Launch setup and get the web contents of the dialog to be able to
  // query `CloudUploadElement`.
  content::WebContents* web_contents =
      LaunchCloudUploadDialogAndGetWebContentsForDialog(
          profile(), files_, CloudProvider::kOneDrive,
          std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                             /*file_count=*/1),
          "cloud-upload");

  // Wait until the "cloud-upload" DOM element is properly initialised.
  WaitUntilJsReturnsTrue(
      web_contents,
      "!!document.querySelector('cloud-upload').$('welcome-page')");

  // Click through the Welcome Page.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('welcome-page')"
      ".querySelector('.action-button').click()")) {
  }

  // Wait for the Office PWA Install Page, this script will fail until the page
  // exists.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('office-pwa-install-page')"
      ".querySelector('.action-button')")) {
  }
}

// Tests that the existing Fixup/Setup dialog is brought to the front when
// trying to launch a second one for a different file.
IN_PROC_BROWSER_TEST_F(
    FixUpFlowBrowserTest,
    FixUpDialogBroughtToFrontWhenFailingToLaunchADifferentOne) {
  // Simulate prefs where the setup flow has already run.
  SetWordFileHandlerToFilesSWA(profile(), kActionIdWebDriveOfficeWord);

  SetUpFiles();

  // ODFS is not mounted, expect that the Fixup flow will need to run.
  ASSERT_TRUE(ShouldFixUpOffice(profile(), CloudProvider::kOneDrive));

  gfx::NativeWindow modal_parent1 = LaunchFilesAppAndWait(browser()->profile());

  // Launch the setup dialog at chrome://cloud-upload.
  LaunchCloudUploadDialogAndGetWebContentsForDialog(
      profile(), files_, CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1),
      "cloud-upload");

  gfx::NativeWindow modal_parent2 = LaunchFilesAppAndWait(browser()->profile());

  auto* modal_parent_widget1 =
      views::Widget::GetWidgetForNativeWindow(modal_parent1);
  auto* modal_parent_widget2 =
      views::Widget::GetWidgetForNativeWindow(modal_parent2);

  // The second files app would have launched above the setup dialog that is
  // modal to the first files app.
  ASSERT_TRUE(modal_parent_widget2->IsStackedAbove(
      modal_parent_widget1->GetNativeView()));
  ASSERT_TRUE(modal_parent_widget2->is_top_level());

  // A second setup dialog cannot be launched at chrome://cloud-upload as there
  // is already the setup dialog.
  base::FilePath file =
      file_manager::util::GetMyFilesFolderForProfile(profile()).AppendASCII(
          "foo2.doc");
  std::vector<storage::FileSystemURL> files;
  files.push_back(FilePathToFileSystemURL(
      profile(), file_manager::util::GetFileManagerFileSystemContext(profile()),
      file));
  ASSERT_FALSE(CloudOpenTask::Execute(
      profile(), files, file_manager::file_tasks::TaskDescriptor(),
      CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1)));

  // The setup dialog would have been brought to the front.
  ASSERT_TRUE(modal_parent_widget1->IsStackedAbove(
      modal_parent_widget2->GetNativeView()));
  ASSERT_TRUE(modal_parent_widget1->is_top_level());
}

// Tests that the existing Fixup/Setup dialog is brought to the front when
// trying to launch a second one for the same file.
IN_PROC_BROWSER_TEST_F(
    FixUpFlowBrowserTest,
    FixUpDialogBroughtToFrontWhenFailingToLaunchADuplicateOne) {
  // Simulate prefs where the setup flow has already run.
  SetWordFileHandlerToFilesSWA(profile(), kActionIdWebDriveOfficeWord);

  SetUpFiles();

  // ODFS is not mounted, expect that the Fixup flow will need to run.
  ASSERT_TRUE(ShouldFixUpOffice(profile(), CloudProvider::kOneDrive));

  gfx::NativeWindow modal_parent1 = LaunchFilesAppAndWait(browser()->profile());

  // Launch the setup dialog at chrome://cloud-upload.
  LaunchCloudUploadDialogAndGetWebContentsForDialog(
      profile(), files_, CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1),
      "cloud-upload");

  gfx::NativeWindow modal_parent2 = LaunchFilesAppAndWait(browser()->profile());

  auto* modal_parent_widget1 =
      views::Widget::GetWidgetForNativeWindow(modal_parent1);
  auto* modal_parent_widget2 =
      views::Widget::GetWidgetForNativeWindow(modal_parent2);

  // The second files app would have launched above the setup dialog that is
  // modal to the first files app.
  ASSERT_TRUE(modal_parent_widget2->IsStackedAbove(
      modal_parent_widget1->GetNativeView()));
  ASSERT_TRUE(modal_parent_widget2->is_top_level());

  // A duplicate setup dialog cannot be launched at chrome://cloud-upload as
  // there is already the setup dialog.
  ASSERT_FALSE(CloudOpenTask::Execute(
      profile(), files_, file_manager::file_tasks::TaskDescriptor(),
      CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1)));

  // The setup dialog would have been brought to the front.
  ASSERT_TRUE(modal_parent_widget1->IsStackedAbove(
      modal_parent_widget2->GetNativeView()));
  ASSERT_TRUE(modal_parent_widget1->is_top_level());
}

// Tests that the existing Fixup/Setup dialog is brought to the front when
// trying to launch a second one via `ShowConnectOneDriveDialog()`.
IN_PROC_BROWSER_TEST_F(
    FixUpFlowBrowserTest,
    FixUpDialogBroughtToFrontWhenShowConnectOneDriveDialogFailsToLaunch) {
  // Simulate prefs where the setup flow has already run.
  SetWordFileHandlerToFilesSWA(profile(), kActionIdWebDriveOfficeWord);

  SetUpFiles();

  // ODFS is not mounted, expect that the Fixup flow will need to run.
  ASSERT_TRUE(ShouldFixUpOffice(profile(), CloudProvider::kOneDrive));

  gfx::NativeWindow modal_parent = LaunchFilesAppAndWait(browser()->profile());

  // Launch the setup dialog at chrome://cloud-upload.
  LaunchCloudUploadDialogAndGetWebContentsForDialog(
      profile(), files_, CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1),
      "cloud-upload");

  // Launch a settings page.
  ash::LaunchSystemWebAppAsync(profile(), ash::SystemWebAppType::SETTINGS);
  Browser* files_app = ui_test_utils::WaitForBrowserToOpen();
  gfx::NativeWindow settings = files_app->window()->GetNativeWindow();

  auto* modal_parent_widget =
      views::Widget::GetWidgetForNativeWindow(modal_parent);
  auto* settings_widget = views::Widget::GetWidgetForNativeWindow(settings);

  // The settings would have launched above the setup dialog that is modal to
  // the first files app.
  ASSERT_TRUE(
      settings_widget->IsStackedAbove(modal_parent_widget->GetNativeView()));
  ASSERT_TRUE(settings_widget->is_top_level());

  // The Connect OneDrive dialog cannot be launched at chrome://cloud-upload as
  // there is already the setup dialog.
  ASSERT_FALSE(ShowConnectOneDriveDialog(nullptr));

  // The setup dialog would have been brought to the front.
  ASSERT_TRUE(
      modal_parent_widget->IsStackedAbove(settings_widget->GetNativeView()));
  ASSERT_TRUE(modal_parent_widget->is_top_level());
}

// Tests that `ShouldFixUpOffice()` returns true when neither ODFS is mounted
// nor Office PWA is installed and OneDrive is selected as the cloud provider.
IN_PROC_BROWSER_TEST_F(FixUpFlowBrowserTest, ShouldFixUpOfficeNoODFSNoPWA) {
  ASSERT_TRUE(ShouldFixUpOffice(profile(), CloudProvider::kOneDrive));
}

// Tests that `ShouldFixUpOffice()` returns false when neither ODFS is mounted
// nor Office PWA is installed but Drive is selected as the cloud provider.
IN_PROC_BROWSER_TEST_F(FixUpFlowBrowserTest, ShouldFixUpOfficeDrive) {
  ASSERT_FALSE(ShouldFixUpOffice(profile(), CloudProvider::kGoogleDrive));
}

// Tests that `ShouldFixUpOffice()` returns false when both ODFS is mounted and
// Office PWA is installed and OneDrive is selected as the cloud provider.
IN_PROC_BROWSER_TEST_F(FixUpFlowBrowserTest, ShouldFixUpOfficeODFSAndPWA) {
  AddFakeODFS();
  AddFakeOfficePWA();
  ASSERT_FALSE(ShouldFixUpOffice(profile(), CloudProvider::kOneDrive));
}

// Test that entering and completing the Setup flow from the OneDrive Set Up
// point changes the default task set when the Setup has not been run before.
IN_PROC_BROWSER_TEST_F(FixUpFlowBrowserTest,
                       OneDriveSetUpChangesDefaultTaskWhenSetUpIncomplete) {
  // Simulate Setup flow incomplete - prefs are empty to begin with.

  // Add a doc test file.
  SetUpFiles();
  AddFakeODFS();
  AddFakeOfficePWA();

  auto cloud_open_task = base::WrapRefCounted(new CloudOpenTask(
      profile(), files_, file_manager::file_tasks::TaskDescriptor(),
      CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1)));
  mojom::DialogArgsPtr args =
      cloud_open_task->CreateDialogArgs(SetupOrMoveDialogPage::kOneDriveSetup);
  // Self-deleted on close.
  CloudUploadDialog* dialog =
      new CloudUploadDialog(std::move(args), base::DoNothing(), false);

  // Watch for OneDrive Setup dialog URL chrome://cloud-upload.
  content::TestNavigationObserver navigation_observer_dialog(
      (GURL(chrome::kChromeUICloudUploadURL)));
  navigation_observer_dialog.StartWatchingNewWebContents();

  // Check that there is not a default task for doc or xlsx files.
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kDocMimeType, kDocFileExtension));
  ASSERT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
      *profile()->GetPrefs(), kXlsxMimeType, kXlsxFileExtension));

  // Open the Welcome Page for the OneDrive set up part of the Setup flow.
  // This will lead to the Office PWA being set as the default task.
  dialog->ShowSystemDialog();

  // Wait for chrome://cloud-upload to open.
  navigation_observer_dialog.Wait();
  ASSERT_TRUE(navigation_observer_dialog.last_navigation_succeeded());

  // Wait until the "cloud-upload" DOM element is properly initialised.
  content::WebContents* web_contents = GetWebContentsFromCloudUploadDialog();
  WaitUntilJsReturnsTrue(
      web_contents,
      "!!document.querySelector('cloud-upload').$('welcome-page')");

  // Click through the Welcome Page.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('welcome-page')"
      ".querySelector('.action-button').click()")) {
  }

  // Click through the Upload Page.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('complete-page')"
      ".querySelector('.action-button').click()")) {
  }

  // Check that the Office PWA has been made the default for doc and xlsx
  // files.
  ASSERT_THAT(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                  *profile()->GetPrefs(), kDocMimeType, kDocFileExtension),
              IsOpenInOfficeTask());
  ASSERT_THAT(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                  *profile()->GetPrefs(), kXlsxMimeType, kXlsxFileExtension),
              IsOpenInOfficeTask());
}

// Test that entering and completing the Setup flow from the OneDrive Set Up
// point does not change the default task set when there was already a default
// handler before setup. This is to test that when the Fixup flow runs, the
// default task does not change.
IN_PROC_BROWSER_TEST_F(FixUpFlowBrowserTest,
                       OneDriveSetUpDoesNotChangeDefaultTaskWhenSetUpComplete) {
  // Simulate prefs where the setup flow has already run.
  SetWordFileHandlerToFilesSWA(profile(), kActionIdWebDriveOfficeWord);

  // Add a doc test file.
  SetUpFiles();
  // Note: although mounting ODFS and installing the Office PWA sets up
  // conditions so that the Fixup flow does not need to be run, this test is
  // just to check that entering the Setup flow from OneDrive Setup point does
  // not set the default task when the Setup flow is already complete.
  // Otherwise, the test would get stuck trying to set up OneDrive, unable to
  // navigate through all the dialog pages.
  AddFakeODFS();
  AddFakeOfficePWA();

  auto cloud_open_task = base::WrapRefCounted(new CloudOpenTask(
      profile(), files_, file_manager::file_tasks::TaskDescriptor(),
      CloudProvider::kOneDrive,
      std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                         /*file_count=*/1)));
  mojom::DialogArgsPtr args =
      cloud_open_task->CreateDialogArgs(SetupOrMoveDialogPage::kOneDriveSetup);
  // Self-deleted on close.
  CloudUploadDialog* dialog =
      new CloudUploadDialog(std::move(args), base::DoNothing(), false);

  // Watch for OneDrive Setup dialog URL chrome://cloud-upload.
  content::TestNavigationObserver navigation_observer_dialog(
      (GURL(chrome::kChromeUICloudUploadURL)));
  navigation_observer_dialog.StartWatchingNewWebContents();

  // Open the Welcome Page for the OneDrive set up part of the Setup flow. This
  // will not lead to the Office PWA being set as the default task because there
  // was already a default before running setup.
  dialog->ShowSystemDialog();

  // Wait for chrome://cloud-upload to open.
  navigation_observer_dialog.Wait();
  ASSERT_TRUE(navigation_observer_dialog.last_navigation_succeeded());

  // Wait until the "cloud-upload" DOM element is properly initialised.
  content::WebContents* web_contents = GetWebContentsFromCloudUploadDialog();
  WaitUntilJsReturnsTrue(
      web_contents,
      "!!document.querySelector('cloud-upload').$('welcome-page')");

  // Click through the Welcome Page.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('welcome-page')"
      ".querySelector('.action-button').click()")) {
  }

  // Click through the Upload Page.
  while (!content::ExecJs(
      web_contents,
      "document.querySelector('cloud-upload').$('complete-page')"
      ".querySelector('.action-button').click()")) {
  }

  // Check that the default task for doc files is still Drive, and not OneDrive,
  // despite running fixup setup.
  ASSERT_THAT(file_manager::file_tasks::GetDefaultTaskFromPrefs(
                  *profile()->GetPrefs(), kDocMimeType, kDocFileExtension),
              testing::Optional(testing::Field(
                  &file_manager::file_tasks::TaskDescriptor::action_id,
                  testing::EndsWith(kActionIdWebDriveOfficeWord))));
}

class CloudOpenTaskBrowserTest : public InProcessBrowserTest {
 public:
  CloudOpenTaskBrowserTest() {
    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
    my_files_dir_ = temp_dir_.GetPath().Append("myfiles");
    read_only_dir_ = temp_dir_.GetPath().Append("readonly");
    smb_dir_ = temp_dir_.GetPath().Append("smb");
  }

  CloudOpenTaskBrowserTest(const CloudOpenTaskBrowserTest&) = delete;
  CloudOpenTaskBrowserTest& operator=(const CloudOpenTaskBrowserTest&) = delete;

  void TearDownOnMainThread() override {
    // Explictly destroy the `upload_task_` before the Profile* is destroyed.
    // Otherwise the `upload_task_` will be destroyed afterwards and the profile
    // pointer owned by the `upload_task_` will become dangling
    upload_task_.reset();
    InProcessBrowserTest::TearDownOnMainThread();
  }

  void SetUpLocalToDriveTask() {
    SetUpMyFiles();

    source_files_.push_back(FilePathToFileSystemURL(
        profile(),
        file_manager::util::GetFileManagerFileSystemContext(profile()),
        my_files_dir_.AppendASCII("file.docx")));

    upload_task_ = base::WrapRefCounted(new ash::cloud_upload::CloudOpenTask(
        profile(), source_files_, file_manager::file_tasks::TaskDescriptor(),
        ash::cloud_upload::CloudProvider::kGoogleDrive,
        std::make_unique<CloudOpenMetrics>(CloudProvider::kGoogleDrive,
                                           /*file_count=*/1)));
  }

  void SetUpCloudToDriveTask() {
    SetUpCloudLocation();

    source_files_.push_back(FilePathToFileSystemURL(
        profile(),
        file_manager::util::GetFileManagerFileSystemContext(profile()),
        smb_dir_.AppendASCII("file.docx")));

    upload_task_ = base::WrapRefCounted(new ash::cloud_upload::CloudOpenTask(
        profile(), source_files_, file_manager::file_tasks::TaskDescriptor(),
        ash::cloud_upload::CloudProvider::kGoogleDrive,
        std::make_unique<CloudOpenMetrics>(CloudProvider::kGoogleDrive,
                                           /*file_count=*/1)));
  }

  void SetUpReadOnlyToDriveTask() {
    SetUpReadOnlyLocation();

    source_files_.push_back(FilePathToFileSystemURL(
        profile(),
        file_manager::util::GetFileManagerFileSystemContext(profile()),
        read_only_dir_.AppendASCII("file.docx")));

    upload_task_ = base::WrapRefCounted(new ash::cloud_upload::CloudOpenTask(
        profile(), source_files_, file_manager::file_tasks::TaskDescriptor(),
        ash::cloud_upload::CloudProvider::kGoogleDrive,
        std::make_unique<CloudOpenMetrics>(CloudProvider::kGoogleDrive,
                                           /*file_count=*/1)));
  }

  void SetUpLocalToOneDriveTask() {
    SetUpMyFiles();

    source_files_.push_back(FilePathToFileSystemURL(
        profile(),
        file_manager::util::GetFileManagerFileSystemContext(profile()),
        my_files_dir_.AppendASCII("file.docx")));

    upload_task_ = base::WrapRefCounted(new ash::cloud_upload::CloudOpenTask(
        profile(), source_files_, file_manager::file_tasks::TaskDescriptor(),
        ash::cloud_upload::CloudProvider::kOneDrive,
        std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                           /*file_count=*/1)));
  }

  void SetUpCloudToOneDriveTask() {
    SetUpCloudLocation();

    source_files_.push_back(FilePathToFileSystemURL(
        profile(),
        file_manager::util::GetFileManagerFileSystemContext(profile()),
        smb_dir_.AppendASCII("file.docx")));

    upload_task_ = base::WrapRefCounted(new ash::cloud_upload::CloudOpenTask(
        profile(), source_files_, file_manager::file_tasks::TaskDescriptor(),
        ash::cloud_upload::CloudProvider::kOneDrive,
        std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                           /*file_count=*/1)));
  }

  void SetUpReadOnlyToOneDriveTask() {
    SetUpReadOnlyLocation();

    source_files_.push_back(FilePathToFileSystemURL(
        profile(),
        file_manager::util::GetFileManagerFileSystemContext(profile()),
        read_only_dir_.AppendASCII("file.docx")));

    upload_task_ = base::WrapRefCounted(new ash::cloud_upload::CloudOpenTask(
        profile(), source_files_, file_manager::file_tasks::TaskDescriptor(),
        ash::cloud_upload::CloudProvider::kOneDrive,
        std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
                                           /*file_count=*/1)));
  }

  bool ShouldShowConfirmationDialog() {
    return upload_task_->ShouldShowConfirmationDialog();
  }

  void OnMoveConfirmationComplete(const std::string& user_response) {
    upload_task_->OnMoveConfirmationComplete(user_response);
  }

  Profile* profile() { return browser()->profile(); }

 protected:
  // Use a non-managed user in this browser test to ensure
  // |IsEligibleAndEnabledUploadOfficeToCloud| returns the result of
  // |IsUploadOfficeToCloudEnabled|.
  void SetUpCommandLine(base::CommandLine* command_line) override {
    SetUpCommandLineForNonManagedUser(command_line);
  }

 private:
  // Creates mount point for MyFiles and registers local filesystem.
  void SetUpMyFiles() {
    {
      base::ScopedAllowBlockingForTesting allow_blocking;
      ASSERT_TRUE(base::CreateDirectory(my_files_dir_));
    }
    std::string mount_point_name =
        file_manager::util::GetDownloadsMountPointName(profile());
    storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
        mount_point_name);
    CHECK(storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
        mount_point_name, storage::kFileSystemTypeLocal,
        storage::FileSystemMountOption(), my_files_dir_));
    file_manager::VolumeManager::Get(profile())
        ->RegisterDownloadsDirectoryForTesting(my_files_dir_);
  }

  // Creates a new SMB filesystem, which we use in tests as an example of cloud
  // location.
  void SetUpCloudLocation() {
    {
      base::ScopedAllowBlockingForTesting allow_blocking;
      ASSERT_TRUE(base::CreateDirectory(smb_dir_));
    }
    std::string mount_point_name = "smb";
    storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
        mount_point_name);
    EXPECT_TRUE(profile()->GetMountPoints()->RegisterFileSystem(
        mount_point_name, storage::kFileSystemTypeLocal,
        storage::FileSystemMountOption(), smb_dir_));
    file_manager::VolumeManager::Get(profile())->AddVolumeForTesting(
        smb_dir_, file_manager::VOLUME_TYPE_SMB, ash::DeviceType::kUnknown,
        /*read_only=*/false);
  }

  // Creates a new filesystem which represents a read-only location, files
  // cannot be moved from it.
  void SetUpReadOnlyLocation() {
    {
      base::ScopedAllowBlockingForTesting allow_blocking;
      ASSERT_TRUE(base::CreateDirectory(read_only_dir_));
    }
    std::string mount_point_name = "readonly";
    storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
        mount_point_name);
    EXPECT_TRUE(profile()->GetMountPoints()->RegisterFileSystem(
        mount_point_name, storage::kFileSystemTypeLocal,
        storage::FileSystemMountOption(), read_only_dir_));
    file_manager::VolumeManager::Get(profile())->AddVolumeForTesting(
        read_only_dir_, file_manager::VOLUME_TYPE_TESTING,
        ash::DeviceType::kUnknown, /*read_only=*/true);
  }

  base::ScopedTempDir temp_dir_;
  base::FilePath my_files_dir_;
  base::FilePath read_only_dir_;
  base::FilePath smb_dir_;
  std::vector<storage::FileSystemURL> source_files_;
  scoped_refptr<CloudOpenTask> upload_task_;
  std::unique_ptr<CloudOpenMetrics> cloud_open_metrics_;
};

// Tests that when moving files from a local location to Drive, the preferences
// |kOfficeFilesAlwaysMoveToDrive| and
// |kOfficeMoveConfirmationShownForLocalToDrive| control whether the
// confirmation dialog is going to be shown or not.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       ShowConfirmationForLocalToDrive) {
  SetUpLocalToDriveTask();

  // Check that if |kOfficeMoveConfirmationShownForLocalToDrive| is false, we
  // always show the confirmation dialog, whether
  // |kOfficeFilesAlwaysMoveToDrive| is true or false.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForLocalToDrive(
      profile(), false);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), true);
  ASSERT_TRUE(ShouldShowConfirmationDialog());

  // Check that if |kOfficeMoveConfirmationShownForLocalToDrive| is true, we
  // only show the confirmation dialog depending on the value of
  // |kOfficeFilesAlwaysMoveToDrive|.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForLocalToDrive(
      profile(), true);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), true);
  ASSERT_FALSE(ShouldShowConfirmationDialog());
}

// Tests that when moving files from a cloud location to Drive, the preferences
// |kOfficeFilesAlwaysMoveToDrive| and
// |kOfficeMoveConfirmationShownForCloudToDrive| control whether the
// confirmation dialog is going to be shown or not.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       ShowConfirmationForCloudToDrive) {
  SetUpCloudToDriveTask();

  // Check that if |kOfficeMoveConfirmationShownForCloudToDrive| is false, we
  // always show the confirmation dialog, whether
  // |kOfficeFilesAlwaysMoveToDrive| is true or false.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToDrive(
      profile(), false);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), true);
  ASSERT_TRUE(ShouldShowConfirmationDialog());

  // Check that if |kOfficeMoveConfirmationShownForLocalToDrive| is true, we
  // only show the confirmation dialog depending on the value of
  // |kOfficeFilesAlwaysMoveToDrive|.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToDrive(
      profile(), true);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), true);
  ASSERT_FALSE(ShouldShowConfirmationDialog());
}

// Tests that when moving files from a read-only location to Drive, the
// preferences |kOfficeFilesAlwaysMoveToDrive|,
// |kOfficeMoveConfirmationShownForLocalToDrive| and
// |kOfficeMoveConfirmationShownForCloudToDrive| control whether the
// confirmation dialog is going to be shown or not.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       ShowConfirmationForReadOnlyToDrive) {
  SetUpReadOnlyToDriveTask();

  // Check that if |kOfficeMoveConfirmationShownForLocalToDrive| and
  // |kOfficeMoveConfirmationShownForCloudToDrive| are both false, we always
  // show the confirmation dialog, whether |kOfficeFilesAlwaysMoveToDrive| is
  // true or false.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForLocalToDrive(
      profile(), false);
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToDrive(
      profile(), false);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), true);
  ASSERT_TRUE(ShouldShowConfirmationDialog());

  // Check that if at least one of |kOfficeMoveConfirmationShownForLocalToDrive|
  // and |kOfficeMoveConfirmationShownForCloudToDrive| is true, we only show the
  // confirmation dialog depending on the value of
  // |kOfficeFilesAlwaysMoveToDrive|.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToDrive(
      profile(), true);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToDrive(profile(), true);
  ASSERT_FALSE(ShouldShowConfirmationDialog());
}

// Tests that when moving files from a local location to OneDrive, the
// preferences |kOfficeFilesAlwaysMoveToOneDrive| and
// |kOfficeMoveConfirmationShownForLocalToOneDrive| control whether the
// confirmation dialog is going to be shown or not.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       ShowConfirmationForLocalToOneDrive) {
  SetUpLocalToOneDriveTask();

  // Check that if |kOfficeMoveConfirmationShownForLocalToOneDrive| is false, we
  // always show the confirmation dialog, whether
  // |kOfficeFilesAlwaysMoveToOneDrive| is true or false.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForLocalToOneDrive(
      profile(), false);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(),
                                                               false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(), true);
  ASSERT_TRUE(ShouldShowConfirmationDialog());

  // Check that if |kOfficeMoveConfirmationShownForLocalToOneDrive| is true, we
  // only show the confirmation dialog depending on the value of
  // |kOfficeFilesAlwaysMoveToOneDrive|.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForLocalToOneDrive(
      profile(), true);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(),
                                                               false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(), true);
  ASSERT_FALSE(ShouldShowConfirmationDialog());
}

// Tests that when moving files from a cloud location to OneDrive, the
// preferences |kOfficeFilesAlwaysMoveToOneDrive| and
// |kOfficeMoveConfirmationShownForCloudToOneDrive| control whether the
// confirmation dialog is going to be shown or not.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       ShowConfirmationForCloudToOneDrive) {
  SetUpCloudToOneDriveTask();

  // Check that if |kOfficeMoveConfirmationShownForCloudToOneDrive| is false, we
  // always show the confirmation dialog, whether
  // |kOfficeFilesAlwaysMoveToOneDrive| is true or false.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToOneDrive(
      profile(), false);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(),
                                                               false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(), true);
  ASSERT_TRUE(ShouldShowConfirmationDialog());

  // Check that if |kOfficeMoveConfirmationShownForLocalToOneDrive| is true, we
  // only show the confirmation dialog depending on the value of
  // |kOfficeFilesAlwaysMoveToOneDrive|.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToOneDrive(
      profile(), true);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(),
                                                               false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(), true);
  ASSERT_FALSE(ShouldShowConfirmationDialog());
}

// Tests that when moving files from a read-only location to OneDrive, the
// preferences |kOfficeFilesAlwaysMoveToOneDrive|,
// |kOfficeMoveConfirmationShownForLocalToOneDrive| and
// |kOfficeMoveConfirmationShownForCloudToOneDrive| control whether the
// confirmation dialog is going to be shown or not.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       ShowConfirmationForReadOnlyToOneDrive) {
  SetUpReadOnlyToOneDriveTask();

  // Check that if |kOfficeMoveConfirmationShownForLocalToOneDrive| and
  // |kOfficeMoveConfirmationShownForCloudToOneDrive| are both false, we always
  // show the confirmation dialog, whether |kOfficeFilesAlwaysMoveToOneDrive| is
  // true or false.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForLocalToOneDrive(
      profile(), false);
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToOneDrive(
      profile(), false);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(),
                                                               false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(), true);
  ASSERT_TRUE(ShouldShowConfirmationDialog());

  // Check that if at least one of
  // |kOfficeMoveConfirmationShownForLocalToOneDrive| and
  // |kOfficeMoveConfirmationShownForCloudToOneDrive| is true, we only show the
  // confirmation dialog depending on the value of
  // |kOfficeFilesAlwaysMoveToOneDrive|.
  file_manager::file_tasks::SetOfficeMoveConfirmationShownForCloudToOneDrive(
      profile(), true);
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(),
                                                               false);
  ASSERT_TRUE(ShouldShowConfirmationDialog());
  file_manager::file_tasks::SetAlwaysMoveOfficeFilesToOneDrive(profile(), true);
  ASSERT_FALSE(ShouldShowConfirmationDialog());
}

// Tests that the preferences |kOfficeMoveConfirmationShownForDrive| and
// |kOfficeMoveConfirmationShownForLocalToDrive| is are both set to true once
// the user has confirmed the upload of a file to Drive.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       SetPrefsAfterConfirmationShownForLocalToDrive) {
  SetUpLocalToDriveTask();
  ASSERT_FALSE(file_manager::file_tasks::GetOfficeMoveConfirmationShownForDrive(
      profile()));
  ASSERT_FALSE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForLocalToDrive(
          profile()));

  OnMoveConfirmationComplete(kUserActionUploadToGoogleDrive);

  ASSERT_TRUE(file_manager::file_tasks::GetOfficeMoveConfirmationShownForDrive(
      profile()));
  ASSERT_TRUE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForLocalToDrive(
          profile()));
}

// Tests that the preferences |kOfficeMoveConfirmationShownForDrive| and
// |kOfficeMoveConfirmationShownForCloudToDrive| is are both set to true once
// the user has confirmed the upload of a file to Drive.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       SetPrefsAfterConfirmationShownForCloudToDrive) {
  SetUpCloudToDriveTask();
  ASSERT_FALSE(file_manager::file_tasks::GetOfficeMoveConfirmationShownForDrive(
      profile()));
  ASSERT_FALSE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForCloudToDrive(
          profile()));

  OnMoveConfirmationComplete(kUserActionUploadToGoogleDrive);

  ASSERT_TRUE(file_manager::file_tasks::GetOfficeMoveConfirmationShownForDrive(
      profile()));
  ASSERT_TRUE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForCloudToDrive(
          profile()));
}

// Tests that the preferences |kOfficeMoveConfirmationShownForOneDrive| and
// |kOfficeMoveConfirmationShownForLocalToOneDrive| is are both set to true once
// the user has confirmed the upload of a file to OneDrive.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       SetPrefsAfterConfirmationShownForLocalToOneDrive) {
  SetUpLocalToOneDriveTask();
  ASSERT_FALSE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForOneDrive(
          profile()));
  ASSERT_FALSE(file_manager::file_tasks::
                   GetOfficeMoveConfirmationShownForLocalToOneDrive(profile()));

  OnMoveConfirmationComplete(kUserActionUploadToOneDrive);

  ASSERT_TRUE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForOneDrive(
          profile()));
  ASSERT_TRUE(file_manager::file_tasks::
                  GetOfficeMoveConfirmationShownForLocalToOneDrive(profile()));
}

// Tests that the preferences |kOfficeMoveConfirmationShownForOneDrive| and
// |kOfficeMoveConfirmationShownForCloudToOneDrive| is are both set to true once
// the user has confirmed the upload of a file to OneDrive.
IN_PROC_BROWSER_TEST_F(CloudOpenTaskBrowserTest,
                       SetPrefsAfterConfirmationShownForCloudToOneDrive) {
  SetUpCloudToOneDriveTask();
  ASSERT_FALSE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForOneDrive(
          profile()));
  ASSERT_FALSE(file_manager::file_tasks::
                   GetOfficeMoveConfirmationShownForCloudToOneDrive(profile()));

  OnMoveConfirmationComplete(kUserActionUploadToOneDrive);

  ASSERT_TRUE(
      file_manager::file_tasks::GetOfficeMoveConfirmationShownForOneDrive(
          profile()));
  ASSERT_TRUE(file_manager::file_tasks::
                  GetOfficeMoveConfirmationShownForCloudToOneDrive(profile()));
}

}  // namespace ash::cloud_upload

void NonManagedUserWebUIBrowserTest::SetUpCommandLine(
    base::CommandLine* command_line) {
  ash::cloud_upload::SetUpCommandLineForNonManagedUser(command_line);
}