Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / embedding / tests / winEmbed / winEmbed.cpp
blob3be299fef41a20583017b48024fc684bdb05b104
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: Mozilla-sample-code 1.0
5 * Copyright (c) 2002 Netscape Communications Corporation and
6 * other contributors
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this Mozilla sample software and associated documentation files
10 * (the "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to permit
13 * persons to whom the Software is furnished to do so, subject to the
14 * following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
27 * Contributor(s):
28 * Doug Turner <dougt@netscape.com>
29 * Adam Lock <adamlock@netscape.com>
31 * ***** END LICENSE BLOCK ***** */
33 // C RunTime Header Files
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <malloc.h>
37 #include <memory.h>
38 #include <tchar.h>
40 // Win32 header files
41 #include <windows.h>
42 #include <commctrl.h>
43 #include <commdlg.h>
45 // Mozilla Frozen APIs
46 #include "nsXULAppAPI.h"
48 XRE_InitEmbeddingType XRE_InitEmbedding;
49 XRE_TermEmbeddingType XRE_TermEmbedding;
51 #include "nsAppDirectoryServiceDefs.h"
52 #include "nsDirectoryServiceDefs.h"
53 #include "nsProfileDirServiceProvider.h"
54 #include "nsStringAPI.h"
55 #include "nsXPCOMGlue.h"
57 #include "nsIClipboardCommands.h"
58 #include "nsIInterfaceRequestor.h"
59 #include "nsIObserverService.h"
60 #include "nsIObserver.h"
61 #include "nsIURI.h"
62 #include "nsIWebBrowserFocus.h"
63 #include "nsIWindowWatcher.h"
65 // NON-FROZEN APIs!
66 #include "nsIBaseWindow.h"
67 #include "nsIWebNavigation.h"
69 // Local header files
70 #include "winEmbed.h"
71 #include "WebBrowserChrome.h"
72 #include "WindowCreator.h"
73 #include "resource.h"
75 #define MAX_LOADSTRING 100
77 const TCHAR *szWindowClass = _T("WINEMBED");
79 // Foward declarations of functions included in this code module:
80 static ATOM MyRegisterClass(HINSTANCE hInstance);
81 static LRESULT CALLBACK BrowserWndProc(HWND, UINT, WPARAM, LPARAM);
82 static BOOL CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
84 static nsresult InitializeWindowCreator();
85 static nsresult OpenWebPage(const char * url);
86 static nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome);
88 // Profile chooser stuff
89 static nsresult StartupProfile();
91 // Global variables
92 static UINT gDialogCount = 0;
93 static HINSTANCE ghInstanceApp = NULL;
94 static char gFirstURL[1024];
96 // like strpbrk but finds the *last* char, not the first
97 static char*
98 ns_strrpbrk(char *string, const char *strCharSet)
100 char *found = NULL;
101 for (; *string; ++string) {
102 for (const char *search = strCharSet; *search; ++search) {
103 if (*search == *string) {
104 found = string;
105 // Since we're looking for the last char, we save "found"
106 // until we're at the end of the string.
111 return found;
114 // A list of URLs to populate the URL drop down list with
115 static const TCHAR *gDefaultURLs[] =
117 _T("http://www.mozilla.org/"),
118 _T("http://www.netscape.com/"),
119 _T("http://browsertest.web.aol.com/tests/javascript/javascpt/index.htm"),
120 _T("http://127.0.0.1/"),
121 _T("http://www.yahoo.com/"),
122 _T("http://www.travelocity.com/"),
123 _T("http://www.disney.com/"),
124 _T("http://www.go.com/"),
125 _T("http://www.google.com/"),
126 _T("http://www.ebay.com/"),
127 _T("http://www.shockwave.com/"),
128 _T("http://www.slashdot.org/"),
129 _T("http://www.quicken.com/"),
130 _T("http://www.hotmail.com/"),
131 _T("http://www.cnn.com/"),
132 _T("http://www.javasoft.com/")
135 int main(int argc, char *argv[])
137 nsresult rv;
139 printf("You are embedded, man!\n\n");
140 printf("******************************************************************\n");
141 printf("* *\n");
142 printf("* IMPORTANT NOTE: *\n");
143 printf("* *\n");
144 printf("* WinEmbed is not supported!!! Do not raise bugs on it unless *\n");
145 printf("* it is badly broken (e.g. crash on start/exit, build errors) *\n");
146 printf("* or you have the patch to make it better! MFCEmbed is now our *\n");
147 printf("* embedding test application on Win32 and all testing should *\n");
148 printf("* be done on that. *\n");
149 printf("* *\n");
150 printf("******************************************************************\n");
151 printf("\n\n");
153 // Sophisticated command-line parsing in action
154 char *szFirstURL = "http://www.mozilla.org/projects/embedding/";
155 int argn;
156 for (argn = 1; argn < argc; argn++)
158 szFirstURL = argv[argn];
160 strncpy(gFirstURL, szFirstURL, sizeof(gFirstURL) - 1);
162 ghInstanceApp = GetModuleHandle(NULL);
164 // Initialize global strings
165 TCHAR szTitle[MAX_LOADSTRING];
166 LoadString(ghInstanceApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
167 MyRegisterClass(ghInstanceApp);
169 // Find the GRE (libxul). We are only using frozen interfaces, so we
170 // should be compatible all the way up to (but not including) mozilla 2.0
171 static const GREVersionRange vr = {
172 "1.8a1",
173 PR_TRUE,
174 "2.0",
175 PR_FALSE
178 char xpcomPath[_MAX_PATH];
179 rv = GRE_GetGREPathWithProperties(&vr, 1, nsnull, 0,
180 xpcomPath, sizeof(xpcomPath));
181 if (NS_FAILED(rv))
182 return 1;
184 char *lastslash = ns_strrpbrk(xpcomPath, "/\\");
185 if (!lastslash)
186 return 2;
188 rv = XPCOMGlueStartup(xpcomPath);
189 if (NS_FAILED(rv))
190 return 3;
192 *lastslash = '\0';
194 char xulPath[_MAX_PATH];
195 _snprintf(xulPath, sizeof(xulPath), "%s\\xul.dll", xpcomPath);
196 xulPath[sizeof(xulPath) - 1] = '\0';
198 HINSTANCE xulModule = LoadLibraryEx(xulPath, NULL, 0);
199 if (!xulModule)
200 return 4;
202 char temp[_MAX_PATH];
203 GetModuleFileName(xulModule, temp, sizeof(temp));
205 XRE_InitEmbedding =
206 (XRE_InitEmbeddingType) GetProcAddress(xulModule, "XRE_InitEmbedding");
207 if (!XRE_InitEmbedding) {
208 fprintf(stderr, "Error: %i\n", GetLastError());
209 return 5;
212 XRE_TermEmbedding =
213 (XRE_TermEmbeddingType) GetProcAddress(xulModule, "XRE_TermEmbedding");
214 if (!XRE_TermEmbedding) {
215 fprintf(stderr, "Error: %i\n", GetLastError());
216 return 5;
219 // Scope all the XPCOM stuff
221 nsCOMPtr<nsILocalFile> xuldir;
222 rv = NS_NewNativeLocalFile(nsCString(xpcomPath), PR_FALSE,
223 getter_AddRefs(xuldir));
224 if (NS_FAILED(rv))
225 return 6;
227 char self[_MAX_PATH];
228 GetModuleFileName(ghInstanceApp, self, sizeof(self));
229 lastslash = ns_strrpbrk(xpcomPath, "/\\");
230 if (!lastslash)
231 return 7;
233 *lastslash = '\0';
235 nsCOMPtr<nsILocalFile> appdir;
236 rv = NS_NewNativeLocalFile(nsCString(self), PR_FALSE,
237 getter_AddRefs(appdir));
238 if (NS_FAILED(rv))
239 return 8;
241 rv = XRE_InitEmbedding(xuldir, appdir, nsnull, nsnull, 0);
242 if (NS_FAILED(rv))
243 return 9;
245 int result = 0;
246 if (NS_FAILED(StartupProfile())) {
247 result = 8;
249 else {
250 InitializeWindowCreator();
252 // Open the initial browser window
253 OpenWebPage(gFirstURL);
255 // Main message loop.
256 // NOTE: We use a fake event and a timeout in order to process idle stuff for
257 // Mozilla every 1/10th of a second.
258 PRBool runCondition = PR_TRUE;
260 rv = AppCallbacks::RunEventLoop(runCondition);
263 XRE_TermEmbedding();
265 return rv;
268 /* InitializeWindowCreator creates and hands off an object with a callback
269 to a window creation function. This is how all new windows are opened,
270 except any created directly by the embedding app. */
271 nsresult
272 InitializeWindowCreator()
274 // create an nsWindowCreator and give it to the WindowWatcher service
275 nsCOMPtr<nsIWindowCreator> creator(new WindowCreator());
276 if (!creator)
277 return NS_ERROR_OUT_OF_MEMORY;
279 nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
280 if (!wwatch)
281 return NS_ERROR_UNEXPECTED;
283 return wwatch->SetWindowCreator(creator);
286 //-----------------------------------------------------------------------------
289 // FUNCTION: OpenWebPage()
291 // PURPOSE: Opens a new browser dialog and starts it loading to the
292 // specified url.
294 nsresult OpenWebPage(const char *url)
296 nsresult rv;
298 // Create the chrome object. Note that it leaves this function
299 // with an extra reference so that it can released correctly during
300 // destruction (via Win32UI::Destroy)
302 nsCOMPtr<nsIWebBrowserChrome> chrome;
303 rv = AppCallbacks::CreateBrowserWindow(nsIWebBrowserChrome::CHROME_ALL,
304 nsnull, getter_AddRefs(chrome));
305 if (NS_SUCCEEDED(rv))
307 // Start loading a page
308 nsCOMPtr<nsIWebBrowser> newBrowser;
309 chrome->GetWebBrowser(getter_AddRefs(newBrowser));
310 nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(newBrowser));
312 return webNav->LoadURI(NS_ConvertASCIItoUTF16(url).get(),
313 nsIWebNavigation::LOAD_FLAGS_NONE,
314 nsnull,
315 nsnull,
316 nsnull);
319 return rv;
323 // FUNCTION: GetBrowserFromChrome()
325 // PURPOSE: Returns the HWND for the webbrowser container associated
326 // with the specified chrome.
328 HWND GetBrowserFromChrome(nsIWebBrowserChrome *aChrome)
330 if (!aChrome)
332 return NULL;
334 nsCOMPtr<nsIEmbeddingSiteWindow> baseWindow = do_QueryInterface(aChrome);
335 HWND hwnd = NULL;
336 baseWindow->GetSiteWindow((void **) & hwnd);
337 return hwnd;
342 // FUNCTION: GetBrowserDlgFromChrome()
344 // PURPOSE: Returns the HWND for the browser dialog associated with
345 // the specified chrome.
347 HWND GetBrowserDlgFromChrome(nsIWebBrowserChrome *aChrome)
349 return GetParent(GetBrowserFromChrome(aChrome));
354 // FUNCTION: ResizeEmbedding()
356 // PURPOSE: Resizes the webbrowser window to fit its container.
358 nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome)
360 if (!chrome)
361 return NS_ERROR_FAILURE;
363 nsCOMPtr<nsIEmbeddingSiteWindow> embeddingSite = do_QueryInterface(chrome);
364 HWND hWnd;
365 embeddingSite->GetSiteWindow((void **) & hWnd);
367 if (!hWnd)
368 return NS_ERROR_NULL_POINTER;
370 RECT rect;
371 GetClientRect(hWnd, &rect);
373 // Make sure the browser is visible and sized
374 nsCOMPtr<nsIWebBrowser> webBrowser;
375 chrome->GetWebBrowser(getter_AddRefs(webBrowser));
376 nsCOMPtr<nsIBaseWindow> webBrowserAsWin = do_QueryInterface(webBrowser);
377 if (webBrowserAsWin)
379 webBrowserAsWin->SetPositionAndSize(rect.left,
380 rect.top,
381 rect.right - rect.left,
382 rect.bottom - rect.top,
383 PR_TRUE);
384 webBrowserAsWin->SetVisibility(PR_TRUE);
387 return NS_OK;
392 // FUNCTION: MyRegisterClass()
394 // PURPOSE: Registers the window class.
396 // COMMENTS:
398 // This function and its usage is only necessary if you want this code
399 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
400 // function that was added to Windows 95. It is important to call this function
401 // so that the application will get 'well formed' small icons associated
402 // with it.
404 ATOM MyRegisterClass(HINSTANCE hInstance)
406 WNDCLASSEX wcex;
408 memset(&wcex, 0, sizeof(wcex));
409 wcex.cbSize = sizeof(WNDCLASSEX);
411 wcex.style = CS_HREDRAW | CS_VREDRAW;
412 wcex.lpfnWndProc = (WNDPROC) BrowserWndProc;
413 wcex.cbClsExtra = 0;
414 wcex.cbWndExtra = 0;
415 wcex.hInstance = hInstance;
416 wcex.hIcon = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_WINEMBED);
417 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
418 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
419 wcex.lpszClassName = szWindowClass;
420 wcex.hIconSm = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_SMALL);
422 return RegisterClassEx(&wcex);
427 // FUNCTION: UpdateUI()
429 // PURPOSE: Refreshes the buttons and menu items in the browser dialog
431 void UpdateUI(nsIWebBrowserChrome *aChrome)
433 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
434 nsCOMPtr<nsIWebBrowser> webBrowser;
435 nsCOMPtr<nsIWebNavigation> webNavigation;
436 aChrome->GetWebBrowser(getter_AddRefs(webBrowser));
437 webNavigation = do_QueryInterface(webBrowser);
439 PRBool canGoBack = PR_FALSE;
440 PRBool canGoForward = PR_FALSE;
441 if (webNavigation)
443 webNavigation->GetCanGoBack(&canGoBack);
444 webNavigation->GetCanGoForward(&canGoForward);
447 PRBool canCutSelection = PR_FALSE;
448 PRBool canCopySelection = PR_FALSE;
449 PRBool canPaste = PR_FALSE;
451 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
452 if (clipCmds)
454 clipCmds->CanCutSelection(&canCutSelection);
455 clipCmds->CanCopySelection(&canCopySelection);
456 clipCmds->CanPaste(&canPaste);
459 HMENU hmenu = GetMenu(hwndDlg);
460 if (hmenu)
462 EnableMenuItem(hmenu, MOZ_GoBack, MF_BYCOMMAND |
463 ((canGoBack) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
464 EnableMenuItem(hmenu, MOZ_GoForward, MF_BYCOMMAND |
465 ((canGoForward) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
467 EnableMenuItem(hmenu, MOZ_Cut, MF_BYCOMMAND |
468 ((canCutSelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
469 EnableMenuItem(hmenu, MOZ_Copy, MF_BYCOMMAND |
470 ((canCopySelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
471 EnableMenuItem(hmenu, MOZ_Paste, MF_BYCOMMAND |
472 ((canPaste) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
475 HWND button;
476 button = GetDlgItem(hwndDlg, IDC_BACK);
477 if (button)
478 EnableWindow(button, canGoBack);
479 button = GetDlgItem(hwndDlg, IDC_FORWARD);
480 if (button)
481 EnableWindow(button, canGoForward);
486 // FUNCTION: BrowserDlgProc()
488 // PURPOSE: Browser dialog windows message handler.
490 // COMMENTS:
492 // The code for handling buttons and menu actions is here.
494 BOOL CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
496 // Get the browser and other pointers since they are used a lot below
497 HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
498 nsIWebBrowserChrome *chrome = nsnull ;
499 if (hwndBrowser)
501 chrome = (nsIWebBrowserChrome *) GetWindowLong(hwndBrowser, GWL_USERDATA);
503 nsCOMPtr<nsIWebBrowser> webBrowser;
504 nsCOMPtr<nsIWebNavigation> webNavigation;
505 if (chrome)
507 chrome->GetWebBrowser(getter_AddRefs(webBrowser));
508 webNavigation = do_QueryInterface(webBrowser);
511 // Test the message
512 switch (uMsg)
514 case WM_INITDIALOG:
515 return TRUE;
517 case WM_INITMENU:
518 UpdateUI(chrome);
519 return TRUE;
521 case WM_SYSCOMMAND:
522 if (wParam == SC_CLOSE)
524 WebBrowserChromeUI::Destroy(chrome);
525 return TRUE;
527 break;
529 case WM_DESTROY:
530 return TRUE;
532 case WM_COMMAND:
533 if (!webBrowser)
535 return TRUE;
538 // Test which command was selected
539 switch (LOWORD(wParam))
541 case IDC_ADDRESS:
542 if (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE)
544 // User has changed the address field so enable the Go button
545 EnableWindow(GetDlgItem(hwndDlg, IDC_GO), TRUE);
547 break;
549 case IDC_GO:
551 TCHAR szURL[2048];
552 memset(szURL, 0, sizeof(szURL));
553 GetDlgItemText(hwndDlg, IDC_ADDRESS, szURL,
554 sizeof(szURL) / sizeof(szURL[0]) - 1);
555 webNavigation->LoadURI(
556 NS_ConvertASCIItoUTF16(szURL).get(),
557 nsIWebNavigation::LOAD_FLAGS_NONE,
558 nsnull,
559 nsnull,
560 nsnull);
562 break;
564 case IDC_STOP:
565 webNavigation->Stop(nsIWebNavigation::STOP_ALL);
566 UpdateUI(chrome);
567 break;
569 case IDC_RELOAD:
570 webNavigation->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
571 break;
573 case IDM_EXIT:
574 PostMessage(hwndDlg, WM_SYSCOMMAND, SC_CLOSE, 0);
575 break;
577 // File menu commands
579 case MOZ_NewBrowser:
580 OpenWebPage(gFirstURL);
581 break;
583 // Edit menu commands
585 case MOZ_Cut:
587 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
588 clipCmds->CutSelection();
590 break;
592 case MOZ_Copy:
594 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
595 clipCmds->CopySelection();
597 break;
599 case MOZ_Paste:
601 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
602 clipCmds->Paste();
604 break;
606 case MOZ_SelectAll:
608 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
609 clipCmds->SelectAll();
611 break;
613 case MOZ_SelectNone:
615 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
616 clipCmds->SelectNone();
618 break;
620 // Go menu commands
621 case IDC_BACK:
622 case MOZ_GoBack:
623 webNavigation->GoBack();
624 UpdateUI(chrome);
625 break;
627 case IDC_FORWARD:
628 case MOZ_GoForward:
629 webNavigation->GoForward();
630 UpdateUI(chrome);
631 break;
633 // Help menu commands
634 case MOZ_About:
636 TCHAR szAboutTitle[MAX_LOADSTRING];
637 TCHAR szAbout[MAX_LOADSTRING];
638 LoadString(ghInstanceApp, IDS_ABOUT_TITLE, szAboutTitle, MAX_LOADSTRING);
639 LoadString(ghInstanceApp, IDS_ABOUT, szAbout, MAX_LOADSTRING);
640 MessageBox(NULL, szAbout, szAboutTitle, MB_OK);
642 break;
645 return TRUE;
647 case WM_ACTIVATE:
649 nsCOMPtr<nsIWebBrowserFocus> focus(do_GetInterface(webBrowser));
650 if(focus)
652 switch (wParam)
654 case WA_ACTIVE:
655 focus->Activate();
656 break;
657 case WA_INACTIVE:
658 focus->Deactivate();
659 break;
660 default:
661 break;
665 break;
667 case WM_SIZE:
669 UINT newDlgWidth = LOWORD(lParam);
670 UINT newDlgHeight = HIWORD(lParam);
672 // TODO Reposition the control bar - for the moment it's fixed size
674 // Reposition the status area. Status bar
675 // gets any space that the fixed size progress bar doesn't use.
676 int progressWidth;
677 int statusWidth;
678 int statusHeight;
679 HWND hwndStatus = GetDlgItem(hwndDlg, IDC_STATUS);
680 if (hwndStatus) {
681 RECT rcStatus;
682 GetWindowRect(hwndStatus, &rcStatus);
683 statusHeight = rcStatus.bottom - rcStatus.top;
684 } else
685 statusHeight = 0;
687 HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
688 if (hwndProgress) {
689 RECT rcProgress;
690 GetWindowRect(hwndProgress, &rcProgress);
691 progressWidth = rcProgress.right - rcProgress.left;
692 } else
693 progressWidth = 0;
694 statusWidth = newDlgWidth - progressWidth;
696 if (hwndStatus)
697 SetWindowPos(hwndStatus,
698 HWND_TOP,
699 0, newDlgHeight - statusHeight,
700 statusWidth,
701 statusHeight,
702 SWP_NOZORDER);
703 if (hwndProgress)
704 SetWindowPos(hwndProgress,
705 HWND_TOP,
706 statusWidth, newDlgHeight - statusHeight,
707 0, 0,
708 SWP_NOSIZE | SWP_NOZORDER);
710 // Resize the browser area (assuming the browse is
711 // sandwiched between the control bar and status area)
712 RECT rcBrowser;
713 POINT ptBrowser;
714 GetWindowRect(hwndBrowser, &rcBrowser);
715 ptBrowser.x = rcBrowser.left;
716 ptBrowser.y = rcBrowser.top;
717 ScreenToClient(hwndDlg, &ptBrowser);
718 int browserHeight = newDlgHeight - ptBrowser.y - statusHeight;
719 if (browserHeight < 1)
721 browserHeight = 1;
723 SetWindowPos(hwndBrowser,
724 HWND_TOP,
725 0, 0,
726 newDlgWidth,
727 newDlgHeight - ptBrowser.y - statusHeight,
728 SWP_NOMOVE | SWP_NOZORDER);
730 return TRUE;
732 return FALSE;
737 // FUNCTION: BrowserWndProc(HWND, unsigned, WORD, LONG)
739 // PURPOSE: Processes messages for the browser container window.
741 LRESULT CALLBACK BrowserWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
743 nsIWebBrowserChrome *chrome = (nsIWebBrowserChrome *) GetWindowLong(hWnd, GWL_USERDATA);
744 switch (message)
746 case WM_SIZE:
747 // Resize the embedded browser
748 ResizeEmbedding(chrome);
749 return 0;
750 case WM_ERASEBKGND:
751 // Reduce flicker by not painting the non-visible background
752 return 1;
754 return DefWindowProc(hWnd, message, wParam, lParam);
758 // FUNCTION: StartupProfile()
760 // PURPOSE:
762 nsresult StartupProfile()
765 nsCOMPtr<nsIFile> appDataDir;
766 nsresult rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(appDataDir));
767 if (NS_FAILED(rv))
768 return rv;
770 appDataDir->AppendNative(nsCString("winembed"));
771 nsCOMPtr<nsILocalFile> localAppDataDir(do_QueryInterface(appDataDir));
773 nsCOMPtr<nsProfileDirServiceProvider> locProvider;
774 NS_NewProfileDirServiceProvider(PR_TRUE, getter_AddRefs(locProvider));
775 if (!locProvider)
776 return NS_ERROR_FAILURE;
778 rv = locProvider->Register();
779 if (NS_FAILED(rv))
780 return rv;
782 return locProvider->SetProfileDir(localAppDataDir);
787 ///////////////////////////////////////////////////////////////////////////////
788 // WebBrowserChromeUI
791 // FUNCTION: CreateNativeWindow()
793 // PURPOSE: Creates a new browser dialog.
795 // COMMENTS:
797 // This function loads the browser dialog from a resource template
798 // and returns the HWND for the webbrowser container dialog item
799 // to the caller.
801 HWND WebBrowserChromeUI::CreateNativeWindow(nsIWebBrowserChrome* chrome)
803 // Load the browser dialog from resource
804 HWND hwndDialog;
805 PRUint32 chromeFlags;
807 chrome->GetChromeFlags(&chromeFlags);
808 if ((chromeFlags & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL)
809 hwndDialog = CreateDialog(ghInstanceApp,
810 MAKEINTRESOURCE(IDD_BROWSER),
811 NULL,
812 BrowserDlgProc);
813 else
814 hwndDialog = CreateDialog(ghInstanceApp,
815 MAKEINTRESOURCE(IDD_BROWSER_NC),
816 NULL,
817 BrowserDlgProc);
818 if (!hwndDialog)
819 return NULL;
821 // Stick a menu onto it
822 if (chromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR) {
823 HMENU hmenuDlg = LoadMenu(ghInstanceApp, MAKEINTRESOURCE(IDC_WINEMBED));
824 SetMenu(hwndDialog, hmenuDlg);
825 } else
826 SetMenu(hwndDialog, 0);
828 // Add some interesting URLs to the address drop down
829 HWND hwndAddress = GetDlgItem(hwndDialog, IDC_ADDRESS);
830 if (hwndAddress) {
831 for (int i = 0; i < sizeof(gDefaultURLs) / sizeof(gDefaultURLs[0]); i++)
833 SendMessage(hwndAddress, CB_ADDSTRING, 0, (LPARAM) gDefaultURLs[i]);
837 // Fetch the browser window handle
838 HWND hwndBrowser = GetDlgItem(hwndDialog, IDC_BROWSER);
839 SetWindowLong(hwndBrowser, GWL_USERDATA, (LONG)chrome); // save the browser LONG_PTR.
840 SetWindowLong(hwndBrowser, GWL_STYLE, GetWindowLong(hwndBrowser, GWL_STYLE) | WS_CLIPCHILDREN);
842 // Activate the window
843 PostMessage(hwndDialog, WM_ACTIVATE, WA_ACTIVE, 0);
845 gDialogCount++;
847 return hwndBrowser;
852 // FUNCTION: Destroy()
854 // PURPOSE: Destroy the window specified by the chrome
856 void WebBrowserChromeUI::Destroy(nsIWebBrowserChrome* chrome)
858 nsCOMPtr<nsIWebBrowser> webBrowser;
859 nsCOMPtr<nsIWebNavigation> webNavigation;
861 chrome->GetWebBrowser(getter_AddRefs(webBrowser));
862 webNavigation = do_QueryInterface(webBrowser);
863 if (webNavigation)
864 webNavigation->Stop(nsIWebNavigation::STOP_ALL);
866 chrome->ExitModalEventLoop(NS_OK);
868 HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
869 if (hwndDlg == NULL)
870 return;
872 // Explicitly destroy the embedded browser and then the chrome
874 // First the browser
875 nsCOMPtr<nsIWebBrowser> browser = nsnull;
876 chrome->GetWebBrowser(getter_AddRefs(browser));
877 nsCOMPtr<nsIBaseWindow> browserAsWin = do_QueryInterface(browser);
878 if (browserAsWin)
879 browserAsWin->Destroy();
881 // Now the chrome
882 chrome->SetWebBrowser(nsnull);
883 NS_RELEASE(chrome);
888 // FUNCTION: Called as the final act of a chrome object during its destructor
890 void WebBrowserChromeUI::Destroyed(nsIWebBrowserChrome* chrome)
892 HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
893 if (hwndDlg == NULL)
895 return;
898 // Clear the window user data
899 HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
900 SetWindowLong(hwndBrowser, GWL_USERDATA, nsnull);
901 DestroyWindow(hwndBrowser);
902 DestroyWindow(hwndDlg);
904 --gDialogCount;
905 if (gDialogCount == 0)
907 // Quit when there are no more browser objects
908 PostQuitMessage(0);
914 // FUNCTION: Set the input focus onto the browser window
916 void WebBrowserChromeUI::SetFocus(nsIWebBrowserChrome *chrome)
918 HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
919 if (hwndDlg == NULL)
921 return;
924 HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
925 ::SetFocus(hwndBrowser);
929 // FUNCTION: UpdateStatusBarText()
931 // PURPOSE: Set the status bar text.
933 void WebBrowserChromeUI::UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const PRUnichar* aStatusText)
935 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
936 nsCString status;
937 if (aStatusText) {
938 nsString wStatusText(aStatusText);
939 NS_UTF16ToCString(wStatusText, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
940 status);
943 SetDlgItemText(hwndDlg, IDC_STATUS, status.get());
948 // FUNCTION: UpdateCurrentURI()
950 // PURPOSE: Updates the URL address field
952 void WebBrowserChromeUI::UpdateCurrentURI(nsIWebBrowserChrome *aChrome)
954 nsCOMPtr<nsIWebBrowser> webBrowser;
955 nsCOMPtr<nsIWebNavigation> webNavigation;
956 aChrome->GetWebBrowser(getter_AddRefs(webBrowser));
957 webNavigation = do_QueryInterface(webBrowser);
959 nsCOMPtr<nsIURI> currentURI;
960 webNavigation->GetCurrentURI(getter_AddRefs(currentURI));
961 if (currentURI)
963 nsCString uriString;
964 currentURI->GetAsciiSpec(uriString);
965 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
966 SetDlgItemText(hwndDlg, IDC_ADDRESS, uriString.get());
972 // FUNCTION: UpdateBusyState()
974 // PURPOSE: Refreshes the stop/go buttons in the browser dialog
976 void WebBrowserChromeUI::UpdateBusyState(nsIWebBrowserChrome *aChrome, PRBool aBusy)
978 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
979 HWND button;
980 button = GetDlgItem(hwndDlg, IDC_STOP);
981 if (button)
982 EnableWindow(button, aBusy);
983 button = GetDlgItem(hwndDlg, IDC_GO);
984 if (button)
985 EnableWindow(button, !aBusy);
986 UpdateUI(aChrome);
991 // FUNCTION: UpdateProgress()
993 // PURPOSE: Refreshes the progress bar in the browser dialog
995 void WebBrowserChromeUI::UpdateProgress(nsIWebBrowserChrome *aChrome, PRInt32 aCurrent, PRInt32 aMax)
997 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
998 HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
999 if (aCurrent < 0)
1001 aCurrent = 0;
1003 if (aCurrent > aMax)
1005 aMax = aCurrent + 20; // What to do?
1007 if (hwndProgress)
1009 SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, aMax));
1010 SendMessage(hwndProgress, PBM_SETPOS, aCurrent, 0);
1015 // FUNCTION: ShowContextMenu()
1017 // PURPOSE: Display a context menu for the given node
1019 void WebBrowserChromeUI::ShowContextMenu(nsIWebBrowserChrome *aChrome, PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
1021 // TODO code to test context flags and display a popup menu should go here
1025 // FUNCTION: ShowTooltip()
1027 // PURPOSE: Show a tooltip
1029 void WebBrowserChromeUI::ShowTooltip(nsIWebBrowserChrome *aChrome, PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText)
1031 // TODO code to show a tooltip should go here
1035 // FUNCTION: HideTooltip()
1037 // PURPOSE: Hide the tooltip
1039 void WebBrowserChromeUI::HideTooltip(nsIWebBrowserChrome *aChrome)
1041 // TODO code to hide a tooltip should go here
1044 void WebBrowserChromeUI::ShowWindow(nsIWebBrowserChrome *aChrome, PRBool aShow)
1046 HWND win = GetBrowserDlgFromChrome(aChrome);
1047 ::ShowWindow(win, aShow ? SW_RESTORE : SW_HIDE);
1050 void WebBrowserChromeUI::SizeTo(nsIWebBrowserChrome *aChrome, PRInt32 aWidth, PRInt32 aHeight)
1052 HWND hchrome = GetBrowserDlgFromChrome(aChrome);
1053 HWND hbrowser = GetBrowserFromChrome(aChrome);
1054 RECT chromeRect, browserRect;
1056 ::GetWindowRect(hchrome, &chromeRect);
1057 ::GetWindowRect(hbrowser, &browserRect);
1059 PRInt32 decoration_x = (browserRect.left - chromeRect.left) +
1060 (chromeRect.right - browserRect.right);
1061 PRInt32 decoration_y = (browserRect.top - chromeRect.top) +
1062 (chromeRect.bottom - browserRect.bottom);
1064 ::MoveWindow(hchrome, chromeRect.left, chromeRect.top,
1065 aWidth+decoration_x,
1066 aHeight+decoration_y, TRUE);
1070 // FUNCTION: GetResourceStringByID()
1072 // PURPOSE: Get the resource string for the ID
1074 void WebBrowserChromeUI::GetResourceStringById(PRInt32 aID, char ** aReturn)
1076 char resBuf[MAX_LOADSTRING];
1077 int retval = LoadString( ghInstanceApp, aID, (LPTSTR)resBuf, sizeof(resBuf) );
1078 if (retval != 0)
1080 int resLen = strlen(resBuf);
1081 *aReturn = (char *)calloc(resLen+1, sizeof(char *));
1082 if (!*aReturn) return;
1083 strncpy(*aReturn, resBuf, resLen);
1085 return;
1088 //-----------------------------------------------------------------------------
1089 // AppCallbacks
1090 //-----------------------------------------------------------------------------
1092 nsresult AppCallbacks::CreateBrowserWindow(PRUint32 aChromeFlags,
1093 nsIWebBrowserChrome *aParent,
1094 nsIWebBrowserChrome **aNewWindow)
1096 WebBrowserChrome * chrome = new WebBrowserChrome();
1097 if (!chrome)
1098 return NS_ERROR_FAILURE;
1100 // the interface to return and one addref, which we assume will be
1101 // immediately released
1102 CallQueryInterface(static_cast<nsIWebBrowserChrome*>(chrome), aNewWindow);
1103 // now an extra addref; the window owns itself (to be released by
1104 // WebBrowserChromeUI::Destroy)
1105 NS_ADDREF(*aNewWindow);
1107 chrome->SetChromeFlags(aChromeFlags);
1108 chrome->SetParent(aParent);
1110 // Insert the browser
1111 nsCOMPtr<nsIWebBrowser> newBrowser;
1112 chrome->CreateBrowser(-1, -1, -1, -1, getter_AddRefs(newBrowser));
1113 if (!newBrowser)
1114 return NS_ERROR_FAILURE;
1116 // Place it where we want it.
1117 ResizeEmbedding(static_cast<nsIWebBrowserChrome*>(chrome));
1119 // if opened as chrome, it'll be made visible after the chrome has loaded.
1120 // otherwise, go ahead and show it now.
1121 if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME))
1122 WebBrowserChromeUI::ShowWindow(*aNewWindow, PR_TRUE);
1124 return NS_OK;
1127 void AppCallbacks::EnableChromeWindow(nsIWebBrowserChrome *aWindow,
1128 PRBool aEnabled)
1130 HWND hwnd = GetBrowserDlgFromChrome(aWindow);
1131 ::EnableWindow(hwnd, aEnabled ? TRUE : FALSE);
1134 PRUint32 AppCallbacks::RunEventLoop(PRBool &aRunCondition)
1136 MSG msg;
1137 HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
1139 while (aRunCondition ) {
1140 // Process pending messages
1141 while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
1142 if (!::GetMessage(&msg, NULL, 0, 0)) {
1143 // WM_QUIT
1144 aRunCondition = PR_FALSE;
1145 break;
1148 ::TranslateMessage(&msg);
1149 ::DispatchMessage(&msg);
1152 // Do idle stuff
1153 ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 100, QS_ALLEVENTS);
1155 ::CloseHandle(hFakeEvent);
1156 return msg.wParam;