2006-11-01 Mark Rowe <bdash@webkit.org>
[WebKit-https.git] / WebKitTools / Spinneret / Spinneret / Spinneret.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "stdafx.h"
27 #include "Spinneret.h"
28 #include "IWebView.h"
29 #include "IWebFrame.h"
30 #include "WebKit.h"
31
32 #include <commctrl.h>
33 #include <objbase.h>
34 #include <shlwapi.h>
35 #include <wininet.h>
36
37 #define MAX_LOADSTRING 100
38 #define URLBAR_HEIGHT  24
39
40 // Global Variables:
41 HINSTANCE hInst;                                // current instance
42 HWND hMainWnd;
43 HWND hURLBarWnd;
44 long DefEditProc;
45 IWebView* gWebView = 0;
46 HWND gViewWindow = 0;
47 SpinneretWebHost* gWebHost = 0;
48 TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text
49 TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
50
51 // Forward declarations of functions included in this code module:
52 ATOM                MyRegisterClass(HINSTANCE hInstance);
53 BOOL                InitInstance(HINSTANCE, int);
54 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
55 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
56 LRESULT CALLBACK    MyEditProc(HWND, UINT, WPARAM, LPARAM);
57
58 static void loadURL(BSTR urlBStr);
59
60 HRESULT SpinneretWebHost::updateAddressBar(IWebView* webView)
61 {
62     IWebFrame* mainFrame = 0;
63     IWebDataSource* dataSource = 0;
64     IWebMutableURLRequest* request = 0;
65     BSTR frameURL = 0;
66
67     HRESULT hr = S_OK;
68
69     hr = webView->mainFrame(&mainFrame);
70     if (FAILED(hr))
71         goto exit;
72
73     hr = mainFrame->dataSource(&dataSource);
74     if (FAILED(hr) || !dataSource)
75         hr = mainFrame->provisionalDataSource(&dataSource);
76     if (FAILED(hr) || !dataSource)
77         goto exit;
78
79     hr = dataSource->request(&request);
80     if (FAILED(hr) || !request)
81         goto exit;
82
83     hr = request->mainDocumentURL(&frameURL);
84     if (FAILED(hr))
85         goto exit;
86
87     SendMessage(hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL);
88
89 exit:
90     if (mainFrame)
91         mainFrame->Release();
92     if (dataSource)
93         dataSource->Release();
94     if (request)
95         request->Release();
96     SysFreeString(frameURL);
97     return 0;
98 }
99
100 HRESULT STDMETHODCALLTYPE SpinneretWebHost::QueryInterface(REFIID riid, void** ppvObject)
101 {
102     *ppvObject = 0;
103     if (IsEqualGUID(riid, IID_IUnknown))
104         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
105     else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate))
106         *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
107     else
108         return E_NOINTERFACE;
109
110     AddRef();
111     return S_OK;
112 }
113
114 ULONG STDMETHODCALLTYPE SpinneretWebHost::AddRef(void)
115 {
116     return ++m_refCount;
117 }
118
119 ULONG STDMETHODCALLTYPE SpinneretWebHost::Release(void)
120 {
121     ULONG newRef = --m_refCount;
122     if (!newRef)
123         delete(this);
124
125     return newRef;
126 }
127
128 static void resizeSubViews()
129 {
130     RECT rcClient;
131     GetClientRect(hMainWnd, &rcClient);
132     MoveWindow(hURLBarWnd, 0, 0, rcClient.right, URLBAR_HEIGHT, TRUE);
133     MoveWindow(gViewWindow, 0, URLBAR_HEIGHT, rcClient.right, rcClient.bottom - URLBAR_HEIGHT, TRUE);
134 }
135
136 int APIENTRY _tWinMain(HINSTANCE hInstance,
137                      HINSTANCE hPrevInstance,
138                      LPTSTR    lpCmdLine,
139                      int       nCmdShow)
140 {
141 #ifdef _CRTDBG_MAP_ALLOC
142     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
143     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
144 #endif
145
146     UNREFERENCED_PARAMETER(hPrevInstance);
147     UNREFERENCED_PARAMETER(lpCmdLine);
148
149      // TODO: Place code here.
150     MSG msg;
151     HACCEL hAccelTable;
152
153     INITCOMMONCONTROLSEX InitCtrlEx;
154
155     InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
156     InitCtrlEx.dwICC  = ICC_STANDARD_CLASSES;
157     InitCommonControlsEx(&InitCtrlEx);
158
159     // Initialize global strings
160     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
161     LoadString(hInstance, IDC_SPINNERET, szWindowClass, MAX_LOADSTRING);
162     MyRegisterClass(hInstance);
163
164     // Perform application initialization:
165     if (!InitInstance (hInstance, nCmdShow))
166         return FALSE;
167
168     // Init COM
169     CoInitialize(NULL);
170
171     hURLBarWnd = CreateWindow(L"EDIT", 0,
172                         WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL, 
173                         0, 0, 0, 0,
174                         hMainWnd,
175                         0,
176                         hInstance, 0);
177
178     DefEditProc = GetWindowLong(hURLBarWnd, GWL_WNDPROC);
179     SetWindowLong(hURLBarWnd, GWL_WNDPROC,(long)MyEditProc);
180     SetFocus(hURLBarWnd);
181
182     HRESULT hr = CoCreateInstance(CLSID_WebView, 0, CLSCTX_ALL, IID_IWebView, (void**)&gWebView);
183     if (FAILED(hr))
184         goto exit;
185
186     gWebHost = new SpinneretWebHost();
187     gWebHost->AddRef();
188     hr = gWebView->setFrameLoadDelegate(gWebHost);
189     if (FAILED(hr))
190         goto exit;
191
192     hr = gWebView->setHostWindow(hMainWnd);
193     if (FAILED(hr))
194         goto exit;
195
196     RECT clientRect;
197     GetClientRect(hMainWnd, &clientRect);
198     hr = gWebView->initWithFrame(&clientRect, 0, 0);
199     if (FAILED(hr))
200         goto exit;
201
202     IWebFrame* frame;
203     hr = gWebView->mainFrame(&frame);
204     if (FAILED(hr))
205         goto exit;
206     static BSTR defaultHTML = 0;
207     if (!defaultHTML)
208         defaultHTML = SysAllocString(TEXT("<p style=\"background-color: #00FF00\">Testing</p><img src=\"http://webkit.org/images/icon-gold.png\" alt=\"Face\"><div style=\"border: solid blue\" contenteditable=\"true\">div with blue border</div><ul><li>foo<li>bar<li>baz</ul>"));
209     frame->loadHTMLString(defaultHTML, 0);
210     frame->Release();
211
212     IWebViewExt* viewExt;
213     hr = gWebView->QueryInterface(IID_IWebViewExt, (void**)&viewExt);
214     if (FAILED(hr))
215         goto exit;
216     hr = viewExt->viewWindow(&gViewWindow);
217     viewExt->Release();
218     if (FAILED(hr) || !gViewWindow)
219         goto exit;
220
221     resizeSubViews();
222
223     ShowWindow(gViewWindow, nCmdShow);
224     UpdateWindow(gViewWindow);
225
226     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SPINNERET));
227
228     // Main message loop:
229     while (GetMessage(&msg, NULL, 0, 0)) {
230         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
231             TranslateMessage(&msg);
232             DispatchMessage(&msg);
233         }
234     }
235
236 exit:
237     delete gWebView;
238 #ifdef _CRTDBG_MAP_ALLOC
239     _CrtDumpMemoryLeaks();
240 #endif
241
242     // Shut down COM.
243     CoUninitialize();
244     
245     return (int) msg.wParam;
246 }
247
248 ATOM MyRegisterClass(HINSTANCE hInstance)
249 {
250     WNDCLASSEX wcex;
251
252     wcex.cbSize = sizeof(WNDCLASSEX);
253
254     wcex.style            = CS_HREDRAW | CS_VREDRAW;
255     wcex.lpfnWndProc    = WndProc;
256     wcex.cbClsExtra        = 0;
257     wcex.cbWndExtra        = 0;
258     wcex.hInstance        = hInstance;
259     wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SPINNERET));
260     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
261     wcex.hbrBackground    = 0;
262     wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_SPINNERET);
263     wcex.lpszClassName    = szWindowClass;
264     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
265
266     return RegisterClassEx(&wcex);
267 }
268
269 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
270 {
271    hInst = hInstance; // Store instance handle in our global variable
272
273    hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
274       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
275
276    if (!hMainWnd)
277       return FALSE;
278
279    ShowWindow(hMainWnd, nCmdShow);
280    UpdateWindow(hMainWnd);
281
282    return TRUE;
283 }
284
285 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
286 {
287     int wmId, wmEvent;
288     PAINTSTRUCT ps;
289     HDC hdc;
290
291     switch (message) {
292     case WM_COMMAND:
293         wmId    = LOWORD(wParam);
294         wmEvent = HIWORD(wParam);
295         // Parse the menu selections:
296         switch (wmId) {
297             case IDM_ABOUT:
298                 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
299                 break;
300             case IDM_EXIT:
301                 DestroyWindow(hWnd);
302                 break;
303             default:
304                 return DefWindowProc(hWnd, message, wParam, lParam);
305         }
306         break;
307     case WM_DESTROY:
308         PostQuitMessage(0);
309         break;
310     case WM_SIZE:
311         if (!gWebView)
312             break;
313         resizeSubViews();
314         break; 
315     default:
316         return DefWindowProc(hWnd, message, wParam, lParam);
317     }
318     return 0;
319 }
320
321
322 #define MAX_URL_LENGTH  1024
323
324 LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
325 {
326     switch (message) {
327         case WM_CHAR:
328             if( wParam == 13 ) { // Enter Key
329                 wchar_t strPtr[MAX_URL_LENGTH];
330                 *((LPWORD)strPtr) = MAX_URL_LENGTH; 
331                 int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr);
332
333                 BSTR bstr = SysAllocStringLen(strPtr, strLen);
334                 loadURL(bstr);
335                 SysFreeString(bstr);
336
337                 return 0;
338             } else
339                 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
340             break;
341         default:
342              return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
343         break;
344     }
345     return 0;
346 }
347
348
349 // Message handler for about box.
350 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
351 {
352     UNREFERENCED_PARAMETER(lParam);
353     switch (message) {
354     case WM_INITDIALOG:
355         return (INT_PTR)TRUE;
356
357     case WM_COMMAND:
358         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
359             EndDialog(hDlg, LOWORD(wParam));
360             return (INT_PTR)TRUE;
361         }
362         break;
363     }
364     return (INT_PTR)FALSE;
365 }
366
367 static void loadURL(BSTR urlBStr)
368 {
369     IWebFrame* frame = 0;
370     IWebMutableURLRequest* request = 0;
371     static BSTR methodBStr = 0;
372
373     if (!methodBStr)
374         methodBStr = SysAllocString(TEXT("GET"));
375
376     if (urlBStr && urlBStr[0] && (PathFileExists(urlBStr) || PathIsUNC(urlBStr))) {
377         TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
378         DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]);
379         if (SUCCEEDED(UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0)))
380             urlBStr = fileURL;
381     }
382
383     HRESULT hr = gWebView->mainFrame(&frame);
384     if (FAILED(hr))
385         goto exit;
386
387     hr = CoCreateInstance(CLSID_WebMutableURLRequest, 0, CLSCTX_ALL, IID_IWebMutableURLRequest, (void**)&request);
388     if (FAILED(hr))
389         goto exit;
390
391     hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 0);
392     if (FAILED(hr))
393         goto exit;
394
395     hr = request->setHTTPMethod(methodBStr);
396     if (FAILED(hr))
397         goto exit;
398
399     hr = frame->loadRequest(request);
400     if (FAILED(hr))
401         goto exit;
402
403     SetFocus(gViewWindow);
404
405 exit:
406     if (frame)
407         frame->Release();
408     if (request)
409         request->Release();
410 }