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.
5 #ifndef CHROME_BROWSER_FILE_SELECT_HELPER_H_
6 #define CHROME_BROWSER_FILE_SELECT_HELPER_H_
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/browser/web_contents_observer.h"
16 #include "content/public/common/file_chooser_params.h"
17 #include "net/base/directory_lister.h"
18 #include "ui/shell_dialogs/select_file_dialog.h"
23 struct FileChooserFileInfo
;
29 struct SelectedFileInfo
;
32 // This class handles file-selection requests coming from WebUI elements
33 // (via the extensions::ExtensionHost class). It implements both the
34 // initialisation and listener functions for file-selection dialogs.
35 class FileSelectHelper
: public base::RefCountedThreadSafe
<FileSelectHelper
>,
36 public ui::SelectFileDialog::Listener
,
37 public content::WebContentsObserver
,
38 public content::NotificationObserver
{
41 // Show the file chooser dialog.
42 static void RunFileChooser(content::WebContents
* tab
,
43 const content::FileChooserParams
& params
);
45 // Enumerates all the files in directory.
46 static void EnumerateDirectory(content::WebContents
* tab
,
48 const base::FilePath
& path
);
51 friend class base::RefCountedThreadSafe
<FileSelectHelper
>;
52 FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest
, IsAcceptTypeValid
);
53 FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest
, ZipPackage
);
54 explicit FileSelectHelper(Profile
* profile
);
55 ~FileSelectHelper() override
;
57 // Utility class which can listen for directory lister events and relay
58 // them to the main object with the correct tracking id.
59 class DirectoryListerDispatchDelegate
60 : public net::DirectoryLister::DirectoryListerDelegate
{
62 DirectoryListerDispatchDelegate(FileSelectHelper
* parent
, int id
)
65 ~DirectoryListerDispatchDelegate() override
{}
67 const net::DirectoryLister::DirectoryListerData
& data
) override
;
68 void OnListDone(int error
) override
;
71 // This FileSelectHelper owns this object.
72 FileSelectHelper
* parent_
;
75 DISALLOW_COPY_AND_ASSIGN(DirectoryListerDispatchDelegate
);
78 void RunFileChooser(content::RenderViewHost
* render_view_host
,
79 content::WebContents
* web_contents
,
80 const content::FileChooserParams
& params
);
81 void RunFileChooserOnFileThread(
82 const content::FileChooserParams
& params
);
83 void RunFileChooserOnUIThread(
84 const content::FileChooserParams
& params
);
86 // Cleans up and releases this instance. This must be called after the last
87 // callback is received from the file chooser dialog.
88 void RunFileChooserEnd();
90 // SelectFileDialog::Listener overrides.
91 void FileSelected(const base::FilePath
& path
,
93 void* params
) override
;
94 void FileSelectedWithExtraInfo(const ui::SelectedFileInfo
& file
,
96 void* params
) override
;
97 void MultiFilesSelected(const std::vector
<base::FilePath
>& files
,
98 void* params
) override
;
99 void MultiFilesSelectedWithExtraInfo(
100 const std::vector
<ui::SelectedFileInfo
>& files
,
101 void* params
) override
;
102 void FileSelectionCanceled(void* params
) override
;
104 // content::NotificationObserver overrides.
105 void Observe(int type
,
106 const content::NotificationSource
& source
,
107 const content::NotificationDetails
& details
) override
;
109 // content::WebContentsObserver overrides.
110 void RenderViewHostChanged(content::RenderViewHost
* old_host
,
111 content::RenderViewHost
* new_host
) override
;
112 void WebContentsDestroyed() override
;
114 void EnumerateDirectory(int request_id
,
115 content::RenderViewHost
* render_view_host
,
116 const base::FilePath
& path
);
118 // Kicks off a new directory enumeration.
119 void StartNewEnumeration(const base::FilePath
& path
,
121 content::RenderViewHost
* render_view_host
);
123 // Callbacks from directory enumeration.
124 virtual void OnListFile(
126 const net::DirectoryLister::DirectoryListerData
& data
);
127 virtual void OnListDone(int id
, int error
);
129 // Cleans up and releases this instance. This must be called after the last
130 // callback is received from the enumeration code.
131 void EnumerateDirectoryEnd();
133 #if defined(OS_MACOSX) && !defined(OS_IOS)
134 // Must be called on the FILE_USER_BLOCKING thread. Each selected file that is
135 // a package will be zipped, and the zip will be passed to the render view
136 // host in place of the package.
137 void ProcessSelectedFilesMac(const std::vector
<ui::SelectedFileInfo
>& files
);
139 // Saves the paths of |zipped_files| for later deletion. Passes |files| to the
141 void ProcessSelectedFilesMacOnUIThread(
142 const std::vector
<ui::SelectedFileInfo
>& files
,
143 const std::vector
<base::FilePath
>& zipped_files
);
145 // Zips the package at |path| into a temporary destination. Returns the
146 // temporary destination, if the zip was successful. Otherwise returns an
148 static base::FilePath
ZipPackage(const base::FilePath
& path
);
149 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
151 // Utility method that passes |files| to the render view host, and ends the
153 void NotifyRenderViewHostAndEnd(
154 const std::vector
<ui::SelectedFileInfo
>& files
);
156 // Sends the result to the render process, and call |RunFileChooserEnd|.
157 void NotifyRenderViewHostAndEndAfterConversion(
158 const std::vector
<content::FileChooserFileInfo
>& list
);
160 // Schedules the deletion of the files in |temporary_files_| and clears the
162 void DeleteTemporaryFiles();
164 // Cleans up when the RenderViewHost of our WebContents changes.
165 void CleanUpOnRenderViewHostChange();
167 // Helper method to get allowed extensions for select file dialog from
168 // the specified accept types as defined in the spec:
169 // http://whatwg.org/html/number-state.html#attr-input-accept
170 // |accept_types| contains only valid lowercased MIME types or file extensions
171 // beginning with a period (.).
172 static scoped_ptr
<ui::SelectFileDialog::FileTypeInfo
>
173 GetFileTypesFromAcceptType(
174 const std::vector
<base::string16
>& accept_types
);
176 // Check the accept type is valid. It is expected to be all lower case with
178 static bool IsAcceptTypeValid(const std::string
& accept_type
);
180 // Profile used to set/retrieve the last used directory.
183 // The RenderViewHost and WebContents for the page showing a file dialog
184 // (may only be one such dialog).
185 content::RenderViewHost
* render_view_host_
;
186 content::WebContents
* web_contents_
;
188 // Dialog box used for choosing files to upload from file form fields.
189 scoped_refptr
<ui::SelectFileDialog
> select_file_dialog_
;
190 scoped_ptr
<ui::SelectFileDialog::FileTypeInfo
> select_file_types_
;
192 // The type of file dialog last shown.
193 ui::SelectFileDialog::Type dialog_type_
;
195 // The mode of file dialog last shown.
196 content::FileChooserParams::Mode dialog_mode_
;
198 // Maintain a list of active directory enumerations. These could come from
199 // the file select dialog or from drag-and-drop of directories, so there could
200 // be more than one going on at a time.
201 struct ActiveDirectoryEnumeration
;
202 std::map
<int, ActiveDirectoryEnumeration
*> directory_enumerations_
;
204 // Registrar for notifications regarding our RenderViewHost.
205 content::NotificationRegistrar notification_registrar_
;
207 // Temporary files only used on OSX. This class is responsible for deleting
208 // these files when they are no longer needed.
209 std::vector
<base::FilePath
> temporary_files_
;
211 DISALLOW_COPY_AND_ASSIGN(FileSelectHelper
);
214 #endif // CHROME_BROWSER_FILE_SELECT_HELPER_H_