Browse Source

Use callback dialog methods in RunFileChooser

Kevin Sawicki 8 years ago
parent
commit
a33ffd621f
1 changed files with 94 additions and 22 deletions
  1. 94 22
      atom/browser/web_dialog_helper.cc

+ 94 - 22
atom/browser/web_dialog_helper.cc

@@ -16,7 +16,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/file_chooser_file_info.h"
@@ -26,6 +28,94 @@
 
 namespace {
 
+class FileSelectHelper : public base::RefCountedThreadSafe<
+                             FileSelectHelper,
+                             content::BrowserThread::DeleteOnUIThread>,
+                         public content::WebContentsObserver {
+ public:
+  FileSelectHelper(content::RenderFrameHost* render_frame_host,
+                   const content::FileChooserParams::Mode& mode)
+      : render_frame_host_(render_frame_host), mode_(mode) {
+    auto web_contents = content::WebContents::FromRenderFrameHost(
+        render_frame_host);
+    content::WebContentsObserver::Observe(web_contents);
+    // Add ref that will be released when the dialog is completed
+    AddRef();
+  }
+
+  void ShowOpenDialog(const file_dialog::DialogSettings& settings) {
+    auto callback = base::Bind(&FileSelectHelper::OnOpenDialogDone,
+                               base::Unretained(this));
+    file_dialog::ShowOpenDialog(settings, callback);
+  }
+
+  void ShowSaveDialog(const file_dialog::DialogSettings& settings) {
+    auto callback = base::Bind(&FileSelectHelper::OnSaveDialogDone,
+                               base::Unretained(this));
+    file_dialog::ShowSaveDialog(settings, callback);
+  }
+
+ private:
+  void OnOpenDialogDone(bool result, const std::vector<base::FilePath>& paths) {
+    std::vector<content::FileChooserFileInfo> file_info;
+    if (result) {
+      for (auto& path : paths) {
+        content::FileChooserFileInfo info;
+        info.file_path = path;
+        info.display_name = path.BaseName().value();
+        file_info.push_back(info);
+      }
+
+      if (!paths.empty()) {
+        auto browser_context = static_cast<atom::AtomBrowserContext*>(
+            render_frame_host_->GetProcess()->GetBrowserContext());
+        browser_context->prefs()->SetFilePath(prefs::kSelectFileLastDirectory,
+                                              paths[0].DirName());
+      }
+    }
+    OnFilesSelected(file_info);
+  }
+
+  void OnSaveDialogDone(bool result, const base::FilePath& path) {
+    std::vector<content::FileChooserFileInfo> file_info;
+    if (result) {
+      content::FileChooserFileInfo info;
+      info.file_path = path;
+      info.display_name = path.BaseName().value();
+      file_info.push_back(info);
+    }
+    OnFilesSelected(file_info);
+  }
+
+  void OnFilesSelected(
+      const std::vector<content::FileChooserFileInfo>& file_info) {
+    if (render_frame_host_)
+      render_frame_host_->FilesSelectedInChooser(file_info, mode_);
+    Release();
+  }
+
+  // content::WebContentsObserver:
+  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
+                              content::RenderFrameHost* new_host) override {
+    if (old_host == render_frame_host_)
+      render_frame_host_ = nullptr;
+  }
+
+  // content::WebContentsObserver:
+  void RenderFrameDeleted(content::RenderFrameHost* deleted_host) override {
+    if (deleted_host == render_frame_host_)
+      render_frame_host_ = nullptr;
+  }
+
+  // content::WebContentsObserver:
+  void WebContentsDestroyed() override {
+    render_frame_host_ = nullptr;
+  }
+
+  content::RenderFrameHost* render_frame_host_;
+  content::FileChooserParams::Mode mode_;
+};
+
 file_dialog::Filters GetFileTypesFromAcceptType(
     const std::vector<base::string16>& accept_types) {
   file_dialog::Filters filters;
@@ -87,15 +177,11 @@ void WebDialogHelper::RunFileChooser(
   settings.parent_window = window_;
   settings.title = base::UTF16ToUTF8(params.title);
 
+  scoped_refptr<FileSelectHelper> file_select_helper(
+      new FileSelectHelper(render_frame_host, params.mode));
   if (params.mode == content::FileChooserParams::Save) {
-    base::FilePath path;
     settings.default_path = params.default_file_name;
-    if (file_dialog::ShowSaveDialog(settings, &path)) {
-      content::FileChooserFileInfo info;
-      info.file_path = path;
-      info.display_name = path.BaseName().value();
-      result.push_back(info);
-    }
+    file_select_helper->ShowSaveDialog(settings);
   } else {
     int flags = file_dialog::FILE_DIALOG_CREATE_DIRECTORY;
     switch (params.mode) {
@@ -111,27 +197,13 @@ void WebDialogHelper::RunFileChooser(
         NOTREACHED();
     }
 
-    std::vector<base::FilePath> paths;
     AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
         window_->web_contents()->GetBrowserContext());
     settings.default_path = browser_context->prefs()->GetFilePath(
         prefs::kSelectFileLastDirectory).Append(params.default_file_name);
     settings.properties = flags;
-    if (file_dialog::ShowOpenDialog(settings, &paths)) {
-      for (auto& path : paths) {
-        content::FileChooserFileInfo info;
-        info.file_path = path;
-        info.display_name = path.BaseName().value();
-        result.push_back(info);
-      }
-      if (!paths.empty()) {
-        browser_context->prefs()->SetFilePath(prefs::kSelectFileLastDirectory,
-                                              paths[0].DirName());
-      }
-    }
+    file_select_helper->ShowOpenDialog(settings);
   }
-
-  render_frame_host->FilesSelectedInChooser(result, params.mode);
 }
 
 void WebDialogHelper::EnumerateDirectory(content::WebContents* web_contents,