root/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. HandleProfileShutdownOnFileThread
  2. GetGalleryFilePathAndId
  3. weak_ptr_factory_
  4. Shutdown
  5. GetFactoryInstance
  6. Get
  7. OnListenerAdded
  8. GetEventRouter
  9. GetGalleryWatchStateTracker
  10. MaybeInitializeEventRouterAndTracker
  11. MediaGalleriesPrivateAddGalleryWatchFunction
  12. RunImpl
  13. OnPreferencesInit
  14. HandleResponse
  15. MediaGalleriesPrivateRemoveGalleryWatchFunction
  16. RunImpl
  17. OnPreferencesInit
  18. MediaGalleriesPrivateGetAllGalleryWatchFunction
  19. RunImpl
  20. OnPreferencesInit
  21. MediaGalleriesPrivateRemoveAllGalleryWatchFunction
  22. RunImpl
  23. OnPreferencesInit
  24. MediaGalleriesPrivateGetHandlersFunction
  25. RunImpl

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.h"
#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
#include "chrome/browser/media_galleries/media_galleries_preferences.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/media_galleries_private/media_galleries_handler.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_system.h"

using base::DictionaryValue;
using base::ListValue;

namespace extensions {

namespace AddGalleryWatch =
    extensions::api::media_galleries_private::AddGalleryWatch;
namespace RemoveGalleryWatch =
    extensions::api::media_galleries_private::RemoveGalleryWatch;
namespace GetAllGalleryWatch =
    extensions::api::media_galleries_private::GetAllGalleryWatch;
namespace media_galleries_private =
    api::media_galleries_private;

namespace {

const char kInvalidGalleryIDError[] = "Invalid gallery ID";

// Handles the profile shutdown event on the file thread to clean up
// GalleryWatchManager.
void HandleProfileShutdownOnFileThread(void* profile_id) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
  GalleryWatchManager::OnProfileShutdown(profile_id);
}

// Gets the |gallery_file_path| and |gallery_pref_id| of the gallery specified
// by the |gallery_id|. Returns true and set |gallery_file_path| and
// |gallery_pref_id| if the |gallery_id| is valid and returns false otherwise.
bool GetGalleryFilePathAndId(const std::string& gallery_id,
                             Profile* profile,
                             const Extension* extension,
                             base::FilePath* gallery_file_path,
                             MediaGalleryPrefId* gallery_pref_id) {
  MediaGalleryPrefId pref_id;
  if (!base::StringToUint64(gallery_id, &pref_id))
    return false;
  MediaGalleriesPreferences* preferences =
      g_browser_process->media_file_system_registry()->GetPreferences(profile);
  base::FilePath file_path(
      preferences->LookUpGalleryPathForExtension(pref_id, extension, false));
  if (file_path.empty())
    return false;
  *gallery_pref_id = pref_id;
  *gallery_file_path = file_path;
  return true;
}

}  // namespace


///////////////////////////////////////////////////////////////////////////////
//                      MediaGalleriesPrivateAPI                             //
///////////////////////////////////////////////////////////////////////////////

MediaGalleriesPrivateAPI::MediaGalleriesPrivateAPI(
    content::BrowserContext* context)
    : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
  DCHECK(profile_);
  EventRouter* event_router = ExtensionSystem::Get(profile_)->event_router();
  event_router->RegisterObserver(
      this, media_galleries_private::OnGalleryChanged::kEventName);
}

MediaGalleriesPrivateAPI::~MediaGalleriesPrivateAPI() {
}

void MediaGalleriesPrivateAPI::Shutdown() {
  ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
  weak_ptr_factory_.InvalidateWeakPtrs();
  content::BrowserThread::PostTask(
      content::BrowserThread::FILE, FROM_HERE,
      base::Bind(&HandleProfileShutdownOnFileThread, profile_));
}

static base::LazyInstance<
    BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI> > g_factory =
    LAZY_INSTANCE_INITIALIZER;

// static
BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>*
MediaGalleriesPrivateAPI::GetFactoryInstance() {
  return g_factory.Pointer();
}

// static
MediaGalleriesPrivateAPI* MediaGalleriesPrivateAPI::Get(
    content::BrowserContext* context) {
  return BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>::Get(context);
}

void MediaGalleriesPrivateAPI::OnListenerAdded(
    const EventListenerInfo& details) {
  // Make sure MediaGalleriesPreferences is initialized. After that,
  // try to initialize the event router for the listener.
  // This method is called synchronously with the message handler for the
  // JS invocation.

  MediaGalleriesPreferences* preferences =
      g_browser_process->media_file_system_registry()->GetPreferences(profile_);
  preferences->EnsureInitialized(base::Bind(
      &MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker,
      weak_ptr_factory_.GetWeakPtr()));
}

