• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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