diff options
Diffstat (limited to 'Src/omBrowser/browserHost.cpp')
-rw-r--r-- | Src/omBrowser/browserHost.cpp | 1232 |
1 files changed, 1232 insertions, 0 deletions
diff --git a/Src/omBrowser/browserHost.cpp b/Src/omBrowser/browserHost.cpp new file mode 100644 index 00000000..368dd43f --- /dev/null +++ b/Src/omBrowser/browserHost.cpp @@ -0,0 +1,1232 @@ +#include "main.h" +#include "./browser.h" +#include "./browserHost.h" +//#include "./browserPopup.h" +#include "./graphics.h" + +//#include "../winamp/wa_dlg.h" +#include "../Plugins/General/gen_ml/colors.h" + +#include "./browserThread.h" + +#include "../winamp/IWasabiDispatchable.h" +#include "../winamp/JSAPI_Info.h" + +#include "./service.h" +//#include "./menu.h" + +#include "./obj_ombrowser.h" +#include "./ifc_skinhelper.h" +#include "./ifc_skinnedbrowser.h" +#include "./ifc_omservice.h" +#include "./ifc_travelloghelper.h" +#include "./ifc_wasabihelper.h" +#include <exdispid.h> +#include <strsafe.h> + +#define NWC_OMBROWSERHOST L"Nullsoft_omBrowserHost" + +typedef struct __BROWSERHOSTCREATEPARAM +{ + HWND hParent; + INT controlId; + UINT fStyle; + INT x; + INT y; + INT cx; + INT cy; + HINSTANCE hInstance; + HACCEL hAccel; + obj_ombrowser *browserManager; +} BROWSERHOSTCREATEPARAM; + +typedef struct __BROWSERHOST +{ + Browser *container; + HACCEL hAccel; + obj_ombrowser *browserManager; +} BROWSERHOST; + + +#define BHT_CONTAINERDOWNLOAD 27 +#define BHT_ACTIVATECONTAINER_DELAY 15 +#define BHT_DEACTIVATECONTAINER_DELAY 75 + +#define GetHost(__hwnd) ((BROWSERHOST*)(LONG_PTR)(LONGX86)GetWindowLongPtr((__hwnd), 0)) + +static LRESULT CALLBACK BrowserHost_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +static void CALLBACK BrowserHost_OnDocumentReady(Browser *browser, IDispatch *pDispatch, VARIANT *URL); +static void CALLBACK BrowserHost_OnNavigateComplete(Browser *browser, IDispatch *pDispatch, VARIANT *URL); +static void CALLBACK BrowserHost_OnContainerDestroy(Browser *browser); +static void CALLBACK BrowserHost_OnDownloadBegin(Browser *browser); +static void CALLBACK BrowserHost_OnDownloadComplete(Browser *browser); +static void CALLBACK BrowserHost_OnCommandStateChange(Browser *browser, INT commandId, BOOL fEnabled); +static void CALLBACK BrowserHost_OnStatusChange(Browser *browser, LPCWSTR pszText); +static void CALLBACK BrowserHost_OnTitleChange(Browser *browser, LPCWSTR pszText); +static void CALLBACK BrowserHost_OnSecureLockIconChange(Browser *browser); +static void CALLBACK BrowserHost_OnCreatePopup(Browser *browser, IDispatch **ppDisp, VARIANT_BOOL *Cancel); +static void CALLBACK BrowserHost_OnVisibleChange(Browser *browser, VARIANT_BOOL fVisible); +static void CALLBACK BrowserHost_OnSetResizable(Browser *browser, VARIANT_BOOL fAllow); +static void CALLBACK BrowserHost_OnSetFullScreen(Browser *browser, VARIANT_BOOL fAllow); +static void CALLBACK BrowserHost_OnWindowClosing(Browser *browser, VARIANT_BOOL fIsChild, VARIANT_BOOL *fCancel); +static void CALLBACK BrowserHost_OnShowUiElenent(Browser *browser, UINT elementId, VARIANT_BOOL fShow); +static void CALLBACK BrowserHost_OnClientToHost(Browser *browser, LONG *cx, LONG *cy); +static void CALLBACK BrowserHost_OnSetWindowPos(Browser *browser, UINT Flags, LONG x, LONG y, LONG cx, LONG cy); +static void CALLBACK BrowserHost_OnFocusChange(Browser *browser, VARIANT_BOOL *fAllow); +static void CALLBACK BrowserHost_OnClosePopup(Browser *browser); + +static HRESULT CALLBACK BrowserHost_GetOmService(Browser *browser, ifc_omservice **ppService); +static LRESULT CALLBACK BrowserHost_RedirectKey(Browser *browser, MSG *pMsg); + +static BOOL BrowserHost_RegisterClass(HINSTANCE hInstance) +{ + WNDCLASS wc = {0}; + if (GetClassInfo(hInstance, NWC_OMBROWSERHOST, &wc)) return TRUE; + + ZeroMemory(&wc, sizeof(WNDCLASS)); + wc.hInstance = hInstance; + wc.lpszClassName = NWC_OMBROWSERHOST; + wc.lpfnWndProc = BrowserHost_WindowProc; + wc.style = CS_DBLCLKS; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.cbWndExtra = sizeof(BROWSERHOST*); + + return ( 0 != RegisterClassW(&wc)); +} + +static HWND CALLBACK BrowserHost_CreateHostWindow(ULONG_PTR user) +{ + BROWSERHOSTCREATEPARAM *param = (BROWSERHOSTCREATEPARAM*)user; + if (NULL == param) return NULL; + + return CreateWindowEx(WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT, + NWC_OMBROWSERHOST, NULL, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | (0x00000FFF & param->fStyle), + param->x, param->y, param->cx, param->cy, + param->hParent, (HMENU)(INT_PTR)param->controlId, + param->hInstance, param); +} + +static BOOL CALLBACK BrowserHost_KeyFilter(HWND hwnd, MSG *pMsg) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host) return FALSE; + + UINT vKey = (UINT)pMsg->wParam; + switch(vKey) + { + case VK_CONTROL: + case VK_MENU: + case VK_SHIFT: + return TRUE; + } + + if (NULL != host->hAccel && (hwnd == pMsg->hwnd || IsChild(hwnd, pMsg->hwnd))) + { + HWND hParent = GetParent(hwnd); + if (NULL != hParent && 0 != TranslateAccelerator(hParent, host->hAccel, pMsg)) + return TRUE; + } + + return (NULL != host->container && + FALSE != host->container->TranslateKey(pMsg)); +} + +HWND BrowserHost_CreateWindow(obj_ombrowser *browserManager, HWND hParent, UINT fStyle, INT x, INT y, INT cx, INT cy, INT controlId, HACCEL hAccel) +{ + if (FALSE == BrowserHost_RegisterClass(Plugin_GetInstance())) + return NULL; + + BROWSERHOSTCREATEPARAM param = {0}; + + param.hParent = hParent; + param.controlId = controlId; + param.hInstance = Plugin_GetInstance(); + param.x = x; + param.y = y; + param.cx = cx; + param.cy = cy; + param.fStyle = fStyle; + param.hAccel = hAccel; + param.browserManager = browserManager; + + HWND hWinamp = NULL; + if (FAILED(Plugin_GetWinampWnd(&hWinamp))) + hWinamp = NULL; + + HWND hHost = NULL; + HANDLE hThread = BrowserThread_Create(hWinamp, BrowserHost_CreateHostWindow, (ULONG_PTR)¶m, BrowserHost_KeyFilter, &hHost, NULL); + if (NULL != hThread) + CloseHandle(hThread); + + return hHost; +} + +static LRESULT BrowserHost_SendBrowserNotification(Browser *browser, INT code, NMHDR *pnmh) +{ + HWND hHost = (NULL != browser) ? browser->GetParentHWND() : NULL; + if (NULL == hHost || NULL == pnmh) + return 0; + + HWND hParent = GetParent(hHost); + if (NULL == hParent) + return 0; + + pnmh->code = code; + pnmh->hwndFrom = hHost; + pnmh->idFrom = GetDlgCtrlID(hHost); + + return SendMessage(hParent, WM_NOTIFY, (WPARAM)pnmh->idFrom, (LPARAM)pnmh); +} + +static LRESULT BrowserHost_SendNotification(HWND hwnd, NMHDR *phdr) +{ + HWND hParent = GetParent(hwnd); + if (NULL == hParent || NULL == phdr || !IsWindow(hParent)) + return 0; + + return SendMessage(hParent, WM_NOTIFY, (WPARAM)phdr->idFrom, (LPARAM)phdr); +} + +static void BrowserHost_UpdateLayout(HWND hwnd, BOOL fRedraw) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host) return; + + RECT clientRect; + if (!GetClientRect(hwnd, &clientRect)) + return; + + if (NULL != host->container) + { + host->container->SetLocation(clientRect.left, clientRect.top, + clientRect.right - clientRect.left, + clientRect.bottom - clientRect.top); + } +} + +static COLORREF BrwoserHost_GetBackColor(HWND hwnd) +{ + COLORREF rgb; + + ifc_skinnedbrowser *skinnedBrowser = NULL; + if (SUCCEEDED(Plugin_GetBrowserSkin(&skinnedBrowser)) && skinnedBrowser != NULL) + { + rgb = skinnedBrowser->GetBackColor(); + skinnedBrowser->Release(); + } + else + rgb = GetSysColor(COLOR_WINDOW); + + return rgb; +} + +static void BrowserHost_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase) +{ + SetBkColor(hdc, BrwoserHost_GetBackColor(hwnd)); + ExtTextOut(hdc, 0, 0, ETO_OPAQUE, prcPaint, NULL, 0, NULL); +} + +static LRESULT BrowserHost_OnCreate(HWND hwnd, CREATESTRUCT *pcs) +{ + BROWSERHOST *host= (BROWSERHOST*)calloc(1, sizeof(BROWSERHOST)); + if (NULL != host) + { + SetLastError(ERROR_SUCCESS); + if (!SetWindowLongPtr(hwnd, 0, (LONGX86)(LONG_PTR)host) && ERROR_SUCCESS != GetLastError()) + { + free(host); + host = NULL; + } + } + + if (NULL == host) + { + DestroyWindow(hwnd); + return -1; + } + + BROWSERHOSTCREATEPARAM *param = (BROWSERHOSTCREATEPARAM*)pcs->lpCreateParams; + host->hAccel = param->hAccel; + host->browserManager = param->browserManager; + if (NULL != host->browserManager) + host->browserManager->AddRef(); + + return 0; +} + +static void BrowserHost_OnDestroy(HWND hwnd) +{ + BROWSERHOST *host = GetHost(hwnd); + /*if (NULL != host->container) + { + // SendMessage(hwnd, BTM_RELEASECONTAINER, 0, 0L); + // BrowserThread_SetFlags(BHTF_BEGINDESTROY, BHTF_BEGINDESTROY, FALSE); + }*/ + + SetWindowLongPtr(hwnd, 0, 0L); + + if (NULL != host) + { + if (NULL != host->browserManager) + { + host->browserManager->Release(); + } + free(host); + } + +#ifdef _DEBUG + aTRACE_FMT("[%d] %S: host window destroyed\r\n", GetCurrentThreadId(), OMBROWSER_NAME); +#endif // _DEBUG +} + +static void BrowserHost_OnPaint(HWND hwnd) +{ + PAINTSTRUCT ps = {0}; + if (BeginPaint(hwnd, &ps)) + { + if (ps.rcPaint.left != ps.rcPaint.right) + BrowserHost_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase); + EndPaint(hwnd, &ps); + } +} + +static void BrowserHost_OnPrintClient(HWND hwnd, HDC hdc, UINT options) +{ + RECT clientRect; + if (GetClientRect(hwnd, &clientRect)) + BrowserHost_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options)); +} + +static void BrowserHost_OnWindowPosChanged(HWND hwnd, WINDOWPOS *pwp) +{ + if (SWP_NOSIZE == ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags)) + return; + BrowserHost_UpdateLayout(hwnd, 0 == (SWP_NOREDRAW & pwp->flags)); +} + +static void BrowserHost_OnCommand(HWND hwnd, INT controlId, INT eventId, HWND hControl) +{ +} + +static HRESULT BrowserHost_AssociateDispatch(HWND hwnd, IDispatch *pDispatch) +{ + if (NULL == pDispatch) + return E_INVALIDARG; + + IWasabiDispatchable *pWasabi = NULL; + HRESULT hr = pDispatch->QueryInterface(IID_IWasabiDispatchable, (void**)&pWasabi); + if (SUCCEEDED(hr) && pWasabi != NULL) + { + JSAPI::ifc_info *pInfo = NULL; + hr = pWasabi->QueryDispatchable(JSAPI::IID_JSAPI_ifc_info, (Dispatchable**)&pInfo); + if (SUCCEEDED(hr) && pInfo != NULL) + { + HWND hParent = GetParent(hwnd); + if (NULL == hParent) hParent = hwnd; + + pInfo->SetHWND(hParent); + + WCHAR szBuffer[512] = {0}; + BROWSERHOST *host = GetHost(hwnd); + if (NULL != host && NULL != host->container) + { + ifc_omservice *service = NULL; + if (SUCCEEDED(BrowserHost_GetOmService(host->container, &service)) && service != NULL) + { + if (FAILED(service->GetName(szBuffer, ARRAYSIZE(szBuffer)))) + szBuffer[0]= L'\0'; + service->Release(); + } + } + + pInfo->SetName(szBuffer); + pInfo->Release(); + } + pWasabi->Release(); + } + return hr; +} + +static void BrowserHost_OnContainerInit(HWND winampWindow, HWND hwnd) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host) return; + + if (NULL != host->container) return; // we're alredy running + + DWORD windowStyle = GetWindowStyle(hwnd); + + HTMLContainer2_Initialize(); + + Browser *container = Browser::CreateInstance(host->browserManager, winampWindow, hwnd); + host->container = container; + if (NULL != container) + { + ifc_omservice *service = NULL; + if (SUCCEEDED(BrowserHost_GetOmService(container, &service)) && service != NULL) + { + IDispatch *pDispatch = NULL; + if (SUCCEEDED(service->GetExternal(&pDispatch)) && NULL != pDispatch) + { + BrowserHost_AssociateDispatch(hwnd, pDispatch); + container->SetExternal(pDispatch); + pDispatch->Release(); + } + service->Release(); + } + + container->EventDocumentReady = BrowserHost_OnDocumentReady; + container->EventNavigateComplete = BrowserHost_OnNavigateComplete; + container->EventContainerDestroyed = BrowserHost_OnContainerDestroy; + container->EventDownloadBegin = BrowserHost_OnDownloadBegin; + container->EventDownloadComplete = BrowserHost_OnDownloadComplete; + container->EventCommandStateChange = BrowserHost_OnCommandStateChange; + container->EventStatusChange = BrowserHost_OnStatusChange; + container->EventTitleChange = BrowserHost_OnTitleChange; + container->EventSecureLockIconChange = BrowserHost_OnSecureLockIconChange; + container->EventCreatePopup = BrowserHost_OnCreatePopup; + container->EventFocusChange = BrowserHost_OnFocusChange; + container->EventWindowClosing = BrowserHost_OnWindowClosing; + + if (0 != (NBHS_POPUP & windowStyle)) + { + container->EventVisible = BrowserHost_OnVisibleChange; + container->EventSetResizable = BrowserHost_OnSetResizable; + container->EventSetFullscreen = BrowserHost_OnSetFullScreen; + container->EventShowUiElement = BrowserHost_OnShowUiElenent; + container->EventClientToHost = BrowserHost_OnClientToHost; + container->EventSetWindowPos = BrowserHost_OnSetWindowPos; + container->EventClosePopup = BrowserHost_OnClosePopup; + } + + container->CallbackGetOmService = BrowserHost_GetOmService; + container->CallbackRedirectKey = BrowserHost_RedirectKey; + + UINT uiFlags = 0; + if (0 != (NBHS_DISABLECONTEXTMENU & windowStyle)) uiFlags |= Browser::flagUiDisableContextMenu; + if (0 != (NBHS_DIALOGMODE & windowStyle)) uiFlags |= Browser::flagUiDialogMode; + if (0 != (NBHS_DISABLEHOSTCSS & windowStyle)) uiFlags |= Browser::flagUiDisableHostCss; + + if (0 != uiFlags) + container->SetUiFlags(uiFlags, uiFlags); + + HRESULT hr = container->Initialize(0 != (NBHS_POPUP & windowStyle)); + if (SUCCEEDED(hr) && 0 == (NBHS_SCRIPTMODE & windowStyle)) + { + // we need to do this to allow script error disabling + hr = container->NavigateToName(NULL, 0); + } + + if (FAILED(hr) || 0 != (NBHS_SCRIPTMODE & windowStyle)) + { + if (0 == (NBHS_BROWSERREADY & windowStyle)) + { + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | NBHS_BROWSERREADY); + + NMHDR hdr; + BrowserHost_SendBrowserNotification(container, NBHN_READY, &hdr); + } + } + } + + HWND hParent = GetParent(hwnd); + if (NULL != hParent) + { + DWORD threadMine = 0, threadParent = 0; + threadMine = GetCurrentThreadId(); + threadParent = GetWindowThreadProcessId(hParent, NULL); + if (0 != threadMine && threadMine != threadParent) + { + AttachThreadInput(threadMine, threadParent, TRUE); + + HKL hkl = GetKeyboardLayout(threadParent); + if (NULL != hkl) + ActivateKeyboardLayout(hkl, 0); + } + } +} + +static void BrowserHost_OnContainerRelease(HWND hwnd) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host) return; + + Browser *container = host->container; + host->container = NULL; + if (NULL == container) return; + + container->EventDocumentReady = NULL; + container->EventNavigateComplete = NULL; + container->EventDownloadBegin = NULL; + container->EventDownloadComplete = NULL; + container->EventCommandStateChange = NULL; + container->EventStatusChange = NULL; + container->EventTitleChange = NULL; + container->EventSecureLockIconChange = NULL; + container->EventCreatePopup = NULL; + container->EventVisible = NULL; + container->EventSetResizable = NULL; + container->EventSetFullscreen = NULL; + container->EventWindowClosing = NULL; + container->EventShowUiElement = NULL; + container->EventClientToHost = NULL; + container->EventSetWindowPos = NULL; + container->EventFocusChange = NULL; + container->CallbackGetOmService = NULL; + container->CallbackRedirectKey = NULL; + + if (SUCCEEDED(container->SendCommand(Browser::commandStop)) && + SUCCEEDED(container->NavigateToName(NULL, navNoHistory | navNoWriteToCache))) + { + IWebBrowser2 *pWeb2 = NULL; + if (SUCCEEDED(container->GetIWebBrowser2(&pWeb2)) && pWeb2 != NULL) + { + ReplyMessage(0); + BrowserThread_WaitNavigateComplete(pWeb2, 30000); + pWeb2->Release(); + } + } + else + { + } + + container->Finish(); + container->Release(); + + HWND hParent = GetParent(hwnd); + if (NULL != hParent) + { + DWORD threadMine = 0, threadParent = 0; + threadMine = GetCurrentThreadId(); + threadParent = GetWindowThreadProcessId(hParent, NULL); + if (0 != threadMine && threadMine != threadParent) + { + AttachThreadInput(threadMine, threadParent, FALSE); + } + } +} + +static LRESULT BrowserHost_OnNiceDestroy(HWND hwnd, BOOL fImmediate) +{ + DWORD windowStyle = GetWindowStyle(hwnd); + if (0 != (WS_VISIBLE & windowStyle)) + SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE); + + BROWSERHOST *host = GetHost(hwnd); + if (NULL != host && NULL != host->container && FALSE == fImmediate) + { + HWND hWinamp = NULL; + if (FAILED(Plugin_GetWinampWnd(&hWinamp))) + hWinamp = NULL; + + if (hWinamp != GetParent(hwnd)) + { + SetParent(hwnd, hWinamp); + SetWindowLongPtr(hwnd, GWLP_HWNDPARENT, (LONGX86)(LONG_PTR)hWinamp); + } + + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST); + + if (FALSE != BrowserThread_PostDestroy(hwnd)) + return TRUE; + } + + BrowserThread_SetFlags(BHTF_BEGINDESTROY, BHTF_BEGINDESTROY, FALSE); + BrowserHost_OnContainerRelease(hwnd); + return (0 != DestroyWindow(hwnd)); +} + +static void BrowserHost_OnContainerCommand(HWND hwnd, INT commandId) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host) return; + + if (NULL == host->container) return; + host->container->SendCommand(commandId); +} + +static void BrowserHost_OnUpdateSkin(HWND hwnd) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host) return; + + if (NULL != host->container) + { + //HWND hWinamp; + //if (NULL == host->browserManager || FAILED(host->browserManager->GetWinampWindow(&hWinamp))) + // hWinamp = NULL; + + //HCURSOR cursor = (HCURSOR)SENDWAIPC(hWinamp, IPC_GETSKINCURSORS, WACURSOR_NORMAL); + //if (NULL != cursor) + //{ + // host->container->RegisterBrowserCursor(/*OCR_NORMAL*/32512, CopyCursor(cursor)); + //} + } + + UINT windowStyle = GetWindowStyle(hwnd); + if (NBHS_BROWSERREADY == ((NBHS_BROWSERREADY | NBHS_BROWSERACTIVE) & windowStyle)) + { + PostMessage(hwnd, NBHM_CONTAINERCOMMAND, (WPARAM)Browser::commandRefresh, 0L); + } +} + +static void BrowserHost_OnNavigate(HWND hwnd, BSTR url, UINT flags) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL != host && + NULL != host->container && + FALSE == BrowserThread_IsQuiting()) + { + host->container->NavigateToName(url, flags); + } + if (NULL != url) + { + SysFreeString(url); + } +} + +static void BrowserHost_OnEnableContainerUpdate(HWND hwnd, BOOL fEnable, BOOL fRedraw) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host || NULL == host->container) return; + + HWND hContainer = host->container->GetHostHWND(); + if (NULL == hContainer) return; + + SendMessage(hContainer, WM_SETREDRAW, fEnable, 0L); + if (fEnable && fRedraw) + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW | RDW_NOERASE | RDW_NOFRAME | RDW_NOINTERNALPAINT | RDW_VALIDATE | RDW_ERASENOW ); +} + +static void BrowserHost_OnQueueAPC(HWND hwnd, PAPCFUNC pfnApc, ULONG_PTR param) +{ + if (NULL == pfnApc) return; + pfnApc(param); +} + +static void BrowserHost_OnShowHistoryPopup(HWND hwnd, UINT fuFlags, POINTS pts) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL != host && NULL != host->container) + { + ifc_travelloghelper *travelLog; + if (SUCCEEDED(host->container->GetTravelLog(&travelLog))) + { + travelLog->ShowPopup(fuFlags, pts.x, pts.y, hwnd, NULL); + travelLog->Release(); + } + } +} + +static void BrowserHost_OnGetDispatchApc(HWND hwnd, DISPATCHAPC callback, ULONG_PTR param) +{ + if (NULL == callback) return; + + IDispatch *pDisp = NULL; + BROWSERHOST *host = GetHost(hwnd); + if (NULL != host && NULL != host->container) + { + IWebBrowser2 *pWeb2 = NULL; + if (SUCCEEDED(host->container->GetIWebBrowser2(&pWeb2)) && pWeb2 != NULL) + { + pWeb2->get_Application(&pDisp); + pWeb2->Release(); + } + } + + callback(pDisp, param); + + if (NULL != pDisp) + pDisp->Release(); +} + +static void BrowserHost_OnActivate(HWND hwnd) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL != host && NULL != host->container) + { + host->container->SetFocus(TRUE); + } +} + +static void BrowserHost_OnQueryTitle(HWND hwnd) +{ + BSTR bstrName = NULL; + BROWSERHOST *host = GetHost(hwnd); + if (NULL != host && NULL != host->container) + { + IWebBrowser2 *pWeb2 = NULL; + if (SUCCEEDED(host->container->GetIWebBrowser2(&pWeb2)) && pWeb2 != NULL) + { + if (FAILED(pWeb2->get_LocationName(&bstrName))) + bstrName = NULL; + pWeb2->Release(); + } + } + + BHNTEXTCHANGE textChange = {0}; + textChange.hdr.code = NBHN_TITLECHANGE; + textChange.hdr.hwndFrom = hwnd; + textChange.hdr.idFrom = GetDlgCtrlID(hwnd); + textChange.pszText = bstrName; + + BrowserHost_SendNotification(hwnd, (NMHDR*)&textChange); + + SysFreeString(bstrName); +} + +static void BrowserHost_OnToggleFullscreen(HWND hwnd) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host || NULL == host->container) + return; + + host->container->ToggleFullscreen(); +} + +static void BrowserHost_OnWriteDocument(HWND hwnd, BSTR documentData) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host || + NULL == host->container || + FAILED(host->container->WriteDocument(documentData))) + { + SysFreeString(documentData); + } +} + +static void BrowserHost_OnEnableWindow(HWND hwnd, BOOL fEnable) +{ + EnableWindow(hwnd, fEnable); +} + +static void BrowserHost_OnUpdateExternal(HWND hwnd) +{ + BROWSERHOST *host = GetHost(hwnd); + if (NULL == host) return; + + if (NULL != host->container) + { + ifc_omservice *service = NULL; + if (SUCCEEDED(BrowserHost_GetOmService(host->container, &service)) && service != NULL) + { + IDispatch *pDispatch = NULL; + if (SUCCEEDED(service->GetExternal(&pDispatch)) && NULL != pDispatch) + { + BrowserHost_AssociateDispatch(hwnd, pDispatch); + host->container->SetExternal(pDispatch); + pDispatch->Release(); + } + service->Release(); + } + } +} + +static LRESULT CALLBACK BrowserHost_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_CREATE: + return BrowserHost_OnCreate(hwnd, (CREATESTRUCT*)lParam); + case WM_DESTROY: + BrowserHost_OnDestroy(hwnd); + break; + case WM_ERASEBKGND: + return 0; + case WM_PAINT: + BrowserHost_OnPaint(hwnd); + return 0; + case WM_PRINTCLIENT: + BrowserHost_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); + return 0; + case WM_WINDOWPOSCHANGED: + BrowserHost_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); + return 0; + case WM_COMMAND: + BrowserHost_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); + break; + case BTM_INITCONTAINER: + BrowserHost_OnContainerInit((HWND)wParam, hwnd); + return 0; + case BTM_RELEASECONTAINER: + BrowserHost_OnContainerRelease(hwnd); + return 0; + case NBHM_DESTROY: + return BrowserHost_OnNiceDestroy(hwnd, (BOOL)wParam); + case NBHM_CONTAINERCOMMAND: + BrowserHost_OnContainerCommand(hwnd, (INT)wParam); + return 0; + case NBHM_UPDATESKIN: + BrowserHost_OnUpdateSkin(hwnd); + return 0; + case NBHM_NAVIGATE: + BrowserHost_OnNavigate(hwnd, (BSTR)lParam, (UINT)wParam); + return 0; + case NBHM_ENABLECONTAINERUPDATE: + BrowserHost_OnEnableContainerUpdate(hwnd, (BOOL)wParam, (BOOL)lParam); + return 0; + case NBHM_QUEUEAPC: + BrowserHost_OnQueueAPC(hwnd, (PAPCFUNC)lParam, (ULONG_PTR)wParam); + return 0; + case NBHM_SHOWHISTORYPOPUP: + BrowserHost_OnShowHistoryPopup(hwnd, (UINT)wParam, MAKEPOINTS(lParam)); + return 0; + case NBHM_GETDISPATCHAPC: + BrowserHost_OnGetDispatchApc(hwnd, (DISPATCHAPC)lParam, (ULONG_PTR)wParam); + return 0; + case NBHM_ACTIVATE: + BrowserHost_OnActivate(hwnd); + return 0; + case NBHM_QUERYTITLE: + BrowserHost_OnQueryTitle(hwnd); + return 0; + case NBHM_TOGGLEFULLSCREEN: + BrowserHost_OnToggleFullscreen(hwnd); + return 0; + case NBHM_WRITEDOCUMENT: + BrowserHost_OnWriteDocument(hwnd, (BSTR)lParam); + return 0; + case NBHM_ENABLEWINDOW: + BrowserHost_OnEnableWindow(hwnd, (BOOL)lParam); + return 0; + case NBHM_UPDATEEXTERNAL: + BrowserHost_OnUpdateExternal(hwnd); + return 0; + } + + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +static DWORD BrowserHost_GetBrowserFlags(Browser *browser) +{ + if (NULL == browser) return 0; + HWND hHost = browser->GetParentHWND(); + if (NULL == hHost) return 0; + + DWORD windowStyle = GetWindowStyle(hHost); + return (NBHS_BROWSERMASK & windowStyle); +} + +static void CALLBACK BrowserHost_OnDocumentReady(Browser *browser, IDispatch *pDispatch, VARIANT *URL) +{ + HWND hHost = browser->GetParentHWND(); + if (NULL == hHost) return; + + DWORD windowStyle = GetWindowStyle(hHost); + if (0 == (NBHS_BROWSERREADY & windowStyle)) + { + SetWindowLongPtr(hHost, GWL_STYLE, windowStyle | NBHS_BROWSERREADY); + + NMHDR hdr = {0}; + BrowserHost_SendBrowserNotification(browser, NBHN_READY, &hdr); + } + else + { + BHNNAVCOMPLETE document = {0}; + document.pDispatch = pDispatch; + document.URL = URL; + document.fTopFrame = TRUE; + BrowserHost_SendBrowserNotification(browser, NBHN_DOCUMENTREADY, (NMHDR*)&document); + } +} + +static void CALLBACK BrowserHost_OnNavigateComplete(Browser *browser, IDispatch *pDispatch, VARIANT *URL) +{ + HWND hHost = browser->GetParentHWND(); + if (NULL == hHost) return; + + DWORD windowStyle = GetWindowStyle(hHost); + if (0 == (NBHS_BROWSERREADY & windowStyle)) + return; + + IWebBrowser2 *pWeb1 = NULL, *pWeb2 = NULL; + + if (FAILED(browser->GetIWebBrowser2(&pWeb1))) + pWeb1 = NULL; + + if (NULL == pDispatch || FAILED(pDispatch->QueryInterface(IID_IWebBrowser2, (void**)&pWeb2))) + pWeb2 = NULL; + + if (NULL != pWeb1) pWeb1->Release(); + if (NULL != pWeb2) pWeb2->Release(); + + BHNNAVCOMPLETE document = {0}; + document.pDispatch = pDispatch; + document.URL = URL; + document.fTopFrame = (NULL != pWeb1 && pWeb1 == pWeb2); + BrowserHost_SendBrowserNotification(browser, NBHN_NAVIGATECOMPLETE, (NMHDR*)&document); +} + +static void CALLBACK BrowserHost_OnContainerDestroy(Browser *browser) +{ + BrowserThread_SetFlags(BHTF_BEGINDESTROY, BHTF_BEGINDESTROY, FALSE); + PostMessage(NULL, WM_QUIT, 0, 0L); +} + +static void BrowserHost_NotifyContainerActive(HWND hwnd, BOOL fActive, UINT_PTR timerId) +{ + if (0 != timerId) + KillTimer(hwnd, timerId); + + DWORD windowStyle = GetWindowStyle(hwnd); + if ((FALSE == fActive) != (0 == (NBHS_BROWSERACTIVE & windowStyle))) + return; + + if (0 == (NBHS_BROWSERREADY & windowStyle)) + fActive = FALSE; + + BHNACTIVE active = {0}; + active.hdr.code = NBHN_BROWSERACTIVE; + active.hdr.hwndFrom = hwnd; + active.hdr.idFrom = GetDlgCtrlID(hwnd); + active.fActive = fActive; + BrowserHost_SendNotification(hwnd, (NMHDR*)&active); + + BROWSERHOST *host = GetHost(hwnd); + INT commandState = 0; + if (NULL != host && + NULL != host->container && + SUCCEEDED(host->container->QueryCommandState(Browser::commandStop, &commandState))) + { + BOOL fEnable = (0 != (Browser::commandStateEnabled & commandState)); + BrowserHost_OnCommandStateChange(host->container, Browser::commandStop, fEnable); + } +} + +static void CALLBACK BrowserHost_ActivateContainerTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD time) +{ + BrowserHost_NotifyContainerActive(hwnd, TRUE, eventId); +} + +static void CALLBACK BrowserHost_DeactivateContainerTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD time) +{ + BrowserHost_NotifyContainerActive(hwnd, FALSE, eventId); +} + +static void CALLBACK BrowserHost_OnDownloadBegin(Browser *browser) +{ + HWND hHost = browser->GetParentHWND(); + if (NULL == hHost) return; + + DWORD windowStyle = GetWindowStyle(hHost); + if (NBHS_BROWSERREADY == ((NBHS_BROWSERACTIVE | NBHS_BROWSERREADY) & windowStyle)) + { + SetWindowLongPtr(hHost, GWL_STYLE, windowStyle | NBHS_BROWSERACTIVE); + SetTimer(hHost, BHT_CONTAINERDOWNLOAD, BHT_ACTIVATECONTAINER_DELAY, BrowserHost_ActivateContainerTimer); + } +} + +static void CALLBACK BrowserHost_OnDownloadComplete(Browser *browser) +{ + HWND hHost = browser->GetParentHWND(); + if (NULL == hHost) return; + + DWORD windowStyle = GetWindowStyle(hHost); + if (0 != (NBHS_BROWSERACTIVE & windowStyle)) + { + SetWindowLongPtr(hHost, GWL_STYLE, windowStyle & ~NBHS_BROWSERACTIVE); + SetTimer(hHost, BHT_CONTAINERDOWNLOAD, BHT_DEACTIVATECONTAINER_DELAY, BrowserHost_DeactivateContainerTimer); + } +} + +static void CALLBACK BrowserHost_OnCommandStateChange(Browser *browser, INT commandId, BOOL fEnabled) +{ + if (Browser::commandStop == commandId && FALSE != fEnabled && + NBHS_BROWSERREADY == ((NBHS_BROWSERACTIVE | NBHS_BROWSERREADY) & BrowserHost_GetBrowserFlags(browser))) + { + fEnabled = FALSE; + } + + BHNCMDSTATE commandState = {0}; + commandState.commandId = commandId; + commandState.fEnabled = fEnabled; + BrowserHost_SendBrowserNotification(browser, NBHN_COMMANDSTATECHANGE, (NMHDR*)&commandState); +} + +static void CALLBACK BrowserHost_OnStatusChange(Browser *browser, LPCWSTR pszText) +{ + if (0 == (NBHS_BROWSERREADY & BrowserHost_GetBrowserFlags(browser))) + return; + + BHNTEXTCHANGE textChange = {0}; + textChange.pszText = pszText; + BrowserHost_SendBrowserNotification(browser, NBHN_STATUSCHANGE, (NMHDR*)&textChange); +} + +static void CALLBACK BrowserHost_OnTitleChange(Browser *browser, LPCWSTR pszText) +{ + if (0 == (NBHS_BROWSERREADY & BrowserHost_GetBrowserFlags(browser))) + return; + + BHNTEXTCHANGE textChange = {0}; + textChange.pszText = pszText; + BrowserHost_SendBrowserNotification(browser, NBHN_TITLECHANGE, (NMHDR*)&textChange); +} + +static void CALLBACK BrowserHost_OnSecureLockIconChange(Browser *browser) +{ + BHNSECUREICON icon = {0}; + icon.iconId = browser->GetSecueLockIcon(); + BrowserHost_SendBrowserNotification(browser, NBHN_SECUREICONCHANGE, (NMHDR*)&icon); +} + +typedef struct __POPUPCALLBACKPARAM +{ + IDispatch **ppDisp; + HANDLE readyEvent; + HWND hHost; +} POPUPCALLBACKPARAM; + +typedef struct __DISPATCHMARSHALPARAM +{ + LPSTREAM pStream; + IDispatch *pDisp; + HRESULT hr; +} DISPATCHMARSHALPARAM; + +static void CALLBACK BrowserHost_DispatchMarshalApc(ULONG_PTR user) +{ + DISPATCHMARSHALPARAM *param = (DISPATCHMARSHALPARAM*)user; + if (NULL == param) return; + + param->hr = CoGetInterfaceAndReleaseStream(param->pStream, IID_IDispatch, (void**)¶m->pDisp); + //if (SUCCEEDED(param->hr) && NULL != param->pDisp) + // param->pDisp->AddRef(); +} + +static void CALLBACK BrowserHost_DispatchCallbackApc(IDispatch *pDisp, ULONG_PTR user) +{ + POPUPCALLBACKPARAM *param = (POPUPCALLBACKPARAM*)user; + if (NULL == param) return; + + if (NULL != pDisp) + { + LPSTREAM pStream = NULL; + if (SUCCEEDED(CoMarshalInterThreadInterfaceInStream(IID_IDispatch, pDisp, &pStream))) + { // switch + DISPATCHMARSHALPARAM marshal = {0}; + marshal.pStream = pStream; + SendMessage(param->hHost, NBHM_QUEUEAPC, (WPARAM)&marshal, (LPARAM)BrowserHost_DispatchMarshalApc); + if (SUCCEEDED(marshal.hr) && NULL != marshal.pDisp) + { + *param->ppDisp = marshal.pDisp; + } + } + } + + if (NULL != param->readyEvent) + SetEvent(param->readyEvent); +} + +static HRESULT BrowserHost_GetSecurityApi(JSAPI2::api_security **securityApi) +{ + if (NULL == securityApi) + return E_POINTER; + + *securityApi = NULL; + + ifc_wasabihelper *wasabiHelper = NULL; + HRESULT hr = Plugin_GetWasabiHelper(&wasabiHelper); + if (SUCCEEDED(hr) && wasabiHelper != NULL) + { + hr = wasabiHelper->GetSecurityApi(securityApi); + wasabiHelper->Release(); + } + return hr; +} + +static BOOL BrowserHost_IsPopupAllowed(HWND hwnd, Browser *browser) +{ + ifc_omservice *service = NULL; + if (FAILED(BrowserHost_GetOmService(browser, &service)) || NULL == service) + return TRUE; + + BOOL fAllowed = TRUE; + + JSAPI::ifc_info *pInfo = NULL; + WCHAR szKey[64] = {0}; + + if (FAILED(StringCchPrintfW(szKey, ARRAYSIZE(szKey), L"%u", service->GetId()))) + szKey[0] = L'\0'; + + IDispatch *pDispatch = NULL; + if (SUCCEEDED(browser->GetExternal(&pDispatch)) && NULL != pDispatch) + { + IWasabiDispatchable *pWasabi = NULL; + if (SUCCEEDED(pDispatch->QueryInterface(IID_IWasabiDispatchable, (void**)&pWasabi)) && pWasabi != NULL) + { + if (FAILED(pWasabi->QueryDispatchable(JSAPI::IID_JSAPI_ifc_info, (Dispatchable**)&pInfo))) + pInfo = NULL; + pWasabi->Release(); + } + pDispatch->Release(); + } + + if (NULL != pInfo && L'\0' != szKey) + { + JSAPI2::api_security *security = NULL; + if (SUCCEEDED(BrowserHost_GetSecurityApi(&security)) && security != NULL) + { + if (security->GetActionAuthorization(L"application", L"launchurl", szKey, pInfo, + JSAPI2::api_security::ACTION_PROMPT) != JSAPI2::api_security::ACTION_ALLOWED) + { + fAllowed = FALSE; + } + security->Release(); + } + } + + if (NULL != pInfo) + pInfo->Release(); + + service->Release(); + return fAllowed; +} + +static void CALLBACK BrowserHost_OnCreatePopup(Browser *browser, IDispatch **ppDisp, VARIANT_BOOL *Cancel) +{ + HWND hHost = browser->GetParentHWND(); + + if (FALSE == BrowserHost_IsPopupAllowed(hHost, browser)) + { + if (NULL != Cancel) *Cancel = VARIANT_TRUE; + return; + } + + POPUPCALLBACKPARAM param = {0}; + param.hHost = browser->GetParentHWND(); + if (NULL == param.hHost) return; + + param.readyEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + param.ppDisp = ppDisp; + + BHNCREATEPOPUP popup = {0}; + popup.callback = BrowserHost_DispatchCallbackApc; + popup.param = (ULONG_PTR)¶m; + + if (FALSE != BrowserHost_SendBrowserNotification(browser, NBHN_CREATEPOPUP, (NMHDR*)&popup)) + { + BrowserThread_ModalLoop(param.hHost, param.readyEvent, 30000); + } + + if (NULL != param.readyEvent) + CloseHandle(param.readyEvent); +} + +static void CALLBACK BrowserHost_OnVisibleChange(Browser *browser, VARIANT_BOOL fVisible) +{ + BHNVISIBLE visible = {0}; + visible.fVisible = (VARIANT_FALSE != fVisible); + BrowserHost_SendBrowserNotification(browser, NBHN_VISIBLECHANGE, (NMHDR*)&visible); +} + +static void CALLBACK BrowserHost_OnSetResizable(Browser *browser, VARIANT_BOOL fAllow) +{ + BHNRESIZABLE resizable = {0}; + resizable.fEnabled = (VARIANT_FALSE != fAllow); + BrowserHost_SendBrowserNotification(browser, NBHN_RESIZABLE, (NMHDR*)&resizable); +} + +static void CALLBACK BrowserHost_OnSetFullScreen(Browser *browser, VARIANT_BOOL fEnable) +{ + BHNFULLSCREEN fullscreen = {0}; + fullscreen.fEnable = (VARIANT_FALSE != fEnable); + BrowserHost_SendBrowserNotification(browser, NBHN_FULLSCREEN, (NMHDR*)&fullscreen); +} + +static void CALLBACK BrowserHost_OnWindowClosing(Browser *browser, VARIANT_BOOL fIsChild, VARIANT_BOOL *fCancel) +{ + BHNCLOSING closing = {0}; + closing.isChild = (VARIANT_FALSE != fIsChild); + closing.cancel = FALSE; + + BrowserHost_SendBrowserNotification(browser, NBHN_CLOSING, (NMHDR*)&closing); + + if (FALSE != closing.cancel && NULL != fCancel) + *fCancel = VARIANT_TRUE; +} + +static void CALLBACK BrowserHost_OnShowUiElenent(Browser *browser, UINT elementId, VARIANT_BOOL fShow) +{ + BHNSHOWUI ui = {0}; + ui.elementId = elementId; + ui.fShow = fShow; + + BrowserHost_SendBrowserNotification(browser, NBHN_SHOWUI, (NMHDR*)&ui); +} + +static void CALLBACK BrowserHost_OnClientToHost(Browser *browser, LONG *cx, LONG *cy) +{ + BHNCLIENTTOHOST convert = {0}; + convert.cx = *cx; + convert.cy = *cy; + BrowserHost_SendBrowserNotification(browser, NBHN_CLIENTTOHOST, (NMHDR*)&convert); + + *cx = convert.cx; + *cy = convert.cy; +} + +static void CALLBACK BrowserHost_OnSetWindowPos(Browser *browser, UINT flags, LONG x, LONG y, LONG cx, LONG cy) +{ + BHNSETWINDOWPOS windowPos = {0}; + windowPos.flags = flags; + windowPos.x = x; + windowPos.y = y; + windowPos.cx = cx; + windowPos.cy = cy; + + BrowserHost_SendBrowserNotification(browser, NBHN_SETWINDOWPOS, (NMHDR*)&windowPos); +} + +static void CALLBACK BrowserHost_OnFocusChange(Browser *browser, VARIANT_BOOL *fAllow) +{ + BHNFOCUSCHANGE focus = {0}; + focus.fAllow = (VARIANT_FALSE != *fAllow); + + BrowserHost_SendBrowserNotification(browser, NBHN_FOCUSCHANGE, (NMHDR*)&focus); + + *fAllow = (FALSE != focus.fAllow) ? VARIANT_TRUE : VARIANT_FALSE; +} + +static void CALLBACK BrowserHost_OnClosePopup(Browser *browser) +{ + NMHDR hdr = {0}; + BrowserHost_SendBrowserNotification(browser, NBHN_CLOSEPOPUP, &hdr); + +} +static HRESULT CALLBACK BrowserHost_GetOmService(Browser *browser, ifc_omservice **ppService) +{ + if (NULL == ppService) return E_POINTER; + + BHNSERVICE service = {0}; + + if (FALSE != BrowserHost_SendBrowserNotification(browser, NBHN_GETOMSERVICE, (NMHDR*)&service) && + NULL != service.instance) + { + *ppService = (ifc_omservice*)service.instance; + return S_OK; + } + + *ppService = NULL; + return E_NOTIMPL; +} + + +static LRESULT CALLBACK BrowserHost_RedirectKey(Browser *browser, MSG *pMsg) +{ + HWND hHost = browser->GetParentHWND(); + HWND hParent = GetParent(hHost); + + if (NULL == hParent) + { + BROWSERHOST *host = GetHost(hHost); + + if (NULL != host && FAILED(Plugin_GetWinampWnd(&hParent))) + hParent = NULL; + } + + return PostMessage(hParent, pMsg->message, pMsg->wParam, pMsg->lParam); +}
\ No newline at end of file |