1// Copyright (c) 2011 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 "base/logging.h"
6#include "chrome/browser/extensions/extension_file_browser_private_api.h"
7#include "chrome/browser/extensions/file_manager_util.h"
8#include "chrome/browser/metrics/user_metrics.h"
9#include "chrome/browser/profiles/profile_manager.h"
10#include "chrome/browser/ui/browser.h"
11#include "chrome/browser/ui/browser_dialogs.h"
12#include "chrome/browser/ui/browser_list.h"
13#include "chrome/browser/ui/views/html_dialog_view.h"
14#include "chrome/browser/ui/views/window.h"
15#include "chrome/browser/ui/webui/html_dialog_ui.h"
16#include "content/browser/browser_thread.h"
17#include "content/browser/tab_contents/tab_contents.h"
18#include "views/window/window.h"
19#include "ui/gfx/rect.h"
20#include "ui/gfx/size.h"
21
22// Shows a dialog box for selecting a file or a folder.
23class FileManagerDialog
24    : public SelectFileDialog,
25      public HtmlDialogUIDelegate {
26
27 public:
28  explicit FileManagerDialog(Listener* listener);
29
30  void CreateHtmlDialogView(Profile* profile, void* params) {
31    HtmlDialogView* html_view = new HtmlDialogView(profile, this);
32    browser::CreateViewsWindow(owner_window_, gfx::Rect(), html_view);
33    html_view->InitDialog();
34    html_view->window()->Show();
35    tab_id_ = html_view->tab_contents()->controller().session_id().id();
36
37    // Register our callback and associate it with our tab.
38    FileDialogFunction::Callback::Add(tab_id_, listener_, html_view, params);
39  }
40
41  // BaseShellDialog implementation.
42
43  virtual bool IsRunning(gfx::NativeWindow owner_window) const {
44    return owner_window_ == owner_window;
45  }
46
47  virtual void ListenerDestroyed() {
48    listener_ = NULL;
49    FileDialogFunction::Callback::Remove(tab_id_);
50  }
51
52  // SelectFileDialog implementation.
53  virtual void set_browser_mode(bool value) {
54    browser_mode_ = value;
55  }
56
57  // HtmlDialogUIDelegate implementation.
58
59  virtual bool IsDialogModal() const {
60    return true;
61  }
62
63  virtual std::wstring GetDialogTitle() const {
64    return title_;
65  }
66
67  virtual GURL GetDialogContentURL() const {
68    return dialog_url_;
69  }
70
71  virtual void GetWebUIMessageHandlers(
72      std::vector<WebUIMessageHandler*>* handlers) const {
73  }
74
75  // Get the size of the dialog.
76  virtual void GetDialogSize(gfx::Size* size) const {
77    size->set_width(720);
78    size->set_height(580);
79  }
80
81  virtual std::string GetDialogArgs() const {
82    return "";
83  }
84
85  // A callback to notify the delegate that the dialog closed.
86  virtual void OnDialogClosed(const std::string& json_retval) {
87    owner_window_ = NULL;
88  }
89
90  virtual void OnWindowClosed() {
91    // Directly closing the window selects no files.
92    const FileDialogFunction::Callback& callback =
93        FileDialogFunction::Callback::Find(tab_id_);
94    if (!callback.IsNull())
95      callback.listener()->FileSelectionCanceled(callback.params());
96  }
97
98  // A callback to notify the delegate that the contents have gone
99  // away. Only relevant if your dialog hosts code that calls
100  // windows.close() and you've allowed that.  If the output parameter
101  // is set to true, then the dialog is closed.  The default is false.
102  virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) {
103    *out_close_dialog = true;
104  }
105
106  // A callback to allow the delegate to dictate that the window should not
107  // have a title bar.  This is useful when presenting branded interfaces.
108  virtual bool ShouldShowDialogTitle() const {
109    return false;
110  }
111
112  // A callback to allow the delegate to inhibit context menu or show
113  // customized menu.
114  virtual bool HandleContextMenu(const ContextMenuParams& params) {
115    return true;
116  }
117
118 protected:
119  // SelectFileDialog implementation.
120  virtual void SelectFileImpl(Type type,
121                              const string16& title,
122                              const FilePath& default_path,
123                              const FileTypeInfo* file_types,
124                              int file_type_index,
125                              const FilePath::StringType& default_extension,
126                              gfx::NativeWindow owning_window,
127                              void* params);
128
129 private:
130  virtual ~FileManagerDialog() {}
131
132  int32 tab_id_;
133
134  // True when opening in browser, otherwise in OOBE/login mode.
135  bool browser_mode_;
136
137  gfx::NativeWindow owner_window_;
138
139  std::wstring title_;
140
141  // Base url plus query string.
142  GURL dialog_url_;
143
144  DISALLOW_COPY_AND_ASSIGN(FileManagerDialog);
145};
146
147// Linking this implementation of SelectFileDialog::Create into the target
148// selects FileManagerDialog as the dialog of choice.
149// static
150SelectFileDialog* SelectFileDialog::Create(Listener* listener) {
151  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
152  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
153  return new FileManagerDialog(listener);
154}
155
156FileManagerDialog::FileManagerDialog(Listener* listener)
157    : SelectFileDialog(listener),
158      tab_id_(0),
159      browser_mode_(true),
160      owner_window_(0) {
161}
162
163void FileManagerDialog::SelectFileImpl(
164    Type type,
165    const string16& title,
166    const FilePath& default_path,
167    const FileTypeInfo* file_types,
168    int file_type_index,
169    const FilePath::StringType& default_extension,
170    gfx::NativeWindow owner_window,
171    void* params) {
172
173  if (owner_window_) {
174    LOG(ERROR) << "File dialog already in use!";
175    return;
176  }
177
178  title_ = UTF16ToWide(title);
179  owner_window_ = owner_window;
180
181  dialog_url_ = FileManagerUtil::GetFileBrowserUrlWithParams(type, title,
182      default_path, file_types, file_type_index, default_extension);
183
184  if (browser_mode_) {
185    Browser* browser = BrowserList::GetLastActive();
186    if (browser) {
187      DCHECK_EQ(browser->type(), Browser::TYPE_NORMAL);
188      CreateHtmlDialogView(browser->profile(), params);
189      return;
190    }
191  }
192
193  BrowserThread::PostTask(
194      BrowserThread::UI,
195      FROM_HERE,
196      NewRunnableMethod(this,
197                        &FileManagerDialog::CreateHtmlDialogView,
198                        ProfileManager::GetDefaultProfile(), params));
199}
200
201