diff options
Diffstat (limited to 'other-licenses/nsis/Contrib/WebBrowser/main.cpp')
-rw-r--r-- | other-licenses/nsis/Contrib/WebBrowser/main.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/other-licenses/nsis/Contrib/WebBrowser/main.cpp b/other-licenses/nsis/Contrib/WebBrowser/main.cpp new file mode 100644 index 0000000000..e0589531ee --- /dev/null +++ b/other-licenses/nsis/Contrib/WebBrowser/main.cpp @@ -0,0 +1,199 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0.If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <windows.h> +#include "resource.h" +#include "WebBrowser.h" +#include "exdll.h" + +// These variables are global because they're needed by more than one of +// our plugin methods. The expectation is that these are safe because the +// NSIS framework doesn't really support more than one dialog or thread +// at a time, and that means we don't have to either. + +// Instance handle for this DLL +HINSTANCE gHInst = nullptr; +// Parent window proc which we'll need to override and then restore +WNDPROC gWndProcOld = nullptr; +// Handle to the dialog we'll create +HWND gHwnd = nullptr; +// Set to true when our dialog should be destroyed +bool gDone = false; +// Web browser OLE site +WebBrowser* gBrowser = nullptr; + +// Set web browser control feature flags that are configured on a per-process +// basis, not for individual instances of the control. This mainly means +// disabling things that could turn into security holes. +static void ConfigurePerProcessBrowserFeatures() { + // For most of the features we're configuring, setting them to TRUE means + // we're disabling something, but for a few setting them to FALSE disables the + // thing. We don't necessarily care about *every* feature that's in the + // INTERNETFEATURELIST enum, but it seems safer to set them all anyway, to + // make sure we don't miss anything we *do* care about. + struct Feature { + INTERNETFEATURELIST id; + BOOL value; + } features[] = {{FEATURE_OBJECT_CACHING, TRUE}, + {FEATURE_ZONE_ELEVATION, TRUE}, + {FEATURE_MIME_HANDLING, TRUE}, + {FEATURE_MIME_SNIFFING, FALSE}, + {FEATURE_WINDOW_RESTRICTIONS, TRUE}, + {FEATURE_WEBOC_POPUPMANAGEMENT, TRUE}, + {FEATURE_BEHAVIORS, TRUE}, + {FEATURE_DISABLE_MK_PROTOCOL, TRUE}, + // It isn't possible to set FEATURE_LOCALMACHINE_LOCKDOWN + // using the SET_FEATURE_ON_PROCESS mode; see the MSDN page + // on CoInternetSetFeatureEnabled for the explanation. + //{FEATURE_LOCALMACHINE_LOCKDOWN, TRUE}, + {FEATURE_SECURITYBAND, FALSE}, + {FEATURE_RESTRICT_ACTIVEXINSTALL, TRUE}, + {FEATURE_VALIDATE_NAVIGATE_URL, TRUE}, + {FEATURE_RESTRICT_FILEDOWNLOAD, TRUE}, + {FEATURE_ADDON_MANAGEMENT, TRUE}, + {FEATURE_PROTOCOL_LOCKDOWN, TRUE}, + {FEATURE_HTTP_USERNAME_PASSWORD_DISABLE, TRUE}, + {FEATURE_SAFE_BINDTOOBJECT, TRUE}, + {FEATURE_UNC_SAVEDFILECHECK, TRUE}, + {FEATURE_GET_URL_DOM_FILEPATH_UNENCODED, FALSE}, + {FEATURE_TABBED_BROWSING, FALSE}, + {FEATURE_SSLUX, FALSE}, + {FEATURE_DISABLE_NAVIGATION_SOUNDS, TRUE}, + {FEATURE_DISABLE_LEGACY_COMPRESSION, TRUE}, + {FEATURE_FORCE_ADDR_AND_STATUS, FALSE}, + {FEATURE_XMLHTTP, FALSE}, + {FEATURE_DISABLE_TELNET_PROTOCOL, TRUE}, + {FEATURE_FEEDS, FALSE}, + {FEATURE_BLOCK_INPUT_PROMPTS, TRUE}}; + + for (Feature feature : features) { + CoInternetSetFeatureEnabled(feature.id, SET_FEATURE_ON_PROCESS, + feature.value); + } +} + +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID) { + if (reason == DLL_PROCESS_ATTACH) { + gHInst = instance; + (void)OleInitialize(nullptr); + ConfigurePerProcessBrowserFeatures(); + } + return TRUE; +} + +UINT_PTR __cdecl NSISPluginCallback(NSPIM msg) { + if (msg == NSPIM_UNLOAD) { + OleUninitialize(); + } + return 0; +} + +BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, + LPARAM lParam) { + BOOL bRes = + CallWindowProc((WNDPROC)gWndProcOld, hwnd, message, wParam, lParam); + if (!bRes && message == WM_NOTIFY_OUTER_NEXT) { + gDone = true; + PostMessage(gHwnd, WM_CLOSE, 0, 0); + } + return bRes; +} + +BOOL CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + return FALSE; +} + +void Init(HWND hWndParent, int string_size, TCHAR* variables, + stack_t** stacktop, extra_parameters* extra) { + EXDLL_INIT(); + extra->RegisterPluginCallback(gHInst, NSISPluginCallback); + + HWND hwndChild = GetDlgItem(hWndParent, 1018); + if (!hwndChild) { + return; + } + + HWND hwnd = + CreateDialog(gHInst, MAKEINTRESOURCE(IDD_DIALOG1), hWndParent, DlgProc); + if (!hwnd) { + gDone = true; + } else { + gDone = false; + gWndProcOld = + (WNDPROC)SetWindowLong(hWndParent, DWL_DLGPROC, (LONG)ParentWndProc); + + // Tell NSIS to replace its inner dialog with ours. + SendMessage(hWndParent, WM_NOTIFY_CUSTOM_READY, (WPARAM)hwnd, 0); + + // Initialize the browser control. + if (gBrowser) { + gBrowser->Shutdown(); + gBrowser->Release(); + } + gBrowser = new WebBrowser(hwnd); + + if (!gBrowser || !gBrowser->IsInitialized()) { + return; + } + + gHwnd = hwnd; + + // Move our dialog to match the size of the parent. + RECT r; + GetClientRect(hwndChild, &r); + MoveWindow(hwnd, r.left, r.top, r.right - r.left, r.bottom - r.top, FALSE); + gBrowser->SetRect(r); + } +} + +PLUGINFUNCTION(ShowPage) { + if (!gBrowser) { + Init(hWndParent, string_size, variables, stacktop, extra); + } + + if (!gBrowser->IsInitialized()) { + return; + } + + TCHAR* sUrl = + (TCHAR*)HeapAlloc(GetProcessHeap(), 0, g_stringsize * sizeof(TCHAR)); + popstring(sUrl); + + if (gBrowser) { + gBrowser->Navigate(sUrl); + + ShowWindow(gHwnd, SW_SHOWNA); + UpdateWindow(gHwnd); + + while (!gDone) { + // This explicit wait call is needed rather than just a blocking + // GetMessage because we need this thread to be alertable so that our + // timers can wake it up and run their callbacks. + MsgWaitForMultipleObjectsEx(0, nullptr, 100, QS_ALLINPUT, + MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); + MSG msg; + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + bool tab = msg.message == WM_KEYDOWN && msg.wParam == VK_TAB; + + if (gBrowser->ActiveObjectTranslateAccelerator(tab, &msg) != S_OK && + !IsDialogMessage(gHwnd, &msg) && + !IsDialogMessage(g_hwndParent, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + + SetWindowLong(g_hwndParent, DWL_DLGPROC, (LONG)gWndProcOld); + if (gHwnd) { + DestroyWindow(gHwnd); + } + + gBrowser->Shutdown(); + gBrowser->Release(); + gBrowser = nullptr; + } + + HeapFree(GetProcessHeap(), 0, (char*)sUrl); +} |