Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Unified Diff: chrome/browser/extensions/api/media_galleries/media_galleries_api.cc

Issue 93643002: Media Galleries: Add chrome.mediaGalleries.addUserSelectedFolder(). (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: rebase Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698