Skip to content
This repository has been archived by the owner on Jan 4, 2019. It is now read-only.

Commit

Permalink
Remove electron file_dialog implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdh committed Jan 13, 2018
1 parent 5a48f65 commit 92fc577
Show file tree
Hide file tree
Showing 13 changed files with 319 additions and 1,046 deletions.
6 changes: 2 additions & 4 deletions atom/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ source_set("browser") {
"browser_context_keyed_service_factories.cc",
"browser_context_keyed_service_factories.h",
"browser_observer.h",
"//chrome/browser/extensions/api/file_system/file_entry_picker.cc",
"//chrome/browser/extensions/api/file_system/file_entry_picker.h",
"common_web_contents_delegate.cc",
"common_web_contents_delegate.h",
"javascript_environment.cc",
Expand Down Expand Up @@ -158,7 +160,6 @@ source_set("browser") {
"ui/atom_menu_model.cc",
"ui/atom_menu_model.h",
"ui/drag_util.h",
"ui/file_dialog.h",
"ui/message_box.h",
"ui/tray_icon.cc",
"ui/tray_icon.h",
Expand Down Expand Up @@ -208,7 +209,6 @@ source_set("browser") {
"ui/cocoa/atom_menu_controller.h",
"ui/cocoa/atom_menu_controller.mm",
"ui/drag_util_mac.mm",
"ui/file_dialog_mac.mm",
"ui/message_box_mac.mm",
"ui/tray_icon_cocoa.h",
"ui/tray_icon_cocoa.mm",
Expand Down Expand Up @@ -249,7 +249,6 @@ source_set("browser") {
"browser_win.cc",
"native_window_views_win.cc",
"relauncher_win.cc",
"ui/file_dialog_win.cc",
"ui/message_box_win.cc",
"ui/tray_icon_win.cc",
"ui/win/atom_desktop_window_tree_host_win.cc",
Expand Down Expand Up @@ -278,7 +277,6 @@ source_set("browser") {
sources += [
"browser_linux.cc",
"relauncher_linux.cc",
"ui/file_dialog_gtk.cc",
"ui/message_box_gtk.cc",
"ui/tray_icon_gtk.cc",
"ui/tray_icon_gtk.h",
Expand Down
130 changes: 91 additions & 39 deletions atom/browser/api/atom_api_dialog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,57 @@

#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/ui/message_box.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "base/bind.h"
#include "base/path_service.h"
#include "chrome/browser/extensions/api/file_system/file_entry_picker.h"
#include "chrome/common/chrome_paths.h"
#include "native_mate/dictionary.h"
#include "vendor/brightray/browser/inspectable_web_contents.h"

#include "atom/common/node_includes.h"

namespace file_dialog {

typedef base::Callback<void(
bool result, const std::vector<base::FilePath>& paths)> DialogCallback;

struct DialogSettings {
atom::NativeWindow* parent_window = nullptr;
base::FilePath default_path;
std::vector<std::vector<base::FilePath::StringType>> extensions;
std::vector<base::string16> extension_description_overrides;
ui::SelectFileDialog::Type type;
bool include_all_files = true;
};
} // namespace file_dialog

namespace mate {

template<>
struct Converter<file_dialog::Filter> {
struct Converter<ui::SelectFileDialog::Type> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
file_dialog::Filter* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!dict.Get("name", &(out->first)))
return false;
if (!dict.Get("extensions", &(out->second)))
ui::SelectFileDialog::Type* out) {
std::string type;
if (!ConvertFromV8(isolate, val, &type))
return false;
if (type == "select-folder") {
*out = ui::SelectFileDialog::SELECT_FOLDER;
} else if (type == "select-upload-folder") {
*out = ui::SelectFileDialog::SELECT_UPLOAD_FOLDER;
} else if (type == "select-saveas-file") {
*out = ui::SelectFileDialog::SELECT_SAVEAS_FILE;
} else if (type == "select-open-file") {
*out = ui::SelectFileDialog::SELECT_OPEN_FILE;
} else if (type == "select-open-multi-file") {
*out = ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE;
} else {
*out = ui::SelectFileDialog::SELECT_NONE;
}
return true;
}
};
Expand All @@ -44,11 +72,12 @@ struct Converter<file_dialog::DialogSettings> {
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("window", &(out->parent_window));
dict.Get("title", &(out->title));
dict.Get("buttonLabel", &(out->button_label));
dict.Get("defaultPath", &(out->default_path));
dict.Get("filters", &(out->filters));
dict.Get("properties", &(out->properties));
dict.Get("type", &(out->type));
dict.Get("extensions", &(out->extensions));
dict.Get("extensionDescriptionOverrides",
&(out->extension_description_overrides));
dict.Get("includeAllFiles", &(out->include_all_files));
return true;
}
};
Expand Down Expand Up @@ -84,43 +113,66 @@ void ShowMessageBox(int type,
}
}

void ShowOpenDialog(const file_dialog::DialogSettings& settings,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
file_dialog::OpenDialogCallback callback;
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowOpenDialog(settings, callback);
} else {
std::vector<base::FilePath> paths;
if (file_dialog::ShowOpenDialog(settings, &paths))
args->Return(paths);
}
void OnShowDialogSelected(const file_dialog::DialogCallback& callback,
const std::vector<base::FilePath>& paths) {
DCHECK(!paths.empty());
callback.Run(true, paths);
}

void ShowSaveDialog(const file_dialog::DialogSettings& settings,
mate::Arguments* args) {
void OnShowDialogCancelled(const file_dialog::DialogCallback& callback) {
std::vector<base::FilePath> files;
files.push_back(base::FilePath());
callback.Run(false, files);
}

void ShowDialog(const file_dialog::DialogSettings& settings,
mate::Arguments* args) {
v8::Local<v8::Value> peek = args->PeekNext();
file_dialog::SaveDialogCallback callback;
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowSaveDialog(settings, callback);
} else {
base::FilePath path;
if (file_dialog::ShowSaveDialog(settings, &path))
args->Return(path);
file_dialog::DialogCallback callback;
if (!args->GetNext(&callback)) {
args->ThrowError("`callback` is a required field");
return;
}

ui::SelectFileDialog::FileTypeInfo file_type_info;
for (size_t i = 0; i < settings.extensions.size(); ++i) {
file_type_info.extensions.push_back(settings.extensions[i]);
}
if (file_type_info.extensions.empty()) {
base::FilePath::StringType extension =
settings.default_path.FinalExtension();
if (!extension.empty()) {
file_type_info.extensions.push_back(
std::vector<base::FilePath::StringType>());
extension.erase(extension.begin()); // drop the .
file_type_info.extensions[0].push_back(extension);
}
}

base::FilePath default_path = settings.default_path;
if (default_path.empty()) {
PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &default_path);
}
file_type_info.include_all_files = settings.include_all_files;
file_type_info.extension_description_overrides =
settings.extension_description_overrides;
file_type_info.allowed_paths =
ui::SelectFileDialog::FileTypeInfo::NATIVE_OR_DRIVE_PATH;
new extensions::FileEntryPicker(
settings.parent_window->inspectable_web_contents()->GetWebContents(),
default_path,
file_type_info,
settings.type,
base::Bind(&OnShowDialogSelected, callback),
base::Bind(&OnShowDialogCancelled, callback));
}

void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("showMessageBox", &ShowMessageBox);
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
dict.SetMethod("showDialog", &ShowDialog);
}

} // namespace
Expand Down
98 changes: 73 additions & 25 deletions atom/browser/atom_download_manager_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@
#include "atom/browser/atom_download_manager_delegate.h"

#include <string>
#include <vector>

#include "atom/browser/api/atom_api_download_item.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/file_dialog.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "chrome/browser/extensions/api/file_system/file_entry_picker.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "net/base/filename_util.h"
#include "net/base/mime_util.h"
#include "vendor/brightray/browser/inspectable_web_contents.h"

namespace atom {

Expand Down Expand Up @@ -53,6 +55,50 @@ void AtomDownloadManagerDelegate::GetItemSavePath(content::DownloadItem* item,
*path = download->GetSavePath();
}

bool AtomDownloadManagerDelegate::GetItemExtension(
content::DownloadItem* item,
base::FilePath::StringType* extension) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
api::DownloadItem* download = api::DownloadItem::FromWrappedClass(isolate,
item);
if (download && !download->GetMimeType().empty())
return net::GetPreferredExtensionForMimeType(
download->GetMimeType(), extension);
return false;
}

void AtomDownloadManagerDelegate:: OnDownloadItemSelected(
const content::DownloadTargetCallback& callback,
api::DownloadItem* download_item,
const std::vector<base::FilePath>& paths) {
DCHECK(!paths.empty());
// Remember the last selected download directory.
Profile* profile = static_cast<Profile*>(
download_manager_->GetBrowserContext());
profile->GetPrefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
paths[0].DirName());
if (download_item)
download_item->SetSavePath(paths[0]);

callback.Run(paths[0],
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, paths[0],
content::DOWNLOAD_INTERRUPT_REASON_NONE);
}

