Reviewed by Adam.
[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/WebKit.h>
40
41 ServerConnection::ServerConnection()
42     : m_globalContext(0)
43 {
44     HRESULT serverCreated = CoCreateInstance(CLSID_WebScriptDebugServer, 0, CLSCTX_LOCAL_SERVER, IID_IWebScriptDebugServer, (void**)&m_server);
45     if (!FAILED(serverCreated))
46         m_server->addListener(this);
47 }
48
49 ServerConnection::~ServerConnection()
50 {
51     if (m_server)
52         m_server->removeListener(this);
53
54     if (m_globalContext)
55         JSGlobalContextRelease(m_globalContext);
56 }
57
58 void ServerConnection::setGlobalContext(JSGlobalContextRef globalContextRef)
59 {
60     m_globalContext = JSGlobalContextRetain(globalContextRef);
61 }
62
63 void ServerConnection::pause()
64 {
65     if (m_server)
66         m_server->pause();
67 }
68
69 void ServerConnection::resume()
70 {
71     if (m_server)
72         m_server->resume();
73 }
74
75 void ServerConnection::stepInto()
76 {
77     if (m_server)
78         m_server->step();
79 }
80
81 // Connection Handling
82
83 void ServerConnection::applicationTerminating()
84 {
85     if (m_server)
86         m_server->removeListener(this);
87 }
88
89 void ServerConnection::serverConnectionDidDie()
90 {
91     if (m_server)
92         m_server->removeListener(this);
93 }
94
95 // Stack & Variables
96
97 IWebScriptCallFrame* ServerConnection::currentFrame() const
98 {
99     return m_currentFrame;
100 }
101
102 IWebScriptCallFrame* ServerConnection::getCallerFrame(int callFrame) const
103 {
104     COMPtr<IWebScriptCallFrame> cframe = currentFrame();
105     COMPtr<IWebScriptCallFrame> callerFrame;
106     for (int count = 0; count < callFrame; count++) {
107         if (FAILED(cframe->caller(&callerFrame)))
108             return 0;
109
110         cframe = callerFrame;
111     }
112
113     return cframe.get();
114 }
115
116
117 // IUnknown --------------------------------------------------
118 HRESULT STDMETHODCALLTYPE ServerConnection::QueryInterface(REFIID riid, void** ppvObject)
119 {
120     *ppvObject = 0;
121     if (IsEqualGUID(riid, IID_IUnknown))
122         *ppvObject = this;
123     else if (IsEqualGUID(riid, IID_IWebScriptDebugListener))
124         *ppvObject = static_cast<IWebScriptDebugListener*>(this);
125     else
126         return E_NOINTERFACE;
127
128     AddRef();
129     return S_OK;
130 }
131
132 ULONG STDMETHODCALLTYPE ServerConnection::AddRef(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
138 ULONG STDMETHODCALLTYPE ServerConnection::Release(void)
139 {
140     // COM ref-counting isn't useful to us because we're in charge of the lifetime of the WebView.
141     return 1;
142 }
143 // IWebScriptDebugListener -----------------------------------
144 HRESULT STDMETHODCALLTYPE ServerConnection::didLoadMainResourceForDataSource(
145     /* [in] */ IWebView*,
146     /* [in] */ IWebDataSource* dataSource)
147 {
148     // Get document source
149     COMPtr<IWebDocumentRepresentation> rep;
150     HRESULT ret = dataSource->representation(&rep);
151     if (FAILED(ret))
152         return ret;
153
154     BOOL canProvideDocumentSource = FALSE;
155     ret = rep->canProvideDocumentSource(&canProvideDocumentSource);
156     if (FAILED(ret))
157         return ret;
158
159     BSTR documentSource = 0;
160     if (canProvideDocumentSource)
161         ret = rep->documentSource(&documentSource);
162
163     if (FAILED(ret) || !documentSource)
164         return ret;
165
166     JSRetainPtr<JSStringRef> documentSourceJS(Adopt, JSStringCreateWithBSTR(documentSource));
167     SysFreeString(documentSource);
168
169     // Get URL
170     COMPtr<IWebURLResponse> response;
171     ret = dataSource->response(&response);
172     if (FAILED(ret))
173         return ret;
174
175     BSTR url = 0;
176     ret = response->URL(&url);
177     if (FAILED(ret))
178         return ret;
179
180     JSRetainPtr<JSStringRef> urlJS(Adopt, JSStringCreateWithBSTR(url));
181     SysFreeString(url);
182
183     DebuggerDocument::updateFileSource(m_globalContext, documentSourceJS.get(), urlJS.get());
184
185     return S_OK;
186 }
187
188 HRESULT STDMETHODCALLTYPE ServerConnection::didParseSource(
189     /* [in] */ IWebView*,
190     /* [in] */ BSTR sourceCode,
191     /* [in] */ UINT baseLineNumber,
192     /* [in] */ BSTR url,
193     /* [in] */ int sourceID,
194     /* [in] */ IWebFrame* webFrame)
195 {
196     HRESULT ret = S_OK;
197     if (!m_globalContext || !sourceCode)\r
198         return ret;\r
199 \r
200     COMPtr<IWebDataSource> dataSource;\r
201     ret = webFrame->dataSource(&dataSource);\r
202     if (FAILED(ret))\r
203         return ret;\r
204 \r
205     COMPtr<IWebURLResponse> response;\r
206     ret = dataSource->response(&response);\r
207     if (FAILED(ret))\r
208         return ret;\r
209 \r
210     BSTR responseURL;\r
211     ret = response->URL(&responseURL);\r
212     if (FAILED(ret))\r
213         return ret;\r
214 \r
215     BSTR documentSource = 0;\r
216     if (!url || !wcscmp(responseURL, url)) {\r
217         COMPtr<IWebDocumentRepresentation> rep;\r
218         ret = dataSource->representation(&rep);\r
219         if (FAILED(ret))\r
220             return ret;\r
221 \r
222         BOOL canProvideDocumentSource;\r
223         rep->canProvideDocumentSource(&canProvideDocumentSource);\r
224         if (FAILED(ret))\r
225             return ret;\r
226 \r
227         if (canProvideDocumentSource) {\r
228             ret = rep->documentSource(&documentSource);\r
229             if (FAILED(ret))\r
230                 return ret;\r
231         }\r
232 \r
233         if (!url) {\r
234             ret = response->URL(&url);\r
235             if (FAILED(ret))\r
236                 return ret;\r
237         }\r
238     }\r
239     SysFreeString(responseURL);\r
240 \r
241     JSRetainPtr<JSStringRef> sourceJS(Adopt, JSStringCreateWithBSTR(sourceCode));\r
242     JSRetainPtr<JSStringRef> documentSourceJS(Adopt, JSStringCreateWithBSTR(documentSource));\r
243     SysFreeString(documentSource);\r
244     JSRetainPtr<JSStringRef> urlJS(Adopt, JSStringCreateWithBSTR(url));\r
245     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);\r
246     JSValueRef baseLineJS = JSValueMakeNumber(m_globalContext, baseLineNumber);\r
247 \r
248     DebuggerDocument::didParseScript(m_globalContext, sourceJS.get(), documentSourceJS.get(), urlJS.get(), sidJS, baseLineJS);\r
249
250     return S_OK;
251 }
252
253 HRESULT STDMETHODCALLTYPE ServerConnection::failedToParseSource(
254     /* [in] */ IWebView*,
255     /* [in] */ BSTR,
256     /* [in] */ UINT,
257     /* [in] */ BSTR,
258     /* [in] */ BSTR,
259     /* [in] */ IWebFrame*)
260 {
261     return S_OK;
262 }
263
264 HRESULT STDMETHODCALLTYPE ServerConnection::didEnterCallFrame(
265     /* [in] */ IWebView*,
266     /* [in] */ IWebScriptCallFrame* frame,
267     /* [in] */ int sourceID,
268     /* [in] */ int lineNumber,
269     /* [in] */ IWebFrame*)
270 {
271     HRESULT ret = S_OK;
272     if (!m_globalContext)\r
273         return ret;\r
274 \r
275     // FIXME: This won't be relevant until IWebScriptCallFrame is implemented on Windows\r
276     m_currentFrame = frame;\r
277 \r
278     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);\r
279     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);\r
280 \r
281     DebuggerDocument::didEnterCallFrame(m_globalContext, sidJS, linenoJS);\r
282
283     return ret;
284 }
285
286 HRESULT STDMETHODCALLTYPE ServerConnection::willExecuteStatement(
287     /* [in] */ IWebView*,
288     /* [in] */ IWebScriptCallFrame*,
289     /* [in] */ int sourceID,
290     /* [in] */ int lineNumber,
291     /* [in] */ IWebFrame*)
292 {
293     HRESULT ret = S_OK;
294     if (!m_globalContext)\r
295         return ret;\r
296 \r
297     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);\r
298     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);\r
299 \r
300     DebuggerDocument::willExecuteStatement(m_globalContext, sidJS, linenoJS);
301     return ret;
302 }
303
304 HRESULT STDMETHODCALLTYPE ServerConnection::willLeaveCallFrame(
305     /* [in] */ IWebView*,
306     /* [in] */ IWebScriptCallFrame* frame,
307     /* [in] */ int sourceID,
308     /* [in] */ int lineNumber,
309     /* [in] */ IWebFrame*)
310 {
311     HRESULT ret = S_OK;
312     if (!m_globalContext)\r
313         return ret;\r
314 \r
315     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);\r
316     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);\r
317 \r
318     DebuggerDocument::willLeaveCallFrame(m_globalContext, sidJS, linenoJS);\r
319 \r
320     // FIXME: This won't be relevant until IWebScriptCallFrame is implemented on Windows\r
321     m_currentFrame = frame;\r
322
323     return S_OK;
324 }
325
326 HRESULT STDMETHODCALLTYPE ServerConnection::exceptionWasRaised(
327     /* [in] */ IWebView*,
328     /* [in] */ IWebScriptCallFrame*,
329     /* [in] */ int sourceID,
330     /* [in] */ int lineNumber,
331     /* [in] */ IWebFrame*)
332 {
333     HRESULT ret = S_OK;
334     if (!m_globalContext)\r
335         return ret;\r
336 \r
337     JSValueRef sidJS = JSValueMakeNumber(m_globalContext, sourceID);\r
338     JSValueRef linenoJS = JSValueMakeNumber(m_globalContext, lineNumber);\r
339 \r
340     DebuggerDocument::exceptionWasRaised(m_globalContext, sidJS, linenoJS);
341
342     return ret;
343 }