1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/windows/WinUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1247 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sts=2 sw=2 et cin: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "WinUtils.h" 1.11 + 1.12 +#include "gfxPlatform.h" 1.13 +#include "nsWindow.h" 1.14 +#include "nsWindowDefs.h" 1.15 +#include "KeyboardLayout.h" 1.16 +#include "nsIDOMMouseEvent.h" 1.17 +#include "mozilla/gfx/2D.h" 1.18 +#include "mozilla/gfx/DataSurfaceHelpers.h" 1.19 +#include "mozilla/Preferences.h" 1.20 +#include "mozilla/RefPtr.h" 1.21 +#include "mozilla/WindowsVersion.h" 1.22 + 1.23 +#ifdef MOZ_LOGGING 1.24 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.25 +#endif // MOZ_LOGGING 1.26 +#include "prlog.h" 1.27 + 1.28 +#include "nsString.h" 1.29 +#include "nsDirectoryServiceUtils.h" 1.30 +#include "imgIContainer.h" 1.31 +#include "imgITools.h" 1.32 +#include "nsStringStream.h" 1.33 +#include "nsNetUtil.h" 1.34 +#ifdef MOZ_PLACES 1.35 +#include "mozIAsyncFavicons.h" 1.36 +#endif 1.37 +#include "nsIIconURI.h" 1.38 +#include "nsIDownloader.h" 1.39 +#include "nsINetUtil.h" 1.40 +#include "nsIChannel.h" 1.41 +#include "nsIObserver.h" 1.42 +#include "imgIEncoder.h" 1.43 +#include "nsIThread.h" 1.44 +#include "MainThreadUtils.h" 1.45 +#include "gfxColor.h" 1.46 +#ifdef MOZ_METRO 1.47 +#include "winrt/MetroInput.h" 1.48 +#include "winrt/MetroUtils.h" 1.49 +#endif // MOZ_METRO 1.50 + 1.51 +#ifdef NS_ENABLE_TSF 1.52 +#include <textstor.h> 1.53 +#include "nsTextStore.h" 1.54 +#endif // #ifdef NS_ENABLE_TSF 1.55 + 1.56 +#ifdef PR_LOGGING 1.57 +PRLogModuleInfo* gWindowsLog = nullptr; 1.58 +#endif 1.59 + 1.60 +using namespace mozilla::gfx; 1.61 + 1.62 +namespace mozilla { 1.63 +namespace widget { 1.64 + 1.65 +NS_IMPL_ISUPPORTS(myDownloadObserver, nsIDownloadObserver) 1.66 +#ifdef MOZ_PLACES 1.67 +NS_IMPL_ISUPPORTS(AsyncFaviconDataReady, nsIFaviconDataCallback) 1.68 +#endif 1.69 +NS_IMPL_ISUPPORTS(AsyncEncodeAndWriteIcon, nsIRunnable) 1.70 +NS_IMPL_ISUPPORTS(AsyncDeleteIconFromDisk, nsIRunnable) 1.71 +NS_IMPL_ISUPPORTS(AsyncDeleteAllFaviconsFromDisk, nsIRunnable) 1.72 + 1.73 + 1.74 +const char FaviconHelper::kJumpListCacheDir[] = "jumpListCache"; 1.75 +const char FaviconHelper::kShortcutCacheDir[] = "shortcutCache"; 1.76 + 1.77 +// apis available on vista and up. 1.78 +WinUtils::SHCreateItemFromParsingNamePtr WinUtils::sCreateItemFromParsingName = nullptr; 1.79 +WinUtils::SHGetKnownFolderPathPtr WinUtils::sGetKnownFolderPath = nullptr; 1.80 + 1.81 +// We just leak these DLL HMODULEs. There's no point in calling FreeLibrary 1.82 +// on them during shutdown anyway. 1.83 +static const wchar_t kShellLibraryName[] = L"shell32.dll"; 1.84 +static HMODULE sShellDll = nullptr; 1.85 +static const wchar_t kDwmLibraryName[] = L"dwmapi.dll"; 1.86 +static HMODULE sDwmDll = nullptr; 1.87 + 1.88 +WinUtils::DwmExtendFrameIntoClientAreaProc WinUtils::dwmExtendFrameIntoClientAreaPtr = nullptr; 1.89 +WinUtils::DwmIsCompositionEnabledProc WinUtils::dwmIsCompositionEnabledPtr = nullptr; 1.90 +WinUtils::DwmSetIconicThumbnailProc WinUtils::dwmSetIconicThumbnailPtr = nullptr; 1.91 +WinUtils::DwmSetIconicLivePreviewBitmapProc WinUtils::dwmSetIconicLivePreviewBitmapPtr = nullptr; 1.92 +WinUtils::DwmGetWindowAttributeProc WinUtils::dwmGetWindowAttributePtr = nullptr; 1.93 +WinUtils::DwmSetWindowAttributeProc WinUtils::dwmSetWindowAttributePtr = nullptr; 1.94 +WinUtils::DwmInvalidateIconicBitmapsProc WinUtils::dwmInvalidateIconicBitmapsPtr = nullptr; 1.95 +WinUtils::DwmDefWindowProcProc WinUtils::dwmDwmDefWindowProcPtr = nullptr; 1.96 +WinUtils::DwmGetCompositionTimingInfoProc WinUtils::dwmGetCompositionTimingInfoPtr = nullptr; 1.97 + 1.98 +/* static */ 1.99 +void 1.100 +WinUtils::Initialize() 1.101 +{ 1.102 +#ifdef PR_LOGGING 1.103 + if (!gWindowsLog) { 1.104 + gWindowsLog = PR_NewLogModule("Widget"); 1.105 + } 1.106 +#endif 1.107 + if (!sDwmDll && IsVistaOrLater()) { 1.108 + sDwmDll = ::LoadLibraryW(kDwmLibraryName); 1.109 + 1.110 + if (sDwmDll) { 1.111 + dwmExtendFrameIntoClientAreaPtr = (DwmExtendFrameIntoClientAreaProc)::GetProcAddress(sDwmDll, "DwmExtendFrameIntoClientArea"); 1.112 + dwmIsCompositionEnabledPtr = (DwmIsCompositionEnabledProc)::GetProcAddress(sDwmDll, "DwmIsCompositionEnabled"); 1.113 + dwmSetIconicThumbnailPtr = (DwmSetIconicThumbnailProc)::GetProcAddress(sDwmDll, "DwmSetIconicThumbnail"); 1.114 + dwmSetIconicLivePreviewBitmapPtr = (DwmSetIconicLivePreviewBitmapProc)::GetProcAddress(sDwmDll, "DwmSetIconicLivePreviewBitmap"); 1.115 + dwmGetWindowAttributePtr = (DwmGetWindowAttributeProc)::GetProcAddress(sDwmDll, "DwmGetWindowAttribute"); 1.116 + dwmSetWindowAttributePtr = (DwmSetWindowAttributeProc)::GetProcAddress(sDwmDll, "DwmSetWindowAttribute"); 1.117 + dwmInvalidateIconicBitmapsPtr = (DwmInvalidateIconicBitmapsProc)::GetProcAddress(sDwmDll, "DwmInvalidateIconicBitmaps"); 1.118 + dwmDwmDefWindowProcPtr = (DwmDefWindowProcProc)::GetProcAddress(sDwmDll, "DwmDefWindowProc"); 1.119 + dwmGetCompositionTimingInfoPtr = (DwmGetCompositionTimingInfoProc)::GetProcAddress(sDwmDll, "DwmGetCompositionTimingInfo"); 1.120 + } 1.121 + } 1.122 +} 1.123 + 1.124 +// static 1.125 +void 1.126 +WinUtils::LogW(const wchar_t *fmt, ...) 1.127 +{ 1.128 + va_list args = nullptr; 1.129 + if(!lstrlenW(fmt)) { 1.130 + return; 1.131 + } 1.132 + va_start(args, fmt); 1.133 + int buflen = _vscwprintf(fmt, args); 1.134 + wchar_t* buffer = new wchar_t[buflen+1]; 1.135 + if (!buffer) { 1.136 + va_end(args); 1.137 + return; 1.138 + } 1.139 + vswprintf(buffer, buflen, fmt, args); 1.140 + va_end(args); 1.141 + 1.142 + // MSVC, including remote debug sessions 1.143 + OutputDebugStringW(buffer); 1.144 + OutputDebugStringW(L"\n"); 1.145 + 1.146 + int len = wcslen(buffer); 1.147 + if (len) { 1.148 + char* utf8 = new char[len+1]; 1.149 + memset(utf8, 0, sizeof(utf8)); 1.150 + if (WideCharToMultiByte(CP_ACP, 0, buffer, 1.151 + -1, utf8, len+1, nullptr, 1.152 + nullptr) > 0) { 1.153 + // desktop console 1.154 + printf("%s\n", utf8); 1.155 +#ifdef PR_LOGGING 1.156 + NS_ASSERTION(gWindowsLog, "Called WinUtils Log() but Widget " 1.157 + "log module doesn't exist!"); 1.158 + PR_LOG(gWindowsLog, PR_LOG_ALWAYS, (utf8)); 1.159 +#endif 1.160 + } 1.161 + delete[] utf8; 1.162 + } 1.163 + delete[] buffer; 1.164 +} 1.165 + 1.166 +// static 1.167 +void 1.168 +WinUtils::Log(const char *fmt, ...) 1.169 +{ 1.170 + va_list args = nullptr; 1.171 + if(!strlen(fmt)) { 1.172 + return; 1.173 + } 1.174 + va_start(args, fmt); 1.175 + int buflen = _vscprintf(fmt, args); 1.176 + char* buffer = new char[buflen+1]; 1.177 + if (!buffer) { 1.178 + va_end(args); 1.179 + return; 1.180 + } 1.181 + vsprintf(buffer, fmt, args); 1.182 + va_end(args); 1.183 + 1.184 + // MSVC, including remote debug sessions 1.185 + OutputDebugStringA(buffer); 1.186 + OutputDebugStringW(L"\n"); 1.187 + 1.188 + // desktop console 1.189 + printf("%s\n", buffer); 1.190 + 1.191 +#ifdef PR_LOGGING 1.192 + NS_ASSERTION(gWindowsLog, "Called WinUtils Log() but Widget " 1.193 + "log module doesn't exist!"); 1.194 + PR_LOG(gWindowsLog, PR_LOG_ALWAYS, (buffer)); 1.195 +#endif 1.196 + delete[] buffer; 1.197 +} 1.198 + 1.199 +/* static */ 1.200 +double 1.201 +WinUtils::LogToPhysFactor() 1.202 +{ 1.203 + // dpi / 96.0 1.204 + if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) { 1.205 +#ifdef MOZ_METRO 1.206 + return MetroUtils::LogToPhysFactor(); 1.207 +#else 1.208 + return 1.0; 1.209 +#endif 1.210 + } else { 1.211 + HDC hdc = ::GetDC(nullptr); 1.212 + double result = ::GetDeviceCaps(hdc, LOGPIXELSY) / 96.0; 1.213 + ::ReleaseDC(nullptr, hdc); 1.214 + return result; 1.215 + } 1.216 +} 1.217 + 1.218 +/* static */ 1.219 +double 1.220 +WinUtils::PhysToLogFactor() 1.221 +{ 1.222 + // 1.0 / (dpi / 96.0) 1.223 + return 1.0 / LogToPhysFactor(); 1.224 +} 1.225 + 1.226 +/* static */ 1.227 +double 1.228 +WinUtils::PhysToLog(int32_t aValue) 1.229 +{ 1.230 + return double(aValue) * PhysToLogFactor(); 1.231 +} 1.232 + 1.233 +/* static */ 1.234 +int32_t 1.235 +WinUtils::LogToPhys(double aValue) 1.236 +{ 1.237 + return int32_t(NS_round(aValue * LogToPhysFactor())); 1.238 +} 1.239 + 1.240 +/* static */ 1.241 +bool 1.242 +WinUtils::PeekMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage, 1.243 + UINT aLastMessage, UINT aOption) 1.244 +{ 1.245 +#ifdef NS_ENABLE_TSF 1.246 + ITfMessagePump* msgPump = nsTextStore::GetMessagePump(); 1.247 + if (msgPump) { 1.248 + BOOL ret = FALSE; 1.249 + HRESULT hr = msgPump->PeekMessageW(aMsg, aWnd, aFirstMessage, aLastMessage, 1.250 + aOption, &ret); 1.251 + NS_ENSURE_TRUE(SUCCEEDED(hr), false); 1.252 + return ret; 1.253 + } 1.254 +#endif // #ifdef NS_ENABLE_TSF 1.255 + return ::PeekMessageW(aMsg, aWnd, aFirstMessage, aLastMessage, aOption); 1.256 +} 1.257 + 1.258 +/* static */ 1.259 +bool 1.260 +WinUtils::GetMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage, 1.261 + UINT aLastMessage) 1.262 +{ 1.263 +#ifdef NS_ENABLE_TSF 1.264 + ITfMessagePump* msgPump = nsTextStore::GetMessagePump(); 1.265 + if (msgPump) { 1.266 + BOOL ret = FALSE; 1.267 + HRESULT hr = msgPump->GetMessageW(aMsg, aWnd, aFirstMessage, aLastMessage, 1.268 + &ret); 1.269 + NS_ENSURE_TRUE(SUCCEEDED(hr), false); 1.270 + return ret; 1.271 + } 1.272 +#endif // #ifdef NS_ENABLE_TSF 1.273 + return ::GetMessageW(aMsg, aWnd, aFirstMessage, aLastMessage); 1.274 +} 1.275 + 1.276 +/* static */ 1.277 +bool 1.278 +WinUtils::GetRegistryKey(HKEY aRoot, 1.279 + char16ptr_t aKeyName, 1.280 + char16ptr_t aValueName, 1.281 + wchar_t* aBuffer, 1.282 + DWORD aBufferLength) 1.283 +{ 1.284 + NS_PRECONDITION(aKeyName, "The key name is NULL"); 1.285 + 1.286 + HKEY key; 1.287 + LONG result = 1.288 + ::RegOpenKeyExW(aRoot, aKeyName, 0, KEY_READ | KEY_WOW64_32KEY, &key); 1.289 + if (result != ERROR_SUCCESS) { 1.290 + result = 1.291 + ::RegOpenKeyExW(aRoot, aKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &key); 1.292 + if (result != ERROR_SUCCESS) { 1.293 + return false; 1.294 + } 1.295 + } 1.296 + 1.297 + DWORD type; 1.298 + result = 1.299 + ::RegQueryValueExW(key, aValueName, nullptr, &type, (BYTE*) aBuffer, 1.300 + &aBufferLength); 1.301 + ::RegCloseKey(key); 1.302 + if (result != ERROR_SUCCESS || type != REG_SZ) { 1.303 + return false; 1.304 + } 1.305 + if (aBuffer) { 1.306 + aBuffer[aBufferLength / sizeof(*aBuffer) - 1] = 0; 1.307 + } 1.308 + return true; 1.309 +} 1.310 + 1.311 +/* static */ 1.312 +bool 1.313 +WinUtils::HasRegistryKey(HKEY aRoot, char16ptr_t aKeyName) 1.314 +{ 1.315 + MOZ_ASSERT(aRoot, "aRoot must not be NULL"); 1.316 + MOZ_ASSERT(aKeyName, "aKeyName must not be NULL"); 1.317 + HKEY key; 1.318 + LONG result = 1.319 + ::RegOpenKeyExW(aRoot, aKeyName, 0, KEY_READ | KEY_WOW64_32KEY, &key); 1.320 + if (result != ERROR_SUCCESS) { 1.321 + result = 1.322 + ::RegOpenKeyExW(aRoot, aKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &key); 1.323 + if (result != ERROR_SUCCESS) { 1.324 + return false; 1.325 + } 1.326 + } 1.327 + ::RegCloseKey(key); 1.328 + return true; 1.329 +} 1.330 + 1.331 +/* static */ 1.332 +HWND 1.333 +WinUtils::GetTopLevelHWND(HWND aWnd, 1.334 + bool aStopIfNotChild, 1.335 + bool aStopIfNotPopup) 1.336 +{ 1.337 + HWND curWnd = aWnd; 1.338 + HWND topWnd = nullptr; 1.339 + 1.340 + while (curWnd) { 1.341 + topWnd = curWnd; 1.342 + 1.343 + if (aStopIfNotChild) { 1.344 + DWORD_PTR style = ::GetWindowLongPtrW(curWnd, GWL_STYLE); 1.345 + 1.346 + VERIFY_WINDOW_STYLE(style); 1.347 + 1.348 + if (!(style & WS_CHILD)) // first top-level window 1.349 + break; 1.350 + } 1.351 + 1.352 + HWND upWnd = ::GetParent(curWnd); // Parent or owner (if has no parent) 1.353 + 1.354 + // GetParent will only return the owner if the passed in window 1.355 + // has the WS_POPUP style. 1.356 + if (!upWnd && !aStopIfNotPopup) { 1.357 + upWnd = ::GetWindow(curWnd, GW_OWNER); 1.358 + } 1.359 + curWnd = upWnd; 1.360 + } 1.361 + 1.362 + return topWnd; 1.363 +} 1.364 + 1.365 +static const wchar_t* 1.366 +GetNSWindowPropName() 1.367 +{ 1.368 + static wchar_t sPropName[40] = L""; 1.369 + if (!*sPropName) { 1.370 + _snwprintf(sPropName, 39, L"MozillansIWidgetPtr%p", 1.371 + ::GetCurrentProcessId()); 1.372 + sPropName[39] = '\0'; 1.373 + } 1.374 + return sPropName; 1.375 +} 1.376 + 1.377 +/* static */ 1.378 +bool 1.379 +WinUtils::SetNSWindowBasePtr(HWND aWnd, nsWindowBase* aWidget) 1.380 +{ 1.381 + if (!aWidget) { 1.382 + ::RemovePropW(aWnd, GetNSWindowPropName()); 1.383 + return true; 1.384 + } 1.385 + return ::SetPropW(aWnd, GetNSWindowPropName(), (HANDLE)aWidget); 1.386 +} 1.387 + 1.388 +/* static */ 1.389 +nsWindowBase* 1.390 +WinUtils::GetNSWindowBasePtr(HWND aWnd) 1.391 +{ 1.392 + return static_cast<nsWindowBase*>(::GetPropW(aWnd, GetNSWindowPropName())); 1.393 +} 1.394 + 1.395 +/* static */ 1.396 +nsWindow* 1.397 +WinUtils::GetNSWindowPtr(HWND aWnd) 1.398 +{ 1.399 + return static_cast<nsWindow*>(::GetPropW(aWnd, GetNSWindowPropName())); 1.400 +} 1.401 + 1.402 +static BOOL CALLBACK 1.403 +AddMonitor(HMONITOR, HDC, LPRECT, LPARAM aParam) 1.404 +{ 1.405 + (*(int32_t*)aParam)++; 1.406 + return TRUE; 1.407 +} 1.408 + 1.409 +/* static */ 1.410 +int32_t 1.411 +WinUtils::GetMonitorCount() 1.412 +{ 1.413 + int32_t monitorCount = 0; 1.414 + EnumDisplayMonitors(nullptr, nullptr, AddMonitor, (LPARAM)&monitorCount); 1.415 + return monitorCount; 1.416 +} 1.417 + 1.418 +/* static */ 1.419 +bool 1.420 +WinUtils::IsOurProcessWindow(HWND aWnd) 1.421 +{ 1.422 + if (!aWnd) { 1.423 + return false; 1.424 + } 1.425 + DWORD processId = 0; 1.426 + ::GetWindowThreadProcessId(aWnd, &processId); 1.427 + return (processId == ::GetCurrentProcessId()); 1.428 +} 1.429 + 1.430 +/* static */ 1.431 +HWND 1.432 +WinUtils::FindOurProcessWindow(HWND aWnd) 1.433 +{ 1.434 + for (HWND wnd = ::GetParent(aWnd); wnd; wnd = ::GetParent(wnd)) { 1.435 + if (IsOurProcessWindow(wnd)) { 1.436 + return wnd; 1.437 + } 1.438 + } 1.439 + return nullptr; 1.440 +} 1.441 + 1.442 +static bool 1.443 +IsPointInWindow(HWND aWnd, const POINT& aPointInScreen) 1.444 +{ 1.445 + RECT bounds; 1.446 + if (!::GetWindowRect(aWnd, &bounds)) { 1.447 + return false; 1.448 + } 1.449 + 1.450 + return (aPointInScreen.x >= bounds.left && aPointInScreen.x < bounds.right && 1.451 + aPointInScreen.y >= bounds.top && aPointInScreen.y < bounds.bottom); 1.452 +} 1.453 + 1.454 +/** 1.455 + * FindTopmostWindowAtPoint() returns the topmost child window (topmost means 1.456 + * forground in this context) of aWnd. 1.457 + */ 1.458 + 1.459 +static HWND 1.460 +FindTopmostWindowAtPoint(HWND aWnd, const POINT& aPointInScreen) 1.461 +{ 1.462 + if (!::IsWindowVisible(aWnd) || !IsPointInWindow(aWnd, aPointInScreen)) { 1.463 + return nullptr; 1.464 + } 1.465 + 1.466 + HWND childWnd = ::GetTopWindow(aWnd); 1.467 + while (childWnd) { 1.468 + HWND topmostWnd = FindTopmostWindowAtPoint(childWnd, aPointInScreen); 1.469 + if (topmostWnd) { 1.470 + return topmostWnd; 1.471 + } 1.472 + childWnd = ::GetNextWindow(childWnd, GW_HWNDNEXT); 1.473 + } 1.474 + 1.475 + return aWnd; 1.476 +} 1.477 + 1.478 +struct FindOurWindowAtPointInfo 1.479 +{ 1.480 + POINT mInPointInScreen; 1.481 + HWND mOutWnd; 1.482 +}; 1.483 + 1.484 +static BOOL CALLBACK 1.485 +FindOurWindowAtPointCallback(HWND aWnd, LPARAM aLPARAM) 1.486 +{ 1.487 + if (!WinUtils::IsOurProcessWindow(aWnd)) { 1.488 + // This isn't one of our top-level windows; continue enumerating. 1.489 + return TRUE; 1.490 + } 1.491 + 1.492 + // Get the top-most child window under the point. If there's no child 1.493 + // window, and the point is within the top-level window, then the top-level 1.494 + // window will be returned. (This is the usual case. A child window 1.495 + // would be returned for plugins.) 1.496 + FindOurWindowAtPointInfo* info = 1.497 + reinterpret_cast<FindOurWindowAtPointInfo*>(aLPARAM); 1.498 + HWND childWnd = FindTopmostWindowAtPoint(aWnd, info->mInPointInScreen); 1.499 + if (!childWnd) { 1.500 + // This window doesn't contain the point; continue enumerating. 1.501 + return TRUE; 1.502 + } 1.503 + 1.504 + // Return the HWND and stop enumerating. 1.505 + info->mOutWnd = childWnd; 1.506 + return FALSE; 1.507 +} 1.508 + 1.509 +/* static */ 1.510 +HWND 1.511 +WinUtils::FindOurWindowAtPoint(const POINT& aPointInScreen) 1.512 +{ 1.513 + FindOurWindowAtPointInfo info; 1.514 + info.mInPointInScreen = aPointInScreen; 1.515 + info.mOutWnd = nullptr; 1.516 + 1.517 + // This will enumerate all top-level windows in order from top to bottom. 1.518 + EnumWindows(FindOurWindowAtPointCallback, reinterpret_cast<LPARAM>(&info)); 1.519 + return info.mOutWnd; 1.520 +} 1.521 + 1.522 +/* static */ 1.523 +UINT 1.524 +WinUtils::GetInternalMessage(UINT aNativeMessage) 1.525 +{ 1.526 + switch (aNativeMessage) { 1.527 + case WM_MOUSEWHEEL: 1.528 + return MOZ_WM_MOUSEVWHEEL; 1.529 + case WM_MOUSEHWHEEL: 1.530 + return MOZ_WM_MOUSEHWHEEL; 1.531 + case WM_VSCROLL: 1.532 + return MOZ_WM_VSCROLL; 1.533 + case WM_HSCROLL: 1.534 + return MOZ_WM_HSCROLL; 1.535 + default: 1.536 + return aNativeMessage; 1.537 + } 1.538 +} 1.539 + 1.540 +/* static */ 1.541 +UINT 1.542 +WinUtils::GetNativeMessage(UINT aInternalMessage) 1.543 +{ 1.544 + switch (aInternalMessage) { 1.545 + case MOZ_WM_MOUSEVWHEEL: 1.546 + return WM_MOUSEWHEEL; 1.547 + case MOZ_WM_MOUSEHWHEEL: 1.548 + return WM_MOUSEHWHEEL; 1.549 + case MOZ_WM_VSCROLL: 1.550 + return WM_VSCROLL; 1.551 + case MOZ_WM_HSCROLL: 1.552 + return WM_HSCROLL; 1.553 + default: 1.554 + return aInternalMessage; 1.555 + } 1.556 +} 1.557 + 1.558 +/* static */ 1.559 +uint16_t 1.560 +WinUtils::GetMouseInputSource() 1.561 +{ 1.562 + int32_t inputSource = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE; 1.563 + LPARAM lParamExtraInfo = ::GetMessageExtraInfo(); 1.564 + if ((lParamExtraInfo & TABLET_INK_SIGNATURE) == TABLET_INK_CHECK) { 1.565 + inputSource = (lParamExtraInfo & TABLET_INK_TOUCH) ? 1.566 + nsIDOMMouseEvent::MOZ_SOURCE_TOUCH : nsIDOMMouseEvent::MOZ_SOURCE_PEN; 1.567 + } 1.568 + return static_cast<uint16_t>(inputSource); 1.569 +} 1.570 + 1.571 +bool 1.572 +WinUtils::GetIsMouseFromTouch(uint32_t aEventType) 1.573 +{ 1.574 +#define MOUSEEVENTF_FROMTOUCH 0xFF515700 1.575 + return (aEventType == NS_MOUSE_BUTTON_DOWN || 1.576 + aEventType == NS_MOUSE_BUTTON_UP || 1.577 + aEventType == NS_MOUSE_MOVE) && 1.578 + (GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH); 1.579 +} 1.580 + 1.581 +/* static */ 1.582 +MSG 1.583 +WinUtils::InitMSG(UINT aMessage, WPARAM wParam, LPARAM lParam, HWND aWnd) 1.584 +{ 1.585 + MSG msg; 1.586 + msg.message = aMessage; 1.587 + msg.wParam = wParam; 1.588 + msg.lParam = lParam; 1.589 + msg.hwnd = aWnd; 1.590 + return msg; 1.591 +} 1.592 + 1.593 +/* static */ 1.594 +HRESULT 1.595 +WinUtils::SHCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, 1.596 + REFIID riid, void **ppv) 1.597 +{ 1.598 + if (sCreateItemFromParsingName) { 1.599 + return sCreateItemFromParsingName(pszPath, pbc, riid, ppv); 1.600 + } 1.601 + 1.602 + if (!sShellDll) { 1.603 + sShellDll = ::LoadLibraryW(kShellLibraryName); 1.604 + if (!sShellDll) { 1.605 + return false; 1.606 + } 1.607 + } 1.608 + 1.609 + sCreateItemFromParsingName = (SHCreateItemFromParsingNamePtr) 1.610 + GetProcAddress(sShellDll, "SHCreateItemFromParsingName"); 1.611 + if (!sCreateItemFromParsingName) 1.612 + return E_FAIL; 1.613 + 1.614 + return sCreateItemFromParsingName(pszPath, pbc, riid, ppv); 1.615 +} 1.616 + 1.617 +/* static */ 1.618 +HRESULT 1.619 +WinUtils::SHGetKnownFolderPath(REFKNOWNFOLDERID rfid, 1.620 + DWORD dwFlags, 1.621 + HANDLE hToken, 1.622 + PWSTR *ppszPath) 1.623 +{ 1.624 + if (sGetKnownFolderPath) { 1.625 + return sGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath); 1.626 + } 1.627 + 1.628 + if (!sShellDll) { 1.629 + sShellDll = ::LoadLibraryW(kShellLibraryName); 1.630 + if (!sShellDll) { 1.631 + return false; 1.632 + } 1.633 + } 1.634 + 1.635 + sGetKnownFolderPath = (SHGetKnownFolderPathPtr) 1.636 + GetProcAddress(sShellDll, "SHGetKnownFolderPath"); 1.637 + if (!sGetKnownFolderPath) 1.638 + return E_FAIL; 1.639 + 1.640 + return sGetKnownFolderPath(rfid, dwFlags, hToken, ppszPath); 1.641 +} 1.642 + 1.643 +#ifdef MOZ_PLACES 1.644 +/************************************************************************/ 1.645 +/* Constructs as AsyncFaviconDataReady Object 1.646 +/* @param aIOThread : the thread which performs the action 1.647 +/* @param aURLShortcut : Differentiates between (false)Jumplistcache and (true)Shortcutcache 1.648 +/************************************************************************/ 1.649 + 1.650 +AsyncFaviconDataReady::AsyncFaviconDataReady(nsIURI *aNewURI, 1.651 + nsCOMPtr<nsIThread> &aIOThread, 1.652 + const bool aURLShortcut): 1.653 + mNewURI(aNewURI), 1.654 + mIOThread(aIOThread), 1.655 + mURLShortcut(aURLShortcut) 1.656 +{ 1.657 +} 1.658 + 1.659 +NS_IMETHODIMP 1.660 +myDownloadObserver::OnDownloadComplete(nsIDownloader *downloader, 1.661 + nsIRequest *request, 1.662 + nsISupports *ctxt, 1.663 + nsresult status, 1.664 + nsIFile *result) 1.665 +{ 1.666 + return NS_OK; 1.667 +} 1.668 + 1.669 +nsresult AsyncFaviconDataReady::OnFaviconDataNotAvailable(void) 1.670 +{ 1.671 + if (!mURLShortcut) { 1.672 + return NS_OK; 1.673 + } 1.674 + 1.675 + nsCOMPtr<nsIFile> icoFile; 1.676 + nsresult rv = FaviconHelper::GetOutputIconPath(mNewURI, icoFile, mURLShortcut); 1.677 + NS_ENSURE_SUCCESS(rv, rv); 1.678 + 1.679 + nsCOMPtr<nsIURI> mozIconURI; 1.680 + rv = NS_NewURI(getter_AddRefs(mozIconURI), "moz-icon://.html?size=32"); 1.681 + if (NS_FAILED(rv)) { 1.682 + return rv; 1.683 + } 1.684 + 1.685 + nsCOMPtr<nsIChannel> channel; 1.686 + rv = NS_NewChannel(getter_AddRefs(channel), mozIconURI); 1.687 + NS_ENSURE_SUCCESS(rv, rv); 1.688 + 1.689 + nsCOMPtr<nsIDownloadObserver> downloadObserver = new myDownloadObserver; 1.690 + nsCOMPtr<nsIStreamListener> listener; 1.691 + rv = NS_NewDownloader(getter_AddRefs(listener), downloadObserver, icoFile); 1.692 + NS_ENSURE_SUCCESS(rv, rv); 1.693 + 1.694 + channel->AsyncOpen(listener, nullptr); 1.695 + return NS_OK; 1.696 +} 1.697 + 1.698 +NS_IMETHODIMP 1.699 +AsyncFaviconDataReady::OnComplete(nsIURI *aFaviconURI, 1.700 + uint32_t aDataLen, 1.701 + const uint8_t *aData, 1.702 + const nsACString &aMimeType) 1.703 +{ 1.704 + if (!aDataLen || !aData) { 1.705 + if (mURLShortcut) { 1.706 + OnFaviconDataNotAvailable(); 1.707 + } 1.708 + 1.709 + return NS_OK; 1.710 + } 1.711 + 1.712 + nsCOMPtr<nsIFile> icoFile; 1.713 + nsresult rv = FaviconHelper::GetOutputIconPath(mNewURI, icoFile, mURLShortcut); 1.714 + NS_ENSURE_SUCCESS(rv, rv); 1.715 + 1.716 + nsAutoString path; 1.717 + rv = icoFile->GetPath(path); 1.718 + NS_ENSURE_SUCCESS(rv, rv); 1.719 + 1.720 + // Convert the obtained favicon data to an input stream 1.721 + nsCOMPtr<nsIInputStream> stream; 1.722 + rv = NS_NewByteInputStream(getter_AddRefs(stream), 1.723 + reinterpret_cast<const char*>(aData), 1.724 + aDataLen, 1.725 + NS_ASSIGNMENT_DEPEND); 1.726 + NS_ENSURE_SUCCESS(rv, rv); 1.727 + 1.728 + // Decode the image from the format it was returned to us in (probably PNG) 1.729 + nsAutoCString mimeTypeOfInputData; 1.730 + mimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon"); 1.731 + nsCOMPtr<imgIContainer> container; 1.732 + nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1"); 1.733 + rv = imgtool->DecodeImageData(stream, aMimeType, 1.734 + getter_AddRefs(container)); 1.735 + NS_ENSURE_SUCCESS(rv, rv); 1.736 + 1.737 + RefPtr<SourceSurface> surface = 1.738 + container->GetFrame(imgIContainer::FRAME_FIRST, 0); 1.739 + NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); 1.740 + 1.741 + RefPtr<DataSourceSurface> dataSurface; 1.742 + IntSize size; 1.743 + 1.744 + if (mURLShortcut) { 1.745 + // Create a 48x48 surface and paint the icon into the central 16x16 rect. 1.746 + size.width = 48; 1.747 + size.height = 48; 1.748 + dataSurface = 1.749 + Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8); 1.750 + NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); 1.751 + 1.752 + DataSourceSurface::MappedSurface map; 1.753 + if (!dataSurface->Map(DataSourceSurface::MapType::WRITE, &map)) { 1.754 + return NS_ERROR_FAILURE; 1.755 + } 1.756 + 1.757 + RefPtr<DrawTarget> dt = 1.758 + Factory::CreateDrawTargetForData(BackendType::CAIRO, 1.759 + map.mData, 1.760 + dataSurface->GetSize(), 1.761 + map.mStride, 1.762 + dataSurface->GetFormat()); 1.763 + dt->FillRect(Rect(0, 0, size.width, size.height), 1.764 + ColorPattern(Color(1.0f, 1.0f, 1.0f, 1.0f))); 1.765 + dt->DrawSurface(surface, 1.766 + Rect(16, 16, 16, 16), 1.767 + Rect(Point(0, 0), 1.768 + Size(surface->GetSize().width, surface->GetSize().height))); 1.769 + 1.770 + dataSurface->Unmap(); 1.771 + } else { 1.772 + // By using the input image surface's size, we may end up encoding 1.773 + // to a different size than a 16x16 (or bigger for higher DPI) ICO, but 1.774 + // Windows will resize appropriately for us. If we want to encode ourselves 1.775 + // one day because we like our resizing better, we'd have to manually 1.776 + // resize the image here and use GetSystemMetrics w/ SM_CXSMICON and 1.777 + // SM_CYSMICON. We don't support resizing images asynchronously at the 1.778 + // moment anyway so getting the DPI aware icon size won't help. 1.779 + size.width = surface->GetSize().width; 1.780 + size.height = surface->GetSize().height; 1.781 + dataSurface = surface->GetDataSurface(); 1.782 + NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); 1.783 + } 1.784 + 1.785 + // Allocate a new buffer that we own and can use out of line in 1.786 + // another thread. 1.787 + uint8_t *data = SurfaceToPackedBGRA(dataSurface); 1.788 + if (!data) { 1.789 + return NS_ERROR_OUT_OF_MEMORY; 1.790 + } 1.791 + int32_t stride = 4 * size.width; 1.792 + int32_t dataLength = stride * size.height; 1.793 + 1.794 + // AsyncEncodeAndWriteIcon takes ownership of the heap allocated buffer 1.795 + nsCOMPtr<nsIRunnable> event = new AsyncEncodeAndWriteIcon(path, data, 1.796 + dataLength, 1.797 + stride, 1.798 + size.width, 1.799 + size.height, 1.800 + mURLShortcut); 1.801 + mIOThread->Dispatch(event, NS_DISPATCH_NORMAL); 1.802 + 1.803 + return NS_OK; 1.804 +} 1.805 +#endif 1.806 + 1.807 +// Warning: AsyncEncodeAndWriteIcon assumes ownership of the aData buffer passed in 1.808 +AsyncEncodeAndWriteIcon::AsyncEncodeAndWriteIcon(const nsAString &aIconPath, 1.809 + uint8_t *aBuffer, 1.810 + uint32_t aBufferLength, 1.811 + uint32_t aStride, 1.812 + uint32_t aWidth, 1.813 + uint32_t aHeight, 1.814 + const bool aURLShortcut) : 1.815 + mURLShortcut(aURLShortcut), 1.816 + mIconPath(aIconPath), 1.817 + mBuffer(aBuffer), 1.818 + mBufferLength(aBufferLength), 1.819 + mStride(aStride), 1.820 + mWidth(aWidth), 1.821 + mHeight(aHeight) 1.822 +{ 1.823 +} 1.824 + 1.825 +NS_IMETHODIMP AsyncEncodeAndWriteIcon::Run() 1.826 +{ 1.827 + NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread."); 1.828 + 1.829 + nsCOMPtr<nsIInputStream> iconStream; 1.830 + nsRefPtr<imgIEncoder> encoder = 1.831 + do_CreateInstance("@mozilla.org/image/encoder;2?" 1.832 + "type=image/vnd.microsoft.icon"); 1.833 + NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE); 1.834 + nsresult rv = encoder->InitFromData(mBuffer, mBufferLength, 1.835 + mWidth, mHeight, 1.836 + mStride, 1.837 + imgIEncoder::INPUT_FORMAT_HOSTARGB, 1.838 + EmptyString()); 1.839 + NS_ENSURE_SUCCESS(rv, rv); 1.840 + CallQueryInterface(encoder.get(), getter_AddRefs(iconStream)); 1.841 + if (!iconStream) { 1.842 + return NS_ERROR_FAILURE; 1.843 + } 1.844 + 1.845 + NS_ENSURE_SUCCESS(rv, rv); 1.846 + nsCOMPtr<nsIFile> icoFile 1.847 + = do_CreateInstance("@mozilla.org/file/local;1"); 1.848 + NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE); 1.849 + rv = icoFile->InitWithPath(mIconPath); 1.850 + 1.851 + // Try to create the directory if it's not there yet 1.852 + nsCOMPtr<nsIFile> dirPath; 1.853 + icoFile->GetParent(getter_AddRefs(dirPath)); 1.854 + rv = (dirPath->Create(nsIFile::DIRECTORY_TYPE, 0777)); 1.855 + if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) { 1.856 + return rv; 1.857 + } 1.858 + 1.859 + // Setup the output stream for the ICO file on disk 1.860 + nsCOMPtr<nsIOutputStream> outputStream; 1.861 + rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile); 1.862 + NS_ENSURE_SUCCESS(rv, rv); 1.863 + 1.864 + // Obtain the ICO buffer size from the re-encoded ICO stream 1.865 + uint64_t bufSize64; 1.866 + rv = iconStream->Available(&bufSize64); 1.867 + NS_ENSURE_SUCCESS(rv, rv); 1.868 + NS_ENSURE_TRUE(bufSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG); 1.869 + 1.870 + uint32_t bufSize = (uint32_t)bufSize64; 1.871 + 1.872 + // Setup a buffered output stream from the stream object 1.873 + // so that we can simply use WriteFrom with the stream object 1.874 + nsCOMPtr<nsIOutputStream> bufferedOutputStream; 1.875 + rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream), 1.876 + outputStream, bufSize); 1.877 + NS_ENSURE_SUCCESS(rv, rv); 1.878 + 1.879 + // Write out the icon stream to disk and make sure we wrote everything 1.880 + uint32_t wrote; 1.881 + rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote); 1.882 + NS_ASSERTION(bufSize == wrote, 1.883 + "Icon wrote size should be equal to requested write size"); 1.884 + 1.885 + // Cleanup 1.886 + bufferedOutputStream->Close(); 1.887 + outputStream->Close(); 1.888 + if (mURLShortcut) { 1.889 + SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0); 1.890 + } 1.891 + return rv; 1.892 +} 1.893 + 1.894 +AsyncEncodeAndWriteIcon::~AsyncEncodeAndWriteIcon() 1.895 +{ 1.896 +} 1.897 + 1.898 +AsyncDeleteIconFromDisk::AsyncDeleteIconFromDisk(const nsAString &aIconPath) 1.899 + : mIconPath(aIconPath) 1.900 +{ 1.901 +} 1.902 + 1.903 +NS_IMETHODIMP AsyncDeleteIconFromDisk::Run() 1.904 +{ 1.905 + // Construct the parent path of the passed in path 1.906 + nsCOMPtr<nsIFile> icoFile = do_CreateInstance("@mozilla.org/file/local;1"); 1.907 + NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE); 1.908 + nsresult rv = icoFile->InitWithPath(mIconPath); 1.909 + NS_ENSURE_SUCCESS(rv, rv); 1.910 + 1.911 + // Check if the cached ICO file exists 1.912 + bool exists; 1.913 + rv = icoFile->Exists(&exists); 1.914 + NS_ENSURE_SUCCESS(rv, rv); 1.915 + 1.916 + // Check that we aren't deleting some arbitrary file that is not an icon 1.917 + if (StringTail(mIconPath, 4).LowerCaseEqualsASCII(".ico")) { 1.918 + // Check if the cached ICO file exists 1.919 + bool exists; 1.920 + if (NS_FAILED(icoFile->Exists(&exists)) || !exists) 1.921 + return NS_ERROR_FAILURE; 1.922 + 1.923 + // We found an ICO file that exists, so we should remove it 1.924 + icoFile->Remove(false); 1.925 + } 1.926 + 1.927 + return NS_OK; 1.928 +} 1.929 + 1.930 +AsyncDeleteIconFromDisk::~AsyncDeleteIconFromDisk() 1.931 +{ 1.932 +} 1.933 + 1.934 +AsyncDeleteAllFaviconsFromDisk::AsyncDeleteAllFaviconsFromDisk() 1.935 +{ 1.936 +} 1.937 + 1.938 +NS_IMETHODIMP AsyncDeleteAllFaviconsFromDisk::Run() 1.939 +{ 1.940 + // Construct the path of our jump list cache 1.941 + nsCOMPtr<nsIFile> jumpListCacheDir; 1.942 + nsresult rv = NS_GetSpecialDirectory("ProfLDS", 1.943 + getter_AddRefs(jumpListCacheDir)); 1.944 + NS_ENSURE_SUCCESS(rv, rv); 1.945 + rv = jumpListCacheDir->AppendNative( 1.946 + nsDependentCString(FaviconHelper::kJumpListCacheDir)); 1.947 + NS_ENSURE_SUCCESS(rv, rv); 1.948 + nsCOMPtr<nsISimpleEnumerator> entries; 1.949 + rv = jumpListCacheDir->GetDirectoryEntries(getter_AddRefs(entries)); 1.950 + NS_ENSURE_SUCCESS(rv, rv); 1.951 + 1.952 + // Loop through each directory entry and remove all ICO files found 1.953 + do { 1.954 + bool hasMore = false; 1.955 + if (NS_FAILED(entries->HasMoreElements(&hasMore)) || !hasMore) 1.956 + break; 1.957 + 1.958 + nsCOMPtr<nsISupports> supp; 1.959 + if (NS_FAILED(entries->GetNext(getter_AddRefs(supp)))) 1.960 + break; 1.961 + 1.962 + nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp)); 1.963 + nsAutoString path; 1.964 + if (NS_FAILED(currFile->GetPath(path))) 1.965 + continue; 1.966 + 1.967 + if (StringTail(path, 4).LowerCaseEqualsASCII(".ico")) { 1.968 + // Check if the cached ICO file exists 1.969 + bool exists; 1.970 + if (NS_FAILED(currFile->Exists(&exists)) || !exists) 1.971 + continue; 1.972 + 1.973 + // We found an ICO file that exists, so we should remove it 1.974 + currFile->Remove(false); 1.975 + } 1.976 + } while(true); 1.977 + 1.978 + return NS_OK; 1.979 +} 1.980 + 1.981 +AsyncDeleteAllFaviconsFromDisk::~AsyncDeleteAllFaviconsFromDisk() 1.982 +{ 1.983 +} 1.984 + 1.985 + 1.986 +/* 1.987 + * (static) If the data is available, will return the path on disk where 1.988 + * the favicon for page aFaviconPageURI is stored. If the favicon does not 1.989 + * exist, or its cache is expired, this method will kick off an async request 1.990 + * for the icon so that next time the method is called it will be available. 1.991 + * @param aFaviconPageURI The URI of the page to obtain 1.992 + * @param aICOFilePath The path of the icon file 1.993 + * @param aIOThread The thread to perform the Fetch on 1.994 + * @param aURLShortcut to distinguish between jumplistcache(false) and shortcutcache(true) 1.995 + */ 1.996 +nsresult FaviconHelper::ObtainCachedIconFile(nsCOMPtr<nsIURI> aFaviconPageURI, 1.997 + nsString &aICOFilePath, 1.998 + nsCOMPtr<nsIThread> &aIOThread, 1.999 + bool aURLShortcut) 1.1000 +{ 1.1001 + // Obtain the ICO file path 1.1002 + nsCOMPtr<nsIFile> icoFile; 1.1003 + nsresult rv = GetOutputIconPath(aFaviconPageURI, icoFile, aURLShortcut); 1.1004 + NS_ENSURE_SUCCESS(rv, rv); 1.1005 + 1.1006 + // Check if the cached ICO file already exists 1.1007 + bool exists; 1.1008 + rv = icoFile->Exists(&exists); 1.1009 + NS_ENSURE_SUCCESS(rv, rv); 1.1010 + 1.1011 + if (exists) { 1.1012 + 1.1013 + // Obtain the file's last modification date in seconds 1.1014 + int64_t fileModTime = 0; 1.1015 + rv = icoFile->GetLastModifiedTime(&fileModTime); 1.1016 + fileModTime /= PR_MSEC_PER_SEC; 1.1017 + int32_t icoReCacheSecondsTimeout = GetICOCacheSecondsTimeout(); 1.1018 + int64_t nowTime = PR_Now() / int64_t(PR_USEC_PER_SEC); 1.1019 + 1.1020 + // If the last mod call failed or the icon is old then re-cache it 1.1021 + // This check is in case the favicon of a page changes 1.1022 + // the next time we try to build the jump list, the data will be available. 1.1023 + if (NS_FAILED(rv) || 1.1024 + (nowTime - fileModTime) > icoReCacheSecondsTimeout) { 1.1025 + CacheIconFileFromFaviconURIAsync(aFaviconPageURI, icoFile, aIOThread, aURLShortcut); 1.1026 + return NS_ERROR_NOT_AVAILABLE; 1.1027 + } 1.1028 + } else { 1.1029 + 1.1030 + // The file does not exist yet, obtain it async from the favicon service so that 1.1031 + // the next time we try to build the jump list it'll be available. 1.1032 + CacheIconFileFromFaviconURIAsync(aFaviconPageURI, icoFile, aIOThread, aURLShortcut); 1.1033 + return NS_ERROR_NOT_AVAILABLE; 1.1034 + } 1.1035 + 1.1036 + // The icoFile is filled with a path that exists, get its path 1.1037 + rv = icoFile->GetPath(aICOFilePath); 1.1038 + return rv; 1.1039 +} 1.1040 + 1.1041 +nsresult FaviconHelper::HashURI(nsCOMPtr<nsICryptoHash> &aCryptoHash, 1.1042 + nsIURI *aUri, 1.1043 + nsACString& aUriHash) 1.1044 +{ 1.1045 + if (!aUri) 1.1046 + return NS_ERROR_INVALID_ARG; 1.1047 + 1.1048 + nsAutoCString spec; 1.1049 + nsresult rv = aUri->GetSpec(spec); 1.1050 + NS_ENSURE_SUCCESS(rv, rv); 1.1051 + 1.1052 + if (!aCryptoHash) { 1.1053 + aCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv); 1.1054 + NS_ENSURE_SUCCESS(rv, rv); 1.1055 + } 1.1056 + 1.1057 + rv = aCryptoHash->Init(nsICryptoHash::MD5); 1.1058 + NS_ENSURE_SUCCESS(rv, rv); 1.1059 + rv = aCryptoHash->Update(reinterpret_cast<const uint8_t*>(spec.BeginReading()), 1.1060 + spec.Length()); 1.1061 + NS_ENSURE_SUCCESS(rv, rv); 1.1062 + rv = aCryptoHash->Finish(true, aUriHash); 1.1063 + NS_ENSURE_SUCCESS(rv, rv); 1.1064 + 1.1065 + return NS_OK; 1.1066 +} 1.1067 + 1.1068 + 1.1069 + 1.1070 +// (static) Obtains the ICO file for the favicon at page aFaviconPageURI 1.1071 +// If successful, the file path on disk is in the format: 1.1072 +// <ProfLDS>\jumpListCache\<hash(aFaviconPageURI)>.ico 1.1073 +nsresult FaviconHelper::GetOutputIconPath(nsCOMPtr<nsIURI> aFaviconPageURI, 1.1074 + nsCOMPtr<nsIFile> &aICOFile, 1.1075 + bool aURLShortcut) 1.1076 +{ 1.1077 + // Hash the input URI and replace any / with _ 1.1078 + nsAutoCString inputURIHash; 1.1079 + nsCOMPtr<nsICryptoHash> cryptoHash; 1.1080 + nsresult rv = HashURI(cryptoHash, aFaviconPageURI, 1.1081 + inputURIHash); 1.1082 + NS_ENSURE_SUCCESS(rv, rv); 1.1083 + char* cur = inputURIHash.BeginWriting(); 1.1084 + char* end = inputURIHash.EndWriting(); 1.1085 + for (; cur < end; ++cur) { 1.1086 + if ('/' == *cur) { 1.1087 + *cur = '_'; 1.1088 + } 1.1089 + } 1.1090 + 1.1091 + // Obtain the local profile directory and construct the output icon file path 1.1092 + rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(aICOFile)); 1.1093 + NS_ENSURE_SUCCESS(rv, rv); 1.1094 + if (!aURLShortcut) 1.1095 + rv = aICOFile->AppendNative(nsDependentCString(kJumpListCacheDir)); 1.1096 + else 1.1097 + rv = aICOFile->AppendNative(nsDependentCString(kShortcutCacheDir)); 1.1098 + NS_ENSURE_SUCCESS(rv, rv); 1.1099 + 1.1100 + // Append the icon extension 1.1101 + inputURIHash.Append(".ico"); 1.1102 + rv = aICOFile->AppendNative(inputURIHash); 1.1103 + 1.1104 + return rv; 1.1105 +} 1.1106 + 1.1107 +// (static) Asynchronously creates a cached ICO file on disk for the favicon of 1.1108 +// page aFaviconPageURI and stores it to disk at the path of aICOFile. 1.1109 +nsresult 1.1110 + FaviconHelper::CacheIconFileFromFaviconURIAsync(nsCOMPtr<nsIURI> aFaviconPageURI, 1.1111 + nsCOMPtr<nsIFile> aICOFile, 1.1112 + nsCOMPtr<nsIThread> &aIOThread, 1.1113 + bool aURLShortcut) 1.1114 +{ 1.1115 +#ifdef MOZ_PLACES 1.1116 + // Obtain the favicon service and get the favicon for the specified page 1.1117 + nsCOMPtr<mozIAsyncFavicons> favIconSvc( 1.1118 + do_GetService("@mozilla.org/browser/favicon-service;1")); 1.1119 + NS_ENSURE_TRUE(favIconSvc, NS_ERROR_FAILURE); 1.1120 + 1.1121 + nsCOMPtr<nsIFaviconDataCallback> callback = 1.1122 + new mozilla::widget::AsyncFaviconDataReady(aFaviconPageURI, 1.1123 + aIOThread, 1.1124 + aURLShortcut); 1.1125 + 1.1126 + favIconSvc->GetFaviconDataForPage(aFaviconPageURI, callback); 1.1127 +#endif 1.1128 + return NS_OK; 1.1129 +} 1.1130 + 1.1131 +// Obtains the jump list 'ICO cache timeout in seconds' pref 1.1132 +int32_t FaviconHelper::GetICOCacheSecondsTimeout() { 1.1133 + 1.1134 + // Only obtain the setting at most once from the pref service. 1.1135 + // In the rare case that 2 threads call this at the same 1.1136 + // time it is no harm and we will simply obtain the pref twice. 1.1137 + // None of the taskbar list prefs are currently updated via a 1.1138 + // pref observer so I think this should suffice. 1.1139 + const int32_t kSecondsPerDay = 86400; 1.1140 + static bool alreadyObtained = false; 1.1141 + static int32_t icoReCacheSecondsTimeout = kSecondsPerDay; 1.1142 + if (alreadyObtained) { 1.1143 + return icoReCacheSecondsTimeout; 1.1144 + } 1.1145 + 1.1146 + // Obtain the pref 1.1147 + const char PREF_ICOTIMEOUT[] = "browser.taskbar.lists.icoTimeoutInSeconds"; 1.1148 + icoReCacheSecondsTimeout = Preferences::GetInt(PREF_ICOTIMEOUT, 1.1149 + kSecondsPerDay); 1.1150 + alreadyObtained = true; 1.1151 + return icoReCacheSecondsTimeout; 1.1152 +} 1.1153 + 1.1154 + 1.1155 + 1.1156 + 1.1157 +/* static */ 1.1158 +bool 1.1159 +WinUtils::GetShellItemPath(IShellItem* aItem, 1.1160 + nsString& aResultString) 1.1161 +{ 1.1162 + NS_ENSURE_TRUE(aItem, false); 1.1163 + LPWSTR str = nullptr; 1.1164 + if (FAILED(aItem->GetDisplayName(SIGDN_FILESYSPATH, &str))) 1.1165 + return false; 1.1166 + aResultString.Assign(str); 1.1167 + CoTaskMemFree(str); 1.1168 + return !aResultString.IsEmpty(); 1.1169 +} 1.1170 + 1.1171 +/* static */ 1.1172 +nsIntRegion 1.1173 +WinUtils::ConvertHRGNToRegion(HRGN aRgn) 1.1174 +{ 1.1175 + NS_ASSERTION(aRgn, "Don't pass NULL region here"); 1.1176 + 1.1177 + nsIntRegion rgn; 1.1178 + 1.1179 + DWORD size = ::GetRegionData(aRgn, 0, nullptr); 1.1180 + nsAutoTArray<uint8_t,100> buffer; 1.1181 + buffer.SetLength(size); 1.1182 + 1.1183 + RGNDATA* data = reinterpret_cast<RGNDATA*>(buffer.Elements()); 1.1184 + if (!::GetRegionData(aRgn, size, data)) 1.1185 + return rgn; 1.1186 + 1.1187 + if (data->rdh.nCount > MAX_RECTS_IN_REGION) { 1.1188 + rgn = ToIntRect(data->rdh.rcBound); 1.1189 + return rgn; 1.1190 + } 1.1191 + 1.1192 + RECT* rects = reinterpret_cast<RECT*>(data->Buffer); 1.1193 + for (uint32_t i = 0; i < data->rdh.nCount; ++i) { 1.1194 + RECT* r = rects + i; 1.1195 + rgn.Or(rgn, ToIntRect(*r)); 1.1196 + } 1.1197 + 1.1198 + return rgn; 1.1199 +} 1.1200 + 1.1201 +nsIntRect 1.1202 +WinUtils::ToIntRect(const RECT& aRect) 1.1203 +{ 1.1204 + return nsIntRect(aRect.left, aRect.top, 1.1205 + aRect.right - aRect.left, 1.1206 + aRect.bottom - aRect.top); 1.1207 +} 1.1208 + 1.1209 +/* static */ 1.1210 +bool 1.1211 +WinUtils::IsIMEEnabled(const InputContext& aInputContext) 1.1212 +{ 1.1213 + return IsIMEEnabled(aInputContext.mIMEState.mEnabled); 1.1214 +} 1.1215 + 1.1216 +/* static */ 1.1217 +bool 1.1218 +WinUtils::IsIMEEnabled(IMEState::Enabled aIMEState) 1.1219 +{ 1.1220 + return (aIMEState == IMEState::ENABLED || 1.1221 + aIMEState == IMEState::PLUGIN); 1.1222 +} 1.1223 + 1.1224 +/* static */ 1.1225 +void 1.1226 +WinUtils::SetupKeyModifiersSequence(nsTArray<KeyPair>* aArray, 1.1227 + uint32_t aModifiers) 1.1228 +{ 1.1229 + for (uint32_t i = 0; i < ArrayLength(sModifierKeyMap); ++i) { 1.1230 + const uint32_t* map = sModifierKeyMap[i]; 1.1231 + if (aModifiers & map[0]) { 1.1232 + aArray->AppendElement(KeyPair(map[1], map[2])); 1.1233 + } 1.1234 + } 1.1235 +} 1.1236 + 1.1237 +/* static */ 1.1238 +bool 1.1239 +WinUtils::ShouldHideScrollbars() 1.1240 +{ 1.1241 +#ifdef MOZ_METRO 1.1242 + if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) { 1.1243 + return widget::winrt::MetroInput::IsInputModeImprecise(); 1.1244 + } 1.1245 +#endif // MOZ_METRO 1.1246 + return false; 1.1247 +} 1.1248 + 1.1249 +} // namespace widget 1.1250 +} // namespace mozilla