Home | History | Annotate | Download | only in media_galleries_private
      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.
      4 
      5 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/bind.h"
      9 #include "base/files/file_path.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/location.h"
     12 #include "base/prefs/pref_service.h"
     13 #include "base/strings/string_number_conversions.h"
     14 #include "chrome/browser/browser_process.h"
     15 #include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.h"
     16 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
     17 #include "chrome/browser/extensions/extension_util.h"
     18 #include "chrome/browser/media_galleries/media_file_system_registry.h"
     19 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
     20 #include "chrome/browser/profiles/profile.h"
     21 #include "content/public/browser/browser_thread.h"
     22 #include "content/public/browser/render_view_host.h"
     23 #include "extensions/browser/event_router.h"
     24 #include "extensions/browser/extension_function.h"
     25 #include "extensions/browser/extension_system.h"
     26 
     27 using base::DictionaryValue;
     28 using base::ListValue;
     29 
     30 namespace extensions {
     31 
     32 namespace AddGalleryWatch =
     33     extensions::api::media_galleries_private::AddGalleryWatch;
     34 namespace RemoveGalleryWatch =
     35     extensions::api::media_galleries_private::RemoveGalleryWatch;
     36 namespace GetAllGalleryWatch =
     37     extensions::api::media_galleries_private::GetAllGalleryWatch;
     38 namespace media_galleries_private =
     39     api::media_galleries_private;
     40 
     41 namespace {
     42 
     43 const char kInvalidGalleryIDError[] = "Invalid gallery ID";
     44 
     45 // Handles the profile shutdown event on the file thread to clean up
     46 // GalleryWatchManager.
     47 void HandleProfileShutdownOnFileThread(void* profile_id) {
     48   DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
     49   GalleryWatchManager::OnProfileShutdown(profile_id);
     50 }
     51 
     52 // Gets the |gallery_file_path| and |gallery_pref_id| of the gallery specified
     53 // by the |gallery_id|. Returns true and set |gallery_file_path| and
     54 // |gallery_pref_id| if the |gallery_id| is valid and returns false otherwise.
     55 bool GetGalleryFilePathAndId(const std::string& gallery_id,
     56                              Profile* profile,
     57                              const Extension* extension,
     58                              base::FilePath* gallery_file_path,
     59                              MediaGalleryPrefId* gallery_pref_id) {
     60   MediaGalleryPrefId pref_id;
     61   if (!base::StringToUint64(gallery_id, &pref_id))
     62     return false;
     63   MediaGalleriesPreferences* preferences =
     64       g_browser_process->media_file_system_registry()->GetPreferences(profile);
     65   base::FilePath file_path(
     66       preferences->LookUpGalleryPathForExtension(pref_id, extension, false));
     67   if (file_path.empty())
     68     return false;
     69   *gallery_pref_id = pref_id;
     70   *gallery_file_path = file_path;
     71   return true;
     72 }
     73 
     74 }  // namespace
     75 
     76 
     77 ///////////////////////////////////////////////////////////////////////////////
     78 //                      MediaGalleriesPrivateAPI                             //
     79 ///////////////////////////////////////////////////////////////////////////////
     80 
     81 MediaGalleriesPrivateAPI::MediaGalleriesPrivateAPI(
     82     content::BrowserContext* context)
     83     : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
     84   DCHECK(profile_);
     85   EventRouter* event_router = EventRouter::Get(profile_);
     86   event_router->RegisterObserver(
     87       this, media_galleries_private::OnGalleryChanged::kEventName);
     88 }
     89 
     90 MediaGalleriesPrivateAPI::~MediaGalleriesPrivateAPI() {
     91 }
     92 
     93 void MediaGalleriesPrivateAPI::Shutdown() {
     94   EventRouter::Get(profile_)->UnregisterObserver(this);
     95   weak_ptr_factory_.InvalidateWeakPtrs();
     96   content::BrowserThread::PostTask(
     97       content::BrowserThread::FILE, FROM_HERE,
     98       base::Bind(&HandleProfileShutdownOnFileThread, profile_));
     99 }
    100 
    101 static base::LazyInstance<
    102     BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI> > g_factory =
    103     LAZY_INSTANCE_INITIALIZER;
    104 
    105 // static
    106 BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>*
    107 MediaGalleriesPrivateAPI::GetFactoryInstance() {
    108   return g_factory.Pointer();
    109 }
    110 
    111 // static
    112 MediaGalleriesPrivateAPI* MediaGalleriesPrivateAPI::Get(
    113     content::BrowserContext* context) {
    114   return BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>::Get(context);
    115 }
    116 
    117 void MediaGalleriesPrivateAPI::OnListenerAdded(
    118     const EventListenerInfo& details) {
    119   // Make sure MediaGalleriesPreferences is initialized. After that,
    120   // try to initialize the event router for the listener.
    121   // This method is called synchronously with the message handler for the
    122   // JS invocation.
    123 
    124   MediaGalleriesPreferences* preferences =
    125       g_browser_process->media_file_system_registry()->GetPreferences(profile_);
    126   preferences->EnsureInitialized(base::Bind(
    127       &MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker,
    128       weak_ptr_factory_.GetWeakPtr()));
    129 }
    130 
    131 MediaGalleriesPrivateEventRouter* MediaGalleriesPrivateAPI::GetEventRouter() {
    132   MaybeInitializeEventRouterAndTracker();
    133   return media_galleries_private_event_router_.get();
    134 }
    135 
    136 GalleryWatchStateTracker*
    137 MediaGalleriesPrivateAPI::GetGalleryWatchStateTracker() {
    138   MaybeInitializeEventRouterAndTracker();
    139   return tracker_.get();
    140 }
    141 
    142 void MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker() {
    143   if (media_galleries_private_event_router_.get())
    144     return;
    145   media_galleries_private_event_router_.reset(
    146       new MediaGalleriesPrivateEventRouter(profile_));
    147   DCHECK(g_browser_process->media_file_system_registry()->
    148              GetPreferences(profile_)->IsInitialized());
    149   tracker_.reset(
    150       new GalleryWatchStateTracker(profile_));
    151 }
    152 
    153 ///////////////////////////////////////////////////////////////////////////////
    154 //              MediaGalleriesPrivateAddGalleryWatchFunction                 //
    155 ///////////////////////////////////////////////////////////////////////////////
    156 MediaGalleriesPrivateAddGalleryWatchFunction::
    157 ~MediaGalleriesPrivateAddGalleryWatchFunction() {
    158 }
    159 
    160 bool MediaGalleriesPrivateAddGalleryWatchFunction::RunAsync() {
    161   DCHECK(GetProfile());
    162   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    163   if (!render_view_host() || !render_view_host()->GetProcess())
    164     return false;
    165 
    166   scoped_ptr<AddGalleryWatch::Params> params(
    167       AddGalleryWatch::Params::Create(*args_));
    168   EXTENSION_FUNCTION_VALIDATE(params.get());
    169 
    170   MediaGalleriesPreferences* preferences =
    171       g_browser_process->media_file_system_registry()->GetPreferences(
    172           GetProfile());
    173   preferences->EnsureInitialized(base::Bind(
    174       &MediaGalleriesPrivateAddGalleryWatchFunction::OnPreferencesInit,
    175       this,
    176       params->gallery_id));
    177 
    178   return true;
    179 }
    180 
    181 void MediaGalleriesPrivateAddGalleryWatchFunction::OnPreferencesInit(
    182     const std::string& pref_id) {
    183   base::FilePath gallery_file_path;
    184   MediaGalleryPrefId gallery_pref_id = 0;
    185   if (!GetGalleryFilePathAndId(pref_id,
    186                                GetProfile(),
    187                                GetExtension(),
    188                                &gallery_file_path,
    189                                &gallery_pref_id)) {
    190     error_ = kInvalidGalleryIDError;
    191     HandleResponse(gallery_pref_id, false);
    192     return;
    193   }
    194 
    195   MediaGalleriesPrivateEventRouter* router =
    196       MediaGalleriesPrivateAPI::Get(GetProfile())->GetEventRouter();
    197   DCHECK(router);
    198   content::BrowserThread::PostTaskAndReplyWithResult(
    199       content::BrowserThread::FILE,
    200       FROM_HERE,
    201       base::Bind(&GalleryWatchManager::SetupGalleryWatch,
    202                  GetProfile(),
    203                  gallery_pref_id,
    204                  gallery_file_path,
    205                  extension_id(),
    206                  router->AsWeakPtr()),
    207       base::Bind(&MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse,
    208                  this,
    209                  gallery_pref_id));
    210 }
    211 
    212 void MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse(
    213     MediaGalleryPrefId gallery_id,
    214     bool success) {
    215   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    216   media_galleries_private::AddGalleryWatchResult result;
    217   result.gallery_id = base::Uint64ToString(gallery_id);
    218   result.success = success;
    219   SetResult(result.ToValue().release());
    220   if (success) {
    221     DCHECK(g_browser_process->media_file_system_registry()
    222                ->GetPreferences(GetProfile())
    223                ->IsInitialized());
    224     GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
    225         GetProfile())->GetGalleryWatchStateTracker();
    226     state_tracker->OnGalleryWatchAdded(extension_id(), gallery_id);
    227   }
    228   SendResponse(true);
    229 }
    230 
    231 
    232 ///////////////////////////////////////////////////////////////////////////////
    233 //              MediaGalleriesPrivateRemoveGalleryWatchFunction              //
    234 ///////////////////////////////////////////////////////////////////////////////
    235 
    236 MediaGalleriesPrivateRemoveGalleryWatchFunction::
    237 ~MediaGalleriesPrivateRemoveGalleryWatchFunction() {
    238 }
    239 
    240 bool MediaGalleriesPrivateRemoveGalleryWatchFunction::RunAsync() {
    241   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    242   if (!render_view_host() || !render_view_host()->GetProcess())
    243     return false;
    244 
    245   scoped_ptr<RemoveGalleryWatch::Params> params(
    246       RemoveGalleryWatch::Params::Create(*args_));
    247   EXTENSION_FUNCTION_VALIDATE(params.get());
    248 
    249   MediaGalleriesPreferences* preferences =
    250       g_browser_process->media_file_system_registry()->GetPreferences(
    251           GetProfile());
    252   preferences->EnsureInitialized(base::Bind(
    253       &MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit,
    254       this,
    255       params->gallery_id));
    256   return true;
    257 }
    258 
    259 void MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit(
    260     const std::string& pref_id) {
    261   base::FilePath gallery_file_path;
    262   MediaGalleryPrefId gallery_pref_id = 0;
    263   if (!GetGalleryFilePathAndId(pref_id,
    264                                GetProfile(),
    265                                GetExtension(),
    266                                &gallery_file_path,
    267                                &gallery_pref_id)) {
    268     error_ = kInvalidGalleryIDError;
    269     SendResponse(false);
    270     return;
    271   }
    272 
    273   content::BrowserThread::PostTask(
    274       content::BrowserThread::FILE,
    275       FROM_HERE,
    276       base::Bind(&GalleryWatchManager::RemoveGalleryWatch,
    277                  GetProfile(),
    278                  gallery_file_path,
    279                  extension_id()));
    280 
    281   GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
    282       GetProfile())->GetGalleryWatchStateTracker();
    283   state_tracker->OnGalleryWatchRemoved(extension_id(), gallery_pref_id);
    284   SendResponse(true);
    285 }
    286 
    287 ///////////////////////////////////////////////////////////////////////////////
    288 //              MediaGalleriesPrivateGetAllGalleryWatchFunction              //
    289 ///////////////////////////////////////////////////////////////////////////////
    290 
    291 MediaGalleriesPrivateGetAllGalleryWatchFunction::
    292 ~MediaGalleriesPrivateGetAllGalleryWatchFunction() {
    293 }
    294 
    295 bool MediaGalleriesPrivateGetAllGalleryWatchFunction::RunAsync() {
    296   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    297   if (!render_view_host() || !render_view_host()->GetProcess())
    298     return false;
    299 
    300   MediaGalleriesPreferences* preferences =
    301       g_browser_process->media_file_system_registry()->GetPreferences(
    302           GetProfile());
    303   preferences->EnsureInitialized(base::Bind(
    304       &MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit,
    305       this));
    306   return true;
    307 }
    308 
    309 void MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit() {
    310   std::vector<std::string> result;
    311   GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
    312       GetProfile())->GetGalleryWatchStateTracker();
    313   MediaGalleryPrefIdSet gallery_ids =
    314       state_tracker->GetAllWatchedGalleryIDsForExtension(extension_id());
    315   for (MediaGalleryPrefIdSet::const_iterator iter = gallery_ids.begin();
    316        iter != gallery_ids.end(); ++iter) {
    317     result.push_back(base::Uint64ToString(*iter));
    318   }
    319   results_ = GetAllGalleryWatch::Results::Create(result);
    320   SendResponse(true);
    321 }
    322 
    323 ///////////////////////////////////////////////////////////////////////////////
    324 //              MediaGalleriesPrivateRemoveAllGalleryWatchFunction           //
    325 ///////////////////////////////////////////////////////////////////////////////
    326 
    327 MediaGalleriesPrivateRemoveAllGalleryWatchFunction::
    328 ~MediaGalleriesPrivateRemoveAllGalleryWatchFunction() {
    329 }
    330 
    331 bool MediaGalleriesPrivateRemoveAllGalleryWatchFunction::RunAsync() {
    332   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
    333   if (!render_view_host() || !render_view_host()->GetProcess())
    334     return false;
    335 
    336   MediaGalleriesPreferences* preferences =
    337       g_browser_process->media_file_system_registry()->GetPreferences(
    338           GetProfile());
    339   preferences->EnsureInitialized(base::Bind(
    340       &MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit,
    341       this));
    342   return true;
    343 }
    344 
    345 void MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit() {
    346   MediaGalleriesPreferences* preferences =
    347       g_browser_process->media_file_system_registry()->GetPreferences(
    348           GetProfile());
    349   GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
    350       GetProfile())->GetGalleryWatchStateTracker();
    351   state_tracker->RemoveAllGalleryWatchersForExtension(
    352       extension_id(), preferences);
    353   SendResponse(true);
    354 }
    355 
    356 }  // namespace extensions
    357