Commit 63e4b8ce authored by Sam McNally's avatar Sam McNally Committed by Commit Bot

Migrate pinned files to DriveFS on first run with DriveFS enabled.

Bug: 877043
Change-Id: Iab18132a8c4750de0f7f96601f6232c41e3aaf54
Reviewed-on: https://chromium-review.googlesource.com/1194544Reviewed-by: default avatarAlexander Alekseev <alemate@chromium.org>
Reviewed-by: default avatarStuart Langley <slangley@chromium.org>
Reviewed-by: default avatarNoel Gordon <noel@chromium.org>
Commit-Queue: Sam McNally <sammc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#588771}
parent e482f1c2
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/sys_info.h" #include "base/sys_info.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
...@@ -178,6 +179,11 @@ FileError InitializeMetadata( ...@@ -178,6 +179,11 @@ FileError InitializeMetadata(
return FILE_ERROR_FAILED; return FILE_ERROR_FAILED;
} }
// When running with DriveFS and migrating pinned files, only
// |metadata_storage| is non-null and needs to be initialized.
if (!cache)
return FILE_ERROR_OK;
if (!cache->Initialize()) { if (!cache->Initialize()) {
LOG(WARNING) << "Failed to initialize the cache."; LOG(WARNING) << "Failed to initialize the cache.";
return FILE_ERROR_FAILED; return FILE_ERROR_FAILED;
...@@ -220,6 +226,56 @@ void ResetCacheDone(base::OnceCallback<void(bool)> callback, FileError error) { ...@@ -220,6 +226,56 @@ void ResetCacheDone(base::OnceCallback<void(bool)> callback, FileError error) {
std::move(callback).Run(error == FILE_ERROR_OK); std::move(callback).Run(error == FILE_ERROR_OK);
} }
base::FilePath GetFullPath(internal::ResourceMetadataStorage* metadata_storage,
const ResourceEntry& entry) {
std::vector<std::string> path_components;
ResourceEntry current_entry = entry;
constexpr int kPathComponentSanityLimit = 100;
for (int i = 0; i < kPathComponentSanityLimit; ++i) {
path_components.push_back(current_entry.base_name());
if (!current_entry.has_parent_local_id()) {
// Ignore anything not contained within the drive grand root.
return {};
}
if (current_entry.parent_local_id() == util::kDriveGrandRootLocalId) {
// Omit the DriveGrantRoot directory from the path; DriveFS paths are
// relative to the mount point.
break;
}
if (metadata_storage->GetEntry(current_entry.parent_local_id(),
&current_entry) != FILE_ERROR_OK) {
return {};
}
}
if (path_components.empty()) {
return {};
}
base::FilePath path("/");
for (auto it = path_components.crbegin(); it != path_components.crend();
++it) {
path = path.Append(*it);
}
return path;
}
std::vector<base::FilePath> GetPinnedFiles(
internal::ResourceMetadataStorage* metadata_storage) {
std::vector<base::FilePath> pinned_files;
for (auto it = metadata_storage->GetIterator(); !it->IsAtEnd();
it->Advance()) {
const auto& value = it->GetValue();
if (!value.has_file_specific_info() ||
!value.file_specific_info().cache_state().is_pinned()) {
continue;
}
auto path = GetFullPath(metadata_storage, value);
if (!path.empty()) {
pinned_files.push_back(std::move(path));
}
}
return pinned_files;
}
} // namespace } // namespace
// Observes drive disable Preference's change. // Observes drive disable Preference's change.
...@@ -443,10 +499,19 @@ DriveIntegrationService::DriveIntegrationService( ...@@ -443,10 +499,19 @@ DriveIntegrationService::DriveIntegrationService(
if (preference_watcher_) if (preference_watcher_)
preference_watcher->set_integration_service(this); preference_watcher->set_integration_service(this);
bool migrated_to_drivefs =
profile_->GetPrefs()->GetBoolean(prefs::kDriveFsPinnedMigrated);
if (!drivefs_holder_ || !migrated_to_drivefs) {
metadata_storage_.reset(new internal::ResourceMetadataStorage(
cache_root_directory_.Append(kMetadataDirectory),
blocking_task_runner_.get()));
}
if (drivefs_holder_) { if (drivefs_holder_) {
delete test_drive_service; delete test_drive_service;
delete test_file_system; delete test_file_system;
state_ = INITIALIZED; if (migrated_to_drivefs) {
state_ = INITIALIZED;
}
SetEnabled(drive::util::IsDriveEnabledForProfile(profile)); SetEnabled(drive::util::IsDriveEnabledForProfile(profile));
return; return;
} }
...@@ -481,9 +546,6 @@ DriveIntegrationService::DriveIntegrationService( ...@@ -481,9 +546,6 @@ DriveIntegrationService::DriveIntegrationService(
scheduler_ = std::make_unique<JobScheduler>( scheduler_ = std::make_unique<JobScheduler>(
profile_->GetPrefs(), logger_.get(), drive_service_.get(), profile_->GetPrefs(), logger_.get(), drive_service_.get(),
blocking_task_runner_.get(), std::move(wake_lock_provider)); blocking_task_runner_.get(), std::move(wake_lock_provider));
metadata_storage_.reset(new internal::ResourceMetadataStorage(
cache_root_directory_.Append(kMetadataDirectory),
blocking_task_runner_.get()));
cache_.reset(new internal::FileCache( cache_.reset(new internal::FileCache(
metadata_storage_.get(), metadata_storage_.get(),
cache_root_directory_.Append(kCacheFileDirectory), cache_root_directory_.Append(kCacheFileDirectory),
...@@ -748,6 +810,10 @@ void DriveIntegrationService::AddDriveMountPointAfterMounted() { ...@@ -748,6 +810,10 @@ void DriveIntegrationService::AddDriveMountPointAfterMounted() {
if (drivefs_holder_ && preference_watcher_) { if (drivefs_holder_ && preference_watcher_) {
preference_watcher_->UpdateSyncPauseState(); preference_watcher_->UpdateSyncPauseState();
} }
if (drivefs_holder_ &&
!profile_->GetPrefs()->GetBoolean(prefs::kDriveFsPinnedMigrated)) {
MigratePinnedFiles();
}
} }
void DriveIntegrationService::RemoveDriveMountPoint() { void DriveIntegrationService::RemoveDriveMountPoint() {
...@@ -830,6 +896,17 @@ void DriveIntegrationService::InitializeAfterMetadataInitialized( ...@@ -830,6 +896,17 @@ void DriveIntegrationService::InitializeAfterMetadataInitialized(
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(INITIALIZING, state_); DCHECK_EQ(INITIALIZING, state_);
if (drivefs_holder_) {
if (error != FILE_ERROR_OK) {
profile_->GetPrefs()->SetBoolean(prefs::kDriveFsPinnedMigrated, true);
metadata_storage_.reset();
}
state_ = INITIALIZED;
if (enabled_)
AddDriveMountPoint();
return;
}
SigninManagerBase* signin_manager = SigninManagerBase* signin_manager =
SigninManagerFactory::GetForProfile(profile_); SigninManagerFactory::GetForProfile(profile_);
drive_service_->Initialize(signin_manager->GetAuthenticatedAccountId()); drive_service_->Initialize(signin_manager->GetAuthenticatedAccountId());
...@@ -916,6 +993,29 @@ void DriveIntegrationService::Observe( ...@@ -916,6 +993,29 @@ void DriveIntegrationService::Observe(
} }
} }
void DriveIntegrationService::MigratePinnedFiles() {
if (!metadata_storage_)
return;
base::PostTaskAndReplyWithResult(
blocking_task_runner_.get(), FROM_HERE,
base::BindOnce(&GetPinnedFiles, metadata_storage_.get()),
base::BindOnce(&DriveIntegrationService::PinFiles,
weak_ptr_factory_.GetWeakPtr()));
}
void DriveIntegrationService::PinFiles(
const std::vector<base::FilePath>& files_to_pin) {
if (!drivefs_holder_->drivefs_host()->IsMounted())
return;
for (const auto& path : files_to_pin) {
GetDriveFsInterface()->SetPinned(path, true, base::DoNothing());
}
profile_->GetPrefs()->SetBoolean(prefs::kDriveFsPinnedMigrated, true);
metadata_storage_.reset();
}
//===================== DriveIntegrationServiceFactory ======================= //===================== DriveIntegrationServiceFactory =======================
DriveIntegrationServiceFactory::FactoryCallback* DriveIntegrationServiceFactory::FactoryCallback*
......
...@@ -213,6 +213,12 @@ class DriveIntegrationService : public KeyedService, ...@@ -213,6 +213,12 @@ class DriveIntegrationService : public KeyedService,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) override; const content::NotificationDetails& details) override;
// Migrate pinned files from the old Drive integration to DriveFS.
void MigratePinnedFiles();
// Pin all the files in |files_to_pin| with DriveFS.
void PinFiles(const std::vector<base::FilePath>& files_to_pin);
friend class DriveIntegrationServiceFactory; friend class DriveIntegrationServiceFactory;
Profile* profile_; Profile* profile_;
......
...@@ -735,4 +735,46 @@ IN_PROC_BROWSER_TEST_F(MultiProfileFilesAppBrowserTest, BasicDrive) { ...@@ -735,4 +735,46 @@ IN_PROC_BROWSER_TEST_F(MultiProfileFilesAppBrowserTest, BasicDrive) {
StartTest(); StartTest();
} }
// Test fixture class for testing migration to DriveFS.
class DriveFsFilesAppBrowserTest : public FileManagerBrowserTestBase {
public:
DriveFsFilesAppBrowserTest() = default;
protected:
GuestMode GetGuestMode() const override { return NOT_IN_GUEST_MODE; }
const char* GetTestCaseName() const override {
return test_case_name_.c_str();
}
std::string GetFullTestCaseName() const override { return test_case_name_; }
const char* GetTestExtensionManifestName() const override {
return "file_manager_test_manifest.json";
}
void set_test_case_name(const std::string& name) { test_case_name_ = name; }
bool GetEnableDriveFs() const override {
return !base::StringPiece(
::testing::UnitTest::GetInstance()->current_test_info()->name())
.starts_with("PRE");
}
private:
std::string test_case_name_;
DISALLOW_COPY_AND_ASSIGN(DriveFsFilesAppBrowserTest);
};
IN_PROC_BROWSER_TEST_F(DriveFsFilesAppBrowserTest, PRE_MigratePinnedFiles) {
set_test_case_name("PRE_driveMigratePinnedFile");
StartTest();
}
IN_PROC_BROWSER_TEST_F(DriveFsFilesAppBrowserTest, MigratePinnedFiles) {
set_test_case_name("driveMigratePinnedFile");
StartTest();
}
} // namespace file_manager } // namespace file_manager
...@@ -353,12 +353,13 @@ class TestVolume { ...@@ -353,12 +353,13 @@ class TestVolume {
bool CreateRootDirectory(const Profile* profile) { bool CreateRootDirectory(const Profile* profile) {
if (root_initialized_) if (root_initialized_)
return true; return true;
root_initialized_ = root_.Set(profile->GetPath().Append(name_)); root_ = profile->GetPath().Append(name_);
root_initialized_ = base::CreateDirectory(root_);
return root_initialized_; return root_initialized_;
} }
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
const base::FilePath& root_path() const { return root_.GetPath(); } const base::FilePath& root_path() const { return root_; }
static base::FilePath GetTestDataFilePath(const std::string& file_name) { static base::FilePath GetTestDataFilePath(const std::string& file_name) {
// Get the path to file manager's test data directory. // Get the path to file manager's test data directory.
...@@ -374,7 +375,7 @@ class TestVolume { ...@@ -374,7 +375,7 @@ class TestVolume {
} }
private: private:
base::ScopedTempDir root_; base::FilePath root_;
bool root_initialized_ = false; bool root_initialized_ = false;
std::string name_; std::string name_;
......
...@@ -318,6 +318,7 @@ void Preferences::RegisterProfilePrefs( ...@@ -318,6 +318,7 @@ void Preferences::RegisterProfilePrefs(
drive::prefs::kDisableDriveHostedFiles, false, drive::prefs::kDisableDriveHostedFiles, false,
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterStringPref(drive::prefs::kDriveFsProfileSalt, ""); registry->RegisterStringPref(drive::prefs::kDriveFsProfileSalt, "");
registry->RegisterBooleanPref(drive::prefs::kDriveFsPinnedMigrated, false);
// We don't sync prefs::kLanguageCurrentInputMethod and PreviousInputMethod // We don't sync prefs::kLanguageCurrentInputMethod and PreviousInputMethod
// because they're just used to track the logout state of the device. // because they're just used to track the logout state of the device.
registry->RegisterStringPref(prefs::kLanguageCurrentInputMethod, ""); registry->RegisterStringPref(prefs::kLanguageCurrentInputMethod, "");
......
...@@ -126,7 +126,9 @@ void FakeDriveFs::SetMetadata(const base::FilePath& path, ...@@ -126,7 +126,9 @@ void FakeDriveFs::SetMetadata(const base::FilePath& path,
stored_metadata.mime_type = mime_type; stored_metadata.mime_type = mime_type;
stored_metadata.original_name = original_name; stored_metadata.original_name = original_name;
stored_metadata.hosted = (original_name != path.BaseName().value()); stored_metadata.hosted = (original_name != path.BaseName().value());
stored_metadata.pinned = pinned; if (pinned) {
stored_metadata.pinned = true;
}
} }
void FakeDriveFs::Init(drivefs::mojom::DriveFsConfigurationPtr config, void FakeDriveFs::Init(drivefs::mojom::DriveFsConfigurationPtr config,
......
...@@ -23,5 +23,8 @@ const char kDisableDriveHostedFiles[] = "gdata.hosted_files.disabled"; ...@@ -23,5 +23,8 @@ const char kDisableDriveHostedFiles[] = "gdata.hosted_files.disabled";
// when passed to drivefs. // when passed to drivefs.
const char kDriveFsProfileSalt[] = "drivefs.profile_salt"; const char kDriveFsProfileSalt[] = "drivefs.profile_salt";
// A boolean pref containing whether pinned files have been migrated to DriveFS.
const char kDriveFsPinnedMigrated[] = "drivefs.pinned_migrated";
} // namespace prefs } // namespace prefs
} // namespace drive } // namespace drive
...@@ -14,6 +14,7 @@ extern const char kDisableDrive[]; ...@@ -14,6 +14,7 @@ extern const char kDisableDrive[];
extern const char kDisableDriveOverCellular[]; extern const char kDisableDriveOverCellular[];
extern const char kDisableDriveHostedFiles[]; extern const char kDisableDriveHostedFiles[];
extern const char kDriveFsProfileSalt[]; extern const char kDriveFsProfileSalt[];
extern const char kDriveFsPinnedMigrated[];
} // namespace prefs } // namespace prefs
} // namespace drive } // namespace drive
......
...@@ -344,3 +344,75 @@ testcase.drivePressCtrlAFromSearch = function() { ...@@ -344,3 +344,75 @@ testcase.drivePressCtrlAFromSearch = function() {
]; ];
StepsRunner.run(steps); StepsRunner.run(steps);
}; };
testcase.PRE_driveMigratePinnedFile = function() {
// Pin a file.
testPromise(
setupAndWaitUntilReady(null, RootPath.DRIVE).then(function(results) {
var windowId = results.windowId;
return remoteCall
.callRemoteTestUtil('selectFile', windowId, ['hello.txt'])
.then(function() {
return remoteCall.waitForElement(
windowId, ['.table-row[selected]']);
})
.then(function() {
return remoteCall.callRemoteTestUtil(
'fakeMouseRightClick', windowId, ['.table-row[selected]']);
})
.then(function(result) {
chrome.test.assertTrue(result);
return remoteCall.waitForElement(
windowId, '#file-context-menu:not([hidden])');
})
.then(function() {
return remoteCall.waitForElement(
windowId, ['[command="#toggle-pinned"]']);
})
.then(function() {
return remoteCall.callRemoteTestUtil(
'fakeMouseClick', windowId, ['[command="#toggle-pinned"]']);
})
.then(function(result) {
return remoteCall.waitForElement(
windowId, '#file-context-menu[hidden]');
})
.then(function() {
return remoteCall.callRemoteTestUtil(
'fakeEvent', windowId, ['#file-list', 'contextmenu']);
})
.then(function(result) {
chrome.test.assertTrue(result);
return remoteCall.waitForElement(
windowId, '[command="#toggle-pinned"][checked]');
});
}));
};
testcase.driveMigratePinnedFile = function() {
// After enabling DriveFS, ensure the file is still pinned.
testPromise(
setupAndWaitUntilReady(null, RootPath.DRIVE).then(function(results) {
var windowId = results.windowId;
return remoteCall
.callRemoteTestUtil('selectFile', windowId, ['hello.txt'])
.then(function() {
return remoteCall.waitForElement(
windowId, ['.table-row[selected]']);
})
.then(function() {
return remoteCall.callRemoteTestUtil(
'fakeMouseRightClick', windowId, ['.table-row[selected]']);
})
.then(function(result) {
chrome.test.assertTrue(result);
return remoteCall.waitForElement(
windowId, '#file-context-menu:not([hidden])');
})
.then(function() {
return remoteCall.waitForElement(
windowId, '[command="#toggle-pinned"][checked]');
});
}));
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment