146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file. 446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/manifest_handlers/permissions_parser.h" 646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/command_line.h" 846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/memory/ref_counted.h" 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/values.h" 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "content/public/common/url_constants.h" 1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/error_utils.h" 1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/extension.h" 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/extensions_client.h" 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/features/feature.h" 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/features/feature_provider.h" 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/manifest.h" 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/manifest_handler.h" 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/api_permission_set.h" 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permission_set.h" 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/switches.h" 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/url_pattern_set.h" 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "url/url_constants.h" 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace extensions { 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace { 3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace keys = manifest_keys; 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace errors = manifest_errors; 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)struct ManifestPermissions : public Extension::ManifestData { 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ManifestPermissions(scoped_refptr<const PermissionSet> permissions); 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ~ManifestPermissions(); 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_refptr<const PermissionSet> permissions; 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ManifestPermissions::ManifestPermissions( 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_refptr<const PermissionSet> permissions) 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : permissions(permissions) { 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ManifestPermissions::~ManifestPermissions() { 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Custom checks for the experimental permission that can't be expressed in 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// _permission_features.json. 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool CanSpecifyExperimentalPermission(const Extension* extension) { 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (extension->location() == Manifest::COMPONENT) 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch( 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) switches::kEnableExperimentalExtensionApis)) { 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // We rely on the webstore to check access to experimental. This way we can 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // whitelist extensions to have access to experimental in just the store, and 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // not have to push a new version of the client. 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (extension->from_webstore()) 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Checks whether the host |pattern| is allowed for the given |extension|, 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// given API permissions |permissions|. 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool CanSpecifyHostPermission(const Extension* extension, 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const URLPattern& pattern, 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const APIPermissionSet& permissions) { 7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!pattern.match_all_urls() && 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pattern.MatchesScheme(content::kChromeUIScheme)) { 7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLPatternSet chrome_scheme_hosts = 7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExtensionsClient::Get()->GetPermittedChromeSchemeHosts(extension, 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permissions); 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (chrome_scheme_hosts.ContainsPattern(pattern)) 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Component extensions can have access to all of chrome://*. 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (PermissionsData::CanExecuteScriptEverywhere(extension)) 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (CommandLine::ForCurrentProcess()->HasSwitch( 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) switches::kExtensionsOnChromeURLs)) { 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(aboxhall): return from_webstore() when webstore handles blocking 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // extensions which request chrome:// urls 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Otherwise, the valid schemes were handled by URLPattern. 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Parses the host and api permissions from the specified permission |key| 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// from |extension|'s manifest. 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ParseHelper(Extension* extension, 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const char* key, 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermissionSet* api_permissions, 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLPatternSet* host_permissions, 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::string16* error) { 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension->manifest()->HasKey(key)) 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::ListValue* permissions = NULL; 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!extension->manifest()->GetList(key, &permissions)) { 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermissions, 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string()); 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // NOTE: We need to get the APIPermission before we check if features 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // associated with them are available because the feature system does not 11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // know about aliases. 12046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<std::string> host_data; 12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!APIPermissionSet::ParseFromJSON( 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permissions, 12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermissionSet::kDisallowInternalPermissions, 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) api_permissions, 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error, 12746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &host_data)) { 12846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Verify feature availability of permissions. 13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<APIPermission::ID> to_remove; 13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const FeatureProvider* permission_features = 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FeatureProvider::GetPermissionFeatures(); 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (APIPermissionSet::const_iterator iter = api_permissions->begin(); 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) iter != api_permissions->end(); 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++iter) { 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Feature* feature = permission_features->GetFeature(iter->name()); 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The feature should exist since we just got an APIPermission for it. The 14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // two systems should be updated together whenever a permission is added. 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(feature) << "Could not find feature for " << iter->name(); 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // http://crbug.com/176381 14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!feature) { 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) to_remove.push_back(iter->id()); 14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Feature::Availability availability = 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) feature->IsAvailableToExtension(extension); 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!availability.is_available()) { 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Don't fail, but warn the developer that the manifest contains 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // unrecognized permissions. This may happen legitimately if the 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // extensions requests platform- or channel-specific permissions. 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->AddInstallWarning( 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) InstallWarning(availability.message(), feature->name())); 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) to_remove.push_back(iter->id()); 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (iter->id() == APIPermission::kExperimental) { 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!CanSpecifyExperimentalPermission(extension)) { 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) *error = base::ASCIIToUTF16(errors::kExperimentalFlagRequired); 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) api_permissions->AddImpliedPermissions(); 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Remove permissions that are not available to this extension. 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (std::vector<APIPermission::ID>::const_iterator iter = to_remove.begin(); 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) iter != to_remove.end(); 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++iter) { 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) api_permissions->erase(*iter); 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Parse host pattern permissions. 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const int kAllowedSchemes = 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PermissionsData::CanExecuteScriptEverywhere(extension) 18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ? URLPattern::SCHEME_ALL 18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : Extension::kValidHostPermissionSchemes; 18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (std::vector<std::string>::const_iterator iter = host_data.begin(); 18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) iter != host_data.end(); 18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ++iter) { 18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& permission_str = *iter; 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Check if it's a host pattern permission. 19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLPattern pattern = URLPattern(kAllowedSchemes); 19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLPattern::ParseResult parse_result = pattern.Parse(permission_str); 19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (parse_result == URLPattern::PARSE_SUCCESS) { 19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // The path component is not used for host permissions, so we force it 19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // to match all paths. 19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pattern.SetPath("/*"); 19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int valid_schemes = pattern.valid_schemes(); 19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (pattern.MatchesScheme(url::kFileScheme) && 19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !PermissionsData::CanExecuteScriptEverywhere(extension)) { 19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->set_wants_file_access(true); 20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS)) 20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) valid_schemes &= ~URLPattern::SCHEME_FILE; 20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (pattern.scheme() != content::kChromeUIScheme && 20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !PermissionsData::CanExecuteScriptEverywhere(extension)) { 20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Keep chrome:// in allowed schemes only if it's explicitly requested 20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // or CanExecuteScriptEverywhere is true. If the 20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission 20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // will fail, so don't check the flag here. 21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) valid_schemes &= ~URLPattern::SCHEME_CHROMEUI; 21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pattern.SetValidSchemes(valid_schemes); 21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!CanSpecifyHostPermission(extension, pattern, *api_permissions)) { 21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(aboxhall): make a warning (see pattern.match_all_urls() block 21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // below). 21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->AddInstallWarning(InstallWarning( 21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ErrorUtils::FormatErrorMessage(errors::kInvalidPermissionScheme, 21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permission_str), 22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) key, 22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permission_str)); 22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) host_permissions->AddPattern(pattern); 22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // We need to make sure all_urls matches chrome://favicon and (maybe) 22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // chrome://thumbnail, so add them back in to host_permissions separately. 22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (pattern.match_all_urls()) { 22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) host_permissions->AddPatterns( 23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ExtensionsClient::Get()->GetPermittedChromeSchemeHosts( 23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension, *api_permissions)); 23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // It's probably an unknown API permission. Do not throw an error so 23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // extensions can retain backwards compatability (http://crbug.com/42742). 23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->AddInstallWarning(InstallWarning( 23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ErrorUtils::FormatErrorMessage( 24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) manifest_errors::kPermissionUnknownOrMalformed, permission_str), 24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) key, 24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permission_str)); 24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} // namespace 24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)struct PermissionsParser::InitialPermissions { 25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermissionSet api_permissions; 25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ManifestPermissionSet manifest_permissions; 25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLPatternSet host_permissions; 25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLPatternSet scriptable_hosts; 25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)PermissionsParser::PermissionsParser() { 25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)PermissionsParser::~PermissionsParser() { 26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool PermissionsParser::Parse(Extension* extension, base::string16* error) { 26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_required_permissions_.reset(new InitialPermissions); 26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!ParseHelper(extension, 26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) keys::kPermissions, 26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &initial_required_permissions_->api_permissions, 26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &initial_required_permissions_->host_permissions, 26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error)) { 27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_optional_permissions_.reset(new InitialPermissions); 27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!ParseHelper(extension, 27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) keys::kOptionalPermissions, 27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &initial_optional_permissions_->api_permissions, 27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &initial_optional_permissions_->host_permissions, 27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error)) { 27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PermissionsParser::Finalize(Extension* extension) { 28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ManifestHandler::AddExtensionInitialRequiredPermissions( 28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension, &initial_required_permissions_->manifest_permissions); 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_refptr<const PermissionSet> required_permissions( 29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new PermissionSet(initial_required_permissions_->api_permissions, 29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_required_permissions_->manifest_permissions, 29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_required_permissions_->host_permissions, 29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_required_permissions_->scriptable_hosts)); 29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->SetManifestData(keys::kPermissions, 29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new ManifestPermissions(required_permissions)); 29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 29746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_refptr<const PermissionSet> optional_permissions( 29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new PermissionSet(initial_optional_permissions_->api_permissions, 29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_optional_permissions_->manifest_permissions, 30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) initial_optional_permissions_->host_permissions, 30146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) URLPatternSet())); 30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->SetManifestData(keys::kOptionalPermissions, 30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new ManifestPermissions(optional_permissions)); 30446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 30546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 30646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PermissionsParser::AddAPIPermission(Extension* extension, 30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermission::ID permission) { 30946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(extension->permissions_parser()); 31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->permissions_parser() 31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ->initial_required_permissions_->api_permissions.insert(permission); 31246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 31546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PermissionsParser::AddAPIPermission(Extension* extension, 31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermission* permission) { 31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(extension->permissions_parser()); 31846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->permissions_parser() 31946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ->initial_required_permissions_->api_permissions.insert(permission); 32046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 32146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 32246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool PermissionsParser::HasAPIPermission(const Extension* extension, 32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) APIPermission::ID permission) { 32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(extension->permissions_parser()); 32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return extension->permissions_parser() 32746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ->initial_required_permissions_->api_permissions.count( 32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) permission) > 0; 32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 33146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 33246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PermissionsParser::SetScriptableHosts( 33346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Extension* extension, 33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const URLPatternSet& scriptable_hosts) { 33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(extension->permissions_parser()); 33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->permissions_parser() 33746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ->initial_required_permissions_->scriptable_hosts = scriptable_hosts; 33846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_refptr<const PermissionSet> PermissionsParser::GetRequiredPermissions( 34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Extension* extension) { 34346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(extension->GetManifestData(keys::kPermissions)); 34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return static_cast<const ManifestPermissions*>( 34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->GetManifestData(keys::kPermissions))->permissions; 34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 34846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_refptr<const PermissionSet> PermissionsParser::GetOptionalPermissions( 35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Extension* extension) { 35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(extension->GetManifestData(keys::kOptionalPermissions)); 35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return static_cast<const ManifestPermissions*>( 35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) extension->GetManifestData(keys::kOptionalPermissions)) 35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ->permissions; 35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} // namespace extensions 358