blob: 3cc95b0222c918d8073aa537e1ca3e46413b0c44 [file] [log] [blame]
// 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/event_names.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_function.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.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/browser/storage_monitor/storage_monitor.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"
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(content::BrowserThread::CurrentlyOn(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(Profile* profile)
: profile_(profile),
weak_ptr_factory_(this) {
DCHECK(profile_);
ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
this, media_galleries_private::OnDeviceAttached::kEventName);
ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
this, media_galleries_private::OnDeviceDetached::kEventName);
ExtensionSystem::Get(profile_)->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<ProfileKeyedAPIFactory<MediaGalleriesPrivateAPI> >
g_factory = LAZY_INSTANCE_INITIALIZER;
// static
ProfileKeyedAPIFactory<MediaGalleriesPrivateAPI>*
MediaGalleriesPrivateAPI::GetFactoryInstance() {
return &g_factory.Get();
}
// static
MediaGalleriesPrivateAPI* MediaGalleriesPrivateAPI::Get(Profile* profile) {
return
ProfileKeyedAPIFactory<MediaGalleriesPrivateAPI>::GetForProfile(profile);
}
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(content::BrowserThread::CurrentlyOn(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(content::BrowserThread::CurrentlyOn(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(content::BrowserThread::CurrentlyOn(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(content::BrowserThread::CurrentlyOn(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(content::BrowserThread::CurrentlyOn(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(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
ExtensionService* service =
extensions::ExtensionSystem::Get(GetProfile())->extension_service();
DCHECK(service);
ListValue* result_list = new ListValue;
for (ExtensionSet::const_iterator iter = service->extensions()->begin();
iter != service->extensions()->end();
++iter) {
const Extension* extension = iter->get();
if (GetProfile()->IsOffTheRecord() &&
!extension_util::IsIncognitoEnabled(extension->id(), service))
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();
DictionaryValue* handler = new 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