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