Home | History | Annotate | Download | only in permissions
      1 // Copyright 2014 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/media_galleries_permission.h"
      6 
      7 #include <set>
      8 #include <string>
      9 
     10 #include "base/logging.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "extensions/common/permissions/permissions_info.h"
     13 #include "grit/extensions_strings.h"
     14 #include "ui/base/l10n/l10n_util.h"
     15 
     16 namespace {
     17 
     18 // copyTo permission requires delete permission as a prerequisite.
     19 // delete permission requires read permission as a prerequisite.
     20 bool IsValidPermissionSet(bool has_read, bool has_copy_to, bool has_delete,
     21                           std::string* error) {
     22   if (has_copy_to) {
     23     if (has_read && has_delete)
     24       return true;
     25     if (error)
     26       *error = "copyTo permission requires read and delete permissions";
     27     return false;
     28   }
     29   if (has_delete) {
     30     if (has_read)
     31       return true;
     32     if (error)
     33       *error = "delete permission requires read permission";
     34     return false;
     35   }
     36   return true;
     37 }
     38 
     39 }  // namespace
     40 
     41 namespace extensions {
     42 
     43 const char MediaGalleriesPermission::kAllAutoDetectedPermission[] =
     44     "allAutoDetected";
     45 const char MediaGalleriesPermission::kScanPermission[] = "scan";
     46 const char MediaGalleriesPermission::kReadPermission[] = "read";
     47 const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo";
     48 const char MediaGalleriesPermission::kDeletePermission[] = "delete";
     49 
     50 MediaGalleriesPermission::MediaGalleriesPermission(
     51     const APIPermissionInfo* info)
     52   : SetDisjunctionPermission<MediaGalleriesPermissionData,
     53                              MediaGalleriesPermission>(info) {
     54 }
     55 
     56 MediaGalleriesPermission::~MediaGalleriesPermission() {
     57 }
     58 
     59 bool MediaGalleriesPermission::FromValue(
     60     const base::Value* value,
     61     std::string* error,
     62     std::vector<std::string>* unhandled_permissions) {
     63   size_t unhandled_permissions_count = 0;
     64   if (unhandled_permissions)
     65     unhandled_permissions_count = unhandled_permissions->size();
     66   bool parsed_ok =
     67       SetDisjunctionPermission<MediaGalleriesPermissionData,
     68                                MediaGalleriesPermission>::FromValue(
     69                                    value, error, unhandled_permissions);
     70   if (unhandled_permissions) {
     71     for (size_t i = unhandled_permissions_count;
     72          i < unhandled_permissions->size();
     73          i++) {
     74       (*unhandled_permissions)[i] =
     75           "{\"mediaGalleries\": [" + (*unhandled_permissions)[i] + "]}";
     76     }
     77   }
     78   if (!parsed_ok)
     79     return false;
     80 
     81   bool has_read = false;
     82   bool has_copy_to = false;
     83   bool has_delete = false;
     84   for (std::set<MediaGalleriesPermissionData>::const_iterator it =
     85       data_set_.begin(); it != data_set_.end(); ++it) {
     86     if (it->permission() == kAllAutoDetectedPermission ||
     87         it->permission() == kScanPermission) {
     88       continue;
     89     }
     90     if (it->permission() == kReadPermission) {
     91       has_read = true;
     92       continue;
     93     }
     94     if (it->permission() == kCopyToPermission) {
     95       has_copy_to = true;
     96       continue;
     97     }
     98     if (it->permission() == kDeletePermission) {
     99       has_delete = true;
    100       continue;
    101     }
    102 
    103     // No other permissions, so reaching this means
    104     // MediaGalleriesPermissionData is probably out of sync in some way.
    105     // Fail so developers notice this.
    106     NOTREACHED();
    107     return false;
    108   }
    109 
    110   return IsValidPermissionSet(has_read, has_copy_to, has_delete, error);
    111 }
    112 
    113 PermissionMessages MediaGalleriesPermission::GetMessages() const {
    114   DCHECK(HasMessages());
    115   PermissionMessages result;
    116 
    117   bool has_all_auto_detected = false;
    118   bool has_read = false;
    119   bool has_copy_to = false;
    120   bool has_delete = false;
    121 
    122   for (std::set<MediaGalleriesPermissionData>::const_iterator it =
    123       data_set_.begin(); it != data_set_.end(); ++it) {
    124     if (it->permission() == kAllAutoDetectedPermission)
    125       has_all_auto_detected = true;
    126     else if (it->permission() == kReadPermission)
    127       has_read = true;
    128     else if (it->permission() == kCopyToPermission)
    129       has_copy_to = true;
    130     else if (it->permission() == kDeletePermission)
    131       has_delete = true;
    132   }
    133 
    134   if (!IsValidPermissionSet(has_read, has_copy_to, has_delete, NULL)) {
    135     NOTREACHED();
    136     return result;
    137   }
    138 
    139   // If |has_all_auto_detected| is false, then Chrome will prompt the user at
    140   // runtime when the extension call the getMediaGalleries API.
    141   if (!has_all_auto_detected)
    142     return result;
    143   // No access permission case.
    144   if (!has_read)
    145     return result;
    146 
    147   // Separate PermissionMessage IDs for read, copyTo, and delete. Otherwise an
    148   // extension can silently gain new access capabilities.
    149   result.push_back(PermissionMessage(
    150       PermissionMessage::kMediaGalleriesAllGalleriesRead,
    151       l10n_util::GetStringUTF16(
    152           IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ)));
    153 
    154   // For copyTo and delete, the proper combined permission message will be
    155   // derived in ChromePermissionMessageProvider::GetWarningMessages(), such
    156   // that the user get 1 entry for all media galleries access permissions,
    157   // rather than several separate entries.
    158   if (has_copy_to) {
    159     result.push_back(PermissionMessage(
    160         PermissionMessage::kMediaGalleriesAllGalleriesCopyTo,
    161         base::string16()));
    162   }
    163   if (has_delete) {
    164     result.push_back(PermissionMessage(
    165         PermissionMessage::kMediaGalleriesAllGalleriesDelete,
    166         base::string16()));
    167   }
    168   return result;
    169 }
    170 
    171 }  // namespace extensions
    172