• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
IsValidPermissionSet(bool has_read,bool has_copy_to,bool has_delete,std::string * error)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 
MediaGalleriesPermission(const APIPermissionInfo * info)50 MediaGalleriesPermission::MediaGalleriesPermission(
51     const APIPermissionInfo* info)
52   : SetDisjunctionPermission<MediaGalleriesPermissionData,
53                              MediaGalleriesPermission>(info) {
54 }
55 
~MediaGalleriesPermission()56 MediaGalleriesPermission::~MediaGalleriesPermission() {
57 }
58 
FromValue(const base::Value * value,std::string * error,std::vector<std::string> * unhandled_permissions)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 
GetMessages() const113 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