diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-28 21:06:48 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-28 21:06:48 +0000 |
commit | 65486ad7c53dd9da35c5464bf8f6ade16bca1f58 (patch) | |
tree | 54bd4e702efaf01d0abf5c2e2ae4edb4a7cc898a /chrome | |
parent | 20e7cd1e49135d40d2d84f87358000defbf82cf6 (diff) | |
download | chromium_src-65486ad7c53dd9da35c5464bf8f6ade16bca1f58.zip chromium_src-65486ad7c53dd9da35c5464bf8f6ade16bca1f58.tar.gz chromium_src-65486ad7c53dd9da35c5464bf8f6ade16bca1f58.tar.bz2 |
Change media galleries to external file system type to add toURL support
BUG=160900
R=creis@chromium.org, joi@chromium.org, thestig@chromium.org, tsepez@chromium.org, tzik@chromium.org
Review URL: https://codereview.chromium.org/185393012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260276 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
24 files changed, 720 insertions, 258 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 50a0d93d..2f5b3a5 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -2567,6 +2567,10 @@ void ChromeContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem( void ChromeContentBrowserClient::GetURLRequestAutoMountHandlers( std::vector<fileapi::URLRequestAutoMountHandler>* handlers) { +#if !defined(OS_ANDROID) + handlers->push_back( + base::Bind(MediaFileSystemBackend::AttemptAutoMountForURLRequest)); +#endif // OS_ANDROID } void ChromeContentBrowserClient::GetAdditionalFileSystemBackends( diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc index 6e16654..a929d3e 100644 --- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc +++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc @@ -176,11 +176,11 @@ base::ListValue* ConstructFileSystemList( if (has_read_permission) { content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); - policy->GrantReadFileSystem(child_id, filesystems[i].fsid); + policy->GrantReadFile(child_id, filesystems[i].path); if (has_delete_permission) { - policy->GrantDeleteFromFileSystem(child_id, filesystems[i].fsid); + policy->GrantDeleteFrom(child_id, filesystems[i].path); if (has_copy_to_permission) { - policy->GrantCopyIntoFileSystem(child_id, filesystems[i].fsid); + policy->GrantCopyInto(child_id, filesystems[i].path); } } } diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc index e2f9070..45a1a5f 100644 --- a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc +++ b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc @@ -195,7 +195,7 @@ class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest { // This function makes a single fake gallery. This is needed to test platforms // with no default media galleries, such as CHROMEOS. This fake gallery is // pre-populated with a test.jpg and test.txt. - void MakeSingleFakeGallery() { + void MakeSingleFakeGallery(MediaGalleryPrefId* pref_id) { ASSERT_FALSE(fake_gallery_temp_dir_.IsValid()); ASSERT_TRUE(fake_gallery_temp_dir_.CreateUniqueTempDir()); @@ -204,15 +204,18 @@ class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest { MediaGalleryPrefInfo gallery_info; ASSERT_FALSE(preferences->LookUpGalleryByPath(fake_gallery_temp_dir_.path(), &gallery_info)); - preferences->AddGallery(gallery_info.device_id, - gallery_info.path, - MediaGalleryPrefInfo::kAutoDetected, - gallery_info.volume_label, - gallery_info.vendor_name, - gallery_info.model_name, - gallery_info.total_size_in_bytes, - gallery_info.last_attach_time, - 0, 0, 0); + MediaGalleryPrefId id = preferences->AddGallery( + gallery_info.device_id, + gallery_info.path, + MediaGalleryPrefInfo::kAutoDetected, + gallery_info.volume_label, + gallery_info.vendor_name, + gallery_info.model_name, + gallery_info.total_size_in_bytes, + gallery_info.last_attach_time, + 0, 0, 0); + if (pref_id) + *pref_id = id; content::RunAllPendingInMessageLoop(); @@ -427,7 +430,7 @@ class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest { #endif IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, MAYBE_MediaGalleriesNoAccess) { - MakeSingleFakeGallery(); + MakeSingleFakeGallery(NULL); base::ListValue custom_args; custom_args.AppendInteger(num_galleries() + 1); @@ -448,7 +451,7 @@ IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, MediaGalleriesRead) { RemoveAllGalleries(); - MakeSingleFakeGallery(); + MakeSingleFakeGallery(NULL); base::ListValue custom_args; custom_args.AppendInteger(test_jpg_size()); @@ -466,13 +469,13 @@ IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, MAYBE_MediaGalleriesCopyTo) { RemoveAllGalleries(); - MakeSingleFakeGallery(); + MakeSingleFakeGallery(NULL); ASSERT_TRUE(RunMediaGalleriesTest("copy_to_access")) << message_; } IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, MediaGalleriesDelete) { - MakeSingleFakeGallery(); + MakeSingleFakeGallery(NULL); base::ListValue custom_args; custom_args.AppendInteger(num_galleries() + 1); ASSERT_TRUE(RunMediaGalleriesTestWithArg("delete_access", custom_args)) @@ -584,9 +587,22 @@ IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, MAYBE_Scan) { ASSERT_TRUE(RunMediaGalleriesTest("scan")) << message_; } +IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, ToURL) { + RemoveAllGalleries(); + MediaGalleryPrefId pref_id; + MakeSingleFakeGallery(&pref_id); + + base::ListValue custom_args; + custom_args.AppendInteger(base::checked_cast<int>(pref_id)); + custom_args.AppendString( + browser()->profile()->GetPath().BaseName().MaybeAsASCII()); + + ASSERT_TRUE(RunMediaGalleriesTestWithArg("tourl", custom_args)) << message_; +} + IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, GetMetadata) { RemoveAllGalleries(); - MakeSingleFakeGallery(); + MakeSingleFakeGallery(NULL); AddFileToSingleFakeGallery(media::GetTestDataFilePath("90rotation.mp4")); AddFileToSingleFakeGallery(media::GetTestDataFilePath("id3_png_test.mp3")); diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc index da66f2e..f04a5c9 100644 --- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc @@ -49,13 +49,13 @@ void CreateSnapshotFileOnBlockingPool( const base::FilePath& profile_path, base::FilePath* snapshot_file_path) { DCHECK(snapshot_file_path); - base::FilePath isolated_media_file_system_dir_path = + base::FilePath media_file_system_dir_path = profile_path.AppendASCII(kDeviceMediaAsyncFileUtilTempDir); - if (!base::CreateDirectory(isolated_media_file_system_dir_path) || - !base::CreateTemporaryFileInDir(isolated_media_file_system_dir_path, + if (!base::CreateDirectory(media_file_system_dir_path) || + !base::CreateTemporaryFileInDir(media_file_system_dir_path, snapshot_file_path)) { LOG(WARNING) << "Could not create media snapshot file " - << isolated_media_file_system_dir_path.value(); + << media_file_system_dir_path.value(); *snapshot_file_path = base::FilePath(); } } diff --git a/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc b/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc index f355957..38ae639 100644 --- a/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc @@ -47,6 +47,21 @@ bool ContainsElement(const std::vector<T>& collection, const T& key) { return false; } +std::vector<std::string> GetVirtualPathComponents( + const fileapi::FileSystemURL& url) { + ImportedMediaGalleryRegistry* imported_registry = + ImportedMediaGalleryRegistry::GetInstance(); + base::FilePath root = imported_registry->ImportedRoot().AppendASCII("iphoto"); + + DCHECK(root.IsParent(url.path()) || root == url.path()); + base::FilePath virtual_path; + root.AppendRelativePath(url.path(), &virtual_path); + + std::vector<std::string> result; + fileapi::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result); + return result; +} + } // namespace const char kIPhotoAlbumsDir[] = "Albums"; @@ -156,8 +171,7 @@ base::File::Error IPhotoFileUtil::GetFileInfoSync( const fileapi::FileSystemURL& url, base::File::Info* file_info, base::FilePath* platform_path) { - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); if (components.size() == 0) { return MakeDirectoryFileInfo(file_info); @@ -206,8 +220,7 @@ base::File::Error IPhotoFileUtil::ReadDirectorySync( const fileapi::FileSystemURL& url, EntryList* file_list) { DCHECK(file_list->empty()); - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); // Root directory. Child is the /Albums dir. if (components.size() == 0) { @@ -290,8 +303,7 @@ base::File::Error IPhotoFileUtil::GetLocalFilePath( fileapi::FileSystemOperationContext* context, const fileapi::FileSystemURL& url, base::FilePath* local_file_path) { - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); if (components.size() == 3 && components[0] == kIPhotoAlbumsDir) { base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum( diff --git a/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc index 645beaf..9ffcceb 100644 --- a/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc @@ -18,6 +18,7 @@ #include "chrome/browser/media_galleries/fileapi/iphoto_file_util.h" #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" +#include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread.h" #include "content/public/test/test_file_system_options.h" @@ -185,6 +186,7 @@ class IPhotoFileUtilTest : public testing::Test { virtual void SetUp() OVERRIDE { ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); + ImportedMediaGalleryRegistry::GetInstance()->Initialize(); scoped_refptr<quota::SpecialStoragePolicy> storage_policy = new quota::MockSpecialStoragePolicy(); @@ -229,10 +231,14 @@ class IPhotoFileUtilTest : public testing::Test { ASSERT_FALSE(completed); } - FileSystemURL CreateURL(const std::string& virtual_path) const { + FileSystemURL CreateURL(const std::string& path) const { + base::FilePath virtual_path = + ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot(); + virtual_path = virtual_path.AppendASCII("iphoto"); + virtual_path = virtual_path.AppendASCII(path); return file_system_context_->CreateCrackedFileSystemURL( GURL("http://www.example.com"), fileapi::kFileSystemTypeIphoto, - base::FilePath::FromUTF8Unsafe(virtual_path)); + virtual_path); } fileapi::FileSystemOperationRunner* operation_runner() const { diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc index 07371f5..9b49c94 100644 --- a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc @@ -34,6 +34,21 @@ base::File::Error MakeDirectoryFileInfo(base::File::Info* file_info) { return base::File::FILE_OK; } +std::vector<std::string> GetVirtualPathComponents( + const fileapi::FileSystemURL& url) { + ImportedMediaGalleryRegistry* imported_registry = + ImportedMediaGalleryRegistry::GetInstance(); + base::FilePath root = imported_registry->ImportedRoot().AppendASCII("itunes"); + + DCHECK(root.IsParent(url.path()) || root == url.path()); + base::FilePath virtual_path; + root.AppendRelativePath(url.path(), &virtual_path); + + std::vector<std::string> result; + fileapi::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result); + return result; +} + } // namespace const char kITunesLibraryXML[] = "iTunes Music Library.xml"; @@ -91,8 +106,7 @@ base::File::Error ITunesFileUtil::GetFileInfoSync( const fileapi::FileSystemURL& url, base::File::Info* file_info, base::FilePath* platform_path) { - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); if (components.size() == 0) return MakeDirectoryFileInfo(file_info); @@ -153,8 +167,7 @@ base::File::Error ITunesFileUtil::ReadDirectorySync( const fileapi::FileSystemURL& url, EntryList* file_list) { DCHECK(file_list->empty()); - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); if (components.size() == 0) { base::File::Info xml_info; @@ -264,8 +277,8 @@ base::File::Error ITunesFileUtil::CreateSnapshotFileSync( base::File::Info* file_info, base::FilePath* platform_path, scoped_refptr<webkit_blob::ShareableFileReference>* file_ref) { - DCHECK(!url.path().IsAbsolute()); - if (url.path() != base::FilePath().AppendASCII(kITunesLibraryXML)) { + std::vector<std::string> components = GetVirtualPathComponents(url); + if (components.size() != 1 || components[0] != kITunesLibraryXML) { return NativeMediaFileUtil::CreateSnapshotFileSync(context, url, file_info, platform_path, file_ref); } @@ -284,8 +297,7 @@ base::File::Error ITunesFileUtil::GetLocalFilePath( fileapi::FileSystemOperationContext* context, const fileapi::FileSystemURL& url, base::FilePath* local_file_path) { - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); if (components.size() == 1 && components[0] == kITunesLibraryXML) { *local_file_path = GetDataProvider()->library_path(); diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc index 43a09be..11b5973 100644 --- a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc @@ -17,6 +17,7 @@ #include "chrome/browser/media_galleries/fileapi/itunes_file_util.h" #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" +#include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread.h" #include "content/public/test/test_file_system_options.h" @@ -153,6 +154,7 @@ class ItunesFileUtilTest : public testing::Test { virtual void SetUp() OVERRIDE { ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); + ImportedMediaGalleryRegistry::GetInstance()->Initialize(); scoped_refptr<quota::SpecialStoragePolicy> storage_policy = new quota::MockSpecialStoragePolicy(); @@ -197,10 +199,14 @@ class ItunesFileUtilTest : public testing::Test { ASSERT_FALSE(completed); } - FileSystemURL CreateURL(const std::string& virtual_path) const { + FileSystemURL CreateURL(const std::string& path) const { + base::FilePath virtual_path = + ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot(); + virtual_path = virtual_path.AppendASCII("itunes"); + virtual_path = virtual_path.AppendASCII(path); return file_system_context_->CreateCrackedFileSystemURL( GURL("http://www.example.com"), fileapi::kFileSystemTypeItunes, - base::FilePath::FromUTF8Unsafe(virtual_path)); + virtual_path); } fileapi::FileSystemOperationRunner* operation_runner() const { 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 eab10d4..3be12a7 100644 --- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc +++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc @@ -12,19 +12,31 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/platform_file.h" #include "base/sequenced_task_runner.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/threading/sequenced_worker_pool.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h" #include "chrome/browser/media_galleries/fileapi/media_file_validator_factory.h" #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h" +#include "chrome/browser/media_galleries/media_file_system_registry.h" +#include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/resource_request_info.h" +#include "extensions/browser/extension_system.h" +#include "net/url_request/url_request.h" #include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/copy_or_move_file_validator.h" #include "webkit/browser/fileapi/file_stream_writer.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation.h" #include "webkit/browser/fileapi/file_system_operation_context.h" -#include "webkit/browser/fileapi/isolated_context.h" +#include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/native_file_util.h" #include "webkit/common/fileapi/file_system_types.h" #include "webkit/common/fileapi/file_system_util.h" @@ -41,6 +53,67 @@ using fileapi::FileSystemContext; using fileapi::FileSystemURL; +namespace { + +const char kMediaGalleryMountPrefix[] = "media_galleries-"; + +void OnPreferencesInit( + const content::RenderViewHost* rvh, + const extensions::Extension* extension, + MediaGalleryPrefId pref_id, + const base::Callback<void(base::File::Error result)>& callback) { + MediaFileSystemRegistry* registry = + g_browser_process->media_file_system_registry(); + registry->RegisterMediaFileSystemForExtension(rvh, extension, pref_id, + callback); +} + +void AttemptAutoMountOnUIThread( + int32 process_id, + int32 routing_id, + const std::string& storage_domain, + const std::string& mount_point, + const base::Callback<void(base::File::Error result)>& callback) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + + content::RenderViewHost* rvh = + content::RenderViewHost::FromID(process_id, routing_id); + if (rvh) { + Profile* profile = + Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext()); + + ExtensionService* extension_service = + extensions::ExtensionSystem::Get(profile)->extension_service(); + const extensions::Extension* extension = + extension_service->GetExtensionById(storage_domain, + false /*include disabled*/); + std::string expected_mount_prefix = + MediaFileSystemBackend::ConstructMountName( + profile->GetPath(), storage_domain, kInvalidMediaGalleryPrefId); + MediaGalleryPrefId pref_id = kInvalidMediaGalleryPrefId; + if (extension && + extension->id() == storage_domain && + StartsWithASCII(mount_point, expected_mount_prefix, true) && + base::StringToUint64(mount_point.substr(expected_mount_prefix.size()), + &pref_id) && + pref_id != kInvalidMediaGalleryPrefId) { + MediaGalleriesPreferences* preferences = + g_browser_process->media_file_system_registry()->GetPreferences( + profile); + preferences->EnsureInitialized( + base::Bind(&OnPreferencesInit, rvh, extension, pref_id, callback)); + return; + } + } + + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND)); +} + +} // namespace + const char MediaFileSystemBackend::kMediaTaskRunnerName[] = "media-task-runner"; @@ -87,6 +160,59 @@ MediaFileSystemBackend::MediaTaskRunner() { return pool->GetSequencedTaskRunner(media_sequence_token); } +// static +std::string MediaFileSystemBackend::ConstructMountName( + const base::FilePath& profile_path, + const std::string& extension_id, + MediaGalleryPrefId pref_id) { + std::string name(kMediaGalleryMountPrefix); + name.append(profile_path.BaseName().MaybeAsASCII()); + name.append("-"); + name.append(extension_id); + name.append("-"); + if (pref_id != kInvalidMediaGalleryPrefId) + name.append(base::Uint64ToString(pref_id)); + base::ReplaceChars(name, " /", "_", &name); + return name; +} + +// static +bool MediaFileSystemBackend::AttemptAutoMountForURLRequest( + const net::URLRequest* url_request, + const fileapi::FileSystemURL& filesystem_url, + const std::string& storage_domain, + const base::Callback<void(base::File::Error result)>& callback) { + if (storage_domain.empty() || + filesystem_url.type() != fileapi::kFileSystemTypeExternal || + storage_domain != filesystem_url.origin().host()) { + return false; + } + + const base::FilePath& virtual_path = filesystem_url.path(); + if (virtual_path.ReferencesParent()) + return false; + std::vector<base::FilePath::StringType> components; + virtual_path.GetComponents(&components); + if (components.empty()) + return false; + std::string mount_point = base::FilePath(components[0]).AsUTF8Unsafe(); + if (!StartsWithASCII(mount_point, kMediaGalleryMountPrefix, true)) + return false; + + const content::ResourceRequestInfo* request_info = + content::ResourceRequestInfo::ForRequest(url_request); + if (!request_info) + return false; + + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::Bind(&AttemptAutoMountOnUIThread, request_info->GetChildID(), + request_info->GetRouteID(), storage_domain, mount_point, + callback)); + return true; +} + bool MediaFileSystemBackend::CanHandleType( fileapi::FileSystemType type) const { switch (type) { @@ -112,7 +238,7 @@ void MediaFileSystemBackend::ResolveURL( const FileSystemURL& url, fileapi::OpenFileSystemMode mode, const OpenFileSystemCallback& callback) { - // We never allow opening a new isolated FileSystem via usual ResolveURL. + // We never allow opening a new FileSystem via usual ResolveURL. base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(callback, 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 7dbfbd1..c5b7991 100644 --- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h +++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h @@ -5,20 +5,28 @@ #ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_MEDIA_FILE_SYSTEM_BACKEND_H_ #define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_MEDIA_FILE_SYSTEM_BACKEND_H_ +#include <string> + +#include "base/callback.h" +#include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "chrome/browser/media_galleries/media_galleries_preferences.h" #include "webkit/browser/fileapi/file_system_backend.h" namespace base { class SequencedTaskRunner; } +namespace fileapi { +class FileSystemURL; +} + namespace net { class URLRequest; } class MediaPathFilter; - class DeviceMediaAsyncFileUtil; class MediaFileSystemBackend : public fileapi::FileSystemBackend { @@ -33,6 +41,12 @@ class MediaFileSystemBackend : public fileapi::FileSystemBackend { static bool CurrentlyOnMediaTaskRunnerThread(); static scoped_refptr<base::SequencedTaskRunner> MediaTaskRunner(); + // Construct the mount point for the gallery specified by |pref_id| in + // the profile located in |profile_path|. + static std::string ConstructMountName(const base::FilePath& profile_path, + const std::string& extension_id, + MediaGalleryPrefId pref_id); + static bool AttemptAutoMountForURLRequest( const net::URLRequest* url_request, const fileapi::FileSystemURL& filesystem_url, diff --git a/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h b/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h index a6cfebf..e28c9a6 100644 --- a/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h +++ b/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h @@ -19,7 +19,7 @@ class IOBuffer; } // Asynchronous delegate for media transfer protocol (MTP) device to perform -// media device isolated file system operations. Class that implements this +// media device file system operations. Class that implements this // delegate does the actual communication with the MTP device. // The lifetime of the delegate is managed by the MTPDeviceMapService class. // Member functions and callbacks run on the IO thread. diff --git a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc index 69d8d07..295c019 100644 --- a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc +++ b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc @@ -10,7 +10,7 @@ #include "base/stl_util.h" #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h" #include "content/public/browser/browser_thread.h" -#include "webkit/browser/fileapi/isolated_context.h" +#include "webkit/browser/fileapi/external_mount_points.h" namespace { @@ -85,7 +85,7 @@ MTPDeviceAsyncDelegate* MTPDeviceMapService::GetMTPDeviceAsyncDelegate( const std::string& filesystem_id) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); base::FilePath device_path; - if (!fileapi::IsolatedContext::GetInstance()->GetRegisteredPath( + if (!fileapi::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath( filesystem_id, &device_path)) { return NULL; } diff --git a/chrome/browser/media_galleries/fileapi/picasa_file_util.cc b/chrome/browser/media_galleries/fileapi/picasa_file_util.cc index 646f9548..6b3ca1f 100644 --- a/chrome/browser/media_galleries/fileapi/picasa_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/picasa_file_util.cc @@ -49,11 +49,24 @@ base::File::Error FindAlbumInfo(const std::string& key, return base::File::FILE_OK; } -PicasaDataProvider::DataType GetDataTypeForURL( +std::vector<std::string> GetVirtualPathComponents( const fileapi::FileSystemURL& url) { - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + ImportedMediaGalleryRegistry* imported_registry = + ImportedMediaGalleryRegistry::GetInstance(); + base::FilePath root = imported_registry->ImportedRoot().AppendASCII("picasa"); + + DCHECK(root.IsParent(url.path()) || root == url.path()); + base::FilePath virtual_path; + root.AppendRelativePath(url.path(), &virtual_path); + + std::vector<std::string> result; + fileapi::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result); + return result; +} +PicasaDataProvider::DataType GetDataTypeForURL( + const fileapi::FileSystemURL& url) { + std::vector<std::string> components = GetVirtualPathComponents(url); if (components.size() >= 2 && components[0] == kPicasaDirAlbums) return PicasaDataProvider::ALBUMS_IMAGES_DATA; @@ -107,8 +120,7 @@ base::File::Error PicasaFileUtil::GetFileInfoSync( if (platform_path) *platform_path = base::FilePath(); - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); switch (components.size()) { case 0: @@ -176,9 +188,7 @@ base::File::Error PicasaFileUtil::ReadDirectorySync( if (!file_info.is_directory) return base::File::FILE_ERROR_NOT_A_DIRECTORY; - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); - + std::vector<std::string> components = GetVirtualPathComponents(url); switch (components.size()) { case 0: { // Root directory. @@ -283,8 +293,7 @@ base::File::Error PicasaFileUtil::GetLocalFilePath( base::FilePath* local_file_path) { DCHECK(local_file_path); DCHECK(url.is_valid()); - std::vector<std::string> components; - fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components); + std::vector<std::string> components = GetVirtualPathComponents(url); switch (components.size()) { case 2: diff --git a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc index c70c2ca..edd294c 100644 --- a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc @@ -22,6 +22,7 @@ #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" #include "chrome/browser/media_galleries/fileapi/picasa_data_provider.h" #include "chrome/browser/media_galleries/fileapi/picasa_file_util.h" +#include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "chrome/common/media_galleries/picasa_types.h" #include "chrome/common/media_galleries/pmp_constants.h" #include "content/public/browser/browser_thread.h" @@ -228,6 +229,7 @@ class PicasaFileUtilTest : public testing::Test { virtual void SetUp() OVERRIDE { ASSERT_TRUE(profile_dir_.CreateUniqueTempDir()); + ImportedMediaGalleryRegistry::GetInstance()->Initialize(); scoped_refptr<quota::SpecialStoragePolicy> storage_policy = new quota::MockSpecialStoragePolicy(); @@ -356,10 +358,14 @@ class PicasaFileUtilTest : public testing::Test { EXPECT_EQ(0u, contents.size()); } - FileSystemURL CreateURL(const std::string& virtual_path) const { + FileSystemURL CreateURL(const std::string& path) const { + base::FilePath virtual_path = + ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot(); + virtual_path = virtual_path.AppendASCII("picasa"); + virtual_path = virtual_path.AppendASCII(path); return file_system_context_->CreateCrackedFileSystemURL( GURL("http://www.example.com"), fileapi::kFileSystemTypePicasa, - base::FilePath::FromUTF8Unsafe(virtual_path)); + virtual_path); } fileapi::FileSystemOperationRunner* operation_runner() const { diff --git a/chrome/browser/media_galleries/imported_media_gallery_registry.cc b/chrome/browser/media_galleries/imported_media_gallery_registry.cc index 245d051..506b8c9 100644 --- a/chrome/browser/media_galleries/imported_media_gallery_registry.cc +++ b/chrome/browser/media_galleries/imported_media_gallery_registry.cc @@ -5,6 +5,7 @@ #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "base/bind.h" +#include "base/file_util.h" #include "base/logging.h" #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h" #include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h" @@ -12,10 +13,11 @@ #include "chrome/browser/media_galleries/fileapi/picasa_data_provider.h" #include "chrome/common/extensions/extension_constants.h" #include "content/public/browser/browser_thread.h" -#include "webkit/browser/fileapi/isolated_context.h" +#include "webkit/browser/fileapi/external_mount_points.h" +#include "webkit/common/fileapi/file_system_mount_option.h" using base::Bind; -using fileapi::IsolatedContext; +using fileapi::ExternalMountPoints; namespace { @@ -29,25 +31,38 @@ ImportedMediaGalleryRegistry* ImportedMediaGalleryRegistry::GetInstance() { return g_imported_media_gallery_registry.Pointer(); } -std::string ImportedMediaGalleryRegistry::RegisterPicasaFilesystemOnUIThread( - const base::FilePath& database_path) { +void ImportedMediaGalleryRegistry::Initialize() { + base::ThreadRestrictions::AssertIOAllowed(); + if (imported_root_.empty()) { + if (!base::CreateTemporaryFile(&imported_root_)) + imported_root_ = base::FilePath(); + // TODO(vandebo) Setting the permissions of |imported_root_| in CPSP to + // zero would be an extra step to ensure permissions are correctly + // enforced. + } +} + +bool ImportedMediaGalleryRegistry::RegisterPicasaFilesystemOnUIThread( + const std::string& fs_name, const base::FilePath& database_path) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK(!fs_name.empty()); DCHECK(!database_path.empty()); - std::string fsid; + bool result = false; #if defined(OS_WIN) || defined(OS_MACOSX) - fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( - fileapi::kFileSystemTypePicasa, - extension_misc::kMediaFileSystemPathPart, - base::FilePath()); - - if (fsid.empty()) - return fsid; - - picasa_fsids_.insert(fsid); - - if (picasa_fsids_.size() == 1) { + base::FilePath root = ImportedRoot(); + if (root.empty()) + return false; + result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( + fs_name, fileapi::kFileSystemTypePicasa, fileapi::FileSystemMountOption(), + root.AppendASCII("picasa")); + if (!result) + return result; + + picasa_fs_names_.insert(fs_name); + + if (picasa_fs_names_.size() == 1) { MediaFileSystemBackend::MediaTaskRunner()->PostTask( FROM_HERE, Bind(&ImportedMediaGalleryRegistry::RegisterPicasaFileSystem, @@ -60,28 +75,29 @@ std::string ImportedMediaGalleryRegistry::RegisterPicasaFilesystemOnUIThread( } #endif // defined(OS_WIN) || defined(OS_MACOSX) - return fsid; + return result; } -std::string ImportedMediaGalleryRegistry::RegisterITunesFilesystemOnUIThread( - const base::FilePath& library_xml_path) { +bool ImportedMediaGalleryRegistry::RegisterITunesFilesystemOnUIThread( + const std::string& fs_name, const base::FilePath& library_xml_path) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(!library_xml_path.empty()); - std::string fsid; + bool result = false; #if defined(OS_WIN) || defined(OS_MACOSX) - fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( - fileapi::kFileSystemTypeItunes, - extension_misc::kMediaFileSystemPathPart, - base::FilePath()); - - if (fsid.empty()) - return fsid; - - itunes_fsids_.insert(fsid); - - if (itunes_fsids_.size() == 1) { + base::FilePath root = ImportedRoot(); + if (root.empty()) + return false; + result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( + fs_name, fileapi::kFileSystemTypeItunes, fileapi::FileSystemMountOption(), + root.AppendASCII("itunes")); + if (!result) + return result; + + itunes_fs_names_.insert(fs_name); + + if (itunes_fs_names_.size() == 1) { MediaFileSystemBackend::MediaTaskRunner()->PostTask( FROM_HERE, Bind(&ImportedMediaGalleryRegistry::RegisterITunesFileSystem, @@ -94,30 +110,31 @@ std::string ImportedMediaGalleryRegistry::RegisterITunesFilesystemOnUIThread( } #endif // defined(OS_WIN) || defined(OS_MACOSX) - return fsid; + return result; } -std::string ImportedMediaGalleryRegistry::RegisterIPhotoFilesystemOnUIThread( - const base::FilePath& library_xml_path) { +bool ImportedMediaGalleryRegistry::RegisterIPhotoFilesystemOnUIThread( + const std::string& fs_name, const base::FilePath& library_xml_path) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(!library_xml_path.empty()); - std::string fsid; + bool result = false; // TODO(gbillock): Investigate how to refactor this to reduce duplicated // code. #if defined(OS_MACOSX) - fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( - fileapi::kFileSystemTypeIphoto, - extension_misc::kMediaFileSystemPathPart, - base::FilePath()); - - if (fsid.empty()) - return fsid; - - iphoto_fsids_.insert(fsid); - - if (iphoto_fsids_.size() == 1) { + base::FilePath root = ImportedRoot(); + if (root.empty()) + return false; + result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( + fs_name, fileapi::kFileSystemTypeIphoto, fileapi::FileSystemMountOption(), + root.AppendASCII("iphoto")); + if (!result) + return result; + + iphoto_fs_names_.insert(fs_name); + + if (iphoto_fs_names_.size() == 1) { MediaFileSystemBackend::MediaTaskRunner()->PostTask( FROM_HERE, Bind(&ImportedMediaGalleryRegistry::RegisterIPhotoFileSystem, @@ -130,50 +147,55 @@ std::string ImportedMediaGalleryRegistry::RegisterIPhotoFilesystemOnUIThread( } #endif // defined(OS_MACOSX) - return fsid; + return result; } bool ImportedMediaGalleryRegistry::RevokeImportedFilesystemOnUIThread( - const std::string& fsid) { + const std::string& fs_name) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); #if defined(OS_WIN) || defined(OS_MACOSX) - if (picasa_fsids_.erase(fsid)) { - if (picasa_fsids_.empty()) { + if (picasa_fs_names_.erase(fs_name)) { + if (picasa_fs_names_.empty()) { MediaFileSystemBackend::MediaTaskRunner()->PostTask( FROM_HERE, Bind(&ImportedMediaGalleryRegistry::RevokePicasaFileSystem, base::Unretained(this))); } - return IsolatedContext::GetInstance()->RevokeFileSystem(fsid); + return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); } - if (itunes_fsids_.erase(fsid)) { - if (itunes_fsids_.empty()) { + if (itunes_fs_names_.erase(fs_name)) { + if (itunes_fs_names_.empty()) { MediaFileSystemBackend::MediaTaskRunner()->PostTask( FROM_HERE, Bind(&ImportedMediaGalleryRegistry::RevokeITunesFileSystem, base::Unretained(this))); } - return IsolatedContext::GetInstance()->RevokeFileSystem(fsid); + return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); } #endif // defined(OS_WIN) || defined(OS_MACOSX) #if defined(OS_MACOSX) - if (iphoto_fsids_.erase(fsid)) { - if (iphoto_fsids_.empty()) { + if (iphoto_fs_names_.erase(fs_name)) { + if (iphoto_fs_names_.empty()) { MediaFileSystemBackend::MediaTaskRunner()->PostTask( FROM_HERE, Bind(&ImportedMediaGalleryRegistry::RevokeIPhotoFileSystem, base::Unretained(this))); } - return IsolatedContext::GetInstance()->RevokeFileSystem(fsid); + return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); } #endif // defined(OS_MACOSX) return false; } +base::FilePath ImportedMediaGalleryRegistry::ImportedRoot() { + DCHECK(!imported_root_.empty()); + return imported_root_; +} + #if defined(OS_WIN) || defined(OS_MACOSX) // static picasa::PicasaDataProvider* @@ -205,12 +227,14 @@ ImportedMediaGalleryRegistry::IPhotoDataProvider() { ImportedMediaGalleryRegistry::ImportedMediaGalleryRegistry() {} ImportedMediaGalleryRegistry::~ImportedMediaGalleryRegistry() { + if (!imported_root_.empty()) + base::DeleteFile(imported_root_, false); #if defined(OS_WIN) || defined(OS_MACOSX) - DCHECK_EQ(0U, picasa_fsids_.size()); - DCHECK_EQ(0U, itunes_fsids_.size()); + DCHECK_EQ(0U, picasa_fs_names_.size()); + DCHECK_EQ(0U, itunes_fs_names_.size()); #endif // defined(OS_WIN) || defined(OS_MACOSX) #if defined(OS_MACOSX) - DCHECK_EQ(0U, iphoto_fsids_.size()); + DCHECK_EQ(0U, iphoto_fs_names_.size()); #endif // defined(OS_MACOSX) } diff --git a/chrome/browser/media_galleries/imported_media_gallery_registry.h b/chrome/browser/media_galleries/imported_media_gallery_registry.h index 9e7e2a2..8c343c1 100644 --- a/chrome/browser/media_galleries/imported_media_gallery_registry.h +++ b/chrome/browser/media_galleries/imported_media_gallery_registry.h @@ -37,17 +37,24 @@ class ImportedMediaGalleryRegistry { public: static ImportedMediaGalleryRegistry* GetInstance(); + void Initialize(); + // Should be called on the UI thread only. - std::string RegisterPicasaFilesystemOnUIThread( - const base::FilePath& database_path); + bool RegisterPicasaFilesystemOnUIThread(const std::string& fs_name, + const base::FilePath& database_path); - std::string RegisterITunesFilesystemOnUIThread( + bool RegisterITunesFilesystemOnUIThread( + const std::string& fs_name, const base::FilePath& xml_library_path); - std::string RegisterIPhotoFilesystemOnUIThread( + bool RegisterIPhotoFilesystemOnUIThread( + const std::string& fs_name, const base::FilePath& xml_library_path); - bool RevokeImportedFilesystemOnUIThread(const std::string& fsid); + bool RevokeImportedFilesystemOnUIThread(const std::string& fs_name); + + // Path where all virtual file systems are "mounted." + base::FilePath ImportedRoot(); // Should be called on the MediaTaskRunner thread only. #if defined(OS_WIN) || defined(OS_MACOSX) @@ -81,14 +88,16 @@ class ImportedMediaGalleryRegistry { void RevokeIPhotoFileSystem(); #endif // defined(OS_MACOSX) + base::FilePath imported_root_; + #if defined(OS_WIN) || defined(OS_MACOSX) // The data providers are only set or accessed on the task runner thread. scoped_ptr<picasa::PicasaDataProvider> picasa_data_provider_; scoped_ptr<itunes::ITunesDataProvider> itunes_data_provider_; // The remaining members are only accessed on the IO thread. - std::set<std::string> picasa_fsids_; - std::set<std::string> itunes_fsids_; + std::set<std::string> picasa_fs_names_; + std::set<std::string> itunes_fs_names_; #ifndef NDEBUG base::FilePath picasa_database_path_; @@ -99,7 +108,7 @@ class ImportedMediaGalleryRegistry { #if defined(OS_MACOSX) scoped_ptr<iphoto::IPhotoDataProvider> iphoto_data_provider_; - std::set<std::string> iphoto_fsids_; + std::set<std::string> iphoto_fs_names_; #ifndef NDEBUG base::FilePath iphoto_xml_library_path_; diff --git a/chrome/browser/media_galleries/media_file_system_context.h b/chrome/browser/media_galleries/media_file_system_context.h index 0ecafd6..a430b31 100644 --- a/chrome/browser/media_galleries/media_file_system_context.h +++ b/chrome/browser/media_galleries/media_file_system_context.h @@ -19,13 +19,18 @@ class MediaFileSystemContext { public: virtual ~MediaFileSystemContext() {} - // Register a new media file system for |path| and return the corresponding - // filesystem ID. - virtual std::string RegisterFileSystem( - const std::string& device_id, const base::FilePath& path) = 0; - - // Revoke the passed |fsid|. - virtual void RevokeFileSystem(const std::string& fsid) = 0; + // Register a new media file system for |path| as |fs_name|. + virtual bool RegisterFileSystem(const std::string& device_id, + const std::string& fs_name, + const base::FilePath& path) = 0; + + // Revoke the passed |fs_name|. + virtual void RevokeFileSystem(const std::string& fs_name) = 0; + + // Return the mount point root for the given |fs_name|. Returns an empty path + // if |fs_name| is not valid. + virtual base::FilePath GetRegisteredPath( + const std::string& fs_name) const = 0; }; #endif // CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_FILE_SYSTEM_CONTEXT_H_ diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc index 1010eb6..9451af8 100644 --- a/chrome/browser/media_galleries/media_file_system_registry.cc +++ b/chrome/browser/media_galleries/media_file_system_registry.cc @@ -13,6 +13,7 @@ #include "base/prefs/pref_service.h" #include "base/stl_util.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h" #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "chrome/browser/media_galleries/media_file_system_context.h" @@ -36,14 +37,15 @@ #include "extensions/browser/extension_system.h" #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" -#include "webkit/browser/fileapi/isolated_context.h" +#include "webkit/browser/fileapi/external_mount_points.h" +#include "webkit/common/fileapi/file_system_mount_option.h" #include "webkit/common/fileapi/file_system_types.h" using content::BrowserThread; using content::NavigationController; using content::RenderProcessHost; using content::WebContents; -using fileapi::IsolatedContext; +using fileapi::ExternalMountPoints; using storage_monitor::MediaStorageUtil; using storage_monitor::StorageInfo; using storage_monitor::StorageMonitor; @@ -261,15 +263,19 @@ class ExtensionGalleriesHost // |no_references_callback| is called when the last RenderViewHost reference // goes away. RenderViewHost references are added through ReferenceFromRVH(). ExtensionGalleriesHost(MediaFileSystemContext* file_system_context, + const base::FilePath& profile_path, + const std::string& extension_id, const base::Closure& no_references_callback) : file_system_context_(file_system_context), + profile_path_(profile_path), + extension_id_(extension_id), no_references_callback_(no_references_callback), rph_refs_(base::Bind(&ExtensionGalleriesHost::CleanUp, base::Unretained(this))) { } // For each gallery in the list of permitted |galleries|, checks if the - // device is attached and if so looks up or creates a file system id and + // device is attached and if so looks up or creates a file system name and // passes the information needed for the renderer to create those file // system objects to the |callback|. void GetMediaFileSystems(const MediaGalleryPrefIdSet& galleries, @@ -288,6 +294,20 @@ class ExtensionGalleriesHost base::Owned(device_ids), galleries, galleries_info, callback)); } + // Checks if |gallery| is attached and if so, registers the file system and + // then calls |callback| with the result. + void RegisterMediaFileSystem( + const MediaGalleryPrefInfo& gallery, + const base::Callback<void(base::File::Error result)>& callback) { + // Extract all the device ids so we can make sure they are attached. + MediaStorageUtil::DeviceIdSet* device_ids = + new MediaStorageUtil::DeviceIdSet; + device_ids->insert(gallery.device_id); + MediaStorageUtil::FilterAttachedDevices(device_ids, base::Bind( + &ExtensionGalleriesHost::RegisterAttachedMediaFileSystem, this, + base::Owned(device_ids), gallery, callback)); + } + // Revoke the file system for |id| if this extension has created one for |id|. void RevokeGalleryByPrefId(MediaGalleryPrefId id) { PrefIdFsInfoMap::iterator gallery = pref_id_map_.find(id); @@ -357,15 +377,15 @@ class ExtensionGalleriesHost if (!MediaStorageUtil::CanCreateFileSystem(device_id, path)) continue; - std::string fsid = - file_system_context_->RegisterFileSystem(device_id, path); - if (fsid.empty()) + std::string fs_name = MediaFileSystemBackend::ConstructMountName( + profile_path_, extension_id_, pref_id); + if (!file_system_context_->RegisterFileSystem(device_id, fs_name, path)) continue; MediaFileSystemInfo new_entry( gallery_info.GetGalleryDisplayName(), - path, - fsid, + file_system_context_->GetRegisteredPath(fs_name), + fs_name, pref_id, GetTransientIdForRemovableDeviceId(device_id), StorageInfo::IsRemovableDevice(device_id), @@ -383,6 +403,46 @@ class ExtensionGalleriesHost callback.Run(result); } + void RegisterAttachedMediaFileSystem( + const MediaStorageUtil::DeviceIdSet* attached_device, + const MediaGalleryPrefInfo& gallery, + const base::Callback<void(base::File::Error result)>& callback) { + base::File::Error result = base::File::FILE_ERROR_NOT_FOUND; + + // If rph_refs is empty then we're actually in the middle of shutdown, and + // Filter...() lagging which can invoke this method interleaved in the + // destruction callback sequence and re-populate pref_id_map_. + if (!attached_device->empty() && !rph_refs_.empty()) { + std::string fs_name = MediaFileSystemBackend::ConstructMountName( + profile_path_, extension_id_, gallery.pref_id); + base::FilePath path = gallery.AbsolutePath(); + const std::string& device_id = gallery.device_id; + + if (ContainsKey(pref_id_map_, gallery.pref_id)) { + result = base::File::FILE_OK; + } else if (MediaStorageUtil::CanCreateFileSystem(device_id, path) && + file_system_context_->RegisterFileSystem(device_id, fs_name, + path)) { + result = base::File::FILE_OK; + pref_id_map_[gallery.pref_id] = MediaFileSystemInfo( + gallery.GetGalleryDisplayName(), + file_system_context_->GetRegisteredPath(fs_name), + fs_name, + gallery.pref_id, + GetTransientIdForRemovableDeviceId(device_id), + StorageInfo::IsRemovableDevice(device_id), + StorageInfo::IsMediaDevice(device_id)); + } + } + + if (pref_id_map_.empty()) { + rph_refs_.Reset(); + CleanUp(); + } + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(callback, result)); + } + std::string GetTransientIdForRemovableDeviceId(const std::string& device_id) { if (!StorageInfo::IsRemovableDevice(device_id)) return std::string(); @@ -406,6 +466,12 @@ class ExtensionGalleriesHost // safe to store a raw pointer. MediaFileSystemContext* file_system_context_; + // Path for the active profile. + const base::FilePath profile_path_; + + // Id of the extension this host belongs to. + const std::string extension_id_; + // A callback to call when the last RVH reference goes away. base::Closure no_references_callback_; @@ -440,22 +506,9 @@ void MediaFileSystemRegistry::GetMediaFileSystemsForExtension( return; } - ExtensionGalleriesHostMap::iterator extension_hosts = - extension_hosts_map_.find(profile); - if (extension_hosts->second.empty()) - preferences->AddGalleryChangeObserver(this); - ExtensionGalleriesHost* extension_host = - extension_hosts->second[extension->id()].get(); - if (!extension_host) { - extension_host = new ExtensionGalleriesHost( - file_system_context_.get(), - base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty, - base::Unretained(this), - profile, - extension->id())); - extension_hosts_map_[profile][extension->id()] = extension_host; - } + GetExtensionGalleryHost(profile, preferences, extension->id()); + // This must come before the GetMediaFileSystems call to make sure the // RVH of the context is referenced before the filesystems are retrieved. extension_host->ReferenceFromRVH(rvh); @@ -464,6 +517,40 @@ void MediaFileSystemRegistry::GetMediaFileSystemsForExtension( callback); } +void MediaFileSystemRegistry::RegisterMediaFileSystemForExtension( + const content::RenderViewHost* rvh, + const extensions::Extension* extension, + MediaGalleryPrefId pref_id, + const base::Callback<void(base::File::Error result)>& callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_NE(kInvalidMediaGalleryPrefId, pref_id); + + Profile* profile = + Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext()); + MediaGalleriesPreferences* preferences = GetPreferences(profile); + MediaGalleriesPrefInfoMap::const_iterator gallery = + preferences->known_galleries().find(pref_id); + MediaGalleryPrefIdSet permitted_galleries = + preferences->GalleriesForExtension(*extension); + + if (gallery == preferences->known_galleries().end() || + !ContainsKey(permitted_galleries, pref_id)) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND)); + return; + } + + ExtensionGalleriesHost* extension_host = + GetExtensionGalleryHost(profile, preferences, extension->id()); + + // This must come before the GetMediaFileSystems call to make sure the + // RVH of the context is referenced before the filesystems are retrieved. + extension_host->ReferenceFromRVH(rvh); + + extension_host->RegisterMediaFileSystem(gallery->second, callback); +} + MediaGalleriesPreferences* MediaFileSystemRegistry::GetPreferences( Profile* profile) { // Create an empty ExtensionHostMap for this profile on first initialization. @@ -538,41 +625,49 @@ void MediaFileSystemRegistry::OnRemovableStorageDetached( class MediaFileSystemRegistry::MediaFileSystemContextImpl : public MediaFileSystemContext { public: - explicit MediaFileSystemContextImpl(MediaFileSystemRegistry* registry) - : registry_(registry) { - DCHECK(registry_); // Suppresses unused warning on Android. - } + MediaFileSystemContextImpl() {} virtual ~MediaFileSystemContextImpl() {} - virtual std::string RegisterFileSystem( - const std::string& device_id, const base::FilePath& path) OVERRIDE { + virtual bool RegisterFileSystem(const std::string& device_id, + const std::string& fs_name, + const base::FilePath& path) OVERRIDE { if (StorageInfo::IsMassStorageDevice(device_id)) { - return RegisterFileSystemForMassStorage(device_id, path); + return RegisterFileSystemForMassStorage(device_id, fs_name, path); } else { - return RegisterFileSystemForMTPDevice(device_id, path); + return RegisterFileSystemForMTPDevice(device_id, fs_name, path); } } - virtual void RevokeFileSystem(const std::string& fsid) OVERRIDE { + virtual void RevokeFileSystem(const std::string& fs_name) OVERRIDE { ImportedMediaGalleryRegistry* imported_registry = ImportedMediaGalleryRegistry::GetInstance(); - if (imported_registry->RevokeImportedFilesystemOnUIThread(fsid)) + if (imported_registry->RevokeImportedFilesystemOnUIThread(fs_name)) return; - IsolatedContext::GetInstance()->RevokeFileSystem(fsid); + ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name); - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, base::Bind( - &MTPDeviceMapService::RevokeMTPFileSystem, - base::Unretained(MTPDeviceMapService::GetInstance()), - fsid)); + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( + &MTPDeviceMapService::RevokeMTPFileSystem, + base::Unretained(MTPDeviceMapService::GetInstance()), + fs_name)); + } + + virtual base::FilePath GetRegisteredPath( + const std::string& fs_name) const OVERRIDE { + base::FilePath result; + if (!ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(fs_name, + &result)) { + return base::FilePath(); + } + return result; } private: // Registers and returns the file system id for the mass storage device // specified by |device_id| and |path|. - std::string RegisterFileSystemForMassStorage( - const std::string& device_id, const base::FilePath& path) { + bool RegisterFileSystemForMassStorage(const std::string& device_id, + const std::string& fs_name, + const base::FilePath& path) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(StorageInfo::IsMassStorageDevice(device_id)); @@ -584,57 +679,52 @@ class MediaFileSystemRegistry::MediaFileSystemContextImpl // call tree, probably by having it figure out by device id what // registration is needed, or having per-device-type handlers at the // next higher level. - std::string fsid; + bool result = false; if (StorageInfo::IsITunesDevice(device_id)) { - ImportedMediaGalleryRegistry* imported_registry = + ImportedMediaGalleryRegistry* registry = ImportedMediaGalleryRegistry::GetInstance(); - fsid = imported_registry->RegisterITunesFilesystemOnUIThread(path); + result = registry->RegisterITunesFilesystemOnUIThread(fs_name, path); } else if (StorageInfo::IsPicasaDevice(device_id)) { - ImportedMediaGalleryRegistry* imported_registry = + ImportedMediaGalleryRegistry* registry = ImportedMediaGalleryRegistry::GetInstance(); - fsid = imported_registry->RegisterPicasaFilesystemOnUIThread( - path); + result = registry->RegisterPicasaFilesystemOnUIThread(fs_name, path); } else if (StorageInfo::IsIPhotoDevice(device_id)) { - ImportedMediaGalleryRegistry* imported_registry = + ImportedMediaGalleryRegistry* registry = ImportedMediaGalleryRegistry::GetInstance(); - fsid = imported_registry->RegisterIPhotoFilesystemOnUIThread( - path); + result = registry->RegisterIPhotoFilesystemOnUIThread(fs_name, path); } else { - std::string fs_name(extension_misc::kMediaFileSystemPathPart); - fsid = IsolatedContext::GetInstance()->RegisterFileSystemForPath( - fileapi::kFileSystemTypeNativeMedia, path, &fs_name); + result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( + fs_name, fileapi::kFileSystemTypeNativeMedia, + fileapi::FileSystemMountOption(), path); } - return fsid; + return result; } - std::string RegisterFileSystemForMTPDevice( - const std::string& device_id, const base::FilePath& path) { + bool RegisterFileSystemForMTPDevice(const std::string& device_id, + const std::string fs_name, + const base::FilePath& path) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!StorageInfo::IsMassStorageDevice(device_id)); // Sanity checks for |path|. CHECK(MediaStorageUtil::CanCreateFileSystem(device_id, path)); - std::string fs_name(extension_misc::kMediaFileSystemPathPart); - const std::string fsid = - IsolatedContext::GetInstance()->RegisterFileSystemForPath( - fileapi::kFileSystemTypeDeviceMedia, path, &fs_name); - CHECK(!fsid.empty()); - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, base::Bind( - &MTPDeviceMapService::RegisterMTPFileSystem, - base::Unretained(MTPDeviceMapService::GetInstance()), - path.value(), fsid)); - return fsid; + bool result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( + fs_name, fileapi::kFileSystemTypeDeviceMedia, + fileapi::FileSystemMountOption(), path); + CHECK(result); + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( + &MTPDeviceMapService::RegisterMTPFileSystem, + base::Unretained(MTPDeviceMapService::GetInstance()), + path.value(), fs_name)); + return result; } - MediaFileSystemRegistry* registry_; - DISALLOW_COPY_AND_ASSIGN(MediaFileSystemContextImpl); }; // Constructor in 'private' section because depends on private class definition. MediaFileSystemRegistry::MediaFileSystemRegistry() - : file_system_context_(new MediaFileSystemContextImpl(this)) { + : file_system_context_(new MediaFileSystemContextImpl) { StorageMonitor::GetInstance()->AddObserver(this); } @@ -698,6 +788,33 @@ void MediaFileSystemRegistry::OnGalleryRemoved( } } +ExtensionGalleriesHost* MediaFileSystemRegistry::GetExtensionGalleryHost( + Profile* profile, + MediaGalleriesPreferences* preferences, + const std::string& extension_id) { + ExtensionGalleriesHostMap::iterator extension_hosts = + extension_hosts_map_.find(profile); + // GetPreferences(), which had to be called because preferences is an + // argument, ensures that profile is in the map. + DCHECK(extension_hosts != extension_hosts_map_.end()); + if (extension_hosts->second.empty()) + preferences->AddGalleryChangeObserver(this); + + ExtensionGalleriesHost* result = extension_hosts->second[extension_id].get(); + if (!result) { + result = new ExtensionGalleriesHost( + file_system_context_.get(), + profile->GetPath(), + extension_id, + base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty, + base::Unretained(this), + profile, + extension_id)); + extension_hosts_map_[profile][extension_id] = result; + } + return result; +} + void MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty( Profile* profile, const std::string& extension_id) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); diff --git a/chrome/browser/media_galleries/media_file_system_registry.h b/chrome/browser/media_galleries/media_file_system_registry.h index 04065ff..9344698 100644 --- a/chrome/browser/media_galleries/media_file_system_registry.h +++ b/chrome/browser/media_galleries/media_file_system_registry.h @@ -14,6 +14,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/files/file.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" @@ -80,6 +81,14 @@ class MediaFileSystemRegistry const extensions::Extension* extension, const MediaFileSystemsCallback& callback); + // Attempt to register the file system for |pref_id|. If |extension| does not + // have permission to |pref_id|, sends |callback| FILE_ERROR_NOT_FOUND. + void RegisterMediaFileSystemForExtension( + const content::RenderViewHost* rvh, + const extensions::Extension* extension, + MediaGalleryPrefId pref_id, + const base::Callback<void(base::File::Error result)>& callback); + // Returns the media galleries preferences for the specified |profile|. // Caller is responsible for ensuring that the preferences are initialized // before use. @@ -110,6 +119,12 @@ class MediaFileSystemRegistry virtual void OnGalleryRemoved(MediaGalleriesPreferences* pref, MediaGalleryPrefId pref_id) OVERRIDE; + // Look up or create the extension gallery host. + ExtensionGalleriesHost* GetExtensionGalleryHost( + Profile* profile, + MediaGalleriesPreferences* preferences, + const std::string& extension_id); + void OnExtensionGalleriesHostEmpty(Profile* profile, const std::string& extension_id); diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc index f771d6a..0bc622a 100644 --- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc +++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc @@ -65,47 +65,47 @@ class TestMediaFileSystemContext : public MediaFileSystemContext { struct FSInfo { FSInfo() {} FSInfo(const std::string& device_id, const base::FilePath& path, - const std::string& fsid); + const std::string& fs_name); bool operator<(const FSInfo& other) const; std::string device_id; base::FilePath path; - std::string fsid; + std::string fs_name; }; explicit TestMediaFileSystemContext(MediaFileSystemRegistry* registry); virtual ~TestMediaFileSystemContext() {} // MediaFileSystemContext implementation. - virtual std::string RegisterFileSystem( - const std::string& device_id, const base::FilePath& path) OVERRIDE; + virtual bool RegisterFileSystem(const std::string& device_id, + const std::string& fs_name, + const base::FilePath& path) OVERRIDE; - virtual void RevokeFileSystem(const std::string& fsid) OVERRIDE; + virtual void RevokeFileSystem(const std::string& fs_name) OVERRIDE; - base::FilePath GetPathForId(const std::string& fsid) const; + virtual base::FilePath GetRegisteredPath( + const std::string& fs_name) const OVERRIDE; MediaFileSystemRegistry* registry() { return registry_; } private: - std::string AddFSEntry(const std::string& device_id, - const base::FilePath& path); + void AddFSEntry(const std::string& device_id, + const base::FilePath& path, + const std::string& fs_name); MediaFileSystemRegistry* registry_; - // A counter used to construct mock FSIDs. - int fsid_; - // The currently allocated mock file systems. - std::map<std::string /*fsid*/, FSInfo> file_systems_by_id_; + std::map<std::string /*fs_name*/, FSInfo> file_systems_by_name_; }; TestMediaFileSystemContext::FSInfo::FSInfo(const std::string& device_id, const base::FilePath& path, - const std::string& fsid) + const std::string& fs_name) : device_id(device_id), path(path), - fsid(fsid) { + fs_name(fs_name) { } bool TestMediaFileSystemContext::FSInfo::operator<(const FSInfo& other) const { @@ -113,47 +113,47 @@ bool TestMediaFileSystemContext::FSInfo::operator<(const FSInfo& other) const { return device_id < other.device_id; if (path.value() != other.path.value()) return path.value() < other.path.value(); - return fsid < other.fsid; + return fs_name < other.fs_name; } TestMediaFileSystemContext::TestMediaFileSystemContext( MediaFileSystemRegistry* registry) - : registry_(registry), - fsid_(0) { + : registry_(registry) { registry_->file_system_context_.reset(this); } -std::string TestMediaFileSystemContext::RegisterFileSystem( - const std::string& device_id, const base::FilePath& path) { - std::string fsid = AddFSEntry(device_id, path); - return fsid; +bool TestMediaFileSystemContext::RegisterFileSystem( + const std::string& device_id, + const std::string& fs_name, + const base::FilePath& path) { + AddFSEntry(device_id, path, fs_name); + return true; } -void TestMediaFileSystemContext::RevokeFileSystem(const std::string& fsid) { - if (!ContainsKey(file_systems_by_id_, fsid)) +void TestMediaFileSystemContext::RevokeFileSystem(const std::string& fs_name) { + if (!ContainsKey(file_systems_by_name_, fs_name)) return; - EXPECT_EQ(1U, file_systems_by_id_.erase(fsid)); + EXPECT_EQ(1U, file_systems_by_name_.erase(fs_name)); } -base::FilePath TestMediaFileSystemContext::GetPathForId( - const std::string& fsid) const { - std::map<std::string /*fsid*/, FSInfo>::const_iterator it = - file_systems_by_id_.find(fsid); - if (it == file_systems_by_id_.end()) +base::FilePath TestMediaFileSystemContext::GetRegisteredPath( + const std::string& fs_name) const { + std::map<std::string /*fs_name*/, FSInfo>::const_iterator it = + file_systems_by_name_.find(fs_name); + if (it == file_systems_by_name_.end()) return base::FilePath(); return it->second.path; } -std::string TestMediaFileSystemContext::AddFSEntry(const std::string& device_id, - const base::FilePath& path) { +void TestMediaFileSystemContext::AddFSEntry(const std::string& device_id, + const base::FilePath& path, + const std::string& fs_name) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(path.IsAbsolute()); DCHECK(!path.ReferencesParent()); - std::string fsid = base::StringPrintf("FSID:%d", ++fsid_); - FSInfo info(device_id, path, fsid); - file_systems_by_id_[fsid] = info; - return fsid; + FSInfo info(device_id, path, fs_name); + file_systems_by_name_[fs_name] = info; } namespace { @@ -184,7 +184,7 @@ void CheckGalleryInfo(const MediaFileSystemInfo& info, else EXPECT_EQ(0UL, info.transient_device_id.size()); - base::FilePath fsid_path = fs_context->GetPathForId(info.fsid); + base::FilePath fsid_path = fs_context->GetRegisteredPath(info.fsid); EXPECT_EQ(path, fsid_path); } @@ -1067,7 +1067,7 @@ TEST_F(MediaFileSystemRegistryTest, PreferenceListener) { FSInfoMap fs_info = profile_state->GetGalleriesInfo( profile_state->regular_permission_extension()); ASSERT_EQ(1U, fs_info.size()); - EXPECT_FALSE(test_file_system_context()->GetPathForId( + EXPECT_FALSE(test_file_system_context()->GetRegisteredPath( fs_info.begin()->second.fsid).empty()); // Revoke permission and ensure that the file system is revoked. @@ -1075,6 +1075,6 @@ TEST_F(MediaFileSystemRegistryTest, PreferenceListener) { profile_state->regular_permission_extension(), device_id, false /*has access*/); - EXPECT_TRUE(test_file_system_context()->GetPathForId( + EXPECT_TRUE(test_file_system_context()->GetRegisteredPath( fs_info.begin()->second.fsid).empty()); } diff --git a/chrome/browser/media_galleries/media_galleries_preferences.cc b/chrome/browser/media_galleries/media_galleries_preferences.cc index e5b05ae..9ab57f4 100644 --- a/chrome/browser/media_galleries/media_galleries_preferences.cc +++ b/chrome/browser/media_galleries/media_galleries_preferences.cc @@ -20,6 +20,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/media_galleries/fileapi/iapps_finder.h" #include "chrome/browser/media_galleries/fileapi/picasa_finder.h" +#include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "chrome/browser/media_galleries/media_file_system_registry.h" #include "chrome/browser/media_galleries/media_galleries_histograms.h" #include "chrome/browser/profiles/profile.h" @@ -306,6 +307,11 @@ base::string16 GetDisplayNameForSubFolder(const base::string16& device_name, device_name); } +void InitializeImportedMediaGalleryRegistryOnFileThread() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + ImportedMediaGalleryRegistry::GetInstance()->Initialize(); +} + } // namespace MediaGalleryPrefInfo::MediaGalleryPrefInfo() @@ -575,7 +581,7 @@ void MediaGalleriesPreferences::OnStorageMonitorInit( } void MediaGalleriesPreferences::OnFinderDeviceID(const std::string& device_id) { - if (!device_id.empty() && !UpdateDeviceIDForSingletonType(device_id)) { + if (!device_id.empty()) { std::string gallery_name; if (StorageInfo::IsIPhotoDevice(device_id)) gallery_name = kIPhotoGalleryName; @@ -583,13 +589,25 @@ void MediaGalleriesPreferences::OnFinderDeviceID(const std::string& device_id) { gallery_name = kITunesGalleryName; else if (StorageInfo::IsPicasaDevice(device_id)) gallery_name = kPicasaGalleryName; - else - NOTREACHED(); - AddGalleryInternal(device_id, base::ASCIIToUTF16(gallery_name), - base::FilePath(), MediaGalleryPrefInfo::kAutoDetected, - base::string16(), base::string16(), base::string16(), 0, - base::Time(), false, 0, 0, 0, kCurrentPrefsVersion); + if (!gallery_name.empty()) { + pre_initialization_callbacks_waiting_++; + content::BrowserThread::PostTaskAndReply( + content::BrowserThread::FILE, + FROM_HERE, + base::Bind(&InitializeImportedMediaGalleryRegistryOnFileThread), + base::Bind( + &MediaGalleriesPreferences::OnInitializationCallbackReturned, + weak_factory_.GetWeakPtr())); + } + + if (!UpdateDeviceIDForSingletonType(device_id)) { + DCHECK(!gallery_name.empty()); + AddGalleryInternal(device_id, base::ASCIIToUTF16(gallery_name), + base::FilePath(), MediaGalleryPrefInfo::kAutoDetected, + base::string16(), base::string16(), base::string16(), + 0, base::Time(), false, 0, 0, 0, kCurrentPrefsVersion); + } } OnInitializationCallbackReturned(); diff --git a/chrome/renderer/extensions/media_galleries_custom_bindings.cc b/chrome/renderer/extensions/media_galleries_custom_bindings.cc index 1b4a0e1..78a4e27 100644 --- a/chrome/renderer/extensions/media_galleries_custom_bindings.cc +++ b/chrome/renderer/extensions/media_galleries_custom_bindings.cc @@ -23,21 +23,22 @@ void GetMediaFileSystemObject(const v8::FunctionCallbackInfo<v8::Value>& args) { CHECK_EQ(1, args.Length()); CHECK(args[0]->IsString()); - std::string fsid(*v8::String::Utf8Value(args[0])); - CHECK(!fsid.empty()); + std::string fs_mount(*v8::String::Utf8Value(args[0])); + CHECK(!fs_mount.empty()); blink::WebFrame* webframe = blink::WebFrame::frameForCurrentContext(); const GURL origin = GURL(webframe->document().securityOrigin().toString()); - const std::string fs_name = fileapi::GetIsolatedFileSystemName(origin, fsid); + std::string fs_name = + fileapi::GetFileSystemName(origin, fileapi::kFileSystemTypeExternal); + fs_name.append("_"); + fs_name.append(fs_mount); const GURL root_url( - fileapi::GetIsolatedFileSystemRootURIString( - origin, fsid, extension_misc::kMediaFileSystemPathPart)); + fileapi::GetExternalFileSystemRootURIString(origin, fs_mount)); args.GetReturnValue().Set( - blink::WebDOMFileSystem::create( - webframe, - blink::WebFileSystemTypeIsolated, - blink::WebString::fromUTF8(fs_name), - root_url).toV8Value()); + blink::WebDOMFileSystem::create(webframe, + blink::WebFileSystemTypeExternal, + blink::WebString::fromUTF8(fs_name), + root_url).toV8Value()); } } // namespace diff --git a/chrome/test/data/extensions/api_test/media_galleries/tourl/manifest.json b/chrome/test/data/extensions/api_test/media_galleries/tourl/manifest.json new file mode 100644 index 0000000..ee63b20 --- /dev/null +++ b/chrome/test/data/extensions/api_test/media_galleries/tourl/manifest.json @@ -0,0 +1,11 @@ +{ + "name": "chrome.mediaGalleries.tourl", + "version": "0.1", + "description": "test url access for chrome.mediaGalleries", + "app": { + "background": { + "scripts": ["common_injected.js", "test.js"] + } + }, + "permissions": [{"mediaGalleries": ["read", "allAutoDetected"]}] +} diff --git a/chrome/test/data/extensions/api_test/media_galleries/tourl/test.js b/chrome/test/data/extensions/api_test/media_galleries/tourl/test.js new file mode 100644 index 0000000..43baf0f --- /dev/null +++ b/chrome/test/data/extensions/api_test/media_galleries/tourl/test.js @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function check_result_factory(expected) { + return function() { + if (expected) { + chrome.test.succeed(); + } else { + chrome.test.fail(); + } + }; +} + +function TestImageLoadFactory(url, should_load) { + return function() { + test_image = document.createElement('img'); + document.body.appendChild(test_image); + test_image.addEventListener('load', check_result_factory(should_load)); + test_image.addEventListener('error', check_result_factory(!should_load)); + + test_image.src = url; + }; +} + +CreateDummyWindowToPreventSleep(); + +chrome.test.getConfig(function(config) { + var customArg = JSON.parse(config.customArg); + var gallery_id = customArg[0]; + var profile_path = customArg[1]; + var extension_url = chrome.runtime.getURL('/'); + var extension_id = extension_url.split('/')[2]; + + var bad_mount_point = 'filesystem:' + extension_url + + 'external/invalid-' + profile_path + '-' + extension_id + '-' + gallery_id + + '/test.jpg'; + + var bad_mount_name = 'filesystem:' + extension_url + + 'external/media_galleries-' + profile_path + '-' + gallery_id + '/test.jpg'; + + var good_url = 'filesystem:' + extension_url + + 'external/media_galleries-' + profile_path + '-' + extension_id + '-' + + gallery_id + '/test.jpg'; + + chrome.test.runTests([ + TestImageLoadFactory(bad_mount_point, false), + TestImageLoadFactory(bad_mount_name, false), + TestImageLoadFactory(good_url, true), + ]); +}) |