Home | History | Annotate | Download | only in permissions
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "extensions/common/permissions/permissions_data.h"
      6 
      7 #include "base/command_line.h"
      8 #include "content/public/common/url_constants.h"
      9 #include "extensions/common/constants.h"
     10 #include "extensions/common/error_utils.h"
     11 #include "extensions/common/extensions_client.h"
     12 #include "extensions/common/manifest.h"
     13 #include "extensions/common/manifest_constants.h"
     14 #include "extensions/common/manifest_handlers/permissions_parser.h"
     15 #include "extensions/common/permissions/permission_message_provider.h"
     16 #include "extensions/common/switches.h"
     17 #include "extensions/common/url_pattern_set.h"
     18 #include "extensions/common/user_script.h"
     19 #include "url/gurl.h"
     20 #include "url/url_constants.h"
     21 
     22 namespace extensions {
     23 
     24 namespace {
     25 
     26 PermissionsData::PolicyDelegate* g_policy_delegate = NULL;
     27 
     28 }  // namespace
     29 
     30 PermissionsData::PermissionsData(const Extension* extension)
     31     : extension_id_(extension->id()), manifest_type_(extension->GetType()) {
     32   base::AutoLock auto_lock(runtime_lock_);
     33   scoped_refptr<const PermissionSet> required_permissions =
     34       PermissionsParser::GetRequiredPermissions(extension);
     35   active_permissions_unsafe_ =
     36       new PermissionSet(required_permissions->apis(),
     37                         required_permissions->manifest_permissions(),
     38                         required_permissions->explicit_hosts(),
     39                         required_permissions->scriptable_hosts());
     40 }
     41 
     42 PermissionsData::~PermissionsData() {
     43 }
     44 
     45 // static
     46 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) {
     47   g_policy_delegate = delegate;
     48 }
     49 
     50 // static
     51 bool PermissionsData::CanSilentlyIncreasePermissions(
     52     const Extension* extension) {
     53   return extension->location() != Manifest::INTERNAL;
     54 }
     55 
     56 // static
     57 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
     58   if (extension->location() == Manifest::COMPONENT)
     59     return true;
     60 
     61   const ExtensionsClient::ScriptingWhitelist& whitelist =
     62       ExtensionsClient::Get()->GetScriptingWhitelist();
     63 
     64   return std::find(whitelist.begin(), whitelist.end(), extension->id()) !=
     65          whitelist.end();
     66 }
     67 
     68 bool PermissionsData::ShouldSkipPermissionWarnings(
     69     const std::string& extension_id) {
     70   // See http://b/4946060 for more details.
     71   return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
     72 }
     73 
     74 // static
     75 bool PermissionsData::IsRestrictedUrl(const GURL& document_url,
     76                                       const GURL& top_frame_url,
     77                                       const Extension* extension,
     78                                       std::string* error) {
     79   if (CanExecuteScriptEverywhere(extension))
     80     return false;
     81 
     82   // Check if the scheme is valid for extensions. If not, return.
     83   if (!URLPattern::IsValidSchemeForExtensions(document_url.scheme()) &&
     84       document_url.spec() != url::kAboutBlankURL) {
     85     if (error) {
     86       *error = ErrorUtils::FormatErrorMessage(
     87                    manifest_errors::kCannotAccessPage,
     88                    document_url.spec());
     89     }
     90     return true;
     91   }
     92 
     93   if (!ExtensionsClient::Get()->IsScriptableURL(document_url, error))
     94     return true;
     95 
     96   bool allow_on_chrome_urls = base::CommandLine::ForCurrentProcess()->HasSwitch(
     97                                   switches::kExtensionsOnChromeURLs);
     98   if (document_url.SchemeIs(content::kChromeUIScheme) &&
     99       !allow_on_chrome_urls) {
    100     if (error)
    101       *error = manifest_errors::kCannotAccessChromeUrl;
    102     return true;
    103   }
    104 
    105   if (top_frame_url.SchemeIs(kExtensionScheme) &&
    106       top_frame_url.host() != extension->id() &&
    107       !allow_on_chrome_urls) {
    108     if (error)
    109       *error = manifest_errors::kCannotAccessExtensionUrl;
    110     return true;
    111   }
    112 
    113   return false;
    114 }
    115 
    116 void PermissionsData::SetActivePermissions(
    117     const PermissionSet* permissions) const {
    118   base::AutoLock auto_lock(runtime_lock_);
    119   active_permissions_unsafe_ = permissions;
    120 }
    121 
    122 void PermissionsData::UpdateTabSpecificPermissions(
    123     int tab_id,
    124     scoped_refptr<const PermissionSet> permissions) const {
    125   base::AutoLock auto_lock(runtime_lock_);
    126   CHECK_GE(tab_id, 0);
    127   TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id);
    128   if (iter == tab_specific_permissions_.end())
    129     tab_specific_permissions_[tab_id] = permissions;
    130   else
    131     iter->second = PermissionSet::CreateUnion(iter->second, permissions);
    132 }
    133 
    134 void PermissionsData::ClearTabSpecificPermissions(int tab_id) const {
    135   base::AutoLock auto_lock(runtime_lock_);
    136   CHECK_GE(tab_id, 0);
    137   tab_specific_permissions_.erase(tab_id);
    138 }
    139 
    140 bool PermissionsData::HasAPIPermission(APIPermission::ID permission) const {
    141   return active_permissions()->HasAPIPermission(permission);
    142 }
    143 
    144 bool PermissionsData::HasAPIPermission(
    145     const std::string& permission_name) const {
    146   return active_permissions()->HasAPIPermission(permission_name);
    147 }
    148 
    149 bool PermissionsData::HasAPIPermissionForTab(
    150     int tab_id,
    151     APIPermission::ID permission) const {
    152   if (HasAPIPermission(permission))
    153     return true;
    154 
    155   scoped_refptr<const PermissionSet> tab_permissions =
    156       GetTabSpecificPermissions(tab_id);
    157 
    158   // Place autolock below the HasAPIPermission() and
    159   // GetTabSpecificPermissions(), since each already acquires the lock.
    160   base::AutoLock auto_lock(runtime_lock_);
    161   return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
    162 }
    163 
    164 bool PermissionsData::CheckAPIPermissionWithParam(
    165     APIPermission::ID permission,
    166     const APIPermission::CheckParam* param) const {
    167   return active_permissions()->CheckAPIPermissionWithParam(permission, param);
    168 }
    169 
    170 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions() const {
    171   return active_permissions()->effective_hosts();
    172 }
    173 
    174 bool PermissionsData::HasHostPermission(const GURL& url) const {
    175   return active_permissions()->HasExplicitAccessToOrigin(url);
    176 }
    177 
    178 bool PermissionsData::HasEffectiveAccessToAllHosts() const {
    179   return active_permissions()->HasEffectiveAccessToAllHosts();
    180 }
    181 
    182 PermissionMessages PermissionsData::GetPermissionMessages() const {
    183   if (ShouldSkipPermissionWarnings(extension_id_)) {
    184     return PermissionMessages();
    185   } else {
    186     return PermissionMessageProvider::Get()->GetPermissionMessages(
    187         active_permissions(), manifest_type_);
    188   }
    189 }
    190 
    191 std::vector<base::string16> PermissionsData::GetPermissionMessageStrings()
    192     const {
    193   if (ShouldSkipPermissionWarnings(extension_id_))
    194     return std::vector<base::string16>();
    195   return PermissionMessageProvider::Get()->GetWarningMessages(
    196       active_permissions(), manifest_type_);
    197 }
    198 
    199 std::vector<base::string16>
    200 PermissionsData::GetPermissionMessageDetailsStrings() const {
    201   if (ShouldSkipPermissionWarnings(extension_id_))
    202     return std::vector<base::string16>();
    203   return PermissionMessageProvider::Get()->GetWarningMessagesDetails(
    204       active_permissions(), manifest_type_);
    205 }
    206 
    207 bool PermissionsData::CanAccessPage(const Extension* extension,
    208                                     const GURL& document_url,
    209                                     const GURL& top_frame_url,
    210                                     int tab_id,
    211                                     int process_id,
    212                                     std::string* error) const {
    213   return CanRunOnPage(extension,
    214                       document_url,
    215                       top_frame_url,
    216                       tab_id,
    217                       process_id,
    218                       active_permissions()->explicit_hosts(),
    219                       error);
    220 }
    221 
    222 bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension,
    223                                                 const GURL& document_url,
    224                                                 const GURL& top_frame_url,
    225                                                 int tab_id,
    226                                                 int process_id,
    227                                                 std::string* error) const {
    228   return CanRunOnPage(extension,
    229                       document_url,
    230                       top_frame_url,
    231                       tab_id,
    232                       process_id,
    233                       active_permissions()->scriptable_hosts(),
    234                       error);
    235 }
    236 
    237 bool PermissionsData::CanCaptureVisiblePage(int tab_id,
    238                                             std::string* error) const {
    239   const URLPattern all_urls(URLPattern::SCHEME_ALL,
    240                             URLPattern::kAllUrlsPattern);
    241 
    242   if (active_permissions()->explicit_hosts().ContainsPattern(all_urls))
    243     return true;
    244 
    245   if (tab_id >= 0) {
    246     scoped_refptr<const PermissionSet> tab_permissions =
    247         GetTabSpecificPermissions(tab_id);
    248     if (tab_permissions &&
    249         tab_permissions->HasAPIPermission(APIPermission::kTab)) {
    250       return true;
    251     }
    252     if (error)
    253       *error = manifest_errors::kActiveTabPermissionNotGranted;
    254     return false;
    255   }
    256 
    257   if (error)
    258     *error = manifest_errors::kAllURLOrActiveTabNeeded;
    259   return false;
    260 }
    261 
    262 // static
    263 bool PermissionsData::RequiresActionForScriptExecution(
    264     const Extension* extension) const {
    265   return RequiresActionForScriptExecution(extension, -1, GURL());
    266 }
    267 
    268 // static
    269 bool PermissionsData::RequiresActionForScriptExecution(
    270     const Extension* extension,
    271     int tab_id,
    272     const GURL& url) const {
    273   // For now, the user should be notified when an extension with all hosts
    274   // permission tries to execute a script on a page. Exceptions for policy-
    275   // enabled and component extensions, and extensions which are whitelisted to
    276   // execute scripts everywhere.
    277   if (!extension->ShouldDisplayInExtensionSettings() ||
    278       Manifest::IsPolicyLocation(extension->location()) ||
    279       Manifest::IsComponentLocation(extension->location()) ||
    280       CanExecuteScriptEverywhere(extension) ||
    281       !active_permissions()->ShouldWarnAllHosts()) {
    282     return false;
    283   }
    284 
    285   // If the extension has explicit permission to run on the given tab, then
    286   // we don't need to alert the user.
    287   if (HasTabSpecificPermissionToExecuteScript(tab_id, url))
    288     return false;
    289 
    290   return true;
    291 }
    292 
    293 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
    294     int tab_id) const {
    295   base::AutoLock auto_lock(runtime_lock_);
    296   CHECK_GE(tab_id, 0);
    297   TabPermissionsMap::const_iterator iter =
    298       tab_specific_permissions_.find(tab_id);
    299   return (iter != tab_specific_permissions_.end()) ? iter->second : NULL;
    300 }
    301 
    302 bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
    303     int tab_id,
    304     const GURL& url) const {
    305   if (tab_id >= 0) {
    306     scoped_refptr<const PermissionSet> tab_permissions =
    307         GetTabSpecificPermissions(tab_id);
    308     if (tab_permissions.get() &&
    309         tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) {
    310       return true;
    311     }
    312   }
    313   return false;
    314 }
    315 
    316 bool PermissionsData::CanRunOnPage(const Extension* extension,
    317                                    const GURL& document_url,
    318                                    const GURL& top_frame_url,
    319                                    int tab_id,
    320                                    int process_id,
    321                                    const URLPatternSet& permitted_url_patterns,
    322                                    std::string* error) const {
    323   if (g_policy_delegate &&
    324       !g_policy_delegate->CanExecuteScriptOnPage(
    325           extension, document_url, top_frame_url, tab_id, process_id, error)) {
    326     return false;
    327   }
    328 
    329   if (IsRestrictedUrl(document_url, top_frame_url, extension, error))
    330     return false;
    331 
    332   if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url))
    333     return true;
    334 
    335   bool can_access = permitted_url_patterns.MatchesURL(document_url);
    336 
    337   if (!can_access && error) {
    338     *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage,
    339                                             document_url.spec());
    340   }
    341 
    342   return can_access;
    343 }
    344 
    345 }  // namespace extensions
    346