This source file includes following definitions.
- media_file_system_registry
- media_scan_manager
- Setup
- GetWebContents
- ConstructFileSystemList
- CheckScanPermission
- callback_
- Show
- FileSelected
- MultiFilesSelected
- FileSelectionCanceled
- weak_ptr_factory_
- Shutdown
- GetFactoryInstance
- Get
- ExtensionHasScanProgressListener
- OnScanStarted
- OnScanCancelled
- OnScanFinished
- OnScanError
- DispatchEventToExtension
- MediaGalleriesGetMediaFileSystemsFunction
- RunImpl
- OnPreferencesInit
- AlwaysShowDialog
- ShowDialogIfNoGalleries
- GetAndReturnGalleries
- ReturnGalleries
- ShowDialog
- GetMediaFileSystemsForExtension
- MediaGalleriesGetAllMediaFileSystemMetadataFunction
- RunImpl
- OnPreferencesInit
- OnGetGalleries
- MediaGalleriesAddUserSelectedFolderFunction
- RunImpl
- OnPreferencesInit
- OnDirectorySelected
- ReturnGalleriesAndId
- GetMediaFileSystemsForExtension
- RunImpl
- OnPreferencesInit
- MediaGalleriesCancelMediaScanFunction
- RunImpl
- OnPreferencesInit
- RunImpl
- MakeDialog
- OnPreferencesInit
- GetAndReturnGalleries
- ReturnGalleries
- RunImpl
- OnPreferencesInit
- SniffMimeType
- OnSafeMediaMetadataParserDone
#include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"
#include <set>
#include <string>
#include <vector>
#include "apps/app_window.h"
#include "apps/app_window_registry.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/platform_file.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#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_tab_util.h"
#include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.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/media_galleries/media_galleries_scan_result_dialog_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/ui/chrome_select_file_policy.h"
#include "chrome/common/extensions/api/media_galleries.h"
#include "chrome/common/pref_names.h"
#include "components/storage_monitor/storage_info.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/browser/event_router.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 "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 GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;
namespace {
const char kDisallowedByPolicy[] =
"Media Galleries API is disallowed by policy: ";
const char kMissingEventListener[] =
"Missing event listener registration.";
const char kNoScanPermission[] =
"No permission to scan.";
const char kDeviceIdKey[] = "deviceId";
const char kGalleryIdKey[] = "galleryId";
const char kIsAvailableKey[] = "isAvailable";
const char kIsMediaDeviceKey[] = "isMediaDevice";
const char kIsRemovableKey[] = "isRemovable";
const char kNameKey[] = "name";
MediaFileSystemRegistry* media_file_system_registry() {
return g_browser_process->media_file_system_registry();
}
MediaScanManager* media_scan_manager() {
return media_file_system_registry()->media_scan_manager();
}
bool Setup(Profile* profile, std::string* error, base::Closure callback) {
if (!ChromeSelectFilePolicy::FileSelectDialogsAllowed()) {
*error = std::string(kDisallowedByPolicy) +
prefs::kAllowFileSelectionDialogs;
return false;
}
MediaGalleriesPreferences* preferences =
media_file_system_registry()->GetPreferences(profile);
preferences->EnsureInitialized(callback);
return true;
}
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) {
apps::AppWindow* window = apps::AppWindowRegistry::Get(profile)
->GetCurrentAppWindowForApp(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());
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->GrantReadFile(child_id, filesystems[i].path);
if (has_delete_permission) {
policy->GrantDeleteFrom(child_id, filesystems[i].path);
if (has_copy_to_permission) {
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 = PermissionsData::CheckAPIPermissionWithParam(
extension, 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:
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();
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);
}
virtual void FileSelected(const base::FilePath& path,
int index,
void* params) OVERRIDE {
callback_.Run(path);
Release();
}
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();
}
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);
};
}
MediaGalleriesEventRouter::MediaGalleriesEventRouter(
content::BrowserContext* context)
: profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(profile_);
media_scan_manager()->AddObserver(profile_, this);
}
MediaGalleriesEventRouter::~MediaGalleriesEventRouter() {
}
void MediaGalleriesEventRouter::Shutdown() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
weak_ptr_factory_.InvalidateWeakPtrs();
media_scan_manager()->RemoveObserver(profile_);
media_scan_manager()->CancelScansForProfile(profile_);
}
static base::LazyInstance<
BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter> > g_factory =
LAZY_INSTANCE_INITIALIZER;
BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
MediaGalleriesEventRouter::GetFactoryInstance() {
return g_factory.Pointer();
}
MediaGalleriesEventRouter* MediaGalleriesEventRouter::Get(
content::BrowserContext* context) {
DCHECK(media_file_system_registry()
->GetPreferences(Profile::FromBrowserContext(context))
->IsInitialized());
return BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>::Get(context);
}
bool MediaGalleriesEventRouter::ExtensionHasScanProgressListener(
const std::string& extension_id) const {
EventRouter* router = ExtensionSystem::Get(profile_)->event_router();
return router->ExtensionHasEventListener(
extension_id,
MediaGalleries::OnScanProgress::kEventName);
}
void MediaGalleriesEventRouter::OnScanStarted(const std::string& extension_id) {
MediaGalleries::ScanProgressDetails details;
details.type = MediaGalleries::SCAN_PROGRESS_TYPE_START;
DispatchEventToExtension(
extension_id,
MediaGalleries::OnScanProgress::kEventName,
MediaGalleries::OnScanProgress::Create(details).Pass());
}
void MediaGalleriesEventRouter::OnScanCancelled(
const std::string& extension_id) {
MediaGalleries::ScanProgressDetails details;
details.type = MediaGalleries::SCAN_PROGRESS_TYPE_CANCEL;
DispatchEventToExtension(
extension_id,
MediaGalleries::OnScanProgress::kEventName,
MediaGalleries::OnScanProgress::Create(details).Pass());
}
void MediaGalleriesEventRouter::OnScanFinished(
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.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,
MediaGalleries::OnScanProgress::Create(details).Pass());
}
void MediaGalleriesEventRouter::DispatchEventToExtension(
const std::string& extension_id,
const std::string& event_name,
scoped_ptr<base::ListValue> event_args) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
EventRouter* router =
extensions::ExtensionSystem::Get(profile_)->event_router();
if (!router->ExtensionHasEventListener(extension_id, event_name))
return;
scoped_ptr<extensions::Event> event(
new extensions::Event(event_name, event_args.Pass()));
router->DispatchEventToExtension(extension_id, event.Pass());
}
MediaGalleriesGetMediaFileSystemsFunction::
~MediaGalleriesGetMediaFileSystemsFunction() {}
bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() {
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;
}
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, this,
interactive));
}
void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit(
MediaGalleries::GetMediaFileSystemsInteractivity interactive) {
switch (interactive) {
case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_YES: {
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();
}
SendResponse(false);
}
void MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog(
const std::vector<MediaFileSystemInfo>& ) {
ShowDialog();
}
void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries(
const std::vector<MediaFileSystemInfo>& filesystems) {
if (filesystems.empty())
ShowDialog();
else
ReturnGalleries(filesystems);
}
void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() {
GetMediaFileSystemsForExtension(base::Bind(
&MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries, this));
}
void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
const std::vector<MediaFileSystemInfo>& filesystems) {
scoped_ptr<base::ListValue> list(
ConstructFileSystemList(render_view_host(), GetExtension(), filesystems));
if (!list.get()) {
SendResponse(false);
return;
}
SetResult(list.release());
SendResponse(true);
}
void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
media_galleries::UsageCount(media_galleries::SHOW_DIALOG);
const Extension* extension = GetExtension();
WebContents* contents =
GetWebContents(render_view_host(), GetProfile(), extension->id());
if (!contents) {
SendResponse(false);
return;
}
base::Closure cb = base::Bind(
&MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this);
new MediaGalleriesDialogController(contents, *extension, cb);
}
void MediaGalleriesGetMediaFileSystemsFunction::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);
}
MediaGalleriesGetAllMediaFileSystemMetadataFunction::
~MediaGalleriesGetAllMediaFileSystemMetadataFunction() {}
bool MediaGalleriesGetAllMediaFileSystemMetadataFunction::RunImpl() {
media_galleries::UsageCount(
media_galleries::GET_ALL_MEDIA_FILE_SYSTEM_METADATA);
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit,
this));
}
void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit() {
MediaFileSystemRegistry* registry = media_file_system_registry();
MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile());
DCHECK(prefs->IsInitialized());
MediaGalleryPrefIdSet permitted_gallery_ids =
prefs->GalleriesForExtension(*GetExtension());
MediaStorageUtil::DeviceIdSet* device_ids = new MediaStorageUtil::DeviceIdSet;
const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
for (MediaGalleryPrefIdSet::const_iterator it = permitted_gallery_ids.begin();
it != permitted_gallery_ids.end(); ++it) {
MediaGalleriesPrefInfoMap::const_iterator gallery_it = galleries.find(*it);
DCHECK(gallery_it != galleries.end());
device_ids->insert(gallery_it->second.device_id);
}
MediaStorageUtil::FilterAttachedDevices(
device_ids,
base::Bind(
&MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries,
this,
permitted_gallery_ids,
base::Owned(device_ids)));
}
void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries(
const MediaGalleryPrefIdSet& permitted_gallery_ids,
const MediaStorageUtil::DeviceIdSet* available_devices) {
MediaFileSystemRegistry* registry = media_file_system_registry();
MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile());
base::ListValue* list = new base::ListValue();
const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
for (MediaGalleryPrefIdSet::const_iterator it = permitted_gallery_ids.begin();
it != permitted_gallery_ids.end(); ++it) {
MediaGalleriesPrefInfoMap::const_iterator gallery_it = galleries.find(*it);
DCHECK(gallery_it != galleries.end());
const MediaGalleryPrefInfo& gallery = gallery_it->second;
MediaGalleries::MediaFileSystemMetadata metadata;
metadata.name = base::UTF16ToUTF8(gallery.GetGalleryDisplayName());
metadata.gallery_id = base::Uint64ToString(gallery.pref_id);
metadata.is_removable = StorageInfo::IsRemovableDevice(gallery.device_id);
metadata.is_media_device = StorageInfo::IsMediaDevice(gallery.device_id);
metadata.is_available = ContainsKey(*available_devices, gallery.device_id);
list->Append(metadata.ToValue().release());
}
SetResult(list);
SendResponse(true);
}
MediaGalleriesAddUserSelectedFolderFunction::
~MediaGalleriesAddUserSelectedFolderFunction() {}
bool MediaGalleriesAddUserSelectedFolderFunction::RunImpl() {
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();
WebContents* contents = GetWebContents(render_view_host(), profile, app_id);
if (!contents) {
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()) {
OnDirectorySelected(base::FilePath());
return;
}
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()) {
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,
MediaGalleryPrefInfo::kUserAdded);
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);
}
MediaGalleriesStartMediaScanFunction::~MediaGalleriesStartMediaScanFunction() {}
bool MediaGalleriesStartMediaScanFunction::RunImpl() {
media_galleries::UsageCount(media_galleries::START_MEDIA_SCAN);
if (!CheckScanPermission(GetExtension(), &error_)) {
MediaGalleriesEventRouter::Get(GetProfile())->OnScanError(
GetExtension()->id());
return false;
}
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesStartMediaScanFunction::OnPreferencesInit, this));
}
void MediaGalleriesStartMediaScanFunction::OnPreferencesInit() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
if (!api->ExtensionHasScanProgressListener(GetExtension()->id())) {
error_ = kMissingEventListener;
SendResponse(false);
return;
}
media_scan_manager()->StartScan(GetProfile(), GetExtension(), user_gesture());
SendResponse(true);
}
MediaGalleriesCancelMediaScanFunction::
~MediaGalleriesCancelMediaScanFunction() {
}
bool MediaGalleriesCancelMediaScanFunction::RunImpl() {
media_galleries::UsageCount(media_galleries::CANCEL_MEDIA_SCAN);
if (!CheckScanPermission(GetExtension(), &error_)) {
MediaGalleriesEventRouter::Get(GetProfile())->OnScanError(
GetExtension()->id());
return false;
}
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesCancelMediaScanFunction::OnPreferencesInit, this));
}
void MediaGalleriesCancelMediaScanFunction::OnPreferencesInit() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
media_scan_manager()->CancelScan(GetProfile(), GetExtension());
SendResponse(true);
}
MediaGalleriesAddScanResultsFunction::~MediaGalleriesAddScanResultsFunction() {}
bool MediaGalleriesAddScanResultsFunction::RunImpl() {
media_galleries::UsageCount(media_galleries::ADD_SCAN_RESULTS);
if (!CheckScanPermission(GetExtension(), &error_)) {
return false;
}
if (!user_gesture())
return false;
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesAddScanResultsFunction::OnPreferencesInit, this));
}
MediaGalleriesScanResultDialogController*
MediaGalleriesAddScanResultsFunction::MakeDialog(
content::WebContents* web_contents,
const extensions::Extension& extension,
const base::Closure& on_finish) {
return new MediaGalleriesScanResultDialogController(web_contents, extension,
on_finish);
}
void MediaGalleriesAddScanResultsFunction::OnPreferencesInit() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
const Extension* extension = GetExtension();
MediaGalleriesPreferences* preferences =
media_file_system_registry()->GetPreferences(GetProfile());
if (MediaGalleriesScanResultDialogController::ScanResultCountForExtension(
preferences, extension) == 0) {
GetAndReturnGalleries();
return;
}
WebContents* contents =
GetWebContents(render_view_host(), GetProfile(), extension->id());
if (!contents) {
SendResponse(false);
return;
}
base::Closure cb = base::Bind(
&MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries, this);
MakeDialog(contents, *extension, cb);
}
void MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries() {
if (!render_view_host()) {
ReturnGalleries(std::vector<MediaFileSystemInfo>());
return;
}
MediaFileSystemRegistry* registry = media_file_system_registry();
DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
registry->GetMediaFileSystemsForExtension(
render_view_host(), GetExtension(),
base::Bind(&MediaGalleriesAddScanResultsFunction::ReturnGalleries,
this));
}
void MediaGalleriesAddScanResultsFunction::ReturnGalleries(
const std::vector<MediaFileSystemInfo>& filesystems) {
scoped_ptr<base::ListValue> list(
ConstructFileSystemList(render_view_host(), GetExtension(), filesystems));
if (!list.get()) {
SendResponse(false);
return;
}
SetResult(list.release());
SendResponse(true);
}
MediaGalleriesGetMetadataFunction::~MediaGalleriesGetMetadataFunction() {}
bool MediaGalleriesGetMetadataFunction::RunImpl() {
std::string blob_uuid;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &blob_uuid));
const base::Value* options_value = NULL;
if (!args_->Get(1, &options_value))
return false;
scoped_ptr<MediaGalleries::MediaMetadataOptions> options =
MediaGalleries::MediaMetadataOptions::FromValue(*options_value);
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));
}
void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
bool mime_type_only, const std::string& blob_uuid) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
BlobReader* reader = new BlobReader(
GetProfile(),
blob_uuid,
base::Bind(&MediaGalleriesGetMetadataFunction::SniffMimeType, this,
mime_type_only, blob_uuid));
reader->SetByteRange(0, net::kMaxBytesToSniff);
reader->Start();
}
void MediaGalleriesGetMetadataFunction::SniffMimeType(
bool mime_type_only, 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) {
SendResponse(false);
return;
}
if (mime_type_only) {
MediaGalleries::MediaMetadata metadata;
metadata.mime_type = mime_type;
SetResult(metadata.ToValue().release());
SendResponse(true);
return;
}
scoped_refptr<metadata::SafeMediaMetadataParser> parser(
new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid,
total_blob_length, mime_type));
parser->Start(base::Bind(
&MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this));
}
void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone(
bool parse_success, base::DictionaryValue* metadata_dictionary) {
if (!parse_success) {
SendResponse(false);
return;
}
SetResult(metadata_dictionary->DeepCopy());
SendResponse(true);
}
}