1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Implements the Chrome Extensions Media Galleries API.
7 #include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"
13 #include "base/callback.h"
14 #include "base/lazy_instance.h"
15 #include "base/numerics/safe_conversions.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/values.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
22 #include "chrome/browser/extensions/blob_reader.h"
23 #include "chrome/browser/extensions/extension_tab_util.h"
24 #include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h"
25 #include "chrome/browser/media_galleries/gallery_watch_manager.h"
26 #include "chrome/browser/media_galleries/media_file_system_registry.h"
27 #include "chrome/browser/media_galleries/media_galleries_histograms.h"
28 #include "chrome/browser/media_galleries/media_galleries_permission_controller.h"
29 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
30 #include "chrome/browser/media_galleries/media_galleries_scan_result_controller.h"
31 #include "chrome/browser/media_galleries/media_scan_manager.h"
32 #include "chrome/browser/platform_util.h"
33 #include "chrome/browser/profiles/profile.h"
34 #include "chrome/browser/ui/chrome_select_file_policy.h"
35 #include "chrome/common/extensions/api/media_galleries.h"
36 #include "chrome/common/pref_names.h"
37 #include "chrome/grit/generated_resources.h"
38 #include "components/storage_monitor/storage_info.h"
39 #include "components/web_modal/web_contents_modal_dialog_manager.h"
40 #include "content/public/browser/blob_handle.h"
41 #include "content/public/browser/browser_context.h"
42 #include "content/public/browser/browser_thread.h"
43 #include "content/public/browser/child_process_security_policy.h"
44 #include "content/public/browser/render_process_host.h"
45 #include "content/public/browser/render_view_host.h"
46 #include "content/public/browser/web_contents.h"
47 #include "extensions/browser/app_window/app_window.h"
48 #include "extensions/browser/app_window/app_window_registry.h"
49 #include "extensions/browser/blob_holder.h"
50 #include "extensions/browser/extension_prefs.h"
51 #include "extensions/browser/extension_system.h"
52 #include "extensions/common/extension.h"
53 #include "extensions/common/permissions/api_permission.h"
54 #include "extensions/common/permissions/media_galleries_permission.h"
55 #include "extensions/common/permissions/permissions_data.h"
56 #include "net/base/mime_sniffer.h"
57 #include "storage/browser/blob/blob_data_handle.h"
58 #include "ui/base/l10n/l10n_util.h"
60 using content::WebContents;
61 using storage_monitor::MediaStorageUtil;
62 using storage_monitor::StorageInfo;
63 using web_modal::WebContentsModalDialogManager;
65 namespace extensions {
67 namespace MediaGalleries = api::media_galleries;
68 namespace DropPermissionForMediaFileSystem =
69 MediaGalleries::DropPermissionForMediaFileSystem;
70 namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;
71 namespace AddGalleryWatch = MediaGalleries::AddGalleryWatch;
72 namespace RemoveGalleryWatch = MediaGalleries::RemoveGalleryWatch;
73 namespace GetAllGalleryWatch = MediaGalleries::GetAllGalleryWatch;
77 const char kDisallowedByPolicy[] =
78 "Media Galleries API is disallowed by policy: ";
79 const char kFailedToSetGalleryPermission[] =
80 "Failed to set gallery permission.";
81 const char kInvalidGalleryIdMsg[] = "Invalid gallery id.";
82 const char kMissingEventListener[] = "Missing event listener registration.";
83 const char kNonExistentGalleryId[] = "Non-existent gallery id.";
84 const char kNoScanPermission[] = "No permission to scan.";
86 const char kDeviceIdKey[] = "deviceId";
87 const char kGalleryIdKey[] = "galleryId";
88 const char kIsAvailableKey[] = "isAvailable";
89 const char kIsMediaDeviceKey[] = "isMediaDevice";
90 const char kIsRemovableKey[] = "isRemovable";
91 const char kNameKey[] = "name";
93 const char kMetadataKey[] = "metadata";
94 const char kAttachedImagesBlobInfoKey[] = "attachedImagesBlobInfo";
95 const char kBlobUUIDKey[] = "blobUUID";
96 const char kTypeKey[] = "type";
97 const char kSizeKey[] = "size";
99 const char kInvalidGalleryId[] = "-1";
101 MediaFileSystemRegistry* media_file_system_registry() {
102 return g_browser_process->media_file_system_registry();
105 GalleryWatchManager* gallery_watch_manager() {
106 return media_file_system_registry()->gallery_watch_manager();
109 MediaScanManager* media_scan_manager() {
110 return media_file_system_registry()->media_scan_manager();
113 // Checks whether the MediaGalleries API is currently accessible (it may be
114 // disallowed even if an extension has the requisite permission). Then
115 // initializes the MediaGalleriesPreferences
116 bool Setup(Profile* profile, std::string* error, base::Closure callback) {
117 if (!ChromeSelectFilePolicy::FileSelectDialogsAllowed()) {
118 *error = std::string(kDisallowedByPolicy) +
119 prefs::kAllowFileSelectionDialogs;
123 MediaGalleriesPreferences* preferences =
124 media_file_system_registry()->GetPreferences(profile);
125 preferences->EnsureInitialized(callback);
129 // Returns true and sets |gallery_file_path| and |gallery_pref_id| if the
130 // |gallery_id| is valid and returns false otherwise.
131 bool GetGalleryFilePathAndId(const std::string& gallery_id,
133 const Extension* extension,
134 base::FilePath* gallery_file_path,
135 MediaGalleryPrefId* gallery_pref_id) {
136 MediaGalleryPrefId pref_id;
137 if (!base::StringToUint64(gallery_id, &pref_id))
139 MediaGalleriesPreferences* preferences =
140 g_browser_process->media_file_system_registry()->GetPreferences(profile);
141 base::FilePath file_path(
142 preferences->LookUpGalleryPathForExtension(pref_id, extension, false));
143 if (file_path.empty())
145 *gallery_pref_id = pref_id;
146 *gallery_file_path = file_path;
150 WebContents* GetWebContents(content::RenderViewHost* rvh,
152 const std::string& app_id) {
153 WebContents* contents = WebContents::FromRenderViewHost(rvh);
154 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
155 WebContentsModalDialogManager::FromWebContents(contents);
156 if (!web_contents_modal_dialog_manager) {
157 // If there is no WebContentsModalDialogManager, then this contents is
158 // probably the background page for an app. Try to find a app window to
160 AppWindow* window = AppWindowRegistry::Get(profile)
161 ->GetCurrentAppWindowForApp(app_id);
162 contents = window ? window->web_contents() : NULL;
167 base::ListValue* ConstructFileSystemList(
168 content::RenderViewHost* rvh,
169 const Extension* extension,
170 const std::vector<MediaFileSystemInfo>& filesystems) {
174 MediaGalleriesPermission::CheckParam read_param(
175 MediaGalleriesPermission::kReadPermission);
176 const PermissionsData* permissions_data = extension->permissions_data();
177 bool has_read_permission = permissions_data->CheckAPIPermissionWithParam(
178 APIPermission::kMediaGalleries, &read_param);
179 MediaGalleriesPermission::CheckParam copy_to_param(
180 MediaGalleriesPermission::kCopyToPermission);
181 bool has_copy_to_permission = permissions_data->CheckAPIPermissionWithParam(
182 APIPermission::kMediaGalleries, ©_to_param);
183 MediaGalleriesPermission::CheckParam delete_param(
184 MediaGalleriesPermission::kDeletePermission);
185 bool has_delete_permission = permissions_data->CheckAPIPermissionWithParam(
186 APIPermission::kMediaGalleries, &delete_param);
188 const int child_id = rvh->GetProcess()->GetID();
189 scoped_ptr<base::ListValue> list(new base::ListValue());
190 for (size_t i = 0; i < filesystems.size(); ++i) {
191 scoped_ptr<base::DictionaryValue> file_system_dict_value(
192 new base::DictionaryValue());
194 // Send the file system id so the renderer can create a valid FileSystem
196 file_system_dict_value->SetStringWithoutPathExpansion(
197 "fsid", filesystems[i].fsid);
199 file_system_dict_value->SetStringWithoutPathExpansion(
200 kNameKey, filesystems[i].name);
201 file_system_dict_value->SetStringWithoutPathExpansion(
203 base::Uint64ToString(filesystems[i].pref_id));
204 if (!filesystems[i].transient_device_id.empty()) {
205 file_system_dict_value->SetStringWithoutPathExpansion(
206 kDeviceIdKey, filesystems[i].transient_device_id);
208 file_system_dict_value->SetBooleanWithoutPathExpansion(
209 kIsRemovableKey, filesystems[i].removable);
210 file_system_dict_value->SetBooleanWithoutPathExpansion(
211 kIsMediaDeviceKey, filesystems[i].media_device);
212 file_system_dict_value->SetBooleanWithoutPathExpansion(
213 kIsAvailableKey, true);
215 list->Append(file_system_dict_value.release());
217 if (filesystems[i].path.empty())
220 if (has_read_permission) {
221 content::ChildProcessSecurityPolicy* policy =
222 content::ChildProcessSecurityPolicy::GetInstance();
223 policy->GrantReadFile(child_id, filesystems[i].path);
224 if (has_delete_permission) {
225 policy->GrantDeleteFrom(child_id, filesystems[i].path);
226 if (has_copy_to_permission) {
227 policy->GrantCopyInto(child_id, filesystems[i].path);
233 return list.release();
236 bool CheckScanPermission(const extensions::Extension* extension,
237 std::string* error) {
240 MediaGalleriesPermission::CheckParam scan_param(
241 MediaGalleriesPermission::kScanPermission);
242 bool has_scan_permission =
243 extension->permissions_data()->CheckAPIPermissionWithParam(
244 APIPermission::kMediaGalleries, &scan_param);
245 if (!has_scan_permission)
246 *error = kNoScanPermission;
247 return has_scan_permission;
250 class SelectDirectoryDialog : public ui::SelectFileDialog::Listener,
251 public base::RefCounted<SelectDirectoryDialog> {
253 // Selected file path, or an empty path if the user canceled.
254 typedef base::Callback<void(const base::FilePath&)> Callback;
256 SelectDirectoryDialog(WebContents* web_contents, const Callback& callback)
257 : web_contents_(web_contents),
258 callback_(callback) {
259 select_file_dialog_ = ui::SelectFileDialog::Create(
260 this, new ChromeSelectFilePolicy(web_contents));
263 void Show(const base::FilePath& default_path) {
264 AddRef(); // Balanced in the two reachable listener outcomes.
265 select_file_dialog_->SelectFile(
266 ui::SelectFileDialog::SELECT_FOLDER,
267 l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE),
271 base::FilePath::StringType(),
272 platform_util::GetTopLevel(web_contents_->GetNativeView()),
276 // ui::SelectFileDialog::Listener implementation.
277 virtual void FileSelected(const base::FilePath& path,
279 void* params) OVERRIDE {
281 Release(); // Balanced in Show().
284 virtual void MultiFilesSelected(const std::vector<base::FilePath>& files,
285 void* params) OVERRIDE {
286 NOTREACHED() << "Should not be able to select multiple files";
289 virtual void FileSelectionCanceled(void* params) OVERRIDE {
290 callback_.Run(base::FilePath());
291 Release(); // Balanced in Show().
295 friend class base::RefCounted<SelectDirectoryDialog>;
296 virtual ~SelectDirectoryDialog() {}
298 scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
299 WebContents* web_contents_;
302 DISALLOW_COPY_AND_ASSIGN(SelectDirectoryDialog);
307 MediaGalleriesEventRouter::MediaGalleriesEventRouter(
308 content::BrowserContext* context)
309 : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
310 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
313 EventRouter::Get(profile_)->RegisterObserver(
314 this, MediaGalleries::OnGalleryChanged::kEventName);
316 gallery_watch_manager()->AddObserver(profile_, this);
317 media_scan_manager()->AddObserver(profile_, this);
320 MediaGalleriesEventRouter::~MediaGalleriesEventRouter() {
323 void MediaGalleriesEventRouter::Shutdown() {
324 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
325 weak_ptr_factory_.InvalidateWeakPtrs();
327 EventRouter::Get(profile_)->UnregisterObserver(this);
329 gallery_watch_manager()->RemoveObserver(profile_);
330 media_scan_manager()->RemoveObserver(profile_);
331 media_scan_manager()->CancelScansForProfile(profile_);
334 static base::LazyInstance<
335 BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter> > g_factory =
336 LAZY_INSTANCE_INITIALIZER;
339 BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
340 MediaGalleriesEventRouter::GetFactoryInstance() {
341 return g_factory.Pointer();
345 MediaGalleriesEventRouter* MediaGalleriesEventRouter::Get(
346 content::BrowserContext* context) {
347 DCHECK(media_file_system_registry()
348 ->GetPreferences(Profile::FromBrowserContext(context))
350 return BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>::Get(context);
353 bool MediaGalleriesEventRouter::ExtensionHasGalleryChangeListener(
354 const std::string& extension_id) const {
355 return EventRouter::Get(profile_)->ExtensionHasEventListener(
356 extension_id, MediaGalleries::OnGalleryChanged::kEventName);
359 bool MediaGalleriesEventRouter::ExtensionHasScanProgressListener(
360 const std::string& extension_id) const {
361 return EventRouter::Get(profile_)->ExtensionHasEventListener(
362 extension_id, MediaGalleries::OnScanProgress::kEventName);
365 void MediaGalleriesEventRouter::OnScanStarted(const std::string& extension_id) {
366 MediaGalleries::ScanProgressDetails details;
367 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_START;
368 DispatchEventToExtension(
370 MediaGalleries::OnScanProgress::kEventName,
371 MediaGalleries::OnScanProgress::Create(details).Pass());
374 void MediaGalleriesEventRouter::OnScanCancelled(
375 const std::string& extension_id) {
376 MediaGalleries::ScanProgressDetails details;
377 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_CANCEL;
378 DispatchEventToExtension(
380 MediaGalleries::OnScanProgress::kEventName,
381 MediaGalleries::OnScanProgress::Create(details).Pass());
384 void MediaGalleriesEventRouter::OnScanFinished(
385 const std::string& extension_id, int gallery_count,
386 const MediaGalleryScanResult& file_counts) {
387 media_galleries::UsageCount(media_galleries::SCAN_FINISHED);
388 MediaGalleries::ScanProgressDetails details;
389 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_FINISH;
390 details.gallery_count.reset(new int(gallery_count));
391 details.audio_count.reset(new int(file_counts.audio_count));
392 details.image_count.reset(new int(file_counts.image_count));
393 details.video_count.reset(new int(file_counts.video_count));
394 DispatchEventToExtension(
396 MediaGalleries::OnScanProgress::kEventName,
397 MediaGalleries::OnScanProgress::Create(details).Pass());
400 void MediaGalleriesEventRouter::OnScanError(
401 const std::string& extension_id) {
402 MediaGalleries::ScanProgressDetails details;
403 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_ERROR;
404 DispatchEventToExtension(
406 MediaGalleries::OnScanProgress::kEventName,
407 MediaGalleries::OnScanProgress::Create(details).Pass());
410 void MediaGalleriesEventRouter::DispatchEventToExtension(
411 const std::string& extension_id,
412 const std::string& event_name,
413 scoped_ptr<base::ListValue> event_args) {
414 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
415 EventRouter* router = EventRouter::Get(profile_);
416 if (!router->ExtensionHasEventListener(extension_id, event_name))
419 scoped_ptr<extensions::Event> event(
420 new extensions::Event(event_name, event_args.Pass()));
421 router->DispatchEventToExtension(extension_id, event.Pass());
424 void MediaGalleriesEventRouter::OnGalleryChanged(
425 const std::string& extension_id, MediaGalleryPrefId gallery_id) {
426 MediaGalleries::GalleryChangeDetails details;
427 details.type = MediaGalleries::GALLERY_CHANGE_TYPE_CONTENTS_CHANGED;
428 details.gallery_id = base::Uint64ToString(gallery_id);
429 DispatchEventToExtension(
431 MediaGalleries::OnGalleryChanged::kEventName,
432 MediaGalleries::OnGalleryChanged::Create(details).Pass());
435 void MediaGalleriesEventRouter::OnGalleryWatchDropped(
436 const std::string& extension_id, MediaGalleryPrefId gallery_id) {
437 MediaGalleries::GalleryChangeDetails details;
438 details.type = MediaGalleries::GALLERY_CHANGE_TYPE_WATCH_DROPPED;
439 details.gallery_id = gallery_id;
440 DispatchEventToExtension(
442 MediaGalleries::OnGalleryChanged::kEventName,
443 MediaGalleries::OnGalleryChanged::Create(details).Pass());
446 void MediaGalleriesEventRouter::OnListenerRemoved(
447 const EventListenerInfo& details) {
448 if (details.event_name == MediaGalleries::OnGalleryChanged::kEventName &&
449 !ExtensionHasGalleryChangeListener(details.extension_id)) {
450 gallery_watch_manager()->RemoveAllWatches(profile_, details.extension_id);
454 ///////////////////////////////////////////////////////////////////////////////
455 // MediaGalleriesGetMediaFileSystemsFunction //
456 ///////////////////////////////////////////////////////////////////////////////
457 MediaGalleriesGetMediaFileSystemsFunction::
458 ~MediaGalleriesGetMediaFileSystemsFunction() {}
460 bool MediaGalleriesGetMediaFileSystemsFunction::RunAsync() {
461 media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS);
462 scoped_ptr<GetMediaFileSystems::Params> params(
463 GetMediaFileSystems::Params::Create(*args_));
464 EXTENSION_FUNCTION_VALIDATE(params.get());
465 MediaGalleries::GetMediaFileSystemsInteractivity interactive =
466 MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO;
467 if (params->details.get() && params->details->interactive != MediaGalleries::
468 GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) {
469 interactive = params->details->interactive;
472 return Setup(GetProfile(), &error_, base::Bind(
473 &MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, this,
477 void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit(
478 MediaGalleries::GetMediaFileSystemsInteractivity interactive) {
479 switch (interactive) {
480 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_YES: {
481 // The MediaFileSystemRegistry only updates preferences for extensions
482 // that it knows are in use. Since this may be the first call to
483 // chrome.getMediaFileSystems for this extension, call
484 // GetMediaFileSystemsForExtension() here solely so that
485 // MediaFileSystemRegistry will send preference changes.
486 GetMediaFileSystemsForExtension(base::Bind(
487 &MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog, this));
490 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_IF_NEEDED: {
491 GetMediaFileSystemsForExtension(base::Bind(
492 &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries,
496 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO:
497 GetAndReturnGalleries();
499 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE:
505 void MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog(
506 const std::vector<MediaFileSystemInfo>& /*filesystems*/) {
510 void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries(
511 const std::vector<MediaFileSystemInfo>& filesystems) {
512 if (filesystems.empty())
515 ReturnGalleries(filesystems);
518 void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() {
519 GetMediaFileSystemsForExtension(base::Bind(
520 &MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries, this));
523 void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
524 const std::vector<MediaFileSystemInfo>& filesystems) {
525 scoped_ptr<base::ListValue> list(
526 ConstructFileSystemList(render_view_host(), extension(), filesystems));
532 // The custom JS binding will use this list to create DOMFileSystem objects.
533 SetResult(list.release());
537 void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
538 media_galleries::UsageCount(media_galleries::SHOW_DIALOG);
539 WebContents* contents =
540 GetWebContents(render_view_host(), GetProfile(), extension()->id());
546 // Controller will delete itself.
547 base::Closure cb = base::Bind(
548 &MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this);
549 new MediaGalleriesPermissionController(contents, *extension(), cb);
552 void MediaGalleriesGetMediaFileSystemsFunction::GetMediaFileSystemsForExtension(
553 const MediaFileSystemsCallback& cb) {
554 if (!render_view_host()) {
555 cb.Run(std::vector<MediaFileSystemInfo>());
558 MediaFileSystemRegistry* registry = media_file_system_registry();
559 DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
560 registry->GetMediaFileSystemsForExtension(
561 render_view_host(), extension(), cb);
565 ///////////////////////////////////////////////////////////////////////////////
566 // MediaGalleriesGetAllMediaFileSystemMetadataFunction //
567 ///////////////////////////////////////////////////////////////////////////////
568 MediaGalleriesGetAllMediaFileSystemMetadataFunction::
569 ~MediaGalleriesGetAllMediaFileSystemMetadataFunction() {}
571 bool MediaGalleriesGetAllMediaFileSystemMetadataFunction::RunAsync() {
572 media_galleries::UsageCount(
573 media_galleries::GET_ALL_MEDIA_FILE_SYSTEM_METADATA);
574 return Setup(GetProfile(), &error_, base::Bind(
575 &MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit,
579 void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit() {
580 MediaFileSystemRegistry* registry = media_file_system_registry();
581 MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile());
582 DCHECK(prefs->IsInitialized());
583 MediaGalleryPrefIdSet permitted_gallery_ids =
584 prefs->GalleriesForExtension(*extension());
586 MediaStorageUtil::DeviceIdSet* device_ids = new MediaStorageUtil::DeviceIdSet;
587 const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
588 for (MediaGalleryPrefIdSet::const_iterator it = permitted_gallery_ids.begin();
589 it != permitted_gallery_ids.end(); ++it) {
590 MediaGalleriesPrefInfoMap::const_iterator gallery_it = galleries.find(*it);
591 DCHECK(gallery_it != galleries.end());
592 device_ids->insert(gallery_it->second.device_id);
595 MediaStorageUtil::FilterAttachedDevices(
598 &MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries,
600 permitted_gallery_ids,
601 base::Owned(device_ids)));
604 void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries(
605 const MediaGalleryPrefIdSet& permitted_gallery_ids,
606 const MediaStorageUtil::DeviceIdSet* available_devices) {
607 MediaFileSystemRegistry* registry = media_file_system_registry();
608 MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile());
610 base::ListValue* list = new base::ListValue();
611 const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
612 for (MediaGalleryPrefIdSet::const_iterator it = permitted_gallery_ids.begin();
613 it != permitted_gallery_ids.end(); ++it) {
614 MediaGalleriesPrefInfoMap::const_iterator gallery_it = galleries.find(*it);
615 DCHECK(gallery_it != galleries.end());
616 const MediaGalleryPrefInfo& gallery = gallery_it->second;
617 MediaGalleries::MediaFileSystemMetadata metadata;
618 metadata.name = base::UTF16ToUTF8(gallery.GetGalleryDisplayName());
619 metadata.gallery_id = base::Uint64ToString(gallery.pref_id);
620 metadata.is_removable = StorageInfo::IsRemovableDevice(gallery.device_id);
621 metadata.is_media_device = StorageInfo::IsMediaDevice(gallery.device_id);
622 metadata.is_available = ContainsKey(*available_devices, gallery.device_id);
623 list->Append(metadata.ToValue().release());
630 ///////////////////////////////////////////////////////////////////////////////
631 // MediaGalleriesAddUserSelectedFolderFunction //
632 ///////////////////////////////////////////////////////////////////////////////
633 MediaGalleriesAddUserSelectedFolderFunction::
634 ~MediaGalleriesAddUserSelectedFolderFunction() {}
636 bool MediaGalleriesAddUserSelectedFolderFunction::RunAsync() {
637 media_galleries::UsageCount(media_galleries::ADD_USER_SELECTED_FOLDER);
638 return Setup(GetProfile(), &error_, base::Bind(
639 &MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit, this));
642 void MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit() {
643 Profile* profile = GetProfile();
644 const std::string& app_id = extension()->id();
645 WebContents* contents = GetWebContents(render_view_host(), profile, app_id);
647 // When the request originated from a background page, but there is no app
648 // window open, check to see if it originated from a tab and display the
649 // dialog in that tab.
650 bool found_tab = extensions::ExtensionTabUtil::GetTabById(
651 source_tab_id(), profile, profile->IsOffTheRecord(),
652 NULL, NULL, &contents, NULL);
653 if (!found_tab || !contents) {
659 if (!user_gesture()) {
660 OnDirectorySelected(base::FilePath());
664 base::FilePath last_used_path =
665 extensions::file_system_api::GetLastChooseEntryDirectory(
666 extensions::ExtensionPrefs::Get(profile), app_id);
667 SelectDirectoryDialog::Callback callback = base::Bind(
668 &MediaGalleriesAddUserSelectedFolderFunction::OnDirectorySelected, this);
669 scoped_refptr<SelectDirectoryDialog> select_directory_dialog =
670 new SelectDirectoryDialog(contents, callback);
671 select_directory_dialog->Show(last_used_path);
674 void MediaGalleriesAddUserSelectedFolderFunction::OnDirectorySelected(
675 const base::FilePath& selected_directory) {
676 if (selected_directory.empty()) {
677 // User cancelled case.
678 GetMediaFileSystemsForExtension(base::Bind(
679 &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
681 kInvalidMediaGalleryPrefId));
685 extensions::file_system_api::SetLastChooseEntryDirectory(
686 extensions::ExtensionPrefs::Get(GetProfile()),
690 MediaGalleriesPreferences* preferences =
691 media_file_system_registry()->GetPreferences(GetProfile());
692 MediaGalleryPrefId pref_id =
693 preferences->AddGalleryByPath(selected_directory,
694 MediaGalleryPrefInfo::kUserAdded);
695 preferences->SetGalleryPermissionForExtension(*extension(), pref_id, true);
697 GetMediaFileSystemsForExtension(base::Bind(
698 &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
703 void MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId(
704 MediaGalleryPrefId pref_id,
705 const std::vector<MediaFileSystemInfo>& filesystems) {
706 scoped_ptr<base::ListValue> list(
707 ConstructFileSystemList(render_view_host(), extension(), filesystems));
714 if (pref_id != kInvalidMediaGalleryPrefId) {
715 for (size_t i = 0; i < filesystems.size(); ++i) {
716 if (filesystems[i].pref_id == pref_id) {
722 base::DictionaryValue* results = new base::DictionaryValue;
723 results->SetWithoutPathExpansion("mediaFileSystems", list.release());
724 results->SetIntegerWithoutPathExpansion("selectedFileSystemIndex", index);
730 MediaGalleriesAddUserSelectedFolderFunction::GetMediaFileSystemsForExtension(
731 const MediaFileSystemsCallback& cb) {
732 if (!render_view_host()) {
733 cb.Run(std::vector<MediaFileSystemInfo>());
736 MediaFileSystemRegistry* registry = media_file_system_registry();
737 DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
738 registry->GetMediaFileSystemsForExtension(
739 render_view_host(), extension(), cb);
742 ///////////////////////////////////////////////////////////////////////////////
743 // MediaGalleriesDropPermissionForMediaFileSystemFunction //
744 ///////////////////////////////////////////////////////////////////////////////
745 MediaGalleriesDropPermissionForMediaFileSystemFunction::
746 ~MediaGalleriesDropPermissionForMediaFileSystemFunction() {}
748 bool MediaGalleriesDropPermissionForMediaFileSystemFunction::RunAsync() {
749 media_galleries::UsageCount(
750 media_galleries::DROP_PERMISSION_FOR_MEDIA_FILE_SYSTEM);
752 scoped_ptr<DropPermissionForMediaFileSystem::Params> params(
753 DropPermissionForMediaFileSystem::Params::Create(*args_));
754 EXTENSION_FUNCTION_VALIDATE(params.get());
755 MediaGalleryPrefId pref_id;
756 if (!base::StringToUint64(params->gallery_id, &pref_id)) {
757 error_ = kInvalidGalleryIdMsg;
761 base::Closure callback = base::Bind(
762 &MediaGalleriesDropPermissionForMediaFileSystemFunction::
766 return Setup(GetProfile(), &error_, callback);
769 void MediaGalleriesDropPermissionForMediaFileSystemFunction::OnPreferencesInit(
770 MediaGalleryPrefId pref_id) {
771 MediaGalleriesPreferences* preferences =
772 media_file_system_registry()->GetPreferences(GetProfile());
773 if (!ContainsKey(preferences->known_galleries(), pref_id)) {
774 error_ = kNonExistentGalleryId;
779 bool dropped = preferences->SetGalleryPermissionForExtension(
780 *extension(), pref_id, false);
782 SetResult(new base::StringValue(base::Uint64ToString(pref_id)));
784 error_ = kFailedToSetGalleryPermission;
785 SendResponse(dropped);
788 ///////////////////////////////////////////////////////////////////////////////
789 // MediaGalleriesStartMediaScanFunction //
790 ///////////////////////////////////////////////////////////////////////////////
791 MediaGalleriesStartMediaScanFunction::~MediaGalleriesStartMediaScanFunction() {}
793 bool MediaGalleriesStartMediaScanFunction::RunAsync() {
794 media_galleries::UsageCount(media_galleries::START_MEDIA_SCAN);
795 if (!CheckScanPermission(extension(), &error_)) {
796 MediaGalleriesEventRouter::Get(GetProfile())
797 ->OnScanError(extension()->id());
800 return Setup(GetProfile(), &error_, base::Bind(
801 &MediaGalleriesStartMediaScanFunction::OnPreferencesInit, this));
804 void MediaGalleriesStartMediaScanFunction::OnPreferencesInit() {
805 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
806 MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
807 if (!api->ExtensionHasScanProgressListener(extension()->id())) {
808 error_ = kMissingEventListener;
813 media_scan_manager()->StartScan(GetProfile(), extension(), user_gesture());
817 ///////////////////////////////////////////////////////////////////////////////
818 // MediaGalleriesCancelMediaScanFunction //
819 ///////////////////////////////////////////////////////////////////////////////
820 MediaGalleriesCancelMediaScanFunction::
821 ~MediaGalleriesCancelMediaScanFunction() {
824 bool MediaGalleriesCancelMediaScanFunction::RunAsync() {
825 media_galleries::UsageCount(media_galleries::CANCEL_MEDIA_SCAN);
826 if (!CheckScanPermission(extension(), &error_)) {
827 MediaGalleriesEventRouter::Get(GetProfile())
828 ->OnScanError(extension()->id());
831 return Setup(GetProfile(), &error_, base::Bind(
832 &MediaGalleriesCancelMediaScanFunction::OnPreferencesInit, this));
835 void MediaGalleriesCancelMediaScanFunction::OnPreferencesInit() {
836 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
837 media_scan_manager()->CancelScan(GetProfile(), extension());
841 ///////////////////////////////////////////////////////////////////////////////
842 // MediaGalleriesAddScanResultsFunction //
843 ///////////////////////////////////////////////////////////////////////////////
844 MediaGalleriesAddScanResultsFunction::~MediaGalleriesAddScanResultsFunction() {}
846 bool MediaGalleriesAddScanResultsFunction::RunAsync() {
847 media_galleries::UsageCount(media_galleries::ADD_SCAN_RESULTS);
848 if (!CheckScanPermission(extension(), &error_)) {
849 // We don't fire a scan progress error here, as it would be unintuitive.
855 return Setup(GetProfile(), &error_, base::Bind(
856 &MediaGalleriesAddScanResultsFunction::OnPreferencesInit, this));
859 MediaGalleriesScanResultController*
860 MediaGalleriesAddScanResultsFunction::MakeDialog(
861 content::WebContents* web_contents,
862 const extensions::Extension& extension,
863 const base::Closure& on_finish) {
864 // Controller will delete itself.
865 return new MediaGalleriesScanResultController(web_contents, extension,
869 void MediaGalleriesAddScanResultsFunction::OnPreferencesInit() {
870 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
871 MediaGalleriesPreferences* preferences =
872 media_file_system_registry()->GetPreferences(GetProfile());
873 if (MediaGalleriesScanResultController::ScanResultCountForExtension(
874 preferences, extension()) == 0) {
875 GetAndReturnGalleries();
879 WebContents* contents =
880 GetWebContents(render_view_host(), GetProfile(), extension()->id());
886 base::Closure cb = base::Bind(
887 &MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries, this);
888 MakeDialog(contents, *extension(), cb);
891 void MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries() {
892 if (!render_view_host()) {
893 ReturnGalleries(std::vector<MediaFileSystemInfo>());
896 MediaFileSystemRegistry* registry = media_file_system_registry();
897 DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
898 registry->GetMediaFileSystemsForExtension(
901 base::Bind(&MediaGalleriesAddScanResultsFunction::ReturnGalleries, this));
904 void MediaGalleriesAddScanResultsFunction::ReturnGalleries(
905 const std::vector<MediaFileSystemInfo>& filesystems) {
906 scoped_ptr<base::ListValue> list(
907 ConstructFileSystemList(render_view_host(), extension(), filesystems));
913 // The custom JS binding will use this list to create DOMFileSystem objects.
914 SetResult(list.release());
918 ///////////////////////////////////////////////////////////////////////////////
919 // MediaGalleriesGetMetadataFunction //
920 ///////////////////////////////////////////////////////////////////////////////
921 MediaGalleriesGetMetadataFunction::~MediaGalleriesGetMetadataFunction() {}
923 bool MediaGalleriesGetMetadataFunction::RunAsync() {
924 std::string blob_uuid;
925 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &blob_uuid));
927 const base::Value* options_value = NULL;
928 if (!args_->Get(1, &options_value))
930 scoped_ptr<MediaGalleries::MediaMetadataOptions> options =
931 MediaGalleries::MediaMetadataOptions::FromValue(*options_value);
935 return Setup(GetProfile(), &error_, base::Bind(
936 &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this,
937 options->metadata_type, blob_uuid));
940 void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
941 MediaGalleries::GetMetadataType metadata_type,
942 const std::string& blob_uuid) {
943 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
945 // BlobReader is self-deleting.
946 BlobReader* reader = new BlobReader(
949 base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this,
950 metadata_type, blob_uuid));
951 reader->SetByteRange(0, net::kMaxBytesToSniff);
955 void MediaGalleriesGetMetadataFunction::GetMetadata(
956 MediaGalleries::GetMetadataType metadata_type, const std::string& blob_uuid,
957 scoped_ptr<std::string> blob_header, int64 total_blob_length) {
958 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
960 std::string mime_type;
961 bool mime_type_sniffed = net::SniffMimeTypeFromLocalData(
962 blob_header->c_str(), blob_header->size(), &mime_type);
964 if (!mime_type_sniffed) {
969 if (metadata_type == MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY) {
970 MediaGalleries::MediaMetadata metadata;
971 metadata.mime_type = mime_type;
973 base::DictionaryValue* result_dictionary = new base::DictionaryValue;
974 result_dictionary->Set(kMetadataKey, metadata.ToValue().release());
975 SetResult(result_dictionary);
980 // We get attached images by default. GET_METADATA_TYPE_NONE is the default
981 // value if the caller doesn't specify the metadata type.
982 bool get_attached_images =
983 metadata_type == MediaGalleries::GET_METADATA_TYPE_ALL ||
984 metadata_type == MediaGalleries::GET_METADATA_TYPE_NONE;
986 scoped_refptr<metadata::SafeMediaMetadataParser> parser(
987 new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid,
988 total_blob_length, mime_type,
989 get_attached_images));
990 parser->Start(base::Bind(
991 &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this));
994 void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone(
995 bool parse_success, scoped_ptr<base::DictionaryValue> metadata_dictionary,
996 scoped_ptr<std::vector<metadata::AttachedImage> > attached_images) {
997 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
999 if (!parse_success) {
1000 SendResponse(false);
1004 DCHECK(metadata_dictionary.get());
1005 DCHECK(attached_images.get());
1007 scoped_ptr<base::DictionaryValue> result_dictionary(
1008 new base::DictionaryValue);
1009 result_dictionary->Set(kMetadataKey, metadata_dictionary.release());
1011 if (attached_images->empty()) {
1012 SetResult(result_dictionary.release());
1017 result_dictionary->Set(kAttachedImagesBlobInfoKey, new base::ListValue);
1018 metadata::AttachedImage* first_image = &attached_images->front();
1019 content::BrowserContext::CreateMemoryBackedBlob(
1021 first_image->data.c_str(),
1022 first_image->data.size(),
1023 base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
1024 this, base::Passed(&result_dictionary),
1025 base::Passed(&attached_images),
1026 base::Passed(make_scoped_ptr(new std::vector<std::string>))));
1029 void MediaGalleriesGetMetadataFunction::ConstructNextBlob(
1030 scoped_ptr<base::DictionaryValue> result_dictionary,
1031 scoped_ptr<std::vector<metadata::AttachedImage> > attached_images,
1032 scoped_ptr<std::vector<std::string> > blob_uuids,
1033 scoped_ptr<content::BlobHandle> current_blob) {
1034 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1036 DCHECK(result_dictionary.get());
1037 DCHECK(attached_images.get());
1038 DCHECK(blob_uuids.get());
1039 DCHECK(current_blob.get());
1041 DCHECK(!attached_images->empty());
1042 DCHECK_LT(blob_uuids->size(), attached_images->size());
1044 // For the newly constructed Blob, store its image's metadata and Blob UUID.
1045 base::ListValue* attached_images_list = NULL;
1046 result_dictionary->GetList(kAttachedImagesBlobInfoKey, &attached_images_list);
1047 DCHECK(attached_images_list);
1048 DCHECK_LT(attached_images_list->GetSize(), attached_images->size());
1050 metadata::AttachedImage* current_image =
1051 &(*attached_images)[blob_uuids->size()];
1052 base::DictionaryValue* attached_image = new base::DictionaryValue;
1053 attached_image->Set(kBlobUUIDKey, new base::StringValue(
1054 current_blob->GetUUID()));
1055 attached_image->Set(kTypeKey, new base::StringValue(
1056 current_image->type));
1057 attached_image->Set(kSizeKey, new base::FundamentalValue(
1058 base::checked_cast<int>(current_image->data.size())));
1059 attached_images_list->Append(attached_image);
1061 blob_uuids->push_back(current_blob->GetUUID());
1062 WebContents* contents = WebContents::FromRenderViewHost(render_view_host());
1063 extensions::BlobHolder* holder =
1064 extensions::BlobHolder::FromRenderProcessHost(
1065 contents->GetRenderProcessHost());
1066 holder->HoldBlobReference(current_blob.Pass());
1068 // Construct the next Blob if necessary.
1069 if (blob_uuids->size() < attached_images->size()) {
1070 metadata::AttachedImage* next_image =
1071 &(*attached_images)[blob_uuids->size()];
1072 content::BrowserContext::CreateMemoryBackedBlob(
1074 next_image->data.c_str(),
1075 next_image->data.size(),
1076 base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
1077 this, base::Passed(&result_dictionary),
1078 base::Passed(&attached_images), base::Passed(&blob_uuids)));
1082 // All Blobs have been constructed. The renderer will take ownership.
1083 SetResult(result_dictionary.release());
1084 SetTransferredBlobUUIDs(*blob_uuids);
1088 ///////////////////////////////////////////////////////////////////////////////
1089 // MediaGalleriesAddGalleryWatchFunction //
1090 ///////////////////////////////////////////////////////////////////////////////
1091 MediaGalleriesAddGalleryWatchFunction::
1092 ~MediaGalleriesAddGalleryWatchFunction() {
1095 bool MediaGalleriesAddGalleryWatchFunction::RunAsync() {
1096 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1097 DCHECK(GetProfile());
1098 if (!render_view_host() || !render_view_host()->GetProcess())
1101 scoped_ptr<AddGalleryWatch::Params> params(
1102 AddGalleryWatch::Params::Create(*args_));
1103 EXTENSION_FUNCTION_VALIDATE(params.get());
1105 MediaGalleriesPreferences* preferences =
1106 g_browser_process->media_file_system_registry()->GetPreferences(
1108 preferences->EnsureInitialized(
1109 base::Bind(&MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit,
1111 params->gallery_id));
1116 void MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit(
1117 const std::string& pref_id) {
1118 base::FilePath gallery_file_path;
1119 MediaGalleryPrefId gallery_pref_id = kInvalidMediaGalleryPrefId;
1120 if (!GetGalleryFilePathAndId(pref_id,
1124 &gallery_pref_id)) {
1125 api::media_galleries::AddGalleryWatchResult result;
1126 error_ = kInvalidGalleryIdMsg;
1127 result.gallery_id = kInvalidGalleryId;
1128 result.success = false;
1129 SetResult(result.ToValue().release());
1130 SendResponse(false);
1134 gallery_watch_manager()->AddWatch(
1138 base::Bind(&MediaGalleriesAddGalleryWatchFunction::HandleResponse,
1143 void MediaGalleriesAddGalleryWatchFunction::HandleResponse(
1144 MediaGalleryPrefId gallery_id,
1145 const std::string& error) {
1146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1148 // If an app added a file watch without any event listeners on the
1149 // onGalleryChanged event, that's an error.
1150 MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
1151 api::media_galleries::AddGalleryWatchResult result;
1152 result.gallery_id = base::Uint64ToString(gallery_id);
1154 if (!api->ExtensionHasGalleryChangeListener(extension()->id())) {
1155 result.success = false;
1156 SetResult(result.ToValue().release());
1157 error_ = kMissingEventListener;
1158 SendResponse(false);
1162 result.success = error.empty();
1163 SetResult(result.ToValue().release());
1164 if (error.empty()) {
1167 error_ = error.c_str();
1168 SendResponse(false);
1172 ///////////////////////////////////////////////////////////////////////////////
1173 // MediaGalleriesRemoveGalleryWatchFunction //
1174 ///////////////////////////////////////////////////////////////////////////////
1176 MediaGalleriesRemoveGalleryWatchFunction::
1177 ~MediaGalleriesRemoveGalleryWatchFunction() {
1180 bool MediaGalleriesRemoveGalleryWatchFunction::RunAsync() {
1181 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1182 if (!render_view_host() || !render_view_host()->GetProcess())
1185 scoped_ptr<RemoveGalleryWatch::Params> params(
1186 RemoveGalleryWatch::Params::Create(*args_));
1187 EXTENSION_FUNCTION_VALIDATE(params.get());
1189 MediaGalleriesPreferences* preferences =
1190 g_browser_process->media_file_system_registry()->GetPreferences(
1192 preferences->EnsureInitialized(
1193 base::Bind(&MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit,
1195 params->gallery_id));
1199 void MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit(
1200 const std::string& pref_id) {
1201 base::FilePath gallery_file_path;
1202 MediaGalleryPrefId gallery_pref_id = 0;
1203 if (!GetGalleryFilePathAndId(pref_id,
1207 &gallery_pref_id)) {
1208 error_ = kInvalidGalleryIdMsg;
1209 SendResponse(false);
1213 gallery_watch_manager()->RemoveWatch(
1214 GetProfile(), extension_id(), gallery_pref_id);
1218 ///////////////////////////////////////////////////////////////////////////////
1219 // MediaGalleriesGetAllGalleryWatchFunction //
1220 ///////////////////////////////////////////////////////////////////////////////
1222 MediaGalleriesGetAllGalleryWatchFunction::
1223 ~MediaGalleriesGetAllGalleryWatchFunction() {
1226 bool MediaGalleriesGetAllGalleryWatchFunction::RunAsync() {
1227 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1228 if (!render_view_host() || !render_view_host()->GetProcess())
1231 MediaGalleriesPreferences* preferences =
1232 g_browser_process->media_file_system_registry()->GetPreferences(
1234 preferences->EnsureInitialized(base::Bind(
1235 &MediaGalleriesGetAllGalleryWatchFunction::OnPreferencesInit, this));
1239 void MediaGalleriesGetAllGalleryWatchFunction::OnPreferencesInit() {
1240 std::vector<std::string> result;
1241 MediaGalleryPrefIdSet gallery_ids =
1242 gallery_watch_manager()->GetWatchSet(GetProfile(), extension_id());
1243 for (MediaGalleryPrefIdSet::const_iterator iter = gallery_ids.begin();
1244 iter != gallery_ids.end();
1246 result.push_back(base::Uint64ToString(*iter));
1248 results_ = GetAllGalleryWatch::Results::Create(result);
1252 ///////////////////////////////////////////////////////////////////////////////
1253 // MediaGalleriesRemoveAllGalleryWatchFunction //
1254 ///////////////////////////////////////////////////////////////////////////////
1256 MediaGalleriesRemoveAllGalleryWatchFunction::
1257 ~MediaGalleriesRemoveAllGalleryWatchFunction() {
1260 bool MediaGalleriesRemoveAllGalleryWatchFunction::RunAsync() {
1261 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1262 if (!render_view_host() || !render_view_host()->GetProcess())
1265 MediaGalleriesPreferences* preferences =
1266 g_browser_process->media_file_system_registry()->GetPreferences(
1268 preferences->EnsureInitialized(base::Bind(
1269 &MediaGalleriesRemoveAllGalleryWatchFunction::OnPreferencesInit, this));
1273 void MediaGalleriesRemoveAllGalleryWatchFunction::OnPreferencesInit() {
1274 gallery_watch_manager()->RemoveAllWatches(GetProfile(), extension_id());
1278 } // namespace extensions