Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extensions_service.h" | 5 #include "chrome/browser/extensions/extensions_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 920 extension); | 920 extension); |
| 921 extensions_.erase(iter); | 921 extensions_.erase(iter); |
| 922 | 922 |
| 923 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, | 923 ExtensionDOMUI::UnregisterChromeURLOverrides(profile_, |
| 924 extension->GetChromeURLOverrides()); | 924 extension->GetChromeURLOverrides()); |
| 925 | 925 |
| 926 NotifyExtensionUnloaded(extension); | 926 NotifyExtensionUnloaded(extension); |
| 927 UpdateActiveExtensionsInCrashReporter(); | 927 UpdateActiveExtensionsInCrashReporter(); |
| 928 } | 928 } |
| 929 | 929 |
| 930 void ExtensionsService::GrantPermissions(const Extension* extension) { | |
| 931 DCHECK(extension); | |
| 932 ExtensionExtent effective_hosts = extension->GetEffectiveHostPermissions(); | |
| 933 extension_prefs_->AddGrantedPermissions(extension->id(), | |
| 934 extension->api_permissions(), | |
| 935 effective_hosts); | |
| 936 } | |
| 937 | |
| 938 void ExtensionsService::GrantPermissionsAndEnableExtension( | |
| 939 const Extension* extension) { | |
| 940 DCHECK(extension); | |
| 941 GrantPermissions(extension); | |
| 942 extension_prefs_->SetDidExtensionEscalatePermissions(extension, false); | |
| 943 EnableExtension(extension->id()); | |
| 944 } | |
| 945 | |
| 930 void ExtensionsService::LoadExtension(const FilePath& extension_path) { | 946 void ExtensionsService::LoadExtension(const FilePath& extension_path) { |
| 931 BrowserThread::PostTask( | 947 BrowserThread::PostTask( |
| 932 BrowserThread::FILE, FROM_HERE, | 948 BrowserThread::FILE, FROM_HERE, |
| 933 NewRunnableMethod( | 949 NewRunnableMethod( |
| 934 backend_.get(), | 950 backend_.get(), |
| 935 &ExtensionsServiceBackend::LoadSingleExtension, | 951 &ExtensionsServiceBackend::LoadSingleExtension, |
| 936 extension_path, scoped_refptr<ExtensionsService>(this))); | 952 extension_path, scoped_refptr<ExtensionsService>(this))); |
| 937 } | 953 } |
| 938 | 954 |
| 939 void ExtensionsService::LoadComponentExtensions() { | 955 void ExtensionsService::LoadComponentExtensions() { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1097 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", packaged_app_count); | 1113 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", packaged_app_count); |
| 1098 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension", extension_count); | 1114 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension", extension_count); |
| 1099 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count); | 1115 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count); |
| 1100 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count); | 1116 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count); |
| 1101 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExternal", external_count); | 1117 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExternal", external_count); |
| 1102 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPageAction", page_action_count); | 1118 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPageAction", page_action_count); |
| 1103 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction", | 1119 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction", |
| 1104 browser_action_count); | 1120 browser_action_count); |
| 1105 } | 1121 } |
| 1106 | 1122 |
| 1107 | |
| 1108 void ExtensionsService::LoadInstalledExtension(const ExtensionInfo& info, | 1123 void ExtensionsService::LoadInstalledExtension(const ExtensionInfo& info, |
| 1109 bool write_to_prefs) { | 1124 bool write_to_prefs) { |
| 1110 std::string error; | 1125 std::string error; |
| 1111 scoped_refptr<const Extension> extension(NULL); | 1126 scoped_refptr<const Extension> extension(NULL); |
| 1112 if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id)) { | 1127 if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id)) { |
| 1113 error = errors::kDisabledByPolicy; | 1128 error = errors::kDisabledByPolicy; |
| 1114 } else if (info.extension_manifest.get()) { | 1129 } else if (info.extension_manifest.get()) { |
| 1115 bool require_key = info.extension_location != Extension::LOAD; | 1130 bool require_key = info.extension_location != Extension::LOAD; |
| 1116 extension = Extension::Create( | 1131 extension = Extension::Create( |
| 1117 info.extension_path, info.extension_location, *info.extension_manifest, | 1132 info.extension_path, info.extension_location, *info.extension_manifest, |
| 1118 require_key, &error); | 1133 require_key, &error); |
| 1119 } else { | 1134 } else { |
| 1120 error = errors::kManifestUnreadable; | 1135 error = errors::kManifestUnreadable; |
| 1121 } | 1136 } |
| 1122 | 1137 |
| 1123 if (!extension) { | 1138 if (!extension) { |
| 1124 ReportExtensionLoadError(info.extension_path, | 1139 ReportExtensionLoadError(info.extension_path, |
| 1125 error, | 1140 error, |
| 1126 NotificationType::EXTENSION_INSTALL_ERROR, | 1141 NotificationType::EXTENSION_INSTALL_ERROR, |
| 1127 false); | 1142 false); |
| 1128 return; | 1143 return; |
| 1129 } | 1144 } |
| 1130 | 1145 |
| 1131 if (write_to_prefs) | 1146 if (write_to_prefs) |
| 1132 extension_prefs_->UpdateManifest(extension); | 1147 extension_prefs_->UpdateManifest(extension); |
| 1133 | 1148 |
| 1134 OnExtensionLoaded(extension, true); | 1149 // External extensions are allowed to increase their privileges without |
| 1135 | 1150 // prompting users. |
| 1136 if (Extension::IsExternalLocation(info.extension_location)) { | 1151 if (Extension::IsExternalLocation(info.extension_location)) { |
| 1152 OnExtensionLoaded(extension, true); | |
| 1137 BrowserThread::PostTask( | 1153 BrowserThread::PostTask( |
| 1138 BrowserThread::FILE, FROM_HERE, | 1154 BrowserThread::FILE, FROM_HERE, |
| 1139 NewRunnableMethod( | 1155 NewRunnableMethod( |
| 1140 backend_.get(), | 1156 backend_.get(), |
| 1141 &ExtensionsServiceBackend::CheckExternalUninstall, | 1157 &ExtensionsServiceBackend::CheckExternalUninstall, |
| 1142 scoped_refptr<ExtensionsService>(this), | 1158 scoped_refptr<ExtensionsService>(this), |
| 1143 info.extension_id)); | 1159 info.extension_id)); |
| 1160 } else { | |
| 1161 OnExtensionLoaded(extension, false); | |
| 1144 } | 1162 } |
| 1145 } | 1163 } |
| 1146 | 1164 |
| 1147 void ExtensionsService::NotifyExtensionLoaded(const Extension* extension) { | 1165 void ExtensionsService::NotifyExtensionLoaded(const Extension* extension) { |
| 1148 // The ChromeURLRequestContexts need to be first to know that the extension | 1166 // The ChromeURLRequestContexts need to be first to know that the extension |
| 1149 // was loaded, otherwise a race can arise where a renderer that is created | 1167 // was loaded, otherwise a race can arise where a renderer that is created |
| 1150 // for the extension may try to load an extension URL with an extension id | 1168 // for the extension may try to load an extension URL with an extension id |
| 1151 // that the request context doesn't yet know about. The profile is responsible | 1169 // that the request context doesn't yet know about. The profile is responsible |
| 1152 // for ensuring its URLRequestContexts appropriately discover the loaded | 1170 // for ensuring its URLRequestContexts appropriately discover the loaded |
| 1153 // extension. | 1171 // extension. |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1500 | 1518 |
| 1501 // The extension is now loaded, remove its data from unloaded extension map. | 1519 // The extension is now loaded, remove its data from unloaded extension map. |
| 1502 unloaded_extension_paths_.erase(extension->id()); | 1520 unloaded_extension_paths_.erase(extension->id()); |
| 1503 | 1521 |
| 1504 // If the extension was disabled for a reload, then enable it. | 1522 // If the extension was disabled for a reload, then enable it. |
| 1505 if (disabled_extension_paths_.erase(extension->id()) > 0) | 1523 if (disabled_extension_paths_.erase(extension->id()) > 0) |
| 1506 EnableExtension(extension->id()); | 1524 EnableExtension(extension->id()); |
| 1507 | 1525 |
| 1508 // TODO(aa): Need to re-evaluate this branch. Does this still make sense now | 1526 // TODO(aa): Need to re-evaluate this branch. Does this still make sense now |
| 1509 // that extensions are enabled by default? | 1527 // that extensions are enabled by default? |
| 1510 if (extensions_enabled() || | 1528 if (extensions_enabled() || |
|
Aaron Boodman
2010/11/22 07:57:53
I think this long check can be removed now. It is
jstritar
2010/11/22 23:01:08
Done.
| |
| 1511 extension->is_theme() || | 1529 extension->is_theme() || |
| 1512 extension->location() == Extension::LOAD || | 1530 extension->location() == Extension::LOAD || |
| 1513 extension->location() == Extension::COMPONENT || | 1531 extension->location() == Extension::COMPONENT || |
| 1514 Extension::IsExternalLocation(extension->location())) { | 1532 Extension::IsExternalLocation(extension->location())) { |
| 1515 const Extension* old = GetExtensionByIdInternal(extension->id(), | 1533 const Extension* old = GetExtensionByIdInternal(extension->id(), |
| 1516 true, true); | 1534 true, true); |
| 1517 if (old) { | 1535 |
| 1536 // We keep track of all permissions the user has granted each extension. | |
|
Aaron Boodman
2010/11/22 07:57:53
How about factoring all this big chunk of upgrade
jstritar
2010/11/22 23:01:08
Done.
| |
| 1537 // This allows extensions to gracefully support backwards compatibility | |
| 1538 // by including unknown permissions in their manifests. When the user | |
| 1539 // installs the extension, only the recognized permissions are recorded. | |
| 1540 // When the unknown permissions become recognized (e.g., through browser | |
| 1541 // upgrade), we can prompt the user to accept these new permissions. | |
| 1542 // Extensions can also silently upgrade to less permissions, and then | |
| 1543 // silently upgrade to a version that adds these permissions back. | |
| 1544 // | |
| 1545 // For example, pretend that Chrome 10 includes a permission "omnibox" | |
| 1546 // for an API that adds suggestions to the omnibox. An extension can | |
| 1547 // maintain backwards compatibility while still having "omnibox" in the | |
| 1548 // manifest. If a user installs the extension on Chrome 9, the browser | |
| 1549 // will record the permissions it recognized, not including "omnibox." | |
| 1550 // When upgrading to Chrome 10, "omnibox" will be recognized and Chrome | |
| 1551 // will disable the extension and prompt the user to approve the increase | |
| 1552 // in privileges. The extension could then release a new version that | |
| 1553 // removes the "omnibox" permission. When the user upgrades, Chrome will | |
| 1554 // still remember that "omnibox" had been granted, so that if the | |
| 1555 // extension once again includes "omnibox" in an upgrade, the extension | |
| 1556 // can upgrade without requiring this user's approval. | |
| 1557 | |
| 1558 std::set<std::string> granted_apis; | |
| 1559 ExtensionExtent granted_extent; | |
| 1560 | |
| 1561 // Add all the recognized permissions to the extension's granted | |
| 1562 // permissions list if the granted permissions list hasn't been | |
| 1563 // initialized yet or privilege increases are allowed. | |
| 1564 if (extension->location() != Extension::COMPONENT && | |
|
Aaron Boodman
2010/11/22 07:57:53
It seems like we only want to store the privileges
jstritar
2010/11/22 23:01:08
Done. I ended up needing to change the allow_privi
| |
| 1565 (!extension_prefs_->GetGrantedPermissions( | |
| 1566 extension->id(), &granted_apis, &granted_extent) || | |
| 1567 allow_privilege_increase)) { | |
| 1568 GrantPermissions(extension); | |
| 1569 DCHECK(extension_prefs_->GetGrantedPermissions( | |
|
Aaron Boodman
2010/11/22 07:57:53
Danger! Never do work with side-effects in DCHECK.
jstritar
2010/11/22 23:01:08
Wow, yeah good point. Fixed.
| |
| 1570 extension->id(), &granted_apis, &granted_extent)); | |
| 1571 } | |
| 1572 | |
| 1573 bool is_extension_upgrade = old != NULL; | |
| 1574 bool is_privilege_increase = false; | |
| 1575 | |
| 1576 // Here, we check if an extension's privileges have increased in a manner | |
| 1577 // that requires the user's approval. This could occur because the browser | |
| 1578 // upgraded and recognized additional privileges, or an extension upgrades | |
| 1579 // to a version that requires additional privileges. | |
| 1580 if ((extension->location() == Extension::INTERNAL || is_extension_upgrade) | |
|
Aaron Boodman
2010/11/22 07:57:53
And we could remove the location() check here too:
jstritar
2010/11/22 23:01:08
Done.
| |
| 1581 && !allow_privilege_increase) { | |
| 1582 is_privilege_increase = Extension::IsPrivilegeIncrease( | |
| 1583 granted_apis, granted_extent, old, extension); | |
| 1584 } | |
| 1585 | |
| 1586 if (is_extension_upgrade) { | |
| 1518 // CrxInstaller should have guaranteed that we aren't downgrading. | 1587 // CrxInstaller should have guaranteed that we aren't downgrading. |
| 1519 CHECK(extension->version()->CompareTo(*(old->version())) >= 0); | 1588 CHECK(extension->version()->CompareTo(*(old->version())) >= 0); |
| 1520 | 1589 |
| 1521 bool allow_silent_upgrade = | 1590 // Extensions get upgraded if the privileges are allowed to increase or |
| 1522 allow_privilege_increase || !Extension::IsPrivilegeIncrease( | 1591 // the privileges haven't increased. |
| 1523 old, extension); | 1592 if (allow_privilege_increase || !is_privilege_increase) { |
| 1524 | |
| 1525 // Extensions get upgraded if silent upgrades are allowed, otherwise | |
| 1526 // they get disabled. | |
| 1527 if (allow_silent_upgrade) { | |
| 1528 SetBeingUpgraded(old, true); | 1593 SetBeingUpgraded(old, true); |
| 1529 SetBeingUpgraded(extension, true); | 1594 SetBeingUpgraded(extension, true); |
| 1530 } | 1595 } |
| 1531 | 1596 |
| 1532 // To upgrade an extension in place, unload the old one and | 1597 // To upgrade an extension in place, unload the old one and |
| 1533 // then load the new one. | 1598 // then load the new one. |
| 1534 UnloadExtension(old->id()); | 1599 UnloadExtension(old->id()); |
| 1535 old = NULL; | 1600 old = NULL; |
| 1601 } | |
| 1536 | 1602 |
| 1537 if (!allow_silent_upgrade) { | 1603 // Extension has changed permissions significantly. Disable it. We |
| 1538 // Extension has changed permissions significantly. Disable it. We | 1604 // send a notification below. |
| 1539 // send a notification below. | 1605 if (is_privilege_increase) { |
| 1540 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); | 1606 extension_prefs_->SetExtensionState(extension, Extension::DISABLED); |
| 1541 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); | 1607 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); |
| 1542 } | |
| 1543 } | 1608 } |
| 1544 | 1609 |
| 1545 switch (extension_prefs_->GetExtensionState(extension->id())) { | 1610 switch (extension_prefs_->GetExtensionState(extension->id())) { |
| 1546 case Extension::ENABLED: | 1611 case Extension::ENABLED: |
| 1547 extensions_.push_back(scoped_extension); | 1612 extensions_.push_back(scoped_extension); |
| 1548 | 1613 |
| 1549 NotifyExtensionLoaded(extension); | 1614 NotifyExtensionLoaded(extension); |
| 1550 | 1615 |
| 1551 ExtensionDOMUI::RegisterChromeURLOverrides(profile_, | 1616 ExtensionDOMUI::RegisterChromeURLOverrides(profile_, |
| 1552 extension->GetChromeURLOverrides()); | 1617 extension->GetChromeURLOverrides()); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1949 } | 2014 } |
| 1950 | 2015 |
| 1951 bool ExtensionsService::IsBeingUpgraded(const Extension* extension) { | 2016 bool ExtensionsService::IsBeingUpgraded(const Extension* extension) { |
| 1952 return extension_runtime_data_[extension->id()].being_upgraded; | 2017 return extension_runtime_data_[extension->id()].being_upgraded; |
| 1953 } | 2018 } |
| 1954 | 2019 |
| 1955 void ExtensionsService::SetBeingUpgraded(const Extension* extension, | 2020 void ExtensionsService::SetBeingUpgraded(const Extension* extension, |
| 1956 bool value) { | 2021 bool value) { |
| 1957 extension_runtime_data_[extension->id()].being_upgraded = value; | 2022 extension_runtime_data_[extension->id()].being_upgraded = value; |
| 1958 } | 2023 } |
| OLD | NEW |