select_file_dialog_impl_kde.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/nix/mime_util_xdg.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/nix/xdg_util.h"
13bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/libgtk2ui/select_file_dialog_impl.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_strings.h"
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window_tree_host.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These conflict with base/tracked_objects.h, so need to come last.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gdk/gdkx.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetTitle(const std::string& title, int message_id) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return title.empty() ? l10n_util::GetStringUTF8(message_id) : title;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kKdialogBinary[] = "kdialog";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace libgtk2ui {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of SelectFileDialog that shows a KDE common dialog for
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// choosing a file or folder. This acts as a modal dialog.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SelectFileDialogImplKDE : public SelectFileDialogImpl {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectFileDialogImplKDE(Listener* listener,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ui::SelectFilePolicy* policy,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          base::nix::DesktopEnvironment desktop);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SelectFileDialogImplKDE();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SelectFileDialog implementation.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |params| is user data we pass back via the Listener interface.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SelectFileImpl(
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Type type,
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const base::string16& title,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& default_path,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const FileTypeInfo* file_types,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int file_type_index,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath::StringType& default_extension,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::NativeWindow owning_window,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      void* params) OVERRIDE;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct KDialogParams {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    KDialogParams(const std::string& type, const std::string& title,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  const base::FilePath& default_path, gfx::NativeWindow parent,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  bool file_operation, bool multiple_selection,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  void* kdialog_params,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  void (SelectFileDialogImplKDE::*callback)(const std::string&,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                            int, void*))
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : type(type), title(title), default_path(default_path), parent(parent),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file_operation(file_operation),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          multiple_selection(multiple_selection),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kdialog_params(kdialog_params), callback(callback) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string type;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string title;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath default_path;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow parent;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool file_operation;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool multiple_selection;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* kdialog_params;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void (SelectFileDialogImplKDE::*callback)(const std::string&, int, void*);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the filters from |file_types_| and concatenate them into
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |filter_string|.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetMimeTypeFilterString();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get KDialog command line representing the Argv array for KDialog.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetKDialogCommandLine(const std::string& type, const std::string& title,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& default_path, gfx::NativeWindow parent,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool file_operation, bool multiple_selection, CommandLine* command_line);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call KDialog on the FILE thread and post results back to the UI thread.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CallKDialogOutput(const KDialogParams& params);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the listener that a single file was chosen.
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void FileSelected(const base::FilePath& path, void* params);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the listener that multiple files were chosen.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void MultiFilesSelected(const std::vector<base::FilePath>& files,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          void* params);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the listener that no file was chosen (the action was canceled).
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dialog is passed so we can find that |params| pointer that was passed to
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // us when we were told to show the dialog.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FileNotSelected(void *params);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void CreateSelectFolderDialog(Type type,
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                const std::string& title,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const base::FilePath& default_path,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                gfx::NativeWindow parent, void* params);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateFileOpenDialog(const std::string& title,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const base::FilePath& default_path,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  gfx::NativeWindow parent, void* params);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateMultiFileOpenDialog(const std::string& title,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::FilePath& default_path,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 gfx::NativeWindow parent, void* params);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateSaveAsDialog(const std::string& title,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const base::FilePath& default_path,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          gfx::NativeWindow parent, void* params);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Common function for OnSelectSingleFileDialogResponse and
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnSelectSingleFolderDialogResponse.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SelectSingleFileHelper(const std::string& output, int exit_code,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              void* params, bool allow_folder);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSelectSingleFileDialogResponse(const std::string& output,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int exit_code, void* params);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSelectMultiFileDialogResponse(const std::string& output,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       int exit_code, void* params);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSelectSingleFolderDialogResponse(const std::string& output,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int exit_code, void* params);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should be either DESKTOP_ENVIRONMENT_KDE3 or DESKTOP_ENVIRONMENT_KDE4.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::nix::DesktopEnvironment desktop_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImplKDE);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelectFileDialogImpl::CheckKDEDialogWorksOnUIThread() {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No choice. UI thread can't continue without an answer here. Fortunately we
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only do this once, the first time a file dialog is displayed.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringVector cmd_vector;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_vector.push_back(kKdialogBinary);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_vector.push_back("--version");
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine command_line(cmd_vector);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dummy;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::GetAppOutput(command_line, &dummy);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogImpl* SelectFileDialogImpl::NewSelectFileDialogImplKDE(
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Listener* listener,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::SelectFilePolicy* policy,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::nix::DesktopEnvironment desktop) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new SelectFileDialogImplKDE(listener, policy, desktop);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogImplKDE::SelectFileDialogImplKDE(
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Listener* listener,
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::SelectFilePolicy* policy,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::nix::DesktopEnvironment desktop)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : SelectFileDialogImpl(listener, policy),
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      desktop_(desktop) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE3 ||
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE4);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SelectFileDialogImplKDE::~SelectFileDialogImplKDE() {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We ignore |default_extension|.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::SelectFileImpl(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Type type,
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& title,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_path,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FileTypeInfo* file_types,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int file_type_index,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath::StringType& default_extension,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow owning_window,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* params) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type_ = type;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |owning_window| can be null when user right-clicks on a downloadable item
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and chooses 'Open Link in New Tab' when 'Ask where to save each file
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before downloading.' preference is turned on. (http://crbug.com/29213)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (owning_window)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parents_.insert(owning_window);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string title_string = base::UTF16ToUTF8(title);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_index_ = file_type_index;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_types)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_types_ = *file_types;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_types_.include_all_files = true;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_FOLDER:
214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case SELECT_UPLOAD_FOLDER:
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      CreateSelectFolderDialog(type, title_string, default_path,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               owning_window, params);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_OPEN_FILE:
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateFileOpenDialog(title_string, default_path, owning_window,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           params);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_OPEN_MULTI_FILE:
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMultiFileOpenDialog(title_string, default_path,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                owning_window, params);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SELECT_SAVEAS_FILE:
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateSaveAsDialog(title_string, default_path, owning_window,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         params);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SelectFileDialogImplKDE::HasMultipleFileTypeChoicesImpl() {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file_types_.extensions.size() > 1;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string SelectFileDialogImplKDE::GetMimeTypeFilterString() {
241e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filter_string;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need a filter set because the same mime type can appear multiple times.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> filter_set;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!file_types_.extensions[i][j].empty()) {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::string mime_type = base::nix::GetFileMimeType(base::FilePath(
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name").ReplaceExtension(file_types_.extensions[i][j]));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        filter_set.insert(mime_type);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the *.* filter, but only if we have added other filters (otherwise it
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is implied).
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_types_.include_all_files && !file_types_.extensions.empty())
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filter_set.insert("application/octet-stream");
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the final output string.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_string.clear();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<std::string>::iterator it = filter_set.begin();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != filter_set.end(); ++it) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filter_string.append(*it + " ");
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return filter_string;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CallKDialogOutput(const KDialogParams& params) {
268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine::StringVector cmd_vector;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cmd_vector.push_back(kKdialogBinary);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine command_line(cmd_vector);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetKDialogCommandLine(params.type, params.title, params.default_path,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        params.parent, params.file_operation,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        params.multiple_selection, &command_line);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int exit_code;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get output from KDialog
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::GetAppOutputWithExitCode(command_line, &output, &exit_code);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!output.empty())
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output.erase(output.size() - 1);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now the dialog is no longer showing. We can erase its parent from the
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parent set.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erg): FIX THIS.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // std::set<GtkWindow*>::iterator iter = parents_.find(params.parent);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if (iter != parents_.end())
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   parents_.erase(iter);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(params.callback, this, output, exit_code,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 params.kdialog_params));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::GetKDialogCommandLine(const std::string& type,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& path,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow parent, bool file_operation, bool multiple_selection,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine* command_line) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(command_line);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attach to the current Chrome window.
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int window_id = parent->GetHost()->GetAcceleratedWidget();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_line->AppendSwitchNative(
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE3 ? "--embed" : "--attach",
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::IntToString(window_id));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the correct title for the dialog.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!title.empty())
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitchNative("--title", title);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enable multiple file selection if we need to.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (multiple_selection) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitch("--multiple");
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitch("--separate-output");
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command_line->AppendSwitch(type);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path should never be empty. If it is, set it to PWD.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path.empty())
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    command_line->AppendArgPath(base::FilePath("."));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendArgPath(path);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Depending on the type of the operation we need, get the path to the
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file/folder and set up mime type filters.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_operation)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendArg(GetMimeTypeFilterString());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "KDialog command line: " << command_line->GetCommandLineString();
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SelectFileDialogImplKDE::FileSelected(const base::FilePath& path,
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           void* params) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type_ == SELECT_SAVEAS_FILE)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *last_saved_path_ = path.DirName();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (type_ == SELECT_OPEN_FILE)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *last_opened_path_ = path.DirName();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (type_ == SELECT_FOLDER)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *last_opened_path_ = path;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_) {  // What does the filter index actually do?
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(dfilimon): Get a reasonable index value from somewhere.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->FileSelected(path, 1, params);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::MultiFilesSelected(
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<base::FilePath>& files, void* params) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *last_opened_path_ = files[0].DirName();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->MultiFilesSelected(files, params);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::FileNotSelected(void* params) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listener_)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listener_->FileSelectionCanceled(params);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateSelectFolderDialog(
356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Type type, const std::string& title, const base::FilePath& default_path,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow parent, void *params) {
358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int title_message_id = (type == SELECT_UPLOAD_FOLDER)
359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE
360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      : IDS_SELECT_FOLDER_DIALOG_TITLE;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getexistingdirectory",
368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)              GetTitle(title, title_message_id),
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_opened_path_ : default_path,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, false, false, params,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse)));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateFileOpenDialog(
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& default_path,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow parent, void* params) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getopenfilename",
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_opened_path_ : default_path,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, true, false, params,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse)));
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateMultiFileOpenDialog(
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& default_path,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow parent, void* params) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getopenfilename",
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE),
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_opened_path_ : default_path,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, true, true, params,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse)));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::CreateSaveAsDialog(
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& title, const base::FilePath& default_path,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow parent, void* params) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SelectFileDialogImplKDE::CallKDialogOutput,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          this,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KDialogParams(
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "--getsavefilename",
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE),
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              default_path.empty() ? *last_saved_path_ : default_path,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parent, true, false, params,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse)));
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::SelectSingleFileHelper(const std::string& output,
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int exit_code, void* params, bool allow_folder) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "[kdialog] SingleFileResponse: " << output;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exit_code != 0 || output.empty()) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(output);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allow_folder) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileSelected(path, params);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CallDirectoryExistsOnUIThread(path))
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileSelected(path, params);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse(
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& output, int exit_code, void* params) {
444e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectSingleFileHelper(output, exit_code, params, false);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse(
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& output, int exit_code, void* params) {
450e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectSingleFileHelper(output, exit_code, params, true);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse(
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& output, int exit_code, void* params) {
456e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "[kdialog] MultiFileResponse: " << output;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (exit_code != 0 || output.empty()) {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> filenames;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tokenize(output, "\n", &filenames);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath> filenames_fp;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<std::string>::iterator iter = filenames.begin();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != filenames.end(); ++iter) {
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath path(*iter);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CallDirectoryExistsOnUIThread(path))
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filenames_fp.push_back(path);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filenames_fp.empty()) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FileNotSelected(params);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MultiFilesSelected(filenames_fp, params);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace libgtk2ui
483