Skip to content

Commit

Permalink
Display notification if DriveFS data dir was removed while user was l…
Browse files Browse the repository at this point in the history
…ogged out

If the DriveFS data directory is not there anymore although DriveFS was
successfully started in the past, then a system notification is
displayed. This notification informs the user that their cached DriveFS
files have been cleared.

BUG=b:262647301, b:262814091

Change-Id: I4ae6cf7f9550543d987fdff91f4b97b33baff6d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4113123
Reviewed-by: Ben Reich <benreich@chromium.org>
Commit-Queue: François Degros <fdegros@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1085274}
  • Loading branch information
fdegros authored and Chromium LUCI CQ committed Dec 20, 2022
1 parent ff33182 commit 23f62a5
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 24 deletions.
83 changes: 61 additions & 22 deletions chrome/browser/ash/drive/drive_integration_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@
#include "base/timer/timer.h"
#include "chrome/browser/ash/drive/drivefs_native_message_host.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/ash/extensions/file_manager/system_notification_manager.h"
#include "chrome/browser/ash/file_manager/path_util.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/drive/drive_notification_manager_factory.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/notification_handler.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
Expand Down Expand Up @@ -292,10 +295,6 @@ DriveMountStatus ConvertMountFailure(
NOTREACHED();
}

bool EnsureDirectoryExists(const base::FilePath& path) {
return base::DirectoryExists(path) || base::CreateDirectory(path);
}

void UmaEmitMountStatus(DriveMountStatus status) {
UMA_HISTOGRAM_ENUMERATION("DriveCommon.Lifecycle.Mount", status);
}
Expand Down Expand Up @@ -892,36 +891,76 @@ void DriveIntegrationService::AddBackDriveMountPoint(
std::move(callback).Run(true);
}

DriveIntegrationService::DirResult
DriveIntegrationService::EnsureDirectoryExists(const base::FilePath& data_dir) {
if (base::DirectoryExists(data_dir)) {
VLOG(1) << "DriveFS data directory '" << data_dir << "' already exists";
return DirResult::kExisting;
}

if (base::CreateDirectory(data_dir)) {
VLOG(1) << "Created DriveFS data directory '" << data_dir << "'";
return DirResult::kCreated;
}

PLOG(ERROR) << "Cannot create DriveFS data directory '" << data_dir << "'";
return DirResult::kError;
}

void DriveIntegrationService::AddDriveMountPoint() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(INITIALIZED, state_);
DCHECK(enabled_);

weak_ptr_factory_.InvalidateWeakPtrs();

if (!GetDriveFsHost()->IsMounted()) {
PrefService* prefs = profile_->GetPrefs();
bool was_ever_mounted =
prefs->GetBoolean(prefs::kDriveFsWasLaunchedAtLeastOnce);
if (mount_start_.is_null() || was_ever_mounted) {
mount_start_ = base::TimeTicks::Now();
}
blocking_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&EnsureDirectoryExists, GetDriveFsHost()->GetDataPath()),
base::BindOnce(&DriveIntegrationService::MaybeMountDrive,
weak_ptr_factory_.GetWeakPtr()));
} else {
if (GetDriveFsHost()->IsMounted()) {
AddDriveMountPointAfterMounted();
return;
}

const bool was_ever_mounted =
profile_->GetPrefs()->GetBoolean(prefs::kDriveFsWasLaunchedAtLeastOnce);

if (mount_start_.is_null() || was_ever_mounted) {
mount_start_ = base::TimeTicks::Now();
}

const base::FilePath data_dir = GetDriveFsHost()->GetDataPath();
blocking_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&EnsureDirectoryExists, data_dir),
base::BindOnce(&DriveIntegrationService::MaybeMountDrive,
weak_ptr_factory_.GetWeakPtr(), data_dir));
}

