| 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 <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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |