/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: Mozilla-sample-code 1.0 * * Copyright (c) 2002 Netscape Communications Corporation and * other contributors * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this Mozilla sample software and associated documentation files * (the "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit * persons to whom the Software is furnished to do so, subject to the * following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Contributor(s): * Doug Turner * Adam Lock * * ***** END LICENSE BLOCK ***** */ // C RunTime Header Files #include #include #include #include #include // Win32 header files #include #include #include // Mozilla Frozen APIs #include "nsXULAppAPI.h" XRE_InitEmbeddingType XRE_InitEmbedding; XRE_TermEmbeddingType XRE_TermEmbedding; #include "nsAppDirectoryServiceDefs.h" #include "nsDirectoryServiceDefs.h" #include "nsProfileDirServiceProvider.h" #include "nsStringAPI.h" #include "nsXPCOMGlue.h" #include "nsIClipboardCommands.h" #include "nsIInterfaceRequestor.h" #include "nsIObserverService.h" #include "nsIObserver.h" #include "nsIURI.h" #include "nsIWebBrowserFocus.h" #include "nsIWindowWatcher.h" // NON-FROZEN APIs! #include "nsIBaseWindow.h" #include "nsIWebNavigation.h" // Local header files #include "winEmbed.h" #include "WebBrowserChrome.h" #include "WindowCreator.h" #include "resource.h" #define MAX_LOADSTRING 100 const TCHAR *szWindowClass = _T("WINEMBED"); // Foward declarations of functions included in this code module: static ATOM MyRegisterClass(HINSTANCE hInstance); static LRESULT CALLBACK BrowserWndProc(HWND, UINT, WPARAM, LPARAM); static BOOL CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static nsresult InitializeWindowCreator(); static nsresult OpenWebPage(const char * url); static nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome); // Profile chooser stuff static nsresult StartupProfile(); // Global variables static UINT gDialogCount = 0; static HINSTANCE ghInstanceApp = NULL; static char gFirstURL[1024]; // like strpbrk but finds the *last* char, not the first static char* ns_strrpbrk(char *string, const char *strCharSet) { char *found = NULL; for (; *string; ++string) { for (const char *search = strCharSet; *search; ++search) { if (*search == *string) { found = string; // Since we're looking for the last char, we save "found" // until we're at the end of the string. } } } return found; } // A list of URLs to populate the URL drop down list with static const TCHAR *gDefaultURLs[] = { _T("http://www.mozilla.org/"), _T("http://www.netscape.com/"), _T("http://browsertest.web.aol.com/tests/javascript/javascpt/index.htm"), _T("http://127.0.0.1/"), _T("http://www.yahoo.com/"), _T("http://www.travelocity.com/"), _T("http://www.disney.com/"), _T("http://www.go.com/"), _T("http://www.google.com/"), _T("http://www.ebay.com/"), _T("http://www.shockwave.com/"), _T("http://www.slashdot.org/"), _T("http://www.quicken.com/"), _T("http://www.hotmail.com/"), _T("http://www.cnn.com/"), _T("http://www.javasoft.com/") }; int main(int argc, char *argv[]) { nsresult rv; printf("You are embedded, man!\n\n"); printf("******************************************************************\n"); printf("* *\n"); printf("* IMPORTANT NOTE: *\n"); printf("* *\n"); printf("* WinEmbed is not supported!!! Do not raise bugs on it unless *\n"); printf("* it is badly broken (e.g. crash on start/exit, build errors) *\n"); printf("* or you have the patch to make it better! MFCEmbed is now our *\n"); printf("* embedding test application on Win32 and all testing should *\n"); printf("* be done on that. *\n"); printf("* *\n"); printf("******************************************************************\n"); printf("\n\n"); // Sophisticated command-line parsing in action char *szFirstURL = "http://www.mozilla.org/projects/embedding/"; int argn; for (argn = 1; argn < argc; argn++) { szFirstURL = argv[argn]; } strncpy(gFirstURL, szFirstURL, sizeof(gFirstURL) - 1); ghInstanceApp = GetModuleHandle(NULL); // Initialize global strings TCHAR szTitle[MAX_LOADSTRING]; LoadString(ghInstanceApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); MyRegisterClass(ghInstanceApp); // Find the GRE (libxul). We are only using frozen interfaces, so we // should be compatible all the way up to (but not including) mozilla 2.0 static const GREVersionRange vr = { "1.8a1", PR_TRUE, "2.0", PR_FALSE }; char xpcomPath[_MAX_PATH]; rv = GRE_GetGREPathWithProperties(&vr, 1, nsnull, 0, xpcomPath, sizeof(xpcomPath)); if (NS_FAILED(rv)) return 1; char *lastslash = ns_strrpbrk(xpcomPath, "/\\"); if (!lastslash) return 2; rv = XPCOMGlueStartup(xpcomPath); if (NS_FAILED(rv)) return 3; *lastslash = '\0'; char xulPath[_MAX_PATH]; _snprintf(xulPath, sizeof(xulPath), "%s\\xul.dll", xpcomPath); xulPath[sizeof(xulPath) - 1] = '\0'; HINSTANCE xulModule = LoadLibraryEx(xulPath, NULL, 0); if (!xulModule) return 4; char temp[_MAX_PATH]; GetModuleFileName(xulModule, temp, sizeof(temp)); XRE_InitEmbedding = (XRE_InitEmbeddingType) GetProcAddress(xulModule, "XRE_InitEmbedding"); if (!XRE_InitEmbedding) { fprintf(stderr, "Error: %i\n", GetLastError()); return 5; } XRE_TermEmbedding = (XRE_TermEmbeddingType) GetProcAddress(xulModule, "XRE_TermEmbedding"); if (!XRE_TermEmbedding) { fprintf(stderr, "Error: %i\n", GetLastError()); return 5; } // Scope all the XPCOM stuff { nsCOMPtr xuldir; rv = NS_NewNativeLocalFile(nsCString(xpcomPath), PR_FALSE, getter_AddRefs(xuldir)); if (NS_FAILED(rv)) return 6; char self[_MAX_PATH]; GetModuleFileName(ghInstanceApp, self, sizeof(self)); lastslash = ns_strrpbrk(xpcomPath, "/\\"); if (!lastslash) return 7; *lastslash = '\0'; nsCOMPtr appdir; rv = NS_NewNativeLocalFile(nsCString(self), PR_FALSE, getter_AddRefs(appdir)); if (NS_FAILED(rv)) return 8; rv = XRE_InitEmbedding(xuldir, appdir, nsnull, nsnull, 0); if (NS_FAILED(rv)) return 9; int result = 0; if (NS_FAILED(StartupProfile())) { result = 8; } else { InitializeWindowCreator(); // Open the initial browser window OpenWebPage(gFirstURL); // Main message loop. // NOTE: We use a fake event and a timeout in order to process idle stuff for // Mozilla every 1/10th of a second. PRBool runCondition = PR_TRUE; rv = AppCallbacks::RunEventLoop(runCondition); } } XRE_TermEmbedding(); return rv; } /* InitializeWindowCreator creates and hands off an object with a callback to a window creation function. This is how all new windows are opened, except any created directly by the embedding app. */ nsresult InitializeWindowCreator() { // create an nsWindowCreator and give it to the WindowWatcher service nsCOMPtr creator(new WindowCreator()); if (!creator) return NS_ERROR_OUT_OF_MEMORY; nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); if (!wwatch) return NS_ERROR_UNEXPECTED; return wwatch->SetWindowCreator(creator); } //----------------------------------------------------------------------------- // // FUNCTION: OpenWebPage() // // PURPOSE: Opens a new browser dialog and starts it loading to the // specified url. // nsresult OpenWebPage(const char *url) { nsresult rv; // Create the chrome object. Note that it leaves this function // with an extra reference so that it can released correctly during // destruction (via Win32UI::Destroy) nsCOMPtr chrome; rv = AppCallbacks::CreateBrowserWindow(nsIWebBrowserChrome::CHROME_ALL, nsnull, getter_AddRefs(chrome)); if (NS_SUCCEEDED(rv)) { // Start loading a page nsCOMPtr newBrowser; chrome->GetWebBrowser(getter_AddRefs(newBrowser)); nsCOMPtr webNav(do_QueryInterface(newBrowser)); return webNav->LoadURI(NS_ConvertASCIItoUTF16(url).get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull); } return rv; } // // FUNCTION: GetBrowserFromChrome() // // PURPOSE: Returns the HWND for the webbrowser container associated // with the specified chrome. // HWND GetBrowserFromChrome(nsIWebBrowserChrome *aChrome) { if (!aChrome) { return NULL; } nsCOMPtr baseWindow = do_QueryInterface(aChrome); HWND hwnd = NULL; baseWindow->GetSiteWindow((void **) & hwnd); return hwnd; } // // FUNCTION: GetBrowserDlgFromChrome() // // PURPOSE: Returns the HWND for the browser dialog associated with // the specified chrome. // HWND GetBrowserDlgFromChrome(nsIWebBrowserChrome *aChrome) { return GetParent(GetBrowserFromChrome(aChrome)); } // // FUNCTION: ResizeEmbedding() // // PURPOSE: Resizes the webbrowser window to fit its container. // nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome) { if (!chrome) return NS_ERROR_FAILURE; nsCOMPtr embeddingSite = do_QueryInterface(chrome); HWND hWnd; embeddingSite->GetSiteWindow((void **) & hWnd); if (!hWnd) return NS_ERROR_NULL_POINTER; RECT rect; GetClientRect(hWnd, &rect); // Make sure the browser is visible and sized nsCOMPtr webBrowser; chrome->GetWebBrowser(getter_AddRefs(webBrowser)); nsCOMPtr webBrowserAsWin = do_QueryInterface(webBrowser); if (webBrowserAsWin) { webBrowserAsWin->SetPositionAndSize(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PR_TRUE); webBrowserAsWin->SetVisibility(PR_TRUE); } return NS_OK; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; memset(&wcex, 0, sizeof(wcex)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC) BrowserWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_WINEMBED); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // FUNCTION: UpdateUI() // // PURPOSE: Refreshes the buttons and menu items in the browser dialog // void UpdateUI(nsIWebBrowserChrome *aChrome) { HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); nsCOMPtr webBrowser; nsCOMPtr webNavigation; aChrome->GetWebBrowser(getter_AddRefs(webBrowser)); webNavigation = do_QueryInterface(webBrowser); PRBool canGoBack = PR_FALSE; PRBool canGoForward = PR_FALSE; if (webNavigation) { webNavigation->GetCanGoBack(&canGoBack); webNavigation->GetCanGoForward(&canGoForward); } PRBool canCutSelection = PR_FALSE; PRBool canCopySelection = PR_FALSE; PRBool canPaste = PR_FALSE; nsCOMPtr clipCmds = do_GetInterface(webBrowser); if (clipCmds) { clipCmds->CanCutSelection(&canCutSelection); clipCmds->CanCopySelection(&canCopySelection); clipCmds->CanPaste(&canPaste); } HMENU hmenu = GetMenu(hwndDlg); if (hmenu) { EnableMenuItem(hmenu, MOZ_GoBack, MF_BYCOMMAND | ((canGoBack) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); EnableMenuItem(hmenu, MOZ_GoForward, MF_BYCOMMAND | ((canGoForward) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); EnableMenuItem(hmenu, MOZ_Cut, MF_BYCOMMAND | ((canCutSelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); EnableMenuItem(hmenu, MOZ_Copy, MF_BYCOMMAND | ((canCopySelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); EnableMenuItem(hmenu, MOZ_Paste, MF_BYCOMMAND | ((canPaste) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); } HWND button; button = GetDlgItem(hwndDlg, IDC_BACK); if (button) EnableWindow(button, canGoBack); button = GetDlgItem(hwndDlg, IDC_FORWARD); if (button) EnableWindow(button, canGoForward); } // // FUNCTION: BrowserDlgProc() // // PURPOSE: Browser dialog windows message handler. // // COMMENTS: // // The code for handling buttons and menu actions is here. // BOOL CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get the browser and other pointers since they are used a lot below HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); nsIWebBrowserChrome *chrome = nsnull ; if (hwndBrowser) { chrome = (nsIWebBrowserChrome *) GetWindowLong(hwndBrowser, GWL_USERDATA); } nsCOMPtr webBrowser; nsCOMPtr webNavigation; if (chrome) { chrome->GetWebBrowser(getter_AddRefs(webBrowser)); webNavigation = do_QueryInterface(webBrowser); } // Test the message switch (uMsg) { case WM_INITDIALOG: return TRUE; case WM_INITMENU: UpdateUI(chrome); return TRUE; case WM_SYSCOMMAND: if (wParam == SC_CLOSE) { WebBrowserChromeUI::Destroy(chrome); return TRUE; } break; case WM_DESTROY: return TRUE; case WM_COMMAND: if (!webBrowser) { return TRUE; } // Test which command was selected switch (LOWORD(wParam)) { case IDC_ADDRESS: if (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE) { // User has changed the address field so enable the Go button EnableWindow(GetDlgItem(hwndDlg, IDC_GO), TRUE); } break; case IDC_GO: { TCHAR szURL[2048]; memset(szURL, 0, sizeof(szURL)); GetDlgItemText(hwndDlg, IDC_ADDRESS, szURL, sizeof(szURL) / sizeof(szURL[0]) - 1); webNavigation->LoadURI( NS_ConvertASCIItoUTF16(szURL).get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull); } break; case IDC_STOP: webNavigation->Stop(nsIWebNavigation::STOP_ALL); UpdateUI(chrome); break; case IDC_RELOAD: webNavigation->Reload(nsIWebNavigation::LOAD_FLAGS_NONE); break; case IDM_EXIT: PostMessage(hwndDlg, WM_SYSCOMMAND, SC_CLOSE, 0); break; // File menu commands case MOZ_NewBrowser: OpenWebPage(gFirstURL); break; // Edit menu commands case MOZ_Cut: { nsCOMPtr clipCmds = do_GetInterface(webBrowser); clipCmds->CutSelection(); } break; case MOZ_Copy: { nsCOMPtr clipCmds = do_GetInterface(webBrowser); clipCmds->CopySelection(); } break; case MOZ_Paste: { nsCOMPtr clipCmds = do_GetInterface(webBrowser); clipCmds->Paste(); } break; case MOZ_SelectAll: { nsCOMPtr clipCmds = do_GetInterface(webBrowser); clipCmds->SelectAll(); } break; case MOZ_SelectNone: { nsCOMPtr clipCmds = do_GetInterface(webBrowser); clipCmds->SelectNone(); } break; // Go menu commands case IDC_BACK: case MOZ_GoBack: webNavigation->GoBack(); UpdateUI(chrome); break; case IDC_FORWARD: case MOZ_GoForward: webNavigation->GoForward(); UpdateUI(chrome); break; // Help menu commands case MOZ_About: { TCHAR szAboutTitle[MAX_LOADSTRING]; TCHAR szAbout[MAX_LOADSTRING]; LoadString(ghInstanceApp, IDS_ABOUT_TITLE, szAboutTitle, MAX_LOADSTRING); LoadString(ghInstanceApp, IDS_ABOUT, szAbout, MAX_LOADSTRING); MessageBox(NULL, szAbout, szAboutTitle, MB_OK); } break; } return TRUE; case WM_ACTIVATE: { nsCOMPtr focus(do_GetInterface(webBrowser)); if(focus) { switch (wParam) { case WA_ACTIVE: focus->Activate(); break; case WA_INACTIVE: focus->Deactivate(); break; default: break; } } } break; case WM_SIZE: { UINT newDlgWidth = LOWORD(lParam); UINT newDlgHeight = HIWORD(lParam); // TODO Reposition the control bar - for the moment it's fixed size // Reposition the status area. Status bar // gets any space that the fixed size progress bar doesn't use. int progressWidth; int statusWidth; int statusHeight; HWND hwndStatus = GetDlgItem(hwndDlg, IDC_STATUS); if (hwndStatus) { RECT rcStatus; GetWindowRect(hwndStatus, &rcStatus); statusHeight = rcStatus.bottom - rcStatus.top; } else statusHeight = 0; HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); if (hwndProgress) { RECT rcProgress; GetWindowRect(hwndProgress, &rcProgress); progressWidth = rcProgress.right - rcProgress.left; } else progressWidth = 0; statusWidth = newDlgWidth - progressWidth; if (hwndStatus) SetWindowPos(hwndStatus, HWND_TOP, 0, newDlgHeight - statusHeight, statusWidth, statusHeight, SWP_NOZORDER); if (hwndProgress) SetWindowPos(hwndProgress, HWND_TOP, statusWidth, newDlgHeight - statusHeight, 0, 0, SWP_NOSIZE | SWP_NOZORDER); // Resize the browser area (assuming the browse is // sandwiched between the control bar and status area) RECT rcBrowser; POINT ptBrowser; GetWindowRect(hwndBrowser, &rcBrowser); ptBrowser.x = rcBrowser.left; ptBrowser.y = rcBrowser.top; ScreenToClient(hwndDlg, &ptBrowser); int browserHeight = newDlgHeight - ptBrowser.y - statusHeight; if (browserHeight < 1) { browserHeight = 1; } SetWindowPos(hwndBrowser, HWND_TOP, 0, 0, newDlgWidth, newDlgHeight - ptBrowser.y - statusHeight, SWP_NOMOVE | SWP_NOZORDER); } return TRUE; } return FALSE; } // // FUNCTION: BrowserWndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the browser container window. // LRESULT CALLBACK BrowserWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { nsIWebBrowserChrome *chrome = (nsIWebBrowserChrome *) GetWindowLong(hWnd, GWL_USERDATA); switch (message) { case WM_SIZE: // Resize the embedded browser ResizeEmbedding(chrome); return 0; case WM_ERASEBKGND: // Reduce flicker by not painting the non-visible background return 1; } return DefWindowProc(hWnd, message, wParam, lParam); } // // FUNCTION: StartupProfile() // // PURPOSE: // nsresult StartupProfile() { nsCOMPtr appDataDir; nsresult rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(appDataDir)); if (NS_FAILED(rv)) return rv; appDataDir->AppendNative(nsCString("winembed")); nsCOMPtr localAppDataDir(do_QueryInterface(appDataDir)); nsCOMPtr locProvider; NS_NewProfileDirServiceProvider(PR_TRUE, getter_AddRefs(locProvider)); if (!locProvider) return NS_ERROR_FAILURE; rv = locProvider->Register(); if (NS_FAILED(rv)) return rv; return locProvider->SetProfileDir(localAppDataDir); } /////////////////////////////////////////////////////////////////////////////// // WebBrowserChromeUI // // FUNCTION: CreateNativeWindow() // // PURPOSE: Creates a new browser dialog. // // COMMENTS: // // This function loads the browser dialog from a resource template // and returns the HWND for the webbrowser container dialog item // to the caller. // HWND WebBrowserChromeUI::CreateNativeWindow(nsIWebBrowserChrome* chrome) { // Load the browser dialog from resource HWND hwndDialog; PRUint32 chromeFlags; chrome->GetChromeFlags(&chromeFlags); if ((chromeFlags & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL) hwndDialog = CreateDialog(ghInstanceApp, MAKEINTRESOURCE(IDD_BROWSER), NULL, BrowserDlgProc); else hwndDialog = CreateDialog(ghInstanceApp, MAKEINTRESOURCE(IDD_BROWSER_NC), NULL, BrowserDlgProc); if (!hwndDialog) return NULL; // Stick a menu onto it if (chromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR) { HMENU hmenuDlg = LoadMenu(ghInstanceApp, MAKEINTRESOURCE(IDC_WINEMBED)); SetMenu(hwndDialog, hmenuDlg); } else SetMenu(hwndDialog, 0); // Add some interesting URLs to the address drop down HWND hwndAddress = GetDlgItem(hwndDialog, IDC_ADDRESS); if (hwndAddress) { for (int i = 0; i < sizeof(gDefaultURLs) / sizeof(gDefaultURLs[0]); i++) { SendMessage(hwndAddress, CB_ADDSTRING, 0, (LPARAM) gDefaultURLs[i]); } } // Fetch the browser window handle HWND hwndBrowser = GetDlgItem(hwndDialog, IDC_BROWSER); SetWindowLong(hwndBrowser, GWL_USERDATA, (LONG)chrome); // save the browser LONG_PTR. SetWindowLong(hwndBrowser, GWL_STYLE, GetWindowLong(hwndBrowser, GWL_STYLE) | WS_CLIPCHILDREN); // Activate the window PostMessage(hwndDialog, WM_ACTIVATE, WA_ACTIVE, 0); gDialogCount++; return hwndBrowser; } // // FUNCTION: Destroy() // // PURPOSE: Destroy the window specified by the chrome // void WebBrowserChromeUI::Destroy(nsIWebBrowserChrome* chrome) { nsCOMPtr webBrowser; nsCOMPtr webNavigation; chrome->GetWebBrowser(getter_AddRefs(webBrowser)); webNavigation = do_QueryInterface(webBrowser); if (webNavigation) webNavigation->Stop(nsIWebNavigation::STOP_ALL); chrome->ExitModalEventLoop(NS_OK); HWND hwndDlg = GetBrowserDlgFromChrome(chrome); if (hwndDlg == NULL) return; // Explicitly destroy the embedded browser and then the chrome // First the browser nsCOMPtr browser = nsnull; chrome->GetWebBrowser(getter_AddRefs(browser)); nsCOMPtr browserAsWin = do_QueryInterface(browser); if (browserAsWin) browserAsWin->Destroy(); // Now the chrome chrome->SetWebBrowser(nsnull); NS_RELEASE(chrome); } // // FUNCTION: Called as the final act of a chrome object during its destructor // void WebBrowserChromeUI::Destroyed(nsIWebBrowserChrome* chrome) { HWND hwndDlg = GetBrowserDlgFromChrome(chrome); if (hwndDlg == NULL) { return; } // Clear the window user data HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); SetWindowLong(hwndBrowser, GWL_USERDATA, nsnull); DestroyWindow(hwndBrowser); DestroyWindow(hwndDlg); --gDialogCount; if (gDialogCount == 0) { // Quit when there are no more browser objects PostQuitMessage(0); } } // // FUNCTION: Set the input focus onto the browser window // void WebBrowserChromeUI::SetFocus(nsIWebBrowserChrome *chrome) { HWND hwndDlg = GetBrowserDlgFromChrome(chrome); if (hwndDlg == NULL) { return; } HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); ::SetFocus(hwndBrowser); } // // FUNCTION: UpdateStatusBarText() // // PURPOSE: Set the status bar text. // void WebBrowserChromeUI::UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const PRUnichar* aStatusText) { HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); nsCString status; if (aStatusText) { nsString wStatusText(aStatusText); NS_UTF16ToCString(wStatusText, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM, status); } SetDlgItemText(hwndDlg, IDC_STATUS, status.get()); } // // FUNCTION: UpdateCurrentURI() // // PURPOSE: Updates the URL address field // void WebBrowserChromeUI::UpdateCurrentURI(nsIWebBrowserChrome *aChrome) { nsCOMPtr webBrowser; nsCOMPtr webNavigation; aChrome->GetWebBrowser(getter_AddRefs(webBrowser)); webNavigation = do_QueryInterface(webBrowser); nsCOMPtr currentURI; webNavigation->GetCurrentURI(getter_AddRefs(currentURI)); if (currentURI) { nsCString uriString; currentURI->GetAsciiSpec(uriString); HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); SetDlgItemText(hwndDlg, IDC_ADDRESS, uriString.get()); } } // // FUNCTION: UpdateBusyState() // // PURPOSE: Refreshes the stop/go buttons in the browser dialog // void WebBrowserChromeUI::UpdateBusyState(nsIWebBrowserChrome *aChrome, PRBool aBusy) { HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); HWND button; button = GetDlgItem(hwndDlg, IDC_STOP); if (button) EnableWindow(button, aBusy); button = GetDlgItem(hwndDlg, IDC_GO); if (button) EnableWindow(button, !aBusy); UpdateUI(aChrome); } // // FUNCTION: UpdateProgress() // // PURPOSE: Refreshes the progress bar in the browser dialog // void WebBrowserChromeUI::UpdateProgress(nsIWebBrowserChrome *aChrome, PRInt32 aCurrent, PRInt32 aMax) { HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); if (aCurrent < 0) { aCurrent = 0; } if (aCurrent > aMax) { aMax = aCurrent + 20; // What to do? } if (hwndProgress) { SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, aMax)); SendMessage(hwndProgress, PBM_SETPOS, aCurrent, 0); } } // // FUNCTION: ShowContextMenu() // // PURPOSE: Display a context menu for the given node // void WebBrowserChromeUI::ShowContextMenu(nsIWebBrowserChrome *aChrome, PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) { // TODO code to test context flags and display a popup menu should go here } // // FUNCTION: ShowTooltip() // // PURPOSE: Show a tooltip // void WebBrowserChromeUI::ShowTooltip(nsIWebBrowserChrome *aChrome, PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText) { // TODO code to show a tooltip should go here } // // FUNCTION: HideTooltip() // // PURPOSE: Hide the tooltip // void WebBrowserChromeUI::HideTooltip(nsIWebBrowserChrome *aChrome) { // TODO code to hide a tooltip should go here } void WebBrowserChromeUI::ShowWindow(nsIWebBrowserChrome *aChrome, PRBool aShow) { HWND win = GetBrowserDlgFromChrome(aChrome); ::ShowWindow(win, aShow ? SW_RESTORE : SW_HIDE); } void WebBrowserChromeUI::SizeTo(nsIWebBrowserChrome *aChrome, PRInt32 aWidth, PRInt32 aHeight) { HWND hchrome = GetBrowserDlgFromChrome(aChrome); HWND hbrowser = GetBrowserFromChrome(aChrome); RECT chromeRect, browserRect; ::GetWindowRect(hchrome, &chromeRect); ::GetWindowRect(hbrowser, &browserRect); PRInt32 decoration_x = (browserRect.left - chromeRect.left) + (chromeRect.right - browserRect.right); PRInt32 decoration_y = (browserRect.top - chromeRect.top) + (chromeRect.bottom - browserRect.bottom); ::MoveWindow(hchrome, chromeRect.left, chromeRect.top, aWidth+decoration_x, aHeight+decoration_y, TRUE); } // // FUNCTION: GetResourceStringByID() // // PURPOSE: Get the resource string for the ID // void WebBrowserChromeUI::GetResourceStringById(PRInt32 aID, char ** aReturn) { char resBuf[MAX_LOADSTRING]; int retval = LoadString( ghInstanceApp, aID, (LPTSTR)resBuf, sizeof(resBuf) ); if (retval != 0) { int resLen = strlen(resBuf); *aReturn = (char *)calloc(resLen+1, sizeof(char *)); if (!*aReturn) return; strncpy(*aReturn, resBuf, resLen); } return; } //----------------------------------------------------------------------------- // AppCallbacks //----------------------------------------------------------------------------- nsresult AppCallbacks::CreateBrowserWindow(PRUint32 aChromeFlags, nsIWebBrowserChrome *aParent, nsIWebBrowserChrome **aNewWindow) { WebBrowserChrome * chrome = new WebBrowserChrome(); if (!chrome) return NS_ERROR_FAILURE; // the interface to return and one addref, which we assume will be // immediately released CallQueryInterface(static_cast(chrome), aNewWindow); // now an extra addref; the window owns itself (to be released by // WebBrowserChromeUI::Destroy) NS_ADDREF(*aNewWindow); chrome->SetChromeFlags(aChromeFlags); chrome->SetParent(aParent); // Insert the browser nsCOMPtr newBrowser; chrome->CreateBrowser(-1, -1, -1, -1, getter_AddRefs(newBrowser)); if (!newBrowser) return NS_ERROR_FAILURE; // Place it where we want it. ResizeEmbedding(static_cast(chrome)); // if opened as chrome, it'll be made visible after the chrome has loaded. // otherwise, go ahead and show it now. if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) WebBrowserChromeUI::ShowWindow(*aNewWindow, PR_TRUE); return NS_OK; } void AppCallbacks::EnableChromeWindow(nsIWebBrowserChrome *aWindow, PRBool aEnabled) { HWND hwnd = GetBrowserDlgFromChrome(aWindow); ::EnableWindow(hwnd, aEnabled ? TRUE : FALSE); } PRUint32 AppCallbacks::RunEventLoop(PRBool &aRunCondition) { MSG msg; HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); while (aRunCondition ) { // Process pending messages while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (!::GetMessage(&msg, NULL, 0, 0)) { // WM_QUIT aRunCondition = PR_FALSE; break; } ::TranslateMessage(&msg); ::DispatchMessage(&msg); } // Do idle stuff ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 100, QS_ALLEVENTS); } ::CloseHandle(hFakeEvent); return msg.wParam; }