d9f46bd3646233dd884ec0bf640786d754fcfd5a
[WebKit-https.git] / Tools / WinLauncher / WinLauncher.cpp
1 /*
2  * Copyright (C) 2006, 2008 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 "DOMDefaultImpl.h"
32 #include "PrintWebUIDelegate.h"
33 #include <WebKit/WebKitCOMAPI.h>
34
35 #include <commctrl.h>
36 #include <commdlg.h>
37 #include <objbase.h>
38 #include <shellapi.h>
39 #include <shlwapi.h>
40 #include <string>
41 #include <wininet.h>
42
43 #define MAX_LOADSTRING 100
44 #define URLBAR_HEIGHT  24
45
46 // Global Variables:
47 HINSTANCE hInst;                                // current instance
48 HWND hMainWnd;
49 HWND hURLBarWnd;
50 WNDPROC DefEditProc = 0;
51 WNDPROC DefWebKitProc = 0;
52 IWebView* gWebView = 0;
53 IWebViewPrivate* gWebViewPrivate = 0;
54 HWND gViewWindow = 0;
55 WinLauncherWebHost* gWebHost = 0;
56 PrintWebUIDelegate* gPrintDelegate = 0;
57 TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
58 TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
59
60 // Support moving the transparent window
61 POINT s_windowPosition = { 100, 100 };
62 SIZE s_windowSize = { 800, 400 };
63 bool s_usesLayeredWebView = false;
64 bool s_fullDesktop = false;
65
66 // Forward declarations of functions included in this code module:
67 ATOM                MyRegisterClass(HINSTANCE hInstance);
68 BOOL                InitInstance(HINSTANCE, int);
69 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
70 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
71 LRESULT CALLBACK    MyEditProc(HWND, UINT, WPARAM, LPARAM);
72
73 static void loadURL(BSTR urlBStr);
74
75 static bool usesLayeredWebView()
76 {
77     return s_usesLayeredWebView;
78 }
79
80 static bool shouldUseFullDesktop()
81 {
82     return s_fullDesktop;
83 }
84
85 class SimpleEventListener : public DOMEventListener {
86 public:
87     SimpleEventListener(LPWSTR type)
88     {
89         wcsncpy_s(m_eventType, 100, type, 100);
90         m_eventType[99] = 0;
91     }
92
93     virtual HRESULT STDMETHODCALLTYPE handleEvent(IDOMEvent* evt)
94     {
95         wchar_t message[255];
96         wcscpy_s(message, 255, m_eventType);
97         wcscat_s(message, 255, L" event fired!");
98         ::MessageBox(0, message, L"Event Handler", MB_OK);
99         return S_OK;
100     }
101
102 private:
103     wchar_t m_eventType[100];
104 };
105
106 HRESULT WinLauncherWebHost::updateAddressBar(IWebView* webView)
107 {
108     IWebFrame* mainFrame = 0;
109     IWebDataSource* dataSource = 0;
110     IWebMutableURLRequest* request = 0;
111     BSTR frameURL = 0;
112
113     HRESULT hr = S_OK;
114
115     hr = webView->mainFrame(&mainFrame);
116     if (FAILED(hr))
117         goto exit;
118
119     hr = mainFrame->dataSource(&dataSource);
120     if (FAILED(hr) || !dataSource)
121         hr = mainFrame->provisionalDataSource(&dataSource);
122     if (FAILED(hr) || !dataSource)
123         goto exit;
124
125     hr = dataSource->request(&request);
126     if (FAILED(hr) || !request)
127         goto exit;
128
129     hr = request->mainDocumentURL(&frameURL);
130     if (FAILED(hr))
131         goto exit;
132
133     SendMessage(hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL);
134
135 exit:
136     if (mainFrame)
137         mainFrame->Release();
138     if (dataSource)
139         dataSource->Release();
140     if (request)
141         request->Release();
142     SysFreeString(frameURL);
143     return 0;
144 }
145
146 HRESULT STDMETHODCALLTYPE WinLauncherWebHost::QueryInterface(REFIID riid, void** ppvObject)
147 {
148     *ppvObject = 0;
149     if (IsEqualGUID(riid, IID_IUnknown))
150         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
151     else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate))
152         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
153     else
154         return E_NOINTERFACE;
155
156     AddRef();
157     return S_OK;
158 }
159
160 ULONG STDMETHODCALLTYPE WinLauncherWebHost::AddRef(void)
161 {
162     return ++m_refCount;
163 }
164
165 ULONG STDMETHODCALLTYPE WinLauncherWebHost::Release(void)
166 {
167     ULONG newRef = --m_refCount;
168     if (!newRef)
169         delete(this);
170
171     return newRef;
172 }
173
174 HRESULT WinLauncherWebHost::didFinishLoadForFrame(IWebView* webView, IWebFrame* frame)
175 {
176     IDOMDocument* doc = 0;
177     frame->DOMDocument(&doc);
178
179     IDOMElement* element = 0;
180     IDOMEventTarget* target = 0;
181     HRESULT hr = doc->getElementById(L"webkit logo", &element);
182     if (!SUCCEEDED(hr))
183         goto exit;
184
185     hr = element->QueryInterface(IID_IDOMEventTarget, reinterpret_cast<void**>(&target));
186     if (!SUCCEEDED(hr))
187         goto exit;
188
189     hr = target->addEventListener(L"click", new SimpleEventListener (L"webkit logo click"), FALSE);
190     if (!SUCCEEDED(hr))
191         goto exit;
192
193 exit:
194     if (target)
195         target->Release();
196     if (element)
197         element->Release();
198     if (doc)
199         doc->Release();
200
201     return hr;
202 }
203
204 static void resizeSubViews()
205 {
206     if (usesLayeredWebView() || !gViewWindow)
207         return;
208
209     RECT rcClient;
210     GetClientRect(hMainWnd, &rcClient);
211     MoveWindow(hURLBarWnd, 0, 0, rcClient.right, URLBAR_HEIGHT, TRUE);
212     MoveWindow(gViewWindow, 0, URLBAR_HEIGHT, rcClient.right, rcClient.bottom - URLBAR_HEIGHT, TRUE);
213 }
214
215 static void subclassForLayeredWindow()
216 {
217     hMainWnd = gViewWindow;
218     DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hMainWnd, GWL_WNDPROC));
219     ::SetWindowLongPtr(hMainWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc));
220 }
221
222 static void computeFullDesktopFrame()
223 {
224     RECT desktop;
225     if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, static_cast<void*>(&desktop), 0))
226         return;
227
228     s_windowPosition.x = 0;
229     s_windowPosition.y = 0;
230     s_windowSize.cx = desktop.right - desktop.left;
231     s_windowSize.cy = desktop.bottom - desktop.top;
232 }
233
234 int APIENTRY _tWinMain(HINSTANCE hInstance,
235                      HINSTANCE hPrevInstance,
236                      LPTSTR    lpCmdLine,
237                      int       nCmdShow)
238 {
239 #ifdef _CRTDBG_MAP_ALLOC
240     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
241     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
242 #endif
243
244     UNREFERENCED_PARAMETER(hPrevInstance);
245     UNREFERENCED_PARAMETER(lpCmdLine);
246
247      // TODO: Place code here.
248     MSG msg = {0};
249     HACCEL hAccelTable;
250
251     INITCOMMONCONTROLSEX InitCtrlEx;
252
253     InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
254     InitCtrlEx.dwICC  = 0x00004000; //ICC_STANDARD_CLASSES;
255     InitCommonControlsEx(&InitCtrlEx);
256
257     int argc = 0;
258     WCHAR** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
259     for (int i = 1; i < argc; ++i) {
260         if (!wcsicmp(argv[i], L"--transparent"))
261             s_usesLayeredWebView = true;
262         else if (!wcsicmp(argv[i], L"--desktop"))
263             s_fullDesktop = true;
264     }
265
266     // Initialize global strings
267     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
268     LoadString(hInstance, IDC_WINLAUNCHER, szWindowClass, MAX_LOADSTRING);
269     MyRegisterClass(hInstance);
270
271     if (shouldUseFullDesktop())
272         computeFullDesktopFrame();
273
274     // Perform application initialization:
275     if (!InitInstance (hInstance, nCmdShow))
276         return FALSE;
277
278     // Init COM
279     OleInitialize(NULL);
280
281     if (usesLayeredWebView()) {
282         hURLBarWnd = CreateWindow(L"EDIT", L"Type URL Here",
283                     WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 
284                     s_windowPosition.x, s_windowPosition.y + s_windowSize.cy, s_windowSize.cx, URLBAR_HEIGHT,
285                     0,
286                     0,
287                     hInstance, 0);
288     } else {
289         hURLBarWnd = CreateWindow(L"EDIT", 0,
290                     WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 
291                     0, 0, 0, 0,
292                     hMainWnd,
293                     0,
294                     hInstance, 0);
295     }
296
297     DefEditProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hURLBarWnd, GWL_WNDPROC));
298     SetWindowLongPtr(hURLBarWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(MyEditProc));
299     SetFocus(hURLBarWnd);
300
301     RECT clientRect = { s_windowPosition.x, s_windowPosition.y, s_windowPosition.x + s_windowSize.cx, s_windowPosition.y + s_windowSize.cy };
302
303     IWebPreferences* tmpPreferences = 0;
304     IWebPreferences* standardPreferences = 0;
305     if (FAILED(WebKitCreateInstance(CLSID_WebPreferences, 0, IID_IWebPreferences, reinterpret_cast<void**>(&tmpPreferences))))
306         goto exit;
307
308     if (FAILED(tmpPreferences->standardPreferences(&standardPreferences)))
309         goto exit;
310
311     standardPreferences->setAcceleratedCompositingEnabled(TRUE);
312
313     HRESULT hr = WebKitCreateInstance(CLSID_WebView, 0, IID_IWebView, reinterpret_cast<void**>(&gWebView));
314     if (FAILED(hr))
315         goto exit;
316
317     hr = gWebView->QueryInterface(IID_IWebViewPrivate, reinterpret_cast<void**>(&gWebViewPrivate));
318     if (FAILED(hr))
319         goto exit;
320
321     gWebHost = new WinLauncherWebHost();
322     gWebHost->AddRef();
323     hr = gWebView->setFrameLoadDelegate(gWebHost);
324     if (FAILED(hr))
325         goto exit;
326
327     gPrintDelegate = new PrintWebUIDelegate;
328     gPrintDelegate->AddRef();
329     hr = gWebView->setUIDelegate(gPrintDelegate);
330     if (FAILED (hr))
331         goto exit;
332
333     hr = gWebView->setHostWindow(reinterpret_cast<OLE_HANDLE>(hMainWnd));
334     if (FAILED(hr))
335         goto exit;
336
337     hr = gWebView->initWithFrame(clientRect, 0, 0);
338     if (FAILED(hr))
339         goto exit;
340
341     IWebFrame* frame;
342     hr = gWebView->mainFrame(&frame);
343     if (FAILED(hr))
344         goto exit;
345
346     static BSTR defaultHTML = SysAllocString(TEXT("<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>"));
347     frame->loadHTMLString(defaultHTML, 0);
348     frame->Release();
349
350     hr = gWebViewPrivate->setTransparent(usesLayeredWebView());
351     if (FAILED(hr))
352         goto exit;
353
354     hr = gWebViewPrivate->setUsesLayeredWindow(usesLayeredWebView());
355     if (FAILED(hr))
356         goto exit;
357
358     hr = gWebViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&gViewWindow));
359     if (FAILED(hr) || !gViewWindow)
360         goto exit;
361
362     if (usesLayeredWebView())
363         subclassForLayeredWindow();
364
365     resizeSubViews();
366
367     ShowWindow(gViewWindow, nCmdShow);
368     UpdateWindow(gViewWindow);
369
370     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINLAUNCHER));
371
372     // Main message loop:
373     while (GetMessage(&msg, NULL, 0, 0)) {
374         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
375             TranslateMessage(&msg);
376             DispatchMessage(&msg);
377         }
378     }
379
380 exit:
381     gPrintDelegate->Release();
382     if (gWebViewPrivate)
383         gWebViewPrivate->Release();
384     gWebView->Release();
385     if (standardPreferences)
386         standardPreferences->Release();
387     tmpPreferences->Release();
388
389     shutDownWebKit();
390 #ifdef _CRTDBG_MAP_ALLOC
391     _CrtDumpMemoryLeaks();
392 #endif
393
394     // Shut down COM.
395     OleUninitialize();
396     
397     return static_cast<int>(msg.wParam);
398 }
399
400 ATOM MyRegisterClass(HINSTANCE hInstance)
401 {
402     WNDCLASSEX wcex;
403
404     wcex.cbSize = sizeof(WNDCLASSEX);
405
406     wcex.style          = CS_HREDRAW | CS_VREDRAW;
407     wcex.lpfnWndProc    = WndProc;
408     wcex.cbClsExtra     = 0;
409     wcex.cbWndExtra     = 0;
410     wcex.hInstance      = hInstance;
411     wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINLAUNCHER));
412     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
413     wcex.hbrBackground  = 0;
414     wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_WINLAUNCHER);
415     wcex.lpszClassName  = szWindowClass;
416     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
417
418     return RegisterClassEx(&wcex);
419 }
420
421 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
422 {
423     hInst = hInstance; // Store instance handle in our global variable
424
425     if (usesLayeredWebView())
426         return TRUE;
427
428     hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
429                    CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, 0);
430
431     if (!hMainWnd)
432         return FALSE;
433
434     ShowWindow(hMainWnd, nCmdShow);
435     UpdateWindow(hMainWnd);
436
437     return TRUE;
438 }
439
440 static BOOL CALLBACK AbortProc(HDC hDC, int Error)
441 {
442     MSG msg;
443     while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
444         ::TranslateMessage(&msg);
445         ::DispatchMessage(&msg);
446     }
447
448     return TRUE;
449 }
450
451 static HDC getPrinterDC()
452 {
453     PRINTDLG pdlg;
454     memset(&pdlg, 0, sizeof(PRINTDLG));
455     pdlg.lStructSize = sizeof(PRINTDLG);
456     pdlg.Flags = PD_PRINTSETUP | PD_RETURNDC;
457
458     ::PrintDlg(&pdlg);
459
460     return pdlg.hDC;
461 }
462
463 static void initDocStruct(DOCINFO* di, TCHAR* docname)
464 {
465     memset(di, 0, sizeof(DOCINFO));
466     di->cbSize = sizeof(DOCINFO);
467     di->lpszDocName = docname;
468 }
469
470 void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
471 {
472     HDC printDC = getPrinterDC();
473     if (!printDC) {
474         ::MessageBoxW(0, L"Error creating printing DC", L"Error", MB_APPLMODAL | MB_OK);
475         return;
476     }
477
478     if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) {
479         ::MessageBoxW(0, L"Error setting up AbortProc", L"Error", MB_APPLMODAL | MB_OK);
480         return;
481     }
482
483     IWebFrame* frame = 0;
484     IWebFramePrivate* framePrivate = 0;
485     if (FAILED(gWebView->mainFrame(&frame)))
486         goto exit;
487
488     if (FAILED(frame->QueryInterface(&framePrivate)))
489         goto exit;
490
491     framePrivate->setInPrintingMode(TRUE, printDC);
492
493     UINT pageCount = 0;
494     framePrivate->getPrintedPageCount(printDC, &pageCount);
495
496     DOCINFO di;
497     initDocStruct(&di, L"WebKit Doc");
498     ::StartDoc(printDC, &di);
499
500     // FIXME: Need CoreGraphics implementation
501     void* graphicsContext = 0;
502     for (size_t page = 1; page <= pageCount; ++page) {
503         ::StartPage(printDC);
504         framePrivate->spoolPages(printDC, page, page, graphicsContext);
505         ::EndPage(printDC);
506     }
507
508     framePrivate->setInPrintingMode(FALSE, printDC);
509
510     ::EndDoc(printDC);
511     ::DeleteDC(printDC);
512
513 exit:
514     if (frame)
515         frame->Release();
516     if (framePrivate)
517         framePrivate->Release();
518 }
519
520 static const int dragBarHeight = 30;
521
522 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
523 {
524     WNDPROC parentProc = usesLayeredWebView() ? DefWebKitProc : DefWindowProc;
525
526     switch (message) {
527     case WM_NCHITTEST:
528         if (usesLayeredWebView()) {
529             RECT window;
530             ::GetWindowRect(hWnd, &window);
531             // For testing our transparent window, we need a region to use as a handle for
532             // dragging. The right way to do this would be to query the web view to see what's
533             // under the mouse. However, for testing purposes we just use an arbitrary
534             // 30 pixel band at the top of the view as an arbitrary gripping location.
535             //
536             // When we are within this bad, return HT_CAPTION to tell Windows we want to
537             // treat this region as if it were the title bar on a normal window.
538             int y = HIWORD(lParam);
539
540             if ((y > window.top) && (y < window.top + dragBarHeight))
541                 return HTCAPTION;
542
543             return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
544         }
545         break;
546     case WM_COMMAND: {
547         int wmId = LOWORD(wParam);
548         int wmEvent = HIWORD(wParam);
549         // Parse the menu selections:
550         switch (wmId) {
551         case IDM_ABOUT:
552             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
553             break;
554         case IDM_EXIT:
555             DestroyWindow(hWnd);
556             break;
557         case IDM_PRINT:
558             PrintView(hWnd, message, wParam, lParam);
559             break;
560         default:
561             return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
562         }
563         }
564         break;
565     case WM_DESTROY:
566         PostQuitMessage(0);
567         break;
568     case WM_SIZE:
569         if (!gWebView || usesLayeredWebView())
570            return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
571
572         resizeSubViews();
573         break;
574     default:
575         return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
576         break;
577     }
578
579     return 0;
580 }
581
582 #define MAX_URL_LENGTH  1024
583
584 LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
585 {
586     switch (message) {
587         case WM_CHAR:
588             if (wParam == 13) { // Enter Key
589                 wchar_t strPtr[MAX_URL_LENGTH];
590                 *((LPWORD)strPtr) = MAX_URL_LENGTH; 
591                 int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr);
592
593                 BSTR bstr = SysAllocStringLen(strPtr, strLen);
594                 loadURL(bstr);
595                 SysFreeString(bstr);
596
597                 return 0;
598             } else
599                 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
600             break;
601         default:
602              return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
603         break;
604     }
605 }
606
607
608 // Message handler for about box.
609 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
610 {
611     UNREFERENCED_PARAMETER(lParam);
612     switch (message) {
613     case WM_INITDIALOG:
614         return (INT_PTR)TRUE;
615
616     case WM_COMMAND:
617         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
618             EndDialog(hDlg, LOWORD(wParam));
619             return (INT_PTR)TRUE;
620         }
621         break;
622     }
623     return (INT_PTR)FALSE;
624 }
625
626 static void loadURL(BSTR urlBStr)
627 {
628     IWebFrame* frame = 0;
629     IWebMutableURLRequest* request = 0;
630
631     static BSTR methodBStr = SysAllocString(TEXT("GET"));
632
633     if (urlBStr && urlBStr[0] && (PathFileExists(urlBStr) || PathIsUNC(urlBStr))) {
634         TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
635         DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]);
636
637         if (SUCCEEDED(UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0)))
638             SysReAllocString(&urlBStr, fileURL);
639     }
640
641     HRESULT hr = gWebView->mainFrame(&frame);
642     if (FAILED(hr))
643         goto exit;
644
645     hr = WebKitCreateInstance(CLSID_WebMutableURLRequest, 0, IID_IWebMutableURLRequest, (void**)&request);
646     if (FAILED(hr))
647         goto exit;
648
649     hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 60);
650     if (FAILED(hr))
651         goto exit;
652
653     hr = request->setHTTPMethod(methodBStr);
654     if (FAILED(hr))
655         goto exit;
656
657     hr = frame->loadRequest(request);
658     if (FAILED(hr))
659         goto exit;
660
661     SetFocus(gViewWindow);
662
663 exit:
664     if (frame)
665         frame->Release();
666     if (request)
667         request->Release();
668 }