OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/extensions/file_manager/file_handler_util.h" | 5 #include "chrome/browser/chromeos/extensions/file_manager/file_handler_util.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/i18n/case_conversion.h" | 9 #include "base/i18n/case_conversion.h" |
10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
58 const char kTaskDrive[] = "drive"; | 58 const char kTaskDrive[] = "drive"; |
59 const char kTaskApp[] = "app"; | 59 const char kTaskApp[] = "app"; |
60 | 60 |
61 namespace { | 61 namespace { |
62 | 62 |
63 // Legacy Drive task extension prefix, used by CrackTaskID. | 63 // Legacy Drive task extension prefix, used by CrackTaskID. |
64 const char kDriveTaskExtensionPrefix[] = "drive-app:"; | 64 const char kDriveTaskExtensionPrefix[] = "drive-app:"; |
65 const size_t kDriveTaskExtensionPrefixLength = | 65 const size_t kDriveTaskExtensionPrefixLength = |
66 arraysize(kDriveTaskExtensionPrefix) - 1; | 66 arraysize(kDriveTaskExtensionPrefix) - 1; |
67 | 67 |
68 typedef std::set<const FileBrowserHandler*> FileBrowserHandlerSet; | |
69 | |
70 const int kReadWriteFilePermissions = base::PLATFORM_FILE_OPEN | | 68 const int kReadWriteFilePermissions = base::PLATFORM_FILE_OPEN | |
71 base::PLATFORM_FILE_CREATE | | 69 base::PLATFORM_FILE_CREATE | |
72 base::PLATFORM_FILE_OPEN_ALWAYS | | 70 base::PLATFORM_FILE_OPEN_ALWAYS | |
73 base::PLATFORM_FILE_CREATE_ALWAYS | | 71 base::PLATFORM_FILE_CREATE_ALWAYS | |
74 base::PLATFORM_FILE_OPEN_TRUNCATED | | 72 base::PLATFORM_FILE_OPEN_TRUNCATED | |
75 base::PLATFORM_FILE_READ | | 73 base::PLATFORM_FILE_READ | |
76 base::PLATFORM_FILE_WRITE | | 74 base::PLATFORM_FILE_WRITE | |
77 base::PLATFORM_FILE_EXCLUSIVE_READ | | 75 base::PLATFORM_FILE_EXCLUSIVE_READ | |
78 base::PLATFORM_FILE_EXCLUSIVE_WRITE | | 76 base::PLATFORM_FILE_EXCLUSIVE_WRITE | |
79 base::PLATFORM_FILE_ASYNC | | 77 base::PLATFORM_FILE_ASYNC | |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 std::string EscapedUtf8ToLower(const std::string& str) { | 151 std::string EscapedUtf8ToLower(const std::string& str) { |
154 string16 utf16 = UTF8ToUTF16( | 152 string16 utf16 = UTF8ToUTF16( |
155 net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL)); | 153 net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL)); |
156 return net::EscapeUrlEncodedData( | 154 return net::EscapeUrlEncodedData( |
157 UTF16ToUTF8(base::i18n::ToLower(utf16)), | 155 UTF16ToUTF8(base::i18n::ToLower(utf16)), |
158 false /* do not replace space with plus */); | 156 false /* do not replace space with plus */); |
159 } | 157 } |
160 | 158 |
161 bool GetFileBrowserHandlers(Profile* profile, | 159 bool GetFileBrowserHandlers(Profile* profile, |
162 const GURL& selected_file_url, | 160 const GURL& selected_file_url, |
163 FileBrowserHandlerSet* results) { | 161 FileBrowserHandlerList* results) { |
164 ExtensionService* service = | 162 ExtensionService* service = |
165 extensions::ExtensionSystem::Get(profile)->extension_service(); | 163 extensions::ExtensionSystem::Get(profile)->extension_service(); |
166 if (!service) | 164 if (!service) |
167 return false; // In unit-tests, we may not have an ExtensionService. | 165 return false; // In unit-tests, we may not have an ExtensionService. |
168 | 166 |
169 // We need case-insensitive matching, and pattern in the handler is already | 167 // We need case-insensitive matching, and pattern in the handler is already |
170 // in lower case. | 168 // in lower case. |
171 const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec())); | 169 const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec())); |
172 | 170 |
173 for (ExtensionSet::const_iterator iter = service->extensions()->begin(); | 171 for (ExtensionSet::const_iterator iter = service->extensions()->begin(); |
174 iter != service->extensions()->end(); | 172 iter != service->extensions()->end(); |
175 ++iter) { | 173 ++iter) { |
176 const Extension* extension = *iter; | 174 const Extension* extension = *iter; |
177 if (profile->IsOffTheRecord() && | 175 if (profile->IsOffTheRecord() && |
178 !service->IsIncognitoEnabled(extension->id())) | 176 !service->IsIncognitoEnabled(extension->id())) |
179 continue; | 177 continue; |
180 | 178 |
181 FileBrowserHandler::List* handler_list = | 179 FileBrowserHandler::List* handler_list = |
182 FileBrowserHandler::GetHandlers(extension); | 180 FileBrowserHandler::GetHandlers(extension); |
183 if (!handler_list) | 181 if (!handler_list) |
184 continue; | 182 continue; |
185 for (FileBrowserHandler::List::const_iterator action_iter = | 183 for (FileBrowserHandler::List::const_iterator action_iter = |
186 handler_list->begin(); | 184 handler_list->begin(); |
187 action_iter != handler_list->end(); | 185 action_iter != handler_list->end(); |
188 ++action_iter) { | 186 ++action_iter) { |
189 const FileBrowserHandler* action = action_iter->get(); | 187 const FileBrowserHandler* action = action_iter->get(); |
190 if (!action->MatchesURL(lowercase_url)) | 188 if (!action->MatchesURL(lowercase_url)) |
191 continue; | 189 continue; |
192 | 190 |
193 results->insert(action_iter->get()); | 191 results->push_back(action_iter->get()); |
194 } | 192 } |
195 } | 193 } |
196 return true; | 194 return true; |
197 } | 195 } |
198 | 196 |
199 } // namespace | 197 } // namespace |
200 | 198 |
201 void UpdateDefaultTask(Profile* profile, | 199 void UpdateDefaultTask(Profile* profile, |
202 const std::string& task_id, | 200 const std::string& task_id, |
203 const std::set<std::string>& suffixes, | 201 const std::set<std::string>& suffixes, |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 *task_type == kTaskApp); | 321 *task_type == kTaskApp); |
324 } | 322 } |
325 | 323 |
326 if (action_id) | 324 if (action_id) |
327 *action_id = result[2]; | 325 *action_id = result[2]; |
328 | 326 |
329 return true; | 327 return true; |
330 } | 328 } |
331 | 329 |
332 // Find a specific handler in the handler list. | 330 // Find a specific handler in the handler list. |
333 FileBrowserHandlerSet::iterator FindHandler( | 331 FileBrowserHandlerList::iterator FindHandler( |
334 FileBrowserHandlerSet* handler_set, | 332 FileBrowserHandlerList* handler_list, |
335 const std::string& extension_id, | 333 const std::string& extension_id, |
336 const std::string& id) { | 334 const std::string& id) { |
337 FileBrowserHandlerSet::iterator iter = handler_set->begin(); | 335 FileBrowserHandlerList::iterator iter = handler_list->begin(); |
338 while (iter != handler_set->end() && | 336 while (iter != handler_list->end() && |
339 !((*iter)->extension_id() == extension_id && | 337 !((*iter)->extension_id() == extension_id && |
340 (*iter)->id() == id)) { | 338 (*iter)->id() == id)) { |
341 iter++; | 339 iter++; |
342 } | 340 } |
343 return iter; | 341 return iter; |
344 } | 342 } |
345 | 343 |
346 // Given the list of selected files, returns array of file action tasks | 344 // Given the list of selected files, returns array of file action tasks |
347 // that are shared between them. | 345 // that are shared between them. |
348 void FindDefaultTasks(Profile* profile, | 346 void FindDefaultTasks(Profile* profile, |
349 const std::vector<base::FilePath>& files_list, | 347 const std::vector<base::FilePath>& files_list, |
350 const FileBrowserHandlerSet& common_tasks, | 348 const FileBrowserHandlerList& common_tasks, |
351 FileBrowserHandlerSet* default_tasks) { | 349 FileBrowserHandlerList* default_tasks) { |
352 DCHECK(default_tasks); | 350 DCHECK(default_tasks); |
353 default_tasks->clear(); | 351 default_tasks->clear(); |
354 | 352 |
355 std::set<std::string> default_ids; | 353 std::set<std::string> default_ids; |
356 for (std::vector<base::FilePath>::const_iterator it = files_list.begin(); | 354 for (std::vector<base::FilePath>::const_iterator it = files_list.begin(); |
357 it != files_list.end(); ++it) { | 355 it != files_list.end(); ++it) { |
358 std::string task_id = file_handler_util::GetDefaultTaskIdFromPrefs( | 356 std::string task_id = file_handler_util::GetDefaultTaskIdFromPrefs( |
359 profile, "", it->Extension()); | 357 profile, "", it->Extension()); |
360 if (!task_id.empty()) | 358 if (!task_id.empty()) |
361 default_ids.insert(task_id); | 359 default_ids.insert(task_id); |
362 } | 360 } |
363 | 361 |
364 const FileBrowserHandler* builtin_task = NULL; | 362 const FileBrowserHandler* builtin_task = NULL; |
365 // Convert the default task IDs collected above to one of the handler pointers | 363 // Convert the default task IDs collected above to one of the handler pointers |
366 // from common_tasks. | 364 // from common_tasks. |
367 for (FileBrowserHandlerSet::const_iterator task_iter = common_tasks.begin(); | 365 for (FileBrowserHandlerList::const_iterator task_iter = common_tasks.begin(); |
368 task_iter != common_tasks.end(); ++task_iter) { | 366 task_iter != common_tasks.end(); ++task_iter) { |
369 std::string task_id = MakeTaskID((*task_iter)->extension_id(), kTaskFile, | 367 std::string task_id = MakeTaskID((*task_iter)->extension_id(), kTaskFile, |
370 (*task_iter)->id()); | 368 (*task_iter)->id()); |
371 std::set<std::string>::iterator default_iter = default_ids.find(task_id); | 369 std::set<std::string>::iterator default_iter = default_ids.find(task_id); |
372 if (default_iter != default_ids.end()) { | 370 if (default_iter != default_ids.end()) { |
373 default_tasks->insert(*task_iter); | 371 default_tasks->push_back(*task_iter); |
374 continue; | 372 continue; |
375 } | 373 } |
376 | 374 |
377 // If it's a built in task, remember it. If there are no default tasks among | 375 // If it's a built in task, remember it. If there are no default tasks among |
378 // common tasks, builtin task will be used as a fallback. | 376 // common tasks, builtin task will be used as a fallback. |
379 // Note that builtin tasks are not overlapping, so there can be at most one | 377 // Note that builtin tasks are not overlapping, so there can be at most one |
380 // builtin tasks for each set of files. | 378 // builtin tasks for each set of files. |
381 if (IsBuiltinTask(*task_iter)) | 379 if (IsBuiltinTask(*task_iter)) |
382 builtin_task = *task_iter; | 380 builtin_task = *task_iter; |
383 } | 381 } |
384 | 382 |
385 // If there are no default tasks found, use builtin task (if found) as a | 383 // If there are no default tasks found, use builtin task (if found) as a |
386 // default. | 384 // default. |
387 if (builtin_task && default_tasks->empty()) | 385 if (builtin_task && default_tasks->empty()) |
388 default_tasks->insert(builtin_task); | 386 default_tasks->push_back(builtin_task); |
389 } | 387 } |
390 | 388 |
391 // Given the list of selected files, returns array of context menu tasks | 389 // Given the list of selected files, returns array of context menu tasks |
392 // that are shared | 390 // that are shared |
393 bool FindCommonTasks(Profile* profile, | 391 bool FindCommonTasks(Profile* profile, |
394 const std::vector<GURL>& files_list, | 392 const std::vector<GURL>& files_list, |
395 FileBrowserHandlerSet* common_tasks) { | 393 FileBrowserHandlerList* common_tasks) { |
396 DCHECK(common_tasks); | 394 DCHECK(common_tasks); |
397 common_tasks->clear(); | 395 common_tasks->clear(); |
398 | 396 |
399 FileBrowserHandlerSet common_task_set; | 397 FileBrowserHandlerList common_task_list; |
400 std::set<std::string> default_task_ids; | 398 std::set<std::string> default_task_ids; |
401 for (std::vector<GURL>::const_iterator it = files_list.begin(); | 399 for (std::vector<GURL>::const_iterator it = files_list.begin(); |
402 it != files_list.end(); ++it) { | 400 it != files_list.end(); ++it) { |
403 FileBrowserHandlerSet file_actions; | 401 FileBrowserHandlerList file_actions; |
404 if (!GetFileBrowserHandlers(profile, *it, &file_actions)) | 402 if (!GetFileBrowserHandlers(profile, *it, &file_actions)) |
405 return false; | 403 return false; |
406 // If there is nothing to do for one file, the intersection of tasks for all | 404 // If there is nothing to do for one file, the intersection of tasks for all |
407 // files will be empty at the end, and so will the default tasks. | 405 // files will be empty at the end, and so will the default tasks. |
408 if (file_actions.empty()) | 406 if (file_actions.empty()) |
409 return true; | 407 return true; |
410 | 408 |
411 // For the very first file, just copy all the elements. | 409 // For the very first file, just copy all the elements. |
412 if (it == files_list.begin()) { | 410 if (it == files_list.begin()) { |
413 common_task_set = file_actions; | 411 common_task_list = file_actions; |
414 } else { | 412 } else { |
415 // For all additional files, find intersection between the accumulated and | 413 // For all additional files, find intersection between the accumulated and |
416 // file specific set. | 414 // file specific set. |
417 FileBrowserHandlerSet intersection; | 415 FileBrowserHandlerList intersection; |
418 std::set_intersection(common_task_set.begin(), common_task_set.end(), | 416 std::set_intersection(common_task_list.begin(), common_task_list.end(), |
419 file_actions.begin(), file_actions.end(), | 417 file_actions.begin(), file_actions.end(), |
420 std::inserter(intersection, | 418 std::inserter(intersection, |
kinaba
2013/05/24 07:34:13
std::back_inserter(intersection)
mtomasz
2013/05/24 07:49:45
Done.
| |
421 intersection.begin())); | 419 intersection.begin())); |
422 common_task_set = intersection; | 420 common_task_list = intersection; |
423 if (common_task_set.empty()) | 421 if (common_task_list.empty()) |
424 return true; | 422 return true; |
425 } | 423 } |
426 } | 424 } |
427 | 425 |
428 FileBrowserHandlerSet::iterator watch_iter = FindHandler( | 426 FileBrowserHandlerList::iterator watch_iter = FindHandler( |
429 &common_task_set, kFileBrowserDomain, kFileBrowserWatchTaskId); | 427 &common_task_list, kFileBrowserDomain, kFileBrowserWatchTaskId); |
430 FileBrowserHandlerSet::iterator gallery_iter = FindHandler( | 428 FileBrowserHandlerList::iterator gallery_iter = FindHandler( |
431 &common_task_set, kFileBrowserDomain, kFileBrowserGalleryTaskId); | 429 &common_task_list, kFileBrowserDomain, kFileBrowserGalleryTaskId); |
432 if (watch_iter != common_task_set.end() && | 430 if (watch_iter != common_task_list.end() && |
433 gallery_iter != common_task_set.end()) { | 431 gallery_iter != common_task_list.end()) { |
434 // Both "watch" and "gallery" actions are applicable which means that the | 432 // Both "watch" and "gallery" actions are applicable which means that the |
435 // selection is all videos. Showing them both is confusing, so we only keep | 433 // selection is all videos. Showing them both is confusing, so we only keep |
436 // the one that makes more sense ("watch" for single selection, "gallery" | 434 // the one that makes more sense ("watch" for single selection, "gallery" |
437 // for multiple selection). | 435 // for multiple selection). |
438 if (files_list.size() == 1) | 436 if (files_list.size() == 1) |
439 common_task_set.erase(gallery_iter); | 437 common_task_list.erase(gallery_iter); |
440 else | 438 else |
441 common_task_set.erase(watch_iter); | 439 common_task_list.erase(watch_iter); |
442 } | 440 } |
443 | 441 |
444 common_tasks->swap(common_task_set); | 442 common_tasks->swap(common_task_list); |
445 return true; | 443 return true; |
446 } | 444 } |
447 | 445 |
448 bool GetTaskForURLAndPath(Profile* profile, | 446 bool GetTaskForURLAndPath(Profile* profile, |
449 const GURL& url, | 447 const GURL& url, |
450 const base::FilePath& file_path, | 448 const base::FilePath& file_path, |
451 const FileBrowserHandler** handler) { | 449 const FileBrowserHandler** handler) { |
452 std::vector<GURL> file_urls; | 450 std::vector<GURL> file_urls; |
453 file_urls.push_back(url); | 451 file_urls.push_back(url); |
454 | 452 |
455 FileBrowserHandlerSet default_tasks; | 453 FileBrowserHandlerList default_tasks; |
456 FileBrowserHandlerSet common_tasks; | 454 FileBrowserHandlerList common_tasks; |
457 if (!FindCommonTasks(profile, file_urls, &common_tasks)) | 455 if (!FindCommonTasks(profile, file_urls, &common_tasks)) |
458 return false; | 456 return false; |
459 | 457 |
460 if (common_tasks.empty()) | 458 if (common_tasks.empty()) |
461 return false; | 459 return false; |
462 | 460 |
463 std::vector<base::FilePath> file_paths; | 461 std::vector<base::FilePath> file_paths; |
464 file_paths.push_back(file_path); | 462 file_paths.push_back(file_path); |
465 | 463 |
466 FindDefaultTasks(profile, file_paths, common_tasks, &default_tasks); | 464 FindDefaultTasks(profile, file_paths, common_tasks, &default_tasks); |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
988 extensions::LaunchPlatformAppWithFileHandler(profile(), GetExtension(), | 986 extensions::LaunchPlatformAppWithFileHandler(profile(), GetExtension(), |
989 action_id_, file_urls[i].path()); | 987 action_id_, file_urls[i].path()); |
990 } | 988 } |
991 | 989 |
992 if (!done.is_null()) | 990 if (!done.is_null()) |
993 done.Run(true); | 991 done.Run(true); |
994 return true; | 992 return true; |
995 } | 993 } |
996 | 994 |
997 } // namespace file_handler_util | 995 } // namespace file_handler_util |
OLD | NEW |