// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.h"
#include <optional>
#include "ash/constants/ash_features.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.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/path_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/mount_path_util.h"
#include "chrome/browser/ash/file_system_provider/provided_file_system_interface.h"
#include "chrome/browser/notifications/notification_display_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/constants/chromeos_features.h"
#include "content/public/test/browser_test.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/browser/file_system/file_system_operation.h"
#include "storage/browser/file_system/file_system_url.h"
using storage::FileSystemURL;
namespace ash::cloud_upload {
namespace {
// Returns full test file path to the given |file_name|.
base::FilePath GetTestFilePath(const std::string& file_name) {
// Get the path to file manager's test data directory.
base::FilePath source_dir;
CHECK(base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &source_dir));
base::FilePath test_data_dir = source_dir.AppendASCII("chrome")
.AppendASCII("test")
.AppendASCII("data")
.AppendASCII("chromeos")
.AppendASCII("file_manager");
return test_data_dir.Append(base::FilePath::FromUTF8Unsafe(file_name));
}
} // namespace
// Tests the OneDrive upload workflow using the static
// `OneDriveUploadHandler::Upload` method. Ensures that the upload completes
// with the expected results.
class OneDriveUploadHandlerTest : public InProcessBrowserTest,
public NotificationDisplayService::Observer {
public:
OneDriveUploadHandlerTest() {
feature_list_.InitAndEnableFeature(
chromeos::features::kUploadOfficeToCloud);
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
my_files_dir_ = temp_dir_.GetPath().Append("myfiles");
read_only_dir_ = temp_dir_.GetPath().Append("readonly");
}
OneDriveUploadHandlerTest(const OneDriveUploadHandlerTest&) = delete;
OneDriveUploadHandlerTest& operator=(const OneDriveUploadHandlerTest&) =
delete;
void TearDown() override {
InProcessBrowserTest::TearDown();
storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems();
}
void TearDownOnMainThread() override {
RemoveObservers();
InProcessBrowserTest::TearDownOnMainThread();
}
// 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 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, true /* read_only */);
}
// Creates and mounts fake provided file system for OneDrive.
void SetUpODFS() {
provided_file_system_ =
file_manager::test::MountFakeProvidedFileSystemOneDrive(profile());
}
// Copy the test file with `test_file_name` into the directory `target_dir`,
// optionally renaming it to `renamed_file_name`. Return the FileSystemURL of
// the new (and maybe renamed) file.
FileSystemURL CopyTestFile(
const std::string& test_file_name,
base::FilePath target_dir,
std::optional<const std::string> renamed_file_name = std::nullopt) {
const base::FilePath copied_file_path = target_dir.AppendASCII(
renamed_file_name ? *renamed_file_name : test_file_name);
// Copy the test file into `target_dir`.
const base::FilePath test_file_path = GetTestFilePath(test_file_name);
{
base::ScopedAllowBlockingForTesting allow_blocking;
CHECK(base::CopyFile(test_file_path, copied_file_path));
}
// Check that the copied file exists at the intended location and is not on
// ODFS.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(copied_file_path));
CheckPathNotFoundOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
FileSystemURL copied_file_url = FilePathToFileSystemURL(
profile(),
file_manager::util::GetFileManagerFileSystemContext(profile()),
copied_file_path);
return copied_file_url;
}
void SetUpObservers() {
// Subscribe to Notification updates to track copy/move ODFS notifications.
NotificationDisplayService::GetForProfile(profile())->AddObserver(this);
}
void RemoveObservers() {
NotificationDisplayService::GetForProfile(browser()->profile())
->RemoveObserver(this);
}
void SetUpRunLoop(int conditions_to_end_wait = 1) {
conditions_to_end_wait_ = conditions_to_end_wait;
ASSERT_FALSE(run_loop_);
run_loop_ = std::make_unique<base::RunLoop>();
}
void Wait() {
base::ScopedAllowBlockingForTesting allow_blocking;
run_loop_->Run();
run_loop_ = nullptr;
}
void SetUpRunLoopAndWait(int conditions_to_end_wait = 1) {
base::ScopedAllowBlockingForTesting allow_blocking;
SetUpRunLoop(conditions_to_end_wait);
Wait();
}
// Quits the run loop started with `Wait()` once `EndWait()` is called
// `conditions_to_end_wait_` number of times.
void EndWait() {
conditions_to_end_wait_--;
ASSERT_TRUE(run_loop_);
if (conditions_to_end_wait_ == 0) {
run_loop_->Quit();
}
}
void CheckPathExistsOnODFS(const base::FilePath& path) {
ASSERT_TRUE(provided_file_system_);
provided_file_system_->GetMetadata(
path, {},
base::BindOnce(&OneDriveUploadHandlerTest::OnGetMetadataExpectSuccess,
base::Unretained(this)));
base::ScopedAllowBlockingForTesting allow_blocking;
SetUpRunLoopAndWait();
}
void CheckPathNotFoundOnODFS(const base::FilePath& path) {
ASSERT_TRUE(provided_file_system_);
provided_file_system_->GetMetadata(
path, {},
base::BindOnce(&OneDriveUploadHandlerTest::OnGetMetadataExpectNotFound,
base::Unretained(this)));
base::ScopedAllowBlockingForTesting allow_blocking;
SetUpRunLoopAndWait();
}
void OnGetMetadataExpectSuccess(
std::unique_ptr<file_system_provider::EntryMetadata> entry_metadata,
base::File::Error result) {
EXPECT_EQ(base::File::Error::FILE_OK, result);
EndWait();
}
void OnGetMetadataExpectNotFound(
std::unique_ptr<file_system_provider::EntryMetadata> entry_metadata,
base::File::Error result) {
EXPECT_EQ(base::File::Error::FILE_ERROR_NOT_FOUND, result);
EndWait();
}
// Watch for a valid `uploaded_file_url`.
void OnUploadSuccessful(
OfficeTaskResult expected_task_result,
OfficeTaskResult task_result,
std::optional<storage::FileSystemURL> uploaded_file_url,
int64_t size) {
ASSERT_TRUE(uploaded_file_url.has_value());
ASSERT_EQ(expected_task_result, task_result);
EndWait();
}
// Watch for an invalid `uploaded_file_url`.
void OnUploadFailedOrAbandoned(
OfficeTaskResult expected_task_result,
OfficeTaskResult task_result,
std::optional<storage::FileSystemURL> uploaded_file_url,
int64_t size) {
ASSERT_FALSE(uploaded_file_url.has_value());
ASSERT_EQ(expected_task_result, task_result);
EndWait();
}
// Run |on_notification_displayed_callback_| with observed |notification|.
void OnNotificationDisplayed(
const message_center::Notification& notification,
const NotificationCommon::Metadata* const metadata) override {
if (on_notification_displayed_callback_) {
std::move(on_notification_displayed_callback_).Run(notification);
}
}
void OnNotificationClosed(const std::string& notification_id) override {}
void OnNotificationDisplayServiceDestroyed(
NotificationDisplayService* service) override {}
void SetOnNotificationDisplayedCallback(
base::RepeatingCallback<void(const message_center::Notification&)>
callback) {
on_notification_displayed_callback_ = std::move(callback);
}
Profile* profile() { return browser()->profile(); }
protected:
base::FilePath my_files_dir_;
base::FilePath read_only_dir_;
raw_ptr<file_manager::test::FakeProvidedFileSystemOneDrive,
DanglingUntriaged>
provided_file_system_; // Owned by Service.
std::unique_ptr<ash::cloud_upload::CloudOpenMetrics> cloud_open_metrics_ =
std::make_unique<CloudOpenMetrics>(CloudProvider::kOneDrive,
/*file_count=*/1);
base::SafeRef<CloudOpenMetrics> cloud_open_metrics_ref_ =
cloud_open_metrics_->GetSafeRef();
base::HistogramTester histogram_;
base::test::ScopedFeatureList feature_list_;
private:
base::ScopedTempDir temp_dir_;
int conditions_to_end_wait_;
std::unique_ptr<base::RunLoop> run_loop_;
// Used to observe upload notifications during the tests.
base::RepeatingCallback<void(const message_center::Notification&)>
on_notification_displayed_callback_;
};
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest, UploadFromMyFiles) {
SetUpMyFiles();
SetUpODFS();
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, my_files_dir_);
// Start the upload workflow and end the test once the upload has completed
// successfully.
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(&OneDriveUploadHandlerTest::OnUploadSuccessful,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kMoved),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
SetUpRunLoopAndWait();
// Check that the source file has been moved to OneDrive.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_FALSE(base::PathExists(my_files_dir_.AppendASCII(test_file_name)));
CheckPathExistsOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kSuccess, 1);
}
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest, UploadTrimsFileName) {
SetUpMyFiles();
SetUpODFS();
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url =
CopyTestFile(test_file_name, my_files_dir_, " text.docx");
// Start the upload workflow and end the test once the upload has completed
// successfully.
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(&OneDriveUploadHandlerTest::OnUploadSuccessful,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kMoved),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
SetUpRunLoopAndWait();
// Check that the source file has been moved to OneDrive.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_FALSE(base::PathExists(my_files_dir_.AppendASCII("text.docx")));
EXPECT_FALSE(base::PathExists(my_files_dir_.AppendASCII(" text.docx")));
CheckPathExistsOnODFS(base::FilePath("/").AppendASCII("text.docx"));
}
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kSuccess, 1);
}
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest,
UploadFromReadOnlyFileSystem) {
SetUpReadOnlyLocation();
SetUpODFS();
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, read_only_dir_);
// Start the upload workflow and end the test once the upload has completed
// successfully.
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(&OneDriveUploadHandlerTest::OnUploadSuccessful,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kCopied),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
SetUpRunLoopAndWait();
// Check that the source file has been copied to OneDrive.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(read_only_dir_.AppendASCII(test_file_name)));
CheckPathExistsOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kSuccess, 1);
}
// Test that when the upload to ODFS fails due reauthentication to OneDrive
// being required, the reauthentication required notification is shown.
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest,
FailToUploadDueToReauthenticationRequired) {
SetUpObservers();
SetUpMyFiles();
SetUpODFS();
provided_file_system_->SetReauthenticationRequired(false);
// Ensure upload fails due to reauthentication to OneDrive being required. We
// want to test ReauthRequired being set after we begin uploading.
provided_file_system_->SetCreateFileCallback(
base::BindLambdaForTesting([&]() {
// Wait until we try to create the file, and then set reauth required to
// emulate auth being lost during upload.
provided_file_system_->SetCreateFileError(
base::File::Error::FILE_ERROR_ACCESS_DENIED);
provided_file_system_->SetReauthenticationRequired(true);
}));
// Expect the reauthentication required notification.
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, my_files_dir_);
// Start the upload workflow and end the test once the upload has failed due
// to reauthentication being required.
auto on_notification = base::BindLambdaForTesting(
[&](const message_center::Notification& notification) {
if (notification.message() ==
base::UTF8ToUTF16(GetReauthenticationRequiredMessage())) {
EndWait();
}
});
SetOnNotificationDisplayedCallback(std::move(on_notification));
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(
&OneDriveUploadHandlerTest::OnUploadFailedOrAbandoned,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kFailedToUpload),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
SetUpRunLoopAndWait(/*conditions_to_end_wait=*/2);
// Check that the source file still exists only at the intended source
// location and did not get uploaded to ODFS.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(my_files_dir_.AppendASCII(test_file_name)));
CheckPathNotFoundOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectUniqueSample(kOneDriveMoveErrorMetricName,
-base::File::FILE_ERROR_ACCESS_DENIED, 1);
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kCloudReauthRequired,
1);
}
// Test that when the upload to ODFS fails due reauthentication to OneDrive
// being required (before starting the upload), the reauthentication required
// notification is shown.
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest,
FailToStartUploadDueToReauthenticationRequired) {
SetUpObservers();
SetUpMyFiles();
SetUpODFS();
// Ensure upload fails due to reauthentication to OneDrive being required.
provided_file_system_->SetReauthenticationRequired(true);
// Expect the reauthentication required notification.
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, my_files_dir_);
// Start the upload workflow and end the test once the upload has failed due
// to reauthentication being required.
auto on_notification = base::BindLambdaForTesting(
[&](const message_center::Notification& notification) {
if (notification.message() ==
base::UTF8ToUTF16(GetReauthenticationRequiredMessage())) {
EndWait();
}
});
SetOnNotificationDisplayedCallback(std::move(on_notification));
SetUpRunLoop(/*conditions_to_end_wait=*/2);
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(
&OneDriveUploadHandlerTest::OnUploadFailedOrAbandoned,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kFailedToUpload),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
Wait();
// Check that the source file still exists only at the intended source
// location and did not get uploaded to ODFS.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(my_files_dir_.AppendASCII(test_file_name)));
CheckPathNotFoundOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectTotalCount(kOneDriveMoveErrorMetricName, 0);
histogram_.ExpectUniqueSample(
kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kUploadNotStartedReauthenticationRequired, 1);
}
// Tests that an appropriate error is shown when INVALID_URL is returned
// (matches to a rejected request in ODFS).
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest, FailToUploadDueToInvalidUrl) {
SetUpObservers();
SetUpMyFiles();
SetUpODFS();
// Set up upload to fail with INVALID_URL.
provided_file_system_->SetCreateFileError(
base::File::Error::FILE_ERROR_INVALID_URL);
// Set up a test source file.
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, my_files_dir_);
// Start the upload workflow and end once the error notification is shown.
std::u16string message;
SetOnNotificationDisplayedCallback(base::BindLambdaForTesting(
[&](const message_center::Notification& notification) {
message = notification.message();
EndWait();
}));
SetUpRunLoop(/*conditions_to_end_wait=*/2);
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(
&OneDriveUploadHandlerTest::OnUploadFailedOrAbandoned,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kFailedToUpload),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
Wait();
EXPECT_EQ(
message,
u"Microsoft OneDrive rejected the request. Please try again later.");
// Check that the source file still exists only at the intended source
// location and did not get uploaded to ODFS.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(my_files_dir_.AppendASCII(test_file_name)));
CheckPathNotFoundOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectTotalCount(kOneDriveMoveErrorMetricName, 1);
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kMoveOperationError,
1);
}
class OneDriveUploadHandlerTest_ReauthEnabled
: public OneDriveUploadHandlerTest {
public:
OneDriveUploadHandlerTest_ReauthEnabled() {
feature_list_.Reset();
feature_list_.InitWithFeatures({chromeos::features::kUploadOfficeToCloud,
features::kOneDriveUploadImmediateReauth},
{});
}
};
// Test that when reauthentication to OneDrive is required (before starting the
// upload) interactive auth is requested without a prompt. And test that when
// the auth succeeds, the upload succeeds.
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest_ReauthEnabled,
UploadSucceedsAfterReauth) {
SetUpMyFiles();
SetUpODFS();
// Ensure the first check of reauth required fails due to reauthentication to
// OneDrive being required.
provided_file_system_->SetReauthenticationRequired(true);
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, my_files_dir_);
// Start the upload workflow and simulate a successful mount() request
// (indicating interactive auth has succeeded).
file_manager::test::GetFakeProviderOneDrive(profile())->SetRequestMountImpl(
base::BindLambdaForTesting(
[&](ash::file_system_provider::RequestMountCallback callback) {
// The second check of reauth required after the mount succeeds
// should be OK so we attempt upload.
provided_file_system_->SetReauthenticationRequired(false);
std::move(callback).Run(base::File::Error::FILE_OK);
}));
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(&OneDriveUploadHandlerTest::OnUploadSuccessful,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kMoved),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
SetUpRunLoopAndWait();
// Check that the source file has been moved to OneDrive.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_FALSE(base::PathExists(my_files_dir_.AppendASCII(test_file_name)));
CheckPathExistsOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kSuccessAfterReauth,
1);
}
// Test that when reauthentication to OneDrive is required (before starting the
// upload) interactive auth is requested without a prompt. And test that when
// the auth fails, the upload is not attempted and instead the sign-in
// notification is shown.
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest,
UploadNotAttemptedAfterFailedReauth) {
SetUpObservers();
SetUpMyFiles();
SetUpODFS();
// Ensure the first check of reauth required fails due to reauthentication to
// OneDrive being required.
provided_file_system_->SetReauthenticationRequired(true);
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, my_files_dir_);
// Start the upload workflow and simulate a failed mount() request (indicating
// interactive auth has failed).
file_manager::test::GetFakeProviderOneDrive(profile())->SetRequestMountImpl(
base::BindLambdaForTesting(
[&](ash::file_system_provider::RequestMountCallback callback) {
std::move(callback).Run(base::File::Error::FILE_ERROR_FAILED);
}));
auto on_notification = base::BindLambdaForTesting(
[&](const message_center::Notification& notification) {
if (notification.message() ==
base::UTF8ToUTF16(GetReauthenticationRequiredMessage())) {
EndWait();
}
});
SetOnNotificationDisplayedCallback(std::move(on_notification));
SetUpRunLoop(/*conditions_to_end_wait=*/2);
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(
&OneDriveUploadHandlerTest::OnUploadFailedOrAbandoned,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kFailedToUpload),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
Wait();
// Check that the source file still exists only at the intended source
// location and did not get uploaded to ODFS.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(my_files_dir_.AppendASCII(test_file_name)));
CheckPathNotFoundOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectTotalCount(kOneDriveMoveErrorMetricName, 0);
histogram_.ExpectUniqueSample(
kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kUploadNotStartedReauthenticationRequired, 1);
}
// Test that when the upload to ODFS fails due an access error that is not
// because reauthentication to OneDrive is required, the generic error
// notification is shown.
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest,
FailToUploadDueToOtherAccessError) {
SetUpObservers();
SetUpMyFiles();
SetUpODFS();
// Ensure Upload fails due to some access error which is not because
// reauthentication to OneDrive is required.
provided_file_system_->SetCreateFileError(
base::File::Error::FILE_ERROR_ACCESS_DENIED);
provided_file_system_->SetReauthenticationRequired(false);
const std::string test_file_name = "text.docx";
FileSystemURL source_file_url = CopyTestFile(test_file_name, my_files_dir_);
// Start the upload workflow and end the test once the upload has failed due
// to some access error.
auto on_notification = base::BindLambdaForTesting(
[&](const message_center::Notification& notification) {
if (notification.message() ==
base::UTF8ToUTF16(GetGenericErrorMessage())) {
EndWait();
}
});
SetOnNotificationDisplayedCallback(std::move(on_notification));
auto one_drive_upload_handler = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url,
base::BindOnce(
&OneDriveUploadHandlerTest::OnUploadFailedOrAbandoned,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kFailedToUpload),
cloud_open_metrics_ref_);
one_drive_upload_handler->Run();
SetUpRunLoopAndWait(/*conditions_to_end_wait=*/2);
// Check that the source file still exists only at the intended source
// location and did not get uploaded to ODFS.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::PathExists(my_files_dir_.AppendASCII(test_file_name)));
CheckPathNotFoundOnODFS(base::FilePath("/").AppendASCII(test_file_name));
}
histogram_.ExpectUniqueSample(kOneDriveMoveErrorMetricName,
-base::File::FILE_ERROR_ACCESS_DENIED, 1);
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kCloudAccessDenied, 1);
}
// Tests that when there is an upload occurring followed by a second, unrelated
// upload, both are successful.
IN_PROC_BROWSER_TEST_F(OneDriveUploadHandlerTest, UnrelatedUploads) {
SetUpObservers();
SetUpMyFiles();
SetUpODFS();
const std::string test_file_name1 = "text.docx";
FileSystemURL source_file_url1 = CopyTestFile(test_file_name1, my_files_dir_);
const std::string test_file_name2 = "presentation.pptx";
FileSystemURL source_file_url2 = CopyTestFile(test_file_name2, my_files_dir_);
// Start the second, unrelated, upload after the first one starts.
std::unique_ptr<OneDriveUploadHandler> one_drive_upload_handler2;
provided_file_system_->SetCreateFileCallback(
base::BindLambdaForTesting([&]() {
one_drive_upload_handler2 = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url2,
base::BindOnce(&OneDriveUploadHandlerTest::OnUploadSuccessful,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kMoved),
cloud_open_metrics_ref_);
one_drive_upload_handler2->Run();
}));
// Start the first upload.
auto one_drive_upload_handler1 = std::make_unique<OneDriveUploadHandler>(
profile(), source_file_url1,
base::BindOnce(&OneDriveUploadHandlerTest::OnUploadSuccessful,
base::Unretained(this),
/*expected_task_result=*/OfficeTaskResult::kMoved),
cloud_open_metrics_ref_);
one_drive_upload_handler1->Run();
SetUpRunLoopAndWait(/*conditions_to_end_wait=*/2);
// Check that the first source file has been moved to OneDrive.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_FALSE(base::PathExists(my_files_dir_.AppendASCII(test_file_name1)));
CheckPathExistsOnODFS(base::FilePath("/").AppendASCII(test_file_name1));
}
// Check that the second source file has been moved to OneDrive.
{
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_FALSE(base::PathExists(my_files_dir_.AppendASCII(test_file_name2)));
CheckPathExistsOnODFS(base::FilePath("/").AppendASCII(test_file_name2));
}
// There should be two UploadResults.
histogram_.ExpectUniqueSample(kOneDriveUploadResultMetricName,
OfficeFilesUploadResult::kSuccess, 2);
}
} // namespace ash::cloud_upload