| 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/common/extensions/extension.h" | 5 #include "chrome/common/extensions/extension.h" | 
| 6 | 6 | 
| 7 #include "base/base64.h" | 7 #include "base/base64.h" | 
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" | 
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" | 
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" | 
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 137   } | 137   } | 
| 138   ~ExtensionConfig() { } | 138   ~ExtensionConfig() { } | 
| 139 | 139 | 
| 140   // A whitelist of extensions that can script anywhere. Do not add to this | 140   // A whitelist of extensions that can script anywhere. Do not add to this | 
| 141   // list (except in tests) without consulting the Extensions team first. | 141   // list (except in tests) without consulting the Extensions team first. | 
| 142   // Note: Component extensions have this right implicitly and do not need to be | 142   // Note: Component extensions have this right implicitly and do not need to be | 
| 143   // added to this list. | 143   // added to this list. | 
| 144   Extension::ScriptingWhitelist scripting_whitelist_; | 144   Extension::ScriptingWhitelist scripting_whitelist_; | 
| 145 }; | 145 }; | 
| 146 | 146 | 
| 147 bool ReadLaunchDimension(const extensions::Manifest* manifest, |  | 
| 148                          const char* key, |  | 
| 149                          int* target, |  | 
| 150                          bool is_valid_container, |  | 
| 151                          string16* error) { |  | 
| 152   const Value* temp = NULL; |  | 
| 153   if (manifest->Get(key, &temp)) { |  | 
| 154     if (!is_valid_container) { |  | 
| 155       *error = ErrorUtils::FormatErrorMessageUTF16( |  | 
| 156           errors::kInvalidLaunchValueContainer, |  | 
| 157           key); |  | 
| 158       return false; |  | 
| 159     } |  | 
| 160     if (!temp->GetAsInteger(target) || *target < 0) { |  | 
| 161       *target = 0; |  | 
| 162       *error = ErrorUtils::FormatErrorMessageUTF16( |  | 
| 163           errors::kInvalidLaunchValue, |  | 
| 164           key); |  | 
| 165       return false; |  | 
| 166     } |  | 
| 167   } |  | 
| 168   return true; |  | 
| 169 } |  | 
| 170 |  | 
| 171 bool ContainsManifestForbiddenPermission(const APIPermissionSet& apis, | 147 bool ContainsManifestForbiddenPermission(const APIPermissionSet& apis, | 
| 172                                          string16* error) { | 148                                          string16* error) { | 
| 173   CHECK(error); | 149   CHECK(error); | 
| 174   for (APIPermissionSet::const_iterator i = apis.begin(); | 150   for (APIPermissionSet::const_iterator i = apis.begin(); | 
| 175       i != apis.end(); ++i) { | 151       i != apis.end(); ++i) { | 
| 176     if ((*i)->ManifestEntryForbidden()) { | 152     if ((*i)->ManifestEntryForbidden()) { | 
| 177       *error = ErrorUtils::FormatErrorMessageUTF16( | 153       *error = ErrorUtils::FormatErrorMessageUTF16( | 
| 178           errors::kPermissionNotAllowedInManifest, | 154           errors::kPermissionNotAllowedInManifest, | 
| 179           (*i)->info()->name()); | 155           (*i)->info()->name()); | 
| 180       return true; | 156       return true; | 
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 793          iter != browser_action->default_icon.map().end(); | 769          iter != browser_action->default_icon.map().end(); | 
| 794          ++iter) { | 770          ++iter) { | 
| 795       image_paths.insert( | 771       image_paths.insert( | 
| 796           base::FilePath::FromWStringHack(UTF8ToWide(iter->second))); | 772           base::FilePath::FromWStringHack(UTF8ToWide(iter->second))); | 
| 797     } | 773     } | 
| 798   } | 774   } | 
| 799 | 775 | 
| 800   return image_paths; | 776   return image_paths; | 
| 801 } | 777 } | 
| 802 | 778 | 
| 803 GURL Extension::GetFullLaunchURL() const { |  | 
| 804   return launch_local_path().empty() ? GURL(launch_web_url()) : |  | 
| 805                                        url().Resolve(launch_local_path()); |  | 
| 806 } |  | 
| 807 |  | 
| 808 bool Extension::CanExecuteScriptOnPage(const GURL& document_url, | 779 bool Extension::CanExecuteScriptOnPage(const GURL& document_url, | 
| 809                                        const GURL& top_frame_url, | 780                                        const GURL& top_frame_url, | 
| 810                                        int tab_id, | 781                                        int tab_id, | 
| 811                                        const UserScript* script, | 782                                        const UserScript* script, | 
| 812                                        std::string* error) const { | 783                                        std::string* error) const { | 
| 813   base::AutoLock auto_lock(runtime_data_lock_); | 784   base::AutoLock auto_lock(runtime_data_lock_); | 
| 814   // The gallery is special-cased as a restricted URL for scripting to prevent | 785   // The gallery is special-cased as a restricted URL for scripting to prevent | 
| 815   // access to special JS bindings we expose to the gallery (and avoid things | 786   // access to special JS bindings we expose to the gallery (and avoid things | 
| 816   // like extensions removing the "report abuse" link). | 787   // like extensions removing the "report abuse" link). | 
| 817   // TODO(erikkay): This seems like the wrong test.  Shouldn't we we testing | 788   // TODO(erikkay): This seems like the wrong test.  Shouldn't we we testing | 
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1114 } | 1085 } | 
| 1115 | 1086 | 
| 1116 bool Extension::can_be_incognito_enabled() const { | 1087 bool Extension::can_be_incognito_enabled() const { | 
| 1117   return !is_platform_app(); | 1088   return !is_platform_app(); | 
| 1118 } | 1089 } | 
| 1119 | 1090 | 
| 1120 void Extension::AddWebExtentPattern(const URLPattern& pattern) { | 1091 void Extension::AddWebExtentPattern(const URLPattern& pattern) { | 
| 1121   extent_.AddPattern(pattern); | 1092   extent_.AddPattern(pattern); | 
| 1122 } | 1093 } | 
| 1123 | 1094 | 
|  | 1095 void Extension::ClearWebExtentPatterns() { | 
|  | 1096   extent_.ClearPatterns(); | 
|  | 1097 } | 
|  | 1098 | 
| 1124 bool Extension::is_theme() const { | 1099 bool Extension::is_theme() const { | 
| 1125   return manifest()->is_theme(); | 1100   return manifest()->is_theme(); | 
| 1126 } | 1101 } | 
| 1127 | 1102 | 
| 1128 bool Extension::is_content_pack() const { | 1103 bool Extension::is_content_pack() const { | 
| 1129   return !content_pack_site_list_.empty(); | 1104   return !content_pack_site_list_.empty(); | 
| 1130 } | 1105 } | 
| 1131 | 1106 | 
| 1132 ExtensionResource Extension::GetContentPackSiteList() const { | 1107 ExtensionResource Extension::GetContentPackSiteList() const { | 
| 1133   if (!is_content_pack()) | 1108   if (!is_content_pack()) | 
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1285 Extension::Extension(const base::FilePath& path, | 1260 Extension::Extension(const base::FilePath& path, | 
| 1286                      scoped_ptr<extensions::Manifest> manifest) | 1261                      scoped_ptr<extensions::Manifest> manifest) | 
| 1287     : manifest_version_(0), | 1262     : manifest_version_(0), | 
| 1288       incognito_split_mode_(false), | 1263       incognito_split_mode_(false), | 
| 1289       kiosk_enabled_(false), | 1264       kiosk_enabled_(false), | 
| 1290       offline_enabled_(false), | 1265       offline_enabled_(false), | 
| 1291       converted_from_user_script_(false), | 1266       converted_from_user_script_(false), | 
| 1292       manifest_(manifest.release()), | 1267       manifest_(manifest.release()), | 
| 1293       finished_parsing_manifest_(false), | 1268       finished_parsing_manifest_(false), | 
| 1294       is_storage_isolated_(false), | 1269       is_storage_isolated_(false), | 
| 1295       launch_container_(extension_misc::LAUNCH_TAB), |  | 
| 1296       launch_width_(0), |  | 
| 1297       launch_height_(0), |  | 
| 1298       display_in_launcher_(true), | 1270       display_in_launcher_(true), | 
| 1299       display_in_new_tab_page_(true), | 1271       display_in_new_tab_page_(true), | 
| 1300       wants_file_access_(false), | 1272       wants_file_access_(false), | 
| 1301       creation_flags_(0) { | 1273       creation_flags_(0) { | 
| 1302   DCHECK(path.empty() || path.IsAbsolute()); | 1274   DCHECK(path.empty() || path.IsAbsolute()); | 
| 1303   path_ = MaybeNormalizePath(path); | 1275   path_ = MaybeNormalizePath(path); | 
| 1304 } | 1276 } | 
| 1305 | 1277 | 
| 1306 Extension::~Extension() { | 1278 Extension::~Extension() { | 
| 1307 } | 1279 } | 
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1484   version_.reset(new Version(version_str)); | 1456   version_.reset(new Version(version_str)); | 
| 1485   if (!version_->IsValid() || version_->components().size() > 4) { | 1457   if (!version_->IsValid() || version_->components().size() > 4) { | 
| 1486     *error = ASCIIToUTF16(errors::kInvalidVersion); | 1458     *error = ASCIIToUTF16(errors::kInvalidVersion); | 
| 1487     return false; | 1459     return false; | 
| 1488   } | 1460   } | 
| 1489   return true; | 1461   return true; | 
| 1490 } | 1462 } | 
| 1491 | 1463 | 
| 1492 bool Extension::LoadAppFeatures(string16* error) { | 1464 bool Extension::LoadAppFeatures(string16* error) { | 
| 1493   if (!LoadExtent(keys::kWebURLs, &extent_, | 1465   if (!LoadExtent(keys::kWebURLs, &extent_, | 
| 1494                   errors::kInvalidWebURLs, errors::kInvalidWebURL, error) || | 1466                   errors::kInvalidWebURLs, errors::kInvalidWebURL, error)) { | 
| 1495       !LoadLaunchURL(error) || |  | 
| 1496       !LoadLaunchContainer(error)) { |  | 
| 1497     return false; | 1467     return false; | 
| 1498   } | 1468   } | 
| 1499   if (manifest_->HasKey(keys::kDisplayInLauncher) && | 1469   if (manifest_->HasKey(keys::kDisplayInLauncher) && | 
| 1500       !manifest_->GetBoolean(keys::kDisplayInLauncher, &display_in_launcher_)) { | 1470       !manifest_->GetBoolean(keys::kDisplayInLauncher, &display_in_launcher_)) { | 
| 1501     *error = ASCIIToUTF16(errors::kInvalidDisplayInLauncher); | 1471     *error = ASCIIToUTF16(errors::kInvalidDisplayInLauncher); | 
| 1502     return false; | 1472     return false; | 
| 1503   } | 1473   } | 
| 1504   if (manifest_->HasKey(keys::kDisplayInNewTabPage)) { | 1474   if (manifest_->HasKey(keys::kDisplayInNewTabPage)) { | 
| 1505     if (!manifest_->GetBoolean(keys::kDisplayInNewTabPage, | 1475     if (!manifest_->GetBoolean(keys::kDisplayInNewTabPage, | 
| 1506                                &display_in_new_tab_page_)) { | 1476                                &display_in_new_tab_page_)) { | 
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1581       return false; | 1551       return false; | 
| 1582     } | 1552     } | 
| 1583     pattern.SetPath(pattern.path() + '*'); | 1553     pattern.SetPath(pattern.path() + '*'); | 
| 1584 | 1554 | 
| 1585     extent->AddPattern(pattern); | 1555     extent->AddPattern(pattern); | 
| 1586   } | 1556   } | 
| 1587 | 1557 | 
| 1588   return true; | 1558   return true; | 
| 1589 } | 1559 } | 
| 1590 | 1560 | 
| 1591 bool Extension::LoadLaunchContainer(string16* error) { |  | 
| 1592   const Value* tmp_launcher_container = NULL; |  | 
| 1593   if (!manifest_->Get(keys::kLaunchContainer, &tmp_launcher_container)) |  | 
| 1594     return true; |  | 
| 1595 |  | 
| 1596   std::string launch_container_string; |  | 
| 1597   if (!tmp_launcher_container->GetAsString(&launch_container_string)) { |  | 
| 1598     *error = ASCIIToUTF16(errors::kInvalidLaunchContainer); |  | 
| 1599     return false; |  | 
| 1600   } |  | 
| 1601 |  | 
| 1602   if (launch_container_string == values::kLaunchContainerPanel) { |  | 
| 1603     launch_container_ = extension_misc::LAUNCH_PANEL; |  | 
| 1604   } else if (launch_container_string == values::kLaunchContainerTab) { |  | 
| 1605     launch_container_ = extension_misc::LAUNCH_TAB; |  | 
| 1606   } else { |  | 
| 1607     *error = ASCIIToUTF16(errors::kInvalidLaunchContainer); |  | 
| 1608     return false; |  | 
| 1609   } |  | 
| 1610 |  | 
| 1611   bool can_specify_initial_size = |  | 
| 1612       launch_container_ == extension_misc::LAUNCH_PANEL || |  | 
| 1613       launch_container_ == extension_misc::LAUNCH_WINDOW; |  | 
| 1614 |  | 
| 1615   // Validate the container width if present. |  | 
| 1616   if (!ReadLaunchDimension(manifest_.get(), |  | 
| 1617                            keys::kLaunchWidth, |  | 
| 1618                            &launch_width_, |  | 
| 1619                            can_specify_initial_size, |  | 
| 1620                            error)) { |  | 
| 1621       return false; |  | 
| 1622   } |  | 
| 1623 |  | 
| 1624   // Validate container height if present. |  | 
| 1625   if (!ReadLaunchDimension(manifest_.get(), |  | 
| 1626                            keys::kLaunchHeight, |  | 
| 1627                            &launch_height_, |  | 
| 1628                            can_specify_initial_size, |  | 
| 1629                            error)) { |  | 
| 1630       return false; |  | 
| 1631   } |  | 
| 1632 |  | 
| 1633   return true; |  | 
| 1634 } |  | 
| 1635 |  | 
| 1636 bool Extension::LoadLaunchURL(string16* error) { |  | 
| 1637   const Value* temp = NULL; |  | 
| 1638 |  | 
| 1639   // launch URL can be either local (to chrome-extension:// root) or an absolute |  | 
| 1640   // web URL. |  | 
| 1641   if (manifest_->Get(keys::kLaunchLocalPath, &temp)) { |  | 
| 1642     if (manifest_->Get(keys::kLaunchWebURL, NULL)) { |  | 
| 1643       *error = ASCIIToUTF16(errors::kLaunchPathAndURLAreExclusive); |  | 
| 1644       return false; |  | 
| 1645     } |  | 
| 1646 |  | 
| 1647     if (manifest_->Get(keys::kWebURLs, NULL)) { |  | 
| 1648       *error = ASCIIToUTF16(errors::kLaunchPathAndExtentAreExclusive); |  | 
| 1649       return false; |  | 
| 1650     } |  | 
| 1651 |  | 
| 1652     std::string launch_path; |  | 
| 1653     if (!temp->GetAsString(&launch_path)) { |  | 
| 1654       *error = ErrorUtils::FormatErrorMessageUTF16( |  | 
| 1655           errors::kInvalidLaunchValue, |  | 
| 1656           keys::kLaunchLocalPath); |  | 
| 1657       return false; |  | 
| 1658     } |  | 
| 1659 |  | 
| 1660     // Ensure the launch path is a valid relative URL. |  | 
| 1661     GURL resolved = url().Resolve(launch_path); |  | 
| 1662     if (!resolved.is_valid() || resolved.GetOrigin() != url()) { |  | 
| 1663       *error = ErrorUtils::FormatErrorMessageUTF16( |  | 
| 1664           errors::kInvalidLaunchValue, |  | 
| 1665           keys::kLaunchLocalPath); |  | 
| 1666       return false; |  | 
| 1667     } |  | 
| 1668 |  | 
| 1669     launch_local_path_ = launch_path; |  | 
| 1670   } else if (manifest_->Get(keys::kLaunchWebURL, &temp)) { |  | 
| 1671     std::string launch_url; |  | 
| 1672     if (!temp->GetAsString(&launch_url)) { |  | 
| 1673       *error = ErrorUtils::FormatErrorMessageUTF16( |  | 
| 1674           errors::kInvalidLaunchValue, |  | 
| 1675           keys::kLaunchWebURL); |  | 
| 1676       return false; |  | 
| 1677     } |  | 
| 1678 |  | 
| 1679     // Ensure the launch URL is a valid absolute URL and web extent scheme. |  | 
| 1680     GURL url(launch_url); |  | 
| 1681     URLPattern pattern(kValidWebExtentSchemes); |  | 
| 1682     if (!url.is_valid() || !pattern.SetScheme(url.scheme())) { |  | 
| 1683       *error = ErrorUtils::FormatErrorMessageUTF16( |  | 
| 1684           errors::kInvalidLaunchValue, |  | 
| 1685           keys::kLaunchWebURL); |  | 
| 1686       return false; |  | 
| 1687     } |  | 
| 1688 |  | 
| 1689     launch_web_url_ = launch_url; |  | 
| 1690   } else if (is_legacy_packaged_app() || is_hosted_app()) { |  | 
| 1691     *error = ASCIIToUTF16(errors::kLaunchURLRequired); |  | 
| 1692     return false; |  | 
| 1693   } |  | 
| 1694 |  | 
| 1695   // If there is no extent, we default the extent based on the launch URL. |  | 
| 1696   if (web_extent().is_empty() && !launch_web_url().empty()) { |  | 
| 1697     GURL launch_url(launch_web_url()); |  | 
| 1698     URLPattern pattern(kValidWebExtentSchemes); |  | 
| 1699     if (!pattern.SetScheme("*")) { |  | 
| 1700       *error = ErrorUtils::FormatErrorMessageUTF16( |  | 
| 1701           errors::kInvalidLaunchValue, |  | 
| 1702           keys::kLaunchWebURL); |  | 
| 1703       return false; |  | 
| 1704     } |  | 
| 1705     pattern.SetHost(launch_url.host()); |  | 
| 1706     pattern.SetPath("/*"); |  | 
| 1707     extent_.AddPattern(pattern); |  | 
| 1708   } |  | 
| 1709 |  | 
| 1710   // In order for the --apps-gallery-url switch to work with the gallery |  | 
| 1711   // process isolation, we must insert any provided value into the component |  | 
| 1712   // app's launch url and web extent. |  | 
| 1713   if (id() == extension_misc::kWebStoreAppId) { |  | 
| 1714     std::string gallery_url_str = CommandLine::ForCurrentProcess()-> |  | 
| 1715         GetSwitchValueASCII(switches::kAppsGalleryURL); |  | 
| 1716 |  | 
| 1717     // Empty string means option was not used. |  | 
| 1718     if (!gallery_url_str.empty()) { |  | 
| 1719       GURL gallery_url(gallery_url_str); |  | 
| 1720       OverrideLaunchUrl(gallery_url); |  | 
| 1721     } |  | 
| 1722   } else if (id() == extension_misc::kCloudPrintAppId) { |  | 
| 1723     // In order for the --cloud-print-service switch to work, we must update |  | 
| 1724     // the launch URL and web extent. |  | 
| 1725     // TODO(sanjeevr): Ideally we want to use CloudPrintURL here but that is |  | 
| 1726     // currently under chrome/browser. |  | 
| 1727     const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |  | 
| 1728     GURL cloud_print_service_url = GURL(command_line.GetSwitchValueASCII( |  | 
| 1729         switches::kCloudPrintServiceURL)); |  | 
| 1730     if (!cloud_print_service_url.is_empty()) { |  | 
| 1731       std::string path( |  | 
| 1732           cloud_print_service_url.path() + "/enable_chrome_connector"); |  | 
| 1733       GURL::Replacements replacements; |  | 
| 1734       replacements.SetPathStr(path); |  | 
| 1735       GURL cloud_print_enable_connector_url = |  | 
| 1736           cloud_print_service_url.ReplaceComponents(replacements); |  | 
| 1737       OverrideLaunchUrl(cloud_print_enable_connector_url); |  | 
| 1738     } |  | 
| 1739   } else if (id() == extension_misc::kChromeAppId) { |  | 
| 1740     // Override launch url to new tab. |  | 
| 1741     launch_web_url_ = chrome::kChromeUINewTabURL; |  | 
| 1742     extent_.ClearPatterns(); |  | 
| 1743   } |  | 
| 1744 |  | 
| 1745   return true; |  | 
| 1746 } |  | 
| 1747 |  | 
| 1748 bool Extension::LoadSharedFeatures(string16* error) { | 1561 bool Extension::LoadSharedFeatures(string16* error) { | 
| 1749   if (!LoadDescription(error) || | 1562   if (!LoadDescription(error) || | 
| 1750       !ManifestHandler::ParseExtension(this, error) || | 1563       !ManifestHandler::ParseExtension(this, error) || | 
| 1751       !LoadNaClModules(error) || | 1564       !LoadNaClModules(error) || | 
| 1752       !LoadSandboxedPages(error) || | 1565       !LoadSandboxedPages(error) || | 
| 1753       !LoadRequirements(error) || | 1566       !LoadRequirements(error) || | 
| 1754       !LoadKioskEnabled(error) || | 1567       !LoadKioskEnabled(error) || | 
| 1755       !LoadOfflineEnabled(error)) | 1568       !LoadOfflineEnabled(error)) | 
| 1756     return false; | 1569     return false; | 
| 1757 | 1570 | 
| (...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2346 | 2159 | 
| 2347   if (ActionInfo::GetBrowserActionInfo(this)) | 2160   if (ActionInfo::GetBrowserActionInfo(this)) | 
| 2348     ++num_surfaces; | 2161     ++num_surfaces; | 
| 2349 | 2162 | 
| 2350   if (is_app()) | 2163   if (is_app()) | 
| 2351     ++num_surfaces; | 2164     ++num_surfaces; | 
| 2352 | 2165 | 
| 2353   return num_surfaces > 1; | 2166   return num_surfaces > 1; | 
| 2354 } | 2167 } | 
| 2355 | 2168 | 
| 2356 void Extension::OverrideLaunchUrl(const GURL& override_url) { |  | 
| 2357   GURL new_url(override_url); |  | 
| 2358   if (!new_url.is_valid()) { |  | 
| 2359     DLOG(WARNING) << "Invalid override url given for " << name(); |  | 
| 2360   } else { |  | 
| 2361     if (new_url.has_port()) { |  | 
| 2362       DLOG(WARNING) << "Override URL passed for " << name() |  | 
| 2363                     << " should not contain a port.  Removing it."; |  | 
| 2364 |  | 
| 2365       GURL::Replacements remove_port; |  | 
| 2366       remove_port.ClearPort(); |  | 
| 2367       new_url = new_url.ReplaceComponents(remove_port); |  | 
| 2368     } |  | 
| 2369 |  | 
| 2370     launch_web_url_ = new_url.spec(); |  | 
| 2371 |  | 
| 2372     URLPattern pattern(kValidWebExtentSchemes); |  | 
| 2373     URLPattern::ParseResult result = pattern.Parse(new_url.spec()); |  | 
| 2374     DCHECK_EQ(result, URLPattern::PARSE_SUCCESS); |  | 
| 2375     pattern.SetPath(pattern.path() + '*'); |  | 
| 2376     extent_.AddPattern(pattern); |  | 
| 2377   } |  | 
| 2378 } |  | 
| 2379 |  | 
| 2380 bool Extension::CanSpecifyExperimentalPermission() const { | 2169 bool Extension::CanSpecifyExperimentalPermission() const { | 
| 2381   if (location() == Manifest::COMPONENT) | 2170   if (location() == Manifest::COMPONENT) | 
| 2382     return true; | 2171     return true; | 
| 2383 | 2172 | 
| 2384   if (CommandLine::ForCurrentProcess()->HasSwitch( | 2173   if (CommandLine::ForCurrentProcess()->HasSwitch( | 
| 2385           switches::kEnableExperimentalExtensionApis)) { | 2174           switches::kEnableExperimentalExtensionApis)) { | 
| 2386     return true; | 2175     return true; | 
| 2387   } | 2176   } | 
| 2388 | 2177 | 
| 2389   // We rely on the webstore to check access to experimental. This way we can | 2178   // We rely on the webstore to check access to experimental. This way we can | 
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2513 | 2302 | 
| 2514 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 2303 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 
| 2515     const Extension* extension, | 2304     const Extension* extension, | 
| 2516     const PermissionSet* permissions, | 2305     const PermissionSet* permissions, | 
| 2517     Reason reason) | 2306     Reason reason) | 
| 2518     : reason(reason), | 2307     : reason(reason), | 
| 2519       extension(extension), | 2308       extension(extension), | 
| 2520       permissions(permissions) {} | 2309       permissions(permissions) {} | 
| 2521 | 2310 | 
| 2522 }   // namespace extensions | 2311 }   // namespace extensions | 
| OLD | NEW | 
|---|