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 // 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,
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))
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())
69 *gallery_pref_id = pref_id;
70 *gallery_file_path = file_path;
77 ///////////////////////////////////////////////////////////////////////////////
78 // MediaGalleriesPrivateAPI //
79 ///////////////////////////////////////////////////////////////////////////////
81 MediaGalleriesPrivateAPI::MediaGalleriesPrivateAPI(
82 content::BrowserContext* context)
83 : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
85 EventRouter* event_router = EventRouter::Get(profile_);
86 event_router->RegisterObserver(
87 this, media_galleries_private::OnGalleryChanged::kEventName);
90 MediaGalleriesPrivateAPI::~MediaGalleriesPrivateAPI() {
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_));
101 static base::LazyInstance<
102 BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI> > g_factory =
103 LAZY_INSTANCE_INITIALIZER;
106 BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>*
107 MediaGalleriesPrivateAPI::GetFactoryInstance() {
108 return g_factory.Pointer();
112 MediaGalleriesPrivateAPI* MediaGalleriesPrivateAPI::Get(
113 content::BrowserContext* context) {
114 return BrowserContextKeyedAPIFactory<MediaGalleriesPrivateAPI>::Get(context);
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
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()));
131 MediaGalleriesPrivateEventRouter* MediaGalleriesPrivateAPI::GetEventRouter() {
132 MaybeInitializeEventRouterAndTracker();
133 return media_galleries_private_event_router_.get();
136 GalleryWatchStateTracker*
137 MediaGalleriesPrivateAPI::GetGalleryWatchStateTracker() {
138 MaybeInitializeEventRouterAndTracker();
139 return tracker_.get();
142 void MediaGalleriesPrivateAPI::MaybeInitializeEventRouterAndTracker() {
143 if (media_galleries_private_event_router_.get())
145 media_galleries_private_event_router_.reset(
146 new MediaGalleriesPrivateEventRouter(profile_));
147 DCHECK(g_browser_process->media_file_system_registry()->
148 GetPreferences(profile_)->IsInitialized());
150 new GalleryWatchStateTracker(profile_));
153 ///////////////////////////////////////////////////////////////////////////////
154 // MediaGalleriesPrivateAddGalleryWatchFunction //
155 ///////////////////////////////////////////////////////////////////////////////
156 MediaGalleriesPrivateAddGalleryWatchFunction::
157 ~MediaGalleriesPrivateAddGalleryWatchFunction() {
160 bool MediaGalleriesPrivateAddGalleryWatchFunction::RunAsync() {
161 DCHECK(GetProfile());
162 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
163 if (!render_view_host() || !render_view_host()->GetProcess())
166 scoped_ptr<AddGalleryWatch::Params> params(
167 AddGalleryWatch::Params::Create(*args_));
168 EXTENSION_FUNCTION_VALIDATE(params.get());
170 MediaGalleriesPreferences* preferences =
171 g_browser_process->media_file_system_registry()->GetPreferences(
173 preferences->EnsureInitialized(base::Bind(
174 &MediaGalleriesPrivateAddGalleryWatchFunction::OnPreferencesInit,
176 params->gallery_id));
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,
190 error_ = kInvalidGalleryIDError;
191 HandleResponse(gallery_pref_id, false);
195 MediaGalleriesPrivateEventRouter* router =
196 MediaGalleriesPrivateAPI::Get(GetProfile())->GetEventRouter();
198 // TODO(tommycli): The new GalleryWatchManager no longer checks that there is
199 // an event listener attached. There should be a check for that here.
202 content::BrowserThread::PostTaskAndReplyWithResult(
203 content::BrowserThread::FILE,
205 base::Bind(&GalleryWatchManager::SetupGalleryWatch,
210 router->AsWeakPtr()),
211 base::Bind(&MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse,
216 void MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse(
217 MediaGalleryPrefId gallery_id,
219 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
220 media_galleries_private::AddGalleryWatchResult result;
221 result.gallery_id = base::Uint64ToString(gallery_id);
222 result.success = success;
223 SetResult(result.ToValue().release());
225 DCHECK(g_browser_process->media_file_system_registry()
226 ->GetPreferences(GetProfile())
228 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
229 GetProfile())->GetGalleryWatchStateTracker();
230 state_tracker->OnGalleryWatchAdded(extension_id(), gallery_id);
236 ///////////////////////////////////////////////////////////////////////////////
237 // MediaGalleriesPrivateRemoveGalleryWatchFunction //
238 ///////////////////////////////////////////////////////////////////////////////
240 MediaGalleriesPrivateRemoveGalleryWatchFunction::
241 ~MediaGalleriesPrivateRemoveGalleryWatchFunction() {
244 bool MediaGalleriesPrivateRemoveGalleryWatchFunction::RunAsync() {
245 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
246 if (!render_view_host() || !render_view_host()->GetProcess())
249 scoped_ptr<RemoveGalleryWatch::Params> params(
250 RemoveGalleryWatch::Params::Create(*args_));
251 EXTENSION_FUNCTION_VALIDATE(params.get());
253 MediaGalleriesPreferences* preferences =
254 g_browser_process->media_file_system_registry()->GetPreferences(
256 preferences->EnsureInitialized(base::Bind(
257 &MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit,
259 params->gallery_id));
263 void MediaGalleriesPrivateRemoveGalleryWatchFunction::OnPreferencesInit(
264 const std::string& pref_id) {
265 base::FilePath gallery_file_path;
266 MediaGalleryPrefId gallery_pref_id = 0;
267 if (!GetGalleryFilePathAndId(pref_id,
272 error_ = kInvalidGalleryIDError;
277 content::BrowserThread::PostTask(
278 content::BrowserThread::FILE,
280 base::Bind(&GalleryWatchManager::RemoveGalleryWatch,
285 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
286 GetProfile())->GetGalleryWatchStateTracker();
287 state_tracker->OnGalleryWatchRemoved(extension_id(), gallery_pref_id);
291 ///////////////////////////////////////////////////////////////////////////////
292 // MediaGalleriesPrivateGetAllGalleryWatchFunction //
293 ///////////////////////////////////////////////////////////////////////////////
295 MediaGalleriesPrivateGetAllGalleryWatchFunction::
296 ~MediaGalleriesPrivateGetAllGalleryWatchFunction() {
299 bool MediaGalleriesPrivateGetAllGalleryWatchFunction::RunAsync() {
300 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
301 if (!render_view_host() || !render_view_host()->GetProcess())
304 MediaGalleriesPreferences* preferences =
305 g_browser_process->media_file_system_registry()->GetPreferences(
307 preferences->EnsureInitialized(base::Bind(
308 &MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit,
313 void MediaGalleriesPrivateGetAllGalleryWatchFunction::OnPreferencesInit() {
314 std::vector<std::string> result;
315 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
316 GetProfile())->GetGalleryWatchStateTracker();
317 MediaGalleryPrefIdSet gallery_ids =
318 state_tracker->GetAllWatchedGalleryIDsForExtension(extension_id());
319 for (MediaGalleryPrefIdSet::const_iterator iter = gallery_ids.begin();
320 iter != gallery_ids.end(); ++iter) {
321 result.push_back(base::Uint64ToString(*iter));
323 results_ = GetAllGalleryWatch::Results::Create(result);
327 ///////////////////////////////////////////////////////////////////////////////
328 // MediaGalleriesPrivateRemoveAllGalleryWatchFunction //
329 ///////////////////////////////////////////////////////////////////////////////
331 MediaGalleriesPrivateRemoveAllGalleryWatchFunction::
332 ~MediaGalleriesPrivateRemoveAllGalleryWatchFunction() {
335 bool MediaGalleriesPrivateRemoveAllGalleryWatchFunction::RunAsync() {
336 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
337 if (!render_view_host() || !render_view_host()->GetProcess())
340 MediaGalleriesPreferences* preferences =
341 g_browser_process->media_file_system_registry()->GetPreferences(
343 preferences->EnsureInitialized(base::Bind(
344 &MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit,
349 void MediaGalleriesPrivateRemoveAllGalleryWatchFunction::OnPreferencesInit() {
350 MediaGalleriesPreferences* preferences =
351 g_browser_process->media_file_system_registry()->GetPreferences(
353 GalleryWatchStateTracker* state_tracker = MediaGalleriesPrivateAPI::Get(
354 GetProfile())->GetGalleryWatchStateTracker();
355 state_tracker->RemoveAllGalleryWatchersForExtension(
356 extension_id(), preferences);
360 } // namespace extensions