OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/extensions_service.h" | 5 #include "chrome/browser/extensions/extension_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/stl_util-inl.h" | 13 #include "base/stl_util-inl.h" |
14 #include "base/string16.h" | 14 #include "base/string16.h" |
15 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 PendingExtensionInfo::PendingExtensionInfo() | 163 PendingExtensionInfo::PendingExtensionInfo() |
164 : update_url(), | 164 : update_url(), |
165 expected_crx_type(PendingExtensionInfo::UNKNOWN), | 165 expected_crx_type(PendingExtensionInfo::UNKNOWN), |
166 is_from_sync(true), | 166 is_from_sync(true), |
167 install_silently(false), | 167 install_silently(false), |
168 enable_on_install(false), | 168 enable_on_install(false), |
169 enable_incognito_on_install(false), | 169 enable_incognito_on_install(false), |
170 install_source(Extension::INVALID) {} | 170 install_source(Extension::INVALID) {} |
171 | 171 |
172 | 172 |
173 ExtensionsService::ExtensionRuntimeData::ExtensionRuntimeData() | 173 ExtensionService::ExtensionRuntimeData::ExtensionRuntimeData() |
174 : background_page_ready(false), | 174 : background_page_ready(false), |
175 being_upgraded(false) { | 175 being_upgraded(false) { |
176 } | 176 } |
177 | 177 |
178 ExtensionsService::ExtensionRuntimeData::~ExtensionRuntimeData() { | 178 ExtensionService::ExtensionRuntimeData::~ExtensionRuntimeData() { |
179 } | 179 } |
180 | 180 |
181 // ExtensionsService. | 181 // ExtensionService. |
182 | 182 |
183 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; | 183 const char* ExtensionService::kInstallDirectoryName = "Extensions"; |
184 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; | 184 const char* ExtensionService::kCurrentVersionFileName = "Current Version"; |
185 | 185 |
186 // Implements IO for the ExtensionsService. | 186 // Implements IO for the ExtensionService. |
187 | 187 |
188 class ExtensionsServiceBackend | 188 class ExtensionServiceBackend |
189 : public base::RefCountedThreadSafe<ExtensionsServiceBackend>, | 189 : public base::RefCountedThreadSafe<ExtensionServiceBackend>, |
190 public ExternalExtensionProvider::Visitor { | 190 public ExternalExtensionProvider::Visitor { |
191 public: | 191 public: |
192 // |install_directory| is a path where to look for extensions to load. | 192 // |install_directory| is a path where to look for extensions to load. |
193 ExtensionsServiceBackend(PrefService* prefs, | 193 ExtensionServiceBackend(PrefService* prefs, |
194 const FilePath& install_directory); | 194 const FilePath& install_directory); |
195 | 195 |
196 // Loads a single extension from |path| where |path| is the top directory of | 196 // Loads a single extension from |path| where |path| is the top directory of |
197 // a specific extension where its manifest file lives. | 197 // a specific extension where its manifest file lives. |
198 // Errors are reported through ExtensionErrorReporter. On success, | 198 // Errors are reported through ExtensionErrorReporter. On success, |
199 // OnExtensionLoaded() is called. | 199 // OnExtensionLoaded() is called. |
200 // TODO(erikkay): It might be useful to be able to load a packed extension | 200 // TODO(erikkay): It might be useful to be able to load a packed extension |
201 // (presumably into memory) without installing it. | 201 // (presumably into memory) without installing it. |
202 void LoadSingleExtension(const FilePath &path, | 202 void LoadSingleExtension(const FilePath &path, |
203 scoped_refptr<ExtensionsService> frontend); | 203 scoped_refptr<ExtensionService> frontend); |
204 | 204 |
205 // Check externally updated extensions for updates and install if necessary. | 205 // Check externally updated extensions for updates and install if necessary. |
206 // Errors are reported through ExtensionErrorReporter. Succcess is not | 206 // Errors are reported through ExtensionErrorReporter. Succcess is not |
207 // reported. | 207 // reported. |
208 void CheckForExternalUpdates(scoped_refptr<ExtensionsService> frontend); | 208 void CheckForExternalUpdates(scoped_refptr<ExtensionService> frontend); |
209 | 209 |
210 // For the extension in |version_path| with |id|, check to see if it's an | 210 // For the extension in |version_path| with |id|, check to see if it's an |
211 // externally managed extension. If so, tell the frontend to uninstall it. | 211 // externally managed extension. If so, tell the frontend to uninstall it. |
212 void CheckExternalUninstall(scoped_refptr<ExtensionsService> frontend, | 212 void CheckExternalUninstall(scoped_refptr<ExtensionService> frontend, |
213 const std::string& id); | 213 const std::string& id); |
214 | 214 |
215 // Clear all ExternalExtensionProviders. | 215 // Clear all ExternalExtensionProviders. |
216 void ClearProvidersForTesting(); | 216 void ClearProvidersForTesting(); |
217 | 217 |
218 // Adds an ExternalExtensionProvider for the service to use during testing. | 218 // Adds an ExternalExtensionProvider for the service to use during testing. |
219 // Takes ownership of |test_provider|. | 219 // Takes ownership of |test_provider|. |
220 void AddProviderForTesting(ExternalExtensionProvider* test_provider); | 220 void AddProviderForTesting(ExternalExtensionProvider* test_provider); |
221 | 221 |
222 // ExternalExtensionProvider::Visitor implementation. | 222 // ExternalExtensionProvider::Visitor implementation. |
223 virtual void OnExternalExtensionFileFound(const std::string& id, | 223 virtual void OnExternalExtensionFileFound(const std::string& id, |
224 const Version* version, | 224 const Version* version, |
225 const FilePath& path, | 225 const FilePath& path, |
226 Extension::Location location); | 226 Extension::Location location); |
227 | 227 |
228 virtual void OnExternalExtensionUpdateUrlFound(const std::string& id, | 228 virtual void OnExternalExtensionUpdateUrlFound(const std::string& id, |
229 const GURL& update_url, | 229 const GURL& update_url, |
230 Extension::Location location); | 230 Extension::Location location); |
231 | 231 |
232 virtual void UpdateExternalPolicyExtensionProvider( | 232 virtual void UpdateExternalPolicyExtensionProvider( |
233 scoped_refptr<RefCountedList> forcelist); | 233 scoped_refptr<RefCountedList> forcelist); |
234 | 234 |
235 private: | 235 private: |
236 friend class base::RefCountedThreadSafe<ExtensionsServiceBackend>; | 236 friend class base::RefCountedThreadSafe<ExtensionServiceBackend>; |
237 | 237 |
238 virtual ~ExtensionsServiceBackend(); | 238 virtual ~ExtensionServiceBackend(); |
239 | 239 |
240 // Finish installing the extension in |crx_path| after it has been unpacked to | 240 // Finish installing the extension in |crx_path| after it has been unpacked to |
241 // |unpacked_path|. If |expected_id| is not empty, it's verified against the | 241 // |unpacked_path|. If |expected_id| is not empty, it's verified against the |
242 // extension's manifest before installation. If |silent| is true, there will | 242 // extension's manifest before installation. If |silent| is true, there will |
243 // be no install confirmation dialog. |from_gallery| indicates whether the | 243 // be no install confirmation dialog. |from_gallery| indicates whether the |
244 // crx was installed from our gallery, which results in different UI. | 244 // crx was installed from our gallery, which results in different UI. |
245 // | 245 // |
246 // Note: We take ownership of |extension|. | 246 // Note: We take ownership of |extension|. |
247 void OnExtensionUnpacked(const FilePath& crx_path, | 247 void OnExtensionUnpacked(const FilePath& crx_path, |
248 const FilePath& unpacked_path, | 248 const FilePath& unpacked_path, |
249 const Extension* extension, | 249 const Extension* extension, |
250 const std::string expected_id); | 250 const std::string expected_id); |
251 | 251 |
252 // Notify the frontend that there was an error loading an extension. | 252 // Notify the frontend that there was an error loading an extension. |
253 void ReportExtensionLoadError(const FilePath& extension_path, | 253 void ReportExtensionLoadError(const FilePath& extension_path, |
254 const std::string& error); | 254 const std::string& error); |
255 | 255 |
256 // This is a naked pointer which is set by each entry point. | 256 // This is a naked pointer which is set by each entry point. |
257 // The entry point is responsible for ensuring lifetime. | 257 // The entry point is responsible for ensuring lifetime. |
258 ExtensionsService* frontend_; | 258 ExtensionService* frontend_; |
259 | 259 |
260 // The top-level extensions directory being installed to. | 260 // The top-level extensions directory being installed to. |
261 FilePath install_directory_; | 261 FilePath install_directory_; |
262 | 262 |
263 // Whether errors result in noisy alerts. | 263 // Whether errors result in noisy alerts. |
264 bool alert_on_error_; | 264 bool alert_on_error_; |
265 | 265 |
266 // A collection of external extension providers. Each provider reads | 266 // A collection of external extension providers. Each provider reads |
267 // a source of external extension information. Examples include the | 267 // a source of external extension information. Examples include the |
268 // windows registry and external_extensions.json. | 268 // windows registry and external_extensions.json. |
269 typedef std::vector<linked_ptr<ExternalExtensionProvider> > | 269 typedef std::vector<linked_ptr<ExternalExtensionProvider> > |
270 ProviderCollection; | 270 ProviderCollection; |
271 ProviderCollection external_extension_providers_; | 271 ProviderCollection external_extension_providers_; |
272 linked_ptr<ExternalPolicyExtensionProvider> | 272 linked_ptr<ExternalPolicyExtensionProvider> |
273 external_policy_extension_provider_; | 273 external_policy_extension_provider_; |
274 | 274 |
275 // Set to true by OnExternalExtensionUpdateUrlFound() when an external | 275 // Set to true by OnExternalExtensionUpdateUrlFound() when an external |
276 // extension URL is found. Used in CheckForExternalUpdates() to see | 276 // extension URL is found. Used in CheckForExternalUpdates() to see |
277 // if an update check is needed to install pending extensions. | 277 // if an update check is needed to install pending extensions. |
278 bool external_extension_added_; | 278 bool external_extension_added_; |
279 | 279 |
280 DISALLOW_COPY_AND_ASSIGN(ExtensionsServiceBackend); | 280 DISALLOW_COPY_AND_ASSIGN(ExtensionServiceBackend); |
281 }; | 281 }; |
282 | 282 |
283 ExtensionsServiceBackend::ExtensionsServiceBackend( | 283 ExtensionServiceBackend::ExtensionServiceBackend( |
284 PrefService* prefs, | 284 PrefService* prefs, |
285 const FilePath& install_directory) | 285 const FilePath& install_directory) |
286 : frontend_(NULL), | 286 : frontend_(NULL), |
287 install_directory_(install_directory), | 287 install_directory_(install_directory), |
288 alert_on_error_(false), | 288 alert_on_error_(false), |
289 external_extension_added_(false) { | 289 external_extension_added_(false) { |
290 // TODO(aa): This ends up doing blocking IO on the UI thread because it reads | 290 // TODO(aa): This ends up doing blocking IO on the UI thread because it reads |
291 // pref data in the ctor and that is called on the UI thread. Would be better | 291 // pref data in the ctor and that is called on the UI thread. Would be better |
292 // to re-read data each time we list external extensions, anyway. | 292 // to re-read data each time we list external extensions, anyway. |
293 external_extension_providers_.push_back( | 293 external_extension_providers_.push_back( |
294 linked_ptr<ExternalExtensionProvider>( | 294 linked_ptr<ExternalExtensionProvider>( |
295 new ExternalPrefExtensionProvider())); | 295 new ExternalPrefExtensionProvider())); |
296 #if defined(OS_WIN) | 296 #if defined(OS_WIN) |
297 external_extension_providers_.push_back( | 297 external_extension_providers_.push_back( |
298 linked_ptr<ExternalExtensionProvider>( | 298 linked_ptr<ExternalExtensionProvider>( |
299 new ExternalRegistryExtensionProvider())); | 299 new ExternalRegistryExtensionProvider())); |
300 #endif | 300 #endif |
301 // The policy-controlled extension provider is also stored in a member | 301 // The policy-controlled extension provider is also stored in a member |
302 // variable so that UpdateExternalPolicyExtensionProvider can access it and | 302 // variable so that UpdateExternalPolicyExtensionProvider can access it and |
303 // update its extension list later. | 303 // update its extension list later. |
304 external_policy_extension_provider_.reset( | 304 external_policy_extension_provider_.reset( |
305 new ExternalPolicyExtensionProvider()); | 305 new ExternalPolicyExtensionProvider()); |
306 external_policy_extension_provider_->SetPreferences( | 306 external_policy_extension_provider_->SetPreferences( |
307 prefs->GetList(prefs::kExtensionInstallForceList)); | 307 prefs->GetList(prefs::kExtensionInstallForceList)); |
308 external_extension_providers_.push_back(external_policy_extension_provider_); | 308 external_extension_providers_.push_back(external_policy_extension_provider_); |
309 } | 309 } |
310 | 310 |
311 ExtensionsServiceBackend::~ExtensionsServiceBackend() { | 311 ExtensionServiceBackend::~ExtensionServiceBackend() { |
312 } | 312 } |
313 | 313 |
314 void ExtensionsServiceBackend::LoadSingleExtension( | 314 void ExtensionServiceBackend::LoadSingleExtension( |
315 const FilePath& path_in, scoped_refptr<ExtensionsService> frontend) { | 315 const FilePath& path_in, scoped_refptr<ExtensionService> frontend) { |
316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
317 | 317 |
318 frontend_ = frontend; | 318 frontend_ = frontend; |
319 | 319 |
320 // Explicit UI loads are always noisy. | 320 // Explicit UI loads are always noisy. |
321 alert_on_error_ = true; | 321 alert_on_error_ = true; |
322 | 322 |
323 FilePath extension_path = path_in; | 323 FilePath extension_path = path_in; |
324 file_util::AbsolutePath(&extension_path); | 324 file_util::AbsolutePath(&extension_path); |
325 | 325 |
326 std::string error; | 326 std::string error; |
327 scoped_refptr<const Extension> extension(extension_file_util::LoadExtension( | 327 scoped_refptr<const Extension> extension(extension_file_util::LoadExtension( |
328 extension_path, | 328 extension_path, |
329 Extension::LOAD, | 329 Extension::LOAD, |
330 false, // Don't require id | 330 false, // Don't require id |
331 &error)); | 331 &error)); |
332 | 332 |
333 if (!extension) { | 333 if (!extension) { |
334 ReportExtensionLoadError(extension_path, error); | 334 ReportExtensionLoadError(extension_path, error); |
335 return; | 335 return; |
336 } | 336 } |
337 | 337 |
338 // Report this as an installed extension so that it gets remembered in the | 338 // Report this as an installed extension so that it gets remembered in the |
339 // prefs. | 339 // prefs. |
340 BrowserThread::PostTask( | 340 BrowserThread::PostTask( |
341 BrowserThread::UI, FROM_HERE, | 341 BrowserThread::UI, FROM_HERE, |
342 NewRunnableMethod(frontend_, | 342 NewRunnableMethod(frontend_, |
343 &ExtensionsService::OnExtensionInstalled, | 343 &ExtensionService::OnExtensionInstalled, |
344 extension)); | 344 extension)); |
345 } | 345 } |
346 | 346 |
347 void ExtensionsServiceBackend::ReportExtensionLoadError( | 347 void ExtensionServiceBackend::ReportExtensionLoadError( |
348 const FilePath& extension_path, const std::string &error) { | 348 const FilePath& extension_path, const std::string &error) { |
349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
350 BrowserThread::PostTask( | 350 BrowserThread::PostTask( |
351 BrowserThread::UI, FROM_HERE, | 351 BrowserThread::UI, FROM_HERE, |
352 NewRunnableMethod( | 352 NewRunnableMethod( |
353 frontend_, | 353 frontend_, |
354 &ExtensionsService::ReportExtensionLoadError, extension_path, | 354 &ExtensionService::ReportExtensionLoadError, extension_path, |
355 error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_)); | 355 error, NotificationType::EXTENSION_INSTALL_ERROR, alert_on_error_)); |
356 } | 356 } |
357 | 357 |
358 // Some extensions will autoupdate themselves externally from Chrome. These | 358 // Some extensions will autoupdate themselves externally from Chrome. These |
359 // are typically part of some larger client application package. To support | 359 // are typically part of some larger client application package. To support |
360 // these, the extension will register its location in the the preferences file | 360 // these, the extension will register its location in the the preferences file |
361 // (and also, on Windows, in the registry) and this code will periodically | 361 // (and also, on Windows, in the registry) and this code will periodically |
362 // check that location for a .crx file, which it will then install locally if | 362 // check that location for a .crx file, which it will then install locally if |
363 // a new version is available. | 363 // a new version is available. |
364 void ExtensionsServiceBackend::CheckForExternalUpdates( | 364 void ExtensionServiceBackend::CheckForExternalUpdates( |
365 scoped_refptr<ExtensionsService> frontend) { | 365 scoped_refptr<ExtensionService> frontend) { |
366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
367 | 367 |
368 // Note that this installation is intentionally silent (since it didn't | 368 // Note that this installation is intentionally silent (since it didn't |
369 // go through the front-end). Extensions that are registered in this | 369 // go through the front-end). Extensions that are registered in this |
370 // way are effectively considered 'pre-bundled', and so implicitly | 370 // way are effectively considered 'pre-bundled', and so implicitly |
371 // trusted. In general, if something has HKLM or filesystem access, | 371 // trusted. In general, if something has HKLM or filesystem access, |
372 // they could install an extension manually themselves anyway. | 372 // they could install an extension manually themselves anyway. |
373 alert_on_error_ = false; | 373 alert_on_error_ = false; |
374 frontend_ = frontend; | 374 frontend_ = frontend; |
375 external_extension_added_ = false; | 375 external_extension_added_ = false; |
376 | 376 |
377 // Ask each external extension provider to give us a call back for each | 377 // Ask each external extension provider to give us a call back for each |
378 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. | 378 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found. |
379 ProviderCollection::const_iterator i; | 379 ProviderCollection::const_iterator i; |
380 for (i = external_extension_providers_.begin(); | 380 for (i = external_extension_providers_.begin(); |
381 i != external_extension_providers_.end(); ++i) { | 381 i != external_extension_providers_.end(); ++i) { |
382 ExternalExtensionProvider* provider = i->get(); | 382 ExternalExtensionProvider* provider = i->get(); |
383 provider->VisitRegisteredExtension(this); | 383 provider->VisitRegisteredExtension(this); |
384 } | 384 } |
385 | 385 |
386 if (external_extension_added_ && frontend->updater()) { | 386 if (external_extension_added_ && frontend->updater()) { |
387 BrowserThread::PostTask( | 387 BrowserThread::PostTask( |
388 BrowserThread::UI, FROM_HERE, | 388 BrowserThread::UI, FROM_HERE, |
389 NewRunnableMethod( | 389 NewRunnableMethod( |
390 frontend->updater(), &ExtensionUpdater::CheckNow)); | 390 frontend->updater(), &ExtensionUpdater::CheckNow)); |
391 } | 391 } |
392 } | 392 } |
393 | 393 |
394 void ExtensionsServiceBackend::CheckExternalUninstall( | 394 void ExtensionServiceBackend::CheckExternalUninstall( |
395 scoped_refptr<ExtensionsService> frontend, const std::string& id) { | 395 scoped_refptr<ExtensionService> frontend, const std::string& id) { |
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
397 | 397 |
398 // Check if the providers know about this extension. | 398 // Check if the providers know about this extension. |
399 ProviderCollection::const_iterator i; | 399 ProviderCollection::const_iterator i; |
400 for (i = external_extension_providers_.begin(); | 400 for (i = external_extension_providers_.begin(); |
401 i != external_extension_providers_.end(); ++i) { | 401 i != external_extension_providers_.end(); ++i) { |
402 if (i->get()->HasExtension(id)) | 402 if (i->get()->HasExtension(id)) |
403 return; // Yup, known extension, don't uninstall. | 403 return; // Yup, known extension, don't uninstall. |
404 } | 404 } |
405 | 405 |
406 // This is an external extension that we don't have registered. Uninstall. | 406 // This is an external extension that we don't have registered. Uninstall. |
407 BrowserThread::PostTask( | 407 BrowserThread::PostTask( |
408 BrowserThread::UI, FROM_HERE, | 408 BrowserThread::UI, FROM_HERE, |
409 NewRunnableMethod( | 409 NewRunnableMethod( |
410 frontend.get(), &ExtensionsService::UninstallExtension, id, true)); | 410 frontend.get(), &ExtensionService::UninstallExtension, id, true)); |
411 } | 411 } |
412 | 412 |
413 void ExtensionsServiceBackend::UpdateExternalPolicyExtensionProvider( | 413 void ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider( |
414 scoped_refptr<RefCountedList> forcelist) { | 414 scoped_refptr<RefCountedList> forcelist) { |
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
416 external_policy_extension_provider_->SetPreferences(forcelist->Get()); | 416 external_policy_extension_provider_->SetPreferences(forcelist->Get()); |
417 } | 417 } |
418 | 418 |
419 void ExtensionsServiceBackend::ClearProvidersForTesting() { | 419 void ExtensionServiceBackend::ClearProvidersForTesting() { |
420 external_extension_providers_.clear(); | 420 external_extension_providers_.clear(); |
421 } | 421 } |
422 | 422 |
423 void ExtensionsServiceBackend::AddProviderForTesting( | 423 void ExtensionServiceBackend::AddProviderForTesting( |
424 ExternalExtensionProvider* test_provider) { | 424 ExternalExtensionProvider* test_provider) { |
425 DCHECK(test_provider); | 425 DCHECK(test_provider); |
426 external_extension_providers_.push_back( | 426 external_extension_providers_.push_back( |
427 linked_ptr<ExternalExtensionProvider>(test_provider)); | 427 linked_ptr<ExternalExtensionProvider>(test_provider)); |
428 } | 428 } |
429 | 429 |
430 void ExtensionsServiceBackend::OnExternalExtensionFileFound( | 430 void ExtensionServiceBackend::OnExternalExtensionFileFound( |
431 const std::string& id, const Version* version, const FilePath& path, | 431 const std::string& id, const Version* version, const FilePath& path, |
432 Extension::Location location) { | 432 Extension::Location location) { |
433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
434 | 434 |
435 DCHECK(version); | 435 DCHECK(version); |
436 BrowserThread::PostTask( | 436 BrowserThread::PostTask( |
437 BrowserThread::UI, FROM_HERE, | 437 BrowserThread::UI, FROM_HERE, |
438 NewRunnableMethod( | 438 NewRunnableMethod( |
439 frontend_, &ExtensionsService::OnExternalExtensionFileFound, id, | 439 frontend_, &ExtensionService::OnExternalExtensionFileFound, id, |
440 version->GetString(), path, location)); | 440 version->GetString(), path, location)); |
441 } | 441 } |
442 | 442 |
443 void ExtensionsServiceBackend::OnExternalExtensionUpdateUrlFound( | 443 void ExtensionServiceBackend::OnExternalExtensionUpdateUrlFound( |
444 const std::string& id, | 444 const std::string& id, |
445 const GURL& update_url, | 445 const GURL& update_url, |
446 Extension::Location location) { | 446 Extension::Location location) { |
447 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 447 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
448 | 448 |
449 if (frontend_->GetExtensionById(id, true)) { | 449 if (frontend_->GetExtensionById(id, true)) { |
450 // Already installed. Do not change the update URL that the extension set. | 450 // Already installed. Do not change the update URL that the extension set. |
451 return; | 451 return; |
452 } | 452 } |
453 | 453 |
454 BrowserThread::PostTask( | 454 BrowserThread::PostTask( |
455 BrowserThread::UI, FROM_HERE, | 455 BrowserThread::UI, FROM_HERE, |
456 NewRunnableMethod( | 456 NewRunnableMethod( |
457 frontend_, | 457 frontend_, |
458 &ExtensionsService::AddPendingExtensionFromExternalUpdateUrl, | 458 &ExtensionService::AddPendingExtensionFromExternalUpdateUrl, |
459 id, update_url, location)); | 459 id, update_url, location)); |
460 external_extension_added_ |= true; | 460 external_extension_added_ |= true; |
461 } | 461 } |
462 | 462 |
463 bool ExtensionsService::IsDownloadFromGallery(const GURL& download_url, | 463 bool ExtensionService::IsDownloadFromGallery(const GURL& download_url, |
464 const GURL& referrer_url) { | 464 const GURL& referrer_url) { |
465 // Special-case the themes mini-gallery. | 465 // Special-case the themes mini-gallery. |
466 // TODO(erikkay) When that gallery goes away, remove this code. | 466 // TODO(erikkay) When that gallery goes away, remove this code. |
467 if (IsDownloadFromMiniGallery(download_url) && | 467 if (IsDownloadFromMiniGallery(download_url) && |
468 StartsWithASCII(referrer_url.spec(), | 468 StartsWithASCII(referrer_url.spec(), |
469 extension_urls::kMiniGalleryBrowsePrefix, false)) { | 469 extension_urls::kMiniGalleryBrowsePrefix, false)) { |
470 return true; | 470 return true; |
471 } | 471 } |
472 | 472 |
473 const Extension* download_extension = GetExtensionByWebExtent(download_url); | 473 const Extension* download_extension = GetExtensionByWebExtent(download_url); |
(...skipping 28 matching lines...) Expand all Loading... |
502 GURL(download_url)); | 502 GURL(download_url)); |
503 | 503 |
504 // Otherwise, the TLD must match the TLD of the command-line url. | 504 // Otherwise, the TLD must match the TLD of the command-line url. |
505 download_valid = (download_tld == store_tld); | 505 download_valid = (download_tld == store_tld); |
506 } | 506 } |
507 } | 507 } |
508 | 508 |
509 return (referrer_valid && download_valid); | 509 return (referrer_valid && download_valid); |
510 } | 510 } |
511 | 511 |
512 bool ExtensionsService::IsDownloadFromMiniGallery(const GURL& download_url) { | 512 bool ExtensionService::IsDownloadFromMiniGallery(const GURL& download_url) { |
513 return StartsWithASCII(download_url.spec(), | 513 return StartsWithASCII(download_url.spec(), |
514 extension_urls::kMiniGalleryDownloadPrefix, | 514 extension_urls::kMiniGalleryDownloadPrefix, |
515 false); // case_sensitive | 515 false); // case_sensitive |
516 } | 516 } |
517 | 517 |
518 bool ExtensionsService::IsInstalledApp(const GURL& url) { | 518 bool ExtensionService::IsInstalledApp(const GURL& url) { |
519 // Check for hosted app. | 519 // Check for hosted app. |
520 if (GetExtensionByWebExtent(url) != NULL) | 520 if (GetExtensionByWebExtent(url) != NULL) |
521 return true; | 521 return true; |
522 | 522 |
523 // Check for packaged app. | 523 // Check for packaged app. |
524 const Extension* extension = GetExtensionByURL(url); | 524 const Extension* extension = GetExtensionByURL(url); |
525 return extension != NULL && extension->is_app(); | 525 return extension != NULL && extension->is_app(); |
526 } | 526 } |
527 | 527 |
528 // static | 528 // static |
529 bool ExtensionsService::UninstallExtensionHelper( | 529 bool ExtensionService::UninstallExtensionHelper( |
530 ExtensionsService* extensions_service, | 530 ExtensionService* extensions_service, |
531 const std::string& extension_id) { | 531 const std::string& extension_id) { |
532 DCHECK(extensions_service); | 532 DCHECK(extensions_service); |
533 | 533 |
534 // We can't call UninstallExtension with an invalid extension ID, so check it | 534 // We can't call UninstallExtension with an invalid extension ID, so check it |
535 // first. | 535 // first. |
536 if (extensions_service->GetExtensionById(extension_id, true)) { | 536 if (extensions_service->GetExtensionById(extension_id, true)) { |
537 extensions_service->UninstallExtension(extension_id, false); | 537 extensions_service->UninstallExtension(extension_id, false); |
538 } else { | 538 } else { |
539 LOG(WARNING) << "Attempted uninstallation of non-existent extension with " | 539 LOG(WARNING) << "Attempted uninstallation of non-existent extension with " |
540 << "id: " << extension_id; | 540 << "id: " << extension_id; |
541 return false; | 541 return false; |
542 } | 542 } |
543 | 543 |
544 return true; | 544 return true; |
545 } | 545 } |
546 | 546 |
547 ExtensionsService::ExtensionsService(Profile* profile, | 547 ExtensionService::ExtensionService(Profile* profile, |
548 const CommandLine* command_line, | 548 const CommandLine* command_line, |
549 const FilePath& install_directory, | 549 const FilePath& install_directory, |
550 ExtensionPrefs* extension_prefs, | 550 ExtensionPrefs* extension_prefs, |
551 bool autoupdate_enabled) | 551 bool autoupdate_enabled) |
552 : profile_(profile), | 552 : profile_(profile), |
553 extension_prefs_(extension_prefs), | 553 extension_prefs_(extension_prefs), |
554 install_directory_(install_directory), | 554 install_directory_(install_directory), |
555 extensions_enabled_(true), | 555 extensions_enabled_(true), |
556 show_extensions_prompts_(true), | 556 show_extensions_prompts_(true), |
557 ready_(false), | 557 ready_(false), |
(...skipping 22 matching lines...) Expand all Loading... |
580 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { | 580 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) { |
581 base::StringToInt(command_line->GetSwitchValueASCII( | 581 base::StringToInt(command_line->GetSwitchValueASCII( |
582 switches::kExtensionsUpdateFrequency), | 582 switches::kExtensionsUpdateFrequency), |
583 &update_frequency); | 583 &update_frequency); |
584 } | 584 } |
585 updater_ = new ExtensionUpdater(this, | 585 updater_ = new ExtensionUpdater(this, |
586 profile->GetPrefs(), | 586 profile->GetPrefs(), |
587 update_frequency); | 587 update_frequency); |
588 } | 588 } |
589 | 589 |
590 backend_ = new ExtensionsServiceBackend(profile->GetPrefs(), | 590 backend_ = new ExtensionServiceBackend(profile->GetPrefs(), |
591 install_directory_); | 591 install_directory_); |
592 | 592 |
593 // Use monochrome icons for Omnibox icons. | 593 // Use monochrome icons for Omnibox icons. |
594 omnibox_popup_icon_manager_.set_monochrome(true); | 594 omnibox_popup_icon_manager_.set_monochrome(true); |
595 omnibox_icon_manager_.set_monochrome(true); | 595 omnibox_icon_manager_.set_monochrome(true); |
596 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, | 596 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, |
597 0, kOmniboxIconPaddingRight)); | 597 0, kOmniboxIconPaddingRight)); |
598 } | 598 } |
599 | 599 |
600 const ExtensionList* ExtensionsService::extensions() const { | 600 const ExtensionList* ExtensionService::extensions() const { |
601 return &extensions_; | 601 return &extensions_; |
602 } | 602 } |
603 | 603 |
604 const ExtensionList* ExtensionsService::disabled_extensions() const { | 604 const ExtensionList* ExtensionService::disabled_extensions() const { |
605 return &disabled_extensions_; | 605 return &disabled_extensions_; |
606 } | 606 } |
607 | 607 |
608 const PendingExtensionMap& ExtensionsService::pending_extensions() const { | 608 const PendingExtensionMap& ExtensionService::pending_extensions() const { |
609 return pending_extensions_; | 609 return pending_extensions_; |
610 } | 610 } |
611 | 611 |
612 bool ExtensionsService::HasInstalledExtensions() { | 612 bool ExtensionService::HasInstalledExtensions() { |
613 return !(extensions_.empty() && disabled_extensions_.empty()); | 613 return !(extensions_.empty() && disabled_extensions_.empty()); |
614 } | 614 } |
615 | 615 |
616 ExtensionsService::~ExtensionsService() { | 616 ExtensionService::~ExtensionService() { |
617 DCHECK(!profile_); // Profile should have told us it's going away. | 617 DCHECK(!profile_); // Profile should have told us it's going away. |
618 UnloadAllExtensions(); | 618 UnloadAllExtensions(); |
619 if (updater_.get()) { | 619 if (updater_.get()) { |
620 updater_->Stop(); | 620 updater_->Stop(); |
621 } | 621 } |
622 } | 622 } |
623 | 623 |
624 void ExtensionsService::InitEventRouters() { | 624 void ExtensionService::InitEventRouters() { |
625 if (event_routers_initialized_) | 625 if (event_routers_initialized_) |
626 return; | 626 return; |
627 | 627 |
628 ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_); | 628 ExtensionHistoryEventRouter::GetInstance()->ObserveProfile(profile_); |
629 ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_); | 629 ExtensionAccessibilityEventRouter::GetInstance()->ObserveProfile(profile_); |
630 ExtensionBrowserEventRouter::GetInstance()->Init(profile_); | 630 ExtensionBrowserEventRouter::GetInstance()->Init(profile_); |
631 ExtensionBookmarkEventRouter::GetInstance()->Observe( | 631 ExtensionBookmarkEventRouter::GetInstance()->Observe( |
632 profile_->GetBookmarkModel()); | 632 profile_->GetBookmarkModel()); |
633 ExtensionCookiesEventRouter::GetInstance()->Init(); | 633 ExtensionCookiesEventRouter::GetInstance()->Init(); |
634 ExtensionManagementEventRouter::GetInstance()->Init(); | 634 ExtensionManagementEventRouter::GetInstance()->Init(); |
635 ExtensionProcessesEventRouter::GetInstance()->ObserveProfile(profile_); | 635 ExtensionProcessesEventRouter::GetInstance()->ObserveProfile(profile_); |
636 ExtensionWebNavigationEventRouter::GetInstance()->Init(); | 636 ExtensionWebNavigationEventRouter::GetInstance()->Init(); |
637 event_routers_initialized_ = true; | 637 event_routers_initialized_ = true; |
638 } | 638 } |
639 | 639 |
640 const Extension* ExtensionsService::GetExtensionById(const std::string& id, | 640 const Extension* ExtensionService::GetExtensionById(const std::string& id, |
641 bool include_disabled) { | 641 bool include_disabled) { |
642 return GetExtensionByIdInternal(id, true, include_disabled); | 642 return GetExtensionByIdInternal(id, true, include_disabled); |
643 } | 643 } |
644 | 644 |
645 void ExtensionsService::Init() { | 645 void ExtensionService::Init() { |
646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
647 | 647 |
648 DCHECK(!ready_); // Can't redo init. | 648 DCHECK(!ready_); // Can't redo init. |
649 DCHECK_EQ(extensions_.size(), 0u); | 649 DCHECK_EQ(extensions_.size(), 0u); |
650 | 650 |
651 // Hack: we need to ensure the ResourceDispatcherHost is ready before we load | 651 // Hack: we need to ensure the ResourceDispatcherHost is ready before we load |
652 // the first extension, because its members listen for loaded notifications. | 652 // the first extension, because its members listen for loaded notifications. |
653 g_browser_process->resource_dispatcher_host(); | 653 g_browser_process->resource_dispatcher_host(); |
654 | 654 |
655 LoadAllExtensions(); | 655 LoadAllExtensions(); |
656 | 656 |
657 // TODO(erikkay) this should probably be deferred to a future point | 657 // TODO(erikkay) this should probably be deferred to a future point |
658 // rather than running immediately at startup. | 658 // rather than running immediately at startup. |
659 CheckForExternalUpdates(); | 659 CheckForExternalUpdates(); |
660 | 660 |
661 // TODO(erikkay) this should probably be deferred as well. | 661 // TODO(erikkay) this should probably be deferred as well. |
662 GarbageCollectExtensions(); | 662 GarbageCollectExtensions(); |
663 } | 663 } |
664 | 664 |
665 void ExtensionsService::InstallExtension(const FilePath& extension_path) { | 665 void ExtensionService::InstallExtension(const FilePath& extension_path) { |
666 scoped_refptr<CrxInstaller> installer( | 666 scoped_refptr<CrxInstaller> installer( |
667 new CrxInstaller(this, // frontend | 667 new CrxInstaller(this, // frontend |
668 NULL)); // no client (silent install) | 668 NULL)); // no client (silent install) |
669 installer->InstallCrx(extension_path); | 669 installer->InstallCrx(extension_path); |
670 } | 670 } |
671 | 671 |
672 namespace { | 672 namespace { |
673 // TODO(akalin): Put this somewhere where both crx_installer.cc and | 673 // TODO(akalin): Put this somewhere where both crx_installer.cc and |
674 // this file can use it. | 674 // this file can use it. |
675 void DeleteFileHelper(const FilePath& path, bool recursive) { | 675 void DeleteFileHelper(const FilePath& path, bool recursive) { |
676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
677 file_util::Delete(path, recursive); | 677 file_util::Delete(path, recursive); |
678 } | 678 } |
679 } // namespace | 679 } // namespace |
680 | 680 |
681 void ExtensionsService::UpdateExtension(const std::string& id, | 681 void ExtensionService::UpdateExtension(const std::string& id, |
682 const FilePath& extension_path, | 682 const FilePath& extension_path, |
683 const GURL& download_url) { | 683 const GURL& download_url) { |
684 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 684 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
685 | 685 |
686 PendingExtensionMap::const_iterator it = pending_extensions_.find(id); | 686 PendingExtensionMap::const_iterator it = pending_extensions_.find(id); |
687 bool is_pending_extension = (it != pending_extensions_.end()); | 687 bool is_pending_extension = (it != pending_extensions_.end()); |
688 | 688 |
689 const Extension* extension = GetExtensionByIdInternal(id, true, true); | 689 const Extension* extension = GetExtensionByIdInternal(id, true, true); |
690 if (!is_pending_extension && !extension) { | 690 if (!is_pending_extension && !extension) { |
691 LOG(WARNING) << "Will not update extension " << id | 691 LOG(WARNING) << "Will not update extension " << id |
(...skipping 18 matching lines...) Expand all Loading... |
710 installer->set_expected_id(id); | 710 installer->set_expected_id(id); |
711 if (is_pending_extension) | 711 if (is_pending_extension) |
712 installer->set_install_source(it->second.install_source); | 712 installer->set_install_source(it->second.install_source); |
713 else if (extension) | 713 else if (extension) |
714 installer->set_install_source(extension->location()); | 714 installer->set_install_source(extension->location()); |
715 installer->set_delete_source(true); | 715 installer->set_delete_source(true); |
716 installer->set_original_url(download_url); | 716 installer->set_original_url(download_url); |
717 installer->InstallCrx(extension_path); | 717 installer->InstallCrx(extension_path); |
718 } | 718 } |
719 | 719 |
720 void ExtensionsService::AddPendingExtensionFromSync( | 720 void ExtensionService::AddPendingExtensionFromSync( |
721 const std::string& id, const GURL& update_url, | 721 const std::string& id, const GURL& update_url, |
722 PendingExtensionInfo::ExpectedCrxType expected_crx_type, | 722 PendingExtensionInfo::ExpectedCrxType expected_crx_type, |
723 bool install_silently, bool enable_on_install, | 723 bool install_silently, bool enable_on_install, |
724 bool enable_incognito_on_install) { | 724 bool enable_incognito_on_install) { |
725 if (GetExtensionByIdInternal(id, true, true)) { | 725 if (GetExtensionByIdInternal(id, true, true)) { |
726 LOG(DFATAL) << "Trying to add pending extension " << id | 726 LOG(DFATAL) << "Trying to add pending extension " << id |
727 << " which already exists"; | 727 << " which already exists"; |
728 return; | 728 return; |
729 } | 729 } |
730 | 730 |
731 AddPendingExtensionInternal(id, update_url, expected_crx_type, true, | 731 AddPendingExtensionInternal(id, update_url, expected_crx_type, true, |
732 install_silently, enable_on_install, | 732 install_silently, enable_on_install, |
733 enable_incognito_on_install, | 733 enable_incognito_on_install, |
734 Extension::INTERNAL); | 734 Extension::INTERNAL); |
735 } | 735 } |
736 | 736 |
737 void ExtensionsService::AddPendingExtensionFromExternalUpdateUrl( | 737 void ExtensionService::AddPendingExtensionFromExternalUpdateUrl( |
738 const std::string& id, const GURL& update_url, | 738 const std::string& id, const GURL& update_url, |
739 Extension::Location location) { | 739 Extension::Location location) { |
740 // Add the extension to this list of extensions to update. | 740 // Add the extension to this list of extensions to update. |
741 const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType = | 741 const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType = |
742 PendingExtensionInfo::UNKNOWN; | 742 PendingExtensionInfo::UNKNOWN; |
743 const bool kIsFromSync = false; | 743 const bool kIsFromSync = false; |
744 const bool kInstallSilently = true; | 744 const bool kInstallSilently = true; |
745 const bool kEnableOnInstall = true; | 745 const bool kEnableOnInstall = true; |
746 const bool kEnableIncognitoOnInstall = false; | 746 const bool kEnableIncognitoOnInstall = false; |
747 if (extension_prefs_->IsExtensionKilled(id)) | 747 if (extension_prefs_->IsExtensionKilled(id)) |
748 return; | 748 return; |
749 | 749 |
750 if (GetExtensionByIdInternal(id, true, true)) { | 750 if (GetExtensionByIdInternal(id, true, true)) { |
751 LOG(DFATAL) << "Trying to add extension " << id | 751 LOG(DFATAL) << "Trying to add extension " << id |
752 << " by external update, but it is already installed."; | 752 << " by external update, but it is already installed."; |
753 return; | 753 return; |
754 } | 754 } |
755 | 755 |
756 AddPendingExtensionInternal(id, update_url, kExpectedCrxType, kIsFromSync, | 756 AddPendingExtensionInternal(id, update_url, kExpectedCrxType, kIsFromSync, |
757 kInstallSilently, kEnableOnInstall, | 757 kInstallSilently, kEnableOnInstall, |
758 kEnableIncognitoOnInstall, | 758 kEnableIncognitoOnInstall, |
759 location); | 759 location); |
760 } | 760 } |
761 | 761 |
762 void ExtensionsService::AddPendingExtensionFromDefaultAppList( | 762 void ExtensionService::AddPendingExtensionFromDefaultAppList( |
763 const std::string& id) { | 763 const std::string& id) { |
764 // Add the extension to this list of extensions to update. | 764 // Add the extension to this list of extensions to update. |
765 const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType = | 765 const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType = |
766 PendingExtensionInfo::APP; | 766 PendingExtensionInfo::APP; |
767 const bool kIsFromSync = false; | 767 const bool kIsFromSync = false; |
768 const bool kInstallSilently = true; | 768 const bool kInstallSilently = true; |
769 const bool kEnableOnInstall = true; | 769 const bool kEnableOnInstall = true; |
770 const bool kEnableIncognitoOnInstall = true; | 770 const bool kEnableIncognitoOnInstall = true; |
771 | 771 |
772 // This can legitimately happen if the user manually installed one of the | 772 // This can legitimately happen if the user manually installed one of the |
773 // default apps before this code ran. | 773 // default apps before this code ran. |
774 if (GetExtensionByIdInternal(id, true, true)) | 774 if (GetExtensionByIdInternal(id, true, true)) |
775 return; | 775 return; |
776 | 776 |
777 AddPendingExtensionInternal(id, GURL(), kExpectedCrxType, kIsFromSync, | 777 AddPendingExtensionInternal(id, GURL(), kExpectedCrxType, kIsFromSync, |
778 kInstallSilently, kEnableOnInstall, | 778 kInstallSilently, kEnableOnInstall, |
779 kEnableIncognitoOnInstall, | 779 kEnableIncognitoOnInstall, |
780 Extension::INTERNAL); | 780 Extension::INTERNAL); |
781 } | 781 } |
782 | 782 |
783 void ExtensionsService::AddPendingExtensionInternal( | 783 void ExtensionService::AddPendingExtensionInternal( |
784 const std::string& id, const GURL& update_url, | 784 const std::string& id, const GURL& update_url, |
785 PendingExtensionInfo::ExpectedCrxType expected_crx_type, | 785 PendingExtensionInfo::ExpectedCrxType expected_crx_type, |
786 bool is_from_sync, bool install_silently, | 786 bool is_from_sync, bool install_silently, |
787 bool enable_on_install, bool enable_incognito_on_install, | 787 bool enable_on_install, bool enable_incognito_on_install, |
788 Extension::Location install_source) { | 788 Extension::Location install_source) { |
789 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 789 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
790 | 790 |
791 // If a non-sync update is pending, a sync request should not | 791 // If a non-sync update is pending, a sync request should not |
792 // overwrite it. This is important for external extensions. | 792 // overwrite it. This is important for external extensions. |
793 // If an external extension download is pending, and the user has | 793 // If an external extension download is pending, and the user has |
(...skipping 11 matching lines...) Expand all Loading... |
805 if (!it->second.is_from_sync && is_from_sync) | 805 if (!it->second.is_from_sync && is_from_sync) |
806 return; | 806 return; |
807 } | 807 } |
808 | 808 |
809 pending_extensions_[id] = | 809 pending_extensions_[id] = |
810 PendingExtensionInfo(update_url, expected_crx_type, is_from_sync, | 810 PendingExtensionInfo(update_url, expected_crx_type, is_from_sync, |
811 install_silently, enable_on_install, | 811 install_silently, enable_on_install, |
812 enable_incognito_on_install, install_source); | 812 enable_incognito_on_install, install_source); |
813 } | 813 } |
814 | 814 |
815 void ExtensionsService::ReloadExtension(const std::string& extension_id) { | 815 void ExtensionService::ReloadExtension(const std::string& extension_id) { |
816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
817 FilePath path; | 817 FilePath path; |
818 const Extension* current_extension = GetExtensionById(extension_id, false); | 818 const Extension* current_extension = GetExtensionById(extension_id, false); |
819 | 819 |
820 // Disable the extension if it's loaded. It might not be loaded if it crashed. | 820 // Disable the extension if it's loaded. It might not be loaded if it crashed. |
821 if (current_extension) { | 821 if (current_extension) { |
822 // If the extension has an inspector open for its background page, detach | 822 // If the extension has an inspector open for its background page, detach |
823 // the inspector and hang onto a cookie for it, so that we can reattach | 823 // the inspector and hang onto a cookie for it, so that we can reattach |
824 // later. | 824 // later. |
825 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); | 825 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); |
(...skipping 22 matching lines...) Expand all Loading... |
848 installed_extension->extension_manifest.get()) { | 848 installed_extension->extension_manifest.get()) { |
849 LoadInstalledExtension(*installed_extension, false); | 849 LoadInstalledExtension(*installed_extension, false); |
850 } else { | 850 } else { |
851 // We should always be able to remember the extension's path. If it's not in | 851 // We should always be able to remember the extension's path. If it's not in |
852 // the map, someone failed to update |unloaded_extension_paths_|. | 852 // the map, someone failed to update |unloaded_extension_paths_|. |
853 CHECK(!path.empty()); | 853 CHECK(!path.empty()); |
854 LoadExtension(path); | 854 LoadExtension(path); |
855 } | 855 } |
856 } | 856 } |
857 | 857 |
858 void ExtensionsService::UninstallExtension(const std::string& extension_id, | 858 void ExtensionService::UninstallExtension(const std::string& extension_id, |
859 bool external_uninstall) { | 859 bool external_uninstall) { |
860 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 860 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
861 | 861 |
862 const Extension* extension = | 862 const Extension* extension = |
863 GetExtensionByIdInternal(extension_id, true, true); | 863 GetExtensionByIdInternal(extension_id, true, true); |
864 | 864 |
865 // Callers should not send us nonexistent extensions. | 865 // Callers should not send us nonexistent extensions. |
866 CHECK(extension); | 866 CHECK(extension); |
867 | 867 |
868 // Get hold of information we need after unloading, since the extension | 868 // Get hold of information we need after unloading, since the extension |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 | 900 |
901 ClearExtensionData(extension_url); | 901 ClearExtensionData(extension_url); |
902 | 902 |
903 // Notify interested parties that we've uninstalled this extension. | 903 // Notify interested parties that we've uninstalled this extension. |
904 NotificationService::current()->Notify( | 904 NotificationService::current()->Notify( |
905 NotificationType::EXTENSION_UNINSTALLED, | 905 NotificationType::EXTENSION_UNINSTALLED, |
906 Source<Profile>(profile_), | 906 Source<Profile>(profile_), |
907 Details<UninstalledExtensionInfo>(&uninstalled_extension_info)); | 907 Details<UninstalledExtensionInfo>(&uninstalled_extension_info)); |
908 } | 908 } |
909 | 909 |
910 void ExtensionsService::ClearExtensionData(const GURL& extension_url) { | 910 void ExtensionService::ClearExtensionData(const GURL& extension_url) { |
911 scoped_refptr<ExtensionDataDeleter> deleter( | 911 scoped_refptr<ExtensionDataDeleter> deleter( |
912 new ExtensionDataDeleter(profile_, extension_url)); | 912 new ExtensionDataDeleter(profile_, extension_url)); |
913 deleter->StartDeleting(); | 913 deleter->StartDeleting(); |
914 } | 914 } |
915 | 915 |
916 void ExtensionsService::EnableExtension(const std::string& extension_id) { | 916 void ExtensionService::EnableExtension(const std::string& extension_id) { |
917 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 917 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
918 | 918 |
919 const Extension* extension = | 919 const Extension* extension = |
920 GetExtensionByIdInternal(extension_id, false, true); | 920 GetExtensionByIdInternal(extension_id, false, true); |
921 if (!extension) | 921 if (!extension) |
922 return; | 922 return; |
923 | 923 |
924 extension_prefs_->SetExtensionState(extension, Extension::ENABLED); | 924 extension_prefs_->SetExtensionState(extension, Extension::ENABLED); |
925 | 925 |
926 // Move it over to the enabled list. | 926 // Move it over to the enabled list. |
927 extensions_.push_back(make_scoped_refptr(extension)); | 927 extensions_.push_back(make_scoped_refptr(extension)); |
928 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(), | 928 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(), |
929 disabled_extensions_.end(), | 929 disabled_extensions_.end(), |
930 extension); | 930 extension); |
931 disabled_extensions_.erase(iter); | 931 disabled_extensions_.erase(iter); |
932 | 932 |
933 // Make sure any browser action contained within it is not hidden. | 933 // Make sure any browser action contained within it is not hidden. |
934 extension_prefs_->SetBrowserActionVisibility(extension, true); | 934 extension_prefs_->SetBrowserActionVisibility(extension, true); |
935 | 935 |
936 ExtensionDOMUI::RegisterChromeURLOverrides(profile_, | 936 ExtensionDOMUI::RegisterChromeURLOverrides(profile_, |
937 extension->GetChromeURLOverrides()); | 937 extension->GetChromeURLOverrides()); |
938 | 938 |
939 NotifyExtensionLoaded(extension); | 939 NotifyExtensionLoaded(extension); |
940 UpdateActiveExtensionsInCrashReporter(); | 940 UpdateActiveExtensionsInCrashReporter(); |
941 } | 941 } |
942 | 942 |
943 void ExtensionsService::DisableExtension(const std::string& extension_id) { | 943 void ExtensionService::DisableExtension(const std::string& extension_id) { |
944 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 944 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
945 | 945 |
946 const Extension* extension = | 946 const Extension* extension = |
947 GetExtensionByIdInternal(extension_id, true, false); | 947 GetExtensionByIdInternal(extension_id, true, false); |
948 // The extension may have been disabled already. | 948 // The extension may have been disabled already. |
949 if (!extension) | 949 if (!extension) |
950 return; | 950 return; |
951 | 951 |
952 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); | 952 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); |
953 | 953 |
954 // Move it over to the disabled list. | 954 // Move it over to the disabled list. |
955 disabled_extensions_.push_back(make_scoped_refptr(extension)); | 955 disabled_extensions_.push_back(make_scoped_refptr(extension)); |
956 ExtensionList::iterator iter = std::find(extensions_.begin(), | 956 ExtensionList::iterator iter = std::find(extensions_.begin(), |
957 extensions_.end(), | 957 extensions_.end(), |
958 extension); | 958 extension); |
959 extensions_.erase(iter); | 959 extensions_.erase(iter); |
960 | 960 |
961 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, | 961 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, |
962 extension->GetChromeURLOverrides()); | 962 extension->GetChromeURLOverrides()); |
963 | 963 |
964 NotifyExtensionUnloaded(extension); | 964 NotifyExtensionUnloaded(extension); |
965 UpdateActiveExtensionsInCrashReporter(); | 965 UpdateActiveExtensionsInCrashReporter(); |
966 } | 966 } |
967 | 967 |
968 void ExtensionsService::GrantPermissions(const Extension* extension) { | 968 void ExtensionService::GrantPermissions(const Extension* extension) { |
969 CHECK(extension); | 969 CHECK(extension); |
970 | 970 |
971 // We only maintain the granted permissions prefs for INTERNAL extensions. | 971 // We only maintain the granted permissions prefs for INTERNAL extensions. |
972 CHECK(extension->location() == Extension::INTERNAL); | 972 CHECK(extension->location() == Extension::INTERNAL); |
973 | 973 |
974 ExtensionExtent effective_hosts = extension->GetEffectiveHostPermissions(); | 974 ExtensionExtent effective_hosts = extension->GetEffectiveHostPermissions(); |
975 extension_prefs_->AddGrantedPermissions(extension->id(), | 975 extension_prefs_->AddGrantedPermissions(extension->id(), |
976 extension->HasFullPermissions(), | 976 extension->HasFullPermissions(), |
977 extension->api_permissions(), | 977 extension->api_permissions(), |
978 effective_hosts); | 978 effective_hosts); |
979 } | 979 } |
980 | 980 |
981 void ExtensionsService::GrantPermissionsAndEnableExtension( | 981 void ExtensionService::GrantPermissionsAndEnableExtension( |
982 const Extension* extension) { | 982 const Extension* extension) { |
983 CHECK(extension); | 983 CHECK(extension); |
984 GrantPermissions(extension); | 984 GrantPermissions(extension); |
985 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); | 985 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); |
986 EnableExtension(extension->id()); | 986 EnableExtension(extension->id()); |
987 } | 987 } |
988 | 988 |
989 void ExtensionsService::LoadExtension(const FilePath& extension_path) { | 989 void ExtensionService::LoadExtension(const FilePath& extension_path) { |
990 BrowserThread::PostTask( | 990 BrowserThread::PostTask( |
991 BrowserThread::FILE, FROM_HERE, | 991 BrowserThread::FILE, FROM_HERE, |
992 NewRunnableMethod( | 992 NewRunnableMethod( |
993 backend_.get(), | 993 backend_.get(), |
994 &ExtensionsServiceBackend::LoadSingleExtension, | 994 &ExtensionServiceBackend::LoadSingleExtension, |
995 extension_path, scoped_refptr<ExtensionsService>(this))); | 995 extension_path, scoped_refptr<ExtensionService>(this))); |
996 } | 996 } |
997 | 997 |
998 void ExtensionsService::LoadComponentExtensions() { | 998 void ExtensionService::LoadComponentExtensions() { |
999 for (RegisteredComponentExtensions::iterator it = | 999 for (RegisteredComponentExtensions::iterator it = |
1000 component_extension_manifests_.begin(); | 1000 component_extension_manifests_.begin(); |
1001 it != component_extension_manifests_.end(); ++it) { | 1001 it != component_extension_manifests_.end(); ++it) { |
1002 JSONStringValueSerializer serializer(it->manifest); | 1002 JSONStringValueSerializer serializer(it->manifest); |
1003 scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL)); | 1003 scoped_ptr<Value> manifest(serializer.Deserialize(NULL, NULL)); |
1004 if (!manifest.get()) { | 1004 if (!manifest.get()) { |
1005 DLOG(ERROR) << "Failed to parse manifest for extension"; | 1005 DLOG(ERROR) << "Failed to parse manifest for extension"; |
1006 continue; | 1006 continue; |
1007 } | 1007 } |
1008 | 1008 |
1009 std::string error; | 1009 std::string error; |
1010 scoped_refptr<const Extension> extension(Extension::Create( | 1010 scoped_refptr<const Extension> extension(Extension::Create( |
1011 it->root_directory, | 1011 it->root_directory, |
1012 Extension::COMPONENT, | 1012 Extension::COMPONENT, |
1013 *static_cast<DictionaryValue*>(manifest.get()), | 1013 *static_cast<DictionaryValue*>(manifest.get()), |
1014 true, // require key | 1014 true, // require key |
1015 &error)); | 1015 &error)); |
1016 if (!extension.get()) { | 1016 if (!extension.get()) { |
1017 NOTREACHED() << error; | 1017 NOTREACHED() << error; |
1018 return; | 1018 return; |
1019 } | 1019 } |
1020 | 1020 |
1021 OnExtensionLoaded(extension); | 1021 OnExtensionLoaded(extension); |
1022 } | 1022 } |
1023 } | 1023 } |
1024 | 1024 |
1025 void ExtensionsService::LoadAllExtensions() { | 1025 void ExtensionService::LoadAllExtensions() { |
1026 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1026 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1027 | 1027 |
1028 base::TimeTicks start_time = base::TimeTicks::Now(); | 1028 base::TimeTicks start_time = base::TimeTicks::Now(); |
1029 | 1029 |
1030 // Load any component extensions. | 1030 // Load any component extensions. |
1031 LoadComponentExtensions(); | 1031 LoadComponentExtensions(); |
1032 | 1032 |
1033 // Load the previously installed extensions. | 1033 // Load the previously installed extensions. |
1034 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 1034 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
1035 extension_prefs_->GetInstalledExtensionsInfo()); | 1035 extension_prefs_->GetInstalledExtensionsInfo()); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", packaged_app_count); | 1156 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", packaged_app_count); |
1157 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension", extension_count); | 1157 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension", extension_count); |
1158 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count); | 1158 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count); |
1159 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count); | 1159 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count); |
1160 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExternal", external_count); | 1160 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExternal", external_count); |
1161 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPageAction", page_action_count); | 1161 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPageAction", page_action_count); |
1162 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction", | 1162 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction", |
1163 browser_action_count); | 1163 browser_action_count); |
1164 } | 1164 } |
1165 | 1165 |
1166 void ExtensionsService::LoadInstalledExtension(const ExtensionInfo& info, | 1166 void ExtensionService::LoadInstalledExtension(const ExtensionInfo& info, |
1167 bool write_to_prefs) { | 1167 bool write_to_prefs) { |
1168 std::string error; | 1168 std::string error; |
1169 scoped_refptr<const Extension> extension(NULL); | 1169 scoped_refptr<const Extension> extension(NULL); |
1170 if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id)) { | 1170 if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id)) { |
1171 error = errors::kDisabledByPolicy; | 1171 error = errors::kDisabledByPolicy; |
1172 } else if (info.extension_manifest.get()) { | 1172 } else if (info.extension_manifest.get()) { |
1173 bool require_key = info.extension_location != Extension::LOAD; | 1173 bool require_key = info.extension_location != Extension::LOAD; |
1174 extension = Extension::Create( | 1174 extension = Extension::Create( |
1175 info.extension_path, info.extension_location, *info.extension_manifest, | 1175 info.extension_path, info.extension_location, *info.extension_manifest, |
1176 require_key, &error); | 1176 require_key, &error); |
(...skipping 12 matching lines...) Expand all Loading... |
1189 if (write_to_prefs) | 1189 if (write_to_prefs) |
1190 extension_prefs_->UpdateManifest(extension); | 1190 extension_prefs_->UpdateManifest(extension); |
1191 | 1191 |
1192 OnExtensionLoaded(extension); | 1192 OnExtensionLoaded(extension); |
1193 | 1193 |
1194 if (Extension::IsExternalLocation(info.extension_location)) { | 1194 if (Extension::IsExternalLocation(info.extension_location)) { |
1195 BrowserThread::PostTask( | 1195 BrowserThread::PostTask( |
1196 BrowserThread::FILE, FROM_HERE, | 1196 BrowserThread::FILE, FROM_HERE, |
1197 NewRunnableMethod( | 1197 NewRunnableMethod( |
1198 backend_.get(), | 1198 backend_.get(), |
1199 &ExtensionsServiceBackend::CheckExternalUninstall, | 1199 &ExtensionServiceBackend::CheckExternalUninstall, |
1200 scoped_refptr<ExtensionsService>(this), | 1200 scoped_refptr<ExtensionService>(this), |
1201 info.extension_id)); | 1201 info.extension_id)); |
1202 } | 1202 } |
1203 } | 1203 } |
1204 | 1204 |
1205 void ExtensionsService::NotifyExtensionLoaded(const Extension* extension) { | 1205 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { |
1206 // The ChromeURLRequestContexts need to be first to know that the extension | 1206 // The ChromeURLRequestContexts need to be first to know that the extension |
1207 // was loaded, otherwise a race can arise where a renderer that is created | 1207 // was loaded, otherwise a race can arise where a renderer that is created |
1208 // for the extension may try to load an extension URL with an extension id | 1208 // for the extension may try to load an extension URL with an extension id |
1209 // that the request context doesn't yet know about. The profile is responsible | 1209 // that the request context doesn't yet know about. The profile is responsible |
1210 // for ensuring its URLRequestContexts appropriately discover the loaded | 1210 // for ensuring its URLRequestContexts appropriately discover the loaded |
1211 // extension. | 1211 // extension. |
1212 if (profile_) { | 1212 if (profile_) { |
1213 profile_->RegisterExtensionWithRequestContexts(extension); | 1213 profile_->RegisterExtensionWithRequestContexts(extension); |
1214 | 1214 |
1215 // Check if this permission requires unlimited storage quota | 1215 // Check if this permission requires unlimited storage quota |
1216 if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) | 1216 if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) |
1217 GrantUnlimitedStorage(extension); | 1217 GrantUnlimitedStorage(extension); |
1218 | 1218 |
1219 // If the extension is an app, protect its local storage from | 1219 // If the extension is an app, protect its local storage from |
1220 // "Clear browsing data." | 1220 // "Clear browsing data." |
1221 if (extension->is_app()) | 1221 if (extension->is_app()) |
1222 GrantProtectedStorage(extension); | 1222 GrantProtectedStorage(extension); |
1223 } | 1223 } |
1224 | 1224 |
1225 NotificationService::current()->Notify( | 1225 NotificationService::current()->Notify( |
1226 NotificationType::EXTENSION_LOADED, | 1226 NotificationType::EXTENSION_LOADED, |
1227 Source<Profile>(profile_), | 1227 Source<Profile>(profile_), |
1228 Details<const Extension>(extension)); | 1228 Details<const Extension>(extension)); |
1229 } | 1229 } |
1230 | 1230 |
1231 void ExtensionsService::NotifyExtensionUnloaded(const Extension* extension) { | 1231 void ExtensionService::NotifyExtensionUnloaded(const Extension* extension) { |
1232 NotificationService::current()->Notify( | 1232 NotificationService::current()->Notify( |
1233 NotificationType::EXTENSION_UNLOADED, | 1233 NotificationType::EXTENSION_UNLOADED, |
1234 Source<Profile>(profile_), | 1234 Source<Profile>(profile_), |
1235 Details<const Extension>(extension)); | 1235 Details<const Extension>(extension)); |
1236 | 1236 |
1237 if (profile_) { | 1237 if (profile_) { |
1238 profile_->UnregisterExtensionWithRequestContexts(extension); | 1238 profile_->UnregisterExtensionWithRequestContexts(extension); |
1239 | 1239 |
1240 // Check if this permission required unlimited storage quota, reset its | 1240 // Check if this permission required unlimited storage quota, reset its |
1241 // in-memory quota. | 1241 // in-memory quota. |
1242 if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) | 1242 if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) |
1243 RevokeUnlimitedStorage(extension); | 1243 RevokeUnlimitedStorage(extension); |
1244 | 1244 |
1245 // If this is an app, then stop protecting its storage so it can be deleted. | 1245 // If this is an app, then stop protecting its storage so it can be deleted. |
1246 if (extension->is_app()) | 1246 if (extension->is_app()) |
1247 RevokeProtectedStorage(extension); | 1247 RevokeProtectedStorage(extension); |
1248 } | 1248 } |
1249 } | 1249 } |
1250 | 1250 |
1251 void ExtensionsService::GrantProtectedStorage(const Extension* extension) { | 1251 void ExtensionService::GrantProtectedStorage(const Extension* extension) { |
1252 DCHECK(extension->is_app()) << "Only Apps are allowed protected storage."; | 1252 DCHECK(extension->is_app()) << "Only Apps are allowed protected storage."; |
1253 std::vector<GURL> origins; | 1253 std::vector<GURL> origins; |
1254 GetExplicitOriginsInExtent(extension, &origins); | 1254 GetExplicitOriginsInExtent(extension, &origins); |
1255 for (size_t i = 0; i < origins.size(); ++i) | 1255 for (size_t i = 0; i < origins.size(); ++i) |
1256 ++protected_storage_map_[origins[i]]; | 1256 ++protected_storage_map_[origins[i]]; |
1257 } | 1257 } |
1258 | 1258 |
1259 void ExtensionsService::RevokeProtectedStorage(const Extension* extension) { | 1259 void ExtensionService::RevokeProtectedStorage(const Extension* extension) { |
1260 DCHECK(extension->is_app()) << "Attempting to revoke protected storage from " | 1260 DCHECK(extension->is_app()) << "Attempting to revoke protected storage from " |
1261 << " a non-app extension."; | 1261 << " a non-app extension."; |
1262 std::vector<GURL> origins; | 1262 std::vector<GURL> origins; |
1263 GetExplicitOriginsInExtent(extension, &origins); | 1263 GetExplicitOriginsInExtent(extension, &origins); |
1264 for (size_t i = 0; i < origins.size(); ++i) { | 1264 for (size_t i = 0; i < origins.size(); ++i) { |
1265 const GURL& origin = origins[i]; | 1265 const GURL& origin = origins[i]; |
1266 DCHECK(protected_storage_map_[origin] > 0); | 1266 DCHECK(protected_storage_map_[origin] > 0); |
1267 if (--protected_storage_map_[origin] <= 0) | 1267 if (--protected_storage_map_[origin] <= 0) |
1268 protected_storage_map_.erase(origin); | 1268 protected_storage_map_.erase(origin); |
1269 } | 1269 } |
1270 } | 1270 } |
1271 | 1271 |
1272 void ExtensionsService::GrantUnlimitedStorage(const Extension* extension) { | 1272 void ExtensionService::GrantUnlimitedStorage(const Extension* extension) { |
1273 DCHECK(extension->HasApiPermission(Extension::kUnlimitedStoragePermission)); | 1273 DCHECK(extension->HasApiPermission(Extension::kUnlimitedStoragePermission)); |
1274 std::vector<GURL> origins; | 1274 std::vector<GURL> origins; |
1275 GetExplicitOriginsInExtent(extension, &origins); | 1275 GetExplicitOriginsInExtent(extension, &origins); |
1276 origins.push_back(extension->url()); | 1276 origins.push_back(extension->url()); |
1277 | 1277 |
1278 for (size_t i = 0; i < origins.size(); ++i) { | 1278 for (size_t i = 0; i < origins.size(); ++i) { |
1279 const GURL& origin = origins[i]; | 1279 const GURL& origin = origins[i]; |
1280 if (++unlimited_storage_map_[origin] == 1) { | 1280 if (++unlimited_storage_map_[origin] == 1) { |
1281 string16 origin_identifier = | 1281 string16 origin_identifier = |
1282 webkit_database::DatabaseUtil::GetOriginIdentifier(origin); | 1282 webkit_database::DatabaseUtil::GetOriginIdentifier(origin); |
(...skipping 14 matching lines...) Expand all Loading... |
1297 BrowserThread::PostTask( | 1297 BrowserThread::PostTask( |
1298 BrowserThread::IO, FROM_HERE, | 1298 BrowserThread::IO, FROM_HERE, |
1299 NewRunnableMethod( | 1299 NewRunnableMethod( |
1300 profile_->GetFileSystemContext(), | 1300 profile_->GetFileSystemContext(), |
1301 &fileapi::SandboxedFileSystemContext::SetOriginQuotaUnlimited, | 1301 &fileapi::SandboxedFileSystemContext::SetOriginQuotaUnlimited, |
1302 origin)); | 1302 origin)); |
1303 } | 1303 } |
1304 } | 1304 } |
1305 } | 1305 } |
1306 | 1306 |
1307 void ExtensionsService::RevokeUnlimitedStorage(const Extension* extension) { | 1307 void ExtensionService::RevokeUnlimitedStorage(const Extension* extension) { |
1308 DCHECK(extension->HasApiPermission(Extension::kUnlimitedStoragePermission)); | 1308 DCHECK(extension->HasApiPermission(Extension::kUnlimitedStoragePermission)); |
1309 std::vector<GURL> origins; | 1309 std::vector<GURL> origins; |
1310 GetExplicitOriginsInExtent(extension, &origins); | 1310 GetExplicitOriginsInExtent(extension, &origins); |
1311 origins.push_back(extension->url()); | 1311 origins.push_back(extension->url()); |
1312 | 1312 |
1313 for (size_t i = 0; i < origins.size(); ++i) { | 1313 for (size_t i = 0; i < origins.size(); ++i) { |
1314 const GURL& origin = origins[i]; | 1314 const GURL& origin = origins[i]; |
1315 DCHECK(unlimited_storage_map_[origin] > 0); | 1315 DCHECK(unlimited_storage_map_[origin] > 0); |
1316 if (--unlimited_storage_map_[origin] == 0) { | 1316 if (--unlimited_storage_map_[origin] == 0) { |
1317 unlimited_storage_map_.erase(origin); | 1317 unlimited_storage_map_.erase(origin); |
(...skipping 14 matching lines...) Expand all Loading... |
1332 BrowserThread::PostTask( | 1332 BrowserThread::PostTask( |
1333 BrowserThread::IO, FROM_HERE, | 1333 BrowserThread::IO, FROM_HERE, |
1334 NewRunnableMethod( | 1334 NewRunnableMethod( |
1335 profile_->GetFileSystemContext(), | 1335 profile_->GetFileSystemContext(), |
1336 &fileapi::SandboxedFileSystemContext::ResetOriginQuotaUnlimited, | 1336 &fileapi::SandboxedFileSystemContext::ResetOriginQuotaUnlimited, |
1337 origin)); | 1337 origin)); |
1338 } | 1338 } |
1339 } | 1339 } |
1340 } | 1340 } |
1341 | 1341 |
1342 void ExtensionsService::UpdateExtensionBlacklist( | 1342 void ExtensionService::UpdateExtensionBlacklist( |
1343 const std::vector<std::string>& blacklist) { | 1343 const std::vector<std::string>& blacklist) { |
1344 // Use this set to indicate if an extension in the blacklist has been used. | 1344 // Use this set to indicate if an extension in the blacklist has been used. |
1345 std::set<std::string> blacklist_set; | 1345 std::set<std::string> blacklist_set; |
1346 for (unsigned int i = 0; i < blacklist.size(); ++i) { | 1346 for (unsigned int i = 0; i < blacklist.size(); ++i) { |
1347 if (Extension::IdIsValid(blacklist[i])) { | 1347 if (Extension::IdIsValid(blacklist[i])) { |
1348 blacklist_set.insert(blacklist[i]); | 1348 blacklist_set.insert(blacklist[i]); |
1349 } | 1349 } |
1350 } | 1350 } |
1351 extension_prefs_->UpdateBlacklist(blacklist_set); | 1351 extension_prefs_->UpdateBlacklist(blacklist_set); |
1352 std::vector<std::string> to_be_removed; | 1352 std::vector<std::string> to_be_removed; |
1353 // Loop current extensions, unload installed extensions. | 1353 // Loop current extensions, unload installed extensions. |
1354 for (ExtensionList::const_iterator iter = extensions_.begin(); | 1354 for (ExtensionList::const_iterator iter = extensions_.begin(); |
1355 iter != extensions_.end(); ++iter) { | 1355 iter != extensions_.end(); ++iter) { |
1356 const Extension* extension = (*iter); | 1356 const Extension* extension = (*iter); |
1357 if (blacklist_set.find(extension->id()) != blacklist_set.end()) { | 1357 if (blacklist_set.find(extension->id()) != blacklist_set.end()) { |
1358 to_be_removed.push_back(extension->id()); | 1358 to_be_removed.push_back(extension->id()); |
1359 } | 1359 } |
1360 } | 1360 } |
1361 | 1361 |
1362 // UnloadExtension will change the extensions_ list. So, we should | 1362 // UnloadExtension will change the extensions_ list. So, we should |
1363 // call it outside the iterator loop. | 1363 // call it outside the iterator loop. |
1364 for (unsigned int i = 0; i < to_be_removed.size(); ++i) { | 1364 for (unsigned int i = 0; i < to_be_removed.size(); ++i) { |
1365 UnloadExtension(to_be_removed[i]); | 1365 UnloadExtension(to_be_removed[i]); |
1366 } | 1366 } |
1367 } | 1367 } |
1368 | 1368 |
1369 void ExtensionsService::DestroyingProfile() { | 1369 void ExtensionService::DestroyingProfile() { |
1370 pref_change_registrar_.RemoveAll(); | 1370 pref_change_registrar_.RemoveAll(); |
1371 profile_ = NULL; | 1371 profile_ = NULL; |
1372 toolbar_model_.DestroyingProfile(); | 1372 toolbar_model_.DestroyingProfile(); |
1373 } | 1373 } |
1374 | 1374 |
1375 ExtensionPrefs* ExtensionsService::extension_prefs() { | 1375 ExtensionPrefs* ExtensionService::extension_prefs() { |
1376 return extension_prefs_; | 1376 return extension_prefs_; |
1377 } | 1377 } |
1378 | 1378 |
1379 void ExtensionsService::CheckAdminBlacklist() { | 1379 void ExtensionService::CheckAdminBlacklist() { |
1380 std::vector<std::string> to_be_removed; | 1380 std::vector<std::string> to_be_removed; |
1381 // Loop through extensions list, unload installed extensions. | 1381 // Loop through extensions list, unload installed extensions. |
1382 for (ExtensionList::const_iterator iter = extensions_.begin(); | 1382 for (ExtensionList::const_iterator iter = extensions_.begin(); |
1383 iter != extensions_.end(); ++iter) { | 1383 iter != extensions_.end(); ++iter) { |
1384 const Extension* extension = (*iter); | 1384 const Extension* extension = (*iter); |
1385 if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id())) | 1385 if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id())) |
1386 to_be_removed.push_back(extension->id()); | 1386 to_be_removed.push_back(extension->id()); |
1387 } | 1387 } |
1388 | 1388 |
1389 // UnloadExtension will change the extensions_ list. So, we should | 1389 // UnloadExtension will change the extensions_ list. So, we should |
1390 // call it outside the iterator loop. | 1390 // call it outside the iterator loop. |
1391 for (unsigned int i = 0; i < to_be_removed.size(); ++i) | 1391 for (unsigned int i = 0; i < to_be_removed.size(); ++i) |
1392 UnloadExtension(to_be_removed[i]); | 1392 UnloadExtension(to_be_removed[i]); |
1393 } | 1393 } |
1394 | 1394 |
1395 bool ExtensionsService::IsIncognitoEnabled(const Extension* extension) { | 1395 bool ExtensionService::IsIncognitoEnabled(const Extension* extension) { |
1396 // If this is a component extension we always allow it to work in incognito | 1396 // If this is a component extension we always allow it to work in incognito |
1397 // mode. | 1397 // mode. |
1398 if (extension->location() == Extension::COMPONENT) | 1398 if (extension->location() == Extension::COMPONENT) |
1399 return true; | 1399 return true; |
1400 | 1400 |
1401 // Check the prefs. | 1401 // Check the prefs. |
1402 return extension_prefs_->IsIncognitoEnabled(extension->id()); | 1402 return extension_prefs_->IsIncognitoEnabled(extension->id()); |
1403 } | 1403 } |
1404 | 1404 |
1405 void ExtensionsService::SetIsIncognitoEnabled(const Extension* extension, | 1405 void ExtensionService::SetIsIncognitoEnabled(const Extension* extension, |
1406 bool enabled) { | 1406 bool enabled) { |
1407 extension_prefs_->SetIsIncognitoEnabled(extension->id(), enabled); | 1407 extension_prefs_->SetIsIncognitoEnabled(extension->id(), enabled); |
1408 | 1408 |
1409 // Broadcast unloaded and loaded events to update browser state. Only bother | 1409 // Broadcast unloaded and loaded events to update browser state. Only bother |
1410 // if the extension is actually enabled, since there is no UI otherwise. | 1410 // if the extension is actually enabled, since there is no UI otherwise. |
1411 bool is_enabled = std::find(extensions_.begin(), extensions_.end(), | 1411 bool is_enabled = std::find(extensions_.begin(), extensions_.end(), |
1412 extension) != extensions_.end(); | 1412 extension) != extensions_.end(); |
1413 if (is_enabled) { | 1413 if (is_enabled) { |
1414 NotifyExtensionUnloaded(extension); | 1414 NotifyExtensionUnloaded(extension); |
1415 NotifyExtensionLoaded(extension); | 1415 NotifyExtensionLoaded(extension); |
1416 } | 1416 } |
1417 } | 1417 } |
1418 | 1418 |
1419 bool ExtensionsService::CanCrossIncognito(const Extension* extension) { | 1419 bool ExtensionService::CanCrossIncognito(const Extension* extension) { |
1420 // We allow the extension to see events and data from another profile iff it | 1420 // We allow the extension to see events and data from another profile iff it |
1421 // uses "spanning" behavior and it has incognito access. "split" mode | 1421 // uses "spanning" behavior and it has incognito access. "split" mode |
1422 // extensions only see events for a matching profile. | 1422 // extensions only see events for a matching profile. |
1423 return IsIncognitoEnabled(extension) && !extension->incognito_split_mode(); | 1423 return IsIncognitoEnabled(extension) && !extension->incognito_split_mode(); |
1424 } | 1424 } |
1425 | 1425 |
1426 bool ExtensionsService::AllowFileAccess(const Extension* extension) { | 1426 bool ExtensionService::AllowFileAccess(const Extension* extension) { |
1427 return (CommandLine::ForCurrentProcess()->HasSwitch( | 1427 return (CommandLine::ForCurrentProcess()->HasSwitch( |
1428 switches::kDisableExtensionsFileAccessCheck) || | 1428 switches::kDisableExtensionsFileAccessCheck) || |
1429 extension_prefs_->AllowFileAccess(extension->id())); | 1429 extension_prefs_->AllowFileAccess(extension->id())); |
1430 } | 1430 } |
1431 | 1431 |
1432 void ExtensionsService::SetAllowFileAccess(const Extension* extension, | 1432 void ExtensionService::SetAllowFileAccess(const Extension* extension, |
1433 bool allow) { | 1433 bool allow) { |
1434 extension_prefs_->SetAllowFileAccess(extension->id(), allow); | 1434 extension_prefs_->SetAllowFileAccess(extension->id(), allow); |
1435 NotificationService::current()->Notify( | 1435 NotificationService::current()->Notify( |
1436 NotificationType::EXTENSION_USER_SCRIPTS_UPDATED, | 1436 NotificationType::EXTENSION_USER_SCRIPTS_UPDATED, |
1437 Source<Profile>(profile_), | 1437 Source<Profile>(profile_), |
1438 Details<const Extension>(extension)); | 1438 Details<const Extension>(extension)); |
1439 } | 1439 } |
1440 | 1440 |
1441 bool ExtensionsService::GetBrowserActionVisibility(const Extension* extension) { | 1441 bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) { |
1442 return extension_prefs_->GetBrowserActionVisibility(extension); | 1442 return extension_prefs_->GetBrowserActionVisibility(extension); |
1443 } | 1443 } |
1444 | 1444 |
1445 void ExtensionsService::SetBrowserActionVisibility(const Extension* extension, | 1445 void ExtensionService::SetBrowserActionVisibility(const Extension* extension, |
1446 bool visible) { | 1446 bool visible) { |
1447 extension_prefs_->SetBrowserActionVisibility(extension, visible); | 1447 extension_prefs_->SetBrowserActionVisibility(extension, visible); |
1448 } | 1448 } |
1449 | 1449 |
1450 void ExtensionsService::CheckForExternalUpdates() { | 1450 void ExtensionService::CheckForExternalUpdates() { |
1451 BrowserThread::PostTask( | 1451 BrowserThread::PostTask( |
1452 BrowserThread::FILE, FROM_HERE, | 1452 BrowserThread::FILE, FROM_HERE, |
1453 NewRunnableMethod( | 1453 NewRunnableMethod( |
1454 backend_.get(), &ExtensionsServiceBackend::CheckForExternalUpdates, | 1454 backend_.get(), &ExtensionServiceBackend::CheckForExternalUpdates, |
1455 scoped_refptr<ExtensionsService>(this))); | 1455 scoped_refptr<ExtensionService>(this))); |
1456 } | 1456 } |
1457 | 1457 |
1458 void ExtensionsService::UpdateExternalPolicyExtensionProvider() { | 1458 void ExtensionService::UpdateExternalPolicyExtensionProvider() { |
1459 const ListValue* list_pref = | 1459 const ListValue* list_pref = |
1460 profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList); | 1460 profile_->GetPrefs()->GetList(prefs::kExtensionInstallForceList); |
1461 ListValue* list_copy = NULL; | 1461 ListValue* list_copy = NULL; |
1462 if (list_pref) | 1462 if (list_pref) |
1463 list_copy = static_cast<ListValue*>(list_pref->DeepCopy()); | 1463 list_copy = static_cast<ListValue*>(list_pref->DeepCopy()); |
1464 BrowserThread::PostTask( | 1464 BrowserThread::PostTask( |
1465 BrowserThread::FILE, FROM_HERE, | 1465 BrowserThread::FILE, FROM_HERE, |
1466 NewRunnableMethod( | 1466 NewRunnableMethod( |
1467 backend_.get(), | 1467 backend_.get(), |
1468 &ExtensionsServiceBackend::UpdateExternalPolicyExtensionProvider, | 1468 &ExtensionServiceBackend::UpdateExternalPolicyExtensionProvider, |
1469 scoped_refptr<RefCountedList>( | 1469 scoped_refptr<RefCountedList>( |
1470 new RefCountedList(list_copy)))); | 1470 new RefCountedList(list_copy)))); |
1471 } | 1471 } |
1472 | 1472 |
1473 void ExtensionsService::UnloadExtension(const std::string& extension_id) { | 1473 void ExtensionService::UnloadExtension(const std::string& extension_id) { |
1474 // Make sure the extension gets deleted after we return from this function. | 1474 // Make sure the extension gets deleted after we return from this function. |
1475 scoped_refptr<const Extension> extension( | 1475 scoped_refptr<const Extension> extension( |
1476 GetExtensionByIdInternal(extension_id, true, true)); | 1476 GetExtensionByIdInternal(extension_id, true, true)); |
1477 | 1477 |
1478 // This method can be called via PostTask, so the extension may have been | 1478 // This method can be called via PostTask, so the extension may have been |
1479 // unloaded by the time this runs. | 1479 // unloaded by the time this runs. |
1480 if (!extension) | 1480 if (!extension) |
1481 return; | 1481 return; |
1482 | 1482 |
1483 // Keep information about the extension so that we can reload it later | 1483 // Keep information about the extension so that we can reload it later |
(...skipping 23 matching lines...) Expand all Loading... |
1507 | 1507 |
1508 iter = std::find(extensions_.begin(), extensions_.end(), extension.get()); | 1508 iter = std::find(extensions_.begin(), extensions_.end(), extension.get()); |
1509 | 1509 |
1510 // Remove the extension from our list. | 1510 // Remove the extension from our list. |
1511 extensions_.erase(iter); | 1511 extensions_.erase(iter); |
1512 | 1512 |
1513 NotifyExtensionUnloaded(extension.get()); | 1513 NotifyExtensionUnloaded(extension.get()); |
1514 UpdateActiveExtensionsInCrashReporter(); | 1514 UpdateActiveExtensionsInCrashReporter(); |
1515 } | 1515 } |
1516 | 1516 |
1517 void ExtensionsService::UnloadAllExtensions() { | 1517 void ExtensionService::UnloadAllExtensions() { |
1518 extensions_.clear(); | 1518 extensions_.clear(); |
1519 disabled_extensions_.clear(); | 1519 disabled_extensions_.clear(); |
1520 extension_runtime_data_.clear(); | 1520 extension_runtime_data_.clear(); |
1521 | 1521 |
1522 // TODO(erikkay) should there be a notification for this? We can't use | 1522 // TODO(erikkay) should there be a notification for this? We can't use |
1523 // EXTENSION_UNLOADED since that implies that the extension has been disabled | 1523 // EXTENSION_UNLOADED since that implies that the extension has been disabled |
1524 // or uninstalled, and UnloadAll is just part of shutdown. | 1524 // or uninstalled, and UnloadAll is just part of shutdown. |
1525 } | 1525 } |
1526 | 1526 |
1527 void ExtensionsService::ReloadExtensions() { | 1527 void ExtensionService::ReloadExtensions() { |
1528 UnloadAllExtensions(); | 1528 UnloadAllExtensions(); |
1529 LoadAllExtensions(); | 1529 LoadAllExtensions(); |
1530 } | 1530 } |
1531 | 1531 |
1532 void ExtensionsService::GarbageCollectExtensions() { | 1532 void ExtensionService::GarbageCollectExtensions() { |
1533 if (extension_prefs_->pref_service()->ReadOnly()) | 1533 if (extension_prefs_->pref_service()->ReadOnly()) |
1534 return; | 1534 return; |
1535 | 1535 |
1536 scoped_ptr<ExtensionPrefs::ExtensionsInfo> info( | 1536 scoped_ptr<ExtensionPrefs::ExtensionsInfo> info( |
1537 extension_prefs_->GetInstalledExtensionsInfo()); | 1537 extension_prefs_->GetInstalledExtensionsInfo()); |
1538 | 1538 |
1539 std::map<std::string, FilePath> extension_paths; | 1539 std::map<std::string, FilePath> extension_paths; |
1540 for (size_t i = 0; i < info->size(); ++i) | 1540 for (size_t i = 0; i < info->size(); ++i) |
1541 extension_paths[info->at(i)->extension_id] = info->at(i)->extension_path; | 1541 extension_paths[info->at(i)->extension_id] = info->at(i)->extension_path; |
1542 | 1542 |
1543 BrowserThread::PostTask( | 1543 BrowserThread::PostTask( |
1544 BrowserThread::FILE, FROM_HERE, | 1544 BrowserThread::FILE, FROM_HERE, |
1545 NewRunnableFunction( | 1545 NewRunnableFunction( |
1546 &extension_file_util::GarbageCollectExtensions, install_directory_, | 1546 &extension_file_util::GarbageCollectExtensions, install_directory_, |
1547 extension_paths)); | 1547 extension_paths)); |
1548 | 1548 |
1549 // Also garbage-collect themes. We check |profile_| to be | 1549 // Also garbage-collect themes. We check |profile_| to be |
1550 // defensive; in the future, we may call GarbageCollectExtensions() | 1550 // defensive; in the future, we may call GarbageCollectExtensions() |
1551 // from somewhere other than Init() (e.g., in a timer). | 1551 // from somewhere other than Init() (e.g., in a timer). |
1552 if (profile_) { | 1552 if (profile_) { |
1553 profile_->GetThemeProvider()->RemoveUnusedThemes(); | 1553 profile_->GetThemeProvider()->RemoveUnusedThemes(); |
1554 } | 1554 } |
1555 } | 1555 } |
1556 | 1556 |
1557 void ExtensionsService::OnLoadedInstalledExtensions() { | 1557 void ExtensionService::OnLoadedInstalledExtensions() { |
1558 if (updater_.get()) { | 1558 if (updater_.get()) { |
1559 updater_->Start(); | 1559 updater_->Start(); |
1560 } | 1560 } |
1561 | 1561 |
1562 ready_ = true; | 1562 ready_ = true; |
1563 NotificationService::current()->Notify( | 1563 NotificationService::current()->Notify( |
1564 NotificationType::EXTENSIONS_READY, | 1564 NotificationType::EXTENSIONS_READY, |
1565 Source<Profile>(profile_), | 1565 Source<Profile>(profile_), |
1566 NotificationService::NoDetails()); | 1566 NotificationService::NoDetails()); |
1567 } | 1567 } |
1568 | 1568 |
1569 void ExtensionsService::OnExtensionLoaded(const Extension* extension) { | 1569 void ExtensionService::OnExtensionLoaded(const Extension* extension) { |
1570 // Ensure extension is deleted unless we transfer ownership. | 1570 // Ensure extension is deleted unless we transfer ownership. |
1571 scoped_refptr<const Extension> scoped_extension(extension); | 1571 scoped_refptr<const Extension> scoped_extension(extension); |
1572 | 1572 |
1573 // The extension is now loaded, remove its data from unloaded extension map. | 1573 // The extension is now loaded, remove its data from unloaded extension map. |
1574 unloaded_extension_paths_.erase(extension->id()); | 1574 unloaded_extension_paths_.erase(extension->id()); |
1575 | 1575 |
1576 // If the extension was disabled for a reload, then enable it. | 1576 // If the extension was disabled for a reload, then enable it. |
1577 if (disabled_extension_paths_.erase(extension->id()) > 0) | 1577 if (disabled_extension_paths_.erase(extension->id()) > 0) |
1578 EnableExtension(extension->id()); | 1578 EnableExtension(extension->id()); |
1579 | 1579 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1619 profile_->GetTemplateURLModel()->RegisterExtensionKeyword(extension); | 1619 profile_->GetTemplateURLModel()->RegisterExtensionKeyword(extension); |
1620 | 1620 |
1621 // Load the icon for omnibox-enabled extensions so it will be ready to display | 1621 // Load the icon for omnibox-enabled extensions so it will be ready to display |
1622 // in the URL bar. | 1622 // in the URL bar. |
1623 if (!extension->omnibox_keyword().empty()) { | 1623 if (!extension->omnibox_keyword().empty()) { |
1624 omnibox_popup_icon_manager_.LoadIcon(extension); | 1624 omnibox_popup_icon_manager_.LoadIcon(extension); |
1625 omnibox_icon_manager_.LoadIcon(extension); | 1625 omnibox_icon_manager_.LoadIcon(extension); |
1626 } | 1626 } |
1627 } | 1627 } |
1628 | 1628 |
1629 void ExtensionsService::DisableIfPrivilegeIncrease(const Extension* extension) { | 1629 void ExtensionService::DisableIfPrivilegeIncrease(const Extension* extension) { |
1630 // We keep track of all permissions the user has granted each extension. | 1630 // We keep track of all permissions the user has granted each extension. |
1631 // This allows extensions to gracefully support backwards compatibility | 1631 // This allows extensions to gracefully support backwards compatibility |
1632 // by including unknown permissions in their manifests. When the user | 1632 // by including unknown permissions in their manifests. When the user |
1633 // installs the extension, only the recognized permissions are recorded. | 1633 // installs the extension, only the recognized permissions are recorded. |
1634 // When the unknown permissions become recognized (e.g., through browser | 1634 // When the unknown permissions become recognized (e.g., through browser |
1635 // upgrade), we can prompt the user to accept these new permissions. | 1635 // upgrade), we can prompt the user to accept these new permissions. |
1636 // Extensions can also silently upgrade to less permissions, and then | 1636 // Extensions can also silently upgrade to less permissions, and then |
1637 // silently upgrade to a version that adds these permissions back. | 1637 // silently upgrade to a version that adds these permissions back. |
1638 // | 1638 // |
1639 // For example, pretend that Chrome 10 includes a permission "omnibox" | 1639 // For example, pretend that Chrome 10 includes a permission "omnibox" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1701 } | 1701 } |
1702 | 1702 |
1703 // Extension has changed permissions significantly. Disable it. A | 1703 // Extension has changed permissions significantly. Disable it. A |
1704 // notification should be sent by the caller. | 1704 // notification should be sent by the caller. |
1705 if (is_privilege_increase) { | 1705 if (is_privilege_increase) { |
1706 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); | 1706 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); |
1707 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); | 1707 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); |
1708 } | 1708 } |
1709 } | 1709 } |
1710 | 1710 |
1711 void ExtensionsService::UpdateActiveExtensionsInCrashReporter() { | 1711 void ExtensionService::UpdateActiveExtensionsInCrashReporter() { |
1712 std::set<std::string> extension_ids; | 1712 std::set<std::string> extension_ids; |
1713 for (size_t i = 0; i < extensions_.size(); ++i) { | 1713 for (size_t i = 0; i < extensions_.size(); ++i) { |
1714 if (!extensions_[i]->is_theme() && | 1714 if (!extensions_[i]->is_theme() && |
1715 extensions_[i]->location() != Extension::COMPONENT) | 1715 extensions_[i]->location() != Extension::COMPONENT) |
1716 extension_ids.insert(extensions_[i]->id()); | 1716 extension_ids.insert(extensions_[i]->id()); |
1717 } | 1717 } |
1718 | 1718 |
1719 child_process_logging::SetActiveExtensions(extension_ids); | 1719 child_process_logging::SetActiveExtensions(extension_ids); |
1720 } | 1720 } |
1721 | 1721 |
1722 void ExtensionsService::OnExtensionInstalled(const Extension* extension) { | 1722 void ExtensionService::OnExtensionInstalled(const Extension* extension) { |
1723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1724 | 1724 |
1725 // Ensure extension is deleted unless we transfer ownership. | 1725 // Ensure extension is deleted unless we transfer ownership. |
1726 scoped_refptr<const Extension> scoped_extension(extension); | 1726 scoped_refptr<const Extension> scoped_extension(extension); |
1727 Extension::State initial_state = Extension::DISABLED; | 1727 Extension::State initial_state = Extension::DISABLED; |
1728 bool initial_enable_incognito = false; | 1728 bool initial_enable_incognito = false; |
1729 PendingExtensionMap::iterator it = | 1729 PendingExtensionMap::iterator it = |
1730 pending_extensions_.find(extension->id()); | 1730 pending_extensions_.find(extension->id()); |
1731 if (it != pending_extensions_.end()) { | 1731 if (it != pending_extensions_.end()) { |
1732 PendingExtensionInfo pending_extension_info = it->second; | 1732 PendingExtensionInfo pending_extension_info = it->second; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1857 if (extension->is_app()) { | 1857 if (extension->is_app()) { |
1858 ExtensionIdSet installed_ids = GetAppIds(); | 1858 ExtensionIdSet installed_ids = GetAppIds(); |
1859 installed_ids.insert(extension->id()); | 1859 installed_ids.insert(extension->id()); |
1860 default_apps_.DidInstallApp(installed_ids); | 1860 default_apps_.DidInstallApp(installed_ids); |
1861 } | 1861 } |
1862 | 1862 |
1863 // Transfer ownership of |extension| to OnExtensionLoaded. | 1863 // Transfer ownership of |extension| to OnExtensionLoaded. |
1864 OnExtensionLoaded(scoped_extension); | 1864 OnExtensionLoaded(scoped_extension); |
1865 } | 1865 } |
1866 | 1866 |
1867 const Extension* ExtensionsService::GetExtensionByIdInternal( | 1867 const Extension* ExtensionService::GetExtensionByIdInternal( |
1868 const std::string& id, bool include_enabled, bool include_disabled) { | 1868 const std::string& id, bool include_enabled, bool include_disabled) { |
1869 std::string lowercase_id = StringToLowerASCII(id); | 1869 std::string lowercase_id = StringToLowerASCII(id); |
1870 if (include_enabled) { | 1870 if (include_enabled) { |
1871 for (ExtensionList::const_iterator iter = extensions_.begin(); | 1871 for (ExtensionList::const_iterator iter = extensions_.begin(); |
1872 iter != extensions_.end(); ++iter) { | 1872 iter != extensions_.end(); ++iter) { |
1873 if ((*iter)->id() == lowercase_id) | 1873 if ((*iter)->id() == lowercase_id) |
1874 return *iter; | 1874 return *iter; |
1875 } | 1875 } |
1876 } | 1876 } |
1877 if (include_disabled) { | 1877 if (include_disabled) { |
1878 for (ExtensionList::const_iterator iter = disabled_extensions_.begin(); | 1878 for (ExtensionList::const_iterator iter = disabled_extensions_.begin(); |
1879 iter != disabled_extensions_.end(); ++iter) { | 1879 iter != disabled_extensions_.end(); ++iter) { |
1880 if ((*iter)->id() == lowercase_id) | 1880 if ((*iter)->id() == lowercase_id) |
1881 return *iter; | 1881 return *iter; |
1882 } | 1882 } |
1883 } | 1883 } |
1884 return NULL; | 1884 return NULL; |
1885 } | 1885 } |
1886 | 1886 |
1887 const Extension* ExtensionsService::GetWebStoreApp() { | 1887 const Extension* ExtensionService::GetWebStoreApp() { |
1888 return GetExtensionById(extension_misc::kWebStoreAppId, false); | 1888 return GetExtensionById(extension_misc::kWebStoreAppId, false); |
1889 } | 1889 } |
1890 | 1890 |
1891 const Extension* ExtensionsService::GetExtensionByURL(const GURL& url) { | 1891 const Extension* ExtensionService::GetExtensionByURL(const GURL& url) { |
1892 return url.scheme() != chrome::kExtensionScheme ? NULL : | 1892 return url.scheme() != chrome::kExtensionScheme ? NULL : |
1893 GetExtensionById(url.host(), false); | 1893 GetExtensionById(url.host(), false); |
1894 } | 1894 } |
1895 | 1895 |
1896 const Extension* ExtensionsService::GetExtensionByWebExtent(const GURL& url) { | 1896 const Extension* ExtensionService::GetExtensionByWebExtent(const GURL& url) { |
1897 for (size_t i = 0; i < extensions_.size(); ++i) { | 1897 for (size_t i = 0; i < extensions_.size(); ++i) { |
1898 if (extensions_[i]->web_extent().ContainsURL(url)) | 1898 if (extensions_[i]->web_extent().ContainsURL(url)) |
1899 return extensions_[i]; | 1899 return extensions_[i]; |
1900 } | 1900 } |
1901 return NULL; | 1901 return NULL; |
1902 } | 1902 } |
1903 | 1903 |
1904 bool ExtensionsService::ExtensionBindingsAllowed(const GURL& url) { | 1904 bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) { |
1905 // Allow bindings for all packaged extension. | 1905 // Allow bindings for all packaged extension. |
1906 if (GetExtensionByURL(url)) | 1906 if (GetExtensionByURL(url)) |
1907 return true; | 1907 return true; |
1908 | 1908 |
1909 // Allow bindings for all component, hosted apps. | 1909 // Allow bindings for all component, hosted apps. |
1910 const Extension* extension = GetExtensionByWebExtent(url); | 1910 const Extension* extension = GetExtensionByWebExtent(url); |
1911 return (extension && extension->location() == Extension::COMPONENT); | 1911 return (extension && extension->location() == Extension::COMPONENT); |
1912 } | 1912 } |
1913 | 1913 |
1914 const Extension* ExtensionsService::GetExtensionByOverlappingWebExtent( | 1914 const Extension* ExtensionService::GetExtensionByOverlappingWebExtent( |
1915 const ExtensionExtent& extent) { | 1915 const ExtensionExtent& extent) { |
1916 for (size_t i = 0; i < extensions_.size(); ++i) { | 1916 for (size_t i = 0; i < extensions_.size(); ++i) { |
1917 if (extensions_[i]->web_extent().OverlapsWith(extent)) | 1917 if (extensions_[i]->web_extent().OverlapsWith(extent)) |
1918 return extensions_[i]; | 1918 return extensions_[i]; |
1919 } | 1919 } |
1920 | 1920 |
1921 return NULL; | 1921 return NULL; |
1922 } | 1922 } |
1923 | 1923 |
1924 const SkBitmap& ExtensionsService::GetOmniboxIcon( | 1924 const SkBitmap& ExtensionService::GetOmniboxIcon( |
1925 const std::string& extension_id) { | 1925 const std::string& extension_id) { |
1926 return omnibox_icon_manager_.GetIcon(extension_id); | 1926 return omnibox_icon_manager_.GetIcon(extension_id); |
1927 } | 1927 } |
1928 | 1928 |
1929 const SkBitmap& ExtensionsService::GetOmniboxPopupIcon( | 1929 const SkBitmap& ExtensionService::GetOmniboxPopupIcon( |
1930 const std::string& extension_id) { | 1930 const std::string& extension_id) { |
1931 return omnibox_popup_icon_manager_.GetIcon(extension_id); | 1931 return omnibox_popup_icon_manager_.GetIcon(extension_id); |
1932 } | 1932 } |
1933 | 1933 |
1934 void ExtensionsService::ClearProvidersForTesting() { | 1934 void ExtensionService::ClearProvidersForTesting() { |
1935 BrowserThread::PostTask( | 1935 BrowserThread::PostTask( |
1936 BrowserThread::FILE, FROM_HERE, | 1936 BrowserThread::FILE, FROM_HERE, |
1937 NewRunnableMethod( | 1937 NewRunnableMethod( |
1938 backend_.get(), &ExtensionsServiceBackend::ClearProvidersForTesting)); | 1938 backend_.get(), &ExtensionServiceBackend::ClearProvidersForTesting)); |
1939 } | 1939 } |
1940 | 1940 |
1941 void ExtensionsService::AddProviderForTesting( | 1941 void ExtensionService::AddProviderForTesting( |
1942 ExternalExtensionProvider* test_provider) { | 1942 ExternalExtensionProvider* test_provider) { |
1943 BrowserThread::PostTask( | 1943 BrowserThread::PostTask( |
1944 BrowserThread::FILE, FROM_HERE, | 1944 BrowserThread::FILE, FROM_HERE, |
1945 NewRunnableMethod( | 1945 NewRunnableMethod( |
1946 backend_.get(), &ExtensionsServiceBackend::AddProviderForTesting, | 1946 backend_.get(), &ExtensionServiceBackend::AddProviderForTesting, |
1947 test_provider)); | 1947 test_provider)); |
1948 } | 1948 } |
1949 | 1949 |
1950 void ExtensionsService::OnExternalExtensionFileFound( | 1950 void ExtensionService::OnExternalExtensionFileFound( |
1951 const std::string& id, | 1951 const std::string& id, |
1952 const std::string& version, | 1952 const std::string& version, |
1953 const FilePath& path, | 1953 const FilePath& path, |
1954 Extension::Location location) { | 1954 Extension::Location location) { |
1955 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1955 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1956 if (extension_prefs_->IsExtensionKilled(id)) | 1956 if (extension_prefs_->IsExtensionKilled(id)) |
1957 return; | 1957 return; |
1958 | 1958 |
1959 // Before even bothering to unpack, check and see if we already have this | 1959 // Before even bothering to unpack, check and see if we already have this |
1960 // version. This is important because these extensions are going to get | 1960 // version. This is important because these extensions are going to get |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1993 location); | 1993 location); |
1994 | 1994 |
1995 scoped_refptr<CrxInstaller> installer( | 1995 scoped_refptr<CrxInstaller> installer( |
1996 new CrxInstaller(this, // frontend | 1996 new CrxInstaller(this, // frontend |
1997 NULL)); // no client (silent install) | 1997 NULL)); // no client (silent install) |
1998 installer->set_install_source(location); | 1998 installer->set_install_source(location); |
1999 installer->set_expected_id(id); | 1999 installer->set_expected_id(id); |
2000 installer->InstallCrx(path); | 2000 installer->InstallCrx(path); |
2001 } | 2001 } |
2002 | 2002 |
2003 void ExtensionsService::ReportExtensionLoadError( | 2003 void ExtensionService::ReportExtensionLoadError( |
2004 const FilePath& extension_path, | 2004 const FilePath& extension_path, |
2005 const std::string &error, | 2005 const std::string &error, |
2006 NotificationType type, | 2006 NotificationType type, |
2007 bool be_noisy) { | 2007 bool be_noisy) { |
2008 NotificationService* service = NotificationService::current(); | 2008 NotificationService* service = NotificationService::current(); |
2009 service->Notify(type, | 2009 service->Notify(type, |
2010 Source<Profile>(profile_), | 2010 Source<Profile>(profile_), |
2011 Details<const std::string>(&error)); | 2011 Details<const std::string>(&error)); |
2012 | 2012 |
2013 // TODO(port): note that this isn't guaranteed to work properly on Linux. | 2013 // TODO(port): note that this isn't guaranteed to work properly on Linux. |
2014 std::string path_str = WideToUTF8(extension_path.ToWStringHack()); | 2014 std::string path_str = WideToUTF8(extension_path.ToWStringHack()); |
2015 std::string message = base::StringPrintf( | 2015 std::string message = base::StringPrintf( |
2016 "Could not load extension from '%s'. %s", | 2016 "Could not load extension from '%s'. %s", |
2017 path_str.c_str(), error.c_str()); | 2017 path_str.c_str(), error.c_str()); |
2018 ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy); | 2018 ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy); |
2019 } | 2019 } |
2020 | 2020 |
2021 void ExtensionsService::DidCreateRenderViewForBackgroundPage( | 2021 void ExtensionService::DidCreateRenderViewForBackgroundPage( |
2022 ExtensionHost* host) { | 2022 ExtensionHost* host) { |
2023 OrphanedDevTools::iterator iter = | 2023 OrphanedDevTools::iterator iter = |
2024 orphaned_dev_tools_.find(host->extension()->id()); | 2024 orphaned_dev_tools_.find(host->extension()->id()); |
2025 if (iter == orphaned_dev_tools_.end()) | 2025 if (iter == orphaned_dev_tools_.end()) |
2026 return; | 2026 return; |
2027 | 2027 |
2028 DevToolsManager::GetInstance()->AttachClientHost( | 2028 DevToolsManager::GetInstance()->AttachClientHost( |
2029 iter->second, host->render_view_host()); | 2029 iter->second, host->render_view_host()); |
2030 orphaned_dev_tools_.erase(iter); | 2030 orphaned_dev_tools_.erase(iter); |
2031 } | 2031 } |
2032 | 2032 |
2033 void ExtensionsService::Observe(NotificationType type, | 2033 void ExtensionService::Observe(NotificationType type, |
2034 const NotificationSource& source, | 2034 const NotificationSource& source, |
2035 const NotificationDetails& details) { | 2035 const NotificationDetails& details) { |
2036 switch (type.value) { | 2036 switch (type.value) { |
2037 case NotificationType::EXTENSION_PROCESS_TERMINATED: { | 2037 case NotificationType::EXTENSION_PROCESS_TERMINATED: { |
2038 if (profile_ != Source<Profile>(source).ptr()->GetOriginalProfile()) | 2038 if (profile_ != Source<Profile>(source).ptr()->GetOriginalProfile()) |
2039 break; | 2039 break; |
2040 | 2040 |
2041 ExtensionHost* host = Details<ExtensionHost>(details).ptr(); | 2041 ExtensionHost* host = Details<ExtensionHost>(details).ptr(); |
2042 | 2042 |
2043 // Unload the entire extension. We want it to be in a consistent state: | 2043 // Unload the entire extension. We want it to be in a consistent state: |
2044 // either fully working or not loaded at all, but never half-crashed. | 2044 // either fully working or not loaded at all, but never half-crashed. |
2045 // We do it in a PostTask so that other handlers of this notification will | 2045 // We do it in a PostTask so that other handlers of this notification will |
2046 // still have access to the Extension and ExtensionHost. | 2046 // still have access to the Extension and ExtensionHost. |
2047 MessageLoop::current()->PostTask(FROM_HERE, | 2047 MessageLoop::current()->PostTask(FROM_HERE, |
2048 NewRunnableMethod(this, &ExtensionsService::UnloadExtension, | 2048 NewRunnableMethod(this, &ExtensionService::UnloadExtension, |
2049 host->extension()->id())); | 2049 host->extension()->id())); |
2050 break; | 2050 break; |
2051 } | 2051 } |
2052 | 2052 |
2053 case NotificationType::PREF_CHANGED: { | 2053 case NotificationType::PREF_CHANGED: { |
2054 std::string* pref_name = Details<std::string>(details).ptr(); | 2054 std::string* pref_name = Details<std::string>(details).ptr(); |
2055 if (*pref_name == prefs::kExtensionInstallAllowList || | 2055 if (*pref_name == prefs::kExtensionInstallAllowList || |
2056 *pref_name == prefs::kExtensionInstallDenyList) { | 2056 *pref_name == prefs::kExtensionInstallDenyList) { |
2057 CheckAdminBlacklist(); | 2057 CheckAdminBlacklist(); |
2058 } else if (*pref_name == prefs::kExtensionInstallForceList) { | 2058 } else if (*pref_name == prefs::kExtensionInstallForceList) { |
2059 UpdateExternalPolicyExtensionProvider(); | 2059 UpdateExternalPolicyExtensionProvider(); |
2060 CheckForExternalUpdates(); | 2060 CheckForExternalUpdates(); |
2061 // TODO(gfeher): Also check for external extensions that can be | 2061 // TODO(gfeher): Also check for external extensions that can be |
2062 // uninstalled because they were removed from the pref. | 2062 // uninstalled because they were removed from the pref. |
2063 // (crbug.com/63667) | 2063 // (crbug.com/63667) |
2064 } else { | 2064 } else { |
2065 NOTREACHED() << "Unexpected preference name."; | 2065 NOTREACHED() << "Unexpected preference name."; |
2066 } | 2066 } |
2067 break; | 2067 break; |
2068 } | 2068 } |
2069 | 2069 |
2070 default: | 2070 default: |
2071 NOTREACHED() << "Unexpected notification type."; | 2071 NOTREACHED() << "Unexpected notification type."; |
2072 } | 2072 } |
2073 } | 2073 } |
2074 | 2074 |
2075 bool ExtensionsService::HasApps() const { | 2075 bool ExtensionService::HasApps() const { |
2076 return !GetAppIds().empty(); | 2076 return !GetAppIds().empty(); |
2077 } | 2077 } |
2078 | 2078 |
2079 ExtensionIdSet ExtensionsService::GetAppIds() const { | 2079 ExtensionIdSet ExtensionService::GetAppIds() const { |
2080 ExtensionIdSet result; | 2080 ExtensionIdSet result; |
2081 for (ExtensionList::const_iterator it = extensions_.begin(); | 2081 for (ExtensionList::const_iterator it = extensions_.begin(); |
2082 it != extensions_.end(); ++it) { | 2082 it != extensions_.end(); ++it) { |
2083 if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT) | 2083 if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT) |
2084 result.insert((*it)->id()); | 2084 result.insert((*it)->id()); |
2085 } | 2085 } |
2086 | 2086 |
2087 return result; | 2087 return result; |
2088 } | 2088 } |
2089 | 2089 |
2090 bool ExtensionsService::IsBackgroundPageReady(const Extension* extension) { | 2090 bool ExtensionService::IsBackgroundPageReady(const Extension* extension) { |
2091 return (extension->background_url().is_empty() || | 2091 return (extension->background_url().is_empty() || |
2092 extension_runtime_data_[extension->id()].background_page_ready); | 2092 extension_runtime_data_[extension->id()].background_page_ready); |
2093 } | 2093 } |
2094 | 2094 |
2095 void ExtensionsService::SetBackgroundPageReady(const Extension* extension) { | 2095 void ExtensionService::SetBackgroundPageReady(const Extension* extension) { |
2096 DCHECK(!extension->background_url().is_empty()); | 2096 DCHECK(!extension->background_url().is_empty()); |
2097 extension_runtime_data_[extension->id()].background_page_ready = true; | 2097 extension_runtime_data_[extension->id()].background_page_ready = true; |
2098 NotificationService::current()->Notify( | 2098 NotificationService::current()->Notify( |
2099 NotificationType::EXTENSION_BACKGROUND_PAGE_READY, | 2099 NotificationType::EXTENSION_BACKGROUND_PAGE_READY, |
2100 Source<const Extension>(extension), | 2100 Source<const Extension>(extension), |
2101 NotificationService::NoDetails()); | 2101 NotificationService::NoDetails()); |
2102 } | 2102 } |
2103 | 2103 |
2104 bool ExtensionsService::IsBeingUpgraded(const Extension* extension) { | 2104 bool ExtensionService::IsBeingUpgraded(const Extension* extension) { |
2105 return extension_runtime_data_[extension->id()].being_upgraded; | 2105 return extension_runtime_data_[extension->id()].being_upgraded; |
2106 } | 2106 } |
2107 | 2107 |
2108 void ExtensionsService::SetBeingUpgraded(const Extension* extension, | 2108 void ExtensionService::SetBeingUpgraded(const Extension* extension, |
2109 bool value) { | 2109 bool value) { |
2110 extension_runtime_data_[extension->id()].being_upgraded = value; | 2110 extension_runtime_data_[extension->id()].being_upgraded = value; |
2111 } | 2111 } |
2112 | 2112 |
2113 PropertyBag* ExtensionsService::GetPropertyBag(const Extension* extension) { | 2113 PropertyBag* ExtensionService::GetPropertyBag(const Extension* extension) { |
2114 return &extension_runtime_data_[extension->id()].property_bag; | 2114 return &extension_runtime_data_[extension->id()].property_bag; |
2115 } | 2115 } |
OLD | NEW |