Index: chrome/browser/extensions/api/media_galleries/media_galleries_api.cc |
=================================================================== |
--- chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (revision 239032) |
+++ chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (working copy) |
@@ -17,12 +17,16 @@ |
#include "base/stl_util.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "base/task_runner_util.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/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" |
@@ -30,10 +34,12 @@ |
#include "chrome/common/extensions/permissions/media_galleries_permission.h" |
#include "chrome/common/pref_names.h" |
#include "components/web_modal/web_contents_modal_dialog_manager.h" |
+#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/child_process_security_policy.h" |
#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" |
@@ -45,11 +51,14 @@ |
namespace MediaGalleries = api::media_galleries; |
namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems; |
+namespace ManageMediaLocations = MediaGalleries::ManageMediaLocations; |
namespace { |
const char kDisallowedByPolicy[] = |
"Media Galleries API is disallowed by policy: "; |
+const char kInvalidManageRequestType[] = |
+ "Invalid manageMediaLocations request type"; |
const char kDeviceIdKey[] = "deviceId"; |
const char kGalleryIdKey[] = "galleryId"; |
@@ -74,88 +83,114 @@ |
return g_browser_process->media_file_system_registry(); |
} |
-} // namespace |
+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; |
-MediaGalleriesGetMediaFileSystemsFunction:: |
- ~MediaGalleriesGetMediaFileSystemsFunction() {} |
+ SelectDirectoryDialog(WebContents* web_contents, const Callback& callback) |
+ : web_contents_(web_contents), |
+ callback_(callback) { |
+ select_file_dialog_ = ui::SelectFileDialog::Create( |
+ this, new ChromeSelectFilePolicy(web_contents)); |
+ } |
-bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() { |
- if (!ApiIsAccessible(&error_)) |
- return false; |
+ void Show(const base::FilePath& default_path) { |
+ AddRef(); // Balanced in the two reachable listener outcomes. |
+ select_file_dialog_->SelectFile( |
+ ui::SelectFileDialog::SELECT_FOLDER, |
+ base::string16(), // TODO(thestig) Add a title. |
vandebo (ex-Chrome)
2013/12/18 20:15:53
This is a privacy requirement. Probably should pu
Lei Zhang
2014/01/08 23:49:54
Done. Re-using the one from the media galleries pe
|
+ default_path, |
+ NULL, |
+ 0, |
+ base::FilePath::StringType(), |
+ platform_util::GetTopLevel(web_contents_->GetView()->GetNativeView()), |
+ NULL); |
+ } |
- media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS); |
- scoped_ptr<GetMediaFileSystems::Params> params( |
- GetMediaFileSystems::Params::Create(*args_)); |
- EXTENSION_FUNCTION_VALIDATE(params.get()); |
- MediaGalleries::GetMediaFileSystemsInteractivity interactive = |
- MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO; |
- if (params->details.get() && params->details->interactive != MediaGalleries:: |
- GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) { |
- interactive = params->details->interactive; |
+ // ui::SelectFileDialog::Listener implementation. |
+ virtual void FileSelected(const base::FilePath& path, |
+ int index, |
+ void* params) OVERRIDE { |
+ callback_.Run(path); |
+ Release(); // Balanced in Show(). |
} |
- MediaGalleriesPreferences* preferences = |
- media_file_system_registry()->GetPreferences(GetProfile()); |
- preferences->EnsureInitialized(base::Bind( |
- &MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, |
- this, |
- interactive)); |
- return true; |
-} |
+ virtual void MultiFilesSelected(const std::vector<base::FilePath>& files, |
+ void* params) OVERRIDE { |
+ NOTREACHED() << "Should not be able to select multiple files"; |
+ } |
-void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit( |
- MediaGalleries::GetMediaFileSystemsInteractivity interactive) { |
- switch (interactive) { |
- case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_YES: { |
- // The MediaFileSystemRegistry only updates preferences for extensions |
- // that it knows are in use. Since this may be the first call to |
- // chrome.getMediaFileSystems for this extension, call |
- // GetMediaFileSystemsForExtension() here solely so that |
- // MediaFileSystemRegistry will send preference changes. |
- GetMediaFileSystemsForExtension(base::Bind( |
- &MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog, this)); |
- return; |
- } |
- case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_IF_NEEDED: { |
- GetMediaFileSystemsForExtension(base::Bind( |
- &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries, |
- this)); |
- return; |
- } |
- case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO: |
- GetAndReturnGalleries(); |
- return; |
- case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE: |
- NOTREACHED(); |
+ virtual void FileSelectionCanceled(void* params) OVERRIDE { |
+ callback_.Run(base::FilePath()); |
+ Release(); // Balanced in Show(). |
} |
- SendResponse(false); |
-} |
-void MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog( |
- const std::vector<MediaFileSystemInfo>& /*filesystems*/) { |
- ShowDialog(); |
+ 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 |
+ |
+MediaGalleriesGetMediaFileSystemsBase:: |
+ ~MediaGalleriesGetMediaFileSystemsBase() {} |
+ |
+void MediaGalleriesGetMediaFileSystemsBase::ReadPrefsAndShowDialog() { |
+ // The MediaFileSystemRegistry only updates preferences for extensions |
+ // that it knows are in use. Since this may be the first call to |
+ // chrome.{getMediaFileSystems, manageMediaLocations} for this extension, |
+ // call GetMediaFileSystemsForExtension() here solely so that |
+ // MediaFileSystemRegistry will send preference changes. |
+ GetMediaFileSystemsForExtension(base::Bind( |
+ &MediaGalleriesGetMediaFileSystemsBase::AlwaysShowDialog, this)); |
} |
-void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries( |
- const std::vector<MediaFileSystemInfo>& filesystems) { |
- if (filesystems.empty()) |
- ShowDialog(); |
- else |
- ReturnGalleries(filesystems); |
+void MediaGalleriesGetMediaFileSystemsBase::ShowDialog() { |
+ media_galleries::UsageCount(media_galleries::SHOW_DIALOG); |
+ |
+ WebContents* contents = GetWebContents(); |
+ if (!contents) { |
+ SendResponse(false); |
+ return; |
+ } |
+ |
+ // Controller will delete itself. |
+ new MediaGalleriesDialogController( |
+ contents, *GetExtension(), base::Bind( |
+ &MediaGalleriesGetMediaFileSystemsBase::GetAndReturnGalleries, this)); |
} |
-void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() { |
+void MediaGalleriesGetMediaFileSystemsBase::GetAndReturnGalleries() { |
GetMediaFileSystemsForExtension(base::Bind( |
- &MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries, this)); |
+ &MediaGalleriesGetMediaFileSystemsBase::ReturnGalleries, this)); |
} |
-void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries( |
+void MediaGalleriesGetMediaFileSystemsBase::ReturnGalleries( |
const std::vector<MediaFileSystemInfo>& filesystems) { |
- content::RenderViewHost* rvh = render_view_host(); |
- if (!rvh) { |
+ scoped_ptr<base::ListValue> list(ConstructFileSystemList(filesystems)); |
+ if (!list.get()) { |
SendResponse(false); |
return; |
} |
+ |
+ SetResult(list.release()); |
+ SendResponse(true); |
+} |
+ |
+base::ListValue* MediaGalleriesGetMediaFileSystemsBase::ConstructFileSystemList( |
+ const std::vector<MediaFileSystemInfo>& filesystems) { |
+ content::RenderViewHost* rvh = render_view_host(); |
+ if (!rvh) |
+ return NULL; |
+ |
MediaGalleriesPermission::CheckParam read_param( |
MediaGalleriesPermission::kReadPermission); |
bool has_read_permission = PermissionsData::CheckAPIPermissionWithParam( |
@@ -170,7 +205,7 @@ |
GetExtension(), APIPermission::kMediaGalleries, &delete_param); |
const int child_id = rvh->GetProcess()->GetID(); |
- base::ListValue* list = new base::ListValue(); |
+ 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()); |
@@ -214,47 +249,103 @@ |
} |
} |
- // The custom JS binding will use this list to create DOMFileSystem objects. |
- SetResult(list); |
- SendResponse(true); |
+ return list.release(); |
} |
-void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() { |
- media_galleries::UsageCount(media_galleries::SHOW_DIALOG); |
+void MediaGalleriesGetMediaFileSystemsBase::GetMediaFileSystemsForExtension( |
+ const MediaFileSystemsCallback& cb) { |
+ if (!render_view_host()) { |
+ cb.Run(std::vector<MediaFileSystemInfo>()); |
+ return; |
+ } |
+ DCHECK(GetMediaGalleriesPreferences()->IsInitialized()); |
+ media_file_system_registry()->GetMediaFileSystemsForExtension( |
+ render_view_host(), GetExtension(), cb); |
+} |
+ |
+WebContents* MediaGalleriesGetMediaFileSystemsBase::GetWebContents() { |
WebContents* contents = WebContents::FromRenderViewHost(render_view_host()); |
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) { |
- SendResponse(false); |
- return; |
- } |
- contents = window->web_contents(); |
+ if (web_contents_modal_dialog_manager) |
+ return contents; |
+ |
+ // 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()); |
+ return window ? window->web_contents() : NULL; |
+} |
+ |
+MediaGalleriesPreferences* |
+MediaGalleriesGetMediaFileSystemsBase::GetMediaGalleriesPreferences() { |
+ return media_file_system_registry()->GetPreferences(GetProfile()); |
+} |
+ |
+void MediaGalleriesGetMediaFileSystemsBase::AlwaysShowDialog( |
+ const std::vector<MediaFileSystemInfo>& /*filesystems*/) { |
+ ShowDialog(); |
+} |
+ |
+ |
+MediaGalleriesGetMediaFileSystemsFunction:: |
+ ~MediaGalleriesGetMediaFileSystemsFunction() {} |
+ |
+bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() { |
+ if (!ApiIsAccessible(&error_)) |
+ return false; |
+ |
+ media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS); |
+ scoped_ptr<GetMediaFileSystems::Params> params( |
+ GetMediaFileSystems::Params::Create(*args_)); |
+ EXTENSION_FUNCTION_VALIDATE(params.get()); |
+ MediaGalleries::GetMediaFileSystemsInteractivity interactive = |
+ MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO; |
+ if (params->details.get() && params->details->interactive != MediaGalleries:: |
+ GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) { |
+ interactive = params->details->interactive; |
} |
- // Controller will delete itself. |
- base::Closure cb = base::Bind( |
- &MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this); |
- new MediaGalleriesDialogController(contents, *GetExtension(), cb); |
+ MediaGalleriesPreferences* preferences = GetMediaGalleriesPreferences(); |
+ preferences->EnsureInitialized(base::Bind( |
+ &MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, |
+ this, |
+ interactive)); |
+ return true; |
} |
-void MediaGalleriesGetMediaFileSystemsFunction::GetMediaFileSystemsForExtension( |
- const MediaFileSystemsCallback& cb) { |
- if (!render_view_host()) { |
- cb.Run(std::vector<MediaFileSystemInfo>()); |
- return; |
+void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit( |
+ MediaGalleries::GetMediaFileSystemsInteractivity interactive) { |
+ switch (interactive) { |
+ case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_YES: { |
+ ReadPrefsAndShowDialog(); |
vandebo (ex-Chrome)
2013/12/18 20:15:53
Shouldn't this just be ShowDialog since the prefs
|
+ return; |
+ } |
+ case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_IF_NEEDED: { |
+ GetMediaFileSystemsForExtension(base::Bind( |
+ &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries, |
+ this)); |
+ return; |
+ } |
+ case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO: |
+ GetAndReturnGalleries(); |
+ return; |
+ case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE: |
+ NOTREACHED(); |
} |
- MediaFileSystemRegistry* registry = media_file_system_registry(); |
- DCHECK(registry->GetPreferences(GetProfile())->IsInitialized()); |
- registry->GetMediaFileSystemsForExtension( |
- render_view_host(), GetExtension(), cb); |
+ SendResponse(false); |
} |
+void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries( |
+ const std::vector<MediaFileSystemInfo>& filesystems) { |
+ if (filesystems.empty()) |
+ ShowDialog(); |
+ else |
+ ReturnGalleries(filesystems); |
+} |
+ |
+ |
MediaGalleriesGetAllMediaFileSystemMetadataFunction:: |
~MediaGalleriesGetAllMediaFileSystemMetadataFunction() {} |
@@ -273,8 +364,8 @@ |
} |
void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit() { |
- MediaFileSystemRegistry* registry = media_file_system_registry(); |
- MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile()); |
+ MediaGalleriesPreferences* prefs = |
+ media_file_system_registry()->GetPreferences(GetProfile()); |
DCHECK(prefs->IsInitialized()); |
MediaGalleryPrefIdSet permitted_gallery_ids = |
prefs->GalleriesForExtension(*GetExtension()); |
@@ -300,8 +391,8 @@ |
void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries( |
const MediaGalleryPrefIdSet& permitted_gallery_ids, |
const MediaStorageUtil::DeviceIdSet* available_devices) { |
- MediaFileSystemRegistry* registry = media_file_system_registry(); |
- MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile()); |
+ MediaGalleriesPreferences* prefs = |
+ media_file_system_registry()->GetPreferences(GetProfile()); |
base::ListValue* list = new base::ListValue(); |
const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries(); |
@@ -323,4 +414,103 @@ |
SendResponse(true); |
} |
+MediaGalleriesManageMediaLocationsFunction:: |
+ ~MediaGalleriesManageMediaLocationsFunction() {} |
+ |
+bool MediaGalleriesManageMediaLocationsFunction::RunImpl() { |
+ if (!ApiIsAccessible(&error_)) |
+ return false; |
+ |
+ media_galleries::UsageCount(media_galleries::MANAGE_MEDIA_LOCATIONS); |
+ scoped_ptr<ManageMediaLocations::Params> params( |
+ ManageMediaLocations::Params::Create(*args_)); |
+ EXTENSION_FUNCTION_VALIDATE(params.get()); |
+ if (params->details.type == MediaGalleries::MANAGE_REQUEST_TYPE_NONE) |
+ EXTENSION_FUNCTION_ERROR(kInvalidManageRequestType); // returns false |
+ |
+ MediaGalleriesPreferences* preferences = GetMediaGalleriesPreferences(); |
+ preferences->EnsureInitialized(base::Bind( |
+ &MediaGalleriesManageMediaLocationsFunction::OnPreferencesInit, |
+ this, |
+ params->details.type)); |
+ return true; |
+} |
+ |
+void MediaGalleriesManageMediaLocationsFunction::OnPreferencesInit( |
+ MediaGalleries::ManageRequestType request_type) { |
+ switch (request_type) { |
+ case MediaGalleries::MANAGE_REQUEST_TYPE_MANAGE: { |
+ ReadPrefsAndShowDialog(); |
+ return; |
+ } |
+ case MediaGalleries::MANAGE_REQUEST_TYPE_DIRECTORY_PROMPT: { |
+ WebContents* contents = GetWebContents(); |
+ if (!contents) { |
+ SendResponse(false); |
+ return; |
+ } |
+ base::FilePath last_used_path = |
+ extensions::file_system_api::GetLastChooseEntryDirectory( |
+ extensions::ExtensionPrefs::Get(GetProfile()), |
+ GetExtension()->id()); |
+ SelectDirectoryDialog::Callback cb = base::Bind( |
+ &MediaGalleriesManageMediaLocationsFunction::OnDirectorySelected, |
+ this); |
+ scoped_refptr<SelectDirectoryDialog> select_directory_dialog = |
+ new SelectDirectoryDialog(contents, cb); |
+ select_directory_dialog->Show(last_used_path); |
+ return; |
+ } |
+ case MediaGalleries::MANAGE_REQUEST_TYPE_NONE: |
+ NOTREACHED(); |
+ } |
+ SendResponse(false); |
+} |
+ |
+void MediaGalleriesManageMediaLocationsFunction::OnDirectorySelected( |
+ const base::FilePath& selected_directory) { |
+ if (selected_directory.empty()) { |
+ // User cancelled case. |
+ GetAndReturnGalleries(); |
+ return; |
+ } |
+ |
+ extensions::file_system_api::SetLastChooseEntryDirectory( |
+ extensions::ExtensionPrefs::Get(GetProfile()), |
+ GetExtension()->id(), |
+ selected_directory); |
+ |
+ MediaGalleryPrefInfo gallery; |
+ MediaGalleriesPreferences* preferences = GetMediaGalleriesPreferences(); |
+ MediaGalleryPrefId pref_id = |
+ preferences->AddGalleryByPath(selected_directory); |
+ preferences->SetGalleryPermissionForExtension(*GetExtension(), pref_id, true); |
+ |
+ GetMediaFileSystemsForExtension(base::Bind( |
+ &MediaGalleriesManageMediaLocationsFunction::ReturnGalleriesAndId, |
+ this, |
+ pref_id)); |
+} |
+ |
+void MediaGalleriesManageMediaLocationsFunction::ReturnGalleriesAndId( |
+ MediaGalleryPrefId pref_id, |
+ const std::vector<MediaFileSystemInfo>& filesystems) { |
+ scoped_ptr<base::ListValue> list(ConstructFileSystemList(filesystems)); |
+ if (!list.get()) { |
+ SendResponse(false); |
+ return; |
+ } |
+ |
+ std::string fsid; |
+ for (size_t i = 0; i < filesystems.size(); ++i) { |
+ if (filesystems[i].pref_id == pref_id) { |
+ fsid = filesystems[i].fsid; |
vandebo (ex-Chrome)
2013/12/18 20:15:53
If the just added directory "isn't attached," we w
|
+ break; |
+ } |
+ } |
+ list->AppendString(fsid); |
+ SetResult(list.release()); |
+ SendResponse(true); |
+} |
+ |
} // namespace extensions |