1 // Copyright (c) 2015 GitHub, Inc.
2 // Use of this source code is governed by the MIT license that can be
3 // found in the LICENSE file.
5 #include "atom/browser/atom_download_manager_delegate.h"
9 #include "atom/browser/api/atom_api_download_item.h"
10 #include "atom/browser/atom_browser_context.h"
11 #include "atom/browser/native_window.h"
12 #include "atom/browser/ui/file_dialog.h"
13 #include "base/bind.h"
14 #include "base/files/file_util.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/prefs/pref_service.h"
17 #include "content/public/browser/browser_context.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/download_manager.h"
20 #include "net/base/filename_util.h"
21 #include "tizen/common/env_variables.h"
25 AtomDownloadManagerDelegate::AtomDownloadManagerDelegate(
26 content::DownloadManager* manager)
27 : download_manager_(manager),
28 weak_ptr_factory_(this) {}
30 AtomDownloadManagerDelegate::~AtomDownloadManagerDelegate() {
31 if (download_manager_) {
32 DCHECK_EQ(static_cast<content::DownloadManagerDelegate*>(this),
33 download_manager_->GetDelegate());
34 download_manager_->SetDelegate(nullptr);
35 download_manager_ = nullptr;
39 void AtomDownloadManagerDelegate::GetItemSavePath(content::DownloadItem* item,
40 base::FilePath* path) {
41 v8::Isolate* isolate = v8::Isolate::GetCurrent();
42 if (!::tizen::is_single_process)
43 v8::Locker locker(isolate);
44 v8::HandleScope handle_scope(isolate);
45 api::DownloadItem* download = api::DownloadItem::FromWrappedClass(isolate,
48 *path = download->GetSavePath();
51 void AtomDownloadManagerDelegate::CreateDownloadPath(
53 const std::string& content_disposition,
54 const std::string& suggested_filename,
55 const std::string& mime_type,
56 const base::FilePath& default_download_path,
57 const CreateDownloadPathCallback& callback) {
58 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
60 auto generated_name = net::GenerateFileName(url,
67 if (!base::PathExists(default_download_path))
68 base::CreateDirectory(default_download_path);
70 base::FilePath path(default_download_path.Append(generated_name));
71 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
72 base::Bind(callback, path));
75 void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
77 const content::DownloadTargetCallback& callback,
78 const base::FilePath& default_path) {
79 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
81 auto item = download_manager_->GetDownload(download_id);
85 NativeWindow* window = nullptr;
86 content::WebContents* web_contents = item->GetWebContents();
87 auto relay = web_contents ? NativeWindowRelay::FromWebContents(web_contents)
90 window = relay->window.get();
93 GetItemSavePath(item, &path);
94 // Show save dialog if save path was not set already on item
95 file_dialog::DialogSettings settings;
96 settings.parent_window = window;
97 settings.title = item->GetURL().spec();
98 settings.default_path = default_path;
99 if (path.empty() && file_dialog::ShowSaveDialog(settings, &path)) {
100 // Remember the last selected download directory.
101 AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
102 download_manager_->GetBrowserContext());
103 browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
106 v8::Isolate* isolate = v8::Isolate::GetCurrent();
107 if (!::tizen::is_single_process)
108 v8::Locker locker(isolate);
109 v8::HandleScope handle_scope(isolate);
110 api::DownloadItem* download_item = api::DownloadItem::FromWrappedClass(
113 download_item->SetSavePath(path);
116 // Running the DownloadTargetCallback with an empty FilePath signals that the
117 // download should be cancelled.
118 // If user cancels the file save dialog, run the callback with empty FilePath.
120 content::DownloadItem::TARGET_DISPOSITION_PROMPT,
121 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path);
124 void AtomDownloadManagerDelegate::Shutdown() {
125 weak_ptr_factory_.InvalidateWeakPtrs();
126 download_manager_ = nullptr;
129 bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
130 content::DownloadItem* download,
131 const content::DownloadTargetCallback& callback) {
132 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
134 if (!download->GetForcedFilePath().empty()) {
135 callback.Run(download->GetForcedFilePath(),
136 content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
137 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
138 download->GetForcedFilePath());
142 // Try to get the save path from JS wrapper.
143 base::FilePath save_path;
144 GetItemSavePath(download, &save_path);
145 if (!save_path.empty()) {
146 callback.Run(save_path,
147 content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
148 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
153 AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
154 download_manager_->GetBrowserContext());
155 base::FilePath default_download_path = browser_context->prefs()->GetFilePath(
156 prefs::kDownloadDefaultDirectory);
158 CreateDownloadPathCallback download_path_callback =
159 base::Bind(&AtomDownloadManagerDelegate::OnDownloadPathGenerated,
160 weak_ptr_factory_.GetWeakPtr(),
161 download->GetId(), callback);
163 content::BrowserThread::PostTask(
164 content::BrowserThread::FILE, FROM_HERE,
165 base::Bind(&AtomDownloadManagerDelegate::CreateDownloadPath,
166 weak_ptr_factory_.GetWeakPtr(),
168 download->GetContentDisposition(),
169 download->GetSuggestedFilename(),
170 download->GetMimeType(),
171 default_download_path,
172 download_path_callback));
176 bool AtomDownloadManagerDelegate::ShouldOpenDownload(
177 content::DownloadItem* download,
178 const content::DownloadOpenDelayedCallback& callback) {
182 void AtomDownloadManagerDelegate::GetNextId(
183 const content::DownloadIdCallback& callback) {
184 static uint32_t next_id = content::DownloadItem::kInvalidId + 1;
185 callback.Run(next_id++);