OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <set> | 8 #include <set> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 omnibox_popup_icon_manager_.set_monochrome(true); | 437 omnibox_popup_icon_manager_.set_monochrome(true); |
438 omnibox_icon_manager_.set_monochrome(true); | 438 omnibox_icon_manager_.set_monochrome(true); |
439 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, | 439 omnibox_icon_manager_.set_padding(gfx::Insets(0, kOmniboxIconPaddingLeft, |
440 0, kOmniboxIconPaddingRight)); | 440 0, kOmniboxIconPaddingRight)); |
441 | 441 |
442 // How long is the path to the Extensions directory? | 442 // How long is the path to the Extensions directory? |
443 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ExtensionRootPathLength", | 443 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ExtensionRootPathLength", |
444 install_directory_.value().length(), 0, 500, 100); | 444 install_directory_.value().length(), 0, 500, 100); |
445 } | 445 } |
446 | 446 |
447 const ExtensionSet* ExtensionService::extensions() const { | 447 const ExtensionList* ExtensionService::extensions() const { |
448 return &extensions_; | 448 return &extensions_; |
449 } | 449 } |
450 | 450 |
451 const ExtensionSet* ExtensionService::disabled_extensions() const { | 451 const ExtensionList* ExtensionService::disabled_extensions() const { |
452 return &disabled_extensions_; | 452 return &disabled_extensions_; |
453 } | 453 } |
454 | 454 |
455 const ExtensionSet* ExtensionService::terminated_extensions() const { | 455 const ExtensionList* ExtensionService::terminated_extensions() const { |
456 return &terminated_extensions_; | 456 return &terminated_extensions_; |
457 } | 457 } |
458 | 458 |
459 PendingExtensionManager* ExtensionService::pending_extension_manager() { | 459 PendingExtensionManager* ExtensionService::pending_extension_manager() { |
460 return &pending_extension_manager_; | 460 return &pending_extension_manager_; |
461 } | 461 } |
462 | 462 |
463 ExtensionService::~ExtensionService() { | 463 ExtensionService::~ExtensionService() { |
464 // No need to unload extensions here because they are profile-scoped, and the | 464 // No need to unload extensions here because they are profile-scoped, and the |
465 // profile is in the process of being deleted. | 465 // profile is in the process of being deleted. |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 // Therefore, we clear warnings of this type for all extensions. | 759 // Therefore, we clear warnings of this type for all extensions. |
760 std::set<ExtensionWarningSet::WarningType> warnings; | 760 std::set<ExtensionWarningSet::WarningType> warnings; |
761 extension_warnings_.GetWarningsAffectingExtension(extension_id, &warnings); | 761 extension_warnings_.GetWarningsAffectingExtension(extension_id, &warnings); |
762 extension_warnings_.ClearWarnings(warnings); | 762 extension_warnings_.ClearWarnings(warnings); |
763 | 763 |
764 return true; | 764 return true; |
765 } | 765 } |
766 | 766 |
767 bool ExtensionService::IsExtensionEnabled( | 767 bool ExtensionService::IsExtensionEnabled( |
768 const std::string& extension_id) const { | 768 const std::string& extension_id) const { |
769 if (extensions_.Contains(extension_id) || | 769 const Extension* extension = |
770 terminated_extensions_.Contains(extension_id)) | 770 GetExtensionByIdInternal(extension_id, true, false, true); |
| 771 if (extension) |
771 return true; | 772 return true; |
772 | 773 |
773 if (disabled_extensions_.Contains(extension_id)) | 774 extension = |
| 775 GetExtensionByIdInternal(extension_id, false, true, false); |
| 776 if (extension) |
774 return false; | 777 return false; |
775 | 778 |
776 // If the extension hasn't been loaded yet, check the prefs for it. Assume | 779 // If the extension hasn't been loaded yet, check the prefs for it. Assume |
777 // enabled unless otherwise noted. | 780 // enabled unless otherwise noted. |
778 return !extension_prefs_->IsExtensionDisabled(extension_id) && | 781 return !extension_prefs_->IsExtensionDisabled(extension_id) && |
779 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); | 782 !extension_prefs_->IsExternalExtensionUninstalled(extension_id); |
780 } | 783 } |
781 | 784 |
782 bool ExtensionService::IsExternalExtensionUninstalled( | 785 bool ExtensionService::IsExternalExtensionUninstalled( |
783 const std::string& extension_id) const { | 786 const std::string& extension_id) const { |
784 return extension_prefs_->IsExternalExtensionUninstalled(extension_id); | 787 return extension_prefs_->IsExternalExtensionUninstalled(extension_id); |
785 } | 788 } |
786 | 789 |
787 void ExtensionService::EnableExtension(const std::string& extension_id) { | 790 void ExtensionService::EnableExtension(const std::string& extension_id) { |
788 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 791 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
789 | 792 |
790 if (IsExtensionEnabled(extension_id)) | 793 if (IsExtensionEnabled(extension_id)) |
791 return; | 794 return; |
792 | 795 |
793 extension_prefs_->SetExtensionState(extension_id, Extension::ENABLED); | 796 extension_prefs_->SetExtensionState(extension_id, Extension::ENABLED); |
794 | 797 |
795 const Extension* extension = | 798 const Extension* extension = |
796 GetExtensionByIdInternal(extension_id, false, true, false); | 799 GetExtensionByIdInternal(extension_id, false, true, false); |
797 // This can happen if sync enables an extension that is not | 800 // This can happen if sync enables an extension that is not |
798 // installed yet. | 801 // installed yet. |
799 if (!extension) | 802 if (!extension) |
800 return; | 803 return; |
801 | 804 |
802 // Move it over to the enabled list. | 805 // Move it over to the enabled list. |
803 extensions_.Insert(make_scoped_refptr(extension)); | 806 extensions_.push_back(make_scoped_refptr(extension)); |
804 disabled_extensions_.Remove(extension->id()); | 807 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(), |
| 808 disabled_extensions_.end(), |
| 809 extension); |
| 810 disabled_extensions_.erase(iter); |
805 | 811 |
806 // Make sure any browser action contained within it is not hidden. | 812 // Make sure any browser action contained within it is not hidden. |
807 extension_prefs_->SetBrowserActionVisibility(extension, true); | 813 extension_prefs_->SetBrowserActionVisibility(extension, true); |
808 | 814 |
809 NotifyExtensionLoaded(extension); | 815 NotifyExtensionLoaded(extension); |
810 | 816 |
811 SyncExtensionChangeIfNeeded(*extension); | 817 SyncExtensionChangeIfNeeded(*extension); |
812 } | 818 } |
813 | 819 |
814 void ExtensionService::DisableExtension(const std::string& extension_id) { | 820 void ExtensionService::DisableExtension(const std::string& extension_id) { |
815 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 821 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
816 | 822 |
817 // The extension may have been disabled already. | 823 // The extension may have been disabled already. |
818 if (!IsExtensionEnabled(extension_id)) | 824 if (!IsExtensionEnabled(extension_id)) |
819 return; | 825 return; |
820 | 826 |
821 const Extension* extension = GetInstalledExtension(extension_id); | 827 const Extension* extension = GetInstalledExtension(extension_id); |
822 // |extension| can be NULL if sync disables an extension that is not | 828 // |extension| can be NULL if sync disables an extension that is not |
823 // installed yet. | 829 // installed yet. |
824 if (extension && !Extension::UserMayDisable(extension->location())) | 830 if (extension && !Extension::UserMayDisable(extension->location())) |
825 return; | 831 return; |
826 | 832 |
827 extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED); | 833 extension_prefs_->SetExtensionState(extension_id, Extension::DISABLED); |
828 | 834 |
829 extension = GetExtensionByIdInternal(extension_id, true, false, true); | 835 extension = GetExtensionByIdInternal(extension_id, true, false, true); |
830 if (!extension) | 836 if (!extension) |
831 return; | 837 return; |
832 | 838 |
833 // Move it over to the disabled list. | 839 // Move it over to the disabled list. |
834 disabled_extensions_.Insert(make_scoped_refptr(extension)); | 840 disabled_extensions_.push_back(make_scoped_refptr(extension)); |
835 if (extensions_.Contains(extension->id())) | 841 ExtensionList::iterator iter = std::find(extensions_.begin(), |
836 extensions_.Remove(extension->id()); | 842 extensions_.end(), |
837 else | 843 extension); |
838 terminated_extensions_.Remove(extension->id()); | 844 if (iter != extensions_.end()) { |
| 845 extensions_.erase(iter); |
| 846 } else { |
| 847 iter = std::find(terminated_extensions_.begin(), |
| 848 terminated_extensions_.end(), |
| 849 extension); |
| 850 terminated_extensions_.erase(iter); |
| 851 } |
839 | 852 |
840 NotifyExtensionUnloaded(extension, extension_misc::UNLOAD_REASON_DISABLE); | 853 NotifyExtensionUnloaded(extension, extension_misc::UNLOAD_REASON_DISABLE); |
841 | 854 |
842 SyncExtensionChangeIfNeeded(*extension); | 855 SyncExtensionChangeIfNeeded(*extension); |
843 | 856 |
844 // Deactivating one extension might have solved the problems of others. | 857 // Deactivating one extension might have solved the problems of others. |
845 // Therefore, we clear warnings of this type for all extensions. | 858 // Therefore, we clear warnings of this type for all extensions. |
846 std::set<ExtensionWarningSet::WarningType> warnings; | 859 std::set<ExtensionWarningSet::WarningType> warnings; |
847 extension_warnings_.GetWarningsAffectingExtension(extension_id, &warnings); | 860 extension_warnings_.GetWarningsAffectingExtension(extension_id, &warnings); |
848 extension_warnings_.ClearWarnings(warnings); | 861 extension_warnings_.ClearWarnings(warnings); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1095 // Use this set to indicate if an extension in the blacklist has been used. | 1108 // Use this set to indicate if an extension in the blacklist has been used. |
1096 std::set<std::string> blacklist_set; | 1109 std::set<std::string> blacklist_set; |
1097 for (unsigned int i = 0; i < blacklist.size(); ++i) { | 1110 for (unsigned int i = 0; i < blacklist.size(); ++i) { |
1098 if (Extension::IdIsValid(blacklist[i])) { | 1111 if (Extension::IdIsValid(blacklist[i])) { |
1099 blacklist_set.insert(blacklist[i]); | 1112 blacklist_set.insert(blacklist[i]); |
1100 } | 1113 } |
1101 } | 1114 } |
1102 extension_prefs_->UpdateBlacklist(blacklist_set); | 1115 extension_prefs_->UpdateBlacklist(blacklist_set); |
1103 std::vector<std::string> to_be_removed; | 1116 std::vector<std::string> to_be_removed; |
1104 // Loop current extensions, unload installed extensions. | 1117 // Loop current extensions, unload installed extensions. |
1105 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 1118 for (ExtensionList::const_iterator iter = extensions_.begin(); |
1106 iter != extensions_.end(); ++iter) { | 1119 iter != extensions_.end(); ++iter) { |
1107 const Extension* extension = (*iter); | 1120 const Extension* extension = (*iter); |
1108 if (blacklist_set.find(extension->id()) != blacklist_set.end()) { | 1121 if (blacklist_set.find(extension->id()) != blacklist_set.end()) { |
1109 to_be_removed.push_back(extension->id()); | 1122 to_be_removed.push_back(extension->id()); |
1110 } | 1123 } |
1111 } | 1124 } |
1112 | 1125 |
1113 // UnloadExtension will change the extensions_ list. So, we should | 1126 // UnloadExtension will change the extensions_ list. So, we should |
1114 // call it outside the iterator loop. | 1127 // call it outside the iterator loop. |
1115 for (unsigned int i = 0; i < to_be_removed.size(); ++i) { | 1128 for (unsigned int i = 0; i < to_be_removed.size(); ++i) { |
(...skipping 22 matching lines...) Expand all Loading... |
1138 return ready_; | 1151 return ready_; |
1139 } | 1152 } |
1140 | 1153 |
1141 ExtensionUpdater* ExtensionService::updater() { | 1154 ExtensionUpdater* ExtensionService::updater() { |
1142 return updater_.get(); | 1155 return updater_.get(); |
1143 } | 1156 } |
1144 | 1157 |
1145 void ExtensionService::CheckAdminBlacklist() { | 1158 void ExtensionService::CheckAdminBlacklist() { |
1146 std::vector<std::string> to_be_removed; | 1159 std::vector<std::string> to_be_removed; |
1147 // Loop through extensions list, unload installed extensions. | 1160 // Loop through extensions list, unload installed extensions. |
1148 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 1161 for (ExtensionList::const_iterator iter = extensions_.begin(); |
1149 iter != extensions_.end(); ++iter) { | 1162 iter != extensions_.end(); ++iter) { |
1150 const Extension* extension = (*iter); | 1163 const Extension* extension = (*iter); |
1151 if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id(), | 1164 if (!extension_prefs_->IsExtensionAllowedByPolicy(extension->id(), |
1152 extension->location())) { | 1165 extension->location())) { |
1153 to_be_removed.push_back(extension->id()); | 1166 to_be_removed.push_back(extension->id()); |
1154 } | 1167 } |
1155 } | 1168 } |
1156 | 1169 |
1157 // UnloadExtension will change the extensions_ list. So, we should | 1170 // UnloadExtension will change the extensions_ list. So, we should |
1158 // call it outside the iterator loop. | 1171 // call it outside the iterator loop. |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 bundle->synced_extensions.erase(extension_sync_data.id()); | 1352 bundle->synced_extensions.erase(extension_sync_data.id()); |
1340 else | 1353 else |
1341 bundle->synced_extensions.insert(extension_sync_data.id()); | 1354 bundle->synced_extensions.insert(extension_sync_data.id()); |
1342 ProcessExtensionSyncData(extension_sync_data, *bundle); | 1355 ProcessExtensionSyncData(extension_sync_data, *bundle); |
1343 } | 1356 } |
1344 | 1357 |
1345 return SyncError(); | 1358 return SyncError(); |
1346 } | 1359 } |
1347 | 1360 |
1348 void ExtensionService::GetSyncDataListHelper( | 1361 void ExtensionService::GetSyncDataListHelper( |
1349 const ExtensionSet& extensions, | 1362 const ExtensionList& extensions, |
1350 const SyncBundle& bundle, | 1363 const SyncBundle& bundle, |
1351 std::vector<ExtensionSyncData>* sync_data_list) const { | 1364 std::vector<ExtensionSyncData>* sync_data_list) const { |
1352 for (ExtensionSet::const_iterator it = extensions.begin(); | 1365 for (ExtensionList::const_iterator it = extensions.begin(); |
1353 it != extensions.end(); ++it) { | 1366 it != extensions.end(); ++it) { |
1354 const Extension& extension = **it; | 1367 const Extension& extension = **it; |
1355 if (bundle.filter(extension) && | 1368 if (bundle.filter(extension) && |
1356 // If we have pending extension data for this extension, then this | 1369 // If we have pending extension data for this extension, then this |
1357 // version is out of date. We'll sync back the version we got from | 1370 // version is out of date. We'll sync back the version we got from |
1358 // sync. | 1371 // sync. |
1359 !bundle.HasPendingExtensionId(extension.id())) { | 1372 !bundle.HasPendingExtensionId(extension.id())) { |
1360 sync_data_list->push_back(ExtensionSyncData( | 1373 sync_data_list->push_back(ExtensionSyncData( |
1361 extension, | 1374 extension, |
1362 IsExtensionEnabled(extension.id()), | 1375 IsExtensionEnabled(extension.id()), |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 | 1486 |
1474 // Broadcast unloaded and loaded events to update browser state. Only bother | 1487 // Broadcast unloaded and loaded events to update browser state. Only bother |
1475 // if the value changed and the extension is actually enabled, since there is | 1488 // if the value changed and the extension is actually enabled, since there is |
1476 // no UI otherwise. | 1489 // no UI otherwise. |
1477 bool old_enabled = extension_prefs_->IsIncognitoEnabled(extension_id); | 1490 bool old_enabled = extension_prefs_->IsIncognitoEnabled(extension_id); |
1478 if (enabled == old_enabled) | 1491 if (enabled == old_enabled) |
1479 return; | 1492 return; |
1480 | 1493 |
1481 extension_prefs_->SetIsIncognitoEnabled(extension_id, enabled); | 1494 extension_prefs_->SetIsIncognitoEnabled(extension_id, enabled); |
1482 | 1495 |
1483 bool extension_is_enabled = extensions_.Contains(extension->id()); | 1496 bool extension_is_enabled = std::find(extensions_.begin(), extensions_.end(), |
| 1497 extension) != extensions_.end(); |
1484 | 1498 |
1485 // When we reload the extension the ID may be invalidated if we've passed it | 1499 // When we reload the extension the ID may be invalidated if we've passed it |
1486 // by const ref everywhere. Make a copy to be safe. | 1500 // by const ref everywhere. Make a copy to be safe. |
1487 std::string id = extension_id; | 1501 std::string id = extension_id; |
1488 if (extension_is_enabled) | 1502 if (extension_is_enabled) |
1489 ReloadExtension(extension->id()); | 1503 ReloadExtension(extension->id()); |
1490 | 1504 |
1491 // Reloading the extension invalidates the |extension| pointer. | 1505 // Reloading the extension invalidates the |extension| pointer. |
1492 extension = GetInstalledExtension(id); | 1506 extension = GetInstalledExtension(id); |
1493 if (extension) | 1507 if (extension) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 void ExtensionService::SetAllowFileAccess(const Extension* extension, | 1564 void ExtensionService::SetAllowFileAccess(const Extension* extension, |
1551 bool allow) { | 1565 bool allow) { |
1552 // Reload to update browser state. Only bother if the value changed and the | 1566 // Reload to update browser state. Only bother if the value changed and the |
1553 // extension is actually enabled, since there is no UI otherwise. | 1567 // extension is actually enabled, since there is no UI otherwise. |
1554 bool old_allow = AllowFileAccess(extension); | 1568 bool old_allow = AllowFileAccess(extension); |
1555 if (allow == old_allow) | 1569 if (allow == old_allow) |
1556 return; | 1570 return; |
1557 | 1571 |
1558 extension_prefs_->SetAllowFileAccess(extension->id(), allow); | 1572 extension_prefs_->SetAllowFileAccess(extension->id(), allow); |
1559 | 1573 |
1560 bool extension_is_enabled = extensions_.Contains(extension->id()); | 1574 bool extension_is_enabled = std::find(extensions_.begin(), extensions_.end(), |
| 1575 extension) != extensions_.end(); |
1561 if (extension_is_enabled) | 1576 if (extension_is_enabled) |
1562 ReloadExtension(extension->id()); | 1577 ReloadExtension(extension->id()); |
1563 } | 1578 } |
1564 | 1579 |
1565 bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) { | 1580 bool ExtensionService::GetBrowserActionVisibility(const Extension* extension) { |
1566 return extension_prefs_->GetBrowserActionVisibility(extension); | 1581 return extension_prefs_->GetBrowserActionVisibility(extension); |
1567 } | 1582 } |
1568 | 1583 |
1569 void ExtensionService::SetBrowserActionVisibility(const Extension* extension, | 1584 void ExtensionService::SetBrowserActionVisibility(const Extension* extension, |
1570 bool visible) { | 1585 bool visible) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1654 switches::kEnableExtensionAlerts)) { | 1669 switches::kEnableExtensionAlerts)) { |
1655 return; // TODO(miket): enable unconditionally when done. | 1670 return; // TODO(miket): enable unconditionally when done. |
1656 } | 1671 } |
1657 | 1672 |
1658 // Build up the lists of extensions that require acknowledgment. | 1673 // Build up the lists of extensions that require acknowledgment. |
1659 // If this is the first time, grandfather extensions that would have | 1674 // If this is the first time, grandfather extensions that would have |
1660 // caused notification. | 1675 // caused notification. |
1661 scoped_ptr<ExtensionGlobalError> global_error( | 1676 scoped_ptr<ExtensionGlobalError> global_error( |
1662 new ExtensionGlobalError(AsWeakPtr())); | 1677 new ExtensionGlobalError(AsWeakPtr())); |
1663 bool needs_alert = false; | 1678 bool needs_alert = false; |
1664 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 1679 for (ExtensionList::const_iterator iter = extensions_.begin(); |
1665 iter != extensions_.end(); ++iter) { | 1680 iter != extensions_.end(); ++iter) { |
1666 const Extension* e = *iter; | 1681 const Extension* e = *iter; |
| 1682 if (!IsExtensionEnabled(e->id())) { |
| 1683 continue; |
| 1684 } |
1667 if (Extension::IsExternalLocation(e->location())) { | 1685 if (Extension::IsExternalLocation(e->location())) { |
1668 if (!extension_prefs_->IsExternalExtensionAcknowledged(e->id())) { | 1686 if (!extension_prefs_->IsExternalExtensionAcknowledged(e->id())) { |
1669 global_error->AddExternalExtension(e->id()); | 1687 global_error->AddExternalExtension(e->id()); |
1670 needs_alert = true; | 1688 needs_alert = true; |
1671 } | 1689 } |
1672 } | 1690 } |
1673 if (extension_prefs_->IsExtensionBlacklisted(e->id())) { | 1691 if (extension_prefs_->IsExtensionBlacklisted(e->id())) { |
1674 if (!extension_prefs_->IsBlacklistedExtensionAcknowledged(e->id())) { | 1692 if (!extension_prefs_->IsBlacklistedExtensionAcknowledged(e->id())) { |
1675 global_error->AddBlacklistedExtension(e->id()); | 1693 global_error->AddBlacklistedExtension(e->id()); |
1676 needs_alert = true; | 1694 needs_alert = true; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1756 // Keep information about the extension so that we can reload it later | 1774 // Keep information about the extension so that we can reload it later |
1757 // even if it's not permanently installed. | 1775 // even if it's not permanently installed. |
1758 unloaded_extension_paths_[extension->id()] = extension->path(); | 1776 unloaded_extension_paths_[extension->id()] = extension->path(); |
1759 | 1777 |
1760 // Clean up if the extension is meant to be enabled after a reload. | 1778 // Clean up if the extension is meant to be enabled after a reload. |
1761 disabled_extension_paths_.erase(extension->id()); | 1779 disabled_extension_paths_.erase(extension->id()); |
1762 | 1780 |
1763 // Clean up runtime data. | 1781 // Clean up runtime data. |
1764 extension_runtime_data_.erase(extension_id); | 1782 extension_runtime_data_.erase(extension_id); |
1765 | 1783 |
1766 if (disabled_extensions_.Contains(extension->id())) { | 1784 ExtensionList::iterator iter = std::find(disabled_extensions_.begin(), |
| 1785 disabled_extensions_.end(), |
| 1786 extension.get()); |
| 1787 if (iter != disabled_extensions_.end()) { |
1767 UnloadedExtensionInfo details(extension, reason); | 1788 UnloadedExtensionInfo details(extension, reason); |
1768 details.already_disabled = true; | 1789 details.already_disabled = true; |
1769 disabled_extensions_.Remove(extension->id()); | 1790 disabled_extensions_.erase(iter); |
1770 content::NotificationService::current()->Notify( | 1791 content::NotificationService::current()->Notify( |
1771 chrome::NOTIFICATION_EXTENSION_UNLOADED, | 1792 chrome::NOTIFICATION_EXTENSION_UNLOADED, |
1772 content::Source<Profile>(profile_), | 1793 content::Source<Profile>(profile_), |
1773 content::Details<UnloadedExtensionInfo>(&details)); | 1794 content::Details<UnloadedExtensionInfo>(&details)); |
1774 // Make sure the profile cleans up its RequestContexts when an already | 1795 // Make sure the profile cleans up its RequestContexts when an already |
1775 // disabled extension is unloaded (since they are also tracking the disabled | 1796 // disabled extension is unloaded (since they are also tracking the disabled |
1776 // extensions). | 1797 // extensions). |
1777 profile_->UnregisterExtensionWithRequestContexts(extension_id, reason); | 1798 profile_->UnregisterExtensionWithRequestContexts(extension_id, reason); |
1778 return; | 1799 return; |
1779 } | 1800 } |
1780 | 1801 |
1781 // Remove the extension from our list. | 1802 iter = std::find(extensions_.begin(), extensions_.end(), extension.get()); |
1782 extensions_.Remove(extension->id()); | 1803 |
| 1804 // Remove the extension from our list. |
| 1805 extensions_.erase(iter); |
1783 | 1806 |
1784 NotifyExtensionUnloaded(extension.get(), reason); | 1807 NotifyExtensionUnloaded(extension.get(), reason); |
1785 } | 1808 } |
1786 | 1809 |
1787 void ExtensionService::UnloadAllExtensions() { | 1810 void ExtensionService::UnloadAllExtensions() { |
1788 profile_->GetExtensionSpecialStoragePolicy()-> | 1811 profile_->GetExtensionSpecialStoragePolicy()-> |
1789 RevokeRightsForAllExtensions(); | 1812 RevokeRightsForAllExtensions(); |
1790 | 1813 |
1791 extensions_.Clear(); | 1814 extensions_.clear(); |
1792 disabled_extensions_.Clear(); | 1815 disabled_extensions_.clear(); |
1793 terminated_extensions_.Clear(); | 1816 terminated_extension_ids_.clear(); |
| 1817 terminated_extensions_.clear(); |
1794 extension_runtime_data_.clear(); | 1818 extension_runtime_data_.clear(); |
1795 | 1819 |
1796 // TODO(erikkay) should there be a notification for this? We can't use | 1820 // TODO(erikkay) should there be a notification for this? We can't use |
1797 // EXTENSION_UNLOADED since that implies that the extension has been disabled | 1821 // EXTENSION_UNLOADED since that implies that the extension has been disabled |
1798 // or uninstalled, and UnloadAll is just part of shutdown. | 1822 // or uninstalled, and UnloadAll is just part of shutdown. |
1799 } | 1823 } |
1800 | 1824 |
1801 void ExtensionService::ReloadExtensions() { | 1825 void ExtensionService::ReloadExtensions() { |
1802 UnloadAllExtensions(); | 1826 UnloadAllExtensions(); |
1803 component_loader_->LoadAll(); | 1827 component_loader_->LoadAll(); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1867 // If the extension was disabled for a reload, then enable it. | 1891 // If the extension was disabled for a reload, then enable it. |
1868 if (disabled_extension_paths_.erase(extension->id()) > 0) | 1892 if (disabled_extension_paths_.erase(extension->id()) > 0) |
1869 EnableExtension(extension->id()); | 1893 EnableExtension(extension->id()); |
1870 | 1894 |
1871 // Check if the extension's privileges have changed and disable the | 1895 // Check if the extension's privileges have changed and disable the |
1872 // extension if necessary. | 1896 // extension if necessary. |
1873 InitializePermissions(extension); | 1897 InitializePermissions(extension); |
1874 | 1898 |
1875 bool disabled = extension_prefs_->IsExtensionDisabled(extension->id()); | 1899 bool disabled = extension_prefs_->IsExtensionDisabled(extension->id()); |
1876 if (disabled) { | 1900 if (disabled) { |
1877 disabled_extensions_.Insert(scoped_extension); | 1901 disabled_extensions_.push_back(scoped_extension); |
1878 // TODO(aa): This seems dodgy. AddExtension() could get called with a | 1902 // TODO(aa): This seems dodgy. It seems that AddExtension() could get called |
1879 // disabled extension for other reasons other than that an update was | 1903 // with a disabled extension for other reasons other than that an update was |
1880 // disabled, e.g. as in ExtensionManagementTest.InstallRequiresConfirm. | 1904 // disabled. |
1881 content::NotificationService::current()->Notify( | 1905 content::NotificationService::current()->Notify( |
1882 chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED, | 1906 chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED, |
1883 content::Source<Profile>(profile_), | 1907 content::Source<Profile>(profile_), |
1884 content::Details<const Extension>(extension)); | 1908 content::Details<const Extension>(extension)); |
1885 SyncExtensionChangeIfNeeded(*extension); | 1909 SyncExtensionChangeIfNeeded(*extension); |
1886 return; | 1910 return; |
1887 } | 1911 } |
1888 | 1912 |
1889 extensions_.Insert(scoped_extension); | 1913 extensions_.push_back(scoped_extension); |
1890 SyncExtensionChangeIfNeeded(*extension); | 1914 SyncExtensionChangeIfNeeded(*extension); |
1891 NotifyExtensionLoaded(extension); | 1915 NotifyExtensionLoaded(extension); |
1892 IdentifyAlertableExtensions(); | 1916 IdentifyAlertableExtensions(); |
1893 } | 1917 } |
1894 | 1918 |
1895 void ExtensionService::InitializePermissions(const Extension* extension) { | 1919 void ExtensionService::InitializePermissions(const Extension* extension) { |
1896 // If the extension has used the optional permissions API, it will have a | 1920 // If the extension has used the optional permissions API, it will have a |
1897 // custom set of active permissions defined in the extension prefs. Here, | 1921 // custom set of active permissions defined in the extension prefs. Here, |
1898 // we update the extension's active permissions based on the prefs. | 1922 // we update the extension's active permissions based on the prefs. |
1899 scoped_refptr<ExtensionPermissionSet> active_permissions = | 1923 scoped_refptr<ExtensionPermissionSet> active_permissions = |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1991 RecordPermissionMessagesHistogram( | 2015 RecordPermissionMessagesHistogram( |
1992 extension, "Extensions.Permissions_AutoDisable"); | 2016 extension, "Extensions.Permissions_AutoDisable"); |
1993 } | 2017 } |
1994 extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED); | 2018 extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED); |
1995 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); | 2019 extension_prefs_->SetDidExtensionEscalatePermissions(extension, true); |
1996 } | 2020 } |
1997 } | 2021 } |
1998 | 2022 |
1999 void ExtensionService::UpdateActiveExtensionsInCrashReporter() { | 2023 void ExtensionService::UpdateActiveExtensionsInCrashReporter() { |
2000 std::set<std::string> extension_ids; | 2024 std::set<std::string> extension_ids; |
2001 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 2025 for (size_t i = 0; i < extensions_.size(); ++i) { |
2002 iter != extensions_.end(); ++iter) { | 2026 if (!extensions_[i]->is_theme() && |
2003 const Extension* extension = *iter; | 2027 extensions_[i]->location() != Extension::COMPONENT) |
2004 if (!extension->is_theme() && extension->location() != Extension::COMPONENT) | 2028 extension_ids.insert(extensions_[i]->id()); |
2005 extension_ids.insert(extension->id()); | |
2006 } | 2029 } |
2007 | 2030 |
2008 child_process_logging::SetActiveExtensions(extension_ids); | 2031 child_process_logging::SetActiveExtensions(extension_ids); |
2009 } | 2032 } |
2010 | 2033 |
2011 void ExtensionService::OnExtensionInstalled( | 2034 void ExtensionService::OnExtensionInstalled( |
2012 const Extension* extension, bool from_webstore, int page_index) { | 2035 const Extension* extension, bool from_webstore, int page_index) { |
2013 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2036 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2014 | 2037 |
2015 // Ensure extension is deleted unless we transfer ownership. | 2038 // Ensure extension is deleted unless we transfer ownership. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2088 | 2111 |
2089 // Transfer ownership of |extension| to AddExtension. | 2112 // Transfer ownership of |extension| to AddExtension. |
2090 AddExtension(scoped_extension); | 2113 AddExtension(scoped_extension); |
2091 } | 2114 } |
2092 | 2115 |
2093 const Extension* ExtensionService::GetExtensionByIdInternal( | 2116 const Extension* ExtensionService::GetExtensionByIdInternal( |
2094 const std::string& id, bool include_enabled, bool include_disabled, | 2117 const std::string& id, bool include_enabled, bool include_disabled, |
2095 bool include_terminated) const { | 2118 bool include_terminated) const { |
2096 std::string lowercase_id = StringToLowerASCII(id); | 2119 std::string lowercase_id = StringToLowerASCII(id); |
2097 if (include_enabled) { | 2120 if (include_enabled) { |
2098 const Extension* extension = extensions_.GetByID(lowercase_id); | 2121 for (ExtensionList::const_iterator iter = extensions_.begin(); |
2099 if (extension) | 2122 iter != extensions_.end(); ++iter) { |
2100 return extension; | 2123 if ((*iter)->id() == lowercase_id) |
| 2124 return *iter; |
| 2125 } |
2101 } | 2126 } |
2102 if (include_disabled) { | 2127 if (include_disabled) { |
2103 const Extension* extension = disabled_extensions_.GetByID(lowercase_id); | 2128 for (ExtensionList::const_iterator iter = disabled_extensions_.begin(); |
2104 if (extension) | 2129 iter != disabled_extensions_.end(); ++iter) { |
2105 return extension; | 2130 if ((*iter)->id() == lowercase_id) |
| 2131 return *iter; |
| 2132 } |
2106 } | 2133 } |
2107 if (include_terminated) { | 2134 if (include_terminated) { |
2108 const Extension* extension = terminated_extensions_.GetByID(lowercase_id); | 2135 for (ExtensionList::const_iterator iter = terminated_extensions_.begin(); |
2109 if (extension) | 2136 iter != terminated_extensions_.end(); ++iter) { |
2110 return extension; | 2137 if ((*iter)->id() == lowercase_id) |
| 2138 return *iter; |
| 2139 } |
2111 } | 2140 } |
2112 return NULL; | 2141 return NULL; |
2113 } | 2142 } |
2114 | 2143 |
2115 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { | 2144 void ExtensionService::TrackTerminatedExtension(const Extension* extension) { |
2116 if (!terminated_extensions_.Contains(extension->id())) | 2145 if (terminated_extension_ids_.insert(extension->id()).second) |
2117 terminated_extensions_.Insert(make_scoped_refptr(extension)); | 2146 terminated_extensions_.push_back(make_scoped_refptr(extension)); |
2118 | 2147 |
| 2148 // TODO(yoz): Listen to navcontrollers for that extension. Is this a todo? |
| 2149 |
| 2150 // TODO(yoz): make sure this is okay in *ALL* the listeners! |
2119 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); | 2151 UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_TERMINATE); |
2120 } | 2152 } |
2121 | 2153 |
2122 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { | 2154 void ExtensionService::UntrackTerminatedExtension(const std::string& id) { |
2123 std::string lowercase_id = StringToLowerASCII(id); | 2155 std::string lowercase_id = StringToLowerASCII(id); |
2124 terminated_extensions_.Remove(lowercase_id); | 2156 if (terminated_extension_ids_.erase(lowercase_id) <= 0) |
| 2157 return; |
| 2158 |
| 2159 for (ExtensionList::iterator iter = terminated_extensions_.begin(); |
| 2160 iter != terminated_extensions_.end(); ++iter) { |
| 2161 if ((*iter)->id() == lowercase_id) { |
| 2162 terminated_extensions_.erase(iter); |
| 2163 return; |
| 2164 } |
| 2165 } |
2125 } | 2166 } |
2126 | 2167 |
2127 const Extension* ExtensionService::GetTerminatedExtension( | 2168 const Extension* ExtensionService::GetTerminatedExtension( |
2128 const std::string& id) const { | 2169 const std::string& id) const { |
2129 return GetExtensionByIdInternal(id, false, false, true); | 2170 return GetExtensionByIdInternal(id, false, false, true); |
2130 } | 2171 } |
2131 | 2172 |
2132 const Extension* ExtensionService::GetInstalledExtension( | 2173 const Extension* ExtensionService::GetInstalledExtension( |
2133 const std::string& id) const { | 2174 const std::string& id) const { |
2134 return GetExtensionByIdInternal(id, true, true, true); | 2175 return GetExtensionByIdInternal(id, true, true, true); |
2135 } | 2176 } |
2136 | 2177 |
2137 const Extension* ExtensionService::GetWebStoreApp() { | 2178 const Extension* ExtensionService::GetWebStoreApp() { |
2138 return GetExtensionById(extension_misc::kWebStoreAppId, false); | 2179 return GetExtensionById(extension_misc::kWebStoreAppId, false); |
2139 } | 2180 } |
2140 | 2181 |
2141 const Extension* ExtensionService::GetExtensionByURL(const GURL& url) { | 2182 const Extension* ExtensionService::GetExtensionByURL(const GURL& url) { |
2142 return url.scheme() != chrome::kExtensionScheme ? NULL : | 2183 return url.scheme() != chrome::kExtensionScheme ? NULL : |
2143 GetExtensionById(url.host(), false); | 2184 GetExtensionById(url.host(), false); |
2144 } | 2185 } |
2145 | 2186 |
2146 const Extension* ExtensionService::GetExtensionByWebExtent(const GURL& url) { | 2187 const Extension* ExtensionService::GetExtensionByWebExtent(const GURL& url) { |
2147 // TODO(yoz): Should be ExtensionSet::GetByURL. | 2188 for (size_t i = 0; i < extensions_.size(); ++i) { |
2148 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 2189 if (extensions_[i]->web_extent().MatchesURL(url)) |
2149 iter != extensions_.end(); ++iter) { | 2190 return extensions_[i]; |
2150 if ((*iter)->web_extent().MatchesURL(url)) | |
2151 return *iter; | |
2152 } | 2191 } |
2153 return NULL; | 2192 return NULL; |
2154 } | 2193 } |
2155 | 2194 |
2156 const Extension* ExtensionService::GetDisabledExtensionByWebExtent( | 2195 const Extension* ExtensionService::GetDisabledExtensionByWebExtent( |
2157 const GURL& url) { | 2196 const GURL& url) { |
2158 // TODO(yoz): Should be ExtensionSet::GetByURL. | 2197 for (size_t i = 0; i < disabled_extensions_.size(); ++i) { |
2159 for (ExtensionSet::const_iterator iter = disabled_extensions_.begin(); | 2198 if (disabled_extensions_[i]->web_extent().MatchesURL(url)) |
2160 iter != disabled_extensions_.end(); ++iter) { | 2199 return disabled_extensions_[i]; |
2161 if ((*iter)->web_extent().MatchesURL(url)) | |
2162 return *iter; | |
2163 } | 2200 } |
2164 return NULL; | 2201 return NULL; |
2165 } | 2202 } |
2166 | 2203 |
2167 bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) { | 2204 bool ExtensionService::ExtensionBindingsAllowed(const GURL& url) { |
2168 // Allow bindings for all packaged extensions. | 2205 // Allow bindings for all packaged extensions. |
2169 // Note that GetExtensionByURL may return an Extension for hosted apps | 2206 // Note that GetExtensionByURL may return an Extension for hosted apps |
2170 // (excluding bookmark apps) if the URL came from GetEffectiveURL. | 2207 // (excluding bookmark apps) if the URL came from GetEffectiveURL. |
2171 const Extension* extension = GetExtensionByURL(url); | 2208 const Extension* extension = GetExtensionByURL(url); |
2172 if (extension && extension->GetType() != Extension::TYPE_HOSTED_APP) | 2209 if (extension && extension->GetType() != Extension::TYPE_HOSTED_APP) |
2173 return true; | 2210 return true; |
2174 | 2211 |
2175 // Allow bindings for all component, hosted apps. | 2212 // Allow bindings for all component, hosted apps. |
2176 if (!extension) | 2213 if (!extension) |
2177 extension = GetExtensionByWebExtent(url); | 2214 extension = GetExtensionByWebExtent(url); |
2178 return (extension && extension->location() == Extension::COMPONENT); | 2215 return (extension && extension->location() == Extension::COMPONENT); |
2179 } | 2216 } |
2180 | 2217 |
2181 const Extension* ExtensionService::GetExtensionByOverlappingWebExtent( | 2218 const Extension* ExtensionService::GetExtensionByOverlappingWebExtent( |
2182 const URLPatternSet& extent) { | 2219 const URLPatternSet& extent) { |
2183 // TODO(yoz): Should be in ExtensionSet. | 2220 for (size_t i = 0; i < extensions_.size(); ++i) { |
2184 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 2221 if (extensions_[i]->web_extent().OverlapsWith(extent)) |
2185 iter != extensions_.end(); ++iter) { | 2222 return extensions_[i]; |
2186 if ((*iter)->web_extent().OverlapsWith(extent)) | |
2187 return *iter; | |
2188 } | 2223 } |
2189 | 2224 |
2190 return NULL; | 2225 return NULL; |
2191 } | 2226 } |
2192 | 2227 |
2193 const SkBitmap& ExtensionService::GetOmniboxIcon( | 2228 const SkBitmap& ExtensionService::GetOmniboxIcon( |
2194 const std::string& extension_id) { | 2229 const std::string& extension_id) { |
2195 return omnibox_icon_manager_.GetIcon(extension_id); | 2230 return omnibox_icon_manager_.GetIcon(extension_id); |
2196 } | 2231 } |
2197 | 2232 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2312 ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names); | 2347 ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names); |
2313 process->Send(new ExtensionMsg_SetFunctionNames(function_names)); | 2348 process->Send(new ExtensionMsg_SetFunctionNames(function_names)); |
2314 | 2349 |
2315 // Scripting whitelist. This is modified by tests and must be communicated | 2350 // Scripting whitelist. This is modified by tests and must be communicated |
2316 // to renderers. | 2351 // to renderers. |
2317 process->Send(new ExtensionMsg_SetScriptingWhitelist( | 2352 process->Send(new ExtensionMsg_SetScriptingWhitelist( |
2318 *Extension::GetScriptingWhitelist())); | 2353 *Extension::GetScriptingWhitelist())); |
2319 | 2354 |
2320 // Loaded extensions. | 2355 // Loaded extensions. |
2321 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions; | 2356 std::vector<ExtensionMsg_Loaded_Params> loaded_extensions; |
2322 for (ExtensionSet::const_iterator iter = extensions_.begin(); | 2357 for (size_t i = 0; i < extensions_.size(); ++i) { |
2323 iter != extensions_.end(); ++iter) { | 2358 loaded_extensions.push_back( |
2324 loaded_extensions.push_back(ExtensionMsg_Loaded_Params(*iter)); | 2359 ExtensionMsg_Loaded_Params(extensions_[i])); |
2325 } | 2360 } |
2326 process->Send(new ExtensionMsg_Loaded(loaded_extensions)); | 2361 process->Send(new ExtensionMsg_Loaded(loaded_extensions)); |
2327 break; | 2362 break; |
2328 } | 2363 } |
2329 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { | 2364 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { |
2330 content::RenderProcessHost* process = | 2365 content::RenderProcessHost* process = |
2331 content::Source<content::RenderProcessHost>(source).ptr(); | 2366 content::Source<content::RenderProcessHost>(source).ptr(); |
2332 Profile* host_profile = | 2367 Profile* host_profile = |
2333 Profile::FromBrowserContext(process->GetBrowserContext()); | 2368 Profile::FromBrowserContext(process->GetBrowserContext()); |
2334 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile())) | 2369 if (!profile_->IsSameProfile(host_profile->GetOriginalProfile())) |
(...skipping 30 matching lines...) Expand all Loading... |
2365 NOTREACHED() << "Unexpected notification type."; | 2400 NOTREACHED() << "Unexpected notification type."; |
2366 } | 2401 } |
2367 } | 2402 } |
2368 | 2403 |
2369 bool ExtensionService::HasApps() const { | 2404 bool ExtensionService::HasApps() const { |
2370 return !GetAppIds().empty(); | 2405 return !GetAppIds().empty(); |
2371 } | 2406 } |
2372 | 2407 |
2373 ExtensionIdSet ExtensionService::GetAppIds() const { | 2408 ExtensionIdSet ExtensionService::GetAppIds() const { |
2374 ExtensionIdSet result; | 2409 ExtensionIdSet result; |
2375 for (ExtensionSet::const_iterator it = extensions_.begin(); | 2410 for (ExtensionList::const_iterator it = extensions_.begin(); |
2376 it != extensions_.end(); ++it) { | 2411 it != extensions_.end(); ++it) { |
2377 if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT) | 2412 if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT) |
2378 result.insert((*it)->id()); | 2413 result.insert((*it)->id()); |
2379 } | 2414 } |
2380 | 2415 |
2381 return result; | 2416 return result; |
2382 } | 2417 } |
2383 | 2418 |
2384 bool ExtensionService::IsBackgroundPageReady(const Extension* extension) { | 2419 bool ExtensionService::IsBackgroundPageReady(const Extension* extension) { |
2385 return (extension->background_url().is_empty() || | 2420 return (extension->background_url().is_empty() || |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2484 | 2519 |
2485 ExtensionService::NaClModuleInfoList::iterator | 2520 ExtensionService::NaClModuleInfoList::iterator |
2486 ExtensionService::FindNaClModule(const GURL& url) { | 2521 ExtensionService::FindNaClModule(const GURL& url) { |
2487 for (NaClModuleInfoList::iterator iter = nacl_module_list_.begin(); | 2522 for (NaClModuleInfoList::iterator iter = nacl_module_list_.begin(); |
2488 iter != nacl_module_list_.end(); ++iter) { | 2523 iter != nacl_module_list_.end(); ++iter) { |
2489 if (iter->url == url) | 2524 if (iter->url == url) |
2490 return iter; | 2525 return iter; |
2491 } | 2526 } |
2492 return nacl_module_list_.end(); | 2527 return nacl_module_list_.end(); |
2493 } | 2528 } |
OLD | NEW |