Browse Source

fix: use async save dialog for anchor download attribute (#16640)

trop[bot] 6 years ago
parent
commit
4d7ddcd750

+ 59 - 21
atom/browser/atom_download_manager_delegate.cc

@@ -100,23 +100,58 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
   if (relay)
     window = relay->GetNativeWindow();
 
-  auto* web_preferences = WebContentsPreferences::From(web_contents);
-  bool offscreen =
-      !web_preferences || web_preferences->IsEnabled(options::kOffscreen);
-
+  // Show save dialog if save path was not set already on item
   base::FilePath path;
   GetItemSavePath(item, &path);
-  // Show save dialog if save path was not set already on item
-  file_dialog::DialogSettings settings;
-  GetItemSaveDialogOptions(item, &settings);
-  if (!settings.parent_window)
-    settings.parent_window = window;
-  settings.force_detached = offscreen;
-  if (settings.title.size() == 0)
-    settings.title = item->GetURL().spec();
-  if (!settings.default_path.empty())
-    settings.default_path = default_path;
-  if (path.empty() && file_dialog::ShowSaveDialog(settings, &path)) {
+  if (path.empty()) {
+    file_dialog::DialogSettings settings;
+    GetItemSaveDialogOptions(item, &settings);
+
+    if (!settings.parent_window)
+      settings.parent_window = window;
+    if (settings.title.size() == 0)
+      settings.title = item->GetURL().spec();
+    if (!settings.default_path.empty())
+      settings.default_path = default_path;
+
+    auto* web_preferences = WebContentsPreferences::From(web_contents);
+    const bool offscreen =
+        !web_preferences || web_preferences->IsEnabled(options::kOffscreen);
+    settings.force_detached = offscreen;
+
+    auto dialog_callback =
+        base::Bind(&AtomDownloadManagerDelegate::OnDownloadSaveDialogDone,
+                   base::Unretained(this), download_id, callback);
+    file_dialog::ShowSaveDialog(settings, dialog_callback);
+  } else {
+    callback.Run(path, download::DownloadItem::TARGET_DISPOSITION_PROMPT,
+                 download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path,
+                 download::DOWNLOAD_INTERRUPT_REASON_NONE);
+  };
+}
+
+#if defined(MAS_BUILD)
+void AtomDownloadManagerDelegate::OnDownloadSaveDialogDone(
+    uint32_t download_id,
+    const content::DownloadTargetCallback& download_callback,
+    bool result,
+    const base::FilePath& path,
+    const std::string& bookmark)
+#else
+void AtomDownloadManagerDelegate::OnDownloadSaveDialogDone(
+    uint32_t download_id,
+    const content::DownloadTargetCallback& download_callback,
+    bool result,
+    const base::FilePath& path)
+#endif
+{
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  auto* item = download_manager_->GetDownload(download_id);
+  if (!item)
+    return;
+
+  if (result) {
     // Remember the last selected download directory.
     AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
         download_manager_->GetBrowserContext());
@@ -133,12 +168,15 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
   }
 
   // Running the DownloadTargetCallback with an empty FilePath signals that the
-  // download should be cancelled.
-  // If user cancels the file save dialog, run the callback with empty FilePath.
-  callback.Run(path, download::DownloadItem::TARGET_DISPOSITION_PROMPT,
-               download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path,
-               path.empty() ? download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
-                            : download::DOWNLOAD_INTERRUPT_REASON_NONE);
+  // download should be cancelled. If user cancels the file save dialog, run
+  // the callback with empty FilePath.
+  const base::FilePath download_path = result ? path : base::FilePath();
+  const auto interrupt_reason =
+      download_path.empty() ? download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
+                            : download::DOWNLOAD_INTERRUPT_REASON_NONE;
+  download_callback.Run(path, download::DownloadItem::TARGET_DISPOSITION_PROMPT,
+                        download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+                        download_path, interrupt_reason);
 }
 
 void AtomDownloadManagerDelegate::Shutdown() {

+ 19 - 4
atom/browser/atom_download_manager_delegate.h

@@ -25,10 +25,6 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate {
   explicit AtomDownloadManagerDelegate(content::DownloadManager* manager);
   ~AtomDownloadManagerDelegate() override;
 
-  void OnDownloadPathGenerated(uint32_t download_id,
-                               const content::DownloadTargetCallback& callback,
-                               const base::FilePath& default_path);
-
   // content::DownloadManagerDelegate:
   void Shutdown() override;
   bool DetermineDownloadTarget(
@@ -45,6 +41,25 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate {
   void GetItemSaveDialogOptions(download::DownloadItem* item,
                                 file_dialog::DialogSettings* settings);
 
+  void OnDownloadPathGenerated(uint32_t download_id,
+                               const content::DownloadTargetCallback& callback,
+                               const base::FilePath& default_path);
+
+#if defined(MAS_BUILD)
+  void OnDownloadSaveDialogDone(
+      uint32_t download_id,
+      const content::DownloadTargetCallback& download_callback,
+      bool result,
+      const base::FilePath& path,
+      const std::string& bookmark);
+#else
+  void OnDownloadSaveDialogDone(
+      uint32_t download_id,
+      const content::DownloadTargetCallback& download_callback,
+      bool result,
+      const base::FilePath& path);
+#endif
+
   content::DownloadManager* download_manager_;
   base::WeakPtrFactory<AtomDownloadManagerDelegate> weak_ptr_factory_;