blob: 1dbbea7626b70e01dc119f9fc1462173c5b00f39 [file] [log] [blame]
[email protected]de7d61ff2013-08-20 11:30:411// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]98d6f152011-09-29 19:35:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]de7d61ff2013-08-20 11:30:415#include "content/shell/browser/shell_download_manager_delegate.h"
[email protected]98d6f152011-09-29 19:35:516
[email protected]08c92ac2012-08-21 23:41:407#if defined(TOOLKIT_GTK)
8#include <gtk/gtk.h>
9#endif
10
[email protected]5c12f4a2011-09-30 21:59:0411#if defined(OS_WIN)
12#include <windows.h>
13#include <commdlg.h>
14#endif
15
[email protected]98d6f152011-09-29 19:35:5116#include "base/bind.h"
[email protected]e6669302013-03-25 14:31:1617#include "base/command_line.h"
[email protected]98d6f152011-09-29 19:35:5118#include "base/file_util.h"
[email protected]5c12f4a2011-09-30 21:59:0419#include "base/logging.h"
[email protected]21aa99682013-06-11 07:17:0120#include "base/strings/string_util.h"
[email protected]74ebfb12013-06-07 20:48:0021#include "base/strings/utf_string_conversions.h"
[email protected]ccb797302011-12-15 16:55:1122#include "content/public/browser/browser_context.h"
[email protected]c38831a12011-10-28 12:44:4923#include "content/public/browser/browser_thread.h"
[email protected]e582fdd2011-12-20 16:48:1724#include "content/public/browser/download_manager.h"
[email protected]0b659b32012-03-26 21:29:3225#include "content/public/browser/web_contents.h"
[email protected]08c92ac2012-08-21 23:41:4026#include "content/public/browser/web_contents_view.h"
[email protected]de7d61ff2013-08-20 11:30:4127#include "content/shell/browser/webkit_test_controller.h"
[email protected]b7c504c2013-05-07 14:42:1228#include "content/shell/common/shell_switches.h"
[email protected]98d6f152011-09-29 19:35:5129#include "net/base/net_util.h"
30
31namespace content {
32
33ShellDownloadManagerDelegate::ShellDownloadManagerDelegate()
[email protected]a558b43a2012-08-30 17:09:2734 : download_manager_(NULL),
[email protected]3d95e542012-11-20 00:52:0835 suppress_prompting_(false) {
[email protected]854e1312012-07-30 17:26:3036 // Balanced in Shutdown();
37 AddRef();
[email protected]98d6f152011-09-29 19:35:5138}
39
40ShellDownloadManagerDelegate::~ShellDownloadManagerDelegate(){
41}
42
43
44void ShellDownloadManagerDelegate::SetDownloadManager(
45 DownloadManager* download_manager) {
46 download_manager_ = download_manager;
47}
48
[email protected]854e1312012-07-30 17:26:3049void ShellDownloadManagerDelegate::Shutdown() {
50 Release();
51}
52
[email protected]47665442012-07-27 02:31:2253bool ShellDownloadManagerDelegate::DetermineDownloadTarget(
54 DownloadItem* download,
55 const DownloadTargetCallback& callback) {
[email protected]a558b43a2012-08-30 17:09:2756 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
[email protected]3d833de2012-05-30 23:32:0664 if (!download->GetForcedFilePath().empty()) {
[email protected]47665442012-07-27 02:31:2265 callback.Run(download->GetForcedFilePath(),
66 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
67 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
68 download->GetForcedFilePath());
[email protected]98d6f152011-09-29 19:35:5169 return true;
[email protected]3d833de2012-05-30 23:32:0670 }
[email protected]98d6f152011-09-29 19:35:5171
[email protected]d30a36f2013-02-07 04:16:2672 base::FilePath generated_name = net::GenerateFileName(
[email protected]98d6f152011-09-29 19:35:5173 download->GetURL(),
[email protected]c09a8fd2011-11-21 19:54:5074 download->GetContentDisposition(),
[email protected]a77996172012-10-23 19:59:5475 EmptyString(),
[email protected]c09a8fd2011-11-21 19:54:5076 download->GetSuggestedFilename(),
77 download->GetMimeType(),
[email protected]c9b6eb62011-10-18 20:49:3978 "download");
[email protected]98d6f152011-09-29 19:35:5179
80 BrowserThread::PostTask(
81 BrowserThread::FILE,
82 FROM_HERE,
83 base::Bind(
84 &ShellDownloadManagerDelegate::GenerateFilename,
[email protected]a558b43a2012-08-30 17:09:2785 this, download->GetId(), callback, generated_name,
86 default_download_path_));
87 return true;
[email protected]98d6f152011-09-29 19:35:5188}
89
[email protected]e6669302013-03-25 14:31:1690bool ShellDownloadManagerDelegate::ShouldOpenDownload(
91 DownloadItem* item,
92 const DownloadOpenDelayedCallback& callback) {
[email protected]a3954082013-05-14 14:26:1893 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree) &&
[email protected]91fde4a32013-06-04 12:35:1394 WebKitTestController::Get()->IsMainWindow(item->GetWebContents()) &&
95 item->GetMimeType() == "text/html") {
[email protected]f8462f52013-03-25 15:27:4696 WebKitTestController::Get()->OpenURL(
97 net::FilePathToFileURL(item->GetFullPath()));
98 }
[email protected]e6669302013-03-25 14:31:1699 return true;
100}
101
[email protected]530047e2013-07-12 17:02:25102void ShellDownloadManagerDelegate::GetNextId(
103 const DownloadIdCallback& callback) {
104 static uint32 next_id = DownloadItem::kInvalidId + 1;
105 callback.Run(next_id++);
106}
107
[email protected]98d6f152011-09-29 19:35:51108void ShellDownloadManagerDelegate::GenerateFilename(
[email protected]530047e2013-07-12 17:02:25109 uint32 download_id,
[email protected]47665442012-07-27 02:31:22110 const DownloadTargetCallback& callback,
[email protected]d30a36f2013-02-07 04:16:26111 const base::FilePath& generated_name,
112 const base::FilePath& suggested_directory) {
[email protected]a558b43a2012-08-30 17:09:27113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]7567484142013-07-11 17:36:07114 if (!base::PathExists(suggested_directory))
[email protected]a558b43a2012-08-30 17:09:27115 file_util::CreateDirectory(suggested_directory);
[email protected]98d6f152011-09-29 19:35:51116
[email protected]d30a36f2013-02-07 04:16:26117 base::FilePath suggested_path(suggested_directory.Append(generated_name));
[email protected]98d6f152011-09-29 19:35:51118 BrowserThread::PostTask(
119 BrowserThread::UI,
120 FROM_HERE,
121 base::Bind(
[email protected]a558b43a2012-08-30 17:09:27122 &ShellDownloadManagerDelegate::OnDownloadPathGenerated,
[email protected]47665442012-07-27 02:31:22123 this, download_id, callback, suggested_path));
[email protected]98d6f152011-09-29 19:35:51124}
125
[email protected]a558b43a2012-08-30 17:09:27126void ShellDownloadManagerDelegate::OnDownloadPathGenerated(
[email protected]530047e2013-07-12 17:02:25127 uint32 download_id,
[email protected]a558b43a2012-08-30 17:09:27128 const DownloadTargetCallback& callback,
[email protected]d30a36f2013-02-07 04:16:26129 const base::FilePath& suggested_path) {
[email protected]a558b43a2012-08-30 17:09:27130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
131 if (suppress_prompting_) {
132 // Testing exit.
133 callback.Run(suggested_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
[email protected]d0d368252012-09-24 17:13:42134 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
135 suggested_path.AddExtension(FILE_PATH_LITERAL(".crdownload")));
[email protected]a558b43a2012-08-30 17:09:27136 return;
137 }
138
139 ChooseDownloadPath(download_id, callback, suggested_path);
140}
141
[email protected]47665442012-07-27 02:31:22142void ShellDownloadManagerDelegate::ChooseDownloadPath(
[email protected]530047e2013-07-12 17:02:25143 uint32 download_id,
[email protected]47665442012-07-27 02:31:22144 const DownloadTargetCallback& callback,
[email protected]d30a36f2013-02-07 04:16:26145 const base::FilePath& suggested_path) {
[email protected]a558b43a2012-08-30 17:09:27146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]db6234e2012-09-25 17:23:01147 DownloadItem* item = download_manager_->GetDownload(download_id);
148 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
[email protected]98d6f152011-09-29 19:35:51149 return;
[email protected]3d833de2012-05-30 23:32:06150
[email protected]d30a36f2013-02-07 04:16:26151 base::FilePath result;
[email protected]fa4a45832012-04-12 21:32:48152#if defined(OS_WIN) && !defined(USE_AURA)
[email protected]d30a36f2013-02-07 04:16:26153 std::wstring file_part = base::FilePath(suggested_path).BaseName().value();
[email protected]5c12f4a2011-09-30 21:59:04154 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);
[email protected]f3615f02013-02-26 06:09:06159 save_as.hwndOwner = item->GetWebContents()->GetView()->GetNativeView();
[email protected]5c12f4a2011-09-30 21:59:04160 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))
[email protected]d30a36f2013-02-07 04:16:26172 result = base::FilePath(std::wstring(save_as.lpstrFile));
[email protected]08c92ac2012-08-21 23:41:40173#elif defined(TOOLKIT_GTK)
174 GtkWidget *dialog;
175 gfx::NativeWindow parent_window;
[email protected]d30a36f2013-02-07 04:16:26176 std::string base_name = base::FilePath(suggested_path).BaseName().value();
[email protected]08c92ac2012-08-21 23:41:40177
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));
[email protected]d30a36f2013-02-07 04:16:26193 result = base::FilePath(filename);
[email protected]94b7dd22013-06-05 18:10:31194 g_free(filename);
[email protected]08c92ac2012-08-21 23:41:40195 }
196 gtk_widget_destroy(dialog);
[email protected]5c12f4a2011-09-30 21:59:04197#else
198 NOTIMPLEMENTED();
199#endif
200
[email protected]47665442012-07-27 02:31:22201 callback.Run(result, DownloadItem::TARGET_DISPOSITION_PROMPT,
202 DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, result);
[email protected]98d6f152011-09-29 19:35:51203}
204
[email protected]a558b43a2012-08-30 17:09:27205void ShellDownloadManagerDelegate::SetDownloadBehaviorForTesting(
[email protected]d30a36f2013-02-07 04:16:26206 const base::FilePath& default_download_path) {
[email protected]a558b43a2012-08-30 17:09:27207 default_download_path_ = default_download_path;
208 suppress_prompting_ = true;
209}
210
[email protected]98d6f152011-09-29 19:35:51211} // namespace content