Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: chrome/browser/download_util.cc

Issue 2826: Move the download code to new directories: (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/download_util.h ('k') | chrome/browser/history/download_database.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 // Download utility implementation
6
7 #include <string>
8
9 #include "chrome/browser/download_util.h"
10
11 #include "base/base_drag_source.h"
12 #include "base/file_util.h"
13 #include "base/gfx/image_operations.h"
14 #include "chrome/app/theme/theme_resources.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/download_manager.h"
17 #include "chrome/common/clipboard_service.h"
18 #include "chrome/browser/drag_utils.h"
19 #include "chrome/common/gfx/chrome_canvas.h"
20 #include "chrome/common/l10n_util.h"
21 #include "chrome/common/os_exchange_data.h"
22 #include "chrome/common/resource_bundle.h"
23 #include "chrome/views/view.h"
24 #include "generated_resources.h"
25 #include "SkPath.h"
26 #include "SkShader.h"
27
28 namespace download_util {
29
30 // BaseContextMenu -------------------------------------------------------------
31
32 BaseContextMenu::BaseContextMenu(DownloadItem* download) : download_(download) {
33 }
34
35 BaseContextMenu::~BaseContextMenu() {
36 }
37
38 // How many times to cycle the complete animation. This should be an odd number
39 // so that the animation ends faded out.
40 static const int kCompleteAnimationCycles = 5;
41
42 bool BaseContextMenu::IsItemChecked(int id) const {
43 switch (id) {
44 case OPEN_WHEN_COMPLETE:
45 return download_->open_when_complete();
46 case ALWAYS_OPEN_TYPE: {
47 const std::wstring extension =
48 file_util::GetFileExtensionFromPath(download_->full_path());
49 return download_->manager()->ShouldOpenFileExtension(extension);
50 }
51 }
52 return false;
53 }
54
55 bool BaseContextMenu::IsItemDefault(int id) const {
56 return false;
57 }
58
59 std::wstring BaseContextMenu::GetLabel(int id) const {
60 switch (id) {
61 case SHOW_IN_FOLDER:
62 return l10n_util::GetString(IDS_DOWNLOAD_LINK_SHOW);
63 case COPY_LINK:
64 return l10n_util::GetString(IDS_CONTENT_CONTEXT_COPYLINKLOCATION);
65 case COPY_PATH:
66 return l10n_util::GetString(IDS_DOWNLOAD_MENU_COPY_PATH);
67 case COPY_FILE:
68 return l10n_util::GetString(IDS_DOWNLOAD_MENU_COPY_FILE);
69 case OPEN_WHEN_COMPLETE:
70 if (download_->state() == DownloadItem::IN_PROGRESS)
71 return l10n_util::GetString(IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE);
72 return l10n_util::GetString(IDS_DOWNLOAD_MENU_OPEN);
73 case ALWAYS_OPEN_TYPE:
74 return l10n_util::GetString(IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE);
75 case REMOVE_ITEM:
76 return l10n_util::GetString(IDS_DOWNLOAD_MENU_REMOVE_ITEM);
77 case CANCEL:
78 return l10n_util::GetString(IDS_DOWNLOAD_MENU_CANCEL);
79 default:
80 NOTREACHED();
81 }
82 return std::wstring();
83 }
84
85 bool BaseContextMenu::SupportsCommand(int id) const {
86 return id > 0 && id < MENU_LAST;
87 }
88
89 bool BaseContextMenu::IsCommandEnabled(int id) const {
90 switch (id) {
91 case SHOW_IN_FOLDER:
92 case COPY_PATH:
93 case COPY_FILE:
94 case OPEN_WHEN_COMPLETE:
95 return download_->state() != DownloadItem::CANCELLED;
96 case ALWAYS_OPEN_TYPE:
97 return CanOpenDownload(download_);
98 case CANCEL:
99 return download_->state() == DownloadItem::IN_PROGRESS;
100 default:
101 return id > 0 && id < MENU_LAST;
102 }
103 }
104
105 void BaseContextMenu::ExecuteCommand(int id) {
106 ClipboardService* clipboard = g_browser_process->clipboard_service();
107 DCHECK(clipboard);
108 switch (id) {
109 case SHOW_IN_FOLDER:
110 download_->manager()->ShowDownloadInShell(download_);
111 break;
112 case COPY_LINK:
113 clipboard->Clear();
114 clipboard->WriteText(download_->url());
115 break;
116 case COPY_PATH:
117 clipboard->Clear();
118 clipboard->WriteText(download_->full_path());
119 break;
120 case COPY_FILE:
121 // TODO(paulg): Move to OSExchangeData when implementing drag and drop?
122 clipboard->Clear();
123 clipboard->WriteFile(download_->full_path());
124 break;
125 case OPEN_WHEN_COMPLETE:
126 OpenDownload(download_);
127 break;
128 case ALWAYS_OPEN_TYPE: {
129 const std::wstring extension =
130 file_util::GetFileExtensionFromPath(download_->full_path());
131 download_->manager()->OpenFilesOfExtension(
132 extension, !IsItemChecked(ALWAYS_OPEN_TYPE));
133 break;
134 }
135 case REMOVE_ITEM:
136 download_->Remove();
137 break;
138 case CANCEL:
139 download_->Cancel(true);
140 break;
141 default:
142 NOTREACHED();
143 }
144 }
145
146 // DownloadShelfContextMenu ----------------------------------------------------
147
148 DownloadShelfContextMenu::DownloadShelfContextMenu(
149 DownloadItem* download,
150 HWND window,
151 DownloadItemView::BaseDownloadItemModel* model,
152 const CPoint& point)
153 : BaseContextMenu(download),
154 model_(model) {
155 DCHECK(model_);
156
157 // The menu's anchor point is determined based on the UI layout.
158 Menu::AnchorPoint anchor_point;
159 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
160 anchor_point = Menu::TOPRIGHT;
161 else
162 anchor_point = Menu::TOPLEFT;
163
164 Menu context_menu(this, anchor_point, window);
165 if (download->state() == DownloadItem::COMPLETE)
166 context_menu.AppendMenuItem(OPEN_WHEN_COMPLETE, L"", Menu::NORMAL);
167 else
168 context_menu.AppendMenuItem(OPEN_WHEN_COMPLETE, L"", Menu::CHECKBOX);
169 context_menu.AppendMenuItem(ALWAYS_OPEN_TYPE, L"", Menu::CHECKBOX);
170 context_menu.AppendSeparator();
171 context_menu.AppendMenuItem(SHOW_IN_FOLDER, L"", Menu::NORMAL);
172 context_menu.AppendSeparator();
173 context_menu.AppendMenuItem(CANCEL, L"", Menu::NORMAL);
174 context_menu.RunMenuAt(point.x, point.y);
175 }
176
177 DownloadShelfContextMenu::~DownloadShelfContextMenu() {
178 }
179
180 bool DownloadShelfContextMenu::IsItemDefault(int id) const {
181 return id == OPEN_WHEN_COMPLETE;
182 }
183
184 void DownloadShelfContextMenu::ExecuteCommand(int id) {
185 if (id == CANCEL)
186 model_->CancelTask();
187 else
188 BaseContextMenu::ExecuteCommand(id);
189 }
190
191 // DownloadDestinationContextMenu ----------------------------------------------
192
193 DownloadDestinationContextMenu::DownloadDestinationContextMenu(
194 DownloadItem* download,
195 HWND window,
196 const CPoint& point)
197 : BaseContextMenu(download) {
198 // The menu's anchor point is determined based on the UI layout.
199 Menu::AnchorPoint anchor_point;
200 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
201 anchor_point = Menu::TOPRIGHT;
202 else
203 anchor_point = Menu::TOPLEFT;
204
205 Menu context_menu(this, anchor_point, window);
206 context_menu.AppendMenuItem(SHOW_IN_FOLDER, L"", Menu::NORMAL);
207 context_menu.AppendSeparator();
208 context_menu.AppendMenuItem(COPY_LINK, L"", Menu::NORMAL);
209 context_menu.AppendMenuItem(COPY_PATH, L"", Menu::NORMAL);
210 context_menu.AppendMenuItem(COPY_FILE, L"", Menu::NORMAL);
211 context_menu.AppendSeparator();
212 context_menu.AppendMenuItem(OPEN_WHEN_COMPLETE, L"", Menu::CHECKBOX);
213 context_menu.AppendMenuItem(ALWAYS_OPEN_TYPE, L"", Menu::CHECKBOX);
214 context_menu.AppendSeparator();
215 context_menu.AppendMenuItem(REMOVE_ITEM, L"", Menu::NORMAL);
216 context_menu.RunMenuAt(point.x, point.y);
217 }
218
219 DownloadDestinationContextMenu::~DownloadDestinationContextMenu() {
220 }
221
222 // Download opening ------------------------------------------------------------
223
224 bool CanOpenDownload(DownloadItem* download) {
225 const std::wstring extension =
226 file_util::GetFileExtensionFromPath(download->full_path());
227 return !download->manager()->IsExecutable(extension);
228 }
229
230 void OpenDownload(DownloadItem* download) {
231 if (download->state() == DownloadItem::IN_PROGRESS)
232 download->set_open_when_complete(!download->open_when_complete());
233 else if (download->state() == DownloadItem::COMPLETE)
234 download->manager()->OpenDownloadInShell(download, NULL);
235 }
236
237 // Download progress painting --------------------------------------------------
238
239 // Common bitmaps used for download progress animations. We load them once the
240 // first time we do a progress paint, then reuse them as they are always the
241 // same.
242 SkBitmap* g_foreground_16 = NULL;
243 SkBitmap* g_background_16 = NULL;
244 SkBitmap* g_foreground_32 = NULL;
245 SkBitmap* g_background_32 = NULL;
246
247 void PaintDownloadProgress(ChromeCanvas* canvas,
248 ChromeViews::View* containing_view,
249 int origin_x,
250 int origin_y,
251 int start_angle,
252 int percent_done,
253 PaintDownloadProgressSize size) {
254 DCHECK(containing_view);
255
256 // Load up our common bitmaps
257 if (!g_background_16) {
258 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
259 g_foreground_16 = rb.GetBitmapNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16);
260 g_background_16 = rb.GetBitmapNamed(IDR_DOWNLOAD_PROGRESS_BACKGROUND_16);
261 g_foreground_32 = rb.GetBitmapNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_32);
262 g_background_32 = rb.GetBitmapNamed(IDR_DOWNLOAD_PROGRESS_BACKGROUND_32);
263 }
264
265 SkBitmap* background = (size == BIG) ? g_background_32 : g_background_16;
266 SkBitmap* foreground = (size == BIG) ? g_foreground_32 : g_foreground_16;
267
268 const int kProgressIconSize = (size == BIG) ? kBigProgressIconSize :
269 kSmallProgressIconSize;
270
271 int height = background->height();
272
273 // We start by storing the bounds of the background and foreground bitmaps
274 // so that it is easy to mirror the bounds if the UI layout is RTL.
275 gfx::Rect background_bounds(origin_x, origin_y,
276 background->width(), background->height());
277 gfx::Rect foreground_bounds(origin_x, origin_y,
278 foreground->width(), foreground->height());
279
280 // Mirror the positions if necessary.
281 int mirrored_x = containing_view->MirroredLeftPointForRect(background_bounds);
282 background_bounds.set_x(mirrored_x);
283 mirrored_x = containing_view->MirroredLeftPointForRect(foreground_bounds);
284 foreground_bounds.set_x(mirrored_x);
285
286 // Draw the background progress image.
287 SkPaint background_paint;
288 canvas->DrawBitmapInt(*background,
289 background_bounds.x(),
290 background_bounds.y(),
291 background_paint);
292
293 // Layer the foreground progress image in an arc proportional to the download
294 // progress. The arc grows clockwise, starting in the midnight position, as
295 // the download progresses. However, if the download does not have known total
296 // size (the server didn't give us one), then we just spin an arc around until
297 // we're done.
298 float sweep_angle = 0.0;
299 float start_pos = static_cast<float>(kStartAngleDegrees);
300 if (percent_done < 0) {
301 sweep_angle = kUnknownAngleDegrees;
302 start_pos = static_cast<float>(start_angle);
303 } else if (percent_done > 0) {
304 sweep_angle = static_cast<float>(kMaxDegrees / 100.0 * percent_done);
305 }
306
307 // Set up an arc clipping region for the foreground image. Don't bother using
308 // a clipping region if it would round to 360 (really 0) degrees, since that
309 // would eliminate the foreground completely and be quite confusing (it would
310 // look like 0% complete when it should be almost 100%).
311 SkPaint foreground_paint;
312 if (sweep_angle < static_cast<float>(kMaxDegrees - 1)) {
313 SkRect oval;
314 oval.set(SkIntToScalar(foreground_bounds.x()),
315 SkIntToScalar(foreground_bounds.y()),
316 SkIntToScalar(foreground_bounds.x() + kProgressIconSize),
317 SkIntToScalar(foreground_bounds.y() + kProgressIconSize));
318 SkPath path;
319 path.arcTo(oval,
320 SkFloatToScalar(start_pos),
321 SkFloatToScalar(sweep_angle), false);
322 path.lineTo(SkIntToScalar(foreground_bounds.x() + kProgressIconSize / 2),
323 SkIntToScalar(foreground_bounds.y() + kProgressIconSize / 2));
324
325 SkShader* shader =
326 SkShader::CreateBitmapShader(*foreground,
327 SkShader::kClamp_TileMode,
328 SkShader::kClamp_TileMode);
329 SkMatrix shader_scale;
330 shader_scale.setTranslate(SkIntToScalar(foreground_bounds.x()),
331 SkIntToScalar(foreground_bounds.y()));
332 shader->setLocalMatrix(shader_scale);
333 foreground_paint.setShader(shader);
334 foreground_paint.setAntiAlias(true);
335 shader->unref();
336 canvas->drawPath(path, foreground_paint);
337 return;
338 }
339
340 canvas->DrawBitmapInt(*foreground,
341 foreground_bounds.x(),
342 foreground_bounds.y(),
343 foreground_paint);
344 }
345
346 void PaintDownloadComplete(ChromeCanvas* canvas,
347 ChromeViews::View* containing_view,
348 int origin_x,
349 int origin_y,
350 double animation_progress,
351 PaintDownloadProgressSize size) {
352 DCHECK(containing_view);
353
354 // Load up our common bitmaps.
355 if (!g_foreground_16) {
356 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
357 g_foreground_16 = rb.GetBitmapNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_16);
358 g_foreground_32 = rb.GetBitmapNamed(IDR_DOWNLOAD_PROGRESS_FOREGROUND_32);
359 }
360
361 SkBitmap* complete = (size == BIG) ? g_foreground_32 : g_foreground_16;
362
363 // Mirror the positions if necessary.
364 gfx::Rect complete_bounds(origin_x, origin_y,
365 complete->width(), complete->height());
366 complete_bounds.set_x(
367 containing_view->MirroredLeftPointForRect(complete_bounds));
368
369 // Start at full opacity, then loop back and forth five times before ending
370 // at zero opacity.
371 static const double PI = 3.141592653589793;
372 double opacity = sin(animation_progress * PI * kCompleteAnimationCycles +
373 PI/2) / 2 + 0.5;
374
375 SkRect bounds;
376 bounds.set(SkIntToScalar(complete_bounds.x()),
377 SkIntToScalar(complete_bounds.y()),
378 SkIntToScalar(complete_bounds.x() + complete_bounds.width()),
379 SkIntToScalar(complete_bounds.y() + complete_bounds.height()));
380 canvas->saveLayerAlpha(&bounds,
381 static_cast<int>(255.0 * opacity),
382 SkCanvas::kARGB_ClipLayer_SaveFlag);
383 canvas->drawARGB(0, 255, 255, 255, SkPorterDuff::kClear_Mode);
384 canvas->DrawBitmapInt(*complete, complete_bounds.x(), complete_bounds.y());
385 canvas->restore();
386 }
387
388 // Download dragging
389 void DragDownload(const DownloadItem* download, SkBitmap* icon) {
390 DCHECK(download);
391
392 // Set up our OLE machinery
393 scoped_refptr<OSExchangeData> data(new OSExchangeData);
394 if (icon)
395 drag_utils::CreateDragImageForFile(download->file_name(), icon, data);
396 data->SetFilename(download->full_path());
397 scoped_refptr<BaseDragSource> drag_source(new BaseDragSource);
398
399 // Run the drag and drop loop
400 DWORD effects;
401 DoDragDrop(data.get(), drag_source.get(), DROPEFFECT_COPY | DROPEFFECT_LINK,
402 &effects);
403 }
404
405
406 } // namespace download_util
407
OLDNEW
« no previous file with comments | « chrome/browser/download_util.h ('k') | chrome/browser/history/download_database.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698