// 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 "chrome/browser/ash/file_manager/office_file_tasks.h"
#include <memory>
#include <string>
#include "base/test/metrics/histogram_tester.h"
#include "base/values.h"
#include "chrome/browser/ash/file_manager/app_id.h"
#include "chrome/browser/ash/file_manager/file_tasks.h"
#include "chrome/browser/ash/file_manager/office_file_tasks.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace file_manager::file_tasks {
class FileManagerOfficeFileTasksTest : public testing::Test {
public:
void SetUp() override {
TestingProfile::Builder profile_builder;
profile_ = profile_builder.Build();
}
TestingProfile* profile() { return profile_.get(); }
const base::Value::Dict& tasks_by_mime_type() {
return profile()->GetTestingPrefService()->GetDict(
prefs::kDefaultTasksByMimeType);
}
const base::Value::Dict& tasks_by_suffix() {
return profile()->GetTestingPrefService()->GetDict(
prefs::kDefaultTasksBySuffix);
}
void ClearPrefs() {
profile()->GetTestingPrefService()->ClearPref(
prefs::kDefaultTasksByMimeType);
profile()->GetTestingPrefService()->ClearPref(prefs::kDefaultTasksBySuffix);
}
protected:
std::unique_ptr<ash::cloud_upload::CloudOpenMetrics>
cloud_open_metrics_for_drive_ =
std::make_unique<ash::cloud_upload::CloudOpenMetrics>(
ash::cloud_upload::CloudProvider::kGoogleDrive,
/*file_count=*/1);
std::unique_ptr<ash::cloud_upload::CloudOpenMetrics>
cloud_open_metrics_for_one_drive_ =
std::make_unique<ash::cloud_upload::CloudOpenMetrics>(
ash::cloud_upload::CloudProvider::kOneDrive,
/*file_count=*/1);
base::HistogramTester histogram_;
private:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_;
};
TEST_F(FileManagerOfficeFileTasksTest,
UpdateDefaultTask_SetsOfficeFileHandlersForGroup) {
std::string app_id = "abcdef";
TaskType task_type = TASK_TYPE_FILE_HANDLER;
std::string activity = "first_activity";
TaskDescriptor fake_office_task(app_id, task_type, activity);
UpdateDefaultTask(profile(), fake_office_task, {".doc"},
{"application/msword"});
std::string expected_task_id = MakeTaskID(app_id, task_type, activity);
ASSERT_EQ(*tasks_by_mime_type().FindString("application/msword"),
expected_task_id);
ASSERT_EQ(*tasks_by_mime_type().FindString(
"application/"
"vnd.openxmlformats-officedocument.wordprocessingml.document"),
expected_task_id);
ASSERT_EQ(*tasks_by_suffix().FindString(".doc"), expected_task_id);
ASSERT_EQ(*tasks_by_suffix().FindString(".docx"), expected_task_id);
ASSERT_EQ(tasks_by_suffix().FindString(".xls"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".pptx"), nullptr);
ClearPrefs();
UpdateDefaultTask(profile(), fake_office_task, {".xlsx"},
{"application/"
"vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
ASSERT_EQ(*tasks_by_mime_type().FindString("application/vnd.ms-excel"),
expected_task_id);
ASSERT_EQ(*tasks_by_mime_type().FindString(
"application/vnd.ms-excel.sheet.macroEnabled.12"),
expected_task_id);
ASSERT_EQ(*tasks_by_mime_type().FindString(
"application/"
"vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
expected_task_id);
ASSERT_EQ(*tasks_by_suffix().FindString(".xls"), expected_task_id);
ASSERT_EQ(*tasks_by_suffix().FindString(".xlsm"), expected_task_id);
ASSERT_EQ(*tasks_by_suffix().FindString(".xlsx"), expected_task_id);
ASSERT_EQ(tasks_by_suffix().FindString(".doc"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".pptx"), nullptr);
ClearPrefs();
UpdateDefaultTask(
profile(), fake_office_task, {".pptx"},
{"application/"
"vnd.openxmlformats-officedocument.presentationml.presentation"});
ASSERT_EQ(*tasks_by_mime_type().FindString("application/vnd.ms-powerpoint"),
expected_task_id);
ASSERT_EQ(
*tasks_by_mime_type().FindString(
"application/"
"vnd.openxmlformats-officedocument.presentationml.presentation"),
expected_task_id);
ASSERT_EQ(*tasks_by_suffix().FindString(".ppt"), expected_task_id);
ASSERT_EQ(*tasks_by_suffix().FindString(".pptx"), expected_task_id);
ASSERT_EQ(tasks_by_suffix().FindString(".doc"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".xlsm"), nullptr);
}
TEST_F(FileManagerOfficeFileTasksTest,
UpdateDefaultTask_DoesNotSetOfficeFileHandlersForGroup) {
std::string app_id = "abcdef";
TaskType task_type = TASK_TYPE_FILE_HANDLER;
std::string activity = "first_activity";
TaskDescriptor fake_office_task(app_id, task_type, activity);
UpdateDefaultTask(profile(), fake_office_task, {".doc"}, {});
std::string expected_task_id = MakeTaskID(app_id, task_type, activity);
ASSERT_EQ(tasks_by_mime_type().FindString("application/msword"), nullptr);
ASSERT_EQ(tasks_by_mime_type().FindString(
"application/"
"vnd.openxmlformats-officedocument.wordprocessingml.document"),
nullptr);
ASSERT_EQ(*tasks_by_suffix().FindString(".doc"), expected_task_id);
ASSERT_EQ(tasks_by_suffix().FindString(".docx"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".xls"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".pptx"), nullptr);
ClearPrefs();
UpdateDefaultTask(profile(), fake_office_task, {}, {"application/msword"});
ASSERT_EQ(*tasks_by_mime_type().FindString("application/msword"),
expected_task_id);
ASSERT_EQ(tasks_by_mime_type().FindString(
"application/"
"vnd.openxmlformats-officedocument.wordprocessingml.document"),
nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".doc"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".docx"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".xls"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".pptx"), nullptr);
ClearPrefs();
UpdateDefaultTask(profile(), fake_office_task, {".doc", ".xls"},
{"application/msword", "application/vnd.ms-excel"});
ASSERT_EQ(*tasks_by_mime_type().FindString("application/msword"),
expected_task_id);
ASSERT_EQ(*tasks_by_mime_type().FindString("application/vnd.ms-excel"),
expected_task_id);
ASSERT_EQ(tasks_by_mime_type().FindString(
"application/vnd.ms-excel.sheet.macroEnabled.12"),
nullptr);
ASSERT_EQ(*tasks_by_suffix().FindString(".doc"), expected_task_id);
ASSERT_EQ(tasks_by_suffix().FindString(".docx"), nullptr);
ASSERT_EQ(*tasks_by_suffix().FindString(".xls"), expected_task_id);
ASSERT_EQ(tasks_by_suffix().FindString(".xlsm"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".xlsx"), nullptr);
ASSERT_EQ(tasks_by_suffix().FindString(".pptx"), nullptr);
}
// Test the setting of a default file task for Office files to a Files App SWA.
TEST_F(FileManagerOfficeFileTasksTest, SetOfficeFileHandlersToFilesSWA) {
TaskDescriptor task(kFileManagerSwaAppId, TaskType::TASK_TYPE_WEB_APP,
"chrome://file-manager/?a");
// Check no default tasks exist for Doc files.
std::string docx_mime(
"application/"
"vnd.openxmlformats-officedocument.wordprocessingml.document");
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/msword", ".doc"));
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), docx_mime, ".docx"));
// Set default task for Doc files as a Files App SWA with action id "a".
SetWordFileHandlerToFilesSWA(profile(), "a");
// Check the default task for Doc files is `task`.
EXPECT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/msword", ".doc"),
task);
EXPECT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), docx_mime, ".docx"),
task);
// Update with replace_existing=false should not change the default.
SetWordFileHandlerToFilesSWA(profile(), "b", false);
EXPECT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/msword", ".doc"),
task);
EXPECT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), docx_mime, ".docx"),
task);
// Removing an action which is not set should not change the default.
RemoveFilesSWAWordFileHandler(profile(), "b");
EXPECT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/msword", ".doc"),
task);
EXPECT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), docx_mime, ".docx"),
task);
// Remove the task.
RemoveFilesSWAWordFileHandler(profile(), "a");
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/msword", ".doc"));
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), docx_mime, ".docx"));
// Check no default tasks exist for Excel files.
std::string xlsx_mime(
"application/"
"vnd.openxmlformats-officedocument.spreadsheetml.sheet");
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/vnd.ms-excel", ".xls"));
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), xlsx_mime, ".xlsx"));
// Set default task for Excel files as a Files App SWA with action id "a".
SetExcelFileHandlerToFilesSWA(profile(), "a");
// Check the default task for Excel files is `task`.
ASSERT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/vnd.ms-excel", ".xls"),
task);
ASSERT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), xlsx_mime, ".xlsx"),
task);
// Remove the task.
RemoveFilesSWAExcelFileHandler(profile(), "a");
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/vnd.ms-excel", ".xls"));
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), xlsx_mime, ".xlsx"));
// Check no default tasks exist for Powerpoint files.
std::string pptx_mime(
"application/"
"vnd.openxmlformats-officedocument.presentationml.presentation");
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/vnd.ms-powerpoint", ".ppt"));
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), pptx_mime, ".pptx"));
// Set default task for Powerpoint files as a Files App SWA with action id
// "a".
SetPowerPointFileHandlerToFilesSWA(profile(), "a");
// Check the default task for Powerpoint files is `task`.
EXPECT_EQ(
file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/vnd.ms-powerpoint", ".ppt"),
task);
EXPECT_EQ(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), pptx_mime, ".pptx"),
task);
// Remove the task.
RemoveFilesSWAPowerPointFileHandler(profile(), "a");
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), "application/vnd.ms-powerpoint", ".ppt"));
EXPECT_FALSE(file_manager::file_tasks::GetDefaultTaskFromPrefs(
*profile()->GetPrefs(), pptx_mime, ".pptx"));
}
/**
* Check Log*MetricsAfterFallback() maps the FallbackReason to the correct
* OpenError and logs the TaskResult.
*/
TEST_F(FileManagerOfficeFileTasksTest,
LogOneDriveMetricsAfterFallback_kOffline) {
LogOneDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kOffline,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice,
std::move(cloud_open_metrics_for_one_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kOneDriveErrorMetricName,
ash::cloud_upload::OfficeOneDriveOpenErrors::kOffline, 1);
histogram_.ExpectUniqueSample(
ash::cloud_upload::kOneDriveTaskResultMetricName,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice, 1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogOneDriveMetricsAfterFallback_kAndroidOneDriveUnsupportedLocation) {
LogOneDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kAndroidOneDriveUnsupportedLocation,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoiceAfterOpen,
std::move(cloud_open_metrics_for_one_drive_));
histogram_.ExpectUniqueSample(ash::cloud_upload::kOneDriveErrorMetricName,
ash::cloud_upload::OfficeOneDriveOpenErrors::
kAndroidOneDriveUnsupportedLocation,
1);
histogram_.ExpectUniqueSample(
ash::cloud_upload::kOneDriveTaskResultMetricName,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoiceAfterOpen,
1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kOffline) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kOffline,
ash::cloud_upload::OfficeTaskResult::kFallbackQuickOffice,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kOffline, 1);
histogram_.ExpectUniqueSample(
ash::cloud_upload::kGoogleDriveTaskResultMetricName,
ash::cloud_upload::OfficeTaskResult::kFallbackQuickOffice, 1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kDriveDisabled) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kDriveDisabled,
ash::cloud_upload::OfficeTaskResult::kCancelledAtFallback,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kDriveDisabled, 1);
histogram_.ExpectUniqueSample(
ash::cloud_upload::kGoogleDriveTaskResultMetricName,
ash::cloud_upload::OfficeTaskResult::kCancelledAtFallback, 1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kNoDriveService) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kNoDriveService,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kNoDriveService, 1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kDriveAuthenticationNotReady) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kDriveAuthenticationNotReady,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kDriveAuthenticationNotReady,
1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kDriveFsInterfaceError) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kDriveFsInterfaceError,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kDriveFsInterface, 1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kMeteredConnection) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kMeteredConnection,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kMeteredConnection, 1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kDisableDrivePreferenceSet) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kDisableDrivePreferenceSet,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kDisableDrivePreferenceSet, 1);
}
TEST_F(FileManagerOfficeFileTasksTest,
LogGoogleDriveMetricsAfterFallback_kDriveDisabledForAccountType) {
LogGoogleDriveMetricsAfterFallback(
ash::office_fallback::FallbackReason::kDriveDisabledForAccountType,
ash::cloud_upload::OfficeTaskResult::kCannotGetFallbackChoice,
std::move(cloud_open_metrics_for_drive_));
histogram_.ExpectUniqueSample(
ash::cloud_upload::kDriveErrorMetricName,
ash::cloud_upload::OfficeDriveOpenErrors::kDriveDisabledForAccountType,
1);
}
TEST_F(FileManagerOfficeFileTasksTest, IsOfficeFileMimeType) {
// Powerpoint.
EXPECT_TRUE(IsOfficeFileMimeType("application/vnd.ms-powerpoint"));
EXPECT_TRUE(IsOfficeFileMimeType(
"application/"
"vnd.openxmlformats-officedocument.presentationml.presentation"));
// Excel.
EXPECT_TRUE(IsOfficeFileMimeType("application/vnd.ms-excel"));
EXPECT_TRUE(IsOfficeFileMimeType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
// Word.
EXPECT_TRUE(IsOfficeFileMimeType("application/msword"));
EXPECT_TRUE(IsOfficeFileMimeType(
"application/"
"vnd.openxmlformats-officedocument.wordprocessingml.document"));
EXPECT_FALSE(IsOfficeFileMimeType("text/plain"));
EXPECT_FALSE(IsOfficeFileMimeType("video/webm"));
EXPECT_FALSE(IsOfficeFileMimeType("image/png'"));
EXPECT_FALSE(IsOfficeFileMimeType("image/png"));
}
} // namespace file_manager::file_tasks