Chromium Code Reviews| Index: chrome/browser/extensions/api/media_galleries/media_galleries_api.cc |
| =================================================================== |
| --- chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (revision 243397) |
| +++ chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (working copy) |
| @@ -18,11 +18,14 @@ |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| +#include "chrome/browser/extensions/api/file_system/file_system_api.h" |
| #include "chrome/browser/extensions/blob_reader.h" |
| +#include "chrome/browser/extensions/extension_prefs.h" |
| #include "chrome/browser/media_galleries/media_file_system_registry.h" |
| #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" |
| #include "chrome/browser/media_galleries/media_galleries_histograms.h" |
| #include "chrome/browser/media_galleries/media_galleries_preferences.h" |
| +#include "chrome/browser/platform_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/storage_monitor/storage_info.h" |
| #include "chrome/browser/ui/chrome_select_file_policy.h" |
| @@ -35,10 +38,13 @@ |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_contents_view.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/permissions/api_permission.h" |
| #include "extensions/common/permissions/permissions_data.h" |
| +#include "grit/generated_resources.h" |
| #include "net/base/mime_sniffer.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| using content::WebContents; |
| using web_modal::WebContentsModalDialogManager; |
| @@ -76,6 +82,129 @@ |
| return g_browser_process->media_file_system_registry(); |
| } |
| +base::ListValue* ConstructFileSystemList( |
| + content::RenderViewHost* rvh, |
| + const Extension* extension, |
| + const std::vector<MediaFileSystemInfo>& filesystems) { |
| + if (!rvh) |
| + return NULL; |
| + |
| + MediaGalleriesPermission::CheckParam read_param( |
| + MediaGalleriesPermission::kReadPermission); |
| + bool has_read_permission = PermissionsData::CheckAPIPermissionWithParam( |
| + extension, APIPermission::kMediaGalleries, &read_param); |
| + MediaGalleriesPermission::CheckParam copy_to_param( |
| + MediaGalleriesPermission::kCopyToPermission); |
| + bool has_copy_to_permission = PermissionsData::CheckAPIPermissionWithParam( |
| + extension, APIPermission::kMediaGalleries, ©_to_param); |
| + MediaGalleriesPermission::CheckParam delete_param( |
| + MediaGalleriesPermission::kDeletePermission); |
| + bool has_delete_permission = PermissionsData::CheckAPIPermissionWithParam( |
| + extension, APIPermission::kMediaGalleries, &delete_param); |
| + |
| + const int child_id = rvh->GetProcess()->GetID(); |
| + scoped_ptr<base::ListValue> list(new base::ListValue()); |
| + for (size_t i = 0; i < filesystems.size(); ++i) { |
| + scoped_ptr<base::DictionaryValue> file_system_dict_value( |
| + new base::DictionaryValue()); |
| + |
| + // Send the file system id so the renderer can create a valid FileSystem |
| + // object. |
| + file_system_dict_value->SetStringWithoutPathExpansion( |
| + "fsid", filesystems[i].fsid); |
| + |
| + file_system_dict_value->SetStringWithoutPathExpansion( |
| + kNameKey, filesystems[i].name); |
| + file_system_dict_value->SetStringWithoutPathExpansion( |
| + kGalleryIdKey, |
| + base::Uint64ToString(filesystems[i].pref_id)); |
| + if (!filesystems[i].transient_device_id.empty()) { |
| + file_system_dict_value->SetStringWithoutPathExpansion( |
| + kDeviceIdKey, filesystems[i].transient_device_id); |
| + } |
| + file_system_dict_value->SetBooleanWithoutPathExpansion( |
| + kIsRemovableKey, filesystems[i].removable); |
| + file_system_dict_value->SetBooleanWithoutPathExpansion( |
| + kIsMediaDeviceKey, filesystems[i].media_device); |
| + file_system_dict_value->SetBooleanWithoutPathExpansion( |
| + kIsAvailableKey, true); |
| + |
| + list->Append(file_system_dict_value.release()); |
| + |
| + if (filesystems[i].path.empty()) |
| + continue; |
| + |
| + if (has_read_permission) { |
| + content::ChildProcessSecurityPolicy* policy = |
| + content::ChildProcessSecurityPolicy::GetInstance(); |
| + policy->GrantReadFileSystem(child_id, filesystems[i].fsid); |
| + if (has_delete_permission) { |
| + policy->GrantDeleteFromFileSystem(child_id, filesystems[i].fsid); |
| + if (has_copy_to_permission) { |
| + policy->GrantCopyIntoFileSystem(child_id, filesystems[i].fsid); |
| + } |
| + } |
| + } |
| + } |
| + |
| + return list.release(); |
| +} |
| + |
| +class SelectDirectoryDialog : public ui::SelectFileDialog::Listener, |
| + public base::RefCounted<SelectDirectoryDialog> { |
| + public: |
| + // Selected file path, or an empty path if the user canceled. |
| + typedef base::Callback<void(const base::FilePath&)> Callback; |
| + |
| + SelectDirectoryDialog(WebContents* web_contents, const Callback& callback) |
| + : web_contents_(web_contents), |
| + callback_(callback) { |
| + select_file_dialog_ = ui::SelectFileDialog::Create( |
| + this, new ChromeSelectFilePolicy(web_contents)); |
| + } |
| + |
| + void Show(const base::FilePath& default_path) { |
| + AddRef(); // Balanced in the two reachable listener outcomes. |
| + select_file_dialog_->SelectFile( |
| + ui::SelectFileDialog::SELECT_FOLDER, |
| + l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE), |
| + default_path, |
| + NULL, |
| + 0, |
| + base::FilePath::StringType(), |
| + platform_util::GetTopLevel(web_contents_->GetView()->GetNativeView()), |
| + NULL); |
| + } |
| + |
| + // ui::SelectFileDialog::Listener implementation. |
| + virtual void FileSelected(const base::FilePath& path, |
| + int index, |
| + void* params) OVERRIDE { |
| + callback_.Run(path); |
| + Release(); // Balanced in Show(). |
| + } |
| + |
| + virtual void MultiFilesSelected(const std::vector<base::FilePath>& files, |
| + void* params) OVERRIDE { |
| + NOTREACHED() << "Should not be able to select multiple files"; |
| + } |
| + |
| + virtual void FileSelectionCanceled(void* params) OVERRIDE { |
| + callback_.Run(base::FilePath()); |
| + Release(); // Balanced in Show(). |
| + } |
| + |
| + private: |
| + friend class base::RefCounted<SelectDirectoryDialog>; |
| + virtual ~SelectDirectoryDialog() {} |
| + |
| + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; |
| + WebContents* web_contents_; |
| + Callback callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SelectDirectoryDialog); |
| +}; |
| + |
| } // namespace |
| MediaGalleriesGetMediaFileSystemsFunction:: |
| @@ -153,71 +282,15 @@ |
| void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries( |
| const std::vector<MediaFileSystemInfo>& filesystems) { |
| - content::RenderViewHost* rvh = render_view_host(); |
| - if (!rvh) { |
| + scoped_ptr<base::ListValue> list( |
| + ConstructFileSystemList(render_view_host(), GetExtension(), filesystems)); |
| + if (!list.get()) { |
| SendResponse(false); |
| return; |
| } |
| - MediaGalleriesPermission::CheckParam read_param( |
| - MediaGalleriesPermission::kReadPermission); |
| - bool has_read_permission = PermissionsData::CheckAPIPermissionWithParam( |
| - GetExtension(), APIPermission::kMediaGalleries, &read_param); |
| - MediaGalleriesPermission::CheckParam copy_to_param( |
| - MediaGalleriesPermission::kCopyToPermission); |
| - bool has_copy_to_permission = PermissionsData::CheckAPIPermissionWithParam( |
| - GetExtension(), APIPermission::kMediaGalleries, ©_to_param); |
| - MediaGalleriesPermission::CheckParam delete_param( |
| - MediaGalleriesPermission::kDeletePermission); |
| - bool has_delete_permission = PermissionsData::CheckAPIPermissionWithParam( |
| - GetExtension(), APIPermission::kMediaGalleries, &delete_param); |
| - const int child_id = rvh->GetProcess()->GetID(); |
| - base::ListValue* list = new base::ListValue(); |
| - for (size_t i = 0; i < filesystems.size(); i++) { |
| - scoped_ptr<base::DictionaryValue> file_system_dict_value( |
| - new base::DictionaryValue()); |
| - |
| - // Send the file system id so the renderer can create a valid FileSystem |
| - // object. |
| - file_system_dict_value->SetStringWithoutPathExpansion( |
| - "fsid", filesystems[i].fsid); |
| - |
| - file_system_dict_value->SetStringWithoutPathExpansion( |
| - kNameKey, filesystems[i].name); |
| - file_system_dict_value->SetStringWithoutPathExpansion( |
| - kGalleryIdKey, |
| - base::Uint64ToString(filesystems[i].pref_id)); |
| - if (!filesystems[i].transient_device_id.empty()) { |
| - file_system_dict_value->SetStringWithoutPathExpansion( |
| - kDeviceIdKey, filesystems[i].transient_device_id); |
| - } |
| - file_system_dict_value->SetBooleanWithoutPathExpansion( |
| - kIsRemovableKey, filesystems[i].removable); |
| - file_system_dict_value->SetBooleanWithoutPathExpansion( |
| - kIsMediaDeviceKey, filesystems[i].media_device); |
| - file_system_dict_value->SetBooleanWithoutPathExpansion( |
| - kIsAvailableKey, true); |
| - |
| - list->Append(file_system_dict_value.release()); |
| - |
| - if (filesystems[i].path.empty()) |
| - continue; |
| - |
| - if (has_read_permission) { |
| - content::ChildProcessSecurityPolicy* policy = |
| - content::ChildProcessSecurityPolicy::GetInstance(); |
| - policy->GrantReadFileSystem(child_id, filesystems[i].fsid); |
| - if (has_delete_permission) { |
| - policy->GrantDeleteFromFileSystem(child_id, filesystems[i].fsid); |
| - if (has_copy_to_permission) { |
| - policy->GrantCopyIntoFileSystem(child_id, filesystems[i].fsid); |
| - } |
| - } |
| - } |
| - } |
| - |
| // The custom JS binding will use this list to create DOMFileSystem objects. |
| - SetResult(list); |
| + SetResult(list.release()); |
| SendResponse(true); |
| } |
| @@ -325,6 +398,113 @@ |
| SendResponse(true); |
| } |
| +MediaGalleriesAddUserSelectedFolderFunction:: |
| + ~MediaGalleriesAddUserSelectedFolderFunction() {} |
| + |
| +bool MediaGalleriesAddUserSelectedFolderFunction::RunImpl() { |
| + if (!ApiIsAccessible(&error_)) |
| + return false; |
| + |
| + media_galleries::UsageCount(media_galleries::ADD_USER_SELECTED_FOLDER); |
| + MediaGalleriesPreferences* preferences = |
| + media_file_system_registry()->GetPreferences(GetProfile()); |
| + preferences->EnsureInitialized(base::Bind( |
| + &MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit, |
| + this)); |
| + return true; |
| +} |
| + |
| +void MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit() { |
| + WebContents* contents = WebContents::FromRenderViewHost(render_view_host()); |
|
vandebo (ex-Chrome)
2014/01/09 00:29:16
nit: pull this window parent finding logic into a
Lei Zhang
2014/01/09 05:28:38
Done.
|
| + WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
| + WebContentsModalDialogManager::FromWebContents(contents); |
| + if (!web_contents_modal_dialog_manager) { |
| + // If there is no WebContentsModalDialogManager, then this contents is |
| + // probably the background page for an app. Try to find a shell window to |
| + // host the dialog. |
| + apps::ShellWindow* window = apps::ShellWindowRegistry::Get( |
| + GetProfile())->GetCurrentShellWindowForApp(GetExtension()->id()); |
| + if (window) |
| + contents = window->web_contents(); |
| + else |
| + contents = NULL; |
| + } |
| + base::FilePath last_used_path = |
| + extensions::file_system_api::GetLastChooseEntryDirectory( |
| + extensions::ExtensionPrefs::Get(GetProfile()), |
| + GetExtension()->id()); |
| + SelectDirectoryDialog::Callback callback = base::Bind( |
|
vandebo (ex-Chrome)
2014/01/09 00:29:16
This create a circular reference, but as we discus
|
| + &MediaGalleriesAddUserSelectedFolderFunction::OnDirectorySelected, this); |
| + scoped_refptr<SelectDirectoryDialog> select_directory_dialog = |
| + new SelectDirectoryDialog(contents, callback); |
| + select_directory_dialog->Show(last_used_path); |
| +} |
| + |
| +void MediaGalleriesAddUserSelectedFolderFunction::OnDirectorySelected( |
| + const base::FilePath& selected_directory) { |
| + if (!selected_directory.empty()) { |
| + // User cancelled case. |
| + GetMediaFileSystemsForExtension(base::Bind( |
| + &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId, |
| + this, |
| + kInvalidMediaGalleryPrefId)); |
| + return; |
| + } |
| + |
| + extensions::file_system_api::SetLastChooseEntryDirectory( |
| + extensions::ExtensionPrefs::Get(GetProfile()), |
| + GetExtension()->id(), |
| + selected_directory); |
| + |
| + MediaGalleriesPreferences* preferences = |
| + media_file_system_registry()->GetPreferences(GetProfile()); |
| + MediaGalleryPrefId pref_id = |
| + preferences->AddGalleryByPath(selected_directory); |
| + preferences->SetGalleryPermissionForExtension(*GetExtension(), pref_id, true); |
| + |
| + GetMediaFileSystemsForExtension(base::Bind( |
| + &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId, |
| + this, |
| + pref_id)); |
| +} |
| + |
| +void MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId( |
| + MediaGalleryPrefId pref_id, |
| + const std::vector<MediaFileSystemInfo>& filesystems) { |
| + scoped_ptr<base::ListValue> list( |
| + ConstructFileSystemList(render_view_host(), GetExtension(), filesystems)); |
| + if (!list.get()) { |
| + SendResponse(false); |
| + return; |
| + } |
| + |
| + std::string fsid; |
| + if (pref_id != kInvalidMediaGalleryPrefId) { |
| + for (size_t i = 0; i < filesystems.size(); ++i) { |
| + if (filesystems[i].pref_id == pref_id) { |
| + fsid = filesystems[i].fsid; |
| + break; |
| + } |
| + } |
| + } |
| + list->AppendString(fsid); |
|
vandebo (ex-Chrome)
2014/01/09 00:29:16
I still think this should use another level of dic
Lei Zhang
2014/01/09 05:28:38
Done.
|
| + SetResult(list.release()); |
| + SendResponse(true); |
| +} |
| + |
| +void |
| +MediaGalleriesAddUserSelectedFolderFunction::GetMediaFileSystemsForExtension( |
| + const MediaFileSystemsCallback& cb) { |
| + if (!render_view_host()) { |
| + cb.Run(std::vector<MediaFileSystemInfo>()); |
| + return; |
| + } |
| + MediaFileSystemRegistry* registry = media_file_system_registry(); |
| + DCHECK(registry->GetPreferences(GetProfile())->IsInitialized()); |
| + registry->GetMediaFileSystemsForExtension( |
| + render_view_host(), GetExtension(), cb); |
| +} |
| + |
| MediaGalleriesGetMetadataFunction::~MediaGalleriesGetMetadataFunction() {} |
| bool MediaGalleriesGetMetadataFunction::RunImpl() { |