| Index: chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
|
| ===================================================================
|
| --- chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (revision 243958)
|
| +++ 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;
|
| + }
|
| +
|
| + int index = -1;
|
| + if (pref_id != kInvalidMediaGalleryPrefId) {
|
| + for (size_t i = 0; i < filesystems.size(); ++i) {
|
| + if (filesystems[i].pref_id == pref_id) {
|
| + index = i;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + base::DictionaryValue* results = new base::DictionaryValue;
|
| + results->SetWithoutPathExpansion("mediaFileSystems", list.release());
|
| + results->SetIntegerWithoutPathExpansion("selectedFileSystemIndex", index);
|
| + 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() {
|
|
|