f0f618ecafbd3fddff6dc5cce57d96a9acd6a199
[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     return ret;
194 }
195
196
197 HRESULT Drosera::initUI(HINSTANCE hInstance, int nCmdShow)
198 {
199     // Initialize global strings
200     LoadString(hInstance, IDS_APP_TITLE, szTitle, ARRAYSIZE(szTitle));
201     LoadString(hInstance, IDC_DROSERA, szWindowClass, ARRAYSIZE(szWindowClass));
202     registerDroseraClass(hInstance);
203
204     Drosera::setInst(hInstance); // Store instance handle in our local variable
205
206     m_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
207         CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInstance, 0);
208
209     if (!m_hWnd)
210         return HRESULT_FROM_WIN32(GetLastError());
211
212     SetLastError(0);
213     SetWindowLongPtr(m_hWnd, 0, reinterpret_cast<LONG_PTR>(this));
214     HRESULT ret = HRESULT_FROM_WIN32(GetLastError());
215     if (FAILED(ret))
216         return ret;
217
218     ret = CoCreateInstance(CLSID_WebView, 0, CLSCTX_ALL, IID_IWebView, (void**)&m_webView);
219     if (FAILED(ret))
220         return ret;
221
222     m_webViewPrivate.query(m_webView.get());
223     if (!m_webView)
224         return E_FAIL;
225
226     ret = m_webView->setHostWindow(reinterpret_cast<OLE_HANDLE>(m_hWnd));
227     if (FAILED(ret))
228         return ret;
229
230     RECT rect = {0};
231     ret = m_webView->initWithFrame(rect, 0, 0);
232     if (FAILED(ret))
233         return ret;
234
235     HWND viewWindow;
236     ret = m_webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow));
237     if (FAILED(ret))
238         return ret;
239
240     ::SetProp(viewWindow, kDroseraPointerProp, (HANDLE)this);
241
242     // FIXME: Implement window size/position save/restore
243
244     RECT frame;
245     frame.left = 60;
246     frame.top = 200;
247     frame.right = 750;
248     frame.bottom = 550;
249     ::SetWindowPos(m_hWnd, HWND_TOPMOST, frame.left, frame.top, frame.right - frame.left, frame.bottom - frame.top, 0);
250     ShowWindow(m_hWnd, nCmdShow);
251     UpdateWindow(m_hWnd);
252
253     return ret;
254 }
255
256 LRESULT Drosera::onSize(WPARAM, LPARAM)
257 {
258     if (!m_webViewPrivate)
259         return 0;
260
261     RECT clientRect = {0};
262     ::GetClientRect(m_hWnd, &clientRect);
263
264     HWND viewWindow;
265     if (FAILED(m_webViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
266         return 0;
267
268     // FIXME should this be the height-command bars height?
269     ::SetWindowPos(viewWindow, 0, clientRect.left, clientRect.top, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top, SWP_NOZORDER);
270     return 0;
271 }
272
273 bool Drosera::webViewLoaded() const
274 {
275     return m_debuggerClient->webViewLoaded();
276 }
277
278 // Server Detection Callbacks
279
280 HRESULT Drosera::attach(const std::wstring& serverName)
281 {
282     // Get selected server
283     m_debuggerClient->initWithServerName(serverName);
284
285     HRESULT ret = m_webView->setFrameLoadDelegate(m_debuggerClient.get());
286     if (FAILED(ret))
287         return ret;
288
289     ret = m_webView->setUIDelegate(m_debuggerClient.get());
290
291     COMPtr<IWebFrame> mainFrame;
292     ret = m_webView->mainFrame(&mainFrame);
293     if (FAILED(ret))
294         return ret;
295
296     COMPtr<IWebMutableURLRequest> request;
297     ret = CoCreateInstance(CLSID_WebMutableURLRequest, 0, CLSCTX_ALL, IID_IWebMutableURLRequest, (void**)&request);
298     if (FAILED(ret))
299         return ret;
300
301     RetainPtr<CFURLRef> htmlURLRef(AdoptCF, ::CFBundleCopyResourceURL(::CFBundleGetBundleWithIdentifier(CFSTR("org.webkit.drosera")), CFSTR("debugger"), CFSTR("html"), CFSTR("Drosera")));
302     if (!htmlURLRef)
303         return E_FAIL;
304
305     CFStringRef urlStringRef = ::CFURLGetString(htmlURLRef.get());
306     BSTR tempStr = cfStringToBSTR(urlStringRef);    // Both initWithRUL and SysFreeString can handle 0.
307     ret = request->initWithURL(tempStr, WebURLRequestUseProtocolCachePolicy, 60);
308     SysFreeString(tempStr);
309     if (FAILED(ret))
310         return ret;
311
312     ret = mainFrame->loadRequest(request.get());
313     if (FAILED(ret))
314         return ret;
315
316     return ret;
317 }