Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / common / extensions / api / file_browser_handlers / file_browser_handler.cc
blob284d3b81b9644ee9c502a839184819098c975a55
1 // Copyright 2013 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.
5 #include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/common/extensions/extension_constants.h"
13 #include "content/public/common/url_constants.h"
14 #include "extensions/common/error_utils.h"
15 #include "extensions/common/manifest.h"
16 #include "extensions/common/manifest_constants.h"
17 #include "extensions/common/url_pattern.h"
19 namespace keys = extensions::manifest_keys;
20 namespace errors = extensions::manifest_errors;
22 namespace {
24 const char kReadAccessString[] = "read";
25 const char kReadWriteAccessString[] = "read-write";
26 const char kCreateAccessString[] = "create";
28 unsigned int kPermissionsNotDefined = 0;
29 unsigned int kReadPermission = 1;
30 unsigned int kWritePermission = 1 << 1;
31 unsigned int kCreatePermission = 1 << 2;
32 unsigned int kInvalidPermission = 1 << 3;
34 unsigned int GetAccessPermissionFlagFromString(const std::string& access_str) {
35 if (access_str == kReadAccessString)
36 return kReadPermission;
37 if (access_str == kReadWriteAccessString)
38 return kReadPermission | kWritePermission;
39 if (access_str == kCreateAccessString)
40 return kCreatePermission;
41 return kInvalidPermission;
44 // Stored on the Extension.
45 struct FileBrowserHandlerInfo : public extensions::Extension::ManifestData {
46 FileBrowserHandler::List file_browser_handlers;
48 FileBrowserHandlerInfo();
49 virtual ~FileBrowserHandlerInfo();
52 FileBrowserHandlerInfo::FileBrowserHandlerInfo() {
55 FileBrowserHandlerInfo::~FileBrowserHandlerInfo() {
58 } // namespace
60 FileBrowserHandler::FileBrowserHandler()
61 : file_access_permission_flags_(kPermissionsNotDefined) {
64 FileBrowserHandler::~FileBrowserHandler() {
67 void FileBrowserHandler::AddPattern(const URLPattern& pattern) {
68 url_set_.AddPattern(pattern);
71 void FileBrowserHandler::ClearPatterns() {
72 url_set_.ClearPatterns();
75 bool FileBrowserHandler::MatchesURL(const GURL& url) const {
76 return url_set_.MatchesURL(url);
79 bool FileBrowserHandler::AddFileAccessPermission(
80 const std::string& access) {
81 file_access_permission_flags_ |= GetAccessPermissionFlagFromString(access);
82 return (file_access_permission_flags_ & kInvalidPermission) != 0U;
85 bool FileBrowserHandler::ValidateFileAccessPermissions() {
86 bool is_invalid = (file_access_permission_flags_ & kInvalidPermission) != 0U;
87 bool can_create = (file_access_permission_flags_ & kCreatePermission) != 0U;
88 bool can_read_or_write = (file_access_permission_flags_ &
89 (kReadPermission | kWritePermission)) != 0U;
90 if (is_invalid || (can_create && can_read_or_write)) {
91 file_access_permission_flags_ = kInvalidPermission;
92 return false;
95 if (file_access_permission_flags_ == kPermissionsNotDefined)
96 file_access_permission_flags_ = kReadPermission | kWritePermission;
97 return true;
100 bool FileBrowserHandler::CanRead() const {
101 DCHECK(!(file_access_permission_flags_ & kInvalidPermission));
102 return (file_access_permission_flags_ & kReadPermission) != 0;
105 bool FileBrowserHandler::CanWrite() const {
106 DCHECK(!(file_access_permission_flags_ & kInvalidPermission));
107 return (file_access_permission_flags_ & kWritePermission) != 0;
110 bool FileBrowserHandler::HasCreateAccessPermission() const {
111 DCHECK(!(file_access_permission_flags_ & kInvalidPermission));
112 return (file_access_permission_flags_ & kCreatePermission) != 0;
115 // static
116 FileBrowserHandler::List*
117 FileBrowserHandler::GetHandlers(const extensions::Extension* extension) {
118 FileBrowserHandlerInfo* info = static_cast<FileBrowserHandlerInfo*>(
119 extension->GetManifestData(keys::kFileBrowserHandlers));
120 if (info)
121 return &info->file_browser_handlers;
122 return NULL;
125 FileBrowserHandlerParser::FileBrowserHandlerParser() {
128 FileBrowserHandlerParser::~FileBrowserHandlerParser() {
131 namespace {
133 FileBrowserHandler* LoadFileBrowserHandler(
134 const std::string& extension_id,
135 const base::DictionaryValue* file_browser_handler,
136 base::string16* error) {
137 scoped_ptr<FileBrowserHandler> result(new FileBrowserHandler());
138 result->set_extension_id(extension_id);
140 std::string handler_id;
141 // Read the file action |id| (mandatory).
142 if (!file_browser_handler->HasKey(keys::kPageActionId) ||
143 !file_browser_handler->GetString(keys::kPageActionId, &handler_id)) {
144 *error = base::ASCIIToUTF16(errors::kInvalidPageActionId);
145 return NULL;
147 result->set_id(handler_id);
149 // Read the page action title from |default_title| (mandatory).
150 std::string title;
151 if (!file_browser_handler->HasKey(keys::kPageActionDefaultTitle) ||
152 !file_browser_handler->GetString(keys::kPageActionDefaultTitle, &title)) {
153 *error = base::ASCIIToUTF16(errors::kInvalidPageActionDefaultTitle);
154 return NULL;
156 result->set_title(title);
158 // Initialize access permissions (optional).
159 const base::ListValue* access_list_value = NULL;
160 if (file_browser_handler->HasKey(keys::kFileAccessList)) {
161 if (!file_browser_handler->GetList(keys::kFileAccessList,
162 &access_list_value) ||
163 access_list_value->empty()) {
164 *error = base::ASCIIToUTF16(errors::kInvalidFileAccessList);
165 return NULL;
167 for (size_t i = 0; i < access_list_value->GetSize(); ++i) {
168 std::string access;
169 if (!access_list_value->GetString(i, &access) ||
170 result->AddFileAccessPermission(access)) {
171 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
172 errors::kInvalidFileAccessValue, base::IntToString(i));
173 return NULL;
177 if (!result->ValidateFileAccessPermissions()) {
178 *error = base::ASCIIToUTF16(errors::kInvalidFileAccessList);
179 return NULL;
182 // Initialize file filters (mandatory, unless "create" access is specified,
183 // in which case is ignored). The list can be empty.
184 if (!result->HasCreateAccessPermission()) {
185 const base::ListValue* file_filters = NULL;
186 if (!file_browser_handler->HasKey(keys::kFileFilters) ||
187 !file_browser_handler->GetList(keys::kFileFilters, &file_filters)) {
188 *error = base::ASCIIToUTF16(errors::kInvalidFileFiltersList);
189 return NULL;
191 for (size_t i = 0; i < file_filters->GetSize(); ++i) {
192 std::string filter;
193 if (!file_filters->GetString(i, &filter)) {
194 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
195 errors::kInvalidFileFilterValue, base::IntToString(i));
196 return NULL;
198 StringToLowerASCII(&filter);
199 if (!StartsWithASCII(filter,
200 std::string(content::kFileSystemScheme) + ':',
201 true)) {
202 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
203 errors::kInvalidURLPatternError, filter);
204 return NULL;
206 // The user inputs filesystem:*; we don't actually implement scheme
207 // wildcards in URLPattern, so transform to what will match correctly.
208 filter.replace(0, 11, "chrome-extension://*/");
209 URLPattern pattern(URLPattern::SCHEME_EXTENSION);
210 if (pattern.Parse(filter) != URLPattern::PARSE_SUCCESS) {
211 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
212 errors::kInvalidURLPatternError, filter);
213 return NULL;
215 std::string path = pattern.path();
216 bool allowed = path == "/*" || path == "/*.*" ||
217 (path.compare(0, 3, "/*.") == 0 &&
218 path.find_first_of('*', 3) == std::string::npos);
219 if (!allowed) {
220 *error = extensions::ErrorUtils::FormatErrorMessageUTF16(
221 errors::kInvalidURLPatternError, filter);
222 return NULL;
224 result->AddPattern(pattern);
228 std::string default_icon;
229 // Read the file browser action |default_icon| (optional).
230 if (file_browser_handler->HasKey(keys::kPageActionDefaultIcon)) {
231 if (!file_browser_handler->GetString(
232 keys::kPageActionDefaultIcon, &default_icon) ||
233 default_icon.empty()) {
234 *error = base::ASCIIToUTF16(errors::kInvalidPageActionIconPath);
235 return NULL;
237 result->set_icon_path(default_icon);
240 return result.release();
243 // Loads FileBrowserHandlers from |extension_actions| into a list in |result|.
244 bool LoadFileBrowserHandlers(
245 const std::string& extension_id,
246 const base::ListValue* extension_actions,
247 FileBrowserHandler::List* result,
248 base::string16* error) {
249 for (base::ListValue::const_iterator iter = extension_actions->begin();
250 iter != extension_actions->end();
251 ++iter) {
252 if (!(*iter)->IsType(base::Value::TYPE_DICTIONARY)) {
253 *error = base::ASCIIToUTF16(errors::kInvalidFileBrowserHandler);
254 return false;
256 scoped_ptr<FileBrowserHandler> action(
257 LoadFileBrowserHandler(
258 extension_id,
259 reinterpret_cast<base::DictionaryValue*>(*iter), error));
260 if (!action.get())
261 return false; // Failed to parse file browser action definition.
262 result->push_back(linked_ptr<FileBrowserHandler>(action.release()));
264 return true;
267 } // namespace
269 bool FileBrowserHandlerParser::Parse(extensions::Extension* extension,
270 base::string16* error) {
271 const base::ListValue* file_browser_handlers_value = NULL;
272 if (!extension->manifest()->GetList(keys::kFileBrowserHandlers,
273 &file_browser_handlers_value)) {
274 *error = base::ASCIIToUTF16(errors::kInvalidFileBrowserHandler);
275 return false;
277 scoped_ptr<FileBrowserHandlerInfo> info(new FileBrowserHandlerInfo);
278 if (!LoadFileBrowserHandlers(extension->id(),
279 file_browser_handlers_value,
280 &info->file_browser_handlers,
281 error)) {
282 return false; // Failed to parse file browser actions definition.
285 extension->SetManifestData(keys::kFileBrowserHandlers, info.release());
286 return true;
289 const std::vector<std::string> FileBrowserHandlerParser::Keys() const {
290 return SingleKey(keys::kFileBrowserHandlers);