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