/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org Code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Radha Kulkarni * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include #include "stdafx.h" // Win32 header files #include "windows.h" #include "commctrl.h" #include "commdlg.h" // Mozilla header files #include "nsCOMPtr.h" #include "nsEmbedAPI.h" #include "nsWeakReference.h" #include "nsIClipboardCommands.h" #include "nsXPIDLString.h" #include "nsIWebBrowserPersist.h" #include "nsIWebBrowserFocus.h" #include "nsIWindowWatcher.h" #include "nsIProfile.h" //#include "nsIObserverService.h" #include "nsIObserver.h" #include "nsIProfileChangeStatus.h" #include "nsIURI.h" #include "plstr.h" #include "nsIInterfaceRequestor.h" #include "nsCRT.h" #include "nsString.h" #include "nsIWebBrowser.h" #include "nsIComponentManager.h" #include "nsServiceManagerUtils.h" #include "nsIEmbeddingSiteWindow.h" #include "nsIWebNavigation.h" #include "nsIWebBrowserChrome.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIComponentRegistrar.h" #include "nsIModule.h" #include "nsIGenericFactory.h" // Local header files //#include "nsIQABrowserChrome.h" #include "mozEmbed.h" #include "nsQAWindowCreator.h" #include "resource.h" #include "nsQABrowserCID.h" #include "nsQABrowserUIGlue.h" //#include "nsIQABrowserView.h" // Printing header files #include "nsIPrintSettings.h" #include "nsIWebBrowserPrint.h" #define MAX_LOADSTRING 100 #define MAX_BROWSER_ALLOWED 50 const TCHAR *szWindowClass = _T("MOZEMBED"); // Forward 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 BOOL ChooseNewProfile(BOOL bShowForMultipleProfilesOnly, const char *szDefaultProfile); static LRESULT CALLBACK ChooseProfileDlgProc(HWND, UINT, WPARAM, LPARAM); extern nsresult RegisterComponents(); // Global variables static UINT gDialogCount = 0; static BOOL gProfileSwitch = FALSE; static HINSTANCE ghInstanceResources = NULL; static HINSTANCE ghInstanceApp = NULL; static char gFirstURL[1024]; // 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/") }; // // 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: 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); } //////////////////////////////////////////////////////////////////////////////////////////// // Main program //////////////////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { 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"; char *szDefaultProfile = nsnull; int argn; for (argn = 1; argn < argc; argn++) { if (stricmp("-P", argv[argn]) == 0) { if (argn + 1 < argc) { szDefaultProfile = argv[++argn]; } } else { szFirstURL = argv[argn]; } } strncpy(gFirstURL, szFirstURL, sizeof(gFirstURL) - 1); ghInstanceApp = GetModuleHandle(NULL); ghInstanceResources = GetModuleHandle(NULL); // Initialize global strings TCHAR szTitle[MAX_LOADSTRING]; LoadString(ghInstanceResources, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); MyRegisterClass(ghInstanceApp); // Init Embedding APIs NS_InitEmbedding(nsnull, nsnull); RegisterComponents(); // Choose the new profile // Have to do this to initialise global history if (!ChooseNewProfile(TRUE, szDefaultProfile)) { NS_TermEmbedding(); return 1; } WPARAM rv; { 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); // observer->Release(); } // Close down Embedding APIs NS_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() { printf("In InitializeWindowCreator\n"); // create an nsWindowCreator and give it to the WindowWatcher service WindowCreator *creatorCallback = new WindowCreator(); if (creatorCallback) { nsCOMPtr windowCreator(static_cast(creatorCallback)); if (windowCreator) { nsCOMPtr wwatch(do_GetService("@mozilla.org/embedcomp/window-watcher;1")); if (wwatch) { wwatch->SetWindowCreator(windowCreator); return NS_OK; } } } return NS_ERROR_FAILURE; } //----------------------------------------------------------------------------- // // FUNCTION: OpenWebPage() // // PURPOSE: Opens a new browser dialog and starts it loading to the // specified url. // nsresult OpenWebPage(const char *url) { nsresult rv; printf("In OpenWebpage\n"); if (gDialogCount == MAX_BROWSER_ALLOWED) return NS_ERROR_FAILURE; // Create the UI Glue object. This is the glue between nsIWebBrowserChrome and // the native UI code. nsCOMPtr browserUIGlue; browserUIGlue = do_CreateInstance(NS_QABROWSERUIGLUE_CONTRACTID, &rv); if (!browserUIGlue) return NS_ERROR_FAILURE; // Create a new browser window nsIWebBrowserChrome * chrome; rv = browserUIGlue->CreateNewBrowserWindow(nsIWebBrowserChrome::CHROME_ALL, nsnull, &chrome); if (NS_SUCCEEDED(rv)) { browserUIGlue->LoadURL(url); } return rv; } // // FUNCTION: SaveWebPage() // // PURPOSE: Saves the contents of the web page to a file // void SaveWebPage(nsIWebBrowser *aWebBrowser) { // Use the browser window title as the initial file name nsCOMPtr webBrowserAsWin = do_QueryInterface(aWebBrowser); nsXPIDLString windowTitle; webBrowserAsWin->GetTitle(getter_Copies(windowTitle)); nsCString fileName; fileName.AssignWithConversion(windowTitle); // Sanitize the title of all illegal characters fileName.CompressWhitespace(); // Remove whitespace from the ends fileName.StripChars("\\*|:\"> persist(do_QueryInterface(aWebBrowser)); nsCOMPtr file; NS_NewNativeLocalFile(nsDependentCString(szFile), TRUE, getter_AddRefs(file)); nsCOMPtr dataPath; if (pszDataPath) { NS_NewNativeLocalFile(nsDependentCString(pszDataPath), TRUE, getter_AddRefs(dataPath)); } persist->SaveDocument(nsnull, file, dataPath, nsnull, 0, 0); } } // // 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(ghInstanceResources, (LPCTSTR)IDI_MOZEMBED); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(ghInstanceResources, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // 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) { if (uMsg == WM_COMMAND && LOWORD(wParam) == MOZ_SwitchProfile) { ChooseNewProfile(FALSE, NULL); return FALSE; } // 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; nsCOMPtr webBrowserPrint; if (chrome) { chrome->GetWebBrowser(getter_AddRefs(webBrowser)); webNavigation = do_QueryInterface(webBrowser); webBrowserPrint = do_GetInterface(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) { if (!webNavigation || !webBrowser || !chrome) return FALSE; webNavigation->Stop(nsIWebNavigation::STOP_ALL); chrome->ExitModalEventLoop(NS_OK); // Explicitly destroy the embedded browser and then the chrome // First the browser nsCOMPtr browserAsWin = do_QueryInterface(webBrowser); if (browserAsWin) browserAsWin->Destroy(); // Now the chrome chrome->SetWebBrowser(nsnull); NS_RELEASE(chrome); return FALSE; } break; case WM_DESTROY: return FALSE; case WM_COMMAND: { if (!webBrowser) { return FALSE; } // 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; case MOZ_Save: SaveWebPage(webBrowser); break; case MOZ_Print: { // NOTE: Embedding code shouldn't need to get the docshell or // contentviewer AT ALL. This code below will break one // day but will have to do until the embedding API has // a cleaner way to do the same thing. if (webBrowserPrint) { nsCOMPtr printSettings; webBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings)); NS_ASSERTION(printSettings, "You can't PrintPreview without a PrintSettings!"); if (printSettings) { printSettings->SetPrintSilent(PR_TRUE); webBrowserPrint->Print(printSettings, (nsIWebProgressListener*)nsnull); } } } 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(ghInstanceResources, IDS_ABOUT_TITLE, szAboutTitle, MAX_LOADSTRING); LoadString(ghInstanceResources, 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); } /////////////////////////////////////////////////////////////////////////////// // Profile chooser dialog // // FUNCTION: ChooseNewProfile() // // PURPOSE: Allows the user to select a new profile from a list. // The bShowForMultipleProfilesOnly argument specifies whether the // function should automatically select the first profile and return // without displaying a dialog box if there is only one profile to // select. // BOOL ChooseNewProfile(BOOL bShowForMultipleProfilesOnly, const char *szDefaultProfile) { nsresult rv; nsCOMPtr profileService = do_GetService(NS_PROFILE_CONTRACTID, &rv); if (NS_FAILED(rv)) { return FALSE; } if (szDefaultProfile) { // Make a new default profile nsAutoString newProfileName; newProfileName.AssignWithConversion(szDefaultProfile); rv = profileService->CreateNewProfile(newProfileName.get(), nsnull, nsnull, PR_FALSE); if (NS_FAILED(rv)) return FALSE; rv = profileService->SetCurrentProfile(newProfileName.get()); if (NS_FAILED(rv)) return FALSE; return TRUE; } PRInt32 profileCount = 0; rv = profileService->GetProfileCount(&profileCount); if (profileCount == 0) { // Make a new default profile NS_NAMED_LITERAL_STRING(newProfileName, "mozEmbed"); rv = profileService->CreateNewProfile(newProfileName.get(), nsnull, nsnull, PR_FALSE); if (NS_FAILED(rv)) return FALSE; rv = profileService->SetCurrentProfile(newProfileName.get()); if (NS_FAILED(rv)) return FALSE; return TRUE; } else if (profileCount == 1 && bShowForMultipleProfilesOnly) { // GetCurrentProfile returns the profile which was last used but is not nescesarily // active. Call SetCurrentProfile to make it installed and active. nsXPIDLString currProfileName; rv = profileService->GetCurrentProfile(getter_Copies(currProfileName)); if (NS_FAILED(rv)) return FALSE; rv = profileService->SetCurrentProfile(currProfileName); if (NS_FAILED(rv)) return FALSE; return TRUE; } INT nResult; nResult = DialogBox(ghInstanceResources, (LPCTSTR)IDD_CHOOSEPROFILE, NULL, (DLGPROC)ChooseProfileDlgProc); return (nResult == IDOK) ? TRUE : FALSE; } // // FUNCTION: ChooseProfileDlgProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Dialog handler procedure for the open uri dialog. // LRESULT CALLBACK ChooseProfileDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { nsresult rv; switch (message) { case WM_INITDIALOG: { HWND hwndProfileList = GetDlgItem(hDlg, IDC_PROFILELIST); nsCOMPtr profileService = do_GetService(NS_PROFILE_CONTRACTID, &rv); // Get the list of profile names and add them to the list box PRUint32 listLen = 0; PRUnichar **profileList = nsnull; rv = profileService->GetProfileList(&listLen, &profileList); for (PRUint32 index = 0; index < listLen; index++) { #ifdef UNICODE SendMessageW(hwndProfileList, LB_ADDSTRING, 0, (LPARAM) profileList[index]); #else nsCAutoString profile; profile.AssignWithConversion(profileList[index]); SendMessageA(hwndProfileList, LB_ADDSTRING, 0, (LPARAM) profile.get()); #endif } // Select the current profile (if there is one) // Get the current profile #ifdef UNICODE nsXPIDLString currProfile; profileService->GetCurrentProfile(getter_Copies(currProfile)); #else nsXPIDLString currProfileUnicode; profileService->GetCurrentProfile(getter_Copies(currProfileUnicode)); nsCAutoString currProfile; currProfile.AssignWithConversion(currProfileUnicode); #endif // Now find and select it INT currentProfileIndex = LB_ERR; currentProfileIndex = SendMessage(hwndProfileList, LB_FINDSTRINGEXACT, -1, (LPARAM) currProfile.get()); if (currentProfileIndex != LB_ERR) { SendMessage(hwndProfileList, LB_SETCURSEL, currentProfileIndex, 0); } } return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || (HIWORD(wParam) & LBN_DBLCLK && LOWORD(wParam) == IDC_PROFILELIST)) { HWND hwndProfileList = GetDlgItem(hDlg, IDC_PROFILELIST); // Get the selected profile from the list box and make it current INT currentProfileIndex = SendMessage(hwndProfileList, LB_GETCURSEL, 0, 0); if (currentProfileIndex != LB_ERR) { nsCOMPtr profileService = do_GetService(NS_PROFILE_CONTRACTID, &rv); // Convert TCHAR name to unicode and make it current INT profileNameLen = SendMessage(hwndProfileList, LB_GETTEXTLEN, currentProfileIndex, 0); TCHAR *profileName = new TCHAR[profileNameLen + 1]; SendMessage(hwndProfileList, LB_GETTEXT, currentProfileIndex, (LPARAM) profileName); nsAutoString newProfile; newProfile.AssignWithConversion(profileName); rv = profileService->SetCurrentProfile(newProfile.get()); } EndDialog(hDlg, IDOK); } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); } return TRUE; } return FALSE; } //----------------------------------------------------------------------------- // AppCallbacks //----------------------------------------------------------------------------- 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; } PRBool wasHandled = PR_FALSE; ::NS_HandleEmbeddingEvent(msg, wasHandled); if (wasHandled) continue; ::TranslateMessage(&msg); ::DispatchMessage(&msg); } // Do idle stuff ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 100, QS_ALLEVENTS); } ::CloseHandle(hFakeEvent); return msg.wParam; } /////////////////////////////////////////////////////////////////////////////// // nsQABrowserUIGlue /////////////////////////////////////////////////////////////////////////////// nsQABrowserUIGlue::nsQABrowserUIGlue():mAllowNewWindows(PR_TRUE) { } nsQABrowserUIGlue::~nsQABrowserUIGlue() { } NS_IMPL_ISUPPORTS1(nsQABrowserUIGlue, nsIQABrowserUIGlue) //////////////////////////////////////////////////////////////////////////////// // nsIQABrowserUIGlue //////////////////////////////////////////////////////////////////////////////// NS_IMETHODIMP nsQABrowserUIGlue::CreateNewBrowserWindow(PRInt32 aChromeFlags, nsIWebBrowserChrome *aParent, nsIWebBrowserChrome **aNewWindow) { printf("In nsQABrowserUIGlue::CreateNewBrowserWindow\n"); nsresult rv; // Create the chrome object. This implements all the interfaces // that an embedding application must implement. nsCOMPtr chrome(do_CreateInstance(NS_QABROWSERCHROME_CONTRACTID, &rv)); if (!chrome) return NS_ERROR_FAILURE; nsCOMPtr webBrowserChrome(do_QueryInterface(chrome)); if (!webBrowserChrome) return NS_ERROR_FAILURE; // now an extra addref; the window owns itself (to be released by // nsQABrowserUIGlue::Destroy) *aNewWindow = webBrowserChrome.get(); NS_ADDREF(*aNewWindow); // Set the chrome flags on the chrome. This may not be necessary. webBrowserChrome->SetChromeFlags(aChromeFlags); // chrome->SetParent(aParent); // Create the browser view object. nsIBrowserView creates and holds // handle to the nsIWebBrowser object. mBrowserView = do_CreateInstance(NS_QABROWSERVIEW_CONTRACTID, &rv); if (!mBrowserView) return NS_ERROR_FAILURE; // Create the native window. nativeWindow nativeWnd; nativeWnd = CreateNativeWindow(*aNewWindow); // Wire all the layers together. chrome->InitQAChrome(this, nativeWnd); // Create the actual browser. mBrowserView->CreateBrowser(nativeWnd, webBrowserChrome); // Place it where we want it. ResizeEmbedding(webBrowserChrome); // 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)) ShowWindow(*aNewWindow, PR_TRUE); return NS_OK; } // // FUNCTION: Destroy() // // PURPOSE: Destroy the window specified by the chrome // NS_IMETHODIMP nsQABrowserUIGlue::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); // Explicitly destroy the embedded browser and then the chrome // First the browser nsCOMPtr browserAsWin = do_QueryInterface(webBrowser); if (browserAsWin) browserAsWin->Destroy(); // Now the chrome chrome->SetWebBrowser(nsnull); NS_RELEASE(chrome); return NS_OK; } // // FUNCTION: Called as the final act of a chrome object during its destructor // NS_IMETHODIMP nsQABrowserUIGlue::Destroyed(nsIWebBrowserChrome* chrome) { HWND hwndDlg = GetBrowserDlgFromChrome(chrome); if (hwndDlg == NULL) { return NS_ERROR_FAILURE; } // Clear the window user data HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); SetWindowLong(hwndBrowser, GWL_USERDATA, nsnull); DestroyWindow(hwndBrowser); DestroyWindow(hwndDlg); --gDialogCount; if (gDialogCount == 0) { if (gProfileSwitch) { gProfileSwitch = FALSE; OpenWebPage(gFirstURL); } else { // Quit when there are no more browser objects PostQuitMessage(0); } } return NS_OK; } // // FUNCTION: Set the input focus onto the browser window // NS_IMETHODIMP nsQABrowserUIGlue::SetFocus(nsIWebBrowserChrome *chrome) { HWND hwndDlg = GetBrowserDlgFromChrome(chrome); if (hwndDlg == NULL) { return NS_ERROR_FAILURE; } HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); ::SetFocus(hwndBrowser); return NS_OK; } // // FUNCTION: UpdateStatusBarText() // // PURPOSE: Set the status bar text. // NS_IMETHODIMP nsQABrowserUIGlue::UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const PRUnichar* aStatusText) { HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); nsCString status; if (aStatusText) status.AssignWithConversion(aStatusText); SetDlgItemText(hwndDlg, IDC_STATUS, status.get()); return NS_OK; } // // FUNCTION: UpdateCurrentURI() // // PURPOSE: Updates the URL address field // NS_IMETHODIMP nsQABrowserUIGlue::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) { nsCAutoString uriString; currentURI->GetAsciiSpec(uriString); HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); SetDlgItemText(hwndDlg, IDC_ADDRESS, uriString.get()); } return NS_OK; } // // FUNCTION: UpdateBusyState() // // PURPOSE: Refreshes the stop/go buttons in the browser dialog // NS_IMETHODIMP nsQABrowserUIGlue::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); return NS_OK; } // // FUNCTION: UpdateProgress() // // PURPOSE: Refreshes the progress bar in the browser dialog // NS_IMETHODIMP nsQABrowserUIGlue::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); } return NS_OK; } // // FUNCTION: ShowContextMenu() // // PURPOSE: Display a context menu for the given node // NS_IMETHODIMP nsQABrowserUIGlue::ShowContextMenu(nsIWebBrowserChrome *aChrome, PRInt32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) { // TODO code to test context flags and display a popup menu should go here return NS_OK; } // // FUNCTION: ShowTooltip() // // PURPOSE: Show a tooltip // NS_IMETHODIMP nsQABrowserUIGlue::ShowTooltip(nsIWebBrowserChrome *aChrome, PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText) { // TODO code to show a tooltip should go here return NS_OK; } // // FUNCTION: HideTooltip() // // PURPOSE: Hide the tooltip // NS_IMETHODIMP nsQABrowserUIGlue::HideTooltip(nsIWebBrowserChrome *aChrome) { // TODO code to hide a tooltip should go here return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::ShowWindow(nsIWebBrowserChrome *aChrome, PRBool aShow) { HWND win = GetBrowserDlgFromChrome(aChrome); return ::ShowWindow(win, aShow ? SW_RESTORE : SW_HIDE); } NS_IMETHODIMP nsQABrowserUIGlue::SizeTo(nsIWebBrowserChrome *aChrome, PRInt32 aWidth, PRInt32 aHeight) { HWND win = GetBrowserDlgFromChrome(aChrome); RECT winRect; ::GetWindowRect(win, &winRect); return ::MoveWindow(win, winRect.left, winRect.top, aWidth, aHeight, TRUE); } // // FUNCTION: GetResourceStringByID() // // PURPOSE: Get the resource string for the ID // NS_IMETHODIMP nsQABrowserUIGlue::GetResourceStringById(PRInt32 aID, char ** aReturn) { char resBuf[MAX_LOADSTRING]; int retval = LoadString( ghInstanceResources, aID, (LPTSTR)resBuf, sizeof(resBuf) ); if (retval != 0) { int resLen = strlen(resBuf); *aReturn = (char *)calloc(resLen+1, sizeof(char *)); if (!*aReturn) return NS_OK; PL_strncpy(*aReturn, (char *) resBuf, resLen); } return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::SetTitle(const PRUnichar * aTitle) { return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::GetTitle(PRUnichar ** aTitle) { return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::SetVisibility(PRBool aVisibility) { return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::GetVisibility(PRBool * aVisibility) { *aVisibility = PR_TRUE; return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::SetAllowNewBrowserWindows(PRBool aValue) { mAllowNewWindows = aValue; return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::GetAllowNewBrowserWindows(PRBool * aReturn) { if (aReturn) *aReturn = mAllowNewWindows; return NS_OK; } NS_IMETHODIMP nsQABrowserUIGlue::LoadHomePage() { NS_NAMED_LITERAL_CSTRING (url, "http://www.mozilla.org/embedding"); return LoadURL(url.get()); } NS_IMETHODIMP nsQABrowserUIGlue::LoadURL(const char * aURL) { nsresult rv = NS_OK; // Start loading a page nsCOMPtr newBrowser; mBrowserView->GetWebBrowser(getter_AddRefs(newBrowser)); nsCOMPtr webNav(do_QueryInterface(newBrowser, &rv)); if (webNav) return webNav->LoadURI(NS_ConvertASCIItoUTF16(aURL).get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull); return rv; } // // 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. // nativeWindow nsQABrowserUIGlue::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(ghInstanceResources, MAKEINTRESOURCE(IDD_BROWSER), NULL, BrowserDlgProc); else hwndDialog = CreateDialog(ghInstanceResources, MAKEINTRESOURCE(IDD_BROWSER_NC), NULL, BrowserDlgProc); if (!hwndDialog) return (void *) nsnull; // Stick a menu onto it if (chromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR) { HMENU hmenuDlg = LoadMenu(ghInstanceResources, MAKEINTRESOURCE(IDC_MOZEMBED)); 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 (void *) hwndBrowser; }