| Index: chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
|
| ===================================================================
|
| --- chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (revision 237402)
|
| +++ chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (working copy)
|
| @@ -17,12 +17,14 @@
|
| #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/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 +32,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 +49,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 +81,116 @@
|
| 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() {
|
| + AddRef(); // Balanced in the two reachable listener outcomes.
|
| + select_file_dialog_->SelectFile(
|
| + ui::SelectFileDialog::SELECT_FOLDER,
|
| + base::string16(),
|
| + base::FilePath(),
|
| + 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(
|
| @@ -214,49 +249,103 @@
|
| }
|
| }
|
|
|
| - // The custom JS binding will use this list to create DOMFileSystem objects.
|
| - SetResult(list);
|
| - SendResponse(true);
|
| + return list;
|
| }
|
|
|
| -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) {
|
| - contents = window->web_contents();
|
| - } else {
|
| - // Abort showing the dialog. TODO(estade) Perhaps return an error instead.
|
| - GetAndReturnGalleries();
|
| - return;
|
| - }
|
| + 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();
|
| + 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() {}
|
|
|
| @@ -275,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());
|
| @@ -302,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();
|
| @@ -325,4 +414,115 @@
|
| 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;
|
| + }
|
| + SelectDirectoryDialog::Callback cb = base::Bind(
|
| + &MediaGalleriesManageMediaLocationsFunction::OnDirectorySelected,
|
| + this);
|
| + scoped_refptr<SelectDirectoryDialog> select_directory_dialog =
|
| + new SelectDirectoryDialog(contents, cb);
|
| + select_directory_dialog->Show();
|
| + return;
|
| + }
|
| + case MediaGalleries::MANAGE_REQUEST_TYPE_NONE:
|
| + NOTREACHED();
|
| + }
|
| + SendResponse(false);
|
| +}
|
| +
|
| +void MediaGalleriesManageMediaLocationsFunction::OnDirectorySelected(
|
| + const base::FilePath& selected_directory) {
|
| + if (selected_directory.empty()) {
|
| + SetResult(new base::ListValue());
|
| + SendResponse(true);
|
| + return;
|
| + }
|
| +
|
| + bool posted = base::PostTaskAndReplyWithResult(
|
| + content::BrowserThread::GetBlockingPool(),
|
| + FROM_HERE,
|
| + base::Bind(&base::PathExists, selected_directory),
|
| + base::Bind(
|
| + &MediaGalleriesManageMediaLocationsFunction::OnDirectoryChecked,
|
| + this,
|
| + selected_directory));
|
| + if (posted)
|
| + return;
|
| + SendResponse(false);
|
| +}
|
| +
|
| +void MediaGalleriesManageMediaLocationsFunction::OnDirectoryChecked(
|
| + const base::FilePath& selected_directory, bool exists) {
|
| + DCHECK(!selected_directory.empty());
|
| +
|
| + if (!exists) {
|
| + SendResponse(false);
|
| + return;
|
| + }
|
| +
|
| + MediaGalleryPrefInfo gallery;
|
| + MediaGalleriesPreferences* preferences = GetMediaGalleriesPreferences();
|
| + MediaGalleryPrefId pref_id =
|
| + preferences->AddGalleryByPath(selected_directory);
|
| + preferences->SetGalleryPermissionForExtension(*GetExtension(), pref_id, true);
|
| +
|
| + GetMediaFileSystemsForExtension(base::Bind(
|
| + &MediaGalleriesManageMediaLocationsFunction::FindGalleryWithPrefId,
|
| + this,
|
| + pref_id));
|
| +}
|
| +
|
| +void MediaGalleriesManageMediaLocationsFunction::FindGalleryWithPrefId(
|
| + MediaGalleryPrefId pref_id,
|
| + const std::vector<MediaFileSystemInfo>& filesystems) {
|
| + for (size_t i = 0; i < filesystems.size(); i++) {
|
| + if (filesystems[i].pref_id == pref_id) {
|
| + std::vector<MediaFileSystemInfo> found_filesystem;
|
| + found_filesystem.push_back(filesystems[i]);
|
| + scoped_ptr<base::ListValue> list(
|
| + ConstructFileSystemList(found_filesystem));
|
| + if (!list.get())
|
| + break;
|
| +
|
| + SetResult(list.release());
|
| + SendResponse(true);
|
| + return;
|
| + }
|
| + }
|
| + SendResponse(false);
|
| +}
|
| +
|
| } // namespace extensions
|
|
|