Upstream version 11.39.252.0
[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::CreateDirectory(suggested_directory)) {
107     LOG(ERROR) << "Failed to create directory: "
108                << suggested_directory.value();
109     return;
110   }
111
112   base::FilePath suggested_path(suggested_directory.Append(generated_name));
113   BrowserThread::PostTask(
114       BrowserThread::UI,
115       FROM_HERE,
116       base::Bind(
117           &RuntimeDownloadManagerDelegate::OnDownloadPathGenerated,
118           this, download_id, callback, suggested_path));
119 }
120
121 void RuntimeDownloadManagerDelegate::OnDownloadPathGenerated(
122     uint32 download_id,
123     const content::DownloadTargetCallback& callback,
124     const base::FilePath& suggested_path) {
125   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
126   if (suppress_prompting_) {
127     // Testing exit.
128     callback.Run(suggested_path,
129                  content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
130                  content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
131                  suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")));
132     return;
133   }
134
135   ChooseDownloadPath(download_id, callback, suggested_path);
136 }
137
138 void RuntimeDownloadManagerDelegate::ChooseDownloadPath(
139     uint32 download_id,
140     const content::DownloadTargetCallback& callback,
141     const base::FilePath& suggested_path) {
142   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143   content::DownloadItem* item = download_manager_->GetDownload(download_id);
144   if (!item || (item->GetState() != content::DownloadItem::IN_PROGRESS))
145     return;
146
147   base::FilePath result;
148 #if defined(OS_WIN) && !defined(USE_AURA)
149   std::wstring file_part = base::FilePath(suggested_path).BaseName().value();
150   wchar_t file_name[MAX_PATH];
151   base::wcslcpy(file_name, file_part.c_str(), arraysize(file_name));
152   OPENFILENAME save_as;
153   ZeroMemory(&save_as, sizeof(save_as));
154   save_as.lStructSize = sizeof(OPENFILENAME);
155   save_as.hwndOwner = item->GetWebContents()->GetView()->GetNativeView();
156   save_as.lpstrFile = file_name;
157   save_as.nMaxFile = arraysize(file_name);
158
159   std::wstring directory;
160   if (!suggested_path.empty())
161     directory = suggested_path.DirName().value();
162
163   save_as.lpstrInitialDir = directory.c_str();
164   save_as.Flags = OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLESIZING |
165                   OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
166
167   if (GetSaveFileName(&save_as))
168     result = base::FilePath(std::wstring(save_as.lpstrFile));
169 #else
170   NOTIMPLEMENTED();
171 #endif
172
173   callback.Run(result, content::DownloadItem::TARGET_DISPOSITION_PROMPT,
174                content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, result);
175 }
176
177 void RuntimeDownloadManagerDelegate::SetDownloadBehaviorForTesting(
178     const base::FilePath& default_download_path) {
179   default_download_path_ = default_download_path;
180   suppress_prompting_ = true;
181 }
182
183 }  // namespace xwalk