Chromium Code Reviews| Index: chrome/browser/ui/intents/native_file_picker_service.cc |
| diff --git a/chrome/browser/ui/intents/native_file_picker_service.cc b/chrome/browser/ui/intents/native_file_picker_service.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c489e41e9fae1fbe2fbf284e5da89486c6be1ddf |
| --- /dev/null |
| +++ b/chrome/browser/ui/intents/native_file_picker_service.cc |
| @@ -0,0 +1,161 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <vector> |
| + |
| +#include "base/file_path.h" |
| +#include "base/logging.h" |
| +#include "base/string16.h" |
| +#include "base/utf_string_conversions.h" |
| +#include "chrome/browser/intents/intent_service_host.h" |
| +#include "chrome/browser/intents/native_services.h" |
| +#include "chrome/browser/intents/web_intents_util.h" |
| +#include "chrome/browser/platform_util.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_intents_dispatcher.h" |
| +#include "googleurl/src/gurl.h" |
| +#include "grit/generated_resources.h" |
| +#include "net/base/mime_util.h" |
| +#include "ui/base/dialogs/select_file_dialog.h" |
| +#include "ui/base/dialogs/selected_file_info.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| +#include "webkit/glue/web_intent_data.h" |
| +#include "webkit/glue/web_intent_service_data.h" |
| + |
| +namespace web_intents { |
| +namespace { |
| + |
| +// static |
| +void AddTypeInfo( |
| + const std::string& mime_type, |
| + ui::SelectFileDialog::FileTypeInfo* info) { |
| + |
| + info->include_all_files = true; |
| + info->extensions.resize(1); |
| + std::vector<FilePath::StringType>* extensions = &info->extensions.back(); |
| + |
| + // Provide a "helpful" description when possible. |
| + int description_id = 0; |
| + if (mime_type == "image/*") |
| + description_id = IDS_IMAGE_FILES; |
| + else if (mime_type == "audio/*") |
| + description_id = IDS_AUDIO_FILES; |
| + else if (mime_type == "video/*") |
| + description_id = IDS_VIDEO_FILES; |
| + |
| + if (description_id) |
| + info->extension_description_overrides.push_back( |
| + l10n_util::GetStringUTF16(description_id)); |
| + |
| + net::GetExtensionsForMimeType(mime_type, extensions); |
| +} |
| + |
| +// FilePicker service allowing a native file picker to handle |
| +// pick+*/* intents. |
|
Greg Billock
2012/10/08 20:36:12
"pick + */*"
|
| +class NativeFilePickerService : public IntentServiceHost { |
| + public: |
| + explicit NativeFilePickerService(content::WebContents* web_contents); |
| + virtual void HandleIntent(content::WebIntentsDispatcher* dispatcher) OVERRIDE; |
| + |
| + private: |
| + virtual ~NativeFilePickerService(); |
| + // Weak pointer to the web contents on which we'll be displayed. |
|
Greg Billock
2012/10/08 20:36:12
we'll --> the selector
|
| + content::WebContents* web_contents_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(NativeFilePickerService); |
| +}; |
| + |
| +class FileSelectedListener : public ui::SelectFileDialog::Listener { |
|
Greg Billock
2012/10/08 20:36:12
It looks like this should be an inner class on Nat
|
| + public: |
| + explicit FileSelectedListener(content::WebIntentsDispatcher* dispatcher); |
| + // SelectFileDialog::Listener |
| + virtual void FileSelected( |
| + const FilePath& path, int index, void* params) OVERRIDE; |
| + |
| + virtual void MultiFilesSelected( |
| + const std::vector<FilePath>& files, void* params) OVERRIDE; |
| + |
| + virtual void FileSelectionCanceled(void* params) OVERRIDE; |
| + private: |
| + virtual ~FileSelectedListener(); |
| + content::WebIntentsDispatcher* dispatcher_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(FileSelectedListener); |
| +}; |
| + |
| +} // namespace |
| + |
| +FileSelectedListener::FileSelectedListener( |
| + content::WebIntentsDispatcher* dispatcher) : dispatcher_(dispatcher) { |
| +} |
| + |
| +void FileSelectedListener::FileSelected( |
| + const FilePath& path, int index, void* params) { |
| + dispatcher_->SendReplyMessage( |
| + webkit_glue::WEB_INTENT_REPLY_SUCCESS, string16()); |
| + delete this; |
| +} |
| + |
| +void FileSelectedListener::MultiFilesSelected( |
| + const std::vector<FilePath>& files, void* params) { |
| + NOTREACHED(); |
| +} |
| + |
| +void FileSelectedListener::FileSelectionCanceled(void* params) { |
| + dispatcher_->SendReplyMessage( |
| + webkit_glue::WEB_INTENT_REPLY_FAILURE, string16()); |
| + delete this; |
| +} |
| + |
| +FileSelectedListener::~FileSelectedListener() {} |
| + |
| +NativeFilePickerService::NativeFilePickerService( |
| + content::WebContents* web_contents) : web_contents_(web_contents) { |
| +} |
| + |
| +void NativeFilePickerService::HandleIntent( |
| + content::WebIntentsDispatcher* dispatcher) { |
| + const webkit_glue::WebIntentData& intent = dispatcher->GetIntent(); |
| + |
| + std::string ascii_type = UTF16ToASCII(intent.type); |
| + DCHECK(!(net::GetIANAMediaType(ascii_type).empty())); |
| + |
| + FileSelectedListener* listener = new FileSelectedListener(dispatcher); |
| + ui::SelectFileDialog* dialog = ui::SelectFileDialog::Create(listener, NULL); |
|
Greg Billock
2012/10/08 20:36:12
Where does this get deleted? Do we need to hang on
Steve McKay
2012/10/08 22:39:53
Now ref counted.
|
| + |
| + ui::SelectFileDialog::FileTypeInfo type_info; |
| + AddTypeInfo(ascii_type, &type_info); |
| + |
| + const FilePath default_path(FILE_PATH_LITERAL(".")); |
| + const FilePath::StringType default_extension = FILE_PATH_LITERAL(""); |
| + const string16 title = FilePickerFactory::GetServiceTitle(); |
| + |
| + dialog->SelectFile( |
| + ui::SelectFileDialog::SELECT_OPEN_FILE, |
| + title, |
| + default_path, |
| + &type_info, |
| + 1, // index of which file description to show |
| + default_extension, |
| + platform_util::GetTopLevel(web_contents_->GetNativeView()), |
| + NULL); |
| + |
| + delete this; |
|
Greg Billock
2012/10/08 20:36:12
Let's not have service hosts be self-deleting. The
Steve McKay
2012/10/08 22:39:53
For the time being, let's keep this self-deleting.
|
| +} |
| + |
| +NativeFilePickerService::~NativeFilePickerService() {} |
| + |
| +// static |
| +IntentServiceHost* FilePickerFactory::CreateServiceInstance( |
| + content::WebContents* web_contents, |
| + const webkit_glue::WebIntentData& intent) { |
| + return new NativeFilePickerService(web_contents); |
|
Greg Billock
2012/10/08 20:36:12
This leaves us without a good hook for testing. Pu
groby-ooo-7-16
2012/10/08 20:58:21
If we need to inject here for testing, I suggest l
Steve McKay
2012/10/08 22:39:53
Talked this over, can use test factory for the dia
|
| +} |
| + |
| +// Returns the action-specific string for |action|. |
| +string16 FilePickerFactory::GetServiceTitle() { |
| + return l10n_util::GetStringUTF16(IDS_WEB_INTENTS_FILE_PICKER_SERVICE_TITLE); |
| +} |
| + |
| +} // web_intents namespace |