15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <X11/Xlib.h>
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/nix/mime_util_xdg.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/nix/xdg_util.h"
15bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/libgtk2ui/select_file_dialog_impl.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window_tree_host.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/strings/grit/ui_strings.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These conflict with base/tracked_objects.h, so need to come last.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gdk/gdkx.h>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h>
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetTitle(const std::string& title, int message_id) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return title.empty() ? l10n_util::GetStringUTF8(message_id) : title;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kKdialogBinary[] = "kdialog";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace libgtk2ui {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of SelectFileDialog that shows a KDE common dialog for
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// choosing a file or folder. This acts as a modal dialog.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SelectFileDialogImplKDE : public SelectFileDialogImpl {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectFileDialogImplKDE(Listener* listener,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ui::SelectFilePolicy* policy,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::nix::DesktopEnvironment desktop);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SelectFileDialogImplKDE();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // BaseShellDialog implementation:
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual bool IsRunning(gfx::NativeWindow parent_window) const OVERRIDE;
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SelectFileDialog implementation.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |params| is user data we pass back via the Listener interface.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SelectFileImpl(
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Type type,
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::string16& title,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& default_path,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const FileTypeInfo* file_types,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int file_type_index,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath::StringType& default_extension,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::NativeWindow owning_window,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      void* params) OVERRIDE;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct KDialogParams {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    KDialogParams(const std::string& type, const std::string& title,
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  const base::FilePath& default_path, XID parent,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  bool file_operation, bool multiple_selection,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  void* kdialog_params,
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  void (SelectFileDialogImplKDE::*callback)(XID,
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                            const std::string&,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                            int, void*))
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : type(type), title(title), default_path(default_path), parent(parent),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file_operation(file_operation),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          multiple_selection(multiple_selection),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kdialog_params(kdialog_params), callback(callback) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string type;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string title;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath default_path;
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool file_operation;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool multiple_selection;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* kdialog_params;
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    void (SelectFileDialogImplKDE::*callback)(XID, const std::string&,
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                              int, void*);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the filters from |file_types_| and concatenate them into
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |filter_string|.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetMimeTypeFilterString();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get KDialog command line representing the Argv array for KDialog.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetKDialogCommandLine(const std::string& type, const std::string& title,
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const base::FilePath& default_path, XID parent,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool file_operation, bool multiple_selection, CommandLine* command_line);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call KDialog on the FILE thread and post results back to the UI thread.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CallKDialogOutput(const KDialogParams& params);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the listener that a single file was chosen.
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void FileSelected(const base::FilePath& path, void* params);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the listener that multiple files were chosen.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MultiFilesSelected(const std::vector<base::FilePath>& files,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          void* params);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the listener that no file was chosen (the action was canceled).
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dialog is passed so we can find that |params| pointer that was passed to
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // us when we were told to show the dialog.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FileNotSelected(void *params);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void CreateSelectFolderDialog(Type type,
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                const std::string& title,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const base::FilePath& default_path,
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                XID parent, void* params);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateFileOpenDialog(const std::string& title,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const base::FilePath& default_path,
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                  XID parent, void* params);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateMultiFileOpenDialog(const std::string& title,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::FilePath& default_path,
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                 XID parent, void* params);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateSaveAsDialog(const std::string& title,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const base::FilePath& default_path,
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                          XID parent, void* params);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Common function for OnSelectSingleFileDialogResponse and
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnSelectSingleFolderDialogResponse.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SelectSingleFileHelper(const std::string& output, int exit_code,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              void* params, bool allow_folder);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void OnSelectSingleFileDialogResponse(XID parent,
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                        const std::string& output,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int exit_code, void* params);
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void OnSelectMultiFileDialogResponse(XID parent,
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       const std::string& output,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       int exit_code, void* params);
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void OnSelectSingleFolderDialogResponse(XID parent,
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                          const std::string& output,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int exit_code, void* params);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should be either DESKTOP_ENVIRONMENT_KDE3 or DESKTOP_ENVIRONMENT_KDE4.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::nix::DesktopEnvironment desktop_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // The set of all parent windows for which we are currently running
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // dialogs. This should only be accessed on the UI thread.
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  std::set<XID> parents_;
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImplKDE);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelectFileDialogImpl::CheckKDEDialogWorksOnUIThread() {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No choice. UI thread can't continue without an answer here. Fortunately we
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only do this once, the first time a file dialog is displayed.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringVector cmd_vector;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_vector.push_back(kKdialogBinary);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_vector.push_back("--version");
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine command_line(cmd_vector);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dummy;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::GetAppOutput(command_line, &dummy);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogImpl* SelectFileDialogImpl::NewSelectFileDialogImplKDE(
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Listener* listener,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::SelectFilePolicy* policy,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::nix::DesktopEnvironment desktop) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new SelectFileDialogImplKDE(listener, policy, desktop);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogImplKDE::SelectFileDialogImplKDE(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Listener* listener,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::SelectFilePolicy* policy,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::nix::DesktopEnvironment desktop)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : SelectFileDialogImpl(listener, policy),
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      desktop_(desktop) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE3 ||
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE4);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogImplKDE::~SelectFileDialogImplKDE() {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool SelectFileDialogImplKDE::IsRunning(gfx::NativeWindow parent_window) const {
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
202c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (parent_window && parent_window->GetHost()) {
203c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID xid = parent_window->GetHost()->GetAcceleratedWidget();
204c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return parents_.find(xid) != parents_.end();
205c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return false;
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We ignore |default_extension|.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::SelectFileImpl(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type type,
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& title,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_path,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileTypeInfo* file_types,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int file_type_index,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath::StringType& default_extension,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow owning_window,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* params) {
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = type;
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  XID window_xid = None;
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (owning_window && owning_window->GetHost()) {
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // |owning_window| can be null when user right-clicks on a downloadable item
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // and chooses 'Open Link in New Tab' when 'Ask where to save each file
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // before downloading.' preference is turned on. (http://crbug.com/29213)
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    window_xid = owning_window->GetHost()->GetAcceleratedWidget();
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    parents_.insert(window_xid);
230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string title_string = base::UTF16ToUTF8(title);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_index_ = file_type_index;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_types)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_types_ = *file_types;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_types_.include_all_files = true;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_FOLDER:
242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case SELECT_UPLOAD_FOLDER:
243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      CreateSelectFolderDialog(type, title_string, default_path,
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                               window_xid, params);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_OPEN_FILE:
247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CreateFileOpenDialog(title_string, default_path, window_xid, params);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_OPEN_MULTI_FILE:
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CreateMultiFileOpenDialog(title_string, default_path, window_xid, params);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_SAVEAS_FILE:
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CreateSaveAsDialog(title_string, default_path, window_xid, params);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelectFileDialogImplKDE::HasMultipleFileTypeChoicesImpl() {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file_types_.extensions.size() > 1;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string SelectFileDialogImplKDE::GetMimeTypeFilterString() {
266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filter_string;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need a filter set because the same mime type can appear multiple times.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> filter_set;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!file_types_.extensions[i][j].empty()) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::string mime_type = base::nix::GetFileMimeType(base::FilePath(
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name").ReplaceExtension(file_types_.extensions[i][j]));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        filter_set.insert(mime_type);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the *.* filter, but only if we have added other filters (otherwise it
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is implied).
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_types_.include_all_files && !file_types_.extensions.empty())
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filter_set.insert("application/octet-stream");
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the final output string.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_string.clear();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::iterator it = filter_set.begin();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != filter_set.end(); ++it) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filter_string.append(*it + " ");
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return filter_string;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CallKDialogOutput(const KDialogParams& params) {
293e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringVector cmd_vector;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_vector.push_back(kKdialogBinary);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine command_line(cmd_vector);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetKDialogCommandLine(params.type, params.title, params.default_path,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        params.parent, params.file_operation,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        params.multiple_selection, &command_line);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get output from KDialog
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::GetAppOutputWithExitCode(command_line, &output, &exit_code);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!output.empty())
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output.erase(output.size() - 1);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
307c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Now the dialog is no longer showing, but we can't erase its parent from the
308c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // parent set yet because we're on the FILE thread.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
311c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::Bind(params.callback, this, params.parent, output, exit_code,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 params.kdialog_params));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::GetKDialogCommandLine(const std::string& type,
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& path,
317c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, bool file_operation, bool multiple_selection,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine* command_line) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(command_line);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attach to the current Chrome window.
322c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (parent != None) {
323c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    command_line->AppendSwitchNative(
324c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE3 ?
325c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            "--embed" : "--attach",
326c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        base::IntToString(parent));
327c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
328c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the correct title for the dialog.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!title.empty())
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitchNative("--title", title);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enable multiple file selection if we need to.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (multiple_selection) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitch("--multiple");
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitch("--separate-output");
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_line->AppendSwitch(type);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path should never be empty. If it is, set it to PWD.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path.empty())
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    command_line->AppendArgPath(base::FilePath("."));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendArgPath(path);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Depending on the type of the operation we need, get the path to the
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file/folder and set up mime type filters.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_operation)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendArg(GetMimeTypeFilterString());
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "KDialog command line: " << command_line->GetCommandLineString();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SelectFileDialogImplKDE::FileSelected(const base::FilePath& path,
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           void* params) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type_ == SELECT_SAVEAS_FILE)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *last_saved_path_ = path.DirName();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (type_ == SELECT_OPEN_FILE)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *last_opened_path_ = path.DirName();
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else if (type_ == SELECT_FOLDER || type_ == SELECT_UPLOAD_FOLDER)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *last_opened_path_ = path;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_) {  // What does the filter index actually do?
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(dfilimon): Get a reasonable index value from somewhere.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->FileSelected(path, 1, params);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::MultiFilesSelected(
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<base::FilePath>& files, void* params) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *last_opened_path_ = files[0].DirName();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->MultiFilesSelected(files, params);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::FileNotSelected(void* params) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->FileSelectionCanceled(params);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateSelectFolderDialog(
379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Type type, const std::string& title, const base::FilePath& default_path,
380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, void *params) {
381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int title_message_id = (type == SELECT_UPLOAD_FOLDER)
382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE
383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      : IDS_SELECT_FOLDER_DIALOG_TITLE;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getexistingdirectory",
391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              GetTitle(title, title_message_id),
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_opened_path_ : default_path,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, false, false, params,
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse)));
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateFileOpenDialog(
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& default_path,
399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, void* params) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getopenfilename",
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_opened_path_ : default_path,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, true, false, params,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse)));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateMultiFileOpenDialog(
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& default_path,
415c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, void* params) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getopenfilename",
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE),
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_opened_path_ : default_path,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, true, true, params,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse)));
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateSaveAsDialog(
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& default_path,
431c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, void* params) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getsavefilename",
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE),
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_saved_path_ : default_path,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, true, false, params,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse)));
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::SelectSingleFileHelper(const std::string& output,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int exit_code, void* params, bool allow_folder) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "[kdialog] SingleFileResponse: " << output;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exit_code != 0 || output.empty()) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(output);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_folder) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileSelected(path, params);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CallDirectoryExistsOnUIThread(path))
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileSelected(path, params);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse(
466c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, const std::string& output, int exit_code, void* params) {
467e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
468c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  parents_.erase(parent);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectSingleFileHelper(output, exit_code, params, false);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse(
473c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, const std::string& output, int exit_code, void* params) {
474e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
475c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  parents_.erase(parent);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectSingleFileHelper(output, exit_code, params, true);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse(
480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    XID parent, const std::string& output, int exit_code, void* params) {
481e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "[kdialog] MultiFileResponse: " << output;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  parents_.erase(parent);
485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exit_code != 0 || output.empty()) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> filenames;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tokenize(output, "\n", &filenames);
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> filenames_fp;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<std::string>::iterator iter = filenames.begin();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != filenames.end(); ++iter) {
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath path(*iter);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CallDirectoryExistsOnUIThread(path))
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filenames_fp.push_back(path);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filenames_fp.empty()) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiFilesSelected(filenames_fp, params);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace libgtk2ui
510