// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/shell_dialogs/select_file_dialog_win.h"

#include <algorithm>
#include <memory>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/registry.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/shell_dialogs/base_shell_dialog_win.h"
#include "ui/shell_dialogs/execute_select_file_win.h"
#include "ui/shell_dialogs/select_file_policy.h"
#include "ui/strings/grit/ui_strings.h"

namespace ui {

namespace {

// Get the file type description from the registry. This will be "Text Document"
// for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't
// have an entry for the file type, we return false, true if the description was
// found. 'file_ext' must be in form ".txt".
bool GetRegistryDescriptionFromExtension(const base::string16& file_ext,
                                         base::string16* reg_description) {
  DCHECK(reg_description);
  base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
  base::string16 reg_app;
  if (reg_ext.ReadValue(NULL, &reg_app) == ERROR_SUCCESS && !reg_app.empty()) {
    base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
    if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS)
      return true;
  }
  return false;
}

// Set up a filter for a Save/Open dialog, |ext_desc| as the text descriptions
// of the |file_ext| types (optional), and (optionally) the default 'All Files'
// view. The purpose of the filter is to show only files of a particular type in
// a Windows Save/Open dialog box. The resulting filter is returned. The filter
// created here are:
//   1. only files that have 'file_ext' as their extension
//   2. all files (only added if 'include_all_files' is true)
// If a description is not provided for a file extension, it will be retrieved
// from the registry. If the file extension does not exist in the registry, a
// default description will be created (e.g. "qqq" yields "QQQ File").
std::vector<FileFilterSpec> FormatFilterForExtensions(
    const std::vector<base::string16>& file_ext,
    const std::vector<base::string16>& ext_desc,
    bool include_all_files) {
  const base::string16 all_ext = L"*.*";
  const base::string16 all_desc =
      l10n_util::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES);

  DCHECK(file_ext.size() >= ext_desc.size());

  if (file_ext.empty())
    include_all_files = true;

  std::vector<FileFilterSpec> result;
  result.reserve(file_ext.size() + 1);

  for (size_t i = 0; i < file_ext.size(); ++i) {
    base::string16 ext = file_ext[i];
    base::string16 desc;
    if (i < ext_desc.size())
      desc = ext_desc[i];

    if (ext.empty()) {
      // Force something reasonable to appear in the dialog box if there is no
      // extension provided.
      include_all_files = true;
      continue;
    }

    if (desc.empty()) {
      DCHECK(ext.find(L'.') != base::string16::npos);
      base::string16 first_extension = ext.substr(ext.find(L'.'));
      size_t first_separator_index = first_extension.find(L';');
      if (first_separator_index != base::string16::npos)
        first_extension = first_extension.substr(0, first_separator_index);

      // Find the extension name without the preceeding '.' character.
      base::string16 ext_name = first_extension;
      size_t ext_index = ext_name.find_first_not_of(L'.');
      if (ext_index != base::string16::npos)
        ext_name = ext_name.substr(ext_index);

      if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
        // The extension doesn't exist in the registry. Create a description
        // based on the unknown extension type (i.e. if the extension is .qqq,
        // then we create a description "QQQ File").
        desc = l10n_util::GetStringFUTF16(IDS_APP_SAVEAS_EXTENSION_FORMAT,
                                          base::i18n::ToUpper(ext_name));
        include_all_files = true;
      }
      if (desc.empty())
        desc = L"*." + ext_name;
    }

    result.push_back({desc, ext});
  }

  if (include_all_files)
    result.push_back({all_desc, all_ext});

  return result;
}

// Forwards the result from a select file operation to the SelectFileDialog
// object on the UI thread.
void OnSelectFileExecutedOnDialogTaskRunner(
    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
    OnSelectFileExecutedCallback on_select_file_executed_callback,
    const std::vector<base::FilePath>& paths,
    int index) {
  ui_task_runner->PostTask(
      FROM_HERE, base::BindOnce(std::move(on_select_file_executed_callback),
                                paths, index));
}

// Implementation of SelectFileDialog that shows a Windows common dialog for
// choosing a file or folder.
class SelectFileDialogImpl : public ui::SelectFileDialog,
                             public ui::BaseShellDialogImpl {
 public:
  SelectFileDialogImpl(
      Listener* listener,
      std::unique_ptr<ui::SelectFilePolicy> policy,
      const ExecuteSelectFileCallback& execute_select_file_callback);

  // BaseShellDialog implementation:
  bool IsRunning(gfx::NativeWindow owning_window) const override;
  void ListenerDestroyed() override;

 protected:
  // SelectFileDialog implementation:
  void SelectFileImpl(Type type,
                      const base::string16& title,
                      const base::FilePath& default_path,
                      const FileTypeInfo* file_types,
                      int file_type_index,
                      const base::FilePath::StringType& default_extension,
                      gfx::NativeWindow owning_window,
                      void* params) override;

 private:
  ~SelectFileDialogImpl() override;

  struct SelectFolderDialogOptions {
    const wchar_t* default_path;
    bool is_upload;
  };

  // Returns the result of the select file operation to the listener.
  void OnSelectFileExecuted(Type type,
                            std::unique_ptr<RunState> run_state,
                            void* params,
                            const std::vector<base::FilePath>& paths,
                            int index);

  bool HasMultipleFileTypeChoicesImpl() override;

  // Returns the filter to be used while displaying the open/save file dialog.
  // This is computed from the extensions for the file types being opened.
  // |file_types| can be NULL in which case the returned filter will be empty.
  static std::vector<FileFilterSpec> GetFilterForFileTypes(
      const FileTypeInfo* file_types);

  bool has_multiple_file_type_choices_;
  ExecuteSelectFileCallback execute_select_file_callback_;

  DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
};

