Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / api / media_galleries / media_galleries_api.cc
blob6c48ca25b063a2c02f2d6ce8988bac7b1c580c82
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"
9 #include <set>
10 #include <string>
11 #include <vector>
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/chrome_extension_function_details.h"
24 #include "chrome/browser/extensions/extension_tab_util.h"
25 #include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h"
26 #include "chrome/browser/media_galleries/gallery_watch_manager.h"
27 #include "chrome/browser/media_galleries/media_file_system_registry.h"
28 #include "chrome/browser/media_galleries/media_galleries_histograms.h"
29 #include "chrome/browser/media_galleries/media_galleries_permission_controller.h"
30 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
31 #include "chrome/browser/media_galleries/media_galleries_scan_result_controller.h"
32 #include "chrome/browser/media_galleries/media_scan_manager.h"
33 #include "chrome/browser/platform_util.h"
34 #include "chrome/browser/profiles/profile.h"
35 #include "chrome/browser/ui/chrome_select_file_policy.h"
36 #include "chrome/common/extensions/api/media_galleries.h"
37 #include "chrome/common/pref_names.h"
38 #include "chrome/grit/generated_resources.h"
39 #include "components/storage_monitor/storage_info.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_frame_host.h"
45 #include "content/public/browser/render_process_host.h"
46 #include "content/public/browser/render_view_host.h"
47 #include "content/public/browser/web_contents.h"
48 #include "extensions/browser/blob_holder.h"
49 #include "extensions/browser/extension_prefs.h"
50 #include "extensions/browser/extension_system.h"
51 #include "extensions/common/extension.h"
52 #include "extensions/common/permissions/api_permission.h"
53 #include "extensions/common/permissions/media_galleries_permission.h"
54 #include "extensions/common/permissions/permissions_data.h"
55 #include "net/base/mime_sniffer.h"
56 #include "storage/browser/blob/blob_data_handle.h"
57 #include "ui/base/l10n/l10n_util.h"
59 using content::WebContents;
60 using storage_monitor::MediaStorageUtil;
61 using storage_monitor::StorageInfo;
63 namespace extensions {
65 namespace MediaGalleries = api::media_galleries;
66 namespace DropPermissionForMediaFileSystem =
67 MediaGalleries::DropPermissionForMediaFileSystem;
68 namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;
69 namespace AddGalleryWatch = MediaGalleries::AddGalleryWatch;
70 namespace RemoveGalleryWatch = MediaGalleries::RemoveGalleryWatch;
71 namespace GetAllGalleryWatch = MediaGalleries::GetAllGalleryWatch;
73 namespace {
75 const char kDisallowedByPolicy[] =
76 "Media Galleries API is disallowed by policy: ";
77 const char kFailedToSetGalleryPermission[] =
78 "Failed to set gallery permission.";
79 const char kInvalidGalleryIdMsg[] = "Invalid gallery id.";
80 const char kMissingEventListener[] = "Missing event listener registration.";
81 const char kNonExistentGalleryId[] = "Non-existent gallery id.";
82 const char kNoScanPermission[] = "No permission to scan.";
84 const char kDeviceIdKey[] = "deviceId";
85 const char kGalleryIdKey[] = "galleryId";
86 const char kIsAvailableKey[] = "isAvailable";
87 const char kIsMediaDeviceKey[] = "isMediaDevice";
88 const char kIsRemovableKey[] = "isRemovable";
89 const char kNameKey[] = "name";
91 const char kMetadataKey[] = "metadata";
92 const char kAttachedImagesBlobInfoKey[] = "attachedImagesBlobInfo";
93 const char kBlobUUIDKey[] = "blobUUID";
94 const char kTypeKey[] = "type";
95 const char kSizeKey[] = "size";
97 const char kInvalidGalleryId[] = "-1";
99 MediaFileSystemRegistry* media_file_system_registry() {
100 return g_browser_process->media_file_system_registry();
103 GalleryWatchManager* gallery_watch_manager() {
104 return media_file_system_registry()->gallery_watch_manager();
107 MediaScanManager* media_scan_manager() {
108 return media_file_system_registry()->media_scan_manager();
111 // Checks whether the MediaGalleries API is currently accessible (it may be
112 // disallowed even if an extension has the requisite permission). Then
113 // initializes the MediaGalleriesPreferences
114 bool Setup(Profile* profile, std::string* error, base::Closure callback) {
115 if (!ChromeSelectFilePolicy::FileSelectDialogsAllowed()) {
116 *error = std::string(kDisallowedByPolicy) +
117 prefs::kAllowFileSelectionDialogs;
118 return false;
121 MediaGalleriesPreferences* preferences =
122 media_file_system_registry()->GetPreferences(profile);
123 preferences->EnsureInitialized(callback);
124 return true;
127 // Returns true and sets |gallery_file_path| and |gallery_pref_id| if the
128 // |gallery_id| is valid and returns false otherwise.
129 bool GetGalleryFilePathAndId(const std::string& gallery_id,
130 Profile* profile,
131 const Extension* extension,
132 base::FilePath* gallery_file_path,
133 MediaGalleryPrefId* gallery_pref_id) {
134 MediaGalleryPrefId pref_id;
135 if (!base::StringToUint64(gallery_id, &pref_id))
136 return false;
137 MediaGalleriesPreferences* preferences =
138 g_browser_process->media_file_system_registry()->GetPreferences(profile);
139 base::FilePath file_path(
140 preferences->LookUpGalleryPathForExtension(pref_id, extension, false));
141 if (file_path.empty())
142 return false;
143 *gallery_pref_id = pref_id;
144 *gallery_file_path = file_path;
145 return true;
148 base::ListValue* ConstructFileSystemList(
149 content::RenderFrameHost* rfh,
150 const Extension* extension,
151 const std::vector<MediaFileSystemInfo>& filesystems) {
152 if (!rfh)
153 return NULL;
155 MediaGalleriesPermission::CheckParam read_param(
156 MediaGalleriesPermission::kReadPermission);
157 const PermissionsData* permissions_data = extension->permissions_data();
158 bool has_read_permission = permissions_data->CheckAPIPermissionWithParam(
159 APIPermission::kMediaGalleries, &read_param);
160 MediaGalleriesPermission::CheckParam copy_to_param(
161 MediaGalleriesPermission::kCopyToPermission);
162 bool has_copy_to_permission = permissions_data->CheckAPIPermissionWithParam(
163 APIPermission::kMediaGalleries, &copy_to_param);
164 MediaGalleriesPermission::CheckParam delete_param(
165 MediaGalleriesPermission::kDeletePermission);
166 bool has_delete_permission = permissions_data->CheckAPIPermissionWithParam(
167 APIPermission::kMediaGalleries, &delete_param);
169 const int child_id = rfh->GetProcess()->GetID();
170 scoped_ptr<base::ListValue> list(new base::ListValue());
171 for (size_t i = 0; i < filesystems.size(); ++i) {
172 scoped_ptr<base::DictionaryValue> file_system_dict_value(
173 new base::DictionaryValue());
175 // Send the file system id so the renderer can create a valid FileSystem
176 // object.
177 file_system_dict_value->SetStringWithoutPathExpansion(
178 "fsid", filesystems[i].fsid);
180 file_system_dict_value->SetStringWithoutPathExpansion(
181 kNameKey, filesystems[i].name);
182 file_system_dict_value->SetStringWithoutPathExpansion(
183 kGalleryIdKey,
184 base::Uint64ToString(filesystems[i].pref_id));
185 if (!filesystems[i].transient_device_id.empty()) {
186 file_system_dict_value->SetStringWithoutPathExpansion(
187 kDeviceIdKey, filesystems[i].transient_device_id);
189 file_system_dict_value->SetBooleanWithoutPathExpansion(
190 kIsRemovableKey, filesystems[i].removable);
191 file_system_dict_value->SetBooleanWithoutPathExpansion(
192 kIsMediaDeviceKey, filesystems[i].media_device);
193 file_system_dict_value->SetBooleanWithoutPathExpansion(
194 kIsAvailableKey, true);
196 list->Append(file_system_dict_value.release());
198 if (filesystems[i].path.empty())
199 continue;
201 if (has_read_permission) {
202 content::ChildProcessSecurityPolicy* policy =
203 content::ChildProcessSecurityPolicy::GetInstance();
204 policy->GrantReadFile(child_id, filesystems[i].path);
205 if (has_delete_permission) {
206 policy->GrantDeleteFrom(child_id, filesystems[i].path);
207 if (has_copy_to_permission) {
208 policy->GrantCopyInto(child_id, filesystems[i].path);
214 return list.release();
217 bool CheckScanPermission(const extensions::Extension* extension,
218 std::string* error) {
219 DCHECK(extension);
220 DCHECK(error);
221 MediaGalleriesPermission::CheckParam scan_param(
222 MediaGalleriesPermission::kScanPermission);
223 bool has_scan_permission =
224 extension->permissions_data()->CheckAPIPermissionWithParam(
225 APIPermission::kMediaGalleries, &scan_param);
226 if (!has_scan_permission)
227 *error = kNoScanPermission;
228 return has_scan_permission;
231 class SelectDirectoryDialog : public ui::SelectFileDialog::Listener,
232 public base::RefCounted<SelectDirectoryDialog> {
233 public:
234 // Selected file path, or an empty path if the user canceled.
235 typedef base::Callback<void(const base::FilePath&)> Callback;
237 SelectDirectoryDialog(WebContents* web_contents, const Callback& callback)
238 : web_contents_(web_contents),
239 callback_(callback) {
240 select_file_dialog_ = ui::SelectFileDialog::Create(
241 this, new ChromeSelectFilePolicy(web_contents));
244 void Show(const base::FilePath& default_path) {
245 AddRef(); // Balanced in the two reachable listener outcomes.
246 select_file_dialog_->SelectFile(
247 ui::SelectFileDialog::SELECT_FOLDER,
248 l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE),
249 default_path,
250 NULL,
252 base::FilePath::StringType(),
253 platform_util::GetTopLevel(web_contents_->GetNativeView()),
254 NULL);
257 // ui::SelectFileDialog::Listener implementation.
258 void FileSelected(const base::FilePath& path,
259 int index,
260 void* params) override {
261 callback_.Run(path);
262 Release(); // Balanced in Show().
265 void MultiFilesSelected(const std::vector<base::FilePath>& files,
266 void* params) override {
267 NOTREACHED() << "Should not be able to select multiple files";
270 void FileSelectionCanceled(void* params) override {
271 callback_.Run(base::FilePath());
272 Release(); // Balanced in Show().
275 private:
276 friend class base::RefCounted<SelectDirectoryDialog>;
277 ~SelectDirectoryDialog() override {}
279 scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
280 WebContents* web_contents_;
281 Callback callback_;
283 DISALLOW_COPY_AND_ASSIGN(SelectDirectoryDialog);
286 } // namespace
288 MediaGalleriesEventRouter::MediaGalleriesEventRouter(
289 content::BrowserContext* context)
290 : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
291 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
292 DCHECK(profile_);
294 EventRouter::Get(profile_)->RegisterObserver(
295 this, MediaGalleries::OnGalleryChanged::kEventName);
297 gallery_watch_manager()->AddObserver(profile_, this);
298 media_scan_manager()->AddObserver(profile_, this);
301 MediaGalleriesEventRouter::~MediaGalleriesEventRouter() {
304 void MediaGalleriesEventRouter::Shutdown() {
305 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
306 weak_ptr_factory_.InvalidateWeakPtrs();
308 EventRouter::Get(profile_)->UnregisterObserver(this);
310 gallery_watch_manager()->RemoveObserver(profile_);
311 media_scan_manager()->RemoveObserver(profile_);
312 media_scan_manager()->CancelScansForProfile(profile_);
315 static base::LazyInstance<
316 BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter> > g_factory =
317 LAZY_INSTANCE_INITIALIZER;
319 // static
320 BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
321 MediaGalleriesEventRouter::GetFactoryInstance() {
322 return g_factory.Pointer();
325 // static
326 MediaGalleriesEventRouter* MediaGalleriesEventRouter::Get(
327 content::BrowserContext* context) {
328 DCHECK(media_file_system_registry()
329 ->GetPreferences(Profile::FromBrowserContext(context))
330 ->IsInitialized());
331 return BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>::Get(context);
334 bool MediaGalleriesEventRouter::ExtensionHasGalleryChangeListener(
335 const std::string& extension_id) const {
336 return EventRouter::Get(profile_)->ExtensionHasEventListener(
337 extension_id, MediaGalleries::OnGalleryChanged::kEventName);
340 bool MediaGalleriesEventRouter::ExtensionHasScanProgressListener(
341 const std::string& extension_id) const {
342 return EventRouter::Get(profile_)->ExtensionHasEventListener(
343 extension_id, MediaGalleries::OnScanProgress::kEventName);
346 void MediaGalleriesEventRouter::OnScanStarted(const std::string& extension_id) {
347 MediaGalleries::ScanProgressDetails details;
348 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_START;
349 DispatchEventToExtension(
350 extension_id, events::MEDIA_GALLERIES_ON_SCAN_PROGRESS,
351 MediaGalleries::OnScanProgress::kEventName,
352 MediaGalleries::OnScanProgress::Create(details).Pass());
355 void MediaGalleriesEventRouter::OnScanCancelled(
356 const std::string& extension_id) {
357 MediaGalleries::ScanProgressDetails details;
358 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_CANCEL;
359 DispatchEventToExtension(
360 extension_id, events::MEDIA_GALLERIES_ON_SCAN_PROGRESS,
361 MediaGalleries::OnScanProgress::kEventName,
362 MediaGalleries::OnScanProgress::Create(details).Pass());
365 void MediaGalleriesEventRouter::OnScanFinished(
366 const std::string& extension_id, int gallery_count,
367 const MediaGalleryScanResult& file_counts) {
368 media_galleries::UsageCount(media_galleries::SCAN_FINISHED);
369 MediaGalleries::ScanProgressDetails details;
370 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_FINISH;
371 details.gallery_count.reset(new int(gallery_count));
372 details.audio_count.reset(new int(file_counts.audio_count));
373 details.image_count.reset(new int(file_counts.image_count));
374 details.video_count.reset(new int(file_counts.video_count));
375 DispatchEventToExtension(
376 extension_id, events::MEDIA_GALLERIES_ON_SCAN_PROGRESS,
377 MediaGalleries::OnScanProgress::kEventName,
378 MediaGalleries::OnScanProgress::Create(details).Pass());
381 void MediaGalleriesEventRouter::OnScanError(
382 const std::string& extension_id) {
383 MediaGalleries::ScanProgressDetails details;
384 details.type = MediaGalleries::SCAN_PROGRESS_TYPE_ERROR;
385 DispatchEventToExtension(
386 extension_id, events::MEDIA_GALLERIES_ON_SCAN_PROGRESS,
387 MediaGalleries::OnScanProgress::kEventName,
388 MediaGalleries::OnScanProgress::Create(details).Pass());
391 void MediaGalleriesEventRouter::DispatchEventToExtension(
392 const std::string& extension_id,
393 events::HistogramValue histogram_value,
394 const std::string& event_name,
395 scoped_ptr<base::ListValue> event_args) {
396 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
398 // TODO(tommycli): Remove these CHECKs after fixing https://crbug.com/467627.
399 CHECK(profile_);
400 EventRouter* router = EventRouter::Get(profile_);
401 CHECK(router);
403 if (!router->ExtensionHasEventListener(extension_id, event_name))
404 return;
406 scoped_ptr<extensions::Event> event(
407 new extensions::Event(histogram_value, event_name, event_args.Pass()));
408 router->DispatchEventToExtension(extension_id, event.Pass());
411 void MediaGalleriesEventRouter::OnGalleryChanged(
412 const std::string& extension_id, MediaGalleryPrefId gallery_id) {
413 MediaGalleries::GalleryChangeDetails details;
414 details.type = MediaGalleries::GALLERY_CHANGE_TYPE_CONTENTS_CHANGED;
415 details.gallery_id = base::Uint64ToString(gallery_id);
416 DispatchEventToExtension(
417 extension_id, events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
418 MediaGalleries::OnGalleryChanged::kEventName,
419 MediaGalleries::OnGalleryChanged::Create(details).Pass());
422 void MediaGalleriesEventRouter::OnGalleryWatchDropped(
423 const std::string& extension_id, MediaGalleryPrefId gallery_id) {
424 MediaGalleries::GalleryChangeDetails details;
425 details.type = MediaGalleries::GALLERY_CHANGE_TYPE_WATCH_DROPPED;
426 details.gallery_id = gallery_id;
427 DispatchEventToExtension(
428 extension_id, events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
429 MediaGalleries::OnGalleryChanged::kEventName,
430 MediaGalleries::OnGalleryChanged::Create(details).Pass());
433 void MediaGalleriesEventRouter::OnListenerRemoved(
434 const EventListenerInfo& details) {
435 if (details.event_name == MediaGalleries::OnGalleryChanged::kEventName &&
436 !ExtensionHasGalleryChangeListener(details.extension_id)) {
437 gallery_watch_manager()->RemoveAllWatches(profile_, details.extension_id);
441 ///////////////////////////////////////////////////////////////////////////////
442 // MediaGalleriesGetMediaFileSystemsFunction //
443 ///////////////////////////////////////////////////////////////////////////////
444 MediaGalleriesGetMediaFileSystemsFunction::
445 ~MediaGalleriesGetMediaFileSystemsFunction() {}
447 bool MediaGalleriesGetMediaFileSystemsFunction::RunAsync() {
448 media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS);
449 scoped_ptr<GetMediaFileSystems::Params> params(
450 GetMediaFileSystems::Params::Create(*args_));
451 EXTENSION_FUNCTION_VALIDATE(params.get());
452 MediaGalleries::GetMediaFileSystemsInteractivity interactive =
453 MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO;
454 if (params->details.get() && params->details->interactive != MediaGalleries::
455 GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) {
456 interactive = params->details->interactive;
459 return Setup(GetProfile(), &error_, base::Bind(
460 &MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, this,
461 interactive));
464 void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit(
465 MediaGalleries::GetMediaFileSystemsInteractivity interactive) {
466 switch (interactive) {
467 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_YES: {
468 // The MediaFileSystemRegistry only updates preferences for extensions
469 // that it knows are in use. Since this may be the first call to
470 // chrome.getMediaFileSystems for this extension, call
471 // GetMediaFileSystemsForExtension() here solely so that
472 // MediaFileSystemRegistry will send preference changes.
473 GetMediaFileSystemsForExtension(base::Bind(
474 &MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog, this));
475 return;
477 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_IF_NEEDED: {
478 GetMediaFileSystemsForExtension(base::Bind(
479 &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries,
480 this));
481 return;
483 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO:
484 GetAndReturnGalleries();
485 return;
486 case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE:
487 NOTREACHED();
489 SendResponse(false);
492 void MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog(
493 const std::vector<MediaFileSystemInfo>& /*filesystems*/) {
494 ShowDialog();
497 void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries(
498 const std::vector<MediaFileSystemInfo>& filesystems) {
499 if (filesystems.empty())
500 ShowDialog();
501 else
502 ReturnGalleries(filesystems);
505 void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() {
506 GetMediaFileSystemsForExtension(base::Bind(
507 &MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries, this));
510 void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
511 const std::vector<MediaFileSystemInfo>& filesystems) {
512 scoped_ptr<base::ListValue> list(
513 ConstructFileSystemList(render_frame_host(), extension(), filesystems));
514 if (!list.get()) {
515 SendResponse(false);
516 return;
519 // The custom JS binding will use this list to create DOMFileSystem objects.
520 SetResult(list.release());
521 SendResponse(true);
524 void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
525 media_galleries::UsageCount(media_galleries::SHOW_DIALOG);
526 WebContents* contents =
527 ChromeExtensionFunctionDetails(this).GetOriginWebContents();
528 if (!contents) {
529 SendResponse(false);
530 return;
533 // Controller will delete itself.
534 base::Closure cb = base::Bind(
535 &MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this);
536 new MediaGalleriesPermissionController(contents, *extension(), cb);
539 void MediaGalleriesGetMediaFileSystemsFunction::GetMediaFileSystemsForExtension(
540 const MediaFileSystemsCallback& cb) {
541 if (!render_frame_host()) {
542 cb.Run(std::vector<MediaFileSystemInfo>());
543 return;
545 MediaFileSystemRegistry* registry = media_file_system_registry();
546 DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
547 registry->GetMediaFileSystemsForExtension(GetSenderWebContents(), extension(),
548 cb);
552 ///////////////////////////////////////////////////////////////////////////////
553 // MediaGalleriesGetAllMediaFileSystemMetadataFunction //
554 ///////////////////////////////////////////////////////////////////////////////
555 MediaGalleriesGetAllMediaFileSystemMetadataFunction::
556 ~MediaGalleriesGetAllMediaFileSystemMetadataFunction() {}
558 bool MediaGalleriesGetAllMediaFileSystemMetadataFunction::RunAsync() {
559 media_galleries::UsageCount(
560 media_galleries::GET_ALL_MEDIA_FILE_SYSTEM_METADATA);
561 return Setup(GetProfile(), &error_, base::Bind(
562 &MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit,
563 this));
566 void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit() {
567 MediaFileSystemRegistry* registry = media_file_system_registry();
568 MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile());
569 DCHECK(prefs->IsInitialized());
570 MediaGalleryPrefIdSet permitted_gallery_ids =
571 prefs->GalleriesForExtension(*extension());
573 MediaStorageUtil::DeviceIdSet* device_ids = new MediaStorageUtil::DeviceIdSet;
574 const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
575 for (MediaGalleryPrefIdSet::const_iterator it = permitted_gallery_ids.begin();
576 it != permitted_gallery_ids.end(); ++it) {
577 MediaGalleriesPrefInfoMap::const_iterator gallery_it = galleries.find(*it);
578 DCHECK(gallery_it != galleries.end());
579 device_ids->insert(gallery_it->second.device_id);
582 MediaStorageUtil::FilterAttachedDevices(
583 device_ids,
584 base::Bind(
585 &MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries,
586 this,
587 permitted_gallery_ids,
588 base::Owned(device_ids)));
591 void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries(
592 const MediaGalleryPrefIdSet& permitted_gallery_ids,
593 const MediaStorageUtil::DeviceIdSet* available_devices) {
594 MediaFileSystemRegistry* registry = media_file_system_registry();
595 MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile());
597 base::ListValue* list = new base::ListValue();
598 const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries();
599 for (MediaGalleryPrefIdSet::const_iterator it = permitted_gallery_ids.begin();
600 it != permitted_gallery_ids.end(); ++it) {
601 MediaGalleriesPrefInfoMap::const_iterator gallery_it = galleries.find(*it);
602 DCHECK(gallery_it != galleries.end());
603 const MediaGalleryPrefInfo& gallery = gallery_it->second;
604 MediaGalleries::MediaFileSystemMetadata metadata;
605 metadata.name = base::UTF16ToUTF8(gallery.GetGalleryDisplayName());
606 metadata.gallery_id = base::Uint64ToString(gallery.pref_id);
607 metadata.is_removable = StorageInfo::IsRemovableDevice(gallery.device_id);
608 metadata.is_media_device = StorageInfo::IsMediaDevice(gallery.device_id);
609 metadata.is_available = ContainsKey(*available_devices, gallery.device_id);
610 list->Append(metadata.ToValue().release());
613 SetResult(list);
614 SendResponse(true);
617 ///////////////////////////////////////////////////////////////////////////////
618 // MediaGalleriesAddUserSelectedFolderFunction //
619 ///////////////////////////////////////////////////////////////////////////////
620 MediaGalleriesAddUserSelectedFolderFunction::
621 ~MediaGalleriesAddUserSelectedFolderFunction() {}
623 bool MediaGalleriesAddUserSelectedFolderFunction::RunAsync() {
624 media_galleries::UsageCount(media_galleries::ADD_USER_SELECTED_FOLDER);
625 return Setup(GetProfile(), &error_, base::Bind(
626 &MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit, this));
629 void MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit() {
630 Profile* profile = GetProfile();
631 const std::string& app_id = extension()->id();
632 WebContents* contents =
633 ChromeExtensionFunctionDetails(this).GetOriginWebContents();
634 if (!contents) {
635 SendResponse(false);
636 return;
639 if (!user_gesture()) {
640 OnDirectorySelected(base::FilePath());
641 return;
644 base::FilePath last_used_path =
645 extensions::file_system_api::GetLastChooseEntryDirectory(
646 extensions::ExtensionPrefs::Get(profile), app_id);
647 SelectDirectoryDialog::Callback callback = base::Bind(
648 &MediaGalleriesAddUserSelectedFolderFunction::OnDirectorySelected, this);
649 scoped_refptr<SelectDirectoryDialog> select_directory_dialog =
650 new SelectDirectoryDialog(contents, callback);
651 select_directory_dialog->Show(last_used_path);
654 void MediaGalleriesAddUserSelectedFolderFunction::OnDirectorySelected(
655 const base::FilePath& selected_directory) {
656 if (selected_directory.empty()) {
657 // User cancelled case.
658 GetMediaFileSystemsForExtension(base::Bind(
659 &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
660 this,
661 kInvalidMediaGalleryPrefId));
662 return;
665 extensions::file_system_api::SetLastChooseEntryDirectory(
666 extensions::ExtensionPrefs::Get(GetProfile()),
667 extension()->id(),
668 selected_directory);
670 MediaGalleriesPreferences* preferences =
671 media_file_system_registry()->GetPreferences(GetProfile());
672 MediaGalleryPrefId pref_id =
673 preferences->AddGalleryByPath(selected_directory,
674 MediaGalleryPrefInfo::kUserAdded);
675 preferences->SetGalleryPermissionForExtension(*extension(), pref_id, true);
677 GetMediaFileSystemsForExtension(base::Bind(
678 &MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
679 this,
680 pref_id));
683 void MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId(
684 MediaGalleryPrefId pref_id,
685 const std::vector<MediaFileSystemInfo>& filesystems) {
686 scoped_ptr<base::ListValue> list(
687 ConstructFileSystemList(render_frame_host(), extension(), filesystems));
688 if (!list.get()) {
689 SendResponse(false);
690 return;
693 int index = -1;
694 if (pref_id != kInvalidMediaGalleryPrefId) {
695 for (size_t i = 0; i < filesystems.size(); ++i) {
696 if (filesystems[i].pref_id == pref_id) {
697 index = i;
698 break;
702 base::DictionaryValue* results = new base::DictionaryValue;
703 results->SetWithoutPathExpansion("mediaFileSystems", list.release());
704 results->SetIntegerWithoutPathExpansion("selectedFileSystemIndex", index);
705 SetResult(results);
706 SendResponse(true);
709 void
710 MediaGalleriesAddUserSelectedFolderFunction::GetMediaFileSystemsForExtension(
711 const MediaFileSystemsCallback& cb) {
712 if (!render_frame_host()) {
713 cb.Run(std::vector<MediaFileSystemInfo>());
714 return;
716 MediaFileSystemRegistry* registry = media_file_system_registry();
717 DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
718 registry->GetMediaFileSystemsForExtension(GetSenderWebContents(), extension(),
719 cb);
722 ///////////////////////////////////////////////////////////////////////////////
723 // MediaGalleriesDropPermissionForMediaFileSystemFunction //
724 ///////////////////////////////////////////////////////////////////////////////
725 MediaGalleriesDropPermissionForMediaFileSystemFunction::
726 ~MediaGalleriesDropPermissionForMediaFileSystemFunction() {}
728 bool MediaGalleriesDropPermissionForMediaFileSystemFunction::RunAsync() {
729 media_galleries::UsageCount(
730 media_galleries::DROP_PERMISSION_FOR_MEDIA_FILE_SYSTEM);
732 scoped_ptr<DropPermissionForMediaFileSystem::Params> params(
733 DropPermissionForMediaFileSystem::Params::Create(*args_));
734 EXTENSION_FUNCTION_VALIDATE(params.get());
735 MediaGalleryPrefId pref_id;
736 if (!base::StringToUint64(params->gallery_id, &pref_id)) {
737 error_ = kInvalidGalleryIdMsg;
738 return false;
741 base::Closure callback = base::Bind(
742 &MediaGalleriesDropPermissionForMediaFileSystemFunction::
743 OnPreferencesInit,
744 this,
745 pref_id);
746 return Setup(GetProfile(), &error_, callback);
749 void MediaGalleriesDropPermissionForMediaFileSystemFunction::OnPreferencesInit(
750 MediaGalleryPrefId pref_id) {
751 MediaGalleriesPreferences* preferences =
752 media_file_system_registry()->GetPreferences(GetProfile());
753 if (!ContainsKey(preferences->known_galleries(), pref_id)) {
754 error_ = kNonExistentGalleryId;
755 SendResponse(false);
756 return;
759 bool dropped = preferences->SetGalleryPermissionForExtension(
760 *extension(), pref_id, false);
761 if (dropped)
762 SetResult(new base::StringValue(base::Uint64ToString(pref_id)));
763 else
764 error_ = kFailedToSetGalleryPermission;
765 SendResponse(dropped);
768 ///////////////////////////////////////////////////////////////////////////////
769 // MediaGalleriesStartMediaScanFunction //
770 ///////////////////////////////////////////////////////////////////////////////
771 MediaGalleriesStartMediaScanFunction::~MediaGalleriesStartMediaScanFunction() {}
773 bool MediaGalleriesStartMediaScanFunction::RunAsync() {
774 media_galleries::UsageCount(media_galleries::START_MEDIA_SCAN);
775 if (!CheckScanPermission(extension(), &error_)) {
776 MediaGalleriesEventRouter::Get(GetProfile())
777 ->OnScanError(extension()->id());
778 return false;
780 return Setup(GetProfile(), &error_, base::Bind(
781 &MediaGalleriesStartMediaScanFunction::OnPreferencesInit, this));
784 void MediaGalleriesStartMediaScanFunction::OnPreferencesInit() {
785 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
786 MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
787 if (!api->ExtensionHasScanProgressListener(extension()->id())) {
788 error_ = kMissingEventListener;
789 SendResponse(false);
790 return;
793 media_scan_manager()->StartScan(GetProfile(), extension(), user_gesture());
794 SendResponse(true);
797 ///////////////////////////////////////////////////////////////////////////////
798 // MediaGalleriesCancelMediaScanFunction //
799 ///////////////////////////////////////////////////////////////////////////////
800 MediaGalleriesCancelMediaScanFunction::
801 ~MediaGalleriesCancelMediaScanFunction() {
804 bool MediaGalleriesCancelMediaScanFunction::RunAsync() {
805 media_galleries::UsageCount(media_galleries::CANCEL_MEDIA_SCAN);
806 if (!CheckScanPermission(extension(), &error_)) {
807 MediaGalleriesEventRouter::Get(GetProfile())
808 ->OnScanError(extension()->id());
809 return false;
811 return Setup(GetProfile(), &error_, base::Bind(
812 &MediaGalleriesCancelMediaScanFunction::OnPreferencesInit, this));
815 void MediaGalleriesCancelMediaScanFunction::OnPreferencesInit() {
816 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
817 media_scan_manager()->CancelScan(GetProfile(), extension());
818 SendResponse(true);
821 ///////////////////////////////////////////////////////////////////////////////
822 // MediaGalleriesAddScanResultsFunction //
823 ///////////////////////////////////////////////////////////////////////////////
824 MediaGalleriesAddScanResultsFunction::~MediaGalleriesAddScanResultsFunction() {}
826 bool MediaGalleriesAddScanResultsFunction::RunAsync() {
827 media_galleries::UsageCount(media_galleries::ADD_SCAN_RESULTS);
828 if (!CheckScanPermission(extension(), &error_)) {
829 // We don't fire a scan progress error here, as it would be unintuitive.
830 return false;
832 if (!user_gesture())
833 return false;
835 return Setup(GetProfile(), &error_, base::Bind(
836 &MediaGalleriesAddScanResultsFunction::OnPreferencesInit, this));
839 MediaGalleriesScanResultController*
840 MediaGalleriesAddScanResultsFunction::MakeDialog(
841 content::WebContents* web_contents,
842 const extensions::Extension& extension,
843 const base::Closure& on_finish) {
844 // Controller will delete itself.
845 return new MediaGalleriesScanResultController(web_contents, extension,
846 on_finish);
849 void MediaGalleriesAddScanResultsFunction::OnPreferencesInit() {
850 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
851 MediaGalleriesPreferences* preferences =
852 media_file_system_registry()->GetPreferences(GetProfile());
853 if (MediaGalleriesScanResultController::ScanResultCountForExtension(
854 preferences, extension()) == 0) {
855 GetAndReturnGalleries();
856 return;
859 WebContents* contents =
860 ChromeExtensionFunctionDetails(this).GetOriginWebContents();
861 if (!contents) {
862 SendResponse(false);
863 return;
866 base::Closure cb = base::Bind(
867 &MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries, this);
868 MakeDialog(contents, *extension(), cb);
871 void MediaGalleriesAddScanResultsFunction::GetAndReturnGalleries() {
872 if (!render_frame_host()) {
873 ReturnGalleries(std::vector<MediaFileSystemInfo>());
874 return;
876 MediaFileSystemRegistry* registry = media_file_system_registry();
877 DCHECK(registry->GetPreferences(GetProfile())->IsInitialized());
878 registry->GetMediaFileSystemsForExtension(
879 GetSenderWebContents(), extension(),
880 base::Bind(&MediaGalleriesAddScanResultsFunction::ReturnGalleries, this));
883 void MediaGalleriesAddScanResultsFunction::ReturnGalleries(
884 const std::vector<MediaFileSystemInfo>& filesystems) {
885 scoped_ptr<base::ListValue> list(
886 ConstructFileSystemList(render_frame_host(), extension(), filesystems));
887 if (!list.get()) {
888 SendResponse(false);
889 return;
892 // The custom JS binding will use this list to create DOMFileSystem objects.
893 SetResult(list.release());
894 SendResponse(true);
897 ///////////////////////////////////////////////////////////////////////////////
898 // MediaGalleriesGetMetadataFunction //
899 ///////////////////////////////////////////////////////////////////////////////
900 MediaGalleriesGetMetadataFunction::~MediaGalleriesGetMetadataFunction() {}
902 bool MediaGalleriesGetMetadataFunction::RunAsync() {
903 std::string blob_uuid;
904 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &blob_uuid));
906 const base::Value* options_value = NULL;
907 if (!args_->Get(1, &options_value))
908 return false;
909 scoped_ptr<MediaGalleries::MediaMetadataOptions> options =
910 MediaGalleries::MediaMetadataOptions::FromValue(*options_value);
911 if (!options)
912 return false;
914 return Setup(GetProfile(), &error_, base::Bind(
915 &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this,
916 options->metadata_type, blob_uuid));
919 void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
920 MediaGalleries::GetMetadataType metadata_type,
921 const std::string& blob_uuid) {
922 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
924 // BlobReader is self-deleting.
925 BlobReader* reader = new BlobReader(
926 GetProfile(),
927 blob_uuid,
928 base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this,
929 metadata_type, blob_uuid));
930 reader->SetByteRange(0, net::kMaxBytesToSniff);
931 reader->Start();
934 void MediaGalleriesGetMetadataFunction::GetMetadata(
935 MediaGalleries::GetMetadataType metadata_type, const std::string& blob_uuid,
936 scoped_ptr<std::string> blob_header, int64 total_blob_length) {
937 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
939 std::string mime_type;
940 bool mime_type_sniffed = net::SniffMimeTypeFromLocalData(
941 blob_header->c_str(), blob_header->size(), &mime_type);
943 if (!mime_type_sniffed) {
944 SendResponse(false);
945 return;
948 if (metadata_type == MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY) {
949 MediaGalleries::MediaMetadata metadata;
950 metadata.mime_type = mime_type;
952 base::DictionaryValue* result_dictionary = new base::DictionaryValue;
953 result_dictionary->Set(kMetadataKey, metadata.ToValue().release());
954 SetResult(result_dictionary);
955 SendResponse(true);
956 return;
959 // We get attached images by default. GET_METADATA_TYPE_NONE is the default
960 // value if the caller doesn't specify the metadata type.
961 bool get_attached_images =
962 metadata_type == MediaGalleries::GET_METADATA_TYPE_ALL ||
963 metadata_type == MediaGalleries::GET_METADATA_TYPE_NONE;
965 scoped_refptr<metadata::SafeMediaMetadataParser> parser(
966 new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid,
967 total_blob_length, mime_type,
968 get_attached_images));
969 parser->Start(base::Bind(
970 &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this));
973 void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone(
974 bool parse_success, scoped_ptr<base::DictionaryValue> metadata_dictionary,
975 scoped_ptr<std::vector<metadata::AttachedImage> > attached_images) {
976 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
978 if (!parse_success) {
979 SendResponse(false);
980 return;
983 DCHECK(metadata_dictionary.get());
984 DCHECK(attached_images.get());
986 scoped_ptr<base::DictionaryValue> result_dictionary(
987 new base::DictionaryValue);
988 result_dictionary->Set(kMetadataKey, metadata_dictionary.release());
990 if (attached_images->empty()) {
991 SetResult(result_dictionary.release());
992 SendResponse(true);
993 return;
996 result_dictionary->Set(kAttachedImagesBlobInfoKey, new base::ListValue);
997 metadata::AttachedImage* first_image = &attached_images->front();
998 content::BrowserContext::CreateMemoryBackedBlob(
999 GetProfile(),
1000 first_image->data.c_str(),
1001 first_image->data.size(),
1002 base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
1003 this, base::Passed(&result_dictionary),
1004 base::Passed(&attached_images),
1005 base::Passed(make_scoped_ptr(new std::vector<std::string>))));
1008 void MediaGalleriesGetMetadataFunction::ConstructNextBlob(
1009 scoped_ptr<base::DictionaryValue> result_dictionary,
1010 scoped_ptr<std::vector<metadata::AttachedImage> > attached_images,
1011 scoped_ptr<std::vector<std::string> > blob_uuids,
1012 scoped_ptr<content::BlobHandle> current_blob) {
1013 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1015 DCHECK(result_dictionary.get());
1016 DCHECK(attached_images.get());
1017 DCHECK(blob_uuids.get());
1018 DCHECK(current_blob.get());
1020 DCHECK(!attached_images->empty());
1021 DCHECK_LT(blob_uuids->size(), attached_images->size());
1023 // For the newly constructed Blob, store its image's metadata and Blob UUID.
1024 base::ListValue* attached_images_list = NULL;
1025 result_dictionary->GetList(kAttachedImagesBlobInfoKey, &attached_images_list);
1026 DCHECK(attached_images_list);
1027 DCHECK_LT(attached_images_list->GetSize(), attached_images->size());
1029 metadata::AttachedImage* current_image =
1030 &(*attached_images)[blob_uuids->size()];
1031 base::DictionaryValue* attached_image = new base::DictionaryValue;
1032 attached_image->Set(kBlobUUIDKey, new base::StringValue(
1033 current_blob->GetUUID()));
1034 attached_image->Set(kTypeKey, new base::StringValue(
1035 current_image->type));
1036 attached_image->Set(kSizeKey, new base::FundamentalValue(
1037 base::checked_cast<int>(current_image->data.size())));
1038 attached_images_list->Append(attached_image);
1040 blob_uuids->push_back(current_blob->GetUUID());
1041 extensions::BlobHolder* holder =
1042 extensions::BlobHolder::FromRenderProcessHost(
1043 render_frame_host()->GetProcess());
1044 holder->HoldBlobReference(current_blob.Pass());
1046 // Construct the next Blob if necessary.
1047 if (blob_uuids->size() < attached_images->size()) {
1048 metadata::AttachedImage* next_image =
1049 &(*attached_images)[blob_uuids->size()];
1050 content::BrowserContext::CreateMemoryBackedBlob(
1051 GetProfile(),
1052 next_image->data.c_str(),
1053 next_image->data.size(),
1054 base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob,
1055 this, base::Passed(&result_dictionary),
1056 base::Passed(&attached_images), base::Passed(&blob_uuids)));
1057 return;
1060 // All Blobs have been constructed. The renderer will take ownership.
1061 SetResult(result_dictionary.release());
1062 SetTransferredBlobUUIDs(*blob_uuids);
1063 SendResponse(true);
1066 ///////////////////////////////////////////////////////////////////////////////
1067 // MediaGalleriesAddGalleryWatchFunction //
1068 ///////////////////////////////////////////////////////////////////////////////
1069 MediaGalleriesAddGalleryWatchFunction::
1070 ~MediaGalleriesAddGalleryWatchFunction() {
1073 bool MediaGalleriesAddGalleryWatchFunction::RunAsync() {
1074 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1075 DCHECK(GetProfile());
1076 if (!render_frame_host() || !render_frame_host()->GetProcess())
1077 return false;
1079 scoped_ptr<AddGalleryWatch::Params> params(
1080 AddGalleryWatch::Params::Create(*args_));
1081 EXTENSION_FUNCTION_VALIDATE(params.get());
1083 MediaGalleriesPreferences* preferences =
1084 g_browser_process->media_file_system_registry()->GetPreferences(
1085 GetProfile());
1086 preferences->EnsureInitialized(
1087 base::Bind(&MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit,
1088 this,
1089 params->gallery_id));
1091 return true;
1094 void MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit(
1095 const std::string& pref_id) {
1096 base::FilePath gallery_file_path;
1097 MediaGalleryPrefId gallery_pref_id = kInvalidMediaGalleryPrefId;
1098 if (!GetGalleryFilePathAndId(pref_id,
1099 GetProfile(),
1100 extension(),
1101 &gallery_file_path,
1102 &gallery_pref_id)) {
1103 api::media_galleries::AddGalleryWatchResult result;
1104 error_ = kInvalidGalleryIdMsg;
1105 result.gallery_id = kInvalidGalleryId;
1106 result.success = false;
1107 SetResult(result.ToValue().release());
1108 SendResponse(false);
1109 return;
1112 gallery_watch_manager()->AddWatch(
1113 GetProfile(),
1114 extension(),
1115 gallery_pref_id,
1116 base::Bind(&MediaGalleriesAddGalleryWatchFunction::HandleResponse,
1117 this,
1118 gallery_pref_id));
1121 void MediaGalleriesAddGalleryWatchFunction::HandleResponse(
1122 MediaGalleryPrefId gallery_id,
1123 const std::string& error) {
1124 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1126 // If an app added a file watch without any event listeners on the
1127 // onGalleryChanged event, that's an error.
1128 MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
1129 api::media_galleries::AddGalleryWatchResult result;
1130 result.gallery_id = base::Uint64ToString(gallery_id);
1132 if (!api->ExtensionHasGalleryChangeListener(extension()->id())) {
1133 result.success = false;
1134 SetResult(result.ToValue().release());
1135 error_ = kMissingEventListener;
1136 SendResponse(false);
1137 return;
1140 result.success = error.empty();
1141 SetResult(result.ToValue().release());
1142 if (error.empty()) {
1143 SendResponse(true);
1144 } else {
1145 error_ = error.c_str();
1146 SendResponse(false);
1150 ///////////////////////////////////////////////////////////////////////////////
1151 // MediaGalleriesRemoveGalleryWatchFunction //
1152 ///////////////////////////////////////////////////////////////////////////////
1154 MediaGalleriesRemoveGalleryWatchFunction::
1155 ~MediaGalleriesRemoveGalleryWatchFunction() {
1158 bool MediaGalleriesRemoveGalleryWatchFunction::RunAsync() {
1159 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1160 if (!render_frame_host() || !render_frame_host()->GetProcess())
1161 return false;
1163 scoped_ptr<RemoveGalleryWatch::Params> params(
1164 RemoveGalleryWatch::Params::Create(*args_));
1165 EXTENSION_FUNCTION_VALIDATE(params.get());
1167 MediaGalleriesPreferences* preferences =
1168 g_browser_process->media_file_system_registry()->GetPreferences(
1169 GetProfile());
1170 preferences->EnsureInitialized(
1171 base::Bind(&MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit,
1172 this,
1173 params->gallery_id));
1174 return true;
1177 void MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit(
1178 const std::string& pref_id) {
1179 base::FilePath gallery_file_path;
1180 MediaGalleryPrefId gallery_pref_id = 0;
1181 if (!GetGalleryFilePathAndId(pref_id,
1182 GetProfile(),
1183 extension(),
1184 &gallery_file_path,
1185 &gallery_pref_id)) {
1186 error_ = kInvalidGalleryIdMsg;
1187 SendResponse(false);
1188 return;
1191 gallery_watch_manager()->RemoveWatch(
1192 GetProfile(), extension_id(), gallery_pref_id);
1193 SendResponse(true);
1196 ///////////////////////////////////////////////////////////////////////////////
1197 // MediaGalleriesGetAllGalleryWatchFunction //
1198 ///////////////////////////////////////////////////////////////////////////////
1200 MediaGalleriesGetAllGalleryWatchFunction::
1201 ~MediaGalleriesGetAllGalleryWatchFunction() {
1204 bool MediaGalleriesGetAllGalleryWatchFunction::RunAsync() {
1205 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1206 if (!render_frame_host() || !render_frame_host()->GetProcess())
1207 return false;
1209 MediaGalleriesPreferences* preferences =
1210 g_browser_process->media_file_system_registry()->GetPreferences(
1211 GetProfile());
1212 preferences->EnsureInitialized(base::Bind(
1213 &MediaGalleriesGetAllGalleryWatchFunction::OnPreferencesInit, this));
1214 return true;
1217 void MediaGalleriesGetAllGalleryWatchFunction::OnPreferencesInit() {
1218 std::vector<std::string> result;
1219 MediaGalleryPrefIdSet gallery_ids =
1220 gallery_watch_manager()->GetWatchSet(GetProfile(), extension_id());
1221 for (MediaGalleryPrefIdSet::const_iterator iter = gallery_ids.begin();
1222 iter != gallery_ids.end();
1223 ++iter) {
1224 result.push_back(base::Uint64ToString(*iter));
1226 results_ = GetAllGalleryWatch::Results::Create(result);
1227 SendResponse(true);
1230 ///////////////////////////////////////////////////////////////////////////////
1231 // MediaGalleriesRemoveAllGalleryWatchFunction //
1232 ///////////////////////////////////////////////////////////////////////////////
1234 MediaGalleriesRemoveAllGalleryWatchFunction::
1235 ~MediaGalleriesRemoveAllGalleryWatchFunction() {
1238 bool MediaGalleriesRemoveAllGalleryWatchFunction::RunAsync() {
1239 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1240 if (!render_frame_host() || !render_frame_host()->GetProcess())
1241 return false;
1243 MediaGalleriesPreferences* preferences =
1244 g_browser_process->media_file_system_registry()->GetPreferences(
1245 GetProfile());
1246 preferences->EnsureInitialized(base::Bind(
1247 &MediaGalleriesRemoveAllGalleryWatchFunction::OnPreferencesInit, this));
1248 return true;
1251 void MediaGalleriesRemoveAllGalleryWatchFunction::OnPreferencesInit() {
1252 gallery_watch_manager()->RemoveAllWatches(GetProfile(), extension_id());
1253 SendResponse(true);
1256 } // namespace extensions