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#include "ui/shell_dialogs/select_file_dialog.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "base/message_loop/message_loop.h"
10#include "build/build_config.h"
11#include "ui/shell_dialogs/select_file_dialog_factory.h"
12#include "ui/shell_dialogs/select_file_policy.h"
13#include "ui/shell_dialogs/selected_file_info.h"
14#include "ui/shell_dialogs/shell_dialogs_delegate.h"
15
16#if defined(OS_WIN)
17#include "ui/shell_dialogs/select_file_dialog_win.h"
18#elif defined(OS_MACOSX)
19#include "ui/shell_dialogs/select_file_dialog_mac.h"
20#elif defined(OS_ANDROID)
21#include "ui/shell_dialogs/select_file_dialog_android.h"
22#elif defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
23#include "ui/shell_dialogs/linux_shell_dialog.h"
24#endif
25
26namespace {
27
28// Optional dialog factory. Leaked.
29ui::SelectFileDialogFactory* dialog_factory_ = NULL;
30
31// The global shell dialogs delegate.
32ui::ShellDialogsDelegate* g_shell_dialogs_delegate_ = NULL;
33
34}  // namespace
35
36namespace ui {
37
38SelectFileDialog::FileTypeInfo::FileTypeInfo()
39    : include_all_files(false),
40      support_drive(false) {}
41
42SelectFileDialog::FileTypeInfo::~FileTypeInfo() {}
43
44void SelectFileDialog::Listener::FileSelectedWithExtraInfo(
45    const ui::SelectedFileInfo& file,
46    int index,
47    void* params) {
48  // Most of the dialogs need actual local path, so default to it.
49  FileSelected(file.local_path, index, params);
50}
51
52void SelectFileDialog::Listener::MultiFilesSelectedWithExtraInfo(
53    const std::vector<ui::SelectedFileInfo>& files,
54    void* params) {
55  std::vector<base::FilePath> file_paths;
56  for (size_t i = 0; i < files.size(); ++i)
57    file_paths.push_back(files[i].local_path);
58
59  MultiFilesSelected(file_paths, params);
60}
61
62// static
63void SelectFileDialog::SetFactory(ui::SelectFileDialogFactory* factory) {
64  delete dialog_factory_;
65  dialog_factory_ = factory;
66}
67
68// static
69scoped_refptr<SelectFileDialog> SelectFileDialog::Create(
70    Listener* listener,
71    ui::SelectFilePolicy* policy) {
72  if (dialog_factory_) {
73    SelectFileDialog* dialog = dialog_factory_->Create(listener, policy);
74    if (dialog)
75      return dialog;
76  }
77
78#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
79  const ui::LinuxShellDialog* shell_dialogs = ui::LinuxShellDialog::instance();
80  if (shell_dialogs)
81    return shell_dialogs->CreateSelectFileDialog(listener, policy);
82#endif
83
84#if defined(OS_WIN)
85  // TODO(ananta)
86  // Fix this for Chrome ASH on Windows.
87  return CreateDefaultWinSelectFileDialog(listener, policy);
88#elif defined(OS_MACOSX) && !defined(USE_AURA)
89  return CreateMacSelectFileDialog(listener, policy);
90#elif defined(OS_ANDROID)
91  return CreateAndroidSelectFileDialog(listener, policy);
92#else
93  NOTIMPLEMENTED();
94  return NULL;
95#endif
96}
97
98void SelectFileDialog::SelectFile(
99    Type type,
100    const base::string16& title,
101    const base::FilePath& default_path,
102    const FileTypeInfo* file_types,
103    int file_type_index,
104    const base::FilePath::StringType& default_extension,
105    gfx::NativeWindow owning_window,
106    void* params) {
107  DCHECK(listener_);
108
109  if (select_file_policy_.get() &&
110      !select_file_policy_->CanOpenSelectFileDialog()) {
111    select_file_policy_->SelectFileDenied();
112
113    // Inform the listener that no file was selected.
114    // Post a task rather than calling FileSelectionCanceled directly to ensure
115    // that the listener is called asynchronously.
116    base::MessageLoop::current()->PostTask(
117        FROM_HERE,
118        base::Bind(&SelectFileDialog::CancelFileSelection, this, params));
119    return;
120  }
121
122  // Call the platform specific implementation of the file selection dialog.
123  SelectFileImpl(type, title, default_path, file_types, file_type_index,
124                 default_extension, owning_window, params);
125}
126
127bool SelectFileDialog::HasMultipleFileTypeChoices() {
128  return HasMultipleFileTypeChoicesImpl();
129}
130
131// static
132void SelectFileDialog::SetShellDialogsDelegate(ShellDialogsDelegate* delegate) {
133  g_shell_dialogs_delegate_ = delegate;
134}
135
136SelectFileDialog::SelectFileDialog(Listener* listener,
137                                   ui::SelectFilePolicy* policy)
138    : listener_(listener),
139      select_file_policy_(policy) {
140  DCHECK(listener_);
141}
142
143SelectFileDialog::~SelectFileDialog() {}
144
145void SelectFileDialog::CancelFileSelection(void* params) {
146  if (listener_)
147    listener_->FileSelectionCanceled(params);
148}
149
150ShellDialogsDelegate* SelectFileDialog::GetShellDialogsDelegate() {
151  return g_shell_dialogs_delegate_;
152}
153
154}  // namespace ui
155