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 16namespace { 17 18// copyTo permission requires delete permission as a prerequisite. 19// delete permission requires read permission as a prerequisite. 20bool 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 41namespace extensions { 42 43const char MediaGalleriesPermission::kAllAutoDetectedPermission[] = 44 "allAutoDetected"; 45const char MediaGalleriesPermission::kScanPermission[] = "scan"; 46const char MediaGalleriesPermission::kReadPermission[] = "read"; 47const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo"; 48const char MediaGalleriesPermission::kDeletePermission[] = "delete"; 49 50MediaGalleriesPermission::MediaGalleriesPermission( 51 const APIPermissionInfo* info) 52 : SetDisjunctionPermission<MediaGalleriesPermissionData, 53 MediaGalleriesPermission>(info) { 54} 55 56MediaGalleriesPermission::~MediaGalleriesPermission() { 57} 58 59bool 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 113PermissionMessages 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