Chromium Code Reviews| 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 13 matching lines...) Expand all Loading... | |
| 93 extensions::ExtensionSystem::Get(profile)->process_manager(); | 91 extensions::ExtensionSystem::Get(profile)->process_manager(); |
| 94 | 92 |
| 95 SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url); | 93 SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url); |
| 96 if (!site_instance || !site_instance->HasProcess()) | 94 if (!site_instance || !site_instance->HasProcess()) |
| 97 return -1; | 95 return -1; |
| 98 content::RenderProcessHost* process = site_instance->GetProcess(); | 96 content::RenderProcessHost* process = site_instance->GetProcess(); |
| 99 | 97 |
| 100 return process->GetID(); | 98 return process->GetID(); |
| 101 } | 99 } |
| 102 | 100 |
| 103 bool IsBuiltinTask(const FileBrowserHandler* task) { | 101 bool IsFallbackTask(const FileBrowserHandler* task) { |
|
hashimoto
2013/05/24 11:15:51
Please add a function comment.
It's not clear from
mtomasz
2013/05/27 01:20:20
I didn't change anything in this class but set ->
| |
| 104 return (task->extension_id() == kFileBrowserDomain || | 102 return (task->extension_id() == kFileBrowserDomain || |
| 105 task->extension_id() == | 103 task->extension_id() == |
| 106 extension_misc::kQuickOfficeComponentExtensionId || | 104 extension_misc::kQuickOfficeComponentExtensionId || |
| 107 task->extension_id() == extension_misc::kQuickOfficeDevExtensionId || | 105 task->extension_id() == extension_misc::kQuickOfficeDevExtensionId || |
| 108 task->extension_id() == extension_misc::kQuickOfficeExtensionId); | 106 task->extension_id() == extension_misc::kQuickOfficeExtensionId); |
| 109 } | 107 } |
| 110 | 108 |
| 111 bool MatchesAllURLs(const FileBrowserHandler* handler) { | |
| 112 const std::set<URLPattern>& patterns = | |
| 113 handler->file_url_patterns().patterns(); | |
| 114 for (std::set<URLPattern>::const_iterator it = patterns.begin(); | |
| 115 it != patterns.end(); | |
| 116 ++it) { | |
| 117 if (it->match_all_urls()) | |
| 118 return true; | |
| 119 } | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 const FileBrowserHandler* FindFileBrowserHandler(const Extension* extension, | 109 const FileBrowserHandler* FindFileBrowserHandler(const Extension* extension, |
| 124 const std::string& action_id) { | 110 const std::string& action_id) { |
| 125 FileBrowserHandler::List* handler_list = | 111 FileBrowserHandler::List* handler_list = |
| 126 FileBrowserHandler::GetHandlers(extension); | 112 FileBrowserHandler::GetHandlers(extension); |
| 127 for (FileBrowserHandler::List::const_iterator action_iter = | 113 for (FileBrowserHandler::List::const_iterator action_iter = |
| 128 handler_list->begin(); | 114 handler_list->begin(); |
| 129 action_iter != handler_list->end(); | 115 action_iter != handler_list->end(); |
| 130 ++action_iter) { | 116 ++action_iter) { |
| 131 if (action_iter->get()->id() == action_id) | 117 if (action_iter->get()->id() == action_id) |
| 132 return action_iter->get(); | 118 return action_iter->get(); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 153 std::string EscapedUtf8ToLower(const std::string& str) { | 139 std::string EscapedUtf8ToLower(const std::string& str) { |
| 154 string16 utf16 = UTF8ToUTF16( | 140 string16 utf16 = UTF8ToUTF16( |
| 155 net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL)); | 141 net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL)); |
| 156 return net::EscapeUrlEncodedData( | 142 return net::EscapeUrlEncodedData( |
| 157 UTF16ToUTF8(base::i18n::ToLower(utf16)), | 143 UTF16ToUTF8(base::i18n::ToLower(utf16)), |
| 158 false /* do not replace space with plus */); | 144 false /* do not replace space with plus */); |
| 159 } | 145 } |
| 160 | 146 |
| 161 bool GetFileBrowserHandlers(Profile* profile, | 147 bool GetFileBrowserHandlers(Profile* profile, |
| 162 const GURL& selected_file_url, | 148 const GURL& selected_file_url, |
| 163 FileBrowserHandlerSet* results) { | 149 FileBrowserHandlerList* results) { |
| 164 ExtensionService* service = | 150 ExtensionService* service = |
| 165 extensions::ExtensionSystem::Get(profile)->extension_service(); | 151 extensions::ExtensionSystem::Get(profile)->extension_service(); |
| 166 if (!service) | 152 if (!service) |
| 167 return false; // In unit-tests, we may not have an ExtensionService. | 153 return false; // In unit-tests, we may not have an ExtensionService. |
| 168 | 154 |
| 169 // We need case-insensitive matching, and pattern in the handler is already | 155 // We need case-insensitive matching, and pattern in the handler is already |
| 170 // in lower case. | 156 // in lower case. |
| 171 const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec())); | 157 const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec())); |
| 172 | 158 |
| 173 for (ExtensionSet::const_iterator iter = service->extensions()->begin(); | 159 for (ExtensionSet::const_iterator iter = service->extensions()->begin(); |
| 174 iter != service->extensions()->end(); | 160 iter != service->extensions()->end(); |
| 175 ++iter) { | 161 ++iter) { |
| 176 const Extension* extension = *iter; | 162 const Extension* extension = *iter; |
| 177 if (profile->IsOffTheRecord() && | 163 if (profile->IsOffTheRecord() && |
| 178 !service->IsIncognitoEnabled(extension->id())) | 164 !service->IsIncognitoEnabled(extension->id())) |
| 179 continue; | 165 continue; |
| 180 | 166 |
| 181 FileBrowserHandler::List* handler_list = | 167 FileBrowserHandler::List* handler_list = |
| 182 FileBrowserHandler::GetHandlers(extension); | 168 FileBrowserHandler::GetHandlers(extension); |
| 183 if (!handler_list) | 169 if (!handler_list) |
| 184 continue; | 170 continue; |
| 185 for (FileBrowserHandler::List::const_iterator action_iter = | 171 for (FileBrowserHandler::List::const_iterator action_iter = |
| 186 handler_list->begin(); | 172 handler_list->begin(); |
| 187 action_iter != handler_list->end(); | 173 action_iter != handler_list->end(); |
| 188 ++action_iter) { | 174 ++action_iter) { |
| 189 const FileBrowserHandler* action = action_iter->get(); | 175 const FileBrowserHandler* action = action_iter->get(); |
| 190 if (!action->MatchesURL(lowercase_url)) | 176 if (!action->MatchesURL(lowercase_url)) |
| 191 continue; | 177 continue; |
| 192 | 178 |
| 193 results->insert(action_iter->get()); | 179 results->push_back(action_iter->get()); |
| 194 } | 180 } |
| 195 } | 181 } |
| 196 return true; | 182 return true; |
| 197 } | 183 } |
| 198 | 184 |
| 199 } // namespace | 185 } // namespace |
| 200 | 186 |
| 201 void UpdateDefaultTask(Profile* profile, | 187 void UpdateDefaultTask(Profile* profile, |
| 202 const std::string& task_id, | 188 const std::string& task_id, |
| 203 const std::set<std::string>& suffixes, | 189 const std::set<std::string>& suffixes, |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 *task_type == kTaskApp); | 309 *task_type == kTaskApp); |
| 324 } | 310 } |
| 325 | 311 |
| 326 if (action_id) | 312 if (action_id) |
| 327 *action_id = result[2]; | 313 *action_id = result[2]; |
| 328 | 314 |
| 329 return true; | 315 return true; |
| 330 } | 316 } |
| 331 | 317 |
| 332 // Find a specific handler in the handler list. | 318 // Find a specific handler in the handler list. |
| 333 FileBrowserHandlerSet::iterator FindHandler( | 319 FileBrowserHandlerList::iterator FindHandler( |
| 334 FileBrowserHandlerSet* handler_set, | 320 FileBrowserHandlerList* handler_list, |
| 335 const std::string& extension_id, | 321 const std::string& extension_id, |
| 336 const std::string& id) { | 322 const std::string& id) { |
| 337 FileBrowserHandlerSet::iterator iter = handler_set->begin(); | 323 FileBrowserHandlerList::iterator iter = handler_list->begin(); |
| 338 while (iter != handler_set->end() && | 324 while (iter != handler_list->end() && |
| 339 !((*iter)->extension_id() == extension_id && | 325 !((*iter)->extension_id() == extension_id && |
| 340 (*iter)->id() == id)) { | 326 (*iter)->id() == id)) { |
| 341 iter++; | 327 iter++; |
| 342 } | 328 } |
| 343 return iter; | 329 return iter; |
| 344 } | 330 } |
| 345 | 331 |
| 346 // Given the list of selected files, returns array of file action tasks | 332 // Given the list of selected files, returns array of file action tasks |
| 347 // that are shared between them. | 333 // that are shared between them. |
| 348 void FindDefaultTasks(Profile* profile, | 334 void FindDefaultTasks(Profile* profile, |
| 349 const std::vector<base::FilePath>& files_list, | 335 const std::vector<base::FilePath>& files_list, |
| 350 const FileBrowserHandlerSet& common_tasks, | 336 const FileBrowserHandlerList& common_tasks, |
| 351 FileBrowserHandlerSet* default_tasks) { | 337 FileBrowserHandlerList* default_tasks) { |
| 352 DCHECK(default_tasks); | 338 DCHECK(default_tasks); |
| 353 default_tasks->clear(); | 339 default_tasks->clear(); |
| 354 | 340 |
| 355 std::set<std::string> default_ids; | 341 std::set<std::string> default_ids; |
| 356 for (std::vector<base::FilePath>::const_iterator it = files_list.begin(); | 342 for (std::vector<base::FilePath>::const_iterator it = files_list.begin(); |
| 357 it != files_list.end(); ++it) { | 343 it != files_list.end(); ++it) { |
| 358 std::string task_id = file_handler_util::GetDefaultTaskIdFromPrefs( | 344 std::string task_id = file_handler_util::GetDefaultTaskIdFromPrefs( |
| 359 profile, "", it->Extension()); | 345 profile, "", it->Extension()); |
| 360 if (!task_id.empty()) | 346 if (!task_id.empty()) |
| 361 default_ids.insert(task_id); | 347 default_ids.insert(task_id); |
| 362 } | 348 } |
| 363 | 349 |
| 364 const FileBrowserHandler* builtin_task = NULL; | 350 const FileBrowserHandler* fallback_task = NULL; |
| 365 // Convert the default task IDs collected above to one of the handler pointers | 351 // Convert the default task IDs collected above to one of the handler pointers |
| 366 // from common_tasks. | 352 // from common_tasks. |
| 367 for (FileBrowserHandlerSet::const_iterator task_iter = common_tasks.begin(); | 353 for (FileBrowserHandlerList::const_iterator task_iter = common_tasks.begin(); |
| 368 task_iter != common_tasks.end(); ++task_iter) { | 354 task_iter != common_tasks.end(); ++task_iter) { |
| 369 std::string task_id = MakeTaskID((*task_iter)->extension_id(), kTaskFile, | 355 std::string task_id = MakeTaskID((*task_iter)->extension_id(), kTaskFile, |
| 370 (*task_iter)->id()); | 356 (*task_iter)->id()); |
| 371 std::set<std::string>::iterator default_iter = default_ids.find(task_id); | 357 std::set<std::string>::iterator default_iter = default_ids.find(task_id); |
| 372 if (default_iter != default_ids.end()) { | 358 if (default_iter != default_ids.end()) { |
| 373 default_tasks->insert(*task_iter); | 359 default_tasks->push_back(*task_iter); |
| 374 continue; | 360 continue; |
| 375 } | 361 } |
| 376 | 362 |
| 377 // If it's a built in task, remember it. If there are no default tasks among | 363 // Remember the first fallback task. |
| 378 // common tasks, builtin task will be used as a fallback. | 364 if (!fallback_task && IsFallbackTask(*task_iter)) |
| 379 // Note that builtin tasks are not overlapping, so there can be at most one | 365 fallback_task = *task_iter; |
| 380 // builtin tasks for each set of files. | |
| 381 if (IsBuiltinTask(*task_iter)) | |
| 382 builtin_task = *task_iter; | |
| 383 } | 366 } |
| 384 | 367 |
| 385 // If there are no default tasks found, use builtin task (if found) as a | 368 // If there are no default tasks found, use fallback as default. |
| 386 // default. | 369 if (fallback_task && default_tasks->empty()) |
| 387 if (builtin_task && default_tasks->empty()) | 370 default_tasks->push_back(fallback_task); |
| 388 default_tasks->insert(builtin_task); | |
| 389 } | 371 } |
| 390 | 372 |
| 391 // Given the list of selected files, returns array of context menu tasks | 373 // Given the list of selected files, returns array of context menu tasks |
| 392 // that are shared | 374 // that are shared |
| 393 bool FindCommonTasks(Profile* profile, | 375 bool FindCommonTasks(Profile* profile, |
| 394 const std::vector<GURL>& files_list, | 376 const std::vector<GURL>& files_list, |
| 395 FileBrowserHandlerSet* common_tasks) { | 377 FileBrowserHandlerList* common_tasks) { |
| 396 DCHECK(common_tasks); | 378 DCHECK(common_tasks); |
| 397 common_tasks->clear(); | 379 common_tasks->clear(); |
| 398 | 380 |
| 399 FileBrowserHandlerSet common_task_set; | 381 FileBrowserHandlerList common_task_list; |
| 400 std::set<std::string> default_task_ids; | 382 std::set<std::string> default_task_ids; |
| 401 for (std::vector<GURL>::const_iterator it = files_list.begin(); | 383 for (std::vector<GURL>::const_iterator it = files_list.begin(); |
| 402 it != files_list.end(); ++it) { | 384 it != files_list.end(); ++it) { |
| 403 FileBrowserHandlerSet file_actions; | 385 FileBrowserHandlerList file_actions; |
| 404 if (!GetFileBrowserHandlers(profile, *it, &file_actions)) | 386 if (!GetFileBrowserHandlers(profile, *it, &file_actions)) |
| 405 return false; | 387 return false; |
| 406 // If there is nothing to do for one file, the intersection of tasks for all | 388 // 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. | 389 // files will be empty at the end, and so will the default tasks. |
| 408 if (file_actions.empty()) | 390 if (file_actions.empty()) |
| 409 return true; | 391 return true; |
| 410 | 392 |
| 411 // For the very first file, just copy all the elements. | 393 // For the very first file, just copy all the elements. |
| 412 if (it == files_list.begin()) { | 394 if (it == files_list.begin()) { |
| 413 common_task_set = file_actions; | 395 common_task_list = file_actions; |
| 414 } else { | 396 } else { |
| 415 // For all additional files, find intersection between the accumulated and | 397 // For all additional files, find intersection between the accumulated and |
| 416 // file specific set. | 398 // file specific set. |
| 417 FileBrowserHandlerSet intersection; | 399 FileBrowserHandlerList intersection; |
| 418 std::set_intersection(common_task_set.begin(), common_task_set.end(), | 400 std::set_intersection(common_task_list.begin(), common_task_list.end(), |
| 419 file_actions.begin(), file_actions.end(), | 401 file_actions.begin(), file_actions.end(), |
| 420 std::inserter(intersection, | 402 std::back_inserter(intersection)); |
| 421 intersection.begin())); | 403 common_task_list = intersection; |
| 422 common_task_set = intersection; | 404 if (common_task_list.empty()) |
| 423 if (common_task_set.empty()) | |
| 424 return true; | 405 return true; |
| 425 } | 406 } |
| 426 } | 407 } |
| 427 | 408 |
| 428 FileBrowserHandlerSet::iterator watch_iter = FindHandler( | 409 FileBrowserHandlerList::iterator watch_iter = FindHandler( |
| 429 &common_task_set, kFileBrowserDomain, kFileBrowserWatchTaskId); | 410 &common_task_list, kFileBrowserDomain, kFileBrowserWatchTaskId); |
| 430 FileBrowserHandlerSet::iterator gallery_iter = FindHandler( | 411 FileBrowserHandlerList::iterator gallery_iter = FindHandler( |
| 431 &common_task_set, kFileBrowserDomain, kFileBrowserGalleryTaskId); | 412 &common_task_list, kFileBrowserDomain, kFileBrowserGalleryTaskId); |
| 432 if (watch_iter != common_task_set.end() && | 413 if (watch_iter != common_task_list.end() && |
| 433 gallery_iter != common_task_set.end()) { | 414 gallery_iter != common_task_list.end()) { |
| 434 // Both "watch" and "gallery" actions are applicable which means that the | 415 // 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 | 416 // 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" | 417 // the one that makes more sense ("watch" for single selection, "gallery" |
| 437 // for multiple selection). | 418 // for multiple selection). |
| 438 if (files_list.size() == 1) | 419 if (files_list.size() == 1) |
| 439 common_task_set.erase(gallery_iter); | 420 common_task_list.erase(gallery_iter); |
| 440 else | 421 else |
| 441 common_task_set.erase(watch_iter); | 422 common_task_list.erase(watch_iter); |
| 442 } | 423 } |
| 443 | 424 |
| 444 common_tasks->swap(common_task_set); | 425 common_tasks->swap(common_task_list); |
| 445 return true; | 426 return true; |
| 446 } | 427 } |
| 447 | 428 |
| 448 bool GetTaskForURLAndPath(Profile* profile, | 429 bool GetTaskForURLAndPath(Profile* profile, |
| 449 const GURL& url, | 430 const GURL& url, |
| 450 const base::FilePath& file_path, | 431 const base::FilePath& file_path, |
| 451 const FileBrowserHandler** handler) { | 432 const FileBrowserHandler** handler) { |
| 452 std::vector<GURL> file_urls; | 433 std::vector<GURL> file_urls; |
| 453 file_urls.push_back(url); | 434 file_urls.push_back(url); |
| 454 | 435 |
| 455 FileBrowserHandlerSet default_tasks; | 436 FileBrowserHandlerList default_tasks; |
| 456 FileBrowserHandlerSet common_tasks; | 437 FileBrowserHandlerList common_tasks; |
| 457 if (!FindCommonTasks(profile, file_urls, &common_tasks)) | 438 if (!FindCommonTasks(profile, file_urls, &common_tasks)) |
| 458 return false; | 439 return false; |
| 459 | 440 |
| 460 if (common_tasks.empty()) | 441 if (common_tasks.empty()) |
| 461 return false; | 442 return false; |
| 462 | 443 |
| 463 std::vector<base::FilePath> file_paths; | 444 std::vector<base::FilePath> file_paths; |
| 464 file_paths.push_back(file_path); | 445 file_paths.push_back(file_path); |
| 465 | 446 |
| 466 FindDefaultTasks(profile, file_paths, common_tasks, &default_tasks); | 447 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(), | 969 extensions::LaunchPlatformAppWithFileHandler(profile(), GetExtension(), |
| 989 action_id_, file_urls[i].path()); | 970 action_id_, file_urls[i].path()); |
| 990 } | 971 } |
| 991 | 972 |
| 992 if (!done.is_null()) | 973 if (!done.is_null()) |
| 993 done.Run(true); | 974 done.Run(true); |
| 994 return true; | 975 return true; |
| 995 } | 976 } |
| 996 | 977 |
| 997 } // namespace file_handler_util | 978 } // namespace file_handler_util |
| OLD | NEW |