| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Download utility implementation | 5 // Download utility implementation |
| 6 | 6 |
| 7 #include "chrome/browser/download/download_util.h" | 7 #include "chrome/browser/download/download_util.h" |
| 8 | 8 |
| 9 #if defined(OS_WIN) | 9 #define _USE_MATH_DEFINES // For VC++ to get M_PI |
| 10 #include <shobjidl.h> | 10 #include <cmath> |
| 11 #endif | |
| 12 #include <string> | 11 #include <string> |
| 13 | 12 |
| 14 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 15 #include "base/i18n/rtl.h" | 14 #include "base/i18n/rtl.h" |
| 16 #include "base/i18n/time_formatting.h" | 15 #include "base/i18n/time_formatting.h" |
| 17 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
| 18 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 19 #include "base/path_service.h" | 18 #include "base/path_service.h" |
| 20 #include "base/string16.h" | 19 #include "base/string16.h" |
| 21 #include "base/string_number_conversions.h" | 20 #include "base/string_number_conversions.h" |
| 22 #include "base/sys_string_conversions.h" | 21 #include "base/sys_string_conversions.h" |
| 23 #include "base/threading/thread_restrictions.h" | 22 #include "base/threading/thread_restrictions.h" |
| 24 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
| 25 #include "base/value_conversions.h" | 24 #include "base/value_conversions.h" |
| 26 #include "base/values.h" | 25 #include "base/values.h" |
| 27 #include "base/win/windows_version.h" | |
| 28 #include "chrome/browser/download/download_extensions.h" | 26 #include "chrome/browser/download/download_extensions.h" |
| 29 #include "chrome/browser/download/download_item_model.h" | 27 #include "chrome/browser/download/download_item_model.h" |
| 30 #include "chrome/browser/profiles/profile.h" | 28 #include "chrome/browser/profiles/profile.h" |
| 31 #include "chrome/browser/ui/browser.h" | 29 #include "chrome/browser/ui/browser.h" |
| 32 #include "chrome/common/chrome_notification_types.h" | 30 #include "chrome/common/chrome_notification_types.h" |
| 33 #include "chrome/common/chrome_paths.h" | 31 #include "chrome/common/chrome_paths.h" |
| 34 #include "chrome/common/time_format.h" | 32 #include "chrome/common/time_format.h" |
| 35 #include "content/public/browser/browser_thread.h" | 33 #include "content/public/browser/browser_thread.h" |
| 36 #include "content/public/browser/download_item.h" | 34 #include "content/public/browser/download_item.h" |
| 37 #include "content/public/browser/download_manager.h" | 35 #include "content/public/browser/download_manager.h" |
| 38 #include "content/public/browser/render_view_host.h" | 36 #include "content/public/browser/render_view_host.h" |
| 39 #include "content/public/common/url_constants.h" | 37 #include "content/public/common/url_constants.h" |
| 40 #include "grit/generated_resources.h" | 38 #include "grit/generated_resources.h" |
| 41 #include "grit/locale_settings.h" | 39 #include "grit/locale_settings.h" |
| 42 #include "grit/theme_resources.h" | 40 #include "grit/theme_resources.h" |
| 43 #include "net/base/mime_util.h" | 41 #include "net/base/mime_util.h" |
| 44 #include "net/base/net_util.h" | 42 #include "net/base/net_util.h" |
| 45 #include "skia/ext/image_operations.h" | 43 #include "skia/ext/image_operations.h" |
| 46 #include "third_party/skia/include/core/SkPath.h" | 44 #include "third_party/skia/include/core/SkPath.h" |
| 47 #include "third_party/skia/include/core/SkShader.h" | 45 #include "third_party/skia/include/core/SkShader.h" |
| 48 #include "ui/base/l10n/l10n_util.h" | 46 #include "ui/base/l10n/l10n_util.h" |
| 49 #include "ui/base/resource/resource_bundle.h" | 47 #include "ui/base/resource/resource_bundle.h" |
| 50 #include "ui/base/text/bytes_formatting.h" | 48 #include "ui/base/text/bytes_formatting.h" |
| 51 #include "ui/gfx/canvas.h" | 49 #include "ui/gfx/canvas.h" |
| 52 #include "ui/gfx/image/image.h" | 50 #include "ui/gfx/image/image.h" |
| 53 #include "ui/gfx/rect.h" | 51 #include "ui/gfx/rect.h" |
| 54 | 52 |
| 53 #if defined(OS_WIN) |
| 54 #include <shobjidl.h> |
| 55 |
| 56 #include "base/win/windows_version.h" |
| 57 #endif |
| 58 |
| 55 #if defined(TOOLKIT_VIEWS) | 59 #if defined(TOOLKIT_VIEWS) |
| 56 #include "ui/base/dragdrop/drag_utils.h" | 60 #include "ui/base/dragdrop/drag_utils.h" |
| 57 #include "ui/base/dragdrop/os_exchange_data.h" | 61 #include "ui/base/dragdrop/os_exchange_data.h" |
| 58 #include "ui/base/dragdrop/drag_drop_types.h" | 62 #include "ui/base/dragdrop/drag_drop_types.h" |
| 59 #include "ui/gfx/screen.h" | 63 #include "ui/gfx/screen.h" |
| 60 #include "ui/views/widget/widget.h" | 64 #include "ui/views/widget/widget.h" |
| 61 #endif | 65 #endif |
| 62 | 66 |
| 63 #if defined(TOOLKIT_GTK) | 67 #if defined(TOOLKIT_GTK) |
| 64 #include "chrome/browser/ui/gtk/custom_drag.h" | 68 #include "chrome/browser/ui/gtk/custom_drag.h" |
| 65 #include "chrome/browser/ui/gtk/unity_service.h" | 69 #include "chrome/browser/ui/gtk/unity_service.h" |
| 66 #endif // defined(TOOLKIT_GTK) | 70 #endif // defined(TOOLKIT_GTK) |
| 67 | 71 |
| 68 #if defined(OS_WIN) && !defined(USE_AURA) | 72 #if defined(OS_WIN) && !defined(USE_AURA) |
| 69 #include "base/win/scoped_comptr.h" | 73 #include "base/win/scoped_comptr.h" |
| 70 #include "chrome/browser/ui/browser_list.h" | 74 #include "chrome/browser/ui/browser_list.h" |
| 71 #include "chrome/browser/ui/views/frame/browser_view.h" | 75 #include "chrome/browser/ui/views/frame/browser_view.h" |
| 72 #include "ui/base/dragdrop/drag_source.h" | 76 #include "ui/base/dragdrop/drag_source.h" |
| 73 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" | 77 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" |
| 74 #endif | 78 #endif |
| 75 | 79 |
| 76 // TODO(phajdan.jr): Find some standard location for this, maintaining | |
| 77 // the same value on all platforms. | |
| 78 static const double PI = 3.141592653589793; | |
| 79 | |
| 80 using content::DownloadItem; | |
| 81 | |
| 82 namespace { | 80 namespace { |
| 83 | 81 |
| 84 // Returns a string constant to be used as the |danger_type| value in | 82 // Returns a string constant to be used as the |danger_type| value in |
| 85 // CreateDownloadItemValue(). We only return strings for DANGEROUS_FILE, | 83 // CreateDownloadItemValue(). We only return strings for DANGEROUS_FILE, |
| 86 // DANGEROUS_URL, DANGEROUS_CONTENT, and UNCOMMON_CONTENT because the | 84 // DANGEROUS_URL, DANGEROUS_CONTENT, and UNCOMMON_CONTENT because the |
| 87 // |danger_type| value is only defined if the value of |state| is |DANGEROUS|. | 85 // |danger_type| value is only defined if the value of |state| is |DANGEROUS|. |
| 88 const char* GetDangerTypeString(content::DownloadDangerType danger_type) { | 86 const char* GetDangerTypeString(content::DownloadDangerType danger_type) { |
| 89 switch (danger_type) { | 87 switch (danger_type) { |
| 90 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: | 88 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: |
| 91 return "DANGEROUS_FILE"; | 89 return "DANGEROUS_FILE"; |
| 92 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: | 90 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: |
| 93 return "DANGEROUS_URL"; | 91 return "DANGEROUS_URL"; |
| 94 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: | 92 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: |
| 95 return "DANGEROUS_CONTENT"; | 93 return "DANGEROUS_CONTENT"; |
| 96 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: | 94 case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: |
| 97 return "UNCOMMON_CONTENT"; | 95 return "UNCOMMON_CONTENT"; |
| 98 default: | 96 default: |
| 99 // We shouldn't be returning a danger type string if it is | 97 // We shouldn't be returning a danger type string if it is |
| 100 // NOT_DANGEROUS or MAYBE_DANGEROUS_CONTENT. | 98 // NOT_DANGEROUS or MAYBE_DANGEROUS_CONTENT. |
| 101 NOTREACHED(); | 99 NOTREACHED(); |
| 102 return ""; | 100 return ""; |
| 103 } | 101 } |
| 104 } | 102 } |
| 105 | 103 |
| 104 // Get the opacity based on |animation_progress|, with values in [0.0, 1.0]. |
| 105 // Range of return value is [0, 255]. |
| 106 int GetOpacity(double animation_progress) { |
| 107 DCHECK(animation_progress >= 0 && animation_progress <= 1); |
| 108 |
| 109 // How many times to cycle the complete animation. This should be an odd |
| 110 // number so that the animation ends faded out. |
| 111 static const int kCompleteAnimationCycles = 5; |
| 112 double temp = animation_progress * kCompleteAnimationCycles * M_PI + M_PI_2; |
| 113 temp = sin(temp) / 2 + 0.5; |
| 114 return static_cast<int>(255.0 * temp); |
| 115 } |
| 116 |
| 106 } // namespace | 117 } // namespace |
| 107 | 118 |
| 108 namespace download_util { | 119 namespace download_util { |
| 109 | 120 |
| 110 // How many times to cycle the complete animation. This should be an odd number | 121 using content::DownloadItem; |
| 111 // so that the animation ends faded out. | |
| 112 static const int kCompleteAnimationCycles = 5; | |
| 113 | 122 |
| 114 // Download temporary file creation -------------------------------------------- | 123 // Download temporary file creation -------------------------------------------- |
| 115 | 124 |
| 116 class DefaultDownloadDirectory { | 125 class DefaultDownloadDirectory { |
| 117 public: | 126 public: |
| 118 const FilePath& path() const { return path_; } | 127 const FilePath& path() const { return path_; } |
| 119 private: | 128 private: |
| 120 DefaultDownloadDirectory() { | 129 DefaultDownloadDirectory() { |
| 121 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &path_)) { | 130 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &path_)) { |
| 122 NOTREACHED(); | 131 NOTREACHED(); |
| 123 } | 132 } |
| 124 if (DownloadPathIsDangerous(path_)) { | 133 if (DownloadPathIsDangerous(path_)) { |
| 134 // This is only useful on platforms that support |
| 135 // DIR_DEFAULT_DOWNLOADS_SAFE. |
| 125 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS_SAFE, &path_)) { | 136 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS_SAFE, &path_)) { |
| 126 NOTREACHED(); | 137 NOTREACHED(); |
| 127 } | 138 } |
| 128 } | 139 } |
| 129 } | 140 } |
| 130 friend struct base::DefaultLazyInstanceTraits<DefaultDownloadDirectory>; | 141 friend struct base::DefaultLazyInstanceTraits<DefaultDownloadDirectory>; |
| 131 FilePath path_; | 142 FilePath path_; |
| 132 }; | 143 }; |
| 133 | 144 |
| 134 static base::LazyInstance<DefaultDownloadDirectory> | 145 static base::LazyInstance<DefaultDownloadDirectory> |
| 135 g_default_download_directory = LAZY_INSTANCE_INITIALIZER; | 146 g_default_download_directory = LAZY_INSTANCE_INITIALIZER; |
| 136 | 147 |
| 137 const FilePath& GetDefaultDownloadDirectory() { | 148 const FilePath& GetDefaultDownloadDirectory() { |
| 138 return g_default_download_directory.Get().path(); | 149 return g_default_download_directory.Get().path(); |
| 139 } | 150 } |
| 140 | 151 |
| 152 // Consider downloads 'dangerous' if they go to the home directory on Linux and |
| 153 // to the desktop on any platform. |
| 141 bool DownloadPathIsDangerous(const FilePath& download_path) { | 154 bool DownloadPathIsDangerous(const FilePath& download_path) { |
| 155 #if defined(OS_LINUX) |
| 156 FilePath home_dir = file_util::GetHomeDir(); |
| 157 if (download_path == home_dir) { |
| 158 return true; |
| 159 } |
| 160 #endif |
| 161 |
| 142 FilePath desktop_dir; | 162 FilePath desktop_dir; |
| 143 if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_dir)) { | 163 if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_dir)) { |
| 144 NOTREACHED(); | 164 NOTREACHED(); |
| 145 return false; | 165 return false; |
| 146 } | 166 } |
| 147 return (download_path == desktop_dir); | 167 return (download_path == desktop_dir); |
| 148 } | 168 } |
| 149 | 169 |
| 150 void GenerateFileNameFromRequest(const DownloadItem& download_item, | 170 void GenerateFileNameFromRequest(const DownloadItem& download_item, |
| 151 FilePath* generated_name) { | 171 FilePath* generated_name) { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 308 |
| 289 gfx::Rect complete_bounds(origin_x, origin_y, | 309 gfx::Rect complete_bounds(origin_x, origin_y, |
| 290 complete->width(), complete->height()); | 310 complete->width(), complete->height()); |
| 291 #if defined(TOOLKIT_VIEWS) | 311 #if defined(TOOLKIT_VIEWS) |
| 292 // Mirror the positions if necessary. | 312 // Mirror the positions if necessary. |
| 293 complete_bounds.set_x(containing_view->GetMirroredXForRect(complete_bounds)); | 313 complete_bounds.set_x(containing_view->GetMirroredXForRect(complete_bounds)); |
| 294 #endif | 314 #endif |
| 295 | 315 |
| 296 // Start at full opacity, then loop back and forth five times before ending | 316 // Start at full opacity, then loop back and forth five times before ending |
| 297 // at zero opacity. | 317 // at zero opacity. |
| 298 double opacity = sin(animation_progress * PI * kCompleteAnimationCycles + | 318 canvas->SaveLayerAlpha(GetOpacity(animation_progress), complete_bounds); |
| 299 PI/2) / 2 + 0.5; | |
| 300 | |
| 301 canvas->SaveLayerAlpha(static_cast<int>(255.0 * opacity), complete_bounds); | |
| 302 canvas->sk_canvas()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); | 319 canvas->sk_canvas()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); |
| 303 canvas->DrawBitmapInt(*complete, complete_bounds.x(), complete_bounds.y()); | 320 canvas->DrawBitmapInt(*complete, complete_bounds.x(), complete_bounds.y()); |
| 304 canvas->Restore(); | 321 canvas->Restore(); |
| 305 } | 322 } |
| 306 | 323 |
| 307 void PaintDownloadInterrupted(gfx::Canvas* canvas, | 324 void PaintDownloadInterrupted(gfx::Canvas* canvas, |
| 308 #if defined(TOOLKIT_VIEWS) | 325 #if defined(TOOLKIT_VIEWS) |
| 309 views::View* containing_view, | 326 views::View* containing_view, |
| 310 #endif | 327 #endif |
| 311 int origin_x, | 328 int origin_x, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 323 | 340 |
| 324 gfx::Rect complete_bounds(origin_x, origin_y, | 341 gfx::Rect complete_bounds(origin_x, origin_y, |
| 325 complete->width(), complete->height()); | 342 complete->width(), complete->height()); |
| 326 #if defined(TOOLKIT_VIEWS) | 343 #if defined(TOOLKIT_VIEWS) |
| 327 // Mirror the positions if necessary. | 344 // Mirror the positions if necessary. |
| 328 complete_bounds.set_x(containing_view->GetMirroredXForRect(complete_bounds)); | 345 complete_bounds.set_x(containing_view->GetMirroredXForRect(complete_bounds)); |
| 329 #endif | 346 #endif |
| 330 | 347 |
| 331 // Start at zero opacity, then loop back and forth five times before ending | 348 // Start at zero opacity, then loop back and forth five times before ending |
| 332 // at full opacity. | 349 // at full opacity. |
| 333 double opacity = sin( | 350 canvas->SaveLayerAlpha(GetOpacity(1.0 - animation_progress), complete_bounds); |
| 334 (1.0 - animation_progress) * PI * kCompleteAnimationCycles + PI/2) / 2 + | |
| 335 0.5; | |
| 336 | |
| 337 canvas->SaveLayerAlpha(static_cast<int>(255.0 * opacity), complete_bounds); | |
| 338 canvas->sk_canvas()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); | 351 canvas->sk_canvas()->drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); |
| 339 canvas->DrawBitmapInt(*complete, complete_bounds.x(), complete_bounds.y()); | 352 canvas->DrawBitmapInt(*complete, complete_bounds.x(), complete_bounds.y()); |
| 340 canvas->Restore(); | 353 canvas->Restore(); |
| 341 } | 354 } |
| 342 | 355 |
| 343 // Load a language dependent height so that the dangerous download confirmation | 356 // Load a language dependent height so that the dangerous download confirmation |
| 344 // message doesn't overlap with the download link label. | 357 // message doesn't overlap with the download link label. |
| 345 int GetBigProgressIconSize() { | 358 int GetBigProgressIconSize() { |
| 346 static int big_progress_icon_size = 0; | 359 static int big_progress_icon_size = 0; |
| 347 if (big_progress_icon_size == 0) { | 360 if (big_progress_icon_size == 0) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 } | 403 } |
| 391 | 404 |
| 392 #if !defined(TOOLKIT_GTK) | 405 #if !defined(TOOLKIT_GTK) |
| 393 #if defined(USE_AURA) | 406 #if defined(USE_AURA) |
| 394 views::Widget* widget = views::Widget::GetWidgetForNativeView(view); | 407 views::Widget* widget = views::Widget::GetWidgetForNativeView(view); |
| 395 gfx::Point location = gfx::Screen::GetCursorScreenPoint(); | 408 gfx::Point location = gfx::Screen::GetCursorScreenPoint(); |
| 396 // We do not care about notifying the DragItemView on completion of drag. So | 409 // We do not care about notifying the DragItemView on completion of drag. So |
| 397 // we pass NULL to RunShellDrag for the source view. | 410 // we pass NULL to RunShellDrag for the source view. |
| 398 widget->RunShellDrag(NULL, data, location, | 411 widget->RunShellDrag(NULL, data, location, |
| 399 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK); | 412 ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK); |
| 400 #else // We are on WIN without AURA | 413 #else // We are on WIN without AURA |
| 401 // We cannot use Widget::RunShellDrag on WIN since the |view| is backed by a | 414 // We cannot use Widget::RunShellDrag on WIN since the |view| is backed by a |
| 402 // TabContentsViewWin, not a NativeWidgetWin. | 415 // TabContentsViewWin, not a NativeWidgetWin. |
| 403 scoped_refptr<ui::DragSource> drag_source(new ui::DragSource); | 416 scoped_refptr<ui::DragSource> drag_source(new ui::DragSource); |
| 404 // Run the drag and drop loop | 417 // Run the drag and drop loop |
| 405 DWORD effects; | 418 DWORD effects; |
| 406 DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data), | 419 DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data), |
| 407 drag_source.get(), DROPEFFECT_COPY | DROPEFFECT_LINK, &effects); | 420 drag_source.get(), DROPEFFECT_COPY | DROPEFFECT_LINK, &effects); |
| 408 #endif | 421 #endif |
| 409 | 422 |
| 410 #else | 423 #else |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 UMA_HISTOGRAM_ENUMERATION( | 655 UMA_HISTOGRAM_ENUMERATION( |
| 643 "Download.CountsChrome", type, CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY); | 656 "Download.CountsChrome", type, CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY); |
| 644 } | 657 } |
| 645 | 658 |
| 646 void RecordDownloadSource(ChromeDownloadSource source) { | 659 void RecordDownloadSource(ChromeDownloadSource source) { |
| 647 UMA_HISTOGRAM_ENUMERATION( | 660 UMA_HISTOGRAM_ENUMERATION( |
| 648 "Download.SourcesChrome", source, CHROME_DOWNLOAD_SOURCE_LAST_ENTRY); | 661 "Download.SourcesChrome", source, CHROME_DOWNLOAD_SOURCE_LAST_ENTRY); |
| 649 } | 662 } |
| 650 | 663 |
| 651 } // namespace download_util | 664 } // namespace download_util |
| OLD | NEW |