1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/extension_service.h"
6
7 #include <algorithm>
8 #include <iterator>
9 #include <set>
10
11 #include "base/command_line.h"
12 #include "base/metrics/histogram.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "base/threading/thread_restrictions.h"
18 #include "base/time/time.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chrome_notification_types.h"
21 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
22 #include "chrome/browser/extensions/component_loader.h"
23 #include "chrome/browser/extensions/crx_installer.h"
24 #include "chrome/browser/extensions/data_deleter.h"
25 #include "chrome/browser/extensions/extension_assets_manager.h"
26 #include "chrome/browser/extensions/extension_disabled_ui.h"
27 #include "chrome/browser/extensions/extension_error_controller.h"
28 #include "chrome/browser/extensions/extension_install_ui.h"
29 #include "chrome/browser/extensions/extension_special_storage_policy.h"
30 #include "chrome/browser/extensions/extension_sync_service.h"
31 #include "chrome/browser/extensions/extension_util.h"
32 #include "chrome/browser/extensions/external_install_ui.h"
33 #include "chrome/browser/extensions/external_provider_impl.h"
34 #include "chrome/browser/extensions/install_verifier.h"
35 #include "chrome/browser/extensions/installed_loader.h"
36 #include "chrome/browser/extensions/pending_extension_manager.h"
37 #include "chrome/browser/extensions/permissions_updater.h"
38 #include "chrome/browser/extensions/shared_module_service.h"
39 #include "chrome/browser/extensions/unpacked_installer.h"
40 #include "chrome/browser/extensions/updater/extension_cache.h"
41 #include "chrome/browser/extensions/updater/extension_updater.h"
42 #include "chrome/browser/profiles/profile.h"
43 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
44 #include "chrome/browser/ui/webui/favicon_source.h"
45 #include "chrome/browser/ui/webui/ntp/thumbnail_source.h"
46 #include "chrome/browser/ui/webui/theme_source.h"
47 #include "chrome/common/chrome_switches.h"
48 #include "chrome/common/crash_keys.h"
49 #include "chrome/common/extensions/extension_constants.h"
50 #include "chrome/common/extensions/features/feature_channel.h"
51 #include "chrome/common/extensions/manifest_url_handler.h"
52 #include "chrome/common/pref_names.h"
53 #include "chrome/common/url_constants.h"
54 #include "components/startup_metric_utils/startup_metric_utils.h"
55 #include "content/public/browser/devtools_agent_host.h"
56 #include "content/public/browser/notification_service.h"
57 #include "content/public/browser/render_process_host.h"
58 #include "content/public/browser/storage_partition.h"
59 #include "extensions/browser/event_router.h"
60 #include "extensions/browser/extension_host.h"
61 #include "extensions/browser/extension_prefs.h"
62 #include "extensions/browser/extension_registry.h"
63 #include "extensions/browser/extension_system.h"
64 #include "extensions/browser/install_flag.h"
65 #include "extensions/browser/pref_names.h"
66 #include "extensions/browser/runtime_data.h"
67 #include "extensions/browser/update_observer.h"
68 #include "extensions/common/extension_messages.h"
69 #include "extensions/common/feature_switch.h"
70 #include "extensions/common/file_util.h"
71 #include "extensions/common/manifest_constants.h"
72 #include "extensions/common/manifest_handlers/background_info.h"
73 #include "extensions/common/one_shot_event.h"
74 #include "extensions/common/permissions/permission_message_provider.h"
75 #include "extensions/common/permissions/permissions_data.h"
76
77 #if defined(OS_CHROMEOS)
78 #include "chrome/browser/chromeos/extensions/install_limiter.h"
79 #include "webkit/browser/fileapi/file_system_backend.h"
80 #include "webkit/browser/fileapi/file_system_context.h"
81 #endif
82
83 using content::BrowserContext;
84 using content::BrowserThread;
85 using content::DevToolsAgentHost;
86 using extensions::CrxInstaller;
87 using extensions::Extension;
88 using extensions::ExtensionIdSet;
89 using extensions::ExtensionInfo;
90 using extensions::ExtensionRegistry;
91 using extensions::ExtensionSet;
92 using extensions::FeatureSwitch;
93 using extensions::InstallVerifier;
94 using extensions::ManagementPolicy;
95 using extensions::Manifest;
96 using extensions::PermissionMessage;
97 using extensions::PermissionMessages;
98 using extensions::PermissionSet;
99 using extensions::SharedModuleInfo;
100 using extensions::SharedModuleService;
101 using extensions::UnloadedExtensionInfo;
102
103 namespace errors = extensions::manifest_errors;
104
105 namespace {
106
107 // Histogram values for logging events related to externally installed
108 // extensions.
109 enum ExternalExtensionEvent {
110 EXTERNAL_EXTENSION_INSTALLED = 0,
111 EXTERNAL_EXTENSION_IGNORED,
112 EXTERNAL_EXTENSION_REENABLED,
113 EXTERNAL_EXTENSION_UNINSTALLED,
114 EXTERNAL_EXTENSION_BUCKET_BOUNDARY,
115 };
116
117 // Prompt the user this many times before considering an extension acknowledged.
118 static const int kMaxExtensionAcknowledgePromptCount = 3;
119
120 // Wait this many seconds after an extensions becomes idle before updating it.
121 static const int kUpdateIdleDelay = 5;
122
IsCWSSharedModule(const Extension * extension)123 static bool IsCWSSharedModule(const Extension* extension) {
124 return extension->from_webstore() &&
125 SharedModuleInfo::IsSharedModule(extension);
126 }
127
128 class SharedModuleProvider : public extensions::ManagementPolicy::Provider {
129 public:
SharedModuleProvider()130 SharedModuleProvider() {}
~SharedModuleProvider()131 virtual ~SharedModuleProvider() {}
132
GetDebugPolicyProviderName() const133 virtual std::string GetDebugPolicyProviderName() const OVERRIDE {
134 return "SharedModuleProvider";
135 }
136
UserMayModifySettings(const Extension * extension,base::string16 * error) const137 virtual bool UserMayModifySettings(const Extension* extension,
138 base::string16* error) const OVERRIDE {
139 return !IsCWSSharedModule(extension);
140 }
141
MustRemainEnabled(const Extension * extension,base::string16 * error) const142 virtual bool MustRemainEnabled(const Extension* extension,
143 base::string16* error) const OVERRIDE {
144 return IsCWSSharedModule(extension);
145 }
146
147 private:
148 DISALLOW_COPY_AND_ASSIGN(SharedModuleProvider);
149 };
150
151 } // namespace
152
153 // ExtensionService.
154
CheckExternalUninstall(const std::string & id)155 void ExtensionService::CheckExternalUninstall(const std::string& id) {
156 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157
158 // Check if the providers know about this extension.
159 extensions::ProviderCollection::const_iterator i;
160 for (i = external_extension_providers_.begin();
161 i != external_extension_providers_.end(); ++i) {
162 DCHECK(i->get()->IsReady());
163 if (i->get()->HasExtension(id))
164 return; // Yup, known extension, don't uninstall.
165 }
166
167 // We get the list of external extensions to check from preferences.
168 // It is possible that an extension has preferences but is not loaded.
169 // For example, an extension that requires experimental permissions
170 // will not be loaded if the experimental command line flag is not used.
171 // In this case, do not uninstall.
172 if (!GetInstalledExtension(id)) {
173 // We can't call UninstallExtension with an unloaded/invalid
174 // extension ID.
175 LOG(WARNING) << "Attempted uninstallation of unloaded/invalid extension "
176 << "with id: " << id;
177 return;
178 }
179 UninstallExtension(id, true, NULL);
180 }
181
SetFileTaskRunnerForTesting(base::SequencedTaskRunner * task_runner)182 void ExtensionService::SetFileTaskRunnerForTesting(
183 base::SequencedTaskRunner* task_runner) {
184 file_task_runner_ = task_runner;
185 }
186
ClearProvidersForTesting()187 void ExtensionService::ClearProvidersForTesting() {
188 external_extension_providers_.clear();
189 }
190
AddProviderForTesting(extensions::ExternalProviderInterface * test_provider)191 void ExtensionService::AddProviderForTesting(
192 extensions::ExternalProviderInterface* test_provider) {
193 CHECK(test_provider);
194 external_extension_providers_.push_back(
195 linked_ptr<extensions::ExternalProviderInterface>(test_provider));
196 }
197
OnExternalExtensionUpdateUrlFound(const std::string & id,const std::string & install_parameter,const GURL & update_url,Manifest::Location location,int creation_flags,bool mark_acknowledged)198 bool ExtensionService::OnExternalExtensionUpdateUrlFound(
199 const std::string& id,
200 const std::string& install_parameter,
201 const GURL& update_url,
202 Manifest::Location location,
203 int creation_flags,
204 bool mark_acknowledged) {
205 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
206 CHECK(Extension::IdIsValid(id));
207
208 if (Manifest::IsExternalLocation(location)) {
209 // All extensions that are not user specific can be cached.
210 extensions::ExtensionCache::GetInstance()->AllowCaching(id);
211 }
212
213 const Extension* extension = GetExtensionById(id, true);
214 if (extension) {
215 // Already installed. Skip this install if the current location has
216 // higher priority than |location|.
217 Manifest::Location current = extension->location();
218 if (current == Manifest::GetHigherPriorityLocation(current, location))
219 return false;
220 // Otherwise, overwrite the current installation.
221 }
222
223 // Add |id| to the set of pending extensions. If it can not be added,
224 // then there is already a pending record from a higher-priority install
225 // source. In this case, signal that this extension will not be
226 // installed by returning false.
227 if (!pending_extension_manager()->AddFromExternalUpdateUrl(
228 id,
229 install_parameter,
230 update_url,
231 location,
232 creation_flags,
233 mark_acknowledged)) {
234 return false;
235 }
236
237 update_once_all_providers_are_ready_ = true;
238 return true;
239 }
240
241 // static
242 // This function is used to implement the command-line switch
243 // --uninstall-extension, and to uninstall an extension via sync. The LOG
244 // statements within this function are used to inform the user if the uninstall
245 // cannot be done.
UninstallExtensionHelper(ExtensionService * extensions_service,const std::string & extension_id)246 bool ExtensionService::UninstallExtensionHelper(
247 ExtensionService* extensions_service,
248 const std::string& extension_id) {
249 // We can't call UninstallExtension with an invalid extension ID.
250 if (!extensions_service->GetInstalledExtension(extension_id)) {
251 LOG(WARNING) << "Attempted uninstallation of non-existent extension with "
252 << "id: " << extension_id;
253 return false;
254 }
255
256 // The following call to UninstallExtension will not allow an uninstall of a
257 // policy-controlled extension.
258 base::string16 error;
259 if (!extensions_service->UninstallExtension(extension_id, false, &error)) {
260 LOG(WARNING) << "Cannot uninstall extension with id " << extension_id
261 << ": " << error;
262 return false;
263 }
264
265 return true;
266 }
267
ExtensionService(Profile * profile,const CommandLine * command_line,const base::FilePath & install_directory,extensions::ExtensionPrefs * extension_prefs,extensions::Blacklist * blacklist,bool autoupdate_enabled,bool extensions_enabled,extensions::OneShotEvent * ready)268 ExtensionService::ExtensionService(Profile* profile,
269 const CommandLine* command_line,
270 const base::FilePath& install_directory,
271 extensions::ExtensionPrefs* extension_prefs,
272 extensions::Blacklist* blacklist,
273 bool autoupdate_enabled,
274 bool extensions_enabled,
275 extensions::OneShotEvent* ready)
276 : extensions::Blacklist::Observer(blacklist),
277 profile_(profile),
278 system_(extensions::ExtensionSystem::Get(profile)),
279 extension_prefs_(extension_prefs),
280 blacklist_(blacklist),
281 extension_sync_service_(NULL),
282 registry_(extensions::ExtensionRegistry::Get(profile)),
283 pending_extension_manager_(profile),
284 install_directory_(install_directory),
285 extensions_enabled_(extensions_enabled),
286 show_extensions_prompts_(true),
287 install_updates_when_idle_(true),
288 ready_(ready),
289 update_once_all_providers_are_ready_(false),
290 browser_terminating_(false),
291 installs_delayed_for_gc_(false),
292 is_first_run_(false),
293 shared_module_service_(new extensions::SharedModuleService(profile_)) {
294 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
295
296 // Figure out if extension installation should be enabled.
297 if (extensions::ExtensionsBrowserClient::Get()->AreExtensionsDisabled(
298 *command_line, profile))
299 extensions_enabled_ = false;
300
301 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
302 content::NotificationService::AllBrowserContextsAndSources());
303 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
304 content::NotificationService::AllBrowserContextsAndSources());
305 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
306 content::NotificationService::AllBrowserContextsAndSources());
307 registrar_.Add(this, chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
308 content::NotificationService::AllBrowserContextsAndSources());
309 registrar_.Add(this,
310 chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED,
311 content::Source<Profile>(profile_));
312 pref_change_registrar_.Init(profile->GetPrefs());
313 base::Closure callback =
314 base::Bind(&ExtensionService::OnExtensionInstallPrefChanged,
315 base::Unretained(this));
316 pref_change_registrar_.Add(extensions::pref_names::kInstallAllowList,
317 callback);
318 pref_change_registrar_.Add(extensions::pref_names::kInstallDenyList,
319 callback);
320 pref_change_registrar_.Add(extensions::pref_names::kAllowedTypes, callback);
321
322 // Set up the ExtensionUpdater
323 if (autoupdate_enabled) {
324 int update_frequency = extensions::kDefaultUpdateFrequencySeconds;
325 if (command_line->HasSwitch(switches::kExtensionsUpdateFrequency)) {
326 base::StringToInt(command_line->GetSwitchValueASCII(
327 switches::kExtensionsUpdateFrequency),
328 &update_frequency);
329 }
330 updater_.reset(new extensions::ExtensionUpdater(
331 this,
332 extension_prefs,
333 profile->GetPrefs(),
334 profile,
335 update_frequency,
336 extensions::ExtensionCache::GetInstance()));
337 }
338
339 component_loader_.reset(
340 new extensions::ComponentLoader(this,
341 profile->GetPrefs(),
342 g_browser_process->local_state(),
343 profile));
344
345 if (extensions_enabled_) {
346 extensions::ExternalProviderImpl::CreateExternalProviders(
347 this, profile_, &external_extension_providers_);
348 }
349
350 // Set this as the ExtensionService for app sorting to ensure it causes syncs
351 // if required.
352 is_first_run_ = !extension_prefs_->SetAlertSystemFirstRun();
353
354 error_controller_.reset(
355 new extensions::ExtensionErrorController(profile_, is_first_run_));
356
357 #if defined(ENABLE_EXTENSIONS)
358 extension_action_storage_manager_.reset(
359 new extensions::ExtensionActionStorageManager(profile_));
360 #endif
361
362 shared_module_policy_provider_.reset(new SharedModuleProvider);
363
364 // How long is the path to the Extensions directory?
365 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ExtensionRootPathLength",
366 install_directory_.value().length(), 0, 500, 100);
367 }
368
extensions() const369 const ExtensionSet* ExtensionService::extensions() const {
370 return ®istry_->enabled_extensions();
371 }
372
373 extensions::PendingExtensionManager*
pending_extension_manager()374 ExtensionService::pending_extension_manager() {
375 return &pending_extension_manager_;
376 }
377
~ExtensionService()378 ExtensionService::~ExtensionService() {
379 // No need to unload extensions here because they are profile-scoped, and the
380 // profile is in the process of being deleted.
381
382 extensions::ProviderCollection::const_iterator i;
383 for (i = external_extension_providers_.begin();
384 i != external_extension_providers_.end(); ++i) {
385 extensions::ExternalProviderInterface* provider = i->get();
386 provider->ServiceShutdown();
387 }
388 }
389
Shutdown()390 void ExtensionService::Shutdown() {
391 system_->management_policy()->UnregisterProvider(
392 shared_module_policy_provider_.get());
393 }
394
GetExtensionById(const std::string & id,bool include_disabled) const395 const Extension* ExtensionService::GetExtensionById(
396 const std::string& id, bool include_disabled) const {
397 int include_mask = ExtensionRegistry::ENABLED;
398 if (include_disabled) {
399 // Include blacklisted extensions here because there are hundreds of
400 // callers of this function, and many might assume that this includes those
401 // that have been disabled due to blacklisting.
402 include_mask |= ExtensionRegistry::DISABLED |
403 ExtensionRegistry::BLACKLISTED;
404 }
405 return registry_->GetExtensionById(id, include_mask);
406 }
407
Init()408 void ExtensionService::Init() {
409 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
410
411 base::Time begin_time = base::Time::Now();
412
413 DCHECK(!is_ready()); // Can't redo init.
414 DCHECK_EQ(registry_->enabled_extensions().size(), 0u);
415
416 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
417 if (cmd_line->HasSwitch(switches::kInstallFromWebstore) ||
418 cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)) {
419 // The sole purpose of this launch is to install a new extension from CWS
420 // and immediately terminate: loading already installed extensions is
421 // unnecessary and may interfere with the inline install dialog (e.g. if an
422 // extension listens to onStartup and opens a window).
423 SetReadyAndNotifyListeners();
424 } else {
425 // LoadAllExtensions() calls OnLoadedInstalledExtensions().
426 component_loader_->LoadAll();
427 extensions::InstalledLoader(this).LoadAllExtensions();
428
429 ReconcileKnownDisabled();
430
431 // Attempt to re-enable extensions whose only disable reason is reloading.
432 std::vector<std::string> extensions_to_enable;
433 const ExtensionSet& disabled_extensions = registry_->disabled_extensions();
434 for (ExtensionSet::const_iterator iter = disabled_extensions.begin();
435 iter != disabled_extensions.end(); ++iter) {
436 const Extension* e = iter->get();
437 if (extension_prefs_->GetDisableReasons(e->id()) ==
438 Extension::DISABLE_RELOAD) {
439 extensions_to_enable.push_back(e->id());
440 }
441 }
442 for (std::vector<std::string>::iterator it = extensions_to_enable.begin();
443 it != extensions_to_enable.end(); ++it) {
444 EnableExtension(*it);
445 }
446
447 // Finish install (if possible) of extensions that were still delayed while
448 // the browser was shut down.
449 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info(
450 extension_prefs_->GetAllDelayedInstallInfo());
451 for (size_t i = 0; i < delayed_info->size(); ++i) {
452 ExtensionInfo* info = delayed_info->at(i).get();
453 scoped_refptr<const Extension> extension(NULL);
454 if (info->extension_manifest) {
455 std::string error;
456 extension = Extension::Create(
457 info->extension_path,
458 info->extension_location,
459 *info->extension_manifest,
460 extension_prefs_->GetDelayedInstallCreationFlags(
461 info->extension_id),
462 info->extension_id,
463 &error);
464 if (extension.get())
465 delayed_installs_.Insert(extension);
466 }
467 }
468 MaybeFinishDelayedInstallations();
469
470 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> delayed_info2(
471 extension_prefs_->GetAllDelayedInstallInfo());
472 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateOnLoad",
473 delayed_info2->size() - delayed_info->size());
474
475 SetReadyAndNotifyListeners();
476
477 // TODO(erikkay) this should probably be deferred to a future point
478 // rather than running immediately at startup.
479 CheckForExternalUpdates();
480
481 system_->management_policy()->RegisterProvider(
482 shared_module_policy_provider_.get());
483
484 LoadGreylistFromPrefs();
485 }
486
487 UMA_HISTOGRAM_TIMES("Extensions.ExtensionServiceInitTime",
488 base::Time::Now() - begin_time);
489 }
490
LoadGreylistFromPrefs()491 void ExtensionService::LoadGreylistFromPrefs() {
492 scoped_ptr<ExtensionSet> all_extensions =
493 registry_->GenerateInstalledExtensionsSet();
494
495 for (ExtensionSet::const_iterator it = all_extensions->begin();
496 it != all_extensions->end(); ++it) {
497 extensions::BlacklistState state =
498 extension_prefs_->GetExtensionBlacklistState((*it)->id());
499 if (state == extensions::BLACKLISTED_SECURITY_VULNERABILITY ||
500 state == extensions::BLACKLISTED_POTENTIALLY_UNWANTED ||
501 state == extensions::BLACKLISTED_CWS_POLICY_VIOLATION)
502 greylist_.Insert(*it);
503 }
504 }
505
UpdateExtension(const std::string & id,const base::FilePath & extension_path,bool file_ownership_passed,CrxInstaller ** out_crx_installer)506 bool ExtensionService::UpdateExtension(const std::string& id,
507 const base::FilePath& extension_path,
508 bool file_ownership_passed,
509 CrxInstaller** out_crx_installer) {
510 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
511 if (browser_terminating_) {
512 LOG(WARNING) << "Skipping UpdateExtension due to browser shutdown";
513 // Leak the temp file at extension_path. We don't want to add to the disk
514 // I/O burden at shutdown, we can't rely on the I/O completing anyway, and
515 // the file is in the OS temp directory which should be cleaned up for us.
516 return false;
517 }
518
519 const extensions::PendingExtensionInfo* pending_extension_info =
520 pending_extension_manager()->GetById(id);
521
522 const Extension* extension = GetInstalledExtension(id);
523 if (!pending_extension_info && !extension) {
524 LOG(WARNING) << "Will not update extension " << id
525 << " because it is not installed or pending";
526 // Delete extension_path since we're not creating a CrxInstaller
527 // that would do it for us.
528 if (!GetFileTaskRunner()->PostTask(
529 FROM_HERE,
530 base::Bind(
531 &extensions::file_util::DeleteFile, extension_path, false)))
532 NOTREACHED();
533
534 return false;
535 }
536
537 // We want a silent install only for non-pending extensions and
538 // pending extensions that have install_silently set.
539 scoped_ptr<ExtensionInstallPrompt> client;
540 if (pending_extension_info && !pending_extension_info->install_silently())
541 client.reset(ExtensionInstallUI::CreateInstallPromptWithProfile(profile_));
542
543 scoped_refptr<CrxInstaller> installer(
544 CrxInstaller::Create(this, client.Pass()));
545 installer->set_expected_id(id);
546 int creation_flags = Extension::NO_FLAGS;
547 if (pending_extension_info) {
548 installer->set_install_source(pending_extension_info->install_source());
549 if (pending_extension_info->install_silently())
550 installer->set_allow_silent_install(true);
551 if (pending_extension_info->remote_install())
552 installer->set_grant_permissions(false);
553 creation_flags = pending_extension_info->creation_flags();
554 if (pending_extension_info->mark_acknowledged())
555 AcknowledgeExternalExtension(id);
556 } else if (extension) {
557 installer->set_install_source(extension->location());
558 }
559 // If the extension was installed from or has migrated to the webstore, or
560 // its auto-update URL is from the webstore, treat it as a webstore install.
561 // Note that we ignore some older extensions with blank auto-update URLs
562 // because we are mostly concerned with restrictions on NaCl extensions,
563 // which are newer.
564 if ((extension && extension->from_webstore()) ||
565 (extension && extensions::ManifestURL::UpdatesFromGallery(extension)) ||
566 (!extension && extension_urls::IsWebstoreUpdateUrl(
567 pending_extension_info->update_url()))) {
568 creation_flags |= Extension::FROM_WEBSTORE;
569 }
570
571 // Bookmark apps being updated is kind of a contradiction, but that's because
572 // we mark the default apps as bookmark apps, and they're hosted in the web
573 // store, thus they can get updated. See http://crbug.com/101605 for more
574 // details.
575 if (extension && extension->from_bookmark())
576 creation_flags |= Extension::FROM_BOOKMARK;
577
578 if (extension && extension->was_installed_by_default())
579 creation_flags |= Extension::WAS_INSTALLED_BY_DEFAULT;
580
581 if (extension && extension->was_installed_by_oem())
582 creation_flags |= Extension::WAS_INSTALLED_BY_OEM;
583
584 if (extension) {
585 installer->set_is_ephemeral(extension_prefs_->IsEphemeralApp(id));
586 installer->set_do_not_sync(extension_prefs_->DoNotSync(id));
587 }
588
589 installer->set_creation_flags(creation_flags);
590
591 installer->set_delete_source(file_ownership_passed);
592 installer->set_install_cause(extension_misc::INSTALL_CAUSE_UPDATE);
593 installer->InstallCrx(extension_path);
594
595 if (out_crx_installer)
596 *out_crx_installer = installer.get();
597
598 return true;
599 }
600
ReloadExtension(const std::string & transient_extension_id)601 void ExtensionService::ReloadExtension(
602 // "transient" because the process of reloading may cause the reference
603 // to become invalid. Instead, use |extension_id|, a copy.
604 const std::string& transient_extension_id) {
605 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
606
607 // If the extension is already reloading, don't reload again.
608 if (extension_prefs_->GetDisableReasons(transient_extension_id) &
609 Extension::DISABLE_RELOAD) {
610 return;
611 }
612
613 // Ignore attempts to reload a blacklisted extension. Sometimes this can
614 // happen in a convoluted reload sequence triggered by the termination of a
615 // blacklisted extension and a naive attempt to reload it. For an example see
616 // http://crbug.com/373842.
617 if (registry_->blacklisted_extensions().Contains(transient_extension_id))
618 return;
619
620 base::FilePath path;
621
622 std::string extension_id = transient_extension_id;
623 const Extension* transient_current_extension =
624 GetExtensionById(extension_id, false);
625
626 // Disable the extension if it's loaded. It might not be loaded if it crashed.
627 if (transient_current_extension) {
628 // If the extension has an inspector open for its background page, detach
629 // the inspector and hang onto a cookie for it, so that we can reattach
630 // later.
631 // TODO(yoz): this is not incognito-safe!
632 extensions::ProcessManager* manager = system_->process_manager();
633 extensions::ExtensionHost* host =
634 manager->GetBackgroundHostForExtension(extension_id);
635 if (host && DevToolsAgentHost::HasFor(host->render_view_host())) {
636 // Look for an open inspector for the background page.
637 scoped_refptr<DevToolsAgentHost> agent_host =
638 DevToolsAgentHost::GetOrCreateFor(host->render_view_host());
639 agent_host->DisconnectRenderViewHost();
640 orphaned_dev_tools_[extension_id] = agent_host;
641 }
642
643 path = transient_current_extension->path();
644 // BeingUpgraded is set back to false when the extension is added.
645 system_->runtime_data()->SetBeingUpgraded(transient_current_extension,
646 true);
647 DisableExtension(extension_id, Extension::DISABLE_RELOAD);
648 reloading_extensions_.insert(extension_id);
649 } else {
650 std::map<std::string, base::FilePath>::const_iterator iter =
651 unloaded_extension_paths_.find(extension_id);
652 if (iter == unloaded_extension_paths_.end()) {
653 return;
654 }
655 path = unloaded_extension_paths_[extension_id];
656 }
657
658 transient_current_extension = NULL;
659
660 if (delayed_installs_.Contains(extension_id)) {
661 FinishDelayedInstallation(extension_id);
662 return;
663 }
664
665 // If we're reloading a component extension, use the component extension
666 // loader's reloader.
667 if (component_loader_->Exists(extension_id)) {
668 SetBeingReloaded(extension_id, true);
669 component_loader_->Reload(extension_id);
670 SetBeingReloaded(extension_id, false);
671 return;
672 }
673
674 // Check the installed extensions to see if what we're reloading was already
675 // installed.
676 SetBeingReloaded(extension_id, true);
677 scoped_ptr<ExtensionInfo> installed_extension(
678 extension_prefs_->GetInstalledExtensionInfo(extension_id));
679 if (installed_extension.get() &&
680 installed_extension->extension_manifest.get()) {
681 extensions::InstalledLoader(this).Load(*installed_extension, false);
682 } else {
683 // Otherwise, the extension is unpacked (location LOAD).
684 // We should always be able to remember the extension's path. If it's not in
685 // the map, someone failed to update |unloaded_extension_paths_|.
686 CHECK(!path.empty());
687 extensions::UnpackedInstaller::Create(this)->Load(path);
688 }
689 // When reloading is done, mark this extension as done reloading.
690 SetBeingReloaded(extension_id, false);
691 }
692
UninstallExtension(const std::string & transient_extension_id,bool external_uninstall,base::string16 * error)693 bool ExtensionService::UninstallExtension(
694 // "transient" because the process of uninstalling may cause the reference
695 // to become invalid. Instead, use |extenson->id()|.
696 const std::string& transient_extension_id,
697 bool external_uninstall,
698 base::string16* error) {
699 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
700
701 scoped_refptr<const Extension> extension =
702 GetInstalledExtension(transient_extension_id);
703
704 // Callers should not send us nonexistent extensions.
705 CHECK(extension.get());
706
707 // Policy change which triggers an uninstall will always set
708 // |external_uninstall| to true so this is the only way to uninstall
709 // managed extensions.
710 // Shared modules being uninstalled will also set |external_uninstall| to true
711 // so that we can guarantee users don't uninstall a shared module.
712 // (crbug.com/273300)
713 // TODO(rdevlin.cronin): This is probably not right. We should do something
714 // else, like include an enum IS_INTERNAL_UNINSTALL or IS_USER_UNINSTALL so
715 // we don't do this.
716 if (!external_uninstall &&
717 !system_->management_policy()->UserMayModifySettings(
718 extension.get(), error)) {
719 content::NotificationService::current()->Notify(
720 chrome::NOTIFICATION_EXTENSION_UNINSTALL_NOT_ALLOWED,
721 content::Source<Profile>(profile_),
722 content::Details<const Extension>(extension.get()));
723 return false;
724 }
725
726 syncer::SyncChange sync_change;
727 if (extension_sync_service_) {
728 sync_change = extension_sync_service_->PrepareToSyncUninstallExtension(
729 extension.get(), is_ready());
730 }
731
732 system_->install_verifier()->Remove(extension->id());
733
734 if (IsUnacknowledgedExternalExtension(extension.get())) {
735 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
736 EXTERNAL_EXTENSION_UNINSTALLED,
737 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
738 if (extensions::ManifestURL::UpdatesFromGallery(extension.get())) {
739 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventWebstore",
740 EXTERNAL_EXTENSION_UNINSTALLED,
741 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
742 } else {
743 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventNonWebstore",
744 EXTERNAL_EXTENSION_UNINSTALLED,
745 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
746 }
747 }
748 UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType",
749 extension->GetType(), 100);
750 RecordPermissionMessagesHistogram(extension.get(),
751 "Extensions.Permissions_Uninstall2");
752
753 // Unload before doing more cleanup to ensure that nothing is hanging on to
754 // any of these resources.
755 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UNINSTALL);
756
757 // Tell the backend to start deleting installed extensions on the file thread.
758 if (!Manifest::IsUnpackedLocation(extension->location())) {
759 if (!GetFileTaskRunner()->PostTask(
760 FROM_HERE,
761 base::Bind(&ExtensionService::UninstallExtensionOnFileThread,
762 extension->id(),
763 profile_,
764 install_directory_,
765 extension->path())))
766 NOTREACHED();
767 }
768
769 extensions::DataDeleter::StartDeleting(profile_, extension.get());
770
771 UntrackTerminatedExtension(extension->id());
772
773 // Notify interested parties that we've uninstalled this extension.
774 content::NotificationService::current()->Notify(
775 chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED,
776 content::Source<Profile>(profile_),
777 content::Details<const Extension>(extension.get()));
778 ExtensionRegistry::Get(profile_)->TriggerOnUninstalled(extension.get());
779
780 if (extension_sync_service_) {
781 extension_sync_service_->ProcessSyncUninstallExtension(extension->id(),
782 sync_change);
783 }
784
785 delayed_installs_.Remove(extension->id());
786
787 extension_prefs_->OnExtensionUninstalled(
788 extension->id(), extension->location(), external_uninstall);
789
790 // Track the uninstallation.
791 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionUninstalled", 1, 2);
792
793 return true;
794 }
795
796 // static
UninstallExtensionOnFileThread(const std::string & id,Profile * profile,const base::FilePath & install_dir,const base::FilePath & extension_path)797 void ExtensionService::UninstallExtensionOnFileThread(
798 const std::string& id,
799 Profile* profile,
800 const base::FilePath& install_dir,
801 const base::FilePath& extension_path) {
802 extensions::ExtensionAssetsManager* assets_manager =
803 extensions::ExtensionAssetsManager::GetInstance();
804 assets_manager->UninstallExtension(id, profile, install_dir, extension_path);
805 }
806
IsExtensionEnabled(const std::string & extension_id) const807 bool ExtensionService::IsExtensionEnabled(
808 const std::string& extension_id) const {
809 if (registry_->enabled_extensions().Contains(extension_id) ||
810 registry_->terminated_extensions().Contains(extension_id)) {
811 return true;
812 }
813
814 if (registry_->disabled_extensions().Contains(extension_id) ||
815 registry_->blacklisted_extensions().Contains(extension_id)) {
816 return false;
817 }
818
819 // If the extension hasn't been loaded yet, check the prefs for it. Assume
820 // enabled unless otherwise noted.
821 return !extension_prefs_->IsExtensionDisabled(extension_id) &&
822 !extension_prefs_->IsExtensionBlacklisted(extension_id) &&
823 !extension_prefs_->IsExternalExtensionUninstalled(extension_id);
824 }
825
EnableExtension(const std::string & extension_id)826 void ExtensionService::EnableExtension(const std::string& extension_id) {
827 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
828
829 if (IsExtensionEnabled(extension_id))
830 return;
831 const Extension* extension =
832 registry_->disabled_extensions().GetByID(extension_id);
833
834 ManagementPolicy* policy = system_->management_policy();
835 if (extension && policy->MustRemainDisabled(extension, NULL, NULL)) {
836 UMA_HISTOGRAM_COUNTS_100("Extensions.EnableDeniedByPolicy", 1);
837 return;
838 }
839
840 extension_prefs_->SetExtensionState(extension_id, Extension::ENABLED);
841 extension_prefs_->ClearDisableReasons(extension_id);
842
843 // This can happen if sync enables an extension that is not
844 // installed yet.
845 if (!extension)
846 return;
847
848 if (IsUnacknowledgedExternalExtension(extension)) {
849 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
850 EXTERNAL_EXTENSION_REENABLED,
851 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
852 if (extensions::ManifestURL::UpdatesFromGallery(extension)) {
853 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventWebstore",
854 EXTERNAL_EXTENSION_REENABLED,
855 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
856 } else {
857 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventNonWebstore",
858 EXTERNAL_EXTENSION_REENABLED,
859 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
860 }
861 AcknowledgeExternalExtension(extension->id());
862 }
863
864 // Move it over to the enabled list.
865 registry_->AddEnabled(make_scoped_refptr(extension));
866 registry_->RemoveDisabled(extension->id());
867
868 NotifyExtensionLoaded(extension);
869
870 // Notify listeners that the extension was enabled.
871 content::NotificationService::current()->Notify(
872 chrome::NOTIFICATION_EXTENSION_ENABLED,
873 content::Source<Profile>(profile_),
874 content::Details<const Extension>(extension));
875
876 if (extension_sync_service_)
877 extension_sync_service_->SyncEnableExtension(*extension);
878 }
879
DisableExtension(const std::string & extension_id,Extension::DisableReason disable_reason)880 void ExtensionService::DisableExtension(
881 const std::string& extension_id,
882 Extension::DisableReason disable_reason) {
883 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
884
885 // The extension may have been disabled already.
886 if (!IsExtensionEnabled(extension_id))
887 return;
888
889 const Extension* extension = GetInstalledExtension(extension_id);
890 // |extension| can be NULL if sync disables an extension that is not
891 // installed yet.
892 if (extension &&
893 disable_reason != Extension::DISABLE_RELOAD &&
894 !system_->management_policy()->UserMayModifySettings(extension, NULL)) {
895 return;
896 }
897
898 extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED);
899 extension_prefs_->AddDisableReason(extension_id, disable_reason);
900
901 int include_mask =
902 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::DISABLED;
903 extension = registry_->GetExtensionById(extension_id, include_mask);
904 if (!extension)
905 return;
906
907 // The extension is either enabled or terminated.
908 DCHECK(registry_->enabled_extensions().Contains(extension->id()) ||
909 registry_->terminated_extensions().Contains(extension->id()));
910
911 // Move it over to the disabled list. Don't send a second unload notification
912 // for terminated extensions being disabled.
913 registry_->AddDisabled(make_scoped_refptr(extension));
914 if (registry_->enabled_extensions().Contains(extension->id())) {
915 registry_->RemoveEnabled(extension->id());
916 NotifyExtensionUnloaded(extension, UnloadedExtensionInfo::REASON_DISABLE);
917 } else {
918 registry_->RemoveTerminated(extension->id());
919 }
920
921 if (extension_sync_service_)
922 extension_sync_service_->SyncDisableExtension(*extension);
923 }
924
DisableUserExtensions(const std::vector<std::string> & except_ids)925 void ExtensionService::DisableUserExtensions(
926 const std::vector<std::string>& except_ids) {
927 extensions::ManagementPolicy* management_policy =
928 system_->management_policy();
929 extensions::ExtensionList to_disable;
930
931 // TODO(rlp): Clean up this code. crbug.com/353266.
932 const ExtensionSet& enabled_set = registry_->enabled_extensions();
933 for (ExtensionSet::const_iterator extension = enabled_set.begin();
934 extension != enabled_set.end(); ++extension) {
935 if (management_policy->UserMayModifySettings(extension->get(), NULL) &&
936 extension->get()->location() != Manifest::EXTERNAL_COMPONENT)
937 to_disable.push_back(*extension);
938 }
939 const ExtensionSet& terminated_set = registry_->terminated_extensions();
940 for (ExtensionSet::const_iterator extension = terminated_set.begin();
941 extension != terminated_set.end(); ++extension) {
942 if (management_policy->UserMayModifySettings(extension->get(), NULL) &&
943 extension->get()->location() != Manifest::EXTERNAL_COMPONENT)
944 to_disable.push_back(*extension);
945 }
946
947 for (extensions::ExtensionList::const_iterator extension = to_disable.begin();
948 extension != to_disable.end(); ++extension) {
949 if ((*extension)->was_installed_by_default() &&
950 extension_urls::IsWebstoreUpdateUrl(
951 extensions::ManifestURL::GetUpdateURL(*extension)))
952 continue;
953 const std::string& id = (*extension)->id();
954 if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id))
955 DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION);
956 }
957 }
958
GrantPermissionsAndEnableExtension(const Extension * extension)959 void ExtensionService::GrantPermissionsAndEnableExtension(
960 const Extension* extension) {
961 GrantPermissions(extension);
962 RecordPermissionMessagesHistogram(extension,
963 "Extensions.Permissions_ReEnable2");
964 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false);
965 EnableExtension(extension->id());
966 }
967
GrantPermissions(const Extension * extension)968 void ExtensionService::GrantPermissions(const Extension* extension) {
969 CHECK(extension);
970 extensions::PermissionsUpdater(profile()).GrantActivePermissions(extension);
971 }
972
973 // static
RecordPermissionMessagesHistogram(const Extension * extension,const char * histogram)974 void ExtensionService::RecordPermissionMessagesHistogram(
975 const Extension* extension, const char* histogram) {
976 // Since this is called from multiple sources, and since the histogram macros
977 // use statics, we need to manually lookup the histogram ourselves.
978 base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
979 histogram,
980 1,
981 PermissionMessage::kEnumBoundary,
982 PermissionMessage::kEnumBoundary + 1,
983 base::HistogramBase::kUmaTargetedHistogramFlag);
984
985 PermissionMessages permissions =
986 extension->permissions_data()->GetPermissionMessages();
987 if (permissions.empty()) {
988 counter->Add(PermissionMessage::kNone);
989 } else {
990 for (PermissionMessages::iterator it = permissions.begin();
991 it != permissions.end(); ++it)
992 counter->Add(it->id());
993 }
994 }
995
NotifyExtensionLoaded(const Extension * extension)996 void ExtensionService::NotifyExtensionLoaded(const Extension* extension) {
997 // The ChromeURLRequestContexts need to be first to know that the extension
998 // was loaded, otherwise a race can arise where a renderer that is created
999 // for the extension may try to load an extension URL with an extension id
1000 // that the request context doesn't yet know about. The profile is responsible
1001 // for ensuring its URLRequestContexts appropriately discover the loaded
1002 // extension.
1003 system_->RegisterExtensionWithRequestContexts(extension);
1004
1005 // Tell renderers about the new extension, unless it's a theme (renderers
1006 // don't need to know about themes).
1007 if (!extension->is_theme()) {
1008 for (content::RenderProcessHost::iterator i(
1009 content::RenderProcessHost::AllHostsIterator());
1010 !i.IsAtEnd(); i.Advance()) {
1011 content::RenderProcessHost* host = i.GetCurrentValue();
1012 Profile* host_profile =
1013 Profile::FromBrowserContext(host->GetBrowserContext());
1014 if (host_profile->GetOriginalProfile() ==
1015 profile_->GetOriginalProfile()) {
1016 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions(
1017 1, ExtensionMsg_Loaded_Params(extension));
1018 host->Send(
1019 new ExtensionMsg_Loaded(loaded_extensions));
1020 }
1021 }
1022 }
1023
1024 // Tell subsystems that use the EXTENSION_LOADED notification about the new
1025 // extension.
1026 //
1027 // NOTE: It is important that this happen after notifying the renderers about
1028 // the new extensions so that if we navigate to an extension URL in
1029 // ExtensionRegistryObserver::OnLoaded or
1030 // NOTIFICATION_EXTENSION_LOADED_DEPRECATED, the
1031 // renderer is guaranteed to know about it.
1032 registry_->TriggerOnLoaded(extension);
1033
1034 content::NotificationService::current()->Notify(
1035 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
1036 content::Source<Profile>(profile_),
1037 content::Details<const Extension>(extension));
1038
1039 // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a
1040 // BrowserContextKeyedService and use ExtensionRegistryObserver.
1041 profile_->GetExtensionSpecialStoragePolicy()->
1042 GrantRightsForExtension(extension);
1043
1044 // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't
1045 // work properly multi-profile. Besides which, it should be using
1046 // ExtensionRegistryObserver. See http://crbug.com/355029.
1047 UpdateActiveExtensionsInCrashReporter();
1048
1049 const extensions::PermissionsData* permissions_data =
1050 extension->permissions_data();
1051
1052 // If the extension has permission to load chrome://favicon/ resources we need
1053 // to make sure that the FaviconSource is registered with the
1054 // ChromeURLDataManager.
1055 if (permissions_data->HasHostPermission(GURL(chrome::kChromeUIFaviconURL))) {
1056 FaviconSource* favicon_source = new FaviconSource(profile_,
1057 FaviconSource::FAVICON);
1058 content::URLDataSource::Add(profile_, favicon_source);
1059 }
1060
1061 #if !defined(OS_ANDROID)
1062 // Same for chrome://theme/ resources.
1063 if (permissions_data->HasHostPermission(GURL(chrome::kChromeUIThemeURL))) {
1064 ThemeSource* theme_source = new ThemeSource(profile_);
1065 content::URLDataSource::Add(profile_, theme_source);
1066 }
1067
1068 // Same for chrome://thumb/ resources.
1069 if (permissions_data->HasHostPermission(
1070 GURL(chrome::kChromeUIThumbnailURL))) {
1071 ThumbnailSource* thumbnail_source = new ThumbnailSource(profile_, false);
1072 content::URLDataSource::Add(profile_, thumbnail_source);
1073 }
1074 #endif
1075 }
1076
NotifyExtensionUnloaded(const Extension * extension,UnloadedExtensionInfo::Reason reason)1077 void ExtensionService::NotifyExtensionUnloaded(
1078 const Extension* extension,
1079 UnloadedExtensionInfo::Reason reason) {
1080 UnloadedExtensionInfo details(extension, reason);
1081
1082 registry_->TriggerOnUnloaded(extension, reason);
1083
1084 content::NotificationService::current()->Notify(
1085 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
1086 content::Source<Profile>(profile_),
1087 content::Details<UnloadedExtensionInfo>(&details));
1088
1089 for (content::RenderProcessHost::iterator i(
1090 content::RenderProcessHost::AllHostsIterator());
1091 !i.IsAtEnd(); i.Advance()) {
1092 content::RenderProcessHost* host = i.GetCurrentValue();
1093 Profile* host_profile =
1094 Profile::FromBrowserContext(host->GetBrowserContext());
1095 if (host_profile->GetOriginalProfile() == profile_->GetOriginalProfile())
1096 host->Send(new ExtensionMsg_Unloaded(extension->id()));
1097 }
1098
1099 system_->UnregisterExtensionWithRequestContexts(extension->id(), reason);
1100
1101 // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a
1102 // BrowserContextKeyedService and use ExtensionRegistryObserver.
1103 profile_->GetExtensionSpecialStoragePolicy()->
1104 RevokeRightsForExtension(extension);
1105
1106 #if defined(OS_CHROMEOS)
1107 // Revoke external file access for the extension from its file system context.
1108 // It is safe to access the extension's storage partition at this point. The
1109 // storage partition may get destroyed only after the extension gets unloaded.
1110 GURL site =
1111 extensions::util::GetSiteForExtensionId(extension->id(), profile_);
1112 fileapi::FileSystemContext* filesystem_context =
1113 BrowserContext::GetStoragePartitionForSite(profile_, site)->
1114 GetFileSystemContext();
1115 if (filesystem_context && filesystem_context->external_backend()) {
1116 filesystem_context->external_backend()->
1117 RevokeAccessForExtension(extension->id());
1118 }
1119 #endif
1120
1121 // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't
1122 // work properly multi-profile. Besides which, it should be using
1123 // ExtensionRegistryObserver::OnExtensionLoaded. See http://crbug.com/355029.
1124 UpdateActiveExtensionsInCrashReporter();
1125 }
1126
GetBrowserContext() const1127 content::BrowserContext* ExtensionService::GetBrowserContext() const {
1128 // Implemented in the .cc file to avoid adding a profile.h dependency to
1129 // extension_service.h.
1130 return profile_;
1131 }
1132
is_ready()1133 bool ExtensionService::is_ready() {
1134 return ready_->is_signaled();
1135 }
1136
GetFileTaskRunner()1137 base::SequencedTaskRunner* ExtensionService::GetFileTaskRunner() {
1138 if (file_task_runner_.get())
1139 return file_task_runner_.get();
1140
1141 // We should be able to interrupt any part of extension install process during
1142 // shutdown. SKIP_ON_SHUTDOWN ensures that not started extension install tasks
1143 // will be ignored/deleted while we will block on started tasks.
1144 std::string token("ext_install-");
1145 token.append(profile_->GetPath().AsUTF8Unsafe());
1146 file_task_runner_ = BrowserThread::GetBlockingPool()->
1147 GetSequencedTaskRunnerWithShutdownBehavior(
1148 BrowserThread::GetBlockingPool()->GetNamedSequenceToken(token),
1149 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
1150 return file_task_runner_.get();
1151 }
1152
CheckManagementPolicy()1153 void ExtensionService::CheckManagementPolicy() {
1154 std::vector<std::string> to_unload;
1155 std::map<std::string, Extension::DisableReason> to_disable;
1156
1157 // Loop through the extensions list, finding extensions we need to unload or
1158 // disable.
1159 const ExtensionSet& extensions = registry_->enabled_extensions();
1160 for (ExtensionSet::const_iterator iter = extensions.begin();
1161 iter != extensions.end(); ++iter) {
1162 const Extension* extension = (iter->get());
1163 if (!system_->management_policy()->UserMayLoad(extension, NULL))
1164 to_unload.push_back(extension->id());
1165 Extension::DisableReason disable_reason = Extension::DISABLE_NONE;
1166 if (system_->management_policy()->MustRemainDisabled(
1167 extension, &disable_reason, NULL))
1168 to_disable[extension->id()] = disable_reason;
1169 }
1170
1171 for (size_t i = 0; i < to_unload.size(); ++i)
1172 UnloadExtension(to_unload[i], UnloadedExtensionInfo::REASON_DISABLE);
1173
1174 for (std::map<std::string, Extension::DisableReason>::const_iterator i =
1175 to_disable.begin(); i != to_disable.end(); ++i)
1176 DisableExtension(i->first, i->second);
1177 }
1178
CheckForUpdatesSoon()1179 void ExtensionService::CheckForUpdatesSoon() {
1180 // This can legitimately happen in unit tests.
1181 if (!updater_.get())
1182 return;
1183
1184 if (AreAllExternalProvidersReady()) {
1185 updater_->CheckSoon();
1186 } else {
1187 // Sync can start updating before all the external providers are ready
1188 // during startup. Start the update as soon as those providers are ready,
1189 // but not before.
1190 update_once_all_providers_are_ready_ = true;
1191 }
1192 }
1193
1194 // Some extensions will autoupdate themselves externally from Chrome. These
1195 // are typically part of some larger client application package. To support
1196 // these, the extension will register its location in the the preferences file
1197 // (and also, on Windows, in the registry) and this code will periodically
1198 // check that location for a .crx file, which it will then install locally if
1199 // a new version is available.
1200 // Errors are reported through ExtensionErrorReporter. Succcess is not
1201 // reported.
CheckForExternalUpdates()1202 void ExtensionService::CheckForExternalUpdates() {
1203 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1204
1205 // Note that this installation is intentionally silent (since it didn't
1206 // go through the front-end). Extensions that are registered in this
1207 // way are effectively considered 'pre-bundled', and so implicitly
1208 // trusted. In general, if something has HKLM or filesystem access,
1209 // they could install an extension manually themselves anyway.
1210
1211 // Ask each external extension provider to give us a call back for each
1212 // extension they know about. See OnExternalExtension(File|UpdateUrl)Found.
1213 extensions::ProviderCollection::const_iterator i;
1214 for (i = external_extension_providers_.begin();
1215 i != external_extension_providers_.end(); ++i) {
1216 extensions::ExternalProviderInterface* provider = i->get();
1217 provider->VisitRegisteredExtension();
1218 }
1219
1220 // Do any required work that we would have done after completion of all
1221 // providers.
1222 if (external_extension_providers_.empty())
1223 OnAllExternalProvidersReady();
1224 }
1225
OnExternalProviderReady(const extensions::ExternalProviderInterface * provider)1226 void ExtensionService::OnExternalProviderReady(
1227 const extensions::ExternalProviderInterface* provider) {
1228 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1229 CHECK(provider->IsReady());
1230
1231 // An external provider has finished loading. We only take action
1232 // if all of them are finished. So we check them first.
1233 if (AreAllExternalProvidersReady())
1234 OnAllExternalProvidersReady();
1235 }
1236
AreAllExternalProvidersReady() const1237 bool ExtensionService::AreAllExternalProvidersReady() const {
1238 extensions::ProviderCollection::const_iterator i;
1239 for (i = external_extension_providers_.begin();
1240 i != external_extension_providers_.end(); ++i) {
1241 if (!i->get()->IsReady())
1242 return false;
1243 }
1244 return true;
1245 }
1246
OnAllExternalProvidersReady()1247 void ExtensionService::OnAllExternalProvidersReady() {
1248 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1249 base::TimeDelta elapsed = base::Time::Now() - profile_->GetStartTime();
1250 UMA_HISTOGRAM_TIMES("Extension.ExternalProvidersReadyAfter", elapsed);
1251
1252 // Install any pending extensions.
1253 if (update_once_all_providers_are_ready_ && updater()) {
1254 update_once_all_providers_are_ready_ = false;
1255 extensions::ExtensionUpdater::CheckParams params;
1256 params.callback = external_updates_finished_callback_;
1257 updater()->CheckNow(params);
1258 }
1259
1260 // Uninstall all the unclaimed extensions.
1261 scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> extensions_info(
1262 extension_prefs_->GetInstalledExtensionsInfo());
1263 for (size_t i = 0; i < extensions_info->size(); ++i) {
1264 ExtensionInfo* info = extensions_info->at(i).get();
1265 if (Manifest::IsExternalLocation(info->extension_location))
1266 CheckExternalUninstall(info->extension_id);
1267 }
1268
1269 error_controller_->ShowErrorIfNeeded();
1270
1271 UpdateExternalExtensionAlert();
1272 }
1273
AcknowledgeExternalExtension(const std::string & id)1274 void ExtensionService::AcknowledgeExternalExtension(const std::string& id) {
1275 extension_prefs_->AcknowledgeExternalExtension(id);
1276 UpdateExternalExtensionAlert();
1277 }
1278
IsUnacknowledgedExternalExtension(const Extension * extension)1279 bool ExtensionService::IsUnacknowledgedExternalExtension(
1280 const Extension* extension) {
1281 if (!FeatureSwitch::prompt_for_external_extensions()->IsEnabled())
1282 return false;
1283
1284 return (Manifest::IsExternalLocation(extension->location()) &&
1285 !extension_prefs_->IsExternalExtensionAcknowledged(extension->id()) &&
1286 !(extension_prefs_->GetDisableReasons(extension->id()) &
1287 Extension::DISABLE_SIDELOAD_WIPEOUT));
1288 }
1289
ReconcileKnownDisabled()1290 void ExtensionService::ReconcileKnownDisabled() {
1291 ExtensionIdSet known_disabled_ids;
1292 if (!extension_prefs_->GetKnownDisabled(&known_disabled_ids)) {
1293 extension_prefs_->SetKnownDisabled(
1294 registry_->disabled_extensions().GetIDs());
1295 UMA_HISTOGRAM_BOOLEAN("Extensions.KnownDisabledInitialized", true);
1296 return;
1297 }
1298
1299 // Both |known_disabled_ids| and |extensions| are ordered (by definition
1300 // of std::map and std::set). Iterate forward over both sets in parallel
1301 // to find matching IDs and disable the corresponding extensions.
1302 const ExtensionSet& enabled_set = registry_->enabled_extensions();
1303 ExtensionSet::const_iterator extensions_it = enabled_set.begin();
1304 ExtensionIdSet::const_iterator known_disabled_ids_it =
1305 known_disabled_ids.begin();
1306 int known_disabled_count = 0;
1307 while (extensions_it != enabled_set.end() &&
1308 known_disabled_ids_it != known_disabled_ids.end()) {
1309 const std::string& extension_id = extensions_it->get()->id();
1310 const int comparison = extension_id.compare(*known_disabled_ids_it);
1311 if (comparison < 0) {
1312 ++extensions_it;
1313 } else if (comparison > 0) {
1314 ++known_disabled_ids_it;
1315 } else {
1316 ++known_disabled_count;
1317 // Advance |extensions_it| immediately as it will be invalidated upon
1318 // disabling the extension it points to.
1319 ++extensions_it;
1320 ++known_disabled_ids_it;
1321 DisableExtension(extension_id, Extension::DISABLE_KNOWN_DISABLED);
1322 }
1323 }
1324 UMA_HISTOGRAM_COUNTS_100("Extensions.KnownDisabledReDisabled",
1325 known_disabled_count);
1326
1327 // Update the list of known disabled to reflect every change to
1328 // |disabled_extensions_| from this point forward.
1329 registry_->SetDisabledModificationCallback(
1330 base::Bind(&extensions::ExtensionPrefs::SetKnownDisabled,
1331 base::Unretained(extension_prefs_)));
1332 }
1333
UpdateExternalExtensionAlert()1334 void ExtensionService::UpdateExternalExtensionAlert() {
1335 if (!FeatureSwitch::prompt_for_external_extensions()->IsEnabled())
1336 return;
1337
1338 const Extension* extension = NULL;
1339 const ExtensionSet& disabled_extensions = registry_->disabled_extensions();
1340 for (ExtensionSet::const_iterator iter = disabled_extensions.begin();
1341 iter != disabled_extensions.end(); ++iter) {
1342 const Extension* e = iter->get();
1343 if (IsUnacknowledgedExternalExtension(e)) {
1344 extension = e;
1345 break;
1346 }
1347 }
1348
1349 if (extension) {
1350 if (!extensions::HasExternalInstallError(this)) {
1351 if (extension_prefs_->IncrementAcknowledgePromptCount(extension->id()) >
1352 kMaxExtensionAcknowledgePromptCount) {
1353 // Stop prompting for this extension, and check if there's another
1354 // one that needs prompting.
1355 extension_prefs_->AcknowledgeExternalExtension(extension->id());
1356 UpdateExternalExtensionAlert();
1357 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
1358 EXTERNAL_EXTENSION_IGNORED,
1359 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1360 if (extensions::ManifestURL::UpdatesFromGallery(extension)) {
1361 UMA_HISTOGRAM_ENUMERATION(
1362 "Extensions.ExternalExtensionEventWebstore",
1363 EXTERNAL_EXTENSION_IGNORED,
1364 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1365 } else {
1366 UMA_HISTOGRAM_ENUMERATION(
1367 "Extensions.ExternalExtensionEventNonWebstore",
1368 EXTERNAL_EXTENSION_IGNORED,
1369 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1370 }
1371 return;
1372 }
1373 if (is_first_run_)
1374 extension_prefs_->SetExternalInstallFirstRun(extension->id());
1375 // first_run is true if the extension was installed during a first run
1376 // (even if it's post-first run now).
1377 bool first_run = extension_prefs_->IsExternalInstallFirstRun(
1378 extension->id());
1379 extensions::AddExternalInstallError(this, extension, first_run);
1380 }
1381 } else {
1382 extensions::RemoveExternalInstallError(this);
1383 }
1384 }
1385
UnloadExtension(const std::string & extension_id,UnloadedExtensionInfo::Reason reason)1386 void ExtensionService::UnloadExtension(
1387 const std::string& extension_id,
1388 UnloadedExtensionInfo::Reason reason) {
1389 // Make sure the extension gets deleted after we return from this function.
1390 int include_mask =
1391 ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::TERMINATED;
1392 scoped_refptr<const Extension> extension(
1393 registry_->GetExtensionById(extension_id, include_mask));
1394
1395 // This method can be called via PostTask, so the extension may have been
1396 // unloaded by the time this runs.
1397 if (!extension.get()) {
1398 // In case the extension may have crashed/uninstalled. Allow the profile to
1399 // clean up its RequestContexts.
1400 system_->UnregisterExtensionWithRequestContexts(extension_id, reason);
1401 return;
1402 }
1403
1404 // Keep information about the extension so that we can reload it later
1405 // even if it's not permanently installed.
1406 unloaded_extension_paths_[extension->id()] = extension->path();
1407
1408 // Clean up if the extension is meant to be enabled after a reload.
1409 reloading_extensions_.erase(extension->id());
1410
1411 if (registry_->disabled_extensions().Contains(extension->id())) {
1412 registry_->RemoveDisabled(extension->id());
1413 // Make sure the profile cleans up its RequestContexts when an already
1414 // disabled extension is unloaded (since they are also tracking the disabled
1415 // extensions).
1416 system_->UnregisterExtensionWithRequestContexts(extension_id, reason);
1417 // Don't send the unloaded notification. It was sent when the extension
1418 // was disabled.
1419 } else {
1420 // Remove the extension from the enabled list.
1421 registry_->RemoveEnabled(extension->id());
1422 NotifyExtensionUnloaded(extension.get(), reason);
1423 }
1424
1425 content::NotificationService::current()->Notify(
1426 chrome::NOTIFICATION_EXTENSION_REMOVED,
1427 content::Source<Profile>(profile_),
1428 content::Details<const Extension>(extension.get()));
1429 }
1430
RemoveComponentExtension(const std::string & extension_id)1431 void ExtensionService::RemoveComponentExtension(
1432 const std::string& extension_id) {
1433 scoped_refptr<const Extension> extension(
1434 GetExtensionById(extension_id, false));
1435 UnloadExtension(extension_id, UnloadedExtensionInfo::REASON_UNINSTALL);
1436 if (extension.get()) {
1437 content::NotificationService::current()->Notify(
1438 chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED,
1439 content::Source<Profile>(profile_),
1440 content::Details<const Extension>(extension.get()));
1441 ExtensionRegistry::Get(profile_)->TriggerOnUninstalled(extension.get());
1442 }
1443 }
1444
UnloadAllExtensionsForTest()1445 void ExtensionService::UnloadAllExtensionsForTest() {
1446 UnloadAllExtensionsInternal();
1447 }
1448
ReloadExtensionsForTest()1449 void ExtensionService::ReloadExtensionsForTest() {
1450 // Calling UnloadAllExtensionsForTest here triggers a false-positive presubmit
1451 // warning about calling test code in production.
1452 UnloadAllExtensionsInternal();
1453 component_loader_->LoadAll();
1454 extensions::InstalledLoader(this).LoadAllExtensions();
1455 // Don't call SetReadyAndNotifyListeners() since tests call this multiple
1456 // times.
1457 }
1458
SetReadyAndNotifyListeners()1459 void ExtensionService::SetReadyAndNotifyListeners() {
1460 ready_->Signal();
1461 content::NotificationService::current()->Notify(
1462 chrome::NOTIFICATION_EXTENSIONS_READY,
1463 content::Source<Profile>(profile_),
1464 content::NotificationService::NoDetails());
1465 }
1466
OnLoadedInstalledExtensions()1467 void ExtensionService::OnLoadedInstalledExtensions() {
1468 if (updater_)
1469 updater_->Start();
1470
1471 OnBlacklistUpdated();
1472 }
1473
AddExtension(const Extension * extension)1474 void ExtensionService::AddExtension(const Extension* extension) {
1475 // TODO(jstritar): We may be able to get rid of this branch by overriding the
1476 // default extension state to DISABLED when the --disable-extensions flag
1477 // is set (http://crbug.com/29067).
1478 if (!extensions_enabled() &&
1479 !extension->is_theme() &&
1480 extension->location() != Manifest::COMPONENT &&
1481 !Manifest::IsExternalLocation(extension->location())) {
1482 return;
1483 }
1484
1485 bool is_extension_upgrade = false;
1486 bool is_extension_installed = false;
1487 const Extension* old = GetInstalledExtension(extension->id());
1488 if (old) {
1489 is_extension_installed = true;
1490 int version_compare_result =
1491 extension->version()->CompareTo(*(old->version()));
1492 is_extension_upgrade = version_compare_result > 0;
1493 // Other than for unpacked extensions, CrxInstaller should have guaranteed
1494 // that we aren't downgrading.
1495 if (!Manifest::IsUnpackedLocation(extension->location()))
1496 CHECK_GE(version_compare_result, 0);
1497 }
1498 system_->runtime_data()->SetBeingUpgraded(extension, is_extension_upgrade);
1499
1500 // The extension is now loaded, remove its data from unloaded extension map.
1501 unloaded_extension_paths_.erase(extension->id());
1502
1503 // If a terminated extension is loaded, remove it from the terminated list.
1504 UntrackTerminatedExtension(extension->id());
1505
1506 // If the extension was disabled for a reload, then enable it.
1507 bool reloading = reloading_extensions_.erase(extension->id()) > 0;
1508
1509 // Check if the extension's privileges have changed and mark the
1510 // extension disabled if necessary.
1511 CheckPermissionsIncrease(extension, is_extension_installed);
1512
1513 if (is_extension_installed && !reloading) {
1514 // To upgrade an extension in place, unload the old one and then load the
1515 // new one. ReloadExtension disables the extension, which is sufficient.
1516 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE);
1517 }
1518
1519 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) {
1520 // Only prefs is checked for the blacklist. We rely on callers to check the
1521 // blacklist before calling into here, e.g. CrxInstaller checks before
1522 // installation then threads through the install and pending install flow
1523 // of this class, and we check when loading installed extensions.
1524 registry_->AddBlacklisted(extension);
1525 } else if (!reloading &&
1526 extension_prefs_->IsExtensionDisabled(extension->id())) {
1527 registry_->AddDisabled(extension);
1528 if (extension_sync_service_)
1529 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension);
1530 content::NotificationService::current()->Notify(
1531 chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
1532 content::Source<Profile>(profile_),
1533 content::Details<const Extension>(extension));
1534
1535 // Show the extension disabled error if a permissions increase or a remote
1536 // installation is the reason it was disabled, and no other reasons exist.
1537 int reasons = extension_prefs_->GetDisableReasons(extension->id());
1538 const int kReasonMask = Extension::DISABLE_PERMISSIONS_INCREASE |
1539 Extension::DISABLE_REMOTE_INSTALL;
1540 if (reasons & kReasonMask && !(reasons & ~kReasonMask)) {
1541 extensions::AddExtensionDisabledError(
1542 this,
1543 extension,
1544 extension_prefs_->HasDisableReason(
1545 extension->id(), Extension::DISABLE_REMOTE_INSTALL));
1546 }
1547 } else if (reloading) {
1548 // Replace the old extension with the new version.
1549 CHECK(!registry_->AddDisabled(extension));
1550 EnableExtension(extension->id());
1551 } else {
1552 // All apps that are displayed in the launcher are ordered by their ordinals
1553 // so we must ensure they have valid ordinals.
1554 if (extension->RequiresSortOrdinal()) {
1555 if (!extension->ShouldDisplayInNewTabPage()) {
1556 extension_prefs_->app_sorting()->MarkExtensionAsHidden(extension->id());
1557 }
1558 extension_prefs_->app_sorting()->EnsureValidOrdinals(
1559 extension->id(), syncer::StringOrdinal());
1560 }
1561
1562 registry_->AddEnabled(extension);
1563 if (extension_sync_service_)
1564 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension);
1565 NotifyExtensionLoaded(extension);
1566 }
1567 system_->runtime_data()->SetBeingUpgraded(extension, false);
1568 }
1569
AddComponentExtension(const Extension * extension)1570 void ExtensionService::AddComponentExtension(const Extension* extension) {
1571 const std::string old_version_string(
1572 extension_prefs_->GetVersionString(extension->id()));
1573 const Version old_version(old_version_string);
1574
1575 VLOG(1) << "AddComponentExtension " << extension->name();
1576 if (!old_version.IsValid() || !old_version.Equals(*extension->version())) {
1577 VLOG(1) << "Component extension " << extension->name() << " ("
1578 << extension->id() << ") installing/upgrading from '"
1579 << old_version_string << "' to " << extension->version()->GetString();
1580
1581 AddNewOrUpdatedExtension(extension,
1582 Extension::ENABLED_COMPONENT,
1583 extensions::kInstallFlagNone,
1584 syncer::StringOrdinal(),
1585 std::string());
1586 return;
1587 }
1588
1589 AddExtension(extension);
1590 }
1591
CheckPermissionsIncrease(const Extension * extension,bool is_extension_installed)1592 void ExtensionService::CheckPermissionsIncrease(const Extension* extension,
1593 bool is_extension_installed) {
1594 extensions::PermissionsUpdater(profile_)
1595 .InitializeActivePermissions(extension);
1596
1597 // We keep track of all permissions the user has granted each extension.
1598 // This allows extensions to gracefully support backwards compatibility
1599 // by including unknown permissions in their manifests. When the user
1600 // installs the extension, only the recognized permissions are recorded.
1601 // When the unknown permissions become recognized (e.g., through browser
1602 // upgrade), we can prompt the user to accept these new permissions.
1603 // Extensions can also silently upgrade to less permissions, and then
1604 // silently upgrade to a version that adds these permissions back.
1605 //
1606 // For example, pretend that Chrome 10 includes a permission "omnibox"
1607 // for an API that adds suggestions to the omnibox. An extension can
1608 // maintain backwards compatibility while still having "omnibox" in the
1609 // manifest. If a user installs the extension on Chrome 9, the browser
1610 // will record the permissions it recognized, not including "omnibox."
1611 // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome
1612 // will disable the extension and prompt the user to approve the increase
1613 // in privileges. The extension could then release a new version that
1614 // removes the "omnibox" permission. When the user upgrades, Chrome will
1615 // still remember that "omnibox" had been granted, so that if the
1616 // extension once again includes "omnibox" in an upgrade, the extension
1617 // can upgrade without requiring this user's approval.
1618 int disable_reasons = extension_prefs_->GetDisableReasons(extension->id());
1619
1620 bool auto_grant_permission =
1621 (!is_extension_installed && extension->was_installed_by_default()) ||
1622 extensions::ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode();
1623 // Silently grant all active permissions to default apps only on install.
1624 // After install they should behave like other apps.
1625 // Silently grant all active permissions to apps install in kiosk mode on both
1626 // install and update.
1627 if (auto_grant_permission)
1628 GrantPermissions(extension);
1629
1630 bool is_privilege_increase = false;
1631 // We only need to compare the granted permissions to the current permissions
1632 // if the extension is not allowed to silently increase its permissions.
1633 if (!extensions::PermissionsData::CanSilentlyIncreasePermissions(extension) &&
1634 !auto_grant_permission) {
1635 // Add all the recognized permissions if the granted permissions list
1636 // hasn't been initialized yet.
1637 scoped_refptr<PermissionSet> granted_permissions =
1638 extension_prefs_->GetGrantedPermissions(extension->id());
1639 CHECK(granted_permissions.get());
1640
1641 // Here, we check if an extension's privileges have increased in a manner
1642 // that requires the user's approval. This could occur because the browser
1643 // upgraded and recognized additional privileges, or an extension upgrades
1644 // to a version that requires additional privileges.
1645 is_privilege_increase =
1646 extensions::PermissionMessageProvider::Get()->IsPrivilegeIncrease(
1647 granted_permissions,
1648 extension->permissions_data()->active_permissions().get(),
1649 extension->GetType());
1650 }
1651
1652 if (is_extension_installed) {
1653 // If the extension was already disabled, suppress any alerts for becoming
1654 // disabled on permissions increase.
1655 bool previously_disabled =
1656 extension_prefs_->IsExtensionDisabled(extension->id());
1657 // Legacy disabled extensions do not have a disable reason. Infer that if
1658 // there was no permission increase, it was likely disabled by the user.
1659 if (previously_disabled && disable_reasons == Extension::DISABLE_NONE &&
1660 !extension_prefs_->DidExtensionEscalatePermissions(extension->id())) {
1661 disable_reasons |= Extension::DISABLE_USER_ACTION;
1662 }
1663 // Extensions that came to us disabled from sync need a similar inference,
1664 // except based on the new version's permissions.
1665 if (previously_disabled &&
1666 disable_reasons == Extension::DISABLE_UNKNOWN_FROM_SYNC) {
1667 // Remove the DISABLE_UNKNOWN_FROM_SYNC reason.
1668 extension_prefs_->ClearDisableReasons(extension->id());
1669 if (!is_privilege_increase)
1670 disable_reasons |= Extension::DISABLE_USER_ACTION;
1671 }
1672 disable_reasons &= ~Extension::DISABLE_UNKNOWN_FROM_SYNC;
1673 }
1674
1675 // Extension has changed permissions significantly. Disable it. A
1676 // notification should be sent by the caller. If the extension is already
1677 // disabled because it was installed remotely, don't add another disable
1678 // reason, but instead always set the "did escalate permissions" flag, to
1679 // ensure enabling it will always show a warning.
1680 if (disable_reasons == Extension::DISABLE_REMOTE_INSTALL) {
1681 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true);
1682 } else if (is_privilege_increase) {
1683 disable_reasons |= Extension::DISABLE_PERMISSIONS_INCREASE;
1684 if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id())) {
1685 RecordPermissionMessagesHistogram(extension,
1686 "Extensions.Permissions_AutoDisable2");
1687 }
1688 extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED);
1689 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true);
1690 }
1691 if (disable_reasons != Extension::DISABLE_NONE) {
1692 extension_prefs_->AddDisableReason(
1693 extension->id(),
1694 static_cast<Extension::DisableReason>(disable_reasons));
1695 }
1696 }
1697
UpdateActiveExtensionsInCrashReporter()1698 void ExtensionService::UpdateActiveExtensionsInCrashReporter() {
1699 std::set<std::string> extension_ids;
1700 const ExtensionSet& extensions = registry_->enabled_extensions();
1701 for (ExtensionSet::const_iterator iter = extensions.begin();
1702 iter != extensions.end(); ++iter) {
1703 const Extension* extension = iter->get();
1704 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT)
1705 extension_ids.insert(extension->id());
1706 }
1707
1708 // TODO(kalman): This is broken. ExtensionService is per-profile.
1709 // crash_keys::SetActiveExtensions is per-process. See
1710 // http://crbug.com/355029.
1711 crash_keys::SetActiveExtensions(extension_ids);
1712 }
1713
OnExtensionInstalled(const Extension * extension,const syncer::StringOrdinal & page_ordinal,int install_flags)1714 void ExtensionService::OnExtensionInstalled(
1715 const Extension* extension,
1716 const syncer::StringOrdinal& page_ordinal,
1717 int install_flags) {
1718 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1719
1720 const std::string& id = extension->id();
1721 bool initial_enable = ShouldEnableOnInstall(extension);
1722 std::string install_parameter;
1723 const extensions::PendingExtensionInfo* pending_extension_info = NULL;
1724 if ((pending_extension_info = pending_extension_manager()->GetById(id))) {
1725 if (!pending_extension_info->ShouldAllowInstall(extension)) {
1726 pending_extension_manager()->Remove(id);
1727
1728 LOG(WARNING) << "ShouldAllowInstall() returned false for "
1729 << id << " of type " << extension->GetType()
1730 << " and update URL "
1731 << extensions::ManifestURL::GetUpdateURL(extension).spec()
1732 << "; not installing";
1733
1734 // Delete the extension directory since we're not going to
1735 // load it.
1736 if (!GetFileTaskRunner()->PostTask(
1737 FROM_HERE,
1738 base::Bind(&extensions::file_util::DeleteFile,
1739 extension->path(),
1740 true))) {
1741 NOTREACHED();
1742 }
1743 return;
1744 }
1745
1746 install_parameter = pending_extension_info->install_parameter();
1747 pending_extension_manager()->Remove(id);
1748 } else {
1749 // We explicitly want to re-enable an uninstalled external
1750 // extension; if we're here, that means the user is manually
1751 // installing the extension.
1752 if (extension_prefs_->IsExternalExtensionUninstalled(id)) {
1753 initial_enable = true;
1754 }
1755 }
1756
1757 // Unsupported requirements overrides the management policy.
1758 if (install_flags & extensions::kInstallFlagHasRequirementErrors) {
1759 initial_enable = false;
1760 extension_prefs_->AddDisableReason(
1761 id, Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
1762 // If the extension was disabled because of unsupported requirements but
1763 // now supports all requirements after an update and there are not other
1764 // disable reasons, enable it.
1765 } else if (extension_prefs_->GetDisableReasons(id) ==
1766 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) {
1767 initial_enable = true;
1768 extension_prefs_->ClearDisableReasons(id);
1769 }
1770
1771 if (install_flags & extensions::kInstallFlagIsBlacklistedForMalware) {
1772 // Installation of a blacklisted extension can happen from sync, policy,
1773 // etc, where to maintain consistency we need to install it, just never
1774 // load it (see AddExtension). Usually it should be the job of callers to
1775 // incercept blacklisted extension earlier (e.g. CrxInstaller, before even
1776 // showing the install dialogue).
1777 extension_prefs_->AcknowledgeBlacklistedExtension(id);
1778 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.SilentInstall",
1779 extension->location(),
1780 Manifest::NUM_LOCATIONS);
1781 }
1782
1783 if (!GetInstalledExtension(extension->id())) {
1784 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallType",
1785 extension->GetType(), 100);
1786 UMA_HISTOGRAM_ENUMERATION("Extensions.InstallSource",
1787 extension->location(), Manifest::NUM_LOCATIONS);
1788 RecordPermissionMessagesHistogram(extension,
1789 "Extensions.Permissions_Install2");
1790 } else {
1791 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateType",
1792 extension->GetType(), 100);
1793 UMA_HISTOGRAM_ENUMERATION("Extensions.UpdateSource",
1794 extension->location(), Manifest::NUM_LOCATIONS);
1795 }
1796
1797 // Certain extension locations are specific enough that we can
1798 // auto-acknowledge any extension that came from one of them.
1799 if (Manifest::IsPolicyLocation(extension->location()) ||
1800 extension->location() == Manifest::EXTERNAL_COMPONENT)
1801 AcknowledgeExternalExtension(extension->id());
1802 const Extension::State initial_state =
1803 initial_enable ? Extension::ENABLED : Extension::DISABLED;
1804 if (ShouldDelayExtensionUpdate(
1805 id,
1806 !!(install_flags & extensions::kInstallFlagInstallImmediately))) {
1807 extension_prefs_->SetDelayedInstallInfo(
1808 extension,
1809 initial_state,
1810 install_flags,
1811 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
1812 page_ordinal,
1813 install_parameter);
1814
1815 // Transfer ownership of |extension|.
1816 delayed_installs_.Insert(extension);
1817
1818 // Notify observers that app update is available.
1819 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
1820 OnAppUpdateAvailable(extension));
1821 return;
1822 }
1823
1824 extensions::SharedModuleService::ImportStatus status =
1825 shared_module_service_->SatisfyImports(extension);
1826 if (installs_delayed_for_gc_) {
1827 extension_prefs_->SetDelayedInstallInfo(
1828 extension,
1829 initial_state,
1830 install_flags,
1831 extensions::ExtensionPrefs::DELAY_REASON_GC,
1832 page_ordinal,
1833 install_parameter);
1834 delayed_installs_.Insert(extension);
1835 } else if (status != SharedModuleService::IMPORT_STATUS_OK) {
1836 if (status == SharedModuleService::IMPORT_STATUS_UNSATISFIED) {
1837 extension_prefs_->SetDelayedInstallInfo(
1838 extension,
1839 initial_state,
1840 install_flags,
1841 extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
1842 page_ordinal,
1843 install_parameter);
1844 delayed_installs_.Insert(extension);
1845 }
1846 } else {
1847 AddNewOrUpdatedExtension(extension,
1848 initial_state,
1849 install_flags,
1850 page_ordinal,
1851 install_parameter);
1852 }
1853 }
1854
AddNewOrUpdatedExtension(const Extension * extension,Extension::State initial_state,int install_flags,const syncer::StringOrdinal & page_ordinal,const std::string & install_parameter)1855 void ExtensionService::AddNewOrUpdatedExtension(
1856 const Extension* extension,
1857 Extension::State initial_state,
1858 int install_flags,
1859 const syncer::StringOrdinal& page_ordinal,
1860 const std::string& install_parameter) {
1861 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1862 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id());
1863 extension_prefs_->OnExtensionInstalled(
1864 extension, initial_state, page_ordinal, install_flags, install_parameter);
1865 delayed_installs_.Remove(extension->id());
1866 if (InstallVerifier::NeedsVerification(*extension))
1867 system_->install_verifier()->VerifyExtension(extension->id());
1868 FinishInstallation(extension, was_ephemeral);
1869 }
1870
MaybeFinishDelayedInstallation(const std::string & extension_id)1871 void ExtensionService::MaybeFinishDelayedInstallation(
1872 const std::string& extension_id) {
1873 // Check if the extension already got installed.
1874 if (!delayed_installs_.Contains(extension_id))
1875 return;
1876 extensions::ExtensionPrefs::DelayReason reason =
1877 extension_prefs_->GetDelayedInstallReason(extension_id);
1878
1879 // Check if the extension is idle. DELAY_REASON_NONE is used for older
1880 // preferences files that will not have set this field but it was previously
1881 // only used for idle updates.
1882 if ((reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE ||
1883 reason == extensions::ExtensionPrefs::DELAY_REASON_NONE) &&
1884 is_ready() && !extensions::util::IsExtensionIdle(extension_id, profile_))
1885 return;
1886
1887 const Extension* extension = delayed_installs_.GetByID(extension_id);
1888 if (reason == extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS) {
1889 extensions::SharedModuleService::ImportStatus status =
1890 shared_module_service_->SatisfyImports(extension);
1891 if (status != SharedModuleService::IMPORT_STATUS_OK) {
1892 if (status == SharedModuleService::IMPORT_STATUS_UNRECOVERABLE) {
1893 delayed_installs_.Remove(extension_id);
1894 // Make sure no version of the extension is actually installed, (i.e.,
1895 // that this delayed install was not an update).
1896 CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id).get());
1897 extension_prefs_->DeleteExtensionPrefs(extension_id);
1898 }
1899 return;
1900 }
1901 }
1902
1903 FinishDelayedInstallation(extension_id);
1904 }
1905
FinishDelayedInstallation(const std::string & extension_id)1906 void ExtensionService::FinishDelayedInstallation(
1907 const std::string& extension_id) {
1908 scoped_refptr<const Extension> extension(
1909 GetPendingExtensionUpdate(extension_id));
1910 CHECK(extension.get());
1911 delayed_installs_.Remove(extension_id);
1912
1913 bool was_ephemeral = extension_prefs_->IsEphemeralApp(extension->id());
1914 if (!extension_prefs_->FinishDelayedInstallInfo(extension_id))
1915 NOTREACHED();
1916
1917 FinishInstallation(extension.get(), was_ephemeral);
1918 }
1919
FinishInstallation(const Extension * extension,bool was_ephemeral)1920 void ExtensionService::FinishInstallation(
1921 const Extension* extension, bool was_ephemeral) {
1922 const extensions::Extension* existing_extension =
1923 GetInstalledExtension(extension->id());
1924 bool is_update = false;
1925 std::string old_name;
1926 if (existing_extension) {
1927 is_update = true;
1928 old_name = existing_extension->name();
1929 }
1930 bool from_ephemeral =
1931 was_ephemeral && !extension_prefs_->IsEphemeralApp(extension->id());
1932 extensions::InstalledExtensionInfo details(
1933 extension, is_update, from_ephemeral, old_name);
1934 content::NotificationService::current()->Notify(
1935 chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
1936 content::Source<Profile>(profile_),
1937 content::Details<const extensions::InstalledExtensionInfo>(&details));
1938
1939 registry_->TriggerOnWillBeInstalled(
1940 extension, is_update, from_ephemeral, old_name);
1941
1942 bool unacknowledged_external = IsUnacknowledgedExternalExtension(extension);
1943
1944 // Unpacked extensions default to allowing file access, but if that has been
1945 // overridden, don't reset the value.
1946 if (Manifest::ShouldAlwaysAllowFileAccess(extension->location()) &&
1947 !extension_prefs_->HasAllowFileAccessSetting(extension->id())) {
1948 extension_prefs_->SetAllowFileAccess(extension->id(), true);
1949 }
1950
1951 AddExtension(extension);
1952
1953 // Notify observers that need to know when an installation is complete.
1954 registry_->TriggerOnInstalled(extension);
1955
1956 // If this is a new external extension that was disabled, alert the user
1957 // so he can reenable it. We do this last so that it has already been
1958 // added to our list of extensions.
1959 if (unacknowledged_external && !is_update) {
1960 UpdateExternalExtensionAlert();
1961 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEvent",
1962 EXTERNAL_EXTENSION_INSTALLED,
1963 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1964 if (extensions::ManifestURL::UpdatesFromGallery(extension)) {
1965 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventWebstore",
1966 EXTERNAL_EXTENSION_INSTALLED,
1967 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1968 } else {
1969 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalExtensionEventNonWebstore",
1970 EXTERNAL_EXTENSION_INSTALLED,
1971 EXTERNAL_EXTENSION_BUCKET_BOUNDARY);
1972 }
1973 }
1974
1975 // Check extensions that may have been delayed only because this shared module
1976 // was not available.
1977 if (SharedModuleInfo::IsSharedModule(extension)) {
1978 MaybeFinishDelayedInstallations();
1979 }
1980 }
1981
PromoteEphemeralApp(const extensions::Extension * extension,bool is_from_sync)1982 void ExtensionService::PromoteEphemeralApp(
1983 const extensions::Extension* extension, bool is_from_sync) {
1984 DCHECK(GetInstalledExtension(extension->id()) &&
1985 extension_prefs_->IsEphemeralApp(extension->id()));
1986
1987 if (!is_from_sync) {
1988 if (extension->RequiresSortOrdinal()) {
1989 // Reset the sort ordinals of the app to ensure it is added to the default
1990 // position, like newly installed apps would.
1991 extension_prefs_->app_sorting()->ClearOrdinals(extension->id());
1992 extension_prefs_->app_sorting()->EnsureValidOrdinals(
1993 extension->id(), syncer::StringOrdinal());
1994 }
1995
1996 // Cached ephemeral apps may be updated and disabled due to permissions
1997 // increase. The app can be enabled as the install was user-acknowledged.
1998 if (extension_prefs_->DidExtensionEscalatePermissions(extension->id()))
1999 GrantPermissionsAndEnableExtension(extension);
2000 }
2001
2002 // Remove the ephemeral flags from the preferences.
2003 extension_prefs_->OnEphemeralAppPromoted(extension->id());
2004
2005 // Fire install-related events to allow observers to handle the promotion
2006 // of the ephemeral app.
2007 extensions::InstalledExtensionInfo details(
2008 extension,
2009 true /* is update */,
2010 true /* from ephemeral */,
2011 extension->name() /* old name */);
2012 content::NotificationService::current()->Notify(
2013 chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
2014 content::Source<Profile>(profile_),
2015 content::Details<const extensions::InstalledExtensionInfo>(&details));
2016
2017 registry_->TriggerOnWillBeInstalled(
2018 extension,
2019 true /* is update */,
2020 true /* from ephemeral */,
2021 extension->name() /* old name */);
2022
2023 if (registry_->enabled_extensions().Contains(extension->id())) {
2024 content::NotificationService::current()->Notify(
2025 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
2026 content::Source<Profile>(profile_),
2027 content::Details<const Extension>(extension));
2028
2029 registry_->TriggerOnLoaded(extension);
2030 }
2031
2032 registry_->TriggerOnInstalled(extension);
2033
2034 if (!is_from_sync && extension_sync_service_)
2035 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension);
2036 }
2037
GetPendingExtensionUpdate(const std::string & id) const2038 const Extension* ExtensionService::GetPendingExtensionUpdate(
2039 const std::string& id) const {
2040 return delayed_installs_.GetByID(id);
2041 }
2042
TrackTerminatedExtension(const Extension * extension)2043 void ExtensionService::TrackTerminatedExtension(const Extension* extension) {
2044 // No need to check for duplicates; inserting a duplicate is a no-op.
2045 registry_->AddTerminated(make_scoped_refptr(extension));
2046 extensions_being_terminated_.erase(extension->id());
2047 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_TERMINATE);
2048 }
2049
TerminateExtension(const std::string & extension_id)2050 void ExtensionService::TerminateExtension(const std::string& extension_id) {
2051 const Extension* extension = GetInstalledExtension(extension_id);
2052 TrackTerminatedExtension(extension);
2053 }
2054
UntrackTerminatedExtension(const std::string & id)2055 void ExtensionService::UntrackTerminatedExtension(const std::string& id) {
2056 std::string lowercase_id = StringToLowerASCII(id);
2057 const Extension* extension =
2058 registry_->terminated_extensions().GetByID(lowercase_id);
2059 registry_->RemoveTerminated(lowercase_id);
2060 if (extension) {
2061 content::NotificationService::current()->Notify(
2062 chrome::NOTIFICATION_EXTENSION_REMOVED,
2063 content::Source<Profile>(profile_),
2064 content::Details<const Extension>(extension));
2065 }
2066 }
2067
GetInstalledExtension(const std::string & id) const2068 const Extension* ExtensionService::GetInstalledExtension(
2069 const std::string& id) const {
2070 return registry_->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
2071 }
2072
OnExternalExtensionFileFound(const std::string & id,const Version * version,const base::FilePath & path,Manifest::Location location,int creation_flags,bool mark_acknowledged)2073 bool ExtensionService::OnExternalExtensionFileFound(
2074 const std::string& id,
2075 const Version* version,
2076 const base::FilePath& path,
2077 Manifest::Location location,
2078 int creation_flags,
2079 bool mark_acknowledged) {
2080 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2081 CHECK(Extension::IdIsValid(id));
2082 if (extension_prefs_->IsExternalExtensionUninstalled(id))
2083 return false;
2084
2085 // Before even bothering to unpack, check and see if we already have this
2086 // version. This is important because these extensions are going to get
2087 // installed on every startup.
2088 const Extension* existing = GetExtensionById(id, true);
2089
2090 if (existing) {
2091 // The default apps will have the location set as INTERNAL. Since older
2092 // default apps are installed as EXTERNAL, we override them. However, if the
2093 // app is already installed as internal, then do the version check.
2094 // TODO(grv) : Remove after Q1-2013.
2095 bool is_default_apps_migration =
2096 (location == Manifest::INTERNAL &&
2097 Manifest::IsExternalLocation(existing->location()));
2098
2099 if (!is_default_apps_migration) {
2100 DCHECK(version);
2101
2102 switch (existing->version()->CompareTo(*version)) {
2103 case -1: // existing version is older, we should upgrade
2104 break;
2105 case 0: // existing version is same, do nothing
2106 return false;
2107 case 1: // existing version is newer, uh-oh
2108 LOG(WARNING) << "Found external version of extension " << id
2109 << "that is older than current version. Current version "
2110 << "is: " << existing->VersionString() << ". New "
2111 << "version is: " << version->GetString()
2112 << ". Keeping current version.";
2113 return false;
2114 }
2115 }
2116 }
2117
2118 // If the extension is already pending, don't start an install.
2119 if (!pending_extension_manager()->AddFromExternalFile(
2120 id, location, *version, creation_flags, mark_acknowledged)) {
2121 return false;
2122 }
2123
2124 // no client (silent install)
2125 scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this));
2126 installer->set_install_source(location);
2127 installer->set_expected_id(id);
2128 installer->set_expected_version(*version);
2129 installer->set_install_cause(extension_misc::INSTALL_CAUSE_EXTERNAL_FILE);
2130 installer->set_creation_flags(creation_flags);
2131 #if defined(OS_CHROMEOS)
2132 extensions::InstallLimiter::Get(profile_)->Add(installer, path);
2133 #else
2134 installer->InstallCrx(path);
2135 #endif
2136
2137 // Depending on the source, a new external extension might not need a user
2138 // notification on installation. For such extensions, mark them acknowledged
2139 // now to suppress the notification.
2140 if (mark_acknowledged)
2141 AcknowledgeExternalExtension(id);
2142
2143 return true;
2144 }
2145
DidCreateRenderViewForBackgroundPage(extensions::ExtensionHost * host)2146 void ExtensionService::DidCreateRenderViewForBackgroundPage(
2147 extensions::ExtensionHost* host) {
2148 OrphanedDevTools::iterator iter =
2149 orphaned_dev_tools_.find(host->extension_id());
2150 if (iter == orphaned_dev_tools_.end())
2151 return;
2152
2153 iter->second->ConnectRenderViewHost(host->render_view_host());
2154 orphaned_dev_tools_.erase(iter);
2155 }
2156
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)2157 void ExtensionService::Observe(int type,
2158 const content::NotificationSource& source,
2159 const content::NotificationDetails& details) {
2160 switch (type) {
2161 case chrome::NOTIFICATION_APP_TERMINATING:
2162 // Shutdown has started. Don't start any more extension installs.
2163 // (We cannot use ExtensionService::Shutdown() for this because it
2164 // happens too late in browser teardown.)
2165 browser_terminating_ = true;
2166 break;
2167 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: {
2168 if (profile_ !=
2169 content::Source<Profile>(source).ptr()->GetOriginalProfile()) {
2170 break;
2171 }
2172
2173 extensions::ExtensionHost* host =
2174 content::Details<extensions::ExtensionHost>(details).ptr();
2175
2176 // If the extension is already being terminated, there is nothing left to
2177 // do.
2178 if (!extensions_being_terminated_.insert(host->extension_id()).second)
2179 break;
2180
2181 // Mark the extension as terminated and Unload it. We want it to
2182 // be in a consistent state: either fully working or not loaded
2183 // at all, but never half-crashed. We do it in a PostTask so
2184 // that other handlers of this notification will still have
2185 // access to the Extension and ExtensionHost.
2186 base::MessageLoop::current()->PostTask(
2187 FROM_HERE,
2188 base::Bind(
2189 &ExtensionService::TrackTerminatedExtension,
2190 AsWeakPtr(),
2191 host->extension()));
2192 break;
2193 }
2194 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
2195 content::RenderProcessHost* process =
2196 content::Source<content::RenderProcessHost>(source).ptr();
2197 Profile* host_profile =
2198 Profile::FromBrowserContext(process->GetBrowserContext());
2199 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile()))
2200 break;
2201
2202 extensions::ProcessMap* process_map =
2203 extensions::ProcessMap::Get(profile_);
2204 if (process_map->Contains(process->GetID())) {
2205 // An extension process was terminated, this might have resulted in an
2206 // app or extension becoming idle.
2207 std::set<std::string> extension_ids =
2208 process_map->GetExtensionsInProcess(process->GetID());
2209 for (std::set<std::string>::const_iterator it = extension_ids.begin();
2210 it != extension_ids.end(); ++it) {
2211 if (delayed_installs_.Contains(*it)) {
2212 base::MessageLoop::current()->PostDelayedTask(
2213 FROM_HERE,
2214 base::Bind(&ExtensionService::MaybeFinishDelayedInstallation,
2215 AsWeakPtr(), *it),
2216 base::TimeDelta::FromSeconds(kUpdateIdleDelay));
2217 }
2218 }
2219 }
2220
2221 process_map->RemoveAllFromProcess(process->GetID());
2222 BrowserThread::PostTask(
2223 BrowserThread::IO,
2224 FROM_HERE,
2225 base::Bind(&extensions::InfoMap::UnregisterAllExtensionsInProcess,
2226 system_->info_map(),
2227 process->GetID()));
2228 break;
2229 }
2230 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: {
2231 // Notify observers that chrome update is available.
2232 FOR_EACH_OBSERVER(extensions::UpdateObserver, update_observers_,
2233 OnChromeUpdateAvailable());
2234 break;
2235 }
2236 case chrome::NOTIFICATION_PROFILE_DESTRUCTION_STARTED: {
2237 OnProfileDestructionStarted();
2238 break;
2239 }
2240
2241 default:
2242 NOTREACHED() << "Unexpected notification type.";
2243 }
2244 }
2245
OnExtensionInstallPrefChanged()2246 void ExtensionService::OnExtensionInstallPrefChanged() {
2247 error_controller_->ShowErrorIfNeeded();
2248 CheckManagementPolicy();
2249 }
2250
IsBeingReloaded(const std::string & extension_id) const2251 bool ExtensionService::IsBeingReloaded(
2252 const std::string& extension_id) const {
2253 return ContainsKey(extensions_being_reloaded_, extension_id);
2254 }
2255
SetBeingReloaded(const std::string & extension_id,bool isBeingReloaded)2256 void ExtensionService::SetBeingReloaded(const std::string& extension_id,
2257 bool isBeingReloaded) {
2258 if (isBeingReloaded)
2259 extensions_being_reloaded_.insert(extension_id);
2260 else
2261 extensions_being_reloaded_.erase(extension_id);
2262 }
2263
ShouldEnableOnInstall(const Extension * extension)2264 bool ExtensionService::ShouldEnableOnInstall(const Extension* extension) {
2265 // Extensions installed by policy can't be disabled. So even if a previous
2266 // installation disabled the extension, make sure it is now enabled.
2267 // TODO(rlp): Clean up the special case for external components as noted
2268 // in crbug.com/353266. For now, EXTERNAL_COMPONENT apps should be
2269 // default enabled on install as before.
2270 if (system_->management_policy()->MustRemainEnabled(extension, NULL) ||
2271 extension->location() == Manifest::EXTERNAL_COMPONENT) {
2272 return true;
2273 }
2274
2275 if (extension_prefs_->IsExtensionDisabled(extension->id()))
2276 return false;
2277
2278 if (FeatureSwitch::prompt_for_external_extensions()->IsEnabled()) {
2279 // External extensions are initially disabled. We prompt the user before
2280 // enabling them. Hosted apps are excepted because they are not dangerous
2281 // (they need to be launched by the user anyway).
2282 if (extension->GetType() != Manifest::TYPE_HOSTED_APP &&
2283 Manifest::IsExternalLocation(extension->location()) &&
2284 !extension_prefs_->IsExternalExtensionAcknowledged(extension->id())) {
2285 return false;
2286 }
2287 }
2288
2289 return true;
2290 }
2291
ShouldDelayExtensionUpdate(const std::string & extension_id,bool install_immediately) const2292 bool ExtensionService::ShouldDelayExtensionUpdate(
2293 const std::string& extension_id,
2294 bool install_immediately) const {
2295 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable";
2296
2297 // If delayed updates are globally disabled, or just for this extension,
2298 // don't delay.
2299 if (!install_updates_when_idle_ || install_immediately)
2300 return false;
2301
2302 const Extension* old = GetInstalledExtension(extension_id);
2303 // If there is no old extension, this is not an update, so don't delay.
2304 if (!old)
2305 return false;
2306
2307 if (extensions::BackgroundInfo::HasPersistentBackgroundPage(old)) {
2308 // Delay installation if the extension listens for the onUpdateAvailable
2309 // event.
2310 return system_->event_router()->ExtensionHasEventListener(
2311 extension_id, kOnUpdateAvailableEvent);
2312 } else {
2313 // Delay installation if the extension is not idle.
2314 return !extensions::util::IsExtensionIdle(extension_id, profile_);
2315 }
2316 }
2317
OnGarbageCollectIsolatedStorageStart()2318 void ExtensionService::OnGarbageCollectIsolatedStorageStart() {
2319 DCHECK(!installs_delayed_for_gc_);
2320 installs_delayed_for_gc_ = true;
2321 }
2322
OnGarbageCollectIsolatedStorageFinished()2323 void ExtensionService::OnGarbageCollectIsolatedStorageFinished() {
2324 DCHECK(installs_delayed_for_gc_);
2325 installs_delayed_for_gc_ = false;
2326 MaybeFinishDelayedInstallations();
2327 }
2328
MaybeFinishDelayedInstallations()2329 void ExtensionService::MaybeFinishDelayedInstallations() {
2330 std::vector<std::string> to_be_installed;
2331 for (ExtensionSet::const_iterator it = delayed_installs_.begin();
2332 it != delayed_installs_.end();
2333 ++it) {
2334 to_be_installed.push_back((*it)->id());
2335 }
2336 for (std::vector<std::string>::const_iterator it = to_be_installed.begin();
2337 it != to_be_installed.end();
2338 ++it) {
2339 MaybeFinishDelayedInstallation(*it);
2340 }
2341 }
2342
OnBlacklistUpdated()2343 void ExtensionService::OnBlacklistUpdated() {
2344 blacklist_->GetBlacklistedIDs(
2345 registry_->GenerateInstalledExtensionsSet()->GetIDs(),
2346 base::Bind(&ExtensionService::ManageBlacklist, AsWeakPtr()));
2347 }
2348
ManageBlacklist(const extensions::Blacklist::BlacklistStateMap & state_map)2349 void ExtensionService::ManageBlacklist(
2350 const extensions::Blacklist::BlacklistStateMap& state_map) {
2351 DCHECK_CURRENTLY_ON(BrowserThread::UI);
2352
2353 std::set<std::string> blocked;
2354 ExtensionIdSet greylist;
2355 ExtensionIdSet unchanged;
2356 for (extensions::Blacklist::BlacklistStateMap::const_iterator it =
2357 state_map.begin();
2358 it != state_map.end();
2359 ++it) {
2360 switch (it->second) {
2361 case extensions::NOT_BLACKLISTED:
2362 break;
2363
2364 case extensions::BLACKLISTED_MALWARE:
2365 blocked.insert(it->first);
2366 break;
2367
2368 case extensions::BLACKLISTED_SECURITY_VULNERABILITY:
2369 case extensions::BLACKLISTED_CWS_POLICY_VIOLATION:
2370 case extensions::BLACKLISTED_POTENTIALLY_UNWANTED:
2371 greylist.insert(it->first);
2372 break;
2373
2374 case extensions::BLACKLISTED_UNKNOWN:
2375 unchanged.insert(it->first);
2376 break;
2377 }
2378 }
2379
2380 UpdateBlockedExtensions(blocked, unchanged);
2381 UpdateGreylistedExtensions(greylist, unchanged, state_map);
2382
2383 error_controller_->ShowErrorIfNeeded();
2384 }
2385
2386 namespace {
Partition(const ExtensionIdSet & before,const ExtensionIdSet & after,const ExtensionIdSet & unchanged,ExtensionIdSet * no_longer,ExtensionIdSet * not_yet)2387 void Partition(const ExtensionIdSet& before,
2388 const ExtensionIdSet& after,
2389 const ExtensionIdSet& unchanged,
2390 ExtensionIdSet* no_longer,
2391 ExtensionIdSet* not_yet) {
2392 *not_yet = base::STLSetDifference<ExtensionIdSet>(after, before);
2393 *no_longer = base::STLSetDifference<ExtensionIdSet>(before, after);
2394 *no_longer = base::STLSetDifference<ExtensionIdSet>(*no_longer, unchanged);
2395 }
2396 } // namespace
2397
UpdateBlockedExtensions(const ExtensionIdSet & blocked,const ExtensionIdSet & unchanged)2398 void ExtensionService::UpdateBlockedExtensions(
2399 const ExtensionIdSet& blocked,
2400 const ExtensionIdSet& unchanged) {
2401 ExtensionIdSet not_yet_blocked, no_longer_blocked;
2402 Partition(registry_->blacklisted_extensions().GetIDs(),
2403 blocked, unchanged,
2404 &no_longer_blocked, ¬_yet_blocked);
2405
2406 for (ExtensionIdSet::iterator it = no_longer_blocked.begin();
2407 it != no_longer_blocked.end(); ++it) {
2408 scoped_refptr<const Extension> extension =
2409 registry_->blacklisted_extensions().GetByID(*it);
2410 if (!extension.get()) {
2411 NOTREACHED() << "Extension " << *it << " no longer blocked, "
2412 << "but it was never blocked.";
2413 continue;
2414 }
2415 registry_->RemoveBlacklisted(*it);
2416 extension_prefs_->SetExtensionBlacklisted(extension->id(), false);
2417 AddExtension(extension.get());
2418 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled",
2419 extension->location(),
2420 Manifest::NUM_LOCATIONS);
2421 }
2422
2423 for (ExtensionIdSet::iterator it = not_yet_blocked.begin();
2424 it != not_yet_blocked.end(); ++it) {
2425 scoped_refptr<const Extension> extension = GetInstalledExtension(*it);
2426 if (!extension.get()) {
2427 NOTREACHED() << "Extension " << *it << " needs to be "
2428 << "blacklisted, but it's not installed.";
2429 continue;
2430 }
2431 registry_->AddBlacklisted(extension);
2432 extension_prefs_->SetExtensionBlacklistState(
2433 extension->id(), extensions::BLACKLISTED_MALWARE);
2434 UnloadExtension(*it, UnloadedExtensionInfo::REASON_BLACKLIST);
2435 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled",
2436 extension->location(), Manifest::NUM_LOCATIONS);
2437 }
2438 }
2439
2440 // TODO(oleg): UMA logging
UpdateGreylistedExtensions(const ExtensionIdSet & greylist,const ExtensionIdSet & unchanged,const extensions::Blacklist::BlacklistStateMap & state_map)2441 void ExtensionService::UpdateGreylistedExtensions(
2442 const ExtensionIdSet& greylist,
2443 const ExtensionIdSet& unchanged,
2444 const extensions::Blacklist::BlacklistStateMap& state_map) {
2445 ExtensionIdSet not_yet_greylisted, no_longer_greylisted;
2446 Partition(greylist_.GetIDs(),
2447 greylist, unchanged,
2448 &no_longer_greylisted, ¬_yet_greylisted);
2449
2450 for (ExtensionIdSet::iterator it = no_longer_greylisted.begin();
2451 it != no_longer_greylisted.end(); ++it) {
2452 scoped_refptr<const Extension> extension = greylist_.GetByID(*it);
2453 if (!extension.get()) {
2454 NOTREACHED() << "Extension " << *it << " no longer greylisted, "
2455 << "but it was not marked as greylisted.";
2456 continue;
2457 }
2458
2459 greylist_.Remove(*it);
2460 extension_prefs_->SetExtensionBlacklistState(extension->id(),
2461 extensions::NOT_BLACKLISTED);
2462 if (extension_prefs_->GetDisableReasons(extension->id()) &
2463 extensions::Extension::DISABLE_GREYLIST)
2464 EnableExtension(*it);
2465 }
2466
2467 for (ExtensionIdSet::iterator it = not_yet_greylisted.begin();
2468 it != not_yet_greylisted.end(); ++it) {
2469 scoped_refptr<const Extension> extension = GetInstalledExtension(*it);
2470 if (!extension.get()) {
2471 NOTREACHED() << "Extension " << *it << " needs to be "
2472 << "disabled, but it's not installed.";
2473 continue;
2474 }
2475 greylist_.Insert(extension);
2476 extension_prefs_->SetExtensionBlacklistState(extension->id(),
2477 state_map.find(*it)->second);
2478 if (registry_->enabled_extensions().Contains(extension->id()))
2479 DisableExtension(*it, extensions::Extension::DISABLE_GREYLIST);
2480 }
2481 }
2482
AddUpdateObserver(extensions::UpdateObserver * observer)2483 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) {
2484 update_observers_.AddObserver(observer);
2485 }
2486
RemoveUpdateObserver(extensions::UpdateObserver * observer)2487 void ExtensionService::RemoveUpdateObserver(
2488 extensions::UpdateObserver* observer) {
2489 update_observers_.RemoveObserver(observer);
2490 }
2491
2492 // Used only by test code.
UnloadAllExtensionsInternal()2493 void ExtensionService::UnloadAllExtensionsInternal() {
2494 profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions();
2495
2496 registry_->ClearAll();
2497 system_->runtime_data()->ClearAll();
2498
2499 // TODO(erikkay) should there be a notification for this? We can't use
2500 // EXTENSION_UNLOADED since that implies that the extension has been disabled
2501 // or uninstalled.
2502 }
2503
OnProfileDestructionStarted()2504 void ExtensionService::OnProfileDestructionStarted() {
2505 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs();
2506 for (ExtensionIdSet::iterator it = ids_to_unload.begin();
2507 it != ids_to_unload.end();
2508 ++it) {
2509 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN);
2510 }
2511 }
2512