MediaGalleriesPrivateEventRouter* MediaGalleriesPrivateAPI::GetEventRouter() {
  MaybeInitializeEventRouterAndTracker();
  return media_galleries_private_event_router_.get();
}

GalleryWatchStateTracker*
MediaGalleriesPrivateAPI::GetGalleryWatchStateTracker() {
  MaybeInitializeEventRouterAndTracker();
  return tracker_.get();
}

void MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker() {
  if (media_galleries_private_event_router_.get())
    return;
  media_galleries_private_event_router_.reset(
      new MediaGalleriesPrivateEventRouter(profile_));
  DCHECK(g_browser_process->media_file_system_registry()->
             GetPreferences(profile_)->IsInitialized());
  tracker_.reset(
      new GalleryWatchStateTracker(profile_));
}

///////////////////////////////////////////////////////////////////////////////
//              MediaGalleriesPrivateAddGalleryWatchFunction                 //
///////////////////////////////////////////////////////////////////////////////
MediaGalleriesPrivateAddGalleryWatchFunction::
~MediaGalleriesPrivateAddGalleryWatchFunction() {
}

bool MediaGalleriesPrivateAddGalleryWatchFunction::RunImpl() {
  DCHECK(GetProfile());
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (!render_view_host() || !render_view_host()->GetProcess())
    return false;

  scoped_ptr<AddGalleryWatch::Params> params(
      AddGalleryWatch::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  MediaGalleriesPreferences* preferences =
      g_browser_process->media_file_system_registry()->GetPreferences(
          GetProfile());
  preferences->EnsureInitialized(base::Bind(
      &MediaGalleriesPrivateAddGalleryWatchFunction::OnPreferencesInit,
      this,
      params->gallery_id));

  return true;
}

void MediaGalleriesPrivateAddGalleryWatchFunction::OnPreferencesInit(
    const std::string& pref_id) {
  base::FilePath gallery_file_path;
  MediaGalleryPrefId gallery_pref_id = 0;
  if (!GetGalleryFilePathAndId(pref_id,
                               GetProfile(),
                               GetExtension(),
                               &gallery_file_path,
                               &gallery_pref_id)) {
    error_ = kInvalidGalleryIDError;
    HandleResponse(gallery_pref_id, false);
    return;
  }

#if defined(OS_WIN)
  MediaGalleriesPrivateEventRouter* router =
      MediaGalleriesPrivateAPI::Get(GetProfile())->GetEventRouter();
  DCHECK(router);
  content::BrowserThread::PostTaskAndReplyWithResult(
      content::BrowserThread::FILE,
      FROM_HERE,
      base::Bind(&GalleryWatchManager::SetupGalleryWatch,
                 GetProfile(),
                 gallery_pref_id,
                 gallery_file_path,
                 extension_id(),
                 router->AsWeakPtr()),
      base::Bind(&MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse,
                 this,
                 gallery_pref_id));
#else
  // Recursive gallery watch operation is not currently supported on
  // non-windows platforms. Please refer to crbug.com/144491 for more details.
  HandleResponse(gallery_pref_id, false);
#endif
}

void MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse(
    MediaGalleryPrefId gallery_id,
    bool success) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  media_galleries_private::AddGalleryWatchResult result;
  result.gallery_id = base::Uint64ToString(gallery_id);
  result.success = success;
  SetResult(result.ToValue().release());
  if (success) {
    DCHECK(g_browser_process->media_file_system_registry()
               ->GetPreferences(GetProfile())
               ->IsInitialized());
    GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
        GetProfile())->GetGalleryWatchStateTracker();
    state_tracker->OnGalleryWatchAdded(extension_id(), gallery_id);
  }
  SendResponse(true);
}


///////////////////////////////////////////////////////////////////////////////
//              MediaGalleriesPrivateRemoveGalleryWatchFunction              //
///////////////////////////////////////////////////////////////////////////////

MediaGalleriesPrivateRemoveGalleryWatchFunction::
~MediaGalleriesPrivateRemoveGalleryWatchFunction() {
}

bool MediaGalleriesPrivateRemoveGalleryWatchFunction::RunImpl() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (!render_view_host() || !render_view_host()->GetProcess())
    return false;

  // Remove gallery watch operation is currently supported on windows platforms.
  // Please refer to crbug.com/144491 for more details.
  scoped_ptr<RemoveGalleryWatch::Params> params(
      RemoveGalleryWatch::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());

  MediaGalleriesPreferences* preferences =
      g_browser_process->media_file_system_registry()->GetPreferences(
          GetProfile());
  preferences->EnsureInitialized(base::Bind(
      &MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit,
      this,
      params->gallery_id));
  return true;
}

void MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit(
    const std::string& pref_id) {
#if defined(OS_WIN)
  base::FilePath gallery_file_path;
  MediaGalleryPrefId gallery_pref_id = 0;
  if (!GetGalleryFilePathAndId(pref_id,
                               GetProfile(),
                               GetExtension(),
                               &gallery_file_path,
                               &gallery_pref_id)) {
    error_ = kInvalidGalleryIDError;
    SendResponse(false);
    return;
  }

  content::BrowserThread::PostTask(
      content::BrowserThread::FILE,
      FROM_HERE,
      base::Bind(&GalleryWatchManager::RemoveGalleryWatch,
                 GetProfile(),
                 gallery_file_path,
                 extension_id()));

  GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
      GetProfile())->GetGalleryWatchStateTracker();
  state_tracker->OnGalleryWatchRemoved(extension_id(), gallery_pref_id);
#endif
  SendResponse(true);
}

///////////////////////////////////////////////////////////////////////////////
//              MediaGalleriesPrivateGetAllGalleryWatchFunction              //
///////////////////////////////////////////////////////////////////////////////

MediaGalleriesPrivateGetAllGalleryWatchFunction::
~MediaGalleriesPrivateGetAllGalleryWatchFunction() {
}

bool MediaGalleriesPrivateGetAllGalleryWatchFunction::RunImpl() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (!render_view_host() || !render_view_host()->GetProcess())
    return false;

  MediaGalleriesPreferences* preferences =
      g_browser_process->media_file_system_registry()->GetPreferences(
          GetProfile());
  preferences->EnsureInitialized(base::Bind(
      &MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit,
      this));
  return true;
}

void MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit() {
  std::vector<std::string> result;
#if defined(OS_WIN)
  GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
      GetProfile())->GetGalleryWatchStateTracker();
  MediaGalleryPrefIdSet gallery_ids =
      state_tracker->GetAllWatchedGalleryIDsForExtension(extension_id());
  for (MediaGalleryPrefIdSet::const_iterator iter = gallery_ids.begin();
       iter != gallery_ids.end(); ++iter) {
    result.push_back(base::Uint64ToString(*iter));
  }
#endif
  results_ = GetAllGalleryWatch::Results::Create(result);
  SendResponse(true);
}

///////////////////////////////////////////////////////////////////////////////
//              MediaGalleriesPrivateRemoveAllGalleryWatchFunction           //
///////////////////////////////////////////////////////////////////////////////

MediaGalleriesPrivateRemoveAllGalleryWatchFunction::
~MediaGalleriesPrivateRemoveAllGalleryWatchFunction() {
}

bool MediaGalleriesPrivateRemoveAllGalleryWatchFunction::RunImpl() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (!render_view_host() || !render_view_host()->GetProcess())
    return false;

  MediaGalleriesPreferences* preferences =
      g_browser_process->media_file_system_registry()->GetPreferences(
          GetProfile());
  preferences->EnsureInitialized(base::Bind(
      &MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit,
      this));
  return true;
}

void MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit() {
#if defined(OS_WIN)
  MediaGalleriesPreferences* preferences =
      g_browser_process->media_file_system_registry()->GetPreferences(
          GetProfile());
  GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
      GetProfile())->GetGalleryWatchStateTracker();
  state_tracker->RemoveAllGalleryWatchersForExtension(
      extension_id(), preferences);
#endif
  SendResponse(true);
}

///////////////////////////////////////////////////////////////////////////////
//              MediaGalleriesPrivateGetHandlersFunction                     //
///////////////////////////////////////////////////////////////////////////////

MediaGalleriesPrivateGetHandlersFunction::
~MediaGalleriesPrivateGetHandlersFunction() {
}

bool MediaGalleriesPrivateGetHandlersFunction::RunImpl() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  ExtensionService* service =
      extensions::ExtensionSystem::Get(GetProfile())->extension_service();
  DCHECK(service);

  base::ListValue* result_list = new base::ListValue;

  for (ExtensionSet::const_iterator iter = service->extensions()->begin();
       iter != service->extensions()->end();
       ++iter) {
    const Extension* extension = iter->get();
    if (GetProfile()->IsOffTheRecord() &&
        !util::IsIncognitoEnabled(extension->id(), GetProfile()))
      continue;

    MediaGalleriesHandler::List* handler_list =
        MediaGalleriesHandler::GetHandlers(extension);
    if (!handler_list)
      continue;

    for (MediaGalleriesHandler::List::const_iterator action_iter =
             handler_list->begin();
         action_iter != handler_list->end();
         ++action_iter) {
      const MediaGalleriesHandler* action = action_iter->get();
      base::DictionaryValue* handler = new base::DictionaryValue;
      handler->SetString("extensionId", action->extension_id());
      handler->SetString("id", action->id());
      handler->SetString("title", action->title());
      handler->SetString("iconUrl", action->icon_path());
      result_list->Append(handler);
    }
  }

  SetResult(result_list);
  SendResponse(true);

  return true;
}

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */