90a3845bf7376903e7a489cd57ac86fb61367aab
[WebKit-https.git] / Tools / WinLauncher / WinLauncher.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2013 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2009, 2011 Brent Fulgham.  All rights reserved.
4  * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
5  * Copyright (C) 2013 Alex Christensen. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  */
28
29 #include "stdafx.h"
30 #include "WinLauncher.h"
31
32 #include "AccessibilityDelegate.h"
33 #include "DOMDefaultImpl.h"
34 #include "PrintWebUIDelegate.h"
35 #include "WinLauncherLibResource.h"
36 #include <WebKit/WebKitCOMAPI.h>
37 #include <wtf/ExportMacros.h>
38 #include <wtf/Platform.h>
39
40 #if USE(CF)
41 #include <CoreFoundation/CFRunLoop.h>
42 #endif
43
44 #include <algorithm>
45 #include <assert.h>
46 #include <comip.h>
47 #include <commctrl.h>
48 #include <commdlg.h>
49 #include <comutil.h>
50 #include <functional>
51 #include <objbase.h>
52 #include <shellapi.h>
53 #include <shlwapi.h>
54 #include <string>
55 #include <vector>
56 #include <wininet.h>
57
58 #define MAX_LOADSTRING 100
59 #define URLBAR_HEIGHT  24
60 #define CONTROLBUTTON_WIDTH 24
61
62 static const int maxHistorySize = 10;
63
64 typedef _com_ptr_t<_com_IIID<IWebFrame, &__uuidof(IWebFrame)>> IWebFramePtr;
65 typedef _com_ptr_t<_com_IIID<IWebHistory, &__uuidof(IWebHistory)>> IWebHistoryPtr;
66 typedef _com_ptr_t<_com_IIID<IWebHistoryItem, &__uuidof(IWebHistoryItem)>> IWebHistoryItemPtr;
67 typedef _com_ptr_t<_com_IIID<IWebInspector, &__uuidof(IWebInspector)>> IWebInspectorPtr;
68 typedef _com_ptr_t<_com_IIID<IWebMutableURLRequest, &__uuidof(IWebMutableURLRequest)>> IWebMutableURLRequestPtr;
69 typedef _com_ptr_t<_com_IIID<IWebPreferences, &__uuidof(IWebPreferences)>> IWebPreferencesPtr;
70 typedef _com_ptr_t<_com_IIID<IWebPreferencesPrivate, &__uuidof(IWebPreferencesPrivate)>> IWebPreferencesPrivatePtr;
71 typedef _com_ptr_t<_com_IIID<IWebView, &__uuidof(IWebView)>> IWebViewPtr;
72 typedef _com_ptr_t<_com_IIID<IWebViewPrivate, &__uuidof(IWebViewPrivate)>> IWebViewPrivatePtr;
73
74 // Global Variables:
75 HINSTANCE hInst;                                // current instance
76 HWND hMainWnd;
77 HWND hURLBarWnd;
78 HWND hBackButtonWnd;
79 HWND hForwardButtonWnd;
80 WNDPROC DefEditProc = 0;
81 WNDPROC DefButtonProc = 0;
82 WNDPROC DefWebKitProc = 0;
83 IWebInspectorPtr gInspector;
84 IWebViewPtr gWebView;
85 IWebViewPrivatePtr gWebViewPrivate;
86 IWebPreferencesPtr gStandardPreferences;
87 IWebPreferencesPrivatePtr gPrefsPrivate;
88 HWND gViewWindow = 0;
89 WinLauncherWebHost* gWebHost = 0;
90 PrintWebUIDelegate* gPrintDelegate = 0;
91 AccessibilityDelegate* gAccessibilityDelegate = 0;
92 IWebHistoryPtr gWebHistory;
93 std::vector<IWebHistoryItemPtr> gHistoryItems;
94 TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
95 TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
96
97 // Support moving the transparent window
98 POINT s_windowPosition = { 100, 100 };
99 SIZE s_windowSize = { 800, 400 };
100 bool s_usesLayeredWebView = false;
101 bool s_fullDesktop = false;
102
103 // Forward declarations of functions included in this code module:
104 ATOM                MyRegisterClass(HINSTANCE hInstance);
105 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
106 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
107 LRESULT CALLBACK    EditProc(HWND, UINT, WPARAM, LPARAM);
108 LRESULT CALLBACK    BackButtonProc(HWND, UINT, WPARAM, LPARAM);
109 LRESULT CALLBACK    ForwardButtonProc(HWND, UINT, WPARAM, LPARAM);
110 LRESULT CALLBACK    ReloadButtonProc(HWND, UINT, WPARAM, LPARAM);
111
112 static void loadURL(BSTR urlBStr);
113
114 static bool usesLayeredWebView()
115 {
116     return s_usesLayeredWebView;
117 }
118
119 static bool shouldUseFullDesktop()
120 {
121     return s_fullDesktop;
122 }
123
124 class SimpleEventListener : public DOMEventListener {
125 public:
126     SimpleEventListener(LPWSTR type)
127     {
128         wcsncpy_s(m_eventType, 100, type, 100);
129         m_eventType[99] = 0;
130     }
131
132     virtual HRESULT STDMETHODCALLTYPE handleEvent(IDOMEvent* evt)
133     {
134         wchar_t message[255];
135         wcscpy_s(message, 255, m_eventType);
136         wcscat_s(message, 255, L" event fired!");
137         ::MessageBox(0, message, L"Event Handler", MB_OK);
138         return S_OK;
139     }
140
141 private:
142     wchar_t m_eventType[100];
143 };
144
145 typedef _com_ptr_t<_com_IIID<IWebDataSource, &__uuidof(IWebDataSource)>> IWebDataSourcePtr;
146
147 HRESULT WinLauncherWebHost::updateAddressBar(IWebView* webView)
148 {
149     IWebFramePtr mainFrame;
150     HRESULT hr = webView->mainFrame(&mainFrame.GetInterfacePtr());
151     if (FAILED(hr))
152         return 0;
153
154     IWebDataSourcePtr dataSource;
155     hr = mainFrame->dataSource(&dataSource.GetInterfacePtr());
156     if (FAILED(hr) || !dataSource)
157         hr = mainFrame->provisionalDataSource(&dataSource.GetInterfacePtr());
158     if (FAILED(hr) || !dataSource)
159         return 0;
160
161     IWebMutableURLRequestPtr request;
162     hr = dataSource->request(&request.GetInterfacePtr());
163     if (FAILED(hr) || !request)
164         return 0;
165
166     _bstr_t frameURL;
167     hr = request->mainDocumentURL(frameURL.GetAddress());
168     if (FAILED(hr))
169         return 0;
170
171     ::SendMessage(hURLBarWnd, static_cast<UINT>(WM_SETTEXT), 0, reinterpret_cast<LPARAM>(frameURL.GetBSTR()));
172
173     return 0;
174 }
175
176 HRESULT WinLauncherWebHost::didFailProvisionalLoadWithError(IWebView*, IWebError *error, IWebFrame*)
177 {
178     _bstr_t errorDescription;
179     HRESULT hr = error->localizedDescription(errorDescription.GetAddress());
180     if (FAILED(hr))
181         errorDescription = L"Failed to load page and to localize error description.";
182
183     ::MessageBoxW(0, static_cast<LPCWSTR>(errorDescription), L"Error", MB_APPLMODAL | MB_OK);
184
185     return S_OK;
186 }
187
188 HRESULT STDMETHODCALLTYPE WinLauncherWebHost::QueryInterface(REFIID riid, void** ppvObject)
189 {
190     *ppvObject = 0;
191     if (IsEqualGUID(riid, IID_IUnknown))
192         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
193     else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate))
194         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
195     else
196         return E_NOINTERFACE;
197
198     AddRef();
199     return S_OK;
200 }
201
202 ULONG STDMETHODCALLTYPE WinLauncherWebHost::AddRef(void)
203 {
204     return ++m_refCount;
205 }
206
207 ULONG STDMETHODCALLTYPE WinLauncherWebHost::Release(void)
208 {
209     ULONG newRef = --m_refCount;
210     if (!newRef)
211         delete(this);
212
213     return newRef;
214 }
215
216 static void updateMenuItemForHistoryItem(HMENU menu, IWebHistoryItem& historyItem, int currentHistoryItem)
217 {
218     UINT menuID = IDM_HISTORY_LINK0 + currentHistoryItem;
219
220     MENUITEMINFO menuItemInfo = {0};
221     menuItemInfo.cbSize = sizeof(MENUITEMINFO);
222     menuItemInfo.fMask = MIIM_TYPE;
223     menuItemInfo.fType = MFT_STRING;
224
225     _bstr_t title;
226     historyItem.title(title.GetAddress());
227     menuItemInfo.dwTypeData = static_cast<LPWSTR>(title);
228
229     ::SetMenuItemInfo(menu, menuID, FALSE, &menuItemInfo);
230     ::EnableMenuItem(menu, menuID, MF_BYCOMMAND | MF_ENABLED);
231 }
232
233 static void showLastVisitedSites(IWebView& webView)
234 {
235     HMENU menu = ::GetMenu(hMainWnd);
236
237     _com_ptr_t<_com_IIID<IWebBackForwardList, &__uuidof(IWebBackForwardList)>> backForwardList;
238     HRESULT hr = webView.backForwardList(&backForwardList.GetInterfacePtr());
239     if (FAILED(hr))
240         return;
241
242     int capacity = 0;
243     hr = backForwardList->capacity(&capacity);
244     if (FAILED(hr))
245         return;
246
247     int backCount = 0;
248     hr = backForwardList->backListCount(&backCount);
249     if (FAILED(hr))
250         return;
251
252     UINT backSetting = MF_BYCOMMAND | (backCount) ? MF_ENABLED : MF_DISABLED;
253     ::EnableMenuItem(menu, IDM_HISTORY_BACKWARD, backSetting);
254
255     int forwardCount = 0;
256     hr = backForwardList->forwardListCount(&forwardCount);
257     if (FAILED(hr))
258         return;
259
260     UINT forwardSetting = MF_BYCOMMAND | (forwardCount) ? MF_ENABLED : MF_DISABLED;
261     ::EnableMenuItem(menu, IDM_HISTORY_FORWARD, forwardSetting);
262
263     IWebHistoryItemPtr currentItem;
264     hr = backForwardList->currentItem(&currentItem.GetInterfacePtr());
265     if (FAILED(hr))
266         return;
267
268     hr = gWebHistory->addItems(1, &currentItem.GetInterfacePtr());
269     if (FAILED(hr))
270         return;
271
272     _com_ptr_t<_com_IIID<IWebHistoryPrivate, &__uuidof(IWebHistoryPrivate)>> webHistory;
273     hr = gWebHistory->QueryInterface(IID_IWebHistoryPrivate, reinterpret_cast<void**>(&webHistory.GetInterfacePtr()));
274     if (FAILED(hr))
275         return;
276
277     int totalListCount = 0;
278     hr = webHistory->allItems(&totalListCount, 0);
279     if (FAILED(hr))
280         return;
281
282     gHistoryItems.resize(totalListCount);
283
284     std::vector<IWebHistoryItem*> historyToLoad(totalListCount);
285     hr = webHistory->allItems(&totalListCount, historyToLoad.data());
286     if (FAILED(hr))
287         return;
288
289     size_t i = 0;
290     for (auto cur = historyToLoad.begin(); cur != historyToLoad.end(); ++cur) {
291         gHistoryItems[i].Attach(*cur);
292         ++i;
293     }
294
295     int allItemsOffset = 0;
296     if (totalListCount > maxHistorySize)
297         allItemsOffset = totalListCount - maxHistorySize;
298
299     int currentHistoryItem = 0;
300     for (int i = 0; i < totalListCount; ++i) {
301         updateMenuItemForHistoryItem(menu, *(gHistoryItems[allItemsOffset + currentHistoryItem]), currentHistoryItem);
302         ++currentHistoryItem;
303     }
304
305     // Hide any history we aren't using yet.
306     for (int i = currentHistoryItem; i < maxHistorySize; ++i)
307         ::EnableMenuItem(menu, IDM_HISTORY_LINK0 + i, MF_BYCOMMAND | MF_DISABLED);
308 }
309
310 typedef _com_ptr_t<_com_IIID<IDOMDocument, &__uuidof(IDOMDocument)>> IDOMDocumentPtr;
311 typedef _com_ptr_t<_com_IIID<IDOMElement, &__uuidof(IDOMElement)>> IDOMElementPtr;
312 typedef _com_ptr_t<_com_IIID<IDOMEventTarget, &__uuidof(IDOMEventTarget)>> IDOMEventTargetPtr;
313
314 HRESULT WinLauncherWebHost::didFinishLoadForFrame(IWebView* webView, IWebFrame* frame)
315 {
316     IDOMDocumentPtr doc;
317     frame->DOMDocument(&doc.GetInterfacePtr());
318
319     IDOMElementPtr element;
320     IDOMEventTargetPtr target;
321
322     showLastVisitedSites(*webView);
323
324     // The following is for the test page:
325     HRESULT hr = doc->getElementById(L"webkit logo", &element.GetInterfacePtr());
326     if (!SUCCEEDED(hr))
327         return hr;
328
329     hr = element->QueryInterface(IID_IDOMEventTarget, reinterpret_cast<void**>(&target.GetInterfacePtr()));
330     if (!SUCCEEDED(hr))
331         return hr;
332
333     hr = target->addEventListener(L"click", new SimpleEventListener (L"webkit logo click"), FALSE);
334     if (!SUCCEEDED(hr))
335         return hr;
336
337     return hr;
338 }
339
340 static void resizeSubViews()
341 {
342     if (usesLayeredWebView() || !gViewWindow)
343         return;
344
345     RECT rcClient;
346     GetClientRect(hMainWnd, &rcClient);
347     MoveWindow(hBackButtonWnd, 0, 0, CONTROLBUTTON_WIDTH, URLBAR_HEIGHT, TRUE);
348     MoveWindow(hForwardButtonWnd, CONTROLBUTTON_WIDTH, 0, CONTROLBUTTON_WIDTH, URLBAR_HEIGHT, TRUE);
349     MoveWindow(hURLBarWnd, CONTROLBUTTON_WIDTH * 2, 0, rcClient.right, URLBAR_HEIGHT, TRUE);
350     MoveWindow(gViewWindow, 0, URLBAR_HEIGHT, rcClient.right, rcClient.bottom - URLBAR_HEIGHT, TRUE);
351 }
352
353 static void subclassForLayeredWindow()
354 {
355     hMainWnd = gViewWindow;
356 #if defined _M_AMD64 || defined _WIN64
357     DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hMainWnd, GWLP_WNDPROC));
358     ::SetWindowLongPtr(hMainWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc));
359 #else
360     DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLong(hMainWnd, GWL_WNDPROC));
361     ::SetWindowLong(hMainWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc));
362 #endif
363 }
364
365 static void computeFullDesktopFrame()
366 {
367     RECT desktop;
368     if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, static_cast<void*>(&desktop), 0))
369         return;
370
371     s_windowPosition.x = 0;
372     s_windowPosition.y = 0;
373     s_windowSize.cx = desktop.right - desktop.left;
374     s_windowSize.cy = desktop.bottom - desktop.top;
375 }
376
377 BOOL WINAPI DllMain(HINSTANCE dllInstance, DWORD reason, LPVOID)
378 {
379     if (reason == DLL_PROCESS_ATTACH)
380         hInst = dllInstance;
381
382     return TRUE;
383 }
384
385 static bool setToDefaultPreferences()
386 {
387     HRESULT hr = gStandardPreferences->QueryInterface(IID_IWebPreferencesPrivate, reinterpret_cast<void**>(&gPrefsPrivate.GetInterfacePtr()));
388     if (!SUCCEEDED(hr))
389         return false;
390
391 #if USE(CG)
392     gStandardPreferences->setAVFoundationEnabled(TRUE);
393     gPrefsPrivate->setAcceleratedCompositingEnabled(TRUE);
394 #endif
395
396     gPrefsPrivate->setFullScreenEnabled(TRUE);
397     gPrefsPrivate->setShowDebugBorders(FALSE);
398     gPrefsPrivate->setShowRepaintCounter(FALSE);
399
400     gStandardPreferences->setLoadsImagesAutomatically(TRUE);
401     gPrefsPrivate->setAuthorAndUserStylesEnabled(TRUE);
402     gStandardPreferences->setJavaScriptEnabled(TRUE);
403     gPrefsPrivate->setAllowUniversalAccessFromFileURLs(FALSE);
404     gPrefsPrivate->setAllowFileAccessFromFileURLs(TRUE);
405
406     gPrefsPrivate->setDeveloperExtrasEnabled(TRUE);
407
408     return true;
409 }
410
411
412 #if USE(CF)
413 extern "C" void _CFRunLoopSetWindowsMessageQueueMask(CFRunLoopRef, uint32_t, CFStringRef);
414 #endif
415
416 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(HINSTANCE, HINSTANCE, LPTSTR, int nCmdShow)
417 {
418 #ifdef _CRTDBG_MAP_ALLOC
419     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
420     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
421 #endif
422
423      // TODO: Place code here.
424     MSG msg = {0};
425     HACCEL hAccelTable;
426
427     INITCOMMONCONTROLSEX InitCtrlEx;
428
429     InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
430     InitCtrlEx.dwICC  = 0x00004000; //ICC_STANDARD_CLASSES;
431     InitCommonControlsEx(&InitCtrlEx);
432
433     _bstr_t requestedURL;
434     int argc = 0;
435     WCHAR** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
436     for (int i = 1; i < argc; ++i) {
437         if (!wcsicmp(argv[i], L"--transparent"))
438             s_usesLayeredWebView = true;
439         else if (!wcsicmp(argv[i], L"--desktop"))
440             s_fullDesktop = true;
441         else if (!requestedURL)
442             requestedURL = argv[i];
443     }
444
445     // Initialize global strings
446     LoadString(hInst, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
447     LoadString(hInst, IDC_WINLAUNCHER, szWindowClass, MAX_LOADSTRING);
448     MyRegisterClass(hInst);
449
450     if (shouldUseFullDesktop())
451         computeFullDesktopFrame();
452
453     // Init COM
454     OleInitialize(NULL);
455
456     if (usesLayeredWebView()) {
457         hURLBarWnd = CreateWindow(L"EDIT", L"Type URL Here",
458                     WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 
459                     s_windowPosition.x, s_windowPosition.y + s_windowSize.cy, s_windowSize.cx, URLBAR_HEIGHT,
460                     0,
461                     0,
462                     hInst, 0);
463     } else {
464         hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
465                        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInst, 0);
466
467         if (!hMainWnd)
468             return FALSE;
469
470         hBackButtonWnd = CreateWindow(L"BUTTON", L"<", WS_CHILD | WS_VISIBLE  | BS_TEXT, 0, 0, 0, 0, hMainWnd, 0, hInst, 0);
471         hForwardButtonWnd = CreateWindow(L"BUTTON", L">", WS_CHILD | WS_VISIBLE  | BS_TEXT, CONTROLBUTTON_WIDTH, 0, 0, 0, hMainWnd, 0, hInst, 0);
472         hURLBarWnd = CreateWindow(L"EDIT", 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, CONTROLBUTTON_WIDTH * 2, 0, 0, 0, hMainWnd, 0, hInst, 0);
473
474         ShowWindow(hMainWnd, nCmdShow);
475         UpdateWindow(hMainWnd);
476     }
477
478     DefEditProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hURLBarWnd, GWLP_WNDPROC));
479     DefButtonProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hBackButtonWnd, GWLP_WNDPROC));
480     SetWindowLongPtr(hURLBarWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(EditProc));
481     SetWindowLongPtr(hBackButtonWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(BackButtonProc));
482     SetWindowLongPtr(hForwardButtonWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(ForwardButtonProc));
483
484     SetFocus(hURLBarWnd);
485
486     RECT clientRect = { s_windowPosition.x, s_windowPosition.y, s_windowPosition.x + s_windowSize.cx, s_windowPosition.y + s_windowSize.cy };
487
488     IWebPreferencesPtr tmpPreferences;
489     if (FAILED(WebKitCreateInstance(CLSID_WebPreferences, 0, IID_IWebPreferences, reinterpret_cast<void**>(&tmpPreferences.GetInterfacePtr()))))
490         goto exit;
491
492     if (FAILED(tmpPreferences->standardPreferences(&gStandardPreferences.GetInterfacePtr())))
493         goto exit;
494
495     if (!setToDefaultPreferences())
496         goto exit;
497
498     HRESULT hr = WebKitCreateInstance(CLSID_WebView, 0, IID_IWebView, reinterpret_cast<void**>(&gWebView.GetInterfacePtr()));
499     if (FAILED(hr))
500         goto exit;
501
502     hr = gWebView->QueryInterface(IID_IWebViewPrivate, reinterpret_cast<void**>(&gWebViewPrivate.GetInterfacePtr()));
503     if (FAILED(hr))
504         goto exit;
505
506     hr = WebKitCreateInstance(CLSID_WebHistory, 0, __uuidof(gWebHistory), reinterpret_cast<void**>(&gWebHistory.GetInterfacePtr()));
507     if (FAILED(hr))
508         goto exit;
509
510     gWebHost = new WinLauncherWebHost();
511     gWebHost->AddRef();
512     hr = gWebView->setFrameLoadDelegate(gWebHost);
513     if (FAILED(hr))
514         goto exit;
515
516     gPrintDelegate = new PrintWebUIDelegate;
517     gPrintDelegate->AddRef();
518     hr = gWebView->setUIDelegate(gPrintDelegate);
519     if (FAILED (hr))
520         goto exit;
521
522     gAccessibilityDelegate = new AccessibilityDelegate;
523     gAccessibilityDelegate->AddRef();
524     hr = gWebView->setAccessibilityDelegate(gAccessibilityDelegate);
525     if (FAILED (hr))
526         goto exit;
527
528     hr = gWebView->setHostWindow(reinterpret_cast<OLE_HANDLE>(hMainWnd));
529     if (FAILED(hr))
530         goto exit;
531
532     hr = gWebView->initWithFrame(clientRect, 0, 0);
533     if (FAILED(hr))
534         goto exit;
535
536     if (!requestedURL) {
537         IWebFramePtr frame;
538         hr = gWebView->mainFrame(&frame.GetInterfacePtr());
539         if (FAILED(hr))
540             goto exit;
541
542         _bstr_t defaultHTML(L"<p style=\"background-color: #00FF00\">Testing</p><img id=\"webkit logo\" src=\"http://webkit.org/images/icon-gold.png\" alt=\"Face\"><div style=\"border: solid blue; background: white;\" contenteditable=\"true\">div with blue border</div><ul><li>foo<li>bar<li>baz</ul>");
543         frame->loadHTMLString(defaultHTML.GetBSTR(), 0);
544     }
545
546     hr = gWebViewPrivate->setTransparent(usesLayeredWebView());
547     if (FAILED(hr))
548         goto exit;
549
550     hr = gWebViewPrivate->setUsesLayeredWindow(usesLayeredWebView());
551     if (FAILED(hr))
552         goto exit;
553
554     hr = gWebViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&gViewWindow));
555     if (FAILED(hr) || !gViewWindow)
556         goto exit;
557
558     if (usesLayeredWebView())
559         subclassForLayeredWindow();
560
561     resizeSubViews();
562
563     ShowWindow(gViewWindow, nCmdShow);
564     UpdateWindow(gViewWindow);
565
566     hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_WINLAUNCHER));
567
568     if (requestedURL.length())
569         loadURL(requestedURL.GetBSTR());
570
571     // Main message loop:
572 #if USE(CF)
573     _CFRunLoopSetWindowsMessageQueueMask(CFRunLoopGetMain(), QS_ALLINPUT | QS_ALLPOSTMESSAGE, kCFRunLoopDefaultMode);
574     CFRunLoopRun();
575 #else
576     while (GetMessage(&msg, NULL, 0, 0)) {
577         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
578             TranslateMessage(&msg);
579             DispatchMessage(&msg);
580         }
581     }
582 #endif
583
584 exit:
585     gPrintDelegate->Release();
586
587     shutDownWebKit();
588 #ifdef _CRTDBG_MAP_ALLOC
589     _CrtDumpMemoryLeaks();
590 #endif
591
592     // Shut down COM.
593     OleUninitialize();
594     
595     return static_cast<int>(msg.wParam);
596 }
597
598 ATOM MyRegisterClass(HINSTANCE hInstance)
599 {
600     WNDCLASSEX wcex;
601
602     wcex.cbSize = sizeof(WNDCLASSEX);
603
604     wcex.style          = CS_HREDRAW | CS_VREDRAW;
605     wcex.lpfnWndProc    = WndProc;
606     wcex.cbClsExtra     = 0;
607     wcex.cbWndExtra     = 0;
608     wcex.hInstance      = hInstance;
609     wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINLAUNCHER));
610     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
611     wcex.hbrBackground  = 0;
612     wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_WINLAUNCHER);
613     wcex.lpszClassName  = szWindowClass;
614     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
615
616     return RegisterClassEx(&wcex);
617 }
618
619 static BOOL CALLBACK AbortProc(HDC hDC, int Error)
620 {
621     MSG msg;
622     while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
623         ::TranslateMessage(&msg);
624         ::DispatchMessage(&msg);
625     }
626
627     return TRUE;
628 }
629
630 static HDC getPrinterDC()
631 {
632     PRINTDLG pdlg;
633     memset(&pdlg, 0, sizeof(PRINTDLG));
634     pdlg.lStructSize = sizeof(PRINTDLG);
635     pdlg.Flags = PD_PRINTSETUP | PD_RETURNDC;
636
637     ::PrintDlg(&pdlg);
638
639     return pdlg.hDC;
640 }
641
642 static void initDocStruct(DOCINFO* di, TCHAR* docname)
643 {
644     memset(di, 0, sizeof(DOCINFO));
645     di->cbSize = sizeof(DOCINFO);
646     di->lpszDocName = docname;
647 }
648
649 typedef _com_ptr_t<_com_IIID<IWebFramePrivate, &__uuidof(IWebFramePrivate)>> IWebFramePrivatePtr;
650
651 void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
652 {
653     HDC printDC = getPrinterDC();
654     if (!printDC) {
655         ::MessageBoxW(0, L"Error creating printing DC", L"Error", MB_APPLMODAL | MB_OK);
656         return;
657     }
658
659     if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) {
660         ::MessageBoxW(0, L"Error setting up AbortProc", L"Error", MB_APPLMODAL | MB_OK);
661         return;
662     }
663
664     IWebFramePtr frame;
665     IWebFramePrivatePtr framePrivate;
666     if (FAILED(gWebView->mainFrame(&frame.GetInterfacePtr())))
667         return;
668
669     if (FAILED(frame->QueryInterface(&framePrivate.GetInterfacePtr())))
670         return;
671
672     framePrivate->setInPrintingMode(TRUE, printDC);
673
674     UINT pageCount = 0;
675     framePrivate->getPrintedPageCount(printDC, &pageCount);
676
677     DOCINFO di;
678     initDocStruct(&di, L"WebKit Doc");
679     ::StartDoc(printDC, &di);
680
681     // FIXME: Need CoreGraphics implementation
682     void* graphicsContext = 0;
683     for (size_t page = 1; page <= pageCount; ++page) {
684         ::StartPage(printDC);
685         framePrivate->spoolPages(printDC, page, page, graphicsContext);
686         ::EndPage(printDC);
687     }
688
689     framePrivate->setInPrintingMode(FALSE, printDC);
690
691     ::EndDoc(printDC);
692     ::DeleteDC(printDC);
693 }
694
695 static void ToggleMenuItem(HWND hWnd, UINT menuID)
696 {
697     HMENU menu = ::GetMenu(hWnd);
698
699     MENUITEMINFO info;
700     ::memset(&info, 0x00, sizeof(info));
701     info.cbSize = sizeof(info);
702     info.fMask = MIIM_STATE;
703
704     if (!::GetMenuItemInfo(menu, menuID, FALSE, &info))
705         return;
706
707     BOOL newState = !(info.fState & MFS_CHECKED);
708
709     if (!gStandardPreferences || !gPrefsPrivate)
710         return;
711
712     switch (menuID) {
713     case IDM_AVFOUNDATION:
714         gStandardPreferences->setAVFoundationEnabled(newState);
715         break;
716     case IDM_ACC_COMPOSITING:
717         gPrefsPrivate->setAcceleratedCompositingEnabled(newState);
718         break;
719     case IDM_WK_FULLSCREEN:
720         gPrefsPrivate->setFullScreenEnabled(newState);
721         break;
722     case IDM_COMPOSITING_BORDERS:
723         gPrefsPrivate->setShowDebugBorders(newState);
724         gPrefsPrivate->setShowRepaintCounter(newState);
725         break;
726     case IDM_DISABLE_IMAGES:
727         gStandardPreferences->setLoadsImagesAutomatically(!newState);
728         break;
729     case IDM_DISABLE_STYLES:
730         gPrefsPrivate->setAuthorAndUserStylesEnabled(!newState);
731         break;
732     case IDM_DISABLE_JAVASCRIPT:
733         gStandardPreferences->setJavaScriptEnabled(!newState);
734         break;
735     case IDM_DISABLE_LOCAL_FILE_RESTRICTIONS:
736         gPrefsPrivate->setAllowUniversalAccessFromFileURLs(newState);
737         gPrefsPrivate->setAllowFileAccessFromFileURLs(newState);
738         break;
739     }
740
741     info.fState = (newState) ? MFS_CHECKED : MFS_UNCHECKED;
742
743     ::SetMenuItemInfo(menu, menuID, FALSE, &info);
744 }
745
746 static void LaunchInspector(HWND hwnd)
747 {
748     if (!gWebViewPrivate)
749         return;
750
751     if (!SUCCEEDED(gWebViewPrivate->inspector(&gInspector.GetInterfacePtr())))
752         return;
753
754     gInspector->show();
755 }
756
757 static void NavigateForwardOrBackward(HWND hWnd, UINT menuID)
758 {
759     if (!gWebView)
760         return;
761
762     BOOL wentBackOrForward = FALSE;
763     if (IDM_HISTORY_FORWARD == menuID)
764         gWebView->goForward(&wentBackOrForward);
765     else
766         gWebView->goBack(&wentBackOrForward);
767 }
768
769 static void NavigateToHistory(HWND hWnd, UINT menuID)
770 {
771     if (!gWebView)
772         return;
773
774     int historyEntry = menuID - IDM_HISTORY_LINK0;
775     if (historyEntry > gHistoryItems.size())
776         return;
777
778     IWebHistoryItemPtr desiredHistoryItem = gHistoryItems[historyEntry];
779     if (!desiredHistoryItem)
780         return;
781
782     BOOL succeeded = FALSE;
783     gWebView->goToBackForwardItem(desiredHistoryItem, &succeeded);
784
785     _bstr_t frameURL;
786     desiredHistoryItem->URLString(frameURL.GetAddress());
787
788     ::SendMessage(hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL.GetBSTR());
789 }
790
791 static const int dragBarHeight = 30;
792
793 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
794 {
795     WNDPROC parentProc = usesLayeredWebView() ? DefWebKitProc : DefWindowProc;
796
797     switch (message) {
798     case WM_NCHITTEST:
799         if (usesLayeredWebView()) {
800             RECT window;
801             ::GetWindowRect(hWnd, &window);
802             // For testing our transparent window, we need a region to use as a handle for
803             // dragging. The right way to do this would be to query the web view to see what's
804             // under the mouse. However, for testing purposes we just use an arbitrary
805             // 30 pixel band at the top of the view as an arbitrary gripping location.
806             //
807             // When we are within this bad, return HT_CAPTION to tell Windows we want to
808             // treat this region as if it were the title bar on a normal window.
809             int y = HIWORD(lParam);
810
811             if ((y > window.top) && (y < window.top + dragBarHeight))
812                 return HTCAPTION;
813         }
814         return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
815     case WM_COMMAND: {
816         int wmId = LOWORD(wParam);
817         int wmEvent = HIWORD(wParam);
818         if (wmId >= IDM_HISTORY_LINK0 && wmId <= IDM_HISTORY_LINK9) {
819             NavigateToHistory(hWnd, wmId);
820             break;
821         }
822         // Parse the menu selections:
823         switch (wmId) {
824         case IDM_ABOUT:
825             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
826             break;
827         case IDM_EXIT:
828             DestroyWindow(hWnd);
829             break;
830         case IDM_PRINT:
831             PrintView(hWnd, message, wParam, lParam);
832             break;
833         case IDM_WEB_INSPECTOR:
834             LaunchInspector(hWnd);
835             break;
836         case IDM_HISTORY_BACKWARD:
837         case IDM_HISTORY_FORWARD:
838             NavigateForwardOrBackward(hWnd, wmId);
839             break;
840         case IDM_AVFOUNDATION:
841         case IDM_ACC_COMPOSITING:
842         case IDM_WK_FULLSCREEN:
843         case IDM_COMPOSITING_BORDERS:
844         case IDM_DISABLE_IMAGES:
845         case IDM_DISABLE_STYLES:
846         case IDM_DISABLE_JAVASCRIPT:
847         case IDM_DISABLE_LOCAL_FILE_RESTRICTIONS:
848             ToggleMenuItem(hWnd, wmId);
849             break;
850         default:
851             return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
852         }
853         }
854         break;
855     case WM_DESTROY:
856 #if USE(CF)
857         CFRunLoopStop(CFRunLoopGetMain());
858 #endif
859         PostQuitMessage(0);
860         break;
861     case WM_SIZE:
862         if (!gWebView || usesLayeredWebView())
863            return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
864
865         resizeSubViews();
866         break;
867     default:
868         return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
869     }
870
871     return 0;
872 }
873
874 LRESULT CALLBACK EditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
875 {
876     switch (message) {
877     case WM_CHAR:
878         if (wParam == 13) { // Enter Key
879             wchar_t strPtr[INTERNET_MAX_URL_LENGTH];
880             *((LPWORD)strPtr) = INTERNET_MAX_URL_LENGTH; 
881             int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr);
882
883             strPtr[strLen] = 0;
884             _bstr_t bstr(strPtr);
885             loadURL(bstr.GetBSTR());
886
887             return 0;
888         } 
889     default:
890         return CallWindowProc(DefEditProc, hDlg, message, wParam, lParam);
891     }
892 }
893
894 LRESULT CALLBACK BackButtonProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
895 {
896     BOOL wentBack = FALSE;
897     switch (message) {
898     case WM_LBUTTONUP:
899         gWebView->goBack(&wentBack);
900     default:
901         return CallWindowProc(DefButtonProc, hDlg, message, wParam, lParam);
902     }
903 }
904
905 LRESULT CALLBACK ForwardButtonProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
906 {
907     BOOL wentForward = FALSE;
908     switch (message) {
909     case WM_LBUTTONUP:
910         gWebView->goForward(&wentForward);
911     default:
912         return CallWindowProc(DefButtonProc, hDlg, message, wParam, lParam);
913     }
914 }
915
916 // Message handler for about box.
917 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
918 {
919     UNREFERENCED_PARAMETER(lParam);
920     switch (message) {
921     case WM_INITDIALOG:
922         return (INT_PTR)TRUE;
923
924     case WM_COMMAND:
925         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
926             EndDialog(hDlg, LOWORD(wParam));
927             return (INT_PTR)TRUE;
928         }
929         break;
930     }
931     return (INT_PTR)FALSE;
932 }
933
934 static void loadURL(BSTR passedURL)
935 {
936     _bstr_t urlBStr(passedURL);
937     if (!!urlBStr && (::PathFileExists(urlBStr) || ::PathIsUNC(urlBStr))) {
938         TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
939         DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]);
940
941         if (SUCCEEDED(::UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0)))
942             urlBStr = fileURL;
943     }
944
945     IWebFramePtr frame;
946     HRESULT hr = gWebView->mainFrame(&frame.GetInterfacePtr());
947     if (FAILED(hr))
948         return;
949
950     IWebMutableURLRequestPtr request;
951     hr = WebKitCreateInstance(CLSID_WebMutableURLRequest, 0, IID_IWebMutableURLRequest, (void**)&request);
952     if (FAILED(hr))
953         return;
954
955     hr = request->initWithURL(wcsstr(static_cast<wchar_t*>(urlBStr), L"://") ? urlBStr : _bstr_t(L"http://") + urlBStr, WebURLRequestUseProtocolCachePolicy, 60);
956     if (FAILED(hr))
957         return;
958
959     _bstr_t methodBStr(L"GET");
960     hr = request->setHTTPMethod(methodBStr);
961     if (FAILED(hr))
962         return;
963
964     hr = frame->loadRequest(request);
965     if (FAILED(hr))
966         return;
967
968     SetFocus(gViewWindow);
969 }