2 * Copyright (C) 2006, 2008, 2013-2015 Apple Inc. All rights reserved.
3 * Copyright (C) 2009, 2011 Brent Fulgham. All rights reserved.
4 * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
5 * Copyright (C) 2013 Alex Christensen. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "AccessibilityDelegate.h"
30 #include "DOMDefaultImpl.h"
31 #include "PrintWebUIDelegate.h"
32 #include "ResourceLoadDelegate.h"
33 #include "WebDownloadDelegate.h"
34 #include "MiniBrowser.h"
35 #include "MiniBrowserReplace.h"
36 #include <WebKit/WebKitCOMAPI.h>
37 #include <wtf/ExportMacros.h>
38 #include <wtf/Platform.h>
39 #include <wtf/text/CString.h>
40 #include <wtf/text/WTFString.h>
43 #include <CoreFoundation/CFRunLoop.h>
44 #include <WebKit/CFDictionaryPropertyBag.h>
62 #define MAX_LOADSTRING 100
63 #define URLBAR_HEIGHT 24
64 #define CONTROLBUTTON_WIDTH 24
66 static const int maxHistorySize = 10;
69 #define WM_DPICHANGED 0x02E0
72 typedef _com_ptr_t<_com_IIID<IWebFrame, &__uuidof(IWebFrame)>> IWebFramePtr;
73 typedef _com_ptr_t<_com_IIID<IWebMutableURLRequest, &__uuidof(IWebMutableURLRequest)>> IWebMutableURLRequestPtr;
81 HWND hForwardButtonWnd;
83 WNDPROC DefEditProc = nullptr;
84 WNDPROC DefButtonProc = nullptr;
85 WNDPROC DefWebKitProc = nullptr;
87 MiniBrowser* gMiniBrowser = nullptr;
88 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
89 TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
91 // Support moving the transparent window
92 POINT s_windowPosition = { 100, 100 };
93 SIZE s_windowSize = { 500, 200 };
95 // Forward declarations of functions included in this code module:
96 ATOM MyRegisterClass(HINSTANCE hInstance);
97 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
98 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
99 INT_PTR CALLBACK CustomUserAgent(HWND, UINT, WPARAM, LPARAM);
100 LRESULT CALLBACK EditProc(HWND, UINT, WPARAM, LPARAM);
101 LRESULT CALLBACK BackButtonProc(HWND, UINT, WPARAM, LPARAM);
102 LRESULT CALLBACK ForwardButtonProc(HWND, UINT, WPARAM, LPARAM);
103 LRESULT CALLBACK ReloadButtonProc(HWND, UINT, WPARAM, LPARAM);
104 INT_PTR CALLBACK Caches(HWND, UINT, WPARAM, LPARAM);
105 INT_PTR CALLBACK AuthDialogProc(HWND, UINT, WPARAM, LPARAM);
107 static void loadURL(BSTR urlBStr);
108 static void updateStatistics(HWND hDlg);
111 float deviceScaleFactorForWindow(HWND);
114 static void resizeSubViews()
116 if (gMiniBrowser->usesLayeredWebView() || !gViewWindow)
119 float scaleFactor = WebCore::deviceScaleFactorForWindow(gViewWindow);
122 GetClientRect(hMainWnd, &rcClient);
124 int height = scaleFactor * URLBAR_HEIGHT;
125 int width = scaleFactor * CONTROLBUTTON_WIDTH;
127 MoveWindow(hBackButtonWnd, 0, 0, width, height, TRUE);
128 MoveWindow(hForwardButtonWnd, width, 0, width, height, TRUE);
129 MoveWindow(hURLBarWnd, width * 2, 0, rcClient.right, height, TRUE);
130 MoveWindow(gViewWindow, 0, height, rcClient.right, rcClient.bottom - height, TRUE);
132 ::SendMessage(hURLBarWnd, static_cast<UINT>(WM_SETFONT), reinterpret_cast<WPARAM>(gMiniBrowser->urlBarFont()), TRUE);
135 static void subclassForLayeredWindow()
137 hMainWnd = gViewWindow;
138 #if defined _M_AMD64 || defined _WIN64
139 DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hMainWnd, GWLP_WNDPROC));
140 ::SetWindowLongPtr(hMainWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc));
142 DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLong(hMainWnd, GWL_WNDPROC));
143 ::SetWindowLong(hMainWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc));
147 static void computeFullDesktopFrame()
150 if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, static_cast<void*>(&desktop), 0))
153 float scaleFactor = WebCore::deviceScaleFactorForWindow(nullptr);
155 s_windowPosition.x = 0;
156 s_windowPosition.y = 0;
157 s_windowSize.cx = scaleFactor * (desktop.right - desktop.left);
158 s_windowSize.cy = scaleFactor * (desktop.bottom - desktop.top);
161 BOOL WINAPI DllMain(HINSTANCE dllInstance, DWORD reason, LPVOID)
163 if (reason == DLL_PROCESS_ATTACH)
169 static bool getAppDataFolder(_bstr_t& directory)
171 wchar_t appDataDirectory[MAX_PATH];
172 if (FAILED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, appDataDirectory)))
175 wchar_t executablePath[MAX_PATH];
176 if (!::GetModuleFileNameW(0, executablePath, MAX_PATH))
179 ::PathRemoveExtensionW(executablePath);
181 directory = _bstr_t(appDataDirectory) + L"\\" + ::PathFindFileNameW(executablePath);
186 static bool setCacheFolder()
188 IWebCachePtr webCache = gMiniBrowser->webCache();
192 _bstr_t appDataFolder;
193 if (!getAppDataFolder(appDataFolder))
196 appDataFolder += L"\\cache";
197 webCache->setCacheFolder(appDataFolder);
202 void createCrashReport(EXCEPTION_POINTERS* exceptionPointers)
206 if (!getAppDataFolder(directory))
209 if (::SHCreateDirectoryEx(0, directory, 0) != ERROR_SUCCESS
210 && ::GetLastError() != ERROR_FILE_EXISTS
211 && ::GetLastError() != ERROR_ALREADY_EXISTS)
214 std::wstring fileName = std::wstring(static_cast<const wchar_t*>(directory)) + L"\\CrashReport.dmp";
215 HANDLE miniDumpFile = ::CreateFile(fileName.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
217 if (miniDumpFile && miniDumpFile != INVALID_HANDLE_VALUE) {
219 MINIDUMP_EXCEPTION_INFORMATION mdei;
220 mdei.ThreadId = ::GetCurrentThreadId();
221 mdei.ExceptionPointers = exceptionPointers;
222 mdei.ClientPointers = 0;
225 MINIDUMP_TYPE dumpType = MiniDumpWithFullMemory;
227 MINIDUMP_TYPE dumpType = MiniDumpNormal;
230 ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), miniDumpFile, dumpType, &mdei, 0, 0);
231 ::CloseHandle(miniDumpFile);
232 processCrashReport(fileName.c_str());
236 static BOOL CALLBACK AbortProc(HDC hDC, int Error)
239 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
240 ::TranslateMessage(&msg);
241 ::DispatchMessage(&msg);
247 static HDC getPrinterDC()
250 memset(&pdlg, 0, sizeof(PRINTDLG));
251 pdlg.lStructSize = sizeof(PRINTDLG);
252 pdlg.Flags = PD_PRINTSETUP | PD_RETURNDC;
259 static void initDocStruct(DOCINFO* di, TCHAR* docname)
261 memset(di, 0, sizeof(DOCINFO));
262 di->cbSize = sizeof(DOCINFO);
263 di->lpszDocName = docname;
266 typedef _com_ptr_t<_com_IIID<IWebFramePrivate, &__uuidof(IWebFramePrivate)>> IWebFramePrivatePtr;
268 void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
270 HDC printDC = getPrinterDC();
272 ::MessageBoxW(0, L"Error creating printing DC", L"Error", MB_APPLMODAL | MB_OK);
276 if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) {
277 ::MessageBoxW(0, L"Error setting up AbortProc", L"Error", MB_APPLMODAL | MB_OK);
281 IWebFramePtr frame = gMiniBrowser->mainFrame();
285 IWebFramePrivatePtr framePrivate;
286 if (FAILED(frame->QueryInterface(&framePrivate.GetInterfacePtr())))
289 framePrivate->setInPrintingMode(TRUE, printDC);
292 framePrivate->getPrintedPageCount(printDC, &pageCount);
295 initDocStruct(&di, L"WebKit Doc");
296 ::StartDoc(printDC, &di);
298 // FIXME: Need CoreGraphics implementation
299 void* graphicsContext = 0;
300 for (size_t page = 1; page <= pageCount; ++page) {
301 ::StartPage(printDC);
302 framePrivate->spoolPages(printDC, page, page, graphicsContext);
306 framePrivate->setInPrintingMode(FALSE, printDC);
312 static void ToggleMenuFlag(HWND hWnd, UINT menuID)
314 HMENU menu = ::GetMenu(hWnd);
317 ::memset(&info, 0x00, sizeof(info));
318 info.cbSize = sizeof(info);
319 info.fMask = MIIM_STATE;
321 if (!::GetMenuItemInfo(menu, menuID, FALSE, &info))
324 BOOL newState = !(info.fState & MFS_CHECKED);
325 info.fState = (newState) ? MFS_CHECKED : MFS_UNCHECKED;
327 ::SetMenuItemInfo(menu, menuID, FALSE, &info);
330 static bool menuItemIsChecked(const MENUITEMINFO& info)
332 return info.fState & MFS_CHECKED;
335 static void turnOffOtherUserAgents(HMENU menu)
338 ::memset(&info, 0x00, sizeof(info));
339 info.cbSize = sizeof(info);
340 info.fMask = MIIM_STATE;
342 // Must unset the other menu items:
343 for (UINT menuToClear = IDM_UA_DEFAULT; menuToClear <= IDM_UA_OTHER; ++menuToClear) {
344 if (!::GetMenuItemInfo(menu, menuToClear, FALSE, &info))
346 if (!menuItemIsChecked(info))
349 info.fState = MFS_UNCHECKED;
350 ::SetMenuItemInfo(menu, menuToClear, FALSE, &info);
354 static bool ToggleMenuItem(HWND hWnd, UINT menuID)
359 HMENU menu = ::GetMenu(hWnd);
362 ::memset(&info, 0x00, sizeof(info));
363 info.cbSize = sizeof(info);
364 info.fMask = MIIM_STATE;
366 if (!::GetMenuItemInfo(menu, menuID, FALSE, &info))
369 BOOL newState = !menuItemIsChecked(info);
371 if (!gMiniBrowser->standardPreferences() || !gMiniBrowser->privatePreferences())
375 case IDM_AVFOUNDATION:
376 gMiniBrowser->standardPreferences()->setAVFoundationEnabled(newState);
378 case IDM_ACC_COMPOSITING:
379 gMiniBrowser->privatePreferences()->setAcceleratedCompositingEnabled(newState);
381 case IDM_WK_FULLSCREEN:
382 gMiniBrowser->privatePreferences()->setFullScreenEnabled(newState);
384 case IDM_COMPOSITING_BORDERS:
385 gMiniBrowser->privatePreferences()->setShowDebugBorders(newState);
386 gMiniBrowser->privatePreferences()->setShowRepaintCounter(newState);
388 case IDM_DEBUG_INFO_LAYER:
389 gMiniBrowser->privatePreferences()->setShowTiledScrollingIndicator(newState);
391 case IDM_INVERT_COLORS:
392 gMiniBrowser->privatePreferences()->setShouldInvertColors(newState);
394 case IDM_DISABLE_IMAGES:
395 gMiniBrowser->standardPreferences()->setLoadsImagesAutomatically(!newState);
397 case IDM_DISABLE_STYLES:
398 gMiniBrowser->privatePreferences()->setAuthorAndUserStylesEnabled(!newState);
400 case IDM_DISABLE_JAVASCRIPT:
401 gMiniBrowser->standardPreferences()->setJavaScriptEnabled(!newState);
403 case IDM_DISABLE_LOCAL_FILE_RESTRICTIONS:
404 gMiniBrowser->privatePreferences()->setAllowUniversalAccessFromFileURLs(newState);
405 gMiniBrowser->privatePreferences()->setAllowFileAccessFromFileURLs(newState);
408 case IDM_UA_SAFARI_8_0:
409 case IDM_UA_SAFARI_IOS_8_IPHONE:
410 case IDM_UA_SAFARI_IOS_8_IPAD:
412 case IDM_UA_CHROME_MAC:
413 case IDM_UA_CHROME_WIN:
414 case IDM_UA_FIREFOX_MAC:
415 case IDM_UA_FIREFOX_WIN:
416 gMiniBrowser->setUserAgent(menuID);
417 turnOffOtherUserAgents(menu);
420 // The actual user agent string will be set by the custom user agent dialog
421 turnOffOtherUserAgents(menu);
427 info.fState = (newState) ? MFS_CHECKED : MFS_UNCHECKED;
429 ::SetMenuItemInfo(menu, menuID, FALSE, &info);
434 static const int dragBarHeight = 30;
436 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
438 WNDPROC parentProc = (gMiniBrowser) ? (gMiniBrowser->usesLayeredWebView() ? DefWebKitProc : DefWindowProc) : DefWindowProc;
442 if (gMiniBrowser && gMiniBrowser->usesLayeredWebView()) {
444 ::GetWindowRect(hWnd, &window);
445 // For testing our transparent window, we need a region to use as a handle for
446 // dragging. The right way to do this would be to query the web view to see what's
447 // under the mouse. However, for testing purposes we just use an arbitrary
448 // 30 logical pixel band at the top of the view as an arbitrary gripping location.
450 // When we are within this bad, return HT_CAPTION to tell Windows we want to
451 // treat this region as if it were the title bar on a normal window.
452 int y = HIWORD(lParam);
453 float scaledDragBarHeightFactor = dragBarHeight * gMiniBrowser->deviceScaleFactor();
454 if ((y > window.top) && (y < window.top + scaledDragBarHeightFactor))
457 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
459 int wmId = LOWORD(wParam);
460 int wmEvent = HIWORD(wParam);
461 if (wmId >= IDM_HISTORY_LINK0 && wmId <= IDM_HISTORY_LINK9) {
463 gMiniBrowser->navigateToHistory(hWnd, wmId);
466 // Parse the menu selections:
469 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
475 PrintView(hWnd, message, wParam, lParam);
477 case IDM_WEB_INSPECTOR:
479 gMiniBrowser->launchInspector();
482 if (!::IsWindow(hCacheWnd)) {
483 hCacheWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_CACHES), hWnd, Caches);
484 ::ShowWindow(hCacheWnd, SW_SHOW);
487 case IDM_HISTORY_BACKWARD:
488 case IDM_HISTORY_FORWARD:
490 gMiniBrowser->navigateForwardOrBackward(hWnd, wmId);
494 ToggleMenuItem(hWnd, wmId);
496 DialogBox(hInst, MAKEINTRESOURCE(IDD_USER_AGENT), hWnd, CustomUserAgent);
498 case IDM_ACTUAL_SIZE:
500 gMiniBrowser->resetZoom();
504 gMiniBrowser->zoomIn();
508 gMiniBrowser->zoomOut();
510 case IDM_SHOW_LAYER_TREE:
512 gMiniBrowser->showLayerTree();
515 if (!ToggleMenuItem(hWnd, wmId))
516 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
522 CFRunLoopStop(CFRunLoopGetMain());
527 if (!gMiniBrowser || !gMiniBrowser->hasWebView() || gMiniBrowser->usesLayeredWebView())
528 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
534 gMiniBrowser->updateDeviceScaleFactor();
535 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
537 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
543 LRESULT CALLBACK EditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
547 if (wParam == 13) { // Enter Key
548 wchar_t strPtr[INTERNET_MAX_URL_LENGTH];
549 *((LPWORD)strPtr) = INTERNET_MAX_URL_LENGTH;
550 int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr);
553 _bstr_t bstr(strPtr);
554 loadURL(bstr.GetBSTR());
559 return CallWindowProc(DefEditProc, hDlg, message, wParam, lParam);
563 LRESULT CALLBACK BackButtonProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
567 gMiniBrowser->goBack();
569 return CallWindowProc(DefButtonProc, hDlg, message, wParam, lParam);
573 LRESULT CALLBACK ForwardButtonProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
577 gMiniBrowser->goForward();
579 return CallWindowProc(DefButtonProc, hDlg, message, wParam, lParam);
583 // Message handler for about box.
584 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
586 UNREFERENCED_PARAMETER(lParam);
589 return (INT_PTR)TRUE;
592 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
593 EndDialog(hDlg, LOWORD(wParam));
594 return (INT_PTR)TRUE;
598 return (INT_PTR)FALSE;
601 INT_PTR CALLBACK Caches(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
603 UNREFERENCED_PARAMETER(lParam);
606 ::SetTimer(hDlg, IDT_UPDATE_STATS, 1000, nullptr);
607 return (INT_PTR)TRUE;
610 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
611 ::KillTimer(hDlg, IDT_UPDATE_STATS);
612 ::DestroyWindow(hDlg);
614 return (INT_PTR)TRUE;
618 case IDT_UPDATE_STATS:
619 ::InvalidateRect(hDlg, nullptr, FALSE);
620 return (INT_PTR)TRUE;
623 updateStatistics(hDlg);
627 return (INT_PTR)FALSE;
630 INT_PTR CALLBACK CustomUserAgent(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
632 UNREFERENCED_PARAMETER(lParam);
634 case WM_INITDIALOG: {
635 HWND edit = ::GetDlgItem(hDlg, IDC_USER_AGENT_INPUT);
638 userAgent = gMiniBrowser->userAgent();
640 ::SetWindowText(edit, static_cast<LPCTSTR>(userAgent));
641 return (INT_PTR)TRUE;
645 if (LOWORD(wParam) == IDOK) {
646 HWND edit = ::GetDlgItem(hDlg, IDC_USER_AGENT_INPUT);
649 int strLen = ::GetWindowText(edit, buffer, 1024);
652 _bstr_t bstr(buffer);
654 gMiniBrowser->setUserAgent(bstr);
655 ::PostMessage(hMainWnd, static_cast<UINT>(WM_COMMAND), MAKELPARAM(IDM_UA_OTHER, 1), 0);
659 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
660 ::EndDialog(hDlg, LOWORD(wParam));
661 return (INT_PTR)TRUE;
665 return (INT_PTR)FALSE;
668 HRESULT DisplayAuthDialog(std::wstring& username, std::wstring& password)
670 auto result = DialogBox(hInst, MAKEINTRESOURCE(IDD_AUTH), hMainWnd, AuthDialogProc);
674 auto pair = reinterpret_cast<std::pair<std::wstring, std::wstring>*>(result);
675 username = pair->first;
676 password = pair->second;
682 INT_PTR CALLBACK AuthDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
685 case WM_INITDIALOG: {
686 HWND edit = ::GetDlgItem(hDlg, IDC_AUTH_USER);
687 ::SetWindowText(edit, static_cast<LPCTSTR>(L""));
689 edit = ::GetDlgItem(hDlg, IDC_AUTH_PASSWORD);
690 ::SetWindowText(edit, static_cast<LPCTSTR>(L""));
691 return (INT_PTR)TRUE;
695 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
698 if (LOWORD(wParam) == IDOK) {
700 int strLen = ::GetWindowText(::GetDlgItem(hDlg, IDC_AUTH_USER), user, 256);
704 strLen = ::GetWindowText(::GetDlgItem(hDlg, IDC_AUTH_PASSWORD), pass, 256);
707 result = reinterpret_cast<INT_PTR>(new std::pair<std::wstring, std::wstring>(user, pass));
710 ::EndDialog(hDlg, result);
711 return (INT_PTR)TRUE;
715 return (INT_PTR)FALSE;
718 static void loadURL(BSTR passedURL)
720 if (FAILED(gMiniBrowser->loadURL(passedURL)))
723 SetFocus(gViewWindow);
726 static void setWindowText(HWND dialog, UINT field, _bstr_t value)
728 ::SetDlgItemText(dialog, field, value);
731 static void setWindowText(HWND dialog, UINT field, UINT value)
733 String valueStr = WTF::String::number(value);
735 setWindowText(dialog, field, _bstr_t(valueStr.utf8().data()));
738 typedef _com_ptr_t<_com_IIID<IPropertyBag, &__uuidof(IPropertyBag)>> IPropertyBagPtr;
740 static void setWindowText(HWND dialog, UINT field, IPropertyBagPtr statistics, const _bstr_t& key)
744 if (FAILED(statistics->Read(key, &var.GetVARIANT(), nullptr)))
747 unsigned long long value = V_UI8(&var);
748 String valueStr = WTF::String::number(value);
750 setWindowText(dialog, field, _bstr_t(valueStr.utf8().data()));
753 static void setWindowText(HWND dialog, UINT field, CFDictionaryRef dictionary, CFStringRef key, UINT& total)
755 CFNumberRef countNum = static_cast<CFNumberRef>(CFDictionaryGetValue(dictionary, key));
760 CFNumberGetValue(countNum, kCFNumberIntType, &count);
762 setWindowText(dialog, field, static_cast<UINT>(count));
766 static void updateStatistics(HWND dialog)
771 IWebCoreStatisticsPtr webCoreStatistics = gMiniBrowser->statistics();
772 if (!webCoreStatistics)
775 IPropertyBagPtr statistics;
776 HRESULT hr = webCoreStatistics->memoryStatistics(&statistics.GetInterfacePtr());
781 setWindowText(dialog, IDC_RESERVED_VM, statistics, "FastMallocReservedVMBytes");
782 setWindowText(dialog, IDC_COMMITTED_VM, statistics, "FastMallocCommittedVMBytes");
783 setWindowText(dialog, IDC_FREE_LIST_BYTES, statistics, "FastMallocFreeListBytes");
787 IWebCachePtr webCache = gMiniBrowser->webCache();
790 IPropertyBag* cacheDict[6] = { 0 };
791 if (FAILED(webCache->statistics(&dictCount, cacheDict)))
794 COMPtr<CFDictionaryPropertyBag> counts, sizes, liveSizes, decodedSizes, purgableSizes;
795 counts.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[0]));
796 sizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[1]));
797 liveSizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[2]));
798 decodedSizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[3]));
799 purgableSizes.adoptRef(reinterpret_cast<CFDictionaryPropertyBag*>(cacheDict[4]));
801 static CFStringRef imagesKey = CFSTR("images");
802 static CFStringRef stylesheetsKey = CFSTR("style sheets");
803 static CFStringRef xslKey = CFSTR("xsl");
804 static CFStringRef scriptsKey = CFSTR("scripts");
807 UINT totalObjects = 0;
808 setWindowText(dialog, IDC_IMAGES_OBJECT_COUNT, counts->dictionary(), imagesKey, totalObjects);
809 setWindowText(dialog, IDC_CSS_OBJECT_COUNT, counts->dictionary(), stylesheetsKey, totalObjects);
810 setWindowText(dialog, IDC_XSL_OBJECT_COUNT, counts->dictionary(), xslKey, totalObjects);
811 setWindowText(dialog, IDC_JSC_OBJECT_COUNT, counts->dictionary(), scriptsKey, totalObjects);
812 setWindowText(dialog, IDC_TOTAL_OBJECT_COUNT, totalObjects);
817 setWindowText(dialog, IDC_IMAGES_BYTES, sizes->dictionary(), imagesKey, totalBytes);
818 setWindowText(dialog, IDC_CSS_BYTES, sizes->dictionary(), stylesheetsKey, totalBytes);
819 setWindowText(dialog, IDC_XSL_BYTES, sizes->dictionary(), xslKey, totalBytes);
820 setWindowText(dialog, IDC_JSC_BYTES, sizes->dictionary(), scriptsKey, totalBytes);
821 setWindowText(dialog, IDC_TOTAL_BYTES, totalBytes);
825 UINT totalLiveBytes = 0;
826 setWindowText(dialog, IDC_IMAGES_LIVE_COUNT, liveSizes->dictionary(), imagesKey, totalLiveBytes);
827 setWindowText(dialog, IDC_CSS_LIVE_COUNT, liveSizes->dictionary(), stylesheetsKey, totalLiveBytes);
828 setWindowText(dialog, IDC_XSL_LIVE_COUNT, liveSizes->dictionary(), xslKey, totalLiveBytes);
829 setWindowText(dialog, IDC_JSC_LIVE_COUNT, liveSizes->dictionary(), scriptsKey, totalLiveBytes);
830 setWindowText(dialog, IDC_TOTAL_LIVE_COUNT, totalLiveBytes);
834 UINT totalDecoded = 0;
835 setWindowText(dialog, IDC_IMAGES_DECODED_COUNT, decodedSizes->dictionary(), imagesKey, totalDecoded);
836 setWindowText(dialog, IDC_CSS_DECODED_COUNT, decodedSizes->dictionary(), stylesheetsKey, totalDecoded);
837 setWindowText(dialog, IDC_XSL_DECODED_COUNT, decodedSizes->dictionary(), xslKey, totalDecoded);
838 setWindowText(dialog, IDC_JSC_DECODED_COUNT, decodedSizes->dictionary(), scriptsKey, totalDecoded);
839 setWindowText(dialog, IDC_TOTAL_DECODED, totalDecoded);
843 UINT totalPurgable = 0;
844 setWindowText(dialog, IDC_IMAGES_PURGEABLE_COUNT, purgableSizes->dictionary(), imagesKey, totalPurgable);
845 setWindowText(dialog, IDC_CSS_PURGEABLE_COUNT, purgableSizes->dictionary(), stylesheetsKey, totalPurgable);
846 setWindowText(dialog, IDC_XSL_PURGEABLE_COUNT, purgableSizes->dictionary(), xslKey, totalPurgable);
847 setWindowText(dialog, IDC_JSC_PURGEABLE_COUNT, purgableSizes->dictionary(), scriptsKey, totalPurgable);
848 setWindowText(dialog, IDC_TOTAL_PURGEABLE, totalPurgable);
853 setWindowText(dialog, IDC_JSC_HEAP_SIZE, statistics, "JavaScriptHeapSize");
854 setWindowText(dialog, IDC_JSC_HEAP_FREE, statistics, "JavaScriptFreeSize");
857 if (SUCCEEDED(webCoreStatistics->javaScriptObjectsCount(&count)))
858 setWindowText(dialog, IDC_TOTAL_JSC_HEAP_OBJECTS, count);
859 if (SUCCEEDED(webCoreStatistics->javaScriptGlobalObjectsCount(&count)))
860 setWindowText(dialog, IDC_GLOBAL_JSC_HEAP_OBJECTS, count);
861 if (SUCCEEDED(webCoreStatistics->javaScriptProtectedObjectsCount(&count)))
862 setWindowText(dialog, IDC_PROTECTED_JSC_HEAP_OBJECTS, count);
864 // Font and Glyph Caches.
865 if (SUCCEEDED(webCoreStatistics->cachedFontDataCount(&count)))
866 setWindowText(dialog, IDC_TOTAL_FONT_OBJECTS, count);
867 if (SUCCEEDED(webCoreStatistics->cachedFontDataInactiveCount(&count)))
868 setWindowText(dialog, IDC_INACTIVE_FONT_OBJECTS, count);
869 if (SUCCEEDED(webCoreStatistics->glyphPageCount(&count)))
870 setWindowText(dialog, IDC_GLYPH_PAGES, count);
872 // Site Icon Database.
873 if (SUCCEEDED(webCoreStatistics->iconPageURLMappingCount(&count)))
874 setWindowText(dialog, IDC_PAGE_URL_MAPPINGS, count);
875 if (SUCCEEDED(webCoreStatistics->iconRetainedPageURLCount(&count)))
876 setWindowText(dialog, IDC_RETAINED_PAGE_URLS, count);
877 if (SUCCEEDED(webCoreStatistics->iconRecordCount(&count)))
878 setWindowText(dialog, IDC_SITE_ICON_RECORDS, count);
879 if (SUCCEEDED(webCoreStatistics->iconsWithDataCount(&count)))
880 setWindowText(dialog, IDC_SITE_ICONS_WITH_DATA, count);
883 static void parseCommandLine(bool& usesLayeredWebView, bool& useFullDesktop, bool& pageLoadTesting, _bstr_t& requestedURL)
885 usesLayeredWebView = false;
886 useFullDesktop = false;
887 pageLoadTesting = false;
890 WCHAR** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
891 for (int i = 1; i < argc; ++i) {
892 if (!wcsicmp(argv[i], L"--transparent"))
893 usesLayeredWebView = true;
894 else if (!wcsicmp(argv[i], L"--desktop"))
895 useFullDesktop = true;
896 else if (!wcsicmp(argv[i], L"--performance"))
897 pageLoadTesting = true;
898 else if (!wcsicmp(argv[i], L"--highDPI"))
900 else if (!requestedURL)
901 requestedURL = argv[i];
905 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpstrCmdLine, int nCmdShow)
907 return wWinMain(hInstance, hPrevInstance, lpstrCmdLine, nCmdShow);