2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "UIDelegate.h"
32 #include "DumpRenderTree.h"
33 #include "DraggingInfo.h"
34 #include "EventSender.h"
35 #include "LayoutTestController.h"
36 #include "DRTDesktopNotificationPresenter.h"
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>
51 DRTUndoObject(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
53 , m_actionName(SysAllocString(actionName))
60 SysFreeString(m_actionName);
65 m_target->invoke(m_actionName, m_obj.get());
69 IWebUndoTarget* m_target;
71 COMPtr<IUnknown> m_obj;
76 ~DRTUndoStack() { deleteAllValues(m_undoVector); }
78 bool isEmpty() const { return m_undoVector.isEmpty(); }
79 void clear() { deleteAllValues(m_undoVector); m_undoVector.clear(); }
81 void push(DRTUndoObject* undoObject) { m_undoVector.append(undoObject); }
82 DRTUndoObject* pop() { DRTUndoObject* top = m_undoVector.last(); m_undoVector.removeLast(); return top; }
85 Vector<DRTUndoObject*> m_undoVector;
88 class DRTUndoManager {
92 void removeAllActions();
93 void registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj);
96 bool canRedo() { return !m_redoStack->isEmpty(); }
97 bool canUndo() { return !m_undoStack->isEmpty(); }
100 OwnPtr<DRTUndoStack> m_redoStack;
101 OwnPtr<DRTUndoStack> m_undoStack;
106 DRTUndoManager::DRTUndoManager()
107 : m_redoStack(adoptPtr(new DRTUndoStack))
108 , m_undoStack(adoptPtr(new DRTUndoStack))
114 void DRTUndoManager::removeAllActions()
116 m_redoStack->clear();
117 m_undoStack->clear();
120 void DRTUndoManager::registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
122 if (!m_isUndoing && !m_isRedoing)
123 m_redoStack->clear();
125 DRTUndoStack* stack = m_isUndoing ? m_redoStack.get() : m_undoStack.get();
126 stack->push(new DRTUndoObject(target, actionName, obj));
129 void DRTUndoManager::redo()
136 DRTUndoObject* redoObject = m_redoStack->pop();
137 redoObject->invoke();
143 void DRTUndoManager::undo()
150 DRTUndoObject* undoObject = m_undoStack->pop();
151 undoObject->invoke();
157 UIDelegate::UIDelegate()
159 , m_undoManager(adoptPtr(new DRTUndoManager))
160 , m_desktopNotifications(new DRTDesktopNotificationPresenter)
168 void UIDelegate::resetUndoManager()
170 m_undoManager = adoptPtr(new DRTUndoManager);
173 HRESULT STDMETHODCALLTYPE UIDelegate::QueryInterface(REFIID riid, void** ppvObject)
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);
189 return E_NOINTERFACE;
195 ULONG STDMETHODCALLTYPE UIDelegate::AddRef()
200 ULONG STDMETHODCALLTYPE UIDelegate::Release()
202 ULONG newRef = --m_refCount;
209 HRESULT STDMETHODCALLTYPE UIDelegate::hasCustomMenuImplementation(
210 /* [retval][out] */ BOOL *hasCustomMenus)
212 *hasCustomMenus = TRUE;
217 HRESULT STDMETHODCALLTYPE UIDelegate::trackCustomPopupMenu(
218 /* [in] */ IWebView *sender,
219 /* [in] */ OLE_HANDLE menu,
220 /* [in] */ LPPOINT point)
226 HRESULT STDMETHODCALLTYPE UIDelegate::registerUndoWithTarget(
227 /* [in] */ IWebUndoTarget* target,
228 /* [in] */ BSTR actionName,
229 /* [in] */ IUnknown* actionArg)
231 m_undoManager->registerUndoWithTarget(target, actionName, actionArg);
235 HRESULT STDMETHODCALLTYPE UIDelegate::removeAllActionsWithTarget(
236 /* [in] */ IWebUndoTarget*)
238 m_undoManager->removeAllActions();
242 HRESULT STDMETHODCALLTYPE UIDelegate::setActionTitle(
243 /* [in] */ BSTR actionTitle)
245 // It is not neccessary to implement this for DRT because there is
246 // menu to write out the title to.
250 HRESULT STDMETHODCALLTYPE UIDelegate::undo()
252 m_undoManager->undo();
256 HRESULT STDMETHODCALLTYPE UIDelegate::redo()
258 m_undoManager->redo();
262 HRESULT STDMETHODCALLTYPE UIDelegate::canUndo(
263 /* [retval][out] */ BOOL* result)
268 *result = m_undoManager->canUndo();
272 HRESULT STDMETHODCALLTYPE UIDelegate::canRedo(
273 /* [retval][out] */ BOOL* result)
278 *result = m_undoManager->canRedo();
282 HRESULT STDMETHODCALLTYPE UIDelegate::printFrame(
283 /* [in] */ IWebView *webView,
284 /* [in] */ IWebFrame *frame)
289 HRESULT STDMETHODCALLTYPE UIDelegate::ftpDirectoryTemplatePath(
290 /* [in] */ IWebView *webView,
291 /* [retval][out] */ BSTR *path)
300 HRESULT STDMETHODCALLTYPE UIDelegate::webViewHeaderHeight(
301 /* [in] */ IWebView *webView,
302 /* [retval][out] */ float *result)
310 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFooterHeight(
311 /* [in] */ IWebView *webView,
312 /* [retval][out] */ float *result)
320 HRESULT STDMETHODCALLTYPE UIDelegate::drawHeaderInRect(
321 /* [in] */ IWebView *webView,
322 /* [in] */ RECT *rect,
323 /* [in] */ OLE_HANDLE drawingContext)
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)
338 HRESULT STDMETHODCALLTYPE UIDelegate::webViewPrintingMarginRect(
339 /* [in] */ IWebView *webView,
340 /* [retval][out] */ RECT *rect)
345 HRESULT STDMETHODCALLTYPE UIDelegate::canRunModal(
346 /* [in] */ IWebView *webView,
347 /* [retval][out] */ BOOL *canRunBoolean)
352 HRESULT STDMETHODCALLTYPE UIDelegate::createModalDialog(
353 /* [in] */ IWebView *sender,
354 /* [in] */ IWebURLRequest *request,
355 /* [retval][out] */ IWebView **newWebView)
360 HRESULT STDMETHODCALLTYPE UIDelegate::runModal(
361 /* [in] */ IWebView *webView)
366 HRESULT STDMETHODCALLTYPE UIDelegate::isMenuBarVisible(
367 /* [in] */ IWebView *webView,
368 /* [retval][out] */ BOOL *visible)
376 HRESULT STDMETHODCALLTYPE UIDelegate::setMenuBarVisible(
377 /* [in] */ IWebView *webView,
378 /* [in] */ BOOL visible)
383 HRESULT STDMETHODCALLTYPE UIDelegate::runDatabaseSizeLimitPrompt(
384 /* [in] */ IWebView *webView,
385 /* [in] */ BSTR displayName,
386 /* [in] */ IWebFrame *initiatedByFrame,
387 /* [retval][out] */ BOOL *allowed)
395 HRESULT STDMETHODCALLTYPE UIDelegate::paintCustomScrollbar(
396 /* [in] */ IWebView *webView,
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)
410 HRESULT STDMETHODCALLTYPE UIDelegate::paintCustomScrollCorner(
411 /* [in] */ IWebView *webView,
413 /* [in] */ RECT rect)
418 HRESULT STDMETHODCALLTYPE UIDelegate::setFrame(
419 /* [in] */ IWebView* /*sender*/,
420 /* [in] */ RECT* frame)
426 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFrame(
427 /* [in] */ IWebView* /*sender*/,
428 /* [retval][out] */ RECT* frame)
434 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptAlertPanelWithMessage(
435 /* [in] */ IWebView* /*sender*/,
436 /* [in] */ BSTR message)
438 printf("ALERT: %S\n", message ? message : L"");
443 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptConfirmPanelWithMessage(
444 /* [in] */ IWebView* sender,
445 /* [in] */ BSTR message,
446 /* [retval][out] */ BOOL* result)
448 printf("CONFIRM: %S\n", message ? message : L"");
454 HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptTextInputPanelWithPrompt(
455 /* [in] */ IWebView *sender,
456 /* [in] */ BSTR message,
457 /* [in] */ BSTR defaultText,
458 /* [retval][out] */ BSTR *result)
460 printf("PROMPT: %S, default text: %S\n", message ? message : L"", defaultText ? defaultText : L"");
461 *result = SysAllocString(defaultText);
466 HRESULT STDMETHODCALLTYPE UIDelegate::runBeforeUnloadConfirmPanelWithMessage(
467 /* [in] */ IWebView* /*sender*/,
468 /* [in] */ BSTR message,
469 /* [in] */ IWebFrame* /*initiatedByFrame*/,
470 /* [retval][out] */ BOOL* result)
474 printf("CONFIRM NAVIGATION: %S\n", message ? message : L"");
475 *result = !gLayoutTestController->shouldStayOnPageAfterHandlingBeforeUnload();
479 HRESULT STDMETHODCALLTYPE UIDelegate::webViewAddMessageToConsole(
480 /* [in] */ IWebView* sender,
481 /* [in] */ BSTR message,
482 /* [in] */ int lineNumber,
484 /* [in] */ BOOL isError)
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));
494 printf("CONSOLE MESSAGE: line %d: %s\n", lineNumber, toUTF8(newMessage).c_str());
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)
505 if (!performedEffect)
508 *performedEffect = 0;
510 draggingInfo = new DraggingInfo(object, source);
511 HRESULT oleDragAndDropReturnValue = DRAGDROP_S_CANCEL;
512 replaySavedEvents(&oleDragAndDropReturnValue);
514 *performedEffect = draggingInfo->performedDropEffect();
518 return oleDragAndDropReturnValue;
521 HRESULT STDMETHODCALLTYPE UIDelegate::webViewGetDlgCode(
522 /* [in] */ IWebView* /*sender*/,
523 /* [in] */ UINT /*keyCode*/,
524 /* [retval][out] */ LONG_PTR *code)
532 HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest(
533 /* [in] */ IWebView *sender,
534 /* [in] */ IWebURLRequest *request,
535 /* [retval][out] */ IWebView **newWebView)
537 if (!::gLayoutTestController->canOpenWindows())
539 *newWebView = createWebViewAndOffscreenWindow();
543 HRESULT STDMETHODCALLTYPE UIDelegate::webViewClose(
544 /* [in] */ IWebView *sender)
547 sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
548 DestroyWindow(hostWindow);
552 HRESULT STDMETHODCALLTYPE UIDelegate::webViewFocus(
553 /* [in] */ IWebView *sender)
556 sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
557 SetForegroundWindow(hostWindow);
561 HRESULT STDMETHODCALLTYPE UIDelegate::webViewUnfocus(
562 /* [in] */ IWebView *sender)
564 SetForegroundWindow(GetDesktopWindow());
568 HRESULT STDMETHODCALLTYPE UIDelegate::webViewPainted(
569 /* [in] */ IWebView *sender)
574 HRESULT STDMETHODCALLTYPE UIDelegate::exceededDatabaseQuota(
575 /* [in] */ IWebView *sender,
576 /* [in] */ IWebFrame *frame,
577 /* [in] */ IWebSecurityOrigin *origin,
578 /* [in] */ BSTR databaseIdentifier)
584 origin->protocol(&protocol);
588 if (!done && gLayoutTestController->dumpDatabaseCallbacks())
589 printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%S, %S, %i} database:%S\n", protocol, host, port, databaseIdentifier);
591 SysFreeString(protocol);
594 static const unsigned long long defaultQuota = 5 * 1024 * 1024;
595 origin->setQuota(defaultQuota);
600 HRESULT STDMETHODCALLTYPE UIDelegate::embeddedViewWithArguments(
601 /* [in] */ IWebView *sender,
602 /* [in] */ IWebFrame *frame,
603 /* [in] */ IPropertyBag *arguments,
604 /* [retval][out] */ IWebEmbeddedView **view)
612 HRESULT STDMETHODCALLTYPE UIDelegate::webViewClosing(
613 /* [in] */ IWebView *sender)
618 HRESULT STDMETHODCALLTYPE UIDelegate::webViewSetCursor(
619 /* [in] */ IWebView *sender,
620 /* [in] */ OLE_HANDLE cursor)
625 HRESULT STDMETHODCALLTYPE UIDelegate::webViewDidInvalidate(
626 /* [in] */ IWebView *sender)
631 HRESULT STDMETHODCALLTYPE UIDelegate::setStatusText(IWebView*, BSTR text)
633 if (gLayoutTestController->dumpStatusCallbacks())
634 printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", text ? toUTF8(text).c_str() : "");
638 HRESULT STDMETHODCALLTYPE UIDelegate::desktopNotificationsDelegate(IWebDesktopNotificationsDelegate** result)
640 m_desktopNotifications.copyRefTo(result);
644 HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest(IWebView* sender, IWebURLRequest* request, IPropertyBag* windowFeatures, IWebView** newWebView)
649 HRESULT STDMETHODCALLTYPE UIDelegate::drawBackground(IWebView* sender, OLE_HANDLE hdc, const RECT* dirtyRect)
654 HRESULT STDMETHODCALLTYPE UIDelegate::decidePolicyForGeolocationRequest(IWebView* sender, IWebFrame* frame, IWebSecurityOrigin* origin, IWebGeolocationPolicyListener* listener)
659 HRESULT STDMETHODCALLTYPE UIDelegate::didPressMissingPluginButton(IDOMElement* element)
661 printf("MISSING PLUGIN BUTTON PRESSED\n");