Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: chrome/browser/chromeos/extensions/file_browser_private_api.cc

Issue 10834383: Chrome OS "open with" picker allowing Web Intents (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: sync to head, comment Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_browser_private_api.h" 5 #include "chrome/browser/chromeos/extensions/file_browser_private_api.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/file_path.h"
12 #include "base/file_util.h"
13 #include "base/i18n/case_conversion.h"
11 #include "base/json/json_writer.h" 14 #include "base/json/json_writer.h"
12 #include "base/logging.h" 15 #include "base/logging.h"
13 #include "base/memory/scoped_vector.h" 16 #include "base/memory/scoped_vector.h"
14 #include "base/memory/singleton.h" 17 #include "base/memory/singleton.h"
15 #include "base/string_split.h" 18 #include "base/string_split.h"
16 #include "base/stringprintf.h" 19 #include "base/stringprintf.h"
17 #include "base/time.h" 20 #include "base/time.h"
18 #include "base/values.h" 21 #include "base/values.h"
22 #include "base/utf_string_conversions.h"
19 #include "chrome/browser/chromeos/cros/cros_library.h" 23 #include "chrome/browser/chromeos/cros/cros_library.h"
20 #include "chrome/browser/chromeos/cros/network_library.h" 24 #include "chrome/browser/chromeos/cros/network_library.h"
21 #include "chrome/browser/chromeos/disks/disk_mount_manager.h" 25 #include "chrome/browser/chromeos/disks/disk_mount_manager.h"
22 #include "chrome/browser/chromeos/extensions/file_handler_util.h" 26 #include "chrome/browser/chromeos/extensions/file_handler_util.h"
23 #include "chrome/browser/chromeos/extensions/file_manager_util.h" 27 #include "chrome/browser/chromeos/extensions/file_manager_util.h"
24 #include "chrome/browser/chromeos/gdata/drive.pb.h" 28 #include "chrome/browser/chromeos/gdata/drive.pb.h"
25 #include "chrome/browser/chromeos/gdata/drive_service_interface.h" 29 #include "chrome/browser/chromeos/gdata/drive_service_interface.h"
26 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h" 30 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h"
27 #include "chrome/browser/chromeos/gdata/gdata_system_service.h" 31 #include "chrome/browser/chromeos/gdata/gdata_system_service.h"
28 #include "chrome/browser/chromeos/gdata/gdata_util.h" 32 #include "chrome/browser/chromeos/gdata/gdata_util.h"
(...skipping 16 matching lines...) Expand all
45 #include "chrome/common/extensions/extension_icon_set.h" 49 #include "chrome/common/extensions/extension_icon_set.h"
46 #include "chrome/common/extensions/file_browser_handler.h" 50 #include "chrome/common/extensions/file_browser_handler.h"
47 #include "chrome/common/pref_names.h" 51 #include "chrome/common/pref_names.h"
48 #include "content/public/browser/child_process_security_policy.h" 52 #include "content/public/browser/child_process_security_policy.h"
49 #include "content/public/browser/render_process_host.h" 53 #include "content/public/browser/render_process_host.h"
50 #include "content/public/browser/render_view_host.h" 54 #include "content/public/browser/render_view_host.h"
51 #include "googleurl/src/gurl.h" 55 #include "googleurl/src/gurl.h"
52 #include "grit/generated_resources.h" 56 #include "grit/generated_resources.h"
53 #include "grit/platform_locale_settings.h" 57 #include "grit/platform_locale_settings.h"
54 #include "net/base/escape.h" 58 #include "net/base/escape.h"
59 #include "net/base/mime_util.h"
55 #include "ui/base/dialogs/selected_file_info.h" 60 #include "ui/base/dialogs/selected_file_info.h"
56 #include "ui/base/l10n/l10n_util.h" 61 #include "ui/base/l10n/l10n_util.h"
57 #include "webkit/chromeos/fileapi/cros_mount_point_provider.h" 62 #include "webkit/chromeos/fileapi/cros_mount_point_provider.h"
58 #include "webkit/fileapi/file_system_context.h" 63 #include "webkit/fileapi/file_system_context.h"
59 #include "webkit/fileapi/file_system_file_util.h" 64 #include "webkit/fileapi/file_system_file_util.h"
60 #include "webkit/fileapi/file_system_operation_context.h" 65 #include "webkit/fileapi/file_system_operation_context.h"
61 #include "webkit/fileapi/file_system_types.h" 66 #include "webkit/fileapi/file_system_types.h"
62 #include "webkit/fileapi/file_system_url.h" 67 #include "webkit/fileapi/file_system_url.h"
63 #include "webkit/fileapi/file_system_util.h" 68 #include "webkit/fileapi/file_system_util.h"
69 #include "webkit/glue/web_intent_service_data.h"
64 70
65 using chromeos::disks::DiskMountManager; 71 using chromeos::disks::DiskMountManager;
66 using content::BrowserContext; 72 using content::BrowserContext;
67 using content::BrowserThread; 73 using content::BrowserThread;
68 using content::ChildProcessSecurityPolicy; 74 using content::ChildProcessSecurityPolicy;
69 using content::SiteInstance; 75 using content::SiteInstance;
70 using content::WebContents; 76 using content::WebContents;
71 using extensions::Extension; 77 using extensions::Extension;
72 using file_handler_util::FileTaskExecutor; 78 using file_handler_util::FileTaskExecutor;
73 using gdata::InstalledApp; 79 using gdata::InstalledApp;
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 if (icons.empty()) 252 if (icons.empty())
247 return result; 253 return result;
248 result = icons.rbegin()->second; 254 result = icons.rbegin()->second;
249 for (InstalledApp::IconList::const_reverse_iterator iter = icons.rbegin(); 255 for (InstalledApp::IconList::const_reverse_iterator iter = icons.rbegin();
250 iter != icons.rend() && iter->first >= preferred_size; ++iter) { 256 iter != icons.rend() && iter->first >= preferred_size; ++iter) {
251 result = iter->second; 257 result = iter->second;
252 } 258 }
253 return result; 259 return result;
254 } 260 }
255 261
262 typedef std::vector<webkit_glue::WebIntentServiceData> ServiceList;
263
264 // Returns the set of Web Intent actions for which the given |mime_type| is
265 // allowed.
266 std::set<std::string> ActionsForType(const std::string& mime_type,
267 const ServiceList& services) {
268 std::set<std::string> actions;
269 for (ServiceList::const_iterator i = services.begin();
270 i != services.end(); ++i) {
271 if (net::MatchesMimeType(UTF16ToUTF8(i->type), mime_type))
272 actions.insert(UTF16ToUTF8(i->action));
273 }
274 return actions;
275 }
276
277 // Given an extension and a set of |mime_types|, return the set of Web Intent
278 // actions that are supported on every type within the set. This set may be
279 // empty, in which case no actions are supported.
280 std::set<std::string> ActionsForExtension(const Extension* extension,
281 const std::set<std::string>& mime_types) {
282 std::set<std::string> actions;
283
284 for (std::set<std::string>::const_iterator i = mime_types.begin();
285 i != mime_types.end(); ++i) {
286 std::set<std::string> inner =
287 ActionsForType(*i, extension->intents_services());
288
289 if (i == mime_types.begin()) {
290 actions = inner;
291 } else {
292 std::set<std::string> tmp;
293 std::set_intersection(actions.begin(),
294 actions.end(),
295 inner.begin(),
296 inner.end(),
297 std::inserter(tmp, tmp.begin()));
298 actions = tmp;
299 }
300
301 if (actions.empty())
302 break; // fall-out early, this set will never grow
303 }
304
305 return actions;
306 }
307
308 // Retrieves the title for the given Extension and action pair, returning true
309 // if it could be found.
310 bool TitleForExtensionAction(const Extension* extension,
311 const std::string& action, std::string* title) {
312 for (ServiceList::const_iterator i = extension->intents_services().begin();
313 i != extension->intents_services().end(); ++i) {
314 if (action == UTF16ToUTF8(i->action)) {
315 *title = UTF16ToUTF8(i->title);
316 return true;
317 }
318 }
319 return false;
320 }
321
256 } // namespace 322 } // namespace
257 323
258 class RequestLocalFileSystemFunction::LocalFileSystemCallbackDispatcher { 324 class RequestLocalFileSystemFunction::LocalFileSystemCallbackDispatcher {
259 public: 325 public:
260 static fileapi::FileSystemContext::OpenFileSystemCallback CreateCallback( 326 static fileapi::FileSystemContext::OpenFileSystemCallback CreateCallback(
261 RequestLocalFileSystemFunction* function, 327 RequestLocalFileSystemFunction* function,
262 scoped_refptr<fileapi::FileSystemContext> file_system_context, 328 scoped_refptr<fileapi::FileSystemContext> file_system_context,
263 int child_id, 329 int child_id,
264 scoped_refptr<const Extension> extension) { 330 scoped_refptr<const Extension> extension) {
265 return base::Bind( 331 return base::Bind(
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 return true; 659 return true;
594 660
595 gdata::GDataSystemService* system_service = 661 gdata::GDataSystemService* system_service =
596 gdata::GDataSystemServiceFactory::GetForProfile(profile_); 662 gdata::GDataSystemServiceFactory::GetForProfile(profile_);
597 // |system_service| is NULL if incognito window / guest login. We return true 663 // |system_service| is NULL if incognito window / guest login. We return true
598 // in this case because there might be other extension tasks, even if we don't 664 // in this case because there might be other extension tasks, even if we don't
599 // have any to add. 665 // have any to add.
600 if (!system_service || !system_service->webapps_registry()) 666 if (!system_service || !system_service->webapps_registry())
601 return true; 667 return true;
602 668
603
604 gdata::DriveWebAppsRegistry* registry = system_service->webapps_registry(); 669 gdata::DriveWebAppsRegistry* registry = system_service->webapps_registry();
605 670
606 // Map of app_id to DriveWebAppInfo so we can look up the apps we've found 671 // Map of app_id to DriveWebAppInfo so we can look up the apps we've found
607 // after taking the intersection of available apps. 672 // after taking the intersection of available apps.
608 std::map<std::string, gdata::DriveWebAppInfo*> app_info; 673 std::map<std::string, gdata::DriveWebAppInfo*> app_info;
609 // Set of application IDs. This will end up with the intersection of the 674 // Set of application IDs. This will end up with the intersection of the
610 // application IDs that apply to the paths in |file_paths|. 675 // application IDs that apply to the paths in |file_paths|.
611 std::set<std::string> available_apps; 676 std::set<std::string> available_apps;
612 677
613 IntersectAvailableDriveTasks(registry, file_info_list, 678 IntersectAvailableDriveTasks(registry, file_info_list,
614 &app_info, &available_apps); 679 &app_info, &available_apps);
615 CreateDriveTasks(registry, app_info, available_apps, result_list); 680 CreateDriveTasks(registry, app_info, available_apps, result_list);
616 681
617 // We own the pointers in |app_info|, so we need to delete them. 682 // We own the pointers in |app_info|, so we need to delete them.
618 STLDeleteContainerPairSecondPointers(app_info.begin(), app_info.end()); 683 STLDeleteContainerPairSecondPointers(app_info.begin(), app_info.end());
619 return true; 684 return true;
620 } 685 }
621 686
687 // Find special tasks here for Web Intent platform apps. Iterate through
688 // matching apps and add them. These tasks will be identified by the "http"
689 // prefix found on the task action.
690 bool GetFileTasksFileBrowserFunction::FindWebIntentTasks(
691 const std::vector<GURL>& file_urls,
692 ListValue* result_list) {
693 DCHECK(!file_urls.empty());
694 ExtensionService* service = profile_->GetExtensionService();
695 if (!service)
696 return false;
697
698 std::set<std::string> mime_types;
699 for (std::vector<GURL>::const_iterator iter = file_urls.begin();
700 iter != file_urls.end(); ++iter) {
701 const FilePath file = FilePath(GURL(iter->spec()).ExtractFileName());
702 const FilePath::StringType file_extension =
703 StringToLowerASCII(file.Extension());
704
705 // TODO(thorogood): Rearchitect this call so it can run on the File thread;
706 // GetMimeTypeFromFile requires this on Linux. Right now, we use
707 // Chrome-level knowledge only.
708 std::string mime_type;
709 if (!file_extension.empty() && !net::GetWellKnownMimeTypeFromExtension(
710 file_extension.substr(1), &mime_type))
711 mime_type = std::string(); // There was no mime-type available from this
712 // file, but we'll still match "*".
713 mime_types.insert(mime_type);
714 }
715
716 for (ExtensionSet::const_iterator iter = service->extensions()->begin();
717 iter != service->extensions()->end();
718 ++iter) {
719 const Extension* extension = *iter;
720
721 // We can't use hosted apps to open files.
722 if (!extension->is_platform_app() || !extension->has_background_page())
benwells 2012/08/27 08:02:59 Don't need to check for background page here, all
thorogood 2012/08/28 00:04:04 Done.
723 continue;
724
725 if (profile_->IsOffTheRecord() &&
726 !service->IsIncognitoEnabled(extension->id()))
727 continue;
728
729 const std::set<std::string> actions =
730 ActionsForExtension(extension, mime_types);
benwells 2012/08/27 08:02:59 I should have mentioned this, but we only care abo
thorogood 2012/08/28 00:04:04 Before I make this change, can I ask why? In my mi
thorogood 2012/08/29 06:34:46 I've updated this file to work this way now. PTAL!
731 for (std::set<std::string>::iterator ai = actions.begin();
732 ai != actions.end(); ++ai) {
733 std::string title;
734 DCHECK(TitleForExtensionAction(extension, *ai, &title));
735
736 DictionaryValue* task = new DictionaryValue;
737 std::string task_id =
738 file_handler_util::MakeTaskID(extension->id(), *ai);
739 task->SetString("taskId", task_id);
740 task->SetString("title", title);
741 task->Set("patterns", new ListValue);
742
743 GURL best_icon = extension->GetIconURL(kPreferredIconSize,
744 ExtensionIconSet::MATCH_BIGGER);
745 task->SetString("iconUrl", best_icon.spec());
746
747 task->SetBoolean("driveApp", false);
748 result_list->Append(task);
749 }
750 }
751
752 return true;
753 }
754
622 bool GetFileTasksFileBrowserFunction::RunImpl() { 755 bool GetFileTasksFileBrowserFunction::RunImpl() {
623 // First argument is the list of files to get tasks for. 756 // First argument is the list of files to get tasks for.
624 ListValue* files_list = NULL; 757 ListValue* files_list = NULL;
625 if (!args_->GetList(0, &files_list)) 758 if (!args_->GetList(0, &files_list))
626 return false; 759 return false;
627 760
628 // Second argument is the list of mime types of each of the files in the list. 761 // Second argument is the list of mime types of each of the files in the list.
629 ListValue* mime_types_list = NULL; 762 ListValue* mime_types_list = NULL;
630 if (!args_->GetList(1, &mime_types_list)) 763 if (!args_->GetList(1, &mime_types_list))
631 return false; 764 return false;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 826
694 // Take the union of Drive and extension tasks: Because any extension tasks we 827 // Take the union of Drive and extension tasks: Because any extension tasks we
695 // found must apply to all of the files (intersection), and because the same 828 // found must apply to all of the files (intersection), and because the same
696 // is true of the drive apps, we simply take the union of two lists by adding 829 // is true of the drive apps, we simply take the union of two lists by adding
697 // the drive tasks to the extension task list. We know there aren't duplicates 830 // the drive tasks to the extension task list. We know there aren't duplicates
698 // because they're entirely different kinds of tasks, but there could be both 831 // because they're entirely different kinds of tasks, but there could be both
699 // kinds of tasks for a file type (an image file, for instance). 832 // kinds of tasks for a file type (an image file, for instance).
700 if (!FindDriveAppTasks(info_list, result_list)) 833 if (!FindDriveAppTasks(info_list, result_list))
701 return false; 834 return false;
702 835
836 // Take the union of Web Intents (that platform apps may accept) and all
837 // previous Drive and extension tasks. As above, we know there aren't
838 // duplicates because they're entirely different kinds of tasks.
839 if (!FindWebIntentTasks(file_urls, result_list))
840 return false;
841
703 if (VLOG_IS_ON(1)) { 842 if (VLOG_IS_ON(1)) {
704 std::string result_json; 843 std::string result_json;
705 base::JSONWriter::WriteWithOptions( 844 base::JSONWriter::WriteWithOptions(
706 result_list, 845 result_list,
707 base::JSONWriter::OPTIONS_DO_NOT_ESCAPE | 846 base::JSONWriter::OPTIONS_DO_NOT_ESCAPE |
708 base::JSONWriter::OPTIONS_PRETTY_PRINT, 847 base::JSONWriter::OPTIONS_PRETTY_PRINT,
709 &result_json); 848 &result_json);
710 VLOG(1) << "GetFileTasks result:\n" << result_json; 849 VLOG(1) << "GetFileTasks result:\n" << result_json;
711 } 850 }
712 851
713 // TODO(zelidrag, serya): Add intent content tasks to result_list once we
714 // implement that API.
715 SendResponse(true); 852 SendResponse(true);
716 return true; 853 return true;
717 } 854 }
718 855
719 ExecuteTasksFileBrowserFunction::ExecuteTasksFileBrowserFunction() {} 856 ExecuteTasksFileBrowserFunction::ExecuteTasksFileBrowserFunction() {}
720 857
721 void ExecuteTasksFileBrowserFunction::OnTaskExecuted(bool success) { 858 void ExecuteTasksFileBrowserFunction::OnTaskExecuted(bool success) {
722 SendResponse(success); 859 SendResponse(success);
723 } 860 }
724 861
(...skipping 1695 matching lines...) Expand 10 before | Expand all | Expand 10 after
2420 gdata::GDataSystemService* system_service = 2557 gdata::GDataSystemService* system_service =
2421 gdata::GDataSystemServiceFactory::GetForProfile(profile_); 2558 gdata::GDataSystemServiceFactory::GetForProfile(profile_);
2422 if (!system_service || !system_service->file_system()) 2559 if (!system_service || !system_service->file_system())
2423 return false; 2560 return false;
2424 2561
2425 FilePath directory_path = GetVirtualPathFromURL(GURL(file_url_as_string)); 2562 FilePath directory_path = GetVirtualPathFromURL(GURL(file_url_as_string));
2426 system_service->file_system()->RequestDirectoryRefresh(directory_path); 2563 system_service->file_system()->RequestDirectoryRefresh(directory_path);
2427 2564
2428 return true; 2565 return true;
2429 } 2566 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698