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 "EditingDelegate.h"
31
32 #include "DumpRenderTree.h"
33 #include "LayoutTestController.h"
34 #include <WebCore/COMPtr.h>
35 #include <wtf/Platform.h>
36 #include <JavaScriptCore/Assertions.h>
37 #include <string>
38 #include <tchar.h>
39
40 using std::wstring;
41
EditingDelegate()42 EditingDelegate::EditingDelegate()
43 : m_refCount(1)
44 , m_acceptsEditing(true)
45 {
46 }
47
48 // IUnknown
QueryInterface(REFIID riid,void ** ppvObject)49 HRESULT STDMETHODCALLTYPE EditingDelegate::QueryInterface(REFIID riid, void** ppvObject)
50 {
51 *ppvObject = 0;
52 if (IsEqualGUID(riid, IID_IUnknown))
53 *ppvObject = static_cast<IWebEditingDelegate*>(this);
54 else if (IsEqualGUID(riid, IID_IWebEditingDelegate))
55 *ppvObject = static_cast<IWebEditingDelegate*>(this);
56 else
57 return E_NOINTERFACE;
58
59 AddRef();
60 return S_OK;
61 }
62
AddRef(void)63 ULONG STDMETHODCALLTYPE EditingDelegate::AddRef(void)
64 {
65 return ++m_refCount;
66 }
67
Release(void)68 ULONG STDMETHODCALLTYPE EditingDelegate::Release(void)
69 {
70 ULONG newRef = --m_refCount;
71 if (!newRef)
72 delete this;
73
74 return newRef;
75 }
76
dumpPath(IDOMNode * node)77 static wstring dumpPath(IDOMNode* node)
78 {
79 ASSERT(node);
80
81 wstring result;
82
83 BSTR name;
84 if (FAILED(node->nodeName(&name)))
85 return result;
86 result.assign(name, SysStringLen(name));
87 SysFreeString(name);
88
89 COMPtr<IDOMNode> parent;
90 if (SUCCEEDED(node->parentNode(&parent)))
91 result += TEXT(" > ") + dumpPath(parent.get());
92
93 return result;
94 }
95
dump(IDOMRange * range)96 static wstring dump(IDOMRange* range)
97 {
98 ASSERT(range);
99
100 int startOffset;
101 if (FAILED(range->startOffset(&startOffset)))
102 return 0;
103
104 int endOffset;
105 if (FAILED(range->endOffset(&endOffset)))
106 return 0;
107
108 COMPtr<IDOMNode> startContainer;
109 if (FAILED(range->startContainer(&startContainer)))
110 return 0;
111
112 COMPtr<IDOMNode> endContainer;
113 if (FAILED(range->endContainer(&endContainer)))
114 return 0;
115
116 wchar_t buffer[1024];
117 _snwprintf(buffer, ARRAYSIZE(buffer), L"range from %ld of %s to %ld of %s", startOffset, dumpPath(startContainer.get()), endOffset, dumpPath(endContainer.get()));
118 return buffer;
119 }
120
shouldBeginEditingInDOMRange(IWebView * webView,IDOMRange * range,BOOL * result)121 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldBeginEditingInDOMRange(
122 /* [in] */ IWebView* webView,
123 /* [in] */ IDOMRange* range,
124 /* [retval][out] */ BOOL* result)
125 {
126 if (!result) {
127 ASSERT_NOT_REACHED();
128 return E_POINTER;
129 }
130
131 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
132 _tprintf(TEXT("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n"), dump(range));
133
134 *result = m_acceptsEditing;
135 return S_OK;
136 }
137
shouldEndEditingInDOMRange(IWebView * webView,IDOMRange * range,BOOL * result)138 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldEndEditingInDOMRange(
139 /* [in] */ IWebView* webView,
140 /* [in] */ IDOMRange* range,
141 /* [retval][out] */ BOOL* result)
142 {
143 if (!result) {
144 ASSERT_NOT_REACHED();
145 return E_POINTER;
146 }
147
148 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
149 _tprintf(TEXT("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n"), dump(range));
150
151 *result = m_acceptsEditing;
152 return S_OK;
153 }
154
shouldInsertNode(IWebView * webView,IDOMNode * node,IDOMRange * range,WebViewInsertAction action)155 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldInsertNode(
156 /* [in] */ IWebView* webView,
157 /* [in] */ IDOMNode* node,
158 /* [in] */ IDOMRange* range,
159 /* [in] */ WebViewInsertAction action)
160 {
161 static LPCTSTR insertactionstring[] = {
162 TEXT("WebViewInsertActionTyped"),
163 TEXT("WebViewInsertActionPasted"),
164 TEXT("WebViewInsertActionDropped"),
165 };
166
167 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
168 _tprintf(TEXT("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n"), dumpPath(node), dump(range), insertactionstring[action]);
169
170 return S_OK;
171 }
172
shouldInsertText(IWebView * webView,BSTR text,IDOMRange * range,WebViewInsertAction action,BOOL * result)173 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldInsertText(
174 /* [in] */ IWebView* webView,
175 /* [in] */ BSTR text,
176 /* [in] */ IDOMRange* range,
177 /* [in] */ WebViewInsertAction action,
178 /* [retval][out] */ BOOL* result)
179 {
180 if (!result) {
181 ASSERT_NOT_REACHED();
182 return E_POINTER;
183 }
184
185 static LPCTSTR insertactionstring[] = {
186 TEXT("WebViewInsertActionTyped"),
187 TEXT("WebViewInsertActionPasted"),
188 TEXT("WebViewInsertActionDropped"),
189 };
190
191 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
192 _tprintf(TEXT("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n"), text ? text : TEXT(""), dump(range), insertactionstring[action]);
193
194 *result = m_acceptsEditing;
195 return S_OK;
196 }
197
shouldDeleteDOMRange(IWebView * webView,IDOMRange * range,BOOL * result)198 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldDeleteDOMRange(
199 /* [in] */ IWebView* webView,
200 /* [in] */ IDOMRange* range,
201 /* [retval][out] */ BOOL* result)
202 {
203 if (!result) {
204 ASSERT_NOT_REACHED();
205 return E_POINTER;
206 }
207
208 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
209 _tprintf(TEXT("EDITING DELEGATE: shouldDeleteDOMRange:%s\n"), dump(range));
210
211 *result = m_acceptsEditing;
212 return S_OK;
213 }
214
shouldChangeSelectedDOMRange(IWebView * webView,IDOMRange * currentRange,IDOMRange * proposedRange,WebSelectionAffinity selectionAffinity,BOOL stillSelecting,BOOL * result)215 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldChangeSelectedDOMRange(
216 /* [in] */ IWebView* webView,
217 /* [in] */ IDOMRange* currentRange,
218 /* [in] */ IDOMRange* proposedRange,
219 /* [in] */ WebSelectionAffinity selectionAffinity,
220 /* [in] */ BOOL stillSelecting,
221 /* [retval][out] */ BOOL* result)
222 {
223 if (!result) {
224 ASSERT_NOT_REACHED();
225 return E_POINTER;
226 }
227
228 static LPCTSTR affinitystring[] = {
229 TEXT("NSSelectionAffinityUpstream"),
230 TEXT("NSSelectionAffinityDownstream")
231 };
232 static LPCTSTR boolstring[] = {
233 TEXT("FALSE"),
234 TEXT("TRUE")
235 };
236
237 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
238 _tprintf(TEXT("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n"), dump(currentRange), dump(proposedRange), affinitystring[selectionAffinity], boolstring[stillSelecting]);
239
240 *result = m_acceptsEditing;
241 return S_OK;
242 }
243
shouldApplyStyle(IWebView * webView,IDOMCSSStyleDeclaration * style,IDOMRange * range,BOOL * result)244 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldApplyStyle(
245 /* [in] */ IWebView* webView,
246 /* [in] */ IDOMCSSStyleDeclaration* style,
247 /* [in] */ IDOMRange* range,
248 /* [retval][out] */ BOOL* result)
249 {
250 if (!result) {
251 ASSERT_NOT_REACHED();
252 return E_POINTER;
253 }
254
255 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
256 _tprintf(TEXT("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n"), TEXT("'style description'")/*[[style description] UTF8String]*/, dump(range));
257
258 *result = m_acceptsEditing;
259 return S_OK;
260 }
261
shouldChangeTypingStyle(IWebView * webView,IDOMCSSStyleDeclaration * currentStyle,IDOMCSSStyleDeclaration * proposedStyle,BOOL * result)262 HRESULT STDMETHODCALLTYPE EditingDelegate::shouldChangeTypingStyle(
263 /* [in] */ IWebView* webView,
264 /* [in] */ IDOMCSSStyleDeclaration* currentStyle,
265 /* [in] */ IDOMCSSStyleDeclaration* proposedStyle,
266 /* [retval][out] */ BOOL* result)
267 {
268 if (!result) {
269 ASSERT_NOT_REACHED();
270 return E_POINTER;
271 }
272
273 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
274 _tprintf(TEXT("EDITING DELEGATE: shouldChangeTypingStyle:%s toStyle:%s\n"), TEXT("'currentStyle description'"), TEXT("'proposedStyle description'"));
275
276 *result = m_acceptsEditing;
277 return S_OK;
278 }
279
doPlatformCommand(IWebView * webView,BSTR command,BOOL * result)280 HRESULT STDMETHODCALLTYPE EditingDelegate::doPlatformCommand(
281 /* [in] */ IWebView *webView,
282 /* [in] */ BSTR command,
283 /* [retval][out] */ BOOL *result)
284 {
285 if (!result) {
286 ASSERT_NOT_REACHED();
287 return E_POINTER;
288 }
289
290 if (::gLayoutTestController->dumpEditingCallbacks() && !done)
291 _tprintf(TEXT("EDITING DELEGATE: doPlatformCommand:%s\n"), command ? command : TEXT(""));
292
293 *result = m_acceptsEditing;
294 return S_OK;
295 }
296
webViewDidBeginEditing(IWebNotification * notification)297 HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidBeginEditing(
298 /* [in] */ IWebNotification* notification)
299 {
300 if (::gLayoutTestController->dumpEditingCallbacks() && !done) {
301 BSTR name;
302 notification->name(&name);
303 _tprintf(TEXT("EDITING DELEGATE: webViewDidBeginEditing:%s\n"), name ? name : TEXT(""));
304 SysFreeString(name);
305 }
306 return S_OK;
307 }
308
webViewDidChange(IWebNotification * notification)309 HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidChange(
310 /* [in] */ IWebNotification *notification)
311 {
312 if (::gLayoutTestController->dumpEditingCallbacks() && !done) {
313 BSTR name;
314 notification->name(&name);
315 _tprintf(TEXT("EDITING DELEGATE: webViewDidBeginEditing:%s\n"), name ? name : TEXT(""));
316 SysFreeString(name);
317 }
318 return S_OK;
319 }
320
webViewDidEndEditing(IWebNotification * notification)321 HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidEndEditing(
322 /* [in] */ IWebNotification *notification)
323 {
324 if (::gLayoutTestController->dumpEditingCallbacks() && !done) {
325 BSTR name;
326 notification->name(&name);
327 _tprintf(TEXT("EDITING DELEGATE: webViewDidEndEditing:%s\n"), name ? name : TEXT(""));
328 SysFreeString(name);
329 }
330 return S_OK;
331 }
332
webViewDidChangeTypingStyle(IWebNotification * notification)333 HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidChangeTypingStyle(
334 /* [in] */ IWebNotification *notification)
335 {
336 if (::gLayoutTestController->dumpEditingCallbacks() && !done) {
337 BSTR name;
338 notification->name(&name);
339 _tprintf(TEXT("EDITING DELEGATE: webViewDidChangeTypingStyle:%s\n"), name ? name : TEXT(""));
340 SysFreeString(name);
341 }
342 return S_OK;
343 }
344
webViewDidChangeSelection(IWebNotification * notification)345 HRESULT STDMETHODCALLTYPE EditingDelegate::webViewDidChangeSelection(
346 /* [in] */ IWebNotification *notification)
347 {
348 if (::gLayoutTestController->dumpEditingCallbacks() && !done) {
349 BSTR name;
350 notification->name(&name);
351 _tprintf(TEXT("EDITING DELEGATE: webViewDidChangeSelection:%s\n"), name ? name : TEXT(""));
352 SysFreeString(name);
353 }
354 return S_OK;
355 }
356