WebKitTools:
[WebKit-https.git] / WebKitTools / Drosera / win / Drosera.cpp
1 /*
2  * Copyright (C) 2007 Apple 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "Drosera.h"
31
32 #include "DebuggerClient.h"
33 #include "DebuggerDocument.h"
34 #include "HelperFunctions.h"
35 #include "resource.h"
36 #include "ServerConnection.h"
37
38 #include <JavaScriptCore/JSStringRef.h>
39 #include <WebCore/IntRect.h>
40 #include <WebKit/IWebMutableURLRequest.h>
41 #include <WebKit/IWebView.h>
42 #include <WebKit/WebKit.h>
43
44 const unsigned MAX_LOADSTRING = 100;
45
46 TCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
47 TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
48
49 static const LRESULT kNotHandledResult = -1;
50 static LPCTSTR kDroseraPointerProp = TEXT("DroseraPointer");
51 static HINSTANCE hInst;
52
53 extern "C" BOOL InitializeCoreGraphics();
54
55 ATOM registerDroseraClass(HINSTANCE hInstance);
56 LRESULT CALLBACK droseraWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
57 INT_PTR CALLBACK aboutWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
58
59 HINSTANCE Drosera::getInst() { return hInst; }
60 void Drosera::setInst(HINSTANCE in) { hInst = in; }
61
62
63 int APIENTRY _tWinMain(HINSTANCE hInstance,
64                        HINSTANCE hPrevInstance,
65                        LPTSTR    lpCmdLine,
66                        int       nCmdShow)
67 {
68     UNREFERENCED_PARAMETER(hPrevInstance);
69     UNREFERENCED_PARAMETER(lpCmdLine);
70
71     MSG msg;
72
73     InitializeCoreGraphics();
74
75     Drosera drosera;
76
77     HRESULT ret = drosera.init(hInstance, nCmdShow);
78     if (FAILED(ret))
79         return ret;
80
81     HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DROSERA));
82
83     // Main message loop:
84     while (GetMessage(&msg, 0, 0, 0)) {
85         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
86             TranslateMessage(&msg);
87             DispatchMessage(&msg);
88         }
89     }
90
91     return static_cast<int>(msg.wParam);
92 }
93
94 ////////////////// Setup Windows Specific Interface //////////////////
95
96 ATOM registerDroseraClass(HINSTANCE hInstance)
97 {
98     WNDCLASSEX wcex;
99
100     wcex.cbSize = sizeof(WNDCLASSEX);
101
102     wcex.style         = CS_HREDRAW | CS_VREDRAW;
103     wcex.lpfnWndProc   = ::droseraWndProc;
104     wcex.cbClsExtra    = 0;
105     wcex.cbWndExtra    = sizeof(Drosera*);
106     wcex.hInstance     = hInstance;
107     wcex.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DROSERA));
108     wcex.hCursor       = LoadCursor(0, IDC_ARROW);
109     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
110     wcex.lpszMenuName  = MAKEINTRESOURCE(IDC_DROSERA);
111     wcex.lpszClassName = szWindowClass;
112     wcex.hIconSm       = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
113
114     return RegisterClassEx(&wcex);
115 }
116
117 //Processes messages for the main window.
118 LRESULT CALLBACK droseraWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
119 {
120     int wmId, wmEvent;
121     PAINTSTRUCT ps;
122     HDC hdc;
123
124     LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0);
125     Drosera* drosera = reinterpret_cast<Drosera*>(longPtr);
126
127     switch (message) {
128         case WM_COMMAND:
129             wmId    = LOWORD(wParam);
130             wmEvent = HIWORD(wParam);
131             switch (wmId) {
132                 case ID_HELP_ABOUT:
133                     DialogBox(Drosera::getInst(), MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, ::aboutWndProc);
134                     break;
135                 case ID_FILE_EXIT:
136                     DestroyWindow(hWnd);
137                     break;
138                 default:
139                     return DefWindowProc(hWnd, message, wParam, lParam);
140             }
141             break;
142         case WM_SIZE:
143             if (!drosera)
144                 return 0;
145             return drosera->webViewLoaded() ? drosera->onSize(wParam, lParam) : 0;
146         case WM_PAINT:
147             hdc = BeginPaint(hWnd, &ps);
148             // TODO: Add any drawing code here...
149             EndPaint(hWnd, &ps);
150             break;
151         case WM_DESTROY:
152             PostQuitMessage(0);
153             break;
154         default:
155             return DefWindowProc(hWnd, message, wParam, lParam);
156     }
157     return 0;
158 }
159
160 // Message handler for about box.
161 INT_PTR CALLBACK aboutWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
162 {
163     UNREFERENCED_PARAMETER(lParam);
164     switch (message) {
165         case WM_INITDIALOG:
166             return (INT_PTR)TRUE;
167
168         case WM_COMMAND:
169             if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
170                 EndDialog(hDlg, LOWORD(wParam));
171                 return (INT_PTR)TRUE;
172             }
173             break;
174     }
175     return (INT_PTR)FALSE;
176 }
177
178 ////////////////// End Setup Windows Specific Interface //////////////////
179
180 Drosera::Drosera()
181     : m_hWnd(0)
182     , m_debuggerClient(new DebuggerClient())
183 {
184     OleInitialize(0);
185 }
186
187 HRESULT Drosera::init(HINSTANCE hInstance, int nCmdShow)
188 {
189     HRESULT ret = initUI(hInstance, nCmdShow);
190     if (FAILED(ret))
191         return ret;
192
193     ret = attach();
194     return ret;
195 }
196
197
198 HRESULT Drosera::initUI(HINSTANCE hInstance, int nCmdShow)
199 {
200     // Initialize global strings
201     LoadString(hInstance, IDS_APP_TITLE, szTitle, ARRAYSIZE(szTitle));
202     LoadString(hInstance, IDC_DROSERA, szWindowClass, ARRAYSIZE(szWindowClass));
203     registerDroseraClass(hInstance);
204
205     Drosera::setInst(hInstance); // Store instance handle in our local variable
206
207     m_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
208         CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, 0);
209
210     if (!m_hWnd)
211         return HRESULT_FROM_WIN32(GetLastError());
212
213     SetLastError(0);
214     SetWindowLongPtr(m_hWnd, 0, reinterpret_cast<LONG_PTR>(this));
215     HRESULT ret = HRESULT_FROM_WIN32(GetLastError());
216     if (FAILED(ret))
217         return ret;
218
219     ret = CoCreateInstance(CLSID_WebView, 0, CLSCTX_ALL, IID_IWebView, (void**)&m_webView);
220     if (FAILED(ret))
221         return ret;
222
223     m_webViewPrivate.query(m_webView.get());
224     if (!m_webView)
225         return E_FAIL;
226
227     ret = m_webView->setHostWindow(reinterpret_cast<OLE_HANDLE>(m_hWnd));
228     if (FAILED(ret))
229         return ret;
230
231     RECT rect = {0};
232     ret = m_webView->initWithFrame(rect, 0, 0);
233     if (FAILED(ret))
234         return ret;
235
236     HWND viewWindow;
237     ret = m_webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow));
238     if (FAILED(ret))
239         return ret;
240
241     ::SetProp(viewWindow, kDroseraPointerProp, (HANDLE)this);
242
243     // FIXME: Implement window size/position save/restore
244
245     RECT frame;
246     frame.left = 60;
247     frame.top = 200;
248     frame.right = 750;
249     frame.bottom = 550;
250     ::SetWindowPos(m_hWnd, HWND_TOPMOST, frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, 0);
251     ShowWindow(m_hWnd, nCmdShow);
252     UpdateWindow(m_hWnd);
253
254     return ret;
255 }
256
257 LRESULT Drosera::onSize(WPARAM, LPARAM)
258 {
259     if (!m_webViewPrivate)
260         return 0;
261
262     RECT clientRect = {0};
263     ::GetClientRect(m_hWnd, &clientRect);
264
265     HWND viewWindow;
266     if (FAILED(m_webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
267         return 0;
268
269     // FIXME should this be the height-command bars height?
270     ::SetWindowPos(viewWindow, 0, clientRect.left, clientRect.top, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, SWP_NOZORDER);
271     return 0;
272 }
273
274 bool Drosera::webViewLoaded() const
275 {
276     return m_debuggerClient->webViewLoaded();
277 }
278
279 // Server Detection Callbacks
280
281 HRESULT Drosera::attach()
282 {
283     // Get selected server
284     HRESULT ret = m_webView->setFrameLoadDelegate(m_debuggerClient.get());
285     if (FAILED(ret))
286         return ret;
287
288     ret = m_webView->setUIDelegate(m_debuggerClient.get());
289
290     COMPtr<IWebFrame> mainFrame;
291     ret = m_webView->mainFrame(&mainFrame);
292     if (FAILED(ret))
293         return ret;
294
295     COMPtr<IWebMutableURLRequest> request;
296     ret = CoCreateInstance(CLSID_WebMutableURLRequest, 0, CLSCTX_ALL, IID_IWebMutableURLRequest, (void**)&request);
297     if (FAILED(ret))
298         return ret;
299
300     RetainPtr<CFURLRef> htmlURLRef(AdoptCF, ::CFBundleCopyResourceURL(::CFBundleGetBundleWithIdentifier(CFSTR("org.webkit.drosera")), CFSTR("debugger"), CFSTR("html"), CFSTR("Drosera")));
301     if (!htmlURLRef)
302         return E_FAIL;
303
304     CFStringRef urlStringRef = ::CFURLGetString(htmlURLRef.get());
305     BSTR tempStr = cfStringToBSTR(urlStringRef);    // Both initWithRUL and SysFreeString can handle 0.
306     ret = request->initWithURL(tempStr, WebURLRequestUseProtocolCachePolicy, 60);
307     SysFreeString(tempStr);
308     if (FAILED(ret))
309         return ret;
310
311     ret = mainFrame->loadRequest(request.get());
312     if (FAILED(ret))
313         return ret;
314
315     return ret;
316 }