// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Browser test for basic Chrome OS file manager functionality: // - The file list is updated when a file is added externally to the Downloads // folder. // - Selecting a file and copy-pasting it with the keyboard copies the file. // - Selecting a file and pressing delete deletes it. #include <deque> #include <string> #include "apps/app_window.h" #include "apps/app_window_registry.h" #include "ash/session/session_state_delegate.h" #include "ash/shell.h" #include "base/bind.h" #include "base/callback.h" #include "base/file_util.h" #include "base/files/file_path.h" #include "base/json/json_reader.h" #include "base/json/json_value_converter.h" #include "base/json/json_writer.h" #include "base/prefs/pref_service.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/drive/drive_integration_service.h" #include "chrome/browser/chromeos/drive/file_system_interface.h" #include "chrome/browser/chromeos/drive/test_util.h" #include "chrome/browser/chromeos/file_manager/app_id.h" #include "chrome/browser/chromeos/file_manager/drive_test_util.h" #include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/chromeos/file_manager/volume_manager.h" #include "chrome/browser/chromeos/login/users/user_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/drive/fake_drive_service.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chromeos/chromeos_switches.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" #include "extensions/browser/api/test/test_api.h" #include "extensions/common/extension.h" #include "google_apis/drive/drive_api_parser.h" #include "google_apis/drive/test_util.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "webkit/browser/fileapi/external_mount_points.h" using drive::DriveIntegrationServiceFactory; namespace file_manager { namespace { enum EntryType { FILE, DIRECTORY, }; enum TargetVolume { LOCAL_VOLUME, DRIVE_VOLUME, USB_VOLUME, }; enum SharedOption { NONE, SHARED, }; enum GuestMode { NOT_IN_GUEST_MODE, IN_GUEST_MODE, }; // This global operator is used from Google Test to format error messages. std::ostream& operator<<(std::ostream& os, const GuestMode& guest_mode) { return os << (guest_mode == IN_GUEST_MODE ? "IN_GUEST_MODE" : "NOT_IN_GUEST_MODE"); } // Maps the given string to EntryType. Returns true on success. bool MapStringToEntryType(const base::StringPiece& value, EntryType* output) { if (value == "file") *output = FILE; else if (value == "directory") *output = DIRECTORY; else return false; return true; } // Maps the given string to SharedOption. Returns true on success. bool MapStringToSharedOption(const base::StringPiece& value, SharedOption* output) { if (value == "shared") *output = SHARED; else if (value == "none") *output = NONE; else return false; return true; } // Maps the given string to TargetVolume. Returns true on success. bool MapStringToTargetVolume(const base::StringPiece& value, TargetVolume* output) { if (value == "drive") *output = DRIVE_VOLUME; else if (value == "local") *output = LOCAL_VOLUME; else if (value == "usb") *output = USB_VOLUME; else return false; return true; } // Maps the given string to base::Time. Returns true on success. bool MapStringToTime(const base::StringPiece& value, base::Time* time) { return base::Time::FromString(value.as_string().c_str(), time); } // Test data of file or directory. struct TestEntryInfo { TestEntryInfo() : type(FILE), shared_option(NONE) {} TestEntryInfo(EntryType type, const std::string& source_file_name, const std::string& target_path, const std::string& mime_type, SharedOption shared_option, const base::Time& last_modified_time) : type(type), source_file_name(source_file_name), target_path(target_path), mime_type(mime_type), shared_option(shared_option), last_modified_time(last_modified_time) { } EntryType type; std::string source_file_name; // Source file name to be used as a prototype. std::string target_path; // Target file or directory path. std::string mime_type; SharedOption shared_option; base::Time last_modified_time; // Registers the member information to the given converter. static void RegisterJSONConverter( base::JSONValueConverter<TestEntryInfo>* converter); }; // static void TestEntryInfo::RegisterJSONConverter( base::JSONValueConverter<TestEntryInfo>* converter) { converter->RegisterCustomField("type", &TestEntryInfo::type, &MapStringToEntryType); converter->RegisterStringField("sourceFileName", &TestEntryInfo::source_file_name); converter->RegisterStringField("targetPath", &TestEntryInfo::target_path); converter->RegisterStringField("mimeType", &TestEntryInfo::mime_type); converter->RegisterCustomField("sharedOption", &TestEntryInfo::shared_option, &MapStringToSharedOption); converter->RegisterCustomField("lastModifiedTime", &TestEntryInfo::last_modified_time, &MapStringToTime); } // Message from JavaScript to add entries. struct AddEntriesMessage { // Target volume to be added the |entries|. TargetVolume volume; // Entries to be added. ScopedVector<TestEntryInfo> entries; // Registers the member information to the given converter. static void RegisterJSONConverter( base::JSONValueConverter<AddEntriesMessage>* converter); }; // static void AddEntriesMessage::RegisterJSONConverter( base::JSONValueConverter<AddEntriesMessage>* converter) { converter->RegisterCustomField("volume", &AddEntriesMessage::volume, &MapStringToTargetVolume); converter->RegisterRepeatedMessage<TestEntryInfo>( "entries", &AddEntriesMessage::entries); } // Test volume. class TestVolume { protected: explicit TestVolume(const std::string& name) : name_(name) {} virtual ~TestVolume() {} bool CreateRootDirectory(const Profile* profile) { const base::FilePath path = profile->GetPath().Append(name_); return root_.path() == path || root_.Set(path); } const std::string& name() { return name_; } const base::FilePath root_path() { return root_.path(); } private: std::string name_; base::ScopedTempDir root_; }; // The local volume class for test. // This class provides the operations for a test volume that simulates local // drive. class LocalTestVolume : public TestVolume { public: explicit LocalTestVolume(const std::string& name) : TestVolume(name) {} virtual ~LocalTestVolume() {} // Adds this volume to the file system as a local volume. Returns true on // success. virtual bool Mount(Profile* profile) = 0; void CreateEntry(const TestEntryInfo& entry) { const base::FilePath target_path = root_path().AppendASCII(entry.target_path); entries_.insert(std::make_pair(target_path, entry)); switch (entry.type) { case FILE: { const base::FilePath source_path = google_apis::test_util::GetTestFilePath("chromeos/file_manager"). AppendASCII(entry.source_file_name); ASSERT_TRUE(base::CopyFile(source_path, target_path)) << "Copy from " << source_path.value() << " to " << target_path.value() << " failed."; break; } case DIRECTORY: ASSERT_TRUE(base::CreateDirectory(target_path)) << "Failed to create a directory: " << target_path.value(); break; } ASSERT_TRUE(UpdateModifiedTime(entry)); } private: // Updates ModifiedTime of the entry and its parents by referring // TestEntryInfo. Returns true on success. bool UpdateModifiedTime(const TestEntryInfo& entry) { const base::FilePath path = root_path().AppendASCII(entry.target_path); if (!base::TouchFile(path, entry.last_modified_time, entry.last_modified_time)) return false; // Update the modified time of parent directories because it may be also // affected by the update of child items. if (path.DirName() != root_path()) { const std::map<base::FilePath, const TestEntryInfo>::iterator it = entries_.find(path.DirName()); if (it == entries_.end()) return false; return UpdateModifiedTime(it->second); } return true; } std::map<base::FilePath, const TestEntryInfo> entries_; }; class DownloadsTestVolume : public LocalTestVolume { public: DownloadsTestVolume() : LocalTestVolume("Downloads") {} virtual ~DownloadsTestVolume() {} virtual bool Mount(Profile* profile) OVERRIDE { return CreateRootDirectory(profile) && VolumeManager::Get(profile) ->RegisterDownloadsDirectoryForTesting(root_path()); } }; // Test volume for mimicing a specified type of volumes by a local folder. class FakeTestVolume : public LocalTestVolume { public: FakeTestVolume(const std::string& name, VolumeType volume_type, chromeos::DeviceType device_type) : LocalTestVolume(name), volume_type_(volume_type), device_type_(device_type) {} virtual ~FakeTestVolume() {} // Simple test entries used for testing, e.g., read-only volumes. bool PrepareTestEntries(Profile* profile) { if (!CreateRootDirectory(profile)) return false; // Must be in sync with BASIC_FAKE_ENTRY_SET in the JS test code. CreateEntry( TestEntryInfo(FILE, "text.txt", "hello.txt", "text/plain", NONE, base::Time::Now())); CreateEntry( TestEntryInfo(DIRECTORY, std::string(), "A", std::string(), NONE, base::Time::Now())); return true; } virtual bool Mount(Profile* profile) OVERRIDE { if (!CreateRootDirectory(profile)) return false; fileapi::ExternalMountPoints* const mount_points = fileapi::ExternalMountPoints::GetSystemInstance(); // First revoke the existing mount point (if any). mount_points->RevokeFileSystem(name()); const bool result = mount_points->RegisterFileSystem(name(), fileapi::kFileSystemTypeNativeLocal, fileapi::FileSystemMountOption(), root_path()); if (!result) return false; VolumeManager::Get(profile)->AddVolumeInfoForTesting( root_path(), volume_type_, device_type_); return true; } private: const VolumeType volume_type_; const chromeos::DeviceType device_type_; }; // The drive volume class for test. // This class provides the operations for a test volume that simulates Google // drive. class DriveTestVolume : public TestVolume { public: DriveTestVolume() : TestVolume("drive"), integration_service_(NULL) {} virtual ~DriveTestVolume() {} void CreateEntry(const TestEntryInfo& entry) { const base::FilePath path = base::FilePath::FromUTF8Unsafe(entry.target_path); const std::string target_name = path.BaseName().AsUTF8Unsafe(); // Obtain the parent entry. drive::FileError error = drive::FILE_ERROR_OK; scoped_ptr<drive::ResourceEntry> parent_entry(new drive::ResourceEntry); integration_service_->file_system()->GetResourceEntry( drive::util::GetDriveMyDriveRootPath().Append(path).DirName(), google_apis::test_util::CreateCopyResultCallback( &error, &parent_entry)); drive::test_util::RunBlockingPoolTask(); ASSERT_EQ(drive::FILE_ERROR_OK, error); ASSERT_TRUE(parent_entry); switch (entry.type) { case FILE: CreateFile(entry.source_file_name, parent_entry->resource_id(), target_name, entry.mime_type, entry.shared_option == SHARED, entry.last_modified_time); break; case DIRECTORY: CreateDirectory( parent_entry->resource_id(), target_name, entry.last_modified_time); break; } } // Creates an empty directory with the given |name| and |modification_time|. void CreateDirectory(const std::string& parent_id, const std::string& target_name, const base::Time& modification_time) { google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; scoped_ptr<google_apis::FileResource> entry; fake_drive_service_->AddNewDirectory( parent_id, target_name, drive::DriveServiceInterface::AddNewDirectoryOptions(), google_apis::test_util::CreateCopyResultCallback(&error, &entry)); base::MessageLoop::current()->RunUntilIdle(); ASSERT_EQ(google_apis::HTTP_CREATED, error); ASSERT_TRUE(entry); fake_drive_service_->SetLastModifiedTime( entry->file_id(), modification_time, google_apis::test_util::CreateCopyResultCallback(&error, &entry)); base::MessageLoop::current()->RunUntilIdle(); ASSERT_TRUE(error == google_apis::HTTP_SUCCESS); ASSERT_TRUE(entry); CheckForUpdates(); } // Creates a test file with the given spec. // Serves |test_file_name| file. Pass an empty string for an empty file. void CreateFile(const std::string& source_file_name, const std::string& parent_id, const std::string& target_name, const std::string& mime_type, bool shared_with_me, const base::Time& modification_time) { google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; std::string content_data; if (!source_file_name.empty()) { base::FilePath source_file_path = google_apis::test_util::GetTestFilePath("chromeos/file_manager"). AppendASCII(source_file_name); ASSERT_TRUE(base::ReadFileToString(source_file_path, &content_data)); } scoped_ptr<google_apis::FileResource> entry; fake_drive_service_->AddNewFile( mime_type, content_data, parent_id, target_name, shared_with_me, google_apis::test_util::CreateCopyResultCallback(&error, &entry)); base::MessageLoop::current()->RunUntilIdle(); ASSERT_EQ(google_apis::HTTP_CREATED, error); ASSERT_TRUE(entry); fake_drive_service_->SetLastModifiedTime( entry->file_id(), modification_time, google_apis::test_util::CreateCopyResultCallback(&error, &entry)); base::MessageLoop::current()->RunUntilIdle(); ASSERT_EQ(google_apis::HTTP_SUCCESS, error); ASSERT_TRUE(entry); CheckForUpdates(); } // Notifies FileSystem that the contents in FakeDriveService are // changed, hence the new contents should be fetched. void CheckForUpdates() { if (integration_service_ && integration_service_->file_system()) { integration_service_->file_system()->CheckForUpdates(); } } // Sets the url base for the test server to be used to generate share urls // on the files and directories. void ConfigureShareUrlBase(const GURL& share_url_base) { fake_drive_service_->set_share_url_base(share_url_base); } drive::DriveIntegrationService* CreateDriveIntegrationService( Profile* profile) { profile_ = profile; fake_drive_service_ = new drive::FakeDriveService; fake_drive_service_->LoadAppListForDriveApi("drive/applist.json"); if (!CreateRootDirectory(profile)) return NULL; integration_service_ = new drive::DriveIntegrationService( profile, NULL, fake_drive_service_, std::string(), root_path(), NULL); return integration_service_; } private: Profile* profile_; drive::FakeDriveService* fake_drive_service_; drive::DriveIntegrationService* integration_service_; }; // Listener to obtain the test relative messages synchronously. class FileManagerTestListener : public content::NotificationObserver { public: struct Message { int type; std::string message; scoped_refptr<extensions::TestSendMessageFunction> function; }; FileManagerTestListener() { registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_PASSED, content::NotificationService::AllSources()); registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_FAILED, content::NotificationService::AllSources()); registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE, content::NotificationService::AllSources()); } Message GetNextMessage() { if (messages_.empty()) content::RunMessageLoop(); const Message entry = messages_.front(); messages_.pop_front(); return entry; } virtual void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE { Message entry; entry.type = type; entry.message = type != chrome::NOTIFICATION_EXTENSION_TEST_PASSED ? *content::Details<std::string>(details).ptr() : std::string(); entry.function = type == chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE ? content::Source<extensions::TestSendMessageFunction>(source).ptr() : NULL; messages_.push_back(entry); base::MessageLoopForUI::current()->Quit(); } private: std::deque<Message> messages_; content::NotificationRegistrar registrar_; }; // The base test class. class FileManagerBrowserTestBase : public ExtensionApiTest { protected: virtual void SetUpInProcessBrowserTestFixture() OVERRIDE; virtual void SetUpOnMainThread() OVERRIDE; // Adds an incognito and guest-mode flags for tests in the guest mode. virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE; // Loads our testing extension and sends it a string identifying the current // test. virtual void StartTest(); void RunTestMessageLoop(); // Overriding point for test configurations. virtual const char* GetTestManifestName() const { return "file_manager_test_manifest.json"; } virtual GuestMode GetGuestModeParam() const = 0; virtual const char* GetTestCaseNameParam() const = 0; virtual std::string OnMessage(const std::string& name, const base::Value* value); scoped_ptr<LocalTestVolume> local_volume_; linked_ptr<DriveTestVolume> drive_volume_; std::map<Profile*, linked_ptr<DriveTestVolume> > drive_volumes_; scoped_ptr<FakeTestVolume> usb_volume_; scoped_ptr<FakeTestVolume> mtp_volume_; private: drive::DriveIntegrationService* CreateDriveIntegrationService( Profile* profile); DriveIntegrationServiceFactory::FactoryCallback create_drive_integration_service_; scoped_ptr<DriveIntegrationServiceFactory::ScopedFactoryForTest> service_factory_for_test_; }; void FileManagerBrowserTestBase::SetUpInProcessBrowserTestFixture() { ExtensionApiTest::SetUpInProcessBrowserTestFixture(); extensions::ComponentLoader::EnableBackgroundExtensionsForTesting(); local_volume_.reset(new DownloadsTestVolume); if (GetGuestModeParam() != IN_GUEST_MODE) { create_drive_integration_service_ = base::Bind(&FileManagerBrowserTestBase::CreateDriveIntegrationService, base::Unretained(this)); service_factory_for_test_.reset( new DriveIntegrationServiceFactory::ScopedFactoryForTest( &create_drive_integration_service_)); } } void FileManagerBrowserTestBase::SetUpOnMainThread() { ExtensionApiTest::SetUpOnMainThread(); ASSERT_TRUE(local_volume_->Mount(profile())); if (GetGuestModeParam() != IN_GUEST_MODE) { // Install the web server to serve the mocked share dialog. ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); const GURL share_url_base(embedded_test_server()->GetURL( "/chromeos/file_manager/share_dialog_mock/index.html")); drive_volume_ = drive_volumes_[profile()]; drive_volume_->ConfigureShareUrlBase(share_url_base); test_util::WaitUntilDriveMountPointIsAdded(profile()); } } void FileManagerBrowserTestBase::SetUpCommandLine(CommandLine* command_line) { if (GetGuestModeParam() == IN_GUEST_MODE) { command_line->AppendSwitch(chromeos::switches::kGuestSession); command_line->AppendSwitchNative(chromeos::switches::kLoginUser, ""); command_line->AppendSwitch(switches::kIncognito); } ExtensionApiTest::SetUpCommandLine(command_line); } void FileManagerBrowserTestBase::StartTest() { // Launch the extension. const base::FilePath path = test_data_dir_.AppendASCII("file_manager_browsertest"); const extensions::Extension* const extension = LoadExtensionAsComponentWithManifest(path, GetTestManifestName()); ASSERT_TRUE(extension); RunTestMessageLoop(); } void FileManagerBrowserTestBase::RunTestMessageLoop() { // Handle the messages from JavaScript. // The while loop is break when the test is passed or failed. FileManagerTestListener listener; while (true) { FileManagerTestListener::Message entry = listener.GetNextMessage(); if (entry.type == chrome::NOTIFICATION_EXTENSION_TEST_PASSED) { // Test succeed. break; } else if (entry.type == chrome::NOTIFICATION_EXTENSION_TEST_FAILED) { // Test failed. ADD_FAILURE() << entry.message; break; } // Parse the message value as JSON. const scoped_ptr<const base::Value> value( base::JSONReader::Read(entry.message)); // If the message is not the expected format, just ignore it. const base::DictionaryValue* message_dictionary = NULL; std::string name; if (!value || !value->GetAsDictionary(&message_dictionary) || !message_dictionary->GetString("name", &name)) continue; entry.function->Reply(OnMessage(name, value.get())); } } std::string FileManagerBrowserTestBase::OnMessage(const std::string& name, const base::Value* value) { if (name == "getTestName") { // Pass the test case name. return GetTestCaseNameParam(); } else if (name == "getRootPaths") { // Pass the root paths. const scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue()); res->SetString("downloads", "/" + util::GetDownloadsMountPointName(profile())); res->SetString("drive", "/" + drive::util::GetDriveMountPointPath(profile() ).BaseName().AsUTF8Unsafe() + "/root"); std::string jsonString; base::JSONWriter::Write(res.get(), &jsonString); return jsonString; } else if (name == "isInGuestMode") { // Obtain whether the test is in guest mode or not. return GetGuestModeParam() ? "true" : "false"; } else if (name == "getCwsWidgetContainerMockUrl") { // Obtain whether the test is in guest mode or not. const GURL url = embedded_test_server()->GetURL( "/chromeos/file_manager/cws_container_mock/index.html"); std::string origin = url.GetOrigin().spec(); // Removes trailing a slash. if (*origin.rbegin() == '/') origin.resize(origin.length() - 1); const scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue()); res->SetString("url", url.spec()); res->SetString("origin", origin); std::string jsonString; base::JSONWriter::Write(res.get(), &jsonString); return jsonString; } else if (name == "addEntries") { // Add entries to the specified volume. base::JSONValueConverter<AddEntriesMessage> add_entries_message_converter; AddEntriesMessage message; if (!add_entries_message_converter.Convert(*value, &message)) return "onError"; for (size_t i = 0; i < message.entries.size(); ++i) { switch (message.volume) { case LOCAL_VOLUME: local_volume_->CreateEntry(*message.entries[i]); break; case DRIVE_VOLUME: if (drive_volume_.get()) drive_volume_->CreateEntry(*message.entries[i]); break; case USB_VOLUME: if (usb_volume_) usb_volume_->CreateEntry(*message.entries[i]); break; default: NOTREACHED(); break; } } return "onEntryAdded"; } else if (name == "mountFakeUsb") { usb_volume_.reset(new FakeTestVolume("fake-usb", VOLUME_TYPE_REMOVABLE_DISK_PARTITION, chromeos::DEVICE_TYPE_USB)); usb_volume_->Mount(profile()); return "true"; } else if (name == "mountFakeMtp") { mtp_volume_.reset(new FakeTestVolume("fake-mtp", VOLUME_TYPE_MTP, chromeos::DEVICE_TYPE_UNKNOWN)); if (!mtp_volume_->PrepareTestEntries(profile())) return "false"; mtp_volume_->Mount(profile()); return "true"; } return "unknownMessage"; } drive::DriveIntegrationService* FileManagerBrowserTestBase::CreateDriveIntegrationService(Profile* profile) { drive_volumes_[profile].reset(new DriveTestVolume()); return drive_volumes_[profile]->CreateDriveIntegrationService(profile); } // Parameter of FileManagerBrowserTest. // The second value is the case name of JavaScript. typedef std::tr1::tuple<GuestMode, const char*> TestParameter; // Test fixture class for normal (not multi-profile related) tests. class FileManagerBrowserTest : public FileManagerBrowserTestBase, public ::testing::WithParamInterface<TestParameter> { virtual GuestMode GetGuestModeParam() const OVERRIDE { return std::tr1::get<0>(GetParam()); } virtual const char* GetTestCaseNameParam() const OVERRIDE { return std::tr1::get<1>(GetParam()); } }; IN_PROC_BROWSER_TEST_P(FileManagerBrowserTest, Test) { StartTest(); } // Unlike TEST/TEST_F, which are macros that expand to further macros, // INSTANTIATE_TEST_CASE_P is a macro that expands directly to code that // stringizes the arguments. As a result, macros passed as parameters (such as // prefix or test_case_name) will not be expanded by the preprocessor. To work // around this, indirect the macro for INSTANTIATE_TEST_CASE_P, so that the // pre-processor will expand macros such as MAYBE_test_name before // instantiating the test. #define WRAPPED_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_FileDisplay DISABLED_FileDisplay #else #define MAYBE_FileDisplay FileDisplay #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_FileDisplay, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDownloads"), TestParameter(IN_GUEST_MODE, "fileDisplayDownloads"), TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDrive"), TestParameter(NOT_IN_GUEST_MODE, "fileDisplayMtp"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_OpenZipFiles DISABLED_OpenZipFiles #else #define MAYBE_OpenZipFiles OpenZipFiles #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_OpenZipFiles, FileManagerBrowserTest, ::testing::Values(TestParameter(IN_GUEST_MODE, "zipOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "zipOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "zipOpenDrive"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_OpenVideoFiles DISABLED_OpenVideoFiles #else #define MAYBE_OpenVideoFiles OpenVideoFiles #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_OpenVideoFiles, FileManagerBrowserTest, ::testing::Values(TestParameter(IN_GUEST_MODE, "videoOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "videoOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "videoOpenDrive"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_OpenAudioFiles DISABLED_OpenAudioFiles #else #define MAYBE_OpenAudioFiles OpenAudioFiles #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_OpenAudioFiles, FileManagerBrowserTest, ::testing::Values( TestParameter(IN_GUEST_MODE, "audioOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "audioOpenDownloads"), TestParameter(NOT_IN_GUEST_MODE, "audioOpenDrive"), TestParameter(NOT_IN_GUEST_MODE, "audioAutoAdvanceDrive"), TestParameter(NOT_IN_GUEST_MODE, "audioRepeatSingleFileDrive"), TestParameter(NOT_IN_GUEST_MODE, "audioNoRepeatSingleFileDrive"), TestParameter(NOT_IN_GUEST_MODE, "audioRepeatMultipleFileDrive"), TestParameter(NOT_IN_GUEST_MODE, "audioNoRepeatMultipleFileDrive"))); // Disabled due to frequent failure: http://crbug.com/377636 INSTANTIATE_TEST_CASE_P( DISABLED_CreateNewFolder, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "createNewFolderAfterSelectFile"), TestParameter(IN_GUEST_MODE, "createNewFolderDownloads"), TestParameter(NOT_IN_GUEST_MODE, "createNewFolderDownloads"), TestParameter(NOT_IN_GUEST_MODE, "createNewFolderDrive"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_KeyboardOperations DISABLED_KeyboardOperations #else #define MAYBE_KeyboardOperations KeyboardOperations #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_KeyboardOperations, FileManagerBrowserTest, ::testing::Values(TestParameter(IN_GUEST_MODE, "keyboardDeleteDownloads"), TestParameter(NOT_IN_GUEST_MODE, "keyboardDeleteDownloads"), TestParameter(NOT_IN_GUEST_MODE, "keyboardDeleteDrive"), TestParameter(IN_GUEST_MODE, "keyboardCopyDownloads"), TestParameter(NOT_IN_GUEST_MODE, "keyboardCopyDownloads"), TestParameter(NOT_IN_GUEST_MODE, "keyboardCopyDrive"), TestParameter(IN_GUEST_MODE, "renameFileDownloads"), TestParameter(NOT_IN_GUEST_MODE, "renameFileDownloads"), TestParameter(NOT_IN_GUEST_MODE, "renameFileDrive"))); // Disabled due to frequent timeouts; http://crbug.com/370980. INSTANTIATE_TEST_CASE_P( DISABLED_DriveSpecific, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "openSidebarRecent"), TestParameter(NOT_IN_GUEST_MODE, "openSidebarOffline"), TestParameter(NOT_IN_GUEST_MODE, "openSidebarSharedWithMe"), TestParameter(NOT_IN_GUEST_MODE, "autocomplete"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_Transfer DISABLED_Transfer #else #define MAYBE_Transfer Transfer #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_Transfer, FileManagerBrowserTest, ::testing::Values( TestParameter(NOT_IN_GUEST_MODE, "transferFromDriveToDownloads"), TestParameter(NOT_IN_GUEST_MODE, "transferFromDownloadsToDrive"), TestParameter(NOT_IN_GUEST_MODE, "transferFromSharedToDownloads"), TestParameter(NOT_IN_GUEST_MODE, "transferFromSharedToDrive"), TestParameter(NOT_IN_GUEST_MODE, "transferFromRecentToDownloads"), TestParameter(NOT_IN_GUEST_MODE, "transferFromRecentToDrive"), TestParameter(NOT_IN_GUEST_MODE, "transferFromOfflineToDownloads"), TestParameter(NOT_IN_GUEST_MODE, "transferFromOfflineToDrive"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_RestorePrefs DISABLED_RestorePrefs #else #define MAYBE_RestorePrefs RestorePrefs #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_RestorePrefs, FileManagerBrowserTest, ::testing::Values(TestParameter(IN_GUEST_MODE, "restoreSortColumn"), TestParameter(NOT_IN_GUEST_MODE, "restoreSortColumn"), TestParameter(IN_GUEST_MODE, "restoreCurrentView"), TestParameter(NOT_IN_GUEST_MODE, "restoreCurrentView"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_ShareDialog DISABLED_ShareDialog #else #define MAYBE_ShareDialog ShareDialog #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_ShareDialog, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "shareFile"), TestParameter(NOT_IN_GUEST_MODE, "shareDirectory"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_RestoreGeometry DISABLED_RestoreGeometry #else #define MAYBE_RestoreGeometry RestoreGeometry #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_RestoreGeometry, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "restoreGeometry"), TestParameter(IN_GUEST_MODE, "restoreGeometry"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_Traverse DISABLED_Traverse #else #define MAYBE_Traverse Traverse #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_Traverse, FileManagerBrowserTest, ::testing::Values(TestParameter(IN_GUEST_MODE, "traverseDownloads"), TestParameter(NOT_IN_GUEST_MODE, "traverseDownloads"), TestParameter(NOT_IN_GUEST_MODE, "traverseDrive"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_SuggestAppDialog DISABLED_SuggestAppDialog #else #define MAYBE_SuggestAppDialog SuggestAppDialog #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_SuggestAppDialog, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "suggestAppDialog"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_ExecuteDefaultTaskOnDownloads \ DISABLED_ExecuteDefaultTaskOnDownloads #else #define MAYBE_ExecuteDefaultTaskOnDownloads ExecuteDefaultTaskOnDownloads #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_ExecuteDefaultTaskOnDownloads, FileManagerBrowserTest, ::testing::Values( TestParameter(NOT_IN_GUEST_MODE, "executeDefaultTaskOnDownloads"), TestParameter(IN_GUEST_MODE, "executeDefaultTaskOnDownloads"))); INSTANTIATE_TEST_CASE_P( ExecuteDefaultTaskOnDrive, FileManagerBrowserTest, ::testing::Values( TestParameter(NOT_IN_GUEST_MODE, "executeDefaultTaskOnDrive"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_NavigationList DISABLED_NavigationList #else #define MAYBE_NavigationList NavigationList #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_NavigationList, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "traverseNavigationList"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_FolderShortcuts DISABLED_FolderShortcuts #else #define MAYBE_FolderShortcuts FolderShortcuts #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_FolderShortcuts, FileManagerBrowserTest, ::testing::Values( TestParameter(NOT_IN_GUEST_MODE, "traverseFolderShortcuts"), TestParameter(NOT_IN_GUEST_MODE, "addRemoveFolderShortcuts"))); INSTANTIATE_TEST_CASE_P( TabIndex, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "searchBoxFocus"))); // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_Thumbnails DISABLED_Thumbnails #else #define MAYBE_Thumbnails Thumbnails #endif WRAPPED_INSTANTIATE_TEST_CASE_P( MAYBE_Thumbnails, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "thumbnailsDownloads"), TestParameter(IN_GUEST_MODE, "thumbnailsDownloads"))); // Test/4 has been failing every 3rd or 4th pass on the waterfall for // "Linux ChromiumOS Tests (dbg)". // http://crbug.com/380339 INSTANTIATE_TEST_CASE_P( DISABLED_CopyBetweenWindows, FileManagerBrowserTest, ::testing::Values( TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsLocalToDrive"), TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsLocalToUsb"), TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsUsbToDrive"), TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsDriveToLocal"), TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsDriveToUsb"), TestParameter(NOT_IN_GUEST_MODE, "copyBetweenWindowsUsbToLocal"))); // Structure to describe an account info. struct TestAccountInfo { const char* const email; const char* const hash; const char* const display_name; }; enum { DUMMY_ACCOUNT_INDEX = 0, PRIMARY_ACCOUNT_INDEX = 1, SECONDARY_ACCOUNT_INDEX_START = 2, }; static const TestAccountInfo kTestAccounts[] = { {"__dummy__@invalid.domain", "hashdummy", "Dummy Account"}, {"alice@invalid.domain", "hashalice", "Alice"}, {"bob@invalid.domain", "hashbob", "Bob"}, {"charlie@invalid.domain", "hashcharlie", "Charlie"}, }; // Test fixture class for testing multi-profile features. class MultiProfileFileManagerBrowserTest : public FileManagerBrowserTestBase { protected: // Enables multi-profiles. virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { FileManagerBrowserTestBase::SetUpCommandLine(command_line); // Logs in to a dummy profile (For making MultiProfileWindowManager happy; // browser test creates a default window and the manager tries to assign a // user for it, and we need a profile connected to a user.) command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, kTestAccounts[DUMMY_ACCOUNT_INDEX].email); command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, kTestAccounts[DUMMY_ACCOUNT_INDEX].hash); } // Logs in to the primary profile of this test. virtual void SetUpOnMainThread() OVERRIDE { const TestAccountInfo& info = kTestAccounts[PRIMARY_ACCOUNT_INDEX]; AddUser(info, true); FileManagerBrowserTestBase::SetUpOnMainThread(); } // Loads all users to the current session and sets up necessary fields. // This is used for preparing all accounts in PRE_ test setup, and for testing // actual login behavior. void AddAllUsers() { for (size_t i = 0; i < arraysize(kTestAccounts); ++i) AddUser(kTestAccounts[i], i >= SECONDARY_ACCOUNT_INDEX_START); } // Returns primary profile (if it is already created.) virtual Profile* profile() OVERRIDE { Profile* const profile = chromeos::ProfileHelper::GetProfileByUserIdHash( kTestAccounts[PRIMARY_ACCOUNT_INDEX].hash); return profile ? profile : FileManagerBrowserTestBase::profile(); } // Sets the test case name (used as a function name in test_cases.js to call.) void set_test_case_name(const std::string& name) { test_case_name_ = name; } // Adds a new user for testing to the current session. void AddUser(const TestAccountInfo& info, bool log_in) { chromeos::UserManager* const user_manager = chromeos::UserManager::Get(); if (log_in) user_manager->UserLoggedIn(info.email, info.hash, false); user_manager->SaveUserDisplayName(info.email, base::UTF8ToUTF16(info.display_name)); chromeos::ProfileHelper::GetProfileByUserIdHash(info.hash)->GetPrefs()-> SetString(prefs::kGoogleServicesUsername, info.email); } private: virtual GuestMode GetGuestModeParam() const OVERRIDE { return NOT_IN_GUEST_MODE; } virtual const char* GetTestCaseNameParam() const OVERRIDE { return test_case_name_.c_str(); } virtual std::string OnMessage(const std::string& name, const base::Value* value) OVERRIDE { if (name == "addAllUsers") { AddAllUsers(); return "true"; } else if (name == "getWindowOwnerId") { chrome::MultiUserWindowManager* const window_manager = chrome::MultiUserWindowManager::GetInstance(); apps::AppWindowRegistry* const app_window_registry = apps::AppWindowRegistry::Get(profile()); DCHECK(window_manager); DCHECK(app_window_registry); const apps::AppWindowRegistry::AppWindowList& list = app_window_registry->GetAppWindowsForApp( file_manager::kFileManagerAppId); return list.size() == 1u ? window_manager->GetUserPresentingWindow( list.front()->GetNativeWindow()) : ""; } return FileManagerBrowserTestBase::OnMessage(name, value); } std::string test_case_name_; }; // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_PRE_BasicDownloads DISABLED_PRE_BasicDownloads #define MAYBE_BasicDownloads DISABLED_BasicDownloads #else #define MAYBE_PRE_BasicDownloads PRE_BasicDownloads #define MAYBE_BasicDownloads BasicDownloads #endif IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_PRE_BasicDownloads) { AddAllUsers(); } IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_BasicDownloads) { AddAllUsers(); // Sanity check that normal operations work in multi-profile setting as well. set_test_case_name("keyboardCopyDownloads"); StartTest(); } // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_PRE_BasicDrive DISABLED_PRE_BasicDrive #define MAYBE_BasicDrive DISABLED_BasicDrive #else #define MAYBE_PRE_BasicDrive PRE_BasicDrive #define MAYBE_BasicDrive BasicDrive #endif IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_PRE_BasicDrive) { AddAllUsers(); } IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_BasicDrive) { AddAllUsers(); // Sanity check that normal operations work in multi-profile setting as well. set_test_case_name("keyboardCopyDrive"); StartTest(); } // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_PRE_Badge DISABLED_PRE_Badge #define MAYBE_Badge DISABLED_Badge #else #define MAYBE_PRE_Badge PRE_Badge #define MAYBE_Badge Badge #endif IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_PRE_Badge) { AddAllUsers(); } IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_Badge) { // Test the profile badge to be correctly shown and hidden. set_test_case_name("multiProfileBadge"); StartTest(); } // Slow tests are disabled on debug build. http://crbug.com/327719 #if !defined(NDEBUG) #define MAYBE_PRE_VisitDesktopMenu DISABLED_PRE_VisitDesktopMenu #define MAYBE_VisitDesktopMenu DISABLED_VisitDesktopMenu #else #define MAYBE_PRE_VisitDesktopMenu PRE_VisitDesktopMenu #define MAYBE_VisitDesktopMenu VisitDesktopMenu #endif IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_PRE_VisitDesktopMenu) { AddAllUsers(); } IN_PROC_BROWSER_TEST_F(MultiProfileFileManagerBrowserTest, MAYBE_VisitDesktopMenu) { // Test for the menu item for visiting other profile's desktop. set_test_case_name("multiProfileVisitDesktopMenu"); StartTest(); } template<GuestMode M> class GalleryBrowserTestBase : public FileManagerBrowserTestBase { public: virtual GuestMode GetGuestModeParam() const OVERRIDE { return M; } virtual const char* GetTestCaseNameParam() const OVERRIDE { return test_case_name_.c_str(); } protected: virtual void SetUp() OVERRIDE { AddScript("gallery/test_util.js"); FileManagerBrowserTestBase::SetUp(); } virtual std::string OnMessage(const std::string& name, const base::Value* value) OVERRIDE; virtual const char* GetTestManifestName() const OVERRIDE { return "gallery_test_manifest.json"; } void AddScript(const std::string& name) { scripts_.AppendString( "chrome-extension://ejhcmmdhhpdhhgmifplfmjobgegbibkn/" + name); } void set_test_case_name(const std::string& name) { test_case_name_ = name; } private: base::ListValue scripts_; std::string test_case_name_; }; template<GuestMode M> std::string GalleryBrowserTestBase<M>::OnMessage(const std::string& name, const base::Value* value) { if (name == "getScripts") { std::string jsonString; base::JSONWriter::Write(&scripts_, &jsonString); return jsonString; } return FileManagerBrowserTestBase::OnMessage(name, value); } typedef GalleryBrowserTestBase<NOT_IN_GUEST_MODE> GalleryBrowserTest; typedef GalleryBrowserTestBase<IN_GUEST_MODE> GalleryBrowserTestInGuestMode; IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, OpenSingleImageOnDownloads) { AddScript("gallery/open_image_files.js"); set_test_case_name("openSingleImageOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTestInGuestMode, OpenSingleImageOnDownloads) { AddScript("gallery/open_image_files.js"); set_test_case_name("openSingleImageOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, OpenSingleImageOnDrive) { AddScript("gallery/open_image_files.js"); set_test_case_name("openSingleImageOnDrive"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, OpenMultipleImagesOnDownloads) { AddScript("gallery/open_image_files.js"); set_test_case_name("openMultipleImagesOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTestInGuestMode, OpenMultipleImagesOnDownloads) { AddScript("gallery/test_util.js"); AddScript("gallery/open_image_files.js"); set_test_case_name("openMultipleImagesOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, OpenMultipleImagesOnDrive) { AddScript("gallery/open_image_files.js"); set_test_case_name("openMultipleImagesOnDrive"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, TraverseSlideImagesOnDownloads) { AddScript("gallery/slide_mode.js"); set_test_case_name("traverseSlideImagesOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTestInGuestMode, TraverseSlideImagesOnDownloads) { AddScript("gallery/slide_mode.js"); set_test_case_name("traverseSlideImagesOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, TraverseSlideImagesOnDrive) { AddScript("gallery/slide_mode.js"); set_test_case_name("traverseSlideImagesOnDrive"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, RenameImageOnDownloads) { AddScript("gallery/slide_mode.js"); set_test_case_name("renameImageOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTestInGuestMode, RenameImageOnDownloads) { AddScript("gallery/slide_mode.js"); set_test_case_name("renameImageOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, RenameImageOnDrive) { AddScript("gallery/slide_mode.js"); set_test_case_name("renameImageOnDrive"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, DeleteImageOnDownloads) { AddScript("gallery/slide_mode.js"); set_test_case_name("deleteImageOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTestInGuestMode, DeleteImageOnDownloads) { AddScript("gallery/slide_mode.js"); set_test_case_name("deleteImageOnDownloads"); StartTest(); } IN_PROC_BROWSER_TEST_F(GalleryBrowserTest, DeleteImageOnDrive) { AddScript("gallery/slide_mode.js"); set_test_case_name("deleteImageOnDrive"); StartTest(); } } // namespace } // namespace file_manager