Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: chrome/browser/extensions/extension_service.cc

Issue 2084613002: Re-enable extensions disabled due to permission increase if they have all permissions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2743
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <iterator> 10 #include <iterator>
(...skipping 1419 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 // default extension state to DISABLED when the --disable-extensions flag 1430 // default extension state to DISABLED when the --disable-extensions flag
1431 // is set (http://crbug.com/29067). 1431 // is set (http://crbug.com/29067).
1432 if (!extensions_enabled() && 1432 if (!extensions_enabled() &&
1433 !extension->is_theme() && 1433 !extension->is_theme() &&
1434 extension->location() != Manifest::COMPONENT && 1434 extension->location() != Manifest::COMPONENT &&
1435 !Manifest::IsExternalLocation(extension->location())) { 1435 !Manifest::IsExternalLocation(extension->location())) {
1436 return; 1436 return;
1437 } 1437 }
1438 1438
1439 bool is_extension_upgrade = false; 1439 bool is_extension_upgrade = false;
1440 bool is_extension_installed = false; 1440 bool is_extension_loaded = false;
1441 const Extension* old = GetInstalledExtension(extension->id()); 1441 const Extension* old = GetInstalledExtension(extension->id());
1442 if (old) { 1442 if (old) {
1443 is_extension_installed = true; 1443 is_extension_loaded = true;
1444 int version_compare_result = 1444 int version_compare_result =
1445 extension->version()->CompareTo(*(old->version())); 1445 extension->version()->CompareTo(*(old->version()));
1446 is_extension_upgrade = version_compare_result > 0; 1446 is_extension_upgrade = version_compare_result > 0;
1447 // Other than for unpacked extensions, CrxInstaller should have guaranteed 1447 // Other than for unpacked extensions, CrxInstaller should have guaranteed
1448 // that we aren't downgrading. 1448 // that we aren't downgrading.
1449 if (!Manifest::IsUnpackedLocation(extension->location())) 1449 if (!Manifest::IsUnpackedLocation(extension->location()))
1450 CHECK_GE(version_compare_result, 0); 1450 CHECK_GE(version_compare_result, 0);
1451 } 1451 }
1452 // If the extension was disabled for a reload, then enable it. 1452 // If the extension was disabled for a reload, then enable it.
1453 bool reloading = reloading_extensions_.erase(extension->id()) > 0; 1453 bool reloading = reloading_extensions_.erase(extension->id()) > 0;
1454 1454
1455 // Set the upgraded bit; we consider reloads upgrades. 1455 // Set the upgraded bit; we consider reloads upgrades.
1456 system_->runtime_data()->SetBeingUpgraded(extension->id(), 1456 system_->runtime_data()->SetBeingUpgraded(extension->id(),
1457 is_extension_upgrade || reloading); 1457 is_extension_upgrade || reloading);
1458 1458
1459 // The extension is now loaded, remove its data from unloaded extension map. 1459 // The extension is now loaded, remove its data from unloaded extension map.
1460 unloaded_extension_paths_.erase(extension->id()); 1460 unloaded_extension_paths_.erase(extension->id());
1461 1461
1462 // If a terminated extension is loaded, remove it from the terminated list. 1462 // If a terminated extension is loaded, remove it from the terminated list.
1463 UntrackTerminatedExtension(extension->id()); 1463 UntrackTerminatedExtension(extension->id());
1464 1464
1465 // Check if the extension's privileges have changed and mark the 1465 // Check if the extension's privileges have changed and mark the
1466 // extension disabled if necessary. 1466 // extension disabled if necessary.
1467 CheckPermissionsIncrease(extension, is_extension_installed); 1467 CheckPermissionsIncrease(extension, is_extension_loaded);
1468 1468
1469 if (is_extension_installed && !reloading) { 1469 if (is_extension_loaded && !reloading) {
1470 // To upgrade an extension in place, unload the old one and then load the 1470 // To upgrade an extension in place, unload the old one and then load the
1471 // new one. ReloadExtension disables the extension, which is sufficient. 1471 // new one. ReloadExtension disables the extension, which is sufficient.
1472 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE); 1472 UnloadExtension(extension->id(), UnloadedExtensionInfo::REASON_UPDATE);
1473 } 1473 }
1474 1474
1475 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { 1475 if (extension_prefs_->IsExtensionBlacklisted(extension->id())) {
1476 // Only prefs is checked for the blacklist. We rely on callers to check the 1476 // Only prefs is checked for the blacklist. We rely on callers to check the
1477 // blacklist before calling into here, e.g. CrxInstaller checks before 1477 // blacklist before calling into here, e.g. CrxInstaller checks before
1478 // installation then threads through the install and pending install flow 1478 // installation then threads through the install and pending install flow
1479 // of this class, and we check when loading installed extensions. 1479 // of this class, and we check when loading installed extensions.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 extensions::kInstallFlagNone, 1539 extensions::kInstallFlagNone,
1540 syncer::StringOrdinal(), 1540 syncer::StringOrdinal(),
1541 std::string()); 1541 std::string());
1542 return; 1542 return;
1543 } 1543 }
1544 1544
1545 AddExtension(extension); 1545 AddExtension(extension);
1546 } 1546 }
1547 1547
1548 void ExtensionService::CheckPermissionsIncrease(const Extension* extension, 1548 void ExtensionService::CheckPermissionsIncrease(const Extension* extension,
1549 bool is_extension_installed) { 1549 bool is_extension_loaded) {
1550 extensions::PermissionsUpdater(profile_).InitializePermissions(extension); 1550 extensions::PermissionsUpdater(profile_).InitializePermissions(extension);
1551 1551
1552 // We keep track of all permissions the user has granted each extension. 1552 // We keep track of all permissions the user has granted each extension.
1553 // This allows extensions to gracefully support backwards compatibility 1553 // This allows extensions to gracefully support backwards compatibility
1554 // by including unknown permissions in their manifests. When the user 1554 // by including unknown permissions in their manifests. When the user
1555 // installs the extension, only the recognized permissions are recorded. 1555 // installs the extension, only the recognized permissions are recorded.
1556 // When the unknown permissions become recognized (e.g., through browser 1556 // When the unknown permissions become recognized (e.g., through browser
1557 // upgrade), we can prompt the user to accept these new permissions. 1557 // upgrade), we can prompt the user to accept these new permissions.
1558 // Extensions can also silently upgrade to less permissions, and then 1558 // Extensions can also silently upgrade to less permissions, and then
1559 // silently upgrade to a version that adds these permissions back. 1559 // silently upgrade to a version that adds these permissions back.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 extension->GetType()); 1602 extension->GetType());
1603 1603
1604 // If there was no privilege increase, the extension might still have new 1604 // If there was no privilege increase, the extension might still have new
1605 // permissions (which either don't generate a warning message, or whose 1605 // permissions (which either don't generate a warning message, or whose
1606 // warning messages are suppressed by existing permissions). Grant the new 1606 // warning messages are suppressed by existing permissions). Grant the new
1607 // permissions. 1607 // permissions.
1608 if (!is_privilege_increase) 1608 if (!is_privilege_increase)
1609 GrantPermissions(extension); 1609 GrantPermissions(extension);
1610 } 1610 }
1611 1611
1612 if (is_extension_installed) { 1612 bool previously_disabled =
1613 // If the extension was already disabled, suppress any alerts for becoming 1613 extension_prefs_->IsExtensionDisabled(extension->id());
1614 // disabled on permissions increase. 1614 // TODO(treib): Is the |is_extension_loaded| check needed here?
1615 bool previously_disabled = 1615 if (is_extension_loaded && previously_disabled) {
1616 extension_prefs_->IsExtensionDisabled(extension->id());
1617 // Legacy disabled extensions do not have a disable reason. Infer that it 1616 // Legacy disabled extensions do not have a disable reason. Infer that it
1618 // was likely disabled by the user. 1617 // was likely disabled by the user.
1619 if (previously_disabled && disable_reasons == Extension::DISABLE_NONE) 1618 if (disable_reasons == Extension::DISABLE_NONE)
1620 disable_reasons |= Extension::DISABLE_USER_ACTION; 1619 disable_reasons |= Extension::DISABLE_USER_ACTION;
1621 1620
1622 // Extensions that came to us disabled from sync need a similar inference, 1621 // Extensions that came to us disabled from sync need a similar inference,
1623 // except based on the new version's permissions. 1622 // except based on the new version's permissions.
1624 // TODO(treib,devlin): Since M48, DISABLE_UNKNOWN_FROM_SYNC isn't used 1623 // TODO(treib,devlin): Since M48, DISABLE_UNKNOWN_FROM_SYNC isn't used
1625 // anymore; this code is still here to migrate any existing old state. 1624 // anymore; this code is still here to migrate any existing old state.
1626 // Remove it after some grace period. 1625 // Remove it after some grace period.
1627 if (previously_disabled && 1626 if (disable_reasons & Extension::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC) {
1628 (disable_reasons & Extension::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC)) {
1629 // Remove the DISABLE_UNKNOWN_FROM_SYNC reason. 1627 // Remove the DISABLE_UNKNOWN_FROM_SYNC reason.
1630 disable_reasons &= ~Extension::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC; 1628 disable_reasons &= ~Extension::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC;
1631 extension_prefs_->RemoveDisableReason( 1629 extension_prefs_->RemoveDisableReason(
1632 extension->id(), Extension::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC); 1630 extension->id(), Extension::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC);
1633 // If there was no privilege increase, it was likely disabled by the user. 1631 // If there was no privilege increase, it was likely disabled by the user.
1634 if (!is_privilege_increase) 1632 if (!is_privilege_increase)
1635 disable_reasons |= Extension::DISABLE_USER_ACTION; 1633 disable_reasons |= Extension::DISABLE_USER_ACTION;
1636 } 1634 }
1637 } 1635 }
1638 1636
1637 // If the extension is disabled due to a permissions increase, but does in
1638 // fact have all permissions, remove that disable reason.
1639 // TODO(devlin): This was added to fix crbug.com/616474, but it's unclear
1640 // if this behavior should stay forever.
1641 if (disable_reasons & Extension::DISABLE_PERMISSIONS_INCREASE) {
1642 bool reset_permissions_increase = false;
1643 if (!is_privilege_increase) {
1644 reset_permissions_increase = true;
1645 disable_reasons &= ~Extension::DISABLE_PERMISSIONS_INCREASE;
1646 extension_prefs_->RemoveDisableReason(
1647 extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE);
1648 }
1649 UMA_HISTOGRAM_BOOLEAN("Extensions.ResetPermissionsIncrease",
1650 reset_permissions_increase);
1651 }
1652
1639 // Extension has changed permissions significantly. Disable it. A 1653 // Extension has changed permissions significantly. Disable it. A
1640 // notification should be sent by the caller. If the extension is already 1654 // notification should be sent by the caller. If the extension is already
1641 // disabled because it was installed remotely, don't add another disable 1655 // disabled because it was installed remotely, don't add another disable
1642 // reason. 1656 // reason.
1643 if (is_privilege_increase && 1657 if (is_privilege_increase &&
1644 !(disable_reasons & Extension::DISABLE_REMOTE_INSTALL)) { 1658 !(disable_reasons & Extension::DISABLE_REMOTE_INSTALL)) {
1645 disable_reasons |= Extension::DISABLE_PERMISSIONS_INCREASE; 1659 disable_reasons |= Extension::DISABLE_PERMISSIONS_INCREASE;
1646 if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id())) 1660 if (!extension_prefs_->DidExtensionEscalatePermissions(extension->id()))
1647 RecordPermissionMessagesHistogram(extension, "AutoDisable"); 1661 RecordPermissionMessagesHistogram(extension, "AutoDisable");
1648 1662
1649 #if defined(ENABLE_SUPERVISED_USERS) 1663 #if defined(ENABLE_SUPERVISED_USERS)
1650 // If a custodian-installed extension is disabled for a supervised user due 1664 // If a custodian-installed extension is disabled for a supervised user due
1651 // to a permissions increase, send a request to the custodian if the 1665 // to a permissions increase, send a request to the custodian if the
1652 // supervised user themselves can't re-enable the extension. 1666 // supervised user themselves can't re-enable the extension.
1653 if (extensions::util::IsExtensionSupervised(extension, profile_) && 1667 if (extensions::util::IsExtensionSupervised(extension, profile_) &&
1654 extensions::util::NeedCustodianApprovalForPermissionIncrease( 1668 extensions::util::NeedCustodianApprovalForPermissionIncrease(
1655 profile_) && 1669 profile_) &&
1656 !ExtensionSyncService::Get(profile_)->HasPendingReenable( 1670 !ExtensionSyncService::Get(profile_)->HasPendingReenable(
1657 extension->id(), *extension->version())) { 1671 extension->id(), *extension->version())) {
1658 SupervisedUserService* supervised_user_service = 1672 SupervisedUserService* supervised_user_service =
1659 SupervisedUserServiceFactory::GetForProfile(profile_); 1673 SupervisedUserServiceFactory::GetForProfile(profile_);
1660 supervised_user_service->AddExtensionUpdateRequest(extension->id(), 1674 supervised_user_service->AddExtensionUpdateRequest(extension->id(),
1661 *extension->version()); 1675 *extension->version());
1662 } 1676 }
1663 #endif 1677 #endif
1664 } 1678 }
1665 if (disable_reasons != Extension::DISABLE_NONE) 1679
1680 if (disable_reasons == Extension::DISABLE_NONE)
1681 extension_prefs_->SetExtensionEnabled(extension->id());
1682 else
1666 extension_prefs_->SetExtensionDisabled(extension->id(), disable_reasons); 1683 extension_prefs_->SetExtensionDisabled(extension->id(), disable_reasons);
1667 } 1684 }
1668 1685
1669 void ExtensionService::UpdateActiveExtensionsInCrashReporter() { 1686 void ExtensionService::UpdateActiveExtensionsInCrashReporter() {
1670 std::set<std::string> extension_ids; 1687 std::set<std::string> extension_ids;
1671 for (const auto& extension : registry_->enabled_extensions()) { 1688 for (const auto& extension : registry_->enabled_extensions()) {
1672 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT) 1689 if (!extension->is_theme() && extension->location() != Manifest::COMPONENT)
1673 extension_ids.insert(extension->id()); 1690 extension_ids.insert(extension->id());
1674 } 1691 }
1675 1692
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after
2433 } 2450 }
2434 2451
2435 void ExtensionService::OnProfileDestructionStarted() { 2452 void ExtensionService::OnProfileDestructionStarted() {
2436 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs(); 2453 ExtensionIdSet ids_to_unload = registry_->enabled_extensions().GetIDs();
2437 for (ExtensionIdSet::iterator it = ids_to_unload.begin(); 2454 for (ExtensionIdSet::iterator it = ids_to_unload.begin();
2438 it != ids_to_unload.end(); 2455 it != ids_to_unload.end();
2439 ++it) { 2456 ++it) {
2440 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN); 2457 UnloadExtension(*it, UnloadedExtensionInfo::REASON_PROFILE_SHUTDOWN);
2441 } 2458 }
2442 } 2459 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_service.h ('k') | chrome/browser/extensions/extension_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698