Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc

Issue 11535008: Implement mediaGalleriesPrivate api to notify extensions about gallery changed events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 // GalleryWatchManager implementation.
6
7 #include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_ma nager.h"
8
9 #include <list>
10
11 #include "base/bind.h"
12 #include "base/compiler_specific.h"
13 #include "base/location.h"
14 #include "base/stl_util.h"
15 #include "base/time.h"
16 #include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_ma nager_factory.h"
17 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_ private_api.h"
18 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_ private_api_factory.h"
19 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_ private_event_router.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "content/public/browser/browser_thread.h"
22
23 namespace extensions {
24
25 namespace {
26
27 using content::BrowserThread;
28
29 // Dispatches the gallery changed event on the UI thread.
30 void SendGalleryChangedEventOnUIThread(
31 const Profile* profile,
32 const std::string& gallery_id,
33 const std::set<std::string>& extension_ids) {
34 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
35 DCHECK(profile);
36 MediaGalleriesPrivateEventRouter* router =
37 MediaGalleriesPrivateAPIFactory::GetForProfile(
38 const_cast<Profile*>(profile))->event_router();
39 if (!router)
40 return;
41 router->OnGalleryChanged(gallery_id, extension_ids);
42 }
43
44 } // namespace
45
46
47 ///////////////////////////////////////////////////////////////////////////////
48 // GalleryWatchManager //
49 ///////////////////////////////////////////////////////////////////////////////
50
51 GalleryWatchManager::GalleryWatchManager(const Profile* profile)
52 : profile_(profile) {
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
54 }
55
56 GalleryWatchManager::~GalleryWatchManager() {
57 DCHECK(thread_checker_.CalledOnValidThread());
58 if (!gallery_watchers_.empty()) {
59 // Profile is in shutdown mode.
60 STLDeleteValues(&gallery_watchers_);
61 }
62 }
63
64 bool GalleryWatchManager::StartGalleryWatch(
65 const std::string& gallery_id,
66 const FilePath& watch_path,
67 const std::string& extension_id) {
68 DCHECK(thread_checker_.CalledOnValidThread());
69 WatcherMap::const_iterator iter = gallery_watchers_.find(watch_path);
Lei Zhang 2012/12/15 04:13:21 It's easier to understand if you write the code as
kmadhusu 2012/12/17 23:58:05 Done.
70 if (iter == gallery_watchers_.end()) {
71 scoped_ptr<GalleryFilePathWatcher> watch(
72 new GalleryFilePathWatcher(profile_, gallery_id, watch_path,
73 extension_id));
74
75 if (watch->SetupWatch())
76 gallery_watchers_[watch_path] = watch.release();
77 else
78 return false;
79 } else {
80 iter->second->AddExtension(extension_id);
81 }
82 return true;
83 }
84
85 void GalleryWatchManager::StopGalleryWatch(
86 const FilePath& watch_path,
87 const std::string& extension_id) {
88 DCHECK(thread_checker_.CalledOnValidThread());
89 WatcherMap::iterator iter = gallery_watchers_.find(watch_path);
90 if (iter == gallery_watchers_.end())
91 return;
92 // Remove the renderer process for this watch.
93 iter->second->RemoveExtension(extension_id);
94 if (iter->second->GetRefCount() == 0) {
95 delete iter->second;
96 gallery_watchers_.erase(iter);
97 }
98 }
99
100 void GalleryWatchManager::OnExtensionDestroyed(
101 const std::string& extension_id) {
102 DCHECK(thread_checker_.CalledOnValidThread());
103 std::list<FilePath> watchers_to_erase;
104 for (WatcherMap::iterator iter = gallery_watchers_.begin();
105 iter != gallery_watchers_.end(); ++iter) {
106 // Remove the renderer process for this watch.
107 iter->second->OnExtensionDestroyed(extension_id);
108 if (iter->second->GetRefCount() == 0)
109 watchers_to_erase.push_back(iter->first);
110 }
111
112 for (std::list<FilePath>::const_iterator path = watchers_to_erase.begin();
113 path != watchers_to_erase.end(); ++path) {
114 WatcherMap::iterator iter = gallery_watchers_.find(*path);
115 DCHECK(iter != gallery_watchers_.end());
116 delete iter->second;
117 gallery_watchers_.erase(iter);
118 }
119 }
120
121
122 ///////////////////////////////////////////////////////////////////////////////
123 // GalleryWatchManager::GalleryFilePathWatcher //
124 ///////////////////////////////////////////////////////////////////////////////
125
126 GalleryWatchManager::GalleryFilePathWatcher::GalleryFilePathWatcher(
127 const Profile* profile,
128 const std::string& gallery_id,
129 const FilePath& path,
130 const std::string& extension_id)
131 : profile_(profile),
132 gallery_id_(gallery_id),
133 ref_count_(0),
134 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
136 file_watcher_.reset(new base::files::FilePathWatcher());
137 gallery_path_ = path;
138 AddExtension(extension_id);
139 }
140
141 GalleryWatchManager::GalleryFilePathWatcher::~GalleryFilePathWatcher() {
142 DCHECK(thread_check_.CalledOnValidThread());
143 }
144
145 void GalleryWatchManager::GalleryFilePathWatcher::AddExtension(
146 const std::string& extension_id) {
147 DCHECK(thread_check_.CalledOnValidThread());
148 ExtensionUsageRegistry::iterator it = extensions_.find(extension_id);
149 if (it != extensions_.end())
150 it->second++;
151 else
152 extensions_.insert(ExtensionUsageRegistry::value_type(extension_id, 1));
153 ref_count_++;
154 }
155
156 void GalleryWatchManager::GalleryFilePathWatcher::RemoveExtension(
157 const std::string& extension_id) {
158 DCHECK(thread_check_.CalledOnValidThread());
159 ExtensionUsageRegistry::iterator it = extensions_.find(extension_id);
160 if (it == extensions_.end())
161 return;
162 // If entry found - decrease it's count and remove if necessary
163 it->second--;
164 if (0 == it->second)
165 extensions_.erase(it);
166 ref_count_--;
167 }
168
169 void GalleryWatchManager::GalleryFilePathWatcher::OnExtensionDestroyed(
170 const std::string& extension_id) {
171 DCHECK(thread_check_.CalledOnValidThread());
172 ExtensionUsageRegistry::iterator it = extensions_.find(extension_id);
173 if (it == extensions_.end())
174 return;
175 ref_count_ -= it->second;
176 extensions_.erase(it);
177 }
178
179 unsigned int GalleryWatchManager::GalleryFilePathWatcher::GetRefCount() const {
180 DCHECK(thread_check_.CalledOnValidThread());
181 return ref_count_;
182 }
183
184 bool GalleryWatchManager::GalleryFilePathWatcher::SetupWatch() {
185 DCHECK(thread_check_.CalledOnValidThread());
186 return file_watcher_->Watch(
187 gallery_path_, true,
188 base::Bind(
189 &GalleryWatchManager::GalleryFilePathWatcher::OnFilePathChanged,
190 weak_ptr_factory_.GetWeakPtr()));
191 }
192
193 void GalleryWatchManager::GalleryFilePathWatcher::OnFilePathChanged(
194 const FilePath& path,
195 bool error) {
196 DCHECK(thread_check_.CalledOnValidThread());
197 if (error || (path != gallery_path_))
198 return;
199
200 if (!last_gallery_changed_event_.is_null()) {
201 // Ignore gallery change event if it is received too frequently.
202 // For example, when an user copies/deletes 1000 media files from a gallery,
203 // this callback is called 1000 times within a span of 10ms.
204 // GalleryWatchManager should not send 1000 gallery changed events to
205 // the watching extension.
206 const int kMinSecondsToIgnoreGalleryChangedEvent = 3;
207 base::TimeDelta diff = base::Time::Now() - last_gallery_changed_event_;
208 if (diff.InSeconds() < kMinSecondsToIgnoreGalleryChangedEvent)
209 return;
210 }
211
212 last_gallery_changed_event_ = base::Time::Now();
213 ExtensionIdSet extension_ids;
214 for (ExtensionUsageRegistry::const_iterator iter = extensions_.begin();
215 iter != extensions_.end(); ++iter)
216 extension_ids.insert(iter->first);
217 content::BrowserThread::PostTask(
218 content::BrowserThread::UI, FROM_HERE,
219 base::Bind(SendGalleryChangedEventOnUIThread, profile_, gallery_id_,
220 extension_ids));
221 }
222
223 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698