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

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

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