diff --git a/atom/browser/atom_download_manager_delegate.cc b/atom/browser/atom_download_manager_delegate.cc index 63ca5f661f98..68095c11e11a 100644 --- a/atom/browser/atom_download_manager_delegate.cc +++ b/atom/browser/atom_download_manager_delegate.cc @@ -35,6 +35,17 @@ AtomDownloadManagerDelegate::~AtomDownloadManagerDelegate() { } } +void AtomDownloadManagerDelegate::GetItemSavePath(content::DownloadItem* item, + base::FilePath* path) { + 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) + *path = download->GetSavePath(); +} + void AtomDownloadManagerDelegate::CreateDownloadPath( const GURL& url, const std::string& content_disposition, @@ -77,9 +88,12 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated( window = relay->window.get(); base::FilePath path; - if (file_dialog::ShowSaveDialog(window, item->GetURL().spec(), - "", default_path, - file_dialog::Filters(), &path)) { + GetItemSavePath(item, &path); + // Show save dialog if save path was not set already on item + if (path.empty() && file_dialog::ShowSaveDialog(window, item->GetURL().spec(), + "", default_path, + file_dialog::Filters(), + &path)) { // Remember the last selected download directory. AtomBrowserContext* browser_context = static_cast( download_manager_->GetBrowserContext()); @@ -122,22 +136,14 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget( } // Try to get the save path from JS wrapper. - { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Locker locker(isolate); - v8::HandleScope handle_scope(isolate); - api::DownloadItem* download_item = api::DownloadItem::FromWrappedClass( - isolate, download); - if (download_item) { - base::FilePath save_path = download_item->GetSavePath(); - if (!save_path.empty()) { - callback.Run(save_path, - content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - save_path); - return true; - } - } + base::FilePath save_path; + GetItemSavePath(download, &save_path); + if (!save_path.empty()) { + callback.Run(save_path, + content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + save_path); + return true; } AtomBrowserContext* browser_context = static_cast( diff --git a/atom/browser/atom_download_manager_delegate.h b/atom/browser/atom_download_manager_delegate.h index 5ea3d50d5aee..d23872129422 100644 --- a/atom/browser/atom_download_manager_delegate.h +++ b/atom/browser/atom_download_manager_delegate.h @@ -46,6 +46,9 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate { void GetNextId(const content::DownloadIdCallback& callback) override; private: + // Get the save path set on the associated api::DownloadItem object + void GetItemSavePath(content::DownloadItem* item, base::FilePath* path); + content::DownloadManager* download_manager_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index 5440ff29b844..1caa08d1219e 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -319,6 +319,17 @@ describe('session module', function () { }) }) }) + + describe('when a save path is specified and the URL is unavailable', function () { + it('does not display a save dialog and reports the done state as interrupted', function (done) { + ipcRenderer.sendSync('set-download-option', false, false) + ipcRenderer.once('download-done', (event, state) => { + assert.equal(state, 'interrupted') + done() + }) + w.webContents.downloadURL('file://' + path.join(__dirname, 'does-not-exist.txt')) + }) + }) }) describe('ses.protocol', function () {