// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "extensions/common/permissions/media_galleries_permission.h" #include <set> #include <string> #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "extensions/common/permissions/permissions_info.h" #include "grit/extensions_strings.h" #include "ui/base/l10n/l10n_util.h" namespace { // copyTo permission requires delete permission as a prerequisite. // delete permission requires read permission as a prerequisite. bool IsValidPermissionSet(bool has_read, bool has_copy_to, bool has_delete, std::string* error) { if (has_copy_to) { if (has_read && has_delete) return true; if (error) *error = "copyTo permission requires read and delete permissions"; return false; } if (has_delete) { if (has_read) return true; if (error) *error = "delete permission requires read permission"; return false; } return true; } } // namespace namespace extensions { const char MediaGalleriesPermission::kAllAutoDetectedPermission[] = "allAutoDetected"; const char MediaGalleriesPermission::kScanPermission[] = "scan"; const char MediaGalleriesPermission::kReadPermission[] = "read"; const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo"; const char MediaGalleriesPermission::kDeletePermission[] = "delete"; MediaGalleriesPermission::MediaGalleriesPermission( const APIPermissionInfo* info) : SetDisjunctionPermission<MediaGalleriesPermissionData, MediaGalleriesPermission>(info) { } MediaGalleriesPermission::~MediaGalleriesPermission() { } bool MediaGalleriesPermission::FromValue( const base::Value* value, std::string* error, std::vector<std::string>* unhandled_permissions) { size_t unhandled_permissions_count = 0; if (unhandled_permissions) unhandled_permissions_count = unhandled_permissions->size(); bool parsed_ok = SetDisjunctionPermission<MediaGalleriesPermissionData, MediaGalleriesPermission>::FromValue( value, error, unhandled_permissions); if (unhandled_permissions) { for (size_t i = unhandled_permissions_count; i < unhandled_permissions->size(); i++) { (*unhandled_permissions)[i] = "{\"mediaGalleries\": [" + (*unhandled_permissions)[i] + "]}"; } } if (!parsed_ok) return false; bool has_read = false; bool has_copy_to = false; bool has_delete = false; for (std::set<MediaGalleriesPermissionData>::const_iterator it = data_set_.begin(); it != data_set_.end(); ++it) { if (it->permission() == kAllAutoDetectedPermission || it->permission() == kScanPermission) { continue; } if (it->permission() == kReadPermission) { has_read = true; continue; } if (it->permission() == kCopyToPermission) { has_copy_to = true; continue; } if (it->permission() == kDeletePermission) { has_delete = true; continue; } // No other permissions, so reaching this means // MediaGalleriesPermissionData is probably out of sync in some way. // Fail so developers notice this. NOTREACHED(); return false; } return IsValidPermissionSet(has_read, has_copy_to, has_delete, error); } PermissionMessages MediaGalleriesPermission::GetMessages() const { DCHECK(HasMessages()); PermissionMessages result; bool has_all_auto_detected = false; bool has_read = false; bool has_copy_to = false; bool has_delete = false; for (std::set<MediaGalleriesPermissionData>::const_iterator it = data_set_.begin(); it != data_set_.end(); ++it) { if (it->permission() == kAllAutoDetectedPermission) has_all_auto_detected = true; else if (it->permission() == kReadPermission) has_read = true; else if (it->permission() == kCopyToPermission) has_copy_to = true; else if (it->permission() == kDeletePermission) has_delete = true; } if (!IsValidPermissionSet(has_read, has_copy_to, has_delete, NULL)) { NOTREACHED(); return result; } // If |has_all_auto_detected| is false, then Chrome will prompt the user at // runtime when the extension call the getMediaGalleries API. if (!has_all_auto_detected) return result; // No access permission case. if (!has_read) return result; // Separate PermissionMessage IDs for read, copyTo, and delete. Otherwise an // extension can silently gain new access capabilities. result.push_back(PermissionMessage( PermissionMessage::kMediaGalleriesAllGalleriesRead, l10n_util::GetStringUTF16( IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ))); // For copyTo and delete, the proper combined permission message will be // derived in ChromePermissionMessageProvider::GetWarningMessages(), such // that the user get 1 entry for all media galleries access permissions, // rather than several separate entries. if (has_copy_to) { result.push_back(PermissionMessage( PermissionMessage::kMediaGalleriesAllGalleriesCopyTo, base::string16())); } if (has_delete) { result.push_back(PermissionMessage( PermissionMessage::kMediaGalleriesAllGalleriesDelete, base::string16())); } return result; } } // namespace extensions