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

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

Issue 10854009: Extension white and force lists (set by policy) should have priority over auto-updated Google black… (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebased and merged Created 8 years, 4 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_prefs.h" 5 #include "chrome/browser/extensions/extension_prefs.h"
6 6
7 #include "base/string_number_conversions.h" 7 #include "base/string_number_conversions.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/extensions/admin_policy.h" 10 #include "chrome/browser/extensions/admin_policy.h"
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 const char* GetToolbarOrderKeyName() { 287 const char* GetToolbarOrderKeyName() {
288 return switch_utils::IsExtensionsInActionBoxEnabled() ? 288 return switch_utils::IsExtensionsInActionBoxEnabled() ?
289 kExtensionActionBoxBar : kExtensionToolbar; 289 kExtensionActionBoxBar : kExtensionToolbar;
290 } 290 }
291 291
292 const char* GetToolbarVisibilityKeyName() { 292 const char* GetToolbarVisibilityKeyName() {
293 return switch_utils::IsExtensionsInActionBoxEnabled() ? 293 return switch_utils::IsExtensionsInActionBoxEnabled() ?
294 kBrowserActionPinned : kBrowserActionVisible; 294 kBrowserActionPinned : kBrowserActionVisible;
295 } 295 }
296 296
297 // Reads a boolean pref from |ext| with key |pref_key|.
298 // Return false if the value is false or |pref_key| does not exist.
299 bool ReadBooleanFromPref(const DictionaryValue* ext,
300 const std::string& pref_key) {
301 bool bool_value = false;
302 ext->GetBoolean(pref_key, &bool_value);
303 return bool_value;
304 }
305
306 // Reads an integer pref from |ext| with key |pref_key|.
307 // Return false if the value does not exist.
308 bool ReadIntegerFromPref(const DictionaryValue* ext,
309 const std::string& pref_key,
310 int* out_value) {
311 if (!ext->GetInteger(pref_key, out_value))
312 return false;
313 return out_value != NULL;
314 }
315
316 // Checks if kPrefBlacklist is set to true in the DictionaryValue.
317 // Return false if the value is false or kPrefBlacklist does not exist.
318 // This is used to decide if an extension is blacklisted.
319 bool IsBlacklistBitSet(const DictionaryValue* ext) {
320 return ReadBooleanFromPref(ext, kPrefBlacklist);
321 }
322
297 } // namespace 323 } // namespace
298 324
299 ExtensionPrefs::ExtensionPrefs( 325 ExtensionPrefs::ExtensionPrefs(
300 PrefService* prefs, 326 PrefService* prefs,
301 const FilePath& root_dir, 327 const FilePath& root_dir,
302 ExtensionPrefValueMap* extension_pref_value_map) 328 ExtensionPrefValueMap* extension_pref_value_map)
303 : prefs_(prefs), 329 : prefs_(prefs),
304 install_directory_(root_dir), 330 install_directory_(root_dir),
305 extension_pref_value_map_(extension_pref_value_map), 331 extension_pref_value_map_(extension_pref_value_map),
306 ALLOW_THIS_IN_INITIALIZER_LIST(extension_sorting_( 332 ALLOW_THIS_IN_INITIALIZER_LIST(extension_sorting_(
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 continue; 400 continue;
375 } 401 }
376 FilePath::StringType path_string; 402 FilePath::StringType path_string;
377 extension_dict->GetString(kPrefPath, &path_string); 403 extension_dict->GetString(kPrefPath, &path_string);
378 FilePath path(path_string); 404 FilePath path(path_string);
379 extension_dict->SetString(kPrefPath, 405 extension_dict->SetString(kPrefPath,
380 MakePathRelative(install_directory_, path)); 406 MakePathRelative(install_directory_, path));
381 } 407 }
382 } 408 }
383 409
384 void ExtensionPrefs::MakePathsAbsolute(DictionaryValue* dict) {
385 if (!dict || dict->empty())
386 return;
387
388 for (DictionaryValue::key_iterator i = dict->begin_keys();
389 i != dict->end_keys(); ++i) {
390 DictionaryValue* extension_dict = NULL;
391 if (!dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) {
392 NOTREACHED();
393 continue;
394 }
395
396 int location_value;
397 if (extension_dict->GetInteger(kPrefLocation, &location_value) &&
398 location_value == Extension::LOAD) {
399 // Unpacked extensions will already have absolute paths.
400 continue;
401 }
402
403 FilePath::StringType path_string;
404 if (!extension_dict->GetString(kPrefPath, &path_string))
405 continue;
406
407 DCHECK(location_value == Extension::COMPONENT ||
408 !FilePath(path_string).IsAbsolute());
409 extension_dict->SetString(
410 kPrefPath, install_directory_.Append(path_string).value());
411 }
412 }
413
414 DictionaryValue* ExtensionPrefs::CopyCurrentExtensions() {
415 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
416 if (extensions) {
417 DictionaryValue* copy = extensions->DeepCopy();
418 MakePathsAbsolute(copy);
419 return copy;
420 }
421 return new DictionaryValue;
422 }
423
424 // static
425 bool ExtensionPrefs::ReadBooleanFromPref(
426 const DictionaryValue* ext, const std::string& pref_key) {
427 bool bool_value = false;
428 ext->GetBoolean(pref_key, &bool_value);
429 return bool_value;
430 }
431
432 bool ExtensionPrefs::ReadExtensionPrefBoolean( 410 bool ExtensionPrefs::ReadExtensionPrefBoolean(
433 const std::string& extension_id, const std::string& pref_key) const { 411 const std::string& extension_id, const std::string& pref_key) const {
434 const DictionaryValue* ext = GetExtensionPref(extension_id); 412 const DictionaryValue* ext = GetExtensionPref(extension_id);
435 if (!ext) { 413 if (!ext) {
436 // No such extension yet. 414 // No such extension yet.
437 return false; 415 return false;
438 } 416 }
439 return ReadBooleanFromPref(ext, pref_key); 417 return ReadBooleanFromPref(ext, pref_key);
440 } 418 }
441 419
442 // static
443 bool ExtensionPrefs::ReadIntegerFromPref(
444 const DictionaryValue* ext, const std::string& pref_key, int* out_value) {
445 if (!ext->GetInteger(pref_key, out_value))
446 return false;
447
448 return out_value != NULL;
449 }
450
451 bool ExtensionPrefs::ReadExtensionPrefInteger( 420 bool ExtensionPrefs::ReadExtensionPrefInteger(
452 const std::string& extension_id, const std::string& pref_key, 421 const std::string& extension_id, const std::string& pref_key,
453 int* out_value) const { 422 int* out_value) const {
454 const DictionaryValue* ext = GetExtensionPref(extension_id); 423 const DictionaryValue* ext = GetExtensionPref(extension_id);
455 if (!ext) { 424 if (!ext) {
456 // No such extension yet. 425 // No such extension yet.
457 return false; 426 return false;
458 } 427 }
459 return ReadIntegerFromPref(ext, pref_key, out_value); 428 return ReadIntegerFromPref(ext, pref_key, out_value);
460 } 429 }
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 } 572 }
604 573
605 // Set the scriptable host permissions. 574 // Set the scriptable host permissions.
606 if (!new_value->scriptable_hosts().is_empty()) { 575 if (!new_value->scriptable_hosts().is_empty()) {
607 SetExtensionPrefURLPatternSet(extension_id, 576 SetExtensionPrefURLPatternSet(extension_id,
608 JoinPrefs(pref_key, kPrefScriptableHosts), 577 JoinPrefs(pref_key, kPrefScriptableHosts),
609 new_value->scriptable_hosts()); 578 new_value->scriptable_hosts());
610 } 579 }
611 } 580 }
612 581
613 // static
614 bool ExtensionPrefs::IsBlacklistBitSet(const DictionaryValue* ext) {
615 return ReadBooleanFromPref(ext, kPrefBlacklist);
616 }
617
618 bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& extension_id) {
619 return ReadExtensionPrefBoolean(extension_id, kPrefBlacklist);
620 }
621
622 bool ExtensionPrefs::IsExtensionOrphaned(const std::string& extension_id) { 582 bool ExtensionPrefs::IsExtensionOrphaned(const std::string& extension_id) {
623 // TODO(miket): we believe that this test will hinge on the number of 583 // TODO(miket): we believe that this test will hinge on the number of
624 // consecutive times that an update check has returned a certain response 584 // consecutive times that an update check has returned a certain response
625 // versus a success response. For now nobody is orphaned. 585 // versus a success response. For now nobody is orphaned.
626 return false; 586 return false;
627 } 587 }
628 588
629 bool ExtensionPrefs::IsExternalExtensionAcknowledged( 589 bool ExtensionPrefs::IsExternalExtensionAcknowledged(
630 const std::string& extension_id) { 590 const std::string& extension_id) {
631 return ReadExtensionPrefBoolean(extension_id, kPrefExternalAcknowledged); 591 return ReadExtensionPrefBoolean(extension_id, kPrefExternalAcknowledged);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 #ifdef NDEBUG 665 #ifdef NDEBUG
706 NOTREACHED(); 666 NOTREACHED();
707 return std::string(); 667 return std::string();
708 #else 668 #else
709 return "admin policy black/white/forcelist, via the ExtensionPrefs"; 669 return "admin policy black/white/forcelist, via the ExtensionPrefs";
710 #endif 670 #endif
711 } 671 }
712 672
713 bool ExtensionPrefs::UserMayLoad(const Extension* extension, 673 bool ExtensionPrefs::UserMayLoad(const Extension* extension,
714 string16* error) const { 674 string16* error) const {
675 const DictionaryValue* ext_prefs = GetExtensionPref(extension->id());
676 bool is_google_blacklisted = ext_prefs && IsBlacklistBitSet(ext_prefs);
715 677
716 const base::ListValue* blacklist = 678 const base::ListValue* blacklist =
717 prefs_->GetList(prefs::kExtensionInstallDenyList); 679 prefs_->GetList(prefs::kExtensionInstallDenyList);
718 const base::ListValue* whitelist = 680 const base::ListValue* whitelist =
719 prefs_->GetList(prefs::kExtensionInstallAllowList); 681 prefs_->GetList(prefs::kExtensionInstallAllowList);
720 return admin_policy::UserMayLoad(blacklist, whitelist, extension, 682 const base::ListValue* forcelist =
721 error); 683 prefs_->GetList(prefs::kExtensionInstallForceList);
684 return admin_policy::UserMayLoad(is_google_blacklisted, blacklist, whitelist,
685 forcelist, extension, error);
722 } 686 }
723 687
724 bool ExtensionPrefs::UserMayModifySettings(const Extension* extension, 688 bool ExtensionPrefs::UserMayModifySettings(const Extension* extension,
725 string16* error) const { 689 string16* error) const {
726 return admin_policy::UserMayModifySettings(extension, error); 690 return admin_policy::UserMayModifySettings(extension, error);
727 } 691 }
728 692
729 bool ExtensionPrefs::MustRemainEnabled(const Extension* extension, 693 bool ExtensionPrefs::MustRemainEnabled(const Extension* extension,
730 string16* error) const { 694 string16* error) const {
731 return admin_policy::MustRemainEnabled(extension, error); 695 return admin_policy::MustRemainEnabled(extension, error);
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
1608 const DictionaryValue* ExtensionPrefs::GetExtensionPref( 1572 const DictionaryValue* ExtensionPrefs::GetExtensionPref(
1609 const std::string& extension_id) const { 1573 const std::string& extension_id) const {
1610 const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref); 1574 const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref);
1611 if (!dict) 1575 if (!dict)
1612 return NULL; 1576 return NULL;
1613 const DictionaryValue* extension = NULL; 1577 const DictionaryValue* extension = NULL;
1614 dict->GetDictionary(extension_id, &extension); 1578 dict->GetDictionary(extension_id, &extension);
1615 return extension; 1579 return extension;
1616 } 1580 }
1617 1581
1618 // Helper function for GetInstalledExtensionsInfo. 1582 ExtensionInfo* ExtensionPrefs::GetInstalledExtensionInfo(
1619 static ExtensionInfo* GetInstalledExtensionInfoImpl( 1583 const std::string& extension_id) const {
1620 DictionaryValue* extension_data, 1584 const DictionaryValue* ext;
1621 DictionaryValue::key_iterator extension_id) { 1585 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
1622 DictionaryValue* ext; 1586 if (!extensions ||
1623 if (!extension_data->GetDictionaryWithoutPathExpansion(*extension_id, &ext)) { 1587 !extensions->GetDictionaryWithoutPathExpansion(extension_id, &ext))
1624 LOG(WARNING) << "Invalid pref for extension " << *extension_id;
1625 NOTREACHED();
1626 return NULL; 1588 return NULL;
1627 } 1589 if (IsBlacklistBitSet(ext))
1628 if (ext->HasKey(kPrefBlacklist)) {
1629 bool is_blacklisted = false;
1630 if (!ext->GetBoolean(kPrefBlacklist, &is_blacklisted)) {
1631 NOTREACHED() << "Invalid blacklist pref:" << *extension_id;
1632 return NULL; 1590 return NULL;
1633 }
1634 if (is_blacklisted) {
1635 return NULL;
1636 }
1637 }
1638 int state_value; 1591 int state_value;
1639 if (!ext->GetInteger(kPrefState, &state_value)) { 1592 if (!ext->GetInteger(kPrefState, &state_value)) {
1640 // This can legitimately happen if we store preferences for component 1593 // This can legitimately happen if we store preferences for component
1641 // extensions. 1594 // extensions.
1642 return NULL; 1595 return NULL;
1643 } 1596 }
1644 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) { 1597 if (state_value == Extension::EXTERNAL_EXTENSION_UNINSTALLED) {
1645 LOG(WARNING) << "External extension with id " << *extension_id 1598 LOG(WARNING) << "External extension with id " << extension_id
1646 << " has been uninstalled by the user"; 1599 << " has been uninstalled by the user";
1647 return NULL; 1600 return NULL;
1648 } 1601 }
1649 FilePath::StringType path; 1602 FilePath::StringType path;
1650 if (!ext->GetString(kPrefPath, &path)) { 1603 int location_value;
1604 if (!ext->GetInteger(kPrefLocation, &location_value))
1651 return NULL; 1605 return NULL;
1652 } 1606
1653 int location_value; 1607 if (!ext->GetString(kPrefPath, &path))
1654 if (!ext->GetInteger(kPrefLocation, &location_value)) {
1655 return NULL; 1608 return NULL;
1609
1610 // Make path absolute. Unpacked extensions will already have absolute paths,
1611 // otherwise make it so.
1612 if (location_value != Extension::LOAD) {
1613 DCHECK(location_value == Extension::COMPONENT ||
1614 !FilePath(path).IsAbsolute());
1615 path = install_directory_.Append(path).value();
1656 } 1616 }
1657 1617
1658 // Only the following extension types can be installed permanently in the 1618 // Only the following extension types can be installed permanently in the
1659 // preferences. 1619 // preferences.
1660 Extension::Location location = 1620 Extension::Location location =
1661 static_cast<Extension::Location>(location_value); 1621 static_cast<Extension::Location>(location_value);
1662 if (location != Extension::INTERNAL && 1622 if (location != Extension::INTERNAL &&
1663 location != Extension::LOAD && 1623 location != Extension::LOAD &&
1664 !Extension::IsExternalLocation(location)) { 1624 !Extension::IsExternalLocation(location)) {
1665 NOTREACHED(); 1625 NOTREACHED();
1666 return NULL; 1626 return NULL;
1667 } 1627 }
1668 1628
1669 DictionaryValue* manifest = NULL; 1629 const DictionaryValue* manifest = NULL;
1670 if (location != Extension::LOAD && 1630 if (location != Extension::LOAD &&
1671 !ext->GetDictionary(kPrefManifest, &manifest)) { 1631 !ext->GetDictionary(kPrefManifest, &manifest)) {
1672 LOG(WARNING) << "Missing manifest for extension " << *extension_id; 1632 LOG(WARNING) << "Missing manifest for extension " << extension_id;
1673 // Just a warning for now. 1633 // Just a warning for now.
1674 } 1634 }
1675 1635
1676 return new ExtensionInfo(manifest, *extension_id, FilePath(path), location); 1636 return new ExtensionInfo(manifest, extension_id, FilePath(path), location);
1677 } 1637 }
1678 1638
1679 ExtensionPrefs::ExtensionsInfo* ExtensionPrefs::GetInstalledExtensionsInfo() { 1639 ExtensionPrefs::ExtensionsInfo* ExtensionPrefs::GetInstalledExtensionsInfo(
1680 scoped_ptr<DictionaryValue> extension_data(CopyCurrentExtensions()); 1640 ) const {
1681
1682 ExtensionsInfo* extensions_info = new ExtensionsInfo; 1641 ExtensionsInfo* extensions_info = new ExtensionsInfo;
1683 1642
1684 for (DictionaryValue::key_iterator extension_id( 1643 const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref);
1685 extension_data->begin_keys()); 1644 for (DictionaryValue::key_iterator extension_id = extensions->begin_keys();
1686 extension_id != extension_data->end_keys(); ++extension_id) { 1645 extension_id != extensions->end_keys(); ++extension_id) {
1687 if (!Extension::IdIsValid(*extension_id)) 1646 if (!Extension::IdIsValid(*extension_id))
1688 continue; 1647 continue;
1689 1648
1690 ExtensionInfo* info = GetInstalledExtensionInfoImpl(extension_data.get(), 1649 ExtensionInfo* info = GetInstalledExtensionInfo(*extension_id);
1691 extension_id);
1692 if (info) 1650 if (info)
1693 extensions_info->push_back(linked_ptr<ExtensionInfo>(info)); 1651 extensions_info->push_back(linked_ptr<ExtensionInfo>(info));
1694 } 1652 }
1695 1653
1696 return extensions_info; 1654 return extensions_info;
1697 } 1655 }
1698 1656
1699 ExtensionInfo* ExtensionPrefs::GetInstalledExtensionInfo(
1700 const std::string& extension_id) {
1701 scoped_ptr<DictionaryValue> extension_data(CopyCurrentExtensions());
1702
1703 for (DictionaryValue::key_iterator extension_iter(
1704 extension_data->begin_keys());
1705 extension_iter != extension_data->end_keys(); ++extension_iter) {
1706 if (*extension_iter == extension_id) {
1707 return GetInstalledExtensionInfoImpl(extension_data.get(),
1708 extension_iter);
1709 }
1710 }
1711
1712 return NULL;
1713 }
1714
1715 void ExtensionPrefs::SetIdleInstallInfo(const std::string& extension_id, 1657 void ExtensionPrefs::SetIdleInstallInfo(const std::string& extension_id,
1716 const FilePath& crx_path, 1658 const FilePath& crx_path,
1717 const std::string& version, 1659 const std::string& version,
1718 const base::Time& fetch_time) { 1660 const base::Time& fetch_time) {
1719 DictionaryValue* info = new DictionaryValue(); 1661 DictionaryValue* info = new DictionaryValue();
1720 info->SetString(kIdleInstallInfoCrxPath, crx_path.value()); 1662 info->SetString(kIdleInstallInfoCrxPath, crx_path.value());
1721 info->SetString(kIdleInstallInfoVersion, version); 1663 info->SetString(kIdleInstallInfoVersion, version);
1722 info->SetString(kIdleInstallInfoFetchTime, 1664 info->SetString(kIdleInstallInfoFetchTime,
1723 base::Int64ToString(fetch_time.ToInternalValue())); 1665 base::Int64ToString(fetch_time.ToInternalValue()));
1724 UpdateExtensionPref(extension_id, kIdleInstallInfo, info); 1666 UpdateExtensionPref(extension_id, kIdleInstallInfo, info);
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1896 scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo()); 1838 scoped_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
1897 1839
1898 for (size_t i = 0; i < extensions_info->size(); ++i) { 1840 for (size_t i = 0; i < extensions_info->size(); ++i) {
1899 ExtensionInfo* info = extensions_info->at(i).get(); 1841 ExtensionInfo* info = extensions_info->at(i).get();
1900 out->push_back(info->extension_id); 1842 out->push_back(info->extension_id);
1901 } 1843 }
1902 } 1844 }
1903 1845
1904 // static 1846 // static
1905 ExtensionPrefs::ExtensionIds ExtensionPrefs::GetExtensionsFrom( 1847 ExtensionPrefs::ExtensionIds ExtensionPrefs::GetExtensionsFrom(
1906 const base::DictionaryValue* extension_prefs) { 1848 const PrefService* pref_service) {
1907 ExtensionIds result; 1849 ExtensionIds result;
1850
1851 const base::DictionaryValue* extension_prefs;
1852 const base::Value* extension_prefs_value =
1853 pref_service->GetUserPrefValue(kExtensionsPref);
1854 if (!extension_prefs_value ||
1855 !extension_prefs_value->GetAsDictionary(&extension_prefs)) {
1856 return result; // Empty set
1857 }
1858
1908 for (base::DictionaryValue::key_iterator it = extension_prefs->begin_keys(); 1859 for (base::DictionaryValue::key_iterator it = extension_prefs->begin_keys();
1909 it != extension_prefs->end_keys(); ++it) { 1860 it != extension_prefs->end_keys(); ++it) {
1910 const DictionaryValue* ext; 1861 const DictionaryValue* ext;
1911 if (!extension_prefs->GetDictionaryWithoutPathExpansion(*it, &ext)) { 1862 if (!extension_prefs->GetDictionaryWithoutPathExpansion(*it, &ext)) {
1912 NOTREACHED() << "Invalid pref for extension " << *it; 1863 NOTREACHED() << "Invalid pref for extension " << *it;
1913 continue; 1864 continue;
1914 } 1865 }
1915 if (!IsBlacklistBitSet(ext)) 1866 if (!IsBlacklistBitSet(ext))
1916 result.push_back(*it); 1867 result.push_back(*it);
1917 } 1868 }
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
2186 const ExtensionIds& strings) { 2137 const ExtensionIds& strings) {
2187 ListPrefUpdate update(prefs_, pref); 2138 ListPrefUpdate update(prefs_, pref);
2188 ListValue* list_of_values = update.Get(); 2139 ListValue* list_of_values = update.Get();
2189 list_of_values->Clear(); 2140 list_of_values->Clear();
2190 for (ExtensionIds::const_iterator iter = strings.begin(); 2141 for (ExtensionIds::const_iterator iter = strings.begin();
2191 iter != strings.end(); ++iter) 2142 iter != strings.end(); ++iter)
2192 list_of_values->Append(new StringValue(*iter)); 2143 list_of_values->Append(new StringValue(*iter));
2193 } 2144 }
2194 2145
2195 } // namespace extensions 2146 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_prefs.h ('k') | chrome/browser/extensions/extension_prefs_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698