void DriveIntegrationService::MaybeMountDrive(bool data_directory_exists) {
if (!data_directory_exists) {
LOG(ERROR) << "Could not create DriveFS data directory";
} else {
GetDriveFsHost()->Mount();
void DriveIntegrationService::MaybeMountDrive(const base::FilePath& data_dir,
const DirResult data_dir_result) {
if (data_dir_result == DirResult::kError) {
return;
}

// Check if the data dir was missing (probably because it got removed while
// the user was logged out).
if (data_dir_result == DirResult::kCreated &&
profile_->GetPrefs()->GetBoolean(prefs::kDriveFsWasLaunchedAtLeastOnce)) {
LOG(WARNING) << "DriveFS data directory '" << data_dir
<< "' was missing and got created again";

// TODO(b/263185253) Remove this IsDriveFsBulkPinningEnabled() condition.
if (ash::features::IsDriveFsBulkPinningEnabled()) {
// Show system notification.
file_manager::SystemNotificationManager snm(profile_);
const std::unique_ptr<const message_center::Notification> notification =
snm.CreateNotification("drive_data_dir_missing",
IDS_FILE_BROWSER_DRIVE_DIRECTORY_LABEL,
IDS_FILE_BROWSER_DRIVE_DATA_DIR_MISSING);
DCHECK(notification);
snm.GetNotificationDisplayService()->Display(
NotificationHandler::Type::TRANSIENT, *notification, nullptr);
}
}

GetDriveFsHost()->Mount();
}

bool DriveIntegrationService::AddDriveMountPointAfterMounted() {
Expand Down
9 changes: 8 additions & 1 deletion chrome/browser/ash/drive/drive_integration_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "base/callback.h"
#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
Expand Down Expand Up @@ -304,13 +305,17 @@ class DriveIntegrationService : public KeyedService,
// Must be called on UI thread.
bool IsDriveEnabled();

enum class DirResult { kError, kExisting, kCreated };
static DirResult EnsureDirectoryExists(const base::FilePath& data_dir);

// Registers remote file system for drive mount point. If DriveFS is enabled,
// but not yet mounted, this will start it mounting and wait for it to
// complete before adding the mount point.
void AddDriveMountPoint();

// Mounts Drive if the directory exists.
void MaybeMountDrive(bool data_directory_exists);
void MaybeMountDrive(const base::FilePath& data_dir,
DirResult data_dir_result);

// Registers remote file system for drive mount point.
bool AddDriveMountPointAfterMounted();
Expand Down Expand Up @@ -416,6 +421,8 @@ class DriveIntegrationService : public KeyedService,
// Note: This should remain the last member so it'll be destroyed and
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<DriveIntegrationService> weak_ptr_factory_{this};

FRIEND_TEST_ALL_PREFIXES(DriveIntegrationServiceTest, EnsureDirectoryExists);
};

// Singleton that owns all instances of DriveIntegrationService and
Expand Down
32 changes: 32 additions & 0 deletions chrome/browser/ash/drive/drive_integration_service_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

#include "chrome/browser/ash/drive/drive_integration_service.h"

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
Expand Down Expand Up @@ -49,4 +52,33 @@ TEST_F(DriveIntegrationServiceTest, DISABLED_ServiceInstanceIdentity) {
DriveIntegrationServiceFactory::GetForProfile(user2));
}

TEST_F(DriveIntegrationServiceTest, EnsureDirectoryExists) {
base::ScopedTempDir tmp_dir;
ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());

const base::FilePath data_dir = tmp_dir.GetPath().Append("a/b/c");
EXPECT_FALSE(base::DirectoryExists(data_dir));

// First time, the data dir should be created.
EXPECT_EQ(DriveIntegrationService::EnsureDirectoryExists(data_dir),
DriveIntegrationService::DirResult::kCreated);
EXPECT_TRUE(base::DirectoryExists(data_dir));

// Second time, the data dir should already exist.
EXPECT_EQ(DriveIntegrationService::EnsureDirectoryExists(data_dir),
DriveIntegrationService::DirResult::kExisting);
EXPECT_TRUE(base::DirectoryExists(data_dir));

// Remove the data dir, and replace it with a file.
EXPECT_TRUE(base::DeleteFile(data_dir));
EXPECT_FALSE(base::DirectoryExists(data_dir));
EXPECT_TRUE(base::WriteFile(data_dir, "Whatever"));

// Trying to create the data dir should now fail.
EXPECT_FALSE(base::DirectoryExists(data_dir));
EXPECT_EQ(DriveIntegrationService::EnsureDirectoryExists(data_dir),
DriveIntegrationService::DirResult::kError);
EXPECT_FALSE(base::DirectoryExists(data_dir));
}

} // namespace drive
5 changes: 4 additions & 1 deletion ui/chromeos/file_manager_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@
An error occured during installation of your Linux application.
</message>

<message name="IDS_FILE_BROWSER_RECOVERED_FILES_FROM_GOOGLE_DRIVE_DIRECTORY_NAME" desc="The name of the direcotry which stores files recovered from Google Drive directory when the locally stored Google Drive data is found to be broken.">
<message name="IDS_FILE_BROWSER_RECOVERED_FILES_FROM_GOOGLE_DRIVE_DIRECTORY_NAME" desc="The name of the directory which stores files recovered from Google Drive directory when the locally stored Google Drive data is found to be broken.">
Recovered files from Google Drive
</message>

Expand Down Expand Up @@ -711,6 +711,9 @@
<message name="IDS_FILE_BROWSER_SYNC_NO_SERVER_SPACE_ORGANIZATION" desc="File Manager status message shown when the drive sync is failed because the user's organization runs out the space in Google Drive server.">
Your organization requires more storage to complete the upload.
</message>
<message name="IDS_FILE_BROWSER_DRIVE_DATA_DIR_MISSING" desc="Don't translate yet; this message is not final. System notification displayed when the Google Drive cache file were removed while the user was logged out.">
Your Google Drive cache was cleared.
</message>
<message name="IDS_FILE_BROWSER_DRIVE_ORGANIZATION_STORAGE_FULL" desc="File Manager menu storage meter message indicating the user's organization has run out of quota.">
Org storage full
</message>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
54e5f11b509ae1b94279c6663a25075ff8f1b4ec

0 comments on commit 23f62a5

Please sign in to comment.