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 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"
7 #include "base/basictypes.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"
27 using base::DictionaryValue;
28 using base::ListValue;
30 namespace extensions {
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;
43 const char kInvalidGalleryIDError[] = "Invalid gallery ID";
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);
52 // Returns true and sets |gallery_file_path| and |gallery_pref_id| if the
53 // |gallery_id| is valid and returns false otherwise.
54 bool GetGalleryFilePathAndId(const std::string& gallery_id,
56 const Extension* extension,
57 base::FilePath* gallery_file_path,
58 MediaGalleryPrefId* gallery_pref_id) {
59 MediaGalleryPrefId pref_id;
60 if (!base::StringToUint64(gallery_id, &pref_id))
62 MediaGalleriesPreferences* preferences =
63 g_browser_process->media_file_system_registry()->GetPreferences(profile);
64 base::FilePath file_path(
65 preferences->LookUpGalleryPathForExtension(pref_id, extension, false));
66 if (file_path.empty())
68 *gallery_pref_id = pref_id;
69 *gallery_file_path = file_path;
76 ///////////////////////////////////////////////////////////////////////////////
77 // MediaGalleriesPrivateAPI //
78 ///////////////////////////////////////////////////////////////////////////////
80 MediaGalleriesPrivateAPI::MediaGalleriesPrivateAPI(
81 content::BrowserContext* context)
82 : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
84 EventRouter* event_router = EventRouter::Get(profile_);
85 event_router->RegisterObserver(
86 this, media_galleries_private::OnGalleryChanged::kEventName);
89 MediaGalleriesPrivateAPI::~MediaGalleriesPrivateAPI() {
92 void MediaGalleriesPrivateAPI::Shutdown() {
93 EventRouter::Get(profile_)->UnregisterObserver(this);
94 weak_ptr_factory_.InvalidateWeakPtrs();
95 content::BrowserThread::PostTask(
96 content::BrowserThread::FILE, FROM_HERE,
97 base::Bind(&HandleProfileShutdownOnFileThread, profile_));
100 static base::LazyInstance<
101 BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI> > g_factory =
102 LAZY_INSTANCE_INITIALIZER;
105 BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>*
106 MediaGalleriesPrivateAPI::GetFactoryInstance() {
107 return g_factory.Pointer();
111 MediaGalleriesPrivateAPI* MediaGalleriesPrivateAPI::Get(
112 content::BrowserContext* context) {
113 return BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>::Get(context);
116 void MediaGalleriesPrivateAPI::OnListenerAdded(
117 const EventListenerInfo& details) {
118 // Make sure MediaGalleriesPreferences is initialized. After that,
119 // try to initialize the event router for the listener.
120 // This method is called synchronously with the message handler for the
123 MediaGalleriesPreferences* preferences =
124 g_browser_process->media_file_system_registry()->GetPreferences(profile_);
125 preferences->EnsureInitialized(base::Bind(
126 &MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker,
127 weak_ptr_factory_.GetWeakPtr()));
130 MediaGalleriesPrivateEventRouter* MediaGalleriesPrivateAPI::GetEventRouter() {
131 MaybeInitializeEventRouterAndTracker();
132 return media_galleries_private_event_router_.get();
135 GalleryWatchStateTracker*
136 MediaGalleriesPrivateAPI::GetGalleryWatchStateTracker() {
137 MaybeInitializeEventRouterAndTracker();
138 return tracker_.get();
141 void MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker() {
142 if (media_galleries_private_event_router_.get())
144 media_galleries_private_event_router_.reset(
145 new MediaGalleriesPrivateEventRouter(profile_));
146 DCHECK(g_browser_process->media_file_system_registry()->
147 GetPreferences(profile_)->IsInitialized());
149 new GalleryWatchStateTracker(profile_));
152 ///////////////////////////////////////////////////////////////////////////////
153 // MediaGalleriesPrivateAddGalleryWatchFunction //
154 ///////////////////////////////////////////////////////////////////////////////
155 MediaGalleriesPrivateAddGalleryWatchFunction::
156 ~MediaGalleriesPrivateAddGalleryWatchFunction() {
159 bool MediaGalleriesPrivateAddGalleryWatchFunction::RunAsync() {
160 DCHECK(GetProfile());
161 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
162 if (!render_view_host() || !render_view_host()->GetProcess())
165 scoped_ptr<AddGalleryWatch::Params> params(
166 AddGalleryWatch::Params::Create(*args_));
167 EXTENSION_FUNCTION_VALIDATE(params.get());
169 MediaGalleriesPreferences* preferences =
170 g_browser_process->media_file_system_registry()->GetPreferences(
172 preferences->EnsureInitialized(base::Bind(
173 &MediaGalleriesPrivateAddGalleryWatchFunction::OnPreferencesInit,
175 params->gallery_id));
180 void MediaGalleriesPrivateAddGalleryWatchFunction::OnPreferencesInit(
181 const std::string& pref_id) {
182 base::FilePath gallery_file_path;
183 MediaGalleryPrefId gallery_pref_id = 0;
184 if (!GetGalleryFilePathAndId(pref_id,
189 error_ = kInvalidGalleryIDError;
190 HandleResponse(gallery_pref_id, false);
194 MediaGalleriesPrivateEventRouter* router =
195 MediaGalleriesPrivateAPI::Get(GetProfile())->GetEventRouter();
197 // TODO(tommycli): The new GalleryWatchManager no longer checks that there is
198 // an event listener attached. There should be a check for that here.
201 content::BrowserThread::PostTaskAndReplyWithResult(
202 content::BrowserThread::FILE,
204 base::Bind(&GalleryWatchManager::SetupGalleryWatch,
209 router->AsWeakPtr()),
210 base::Bind(&MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse,
215 void MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse(
216 MediaGalleryPrefId gallery_id,
218 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
219 media_galleries_private::AddGalleryWatchResult result;
220 result.gallery_id = base::Uint64ToString(gallery_id);
221 result.success = success;
222 SetResult(result.ToValue().release());
224 DCHECK(g_browser_process->media_file_system_registry()
225 ->GetPreferences(GetProfile())
227 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
228 GetProfile())->GetGalleryWatchStateTracker();
229 state_tracker->OnGalleryWatchAdded(extension_id(), gallery_id);
235 ///////////////////////////////////////////////////////////////////////////////
236 // MediaGalleriesPrivateRemoveGalleryWatchFunction //
237 ///////////////////////////////////////////////////////////////////////////////
239 MediaGalleriesPrivateRemoveGalleryWatchFunction::
240 ~MediaGalleriesPrivateRemoveGalleryWatchFunction() {
243 bool MediaGalleriesPrivateRemoveGalleryWatchFunction::RunAsync() {
244 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
245 if (!render_view_host() || !render_view_host()->GetProcess())
248 scoped_ptr<RemoveGalleryWatch::Params> params(
249 RemoveGalleryWatch::Params::Create(*args_));
250 EXTENSION_FUNCTION_VALIDATE(params.get());
252 MediaGalleriesPreferences* preferences =
253 g_browser_process->media_file_system_registry()->GetPreferences(
255 preferences->EnsureInitialized(base::Bind(
256 &MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit,
258 params->gallery_id));
262 void MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit(
263 const std::string& pref_id) {
264 base::FilePath gallery_file_path;
265 MediaGalleryPrefId gallery_pref_id = 0;
266 if (!GetGalleryFilePathAndId(pref_id,
271 error_ = kInvalidGalleryIDError;
276 content::BrowserThread::PostTask(
277 content::BrowserThread::FILE,
279 base::Bind(&GalleryWatchManager::RemoveGalleryWatch,
284 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
285 GetProfile())->GetGalleryWatchStateTracker();
286 state_tracker->OnGalleryWatchRemoved(extension_id(), gallery_pref_id);
290 ///////////////////////////////////////////////////////////////////////////////
291 // MediaGalleriesPrivateGetAllGalleryWatchFunction //
292 ///////////////////////////////////////////////////////////////////////////////
294 MediaGalleriesPrivateGetAllGalleryWatchFunction::
295 ~MediaGalleriesPrivateGetAllGalleryWatchFunction() {
298 bool MediaGalleriesPrivateGetAllGalleryWatchFunction::RunAsync() {
299 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
300 if (!render_view_host() || !render_view_host()->GetProcess())
303 MediaGalleriesPreferences* preferences =
304 g_browser_process->media_file_system_registry()->GetPreferences(
306 preferences->EnsureInitialized(base::Bind(
307 &MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit,
312 void MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit() {
313 std::vector<std::string> result;
314 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
315 GetProfile())->GetGalleryWatchStateTracker();
316 MediaGalleryPrefIdSet gallery_ids =
317 state_tracker->GetAllWatchedGalleryIDsForExtension(extension_id());
318 for (MediaGalleryPrefIdSet::const_iterator iter = gallery_ids.begin();
319 iter != gallery_ids.end(); ++iter) {
320 result.push_back(base::Uint64ToString(*iter));
322 results_ = GetAllGalleryWatch::Results::Create(result);
326 ///////////////////////////////////////////////////////////////////////////////
327 // MediaGalleriesPrivateRemoveAllGalleryWatchFunction //
328 ///////////////////////////////////////////////////////////////////////////////
330 MediaGalleriesPrivateRemoveAllGalleryWatchFunction::
331 ~MediaGalleriesPrivateRemoveAllGalleryWatchFunction() {
334 bool MediaGalleriesPrivateRemoveAllGalleryWatchFunction::RunAsync() {
335 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
336 if (!render_view_host() || !render_view_host()->GetProcess())
339 MediaGalleriesPreferences* preferences =
340 g_browser_process->media_file_system_registry()->GetPreferences(
342 preferences->EnsureInitialized(base::Bind(
343 &MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit,
348 void MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit() {
349 MediaGalleriesPreferences* preferences =
350 g_browser_process->media_file_system_registry()->GetPreferences(
352 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
353 GetProfile())->GetGalleryWatchStateTracker();
354 state_tracker->RemoveAllGalleryWatchersForExtension(
355 extension_id(), preferences);
359 } // namespace extensions