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

Side by Side Diff: chrome/common/extensions/extension.cc

Issue 12316077: Move the parsing of app.launch related keys out of Extension class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase + review comments addressed Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/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
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 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 iter != browser_action->default_icon.map().end(); 743 iter != browser_action->default_icon.map().end();
768 ++iter) { 744 ++iter) {
769 image_paths.insert( 745 image_paths.insert(
770 base::FilePath::FromWStringHack(UTF8ToWide(iter->second))); 746 base::FilePath::FromWStringHack(UTF8ToWide(iter->second)));
771 } 747 }
772 } 748 }
773 749
774 return image_paths; 750 return image_paths;
775 } 751 }
776 752
777 GURL Extension::GetFullLaunchURL() const {
778 return launch_local_path().empty() ? GURL(launch_web_url()) :
779 url().Resolve(launch_local_path());
780 }
781
782 bool Extension::CanExecuteScriptOnPage(const GURL& document_url, 753 bool Extension::CanExecuteScriptOnPage(const GURL& document_url,
783 const GURL& top_frame_url, 754 const GURL& top_frame_url,
784 int tab_id, 755 int tab_id,
785 const UserScript* script, 756 const UserScript* script,
786 std::string* error) const { 757 std::string* error) const {
787 base::AutoLock auto_lock(runtime_data_lock_); 758 base::AutoLock auto_lock(runtime_data_lock_);
788 // The gallery is special-cased as a restricted URL for scripting to prevent 759 // The gallery is special-cased as a restricted URL for scripting to prevent
789 // access to special JS bindings we expose to the gallery (and avoid things 760 // access to special JS bindings we expose to the gallery (and avoid things
790 // like extensions removing the "report abuse" link). 761 // like extensions removing the "report abuse" link).
791 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing 762 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 } 1053 }
1083 1054
1084 bool Extension::can_be_incognito_enabled() const { 1055 bool Extension::can_be_incognito_enabled() const {
1085 return !is_platform_app(); 1056 return !is_platform_app();
1086 } 1057 }
1087 1058
1088 void Extension::AddWebExtentPattern(const URLPattern& pattern) { 1059 void Extension::AddWebExtentPattern(const URLPattern& pattern) {
1089 extent_.AddPattern(pattern); 1060 extent_.AddPattern(pattern);
1090 } 1061 }
1091 1062
1063 void Extension::ClearWebExtentPatterns() {
1064 extent_.ClearPatterns();
1065 }
1066
1092 bool Extension::is_theme() const { 1067 bool Extension::is_theme() const {
1093 return manifest()->is_theme(); 1068 return manifest()->is_theme();
1094 } 1069 }
1095 1070
1096 bool Extension::is_content_pack() const { 1071 bool Extension::is_content_pack() const {
1097 return !content_pack_site_list_.empty(); 1072 return !content_pack_site_list_.empty();
1098 } 1073 }
1099 1074
1100 ExtensionResource Extension::GetContentPackSiteList() const { 1075 ExtensionResource Extension::GetContentPackSiteList() const {
1101 if (!is_content_pack()) 1076 if (!is_content_pack())
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 1227
1253 Extension::Extension(const base::FilePath& path, 1228 Extension::Extension(const base::FilePath& path,
1254 scoped_ptr<extensions::Manifest> manifest) 1229 scoped_ptr<extensions::Manifest> manifest)
1255 : manifest_version_(0), 1230 : manifest_version_(0),
1256 incognito_split_mode_(false), 1231 incognito_split_mode_(false),
1257 offline_enabled_(false), 1232 offline_enabled_(false),
1258 converted_from_user_script_(false), 1233 converted_from_user_script_(false),
1259 manifest_(manifest.release()), 1234 manifest_(manifest.release()),
1260 finished_parsing_manifest_(false), 1235 finished_parsing_manifest_(false),
1261 is_storage_isolated_(false), 1236 is_storage_isolated_(false),
1262 launch_container_(extension_misc::LAUNCH_TAB),
1263 launch_width_(0),
1264 launch_height_(0),
1265 display_in_launcher_(true), 1237 display_in_launcher_(true),
1266 display_in_new_tab_page_(true), 1238 display_in_new_tab_page_(true),
1267 wants_file_access_(false), 1239 wants_file_access_(false),
1268 creation_flags_(0) { 1240 creation_flags_(0) {
1269 DCHECK(path.empty() || path.IsAbsolute()); 1241 DCHECK(path.empty() || path.IsAbsolute());
1270 path_ = MaybeNormalizePath(path); 1242 path_ = MaybeNormalizePath(path);
1271 } 1243 }
1272 1244
1273 Extension::~Extension() { 1245 Extension::~Extension() {
1274 } 1246 }
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1451 version_.reset(new Version(version_str)); 1423 version_.reset(new Version(version_str));
1452 if (!version_->IsValid() || version_->components().size() > 4) { 1424 if (!version_->IsValid() || version_->components().size() > 4) {
1453 *error = ASCIIToUTF16(errors::kInvalidVersion); 1425 *error = ASCIIToUTF16(errors::kInvalidVersion);
1454 return false; 1426 return false;
1455 } 1427 }
1456 return true; 1428 return true;
1457 } 1429 }
1458 1430
1459 bool Extension::LoadAppFeatures(string16* error) { 1431 bool Extension::LoadAppFeatures(string16* error) {
1460 if (!LoadExtent(keys::kWebURLs, &extent_, 1432 if (!LoadExtent(keys::kWebURLs, &extent_,
1461 errors::kInvalidWebURLs, errors::kInvalidWebURL, error) || 1433 errors::kInvalidWebURLs, errors::kInvalidWebURL, error)) {
1462 !LoadLaunchURL(error) ||
1463 !LoadLaunchContainer(error)) {
1464 return false; 1434 return false;
1465 } 1435 }
1466 if (manifest_->HasKey(keys::kDisplayInLauncher) && 1436 if (manifest_->HasKey(keys::kDisplayInLauncher) &&
1467 !manifest_->GetBoolean(keys::kDisplayInLauncher, &display_in_launcher_)) { 1437 !manifest_->GetBoolean(keys::kDisplayInLauncher, &display_in_launcher_)) {
1468 *error = ASCIIToUTF16(errors::kInvalidDisplayInLauncher); 1438 *error = ASCIIToUTF16(errors::kInvalidDisplayInLauncher);
1469 return false; 1439 return false;
1470 } 1440 }
1471 if (manifest_->HasKey(keys::kDisplayInNewTabPage)) { 1441 if (manifest_->HasKey(keys::kDisplayInNewTabPage)) {
1472 if (!manifest_->GetBoolean(keys::kDisplayInNewTabPage, 1442 if (!manifest_->GetBoolean(keys::kDisplayInNewTabPage,
1473 &display_in_new_tab_page_)) { 1443 &display_in_new_tab_page_)) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1548 return false; 1518 return false;
1549 } 1519 }
1550 pattern.SetPath(pattern.path() + '*'); 1520 pattern.SetPath(pattern.path() + '*');
1551 1521
1552 extent->AddPattern(pattern); 1522 extent->AddPattern(pattern);
1553 } 1523 }
1554 1524
1555 return true; 1525 return true;
1556 } 1526 }
1557 1527
1558 bool Extension::LoadLaunchContainer(string16* error) {
1559 const Value* tmp_launcher_container = NULL;
1560 if (!manifest_->Get(keys::kLaunchContainer, &tmp_launcher_container))
1561 return true;
1562
1563 std::string launch_container_string;
1564 if (!tmp_launcher_container->GetAsString(&launch_container_string)) {
1565 *error = ASCIIToUTF16(errors::kInvalidLaunchContainer);
1566 return false;
1567 }
1568
1569 if (launch_container_string == values::kLaunchContainerPanel) {
1570 launch_container_ = extension_misc::LAUNCH_PANEL;
1571 } else if (launch_container_string == values::kLaunchContainerTab) {
1572 launch_container_ = extension_misc::LAUNCH_TAB;
1573 } else {
1574 *error = ASCIIToUTF16(errors::kInvalidLaunchContainer);
1575 return false;
1576 }
1577
1578 bool can_specify_initial_size =
1579 launch_container_ == extension_misc::LAUNCH_PANEL ||
1580 launch_container_ == extension_misc::LAUNCH_WINDOW;
1581
1582 // Validate the container width if present.
1583 if (!ReadLaunchDimension(manifest_.get(),
1584 keys::kLaunchWidth,
1585 &launch_width_,
1586 can_specify_initial_size,
1587 error)) {
1588 return false;
1589 }
1590
1591 // Validate container height if present.
1592 if (!ReadLaunchDimension(manifest_.get(),
1593 keys::kLaunchHeight,
1594 &launch_height_,
1595 can_specify_initial_size,
1596 error)) {
1597 return false;
1598 }
1599
1600 return true;
1601 }
1602
1603 bool Extension::LoadLaunchURL(string16* error) {
1604 const Value* temp = NULL;
1605
1606 // launch URL can be either local (to chrome-extension:// root) or an absolute
1607 // web URL.
1608 if (manifest_->Get(keys::kLaunchLocalPath, &temp)) {
1609 if (manifest_->Get(keys::kLaunchWebURL, NULL)) {
1610 *error = ASCIIToUTF16(errors::kLaunchPathAndURLAreExclusive);
1611 return false;
1612 }
1613
1614 if (manifest_->Get(keys::kWebURLs, NULL)) {
1615 *error = ASCIIToUTF16(errors::kLaunchPathAndExtentAreExclusive);
1616 return false;
1617 }
1618
1619 std::string launch_path;
1620 if (!temp->GetAsString(&launch_path)) {
1621 *error = ErrorUtils::FormatErrorMessageUTF16(
1622 errors::kInvalidLaunchValue,
1623 keys::kLaunchLocalPath);
1624 return false;
1625 }
1626
1627 // Ensure the launch path is a valid relative URL.
1628 GURL resolved = url().Resolve(launch_path);
1629 if (!resolved.is_valid() || resolved.GetOrigin() != url()) {
1630 *error = ErrorUtils::FormatErrorMessageUTF16(
1631 errors::kInvalidLaunchValue,
1632 keys::kLaunchLocalPath);
1633 return false;
1634 }
1635
1636 launch_local_path_ = launch_path;
1637 } else if (manifest_->Get(keys::kLaunchWebURL, &temp)) {
1638 std::string launch_url;
1639 if (!temp->GetAsString(&launch_url)) {
1640 *error = ErrorUtils::FormatErrorMessageUTF16(
1641 errors::kInvalidLaunchValue,
1642 keys::kLaunchWebURL);
1643 return false;
1644 }
1645
1646 // Ensure the launch URL is a valid absolute URL and web extent scheme.
1647 GURL url(launch_url);
1648 URLPattern pattern(kValidWebExtentSchemes);
1649 if (!url.is_valid() || !pattern.SetScheme(url.scheme())) {
1650 *error = ErrorUtils::FormatErrorMessageUTF16(
1651 errors::kInvalidLaunchValue,
1652 keys::kLaunchWebURL);
1653 return false;
1654 }
1655
1656 launch_web_url_ = launch_url;
1657 } else if (is_legacy_packaged_app() || is_hosted_app()) {
1658 *error = ASCIIToUTF16(errors::kLaunchURLRequired);
1659 return false;
1660 }
1661
1662 // If there is no extent, we default the extent based on the launch URL.
1663 if (web_extent().is_empty() && !launch_web_url().empty()) {
1664 GURL launch_url(launch_web_url());
1665 URLPattern pattern(kValidWebExtentSchemes);
1666 if (!pattern.SetScheme("*")) {
1667 *error = ErrorUtils::FormatErrorMessageUTF16(
1668 errors::kInvalidLaunchValue,
1669 keys::kLaunchWebURL);
1670 return false;
1671 }
1672 pattern.SetHost(launch_url.host());
1673 pattern.SetPath("/*");
1674 extent_.AddPattern(pattern);
1675 }
1676
1677 // In order for the --apps-gallery-url switch to work with the gallery
1678 // process isolation, we must insert any provided value into the component
1679 // app's launch url and web extent.
1680 if (id() == extension_misc::kWebStoreAppId) {
1681 std::string gallery_url_str = CommandLine::ForCurrentProcess()->
1682 GetSwitchValueASCII(switches::kAppsGalleryURL);
1683
1684 // Empty string means option was not used.
1685 if (!gallery_url_str.empty()) {
1686 GURL gallery_url(gallery_url_str);
1687 OverrideLaunchUrl(gallery_url);
1688 }
1689 } else if (id() == extension_misc::kCloudPrintAppId) {
1690 // In order for the --cloud-print-service switch to work, we must update
1691 // the launch URL and web extent.
1692 // TODO(sanjeevr): Ideally we want to use CloudPrintURL here but that is
1693 // currently under chrome/browser.
1694 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1695 GURL cloud_print_service_url = GURL(command_line.GetSwitchValueASCII(
1696 switches::kCloudPrintServiceURL));
1697 if (!cloud_print_service_url.is_empty()) {
1698 std::string path(
1699 cloud_print_service_url.path() + "/enable_chrome_connector");
1700 GURL::Replacements replacements;
1701 replacements.SetPathStr(path);
1702 GURL cloud_print_enable_connector_url =
1703 cloud_print_service_url.ReplaceComponents(replacements);
1704 OverrideLaunchUrl(cloud_print_enable_connector_url);
1705 }
1706 } else if (id() == extension_misc::kChromeAppId) {
1707 // Override launch url to new tab.
1708 launch_web_url_ = chrome::kChromeUINewTabURL;
1709 extent_.ClearPatterns();
1710 }
1711
1712 return true;
1713 }
1714
1715 bool Extension::LoadSharedFeatures(string16* error) { 1528 bool Extension::LoadSharedFeatures(string16* error) {
1716 if (!LoadDescription(error) || 1529 if (!LoadDescription(error) ||
1717 !ManifestHandler::ParseExtension(this, error) || 1530 !ManifestHandler::ParseExtension(this, error) ||
1718 !LoadPlugins(error) || 1531 !LoadPlugins(error) ||
1719 !LoadNaClModules(error) || 1532 !LoadNaClModules(error) ||
1720 !LoadSandboxedPages(error) || 1533 !LoadSandboxedPages(error) ||
1721 !LoadRequirements(error) || 1534 !LoadRequirements(error) ||
1722 !LoadOfflineEnabled(error)) 1535 !LoadOfflineEnabled(error))
1723 return false; 1536 return false;
1724 1537
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after
2338 2151
2339 if (ActionInfo::GetBrowserActionInfo(this)) 2152 if (ActionInfo::GetBrowserActionInfo(this))
2340 ++num_surfaces; 2153 ++num_surfaces;
2341 2154
2342 if (is_app()) 2155 if (is_app())
2343 ++num_surfaces; 2156 ++num_surfaces;
2344 2157
2345 return num_surfaces > 1; 2158 return num_surfaces > 1;
2346 } 2159 }
2347 2160
2348 void Extension::OverrideLaunchUrl(const GURL& override_url) {
2349 GURL new_url(override_url);
2350 if (!new_url.is_valid()) {
2351 DLOG(WARNING) << "Invalid override url given for " << name();
2352 } else {
2353 if (new_url.has_port()) {
2354 DLOG(WARNING) << "Override URL passed for " << name()
2355 << " should not contain a port. Removing it.";
2356
2357 GURL::Replacements remove_port;
2358 remove_port.ClearPort();
2359 new_url = new_url.ReplaceComponents(remove_port);
2360 }
2361
2362 launch_web_url_ = new_url.spec();
2363
2364 URLPattern pattern(kValidWebExtentSchemes);
2365 URLPattern::ParseResult result = pattern.Parse(new_url.spec());
2366 DCHECK_EQ(result, URLPattern::PARSE_SUCCESS);
2367 pattern.SetPath(pattern.path() + '*');
2368 extent_.AddPattern(pattern);
2369 }
2370 }
2371
2372 bool Extension::CanSpecifyExperimentalPermission() const { 2161 bool Extension::CanSpecifyExperimentalPermission() const {
2373 if (location() == Manifest::COMPONENT) 2162 if (location() == Manifest::COMPONENT)
2374 return true; 2163 return true;
2375 2164
2376 if (CommandLine::ForCurrentProcess()->HasSwitch( 2165 if (CommandLine::ForCurrentProcess()->HasSwitch(
2377 switches::kEnableExperimentalExtensionApis)) { 2166 switches::kEnableExperimentalExtensionApis)) {
2378 return true; 2167 return true;
2379 } 2168 }
2380 2169
2381 // We rely on the webstore to check access to experimental. This way we can 2170 // We rely on the webstore to check access to experimental. This way we can
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2499 2288
2500 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( 2289 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo(
2501 const Extension* extension, 2290 const Extension* extension,
2502 const PermissionSet* permissions, 2291 const PermissionSet* permissions,
2503 Reason reason) 2292 Reason reason)
2504 : reason(reason), 2293 : reason(reason),
2505 extension(extension), 2294 extension(extension),
2506 permissions(permissions) {} 2295 permissions(permissions) {}
2507 2296
2508 } // namespace extensions 2297 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698