/* -*- 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): * Chak Nanga * Conrad Carlen * * ***** END LICENSE BLOCK ***** */ // File Overview.... // // The typical MFC app, frame creation code + AboutDlg handling // // NS_InitEmbedding() is called in InitInstance() // // NS_TermEmbedding() is called in ExitInstance() // ExitInstance() also takes care of cleaning up of // multiple browser frame windows on app exit // // Code to handle the creation of a new browser window // Next suggested file to look at : BrowserFrm.cpp // Local Includes #include "stdafx.h" #include "MfcEmbed.h" #include "nsXPCOM.h" #include "nsXPCOMGlue.h" #include "nsMemory.h" #include "nsIComponentRegistrar.h" #include "nsIFactory.h" #include "nsServiceManagerUtils.h" #include "BrowserFrm.h" #include "EditorFrm.h" #include "winEmbedFileLocProvider.h" #include "BrowserImpl.h" #include "nsIWindowWatcher.h" #include "plstr.h" #include "Preferences.h" #include #include #ifdef USE_PROFILES #include "ProfileMgr.h" #else #include "nsProfileDirServiceProvider.h" #endif #ifdef MOZ_PROFILESHARING #include "nsIProfileSharingSetup.h" #endif #ifdef _BUILD_STATIC_BIN #include "nsStaticComponent.h" nsresult PR_CALLBACK app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count); #endif #ifdef NS_TRACE_MALLOC #include "nsTraceMalloc.h" #endif #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // this is for overriding the Mozilla default PromptService component #include "PromptService.h" #define kComponentsLibname _T("mfcEmbedComponents.dll") #define NS_PROMPTSERVICE_CID \ {0xa2112d6a, 0x0e28, 0x421f, {0xb4, 0x6a, 0x25, 0xc0, 0xb3, 0x8, 0xcb, 0xd0}} static NS_DEFINE_CID(kPromptServiceCID, NS_PROMPTSERVICE_CID); // this is for overriding the Mozilla default PrintingPromptService component #include "PrintingPromptService.h" #define NS_PRINTINGPROMPTSERVICE_CID \ {0xe042570c, 0x62de, 0x4bb6, { 0xa6, 0xe0, 0x79, 0x8e, 0x3c, 0x7, 0xb4, 0xdf}} static NS_DEFINE_CID(kPrintingPromptServiceCID, NS_PRINTINGPROMPTSERVICE_CID); // this is for overriding the Mozilla default HelperAppLauncherDialog #include "HelperAppService.h" #define NS_HELPERAPPLAUNCHERDIALOG_CID \ {0xf68578eb, 0x6ec2, 0x4169, {0xae, 0x19, 0x8c, 0x62, 0x43, 0xf0, 0xab, 0xe1}} static NS_DEFINE_CID(kHelperAppLauncherDialogCID, NS_HELPERAPPLAUNCHERDIALOG_CID); class CMfcEmbedCommandLine : public CCommandLineInfo { public: CMfcEmbedCommandLine(CMfcEmbedApp& app) : CCommandLineInfo(), mApp(app) { } // generic parser which bundles up flags and their parameters, to // pass to HandleFlag() or HandleNakedParameter() // if you're adding new parameters, please don't touch this // function and instead add your own handler below virtual void ParseParam(LPCTSTR szParam, BOOL bFlag, BOOL bLast) { CCommandLineInfo::ParseParam(szParam, bFlag, bLast); if (bFlag) { // advance past extra stuff like --foo while (*szParam && *szParam == '-') szParam++; // previous argument was a flag too, so process that first if (mLastFlag.Length() != 0) HandleFlag(mLastFlag); mLastFlag = szParam; // oops, no more arguments coming, so handle this now if (bLast) HandleFlag(mLastFlag); } else { if (mLastFlag.Length() != 0) HandleFlag(mLastFlag, szParam); mLastFlag.Cut(0, PR_UINT32_MAX); } } // handle flag-based parameters #ifdef _UNICODE void HandleFlag(const nsAString& flag, const TCHAR * param = nsnull) #else void HandleFlag(const nsACString& flag, const TCHAR * param = nsnull) #endif { if (_tcscmp(flag.BeginReading(), _T("console")) == 0) DoConsole(); else if (_tcscmp(flag.BeginReading(), _T("chrome")) == 0) DoChrome(); #ifdef NS_TRACE_MALLOC else if (_tcscmp(flag.BeginReading(), _T("trace-malloc")) == 0) { USES_CONVERSION; DoTraceMalloc(flag, T2CA(param)); } #endif // add new flag handlers here (please add a DoFoo() method below!) } void HandleNakedParameter(const char* flag) { // handle non-flag arguments here } // add your specific handlers here void DoConsole() { mApp.ShowDebugConsole(); } void DoChrome() { mApp.m_bChrome = TRUE; } #ifdef NS_TRACE_MALLOC void DoTraceMalloc(const nsACString& flag, const char* param) { if (!param) { NS_WARNING("--trace-malloc needs a filename as a parameter"); return; } // build up fake argv/argc arguments for tracemalloc stuff char* argv[] = { "mfcembed", "--trace-malloc", NS_CONST_CAST(char*, param) }; NS_TraceMallocStartupArgs(3, argv); } #endif private: // autostring is fine, this is a stack based object anyway #ifdef _UNICODE nsEmbedString mLastFlag; #else nsEmbedCString mLastFlag; #endif CMfcEmbedApp& mApp; }; BEGIN_MESSAGE_MAP(CMfcEmbedApp, CWinApp) //{{AFX_MSG_MAP(CMfcEmbedApp) ON_COMMAND(ID_NEW_BROWSER, OnNewBrowser) ON_COMMAND(ID_NEW_EDITORWINDOW, OnNewEditor) #ifdef USE_PROFILES ON_COMMAND(ID_MANAGE_PROFILES, OnManageProfiles) #endif ON_COMMAND(ID_APP_ABOUT, OnAppAbout) ON_COMMAND(ID_EDIT_PREFERENCES, OnEditPreferences) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() CMfcEmbedApp::CMfcEmbedApp() { mRefCnt = 1; // Start at one - nothing is going to addref this object #ifdef USE_PROFILES m_ProfileMgr = NULL; #endif m_strHomePage = ""; m_iStartupPage = 0; m_bChrome = FALSE; } CMfcEmbedApp theApp; /* Some Gecko interfaces are implemented as components, automatically registered at application initialization. nsIPrompt is an example: the default implementation uses XUL, not native windows. Embedding apps can override the default implementation by implementing the nsIPromptService interface and registering a factory for it with the same CID and Contract ID as the default's. Note that this example implements the service in a separate DLL, replacing the default if the override DLL is present. This could also have been done in the same module, without a separate DLL. See the PowerPlant example for, well, an example. */ nsresult CMfcEmbedApp::OverrideComponents() { nsCOMPtr compReg; nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(compReg)); NS_ENSURE_SUCCESS(rv, rv); // replace Mozilla's default PromptService with our own, if the // expected override DLL is present HMODULE overlib = ::LoadLibrary(kComponentsLibname); if (overlib) { InitPromptServiceType InitLib; MakeFactoryType MakeFactory; InitLib = reinterpret_cast(::GetProcAddress(overlib, kPromptServiceInitFuncName)); MakeFactory = reinterpret_cast(::GetProcAddress(overlib, kPromptServiceFactoryFuncName)); if (InitLib && MakeFactory) { InitLib(overlib); nsCOMPtr promptFactory; rv = MakeFactory(getter_AddRefs(promptFactory)); if (NS_SUCCEEDED(rv)) { compReg->RegisterFactory(kPromptServiceCID, "Prompt Service", "@mozilla.org/embedcomp/prompt-service;1", promptFactory); } } else ::FreeLibrary(overlib); } // Replace Mozilla's helper app launcher dialog with our own overlib = ::LoadLibrary(kComponentsLibname); if (overlib) { InitHelperAppDlgType InitLib; MakeFactoryType MakeFactory; InitLib = reinterpret_cast(::GetProcAddress(overlib, kHelperAppDlgInitFuncName)); MakeFactory = reinterpret_cast(::GetProcAddress(overlib, kHelperAppDlgFactoryFuncName)); if (InitLib && MakeFactory) { InitLib(overlib); nsCOMPtr helperAppDlgFactory; rv = MakeFactory(getter_AddRefs(helperAppDlgFactory)); if (NS_SUCCEEDED(rv)) compReg->RegisterFactory(kHelperAppLauncherDialogCID, "Helper App Launcher Dialog", "@mozilla.org/helperapplauncherdialog;1", helperAppDlgFactory); } else ::FreeLibrary(overlib); } // replace Mozilla's default PrintingPromptService with our own, if the // expected override DLL is present overlib = ::LoadLibrary(kComponentsLibname); if (overlib) { InitPrintingPromptServiceType InitLib; MakeFactoryType MakeFactory; InitLib = reinterpret_cast(::GetProcAddress(overlib, kPrintingPromptServiceInitFuncName)); MakeFactory = reinterpret_cast(::GetProcAddress(overlib, kPrintingPromptServiceFactoryFuncName)); if (InitLib && MakeFactory) { InitLib(overlib); nsCOMPtr printingPromptFactory; rv = MakeFactory(getter_AddRefs(printingPromptFactory)); if (NS_SUCCEEDED(rv)) compReg->RegisterFactory(kPrintingPromptServiceCID, "Printing Prompt Service", "@mozilla.org/embedcomp/printingprompt-service;1", printingPromptFactory); } else ::FreeLibrary(overlib); } return rv; } void CMfcEmbedApp::ShowDebugConsole() { #ifdef _DEBUG // Show console only in debug mode if(! AllocConsole()) return; // Redirect stdout to the console int hCrtOut = _open_osfhandle( (long) GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT); if(hCrtOut == -1) return; FILE *hfOut = _fdopen(hCrtOut, "w"); if(hfOut != NULL) { // Setup for unbuffered I/O so the console // output shows up right away *stdout = *hfOut; setvbuf(stdout, NULL, _IONBF, 0); } // Redirect stderr to the console int hCrtErr = _open_osfhandle( (long) GetStdHandle(STD_ERROR_HANDLE), _O_TEXT); if(hCrtErr == -1) return; FILE *hfErr = _fdopen(hCrtErr, "w"); if(hfErr != NULL) { // Setup for unbuffered I/O so the console // output shows up right away *stderr = *hfErr; setvbuf(stderr, NULL, _IONBF, 0); } #endif } // Initialize our MFC application and also init // the Gecko embedding APIs // Note that we're also init'ng the profile switching // code here // Then, create a new BrowserFrame and load our // default homepage // BOOL CMfcEmbedApp::InitInstance() { #ifdef _BUILD_STATIC_BIN // Initialize XPCOM's module info table NSGetStaticModuleInfo = app_getModuleInfo; #endif #ifdef XPCOM_GLUE if (NS_FAILED(XPCOMGlueStartup(GRE_GetXPCOMPath()))) { MessageBox(NULL, "Could not initialize XPCOM. Perhaps the GRE\nis not installed or could not be found?", "MFCEmbed", MB_OK | MB_ICONERROR); return FALSE; } #endif CMfcEmbedCommandLine cmdLine(*this); ParseCommandLine(cmdLine); Enable3dControls(); // // 1. Determine the name of the dir from which the GRE based app is being run // from [It's OK to do this even if you're not running in an GRE env] // // 2. Create an nsILocalFile out of it which will passed in to NS_InitEmbedding() // // Please see http://www.mozilla.org/projects/embedding/GRE.html // for more info. on GRE TCHAR path[_MAX_PATH+1]; ::GetModuleFileName(0, path, _MAX_PATH); TCHAR* lastSlash = _tcsrchr(path, _T('\\')); if (!lastSlash) { NS_ERROR("No slash in module file name... something is wrong."); return FALSE; } *lastSlash = _T('\0'); USES_CONVERSION; nsresult rv; nsCOMPtr mreAppDir; rv = NS_NewNativeLocalFile(nsEmbedCString(T2A(path)), TRUE, getter_AddRefs(mreAppDir)); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create mreAppDir localfile"); // Take a look at // http://www.mozilla.org/projects/xpcom/file_locations.html // for more info on File Locations CString strRes; strRes.LoadString(IDS_PROFILES_FOLDER_NAME); winEmbedFileLocProvider *provider = new winEmbedFileLocProvider(nsEmbedCString(strRes)); if(!provider) { ASSERT(FALSE); return FALSE; } rv = NS_InitEmbedding(mreAppDir, provider); if(NS_FAILED(rv)) { ASSERT(FALSE); return FALSE; } rv = OverrideComponents(); if(NS_FAILED(rv)) { ASSERT(FALSE); return FALSE; } rv = InitializeWindowCreator(); if (NS_FAILED(rv)) { ASSERT(FALSE); return FALSE; } if(!InitializeProfiles()) { ASSERT(FALSE); NS_TermEmbedding(); return FALSE; } if(!CreateHiddenWindow()) { ASSERT(FALSE); NS_TermEmbedding(); return FALSE; } // Create the first browser frame window OnNewBrowser(); return TRUE; } CBrowserFrame* CMfcEmbedApp::CreateNewBrowserFrame(PRUint32 chromeMask, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy, PRBool bShowWindow, PRBool bIsEditor ) { UINT resId = bIsEditor ? IDR_EDITOR : IDR_MAINFRAME; // Setup a CRect with the requested window dimensions CRect winSize(x, y, cx, cy); // Use the Windows default if all are specified as -1 if(x == -1 && y == -1 && cx == -1 && cy == -1) winSize = CFrameWnd::rectDefault; // Load the window title from the string resource table CString strTitle; strTitle.LoadString(IDR_MAINFRAME); // Now, create the browser frame CBrowserFrame* pFrame = bIsEditor ? ( new CEditorFrame(chromeMask) ) : ( new CBrowserFrame(chromeMask) ); pFrame->SetEditable(bIsEditor); if (!pFrame->Create(NULL, strTitle, WS_OVERLAPPEDWINDOW, winSize, NULL, MAKEINTRESOURCE(resId), 0L, NULL)) { return NULL; } // load accelerator resource pFrame->LoadAccelTable(MAKEINTRESOURCE(IDR_MAINFRAME)); // Show the window... if(bShowWindow) { pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); } // Add to the list of BrowserFrame windows m_FrameWndLst.AddHead(pFrame); return pFrame; } void CMfcEmbedApp::OnNewBrowser() { CBrowserFrame *pBrowserFrame = CreateNewBrowserFrame(); //Load the HomePage into the browser view if(pBrowserFrame && (GetStartupPageMode() == 1)) pBrowserFrame->m_wndBrowserView.LoadHomePage(); } void CMfcEmbedApp::OnNewEditor() { CEditorFrame *pEditorFrame = (CEditorFrame *)CreateNewBrowserFrame(nsIWebBrowserChrome::CHROME_ALL, -1, -1, -1, -1, PR_TRUE,PR_TRUE); if (pEditorFrame) { pEditorFrame->InitEditor(); pEditorFrame->m_wndBrowserView.OpenURL("about:blank"); } } // This gets called anytime a BrowserFrameWindow is // closed i.e. by choosing the "close" menu item from // a window's system menu or by dbl clicking on the // system menu box // // Sends a WM_QUIT to the hidden window which results // in ExitInstance() being called and the app is // properly cleaned up and shutdown // void CMfcEmbedApp::RemoveFrameFromList(CBrowserFrame* pFrm, BOOL bCloseAppOnLastFrame/*= TRUE*/) { POSITION pos = m_FrameWndLst.Find(pFrm); m_FrameWndLst.RemoveAt(pos); // Send a WM_QUIT msg. to the hidden window if we've // just closed the last browserframe window and // if the bCloseAppOnLastFrame is TRUE. This be FALSE // only in the case we're switching profiles // Without this the hidden window will stick around // i.e. the app will never die even after all the // visible windows are gone. if(m_FrameWndLst.GetCount() == 0 && bCloseAppOnLastFrame) m_pMainWnd->PostMessage(WM_QUIT); } int CMfcEmbedApp::ExitInstance() { // When File/Exit is chosen and if the user // has opened multiple browser windows shut all // of them down properly before exiting the app CBrowserFrame* pBrowserFrame = NULL; POSITION pos = m_FrameWndLst.GetHeadPosition(); while( pos != NULL ) { pBrowserFrame = (CBrowserFrame *) m_FrameWndLst.GetNext(pos); if(pBrowserFrame) { pBrowserFrame->ShowWindow(false); pBrowserFrame->DestroyWindow(); } } m_FrameWndLst.RemoveAll(); if (m_pMainWnd) m_pMainWnd->DestroyWindow(); #ifdef USE_PROFILES delete m_ProfileMgr; #else if (m_ProfileDirServiceProvider) { m_ProfileDirServiceProvider->Shutdown(); NS_RELEASE(m_ProfileDirServiceProvider); } #endif NS_TermEmbedding(); #ifdef XPCOM_GLUE XPCOMGlueShutdown(); #endif return 1; } BOOL CMfcEmbedApp::OnIdle(LONG lCount) { CWinApp::OnIdle(lCount); return FALSE; } void CMfcEmbedApp::OnManageProfiles() { #ifdef USE_PROFILES m_ProfileMgr->DoManageProfilesDialog(PR_FALSE); #endif } void CMfcEmbedApp::OnEditPreferences() { CPreferences prefs(_T("Preferences")); prefs.m_startupPage.m_iStartupPage = m_iStartupPage; prefs.m_startupPage.m_strHomePage = m_strHomePage; if(prefs.DoModal() == IDOK) { // Update our member vars with these new pref values m_iStartupPage = prefs.m_startupPage.m_iStartupPage; m_strHomePage = prefs.m_startupPage.m_strHomePage; // Save these changes to disk now nsresult rv; nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID, &rv)); if (NS_SUCCEEDED(rv)) { USES_CONVERSION; prefs->SetIntPref("browser.startup.page", m_iStartupPage); rv = prefs->SetCharPref("browser.startup.homepage", T2CA(m_strHomePage)); if (NS_SUCCEEDED(rv)) rv = prefs->SavePrefFile(nsnull); } else NS_ASSERTION(PR_FALSE, "Could not get preferences service"); } } BOOL CMfcEmbedApp::InitializeProfiles() { #ifdef MOZ_PROFILESHARING // If we are using profile sharing, get the sharing setup service nsCOMPtr sharingSetup = do_GetService("@mozilla.org/embedcomp/profile-sharing-setup;1"); if (sharingSetup) { USES_CONVERSION; CString strRes; strRes.LoadString(IDS_PROFILES_NONSHARED_NAME); nsEmbedString nonSharedName(T2W(strRes)); sharingSetup->EnableSharing(nonSharedName); } #endif nsCOMPtr observerService = do_GetService("@mozilla.org/observer-service;1"); if (!observerService) return FALSE; // Both the profile mgr and standalone nsProfileDirServiceProvider // send this notification. observerService->AddObserver(this, "profile-after-change", PR_TRUE); #ifdef USE_PROFILES m_ProfileMgr = new CProfileMgr; if (!m_ProfileMgr) return FALSE; observerService->AddObserver(this, "profile-approve-change", PR_TRUE); observerService->AddObserver(this, "profile-change-teardown", PR_TRUE); m_ProfileMgr->StartUp(); #else nsresult rv; nsCOMPtr appDataDir; NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(appDataDir)); if (!appDataDir) return FALSE; nsCOMPtr profProvider; NS_NewProfileDirServiceProvider(PR_TRUE, getter_AddRefs(profProvider)); if (!profProvider) return FALSE; profProvider->Register(); nsCOMPtr localAppDataDir(do_QueryInterface(appDataDir)); rv = profProvider->SetProfileDir(localAppDataDir); if (NS_FAILED(rv)) return FALSE; NS_ADDREF(m_ProfileDirServiceProvider = profProvider); #endif return TRUE; } // When the profile switch happens, all open browser windows need to be // closed. // In order for that not to kill off the app, we just make the MFC app's // mainframe be an invisible window which doesn't get closed on profile // switches BOOL CMfcEmbedApp::CreateHiddenWindow() { CFrameWnd *hiddenWnd = new CFrameWnd; if(!hiddenWnd) return FALSE; RECT bounds = { -10010, -10010, -10000, -10000 }; hiddenWnd->Create(NULL, _T("main"), WS_DISABLED, bounds, NULL, NULL, 0, NULL); m_pMainWnd = hiddenWnd; return TRUE; } nsresult CMfcEmbedApp::InitializePrefs() { nsresult rv; nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID, &rv)); if (NS_SUCCEEDED(rv)) { // We are using the default prefs from mozilla. If you were // disributing your own, this would be done simply by editing // the default pref files. PRBool inited; rv = prefs->GetBoolPref("mfcbrowser.prefs_inited", &inited); if (NS_FAILED(rv) || !inited) { USES_CONVERSION; m_iStartupPage = 1; m_strHomePage = "http://www.mozilla.org/projects/embedding"; prefs->SetIntPref("browser.startup.page", m_iStartupPage); prefs->SetCharPref("browser.startup.homepage", T2CA(m_strHomePage)); prefs->SetIntPref("font.size.variable.x-western", 16); prefs->SetIntPref("font.size.fixed.x-western", 13); rv = prefs->SetBoolPref("mfcbrowser.prefs_inited", PR_TRUE); if (NS_SUCCEEDED(rv)) rv = prefs->SavePrefFile(nsnull); } else { // The prefs are present, read them in prefs->GetIntPref("browser.startup.page", &m_iStartupPage); char* str = nsnull; prefs->GetCharPref("browser.startup.homepage", &str); if (str) { USES_CONVERSION; m_strHomePage = A2CT(str); } else { m_strHomePage.Empty(); } nsMemory::Free(str); } } else NS_ASSERTION(PR_FALSE, "Could not get preferences service"); return rv; } /* InitializeWindowCreator creates and hands off an object with a callback to a window creation function. This will be used by Gecko C++ code (never JS) to create new windows when no previous window is handy to begin with. This is done in a few exceptional cases, like PSM code. Failure to set this callback will only disable the ability to create new windows under these circumstances. */ nsresult CMfcEmbedApp::InitializeWindowCreator() { // give an nsIWindowCreator to the WindowWatcher service nsCOMPtr windowCreator(NS_STATIC_CAST(nsIWindowCreator *, this)); if (windowCreator) { nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); if (wwatch) { wwatch->SetWindowCreator(windowCreator); return NS_OK; } } return NS_ERROR_FAILURE; } // --------------------------------------------------------------------------- // CMfcEmbedApp : nsISupports // --------------------------------------------------------------------------- NS_IMPL_ISUPPORTS3(CMfcEmbedApp, nsIObserver, nsIWindowCreator, nsISupportsWeakReference) // --------------------------------------------------------------------------- // CMfcEmbedApp : nsIObserver // --------------------------------------------------------------------------- // Mainly needed to support "on the fly" profile switching NS_IMETHODIMP CMfcEmbedApp::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData) { nsresult rv = NS_OK; if (strcmp(aTopic, "profile-approve-change") == 0) { // Ask the user if they want to int result = MessageBox(NULL, _T("Do you want to close all windows in order to switch the profile?"), _T("Confirm"), MB_YESNO | MB_ICONQUESTION); if (result != IDYES) { nsCOMPtr status = do_QueryInterface(aSubject); NS_ENSURE_TRUE(status, NS_ERROR_FAILURE); status->VetoChange(); } } else if (strcmp(aTopic, "profile-change-teardown") == 0) { // Close all open windows. Alternatively, we could just call CBrowserWindow::Stop() // on each. Either way, we have to stop all network activity on this phase. POSITION pos = m_FrameWndLst.GetHeadPosition(); while( pos != NULL ) { CBrowserFrame *pBrowserFrame = (CBrowserFrame *) m_FrameWndLst.GetNext(pos); if(pBrowserFrame) { pBrowserFrame->ShowWindow(false); // Passing in FALSE below so that we do not // kill the main app during a profile switch RemoveFrameFromList(pBrowserFrame, FALSE); pBrowserFrame->DestroyWindow(); } } } else if (strcmp(aTopic, "profile-after-change") == 0) { InitializePrefs(); // In case we have just switched to a newly created profile. // Only make a new browser window on a switch. This also gets // called at start up and we already make a window then. if (!wcscmp(someData, L"switch")) OnNewBrowser(); } return rv; } // --------------------------------------------------------------------------- // CMfcEmbedApp : nsIWindowCreator // --------------------------------------------------------------------------- NS_IMETHODIMP CMfcEmbedApp::CreateChromeWindow(nsIWebBrowserChrome *parent, PRUint32 chromeFlags, nsIWebBrowserChrome **_retval) { // XXX we're ignoring the "parent" parameter NS_ENSURE_ARG_POINTER(_retval); *_retval = 0; CBrowserFrame *pBrowserFrame = CreateNewBrowserFrame(chromeFlags); if(pBrowserFrame) { *_retval = NS_STATIC_CAST(nsIWebBrowserChrome *, pBrowserFrame->GetBrowserImpl()); NS_ADDREF(*_retval); } return NS_OK; } // AboutDlg Stuff class CAboutDlg : public CDialog { public: CAboutDlg(); enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // Show the AboutDlg void CMfcEmbedApp::OnAppAbout() { CAboutDlg aboutDlg; aboutDlg.DoModal(); }