de2b41662d188572581379d07e918174e62d2fa1
[WebKit-https.git] / WebKitTools / Drosera / win / ServerConnection.cpp
1 /*
2  * Copyright (C) 2007 Apple Inc.  All rights reserved.
3  * Copyright (C) 2006, 2007 Vladimir Olexa (vladimir.olexa@gmail.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
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  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "ServerConnection.h"
32
33 #include "DebuggerDocument.h"
34
35 #include <JavaScriptCore/JSContextRef.h>
36 #include <JavaScriptCore/JSRetainPtr.h>
37 #include <JavaScriptCore/JSStringRefBSTR.h>
38 #include <JavaScriptCore/RetainPtr.h>
39 #include <WebKit/ForEachCoClass.h>
40 #include <WebKit/WebKit.h>
41
42 #include <iostream>
43
44 ServerConnection::ServerConnection()
45     : m_globalContext(0)
46     , m_serverConnected(false)
47 {
48     OleInitialize(0);
49     attemptToCreateServerConnection();
50 }
51
52 ServerConnection::~ServerConnection()
53 {
54     if (m_server)
55         m_server->removeListener(this);
56
57     if (m_globalContext)
58         JSGlobalContextRelease(m_globalContext);
59 }
60
61 void ServerConnection::attemptToCreateServerConnection(JSGlobalContextRef globalContextRef)
62 {
63     COMPtr<IWebScriptDebugServer> tempServer;
64
65     CLSID clsid = CLSID_NULL;
66     if (FAILED(CLSIDFromProgID(PROGID(WebScriptDebugServer), &clsid)))
67         return;
68
69     if (FAILED(CoCreateInstance(clsid, 0, CLSCTX_LOCAL_SERVER, IID_IWebScriptDebugServer, (void**)&tempServer)))
70         return;
71
72     if (FAILED(tempServer->sharedWebScriptDebugServer(&m_server)))
73         return;
74
75     if (FAILED(m_server->addListener(this))) {
76         m_server = 0;
77         return;
78     }
79
80     m_serverConnected = true;
81
82     if (globalContextRef)
83         m_globalContext = JSGlobalContextRetain(globalContextRef);
84 }
85
86 void ServerConnection::setGlobalContext(JSGlobalContextRef globalContextRef)
87 {
88     m_globalContext = JSGlobalContextRetain(globalContextRef);
89 }
90
91 // Pause & Step
92
93 void ServerConnection::pause()
94 {
95     if (m_server)
96         m_server->pause();
97 }
98
99 void ServerConnection::resume()
100 {
101     if (m_server)
102         m_server->resume();
103 }
104
105 void ServerConnection::stepInto()
106 {
107     if (m_server)
108         m_server->step();
109 }
110
111 // IUnknown --------------------------------------------------
112 HRESULT STDMETHODCALLTYPE ServerConnection::QueryInterface(REFIID riid, void** ppvObject)
113 {
114     *ppvObject = 0;
115     if (IsEqualGUID(riid, IID_IUnknown))
116         *ppvObject = this;
117     else if (IsEqualGUID(riid, IID_IWebScriptDebugListener))
118         *ppvObject = static_cast<IWebScriptDebugListener*>(this);
119     else
120         return E_NOINTERFACE;
121
122     AddRef();
123     return S_OK;
124 }
125
126 ULONG STDMETHODCALLTYPE ServerConnection::AddRef(void)
127 {
128     // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView.
129     return 1;
130 }
131
132 ULONG STDMETHODCALLTYPE ServerConnection::Release(void)
133 {
134     // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView.
135     return 1;
136 }
137 // IWebScriptDebugListener -----------------------------------
138 HRESULT STDMETHODCALLTYPE ServerConnection::didLoadMainResourceForDataSource(
139     /* [in] */ IWebView*,
140     /* [in] */ IWebDataSource* dataSource)
141 {
142     HRESULT ret = S_OK;
143     if (!m_globalContext || !dataSource)
144         return ret;
145
146     // Get document source
147     COMPtr<IWebDocumentRepresentation> rep;
148     ret = dataSource->representation(&rep);
149     if (FAILED(ret))
150         return ret;
151
152     BOOL canProvideDocumentSource = FALSE;
153     ret = rep->canProvideDocumentSource(&canProvideDocumentSource);
154     if (FAILED(ret))
155         return ret;
156
157     BSTR documentSource = 0;
158     if (canProvideDocumentSource)
159         ret = rep->documentSource(&documentSource);
160
161     if (FAILED(ret) || !documentSource)
162         return ret;
163
164     JSRetainPtr<JSStringRef> documentSourceJS(Adopt, JSStringCreateWithBSTR(documentSource));
165     SysFreeString(documentSource);
166
167     // Get URL
168     COMPtr<IWebURLResponse> response;
169     ret = dataSource->response(&response);
170     if (FAILED(ret))
171         return ret;
172
173     BSTR url = 0;
174     ret = response->URL(&url);
175     if (FAILED(ret))
176         return ret;
177
178     JSRetainPtr<JSStringRef> urlJS(Adopt, JSStringCreateWithBSTR(url));
179     SysFreeString(url);
180
181     DebuggerDocument::updateFileSource(m_globalContext, documentSourceJS.get(), urlJS.get());
182
183     return S_OK;
184 }
185
186 HRESULT STDMETHODCALLTYPE ServerConnection::didParseSource(
187     /* [in] */ IWebView*,
188     /* [in] */ BSTR sourceCode,
189     /* [in] */ UINT baseLineNumber,
190     /* [in] */ BSTR url,
191     /* [in] */ int sourceID,
192     /* [in] */ IWebFrame* webFrame)
193 {
194     HRESULT ret = S_OK;
195     if (!m_globalContext || !sourceCode)
196         return ret;
197
198     COMPtr<IWebDataSource> dataSource;
199     ret = webFrame->dataSource(&dataSource);
200     if (FAILED(ret))
201         return ret;
202
203     COMPtr<IWebURLResponse> response;
204     ret = dataSource->response(&response);
205     if (FAILED(ret))
206         return ret;
207
208     BSTR responseURL;
209     ret = response->URL(&responseURL);
210     if (FAILED(ret))
211         return ret;
212
213     BSTR documentSource = 0;
214     if (!url || !wcscmp(responseURL, url)) {
215         COMPtr<IWebDocumentRepresentation> rep;
216         ret = dataSource->representation(&rep);
217         if (FAILED(ret))
218             return ret;
219
220         BOOL canProvideDocumentSource;
221         rep->canProvideDocumentSource(&canProvideDocumentSource);
222         if (FAILED(ret))
223             return ret;
224
225         if (canProvideDocumentSource) {
226             ret = rep->documentSource(&documentSource);
227             if (FAILED(ret))
228                 return ret;
229         }
230
231         if (!url) {
232             ret = response->URL(&url);
233             if (FAILED(ret))
234                 return ret;
235         }
236     }
237     SysFreeString(responseURL);
238
239     JSRetainPtr<JSStringRef> sourceJS(Adopt, JSStringCreateWithBSTR(sourceCode));
240     JSRetainPtr<JSStringRef> documentSourceJS(Adopt, JSStringCreateWithBSTR(documentSource));
241     SysFreeString(documentSource);
242     JSRetainPtr<JSStringRef> urlJS(Adopt, JSStringCreateWithBSTR(url));
243     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);
244     JSValueRef baseLineJS = JSValueMakeNumber(m_globalContext, baseLineNumber);
245
246     DebuggerDocument::didParseScript(m_globalContext, sourceJS.get(), documentSourceJS.get(), urlJS.get(), sidJS, baseLineJS);
247
248     return S_OK;
249 }
250
251 HRESULT STDMETHODCALLTYPE ServerConnection::failedToParseSource(
252     /* [in] */ IWebView*,
253     /* [in] */ BSTR,
254     /* [in] */ UINT,
255     /* [in] */ BSTR,
256     /* [in] */ BSTR,
257     /* [in] */ IWebFrame*)
258 {
259     return S_OK;
260 }
261
262 HRESULT STDMETHODCALLTYPE ServerConnection::didEnterCallFrame(
263     /* [in] */ IWebView*,
264     /* [in] */ IWebScriptCallFrame* frame,
265     /* [in] */ int sourceID,
266     /* [in] */ int lineNumber,
267     /* [in] */ IWebFrame*)
268 {
269     HRESULT ret = S_OK;
270     if (!m_globalContext)
271         return ret;
272
273     m_currentFrame = frame;
274
275     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);
276     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);
277
278     DebuggerDocument::didEnterCallFrame(m_globalContext, sidJS, linenoJS);
279
280     return ret;
281 }
282
283 HRESULT STDMETHODCALLTYPE ServerConnection::willExecuteStatement(
284     /* [in] */ IWebView*,
285     /* [in] */ IWebScriptCallFrame*,
286     /* [in] */ int sourceID,
287     /* [in] */ int lineNumber,
288     /* [in] */ IWebFrame*)
289 {
290     HRESULT ret = S_OK;
291     if (!m_globalContext)
292         return ret;
293
294     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);
295     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);
296
297     DebuggerDocument::willExecuteStatement(m_globalContext, sidJS, linenoJS);
298     return ret;
299 }
300
301 HRESULT STDMETHODCALLTYPE ServerConnection::willLeaveCallFrame(
302     /* [in] */ IWebView*,
303     /* [in] */ IWebScriptCallFrame* frame,
304     /* [in] */ int sourceID,
305     /* [in] */ int lineNumber,
306     /* [in] */ IWebFrame*)
307 {
308     HRESULT ret = S_OK;
309     if (!m_globalContext)
310         return ret;
311
312     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);
313     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);
314
315     DebuggerDocument::willLeaveCallFrame(m_globalContext, sidJS, linenoJS);
316
317     m_currentFrame = frame;
318
319     return S_OK;
320 }
321
322 HRESULT STDMETHODCALLTYPE ServerConnection::exceptionWasRaised(
323     /* [in] */ IWebView*,
324     /* [in] */ IWebScriptCallFrame*,
325     /* [in] */ int sourceID,
326     /* [in] */ int lineNumber,
327     /* [in] */ IWebFrame*)
328 {
329     HRESULT ret = S_OK;
330     if (!m_globalContext)
331         return ret;
332
333     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);
334     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);
335
336     DebuggerDocument::exceptionWasRaised(m_globalContext, sidJS, linenoJS);
337
338     return ret;
339 }
340
341 HRESULT STDMETHODCALLTYPE ServerConnection::serverDidDie()
342 {
343     m_server = 0;
344     m_currentFrame = 0;
345     m_serverConnected = false;
346     return S_OK;
347 }
348
349 // Stack & Variables
350
351 IWebScriptCallFrame* ServerConnection::currentFrame() const
352 {
353     return m_currentFrame.get();
354 }
355
356 COMPtr<IWebScriptCallFrame> ServerConnection::getCallerFrame(int callFrame) const
357 {
358     COMPtr<IWebScriptCallFrame> cframe = currentFrame();
359     for (int count = 0; count < callFrame; count++) {
360         COMPtr<IWebScriptCallFrame> callerFrame;
361         if (FAILED(cframe->caller(&callerFrame)))
362             return 0;
363
364         cframe = callerFrame;
365     }
366
367     return cframe;
368 }