168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file. 468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "extensions/common/permissions/media_galleries_permission.h" 668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <set> 868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <string> 968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/logging.h" 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/common/permissions/permissions_info.h" 1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "grit/extensions_strings.h" 1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// copyTo permission requires delete permission as a prerequisite. 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// delete permission requires read permission as a prerequisite. 2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool IsValidPermissionSet(bool has_read, bool has_copy_to, bool has_delete, 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string* error) { 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (has_copy_to) { 2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (has_read && has_delete) 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; 2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (error) 2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *error = "copyTo permission requires read and delete permissions"; 2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (has_delete) { 3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (has_read) 3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (error) 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) *error = "delete permission requires read permission"; 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return true; 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} // namespace 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace extensions { 4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char MediaGalleriesPermission::kAllAutoDetectedPermission[] = 4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "allAutoDetected"; 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char MediaGalleriesPermission::kScanPermission[] = "scan"; 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char MediaGalleriesPermission::kReadPermission[] = "read"; 4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo"; 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char MediaGalleriesPermission::kDeletePermission[] = "delete"; 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)MediaGalleriesPermission::MediaGalleriesPermission( 5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const APIPermissionInfo* info) 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) : SetDisjunctionPermission<MediaGalleriesPermissionData, 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) MediaGalleriesPermission>(info) { 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)MediaGalleriesPermission::~MediaGalleriesPermission() { 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool MediaGalleriesPermission::FromValue( 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const base::Value* value, 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string* error, 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<std::string>* unhandled_permissions) { 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t unhandled_permissions_count = 0; 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (unhandled_permissions) 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) unhandled_permissions_count = unhandled_permissions->size(); 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool parsed_ok = 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SetDisjunctionPermission<MediaGalleriesPermissionData, 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) MediaGalleriesPermission>::FromValue( 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) value, error, unhandled_permissions); 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (unhandled_permissions) { 7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (size_t i = unhandled_permissions_count; 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) i < unhandled_permissions->size(); 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) i++) { 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (*unhandled_permissions)[i] = 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "{\"mediaGalleries\": [" + (*unhandled_permissions)[i] + "]}"; 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!parsed_ok) 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool has_read = false; 8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool has_copy_to = false; 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 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