1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// found in the LICENSE file.
4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h"
6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/command_line.h"
8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/values.h"
14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/extension.h"
15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h"
16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/features/base_feature_provider.h"
17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/features/feature.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/extensions/manifest.h"
19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/permissions/api_permission_set.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/extensions/permissions/chrome_scheme_hosts.h"
21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permission_set.h"
22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_info.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/common/url_constants.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "extensions/common/constants.h"
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "extensions/common/error_utils.h"
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "extensions/common/switches.h"
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "extensions/common/url_pattern_set.h"
28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "extensions/common/user_script.h"
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace keys = extension_manifest_keys;
32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace errors = extension_manifest_errors;
33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace extensions {
35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace {
37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PermissionsData::PolicyDelegate* g_policy_delegate = NULL;
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ContainsManifestForbiddenPermission(const APIPermissionSet& apis,
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                         string16* error) {
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  CHECK(error);
43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (APIPermissionSet::const_iterator iter = apis.begin();
44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       iter != apis.end(); ++iter) {
45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if ((*iter)->ManifestEntryForbidden()) {
46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      *error = ErrorUtils::FormatErrorMessageUTF16(
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          errors::kPermissionNotAllowedInManifest,
48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          (*iter)->info()->name());
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return true;
50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return false;
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Custom checks for the experimental permission that can't be expressed in
56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// _permission_features.json.
57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool CanSpecifyExperimentalPermission(const Extension* extension) {
58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (extension->location() == Manifest::COMPONENT)
59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return true;
60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          switches::kEnableExperimentalExtensionApis)) {
63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return true;
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // We rely on the webstore to check access to experimental. This way we can
67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // whitelist extensions to have access to experimental in just the store, and
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // not have to push a new version of the client.
69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (extension->from_webstore())
70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return true;
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return false;
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Checks whether the host |pattern| is allowed for the given |extension|,
76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// given API permissions |permissions|.
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool CanSpecifyHostPermission(const Extension* extension,
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              const URLPattern& pattern,
79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              const APIPermissionSet& permissions) {
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!pattern.match_all_urls() &&
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      pattern.MatchesScheme(chrome::kChromeUIScheme)) {
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    URLPatternSet chrome_scheme_hosts =
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        GetPermittedChromeSchemeHosts(extension, permissions);
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (chrome_scheme_hosts.ContainsPattern(pattern))
85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return true;
86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // Component extensions can have access to all of chrome://*.
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (PermissionsData::CanExecuteScriptEverywhere(extension))
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return true;
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (CommandLine::ForCurrentProcess()->HasSwitch(
92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          switches::kExtensionsOnChromeURLs)) {
93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return true;
94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // TODO(aboxhall): return from_webstore() when webstore handles blocking
97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // extensions which request chrome:// urls
98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Otherwise, the valid schemes were handled by URLPattern.
102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Parses the host and api permissions from the specified permission |key|
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// from |extension|'s manifest.
107b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ParseHelper(Extension* extension,
108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 const char* key,
109b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 APIPermissionSet* api_permissions,
110b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 URLPatternSet* host_permissions,
111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 string16* error) {
112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!extension->manifest()->HasKey(key))
113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return true;
114b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::ListValue* permissions = NULL;
116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!extension->manifest()->GetList(key, &permissions)) {
117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermissions,
118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                 std::string());
119b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
122b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // NOTE: We need to get the APIPermission before we check if features
123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // associated with them are available because the feature system does not
124b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // know about aliases.
125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::vector<std::string> host_data;
127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!APIPermissionSet::ParseFromJSON(
128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          permissions, APIPermissionSet::kDisallowInternalPermissions,
129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          api_permissions, error, &host_data)) {
130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Verify feature availability of permissions.
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::vector<APIPermission::ID> to_remove;
135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  FeatureProvider* permission_features =
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      BaseFeatureProvider::GetByName("permission");
137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (APIPermissionSet::const_iterator iter = api_permissions->begin();
138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       iter != api_permissions->end(); ++iter) {
139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Feature* feature = permission_features->GetFeature(iter->name());
140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // The feature should exist since we just got an APIPermission for it. The
142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // two systems should be updated together whenever a permission is added.
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DCHECK(feature);
144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // http://crbug.com/176381
145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!feature) {
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      to_remove.push_back(iter->id());
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      continue;
148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Feature::Availability availability = feature->IsAvailableToManifest(
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        extension->id(),
152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        extension->GetType(),
153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        Feature::ConvertLocation(extension->location()),
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        extension->manifest_version());
155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
156b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!availability.is_available()) {
157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // Don't fail, but warn the developer that the manifest contains
158b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // unrecognized permissions. This may happen legitimately if the
159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // extensions requests platform- or channel-specific permissions.
160b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      extension->AddInstallWarning(InstallWarning(InstallWarning::FORMAT_TEXT,
161b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                  availability.message()));
162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      to_remove.push_back(iter->id());
163b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      continue;
164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (iter->id() == APIPermission::kExperimental) {
167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (!CanSpecifyExperimentalPermission(extension)) {
168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        *error = ASCIIToUTF16(errors::kExperimentalFlagRequired);
169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return false;
170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      }
171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Remove permissions that are not available to this extension.
175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (std::vector<APIPermission::ID>::const_iterator iter = to_remove.begin();
176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       iter != to_remove.end(); ++iter) {
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      api_permissions->erase(*iter);
178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Parse host pattern permissions.
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int kAllowedSchemes =
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      PermissionsData::CanExecuteScriptEverywhere(extension) ?
183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      URLPattern::SCHEME_ALL : Extension::kValidHostPermissionSchemes;
184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (std::vector<std::string>::const_iterator iter = host_data.begin();
186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       iter != host_data.end(); ++iter) {
187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& permission_str = *iter;
188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // Check if it's a host pattern permission.
190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    URLPattern pattern = URLPattern(kAllowedSchemes);
191b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    URLPattern::ParseResult parse_result = pattern.Parse(permission_str);
192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (parse_result == URLPattern::PARSE_SUCCESS) {
193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // The path component is not used for host permissions, so we force it
194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // to match all paths.
195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      pattern.SetPath("/*");
196b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      int valid_schemes = pattern.valid_schemes();
197b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (pattern.MatchesScheme(chrome::kFileScheme) &&
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          !PermissionsData::CanExecuteScriptEverywhere(extension)) {
199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        extension->set_wants_file_access(true);
200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS))
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          valid_schemes &= ~URLPattern::SCHEME_FILE;
202b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      }
203b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (pattern.scheme() != chrome::kChromeUIScheme &&
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          !PermissionsData::CanExecuteScriptEverywhere(extension)) {
206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // Keep chrome:// in allowed schemes only if it's explicitly requested
207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // or CanExecuteScriptEverywhere is true. If the
208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission
209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // will fail, so don't check the flag here.
210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        valid_schemes &= ~URLPattern::SCHEME_CHROMEUI;
211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      }
212b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      pattern.SetValidSchemes(valid_schemes);
213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
214b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (!CanSpecifyHostPermission(extension, pattern, *api_permissions)) {
215b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // TODO(aboxhall): make a warning (see pattern.match_all_urls() block
216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        // below).
217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            errors::kInvalidPermissionScheme, permission_str);
219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return false;
220b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      }
221b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      host_permissions->AddPattern(pattern);
223b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // We need to make sure all_urls matches chrome://favicon and (maybe)
224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      // chrome://thumbnail, so add them back in to host_permissions separately.
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (pattern.match_all_urls())
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        host_permissions->AddPatterns(GetPermittedChromeSchemeHosts(
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            extension, *api_permissions));
228b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      continue;
229b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
230b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // It's probably an unknown API permission. Do not throw an error so
232b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // extensions can retain backwards compatability (http://crbug.com/42742).
233b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    extension->AddInstallWarning(InstallWarning(
234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        InstallWarning::FORMAT_TEXT,
235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        base::StringPrintf(
236b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            "Permission '%s' is unknown or URL pattern is malformed.",
237b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            permission_str.c_str())));
238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
239b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
240b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returns true if this extension id is from a trusted provider.
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool IsTrustedId(const std::string& extension_id) {
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // See http://b/4946060 for more details.
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace
250b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)struct PermissionsData::InitialPermissions {
252b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  APIPermissionSet api_permissions;
253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  URLPatternSet host_permissions;
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  URLPatternSet scriptable_hosts;
255b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)};
256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)PermissionsData::PermissionsData() {
258b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
260b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)PermissionsData::~PermissionsData() {
261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
262b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) {
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  g_policy_delegate = delegate;
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const PermissionSet* PermissionsData::GetOptionalPermissions(
270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const Extension* extension) {
271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return extension->permissions_data()->optional_permission_set_.get();
272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const PermissionSet* PermissionsData::GetRequiredPermissions(
276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const Extension* extension) {
277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return extension->permissions_data()->required_permission_set_.get();
278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const APIPermissionSet* PermissionsData::GetInitialAPIPermissions(
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const Extension* extension) {
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return &extension->permissions_data()->
284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_required_permissions_->api_permissions;
285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static
288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)APIPermissionSet* PermissionsData::GetInitialAPIPermissions(
289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    Extension* extension) {
290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return &extension->permissions_data()->
291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_required_permissions_->api_permissions;
292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PermissionsData::SetInitialScriptableHosts(
2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Extension* extension, const URLPatternSet& scriptable_hosts) {
2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  extension->permissions_data()->
2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      initial_required_permissions_->scriptable_hosts = scriptable_hosts;
2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PermissionsData::SetActivePermissions(const Extension* extension,
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                           const PermissionSet* permissions) {
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  extension->permissions_data()->active_permissions_ = permissions;
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_refptr<const PermissionSet> PermissionsData::GetActivePermissions(
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension) {
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return extension->permissions_data()->active_permissions_;
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension,
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int tab_id) {
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CHECK_GE(tab_id, 0);
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TabPermissionsMap::const_iterator iter =
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      extension->permissions_data()->tab_specific_permissions_.find(tab_id);
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      (iter != extension->permissions_data()->tab_specific_permissions_.end())
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          ? iter->second
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          : NULL;
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PermissionsData::UpdateTabSpecificPermissions(
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension,
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int tab_id,
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<const PermissionSet> permissions) {
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CHECK_GE(tab_id, 0);
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TabPermissionsMap* tab_permissions =
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &extension->permissions_data()->tab_specific_permissions_;
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (tab_permissions->count(tab_id)) {
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    (*tab_permissions)[tab_id] = PermissionSet::CreateUnion(
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        (*tab_permissions)[tab_id].get(), permissions.get());
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    (*tab_permissions)[tab_id] = permissions;
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PermissionsData::ClearTabSpecificPermissions(
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension,
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int tab_id) {
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CHECK_GE(tab_id, 0);
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  extension->permissions_data()->tab_specific_permissions_.erase(tab_id);
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::HasAPIPermission(const Extension* extension,
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       APIPermission::ID permission) {
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetActivePermissions(extension)->HasAPIPermission(permission);
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool PermissionsData::HasAPIPermission(
360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const Extension* extension,
361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const std::string& permission_name) {
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return GetActivePermissions(extension)->HasAPIPermission(permission_name);
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::HasAPIPermissionForTab(
36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension,
36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int tab_id,
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    APIPermission::ID permission) {
37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (HasAPIPermission(extension, permission))
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Place autolock below the HasAPIPermission() check, since HasAPIPermission
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // also acquires the lock.
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<const PermissionSet> tab_permissions =
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GetTabSpecificPermissions(extension, tab_id);
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::CheckAPIPermissionWithParam(
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension,
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    APIPermission::ID permission,
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const APIPermission::CheckParam* param) {
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetActivePermissions(extension)->CheckAPIPermissionWithParam(
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      permission, param);
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const URLPatternSet& PermissionsData::GetEffectiveHostPermissions(
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension) {
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetActivePermissions(extension)->effective_hosts();
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::CanSilentlyIncreasePermissions(
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension) {
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return extension->location() != Manifest::INTERNAL;
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::ShouldSkipPermissionWarnings(const Extension* extension) {
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return IsTrustedId(extension->id());
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::HasHostPermission(const Extension* extension,
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                        const GURL& url) {
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetActivePermissions(extension)->HasExplicitAccessToOrigin(url);
41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::HasEffectiveAccessToAllHosts(const Extension* extension) {
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return GetActivePermissions(extension)->HasEffectiveAccessToAllHosts();
42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PermissionMessages PermissionsData::GetPermissionMessages(
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension) {
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (ShouldSkipPermissionWarnings(extension)) {
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return PermissionMessages();
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetActivePermissions(extension)->GetPermissionMessages(
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        extension->GetType());
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<string16> PermissionsData::GetPermissionMessageStrings(
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Extension* extension) {
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (ShouldSkipPermissionWarnings(extension)) {
44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return std::vector<string16>();
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
44290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return GetActivePermissions(extension)->GetWarningMessages(
44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        extension->GetType());
44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstd::vector<string16> PermissionsData::GetPermissionMessageDetailsStrings(
4497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const Extension* extension) {
4507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
4517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (ShouldSkipPermissionWarnings(extension)) {
4527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return std::vector<string16>();
4537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
4547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return GetActivePermissions(extension)->GetWarningMessagesDetails(
4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        extension->GetType());
4567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension,
46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             const GURL& document_url,
46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             const GURL& top_frame_url,
46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             int tab_id,
46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             const UserScript* script,
46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             int process_id,
46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             std::string* error) {
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The gallery is special-cased as a restricted URL for scripting to prevent
46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // access to special JS bindings we expose to the gallery (and avoid things
47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // like extensions removing the "report abuse" link).
47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(erikkay): This seems like the wrong test.  Shouldn't we we testing
47290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // against the store app extent?
47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL store_url(extension_urls::GetWebstoreLaunchURL());
47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const CommandLine* command_line = CommandLine::ForCurrentProcess();
47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool can_execute_everywhere = CanExecuteScriptEverywhere(extension);
47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (g_policy_delegate &&
47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !g_policy_delegate->CanExecuteScriptOnPage(
47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           extension, document_url, top_frame_url, tab_id,
48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           script, process_id, error))
48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
48290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
48390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((document_url.host() == store_url.host()) &&
48490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !can_execute_everywhere &&
48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !command_line->HasSwitch(switches::kAllowScriptingGallery)) {
48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (error)
48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *error = errors::kCannotScriptGallery;
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!command_line->HasSwitch(switches::kExtensionsOnChromeURLs)) {
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (document_url.SchemeIs(chrome::kChromeUIScheme) &&
49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        !can_execute_everywhere) {
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (error)
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        *error = errors::kCannotAccessChromeUrl;
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return false;
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (top_frame_url.SchemeIs(extensions::kExtensionScheme) &&
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      top_frame_url.GetOrigin() !=
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() &&
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !can_execute_everywhere) {
50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (error)
50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *error = errors::kCannotAccessExtensionUrl;
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If a tab ID is specified, try the tab-specific permissions.
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (tab_id >= 0) {
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<const PermissionSet> tab_permissions =
51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        GetTabSpecificPermissions(extension, tab_id);
51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (tab_permissions.get() &&
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        tab_permissions->explicit_hosts().MatchesSecurityOrigin(document_url)) {
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool can_access = false;
52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (script) {
52290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // If a script is specified, use its matches.
52390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    can_access = script->MatchesURL(document_url);
52490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
52590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Otherwise, see if this extension has permission to execute script
52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // programmatically on pages.
52790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    can_access = GetActivePermissions(extension)->
52890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        HasExplicitAccessToOrigin(document_url);
52990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
53090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!can_access && error) {
53290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            document_url.spec());
53490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
53590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return can_access;
53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
54190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (extension->location() == Manifest::COMPONENT)
54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const Extension::ScriptingWhitelist* whitelist =
54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Extension::GetScriptingWhitelist();
54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (Extension::ScriptingWhitelist::const_iterator iter = whitelist->begin();
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       iter != whitelist->end(); ++iter) {
54990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (extension->id() == *iter)
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
55290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool PermissionsData::CanCaptureVisiblePage(const Extension* extension,
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            const GURL& page_url,
55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            int tab_id,
56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            std::string* error) {
56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (tab_id >= 0) {
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<const PermissionSet> tab_permissions =
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        GetTabSpecificPermissions(extension, tab_id);
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (tab_permissions.get() &&
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        tab_permissions->explicit_hosts().MatchesSecurityOrigin(page_url)) {
56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (HasHostPermission(extension, page_url) ||
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      page_url.GetOrigin() == extension->url()) {
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
57490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (error) {
57690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage,
57790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            page_url.spec());
57890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
57990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
58090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
58190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool PermissionsData::ParsePermissions(Extension* extension, string16* error) {
583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  initial_required_permissions_.reset(new InitialPermissions);
584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!ParseHelper(extension,
585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   keys::kPermissions,
586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   &initial_required_permissions_->api_permissions,
587b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   &initial_required_permissions_->host_permissions,
588b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   error)) {
589b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
590b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
591b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
592b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // TODO(jeremya/kalman) do this via the features system by exposing the
593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // app.window API to platform apps, with no dependency on any permissions.
594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // See http://crbug.com/120069.
595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (extension->is_platform_app()) {
596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    initial_required_permissions_->api_permissions.insert(
597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        APIPermission::kAppCurrentWindowInternal);
598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    initial_required_permissions_->api_permissions.insert(
599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        APIPermission::kAppRuntime);
600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    initial_required_permissions_->api_permissions.insert(
601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        APIPermission::kAppWindow);
602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  initial_optional_permissions_.reset(new InitialPermissions);
605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!ParseHelper(extension,
606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   keys::kOptionalPermissions,
607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   &initial_optional_permissions_->api_permissions,
608b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   &initial_optional_permissions_->host_permissions,
609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   error)) {
610b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
611b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
612b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
613b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (ContainsManifestForbiddenPermission(
614b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          initial_required_permissions_->api_permissions, error) ||
615b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      ContainsManifestForbiddenPermission(
616b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          initial_optional_permissions_->api_permissions, error)) {
617b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
618b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
619b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
620b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
621b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
622b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
623b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void PermissionsData::FinalizePermissions(Extension* extension) {
62490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  active_permissions_ = new PermissionSet(
625b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_required_permissions_->api_permissions,
626b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_required_permissions_->host_permissions,
6277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      initial_required_permissions_->scriptable_hosts);
628b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  required_permission_set_ = new PermissionSet(
630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_required_permissions_->api_permissions,
631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_required_permissions_->host_permissions,
6327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      initial_required_permissions_->scriptable_hosts);
633b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
634b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  optional_permission_set_ = new PermissionSet(
635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_optional_permissions_->api_permissions,
636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initial_optional_permissions_->host_permissions,
637b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      URLPatternSet());
638b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
639b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  initial_required_permissions_.reset();
640b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  initial_optional_permissions_.reset();
641b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
642b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
643b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace extensions
644