Commit 57ce6a16 authored by Sam McNally's avatar Sam McNally Committed by Commit Bot

Add an integration test for backing up photos to Drive.

In order to make the test pass:
- Change chrome.fileManagerPrivate.setEntryTag() to succeed but take no
  other action with DriveFS enabled; it won't be supported with DriveFS.
- Enable a mock SyncFileSystemService so the use of the syncFileSystem
  API can succeed locally.
- Add support for mounting a USB drive containing a DCIM directory with
  an image.

This test only exercises basic functionality:
- There is no previous photo backup history in the syncFileSystem.
- Images in the external drive are not duplicated in Drive.

Bug: 883628
Change-Id: Ic5244de54bdd6f3fee0c82a356e7e530b85dba64
Reviewed-on: https://chromium-review.googlesource.com/1230193Reviewed-by: default avatarNoel Gordon <noel@chromium.org>
Commit-Queue: Sam McNally <sammc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592313}
parent 62e3afab
...@@ -1063,9 +1063,17 @@ FileManagerPrivateInternalSetEntryTagFunction::Run() { ...@@ -1063,9 +1063,17 @@ FileManagerPrivateInternalSetEntryTagFunction::Run() {
const std::unique_ptr<Params> params(Params::Create(*args_)); const std::unique_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params); EXTENSION_FUNCTION_VALIDATE(params);
const base::FilePath local_path = file_manager::util::GetLocalPathFromURL( scoped_refptr<storage::FileSystemContext> file_system_context =
render_frame_host(), chrome_details_.GetProfile(), GURL(params->url)); file_manager::util::GetFileSystemContextForRenderFrameHost(
const base::FilePath drive_path = drive::util::ExtractDrivePath(local_path); Profile::FromBrowserContext(browser_context()), render_frame_host());
const storage::FileSystemURL file_system_url(
file_system_context->CrackURL(GURL(params->url)));
if (file_system_url.type() == storage::kFileSystemTypeDriveFs) {
return RespondNow(NoArguments());
}
const base::FilePath drive_path =
drive::util::ExtractDrivePath(file_system_url.path());
if (drive_path.empty()) if (drive_path.empty())
return RespondNow(Error("Only Drive files and directories are supported.")); return RespondNow(Error("Only Drive files and directories are supported."));
......
...@@ -388,7 +388,9 @@ WRAPPED_INSTANTIATE_TEST_CASE_P( ...@@ -388,7 +388,9 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(
TestCase("drivePinFileMobileNetwork").EnableDriveFs(), TestCase("drivePinFileMobileNetwork").EnableDriveFs(),
TestCase("driveClickFirstSearchResult"), TestCase("driveClickFirstSearchResult"),
TestCase("drivePressEnterToSearch"), TestCase("drivePressEnterToSearch"),
TestCase("drivePressCtrlAFromSearch"))); TestCase("drivePressCtrlAFromSearch"),
TestCase("driveBackupPhotos"),
TestCase("driveBackupPhotos").EnableDriveFs()));
WRAPPED_INSTANTIATE_TEST_CASE_P( WRAPPED_INSTANTIATE_TEST_CASE_P(
Transfer, /* transfer.js */ Transfer, /* transfer.js */
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include "chrome/browser/chromeos/file_manager/volume_manager.h" #include "chrome/browser/chromeos/file_manager/volume_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/sync_file_system/mock_remote_file_sync_service.h"
#include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
...@@ -571,6 +573,30 @@ class FakeTestVolume : public LocalTestVolume { ...@@ -571,6 +573,30 @@ class FakeTestVolume : public LocalTestVolume {
return true; return true;
} }
bool PrepareDcimTestEntries(Profile* profile) {
if (!CreateRootDirectory(profile))
return false;
CreateEntry(AddEntriesMessage::TestEntryInfo(
AddEntriesMessage::DIRECTORY, "", "DCIM", std::string(), "",
AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
AddEntriesMessage::EntryCapabilities(), false));
CreateEntry(AddEntriesMessage::TestEntryInfo(
AddEntriesMessage::FILE, "image2.png", "image2.png", std::string(),
"image/png", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
AddEntriesMessage::EntryCapabilities(), false));
CreateEntry(AddEntriesMessage::TestEntryInfo(
AddEntriesMessage::FILE, "image3.jpg", "DCIM/image3.jpg", std::string(),
"image/jpeg", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
AddEntriesMessage::EntryCapabilities(), false));
CreateEntry(AddEntriesMessage::TestEntryInfo(
AddEntriesMessage::FILE, "text.txt", "DCIM/hello.txt", std::string(),
"text/plain", AddEntriesMessage::SharedOption::NONE, base::Time::Now(),
AddEntriesMessage::EntryCapabilities(), false));
base::RunLoop().RunUntilIdle();
return true;
}
bool Mount(Profile* profile) override { bool Mount(Profile* profile) override {
if (!CreateRootDirectory(profile)) if (!CreateRootDirectory(profile))
return false; return false;
...@@ -1031,6 +1057,14 @@ void FileManagerBrowserTestBase::SetUpInProcessBrowserTestFixture() { ...@@ -1031,6 +1057,14 @@ void FileManagerBrowserTestBase::SetUpInProcessBrowserTestFixture() {
} }
void FileManagerBrowserTestBase::SetUpOnMainThread() { void FileManagerBrowserTestBase::SetUpOnMainThread() {
// Must happen after the browser process is created because instantiating
// the factory will instantiate ExtensionSystemFactory which depends on
// ExtensionsBrowserClient setup in BrowserProcessImpl.
sync_file_system::SyncFileSystemServiceFactory::GetInstance()
->set_mock_remote_file_service(
std::make_unique<::testing::NiceMock<
sync_file_system::MockRemoteFileSyncService>>());
extensions::ExtensionApiTest::SetUpOnMainThread(); extensions::ExtensionApiTest::SetUpOnMainThread();
CHECK(profile()); CHECK(profile());
CHECK_EQ(!!browser(), GetRequiresStartupBrowser()); CHECK_EQ(!!browser(), GetRequiresStartupBrowser());
...@@ -1266,13 +1300,16 @@ void FileManagerBrowserTestBase::OnCommand(const std::string& name, ...@@ -1266,13 +1300,16 @@ void FileManagerBrowserTestBase::OnCommand(const std::string& name,
return; return;
} }
if (name == "mountFakeUsb" || name == "mountFakeUsbEmpty") { if (name == "mountFakeUsb" || name == "mountFakeUsbEmpty" ||
name == "mountFakeUsbDcim") {
usb_volume_ = std::make_unique<FakeTestVolume>( usb_volume_ = std::make_unique<FakeTestVolume>(
"fake-usb", VOLUME_TYPE_REMOVABLE_DISK_PARTITION, "fake-usb", VOLUME_TYPE_REMOVABLE_DISK_PARTITION,
chromeos::DEVICE_TYPE_USB); chromeos::DEVICE_TYPE_USB);
if (name == "mountFakeUsb") if (name == "mountFakeUsb")
ASSERT_TRUE(usb_volume_->PrepareTestEntries(profile())); ASSERT_TRUE(usb_volume_->PrepareTestEntries(profile()));
else if (name == "mountFakeUsbDcim")
ASSERT_TRUE(usb_volume_->PrepareDcimTestEntries(profile()));
ASSERT_TRUE(usb_volume_->Mount(profile())); ASSERT_TRUE(usb_volume_->Mount(profile()));
return; return;
......
...@@ -416,3 +416,87 @@ testcase.driveMigratePinnedFile = function() { ...@@ -416,3 +416,87 @@ testcase.driveMigratePinnedFile = function() {
})); }));
}; };
// Match the way the production version formats dates.
function formatDate(date) {
var padAndConvert = function(i) {
return (i < 10 ? '0' : '') + i.toString();
};
var year = date.getFullYear().toString();
// Months are 0-based, but days aren't.
var month = padAndConvert(date.getMonth() + 1);
var day = padAndConvert(date.getDate());
return `${year}-${month}-${day}`;
}
testcase.driveBackupPhotos = function() {
let appId;
const USB_VOLUME_QUERY = '#directory-tree [volume-type-icon="removable"]';
let date;
StepsRunner.run([
// Open Files app on local downloads.
function() {
setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next);
},
// Mount USB volume in the Downloads window.
function(results) {
appId = results.windowId;
chrome.test.sendMessage(
JSON.stringify({name: 'mountFakeUsbDcim'}), this.next);
},
// Wait for the USB mount.
function() {
remoteCall.waitForElement(appId, USB_VOLUME_QUERY).then(this.next);
},
// Navigate to the DCIM directory.
function() {
remoteCall
.navigateWithDirectoryTree(appId, '/DCIM', 'fake-usb', 'removable')
.then(this.next);
},
// Wait for the import button to be ready.
function() {
remoteCall
.waitForElement(
appId, '#cloud-import-button [icon="files:cloud-upload"]')
.then(this.next);
},
// Start the import.
function() {
date = new Date();
remoteCall
.callRemoteTestUtil('fakeMouseClick', appId, ['#cloud-import-button'])
.then(this.next);
},
// Wait for the image to be marked as imported.
function(success) {
chrome.test.assertTrue(success);
remoteCall
.waitForElement(appId, '.status-icon[file-status-icon="imported"]')
.then(this.next);
},
// Navigate to today's backup directory in Drive.
function() {
const formattedDate = formatDate(date);
remoteCall
.navigateWithDirectoryTree(
appId, `/root/Chrome OS Cloud backup/${formattedDate}`,
'My Drive', 'drive')
.then(this.next);
},
// Verify the backed-up file list contains only a copy of the image within
// DCIM in the removable storage.
function() {
const files = TestEntryInfo.getExpectedRows([ENTRIES.image3]);
remoteCall.waitForFiles(appId, files, {ignoreLastModifiedTime: true})
.then(this.next);
},
function() {
checkIfNoErrorsOccured(this.next);
}
]);
};
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