summaryrefslogtreecommitdiff
path: root/chromium/ui/shell_dialogs/select_file_dialog.h
blob: f8b7aea68e545a1f048a8bbe5588aa9b7d1d6526 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// Copyright (c) 2013 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.

#ifndef UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_
#define UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_

#include <memory>
#include <string>
#include <vector>

#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/shell_dialogs/base_shell_dialog.h"
#include "ui/shell_dialogs/shell_dialogs_export.h"

namespace ui {

class SelectFileDialogFactory;
class SelectFilePolicy;
struct SelectedFileInfo;

// Shows a dialog box for selecting a file or a folder.
class SHELL_DIALOGS_EXPORT SelectFileDialog
    : public base::RefCountedThreadSafe<SelectFileDialog>,
      public BaseShellDialog {
 public:
  enum Type {
    SELECT_NONE,

    // For opening a folder.
    SELECT_FOLDER,

    // Like SELECT_FOLDER, but the dialog UI should explicitly show it's
    // specifically for "upload".
    SELECT_UPLOAD_FOLDER,

    // Like SELECT_FOLDER, but folder creation is disabled, if possible.
    SELECT_EXISTING_FOLDER,

    // For saving into a file, allowing a nonexistent file to be selected.
    SELECT_SAVEAS_FILE,

    // For opening a file.
    SELECT_OPEN_FILE,

    // Like SELECT_OPEN_FILE, but allowing multiple files to open.
    SELECT_OPEN_MULTI_FILE
  };

  // An interface implemented by a Listener object wishing to know about the
  // the result of the Select File/Folder action. These callbacks must be
  // re-entrant.
  class SHELL_DIALOGS_EXPORT Listener {
   public:
    // Notifies the Listener that a file/folder selection has been made. The
    // file/folder path is in |path|. |params| is contextual passed to
    // SelectFile. |index| specifies the index of the filter passed to the
    // the initial call to SelectFile.
    virtual void FileSelected(const base::FilePath& path,
                              int index, void* params) = 0;

    // Similar to FileSelected() but takes SelectedFileInfo instead of
    // base::FilePath. Used for passing extra information (ex. display name).
    //
    // If not overridden, calls FileSelected() with path from |file|.
    virtual void FileSelectedWithExtraInfo(
        const SelectedFileInfo& file,
        int index,
        void* params);

    // Notifies the Listener that many files have been selected. The
    // files are in |files|. |params| is contextual passed to SelectFile.
    virtual void MultiFilesSelected(
        const std::vector<base::FilePath>& files, void* params) {}

    // Similar to MultiFilesSelected() but takes SelectedFileInfo instead of
    // base::FilePath. Used for passing extra information (ex. display name).
    //
    // If not overridden, calls MultiFilesSelected() with paths from |files|.
    virtual void MultiFilesSelectedWithExtraInfo(
        const std::vector<SelectedFileInfo>& files,
        void* params);

    // Notifies the Listener that the file/folder selection was aborted (via
    // the  user canceling or closing the selection dialog box, for example).
    // |params| is contextual passed to SelectFile.
    virtual void FileSelectionCanceled(void* params) {}

   protected:
    virtual ~Listener() {}
  };

  // Sets the factory that creates SelectFileDialog objects, overriding default
  // behaviour.
  //
  // This is optional and should only be used by components that have to live
  // elsewhere in the tree due to layering violations. (For example, because of
  // a dependency on chrome's extension system.)
  static void SetFactory(SelectFileDialogFactory* factory);

  // Creates a dialog box helper. This is an inexpensive wrapper around the
  // platform-native file selection dialog. |policy| is an optional class that
  // can prevent showing a dialog.
  //
  // The lifetime of the Listener is not managed by this class. The calling
  // code should call always ListenerDestroyed() (on the base class
  // BaseShellDialog) when the listener is destroyed since the SelectFileDialog
  // is refcounted and uses a background thread.
  static scoped_refptr<SelectFileDialog> Create(
      Listener* listener,
      std::unique_ptr<SelectFilePolicy> policy);

  // Holds information about allowed extensions on a file save dialog.
  struct SHELL_DIALOGS_EXPORT FileTypeInfo {
    FileTypeInfo();
    FileTypeInfo(const FileTypeInfo& other);
    ~FileTypeInfo();

    // A list of allowed extensions. For example, it might be
    //
    //   { { "htm", "html" }, { "txt" } }
    //
    // Only pass more than one extension in the inner vector if the extensions
    // are equivalent. Do NOT include leading periods.
    std::vector<std::vector<base::FilePath::StringType>> extensions;

    // Overrides the system descriptions of the specified extensions. Entries
    // correspond to |extensions|; if left blank the system descriptions will
    // be used.
    std::vector<base::string16> extension_description_overrides;

    // Specifies whether there will be a filter added for all files (i.e. *.*).
    bool include_all_files;

    // Specifies which type of paths the caller can handle. If it is
    // NATIVE_PATH, the dialog creates a native replica of the non-native file
    // and returns its path, so that the caller can use it without any
    // difference than when it were local.
    enum AllowedPaths {
      ANY_PATH,
      NATIVE_PATH,
      NATIVE_OR_DRIVE_PATH,
      ANY_PATH_OR_URL
    };
    AllowedPaths allowed_paths;
  };

  // Returns a file path with a base name at most 255 characters long. This
  // is the limit on Windows and Linux, and on Windows the system file
  // selection dialog will fail to open if the file name exceeds 255 characters.
  static base::FilePath GetShortenedFilePath(const base::FilePath& path);

  // Selects a File.
  // Before doing anything this function checks if FileBrowsing is forbidden
  // by Policy. If so, it tries to show an InfoBar and behaves as though no File
  // was selected (the user clicked `Cancel` immediately).
  // Otherwise it will start displaying the dialog box. This will also
  // block the calling window until the dialog box is complete. The listener
  // associated with this object will be notified when the selection is
  // complete.
  // |type| is the type of file dialog to be shown, see Type enumeration above.
  // |title| is the title to be displayed in the dialog. If this string is
  //   empty, the default title is used.
  // |default_path| is the default path and suggested file name to be shown in
  //   the dialog. This only works for SELECT_SAVEAS_FILE and SELECT_OPEN_FILE.
  //   Can be an empty string to indicate the platform default.
  // |file_types| holds the information about the file types allowed. Pass NULL
  //   to get no special behavior
  // |file_type_index| is the 1-based index into the file type list in
  //   |file_types|. Specify 0 if you don't need to specify extension behavior.
  // |default_extension| is the default extension to add to the file if the
  //   user doesn't type one. This should NOT include the '.'. On Windows, if
  //   you specify this you must also specify |file_types|.
  // |owning_window| is the window the dialog is modal to, or NULL for a
  //   modeless dialog.
  // |params| is data from the calling context which will be passed through to
  //   the listener. Can be NULL.
  // NOTE: only one instance of any shell dialog can be shown per owning_window
  //       at a time (for obvious reasons).
  void SelectFile(Type type,
                  const base::string16& title,
                  const base::FilePath& default_path,
                  const FileTypeInfo* file_types,
                  int file_type_index,
                  const base::FilePath::StringType& default_extension,
                  gfx::NativeWindow owning_window,
                  void* params);
  bool HasMultipleFileTypeChoices();

 protected:
  friend class base::RefCountedThreadSafe<SelectFileDialog>;

  explicit SelectFileDialog(Listener* listener,
                            std::unique_ptr<SelectFilePolicy> policy);
  ~SelectFileDialog() override;

  // Displays the actual file-selection dialog.
  // This is overridden in the platform-specific descendants of FileSelectDialog
  // and gets called from SelectFile after testing the
  // AllowFileSelectionDialogs-Policy.
  virtual void SelectFileImpl(
      Type type,
      const base::string16& title,
      const base::FilePath& default_path,
      const FileTypeInfo* file_types,
      int file_type_index,
      const base::FilePath::StringType& default_extension,
      gfx::NativeWindow owning_window,
      void* params) = 0;

  // The listener to be notified of selection completion.
  Listener* listener_;

 private:
  // Tests if the file selection dialog can be displayed by
  // testing if the AllowFileSelectionDialogs-Policy is
  // either unset or set to true.
  bool CanOpenSelectFileDialog();

  // Informs the |listener_| that the file selection dialog was canceled. Moved
  // to a function for being able to post it to the message loop.
  void CancelFileSelection(void* params);

  // Returns true if the dialog has multiple file type choices.
  virtual bool HasMultipleFileTypeChoicesImpl() = 0;

  std::unique_ptr<SelectFilePolicy> select_file_policy_;

  DISALLOW_COPY_AND_ASSIGN(SelectFileDialog);
};

SelectFileDialog* CreateSelectFileDialog(
    SelectFileDialog::Listener* listener,
    std::unique_ptr<SelectFilePolicy> policy);

}  // namespace ui

#endif  // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_