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,146 @@ |
return g_browser_process->media_file_system_registry(); |
} |
+WebContents* GetWebContents(content::RenderViewHost* rvh, |
+ Profile* profile, |
+ const std::string& app_id) { |
+ WebContents* contents = WebContents::FromRenderViewHost(rvh); |
+ 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( |
+ profile)->GetCurrentShellWindowForApp(app_id); |
+ contents = window ? window->web_contents() : NULL; |
+ } |
+ return contents; |
+} |
+ |
+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,96 +299,28 @@ |
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); |
} |
void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() { |
media_galleries::UsageCount(media_galleries::SHOW_DIALOG); |
- 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(); |
- } |
+ const Extension* extension = GetExtension(); |
+ WebContents* contents = |
+ GetWebContents(render_view_host(), GetProfile(), extension->id()); |
// Controller will delete itself. |
base::Closure cb = base::Bind( |
&MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this); |
- new MediaGalleriesDialogController(contents, *GetExtension(), cb); |
+ new MediaGalleriesDialogController(contents, *extension, cb); |
} |
void MediaGalleriesGetMediaFileSystemsFunction::GetMediaFileSystemsForExtension( |
@@ -325,6 +403,103 @@ |
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() { |
+ Profile* profile = GetProfile(); |
+ const std::string& app_id = GetExtension()->id(); |
+ WebContents* contents = GetWebContents(render_view_host(), profile, app_id); |
+ base::FilePath last_used_path = |
+ extensions::file_system_api::GetLastChooseEntryDirectory( |
+ extensions::ExtensionPrefs::Get(profile), app_id); |
+ SelectDirectoryDialog::Callback callback = base::Bind( |
+ &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; |
+ } |
+ } |
+ } |
+ base::DictionaryValue* results = new base::DictionaryValue; |
+ results->SetWithoutPathExpansion("mediaFileSystems", list.release()); |
+ results->SetStringWithoutPathExpansion("selectedFileSystemName", fsid); |
vandebo (ex-Chrome)
2014/01/09 16:17:29
It looks like this value gets to the user unmolest
Lei Zhang
2014/01/10 00:16:13
Nope, fixed in patch set 9.
|
+ SetResult(results); |
+ 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() { |