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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/download/download_status_updater.h" 6 7 #include <shobjidl.h> 8 #include <string> 9 10 #include "base/files/file_path.h" 11 #include "base/logging.h" 12 #include "base/stl_util.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/win/metro.h" 15 #include "base/win/scoped_comptr.h" 16 #include "base/win/windows_version.h" 17 #include "chrome/browser/platform_util.h" 18 #include "chrome/browser/ui/browser.h" 19 #include "chrome/browser/ui/browser_iterator.h" 20 #include "chrome/browser/ui/browser_window.h" 21 #include "content/public/browser/browser_context.h" 22 #include "content/public/browser/browser_thread.h" 23 #include "grit/generated_resources.h" 24 #include "ui/base/l10n/l10n_util.h" 25 #include "url/gurl.h" 26 #include "win8/util/win8_util.h" 27 28 // This code doesn't compile with Aura on. TODO(avi): hook it up so that 29 // win_aura can do platform integration. 30 #if !defined(USE_AURA) 31 32 namespace { 33 34 const char kDownloadNotificationPrefix[] = "DownloadNotification"; 35 int g_next_notification_id = 0; 36 37 void UpdateTaskbarProgressBar(int download_count, 38 bool progress_known, 39 float progress) { 40 // Taskbar progress bar is only supported on Win7. 41 if (base::win::GetVersion() < base::win::VERSION_WIN7) 42 return; 43 44 base::win::ScopedComPtr<ITaskbarList3> taskbar; 45 HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL, 46 CLSCTX_INPROC_SERVER); 47 if (FAILED(result)) { 48 VLOG(1) << "Failed creating a TaskbarList object: " << result; 49 return; 50 } 51 52 result = taskbar->HrInit(); 53 if (FAILED(result)) { 54 LOG(ERROR) << "Failed initializing an ITaskbarList3 interface."; 55 return; 56 } 57 58 // Iterate through all the browser windows, and draw the progress bar. 59 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 60 Browser* browser = *it; 61 BrowserWindow* window = browser->window(); 62 if (!window) 63 continue; 64 HWND frame = window->GetNativeWindow(); 65 if (download_count == 0 || progress == 1.0f) 66 taskbar->SetProgressState(frame, TBPF_NOPROGRESS); 67 else if (!progress_known) 68 taskbar->SetProgressState(frame, TBPF_INDETERMINATE); 69 else 70 taskbar->SetProgressValue(frame, static_cast<int>(progress * 100), 100); 71 } 72 } 73 74 void MetroDownloadNotificationClickedHandler(const wchar_t* download_path) { 75 // Metro chrome will invoke these handlers on the metro thread. 76 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 77 78 // Ensure that we invoke the function to display the downloaded item on the 79 // UI thread. 80 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 81 base::Bind(platform_util::ShowItemInFolder, 82 base::FilePath(download_path))); 83 } 84 85 } // namespace 86 87 void DownloadStatusUpdater::UpdateAppIconDownloadProgress( 88 content::DownloadItem* download) { 89 90 // Always update overall progress. 91 float progress = 0; 92 int download_count = 0; 93 bool progress_known = GetProgress(&progress, &download_count); 94 UpdateTaskbarProgressBar(download_count, progress_known, progress); 95 96 // Fire notifications when downloads complete. 97 if (!win8::IsSingleWindowMetroMode()) 98 return; 99 100 if (download->GetState() != content::DownloadItem::COMPLETE) 101 return; 102 103 if (download->GetOpenWhenComplete() || 104 download->ShouldOpenFileBasedOnExtension() || 105 download->IsTemporary() || 106 download->GetAutoOpened()) 107 return; 108 109 // Don't display the Windows8 metro notifications for an incognito download. 110 if (download->GetBrowserContext() && 111 download->GetBrowserContext()->IsOffTheRecord()) 112 return; 113 114 // Don't display the Windows 8 metro notifications if we are in the 115 // foreground. 116 HWND foreground_window = ::GetForegroundWindow(); 117 if (::IsWindow(foreground_window)) { 118 DWORD process_id = 0; 119 ::GetWindowThreadProcessId(foreground_window, &process_id); 120 if (process_id == ::GetCurrentProcessId()) 121 return; 122 } 123 124 // In Windows 8 metro mode display a metro style notification which 125 // informs the user that the download is complete. 126 HMODULE metro = base::win::GetMetroModule(); 127 base::win::MetroNotification display_notification = 128 reinterpret_cast<base::win::MetroNotification>( 129 ::GetProcAddress(metro, "DisplayNotification")); 130 DCHECK(display_notification); 131 if (display_notification) { 132 string16 title = l10n_util::GetStringUTF16( 133 IDS_METRO_DOWNLOAD_COMPLETE_NOTIFICATION_TITLE); 134 string16 body = l10n_util::GetStringUTF16( 135 IDS_METRO_DOWNLOAD_COMPLETE_NOTIFICATION); 136 137 // Dummy notification id. Every metro style notification needs a 138 // unique notification id. 139 std::string notification_id = kDownloadNotificationPrefix; 140 notification_id += base::IntToString(g_next_notification_id++); 141 142 display_notification(download->GetURL().spec().c_str(), 143 "", 144 title.c_str(), 145 body.c_str(), 146 L"", 147 notification_id.c_str(), 148 MetroDownloadNotificationClickedHandler, 149 download->GetTargetFilePath().value().c_str()); 150 } 151 } 152 153 #endif // !USE_AURA 154