baa63bfd9276dc658c80f9bd77c63094299c667b
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / runtime_download_manager_delegate.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Copyright (c) 2013 Intel Corporation. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5
6 #include "xwalk/runtime/browser/runtime_download_manager_delegate.h"
7
8 #if defined(OS_WIN)
9 #include <windows.h>
10 #include <commdlg.h>
11 #endif
12
13 #include <string>
14
15 #include "base/bind.h"
16 #include "base/command_line.h"
17 #include "base/file_util.h"
18 #include "base/logging.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "content/public/browser/browser_context.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/download_manager.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/shell/common/shell_switches.h"
26 #include "content/shell/browser/webkit_test_controller.h"
27 #include "net/base/filename_util.h"
28
29 using content::BrowserThread;
30
31 namespace xwalk {
32
33 RuntimeDownloadManagerDelegate::RuntimeDownloadManagerDelegate()
34     : download_manager_(NULL),
35       suppress_prompting_(false) {
36   // Balanced in Shutdown();
37   AddRef();
38 }
39
40 RuntimeDownloadManagerDelegate::~RuntimeDownloadManagerDelegate() {}
41
42 void RuntimeDownloadManagerDelegate::SetDownloadManager(
43     content::DownloadManager* download_manager) {
44   download_manager_ = download_manager;
45 }
46
47 void RuntimeDownloadManagerDelegate::Shutdown() {
48   Release();
49 }
50
51 bool RuntimeDownloadManagerDelegate::DetermineDownloadTarget(
52     content::DownloadItem* download,
53     const content::DownloadTargetCallback& callback) {
54   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
55   // This assignment needs to be here because even at the call to
56   // SetDownloadManager, the system is not fully initialized.
57   if (default_download_path_.empty()) {
58     default_download_path_ = download_manager_->GetBrowserContext()->GetPath().
59         Append(FILE_PATH_LITERAL("Downloads"));
60   }
61
62   if (!download->GetForcedFilePath().empty()) {
63     callback.Run(download->GetForcedFilePath(),
64                  content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
65                  content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
66                  download->GetForcedFilePath());
67     return true;
68   }
69
70   base::FilePath generated_name = net::GenerateFileName(
71       download->GetURL(),
72       download->GetContentDisposition(),
73       base::EmptyString(),
74       download->GetSuggestedFilename(),
75       download->GetMimeType(),
76       "download");
77
78   BrowserThread::PostTask(
79       BrowserThread::FILE,
80       FROM_HERE,
81       base::Bind(
82           &RuntimeDownloadManagerDelegate::GenerateFilename,
83           this, download->GetId(), callback, generated_name,
84           default_download_path_));
85   return true;
86 }
87
88 bool RuntimeDownloadManagerDelegate::ShouldOpenDownload(
89       content::DownloadItem* item,
90       const content::DownloadOpenDelayedCallback& callback) {
91   return true;
92 }
93
94 void RuntimeDownloadManagerDelegate::GetNextId(
95     const content::DownloadIdCallback& callback) {
96   static uint32 next_id = content::DownloadItem::kInvalidId + 1;
97   callback.Run(next_id++);
98 }
99
100 void RuntimeDownloadManagerDelegate::GenerateFilename(
101     uint32 download_id,
102     const content::DownloadTargetCallback& callback,
103     const base::FilePath& generated_name,
104     const base::FilePath& suggested_directory) {
105   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
106   if (!base::PathExists(suggested_directory))
107     base::CreateDirectory(suggested_directory);
108
109   base::FilePath suggested_path(suggested_directory.Append(generated_name));
110   BrowserThread::PostTask(
111       BrowserThread::UI,
112       FROM_HERE,
113       base::Bind(
114           &RuntimeDownloadManagerDelegate::OnDownloadPathGenerated,
115           this, download_id, callback, suggested_path));
116 }
117
118 void RuntimeDownloadManagerDelegate::OnDownloadPathGenerated(
119     uint32 download_id,
120     const content::DownloadTargetCallback& callback,
121     const base::FilePath& suggested_path) {
122   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
123   if (suppress_prompting_) {
124     // Testing exit.
125     callback.Run(suggested_path,
126                  content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
127                  content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
128                  suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")));
129     return;
130   }
131
132   ChooseDownloadPath(download_id, callback, suggested_path);
133 }
134
135 void RuntimeDownloadManagerDelegate::ChooseDownloadPath(
136     uint32 download_id,
137     const content::DownloadTargetCallback& callback,
138     const base::FilePath& suggested_path) {
139   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140   content::DownloadItem* item = download_manager_->GetDownload(download_id);
141   if (!item || (item->GetState() != content::DownloadItem::IN_PROGRESS))
142     return;
143
144   base::FilePath result;
145 #if defined(OS_WIN) && !defined(USE_AURA)
146   std::wstring file_part = base::FilePath(suggested_path).BaseName().value();
147   wchar_t file_name[MAX_PATH];
148   base::wcslcpy(file_name, file_part.c_str(), arraysize(file_name));
149   OPENFILENAME save_as;
150   ZeroMemory(&save_as, sizeof(save_as));
151   save_as.lStructSize = sizeof(OPENFILENAME);
152   save_as.hwndOwner = item->GetWebContents()->GetView()->GetNativeView();
153   save_as.lpstrFile = file_name;
154   save_as.nMaxFile = arraysize(file_name);
155
156   std::wstring directory;
157   if (!suggested_path.empty())
158     directory = suggested_path.DirName().value();
159
160   save_as.lpstrInitialDir = directory.c_str();
161   save_as.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLESIZING |
162                   OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
163
164   if (GetSaveFileName(&save_as))
165     result = base::FilePath(std::wstring(save_as.lpstrFile));
166 #else
167   NOTIMPLEMENTED();
168 #endif
169
170   callback.Run(result, content::DownloadItem::TARGET_DISPOSITION_PROMPT,
171                content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, result);
172 }
173
174 void RuntimeDownloadManagerDelegate::SetDownloadBehaviorForTesting(
175     const base::FilePath& default_download_path) {
176   default_download_path_ = default_download_path;
177   suppress_prompting_ = true;
178 }
179
180 }  // namespace xwalk