void AtomDownloadManagerDelegate::OnDownloadItemSelectionCancelled(
const content::DownloadTargetCallback& callback,
content::DownloadItem* item) {
item->Remove();
base::FilePath path;
callback.Run(path,
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path,
content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
}

void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
int32_t download_id,
const content::DownloadTargetCallback& callback,
Expand Down Expand Up @@ -89,30 +135,32 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
GetItemSavePath(item, &path);

// Show save dialog if save path was not set already on item
file_dialog::DialogSettings settings;
settings.parent_window = window;
settings.title = item->GetURL().spec();
settings.default_path = target_path;
if (path.empty() && file_dialog::ShowSaveDialog(settings, &path)) {
// Remember the last selected download directory.
Profile* profile = static_cast<Profile*>(
download_manager_->GetBrowserContext());
profile->GetPrefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
path.DirName());
ui::SelectFileDialog::FileTypeInfo file_type_info;
if (path.empty()) {
std::vector<base::FilePath::StringType> extensions;
base::FilePath::StringType extension;
if (GetItemExtension(item, &extension)) {
extensions.push_back(extension);
file_type_info.extensions.push_back(extensions);
}
new extensions::FileEntryPicker(
window->inspectable_web_contents()->GetWebContents(),
target_path,
file_type_info,
ui::SelectFileDialog::SELECT_SAVEAS_FILE,
base::Bind(&AtomDownloadManagerDelegate::OnDownloadItemSelected,
base::Unretained(this), callback, download_item),
base::Bind(&AtomDownloadManagerDelegate::OnDownloadItemSelectionCancelled,
base::Unretained(this), callback, item));
} else {
if (download_item)
download_item->SetSavePath(path);

callback.Run(path,
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path,
content::DOWNLOAD_INTERRUPT_REASON_NONE);
}

if (path.empty())
item->Remove();

if (download_item)
download_item->SetSavePath(path);

callback.Run(path,
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path,
path.empty()
? content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
: content::DOWNLOAD_INTERRUPT_REASON_NONE);
}

void AtomDownloadManagerDelegate::Shutdown() {
Expand Down
14 changes: 14 additions & 0 deletions atom/browser/atom_download_manager_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#define ATOM_BROWSER_ATOM_DOWNLOAD_MANAGER_DELEGATE_H_

#include <string>
#include <vector>

#include "atom/browser/api/atom_api_download_item.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/download/download_path_reservation_tracker.h"
#include "content/public/browser/download_manager_delegate.h"
Expand Down Expand Up @@ -42,6 +44,18 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate {
// Get the save path set on the associated api::DownloadItem object
void GetItemSavePath(content::DownloadItem* item, base::FilePath* path);

bool GetItemExtension(content::DownloadItem* item,
base::FilePath::StringType* extension);

void OnDownloadItemSelected(const content::DownloadTargetCallback& callback,
api::DownloadItem* download_item,
const std::vector<base::FilePath>& paths);

void OnDownloadItemSelectionCancelled(
const content::DownloadTargetCallback& callback,
content::DownloadItem* item);


content::DownloadManager* download_manager_;
base::WeakPtrFactory<AtomDownloadManagerDelegate> weak_ptr_factory_;

Expand Down
Loading

0 comments on commit 92fc577

Please sign in to comment.