OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_service.h" | 5 #include "chrome/browser/extensions/extension_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <set> | 9 #include <set> |
10 | 10 |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 pending_extension_manager_(profile), | 263 pending_extension_manager_(profile), |
264 install_directory_(install_directory), | 264 install_directory_(install_directory), |
265 extensions_enabled_(extensions_enabled), | 265 extensions_enabled_(extensions_enabled), |
266 show_extensions_prompts_(true), | 266 show_extensions_prompts_(true), |
267 install_updates_when_idle_(true), | 267 install_updates_when_idle_(true), |
268 ready_(ready), | 268 ready_(ready), |
269 update_once_all_providers_are_ready_(false), | 269 update_once_all_providers_are_ready_(false), |
270 browser_terminating_(false), | 270 browser_terminating_(false), |
271 installs_delayed_for_gc_(false), | 271 installs_delayed_for_gc_(false), |
272 is_first_run_(false), | 272 is_first_run_(false), |
273 block_extensions_(false), | |
273 shared_module_service_(new extensions::SharedModuleService(profile_)) { | 274 shared_module_service_(new extensions::SharedModuleService(profile_)) { |
274 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 275 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
275 | 276 |
276 // Figure out if extension installation should be enabled. | 277 // Figure out if extension installation should be enabled. |
277 if (extensions::ExtensionsBrowserClient::Get()->AreExtensionsDisabled( | 278 if (extensions::ExtensionsBrowserClient::Get()->AreExtensionsDisabled( |
278 *command_line, profile)) | 279 *command_line, profile)) |
279 extensions_enabled_ = false; | 280 extensions_enabled_ = false; |
280 | 281 |
281 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, | 282 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, |
282 content::NotificationService::AllBrowserContextsAndSources()); | 283 content::NotificationService::AllBrowserContextsAndSources()); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 ->GetForBrowserContext(profile()) | 368 ->GetForBrowserContext(profile()) |
368 ->RemoveObserver(this); | 369 ->RemoveObserver(this); |
369 system_->management_policy()->UnregisterProvider( | 370 system_->management_policy()->UnregisterProvider( |
370 shared_module_policy_provider_.get()); | 371 shared_module_policy_provider_.get()); |
371 } | 372 } |
372 | 373 |
373 const Extension* ExtensionService::GetExtensionById( | 374 const Extension* ExtensionService::GetExtensionById( |
374 const std::string& id, bool include_disabled) const { | 375 const std::string& id, bool include_disabled) const { |
375 int include_mask = ExtensionRegistry::ENABLED; | 376 int include_mask = ExtensionRegistry::ENABLED; |
376 if (include_disabled) { | 377 if (include_disabled) { |
377 // Include blacklisted extensions here because there are hundreds of | 378 // Include blacklisted and blocked extensions here because there are |
378 // callers of this function, and many might assume that this includes those | 379 // hundreds of callers of this function, and many might assume that this |
379 // that have been disabled due to blacklisting. | 380 // includes those that have been disabled due to blacklisting or blocking. |
380 include_mask |= ExtensionRegistry::DISABLED | | 381 include_mask |= ExtensionRegistry::DISABLED | |
381 ExtensionRegistry::BLACKLISTED; | 382 ExtensionRegistry::BLACKLISTED | |
383 ExtensionRegistry::BLOCKED; | |
382 } | 384 } |
383 return registry_->GetExtensionById(id, include_mask); | 385 return registry_->GetExtensionById(id, include_mask); |
384 } | 386 } |
385 | 387 |
386 void ExtensionService::Init() { | 388 void ExtensionService::Init() { |
387 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 389 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
388 | 390 |
389 base::Time begin_time = base::Time::Now(); | 391 base::Time begin_time = base::Time::Now(); |
390 | 392 |
391 DCHECK(!is_ready()); // Can't redo init. | 393 DCHECK(!is_ready()); // Can't redo init. |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
572 const std::string& transient_extension_id, | 574 const std::string& transient_extension_id, |
573 bool be_noisy) { | 575 bool be_noisy) { |
574 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 576 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
575 | 577 |
576 // If the extension is already reloading, don't reload again. | 578 // If the extension is already reloading, don't reload again. |
577 if (extension_prefs_->GetDisableReasons(transient_extension_id) & | 579 if (extension_prefs_->GetDisableReasons(transient_extension_id) & |
578 Extension::DISABLE_RELOAD) { | 580 Extension::DISABLE_RELOAD) { |
579 return; | 581 return; |
580 } | 582 } |
581 | 583 |
582 // Ignore attempts to reload a blacklisted extension. Sometimes this can | 584 // Ignore attempts to reload a blacklisted or blocked extension. Sometimes |
583 // happen in a convoluted reload sequence triggered by the termination of a | 585 // this can happen in a convoluted reload sequence triggered by the |
584 // blacklisted extension and a naive attempt to reload it. For an example see | 586 // termination of a blacklisted or blocked extension and a naive attempt to |
585 // http://crbug.com/373842. | 587 // reload it. For an example see http://crbug.com/373842. |
586 if (registry_->blacklisted_extensions().Contains(transient_extension_id)) | 588 if (registry_->blacklisted_extensions().Contains(transient_extension_id) || |
589 registry_->blocked_extensions().Contains(transient_extension_id)) { | |
587 return; | 590 return; |
591 } | |
588 | 592 |
589 base::FilePath path; | 593 base::FilePath path; |
590 | 594 |
591 std::string extension_id = transient_extension_id; | 595 std::string extension_id = transient_extension_id; |
592 const Extension* transient_current_extension = | 596 const Extension* transient_current_extension = |
593 GetExtensionById(extension_id, false); | 597 GetExtensionById(extension_id, false); |
594 | 598 |
595 // Disable the extension if it's loaded. It might not be loaded if it crashed. | 599 // Disable the extension if it's loaded. It might not be loaded if it crashed. |
596 if (transient_current_extension) { | 600 if (transient_current_extension) { |
597 // If the extension has an inspector open for its background page, detach | 601 // If the extension has an inspector open for its background page, detach |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
782 } | 786 } |
783 | 787 |
784 bool ExtensionService::IsExtensionEnabled( | 788 bool ExtensionService::IsExtensionEnabled( |
785 const std::string& extension_id) const { | 789 const std::string& extension_id) const { |
786 if (registry_->enabled_extensions().Contains(extension_id) || | 790 if (registry_->enabled_extensions().Contains(extension_id) || |
787 registry_->terminated_extensions().Contains(extension_id)) { | 791 registry_->terminated_extensions().Contains(extension_id)) { |
788 return true; | 792 return true; |
789 } | 793 } |
790 | 794 |
791 if (registry_->disabled_extensions().Contains(extension_id) || | 795 if (registry_->disabled_extensions().Contains(extension_id) || |
792 registry_->blacklisted_extensions().Contains(extension_id)) { | 796 registry_->blacklisted_extensions().Contains(extension_id) || |
797 registry_->blocked_extensions().Contains(extension_id)) { | |
793 return false; | 798 return false; |
794 } | 799 } |
795 | 800 |
796 // If the extension hasn't been loaded yet, check the prefs for it. Assume | 801 // If the extension hasn't been loaded yet, check the prefs for it. Assume |
797 // enabled unless otherwise noted. | 802 // enabled unless otherwise noted. |
798 return !extension_prefs_->IsExtensionDisabled(extension_id) && | 803 return !extension_prefs_->IsExtensionDisabled(extension_id) && |
799 !extension_prefs_->IsExtensionBlacklisted(extension_id) && | 804 !extension_prefs_->IsExtensionBlacklisted(extension_id) && |
805 !extension_prefs_->IsExtensionBlocked(extension_id) && | |
800 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); | 806 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); |
801 } | 807 } |
802 | 808 |
803 void ExtensionService::EnableExtension(const std::string& extension_id) { | 809 void ExtensionService::EnableExtension(const std::string& extension_id) { |
804 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 810 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
805 | 811 |
806 if (IsExtensionEnabled(extension_id)) | 812 if (IsExtensionEnabled(extension_id)) |
807 return; | 813 return; |
808 const Extension* extension = | 814 const Extension* extension = |
809 registry_->disabled_extensions().GetByID(extension_id); | 815 registry_->disabled_extensions().GetByID(extension_id); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
913 if ((*extension)->was_installed_by_default() && | 919 if ((*extension)->was_installed_by_default() && |
914 extension_urls::IsWebstoreUpdateUrl( | 920 extension_urls::IsWebstoreUpdateUrl( |
915 extensions::ManifestURL::GetUpdateURL(extension->get()))) | 921 extensions::ManifestURL::GetUpdateURL(extension->get()))) |
916 continue; | 922 continue; |
917 const std::string& id = (*extension)->id(); | 923 const std::string& id = (*extension)->id(); |
918 if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id)) | 924 if (except_ids.end() == std::find(except_ids.begin(), except_ids.end(), id)) |
919 DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION); | 925 DisableExtension(id, extensions::Extension::DISABLE_USER_ACTION); |
920 } | 926 } |
921 } | 927 } |
922 | 928 |
929 // Extensions that are not locked, components or forced by policy should be | |
930 // locked. Extensions are no longer considered enabled or disabled. Blacklisted | |
931 // extensions are now considered both blacklisted and locked. | |
932 void ExtensionService::BlockAllExtensions() { | |
not at google - send to devlin
2014/11/12 23:41:43
Oh, you might want to check that it's not already
Mike Lerman
2014/11/13 15:30:05
There's no reason this method couldn't be called m
| |
933 block_extensions_ = true; | |
934 scoped_ptr<ExtensionSet> extensions = | |
935 registry_->GenerateInstalledExtensionsSet(); | |
936 | |
937 ExtensionIdSet to_lock; | |
not at google - send to devlin
2014/11/12 23:41:43
You can delete this now.
Mike Lerman
2014/11/13 15:30:05
Bye bye!
| |
938 for (const scoped_refptr<const Extension> extension : *extensions.get()) { | |
939 const std::string& id = extension.get()->id(); | |
not at google - send to devlin
2014/11/12 23:41:43
just extension->id();
Mike Lerman
2014/11/13 15:30:04
Done.
| |
940 | |
941 if (!CanBlockExtension(extension.get())) | |
942 continue; | |
943 | |
944 // Blacklisted extensions remain in the blacklisted list. | |
945 registry_->RemoveEnabled(id); | |
946 registry_->RemoveDisabled(id); | |
947 registry_->RemoveTerminated(id); | |
948 | |
not at google - send to devlin
2014/11/12 23:41:43
Come to think of it it's probably also wise/safer
Mike Lerman
2014/11/13 15:30:05
I'm concerned about removing things from the black
not at google - send to devlin
2014/11/13 18:09:47
I'm not suggesting removing it from the blacklist.
Mike Lerman
2014/11/13 21:42:32
Done.
| |
949 registry_->AddBlocked(extension.get()); | |
950 extension_prefs_->SetExtensionState(id, Extension::BLOCKED); | |
not at google - send to devlin
2014/11/12 23:41:43
Actually - why do you need to change prefs at all?
Mike Lerman
2014/11/13 15:30:04
The goal was the keep the ExtensionState sync-ed w
not at google - send to devlin
2014/11/13 18:09:47
I don't think so. For example we keep terminated e
Mike Lerman
2014/11/13 21:42:32
Done.
| |
951 UnloadExtension( | |
952 id, extensions::UnloadedExtensionInfo::REASON_LOCK_ALL); | |
953 } | |
954 } | |
955 | |
956 // All locked extensions should revert to being either enabled or disabled | |
957 // as appropriate. | |
958 void ExtensionService::UnblockAllBlockedExtensions() { | |
959 ExtensionIdSet to_unblock = registry_->blocked_extensions().GetIDs(); | |
not at google - send to devlin
2014/11/12 23:41:43
(see previous point about just copying the whole e
Mike Lerman
2014/11/13 15:30:04
Which one?
Is making a copy of the set better tha
not at google - send to devlin
2014/11/13 18:09:47
Maybe they should copy the set as well. Needing 7
Mike Lerman
2014/11/13 21:42:32
Copied as well. Done.
| |
960 | |
961 block_extensions_ = false; | |
962 for (ExtensionIdSet::iterator it = to_unblock.begin(); | |
not at google - send to devlin
2014/11/12 23:41:43
(and use : syntax here too)
Mike Lerman
2014/11/13 15:30:04
Done.
| |
963 it != to_unblock.end(); ++it) { | |
964 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); | |
965 if (!extension.get()) { | |
966 NOTREACHED() << "Extension " << *it << " needs to be " | |
967 << "unblocked, but it's not installed."; | |
968 continue; | |
969 } | |
970 | |
971 registry_->RemoveBlocked(*it); | |
972 if (extensions_being_terminated_.find(extension->id()) != | |
not at google - send to devlin
2014/11/12 23:41:43
Mm, maybe this isn't actually useful. I doubt this
Mike Lerman
2014/11/13 15:30:05
Done.
| |
973 extensions_being_terminated_.end()) { | |
974 registry_->AddTerminated(extension.get()); | |
975 } else { | |
976 if (extension_prefs_->GetDisableReasons(*it)) { | |
not at google - send to devlin
2014/11/12 23:41:43
GetDisableReasons returns a bitmask, so it's a lit
Mike Lerman
2014/11/13 15:30:04
I agree about using IsExtensionDisabled, if we hav
| |
977 extension_prefs_->SetExtensionState(*it, Extension::DISABLED); | |
978 } else { | |
979 extension_prefs_->SetExtensionState(*it, Extension::ENABLED); | |
980 } | |
981 AddExtension(extension.get()); | |
982 } | |
983 } | |
984 } | |
985 | |
923 void ExtensionService::GrantPermissionsAndEnableExtension( | 986 void ExtensionService::GrantPermissionsAndEnableExtension( |
924 const Extension* extension) { | 987 const Extension* extension) { |
925 GrantPermissions(extension); | 988 GrantPermissions(extension); |
926 RecordPermissionMessagesHistogram(extension, | 989 RecordPermissionMessagesHistogram(extension, |
927 "Extensions.Permissions_ReEnable2"); | 990 "Extensions.Permissions_ReEnable2"); |
928 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); | 991 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); |
929 EnableExtension(extension->id()); | 992 EnableExtension(extension->id()); |
930 } | 993 } |
931 | 994 |
932 void ExtensionService::GrantPermissions(const Extension* extension) { | 995 void ExtensionService::GrantPermissions(const Extension* extension) { |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1366 // new one. ReloadExtension disables the extension, which is sufficient. | 1429 // new one. ReloadExtension disables the extension, which is sufficient. |
1367 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE); | 1430 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE); |
1368 } | 1431 } |
1369 | 1432 |
1370 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { | 1433 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { |
1371 // Only prefs is checked for the blacklist. We rely on callers to check the | 1434 // Only prefs is checked for the blacklist. We rely on callers to check the |
1372 // blacklist before calling into here, e.g. CrxInstaller checks before | 1435 // blacklist before calling into here, e.g. CrxInstaller checks before |
1373 // installation then threads through the install and pending install flow | 1436 // installation then threads through the install and pending install flow |
1374 // of this class, and we check when loading installed extensions. | 1437 // of this class, and we check when loading installed extensions. |
1375 registry_->AddBlacklisted(extension); | 1438 registry_->AddBlacklisted(extension); |
1439 } else if (extension_prefs_->IsExtensionBlocked(extension->id()) || | |
1440 (block_extensions_ && CanBlockExtension(extension))) { | |
1441 registry_->AddBlocked(extension); | |
1376 } else if (!reloading && | 1442 } else if (!reloading && |
1377 extension_prefs_->IsExtensionDisabled(extension->id())) { | 1443 extension_prefs_->IsExtensionDisabled(extension->id())) { |
1378 registry_->AddDisabled(extension); | 1444 registry_->AddDisabled(extension); |
1379 if (extension_sync_service_) | 1445 if (extension_sync_service_) |
1380 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); | 1446 extension_sync_service_->SyncExtensionChangeIfNeeded(*extension); |
1381 content::NotificationService::current()->Notify( | 1447 content::NotificationService::current()->Notify( |
1382 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED, | 1448 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED, |
1383 content::Source<Profile>(profile_), | 1449 content::Source<Profile>(profile_), |
1384 content::Details<const Extension>(extension)); | 1450 content::Details<const Extension>(extension)); |
1385 | 1451 |
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2168 if (extension->GetType() != Manifest::TYPE_HOSTED_APP && | 2234 if (extension->GetType() != Manifest::TYPE_HOSTED_APP && |
2169 Manifest::IsExternalLocation(extension->location()) && | 2235 Manifest::IsExternalLocation(extension->location()) && |
2170 !extension_prefs_->IsExternalExtensionAcknowledged(extension->id())) { | 2236 !extension_prefs_->IsExternalExtensionAcknowledged(extension->id())) { |
2171 return false; | 2237 return false; |
2172 } | 2238 } |
2173 } | 2239 } |
2174 | 2240 |
2175 return true; | 2241 return true; |
2176 } | 2242 } |
2177 | 2243 |
2244 // Helper method to determine if an extension can be blocked. | |
2245 bool ExtensionService::CanBlockExtension(const Extension* extension) { | |
2246 return (extension->location() != Manifest::COMPONENT && | |
not at google - send to devlin
2014/11/12 23:41:43
Outer parens are unnecessary.
Mike Lerman
2014/11/13 15:30:04
Done.
| |
2247 extension->location() != Manifest::EXTERNAL_COMPONENT && | |
2248 !system_->management_policy()->MustRemainEnabled(extension, NULL)); | |
2249 } | |
2250 | |
2178 bool ExtensionService::ShouldDelayExtensionUpdate( | 2251 bool ExtensionService::ShouldDelayExtensionUpdate( |
2179 const std::string& extension_id, | 2252 const std::string& extension_id, |
2180 bool install_immediately) const { | 2253 bool install_immediately) const { |
2181 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable"; | 2254 const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable"; |
2182 | 2255 |
2183 // If delayed updates are globally disabled, or just for this extension, | 2256 // If delayed updates are globally disabled, or just for this extension, |
2184 // don't delay. | 2257 // don't delay. |
2185 if (!install_updates_when_idle_ || install_immediately) | 2258 if (!install_updates_when_idle_ || install_immediately) |
2186 return false; | 2259 return false; |
2187 | 2260 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2256 case extensions::BLACKLISTED_POTENTIALLY_UNWANTED: | 2329 case extensions::BLACKLISTED_POTENTIALLY_UNWANTED: |
2257 greylist.insert(it->first); | 2330 greylist.insert(it->first); |
2258 break; | 2331 break; |
2259 | 2332 |
2260 case extensions::BLACKLISTED_UNKNOWN: | 2333 case extensions::BLACKLISTED_UNKNOWN: |
2261 unchanged.insert(it->first); | 2334 unchanged.insert(it->first); |
2262 break; | 2335 break; |
2263 } | 2336 } |
2264 } | 2337 } |
2265 | 2338 |
2266 UpdateBlockedExtensions(blocked, unchanged); | 2339 UpdateBlockedExtensions(blocked, unchanged); |
not at google - send to devlin
2014/11/12 23:41:43
Looks like the "blocked" term is already used, but
Mike Lerman
2014/11/13 15:30:04
Done.
| |
2267 UpdateGreylistedExtensions(greylist, unchanged, state_map); | 2340 UpdateGreylistedExtensions(greylist, unchanged, state_map); |
2268 | 2341 |
2269 error_controller_->ShowErrorIfNeeded(); | 2342 error_controller_->ShowErrorIfNeeded(); |
2270 } | 2343 } |
2271 | 2344 |
2272 namespace { | 2345 namespace { |
2273 void Partition(const ExtensionIdSet& before, | 2346 void Partition(const ExtensionIdSet& before, |
2274 const ExtensionIdSet& after, | 2347 const ExtensionIdSet& after, |
2275 const ExtensionIdSet& unchanged, | 2348 const ExtensionIdSet& unchanged, |
2276 ExtensionIdSet* no_longer, | 2349 ExtensionIdSet* no_longer, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2388 } | 2461 } |
2389 | 2462 |
2390 void ExtensionService::OnProfileDestructionStarted() { | 2463 void ExtensionService::OnProfileDestructionStarted() { |
2391 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); | 2464 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); |
2392 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); | 2465 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); |
2393 it != ids_to_unload.end(); | 2466 it != ids_to_unload.end(); |
2394 ++it) { | 2467 ++it) { |
2395 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); | 2468 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); |
2396 } | 2469 } |
2397 } | 2470 } |
OLD | NEW |