172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/shell_dialogs.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_reader.h"
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/sys_string_conversions.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile_manager.h"
164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/browser_dialogs.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/html_dialog_view.h"
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/html_dialog_ui.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/non_client_view.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kKeyNamePath[] = "path";
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kSaveCompletePageIndex = 2;
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}  // namespace
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Implementation of SelectFileDialog that shows an UI for choosing a file
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// or folder using FileBrowseUI.
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SelectFileDialogImpl : public SelectFileDialog {
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit SelectFileDialogImpl(Listener* listener);
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // BaseShellDialog implementation.
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool IsRunning(gfx::NativeWindow parent_window) const;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void ListenerDestroyed();
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void set_browser_mode(bool value) {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_mode_ = value;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen protected:
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // SelectFileDialog implementation.
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // |params| is user data we pass back via the Listener interface.
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void SelectFileImpl(Type type,
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              const string16& title,
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              const FilePath& default_path,
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              const FileTypeInfo* file_types,
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              int file_type_index,
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              const FilePath::StringType& default_extension,
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              gfx::NativeWindow owning_window,
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              void* params);
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~SelectFileDialogImpl();
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  class FileBrowseDelegate : public HtmlDialogUIDelegate {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FileBrowseDelegate(SelectFileDialogImpl* owner,
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       Type type,
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       const std::wstring& title,
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       const FilePath& default_path,
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       const FileTypeInfo* file_types,
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       int file_type_index,
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       const FilePath::StringType& default_extension,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       gfx::NativeWindow parent,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       void* params);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Owner of this FileBrowseDelegate.
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<SelectFileDialogImpl> owner_;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Parent window.
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::NativeWindow parent_;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The type of dialog we are showing the user.
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Type type_;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The dialog title.
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::wstring title_;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Default path of the file dialog.
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FilePath default_path_;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The file filters.
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FileTypeInfo file_types_;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The index of the default selected file filter.
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Note: This starts from 1, not 0.
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int file_type_index_;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Default extension to be added to file if user does not type one.
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FilePath::StringType default_extension_;
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Associated user data.
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* params_;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   private:
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ~FileBrowseDelegate();
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Overridden from HtmlDialogUI::Delegate:
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual bool IsDialogModal() const;
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual std::wstring GetDialogTitle() const;
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual GURL GetDialogContentURL() const;
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    virtual void GetWebUIMessageHandlers(
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        std::vector<WebUIMessageHandler*>* handlers) const;
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual void GetDialogSize(gfx::Size* size) const;
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual std::string GetDialogArgs() const;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual void OnDialogClosed(const std::string& json_retval);
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    virtual bool ShouldShowDialogTitle() const { return true; }
120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    virtual bool HandleContextMenu(const ContextMenuParams& params) {
121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return true;
122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegate);
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  class FileBrowseDelegateHandler : public WebUIMessageHandler {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   public:
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    explicit FileBrowseDelegateHandler(FileBrowseDelegate* delegate);
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // WebUIMessageHandler implementation.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    virtual void RegisterMessages();
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Callback for the "setDialogTitle" message.
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    void HandleSetDialogTitle(const ListValue* args);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   private:
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FileBrowseDelegate* delegate_;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegateHandler);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Notification from FileBrowseDelegate when file browse UI is dismissed.
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnDialogClosed(FileBrowseDelegate* delegate, const std::string& json);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Callback method to open HTML
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OpenHtmlDialog(gfx::NativeWindow owning_window,
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      FileBrowseDelegate* file_browse_delegate);
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The set of all parent windows for which we are currently running dialogs.
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::set<gfx::NativeWindow> parents_;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The set of all FileBrowseDelegate that we are currently running.
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::set<FileBrowseDelegate*> delegates_;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // True when opening in browser, otherwise in OOBE/login mode.
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool browser_mode_;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSelectFileDialog* SelectFileDialog::Create(Listener* listener) {
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return new SelectFileDialogImpl(listener);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSelectFileDialogImpl::SelectFileDialogImpl(Listener* listener)
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : SelectFileDialog(listener),
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      browser_mode_(true) {
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSelectFileDialogImpl::~SelectFileDialogImpl() {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // All dialogs should be dismissed by now.
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(parents_.empty() && delegates_.empty());
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return parent_window && parents_.find(parent_window) != parents_.end();
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SelectFileDialogImpl::ListenerDestroyed() {
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  listener_ = NULL;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SelectFileDialogImpl::SelectFileImpl(
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Type type,
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const string16& title,
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath& default_path,
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FileTypeInfo* file_types,
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int file_type_index,
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath::StringType& default_extension,
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::NativeWindow owning_window,
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* params) {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring title_string;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (title.empty()) {
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int string_id;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (type) {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case SELECT_FOLDER:
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        string_id = IDS_SELECT_FOLDER_DIALOG_TITLE;
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case SELECT_OPEN_FILE:
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case SELECT_OPEN_MULTI_FILE:
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        string_id = IDS_OPEN_FILE_DIALOG_TITLE;
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case SELECT_SAVEAS_FILE:
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        string_id = IDS_SAVE_AS_DIALOG_TITLE;
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    title_string = UTF16ToWide(l10n_util::GetStringUTF16(string_id));
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    title_string = UTF16ToWide(title);
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (owning_window)
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parents_.insert(owning_window);
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FileBrowseDelegate* file_browse_delegate = new FileBrowseDelegate(this,
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      type, title_string, default_path, file_types, file_type_index,
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default_extension, owning_window, params);
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegates_.insert(file_browse_delegate);
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_mode_) {
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Browser* browser = BrowserList::GetLastActive();
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // As SelectFile may be invoked after a delay, it is entirely possible for
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // it be invoked when no browser is around. Silently ignore this case.
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (browser)
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      browser->BrowserShowHtmlDialog(file_browse_delegate, owning_window);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
235731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::UI,
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FROM_HERE,
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this,
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          &SelectFileDialogImpl::OpenHtmlDialog,
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          owning_window,
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          file_browse_delegate));
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SelectFileDialogImpl::OnDialogClosed(FileBrowseDelegate* delegate,
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const std::string& json) {
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Nothing to do if listener_ is gone.
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!listener_)
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool notification_fired = false;
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!json.empty()) {
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_ptr<Value> value(base::JSONReader::Read(json, false));
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Bad json value returned.
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (delegate->type_ == SELECT_OPEN_FILE ||
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          delegate->type_ == SELECT_SAVEAS_FILE ||
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          delegate->type_ == SELECT_FOLDER) {
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        std::string path_string;
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (dict->HasKey(kKeyNamePath) &&
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            dict->GetString(kKeyNamePath, &path_string)) {
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN)
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          FilePath path(base::SysUTF8ToWide(path_string));
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          FilePath path(
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              base::SysWideToNativeMB(base::SysUTF8ToWide(path_string)));
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          listener_->
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              FileSelected(path, kSaveCompletePageIndex, delegate->params_);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          notification_fired = true;
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (delegate->type_ == SELECT_OPEN_MULTI_FILE) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ListValue* paths_value = NULL;
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (dict->HasKey(kKeyNamePath) &&
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            dict->GetList(kKeyNamePath, &paths_value) &&
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            paths_value) {
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::vector<FilePath> paths;
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          paths.reserve(paths_value->GetSize());
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          for (size_t i = 0; i < paths_value->GetSize(); ++i) {
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            std::string path_string;
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            if (paths_value->GetString(i, &path_string) &&
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                !path_string.empty()) {
28772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN)
28872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              FilePath path(base::SysUTF8ToWide(path_string));
28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else
29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              FilePath path(
29172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                  base::SysWideToNativeMB(base::SysUTF8ToWide(path_string)));
29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              paths.push_back(path);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            }
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          listener_->MultiFilesSelected(paths, delegate->params_);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          notification_fired = true;
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Always notify listener when dialog is dismissed.
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!notification_fired)
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    listener_->FileSelectionCanceled(delegate->params_);
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  parents_.erase(delegate->parent_);
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegates_.erase(delegate);
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SelectFileDialogImpl::OpenHtmlDialog(
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::NativeWindow owning_window,
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FileBrowseDelegate* file_browse_delegate) {
31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  browser::ShowHtmlDialog(owning_window,
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                          ProfileManager::GetDefaultProfile(),
31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                          file_browse_delegate);
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSelectFileDialogImpl::FileBrowseDelegate::FileBrowseDelegate(
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SelectFileDialogImpl* owner,
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Type type,
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::wstring& title,
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath& default_path,
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FileTypeInfo* file_types,
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int file_type_index,
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath::StringType& default_extension,
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::NativeWindow parent,
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* params)
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  : owner_(owner),
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parent_(parent),
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    type_(type),
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    title_(title),
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default_path_(default_path),
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_type_index_(file_type_index),
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default_extension_(default_extension),
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    params_(params) {
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (file_types)
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_types_ = *file_types;
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    file_types_.include_all_files = true;
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSelectFileDialogImpl::FileBrowseDelegate::~FileBrowseDelegate() {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SelectFileDialogImpl::FileBrowseDelegate::IsDialogModal() const {
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::wstring SelectFileDialogImpl::FileBrowseDelegate::GetDialogTitle() const {
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return title_;
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL SelectFileDialogImpl::FileBrowseDelegate::GetDialogContentURL() const {
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url_string(chrome::kChromeUIFileBrowseURL);
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GURL(url_string);
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SelectFileDialogImpl::FileBrowseDelegate::GetWebUIMessageHandlers(
36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::vector<WebUIMessageHandler*>* handlers) const {
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  handlers->push_back(new FileBrowseDelegateHandler(
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const_cast<FileBrowseDelegate*>(this)));
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return;
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SelectFileDialogImpl::FileBrowseDelegate::GetDialogSize(
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Size* size) const {
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size->SetSize(320, 240);
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string SelectFileDialogImpl::FileBrowseDelegate::GetDialogArgs() const {
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // SelectFile inputs as json.
37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //   {
37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //     "type"            : "open",   // (or "open_multiple", "save", "folder"
37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //     "all_files"       : true,
38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //     "file_types"      : {
38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //                           "exts" : [ ["htm", "html"], ["txt"] ],
38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //                           "desc" : [ "HTML files", "Text files" ],
38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //                         },
38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //     "file_type_index" : 1,    // 1-based file type index.
38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //   }
38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // See browser/ui/shell_dialogs.h for more details.
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string type_string;
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type_) {
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SELECT_FOLDER:
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      type_string = "folder";
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SELECT_OPEN_FILE:
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      type_string = "open";
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SELECT_OPEN_MULTI_FILE:
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      type_string = "open_multiple";
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case SELECT_SAVEAS_FILE:
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      type_string = "save";
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return std::string();
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string exts_list;
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string desc_list;
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(!file_types_.extensions[i].empty());
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string exts;
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!exts.empty())
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        exts.append(",");
4164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      base::StringAppendF(&exts, "\"%s\"",
4174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                          file_types_.extensions[i][j].c_str());
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!exts_list.empty())
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exts_list.append(",");
4224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    base::StringAppendF(&exts_list, "[%s]", exts.c_str());
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string desc;
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i < file_types_.extension_description_overrides.size()) {
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      desc = UTF16ToUTF8(file_types_.extension_description_overrides[i]);
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      desc = WideToUTF8(file_types_.extensions[i][0]);
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_POSIX)
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      desc = file_types_.extensions[i][0];
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTIMPLEMENTED();
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!desc_list.empty())
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      desc_list.append(",");
4394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    base::StringAppendF(&desc_list, "\"%s\"", desc.c_str());
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string filename = default_path_.BaseName().value();
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return StringPrintf("{"
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "\"type\":\"%s\","
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "\"all_files\":%s,"
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "\"current_file\":\"%s\","
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "\"file_types\":{\"exts\":[%s],\"desc\":[%s]},"
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "\"file_type_index\":%d"
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "}",
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      type_string.c_str(),
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      file_types_.include_all_files ? "true" : "false",
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      filename.c_str(),
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exts_list.c_str(),
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      desc_list.c_str(),
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      file_type_index_);
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SelectFileDialogImpl::FileBrowseDelegate::OnDialogClosed(
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& json_retval) {
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  owner_->OnDialogClosed(this, json_retval);
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return;
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSelectFileDialogImpl::FileBrowseDelegateHandler::FileBrowseDelegateHandler(
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FileBrowseDelegate* delegate)
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : delegate_(delegate) {
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SelectFileDialogImpl::FileBrowseDelegateHandler::RegisterMessages() {
47272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  web_ui_->RegisterMessageCallback("setDialogTitle",
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &FileBrowseDelegateHandler::HandleSetDialogTitle));
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SelectFileDialogImpl::FileBrowseDelegateHandler::HandleSetDialogTitle(
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const ListValue* args) {
478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::wstring new_title = UTF16ToWideHack(ExtractStringValue(args));
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_title != delegate_->title_) {
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delegate_->title_ = new_title;
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Notify the containing view about the title change.
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The current HtmlDialogUIDelegate and HtmlDialogView does not support
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // dynamic title change. We hijacked the mechanism between HTMLDialogUI
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // and HtmlDialogView to get the HtmlDialogView and forced it to update
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // its title.
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(xiyuan): Change this when the infrastructure is improved.
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HtmlDialogUIDelegate** delegate = HtmlDialogUI::GetPropertyAccessor().
48972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        GetProperty(web_ui_->tab_contents()->property_bag());
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HtmlDialogView* containing_view = static_cast<HtmlDialogView*>(*delegate);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(containing_view);
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    containing_view->GetWindow()->UpdateWindowTitle();
494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    containing_view->GetWindow()->non_client_view()->SchedulePaint();
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
497