 |
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * The contents of this file are subject to the Netscape Public
4 * License Version 1.1 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of
6 * the License at http://www.mozilla.org/NPL/
7 *
8 * Software distributed under the License is distributed on an "AS
9 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10 * implied. See the License for the specific language governing
11 * rights and limitations under the License.
12 *
13 * The Original Code is mozilla.org code.
14 *
15 * The Initial Developer of the Original Code is Netscape
16 * Communications Corporation. Portions created by Netscape are
17 * Copyright (C) 1998 Netscape Communications Corporation. All
18 * Rights Reserved.
19 *
20 * Contributor(s):
21 * Chak Nanga <[EMAIL PROTECTED]>
22 * Conrad Carlen <[EMAIL PROTECTED]>
23 */
24
25 // File Overview....
26 //
27 // The typical MFC app, frame creation code + AboutDlg handling
28 //
29 // NS_InitEmbedding() is called in InitInstance()
30 //
31 // NS_TermEmbedding() is called in ExitInstance()
32 // ExitInstance() also takes care of cleaning up of
33 // multiple browser frame windows on app exit
34 //
35 // NS_DoIdleEmbeddingStuff(); is called in the overridden
36 // OnIdle() method
37 //
38 // Code to handle the creation of a new browser window
39
40 // Next suggested file to look at : BrowserFrm.cpp
41
42 // Local Includes
43 #include "stdafx.h"
44 #include "MfcEmbed.h"
45 #include "BrowserFrm.h"
46 #include "winEmbedFileLocProvider.h"
47 #include "ProfileMgr.h"
48
49 #ifdef _DEBUG
50 #define new DEBUG_NEW
51 #undef THIS_FILE
52 static char THIS_FILE[] = __FILE__;
53 #endif
54
55 BEGIN_MESSAGE_MAP(CMfcEmbedApp, CWinApp)
56 //{{AFX_MSG_MAP(CMfcEmbedApp)
57 ON_COMMAND(ID_NEW_BROWSER, OnNewBrowser)
58 ON_COMMAND(ID_MANAGE_PROFILES, OnManageProfiles)
59 ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
60 // NOTE - the ClassWizard will add and remove mapping macros here.
61 // DO NOT EDIT what you see in these blocks of generated code!
62 //}}AFX_MSG_MAP
63 END_MESSAGE_MAP()
64
65 CMfcEmbedApp::CMfcEmbedApp() :
66 m_ProfileMgr(NULL)
67 {
68 mRefCnt = 1; // Start at one - nothing is going to addref this object
69 }
70
71 CMfcEmbedApp theApp;
72
73 // Initialize our MFC application and also init
74 // the Gecko embedding APIs
75 // Note that we're also init'ng the profile switching
76 // code here
77 // Then, create a new BrowserFrame and load our
78 // default homepage
79 //
80 BOOL CMfcEmbedApp::InitInstance()
81 {
82 Enable3dControls();
83
84 // Take a look at
85 // http://www.mozilla.org/projects/xpcom/file_locations.html
86 // for more info on File Locations
87
88 winEmbedFileLocProvider *provider = new winEmbedFileLocProvider("MfcEmbed");
89 if(!provider)
90 {
91 ASSERT(FALSE);
92 return FALSE;
93 }
94
95 nsresult rv;
96 rv = NS_InitEmbedding(nsnull, provider);
97 if(NS_FAILED(rv))
98 {
99 ASSERT(FALSE);
100 return FALSE;
101 }
102
103 if(!InitializeProfiles())
104 {
105 ASSERT(FALSE);
106 NS_TermEmbedding();
107 return FALSE;
108 }
109
110 InitializePrefs();
111
112 if(!CreateHiddenWindow())
113 {
114 ASSERT(FALSE);
115 NS_TermEmbedding();
116 return FALSE;
117 }
118
119 // Create the first browser frame window
120 OnNewBrowser();
121
122 return TRUE;
123 }
124
125 CBrowserFrame* CMfcEmbedApp::CreateNewBrowserFrame(PRUint32 chromeMask,
126 PRInt32 x, PRInt32 y,
127 PRInt32 cx, PRInt32 cy,
128 PRBool bShowWindow)
129 {
130 // Setup a CRect with the requested window dimensions
131 CRect winSize(x, y, cx, cy);
132
133 // Use the Windows default if all are specified as -1
134 if(x == -1 && y == -1 && cx == -1 && cy == -1)
135 winSize = CFrameWnd::rectDefault;
136
137 // Load the window title from the string resource table
138 CString strTitle;
139 strTitle.LoadString(IDR_MAINFRAME);
140
141 // Now, create the browser frame
142 CBrowserFrame* pFrame = new CBrowserFrame(chromeMask);
143 if (!pFrame->Create(NULL, strTitle, WS_OVERLAPPEDWINDOW,
144 winSize, NULL, MAKEINTRESOURCE(IDR_MAINFRAME), 0L, NULL))
145 {
146 return NULL;
147 }
148
149 // load accelerator resource
150 pFrame->LoadAccelTable(MAKEINTRESOURCE(IDR_MAINFRAME));
151
152 // Show the window...
153 if(bShowWindow)
154 {
155 pFrame->ShowWindow(SW_SHOW);
156 pFrame->UpdateWindow();
157 }
158
159 // Add to the list of BrowserFrame windows
160 m_FrameWndLst.AddHead(pFrame);
161
162 return pFrame;
163 }
164
165 void CMfcEmbedApp::OnNewBrowser()
166 {
167 CBrowserFrame *pBrowserFrame = CreateNewBrowserFrame();
168
169 //Load the HomePage into the browser view
170 if(pBrowserFrame)
171 pBrowserFrame->m_wndBrowserView.LoadHomePage();
172 }
173
174 // This gets called anytime a BrowserFrameWindow is
175 // closed i.e. by choosing the "close" menu item from
176 // a window's system menu or by dbl clicking on the
177 // system menu box
178 //
179 // Sends a WM_QUIT to the hidden window which results
180 // in ExitInstance() being called and the app is
181 // properly cleaned up and shutdown
182 //
183 void CMfcEmbedApp::RemoveFrameFromList(CBrowserFrame* pFrm, BOOL bCloseAppOnLastFrame/*= TRUE*/)
184 {
185 POSITION pos = m_FrameWndLst.Find(pFrm);
186 m_FrameWndLst.RemoveAt(pos);
187
188 // Send a WM_QUIT msg. to the hidden window if we've
189 // just closed the last browserframe window and
190 // if the bCloseAppOnLastFrame is TRUE. This be FALSE
191 // only in the case we're switching profiles
192 // Without this the hidden window will stick around
193 // i.e. the app will never die even after all the
194 // visible windows are gone.
195 if(m_FrameWndLst.GetCount() == 0 && bCloseAppOnLastFrame)
196 m_pMainWnd->PostMessage(WM_QUIT);
197 }
198
199 int CMfcEmbedApp::ExitInstance()
200 {
201 // When File/Exit is chosen and if the user
202 // has opened multiple browser windows shut all
203 // of them down properly before exiting the app
204
205 CBrowserFrame* pBrowserFrame = NULL;
206
207 POSITION pos = m_FrameWndLst.GetHeadPosition();
208 while( pos != NULL )
209 {
210 pBrowserFrame = (CBrowserFrame *) m_FrameWndLst.GetNext(pos);
211 if(pBrowserFrame)
212 {
213 pBrowserFrame->ShowWindow(false);
214 pBrowserFrame->DestroyWindow();
215 }
216 }
217 m_FrameWndLst.RemoveAll();
218
219 if (m_pMainWnd)
220 m_pMainWnd->DestroyWindow();
221
222 delete m_ProfileMgr;
223
224 NS_TermEmbedding();
225
226 return 1;
227 }
228
229 BOOL CMfcEmbedApp::OnIdle(LONG lCount)
230 {
231 CWinApp::OnIdle(lCount);
232
233 NS_DoIdleEmbeddingStuff();
234
235 return FALSE;
236 }
237
238 void CMfcEmbedApp::OnManageProfiles()
239 {
240 m_ProfileMgr->DoManageProfilesDialog(PR_FALSE);
241 }
242
243 BOOL CMfcEmbedApp::InitializeProfiles()
244 {
245 m_ProfileMgr = new CProfileMgr;
246 if (!m_ProfileMgr)
247 return FALSE;
248
249 m_ProfileMgr->StartUp();
250
251 nsresult rv;
252 NS_WITH_SERVICE(nsIObserverService, observerService, NS_OBSERVERSERVICE_CONTRACTID, &rv);
253 observerService->AddObserver(this, PROFILE_APPROVE_CHANGE_TOPIC);
254 observerService->AddObserver(this, PROFILE_CHANGE_TEARDOWN_TOPIC);
255 observerService->AddObserver(this, PROFILE_AFTER_CHANGE_TOPIC);
256
257 return TRUE;
258 }
259
260 // When the profile switch happens, all open browser windows need to be
261 // closed.
262 // In order for that not to kill off the app, we just make the MFC app's
263 // mainframe be an invisible window which doesn't get closed on profile
264 // switches
265 BOOL CMfcEmbedApp::CreateHiddenWindow()
266 {
267 CFrameWnd *hiddenWnd = new CFrameWnd;
268 if(!hiddenWnd)
269 return FALSE;
270
271 RECT bounds = { -10010, -10010, -10000, -10000 };
272 hiddenWnd->Create(NULL, "main", WS_DISABLED, bounds, NULL, NULL, 0, NULL);
273 m_pMainWnd = hiddenWnd;
274
275 return TRUE;
276 }
277
278 nsresult CMfcEmbedApp::InitializePrefs()
279 {
280 nsresult rv;
281 NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv);
282 if (NS_SUCCEEDED(rv)) {
283
284 rv = InitializeCachePrefs();
285 NS_ASSERTION(NS_SUCCEEDED(rv), "Could not initialize cache prefs");
286
287 // We are using the default prefs from mozilla. If you were
288 // disributing your own, this would be done simply by editing
289 // the default pref files.
290
291 PRBool inited;
292 rv = prefs->GetBoolPref("mfcbrowser.prefs_inited", &inited);
293 if (NS_FAILED(rv) || !inited)
294 {
295 prefs->SetIntPref("font.size.variable.x-western", 12);
296 prefs->SetIntPref("font.size.fixed.x-western", 12);
297 rv = prefs->SetBoolPref("mfcbrowser.prefs_inited", PR_TRUE);
298 if (NS_SUCCEEDED(rv))
299 rv = prefs->SavePrefFile();
300 }
301
302 }
303 else
304 NS_ASSERTION(PR_FALSE, "Could not get preferences service");
305
306 return rv;
307 }
308
309 nsresult CMfcEmbedApp::InitializeCachePrefs()
310 {
311 const char * const CACHE_DIR_PREF = "browser.cache.directory";
312
313 nsresult rv;
314 NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv);
315 if (NS_FAILED(rv)) return rv;
316
317 // See if we have a pref to a dir which exists
318 nsCOMPtr<nsILocalFile> prefDir;
319 rv = prefs->GetFileXPref(CACHE_DIR_PREF, getter_AddRefs(prefDir));
320 if (NS_SUCCEEDED(rv)) {
321 PRBool isDir;
322 rv = prefDir->IsDirectory(&isDir);
323 if (NS_SUCCEEDED(rv) && isDir)
324 return NS_OK;
325 }
326
327 // Set up the new pref
328 nsCOMPtr<nsIFile> profileDir;
329 rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(profileDir));
330 NS_ASSERTION(profileDir, "NS_APP_USER_PROFILE_50_DIR is not defined");
331 if (NS_FAILED(rv)) return rv;
332
333 nsCOMPtr<nsILocalFile> cacheDir(do_QueryInterface(profileDir));
334 NS_ASSERTION(cacheDir, "Cannot get nsILocalFile from cache dir");
335
336 PRBool exists;
337 cacheDir->Append("Cache");
338 rv = cacheDir->Exists(&exists);
339 if (NS_SUCCEEDED(rv) && !exists)
340 rv = cacheDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
341 if (NS_FAILED(rv)) return rv;
342
343 return prefs->SetFileXPref(CACHE_DIR_PREF, cacheDir);
344 }
345
346 // ---------------------------------------------------------------------------
347 // CMfcEmbedApp : nsISupports
348 // ---------------------------------------------------------------------------
349
350 NS_IMPL_THREADSAFE_ISUPPORTS2(CMfcEmbedApp, nsIObserver, nsISupportsWeakReference);
351
352 // ---------------------------------------------------------------------------
353 // CMfcEmbedApp : nsIObserver
354 // ---------------------------------------------------------------------------
355
356 // Mainly needed to support "on the fly" profile switching
357
358 NS_IMETHODIMP CMfcEmbedApp::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData)
359 {
360 nsresult rv = NS_OK;
361
362 if (nsCRT::strcmp(aTopic, PROFILE_APPROVE_CHANGE_TOPIC) == 0)
363 {
364 // Ask the user if they want to
365 int result = MessageBox(NULL, "Do you want to close all windows in order to switch the profile?", "Confirm", MB_YESNO | MB_ICONQUESTION);
366 if (result != IDYES)
367 {
368 nsCOMPtr<nsIProfileChangeStatus> status = do_QueryInterface(aSubject);
369 NS_ENSURE_TRUE(status, NS_ERROR_FAILURE);
370 status->VetoChange();
371 }
372 }
373 else if (nsCRT::strcmp(aTopic, PROFILE_CHANGE_TEARDOWN_TOPIC) == 0)
374 {
375 // Close all open windows. Alternatively, we could just call CBrowserWindow::Stop()
376 // on each. Either way, we have to stop all network activity on this phase.
377
378 POSITION pos = m_FrameWndLst.GetHeadPosition();
379 while( pos != NULL )
380 {
381 CBrowserFrame *pBrowserFrame = (CBrowserFrame *) m_FrameWndLst.GetNext(pos);
382 if(pBrowserFrame)
383 {
384 pBrowserFrame->ShowWindow(false);
385
386 // Passing in FALSE below so that we do not
387 // kill the main app during a profile switch
388 RemoveFrameFromList(pBrowserFrame, FALSE);
389
390 pBrowserFrame->DestroyWindow();
391 }
392 }
393
394 NS_WITH_SERVICE(nsINetDataCacheManager, cacheMgr, NS_NETWORK_CACHE_MANAGER_CONTRACTID, &rv);
395 if (NS_SUCCEEDED(rv))
396 cacheMgr->Clear(nsINetDataCacheManager::MEM_CACHE);
397 }
398 else if (nsCRT::strcmp(aTopic, PROFILE_AFTER_CHANGE_TOPIC) == 0)
399 {
400 InitializePrefs(); // In case we have just switched to a newly created profile.
401
402 OnNewBrowser();
403 }
404 return rv;
405 }
406
407 // AboutDlg Stuff
408
409 class CAboutDlg : public CDialog
410 {
411 public:
412 CAboutDlg();
413
414 enum { IDD = IDD_ABOUTBOX };
415
416 protected:
417 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
418
419 protected:
420 DECLARE_MESSAGE_MAP()
421 };
422
423 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
424 {
425 }
426
427 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
428 {
429 CDialog::DoDataExchange(pDX);
430 }
431
432 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
433 END_MESSAGE_MAP()
434
435 // Show the AboutDlg
436 void CMfcEmbedApp::OnAppAbout()
437 {
438 CAboutDlg aboutDlg;
439 aboutDlg.DoModal();
440 }
441
This page was automatically generated by
LXR.