SelectFileDialogImpl::SelectFileDialogImpl(
    Listener* listener,
    std::unique_ptr<ui::SelectFilePolicy> policy,
    const ExecuteSelectFileCallback& execute_select_file_callback)
    : SelectFileDialog(listener, std::move(policy)),
      BaseShellDialogImpl(),
      has_multiple_file_type_choices_(false),
      execute_select_file_callback_(execute_select_file_callback) {}

SelectFileDialogImpl::~SelectFileDialogImpl() = default;

// Invokes the |execute_select_file_callback| and returns the result to
void DoSelectFileOnDialogTaskRunner(
    const ExecuteSelectFileCallback& execute_select_file_callback,
    SelectFileDialog::Type type,
    const base::string16& title,
    const base::FilePath& default_path,
    const std::vector<ui::FileFilterSpec>& filter,
    int file_type_index,
    const base::string16& default_extension,
    HWND owner,
    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
    OnSelectFileExecutedCallback on_select_file_executed_callback) {
  execute_select_file_callback.Run(
      type, title, default_path, filter, file_type_index, default_extension,
      owner,
      base::BindOnce(&OnSelectFileExecutedOnDialogTaskRunner,
                     std::move(ui_task_runner),
                     std::move(on_select_file_executed_callback)));
}

void SelectFileDialogImpl::SelectFileImpl(
    Type type,
    const base::string16& title,
    const base::FilePath& default_path,
    const FileTypeInfo* file_types,
    int file_type_index,
    const base::FilePath::StringType& default_extension,
    gfx::NativeWindow owning_window,
    void* params) {
  has_multiple_file_type_choices_ =
      file_types ? file_types->extensions.size() > 1 : true;

  std::vector<FileFilterSpec> filter = GetFilterForFileTypes(file_types);
  HWND owner = owning_window && owning_window->GetRootWindow()
                   ? owning_window->GetHost()->GetAcceleratedWidget()
                   : NULL;

  std::unique_ptr<RunState> run_state = BeginRun(owner);

  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
      run_state->dialog_task_runner;
  task_runner->PostTask(
      FROM_HERE,
      base::BindOnce(&DoSelectFileOnDialogTaskRunner,
                     execute_select_file_callback_, type, title, default_path,
                     filter, file_type_index, default_extension, owner,
                     base::ThreadTaskRunnerHandle::Get(),
                     base::BindOnce(&SelectFileDialogImpl::OnSelectFileExecuted,
                                    this, type, std::move(run_state), params)));
}

bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
  return has_multiple_file_type_choices_;
}

bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow owning_window) const {
  if (!owning_window->GetRootWindow())
    return false;
  HWND owner = owning_window->GetHost()->GetAcceleratedWidget();
  return listener_ && IsRunningDialogForOwner(owner);
}

void SelectFileDialogImpl::ListenerDestroyed() {
  // Our associated listener has gone away, so we shouldn't call back to it if
  // our worker thread returns after the listener is dead.
  listener_ = NULL;
}

void SelectFileDialogImpl::OnSelectFileExecuted(
    Type type,
    std::unique_ptr<RunState> run_state,
    void* params,
    const std::vector<base::FilePath>& paths,
    int index) {
  if (listener_) {
    // The paths vector is empty when the user cancels the dialog.
    if (paths.empty()) {
      listener_->FileSelectionCanceled(params);
    } else {
      switch (type) {
        case SELECT_FOLDER:
        case SELECT_UPLOAD_FOLDER:
        case SELECT_EXISTING_FOLDER:
        case SELECT_SAVEAS_FILE:
        case SELECT_OPEN_FILE:
          DCHECK_EQ(paths.size(), 1u);
          listener_->FileSelected(paths[0], index, params);
          break;
        case SELECT_OPEN_MULTI_FILE:
          listener_->MultiFilesSelected(paths, params);
          break;
        case SELECT_NONE:
          NOTREACHED();
      }
    }
  }

  EndRun(std::move(run_state));
}

// static
std::vector<FileFilterSpec> SelectFileDialogImpl::GetFilterForFileTypes(
    const FileTypeInfo* file_types) {
  if (!file_types)
    return std::vector<FileFilterSpec>();

  std::vector<base::string16> exts;
  for (size_t i = 0; i < file_types->extensions.size(); ++i) {
    const std::vector<base::string16>& inner_exts = file_types->extensions[i];
    base::string16 ext_string;
    for (size_t j = 0; j < inner_exts.size(); ++j) {
      if (!ext_string.empty())
        ext_string.push_back(L';');
      ext_string.append(L"*.");
      ext_string.append(inner_exts[j]);
    }
    exts.push_back(ext_string);
  }
  return FormatFilterForExtensions(exts,
                                   file_types->extension_description_overrides,
                                   file_types->include_all_files);
}

}  // namespace

SelectFileDialog* CreateWinSelectFileDialog(
    SelectFileDialog::Listener* listener,
    std::unique_ptr<SelectFilePolicy> policy,
    const ExecuteSelectFileCallback& execute_select_file_callback) {
  return new SelectFileDialogImpl(listener, std::move(policy),
                                  execute_select_file_callback);
}

SelectFileDialog* CreateSelectFileDialog(
    SelectFileDialog::Listener* listener,
    std::unique_ptr<SelectFilePolicy> policy) {
  return CreateWinSelectFileDialog(listener, std::move(policy),
                                   base::BindRepeating(&ui::ExecuteSelectFile));
}

}  // namespace ui
