OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_settings_frontend.h" | 5 #include "chrome/browser/extensions/extension_settings_frontend.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
9 #include "chrome/browser/extensions/extension_event_names.h" | 9 #include "chrome/browser/extensions/extension_event_names.h" |
10 #include "chrome/browser/extensions/extension_event_router.h" | 10 #include "chrome/browser/extensions/extension_event_router.h" |
11 #include "chrome/browser/extensions/extension_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
12 #include "chrome/browser/extensions/extension_settings_backend.h" | 12 #include "chrome/browser/extensions/extension_settings_backend.h" |
13 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
14 #include "content/browser/browser_thread.h" | 14 #include "content/browser/browser_thread.h" |
15 #include "content/public/browser/notification_service.h" | 15 #include "content/public/browser/notification_service.h" |
16 | 16 |
| 17 namespace { |
| 18 |
| 19 struct Backends { |
| 20 Backends( |
| 21 const scoped_refptr<ExtensionSettingsObserverList>& observers, |
| 22 const FilePath& profile_path) |
| 23 : extensions_backend_( |
| 24 profile_path.AppendASCII( |
| 25 ExtensionService::kExtensionSettingsDirectoryName), |
| 26 observers), |
| 27 apps_backend_( |
| 28 profile_path.AppendASCII( |
| 29 ExtensionService::kAppSettingsDirectoryName), |
| 30 observers) {} |
| 31 |
| 32 ExtensionSettingsBackend extensions_backend_; |
| 33 ExtensionSettingsBackend apps_backend_; |
| 34 }; |
| 35 |
| 36 static void CallbackWithExtensionsBackend( |
| 37 const ExtensionSettingsFrontend::SyncableServiceCallback& callback, |
| 38 Backends* backends) { |
| 39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 40 callback.Run(&backends->extensions_backend_); |
| 41 } |
| 42 |
| 43 void CallbackWithAppsBackend( |
| 44 const ExtensionSettingsFrontend::SyncableServiceCallback& callback, |
| 45 Backends* backends) { |
| 46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 47 callback.Run(&backends->apps_backend_); |
| 48 } |
| 49 |
| 50 void CallbackWithExtensionsStorage( |
| 51 const std::string& extension_id, |
| 52 const ExtensionSettingsFrontend::StorageCallback& callback, |
| 53 Backends* backends) { |
| 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 55 callback.Run(backends->extensions_backend_.GetStorage(extension_id)); |
| 56 } |
| 57 |
| 58 void CallbackWithAppsStorage( |
| 59 const std::string& extension_id, |
| 60 const ExtensionSettingsFrontend::StorageCallback& callback, |
| 61 Backends* backends) { |
| 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 63 callback.Run(backends->apps_backend_.GetStorage(extension_id)); |
| 64 } |
| 65 |
| 66 void CallbackWithNullStorage( |
| 67 const ExtensionSettingsFrontend::StorageCallback& callback) { |
| 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 69 callback.Run(NULL); |
| 70 } |
| 71 |
| 72 void DeleteStorageOnFileThread( |
| 73 const std::string& extension_id, Backends* backends) { |
| 74 backends->extensions_backend_.DeleteStorage(extension_id); |
| 75 backends->apps_backend_.DeleteStorage(extension_id); |
| 76 } |
| 77 |
| 78 } // namespace |
| 79 |
17 class ExtensionSettingsFrontend::DefaultObserver | 80 class ExtensionSettingsFrontend::DefaultObserver |
18 : public ExtensionSettingsObserver { | 81 : public ExtensionSettingsObserver { |
19 public: | 82 public: |
20 explicit DefaultObserver(Profile* profile) : target_profile_(profile) {} | 83 explicit DefaultObserver(Profile* profile) : target_profile_(profile) {} |
21 virtual ~DefaultObserver() {} | 84 virtual ~DefaultObserver() {} |
22 | 85 |
23 virtual void OnSettingsChanged( | 86 virtual void OnSettingsChanged( |
24 const Profile* origin_profile, | 87 const Profile* origin_profile, |
25 const std::string& extension_id, | 88 const std::string& extension_id, |
26 const ExtensionSettingChanges& changes) OVERRIDE { | 89 const ExtensionSettingChanges& changes) OVERRIDE { |
(...skipping 10 matching lines...) Expand all Loading... |
37 } | 100 } |
38 | 101 |
39 private: | 102 private: |
40 Profile* target_profile_; | 103 Profile* target_profile_; |
41 }; | 104 }; |
42 | 105 |
43 class ExtensionSettingsFrontend::Core | 106 class ExtensionSettingsFrontend::Core |
44 : public base::RefCountedThreadSafe<Core> { | 107 : public base::RefCountedThreadSafe<Core> { |
45 public: | 108 public: |
46 explicit Core( | 109 explicit Core( |
47 const scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> >& | 110 const scoped_refptr<ExtensionSettingsObserverList>& observers) |
48 observers) | 111 : observers_(observers), backends_(NULL) { |
49 : observers_(observers), backend_(NULL) { | |
50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
51 } | 113 } |
52 | 114 |
53 // Does any FILE thread specific initialization, such as construction of | 115 // Does any FILE thread specific initialization, such as construction of |
54 // |backend_|. Must be called before any call to | 116 // |backend_|. Must be called before any call to |
55 // RunWithBackendOnFileThread(). | 117 // RunWithBackendOnFileThread(). |
56 void InitOnFileThread(const FilePath& base_path) { | 118 void InitOnFileThread(const FilePath& profile_path) { |
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
58 DCHECK(!backend_); | 120 DCHECK(!backends_); |
59 backend_ = new ExtensionSettingsBackend(base_path, observers_); | 121 backends_ = new Backends(observers_, profile_path); |
60 } | 122 } |
61 | 123 |
62 // Runs |callback| with the extension backend. | 124 // Runs |callback| with both the extensions and apps settings on the FILE |
63 void RunWithBackendOnFileThread(const BackendCallback& callback) { | 125 // thread. |
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 126 typedef base::Callback<void(Backends*)> BackendsCallback; |
65 DCHECK(backend_); | 127 void RunWithBackends(const BackendsCallback& callback) { |
66 callback.Run(backend_); | 128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 129 BrowserThread::PostTask( |
| 130 BrowserThread::FILE, |
| 131 FROM_HERE, |
| 132 base::Bind( |
| 133 &ExtensionSettingsFrontend::Core::RunWithBackendsOnFileThread, |
| 134 this, |
| 135 callback)); |
67 } | 136 } |
68 | 137 |
69 private: | 138 private: |
| 139 void RunWithBackendsOnFileThread(const BackendsCallback& callback) { |
| 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 141 DCHECK(backends_); |
| 142 callback.Run(backends_); |
| 143 } |
| 144 |
70 virtual ~Core() { | 145 virtual ~Core() { |
71 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | 146 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) { |
72 delete backend_; | 147 delete backends_; |
73 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 148 } else if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
74 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backend_); | 149 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, backends_); |
75 } else { | 150 } else { |
76 NOTREACHED(); | 151 NOTREACHED(); |
77 } | 152 } |
78 } | 153 } |
79 | 154 |
80 friend class base::RefCountedThreadSafe<Core>; | 155 friend class base::RefCountedThreadSafe<Core>; |
81 | 156 |
82 // Observers to settings changes (thread safe). | 157 // Observers to settings changes (thread safe). |
83 scoped_refptr<ObserverListThreadSafe<ExtensionSettingsObserver> > | 158 scoped_refptr<ExtensionSettingsObserverList> observers_; |
84 observers_; | |
85 | 159 |
86 // Lives on the FILE thread. | 160 // Backends for extensions and apps settings. Lives on FILE thread. |
87 ExtensionSettingsBackend* backend_; | 161 Backends* backends_; |
88 | 162 |
89 DISALLOW_COPY_AND_ASSIGN(Core); | 163 DISALLOW_COPY_AND_ASSIGN(Core); |
90 }; | 164 }; |
91 | 165 |
92 ExtensionSettingsFrontend::ExtensionSettingsFrontend(Profile* profile) | 166 ExtensionSettingsFrontend::ExtensionSettingsFrontend(Profile* profile) |
93 : profile_(profile), | 167 : profile_(profile), |
94 observers_(new ObserverListThreadSafe<ExtensionSettingsObserver>()), | 168 observers_(new ExtensionSettingsObserverList()), |
95 core_(new ExtensionSettingsFrontend::Core(observers_.get())) { | 169 core_(new ExtensionSettingsFrontend::Core(observers_)) { |
96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
97 DCHECK(!profile->IsOffTheRecord()); | 171 DCHECK(!profile->IsOffTheRecord()); |
98 | 172 |
99 // This class listens to all PROFILE_{CREATED,DESTROYED} events but we're | 173 // This class listens to all PROFILE_{CREATED,DESTROYED} events but we're |
100 // only interested in those for the original Profile given on construction | 174 // only interested in those for the original Profile given on construction |
101 // and its incognito version. | 175 // and its incognito version. |
102 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | 176 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, |
103 content::NotificationService::AllBrowserContextsAndSources()); | 177 content::NotificationService::AllBrowserContextsAndSources()); |
104 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 178 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
105 content::NotificationService::AllBrowserContextsAndSources()); | 179 content::NotificationService::AllBrowserContextsAndSources()); |
106 OnProfileCreated(profile); | 180 OnProfileCreated(profile); |
107 | 181 |
108 BrowserThread::PostTask( | 182 BrowserThread::PostTask( |
109 BrowserThread::FILE, | 183 BrowserThread::FILE, |
110 FROM_HERE, | 184 FROM_HERE, |
111 base::Bind( | 185 base::Bind( |
112 &ExtensionSettingsFrontend::Core::InitOnFileThread, | 186 &ExtensionSettingsFrontend::Core::InitOnFileThread, |
113 core_.get(), | 187 core_.get(), |
114 profile->GetPath().AppendASCII( | 188 profile->GetPath())); |
115 ExtensionService::kSettingsDirectoryName))); | |
116 } | 189 } |
117 | 190 |
118 ExtensionSettingsFrontend::~ExtensionSettingsFrontend() { | 191 ExtensionSettingsFrontend::~ExtensionSettingsFrontend() { |
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
120 } | 193 } |
121 | 194 |
122 void ExtensionSettingsFrontend::RunWithBackend( | 195 void ExtensionSettingsFrontend::RunWithSyncableService( |
123 const BackendCallback& callback) { | 196 syncable::ModelType model_type, const SyncableServiceCallback& callback) { |
124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
125 BrowserThread::PostTask( | 198 switch (model_type) { |
126 BrowserThread::FILE, | 199 case syncable::EXTENSION_SETTINGS: |
127 FROM_HERE, | 200 core_->RunWithBackends( |
128 base::Bind( | 201 base::Bind(&CallbackWithExtensionsBackend, callback)); |
129 &ExtensionSettingsFrontend::Core::RunWithBackendOnFileThread, | 202 break; |
130 core_.get(), | 203 case syncable::APP_SETTINGS: |
131 callback)); | 204 core_->RunWithBackends( |
| 205 base::Bind(&CallbackWithAppsBackend, callback)); |
| 206 break; |
| 207 default: |
| 208 NOTREACHED(); |
| 209 } |
132 } | 210 } |
133 | 211 |
134 void ExtensionSettingsFrontend::AddObserver( | 212 void ExtensionSettingsFrontend::RunWithStorage( |
135 ExtensionSettingsObserver* observer) { | 213 const std::string& extension_id, |
136 observers_->AddObserver(observer); | 214 const StorageCallback& callback) { |
| 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 216 |
| 217 const Extension* extension = |
| 218 profile_->GetExtensionService()->GetExtensionById(extension_id, true); |
| 219 if (extension) { |
| 220 if (extension->is_app()) { |
| 221 core_->RunWithBackends( |
| 222 base::Bind(&CallbackWithAppsStorage, extension_id, callback)); |
| 223 } else { |
| 224 core_->RunWithBackends( |
| 225 base::Bind(&CallbackWithExtensionsStorage, extension_id, callback)); |
| 226 } |
| 227 } else { |
| 228 BrowserThread::PostTask( |
| 229 BrowserThread::FILE, |
| 230 FROM_HERE, |
| 231 base::Bind(&CallbackWithNullStorage, callback)); |
| 232 } |
137 } | 233 } |
138 | 234 |
139 void ExtensionSettingsFrontend::RemoveObserver( | 235 void ExtensionSettingsFrontend::DeleteStorageSoon( |
140 ExtensionSettingsObserver* observer) { | 236 const std::string& extension_id) { |
141 observers_->RemoveObserver(observer); | 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 238 core_->RunWithBackends(base::Bind(&DeleteStorageOnFileThread, extension_id)); |
| 239 } |
| 240 |
| 241 scoped_refptr<ExtensionSettingsObserverList> |
| 242 ExtensionSettingsFrontend::GetObservers() { |
| 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 244 return observers_; |
142 } | 245 } |
143 | 246 |
144 void ExtensionSettingsFrontend::Observe( | 247 void ExtensionSettingsFrontend::Observe( |
145 int type, | 248 int type, |
146 const content::NotificationSource& source, | 249 const content::NotificationSource& source, |
147 const content::NotificationDetails& details) { | 250 const content::NotificationDetails& details) { |
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
149 switch (type) { | 252 switch (type) { |
150 case chrome::NOTIFICATION_PROFILE_CREATED: | 253 case chrome::NOTIFICATION_PROFILE_CREATED: |
151 OnProfileCreated(content::Source<Profile>(source).ptr()); | 254 OnProfileCreated(content::Source<Profile>(source).ptr()); |
(...skipping 25 matching lines...) Expand all Loading... |
177 } else if (old_profile->GetOriginalProfile() == profile_) { | 280 } else if (old_profile->GetOriginalProfile() == profile_) { |
178 DCHECK(old_profile->IsOffTheRecord()); | 281 DCHECK(old_profile->IsOffTheRecord()); |
179 ClearDefaultObserver(&incognito_profile_observer_); | 282 ClearDefaultObserver(&incognito_profile_observer_); |
180 } | 283 } |
181 } | 284 } |
182 | 285 |
183 void ExtensionSettingsFrontend::SetDefaultObserver( | 286 void ExtensionSettingsFrontend::SetDefaultObserver( |
184 Profile* profile, scoped_ptr<DefaultObserver>* observer) { | 287 Profile* profile, scoped_ptr<DefaultObserver>* observer) { |
185 DCHECK(!observer->get()); | 288 DCHECK(!observer->get()); |
186 observer->reset(new DefaultObserver(profile)); | 289 observer->reset(new DefaultObserver(profile)); |
187 AddObserver(observer->get()); | 290 observers_->AddObserver(observer->get()); |
188 } | 291 } |
189 | 292 |
190 void ExtensionSettingsFrontend::ClearDefaultObserver( | 293 void ExtensionSettingsFrontend::ClearDefaultObserver( |
191 scoped_ptr<DefaultObserver>* observer) { | 294 scoped_ptr<DefaultObserver>* observer) { |
192 if (observer->get()) { | 295 if (observer->get()) { |
193 RemoveObserver(observer->get()); | 296 observers_->RemoveObserver(observer->get()); |
194 observer->reset(); | 297 observer->reset(); |
195 } | 298 } |
196 } | 299 } |
OLD | NEW |