diff options
49 files changed, 1149 insertions, 647 deletions
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h index d458634..9786073 100644 --- a/chrome/browser/chromeos/drive/file_system_interface.h +++ b/chrome/browser/chromeos/drive/file_system_interface.h @@ -34,16 +34,15 @@ struct SearchResultInfo { // Struct to represent a search result for SearchMetadata(). struct MetadataSearchResult { MetadataSearchResult(const base::FilePath& in_path, - const ResourceEntry& in_entry, + bool is_directory, const std::string& in_highlighted_base_name) : path(in_path), - entry(in_entry), - highlighted_base_name(in_highlighted_base_name) { - } + is_directory(is_directory), + highlighted_base_name(in_highlighted_base_name) {} // The two members are used to create FileEntry object. base::FilePath path; - ResourceEntry entry; + bool is_directory; // The base name to be displayed in the UI. The parts matched the search // query are highlighted with <b> tag. Meta characters are escaped like < diff --git a/chrome/browser/chromeos/drive/search_metadata.cc b/chrome/browser/chromeos/drive/search_metadata.cc index 6b1d950..adbcd29 100644 --- a/chrome/browser/chromeos/drive/search_metadata.cc +++ b/chrome/browser/chromeos/drive/search_metadata.cc @@ -272,8 +272,9 @@ FileError SearchMetadataOnBlockingPool(ResourceMetadata* resource_metadata, base::FilePath path = resource_metadata->GetFilePath(candidate.local_id); if (path.empty()) return FILE_ERROR_FAILED; + bool is_directory = candidate.entry.file_info().is_directory(); results->push_back(MetadataSearchResult( - path, candidate.entry, candidate.highlighted_base_name)); + path, is_directory, candidate.highlighted_base_name)); } // Reverse the order here because |result_candidates| puts the most diff --git a/chrome/browser/chromeos/drive/search_metadata_unittest.cc b/chrome/browser/chromeos/drive/search_metadata_unittest.cc index 22e2895..292e4b2 100644 --- a/chrome/browser/chromeos/drive/search_metadata_unittest.cc +++ b/chrome/browser/chromeos/drive/search_metadata_unittest.cc @@ -229,11 +229,8 @@ TEST_F(SearchMetadataTest, SearchMetadata_RegularFiles) { ASSERT_TRUE(result); ASSERT_EQ(2U, result->size()); - // The results should be sorted by the last accessed time in descending order. - EXPECT_EQ(6, result->at(0).entry.file_info().last_accessed()); - EXPECT_EQ(2, result->at(1).entry.file_info().last_accessed()); - - // All base names should contain "File". + // All base names should contain "File". The results should be sorted by the + // last accessed time in descending order. EXPECT_EQ("drive/root/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt", result->at(0).path.AsUTF8Unsafe()); EXPECT_EQ("drive/root/Directory 1/SubDirectory File 1.txt", diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc index ab2c043..dc3f9e5 100644 --- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc +++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc @@ -48,6 +48,8 @@ using chromeos::NetworkHandler; using content::BrowserThread; using drive::DriveIntegrationService; using drive::DriveIntegrationServiceFactory; +using file_manager::util::EntryDefinition; +using file_manager::util::FileDefinition; namespace file_browser_private = extensions::api::file_browser_private; @@ -679,28 +681,48 @@ void EventRouter::DispatchDirectoryChangeEvent( for (size_t i = 0; i < extension_ids.size(); ++i) { const std::string& extension_id = extension_ids[i]; - const GURL target_origin_url( - extensions::Extension::GetBaseURLFromExtensionId(extension_id)); - // This will be replaced with a real Entry in custom bindings. - const fileapi::FileSystemInfo info = - fileapi::GetFileSystemInfoForChromeOS(target_origin_url.GetOrigin()); - - file_browser_private::FileWatchEvent event; - event.event_type = got_error ? - file_browser_private::FILE_WATCH_EVENT_TYPE_ERROR : - file_browser_private::FILE_WATCH_EVENT_TYPE_CHANGED; - event.entry.additional_properties.SetString("fileSystemName", info.name); - event.entry.additional_properties.SetString("fileSystemRoot", - info.root_url.spec()); - event.entry.additional_properties.SetString("fileFullPath", - "/" + virtual_path.value()); - event.entry.additional_properties.SetBoolean("fileIsDirectory", true); - - BroadcastEvent( + + FileDefinition file_definition; + file_definition.virtual_path = virtual_path; + file_definition.is_directory = true; + + file_manager::util::ConvertFileDefinitionToEntryDefinition( profile_, - file_browser_private::OnDirectoryChanged::kEventName, - file_browser_private::OnDirectoryChanged::Create(event)); + extension_id, + file_definition, + base::Bind( + &EventRouter::DispatchDirectoryChangeEventWithEntryDefinition, + weak_factory_.GetWeakPtr(), + got_error)); + } +} + +void EventRouter::DispatchDirectoryChangeEventWithEntryDefinition( + bool watcher_error, + const EntryDefinition& entry_definition) { + if (entry_definition.error != base::File::FILE_OK) { + DVLOG(1) << "Unable to dispatch event because resolving the entry " + << "definition failed."; + return; } + + file_browser_private::FileWatchEvent event; + event.event_type = watcher_error + ? file_browser_private::FILE_WATCH_EVENT_TYPE_ERROR + : file_browser_private::FILE_WATCH_EVENT_TYPE_CHANGED; + + event.entry.additional_properties.SetString( + "fileSystemName", entry_definition.file_system_name); + event.entry.additional_properties.SetString( + "fileSystemRoot", entry_definition.file_system_root_url); + event.entry.additional_properties.SetString( + "fileFullPath", "/" + entry_definition.full_path.value()); + event.entry.additional_properties.SetBoolean("fileIsDirectory", + entry_definition.is_directory); + + BroadcastEvent(profile_, + file_browser_private::OnDirectoryChanged::kEventName, + file_browser_private::OnDirectoryChanged::Create(event)); } void EventRouter::ShowRemovableDeviceInFileManager( diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h index 0813807..8be34a1 100644 --- a/chrome/browser/chromeos/extensions/file_manager/event_router.h +++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h @@ -17,6 +17,7 @@ #include "chrome/browser/chromeos/drive/job_list.h" #include "chrome/browser/chromeos/drive/sync_client.h" #include "chrome/browser/chromeos/file_manager/file_watcher.h" +#include "chrome/browser/chromeos/file_manager/fileapi_util.h" #include "chrome/browser/chromeos/file_manager/volume_manager_observer.h" #include "chrome/browser/drive/drive_service_interface.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" @@ -30,6 +31,8 @@ class PrefChangeRegistrar; class Profile; +using file_manager::util::EntryDefinition; + namespace base { class ListValue; } @@ -150,6 +153,12 @@ class EventRouter bool error, const std::vector<std::string>& extension_ids); + // Sends directory change event, after converting the file definition to entry + // definition. + void DispatchDirectoryChangeEventWithEntryDefinition( + bool watcher_error, + const EntryDefinition& entry_definition); + // If needed, opens a file manager window for the removable device mounted at // |mount_path|. Disk.mount_path() is empty, since it is being filled out // after calling notifying observers by DiskMountManager. diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc index 6ddb5c1..b36285e 100644 --- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc +++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.cc @@ -54,6 +54,8 @@ using content::BrowserThread; using extensions::api::file_browser_handler_internal::FileEntryInfo; using file_manager::FileSelector; using file_manager::FileSelectorFactory; +using file_manager::util::EntryDefinition; +using file_manager::util::FileDefinition; namespace SelectFile = extensions::api::file_browser_handler_internal::SelectFile; @@ -309,54 +311,71 @@ void FileBrowserHandlerInternalSelectFileFunction::OnFilePathSelected( DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!success) { - Respond(false); + Respond(EntryDefinition(), false); return; } - full_path_ = full_path; - - fileapi::FileSystemInfo info = - fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin()); - file_system_name_ = info.name; - file_system_root_ = info.root_url; - - GrantPermissions(); + fileapi::ExternalFileSystemBackend* external_backend = + file_manager::util::GetFileSystemContextForRenderViewHost( + GetProfile(), render_view_host())->external_backend(); + DCHECK(external_backend); - Respond(true); + FileDefinition file_definition; + file_definition.is_directory = false; + + external_backend->GetVirtualPath(full_path, &file_definition.virtual_path); + DCHECK(!file_definition.virtual_path.empty()); + + file_manager::util::ConvertFileDefinitionToEntryDefinition( + GetProfile(), + extension_id(), + file_definition, + base::Bind( + &FileBrowserHandlerInternalSelectFileFunction::GrantPermissions, + this, + full_path, + file_definition)); } -void FileBrowserHandlerInternalSelectFileFunction::GrantPermissions() { +void FileBrowserHandlerInternalSelectFileFunction::GrantPermissions( + const base::FilePath& full_path, + const FileDefinition& file_definition, + const EntryDefinition& entry_definition) { fileapi::ExternalFileSystemBackend* external_backend = file_manager::util::GetFileSystemContextForRenderViewHost( GetProfile(), render_view_host())->external_backend(); DCHECK(external_backend); - external_backend->GetVirtualPath(full_path_, &virtual_path_); - DCHECK(!virtual_path_.empty()); - // Grant access to this particular file to target extension. This will // ensure that the target extension can access only this FS entry and // prevent from traversing FS hierarchy upward. - external_backend->GrantFileAccessToExtension(extension_id(), virtual_path_); + external_backend->GrantFileAccessToExtension(extension_id(), + file_definition.virtual_path); // Grant access to the selected file to target extensions render view process. content::ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFile( - render_view_host()->GetProcess()->GetID(), full_path_); + render_view_host()->GetProcess()->GetID(), full_path); + + Respond(entry_definition, true); } -void FileBrowserHandlerInternalSelectFileFunction::Respond(bool success) { +void FileBrowserHandlerInternalSelectFileFunction::Respond( + const EntryDefinition& entry_definition, + bool success) { scoped_ptr<SelectFile::Results::Result> result( new SelectFile::Results::Result()); result->success = success; // If the file was selected, add 'entry' object which will be later used to // create a FileEntry instance for the selected file. - if (success) { + if (success && entry_definition.error == base::File::FILE_OK) { result->entry.reset(new FileEntryInfo()); - result->entry->file_system_name = file_system_name_; - result->entry->file_system_root = file_system_root_.spec(); - result->entry->file_full_path = "/" + virtual_path_.AsUTF8Unsafe(); - result->entry->file_is_directory = false; + // TODO(mtomasz): Make the response fields consistent with other files. + result->entry->file_system_name = entry_definition.file_system_name; + result->entry->file_system_root = entry_definition.file_system_root_url; + result->entry->file_full_path = + "/" + entry_definition.full_path.AsUTF8Unsafe(); + result->entry->file_is_directory = entry_definition.is_directory; } results_ = SelectFile::Results::Create(*result); diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h index 6c67de0..5b78194 100644 --- a/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h +++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handler_api.h @@ -23,6 +23,11 @@ class FileBrowserHandlerInternalSelectFileFunction; namespace file_manager { +namespace util { +struct EntryDefinition; +struct FileDefinition; +} + // Interface that is used by FileBrowserHandlerInternalSelectFileFunction to // select the file path that should be reported back to the extension function // caller. Nobody will take the ownership of the interface implementation, so @@ -109,24 +114,23 @@ class FileBrowserHandlerInternalSelectFileFunction private: // Grants file access permissions for the created file to the caller. - // Inside this method, |virtual_path_| value is set. - void GrantPermissions(); + // Inside this method, + void GrantPermissions( + const base::FilePath& full_path, + const file_manager::util::FileDefinition& file_definition, + const file_manager::util::EntryDefinition& entry_definition); // Creates dictionary value that will be used to as the extension function's // callback argument and ends extension function execution by calling // |SendResponse(true)|. // The |results_| value will be set to dictionary containing two properties: // * boolean 'success', which will be equal to |success|. - // * object 'entry', which will be set only when |success| if true and - // will contain information needed to create a FileEntry object for the - // selected file. It contains following properties: - // * 'file_system_name' set to |file_system_name_| - // * 'file_system_root' set to |file_system_root_| - // * 'file_full_path' set to |virtual_path_| (with leading '/') - // * 'file_is_directory' set to |false|. - // |file_system_name_|, |file_system_root_| and |virtual_path_| are ignored - // if |success| if false. - void Respond(bool success); + // * object 'entry', which will be set only when |success| is true, and the + // conversion to |entry_definition| was successful. In such case, it will + // contain information needed to create a FileEntry object for the selected + // file. + void Respond(const file_manager::util::EntryDefinition& entry_definition, + bool success); // Factory used to create FileSelector to be used for prompting user to select // file. @@ -134,15 +138,6 @@ class FileBrowserHandlerInternalSelectFileFunction // Whether user gesture check is disabled. This should be true only in tests. bool user_gesture_check_enabled_; - // Full file system path of the selected file. - base::FilePath full_path_; - // Selected file's virtual path in extension function caller's file system. - base::FilePath virtual_path_; - // Extension function caller's file system name. - std::string file_system_name_; - // Extension function caller's file system root URL. - GURL file_system_root_; - // List of permissions and paths that have to be granted for the selected // files. std::vector<std::pair<base::FilePath, int> > permissions_to_grant_; diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc index f8d18b0..cdc26ef 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc @@ -20,6 +20,13 @@ using content::BrowserThread; +using file_manager::util::EntryDefinition; +using file_manager::util::EntryDefinitionCallback; +using file_manager::util::EntryDefinitionList; +using file_manager::util::EntryDefinitionListCallback; +using file_manager::util::FileDefinition; +using file_manager::util::FileDefinitionList; + namespace extensions { namespace { @@ -69,6 +76,31 @@ void FillDriveEntryPropertiesValue( new std::string(file_specific_info.content_mime_type())); } +// Creates entry definition list for (metadata) search result info list. +template <class T> +void ConvertSearchResultInfoListToEntryDefinitionList( + Profile* profile, + const std::string& extension_id, + const std::vector<T>& search_result_info_list, + const EntryDefinitionListCallback& callback) { + FileDefinitionList file_definition_list; + + for (size_t i = 0; i < search_result_info_list.size(); ++i) { + FileDefinition file_definition; + file_definition.virtual_path = + file_manager::util::ConvertDrivePathToRelativeFileSystemPath( + profile, extension_id, search_result_info_list.at(i).path); + file_definition.is_directory = search_result_info_list.at(i).is_directory; + file_definition_list.push_back(file_definition); + } + + file_manager::util::ConvertFileDefinitionListToEntryDefinitionList( + profile, + extension_id, + file_definition_list, // Safe, since copied internally. + callback); +} + } // namespace FileBrowserPrivateGetDriveEntryPropertiesFunction:: @@ -382,28 +414,43 @@ bool FileBrowserPrivateSearchDriveFunction::RunImpl() { void FileBrowserPrivateSearchDriveFunction::OnSearch( drive::FileError error, const GURL& next_link, - scoped_ptr<std::vector<drive::SearchResultInfo> > results) { + scoped_ptr<SearchResultInfoList> results) { if (error != drive::FILE_ERROR_OK) { SendResponse(false); return; } + // Outlives the following conversion, since the pointer is bound to the + // callback. DCHECK(results.get()); + const SearchResultInfoList& results_ref = *results.get(); + + ConvertSearchResultInfoListToEntryDefinitionList( + GetProfile(), + extension_->id(), + results_ref, + base::Bind(&FileBrowserPrivateSearchDriveFunction::OnEntryDefinitionList, + this, + next_link, + base::Passed(&results))); +} +void FileBrowserPrivateSearchDriveFunction::OnEntryDefinitionList( + const GURL& next_link, + scoped_ptr<SearchResultInfoList> search_result_info_list, + scoped_ptr<EntryDefinitionList> entry_definition_list) { + DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size()); base::ListValue* entries = new base::ListValue(); // Convert Drive files to something File API stack can understand. - fileapi::FileSystemInfo info = - fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin()); - for (size_t i = 0; i < results->size(); ++i) { + for (EntryDefinitionList::const_iterator it = entry_definition_list->begin(); + it != entry_definition_list->end(); + ++it) { base::DictionaryValue* entry = new base::DictionaryValue(); - entry->SetString("fileSystemName", info.name); - entry->SetString("fileSystemRoot", info.root_url.spec()); - entry->SetString("fileFullPath", - "/" + file_manager::util::ConvertDrivePathToRelativeFileSystemPath( - GetProfile(), extension_->id(), - results->at(i).path).AsUTF8Unsafe()); - entry->SetBoolean("fileIsDirectory", results->at(i).is_directory); + entry->SetString("fileSystemName", it->file_system_name); + entry->SetString("fileSystemRoot", it->file_system_root_url); + entry->SetString("fileFullPath", "/" + it->full_path.AsUTF8Unsafe()); + entry->SetBoolean("fileIsDirectory", it->is_directory); entries->Append(entry); } @@ -475,33 +522,50 @@ void FileBrowserPrivateSearchDriveMetadataFunction::OnSearchMetadata( return; } + // Outlives the following conversion, since the pointer is bound to the + // callback. DCHECK(results.get()); + const drive::MetadataSearchResultVector& results_ref = *results.get(); + + ConvertSearchResultInfoListToEntryDefinitionList( + GetProfile(), + extension_->id(), + results_ref, + base::Bind( + &FileBrowserPrivateSearchDriveMetadataFunction::OnEntryDefinitionList, + this, + base::Passed(&results))); +} +void FileBrowserPrivateSearchDriveMetadataFunction::OnEntryDefinitionList( + scoped_ptr<drive::MetadataSearchResultVector> search_result_info_list, + scoped_ptr<EntryDefinitionList> entry_definition_list) { + DCHECK_EQ(search_result_info_list->size(), entry_definition_list->size()); base::ListValue* results_list = new base::ListValue(); // Convert Drive files to something File API stack can understand. See // file_browser_handler_custom_bindings.cc and // file_browser_private_custom_bindings.js for how this is magically // converted to a FileEntry. - fileapi::FileSystemInfo info = - fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin()); - for (size_t i = 0; i < results->size(); ++i) { + for (size_t i = 0; i < entry_definition_list->size(); ++i) { base::DictionaryValue* result_dict = new base::DictionaryValue(); // FileEntry fields. base::DictionaryValue* entry = new base::DictionaryValue(); - entry->SetString("fileSystemName", info.name); - entry->SetString("fileSystemRoot", info.root_url.spec()); - entry->SetString("fileFullPath", - "/" + file_manager::util::ConvertDrivePathToRelativeFileSystemPath( - GetProfile(), extension_->id(), - results->at(i).path).AsUTF8Unsafe()); + entry->SetString( + "fileSystemName", entry_definition_list->at(i).file_system_name); + entry->SetString( + "fileSystemRoot", entry_definition_list->at(i).file_system_root_url); + entry->SetString( + "fileFullPath", + "/" + entry_definition_list->at(i).full_path.AsUTF8Unsafe()); entry->SetBoolean("fileIsDirectory", - results->at(i).entry.file_info().is_directory()); + entry_definition_list->at(i).is_directory); result_dict->Set("entry", entry); - result_dict->SetString("highlightedBaseName", - results->at(i).highlighted_base_name); + result_dict->SetString( + "highlightedBaseName", + search_result_info_list->at(i).highlighted_base_name); results_list->Append(result_dict); } diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h index 5a68f27..158bd3e 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h @@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/drive/file_errors.h" #include "chrome/browser/chromeos/drive/file_system_interface.h" #include "chrome/browser/chromeos/extensions/file_manager/private_api_base.h" +#include "chrome/browser/chromeos/file_manager/fileapi_util.h" namespace drive { class FileCacheEntry; @@ -18,11 +19,12 @@ struct SearchResultInfo; } namespace extensions { + namespace api { -namespace file_browser_private{ +namespace file_browser_private { struct DriveEntryProperties; -} -} +} // namespace file_browser_private +} // namespace api // Retrieves property information for an entry and returns it as a dictionary. // On error, returns a dictionary with the key "error" set to the error number @@ -127,6 +129,8 @@ class FileBrowserPrivateCancelFileTransfersFunction class FileBrowserPrivateSearchDriveFunction : public LoggedAsyncExtensionFunction { public: + typedef std::vector<drive::SearchResultInfo> SearchResultInfoList; + DECLARE_EXTENSION_FUNCTION("fileBrowserPrivate.searchDrive", FILEBROWSERPRIVATE_SEARCHDRIVE) @@ -140,6 +144,14 @@ class FileBrowserPrivateSearchDriveFunction void OnSearch(drive::FileError error, const GURL& next_link, scoped_ptr<std::vector<drive::SearchResultInfo> > result_paths); + + // Called when |result_paths| in OnSearch() are converted to a list of + // entry definitions. + void OnEntryDefinitionList( + const GURL& next_link, + scoped_ptr<SearchResultInfoList> search_result_info_list, + scoped_ptr<file_manager::util::EntryDefinitionList> + entry_definition_list); }; // Similar to FileBrowserPrivateSearchDriveFunction but this one is used for @@ -159,6 +171,13 @@ class FileBrowserPrivateSearchDriveMetadataFunction // Callback for SearchMetadata(); void OnSearchMetadata(drive::FileError error, scoped_ptr<drive::MetadataSearchResultVector> results); + + // Called when |results| in OnSearchMetadata() are converted to a list of + // entry definitions. + void OnEntryDefinitionList( + scoped_ptr<drive::MetadataSearchResultVector> search_result_info_list, + scoped_ptr<file_manager::util::EntryDefinitionList> + entry_definition_list); }; // Implements the chrome.fileBrowserPrivate.getDriveConnectionState method. diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc index 3464df3..0edaaaf 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc @@ -40,6 +40,8 @@ using chromeos::disks::DiskMountManager; using content::BrowserThread; using content::ChildProcessSecurityPolicy; +using file_manager::util::EntryDefinition; +using file_manager::util::FileDefinition; using fileapi::FileSystemURL; namespace extensions { @@ -262,14 +264,23 @@ bool FileBrowserPrivateRequestFileSystemFunction::RunImpl() { const scoped_ptr<Params> params(Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); - // TODO(satorux): Handle the file system ID. crbug.com/322305. - DCHECK_EQ("compatible", params->volume_id); - if (!dispatcher() || !render_view_host() || !render_view_host()->GetProcess()) return false; set_log_on_completion(true); + using file_manager::VolumeManager; + using file_manager::VolumeInfo; + VolumeManager* volume_manager = VolumeManager::Get(GetProfile()); + if (!volume_manager) + return false; + + VolumeInfo volume_info; + if (!volume_manager->FindVolumeInfoById(params->volume_id, &volume_info)) { + DidFail(base::File::FILE_ERROR_NOT_FOUND); + return false; + } + scoped_refptr<fileapi::FileSystemContext> file_system_context = file_manager::util::GetFileSystemContextForRenderViewHost( GetProfile(), render_view_host()); @@ -284,16 +295,42 @@ bool FileBrowserPrivateRequestFileSystemFunction::RunImpl() { return false; } - fileapi::FileSystemInfo info = - fileapi::GetFileSystemInfoForChromeOS(source_url_.GetOrigin()); + FileDefinition file_definition; + if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath( + GetProfile(), + extension_id(), + volume_info.mount_path, + &file_definition.virtual_path)) { + DidFail(base::File::FILE_ERROR_INVALID_OPERATION); + return false; + } + file_definition.is_directory = true; + + file_manager::util::ConvertFileDefinitionToEntryDefinition( + GetProfile(), + extension_id(), + file_definition, + base::Bind( + &FileBrowserPrivateRequestFileSystemFunction::OnEntryDefinition, + this)); + return true; +} + +void FileBrowserPrivateRequestFileSystemFunction::OnEntryDefinition( + const EntryDefinition& entry_definition) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (entry_definition.error != base::File::FILE_OK) { + DidFail(entry_definition.error); + return; + } base::DictionaryValue* dict = new base::DictionaryValue(); SetResult(dict); - dict->SetString("name", info.name); - dict->SetString("root_url", info.root_url.spec()); + dict->SetString("name", entry_definition.file_system_name); + dict->SetString("root_url", entry_definition.file_system_root_url); dict->SetInteger("error", drive::FILE_ERROR_OK); SendResponse(true); - return true; } void FileWatchFunctionBase::Respond(bool success) { diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h index 57f00ea..b3d4280 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h @@ -23,6 +23,12 @@ namespace fileapi { class FileSystemContext; } +namespace file_manager { +namespace util { +struct EntryDefinition; +} // namespace util +} // namespace file_manager + namespace extensions { // Implements the chrome.fileBrowserPrivate.requestFileSystem method. @@ -54,6 +60,10 @@ class FileBrowserPrivateRequestFileSystemFunction int child_id, Profile* profile, scoped_refptr<const extensions::Extension> extension); + + // Called when the entry definition is computed. + void OnEntryDefinition( + const file_manager::util::EntryDefinition& entry_definition); }; // Base class for FileBrowserPrivateAddFileWatchFunction and diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc index f24fdfa..c58fcd1 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc @@ -168,6 +168,10 @@ void VolumeInfoToVolumeMetadata( volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_CLOUD_DEVICE; break; + case VOLUME_TYPE_TESTING: + volume_metadata->volume_type = + file_browser_private::VOLUME_TYPE_TESTING; + break; } // Fill device_type iff the volume is removable partition. diff --git a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc index 14e974a..441aac2 100644 --- a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc +++ b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc @@ -9,6 +9,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/drive/drive_integration_service.h" #include "chrome/browser/chromeos/file_manager/drive_test_util.h" +#include "chrome/browser/chromeos/file_manager/volume_manager.h" #include "chrome/browser/drive/fake_drive_service.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/profiles/profile.h" @@ -82,12 +83,14 @@ const char kTestRootFeed[] = // Sets up the initial file system state for native local and restricted native // local file systems. The hierarchy is the same as for the drive file system. -bool InitializeLocalFileSystem(base::ScopedTempDir* tmp_dir, +// The directory is created at unique_temp_dir/|mount_point_name| path. +bool InitializeLocalFileSystem(std::string mount_point_name, + base::ScopedTempDir* tmp_dir, base::FilePath* mount_point_dir) { if (!tmp_dir->CreateUniqueTempDir()) return false; - *mount_point_dir = tmp_dir->path().AppendASCII("mount"); + *mount_point_dir = tmp_dir->path().AppendASCII(mount_point_name); // Create the mount point. if (!base::CreateDirectory(*mount_point_dir)) return false; @@ -241,7 +244,8 @@ class LocalFileSystemExtensionApiTest : public FileSystemExtensionApiTestBase { // FileSystemExtensionApiTestBase OVERRIDE. virtual void InitTestFileSystem() OVERRIDE { - ASSERT_TRUE(InitializeLocalFileSystem(&tmp_dir_, &mount_point_dir_)) + ASSERT_TRUE(InitializeLocalFileSystem( + kLocalMountPointName, &tmp_dir_, &mount_point_dir_)) << "Failed to initialize file system."; } @@ -252,6 +256,8 @@ class LocalFileSystemExtensionApiTest : public FileSystemExtensionApiTestBase { fileapi::kFileSystemTypeNativeLocal, fileapi::FileSystemMountOption(), mount_point_dir_)); + VolumeManager::Get(browser()->profile())->AddVolumeInfoForTesting( + mount_point_dir_); } private: @@ -268,7 +274,8 @@ class RestrictedFileSystemExtensionApiTest // FileSystemExtensionApiTestBase OVERRIDE. virtual void InitTestFileSystem() OVERRIDE { - ASSERT_TRUE(InitializeLocalFileSystem(&tmp_dir_, &mount_point_dir_)) + ASSERT_TRUE(InitializeLocalFileSystem( + kRestrictedMountPointName, &tmp_dir_, &mount_point_dir_)) << "Failed to initialize file system."; } @@ -279,6 +286,8 @@ class RestrictedFileSystemExtensionApiTest fileapi::kFileSystemTypeRestrictedNativeLocal, fileapi::FileSystemMountOption(), mount_point_dir_)); + VolumeManager::Get(browser()->profile())->AddVolumeInfoForTesting( + mount_point_dir_); } private: diff --git a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc index 2cb3ecb..7270550 100644 --- a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc +++ b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc @@ -42,6 +42,10 @@ using content::SiteInstance; using content::WebContents; using extensions::Extension; using fileapi::FileSystemURL; +using file_manager::util::EntryDefinition; +using file_manager::util::EntryDefinitionList; +using file_manager::util::FileDefinition; +using file_manager::util::FileDefinitionList; namespace file_manager { namespace file_browser_handlers { @@ -174,36 +178,28 @@ class FileBrowserHandlerExecutor { // This object is responsible to delete itself. virtual ~FileBrowserHandlerExecutor(); - struct FileDefinition { - FileDefinition(); - ~FileDefinition(); - - base::FilePath virtual_path; - base::FilePath absolute_path; - bool is_directory; - }; - - typedef std::vector<FileDefinition> FileDefinitionList; - // Checks legitimacy of file url and grants file RO access permissions from // handler (target) extension and its renderer process. - static FileDefinitionList SetupFileAccessPermissions( + static scoped_ptr<FileDefinitionList> SetupFileAccessPermissions( scoped_refptr<fileapi::FileSystemContext> file_system_context_handler, const scoped_refptr<const Extension>& handler_extension, const std::vector<FileSystemURL>& file_urls); void ExecuteDoneOnUIThread(bool success); - void ExecuteFileActionsOnUIThread(const FileDefinitionList& file_list); - void SetupPermissionsAndDispatchEvent(const std::string& file_system_name, - const GURL& file_system_root, - const FileDefinitionList& file_list, - int handler_pid_in, - extensions::ExtensionHost* host); + void ExecuteAfterSetupFileAccess(scoped_ptr<FileDefinitionList> file_list); + void ExecuteFileActionsOnUIThread( + scoped_ptr<FileDefinitionList> file_definition_list, + scoped_ptr<EntryDefinitionList> entry_definition_list); + void SetupPermissionsAndDispatchEvent( + scoped_ptr<FileDefinitionList> file_definition_list, + scoped_ptr<EntryDefinitionList> entry_definition_list, + int handler_pid_in, + extensions::ExtensionHost* host); // Registers file permissions from |handler_host_permissions_| with // ChildProcessSecurityPolicy for process with id |handler_pid|. void SetupHandlerHostFileAccessPermissions( - const FileDefinitionList& file_list, + FileDefinitionList* file_definition_list, const Extension* extension, int handler_pid); @@ -216,15 +212,8 @@ class FileBrowserHandlerExecutor { DISALLOW_COPY_AND_ASSIGN(FileBrowserHandlerExecutor); }; -FileBrowserHandlerExecutor::FileDefinition::FileDefinition() - : is_directory(false) { -} - -FileBrowserHandlerExecutor::FileDefinition::~FileDefinition() { -} - // static -FileBrowserHandlerExecutor::FileDefinitionList +scoped_ptr<FileDefinitionList> FileBrowserHandlerExecutor::SetupFileAccessPermissions( scoped_refptr<fileapi::FileSystemContext> file_system_context_handler, const scoped_refptr<const Extension>& handler_extension, @@ -235,7 +224,7 @@ FileBrowserHandlerExecutor::SetupFileAccessPermissions( fileapi::ExternalFileSystemBackend* backend = file_system_context_handler->external_backend(); - FileDefinitionList file_list; + scoped_ptr<FileDefinitionList> file_definition_list(new FileDefinitionList); for (size_t i = 0; i < file_urls.size(); ++i) { const FileSystemURL& url = file_urls[i]; @@ -264,13 +253,14 @@ FileBrowserHandlerExecutor::SetupFileAccessPermissions( backend->GrantFileAccessToExtension(handler_extension->id(), virtual_path); // Output values. - FileDefinition file; - file.virtual_path = virtual_path; - file.is_directory = file_info.is_directory; - file.absolute_path = local_path; - file_list.push_back(file); + FileDefinition file_definition; + file_definition.virtual_path = virtual_path; + file_definition.is_directory = file_info.is_directory; + file_definition.absolute_path = local_path; + file_definition_list->push_back(file_definition); } - return file_list; + + return file_definition_list.Pass(); } FileBrowserHandlerExecutor::FileBrowserHandlerExecutor( @@ -304,10 +294,24 @@ void FileBrowserHandlerExecutor::Execute( file_system_context, extension_, file_urls), - base::Bind(&FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread, + base::Bind(&FileBrowserHandlerExecutor::ExecuteAfterSetupFileAccess, weak_ptr_factory_.GetWeakPtr())); } +void FileBrowserHandlerExecutor::ExecuteAfterSetupFileAccess( + scoped_ptr<FileDefinitionList> file_definition_list) { + // Outlives the conversion process, since bound to the callback. + const FileDefinitionList& file_definition_list_ref = + *file_definition_list.get(); + file_manager::util::ConvertFileDefinitionListToEntryDefinitionList( + profile_, + extension_->id(), + file_definition_list_ref, + base::Bind(&FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(&file_definition_list))); +} + void FileBrowserHandlerExecutor::ExecuteDoneOnUIThread(bool success) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!done_.is_null()) @@ -319,10 +323,11 @@ void FileBrowserHandlerExecutor::ExecuteDoneOnUIThread(bool success) { } void FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread( - const FileDefinitionList& file_list) { + scoped_ptr<FileDefinitionList> file_definition_list, + scoped_ptr<EntryDefinitionList> entry_definition_list) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (file_list.empty()) { + if (file_definition_list->empty() || entry_definition_list->empty()) { ExecuteDoneOnUIThread(false); return; } @@ -334,13 +339,11 @@ void FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread( return; } - fileapi::FileSystemInfo info = - fileapi::GetFileSystemInfoForChromeOS( - Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin()); - if (handler_pid > 0) { - SetupPermissionsAndDispatchEvent(info.name, info.root_url, - file_list, handler_pid, NULL); + SetupPermissionsAndDispatchEvent(file_definition_list.Pass(), + entry_definition_list.Pass(), + handler_pid, + NULL); } else { // We have to wake the handler background page before we proceed. extensions::LazyBackgroundTaskQueue* queue = @@ -351,18 +354,20 @@ void FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread( return; } queue->AddPendingTask( - profile_, extension_->id(), + profile_, + extension_->id(), base::Bind( &FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent, weak_ptr_factory_.GetWeakPtr(), - info.name, info.root_url, file_list, handler_pid)); + base::Passed(file_definition_list.Pass()), + base::Passed(entry_definition_list.Pass()), + handler_pid)); } } void FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent( - const std::string& file_system_name, - const GURL& file_system_root, - const FileDefinitionList& file_list, + scoped_ptr<FileDefinitionList> file_definition_list, + scoped_ptr<EntryDefinitionList> entry_definition_list, int handler_pid_in, extensions::ExtensionHost* host) { int handler_pid = host ? host->render_process_host()->GetID() : @@ -381,7 +386,7 @@ void FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent( } SetupHandlerHostFileAccessPermissions( - file_list, extension_.get(), handler_pid); + file_definition_list.get(), extension_.get(), handler_pid); scoped_ptr<base::ListValue> event_args(new base::ListValue()); event_args->Append(new base::StringValue(action_id_)); @@ -391,15 +396,17 @@ void FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent( // dispatchEvent() method from event_binding.js. base::ListValue* file_entries = new base::ListValue(); details->Set("entries", file_entries); - for (FileDefinitionList::const_iterator iter = file_list.begin(); - iter != file_list.end(); + + for (EntryDefinitionList::const_iterator iter = + entry_definition_list->begin(); + iter != entry_definition_list->end(); ++iter) { base::DictionaryValue* file_def = new base::DictionaryValue(); file_entries->Append(file_def); - file_def->SetString("fileSystemName", file_system_name); - file_def->SetString("fileSystemRoot", file_system_root.spec()); + file_def->SetString("fileSystemName", iter->file_system_name); + file_def->SetString("fileSystemRoot", iter->file_system_root_url); file_def->SetString("fileFullPath", - "/" + iter->virtual_path.AsUTF8Unsafe()); + "/" + iter->full_path.AsUTF8Unsafe()); file_def->SetBoolean("fileIsDirectory", iter->is_directory); } @@ -412,13 +419,13 @@ void FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent( } void FileBrowserHandlerExecutor::SetupHandlerHostFileAccessPermissions( - const FileDefinitionList& file_list, + FileDefinitionList* file_definition_list, const Extension* extension, int handler_pid) { const FileBrowserHandler* action = FindFileBrowserHandlerForActionId( extension_, action_id_); - for (FileDefinitionList::const_iterator iter = file_list.begin(); - iter != file_list.end(); + for (FileDefinitionList::const_iterator iter = file_definition_list->begin(); + iter != file_definition_list->end(); ++iter) { if (!action) continue; diff --git a/chrome/browser/chromeos/file_manager/fileapi_util.cc b/chrome/browser/chromeos/file_manager/fileapi_util.cc index 2cf6044..e946650 100644 --- a/chrome/browser/chromeos/file_manager/fileapi_util.cc +++ b/chrome/browser/chromeos/file_manager/fileapi_util.cc @@ -4,10 +4,12 @@ #include "chrome/browser/chromeos/file_manager/fileapi_util.h" +#include "base/files/file.h" #include "base/files/file_path.h" #include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/storage_partition.h" @@ -15,8 +17,11 @@ #include "net/base/escape.h" #include "url/gurl.h" #include "webkit/browser/fileapi/file_system_context.h" +#include "webkit/browser/fileapi/open_file_system_mode.h" #include "webkit/common/fileapi/file_system_util.h" +using content::BrowserThread; + namespace file_manager { namespace util { @@ -32,8 +37,189 @@ GURL ConvertRelativeFilePathToFileSystemUrl(const base::FilePath& relative_path, false)); // Space to %20 instead of +. } +// Creates an ErrorDefinition with an error set to |error|. +EntryDefinition CreateEntryDefinitionWithError(base::File::Error error) { + EntryDefinition result; + result.error = error; + return result; +} + +// Helper class for performing conversions from file definitions to entry +// definitions. It is possible to do it without a class, but the code would be +// crazy and super tricky. +// +// This class copies the input |file_definition_list|, +// so there is no need to worry about validity of passed |file_definition_list| +// reference. Also, it automatically deletes itself after converting finished, +// or if shutdown is invoked during ResolveURL(). Must be called on UI thread. +class FileDefinitionListConverter { + public: + FileDefinitionListConverter(Profile* profile, + const std::string& extension_id, + const FileDefinitionList& file_definition_list, + const EntryDefinitionListCallback& callback); + ~FileDefinitionListConverter() {} + + private: + // Converts the element under the iterator to an entry. First, converts + // the virtual path to an URL, and calls OnResolvedURL(). In case of error + // calls OnIteratorConverted with an error entry definition. + void ConvertNextIterator(scoped_ptr<FileDefinitionListConverter> self_deleter, + FileDefinitionList::const_iterator iterator); + + // Creates an entry definition from the URL as well as the file definition. + // Then, calls OnIteratorConverted with the created entry definition. + void OnResolvedURL(scoped_ptr<FileDefinitionListConverter> self_deleter, + FileDefinitionList::const_iterator iterator, + const GURL& root_url, + const std::string& name, + base::File::Error error); + + // Called when the iterator is converted. Adds the |entry_definition| to + // |results_| and calls ConvertNextIterator() for the next element. + void OnIteratorConverted(scoped_ptr<FileDefinitionListConverter> self_deleter, + FileDefinitionList::const_iterator iterator, + const EntryDefinition& entry_definition); + + scoped_refptr<fileapi::FileSystemContext> file_system_context_; + const std::string extension_id_; + const FileDefinitionList file_definition_list_; + const EntryDefinitionListCallback callback_; + scoped_ptr<EntryDefinitionList> result_; +}; + +FileDefinitionListConverter::FileDefinitionListConverter( + Profile* profile, + const std::string& extension_id, + const FileDefinitionList& file_definition_list, + const EntryDefinitionListCallback& callback) + : extension_id_(extension_id), + file_definition_list_(file_definition_list), + callback_(callback), + result_(new EntryDefinitionList) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // May be NULL during unit_tests. + ExtensionService* service = + extensions::ExtensionSystem::Get(profile)->extension_service(); + if (service) { + // File browser APIs are meant to be used only from extension context, so + // the extension's site is the one in whose file system context the virtual + // path should be found. + GURL site = service->GetSiteForExtensionId(extension_id_); + file_system_context_ = + content::BrowserContext::GetStoragePartitionForSite( + profile, site)->GetFileSystemContext(); + } + + // Deletes the converter, once the scoped pointer gets out of scope. It is + // either, if the conversion is finished, or ResolveURL() is terminated, and + // the callback not called because of shutdown. + scoped_ptr<FileDefinitionListConverter> self_deleter(this); + ConvertNextIterator(self_deleter.Pass(), file_definition_list_.begin()); +} + +void FileDefinitionListConverter::ConvertNextIterator( + scoped_ptr<FileDefinitionListConverter> self_deleter, + FileDefinitionList::const_iterator iterator) { + if (iterator == file_definition_list_.end()) { + // The converter object will be destroyed since |self_deleter| gets out of + // scope. + callback_.Run(result_.Pass()); + return; + } + + if (!file_system_context_.get()) { + OnIteratorConverted(self_deleter.Pass(), + iterator, + CreateEntryDefinitionWithError( + base::File::FILE_ERROR_INVALID_OPERATION)); + return; + } + + fileapi::ExternalFileSystemBackend* backend = + file_system_context_->external_backend(); + if (!backend) { + OnIteratorConverted(self_deleter.Pass(), + iterator, + CreateEntryDefinitionWithError( + base::File::FILE_ERROR_INVALID_OPERATION)); + return; + } + + fileapi::FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( + extensions::Extension::GetBaseURLFromExtensionId(extension_id_), + fileapi::kFileSystemTypeExternal, + iterator->virtual_path); + DCHECK(url.is_valid()); + + // The converter object will be deleted if the callback is not called because + // of shutdown during ResolveURL(). + // + // TODO(mtomasz, nhiroki): Call FileSystemContext::ResolveURL() directly, + // after removing redundant thread restrictions in there. + backend->ResolveURL( + url, + // Not sandboxed file systems are not creatable via ResolveURL(). + fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, + base::Bind(&FileDefinitionListConverter::OnResolvedURL, + base::Unretained(this), + base::Passed(&self_deleter), + iterator)); +} + +void FileDefinitionListConverter::OnResolvedURL( + scoped_ptr<FileDefinitionListConverter> self_deleter, + FileDefinitionList::const_iterator iterator, + const GURL& root_url, + const std::string& name, + base::File::Error error) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + EntryDefinition entry_definition; + entry_definition.file_system_root_url = root_url.spec(); + entry_definition.file_system_name = name; + entry_definition.is_directory = iterator->is_directory; + entry_definition.error = error; + + // Construct a target Entry.fullPath value from the virtual path and the + // root URL. Eg. Downloads/A/b.txt -> A/b.txt. + const base::FilePath root_virtual_path = + file_system_context_->CrackURL(root_url).virtual_path(); + DCHECK(root_virtual_path == iterator->virtual_path || + root_virtual_path.IsParent(iterator->virtual_path)); + base::FilePath full_path; + root_virtual_path.AppendRelativePath(iterator->virtual_path, &full_path); + entry_definition.full_path = full_path; + + OnIteratorConverted(self_deleter.Pass(), iterator, entry_definition); +} + +void FileDefinitionListConverter::OnIteratorConverted( + scoped_ptr<FileDefinitionListConverter> self_deleter, + FileDefinitionList::const_iterator iterator, + const EntryDefinition& entry_definition) { + result_->push_back(entry_definition); + ConvertNextIterator(self_deleter.Pass(), ++iterator); +} + +// Helper function to return the converted definition entry directly, without +// the redundant container. +void OnConvertFileDefinitionDone( + const EntryDefinitionCallback& callback, + scoped_ptr<EntryDefinitionList> entry_definition_list) { + DCHECK_EQ(1u, entry_definition_list->size()); + callback.Run(entry_definition_list->at(0)); +} + } // namespace +EntryDefinition::EntryDefinition() { +} + +EntryDefinition::~EntryDefinition() { +} + fileapi::FileSystemContext* GetFileSystemContextForExtensionId( Profile* profile, const std::string& extension_id) { @@ -122,5 +308,33 @@ bool ConvertAbsoluteFilePathToRelativeFileSystemPath( return true; } +void ConvertFileDefinitionListToEntryDefinitionList( + Profile* profile, + const std::string& extension_id, + const FileDefinitionList& file_definition_list, + const EntryDefinitionListCallback& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // The converter object destroys itself. + new FileDefinitionListConverter( + profile, extension_id, file_definition_list, callback); +} + +void ConvertFileDefinitionToEntryDefinition( + Profile* profile, + const std::string& extension_id, + const FileDefinition& file_definition, + const EntryDefinitionCallback& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + FileDefinitionList file_definition_list; + file_definition_list.push_back(file_definition); + ConvertFileDefinitionListToEntryDefinitionList( + profile, + extension_id, + file_definition_list, + base::Bind(&OnConvertFileDefinitionDone, callback)); +} + } // namespace util } // namespace file_manager diff --git a/chrome/browser/chromeos/file_manager/fileapi_util.h b/chrome/browser/chromeos/file_manager/fileapi_util.h index d935785..8adbd09 100644 --- a/chrome/browser/chromeos/file_manager/fileapi_util.h +++ b/chrome/browser/chromeos/file_manager/fileapi_util.h @@ -8,14 +8,14 @@ #define CHROME_BROWSER_CHROMEOS_FILE_MANAGER_FILEAPI_UTIL_H_ #include <string> + +#include "base/callback_forward.h" +#include "base/files/file.h" +#include "base/files/file_path.h" #include "url/gurl.h" class Profile; -namespace base { -class FilePath; -} - namespace content { class RenderViewHost; } @@ -27,6 +27,39 @@ class FileSystemContext; namespace file_manager { namespace util { +// Structure information necessary to create a EntryDefinition, and therefore +// an Entry object on the JavaScript side. +struct FileDefinition { + base::FilePath virtual_path; + base::FilePath absolute_path; + bool is_directory; +}; + +// Contains all information needed to create an Entry object in custom bindings. +struct EntryDefinition { + EntryDefinition(); + ~EntryDefinition(); + + std::string file_system_root_url; // Used to create DOMFileSystem. + std::string file_system_name; // Value of DOMFileSystem.name. + base::FilePath full_path; // Value of Entry.fullPath. + bool is_directory; // Whether to create FileEntry or DirectoryEntry. + base::File::Error error; +}; + +typedef std::vector<FileDefinition> FileDefinitionList; +typedef std::vector<EntryDefinition> EntryDefinitionList; + +// The callback used by ConvertFileDefinitionToEntryDefinition. Returns the +// result of the conversion. +typedef base::Callback<void(const EntryDefinition& entry_definition)> + EntryDefinitionCallback; + +// The callback used by ConvertFileDefinitionListToEntryDefinitionList. Returns +// the result of the conversion as a list. +typedef base::Callback<void(scoped_ptr< + EntryDefinitionList> entry_definition_list)> EntryDefinitionListCallback; + // Returns a file system context associated with the given profile and the // extension ID. fileapi::FileSystemContext* GetFileSystemContextForExtensionId( @@ -71,6 +104,24 @@ bool ConvertAbsoluteFilePathToRelativeFileSystemPath( const base::FilePath& absolute_path, base::FilePath* relative_path); +// Converts a file definition to a entry definition and returns the result +// via a callback. |profile| cannot be null. Must be called on UI thread. +void ConvertFileDefinitionToEntryDefinition( + Profile* profile, + const std::string& extension_id, + const FileDefinition& file_definition, + const EntryDefinitionCallback& callback); + +// Converts a list of file definitions into a list of entry definitions and +// returns it via |callback|. The method is safe, |file_definition_list| is +// copied internally. The output list has the same order of items and size as +// the input vector. |profile| cannot be null. Must be called on UI thread. +void ConvertFileDefinitionListToEntryDefinitionList( + Profile* profile, + const std::string& extension_id, + const FileDefinitionList& file_definition_list, + const EntryDefinitionListCallback& callback); + } // namespace util } // namespace file_manager diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc index 98a6c2e..ef0e3b3 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.cc +++ b/chrome/browser/chromeos/file_manager/volume_manager.cc @@ -101,6 +101,8 @@ std::string VolumeTypeToString(VolumeType type) { return "archive"; case VOLUME_TYPE_CLOUD_DEVICE: return "cloud_device"; + case VOLUME_TYPE_TESTING: + return "testing"; } NOTREACHED(); return ""; @@ -131,8 +133,7 @@ VolumeInfo CreateDriveVolumeInfo(Profile* profile) { return volume_info; } -VolumeInfo CreateDownloadsVolumeInfo( - const base::FilePath& downloads_path) { +VolumeInfo CreateDownloadsVolumeInfo(const base::FilePath& downloads_path) { VolumeInfo volume_info; volume_info.type = VOLUME_TYPE_DOWNLOADS_DIRECTORY; volume_info.device_type = chromeos::DEVICE_TYPE_UNKNOWN; @@ -145,6 +146,19 @@ VolumeInfo CreateDownloadsVolumeInfo( return volume_info; } +VolumeInfo CreateTestingVolumeInfo(const base::FilePath& path) { + VolumeInfo volume_info; + volume_info.type = VOLUME_TYPE_TESTING; + volume_info.device_type = chromeos::DEVICE_TYPE_UNKNOWN; + // Keep source_path empty. + volume_info.mount_path = path; + volume_info.mount_condition = chromeos::disks::MOUNT_CONDITION_NONE; + volume_info.is_parent = false; + volume_info.is_read_only = false; + volume_info.volume_id = GenerateVolumeId(volume_info); + return volume_info; +} + VolumeInfo CreateVolumeInfoFromMountPointInfo( const chromeos::disks::DiskMountManager::MountPointInfo& mount_point, const chromeos::disks::DiskMountManager::Disk* disk) { @@ -382,6 +396,14 @@ bool VolumeManager::RegisterDownloadsDirectoryForTesting( return success; } +void VolumeManager::AddVolumeInfoForTesting(const base::FilePath& path) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DoMountEvent( + chromeos::MOUNT_ERROR_NONE, + CreateTestingVolumeInfo(path), + false /* is_remounting */); +} + void VolumeManager::OnFileSystemMounted() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); diff --git a/chrome/browser/chromeos/file_manager/volume_manager.h b/chrome/browser/chromeos/file_manager/volume_manager.h index da3b2e7e..ec74330 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.h +++ b/chrome/browser/chromeos/file_manager/volume_manager.h @@ -45,7 +45,8 @@ enum VolumeType { VOLUME_TYPE_DOWNLOADS_DIRECTORY, VOLUME_TYPE_REMOVABLE_DISK_PARTITION, VOLUME_TYPE_MOUNTED_ARCHIVE_FILE, - VOLUME_TYPE_CLOUD_DEVICE + VOLUME_TYPE_CLOUD_DEVICE, + VOLUME_TYPE_TESTING }; struct VolumeInfo { @@ -130,9 +131,14 @@ class VolumeManager : public BrowserContextKeyedService, bool FindVolumeInfoById(const std::string& volume_id, VolumeInfo* result) const; - // For testing purpose, adds the custom |path| as the "Downloads" folder. + // For testing purpose, registers a native local file system poniting to + // |path| with DOWNLOADS type, and adds its volume info. bool RegisterDownloadsDirectoryForTesting(const base::FilePath& path); + // For testing purpose, adds a volume info pointing to |path|, with TESTING + // type. Assumes that the mount point is already registered. + void AddVolumeInfoForTesting(const base::FilePath& path); + // drive::DriveIntegrationServiceObserver overrides. virtual void OnFileSystemMounted() OVERRIDE; virtual void OnFileSystemBeingUnmounted() OVERRIDE; diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.cc b/chrome/browser/chromeos/fileapi/file_system_backend.cc index e652ed1..f5e80fb 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend.cc +++ b/chrome/browser/chromeos/fileapi/file_system_backend.cc @@ -93,15 +93,51 @@ bool FileSystemBackend::CanHandleType(fileapi::FileSystemType type) const { void FileSystemBackend::Initialize(fileapi::FileSystemContext* context) { } -void FileSystemBackend::OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) { - // TODO(nhiroki): Deprecate OpenFileSystem for non-sandboxed filesystem. - // (http://crbug.com/297412) - NOTREACHED(); - callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY); +void FileSystemBackend::ResolveURL(const fileapi::FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) { + std::string id; + fileapi::FileSystemType type; + base::FilePath path; + fileapi::FileSystemMountOption option; + if (!mount_points_->CrackVirtualPath( + url.virtual_path(), &id, &type, &path, &option) && + !system_mount_points_->CrackVirtualPath( + url.virtual_path(), &id, &type, &path, &option)) { + // Not under a mount point, so return an error, since the root is not + // accessible. + GURL root_url = GURL(fileapi::GetExternalFileSystemRootURIString( + url.origin(), std::string())); + callback.Run(root_url, std::string(), base::File::FILE_ERROR_SECURITY); + return; + } + + std::string name; + // Construct a URL restricted to the found mount point. + std::string root_url = + fileapi::GetExternalFileSystemRootURIString(url.origin(), id); + + // For removable and archives, the file system root is the external mount + // point plus the inner mount point. + if (id == "archive" || id == "removable") { + std::vector<std::string> components; + url.virtual_path().GetComponents(&components); + DCHECK_EQ(id, components.at(0)); + if (components.size() < 2) { + // Unable to access /archive and /removable directories directly. The + // inner mount name must be specified. + callback.Run( + GURL(root_url), std::string(), base::File::FILE_ERROR_SECURITY); + return; + } + std::string inner_mount_name = components[1]; + root_url += inner_mount_name + "/"; + name = inner_mount_name; + } else { + name = id; + } + + callback.Run(GURL(root_url), name, base::File::FILE_OK); } fileapi::FileSystemQuotaUtil* FileSystemBackend::GetQuotaUtil() { diff --git a/chrome/browser/chromeos/fileapi/file_system_backend.h b/chrome/browser/chromeos/fileapi/file_system_backend.h index e6c1e57..df7bff1 100644 --- a/chrome/browser/chromeos/fileapi/file_system_backend.h +++ b/chrome/browser/chromeos/fileapi/file_system_backend.h @@ -90,11 +90,9 @@ class FileSystemBackend : public fileapi::ExternalFileSystemBackend { // fileapi::FileSystemBackend overrides. virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE; virtual void Initialize(fileapi::FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const fileapi::FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual fileapi::AsyncFileUtil* GetAsyncFileUtil( fileapi::FileSystemType type) OVERRIDE; virtual fileapi::CopyOrMoveFileValidatorFactory* diff --git a/chrome/browser/local_discovery/storage/privet_filesystem_backend.cc b/chrome/browser/local_discovery/storage/privet_filesystem_backend.cc index 0d25177..70433cd 100644 --- a/chrome/browser/local_discovery/storage/privet_filesystem_backend.cc +++ b/chrome/browser/local_discovery/storage/privet_filesystem_backend.cc @@ -9,6 +9,7 @@ #include "chrome/browser/local_discovery/storage/privet_filesystem_async_util.h" #include "chrome/browser/local_discovery/storage/privet_filesystem_constants.h" #include "webkit/browser/fileapi/file_system_operation.h" +#include "webkit/browser/fileapi/file_system_url.h" namespace local_discovery { @@ -35,15 +36,14 @@ void PrivetFileSystemBackend::Initialize(fileapi::FileSystemContext* context) { base::FilePath(kPrivetFilePath)); } -void PrivetFileSystemBackend::OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, +void PrivetFileSystemBackend::ResolveURL( + const fileapi::FileSystemURL& url, fileapi::OpenFileSystemMode mode, const OpenFileSystemCallback& callback) { - // Copied from src/chrome/browser/chromeos/fileapi/file_system_backend.cc - // This is deprecated for non-sandboxed filesystems. - NOTREACHED(); - callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY); + // TODO(noamsml): Provide a proper root url and a proper name. + GURL root_url = GURL( + fileapi::GetExternalFileSystemRootURIString(url.origin(), std::string())); + callback.Run(root_url, std::string(), base::File::FILE_OK); } fileapi::FileSystemQuotaUtil* PrivetFileSystemBackend::GetQuotaUtil() { diff --git a/chrome/browser/local_discovery/storage/privet_filesystem_backend.h b/chrome/browser/local_discovery/storage/privet_filesystem_backend.h index 2b46ae9..e143d0e 100644 --- a/chrome/browser/local_discovery/storage/privet_filesystem_backend.h +++ b/chrome/browser/local_discovery/storage/privet_filesystem_backend.h @@ -29,11 +29,9 @@ class PrivetFileSystemBackend : public fileapi::FileSystemBackend { virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE; virtual void Initialize(fileapi::FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const fileapi::FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual fileapi::AsyncFileUtil* GetAsyncFileUtil( fileapi::FileSystemType type) OVERRIDE; diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc index 493d8d9..5b344de 100644 --- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc +++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc @@ -108,17 +108,16 @@ bool MediaFileSystemBackend::CanHandleType( void MediaFileSystemBackend::Initialize(fileapi::FileSystemContext* context) { } -void MediaFileSystemBackend::OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, +void MediaFileSystemBackend::ResolveURL( + const FileSystemURL& url, fileapi::OpenFileSystemMode mode, const OpenFileSystemCallback& callback) { - // We never allow opening a new isolated FileSystem via usual OpenFileSystem. + // We never allow opening a new isolated FileSystem via usual ResolveURL. base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(callback, - GetFileSystemRootURI(origin_url, type), - GetFileSystemName(origin_url, type), + GURL(), + std::string(), base::File::FILE_ERROR_SECURITY)); } diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h index ff0d134..c5f8d99 100644 --- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h +++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h @@ -32,11 +32,9 @@ class MediaFileSystemBackend : public fileapi::FileSystemBackend { // FileSystemBackend implementation. virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE; virtual void Initialize(fileapi::FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const fileapi::FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual fileapi::AsyncFileUtil* GetAsyncFileUtil( fileapi::FileSystemType type) OVERRIDE; virtual fileapi::CopyOrMoveFileValidatorFactory* diff --git a/chrome/browser/resources/file_manager/background/js/volume_manager.js b/chrome/browser/resources/file_manager/background/js/volume_manager.js index 67eaffe..bfc5458 100644 --- a/chrome/browser/resources/file_manager/background/js/volume_manager.js +++ b/chrome/browser/resources/file_manager/background/js/volume_manager.js @@ -168,23 +168,23 @@ volumeManagerUtil.validateError = function(error) { /** * Returns the root entry of a volume mounted at mountPath. - * TODO(mtomasz): Migrate to volumeId, once requestFileSystem can handle it. + * TODO(mtomasz): Remove this method. * - * @param {string} mountPath The mounted path of the volume. + * @param {string} volumeId ID of the volume to be mounted. * @param {function(DirectoryEntry)} successCallback Called when the root entry * is found. * @param {function(FileError)} errorCallback Called when an error is found. * @private */ volumeManagerUtil.getRootEntry_ = function( - mountPath, successCallback, errorCallback) { + volumeId, successCallback, errorCallback) { // We always request FileSystem here, because requestFileSystem() grants // permissions if necessary, especially for Drive File System at first mount // time. // Note that we actually need to request FileSystem after multi file system // support, so this will be more natural code then. chrome.fileBrowserPrivate.requestFileSystem( - 'compatible', + volumeId, function(fileSystem) { // TODO(hidehiko): chrome.runtime.lastError should have error reason. if (!fileSystem) { @@ -192,9 +192,7 @@ volumeManagerUtil.getRootEntry_ = function( return; } - fileSystem.root.getDirectory( - mountPath.substring(1), // Strip leading '/'. - {create: false}, successCallback, errorCallback); + successCallback(fileSystem.root); }); }; @@ -205,7 +203,7 @@ volumeManagerUtil.getRootEntry_ = function( */ volumeManagerUtil.createVolumeInfo = function(volumeMetadata, callback) { volumeManagerUtil.getRootEntry_( - volumeMetadata.mountPath, + volumeMetadata.volumeId, function(entry) { if (volumeMetadata.volumeType === util.VolumeType.DRIVE) { // After file system is mounted, we "read" drive grand root @@ -369,8 +367,9 @@ VolumeInfoList.prototype.findByEntry = function(entry) { var volumeInfo = this.item(i); if (!volumeInfo.root) continue; + // URL of the root always contains the trailing slash. if (util.isSameEntry(entry, volumeInfo.root) || - entry.toURL().indexOf(volumeInfo.root.toURL() + '/') === 0) { + entry.toURL().indexOf(volumeInfo.root.toURL()) === 0) { return volumeInfo; } // Additionally, check fake entries. @@ -674,18 +673,19 @@ VolumeManager.prototype.getLocationInfo = function(entry) { var isReadOnly; var isRootEntry; if (volumeInfo.volumeType === util.VolumeType.DRIVE) { - // For Drive, the roots are /root and /other, instead of /. + // For Drive, the roots are /root and /other, instead of /. Root URLs + // contain trailing slashes. // TODO(mtomasz): Simplify once switching to filesystem per volume. - if (entry.toURL() === volumeInfo.root.toURL() + '/root' || - entry.toURL().indexOf(volumeInfo.root.toURL() + '/root/') === 0) { + if (entry.toURL() === volumeInfo.root.toURL() + 'root' || + entry.toURL().indexOf(volumeInfo.root.toURL() + 'root/') === 0) { rootType = RootType.DRIVE; isReadOnly = volumeInfo.isReadOnly; - isRootEntry = entry.toURL() === volumeInfo.root.toURL() + '/root'; - } else if (entry.toURL() === volumeInfo.root.toURL() + '/other' || - entry.toURL().indexOf(volumeInfo.root.toURL() + '/other/') === 0) { + isRootEntry = entry.toURL() === volumeInfo.root.toURL() + 'root'; + } else if (entry.toURL() === volumeInfo.root.toURL() + 'other' || + entry.toURL().indexOf(volumeInfo.root.toURL() + 'other/') === 0) { rootType = RootType.DRIVE_OTHER; isReadOnly = true; - isRootEntry = entry.toURL() === volumeInfo.root.toURL() + '/other'; + isRootEntry = entry.toURL() === volumeInfo.root.toURL() + 'other'; } else { // Accessing Drive files outside of /drive/root and /drive/other is not // allowed, but can happen. Therefore returning null. diff --git a/chrome/browser/resources/file_manager/foreground/js/folder_shortcuts_data_model.js b/chrome/browser/resources/file_manager/foreground/js/folder_shortcuts_data_model.js index 30cd40c..b3be449 100644 --- a/chrome/browser/resources/file_manager/foreground/js/folder_shortcuts_data_model.js +++ b/chrome/browser/resources/file_manager/foreground/js/folder_shortcuts_data_model.js @@ -529,12 +529,13 @@ FolderShortcutsDataModel.prototype = { * @private */ convertUrlToStoredPath_: function(url) { - if (url.indexOf(this.lastDriveRootURL_ + '/') !== 0) { + // Root URLs contain a trailing slash. + if (url.indexOf(this.lastDriveRootURL_) !== 0) { console.warn(url + ' is not a drive URL.'); return null; } - return STORED_DRIVE_MOUNT_PATH + decodeURIComponent( + return STORED_DRIVE_MOUNT_PATH + '/' + decodeURIComponent( url.substr(this.lastDriveRootURL_.length)); }, }; diff --git a/chrome/browser/resources/image_loader/image_loader.js b/chrome/browser/resources/image_loader/image_loader.js index a353627..da5e3bc 100644 --- a/chrome/browser/resources/image_loader/image_loader.js +++ b/chrome/browser/resources/image_loader/image_loader.js @@ -23,15 +23,34 @@ function ImageLoader() { */ this.worker_ = new Worker(); - // Grant permissions to the local file system and initialize the cache. - chrome.fileBrowserPrivate.requestFileSystem( - 'compatible', - function(filesystem) { - this.cache_.initialize(function() { - this.worker_.start(); - }.bind(this)); - }.bind(this)); + // Grant permissions to all volumes, initialize the cache and then start the + // worker. + chrome.fileBrowserPrivate.getVolumeMetadataList(function(volumeMetadataList) { + var initPromises = volumeMetadataList.map(function(volumeMetadata) { + var requestPromise = new Promise(function(callback) { + chrome.fileBrowserPrivate.requestFileSystem( + volumeMetadata.volumeId, + callback); + }); + return requestPromise; + }); + initPromises.push(new Promise(this.cache_.initialize.bind(this.cache_))); + + // After all initializatino promises are done, start the worker. + Promise.all(initPromises).then(this.worker_.start.bind(this.worker_)); + + // Listen for mount events, and grant permissions to volumes being mounted. + chrome.fileBrowserPrivate.onMountCompleted.addListener( + function(event) { + // TODO(mtomasz): Get rid of mountPath when possible. + if (event.eventType == 'mount' && event.volumeMetadata.mountPath) { + chrome.fileBrowserPrivate.requestFileSystem( + event.volumeMetadata.volumeId, function() {}); + } + }); + }.bind(this)); + // Listen for incoming requests. chrome.extension.onMessageExternal.addListener(function(request, sender, sendResponse) { diff --git a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc index 5e693db..50e5b947 100644 --- a/chrome/browser/sync_file_system/local/sync_file_system_backend.cc +++ b/chrome/browser/sync_file_system/local/sync_file_system_backend.cc @@ -108,25 +108,30 @@ void SyncFileSystemBackend::Initialize(fileapi::FileSystemContext* context) { fileapi::kFileSystemTypeSyncableForInternalSync); } -void SyncFileSystemBackend::OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) { - DCHECK(CanHandleType(type)); +void SyncFileSystemBackend::ResolveURL(const fileapi::FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) { + DCHECK(CanHandleType(url.type())); if (skip_initialize_syncfs_service_for_testing_) { - GetDelegate()->OpenFileSystem(origin_url, type, mode, callback, - GetSyncableFileSystemRootURI(origin_url)); + GetDelegate()->OpenFileSystem(url.origin(), + url.type(), + mode, + callback, + GetSyncableFileSystemRootURI(url.origin())); return; } // It is safe to pass Unretained(this) since |context_| owns it. SyncStatusCallback initialize_callback = base::Bind(&SyncFileSystemBackend::DidInitializeSyncFileSystemService, - base::Unretained(this), make_scoped_refptr(context_), - origin_url, type, mode, callback); - InitializeSyncFileSystemService(origin_url, initialize_callback); + base::Unretained(this), + make_scoped_refptr(context_), + url.origin(), + url.type(), + mode, + callback); + InitializeSyncFileSystemService(url.origin(), initialize_callback); } fileapi::AsyncFileUtil* SyncFileSystemBackend::GetAsyncFileUtil( diff --git a/chrome/browser/sync_file_system/local/sync_file_system_backend.h b/chrome/browser/sync_file_system/local/sync_file_system_backend.h index a6bd5cb..86ef76f 100644 --- a/chrome/browser/sync_file_system/local/sync_file_system_backend.h +++ b/chrome/browser/sync_file_system/local/sync_file_system_backend.h @@ -30,11 +30,9 @@ class SyncFileSystemBackend // FileSystemBackend overrides. virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE; virtual void Initialize(fileapi::FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const fileapi::FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual fileapi::AsyncFileUtil* GetAsyncFileUtil( fileapi::FileSystemType type) OVERRIDE; virtual fileapi::CopyOrMoveFileValidatorFactory* diff --git a/chrome/common/extensions/api/file_browser_private.idl b/chrome/common/extensions/api/file_browser_private.idl index a36a0fb..8077578 100644 --- a/chrome/common/extensions/api/file_browser_private.idl +++ b/chrome/common/extensions/api/file_browser_private.idl @@ -8,7 +8,7 @@ implemented_in="chrome/browser/chromeos/extensions/file_manager/file_browser_private_api_functions.h"] namespace fileBrowserPrivate { // Type of the mounted volume. -enum VolumeType { drive, downloads, removable, archive, cloud_device }; +enum VolumeType { drive, downloads, removable, archive, cloud_device, testing }; // Device type. Available if this is removable volume. enum DeviceType { usb, sd, optical, mobile, unknown }; diff --git a/chrome/test/data/extensions/api_test/file_browser/drive_search_test/test.js b/chrome/test/data/extensions/api_test/file_browser/drive_search_test/test.js index 9450f75..f4cf43c 100644 --- a/chrome/test/data/extensions/api_test/file_browser/drive_search_test/test.js +++ b/chrome/test/data/extensions/api_test/file_browser/drive_search_test/test.js @@ -5,8 +5,7 @@ /** * Extension apitests for drive search methods. * There are three tests functions run: - * - loadFileSystem() which requests local file system and verifies the drive - * mount point exists. + * - loadFileSystem() which requests the Drive file system. * - driveSearch() which tests chrome.fileBrowserPrivate.searchDrive function. * - driveMetadataSearch() which tests * chrome.fileBrowserPrivate.searchDriveMetadata function. @@ -29,7 +28,9 @@ function verifyFile(entry, successCallback) { chrome.test.assertFalse(!entry.file, 'Entry has no file method.'); entry.file(successCallback, - chrome.test.fail.bind(null, 'Error reading result file.')); + function() { + chrome.test.fail('Error reading result file.'); + }); } /** @@ -71,10 +72,10 @@ chrome.test.runTests([ // Loads filesystem that contains drive mount point. function loadFileSystem() { chrome.fileBrowserPrivate.requestFileSystem( - 'compatible', + 'drive:drive-user', function (fileSystem) { chrome.test.assertFalse(!fileSystem, 'Failed to get file system.'); - fileSystem.root.getDirectory('drive/root/test_dir', {create: false}, + fileSystem.root.getDirectory('/root/test_dir', {create: false}, // Also read a non-root directory. This will initiate loading of // the full resource metadata. As of now, 'search' only works // with the resource metadata fully loaded. crbug.com/181075 @@ -82,9 +83,13 @@ chrome.test.runTests([ var reader = entry.createReader(); reader.readEntries( chrome.test.succeed, - chrome.test.fail.bind(null, 'Error reading directory.')); + function() { + chrome.test.fail('Error reading directory.'); + }); }, - chrome.test.fail.bind(null, 'Unable to get drive mount point.')); + function() { + chrome.test.fail('Unable to get the testing directory.'); + }); }); }, @@ -92,8 +97,8 @@ chrome.test.runTests([ function driveSearch() { var query = 'empty'; var expectedEntries = [ - {path: '/drive/root/test_dir/empty_test_dir', type: 'dir'}, - {path: '/drive/root/test_dir/empty_test_file.foo', type: 'file'}, + {path: '/root/test_dir/empty_test_dir', type: 'dir'}, + {path: '/root/test_dir/empty_test_file.foo', type: 'file'}, ]; function runNextQuery(entries, nextFeed) { @@ -140,13 +145,13 @@ chrome.test.runTests([ // matches in the test file system. var expectedResults = [ // (2012-01-02T00:00:01.000Z, 2012-01-02T00:00:0.000Z) - {path: '/drive/root/test_dir', type: 'dir'}, + {path: '/root/test_dir', type: 'dir'}, // (2012-01-02T00:00:00.000Z, 2012-01-01T00:00:00.005Z) - {path: '/drive/root/test_dir/test_file.xul', type: 'file'}, + {path: '/root/test_dir/test_file.xul', type: 'file'}, // (2012-01-02T00:00:00.000Z, 2011-04-03T11:11:10.000Z) - {path: '/drive/root/test_dir/test_file.tiff', type: 'file'}, + {path: '/root/test_dir/test_file.tiff', type: 'file'}, // (2012-01-01T11:00:00.000Z, 2012-01-01T10:00:30.00Z) - {path: '/drive/root/test_dir/test_file.xul.foo', type: 'file'}, + {path: '/root/test_dir/test_file.xul.foo', type: 'file'}, ]; var query = { diff --git a/chrome/test/data/extensions/api_test/file_browser/file_watcher_test/test.js b/chrome/test/data/extensions/api_test/file_browser/file_watcher_test/test.js index d7cad0e..18f7d88 100644 --- a/chrome/test/data/extensions/api_test/file_browser/file_watcher_test/test.js +++ b/chrome/test/data/extensions/api_test/file_browser/file_watcher_test/test.js @@ -212,97 +212,94 @@ function initTests(callback) { */ valid: false, /** - * Mount point root directory entry. - * @type {DirectoryEntry} + * TODO(tbarzic) : We should not need to have this. The watch api should + * have the same behavior for local and drive file system. + * @type {boolean}} */ - mountPoint: null, - // TODO(tbarzic) : We should not need to have this. The watch api should - // have the same behavior for local and drive file system. isOnDrive: false, /** * Set of entries that are being watched during the tests. * @type {Object.<Entry>} */ - entries: {} + entries: {}, + /** + * File system for the testing volume. + * @type {DOMFileSystem} + */ + fileSystem: null }; - // Get the file system. - chrome.fileBrowserPrivate.requestFileSystem( - 'compatible', function(fileSystem) { - if(!fileSystem) { - callback(testParams, 'Failed to get file system,'); - return; - } - - var possibleMountPoints = ['local/', 'drive/']; + chrome.fileBrowserPrivate.getVolumeMetadataList(function(volumeMetadataList) { + var possibleVolumeTypes = ['testing', 'drive']; - function tryNextMountPoint() { - if (possibleMountPoints.length == 0) { - callback(testParams, 'No mount point found.'); - return; - } + var sortedVolumeMetadataList = volumeMetadataList.filter(function(volume) { + return possibleVolumeTypes.indexOf(volume.volumeType) != -1; + }).sort(function(volumeA, volumeB) { + return possibleVolumeTypes.indexOf(volumeA.volumeType) > + possibleVolumeTypes.indexOf(volumeB.volumeType); + }); - var mountPointPath = possibleMountPoints.shift(); - - // Try to get the current mount point path. On failure, - // |tryNextMountPoint| is called. - fileSystem.root.getDirectory( - mountPointPath, {}, - function(mountPoint) { - // The test mount point has been found. Get all the entries that - // will be watched during the test. - testParams.mountPoint = mountPoint; - testParams.isOnDrive = mountPointPath == 'drive/'; - - var testWatchEntries = [ - {name: 'file', - path: getPath('test_dir/test_file.xul', testParams.isOnDrive), - type: 'file'}, - {name: 'dir', path: getPath('test_dir/', testParams.isOnDrive), - type: 'dir'}, - {name: 'subdir', - path: getPath('test_dir/subdir', testParams.isOnDrive), - type: 'dir'}, - ]; - - // Gets the first entry in |testWatchEntries| list. - function getNextEntry() { - // If the list is empty, the test has been successfully - // initialized, so call callback. - if (testWatchEntries.length == 0) { - testParams.valid = true; - callback(testParams, 'Success.'); - return; - } - - var testEntry = testWatchEntries.shift(); - - var getFunction = null; - if (testEntry.type == 'file') { - getFunction = mountPoint.getFile.bind(mountPoint); - } else { - getFunction = mountPoint.getDirectory.bind(mountPoint); - } - - getFunction(testEntry.path, {}, - function(entry) { - testParams.entries[testEntry.name] = entry; - getNextEntry(); - }, - callback.bind(null, testParams, - 'Unable to get entry: \'' + testEntry.path + '\'.')); - }; - - // Trigger getting the watched entries. - getNextEntry(); - - }, - tryNextMountPoint); - }; + if (sortedVolumeMetadataList.length == 0) { + callback( + testParams, 'No volumes available, which could be used for testing.'); + return; + } - // Trigger getting the test mount point. - tryNextMountPoint(); - }) + chrome.fileBrowserPrivate.requestFileSystem( + sortedVolumeMetadataList[0].volumeId, + function(fileSystem) { + if (!fileSystem) { + callback(testParams, 'Failed to acquire the testing volume.'); + return; + } + + testParams.fileSystem = fileSystem; + testParams.isOnDrive = + sortedVolumeMetadataList[0].volumeType == 'drive'; + + var testWatchEntries = [ + {name: 'file', + path: getPath('test_dir/test_file.xul', testParams.isOnDrive), + type: 'file'}, + {name: 'dir', path: getPath('test_dir/', testParams.isOnDrive), + type: 'dir'}, + {name: 'subdir', + path: getPath('test_dir/subdir', testParams.isOnDrive), + type: 'dir'}, + ]; + + // Gets the first entry in |testWatchEntries| list. + var getNextEntry = function() { + // If the list is empty, the test has been successfully + // initialized, so call callback. + if (testWatchEntries.length == 0) { + testParams.valid = true; + callback(testParams, 'Success.'); + return; + } + + var testEntry = testWatchEntries.shift(); + + var getFunction = null; + if (testEntry.type == 'file') { + getFunction = fileSystem.root.getFile.bind(fileSystem.root); + } else { + getFunction = fileSystem.root.getDirectory.bind(fileSystem.root); + } + + getFunction(testEntry.path, {}, + function(entry) { + testParams.entries[testEntry.name] = entry; + getNextEntry(); + }, + callback.bind(null, testParams, + 'Unable to get entry: \'' + testEntry.path + '\'.')); + }; + + // Trigger getting the watched entries. + getNextEntry(); + }); + }); }; // Starts the test. @@ -345,7 +342,7 @@ initTests(function(testParams, errorMessage) { 'changed', 'added'); testEventListener.start(); - testParams.mountPoint.getDirectory( + testParams.fileSystem.root.getDirectory( getPath('test_dir/subdir/subsubdir', testParams.isOnDrive), {create: true, exclusive: true}, testEventListener.onFileSystemOperation.bind(testEventListener), @@ -361,7 +358,7 @@ initTests(function(testParams, errorMessage) { 'changed', 'added'); testEventListener.start(); - testParams.mountPoint.getFile( + testParams.fileSystem.root.getFile( getPath('test_dir/subdir/file', testParams.isOnDrive), {create: true, exclusive: true}, testEventListener.onFileSystemOperation.bind(testEventListener), @@ -378,7 +375,7 @@ initTests(function(testParams, errorMessage) { testEventListener.start(); - testParams.mountPoint.getFile( + testParams.fileSystem.root.getFile( getPath('test_dir/subdir/file', testParams.isOnDrive), {}, function(entry) { @@ -399,7 +396,7 @@ initTests(function(testParams, errorMessage) { 'changed', 'deleted'); testEventListener.start(); - testParams.mountPoint.getFile( + testParams.fileSystem.root.getFile( getPath('test_dir/subdir/renamed', testParams.isOnDrive), {}, function(entry) { entry.remove( @@ -426,7 +423,7 @@ initTests(function(testParams, errorMessage) { } testEventListener.start(); - testParams.mountPoint.getFile( + testParams.fileSystem.root.getFile( getPath('test_dir/test_file.xul', testParams.isOnDrive), {}, function(entry) { entry.remove( @@ -447,7 +444,7 @@ initTests(function(testParams, errorMessage) { 'changed', 'deleted'); testEventListener.start(); - testParams.mountPoint.getDirectory( + testParams.fileSystem.root.getDirectory( getPath('test_dir/subdir/subsubdir', testParams.isOnDrive), {}, function(entry) { entry.removeRecursively( @@ -474,7 +471,7 @@ initTests(function(testParams, errorMessage) { 'changed', 'deleted'); testEventListener.start(); - testParams.mountPoint.getDirectory( + testParams.fileSystem.root.getDirectory( getPath('test_dir/subdir', testParams.isOnDrive), {}, function(entry) { entry.removeRecursively( diff --git a/chrome/test/data/extensions/api_test/file_browser/filesystem_operations_test/test.js b/chrome/test/data/extensions/api_test/file_browser/filesystem_operations_test/test.js index 89f7ea1..0f1c58a 100644 --- a/chrome/test/data/extensions/api_test/file_browser/filesystem_operations_test/test.js +++ b/chrome/test/data/extensions/api_test/file_browser/filesystem_operations_test/test.js @@ -6,33 +6,31 @@ * Component extension that tests the extensions with fileBrowesrPrivate * permission are able to perform file system operations on external file * systems. The test can be run for three different external file system types: - * local native, restricted local native and drive. The exact file system for - * which the test is run is determined by trying to get the file systems root - * dir ('local', 'restricted' or 'drive'). C++ side of the test - * (external_file_system_extension_apitest.cc) should make sure the file system - * root dirs are properly named and that exactly one of them exists. + * local native, restricted local native and drive. Depending on the type, + * a file system with specific volumeId is acquired. C++ side of the test + * (external_file_system_extension_apitest.cc) should make sure the file systems + * are available, and the volume IDs are correct. * * The test files on file systems should be created before running the test * extension. The test extension expects following hierarchy: - * mount_point_root - (root) - test_dir - - subdir - * | - * - empty_test_dir - * | - * - test_file.xul - * | - * - test_file.xul.foo - * | - * - test_file.tiff - * | - * - test_file.tiff.foo + * (root) - test_dir - subdir + * | + * - empty_test_dir + * | + * - test_file.xul + * | + * - test_file.xul.foo + * | + * - test_file.tiff + * | + * - test_file.tiff.foo * - * mount_point_root/root exists only for Drive. - * mount_point_root/(root/)test_dir/subdir/ will be used as destination dir for - * copy and move operations. - * mount_point_root/(root/)test_dir/empty_test_dir/ should be empty and will - * stay empty until the end of the test. - * mount_point_root/(root/)test_dir/test_file.xul will not change during the - * test. + * 'root' exists only for Drive. + * (root/)test_dir/subdir/ will be used as destination dir for copy and move + * operations. + * (root/)test_dir/empty_test_dir/ should be empty and will stay empty until + * the end of the test. + * (root/)test_dir/test_file.xul will not change during the test. * * All files should initially have content: kInitialFileContent. */ @@ -62,43 +60,45 @@ function assertEqAndRunCallback(expectedValue, value, errorMessage, * as an argument. For Other methods, the callback argument should be ignored. */ -// Gets the path for operations. The path is relative to the mount point for +// Gets the path for operations. The path is relative to the volume for // local entries and relative to the "My Drive" root for Drive entries. function getPath(relativePath, isOnDrive) { return (isOnDrive ? 'root/' : '') + relativePath; } -// Gets the directory mountPoint/path -function getDirectory(mountPoint, path, shouldCreate, expectSuccess, callback) { +// Gets the directory entry. +function getDirectory( + volumeId, entry, path, shouldCreate, expectSuccess, callback) { var messagePrefix = shouldCreate ? 'Creating ' : 'Getting '; var message = messagePrefix + 'directory: \'' + path +'\'.'; - var isOnDrive = mountPoint.fullPath == '/drive'; + var isOnDrive = volumeId == 'drive:drive-user'; - mountPoint.getDirectory( + entry.getDirectory( getPath(path, isOnDrive), {create: shouldCreate}, assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback), assertEqAndRunCallback.bind(null, expectSuccess, false, message, callback, null)); } -// Gets the file mountPoint/path -function getFile(mountPoint, path, shouldCreate, expectSuccess, callback) { +// Gets the file entry. +function getFile(volumeId, entry, path, shouldCreate, expectSuccess, callback) { var messagePrefix = shouldCreate ? 'Creating ' : 'Getting '; var message = messagePrefix + 'file: \'' + path +'\'.'; - var isOnDrive = mountPoint.fullPath == '/drive'; + var isOnDrive = volumeId == 'drive:drive-user'; - mountPoint.getFile( + entry.getFile( getPath(path, isOnDrive), {create: shouldCreate}, assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback), assertEqAndRunCallback.bind(null, expectSuccess, false, message, callback, null)); } -// Reads file mountPoint/path and verifies its content. The read operation +// Reads file entry/path and verifies its content. The read operation // should always succeed. -function readFileAndExpectContent(mountPoint, path, expectedContent, callback) { +function readFileAndExpectContent( + volumeId, entry, path, expectedContent, callback) { var message = 'Content of the file \'' + path + '\'.'; - getFile(mountPoint, path, false, true, function(entry) { + getFile(volumeId, entry, path, false, true, function(entry) { var reader = new FileReader(); reader.onload = function() { assertEqAndRunCallback(expectedContent, reader.result, message, callback); @@ -110,11 +110,12 @@ function readFileAndExpectContent(mountPoint, path, expectedContent, callback) { }); } -// Writes |content| to the file mountPoint/path with offest |offest|. -function writeFile(mountPoint, path, offset, content, expectSuccess, callback) { +// Writes |content| to the file entry/path with offest |offest|. +function writeFile( + volumeId, entry, path, offset, content, expectSuccess, callback) { var message = 'Writing to file: \'' + path + '\'.'; - getFile(mountPoint, path, false, true, function(entry) { + getFile(volumeId, entry, path, false, true, function(entry) { entry.createWriter(function(writer) { writer.onwrite = assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback); @@ -129,9 +130,9 @@ function writeFile(mountPoint, path, offset, content, expectSuccess, callback) { }); } -// Starts and aborts write operation to mountPoint/path. -function abortWriteFile(mountPoint, path, callback) { - getFile(mountPoint, path, false, true, function(entry) { +// Starts and aborts write operation to entry/path. +function abortWriteFile(volumeId, entry, path, callback) { + getFile(volumeId, entry, path, false, true, function(entry) { entry.createWriter(function(writer) { var aborted = false; var failed = false; @@ -153,10 +154,10 @@ function abortWriteFile(mountPoint, path, callback) { }); } -// Truncates file mountPoint/path to lenght |lenght|. -function truncateFile(mountPoint, path, length, expectSuccess, callback) { +// Truncates file entry/path to lenght |lenght|. +function truncateFile(volumeId, entry, path, length, expectSuccess, callback) { var message = 'Truncating file: \'' + path + '\' to length ' + length + '.'; - getFile(mountPoint, path, false, true, function(entry) { + getFile(volumeId, entry, path, false, true, function(entry) { entry.createWriter(function(writer) { writer.onwrite = assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback); @@ -170,9 +171,9 @@ function truncateFile(mountPoint, path, length, expectSuccess, callback) { }); } -// Starts and aborts truncate operation on mountPoint/path. -function abortTruncateFile(mountPoint, path, callback) { - getFile(mountPoint, path, false, true, function(entry) { +// Starts and aborts truncate operation on entry/path. +function abortTruncateFile(volumeId, entry, path, callback) { + getFile(volumeId, entry, path, false, true, function(entry) { entry.createWriter(function(writer) { var aborted = false; var failed = false; @@ -194,12 +195,12 @@ function abortTruncateFile(mountPoint, path, callback) { }); } -// Copies file mountPoint/from to mountPoint/to/newName. -function copyFile(mountPoint, from, to, newName, expectSuccess, callback) { +// Copies file entry/path from to entry/to/newName. +function copyFile(volumeId, entry, from, to, newName, expectSuccess, callback) { var message = 'Copying \'' + from + '\' to \'' + to + '/' + newName + '\'.'; - getFile(mountPoint, from, false, true, function(sourceEntry) { - getDirectory(mountPoint, to, false, true, function(targetDir) { + getFile(volumeId, entry, from, false, true, function(sourceEntry) { + getDirectory(volumeId, entry, to, false, true, function(targetDir) { sourceEntry.copyTo(targetDir, newName, assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback), @@ -209,12 +210,12 @@ function copyFile(mountPoint, from, to, newName, expectSuccess, callback) { }); } -// Moves file mountPoint/from to mountPoint/to/newName. -function moveFile(mountPoint, from, to, newName, expectSuccess, callback) { +// Moves file entry/from to entry/to/newName. +function moveFile(volumeId, entry, from, to, newName, expectSuccess, callback) { var message = 'Moving \'' + from + '\' to \'' + to + '/' + newName + '\'.'; - getFile(mountPoint, from, false, true, function(sourceEntry) { - getDirectory(mountPoint, to, false, true, function(targetDir) { + getFile(volumeId, entry, from, false, true, function(sourceEntry) { + getDirectory(volumeId, entry, to, false, true, function(targetDir) { sourceEntry.moveTo(targetDir, newName, assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback), @@ -224,11 +225,11 @@ function moveFile(mountPoint, from, to, newName, expectSuccess, callback) { }); } -// Deletes file mountPoint/path. -function deleteFile(mountPoint, path, expectSuccess, callback) { +// Deletes file entry/path. +function deleteFile(volumeId, entry, path, expectSuccess, callback) { var message = 'Deleting file \'' + path + '\'.'; - getFile(mountPoint, path, false, true, function(entry) { + getFile(volumeId, entry, path, false, true, function(entry) { entry.remove( assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback), @@ -237,11 +238,11 @@ function deleteFile(mountPoint, path, expectSuccess, callback) { }); } -// Deletes directory mountPoint/path. -function deleteDirectory(mountPoint, path, expectSuccess, callback) { +// Deletes directory entry/path. +function deleteDirectory(volumeId, entry, path, expectSuccess, callback) { var message = 'Deleting directory \'' + path + '\'.'; - getDirectory(mountPoint, path, false, true, function(entry) { + getDirectory(volumeId, entry, path, false, true, function(entry) { entry.remove( assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback), @@ -250,11 +251,12 @@ function deleteDirectory(mountPoint, path, expectSuccess, callback) { }); } -// Recursively deletes directory mountPoint/path. -function deleteDirectoryRecursively(mountPoint, path, expectSuccess, callback) { +// Recursively deletes directory entry/path. +function deleteDirectoryRecursively( + volumeId, entry, path, expectSuccess, callback) { var message = 'Recursively deleting directory \'' + path + '\'.'; - getDirectory(mountPoint, path, false, true, function(entry) { + getDirectory(volumeId, entry, path, false, true, function(entry) { entry.removeRecursively( assertEqAndRunCallback.bind(null, expectSuccess, true, message, callback), @@ -264,51 +266,54 @@ function deleteDirectoryRecursively(mountPoint, path, expectSuccess, callback) { } /** - * Collects all tests that should be run for the test mount point. + * Collects all tests that should be run for the test volume. * - * @param {string} mountPointName The name of the mount points root directory. - * @param {DirectoryEntry} mountPoint The mount point's root directory. + * @param {string} volumeId ID of the volume. + * @param {DOMFileSystem} fileSystem File system of the volume. * @returns {Array.<function()>} The list of tests that should be run. */ -function collectTestsForMountPoint(mountPointName, mountPoint) { - var isReadOnly = mountPointName == 'restricted/'; - var isOnDrive = mountPointName == 'drive/'; +function collectTestsForVolumeId(volumeId, fileSystem) { + console.log(volumeId); + var isReadOnly = volumeId == 'testing:restricted'; + var isOnDrive = volumeId == 'drive:drive-user'; var testsToRun = []; testsToRun.push(function getDirectoryTest() { - getDirectory(mountPoint, 'test_dir', false, true, chrome.test.succeed); + getDirectory(volumeId, fileSystem.root, 'test_dir', false, true, + chrome.test.succeed); }); testsToRun.push(function createDirectoryTest() { // callback checks whether the new directory exists after create operation. // It should exists iff the file system is not read only. - var callback = - getDirectory.bind(null, mountPoint, 'new_test_dir', false, !isReadOnly, - chrome.test.succeed); + var callback = getDirectory.bind(null, volumeId, fileSystem.root, + 'new_test_dir', false, !isReadOnly, chrome.test.succeed); // Create operation should succeed only for non read-only file systems. - getDirectory(mountPoint, 'new_test_dir', true, !isReadOnly, callback); + getDirectory(volumeId, fileSystem.root, 'new_test_dir', true, !isReadOnly, + callback); }); testsToRun.push(function getFileTest() { - getFile(mountPoint, 'test_dir/test_file.xul', false, true, + getFile(volumeId, fileSystem.root, 'test_dir/test_file.xul', false, true, chrome.test.succeed); }); testsToRun.push(function createFileTest() { // Checks whether the new file exists after create operation. // It should exists iff the file system is not read only. - var callback = getFile.bind(null, mountPoint, 'test_dir/new_file', false, - !isReadOnly, chrome.test.succeed); + var callback = getFile.bind(null, volumeId, fileSystem.root, + 'test_dir/new_file', false, !isReadOnly, chrome.test.succeed); // Create operation should succeed only for non read-only file systems. - getFile(mountPoint, 'test_dir/new_file', true, !isReadOnly, callback); + getFile(volumeId, fileSystem.root, 'test_dir/new_file', true, !isReadOnly, + callback); }); testsToRun.push(function readFileTest() { - readFileAndExpectContent(mountPoint, 'test_dir/test_file.xul', - kInitialFileContent, chrome.test.succeed); + readFileAndExpectContent(volumeId, fileSystem.root, + 'test_dir/test_file.xul', kInitialFileContent, chrome.test.succeed); }); testsToRun.push(function writeFileTest() { @@ -316,13 +321,13 @@ function collectTestsForMountPoint(mountPointName, mountPoint) { kFileContentAfterWrite; // Check file content after write operation. The content should not change // on read-only file system. - var callback = readFileAndExpectContent.bind(null, - mountPoint, 'test_dir/test_file.tiff', expectedFinalContent, + var callback = readFileAndExpectContent.bind(null, volumeId, + fileSystem.root, 'test_dir/test_file.tiff', expectedFinalContent, chrome.test.succeed); // Write should fail only on read-only file system. - writeFile(mountPoint, 'test_dir/test_file.tiff', kWriteOffset, kWriteData, - !isReadOnly, callback); + writeFile(volumeId, fileSystem.root, 'test_dir/test_file.tiff', + kWriteOffset, kWriteData, !isReadOnly, callback); }); testsToRun.push(function truncateFileShortTest() { @@ -330,13 +335,13 @@ function collectTestsForMountPoint(mountPointName, mountPoint) { kFileContentAfterTruncateShort; // Check file content after truncate operation. The content should not // change on read-only file system. - var callback = readFileAndExpectContent.bind(null, - mountPoint, 'test_dir/test_file.tiff', expectedFinalContent, + var callback = readFileAndExpectContent.bind(null, volumeId, + fileSystem.root, 'test_dir/test_file.tiff', expectedFinalContent, chrome.test.succeed); // Truncate should fail only on read-only file system. - truncateFile(mountPoint, 'test_dir/test_file.tiff', kTruncateShortLength, - !isReadOnly, callback); + truncateFile(volumeId, fileSystem.root, 'test_dir/test_file.tiff', + kTruncateShortLength, !isReadOnly, callback); }); testsToRun.push(function truncateFileLongTest() { @@ -344,24 +349,24 @@ function collectTestsForMountPoint(mountPointName, mountPoint) { kFileContentAfterTruncateLong; // Check file content after truncate operation. The content should not // change on read-only file system. - var callback = readFileAndExpectContent.bind(null, - mountPoint, 'test_dir/test_file.tiff', expectedFinalContent, + var callback = readFileAndExpectContent.bind(null, volumeId, + fileSystem.root, 'test_dir/test_file.tiff', expectedFinalContent, chrome.test.succeed); // Truncate should fail only on read-only file system. - truncateFile(mountPoint, 'test_dir/test_file.tiff', kTruncateLongLength, - !isReadOnly, callback); + truncateFile(volumeId, fileSystem.root, 'test_dir/test_file.tiff', + kTruncateLongLength, !isReadOnly, callback); }); // Skip abort tests for read-only file systems. if (!isReadOnly) { testsToRun.push(function abortWriteTest() { - abortWriteFile(mountPoint, 'test_dir/test_file.xul.foo', + abortWriteFile(volumeId, fileSystem.root, 'test_dir/test_file.xul.foo', chrome.test.succeed); }); testsToRun.push(function abortTruncateTest() { - abortTruncateFile(mountPoint, 'test_dir/test_file.xul.foo', + abortTruncateFile(volumeId, fileSystem.root, 'test_dir/test_file.xul.foo', chrome.test.succeed); }); } @@ -371,22 +376,24 @@ function collectTestsForMountPoint(mountPointName, mountPoint) { if (isReadOnly) { // If the file system is read-only, the target file should not exist after // copy operation. - verifyTarget = getFile.bind(null, mountPoint, 'test_dir/subdir/copy', - false, false, chrome.test.succeed); + verifyTarget = getFile.bind(null, volumeId, fileSystem.root, + 'test_dir/subdir/copy', false, false, chrome.test.succeed); } else { // If the file system is not read-only, the target file should be created // during copy operation and its content should match the source file. - verifyTarget = readFileAndExpectContent.bind(null, mountPoint, - 'test_dir/subdir/copy', kInitialFileContent, chrome.test.succeed); + verifyTarget = readFileAndExpectContent.bind(null, volumeId, + fileSystem.root, 'test_dir/subdir/copy', kInitialFileContent, + chrome.test.succeed); } // Verify the source file stil exists and its content hasn't changed. - var verifySource = readFileAndExpectContent.bind(null, mountPoint, - 'test_dir/test_file.xul', kInitialFileContent, verifyTarget); + var verifySource = readFileAndExpectContent.bind(null, volumeId, + fileSystem.root, 'test_dir/test_file.xul', kInitialFileContent, + verifyTarget); // Copy file should fail on read-only file system. - copyFile(mountPoint, 'test_dir/test_file.xul', 'test_dir/subdir', - 'copy', !isReadOnly, chrome.test.succeed); + copyFile(volumeId, fileSystem.root, 'test_dir/test_file.xul', + 'test_dir/subdir', 'copy', !isReadOnly, chrome.test.succeed); }); testsToRun.push(function moveFileTest() { @@ -394,55 +401,57 @@ function collectTestsForMountPoint(mountPointName, mountPoint) { if (isReadOnly) { // If the file system is read-only, the target file should not be created // during move. - verifyTarget = getFile.bind(null, mountPoint, 'test_dir/subdir/move', - false, false, chrome.test.succeed); + verifyTarget = getFile.bind(null, volumeId, fileSystem.root, + 'test_dir/subdir/move', false, false, chrome.test.succeed); } else { // If the file system is read-only, the target file should be created // during move and its content should match the source file. - verifyTarget = readFileAndExpectContent.bind(null, mountPoint, - 'test_dir/subdir/move', kInitialFileContent, chrome.test.succeed); + verifyTarget = readFileAndExpectContent.bind(null, volumeId, + fileSystem.root, 'test_dir/subdir/move', kInitialFileContent, + chrome.test.succeed); } // On read-only file system the source file should still exist. Otherwise // the source file should have been deleted during move operation. - var verifySource = getFile.bind(null, mountPoint, + var verifySource = getFile.bind(null, volumeId, fileSystem.root, 'test_dir/test_file.xul', false, isReadOnly, verifyTarget); // Copy file should fail on read-only file system. - moveFile(mountPoint, 'test_dir/test_file.xul', 'test_dir/subdir', - 'move', !isReadOnly, chrome.test.succeed); + moveFile(volumeId, fileSystem.root, 'test_dir/test_file.xul', + 'test_dir/subdir', 'move', !isReadOnly, chrome.test.succeed); }); testsToRun.push(function deleteFileTest() { // Verify that file exists after delete operation if and only if the file // system is read only. - var callback = getFile.bind(null, mountPoint, 'test_dir/test_file.xul.foo', - false, isReadOnly, chrome.test.succeed); + var callback = getFile.bind(null, volumeId, fileSystem.root, + 'test_dir/test_file.xul.foo', false, isReadOnly, chrome.test.succeed); // Delete operation should fail for read-only file systems. - deleteFile(mountPoint, 'test_dir/test_file.xul.foo', !isReadOnly, callback); + deleteFile(volumeId, fileSystem.root, 'test_dir/test_file.xul.foo', + !isReadOnly, callback); }); testsToRun.push(function deleteEmptyDirectoryTest() { // Verify that the directory exists after delete operation if and only if // the file system is read-only. - var callback = getDirectory.bind(null, mountPoint, + var callback = getDirectory.bind(null, volumeId, fileSystem.root, 'test_dir/empty_test_dir', false, isReadOnly, chrome.test.succeed); // Deleting empty directory should fail for read-only file systems, and // succeed otherwise. - deleteDirectory(mountPoint, 'test_dir/empty_test_dir', !isReadOnly, - callback); + deleteDirectory(volumeId, fileSystem.root, 'test_dir/empty_test_dir', + !isReadOnly, callback); }); testsToRun.push(function deleteDirectoryTest() { // Verify that the directory still exists after the operation. - var callback = getDirectory.bind(null, mountPoint, 'test_dir', false, - true, chrome.test.succeed); + var callback = getDirectory.bind(null, volumeId, fileSystem.root, + 'test_dir', false, true, chrome.test.succeed); // The directory should still contain some files, so non-recursive delete // should fail. - deleteDirectory(mountPoint, 'test_dir', false, callback); + deleteDirectory(volumeId, fileSystem.root, 'test_dir', false, callback); }); // On drive, the directory was deleted in the previous test. @@ -450,11 +459,12 @@ function collectTestsForMountPoint(mountPointName, mountPoint) { testsToRun.push(function deleteDirectoryRecursivelyTest() { // Verify that the directory exists after delete operation if and only if // the file system is read-only. - var callback = getDirectory.bind(null, mountPoint, 'test_dir', false, - isReadOnly, chrome.test.succeed); + var callback = getDirectory.bind(null, volumeId, fileSystem.root, + 'test_dir', false, isReadOnly, chrome.test.succeed); // Recursive delete dhouls fail only for read-only file system. - deleteDirectoryRecursively(mountPoint, 'test_dir', !isReadOnly, callback); + deleteDirectoryRecursively(volumeId, fileSystem.root, 'test_dir', + !isReadOnly, callback); }); } @@ -463,41 +473,40 @@ function collectTestsForMountPoint(mountPointName, mountPoint) { /** * Initializes testParams. - * Gets test mount point and creates list of tests that should be run for it. + * Gets test volume and creates list of tests that should be run for it. * * @param {function(Array, string)} callback. Called with an array containing * the list of the tests to run and an error message. On error list of tests * to run will be null. */ function initTests(callback) { - chrome.fileBrowserPrivate.requestFileSystem( - 'compatible', - function(fileSystem) { - if(!fileSystem) { - callback(null, 'Failed to get file system.'); - return; - } - - var possibleMountPoints = ['local/', 'restricted/', 'drive/']; - - function tryNextMountPoint() { - if (possibleMountPoints.length == 0) { - callback(null, 'Failed to get test mount point.'); - return; - } - - var mountPointName = possibleMountPoints.shift(); + chrome.fileBrowserPrivate.getVolumeMetadataList(function(volumeMetadataList) { + var possibleVolumeTypes = ['testing', 'drive']; + + var sortedVolumeMetadataList = volumeMetadataList.filter(function(volume) { + return possibleVolumeTypes.indexOf(volume.volumeType) != -1; + }).sort(function(volumeA, volumeB) { + return possibleVolumeTypes.indexOf(volumeA.volumeType) > + possibleVolumeTypes.indexOf(volumeB.volumeType); + }); - fileSystem.root.getDirectory( - mountPointName, {}, - function(entry) { - var testsToRun = collectTestsForMountPoint(mountPointName, entry); - callback(testsToRun, 'Success.'); - }, - tryNextMountPoint); + if (sortedVolumeMetadataList.length == 0) { + callback(null, 'No volumes available, which could be used for testing.'); + return; } - tryNextMountPoint(); + chrome.fileBrowserPrivate.requestFileSystem( + sortedVolumeMetadataList[0].volumeId, + function(fileSystem) { + if (!fileSystem) { + callback(null, 'Failed to acquire the testing volume.'); + return; + } + + var testsToRun = collectTestsForVolumeId( + sortedVolumeMetadataList[0].volumeId, fileSystem); + callback(testsToRun, 'Success.'); + }); }); } diff --git a/chrome/test/data/extensions/api_test/file_browser/handler_test_runner/test.js b/chrome/test/data/extensions/api_test/file_browser/handler_test_runner/test.js index 87f1ecc..37d733b 100644 --- a/chrome/test/data/extensions/api_test/file_browser/handler_test_runner/test.js +++ b/chrome/test/data/extensions/api_test/file_browser/handler_test_runner/test.js @@ -6,8 +6,8 @@ * Runs test to verify that file browser tasks can successfully be executed. * The test does the following: * - Open external filesystem. - * - Get the test mount point root. The root is determined by probing exitents - * of root directories 'local' or 'drive'. + * - Get the test file system. The root is determined by probing volumes with + * whitelisted ids. * - Get files 'test_dir/test_file.xul' and 'test_dir/test_file.tiff' * on the test mount point. * Chrome part of the test should ensure that these actually exist. @@ -180,51 +180,42 @@ function run() { * Called when the test mount point has been determined. It starts resolving * test cases (i.e. getting file entries for the test file paths). * - * @param {DirectoryEntry} mountPointEntry The mount points root dir entry. + * @param {DOMFileSystem} fileSystem The testing volume. + * @param {string} volumeType Type of the volume. */ - function onFoundMountPoint(mountPointEntry) { - var isOnDrive = mountPointEntry.fullPath == '/drive'; + function onGotFileSystem(fileSystem, volumeType) { + var isOnDrive = volumeType == 'drive'; kTestCases.forEach(function(testCase) { - mountPointEntry.getFile( + fileSystem.root.getFile( (isOnDrive ? 'root/' : '') + testCase.path, {}, onGotEntry.bind(null, testCase.mimeType), onError.bind(null, 'Unable to get file: ' + testCase.path)); }); } - /** - * Callback for chrome.fileBrowserPrivate.requestFileSystem. - * When the local fileSystem is found, tries to get the test mount point root - * dir by probing for existence of possible mount point root dirs. - * The Chrome should have enabled either 'local/' or 'drive/' mount point. - * - * @param {FileSystem} fileSystem External file system. - */ - function onGotFileSystem(fileSystem) { - if (!fileSystem) { - onError('Failed to get file system for test.'); + chrome.fileBrowserPrivate.getVolumeMetadataList(function(volumeMetadataList) { + // Try to acquire the first volume which is either TESTING or DRIVE type. + var possibleVolumeTypes = ['testing', 'drive']; + var sortedVolumeMetadataList = volumeMetadataList.filter(function(volume) { + return possibleVolumeTypes.indexOf(volume.volumeType) != -1; + }).sort(function(volumeA, volumeB) { + return possibleVolumeTypes.indexOf(volumeA.volumeType) > + possibleVolumeTypes.indexOf(volumeB.volumeType); + }); + if (sortedVolumeMetadataList.length == 0) { + onError('No volumes available, which could be used for testing.'); return; } - - var possibleMountPoints = ['local/', 'drive/']; - - function tryNextMountPoint() { - if (possibleMountPoints.length == 0) { - onError('Unable to find mounted mount point.'); - return; - } - - var mountPointRoot = possibleMountPoints.shift(); - - fileSystem.root.getDirectory(mountPointRoot, {}, - onFoundMountPoint, - tryNextMountPoint); - } - - tryNextMountPoint(); - } - - chrome.fileBrowserPrivate.requestFileSystem('compatible', onGotFileSystem); + chrome.fileBrowserPrivate.requestFileSystem( + sortedVolumeMetadataList[0].volumeId, + function(fileSystem) { + if (!fileSystem) { + onError('Failed to acquire the testing volume.'); + return; + } + onGotFileSystem(fileSystem, sortedVolumeMetadataList[0].volumeType); + }); + }); } // Start the testing. diff --git a/content/browser/fileapi/copy_or_move_file_validator_unittest.cc b/content/browser/fileapi/copy_or_move_file_validator_unittest.cc index abba59a..be0f94b 100644 --- a/content/browser/fileapi/copy_or_move_file_validator_unittest.cc +++ b/content/browser/fileapi/copy_or_move_file_validator_unittest.cc @@ -70,8 +70,8 @@ class CopyOrMoveFileValidatorTestHelper { // Sets up source. fileapi::FileSystemBackend* src_file_system_backend = file_system_context_->GetFileSystemBackend(src_type_); - src_file_system_backend->OpenFileSystem( - origin_, src_type_, + src_file_system_backend->ResolveURL( + FileSystemURL::CreateForTest(origin_, src_type_, base::FilePath()), fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, base::Bind(&ExpectOk)); base::RunLoop().RunUntilIdle(); diff --git a/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc index 833b7a9..e9fbfae 100644 --- a/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc +++ b/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc @@ -208,9 +208,10 @@ class CopyOrMoveOperationTestHelper { // Prepare the origin's root directory. fileapi::FileSystemBackend* backend = file_system_context_->GetFileSystemBackend(src_type_); - backend->OpenFileSystem(origin_, src_type_, - fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, - base::Bind(&ExpectOk)); + backend->ResolveURL( + FileSystemURL::CreateForTest(origin_, src_type_, base::FilePath()), + fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, + base::Bind(&ExpectOk)); backend = file_system_context_->GetFileSystemBackend(dest_type_); if (dest_type_ == fileapi::kFileSystemTypeTest) { TestFileSystemBackend* test_backend = @@ -222,9 +223,10 @@ class CopyOrMoveOperationTestHelper { if (init_copy_or_move_validator) test_backend->InitializeCopyOrMoveFileValidatorFactory(factory.Pass()); } - backend->OpenFileSystem(origin_, dest_type_, - fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, - base::Bind(&ExpectOk)); + backend->ResolveURL( + FileSystemURL::CreateForTest(origin_, dest_type_, base::FilePath()), + fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, + base::Bind(&ExpectOk)); base::RunLoop().RunUntilIdle(); // Grant relatively big quota initially. diff --git a/content/browser/fileapi/sandbox_file_system_backend_unittest.cc b/content/browser/fileapi/sandbox_file_system_backend_unittest.cc index caca5b8..eda3461 100644 --- a/content/browser/fileapi/sandbox_file_system_backend_unittest.cc +++ b/content/browser/fileapi/sandbox_file_system_backend_unittest.cc @@ -20,6 +20,7 @@ #include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "webkit/common/fileapi/file_system_util.h" +using fileapi::FileSystemURL; using fileapi::SandboxFileSystemBackend; using fileapi::SandboxFileSystemBackendDelegate; @@ -117,8 +118,9 @@ class SandboxFileSystemBackendTest : public testing::Test { fileapi::OpenFileSystemMode mode, base::FilePath* root_path) { base::File::Error error = base::File::FILE_OK; - backend_->OpenFileSystem( - origin_url, type, mode, + backend_->ResolveURL( + FileSystemURL::CreateForTest(origin_url, type, base::FilePath()), + mode, base::Bind(&DidOpenFileSystem, &error)); base::RunLoop().RunUntilIdle(); if (error != base::File::FILE_OK) diff --git a/content/public/test/test_file_system_backend.cc b/content/public/test/test_file_system_backend.cc index d945460..b473716 100644 --- a/content/public/test/test_file_system_backend.cc +++ b/content/public/test/test_file_system_backend.cc @@ -179,13 +179,11 @@ bool TestFileSystemBackend::CanHandleType(FileSystemType type) const { void TestFileSystemBackend::Initialize(FileSystemContext* context) { } -void TestFileSystemBackend::OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) { - callback.Run(GetFileSystemRootURI(origin_url, type), - GetFileSystemName(origin_url, type), +void TestFileSystemBackend::ResolveURL(const FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) { + callback.Run(GetFileSystemRootURI(url.origin(), url.type()), + GetFileSystemName(url.origin(), url.type()), base::File::FILE_OK); } diff --git a/content/public/test/test_file_system_backend.h b/content/public/test/test_file_system_backend.h index e1a2bf4..1b0c76b 100644 --- a/content/public/test/test_file_system_backend.h +++ b/content/public/test/test_file_system_backend.h @@ -36,11 +36,9 @@ class TestFileSystemBackend : public fileapi::FileSystemBackend { // FileSystemBackend implementation. virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE; virtual void Initialize(fileapi::FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, - fileapi::OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const fileapi::FileSystemURL& url, + fileapi::OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual fileapi::AsyncFileUtil* GetAsyncFileUtil( fileapi::FileSystemType type) OVERRIDE; virtual fileapi::CopyOrMoveFileValidatorFactory* diff --git a/webkit/browser/fileapi/file_system_backend.h b/webkit/browser/fileapi/file_system_backend.h index e506550..52c0ec6 100644 --- a/webkit/browser/fileapi/file_system_backend.h +++ b/webkit/browser/fileapi/file_system_backend.h @@ -57,17 +57,15 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemBackend { // do additional initialization which depends on FileSystemContext here. virtual void Initialize(FileSystemContext* context) = 0; - // Opens the filesystem for the given |origin_url| and |type|. - // This verifies if it is allowed to request (or create) the filesystem - // and if it can access (or create) the root directory. - // If |mode| is CREATE_IF_NONEXISTENT calling this may also create - // the root directory (and/or related database entries etc) for - // the filesystem if it doesn't exist. - virtual void OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) = 0; + // Resolves the filesystem root URL and the name for the given |url|. + // This verifies if it is allowed to request (or create) the filesystem and if + // it can access (or create) the root directory. + // If |mode| is CREATE_IF_NONEXISTENT calling this may also create the root + // directory (and/or related database entries etc) for the filesystem if it + // doesn't exist. + virtual void ResolveURL(const FileSystemURL& url, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) = 0; // Returns the specialized AsyncFileUtil for this backend. virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) = 0; diff --git a/webkit/browser/fileapi/file_system_context.cc b/webkit/browser/fileapi/file_system_context.cc index 17f9cf8..c42eadb 100644 --- a/webkit/browser/fileapi/file_system_context.cc +++ b/webkit/browser/fileapi/file_system_context.cc @@ -307,31 +307,20 @@ void FileSystemContext::OpenFileSystem( return; } - backend->OpenFileSystem(origin_url, type, mode, callback); + backend->ResolveURL( + CreateCrackedFileSystemURL(origin_url, type, base::FilePath()), + mode, + callback); } void FileSystemContext::ResolveURL( const FileSystemURL& url, const ResolveURLCallback& callback) { + // TODO(nhiroki, kinuko): Remove this thread restriction, so it can be called + // on either UI or IO thread. DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); DCHECK(!callback.is_null()); - if (!FileSystemContext::IsSandboxFileSystem(url.type())) { -#ifdef OS_CHROMEOS - // Do not have to open a non-sandboxed filesystem. - // TODO(nhiroki): For now we assume this path is called only on ChromeOS, - // but this assumption may be broken in the future and we should handle - // more generally. http://crbug.com/304062. - FileSystemInfo info = GetFileSystemInfoForChromeOS(url.origin()); - DidOpenFileSystemForResolveURL( - url, callback, info.root_url, info.name, base::File::FILE_OK); - return; -#endif - callback.Run(base::File::FILE_ERROR_SECURITY, - FileSystemInfo(), base::FilePath(), false); - return; - } - FileSystemBackend* backend = GetFileSystemBackend(url.type()); if (!backend) { callback.Run(base::File::FILE_ERROR_SECURITY, @@ -339,11 +328,13 @@ void FileSystemContext::ResolveURL( return; } - backend->OpenFileSystem( - url.origin(), url.type(), + backend->ResolveURL( + url, OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, base::Bind(&FileSystemContext::DidOpenFileSystemForResolveURL, - this, url, callback)); + this, + url, + callback)); } void FileSystemContext::DeleteFileSystem( diff --git a/webkit/browser/fileapi/isolated_file_system_backend.cc b/webkit/browser/fileapi/isolated_file_system_backend.cc index 06050f8..a8acffb 100644 --- a/webkit/browser/fileapi/isolated_file_system_backend.cc +++ b/webkit/browser/fileapi/isolated_file_system_backend.cc @@ -57,17 +57,16 @@ bool IsolatedFileSystemBackend::CanHandleType(FileSystemType type) const { void IsolatedFileSystemBackend::Initialize(FileSystemContext* context) { } -void IsolatedFileSystemBackend::OpenFileSystem( - const GURL& origin_url, - FileSystemType type, +void IsolatedFileSystemBackend::ResolveURL( + const FileSystemURL& url, OpenFileSystemMode mode, const OpenFileSystemCallback& callback) { - // We never allow opening a new isolated FileSystem via usual OpenFileSystem. + // We never allow opening a new isolated FileSystem via usual ResolveURL. base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(callback, - GetFileSystemRootURI(origin_url, type), - GetFileSystemName(origin_url, type), + GURL(), + std::string(), base::File::FILE_ERROR_SECURITY)); } diff --git a/webkit/browser/fileapi/isolated_file_system_backend.h b/webkit/browser/fileapi/isolated_file_system_backend.h index ca266e8..1c2edfdd 100644 --- a/webkit/browser/fileapi/isolated_file_system_backend.h +++ b/webkit/browser/fileapi/isolated_file_system_backend.h @@ -20,11 +20,9 @@ class IsolatedFileSystemBackend : public FileSystemBackend { // FileSystemBackend implementation. virtual bool CanHandleType(FileSystemType type) const OVERRIDE; virtual void Initialize(FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const FileSystemURL& url, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, diff --git a/webkit/browser/fileapi/plugin_private_file_system_backend.cc b/webkit/browser/fileapi/plugin_private_file_system_backend.cc index 35ad8eb..2c8ed3b 100644 --- a/webkit/browser/fileapi/plugin_private_file_system_backend.cc +++ b/webkit/browser/fileapi/plugin_private_file_system_backend.cc @@ -143,13 +143,12 @@ bool PluginPrivateFileSystemBackend::CanHandleType(FileSystemType type) const { void PluginPrivateFileSystemBackend::Initialize(FileSystemContext* context) { } -void PluginPrivateFileSystemBackend::OpenFileSystem( - const GURL& origin_url, - FileSystemType type, +void PluginPrivateFileSystemBackend::ResolveURL( + const FileSystemURL& url, OpenFileSystemMode mode, const OpenFileSystemCallback& callback) { // We never allow opening a new plugin-private filesystem via usual - // OpenFileSystem. + // ResolveURL. base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(callback, GURL(), std::string(), diff --git a/webkit/browser/fileapi/plugin_private_file_system_backend.h b/webkit/browser/fileapi/plugin_private_file_system_backend.h index 7dc2e13..35612b1 100644 --- a/webkit/browser/fileapi/plugin_private_file_system_backend.h +++ b/webkit/browser/fileapi/plugin_private_file_system_backend.h @@ -61,11 +61,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT PluginPrivateFileSystemBackend // FileSystemBackend overrides. virtual bool CanHandleType(FileSystemType type) const OVERRIDE; virtual void Initialize(FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const FileSystemURL& url, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, diff --git a/webkit/browser/fileapi/sandbox_file_system_backend.cc b/webkit/browser/fileapi/sandbox_file_system_backend.cc index 62f91de..cb288aa 100644 --- a/webkit/browser/fileapi/sandbox_file_system_backend.cc +++ b/webkit/browser/fileapi/sandbox_file_system_backend.cc @@ -60,24 +60,25 @@ void SandboxFileSystemBackend::Initialize(FileSystemContext* context) { delegate_->quota_observer(), NULL); } -void SandboxFileSystemBackend::OpenFileSystem( - const GURL& origin_url, - fileapi::FileSystemType type, +void SandboxFileSystemBackend::ResolveURL( + const FileSystemURL& url, OpenFileSystemMode mode, const OpenFileSystemCallback& callback) { - DCHECK(CanHandleType(type)); + DCHECK(CanHandleType(url.type())); DCHECK(delegate_); if (delegate_->file_system_options().is_incognito() && - !(type == kFileSystemTypeTemporary && + !(url.type() == kFileSystemTypeTemporary && enable_temporary_file_system_in_incognito_)) { // TODO(kinuko): return an isolated temporary directory. callback.Run(GURL(), std::string(), base::File::FILE_ERROR_SECURITY); return; } - delegate_->OpenFileSystem( - origin_url, type, mode, callback, - GetFileSystemRootURI(origin_url, type)); + delegate_->OpenFileSystem(url.origin(), + url.type(), + mode, + callback, + GetFileSystemRootURI(url.origin(), url.type())); } AsyncFileUtil* SandboxFileSystemBackend::GetAsyncFileUtil( diff --git a/webkit/browser/fileapi/sandbox_file_system_backend.h b/webkit/browser/fileapi/sandbox_file_system_backend.h index 7dd7eb8..f82c294 100644 --- a/webkit/browser/fileapi/sandbox_file_system_backend.h +++ b/webkit/browser/fileapi/sandbox_file_system_backend.h @@ -21,7 +21,6 @@ namespace fileapi { -// An interface to construct or crack sandboxed filesystem paths for // TEMPORARY or PERSISTENT filesystems, which are placed under the user's // profile directory in a sandboxed way. // This interface also lets one enumerate and remove storage for the origins @@ -35,11 +34,9 @@ class WEBKIT_STORAGE_BROWSER_EXPORT SandboxFileSystemBackend // FileSystemBackend overrides. virtual bool CanHandleType(FileSystemType type) const OVERRIDE; virtual void Initialize(FileSystemContext* context) OVERRIDE; - virtual void OpenFileSystem( - const GURL& origin_url, - FileSystemType type, - OpenFileSystemMode mode, - const OpenFileSystemCallback& callback) OVERRIDE; + virtual void ResolveURL(const FileSystemURL& url, + OpenFileSystemMode mode, + const OpenFileSystemCallback& callback) OVERRIDE; virtual AsyncFileUtil* GetAsyncFileUtil(FileSystemType type) OVERRIDE; virtual CopyOrMoveFileValidatorFactory* GetCopyOrMoveFileValidatorFactory( FileSystemType type, diff --git a/webkit/common/fileapi/file_system_util.cc b/webkit/common/fileapi/file_system_util.cc index 9f01b3e..07136e6 100644 --- a/webkit/common/fileapi/file_system_util.cc +++ b/webkit/common/fileapi/file_system_util.cc @@ -445,13 +445,4 @@ base::File::Error NetErrorToFileError(int error) { } } -#if defined(OS_CHROMEOS) -FileSystemInfo GetFileSystemInfoForChromeOS(const GURL& origin_url) { - FileSystemType mount_type = fileapi::kFileSystemTypeExternal; - return FileSystemInfo(fileapi::GetFileSystemName(origin_url, mount_type), - fileapi::GetFileSystemRootURI(origin_url, mount_type), - mount_type); -} -#endif - } // namespace fileapi diff --git a/webkit/common/fileapi/file_system_util.h b/webkit/common/fileapi/file_system_util.h index 3ed3769..32463bd 100644 --- a/webkit/common/fileapi/file_system_util.h +++ b/webkit/common/fileapi/file_system_util.h @@ -168,15 +168,6 @@ WEBKIT_STORAGE_COMMON_EXPORT std::string GetExternalFileSystemRootURIString( WEBKIT_STORAGE_COMMON_EXPORT base::File::Error NetErrorToFileError(int error); -#if defined(OS_CHROMEOS) -// Returns the filesystem info that can be specified by |origin_url|. -// TODO(nhiroki): This should be deprecated and use -// GetExternalFileSystemRootURIString() to get separate file systems for each -// mount type. http://crbug.com/284963. -WEBKIT_STORAGE_COMMON_EXPORT FileSystemInfo -GetFileSystemInfoForChromeOS(const GURL& origin_url); -#endif - } // namespace fileapi #endif // WEBKIT_COMMON_FILEAPI_FILE_SYSTEM_UTIL_H_ |