initial import
[vuplus_webkit] / Tools / DumpRenderTree / win / UIDelegate.cpp
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 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 "UIDelegate.h"
31
32 #include "DumpRenderTree.h"
33 #include "DraggingInfo.h"
34 #include "EventSender.h"
35 #include "LayoutTestController.h"
36 #include "DRTDesktopNotificationPresenter.h"
37
38 #include <WebCore/COMPtr.h>
39 #include <wtf/PassOwnPtr.h>
40 #include <wtf/Platform.h>
41 #include <wtf/Vector.h>
42 #include <JavaScriptCore/Assertions.h>
43 #include <JavaScriptCore/JavaScriptCore.h>
44 #include <WebKit/WebKit.h>
45 #include <stdio.h>
46
47 using std::wstring;
48
49 class DRTUndoObject {
50 public:
51     DRTUndoObject(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
52         : m_target(target)
53         , m_actionName(SysAllocString(actionName))
54         , m_obj(obj)
55     {
56     }
57
58     ~DRTUndoObject()
59     {
60         SysFreeString(m_actionName);
61     }
62
63     void invoke()
64     {
65         m_target->invoke(m_actionName, m_obj.get());
66     }
67
68 private:
69     IWebUndoTarget* m_target;
70     BSTR m_actionName;
71     COMPtr<IUnknown> m_obj;
72 };
73
74 class DRTUndoStack {
75 public:
76     ~DRTUndoStack() { deleteAllValues(m_undoVector); }
77
78     bool isEmpty() const { return m_undoVector.isEmpty(); }
79     void clear() { deleteAllValues(m_undoVector); m_undoVector.clear(); }
80
81     void push(DRTUndoObject* undoObject) { m_undoVector.append(undoObject); }
82     DRTUndoObject* pop() { DRTUndoObject* top = m_undoVector.last(); m_undoVector.removeLast(); return top; }
83
84 private:
85     Vector<DRTUndoObject*> m_undoVector;
86 };
87
88 class DRTUndoManager {
89 public:
90     DRTUndoManager();
91
92     void removeAllActions();
93     void registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj);
94     void redo();
95     void undo();
96     bool canRedo() { return !m_redoStack->isEmpty(); }
97     bool canUndo() { return !m_undoStack->isEmpty(); }
98
99 private:
100     OwnPtr<DRTUndoStack> m_redoStack;
101     OwnPtr<DRTUndoStack> m_undoStack;
102     bool m_isRedoing;
103     bool m_isUndoing;
104 };
105
106 DRTUndoManager::DRTUndoManager()
107     : m_redoStack(adoptPtr(new DRTUndoStack))
108     , m_undoStack(adoptPtr(new DRTUndoStack))
109     , m_isRedoing(false)
110     , m_isUndoing(false)
111 {
112 }
113
114 void DRTUndoManager::removeAllActions()
115 {
116     m_redoStack->clear();
117     m_undoStack->clear();
118 }
119
120 void DRTUndoManager::registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
121 {
122     if (!m_isUndoing && !m_isRedoing)
123         m_redoStack->clear();
124
125     DRTUndoStack* stack = m_isUndoing ? m_redoStack.get() : m_undoStack.get();
126     stack->push(new DRTUndoObject(target, actionName, obj));
127 }
128
129 void DRTUndoManager::redo()
130 {
131     if (!canRedo())
132         return;
133
134     m_isRedoing = true;
135
136     DRTUndoObject* redoObject = m_redoStack->pop();
137     redoObject->invoke();
138     delete redoObject;
139
140     m_isRedoing = false;
141 }
142
143 void DRTUndoManager::undo()
144 {
145     if (!canUndo())
146         return;
147
148     m_isUndoing = true;
149
150     DRTUndoObject* undoObject = m_undoStack->pop();
151     undoObject->invoke();
152     delete undoObject;
153
154     m_isUndoing = false;
155 }
156
157 UIDelegate::UIDelegate()
158     : m_refCount(1)
159     , m_undoManager(adoptPtr(new DRTUndoManager))
160     , m_desktopNotifications(new DRTDesktopNotificationPresenter)
161 {
162     m_frame.bottom = 0;
163     m_frame.top = 0;
164     m_frame.left = 0;
165     m_frame.right = 0;
166 }
167
168 void UIDelegate::resetUndoManager()
169 {
170     m_undoManager = adoptPtr(new DRTUndoManager);
171 }
172
173 HRESULT STDMETHODCALLTYPE UIDelegate::QueryInterface(REFIID riid, void** ppvObject)
174 {
175     *ppvObject = 0;
176     if (IsEqualGUID(riid, IID_IUnknown))
177         *ppvObject = static_cast<IWebUIDelegate*>(this);
178     else if (IsEqualGUID(riid, IID_IWebUIDelegate))
179         *ppvObject = static_cast<IWebUIDelegate*>(this);
180     else if (IsEqualGUID(riid, IID_IWebUIDelegate2))
181         *ppvObject = static_cast<IWebUIDelegate2*>(this);
182     else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate))
183         *ppvObject = static_cast<IWebUIDelegatePrivate*>(this);
184     else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate2))
185         *ppvObject = static_cast<IWebUIDelegatePrivate2*>(this);
186     else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate3))
187         *ppvObject = static_cast<IWebUIDelegatePrivate3*>(this);
188     else
189         return E_NOINTERFACE;
190
191     AddRef();
192     return S_OK;
193 }
194
195 ULONG STDMETHODCALLTYPE UIDelegate::AddRef()
196 {
197     return ++m_refCount;
198 }
199
200 ULONG STDMETHODCALLTYPE UIDelegate::Release()
201 {
202     ULONG newRef = --m_refCount;
203     if (!newRef)
204         delete(this);
205
206     return newRef;
207 }
208
209 HRESULT STDMETHODCALLTYPE UIDelegate::hasCustomMenuImplementation( 
210         /* [retval][out] */ BOOL *hasCustomMenus)
211 {
212     *hasCustomMenus = TRUE;
213
214     return S_OK;
215 }
216
217 HRESULT STDMETHODCALLTYPE UIDelegate::trackCustomPopupMenu( 
218         /* [in] */ IWebView *sender,
219         /* [in] */ OLE_HANDLE menu,
220         /* [in] */ LPPOINT point)
221 {
222     // Do nothing
223     return S_OK;
224 }
225
226 HRESULT STDMETHODCALLTYPE UIDelegate::registerUndoWithTarget(
227         /* [in] */ IWebUndoTarget* target,
228         /* [in] */ BSTR actionName,
229         /* [in] */ IUnknown* actionArg)
230 {
231     m_undoManager->registerUndoWithTarget(target, actionName, actionArg);
232     return S_OK;
233 }
234
235 HRESULT STDMETHODCALLTYPE UIDelegate::removeAllActionsWithTarget(
236         /* [in] */ IWebUndoTarget*)
237 {
238     m_undoManager->removeAllActions();
239     return S_OK;
240 }
241
242 HRESULT STDMETHODCALLTYPE UIDelegate::setActionTitle(
243         /* [in] */ BSTR actionTitle)
244 {
245     // It is not neccessary to implement this for DRT because there is
246     // menu to write out the title to.
247     return S_OK;
248 }
249
250 HRESULT STDMETHODCALLTYPE UIDelegate::undo()
251 {
252     m_undoManager->undo();
253     return S_OK;
254 }
255
256 HRESULT STDMETHODCALLTYPE UIDelegate::redo()
257 {
258     m_undoManager->redo();
259     return S_OK;
260 }
261
262 HRESULT STDMETHODCALLTYPE UIDelegate::canUndo(
263         /* [retval][out] */ BOOL* result)
264 {
265     if (!result)
266         return E_POINTER;
267
268     *result = m_undoManager->canUndo();
269     return S_OK;
270 }
271
272 HRESULT STDMETHODCALLTYPE UIDelegate::canRedo(
273         /* [retval][out] */ BOOL* result)
274 {
275     if (!result)
276         return E_POINTER;
277
278     *result = m_undoManager->canRedo();
279     return S_OK;
280 }
281
282 HRESULT STDMETHODCALLTYPE UIDelegate::printFrame( 
283     /* [in] */ IWebView *webView,
284     /* [in] */ IWebFrame *frame)
285 {
286     return E_NOTIMPL;
287 }
288
289 HRESULT STDMETHODCALLTYPE UIDelegate::ftpDirectoryTemplatePath( 
290     /* [in] */ IWebView *webView,
291     /* [retval][out] */ BSTR *path)
292 {
293     if (!path)
294         return E_POINTER;
295     *path = 0;
296     return E_NOTIMPL;
297 }
298
299
300 HRESULT STDMETHODCALLTYPE UIDelegate::webViewHeaderHeight( 
301     /* [in] */ IWebView *webView,
302     /* [retval][out] */ float *result)
303 {
304     if (!result)
305         return E_POINTER;
306     *result = 0;
307     return E_NOTIMPL;
308 }
309
310 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFooterHeight( 
311     /* [in] */ IWebView *webView,
312     /* [retval][out] */ float *result)
313 {
314     if (!result)
315         return E_POINTER;
316     *result = 0;
317     return E_NOTIMPL;
318 }
319
320 HRESULT STDMETHODCALLTYPE UIDelegate::drawHeaderInRect( 
321     /* [in] */ IWebView *webView,
322     /* [in] */ RECT *rect,
323     /* [in] */ OLE_HANDLE drawingContext)
324 {
325     return E_NOTIMPL;
326 }
327
328 HRESULT STDMETHODCALLTYPE UIDelegate::drawFooterInRect( 
329     /* [in] */ IWebView *webView,
330     /* [in] */ RECT *rect,
331     /* [in] */ OLE_HANDLE drawingContext,
332     /* [in] */ UINT pageIndex,
333     /* [in] */ UINT pageCount)
334 {
335     return E_NOTIMPL;
336 }
337
338 HRESULT STDMETHODCALLTYPE UIDelegate::webViewPrintingMarginRect( 
339     /* [in] */ IWebView *webView,
340     /* [retval][out] */ RECT *rect)
341 {
342     return E_NOTIMPL;
343 }
344
345 HRESULT STDMETHODCALLTYPE UIDelegate::canRunModal( 
346     /* [in] */ IWebView *webView,
347     /* [retval][out] */ BOOL *canRunBoolean)
348 {
349     return E_NOTIMPL;
350 }
351
352 HRESULT STDMETHODCALLTYPE UIDelegate::createModalDialog( 
353     /* [in] */ IWebView *sender,
354     /* [in] */ IWebURLRequest *request,
355     /* [retval][out] */ IWebView **newWebView)
356 {
357     return E_NOTIMPL;
358 }
359
360 HRESULT STDMETHODCALLTYPE UIDelegate::runModal( 
361     /* [in] */ IWebView *webView)
362 {
363     return E_NOTIMPL;
364 }
365
366 HRESULT STDMETHODCALLTYPE UIDelegate::isMenuBarVisible( 
367     /* [in] */ IWebView *webView,
368     /* [retval][out] */ BOOL *visible)
369 {
370     if (!visible)
371         return E_POINTER;
372     *visible = false;
373     return E_NOTIMPL;
374 }
375
376 HRESULT STDMETHODCALLTYPE UIDelegate::setMenuBarVisible( 
377     /* [in] */ IWebView *webView,
378     /* [in] */ BOOL visible)
379 {
380     return E_NOTIMPL;
381 }
382
383 HRESULT STDMETHODCALLTYPE UIDelegate::runDatabaseSizeLimitPrompt( 
384     /* [in] */ IWebView *webView,
385     /* [in] */ BSTR displayName,
386     /* [in] */ IWebFrame *initiatedByFrame,
387     /* [retval][out] */ BOOL *allowed)
388 {
389     if (!allowed)
390         return E_POINTER;
391     *allowed = false;
392     return E_NOTIMPL;
393 }
394
395 HRESULT STDMETHODCALLTYPE UIDelegate::paintCustomScrollbar( 
396     /* [in] */ IWebView *webView,
397     /* [in] */ HDC hDC,
398     /* [in] */ RECT rect,
399     /* [in] */ WebScrollBarControlSize size,
400     /* [in] */ WebScrollbarControlState state,
401     /* [in] */ WebScrollbarControlPart pressedPart,
402     /* [in] */ BOOL vertical,
403     /* [in] */ float value,
404     /* [in] */ float proportion,
405     /* [in] */ WebScrollbarControlPartMask parts)
406 {
407     return E_NOTIMPL;
408 }
409
410 HRESULT STDMETHODCALLTYPE UIDelegate::paintCustomScrollCorner( 
411     /* [in] */ IWebView *webView,
412     /* [in] */ HDC hDC,
413     /* [in] */ RECT rect)
414 {
415     return E_NOTIMPL;
416 }
417
418 HRESULT STDMETHODCALLTYPE UIDelegate::setFrame( 
419         /* [in] */ IWebView* /*sender*/,
420         /* [in] */ RECT* frame)
421 {
422     m_frame = *frame;
423     return S_OK;
424 }
425
426 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFrame( 
427         /* [in] */ IWebView* /*sender*/,
428         /* [retval][out] */ RECT* frame)
429 {
430     *frame = m_frame;
431     return S_OK;
432 }
433
434 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptAlertPanelWithMessage( 
435         /* [in] */ IWebView* /*sender*/,
436         /* [in] */ BSTR message)
437 {
438     printf("ALERT: %S\n", message ? message : L"");
439
440     return S_OK;
441 }
442
443 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptConfirmPanelWithMessage( 
444     /* [in] */ IWebView* sender,
445     /* [in] */ BSTR message,
446     /* [retval][out] */ BOOL* result)
447 {
448     printf("CONFIRM: %S\n", message ? message : L"");
449     *result = TRUE;
450
451     return S_OK;
452 }
453
454 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptTextInputPanelWithPrompt( 
455     /* [in] */ IWebView *sender,
456     /* [in] */ BSTR message,
457     /* [in] */ BSTR defaultText,
458     /* [retval][out] */ BSTR *result)
459 {
460     printf("PROMPT: %S, default text: %S\n", message ? message : L"", defaultText ? defaultText : L"");
461     *result = SysAllocString(defaultText);
462
463     return S_OK;
464 }
465
466 HRESULT STDMETHODCALLTYPE UIDelegate::runBeforeUnloadConfirmPanelWithMessage( 
467     /* [in] */ IWebView* /*sender*/,
468     /* [in] */ BSTR message,
469     /* [in] */ IWebFrame* /*initiatedByFrame*/,
470     /* [retval][out] */ BOOL* result)
471 {
472     if (!result)
473         return E_POINTER;
474     printf("CONFIRM NAVIGATION: %S\n", message ? message : L"");
475     *result = !gLayoutTestController->shouldStayOnPageAfterHandlingBeforeUnload();
476     return S_OK;
477 }
478
479 HRESULT STDMETHODCALLTYPE UIDelegate::webViewAddMessageToConsole( 
480     /* [in] */ IWebView* sender,
481     /* [in] */ BSTR message,
482     /* [in] */ int lineNumber,
483     /* [in] */ BSTR url,
484     /* [in] */ BOOL isError)
485 {
486     wstring newMessage;
487     if (message) {
488         newMessage = message;
489         size_t fileProtocol = newMessage.find(L"file://");
490         if (fileProtocol != wstring::npos)
491             newMessage = newMessage.substr(0, fileProtocol) + lastPathComponent(newMessage.substr(fileProtocol));
492     }
493
494     printf("CONSOLE MESSAGE: line %d: %s\n", lineNumber, toUTF8(newMessage).c_str());
495     return S_OK;
496 }
497
498 HRESULT STDMETHODCALLTYPE UIDelegate::doDragDrop( 
499     /* [in] */ IWebView* sender,
500     /* [in] */ IDataObject* object,
501     /* [in] */ IDropSource* source,
502     /* [in] */ DWORD okEffect,
503     /* [retval][out] */ DWORD* performedEffect)
504 {
505     if (!performedEffect)
506         return E_POINTER;
507
508     *performedEffect = 0;
509
510     draggingInfo = new DraggingInfo(object, source);
511     HRESULT oleDragAndDropReturnValue = DRAGDROP_S_CANCEL;
512     replaySavedEvents(&oleDragAndDropReturnValue);
513     if (draggingInfo) {
514         *performedEffect = draggingInfo->performedDropEffect();
515         delete draggingInfo;
516         draggingInfo = 0;
517     }
518     return oleDragAndDropReturnValue;
519 }
520
521 HRESULT STDMETHODCALLTYPE UIDelegate::webViewGetDlgCode( 
522     /* [in] */ IWebView* /*sender*/,
523     /* [in] */ UINT /*keyCode*/,
524     /* [retval][out] */ LONG_PTR *code)
525 {
526     if (!code)
527         return E_POINTER;
528     *code = 0;
529     return E_NOTIMPL;
530 }
531
532 HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest( 
533         /* [in] */ IWebView *sender,
534         /* [in] */ IWebURLRequest *request,
535         /* [retval][out] */ IWebView **newWebView)
536 {
537     if (!::gLayoutTestController->canOpenWindows())
538         return E_FAIL;
539     *newWebView = createWebViewAndOffscreenWindow();
540     return S_OK;
541 }
542
543 HRESULT STDMETHODCALLTYPE UIDelegate::webViewClose(
544         /* [in] */ IWebView *sender)
545 {
546     HWND hostWindow;
547     sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
548     DestroyWindow(hostWindow);
549     return S_OK;
550 }
551
552 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFocus( 
553         /* [in] */ IWebView *sender)
554 {
555     HWND hostWindow;
556     sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
557     SetForegroundWindow(hostWindow);
558     return S_OK; 
559 }
560
561 HRESULT STDMETHODCALLTYPE UIDelegate::webViewUnfocus( 
562         /* [in] */ IWebView *sender)
563 {
564     SetForegroundWindow(GetDesktopWindow());
565     return S_OK; 
566 }
567
568 HRESULT STDMETHODCALLTYPE UIDelegate::webViewPainted( 
569         /* [in] */ IWebView *sender)
570 {
571     return S_OK;
572 }
573
574 HRESULT STDMETHODCALLTYPE UIDelegate::exceededDatabaseQuota( 
575         /* [in] */ IWebView *sender,
576         /* [in] */ IWebFrame *frame,
577         /* [in] */ IWebSecurityOrigin *origin,
578         /* [in] */ BSTR databaseIdentifier)
579 {
580     BSTR protocol;
581     BSTR host;
582     unsigned short port;
583
584     origin->protocol(&protocol);
585     origin->host(&host);
586     origin->port(&port);
587
588     if (!done && gLayoutTestController->dumpDatabaseCallbacks())
589         printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%S, %S, %i} database:%S\n", protocol, host, port, databaseIdentifier);
590
591     SysFreeString(protocol);
592     SysFreeString(host);
593
594     static const unsigned long long defaultQuota = 5 * 1024 * 1024;
595     origin->setQuota(defaultQuota);
596
597     return S_OK;
598 }
599
600 HRESULT STDMETHODCALLTYPE UIDelegate::embeddedViewWithArguments( 
601     /* [in] */ IWebView *sender,
602     /* [in] */ IWebFrame *frame,
603     /* [in] */ IPropertyBag *arguments,
604     /* [retval][out] */ IWebEmbeddedView **view)
605 {
606     if (!view)
607         return E_POINTER;
608     *view = 0;
609     return E_NOTIMPL;
610 }
611
612 HRESULT STDMETHODCALLTYPE UIDelegate::webViewClosing( 
613     /* [in] */ IWebView *sender)
614 {
615     return E_NOTIMPL;
616 }
617
618 HRESULT STDMETHODCALLTYPE UIDelegate::webViewSetCursor( 
619     /* [in] */ IWebView *sender,
620     /* [in] */ OLE_HANDLE cursor)
621 {
622     return E_NOTIMPL;
623 }
624
625 HRESULT STDMETHODCALLTYPE UIDelegate::webViewDidInvalidate( 
626     /* [in] */ IWebView *sender)
627 {
628     return E_NOTIMPL;
629 }
630
631 HRESULT STDMETHODCALLTYPE UIDelegate::setStatusText(IWebView*, BSTR text)
632
633     if (gLayoutTestController->dumpStatusCallbacks())
634         printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", text ? toUTF8(text).c_str() : "");
635     return S_OK;
636 }
637
638 HRESULT STDMETHODCALLTYPE UIDelegate::desktopNotificationsDelegate(IWebDesktopNotificationsDelegate** result)
639 {
640     m_desktopNotifications.copyRefTo(result);
641     return S_OK;
642 }
643
644 HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest(IWebView* sender, IWebURLRequest* request, IPropertyBag* windowFeatures, IWebView** newWebView)
645 {
646     return E_NOTIMPL;
647 }
648
649 HRESULT STDMETHODCALLTYPE UIDelegate::drawBackground(IWebView* sender, OLE_HANDLE hdc, const RECT* dirtyRect)
650 {
651     return E_NOTIMPL;
652 }
653
654 HRESULT STDMETHODCALLTYPE UIDelegate::decidePolicyForGeolocationRequest(IWebView* sender, IWebFrame* frame, IWebSecurityOrigin* origin, IWebGeolocationPolicyListener* listener)
655 {
656     return E_NOTIMPL;
657 }
658
659 HRESULT STDMETHODCALLTYPE UIDelegate::didPressMissingPluginButton(IDOMElement* element)
660 {
661     printf("MISSING PLUGIN BUTTON PRESSED\n");
662     return S_OK;
663 }
664