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