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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_FILE_SELECT_HELPER_H_ 6 #define CHROME_BROWSER_FILE_SELECT_HELPER_H_ 7 8 #include <map> 9 #include <vector> 10 11 #include "base/compiler_specific.h" 12 #include "base/gtest_prod_util.h" 13 #include "content/public/browser/notification_observer.h" 14 #include "content/public/browser/notification_registrar.h" 15 #include "content/public/common/file_chooser_params.h" 16 #include "net/base/directory_lister.h" 17 #include "ui/shell_dialogs/select_file_dialog.h" 18 19 class Profile; 20 21 namespace content { 22 class RenderViewHost; 23 class WebContents; 24 } 25 26 namespace ui { 27 struct SelectedFileInfo; 28 } 29 30 // This class handles file-selection requests coming from WebUI elements 31 // (via the extensions::ExtensionHost class). It implements both the 32 // initialisation and listener functions for file-selection dialogs. 33 class FileSelectHelper 34 : public base::RefCountedThreadSafe<FileSelectHelper>, 35 public ui::SelectFileDialog::Listener, 36 public content::NotificationObserver { 37 public: 38 39 // Show the file chooser dialog. 40 static void RunFileChooser(content::WebContents* tab, 41 const content::FileChooserParams& params); 42 43 // Enumerates all the files in directory. 44 static void EnumerateDirectory(content::WebContents* tab, 45 int request_id, 46 const base::FilePath& path); 47 48 private: 49 friend class base::RefCountedThreadSafe<FileSelectHelper>; 50 FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, IsAcceptTypeValid); 51 explicit FileSelectHelper(Profile* profile); 52 virtual ~FileSelectHelper(); 53 54 // Utility class which can listen for directory lister events and relay 55 // them to the main object with the correct tracking id. 56 class DirectoryListerDispatchDelegate 57 : public net::DirectoryLister::DirectoryListerDelegate { 58 public: DirectoryListerDispatchDelegate(FileSelectHelper * parent,int id)59 DirectoryListerDispatchDelegate(FileSelectHelper* parent, int id) 60 : parent_(parent), 61 id_(id) {} ~DirectoryListerDispatchDelegate()62 virtual ~DirectoryListerDispatchDelegate() {} 63 virtual void OnListFile( 64 const net::DirectoryLister::DirectoryListerData& data) OVERRIDE; 65 virtual void OnListDone(int error) OVERRIDE; 66 private: 67 // This FileSelectHelper owns this object. 68 FileSelectHelper* parent_; 69 int id_; 70 71 DISALLOW_COPY_AND_ASSIGN(DirectoryListerDispatchDelegate); 72 }; 73 74 void RunFileChooser(content::RenderViewHost* render_view_host, 75 content::WebContents* web_contents, 76 const content::FileChooserParams& params); 77 void RunFileChooserOnFileThread( 78 const content::FileChooserParams& params); 79 void RunFileChooserOnUIThread( 80 const content::FileChooserParams& params); 81 82 // Cleans up and releases this instance. This must be called after the last 83 // callback is received from the file chooser dialog. 84 void RunFileChooserEnd(); 85 86 // SelectFileDialog::Listener overrides. 87 virtual void FileSelected( 88 const base::FilePath& path, int index, void* params) OVERRIDE; 89 virtual void FileSelectedWithExtraInfo( 90 const ui::SelectedFileInfo& file, 91 int index, 92 void* params) OVERRIDE; 93 virtual void MultiFilesSelected(const std::vector<base::FilePath>& files, 94 void* params) OVERRIDE; 95 virtual void MultiFilesSelectedWithExtraInfo( 96 const std::vector<ui::SelectedFileInfo>& files, 97 void* params) OVERRIDE; 98 virtual void FileSelectionCanceled(void* params) OVERRIDE; 99 100 // content::NotificationObserver overrides. 101 virtual void Observe(int type, 102 const content::NotificationSource& source, 103 const content::NotificationDetails& details) OVERRIDE; 104 105 void EnumerateDirectory(int request_id, 106 content::RenderViewHost* render_view_host, 107 const base::FilePath& path); 108 109 // Kicks off a new directory enumeration. 110 void StartNewEnumeration(const base::FilePath& path, 111 int request_id, 112 content::RenderViewHost* render_view_host); 113 114 // Callbacks from directory enumeration. 115 virtual void OnListFile( 116 int id, 117 const net::DirectoryLister::DirectoryListerData& data); 118 virtual void OnListDone(int id, int error); 119 120 // Cleans up and releases this instance. This must be called after the last 121 // callback is received from the enumeration code. 122 void EnumerateDirectoryEnd(); 123 124 // Helper method to get allowed extensions for select file dialog from 125 // the specified accept types as defined in the spec: 126 // http://whatwg.org/html/number-state.html#attr-input-accept 127 // |accept_types| contains only valid lowercased MIME types or file extensions 128 // beginning with a period (.). 129 static scoped_ptr<ui::SelectFileDialog::FileTypeInfo> 130 GetFileTypesFromAcceptType( 131 const std::vector<base::string16>& accept_types); 132 133 // Check the accept type is valid. It is expected to be all lower case with 134 // no whitespace. 135 static bool IsAcceptTypeValid(const std::string& accept_type); 136 137 // Profile used to set/retrieve the last used directory. 138 Profile* profile_; 139 140 // The RenderViewHost and WebContents for the page showing a file dialog 141 // (may only be one such dialog). 142 content::RenderViewHost* render_view_host_; 143 content::WebContents* web_contents_; 144 145 // Dialog box used for choosing files to upload from file form fields. 146 scoped_refptr<ui::SelectFileDialog> select_file_dialog_; 147 scoped_ptr<ui::SelectFileDialog::FileTypeInfo> select_file_types_; 148 149 // The type of file dialog last shown. 150 ui::SelectFileDialog::Type dialog_type_; 151 152 // The mode of file dialog last shown. 153 content::FileChooserParams::Mode dialog_mode_; 154 155 // Maintain a list of active directory enumerations. These could come from 156 // the file select dialog or from drag-and-drop of directories, so there could 157 // be more than one going on at a time. 158 struct ActiveDirectoryEnumeration; 159 std::map<int, ActiveDirectoryEnumeration*> directory_enumerations_; 160 161 // Registrar for notifications regarding our RenderViewHost. 162 content::NotificationRegistrar notification_registrar_; 163 164 DISALLOW_COPY_AND_ASSIGN(FileSelectHelper); 165 }; 166 167 #endif // CHROME_BROWSER_FILE_SELECT_HELPER_H_ 168