Run Tizen Webapps in single process mode
[platform/framework/web/crosswalk-tizen.git] / atom / browser / atom_download_manager_delegate.cc
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.
4
5 #include "atom/browser/atom_download_manager_delegate.h"
6
7 #include <string>
8
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"
22
23 namespace atom {
24
25 AtomDownloadManagerDelegate::AtomDownloadManagerDelegate(
26     content::DownloadManager* manager)
27     : download_manager_(manager),
28       weak_ptr_factory_(this) {}
29
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;
36   }
37 }
38
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,
46                                                                     item);
47   if (download)
48     *path = download->GetSavePath();
49 }
50
51 void AtomDownloadManagerDelegate::CreateDownloadPath(
52     const GURL& url,
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);
59
60   auto generated_name = net::GenerateFileName(url,
61                                               content_disposition,
62                                               std::string(),
63                                               suggested_filename,
64                                               mime_type,
65                                               "download");
66
67   if (!base::PathExists(default_download_path))
68     base::CreateDirectory(default_download_path);
69
70   base::FilePath path(default_download_path.Append(generated_name));
71   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
72                                    base::Bind(callback, path));
73 }
74
75 void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
76     uint32_t download_id,
77     const content::DownloadTargetCallback& callback,
78     const base::FilePath& default_path) {
79   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
80
81   auto item = download_manager_->GetDownload(download_id);
82   if (!item)
83     return;
84
85   NativeWindow* window = nullptr;
86   content::WebContents* web_contents = item->GetWebContents();
87   auto relay = web_contents ? NativeWindowRelay::FromWebContents(web_contents)
88                             : nullptr;
89   if (relay)
90     window = relay->window.get();
91
92   base::FilePath path;
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,
104                                           path.DirName());
105
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(
111         isolate, item);
112     if (download_item)
113       download_item->SetSavePath(path);
114   }
115
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.
119   callback.Run(path,
120                content::DownloadItem::TARGET_DISPOSITION_PROMPT,
121                content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path);
122 }
123
124 void AtomDownloadManagerDelegate::Shutdown() {
125   weak_ptr_factory_.InvalidateWeakPtrs();
126   download_manager_ = nullptr;
127 }
128
129 bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
130     content::DownloadItem* download,
131     const content::DownloadTargetCallback& callback) {
132   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
133
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());
139     return true;
140   }
141
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,
149                  save_path);
150     return true;
151   }
152
153   AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
154       download_manager_->GetBrowserContext());
155   base::FilePath default_download_path = browser_context->prefs()->GetFilePath(
156       prefs::kDownloadDefaultDirectory);
157
158   CreateDownloadPathCallback download_path_callback =
159       base::Bind(&AtomDownloadManagerDelegate::OnDownloadPathGenerated,
160                  weak_ptr_factory_.GetWeakPtr(),
161                  download->GetId(), callback);
162
163   content::BrowserThread::PostTask(
164       content::BrowserThread::FILE, FROM_HERE,
165       base::Bind(&AtomDownloadManagerDelegate::CreateDownloadPath,
166                  weak_ptr_factory_.GetWeakPtr(),
167                  download->GetURL(),
168                  download->GetContentDisposition(),
169                  download->GetSuggestedFilename(),
170                  download->GetMimeType(),
171                  default_download_path,
172                  download_path_callback));
173   return true;
174 }
175
176 bool AtomDownloadManagerDelegate::ShouldOpenDownload(
177     content::DownloadItem* download,
178     const content::DownloadOpenDelayedCallback& callback) {
179   return true;
180 }
181
182 void AtomDownloadManagerDelegate::GetNextId(
183     const content::DownloadIdCallback& callback) {
184   static uint32_t next_id = content::DownloadItem::kInvalidId + 1;
185   callback.Run(next_id++);
186 }
187
188 }  // namespace atom