#include <string>
#include <vector>
-#include "apps/shell_window.h"
-#include "apps/shell_window_registry.h"
+#include "base/callback.h"
#include "base/lazy_instance.h"
-#include "base/platform_file.h"
+#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.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_tab_util.h"
+#include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h"
+#include "chrome/browser/media_galleries/gallery_watch_manager.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_permission_controller.h"
#include "chrome/browser/media_galleries/media_galleries_preferences.h"
-#include "chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller.h"
+#include "chrome/browser/media_galleries/media_galleries_scan_result_controller.h"
#include "chrome/browser/media_galleries/media_scan_manager.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"
#include "chrome/common/extensions/api/media_galleries.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
#include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/storage_monitor/storage_info.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
+#include "content/public/browser/blob_handle.h"
+#include "content/public/browser/browser_context.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/browser/event_router.h"
+#include "extensions/browser/app_window/app_window.h"
+#include "extensions/browser/app_window/app_window_registry.h"
+#include "extensions/browser/blob_holder.h"
#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
#include "extensions/common/permissions/permissions_data.h"
-#include "grit/generated_resources.h"
#include "net/base/mime_sniffer.h"
+#include "storage/browser/blob/blob_data_handle.h"
#include "ui/base/l10n/l10n_util.h"
using content::WebContents;
+using storage_monitor::MediaStorageUtil;
+using storage_monitor::StorageInfo;
using web_modal::WebContentsModalDialogManager;
namespace extensions {
namespace MediaGalleries = api::media_galleries;
+namespace DropPermissionForMediaFileSystem =
+ MediaGalleries::DropPermissionForMediaFileSystem;
namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;
+namespace AddGalleryWatch = MediaGalleries::AddGalleryWatch;
+namespace RemoveGalleryWatch = MediaGalleries::RemoveGalleryWatch;
+namespace GetAllGalleryWatch = MediaGalleries::GetAllGalleryWatch;
namespace {
const char kDisallowedByPolicy[] =
"Media Galleries API is disallowed by policy: ";
-const char kMissingEventListener[] =
- "Missing event listener registration.";
+const char kFailedToSetGalleryPermission[] =
+ "Failed to set gallery permission.";
+const char kInvalidGalleryIdMsg[] = "Invalid gallery id.";
+const char kMissingEventListener[] = "Missing event listener registration.";
+const char kNonExistentGalleryId[] = "Non-existent gallery id.";
+const char kNoScanPermission[] = "No permission to scan.";
const char kDeviceIdKey[] = "deviceId";
const char kGalleryIdKey[] = "galleryId";
const char kIsRemovableKey[] = "isRemovable";
const char kNameKey[] = "name";
+const char kMetadataKey[] = "metadata";
+const char kAttachedImagesBlobInfoKey[] = "attachedImagesBlobInfo";
+const char kBlobUUIDKey[] = "blobUUID";
+const char kTypeKey[] = "type";
+const char kSizeKey[] = "size";
+
+const char kInvalidGalleryId[] = "-1";
+
MediaFileSystemRegistry* media_file_system_registry() {
return g_browser_process->media_file_system_registry();
}
+GalleryWatchManager* gallery_watch_manager() {
+ return media_file_system_registry()->gallery_watch_manager();
+}
+
MediaScanManager* media_scan_manager() {
return media_file_system_registry()->media_scan_manager();
}
return true;
}
+// Returns true and sets |gallery_file_path| and |gallery_pref_id| if the
+// |gallery_id| is valid and returns false otherwise.
+bool GetGalleryFilePathAndId(const std::string& gallery_id,
+ Profile* profile,
+ const Extension* extension,
+ base::FilePath* gallery_file_path,
+ MediaGalleryPrefId* gallery_pref_id) {
+ MediaGalleryPrefId pref_id;
+ if (!base::StringToUint64(gallery_id, &pref_id))
+ return false;
+ MediaGalleriesPreferences* preferences =
+ g_browser_process->media_file_system_registry()->GetPreferences(profile);
+ base::FilePath file_path(
+ preferences->LookUpGalleryPathForExtension(pref_id, extension, false));
+ if (file_path.empty())
+ return false;
+ *gallery_pref_id = pref_id;
+ *gallery_file_path = file_path;
+ return true;
+}
+
WebContents* GetWebContents(content::RenderViewHost* rvh,
Profile* profile,
const std::string& app_id) {
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
+ // probably the background page for an app. Try to find a app window to
// host the dialog.
- apps::ShellWindow* window = apps::ShellWindowRegistry::Get(
- profile)->GetCurrentShellWindowForApp(app_id);
+ AppWindow* window = AppWindowRegistry::Get(profile)
+ ->GetCurrentAppWindowForApp(app_id);
contents = window ? window->web_contents() : NULL;
}
return contents;
MediaGalleriesPermission::CheckParam read_param(
MediaGalleriesPermission::kReadPermission);
- bool has_read_permission = PermissionsData::CheckAPIPermissionWithParam(
- extension, APIPermission::kMediaGalleries, &read_param);
+ const PermissionsData* permissions_data = extension->permissions_data();
+ bool has_read_permission = permissions_data->CheckAPIPermissionWithParam(
+ APIPermission::kMediaGalleries, &read_param);
MediaGalleriesPermission::CheckParam copy_to_param(
MediaGalleriesPermission::kCopyToPermission);
- bool has_copy_to_permission = PermissionsData::CheckAPIPermissionWithParam(
- extension, APIPermission::kMediaGalleries, ©_to_param);
+ bool has_copy_to_permission = permissions_data->CheckAPIPermissionWithParam(
+ APIPermission::kMediaGalleries, ©_to_param);
MediaGalleriesPermission::CheckParam delete_param(
MediaGalleriesPermission::kDeletePermission);
- bool has_delete_permission = PermissionsData::CheckAPIPermissionWithParam(
- extension, APIPermission::kMediaGalleries, &delete_param);
+ bool has_delete_permission = permissions_data->CheckAPIPermissionWithParam(
+ APIPermission::kMediaGalleries, &delete_param);
const int child_id = rvh->GetProcess()->GetID();
scoped_ptr<base::ListValue> list(new base::ListValue());
if (has_read_permission) {
content::ChildProcessSecurityPolicy* policy =
content::ChildProcessSecurityPolicy::GetInstance();
- policy->GrantReadFileSystem(child_id, filesystems[i].fsid);
+ policy->GrantReadFile(child_id, filesystems[i].path);
if (has_delete_permission) {
- policy->GrantDeleteFromFileSystem(child_id, filesystems[i].fsid);
+ policy->GrantDeleteFrom(child_id, filesystems[i].path);
if (has_copy_to_permission) {
- policy->GrantCopyIntoFileSystem(child_id, filesystems[i].fsid);
+ policy->GrantCopyInto(child_id, filesystems[i].path);
}
}
}
return list.release();
}
+bool CheckScanPermission(const extensions::Extension* extension,
+ std::string* error) {
+ DCHECK(extension);
+ DCHECK(error);
+ MediaGalleriesPermission::CheckParam scan_param(
+ MediaGalleriesPermission::kScanPermission);
+ bool has_scan_permission =
+ extension->permissions_data()->CheckAPIPermissionWithParam(
+ APIPermission::kMediaGalleries, &scan_param);
+ if (!has_scan_permission)
+ *error = kNoScanPermission;
+ return has_scan_permission;
+}
+
class SelectDirectoryDialog : public ui::SelectFileDialog::Listener,
public base::RefCounted<SelectDirectoryDialog> {
public:
NULL,
0,
base::FilePath::StringType(),
- platform_util::GetTopLevel(web_contents_->GetView()->GetNativeView()),
+ platform_util::GetTopLevel(web_contents_->GetNativeView()),
NULL);
}
// ui::SelectFileDialog::Listener implementation.
- virtual void FileSelected(const base::FilePath& path,
- int index,
- void* params) OVERRIDE {
+ 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 {
+ 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 {
+ void FileSelectionCanceled(void* params) override {
callback_.Run(base::FilePath());
Release(); // Balanced in Show().
}
private:
friend class base::RefCounted<SelectDirectoryDialog>;
- virtual ~SelectDirectoryDialog() {}
+ ~SelectDirectoryDialog() override {}
scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
WebContents* web_contents_;
} // namespace
-MediaGalleriesEventRouter::MediaGalleriesEventRouter(Profile* profile)
- : profile_(profile),
- weak_ptr_factory_(this) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+MediaGalleriesEventRouter::MediaGalleriesEventRouter(
+ content::BrowserContext* context)
+ : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(profile_);
+
+ EventRouter::Get(profile_)->RegisterObserver(
+ this, MediaGalleries::OnGalleryChanged::kEventName);
+
+ gallery_watch_manager()->AddObserver(profile_, this);
media_scan_manager()->AddObserver(profile_, this);
}
}
void MediaGalleriesEventRouter::Shutdown() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
weak_ptr_factory_.InvalidateWeakPtrs();
+
+ EventRouter::Get(profile_)->UnregisterObserver(this);
+
+ gallery_watch_manager()->RemoveObserver(profile_);
media_scan_manager()->RemoveObserver(profile_);
media_scan_manager()->CancelScansForProfile(profile_);
}
-static base::LazyInstance<ProfileKeyedAPIFactory<MediaGalleriesEventRouter> >
-g_factory = LAZY_INSTANCE_INITIALIZER;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter> > g_factory =
+ LAZY_INSTANCE_INITIALIZER;
// static
-ProfileKeyedAPIFactory<MediaGalleriesEventRouter>*
+BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
MediaGalleriesEventRouter::GetFactoryInstance() {
return g_factory.Pointer();
}
// static
-MediaGalleriesEventRouter* MediaGalleriesEventRouter::Get(Profile* profile) {
- DCHECK(media_file_system_registry()->GetPreferences(profile)->
- IsInitialized());
- return ProfileKeyedAPIFactory<MediaGalleriesEventRouter>::GetForProfile(
- profile);
+MediaGalleriesEventRouter* MediaGalleriesEventRouter::Get(
+ content::BrowserContext* context) {
+ DCHECK(media_file_system_registry()
+ ->GetPreferences(Profile::FromBrowserContext(context))
+ ->IsInitialized());
+ return BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>::Get(context);
+}
+
+bool MediaGalleriesEventRouter::ExtensionHasGalleryChangeListener(
+ const std::string& extension_id) const {
+ return EventRouter::Get(profile_)->ExtensionHasEventListener(
+ extension_id, MediaGalleries::OnGalleryChanged::kEventName);
}
bool MediaGalleriesEventRouter::ExtensionHasScanProgressListener(
const std::string& extension_id) const {
- EventRouter* router = ExtensionSystem::Get(profile_)->event_router();
- return router->ExtensionHasEventListener(
- extension_id,
- MediaGalleries::OnScanProgress::kEventName);
+ return EventRouter::Get(profile_)->ExtensionHasEventListener(
+ extension_id, MediaGalleries::OnScanProgress::kEventName);
}
void MediaGalleriesEventRouter::OnScanStarted(const std::string& extension_id) {
}
void MediaGalleriesEventRouter::OnScanFinished(
- const std::string& extension_id, int gallery_count, int image_count,
- int audio_count, int video_count) {
+ const std::string& extension_id, int gallery_count,
+ const MediaGalleryScanResult& file_counts) {
+ media_galleries::UsageCount(media_galleries::SCAN_FINISHED);
MediaGalleries::ScanProgressDetails details;
details.type = MediaGalleries::SCAN_PROGRESS_TYPE_FINISH;
details.gallery_count.reset(new int(gallery_count));
- details.image_count.reset(new int(image_count));
- details.audio_count.reset(new int(audio_count));
- details.video_count.reset(new int(video_count));
+ details.audio_count.reset(new int(file_counts.audio_count));
+ details.image_count.reset(new int(file_counts.image_count));
+ details.video_count.reset(new int(file_counts.video_count));
+ DispatchEventToExtension(
+ extension_id,
+ MediaGalleries::OnScanProgress::kEventName,
+ MediaGalleries::OnScanProgress::Create(details).Pass());
+}
+
+void MediaGalleriesEventRouter::OnScanError(
+ const std::string& extension_id) {
+ MediaGalleries::ScanProgressDetails details;
+ details.type = MediaGalleries::SCAN_PROGRESS_TYPE_ERROR;
DispatchEventToExtension(
extension_id,
MediaGalleries::OnScanProgress::kEventName,
const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- EventRouter* router =
- extensions::ExtensionSystem::Get(profile_)->event_router();
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ EventRouter* router = EventRouter::Get(profile_);
if (!router->ExtensionHasEventListener(extension_id, event_name))
return;
router->DispatchEventToExtension(extension_id, event.Pass());
}
+void MediaGalleriesEventRouter::OnGalleryChanged(
+ const std::string& extension_id, MediaGalleryPrefId gallery_id) {
+ MediaGalleries::GalleryChangeDetails details;
+ details.type = MediaGalleries::GALLERY_CHANGE_TYPE_CONTENTS_CHANGED;
+ details.gallery_id = base::Uint64ToString(gallery_id);
+ DispatchEventToExtension(
+ extension_id,
+ MediaGalleries::OnGalleryChanged::kEventName,
+ MediaGalleries::OnGalleryChanged::Create(details).Pass());
+}
+
+void MediaGalleriesEventRouter::OnGalleryWatchDropped(
+ const std::string& extension_id, MediaGalleryPrefId gallery_id) {
+ MediaGalleries::GalleryChangeDetails details;
+ details.type = MediaGalleries::GALLERY_CHANGE_TYPE_WATCH_DROPPED;
+ details.gallery_id = gallery_id;
+ DispatchEventToExtension(
+ extension_id,
+ MediaGalleries::OnGalleryChanged::kEventName,
+ MediaGalleries::OnGalleryChanged::Create(details).Pass());
+}
+
+void MediaGalleriesEventRouter::OnListenerRemoved(
+ const EventListenerInfo& details) {
+ if (details.event_name == MediaGalleries::OnGalleryChanged::kEventName &&
+ !ExtensionHasGalleryChangeListener(details.extension_id)) {
+ gallery_watch_manager()->RemoveAllWatches(profile_, details.extension_id);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesGetMediaFileSystemsFunction //
+///////////////////////////////////////////////////////////////////////////////
MediaGalleriesGetMediaFileSystemsFunction::
~MediaGalleriesGetMediaFileSystemsFunction() {}
-bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() {
+bool MediaGalleriesGetMediaFileSystemsFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS);
scoped_ptr<GetMediaFileSystems::Params> params(
GetMediaFileSystems::Params::Create(*args_));
void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
const std::vector<MediaFileSystemInfo>& filesystems) {
scoped_ptr<base::ListValue> list(
- ConstructFileSystemList(render_view_host(), GetExtension(), filesystems));
+ ConstructFileSystemList(render_view_host(), extension(), filesystems));
if (!list.get()) {
SendResponse(false);
return;
void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
media_galleries::UsageCount(media_galleries::SHOW_DIALOG);
- const Extension* extension = GetExtension();
WebContents* contents =
- GetWebContents(render_view_host(), GetProfile(), extension->id());
+ GetWebContents(render_view_host(), GetProfile(), extension()->id());
if (!contents) {
SendResponse(false);
return;
// Controller will delete itself.
base::Closure cb = base::Bind(
&MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this);
- new MediaGalleriesDialogController(contents, *extension, cb);
+ new MediaGalleriesPermissionController(contents, *extension(), cb);
}
void MediaGalleriesGetMediaFileSystemsFunction::GetMediaFileSystemsForExtension(
MediaFileSystemRegistry* registry = media_file_system_registry();
DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
registry->GetMediaFileSystemsForExtension(
- render_view_host(), GetExtension(), cb);
+ render_view_host(), extension(), cb);
}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesGetAllMediaFileSystemMetadataFunction //
+///////////////////////////////////////////////////////////////////////////////
MediaGalleriesGetAllMediaFileSystemMetadataFunction::
~MediaGalleriesGetAllMediaFileSystemMetadataFunction() {}
-bool MediaGalleriesGetAllMediaFileSystemMetadataFunction::RunImpl() {
+bool MediaGalleriesGetAllMediaFileSystemMetadataFunction::RunAsync() {
media_galleries::UsageCount(
media_galleries::GET_ALL_MEDIA_FILE_SYSTEM_METADATA);
return Setup(GetProfile(), &error_, base::Bind(
MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile());
DCHECK(prefs->IsInitialized());
MediaGalleryPrefIdSet permitted_gallery_ids =
- prefs->GalleriesForExtension(*GetExtension());
+ prefs->GalleriesForExtension(*extension());
MediaStorageUtil::DeviceIdSet* device_ids = new MediaStorageUtil::DeviceIdSet;
const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
SendResponse(true);
}
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesAddUserSelectedFolderFunction //
+///////////////////////////////////////////////////////////////////////////////
MediaGalleriesAddUserSelectedFolderFunction::
~MediaGalleriesAddUserSelectedFolderFunction() {}
-bool MediaGalleriesAddUserSelectedFolderFunction::RunImpl() {
+bool MediaGalleriesAddUserSelectedFolderFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::ADD_USER_SELECTED_FOLDER);
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit, this));
void MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit() {
Profile* profile = GetProfile();
- const std::string& app_id = GetExtension()->id();
+ const std::string& app_id = extension()->id();
WebContents* contents = GetWebContents(render_view_host(), profile, app_id);
if (!contents) {
- SendResponse(false);
- return;
+ // When the request originated from a background page, but there is no app
+ // window open, check to see if it originated from a tab and display the
+ // dialog in that tab.
+ bool found_tab = extensions::ExtensionTabUtil::GetTabById(
+ source_tab_id(), profile, profile->IsOffTheRecord(),
+ NULL, NULL, &contents, NULL);
+ if (!found_tab || !contents) {
+ SendResponse(false);
+ return;
+ }
}
if (!user_gesture()) {
extensions::file_system_api::SetLastChooseEntryDirectory(
extensions::ExtensionPrefs::Get(GetProfile()),
- GetExtension()->id(),
+ extension()->id(),
selected_directory);
MediaGalleriesPreferences* preferences =
MediaGalleryPrefId pref_id =
preferences->AddGalleryByPath(selected_directory,
MediaGalleryPrefInfo::kUserAdded);
- preferences->SetGalleryPermissionForExtension(*GetExtension(), pref_id, true);
+ preferences->SetGalleryPermissionForExtension(*extension(), pref_id, true);
GetMediaFileSystemsForExtension(base::Bind(
&MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
MediaGalleryPrefId pref_id,
const std::vector<MediaFileSystemInfo>& filesystems) {
scoped_ptr<base::ListValue> list(
- ConstructFileSystemList(render_view_host(), GetExtension(), filesystems));
+ ConstructFileSystemList(render_view_host(), extension(), filesystems));
if (!list.get()) {
SendResponse(false);
return;
MediaFileSystemRegistry* registry = media_file_system_registry();
DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
registry->GetMediaFileSystemsForExtension(
- render_view_host(), GetExtension(), cb);
+ render_view_host(), extension(), cb);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesDropPermissionForMediaFileSystemFunction //
+///////////////////////////////////////////////////////////////////////////////
+MediaGalleriesDropPermissionForMediaFileSystemFunction::
+ ~MediaGalleriesDropPermissionForMediaFileSystemFunction() {}
+
+bool MediaGalleriesDropPermissionForMediaFileSystemFunction::RunAsync() {
+ media_galleries::UsageCount(
+ media_galleries::DROP_PERMISSION_FOR_MEDIA_FILE_SYSTEM);
+
+ scoped_ptr<DropPermissionForMediaFileSystem::Params> params(
+ DropPermissionForMediaFileSystem::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+ MediaGalleryPrefId pref_id;
+ if (!base::StringToUint64(params->gallery_id, &pref_id)) {
+ error_ = kInvalidGalleryIdMsg;
+ return false;
+ }
+
+ base::Closure callback = base::Bind(
+ &MediaGalleriesDropPermissionForMediaFileSystemFunction::
+ OnPreferencesInit,
+ this,
+ pref_id);
+ return Setup(GetProfile(), &error_, callback);
}
+void MediaGalleriesDropPermissionForMediaFileSystemFunction::OnPreferencesInit(
+ MediaGalleryPrefId pref_id) {
+ MediaGalleriesPreferences* preferences =
+ media_file_system_registry()->GetPreferences(GetProfile());
+ if (!ContainsKey(preferences->known_galleries(), pref_id)) {
+ error_ = kNonExistentGalleryId;
+ SendResponse(false);
+ return;
+ }
+
+ bool dropped = preferences->SetGalleryPermissionForExtension(
+ *extension(), pref_id, false);
+ if (dropped)
+ SetResult(new base::StringValue(base::Uint64ToString(pref_id)));
+ else
+ error_ = kFailedToSetGalleryPermission;
+ SendResponse(dropped);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesStartMediaScanFunction //
+///////////////////////////////////////////////////////////////////////////////
MediaGalleriesStartMediaScanFunction::~MediaGalleriesStartMediaScanFunction() {}
-bool MediaGalleriesStartMediaScanFunction::RunImpl() {
+bool MediaGalleriesStartMediaScanFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::START_MEDIA_SCAN);
+ if (!CheckScanPermission(extension(), &error_)) {
+ MediaGalleriesEventRouter::Get(GetProfile())
+ ->OnScanError(extension()->id());
+ return false;
+ }
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesStartMediaScanFunction::OnPreferencesInit, this));
}
void MediaGalleriesStartMediaScanFunction::OnPreferencesInit() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
- if (!api->ExtensionHasScanProgressListener(GetExtension()->id())) {
+ if (!api->ExtensionHasScanProgressListener(extension()->id())) {
error_ = kMissingEventListener;
SendResponse(false);
return;
}
- media_scan_manager()->StartScan(GetProfile(), GetExtension()->id());
+ media_scan_manager()->StartScan(GetProfile(), extension(), user_gesture());
SendResponse(true);
}
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesCancelMediaScanFunction //
+///////////////////////////////////////////////////////////////////////////////
MediaGalleriesCancelMediaScanFunction::
~MediaGalleriesCancelMediaScanFunction() {
}
-bool MediaGalleriesCancelMediaScanFunction::RunImpl() {
+bool MediaGalleriesCancelMediaScanFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::CANCEL_MEDIA_SCAN);
+ if (!CheckScanPermission(extension(), &error_)) {
+ MediaGalleriesEventRouter::Get(GetProfile())
+ ->OnScanError(extension()->id());
+ return false;
+ }
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesCancelMediaScanFunction::OnPreferencesInit, this));
}
void MediaGalleriesCancelMediaScanFunction::OnPreferencesInit() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- media_scan_manager()->CancelScan(GetProfile(), GetExtension()->id());
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ media_scan_manager()->CancelScan(GetProfile(), extension());
SendResponse(true);
}
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesAddScanResultsFunction //
+///////////////////////////////////////////////////////////////////////////////
MediaGalleriesAddScanResultsFunction::~MediaGalleriesAddScanResultsFunction() {}
-bool MediaGalleriesAddScanResultsFunction::RunImpl() {
+bool MediaGalleriesAddScanResultsFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::ADD_SCAN_RESULTS);
+ if (!CheckScanPermission(extension(), &error_)) {
+ // We don't fire a scan progress error here, as it would be unintuitive.
+ return false;
+ }
+ if (!user_gesture())
+ return false;
+
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesAddScanResultsFunction::OnPreferencesInit, this));
}
+MediaGalleriesScanResultController*
+MediaGalleriesAddScanResultsFunction::MakeDialog(
+ content::WebContents* web_contents,
+ const extensions::Extension& extension,
+ const base::Closure& on_finish) {
+ // Controller will delete itself.
+ return new MediaGalleriesScanResultController(web_contents, extension,
+ on_finish);
+}
+
void MediaGalleriesAddScanResultsFunction::OnPreferencesInit() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- const Extension* extension = GetExtension();
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ MediaGalleriesPreferences* preferences =
+ media_file_system_registry()->GetPreferences(GetProfile());
+ if (MediaGalleriesScanResultController::ScanResultCountForExtension(
+ preferences, extension()) == 0) {
+ GetAndReturnGalleries();
+ return;
+ }
+
WebContents* contents =
- GetWebContents(render_view_host(), GetProfile(), extension->id());
+ GetWebContents(render_view_host(), GetProfile(), extension()->id());
if (!contents) {
SendResponse(false);
return;
}
- // Controller will delete itself.
base::Closure cb = base::Bind(
&MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries, this);
- new MediaGalleriesScanResultDialogController(contents, *extension, cb);
+ MakeDialog(contents, *extension(), cb);
}
void MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries() {
MediaFileSystemRegistry* registry = media_file_system_registry();
DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
registry->GetMediaFileSystemsForExtension(
- render_view_host(), GetExtension(),
- base::Bind(&MediaGalleriesAddScanResultsFunction::ReturnGalleries,
- this));
+ render_view_host(),
+ extension(),
+ base::Bind(&MediaGalleriesAddScanResultsFunction::ReturnGalleries, this));
}
void MediaGalleriesAddScanResultsFunction::ReturnGalleries(
const std::vector<MediaFileSystemInfo>& filesystems) {
scoped_ptr<base::ListValue> list(
- ConstructFileSystemList(render_view_host(), GetExtension(), filesystems));
+ ConstructFileSystemList(render_view_host(), extension(), filesystems));
if (!list.get()) {
SendResponse(false);
return;
SendResponse(true);
}
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesGetMetadataFunction //
+///////////////////////////////////////////////////////////////////////////////
MediaGalleriesGetMetadataFunction::~MediaGalleriesGetMetadataFunction() {}
-bool MediaGalleriesGetMetadataFunction::RunImpl() {
+bool MediaGalleriesGetMetadataFunction::RunAsync() {
std::string blob_uuid;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &blob_uuid));
if (!options)
return false;
- bool mime_type_only = options->metadata_type ==
- MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY;
-
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesGetMetadataFunction::OnPreferencesInit, this,
- mime_type_only, blob_uuid));
+ options->metadata_type, blob_uuid));
}
void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
- bool mime_type_only, const std::string& blob_uuid) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ MediaGalleries::GetMetadataType metadata_type,
+ const std::string& blob_uuid) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// BlobReader is self-deleting.
BlobReader* reader = new BlobReader(
GetProfile(),
blob_uuid,
- base::Bind(&MediaGalleriesGetMetadataFunction::SniffMimeType, this,
- mime_type_only));
+ base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this,
+ metadata_type, blob_uuid));
reader->SetByteRange(0, net::kMaxBytesToSniff);
reader->Start();
}
-void MediaGalleriesGetMetadataFunction::SniffMimeType(
- bool mime_type_only, scoped_ptr<std::string> blob_header,
- int64 /* total_blob_length */) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
- MediaGalleries::MediaMetadata metadata;
+void MediaGalleriesGetMetadataFunction::GetMetadata(
+ MediaGalleries::GetMetadataType metadata_type, const std::string& blob_uuid,
+ scoped_ptr<std::string> blob_header, int64 total_blob_length) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
std::string mime_type;
bool mime_type_sniffed = net::SniffMimeTypeFromLocalData(
blob_header->c_str(), blob_header->size(), &mime_type);
- if (mime_type_sniffed)
+
+ if (!mime_type_sniffed) {
+ SendResponse(false);
+ return;
+ }
+
+ if (metadata_type == MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY) {
+ MediaGalleries::MediaMetadata metadata;
metadata.mime_type = mime_type;
- // TODO(tommycli): Kick off SafeMediaMetadataParser if |mime_type_only| false.
+ base::DictionaryValue* result_dictionary = new base::DictionaryValue;
+ result_dictionary->Set(kMetadataKey, metadata.ToValue().release());
+ SetResult(result_dictionary);
+ SendResponse(true);
+ return;
+ }
+
+ // We get attached images by default. GET_METADATA_TYPE_NONE is the default
+ // value if the caller doesn't specify the metadata type.
+ bool get_attached_images =
+ metadata_type == MediaGalleries::GET_METADATA_TYPE_ALL ||
+ metadata_type == MediaGalleries::GET_METADATA_TYPE_NONE;
+
+ scoped_refptr<metadata::SafeMediaMetadataParser> parser(
+ new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid,
+ total_blob_length, mime_type,
+ get_attached_images));
+ parser->Start(base::Bind(
+ &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this));
+}
+
+void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone(
+ bool parse_success, scoped_ptr<base::DictionaryValue> metadata_dictionary,
+ scoped_ptr<std::vector<metadata::AttachedImage> > attached_images) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ if (!parse_success) {
+ SendResponse(false);
+ return;
+ }
+
+ DCHECK(metadata_dictionary.get());
+ DCHECK(attached_images.get());
+
+ scoped_ptr<base::DictionaryValue> result_dictionary(
+ new base::DictionaryValue);
+ result_dictionary->Set(kMetadataKey, metadata_dictionary.release());
+
+ if (attached_images->empty()) {
+ SetResult(result_dictionary.release());
+ SendResponse(true);
+ return;
+ }
+
+ result_dictionary->Set(kAttachedImagesBlobInfoKey, new base::ListValue);
+ metadata::AttachedImage* first_image = &attached_images->front();
+ content::BrowserContext::CreateMemoryBackedBlob(
+ GetProfile(),
+ first_image->data.c_str(),
+ first_image->data.size(),
+ base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
+ this, base::Passed(&result_dictionary),
+ base::Passed(&attached_images),
+ base::Passed(make_scoped_ptr(new std::vector<std::string>))));
+}
+
+void MediaGalleriesGetMetadataFunction::ConstructNextBlob(
+ scoped_ptr<base::DictionaryValue> result_dictionary,
+ scoped_ptr<std::vector<metadata::AttachedImage> > attached_images,
+ scoped_ptr<std::vector<std::string> > blob_uuids,
+ scoped_ptr<content::BlobHandle> current_blob) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ DCHECK(result_dictionary.get());
+ DCHECK(attached_images.get());
+ DCHECK(blob_uuids.get());
+ DCHECK(current_blob.get());
+
+ DCHECK(!attached_images->empty());
+ DCHECK_LT(blob_uuids->size(), attached_images->size());
+
+ // For the newly constructed Blob, store its image's metadata and Blob UUID.
+ base::ListValue* attached_images_list = NULL;
+ result_dictionary->GetList(kAttachedImagesBlobInfoKey, &attached_images_list);
+ DCHECK(attached_images_list);
+ DCHECK_LT(attached_images_list->GetSize(), attached_images->size());
+
+ metadata::AttachedImage* current_image =
+ &(*attached_images)[blob_uuids->size()];
+ base::DictionaryValue* attached_image = new base::DictionaryValue;
+ attached_image->Set(kBlobUUIDKey, new base::StringValue(
+ current_blob->GetUUID()));
+ attached_image->Set(kTypeKey, new base::StringValue(
+ current_image->type));
+ attached_image->Set(kSizeKey, new base::FundamentalValue(
+ base::checked_cast<int>(current_image->data.size())));
+ attached_images_list->Append(attached_image);
+
+ blob_uuids->push_back(current_blob->GetUUID());
+ WebContents* contents = WebContents::FromRenderViewHost(render_view_host());
+ extensions::BlobHolder* holder =
+ extensions::BlobHolder::FromRenderProcessHost(
+ contents->GetRenderProcessHost());
+ holder->HoldBlobReference(current_blob.Pass());
+
+ // Construct the next Blob if necessary.
+ if (blob_uuids->size() < attached_images->size()) {
+ metadata::AttachedImage* next_image =
+ &(*attached_images)[blob_uuids->size()];
+ content::BrowserContext::CreateMemoryBackedBlob(
+ GetProfile(),
+ next_image->data.c_str(),
+ next_image->data.size(),
+ base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
+ this, base::Passed(&result_dictionary),
+ base::Passed(&attached_images), base::Passed(&blob_uuids)));
+ return;
+ }
+
+ // All Blobs have been constructed. The renderer will take ownership.
+ SetResult(result_dictionary.release());
+ SetTransferredBlobUUIDs(*blob_uuids);
+ SendResponse(true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesAddGalleryWatchFunction //
+///////////////////////////////////////////////////////////////////////////////
+MediaGalleriesAddGalleryWatchFunction::
+ ~MediaGalleriesAddGalleryWatchFunction() {
+}
+
+bool MediaGalleriesAddGalleryWatchFunction::RunAsync() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(GetProfile());
+ if (!render_view_host() || !render_view_host()->GetProcess())
+ return false;
+
+ scoped_ptr<AddGalleryWatch::Params> params(
+ AddGalleryWatch::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ MediaGalleriesPreferences* preferences =
+ g_browser_process->media_file_system_registry()->GetPreferences(
+ GetProfile());
+ preferences->EnsureInitialized(
+ base::Bind(&MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit,
+ this,
+ params->gallery_id));
+
+ return true;
+}
+
+void MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit(
+ const std::string& pref_id) {
+ base::FilePath gallery_file_path;
+ MediaGalleryPrefId gallery_pref_id = kInvalidMediaGalleryPrefId;
+ if (!GetGalleryFilePathAndId(pref_id,
+ GetProfile(),
+ extension(),
+ &gallery_file_path,
+ &gallery_pref_id)) {
+ api::media_galleries::AddGalleryWatchResult result;
+ error_ = kInvalidGalleryIdMsg;
+ result.gallery_id = kInvalidGalleryId;
+ result.success = false;
+ SetResult(result.ToValue().release());
+ SendResponse(false);
+ return;
+ }
+
+ gallery_watch_manager()->AddWatch(
+ GetProfile(),
+ extension(),
+ gallery_pref_id,
+ base::Bind(&MediaGalleriesAddGalleryWatchFunction::HandleResponse,
+ this,
+ gallery_pref_id));
+}
+
+void MediaGalleriesAddGalleryWatchFunction::HandleResponse(
+ MediaGalleryPrefId gallery_id,
+ const std::string& error) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // If an app added a file watch without any event listeners on the
+ // onGalleryChanged event, that's an error.
+ MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
+ api::media_galleries::AddGalleryWatchResult result;
+ result.gallery_id = base::Uint64ToString(gallery_id);
+
+ if (!api->ExtensionHasGalleryChangeListener(extension()->id())) {
+ result.success = false;
+ SetResult(result.ToValue().release());
+ error_ = kMissingEventListener;
+ SendResponse(false);
+ return;
+ }
+
+ result.success = error.empty();
+ SetResult(result.ToValue().release());
+ if (error.empty()) {
+ SendResponse(true);
+ } else {
+ error_ = error.c_str();
+ SendResponse(false);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesRemoveGalleryWatchFunction //
+///////////////////////////////////////////////////////////////////////////////
+
+MediaGalleriesRemoveGalleryWatchFunction::
+ ~MediaGalleriesRemoveGalleryWatchFunction() {
+}
+
+bool MediaGalleriesRemoveGalleryWatchFunction::RunAsync() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (!render_view_host() || !render_view_host()->GetProcess())
+ return false;
+
+ scoped_ptr<RemoveGalleryWatch::Params> params(
+ RemoveGalleryWatch::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ MediaGalleriesPreferences* preferences =
+ g_browser_process->media_file_system_registry()->GetPreferences(
+ GetProfile());
+ preferences->EnsureInitialized(
+ base::Bind(&MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit,
+ this,
+ params->gallery_id));
+ return true;
+}
+
+void MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit(
+ const std::string& pref_id) {
+ base::FilePath gallery_file_path;
+ MediaGalleryPrefId gallery_pref_id = 0;
+ if (!GetGalleryFilePathAndId(pref_id,
+ GetProfile(),
+ extension(),
+ &gallery_file_path,
+ &gallery_pref_id)) {
+ error_ = kInvalidGalleryIdMsg;
+ SendResponse(false);
+ return;
+ }
+
+ gallery_watch_manager()->RemoveWatch(
+ GetProfile(), extension_id(), gallery_pref_id);
+ SendResponse(true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesGetAllGalleryWatchFunction //
+///////////////////////////////////////////////////////////////////////////////
+
+MediaGalleriesGetAllGalleryWatchFunction::
+ ~MediaGalleriesGetAllGalleryWatchFunction() {
+}
+
+bool MediaGalleriesGetAllGalleryWatchFunction::RunAsync() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (!render_view_host() || !render_view_host()->GetProcess())
+ return false;
+
+ MediaGalleriesPreferences* preferences =
+ g_browser_process->media_file_system_registry()->GetPreferences(
+ GetProfile());
+ preferences->EnsureInitialized(base::Bind(
+ &MediaGalleriesGetAllGalleryWatchFunction::OnPreferencesInit, this));
+ return true;
+}
+
+void MediaGalleriesGetAllGalleryWatchFunction::OnPreferencesInit() {
+ std::vector<std::string> result;
+ MediaGalleryPrefIdSet gallery_ids =
+ gallery_watch_manager()->GetWatchSet(GetProfile(), extension_id());
+ for (MediaGalleryPrefIdSet::const_iterator iter = gallery_ids.begin();
+ iter != gallery_ids.end();
+ ++iter) {
+ result.push_back(base::Uint64ToString(*iter));
+ }
+ results_ = GetAllGalleryWatch::Results::Create(result);
+ SendResponse(true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// MediaGalleriesRemoveAllGalleryWatchFunction //
+///////////////////////////////////////////////////////////////////////////////
+
+MediaGalleriesRemoveAllGalleryWatchFunction::
+ ~MediaGalleriesRemoveAllGalleryWatchFunction() {
+}
+
+bool MediaGalleriesRemoveAllGalleryWatchFunction::RunAsync() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (!render_view_host() || !render_view_host()->GetProcess())
+ return false;
+
+ MediaGalleriesPreferences* preferences =
+ g_browser_process->media_file_system_registry()->GetPreferences(
+ GetProfile());
+ preferences->EnsureInitialized(base::Bind(
+ &MediaGalleriesRemoveAllGalleryWatchFunction::OnPreferencesInit, this));
+ return true;
+}
- SetResult(metadata.ToValue().release());
+void MediaGalleriesRemoveAllGalleryWatchFunction::OnPreferencesInit() {
+ gallery_watch_manager()->RemoveAllWatches(GetProfile(), extension_id());
SendResponse(true);
}