embedding/tests/winEmbed/winEmbed.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:29206735c36d
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
4 *
5 * Copyright (c) 2002 Netscape Communications Corporation and
6 * other contributors
7 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
26 *
27 * Contributor(s):
28 * Doug Turner <dougt@netscape.com>
29 * Adam Lock <adamlock@netscape.com>
30 *
31 * ***** END LICENSE BLOCK ***** */
32
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>
39
40 // Win32 header files
41 #include <windows.h>
42 #include <commctrl.h>
43 #include <commdlg.h>
44
45 // Mozilla Frozen APIs
46 #include "nsXULAppAPI.h"
47
48 XRE_InitEmbedding2Type XRE_InitEmbedding2;
49 XRE_TermEmbeddingType XRE_TermEmbedding;
50
51 #include "nsAppDirectoryServiceDefs.h"
52 #include "nsDirectoryServiceDefs.h"
53 #include "nsProfileDirServiceProvider.h"
54 #include "nsStringAPI.h"
55 #include "nsXPCOMGlue.h"
56
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"
64
65 // NON-FROZEN APIs!
66 #include "nsIBaseWindow.h"
67 #include "nsIWebNavigation.h"
68
69 // Local header files
70 #include "winEmbed.h"
71 #include "WebBrowserChrome.h"
72 #include "WindowCreator.h"
73 #include "resource.h"
74
75 #define MAX_LOADSTRING 100
76
77 const TCHAR *szWindowClass = _T("WINEMBED");
78
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 INT_PTR CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
83
84 static nsresult InitializeWindowCreator();
85 static nsresult OpenWebPage(const char * url);
86 static nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome);
87
88 // Profile chooser stuff
89 static nsresult StartupProfile();
90
91 // Global variables
92 static UINT gDialogCount = 0;
93 static HINSTANCE ghInstanceApp = nullptr;
94 static char gFirstURL[1024];
95
96 // like strpbrk but finds the *last* char, not the first
97 static char*
98 ns_strrpbrk(char *string, const char *strCharSet)
99 {
100 char *found = nullptr;
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.
107 }
108 }
109 }
110
111 return found;
112 }
113
114 // A list of URLs to populate the URL drop down list with
115 static const TCHAR *gDefaultURLs[] =
116 {
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/")
133 };
134
135 int main(int argc, char *argv[])
136 {
137 nsresult rv;
138
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");
152
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++)
157 {
158 szFirstURL = argv[argn];
159 }
160 strncpy(gFirstURL, szFirstURL, sizeof(gFirstURL) - 1);
161
162 ghInstanceApp = GetModuleHandle(nullptr);
163
164 // Initialize global strings
165 TCHAR szTitle[MAX_LOADSTRING];
166 LoadString(ghInstanceApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
167 MyRegisterClass(ghInstanceApp);
168
169 char path[_MAX_PATH];
170 GetModuleFileName(ghInstanceApp, path, sizeof(path));
171 char* lastslash = ns_strrpbrk(path, "/\\");
172 if (!lastslash)
173 return 7;
174
175 strcpy(lastslash, "\\xulrunner\\xpcom.dll");
176
177 rv = XPCOMGlueStartup(path);
178 if (NS_FAILED(rv))
179 return 3;
180
181 strcpy(lastslash, "\\xulrunner\\xul.dll");
182
183 HINSTANCE xulModule = LoadLibraryEx(path, nullptr, 0);
184 if (!xulModule)
185 return 4;
186
187 XRE_InitEmbedding2 =
188 (XRE_InitEmbedding2Type) GetProcAddress(xulModule, "XRE_InitEmbedding2");
189 if (!XRE_InitEmbedding2) {
190 fprintf(stderr, "Error: %i\n", GetLastError());
191 return 5;
192 }
193
194 XRE_TermEmbedding =
195 (XRE_TermEmbeddingType) GetProcAddress(xulModule, "XRE_TermEmbedding");
196 if (!XRE_TermEmbedding) {
197 fprintf(stderr, "Error: %i\n", GetLastError());
198 return 5;
199 }
200
201 int result = 0;
202
203 // Scope all the XPCOM stuff
204 {
205 strcpy(lastslash, "\\xulrunner");
206
207 nsCOMPtr<nsIFile> xuldir;
208 rv = NS_NewNativeLocalFile(nsCString(path), false,
209 getter_AddRefs(xuldir));
210 if (NS_FAILED(rv))
211 return 6;
212
213 *lastslash = '\0';
214
215 nsCOMPtr<nsIFile> appdir;
216 rv = NS_NewNativeLocalFile(nsCString(path), false,
217 getter_AddRefs(appdir));
218 if (NS_FAILED(rv))
219 return 8;
220
221 rv = XRE_InitEmbedding2(xuldir, appdir, nullptr);
222 if (NS_FAILED(rv))
223 return 9;
224
225 if (NS_FAILED(StartupProfile())) {
226 result = 8;
227 }
228 else {
229 InitializeWindowCreator();
230
231 // Open the initial browser window
232 OpenWebPage(gFirstURL);
233
234 // Main message loop.
235 // NOTE: We use a fake event and a timeout in order to process idle stuff for
236 // Mozilla every 1/10th of a second.
237 bool runCondition = true;
238
239 result = AppCallbacks::RunEventLoop(runCondition);
240 }
241 }
242 XRE_TermEmbedding();
243
244 return result;
245 }
246
247 /* InitializeWindowCreator creates and hands off an object with a callback
248 to a window creation function. This is how all new windows are opened,
249 except any created directly by the embedding app. */
250 nsresult
251 InitializeWindowCreator()
252 {
253 // create an nsWindowCreator and give it to the WindowWatcher service
254 nsCOMPtr<nsIWindowCreator> creator(new WindowCreator());
255 if (!creator)
256 return NS_ERROR_OUT_OF_MEMORY;
257
258 nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
259 if (!wwatch)
260 return NS_ERROR_UNEXPECTED;
261
262 return wwatch->SetWindowCreator(creator);
263 }
264
265 //-----------------------------------------------------------------------------
266
267 //
268 // FUNCTION: OpenWebPage()
269 //
270 // PURPOSE: Opens a new browser dialog and starts it loading to the
271 // specified url.
272 //
273 nsresult OpenWebPage(const char *url)
274 {
275 nsresult rv;
276
277 // Create the chrome object. Note that it leaves this function
278 // with an extra reference so that it can released correctly during
279 // destruction (via Win32UI::Destroy)
280
281 nsCOMPtr<nsIWebBrowserChrome> chrome;
282 rv = AppCallbacks::CreateBrowserWindow(nsIWebBrowserChrome::CHROME_ALL,
283 nullptr, getter_AddRefs(chrome));
284 if (NS_SUCCEEDED(rv))
285 {
286 // Start loading a page
287 nsCOMPtr<nsIWebBrowser> newBrowser;
288 chrome->GetWebBrowser(getter_AddRefs(newBrowser));
289 nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(newBrowser));
290
291 return webNav->LoadURI(NS_ConvertASCIItoUTF16(url).get(),
292 nsIWebNavigation::LOAD_FLAGS_NONE,
293 nullptr,
294 nullptr,
295 nullptr);
296 }
297
298 return rv;
299 }
300
301 //
302 // FUNCTION: GetBrowserFromChrome()
303 //
304 // PURPOSE: Returns the HWND for the webbrowser container associated
305 // with the specified chrome.
306 //
307 HWND GetBrowserFromChrome(nsIWebBrowserChrome *aChrome)
308 {
309 if (!aChrome)
310 {
311 return nullptr;
312 }
313 nsCOMPtr<nsIEmbeddingSiteWindow> baseWindow = do_QueryInterface(aChrome);
314 HWND hwnd = nullptr;
315 baseWindow->GetSiteWindow((void **) & hwnd);
316 return hwnd;
317 }
318
319
320 //
321 // FUNCTION: GetBrowserDlgFromChrome()
322 //
323 // PURPOSE: Returns the HWND for the browser dialog associated with
324 // the specified chrome.
325 //
326 HWND GetBrowserDlgFromChrome(nsIWebBrowserChrome *aChrome)
327 {
328 return GetParent(GetBrowserFromChrome(aChrome));
329 }
330
331
332 //
333 // FUNCTION: ResizeEmbedding()
334 //
335 // PURPOSE: Resizes the webbrowser window to fit its container.
336 //
337 nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome)
338 {
339 if (!chrome)
340 return NS_ERROR_FAILURE;
341
342 nsCOMPtr<nsIEmbeddingSiteWindow> embeddingSite = do_QueryInterface(chrome);
343 HWND hWnd;
344 embeddingSite->GetSiteWindow((void **) & hWnd);
345
346 if (!hWnd)
347 return NS_ERROR_NULL_POINTER;
348
349 RECT rect;
350 GetClientRect(hWnd, &rect);
351
352 // Make sure the browser is visible and sized
353 nsCOMPtr<nsIWebBrowser> webBrowser;
354 chrome->GetWebBrowser(getter_AddRefs(webBrowser));
355 nsCOMPtr<nsIBaseWindow> webBrowserAsWin = do_QueryInterface(webBrowser);
356 if (webBrowserAsWin)
357 {
358 webBrowserAsWin->SetPositionAndSize(rect.left,
359 rect.top,
360 rect.right - rect.left,
361 rect.bottom - rect.top,
362 true);
363 webBrowserAsWin->SetVisibility(true);
364 }
365
366 return NS_OK;
367 }
368
369
370 //
371 // FUNCTION: MyRegisterClass()
372 //
373 // PURPOSE: Registers the window class.
374 //
375 // COMMENTS:
376 //
377 // This function and its usage is only necessary if you want this code
378 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
379 // function that was added to Windows 95. It is important to call this function
380 // so that the application will get 'well formed' small icons associated
381 // with it.
382 //
383 ATOM MyRegisterClass(HINSTANCE hInstance)
384 {
385 WNDCLASSEX wcex;
386
387 memset(&wcex, 0, sizeof(wcex));
388 wcex.cbSize = sizeof(WNDCLASSEX);
389
390 wcex.style = CS_HREDRAW | CS_VREDRAW;
391 wcex.lpfnWndProc = (WNDPROC) BrowserWndProc;
392 wcex.cbClsExtra = 0;
393 wcex.cbWndExtra = 0;
394 wcex.hInstance = hInstance;
395 wcex.hIcon = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_WINEMBED);
396 wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
397 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
398 wcex.lpszClassName = szWindowClass;
399 wcex.hIconSm = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_SMALL);
400
401 return RegisterClassEx(&wcex);
402 }
403
404
405 //
406 // FUNCTION: UpdateUI()
407 //
408 // PURPOSE: Refreshes the buttons and menu items in the browser dialog
409 //
410 void UpdateUI(nsIWebBrowserChrome *aChrome)
411 {
412 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
413 nsCOMPtr<nsIWebBrowser> webBrowser;
414 nsCOMPtr<nsIWebNavigation> webNavigation;
415 aChrome->GetWebBrowser(getter_AddRefs(webBrowser));
416 webNavigation = do_QueryInterface(webBrowser);
417
418 bool canGoBack = false;
419 bool canGoForward = false;
420 if (webNavigation)
421 {
422 webNavigation->GetCanGoBack(&canGoBack);
423 webNavigation->GetCanGoForward(&canGoForward);
424 }
425
426 bool canCutSelection = false;
427 bool canCopySelection = false;
428 bool canPaste = false;
429
430 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
431 if (clipCmds)
432 {
433 clipCmds->CanCutSelection(&canCutSelection);
434 clipCmds->CanCopySelection(&canCopySelection);
435 clipCmds->CanPaste(&canPaste);
436 }
437
438 HMENU hmenu = GetMenu(hwndDlg);
439 if (hmenu)
440 {
441 EnableMenuItem(hmenu, MOZ_GoBack, MF_BYCOMMAND |
442 ((canGoBack) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
443 EnableMenuItem(hmenu, MOZ_GoForward, MF_BYCOMMAND |
444 ((canGoForward) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
445
446 EnableMenuItem(hmenu, MOZ_Cut, MF_BYCOMMAND |
447 ((canCutSelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
448 EnableMenuItem(hmenu, MOZ_Copy, MF_BYCOMMAND |
449 ((canCopySelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
450 EnableMenuItem(hmenu, MOZ_Paste, MF_BYCOMMAND |
451 ((canPaste) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
452 }
453
454 HWND button;
455 button = GetDlgItem(hwndDlg, IDC_BACK);
456 if (button)
457 EnableWindow(button, canGoBack);
458 button = GetDlgItem(hwndDlg, IDC_FORWARD);
459 if (button)
460 EnableWindow(button, canGoForward);
461 }
462
463
464 //
465 // FUNCTION: BrowserDlgProc()
466 //
467 // PURPOSE: Browser dialog windows message handler.
468 //
469 // COMMENTS:
470 //
471 // The code for handling buttons and menu actions is here.
472 //
473 INT_PTR CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
474 {
475 // Get the browser and other pointers since they are used a lot below
476 HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
477 nsIWebBrowserChrome *chrome = nullptr ;
478 if (hwndBrowser)
479 {
480 chrome = (nsIWebBrowserChrome *) GetWindowLongPtr(hwndBrowser, GWLP_USERDATA);
481 }
482 nsCOMPtr<nsIWebBrowser> webBrowser;
483 nsCOMPtr<nsIWebNavigation> webNavigation;
484 if (chrome)
485 {
486 chrome->GetWebBrowser(getter_AddRefs(webBrowser));
487 webNavigation = do_QueryInterface(webBrowser);
488 }
489
490 // Test the message
491 switch (uMsg)
492 {
493 case WM_INITDIALOG:
494 return TRUE;
495
496 case WM_INITMENU:
497 UpdateUI(chrome);
498 return TRUE;
499
500 case WM_SYSCOMMAND:
501 if (wParam == SC_CLOSE)
502 {
503 WebBrowserChromeUI::Destroy(chrome);
504 return TRUE;
505 }
506 break;
507
508 case WM_DESTROY:
509 return TRUE;
510
511 case WM_COMMAND:
512 if (!webBrowser)
513 {
514 return TRUE;
515 }
516
517 // Test which command was selected
518 switch (LOWORD(wParam))
519 {
520 case IDC_ADDRESS:
521 if (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE)
522 {
523 // User has changed the address field so enable the Go button
524 EnableWindow(GetDlgItem(hwndDlg, IDC_GO), TRUE);
525 }
526 break;
527
528 case IDC_GO:
529 {
530 TCHAR szURL[2048];
531 memset(szURL, 0, sizeof(szURL));
532 GetDlgItemText(hwndDlg, IDC_ADDRESS, szURL,
533 sizeof(szURL) / sizeof(szURL[0]) - 1);
534 webNavigation->LoadURI(
535 NS_ConvertASCIItoUTF16(szURL).get(),
536 nsIWebNavigation::LOAD_FLAGS_NONE,
537 nullptr,
538 nullptr,
539 nullptr);
540 }
541 break;
542
543 case IDC_STOP:
544 webNavigation->Stop(nsIWebNavigation::STOP_ALL);
545 UpdateUI(chrome);
546 break;
547
548 case IDC_RELOAD:
549 webNavigation->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
550 break;
551
552 case IDM_EXIT:
553 PostMessage(hwndDlg, WM_SYSCOMMAND, SC_CLOSE, 0);
554 break;
555
556 // File menu commands
557
558 case MOZ_NewBrowser:
559 OpenWebPage(gFirstURL);
560 break;
561
562 // Edit menu commands
563
564 case MOZ_Cut:
565 {
566 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
567 clipCmds->CutSelection();
568 }
569 break;
570
571 case MOZ_Copy:
572 {
573 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
574 clipCmds->CopySelection();
575 }
576 break;
577
578 case MOZ_Paste:
579 {
580 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
581 clipCmds->Paste();
582 }
583 break;
584
585 case MOZ_SelectAll:
586 {
587 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
588 clipCmds->SelectAll();
589 }
590 break;
591
592 case MOZ_SelectNone:
593 {
594 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
595 clipCmds->SelectNone();
596 }
597 break;
598
599 // Go menu commands
600 case IDC_BACK:
601 case MOZ_GoBack:
602 webNavigation->GoBack();
603 UpdateUI(chrome);
604 break;
605
606 case IDC_FORWARD:
607 case MOZ_GoForward:
608 webNavigation->GoForward();
609 UpdateUI(chrome);
610 break;
611
612 // Help menu commands
613 case MOZ_About:
614 {
615 TCHAR szAboutTitle[MAX_LOADSTRING];
616 TCHAR szAbout[MAX_LOADSTRING];
617 LoadString(ghInstanceApp, IDS_ABOUT_TITLE, szAboutTitle, MAX_LOADSTRING);
618 LoadString(ghInstanceApp, IDS_ABOUT, szAbout, MAX_LOADSTRING);
619 MessageBox(nullptr, szAbout, szAboutTitle, MB_OK);
620 }
621 break;
622 }
623
624 return TRUE;
625
626 case WM_ACTIVATE:
627 {
628 nsCOMPtr<nsIWebBrowserFocus> focus(do_GetInterface(webBrowser));
629 if(focus)
630 {
631 switch (wParam)
632 {
633 case WA_ACTIVE:
634 focus->Activate();
635 break;
636 case WA_INACTIVE:
637 focus->Deactivate();
638 break;
639 default:
640 break;
641 }
642 }
643 }
644 break;
645
646 case WM_SIZE:
647 {
648 UINT newDlgWidth = LOWORD(lParam);
649 UINT newDlgHeight = HIWORD(lParam);
650
651 // TODO Reposition the control bar - for the moment it's fixed size
652
653 // Reposition the status area. Status bar
654 // gets any space that the fixed size progress bar doesn't use.
655 int progressWidth;
656 int statusWidth;
657 int statusHeight;
658 HWND hwndStatus = GetDlgItem(hwndDlg, IDC_STATUS);
659 if (hwndStatus) {
660 RECT rcStatus;
661 GetWindowRect(hwndStatus, &rcStatus);
662 statusHeight = rcStatus.bottom - rcStatus.top;
663 } else
664 statusHeight = 0;
665
666 HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
667 if (hwndProgress) {
668 RECT rcProgress;
669 GetWindowRect(hwndProgress, &rcProgress);
670 progressWidth = rcProgress.right - rcProgress.left;
671 } else
672 progressWidth = 0;
673 statusWidth = newDlgWidth - progressWidth;
674
675 if (hwndStatus)
676 SetWindowPos(hwndStatus,
677 HWND_TOP,
678 0, newDlgHeight - statusHeight,
679 statusWidth,
680 statusHeight,
681 SWP_NOZORDER);
682 if (hwndProgress)
683 SetWindowPos(hwndProgress,
684 HWND_TOP,
685 statusWidth, newDlgHeight - statusHeight,
686 0, 0,
687 SWP_NOSIZE | SWP_NOZORDER);
688
689 // Resize the browser area (assuming the browse is
690 // sandwiched between the control bar and status area)
691 RECT rcBrowser;
692 POINT ptBrowser;
693 GetWindowRect(hwndBrowser, &rcBrowser);
694 ptBrowser.x = rcBrowser.left;
695 ptBrowser.y = rcBrowser.top;
696 ScreenToClient(hwndDlg, &ptBrowser);
697 int browserHeight = newDlgHeight - ptBrowser.y - statusHeight;
698 if (browserHeight < 1)
699 {
700 browserHeight = 1;
701 }
702 SetWindowPos(hwndBrowser,
703 HWND_TOP,
704 0, 0,
705 newDlgWidth,
706 newDlgHeight - ptBrowser.y - statusHeight,
707 SWP_NOMOVE | SWP_NOZORDER);
708 }
709 return TRUE;
710 }
711 return FALSE;
712 }
713
714
715 //
716 // FUNCTION: BrowserWndProc(HWND, UINT, WRAPAM, LPARAM)
717 //
718 // PURPOSE: Processes messages for the browser container window.
719 //
720 LRESULT CALLBACK BrowserWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
721 {
722 nsIWebBrowserChrome *chrome = (nsIWebBrowserChrome *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
723 switch (message)
724 {
725 case WM_SIZE:
726 // Resize the embedded browser
727 ResizeEmbedding(chrome);
728 return 0;
729 case WM_ERASEBKGND:
730 // Reduce flicker by not painting the non-visible background
731 return 1;
732 }
733 return DefWindowProc(hWnd, message, wParam, lParam);
734 }
735
736 //
737 // FUNCTION: StartupProfile()
738 //
739 // PURPOSE:
740 //
741 nsresult StartupProfile()
742 {
743
744 nsCOMPtr<nsIFile> appDataDir;
745 nsresult rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(appDataDir));
746 if (NS_FAILED(rv))
747 return rv;
748
749 appDataDir->AppendNative(nsCString("winembed"));
750
751 nsCOMPtr<nsProfileDirServiceProvider> locProvider;
752 NS_NewProfileDirServiceProvider(true, getter_AddRefs(locProvider));
753 if (!locProvider)
754 return NS_ERROR_FAILURE;
755
756 rv = locProvider->Register();
757 if (NS_FAILED(rv))
758 return rv;
759
760 return locProvider->SetProfileDir(appDataDir);
761
762 }
763
764
765 ///////////////////////////////////////////////////////////////////////////////
766 // WebBrowserChromeUI
767
768 //
769 // FUNCTION: CreateNativeWindow()
770 //
771 // PURPOSE: Creates a new browser dialog.
772 //
773 // COMMENTS:
774 //
775 // This function loads the browser dialog from a resource template
776 // and returns the HWND for the webbrowser container dialog item
777 // to the caller.
778 //
779 HWND WebBrowserChromeUI::CreateNativeWindow(nsIWebBrowserChrome* chrome)
780 {
781 // Load the browser dialog from resource
782 HWND hwndDialog;
783 uint32_t chromeFlags;
784
785 chrome->GetChromeFlags(&chromeFlags);
786 if ((chromeFlags & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL)
787 hwndDialog = CreateDialog(ghInstanceApp,
788 MAKEINTRESOURCE(IDD_BROWSER),
789 nullptr,
790 BrowserDlgProc);
791 else
792 hwndDialog = CreateDialog(ghInstanceApp,
793 MAKEINTRESOURCE(IDD_BROWSER_NC),
794 nullptr,
795 BrowserDlgProc);
796 if (!hwndDialog)
797 return nullptr;
798
799 // Stick a menu onto it
800 if (chromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR) {
801 HMENU hmenuDlg = LoadMenu(ghInstanceApp, MAKEINTRESOURCE(IDC_WINEMBED));
802 SetMenu(hwndDialog, hmenuDlg);
803 } else
804 SetMenu(hwndDialog, 0);
805
806 // Add some interesting URLs to the address drop down
807 HWND hwndAddress = GetDlgItem(hwndDialog, IDC_ADDRESS);
808 if (hwndAddress) {
809 for (int i = 0; i < sizeof(gDefaultURLs) / sizeof(gDefaultURLs[0]); i++)
810 {
811 SendMessage(hwndAddress, CB_ADDSTRING, 0, (LPARAM) gDefaultURLs[i]);
812 }
813 }
814
815 // Fetch the browser window handle
816 HWND hwndBrowser = GetDlgItem(hwndDialog, IDC_BROWSER);
817 SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, (LONG_PTR)chrome); // save the browser LONG_PTR.
818 SetWindowLongPtr(hwndBrowser, GWL_STYLE, GetWindowLongPtr(hwndBrowser, GWL_STYLE) | WS_CLIPCHILDREN);
819
820 // Activate the window
821 PostMessage(hwndDialog, WM_ACTIVATE, WA_ACTIVE, 0);
822
823 gDialogCount++;
824
825 return hwndBrowser;
826 }
827
828
829 //
830 // FUNCTION: Destroy()
831 //
832 // PURPOSE: Destroy the window specified by the chrome
833 //
834 void WebBrowserChromeUI::Destroy(nsIWebBrowserChrome* chrome)
835 {
836 nsCOMPtr<nsIWebBrowser> webBrowser;
837 nsCOMPtr<nsIWebNavigation> webNavigation;
838
839 chrome->GetWebBrowser(getter_AddRefs(webBrowser));
840 webNavigation = do_QueryInterface(webBrowser);
841 if (webNavigation)
842 webNavigation->Stop(nsIWebNavigation::STOP_ALL);
843
844 chrome->ExitModalEventLoop(NS_OK);
845
846 HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
847 if (hwndDlg == nullptr)
848 return;
849
850 // Explicitly destroy the embedded browser and then the chrome
851
852 // First the browser
853 nsCOMPtr<nsIWebBrowser> browser = nullptr;
854 chrome->GetWebBrowser(getter_AddRefs(browser));
855 nsCOMPtr<nsIBaseWindow> browserAsWin = do_QueryInterface(browser);
856 if (browserAsWin)
857 browserAsWin->Destroy();
858
859 // Now the chrome
860 chrome->SetWebBrowser(nullptr);
861 NS_RELEASE(chrome);
862 }
863
864
865 //
866 // FUNCTION: Called as the final act of a chrome object during its destructor
867 //
868 void WebBrowserChromeUI::Destroyed(nsIWebBrowserChrome* chrome)
869 {
870 HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
871 if (hwndDlg == nullptr)
872 {
873 return;
874 }
875
876 // Clear the window user data
877 HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
878 SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, 0);
879 DestroyWindow(hwndBrowser);
880 DestroyWindow(hwndDlg);
881
882 --gDialogCount;
883 if (gDialogCount == 0)
884 {
885 // Quit when there are no more browser objects
886 PostQuitMessage(0);
887 }
888 }
889
890
891 //
892 // FUNCTION: Set the input focus onto the browser window
893 //
894 void WebBrowserChromeUI::SetFocus(nsIWebBrowserChrome *chrome)
895 {
896 HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
897 if (hwndDlg == nullptr)
898 {
899 return;
900 }
901
902 HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
903 ::SetFocus(hwndBrowser);
904 }
905
906 //
907 // FUNCTION: UpdateStatusBarText()
908 //
909 // PURPOSE: Set the status bar text.
910 //
911 void WebBrowserChromeUI::UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const char16_t* aStatusText)
912 {
913 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
914 nsCString status;
915 if (aStatusText) {
916 nsString wStatusText(aStatusText);
917 NS_UTF16ToCString(wStatusText, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
918 status);
919 }
920
921 SetDlgItemText(hwndDlg, IDC_STATUS, status.get());
922 }
923
924
925 //
926 // FUNCTION: UpdateCurrentURI()
927 //
928 // PURPOSE: Updates the URL address field
929 //
930 void WebBrowserChromeUI::UpdateCurrentURI(nsIWebBrowserChrome *aChrome)
931 {
932 nsCOMPtr<nsIWebBrowser> webBrowser;
933 nsCOMPtr<nsIWebNavigation> webNavigation;
934 aChrome->GetWebBrowser(getter_AddRefs(webBrowser));
935 webNavigation = do_QueryInterface(webBrowser);
936
937 nsCOMPtr<nsIURI> currentURI;
938 webNavigation->GetCurrentURI(getter_AddRefs(currentURI));
939 if (currentURI)
940 {
941 nsCString uriString;
942 currentURI->GetAsciiSpec(uriString);
943 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
944 SetDlgItemText(hwndDlg, IDC_ADDRESS, uriString.get());
945 }
946 }
947
948
949 //
950 // FUNCTION: UpdateBusyState()
951 //
952 // PURPOSE: Refreshes the stop/go buttons in the browser dialog
953 //
954 void WebBrowserChromeUI::UpdateBusyState(nsIWebBrowserChrome *aChrome, bool aBusy)
955 {
956 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
957 HWND button;
958 button = GetDlgItem(hwndDlg, IDC_STOP);
959 if (button)
960 EnableWindow(button, aBusy);
961 button = GetDlgItem(hwndDlg, IDC_GO);
962 if (button)
963 EnableWindow(button, !aBusy);
964 UpdateUI(aChrome);
965 }
966
967
968 //
969 // FUNCTION: UpdateProgress()
970 //
971 // PURPOSE: Refreshes the progress bar in the browser dialog
972 //
973 void WebBrowserChromeUI::UpdateProgress(nsIWebBrowserChrome *aChrome, int32_t aCurrent, int32_t aMax)
974 {
975 HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
976 HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
977 if (aCurrent < 0)
978 {
979 aCurrent = 0;
980 }
981 if (aCurrent > aMax)
982 {
983 aMax = aCurrent + 20; // What to do?
984 }
985 if (hwndProgress)
986 {
987 SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, aMax));
988 SendMessage(hwndProgress, PBM_SETPOS, aCurrent, 0);
989 }
990 }
991
992 //
993 // FUNCTION: ShowContextMenu()
994 //
995 // PURPOSE: Display a context menu for the given node
996 //
997 void WebBrowserChromeUI::ShowContextMenu(nsIWebBrowserChrome *aChrome, uint32_t aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
998 {
999 // TODO code to test context flags and display a popup menu should go here
1000 }
1001
1002 //
1003 // FUNCTION: ShowTooltip()
1004 //
1005 // PURPOSE: Show a tooltip
1006 //
1007 void WebBrowserChromeUI::ShowTooltip(nsIWebBrowserChrome *aChrome, int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText)
1008 {
1009 // TODO code to show a tooltip should go here
1010 }
1011
1012 //
1013 // FUNCTION: HideTooltip()
1014 //
1015 // PURPOSE: Hide the tooltip
1016 //
1017 void WebBrowserChromeUI::HideTooltip(nsIWebBrowserChrome *aChrome)
1018 {
1019 // TODO code to hide a tooltip should go here
1020 }
1021
1022 void WebBrowserChromeUI::ShowWindow(nsIWebBrowserChrome *aChrome, bool aShow)
1023 {
1024 HWND win = GetBrowserDlgFromChrome(aChrome);
1025 ::ShowWindow(win, aShow ? SW_RESTORE : SW_HIDE);
1026 }
1027
1028 void WebBrowserChromeUI::SizeTo(nsIWebBrowserChrome *aChrome, int32_t aWidth, int32_t aHeight)
1029 {
1030 HWND hchrome = GetBrowserDlgFromChrome(aChrome);
1031 HWND hbrowser = GetBrowserFromChrome(aChrome);
1032 RECT chromeRect, browserRect;
1033
1034 ::GetWindowRect(hchrome, &chromeRect);
1035 ::GetWindowRect(hbrowser, &browserRect);
1036
1037 int32_t decoration_x = (browserRect.left - chromeRect.left) +
1038 (chromeRect.right - browserRect.right);
1039 int32_t decoration_y = (browserRect.top - chromeRect.top) +
1040 (chromeRect.bottom - browserRect.bottom);
1041
1042 ::MoveWindow(hchrome, chromeRect.left, chromeRect.top,
1043 aWidth+decoration_x,
1044 aHeight+decoration_y, TRUE);
1045 }
1046
1047 //
1048 // FUNCTION: GetResourceStringByID()
1049 //
1050 // PURPOSE: Get the resource string for the ID
1051 //
1052 void WebBrowserChromeUI::GetResourceStringById(int32_t aID, char ** aReturn)
1053 {
1054 char resBuf[MAX_LOADSTRING];
1055 int retval = LoadString( ghInstanceApp, aID, (LPTSTR)resBuf, sizeof(resBuf) );
1056 if (retval != 0)
1057 {
1058 size_t resLen = strlen(resBuf);
1059 *aReturn = (char *)calloc(resLen+1, sizeof(char *));
1060 if (!*aReturn) return;
1061 strncpy(*aReturn, resBuf, resLen);
1062 }
1063 return;
1064 }
1065
1066 //-----------------------------------------------------------------------------
1067 // AppCallbacks
1068 //-----------------------------------------------------------------------------
1069
1070 nsresult AppCallbacks::CreateBrowserWindow(uint32_t aChromeFlags,
1071 nsIWebBrowserChrome *aParent,
1072 nsIWebBrowserChrome **aNewWindow)
1073 {
1074 WebBrowserChrome * chrome = new WebBrowserChrome();
1075 if (!chrome)
1076 return NS_ERROR_FAILURE;
1077
1078 // the interface to return and one addref, which we assume will be
1079 // immediately released
1080 *aNewWindow = static_cast<nsIWebBrowserChrome*>(chrome);
1081 // now an extra addref; the window owns itself (to be released by
1082 // WebBrowserChromeUI::Destroy)
1083 NS_ADDREF(*aNewWindow);
1084
1085 chrome->SetChromeFlags(aChromeFlags);
1086 chrome->SetParent(aParent);
1087
1088 // Insert the browser
1089 nsCOMPtr<nsIWebBrowser> newBrowser;
1090 chrome->CreateBrowser(-1, -1, -1, -1, getter_AddRefs(newBrowser));
1091 if (!newBrowser)
1092 return NS_ERROR_FAILURE;
1093
1094 // Place it where we want it.
1095 ResizeEmbedding(static_cast<nsIWebBrowserChrome*>(chrome));
1096
1097 // if opened as chrome, it'll be made visible after the chrome has loaded.
1098 // otherwise, go ahead and show it now.
1099 if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME))
1100 WebBrowserChromeUI::ShowWindow(*aNewWindow, true);
1101
1102 return NS_OK;
1103 }
1104
1105 void AppCallbacks::EnableChromeWindow(nsIWebBrowserChrome *aWindow,
1106 bool aEnabled)
1107 {
1108 HWND hwnd = GetBrowserDlgFromChrome(aWindow);
1109 ::EnableWindow(hwnd, aEnabled ? TRUE : FALSE);
1110 }
1111
1112 uint32_t AppCallbacks::RunEventLoop(bool &aRunCondition)
1113 {
1114 MSG msg;
1115 HANDLE hFakeEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
1116
1117 while (aRunCondition ) {
1118 // Process pending messages
1119 while (::PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) {
1120 if (!::GetMessage(&msg, nullptr, 0, 0)) {
1121 // WM_QUIT
1122 aRunCondition = false;
1123 break;
1124 }
1125
1126 ::TranslateMessage(&msg);
1127 ::DispatchMessage(&msg);
1128 }
1129
1130 // Do idle stuff
1131 ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 100, QS_ALLEVENTS);
1132 }
1133 ::CloseHandle(hFakeEvent);
1134 return (uint32_t)msg.wParam;
1135 }

mercurial