WebKitTools/DumpRenderTree/win/UIDelegate.cpp
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebKitTools/DumpRenderTree/win/UIDelegate.cpp	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,662 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "UIDelegate.h"
+
+#include "DumpRenderTree.h"
+#include "DraggingInfo.h"
+#include "EventSender.h"
+#include "LayoutTestController.h"
+#include "DRTDesktopNotificationPresenter.h"
+
+#include <WebCore/COMPtr.h>
+#include <wtf/Platform.h>
+#include <wtf/Vector.h>
+#include <JavaScriptCore/Assertions.h>
+#include <JavaScriptCore/JavaScriptCore.h>
+#include <WebKit/WebKit.h>
+#include <stdio.h>
+
+using std::wstring;
+
+class DRTUndoObject {
+public:
+    DRTUndoObject(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
+        : m_target(target)
+        , m_actionName(SysAllocString(actionName))
+        , m_obj(obj)
+    {
+    }
+
+    ~DRTUndoObject()
+    {
+        SysFreeString(m_actionName);
+    }
+
+    void invoke()
+    {
+        m_target->invoke(m_actionName, m_obj.get());
+    }
+
+private:
+    IWebUndoTarget* m_target;
+    BSTR m_actionName;
+    COMPtr<IUnknown> m_obj;
+};
+
+class DRTUndoStack {
+public:
+    ~DRTUndoStack() { deleteAllValues(m_undoVector); }
+
+    bool isEmpty() const { return m_undoVector.isEmpty(); }
+    void clear() { deleteAllValues(m_undoVector); m_undoVector.clear(); }
+
+    void push(DRTUndoObject* undoObject) { m_undoVector.append(undoObject); }
+    DRTUndoObject* pop() { DRTUndoObject* top = m_undoVector.last(); m_undoVector.removeLast(); return top; }
+
+private:
+    Vector<DRTUndoObject*> m_undoVector;
+};
+
+class DRTUndoManager {
+public:
+    DRTUndoManager();
+
+    void removeAllActions();
+    void registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj);
+    void redo();
+    void undo();
+    bool canRedo() { return !m_redoStack->isEmpty(); }
+    bool canUndo() { return !m_undoStack->isEmpty(); }
+
+private:
+    OwnPtr<DRTUndoStack> m_redoStack;
+    OwnPtr<DRTUndoStack> m_undoStack;
+    bool m_isRedoing;
+    bool m_isUndoing;
+};
+
+DRTUndoManager::DRTUndoManager()
+    : m_redoStack(new DRTUndoStack)
+    , m_undoStack(new DRTUndoStack)
+    , m_isRedoing(false)
+    , m_isUndoing(false)
+{
+}
+
+void DRTUndoManager::removeAllActions()
+{
+    m_redoStack->clear();
+    m_undoStack->clear();
+}
+
+void DRTUndoManager::registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
+{
+    if (!m_isUndoing && !m_isRedoing)
+        m_redoStack->clear();
+
+    DRTUndoStack* stack = m_isUndoing ? m_redoStack.get() : m_undoStack.get();
+    stack->push(new DRTUndoObject(target, actionName, obj));
+}
+
+void DRTUndoManager::redo()
+{
+    if (!canRedo())
+        return;
+
+    m_isRedoing = true;
+
+    DRTUndoObject* redoObject = m_redoStack->pop();
+    redoObject->invoke();
+    delete redoObject;
+
+    m_isRedoing = false;
+}
+
+void DRTUndoManager::undo()
+{
+    if (!canUndo())
+        return;
+
+    m_isUndoing = true;
+
+    DRTUndoObject* undoObject = m_undoStack->pop();
+    undoObject->invoke();
+    delete undoObject;
+
+    m_isUndoing = false;
+}
+
+UIDelegate::UIDelegate()
+    : m_refCount(1)
+    , m_undoManager(new DRTUndoManager)
+    , m_desktopNotifications(new DRTDesktopNotificationPresenter)
+{
+    m_frame.bottom = 0;
+    m_frame.top = 0;
+    m_frame.left = 0;
+    m_frame.right = 0;
+}
+
+void UIDelegate::resetUndoManager()
+{
+    m_undoManager.set(new DRTUndoManager);
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::QueryInterface(REFIID riid, void** ppvObject)
+{
+    *ppvObject = 0;
+    if (IsEqualGUID(riid, IID_IUnknown))
+        *ppvObject = static_cast<IWebUIDelegate*>(this);
+    else if (IsEqualGUID(riid, IID_IWebUIDelegate))
+        *ppvObject = static_cast<IWebUIDelegate*>(this);
+    else if (IsEqualGUID(riid, IID_IWebUIDelegate2))
+        *ppvObject = static_cast<IWebUIDelegate2*>(this);
+    else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate))
+        *ppvObject = static_cast<IWebUIDelegatePrivate*>(this);
+    else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate2))
+        *ppvObject = static_cast<IWebUIDelegatePrivate2*>(this);
+    else if (IsEqualGUID(riid, IID_IWebUIDelegatePrivate3))
+        *ppvObject = static_cast<IWebUIDelegatePrivate3*>(this);
+    else
+        return E_NOINTERFACE;
+
+    AddRef();
+    return S_OK;
+}
+
+ULONG STDMETHODCALLTYPE UIDelegate::AddRef()
+{
+    return ++m_refCount;
+}
+
+ULONG STDMETHODCALLTYPE UIDelegate::Release()
+{
+    ULONG newRef = --m_refCount;
+    if (!newRef)
+        delete(this);
+
+    return newRef;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::hasCustomMenuImplementation( 
+        /* [retval][out] */ BOOL *hasCustomMenus)
+{
+    *hasCustomMenus = TRUE;
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::trackCustomPopupMenu( 
+        /* [in] */ IWebView *sender,
+        /* [in] */ OLE_HANDLE menu,
+        /* [in] */ LPPOINT point)
+{
+    // Do nothing
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::registerUndoWithTarget(
+        /* [in] */ IWebUndoTarget* target,
+        /* [in] */ BSTR actionName,
+        /* [in] */ IUnknown* actionArg)
+{
+    m_undoManager->registerUndoWithTarget(target, actionName, actionArg);
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::removeAllActionsWithTarget(
+        /* [in] */ IWebUndoTarget*)
+{
+    m_undoManager->removeAllActions();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::setActionTitle(
+        /* [in] */ BSTR actionTitle)
+{
+    // It is not neccessary to implement this for DRT because there is
+    // menu to write out the title to.
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::undo()
+{
+    m_undoManager->undo();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::redo()
+{
+    m_undoManager->redo();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::canUndo(
+        /* [retval][out] */ BOOL* result)
+{
+    if (!result)
+        return E_POINTER;
+
+    *result = m_undoManager->canUndo();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::canRedo(
+        /* [retval][out] */ BOOL* result)
+{
+    if (!result)
+        return E_POINTER;
+
+    *result = m_undoManager->canRedo();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::printFrame( 
+    /* [in] */ IWebView *webView,
+    /* [in] */ IWebFrame *frame)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::ftpDirectoryTemplatePath( 
+    /* [in] */ IWebView *webView,
+    /* [retval][out] */ BSTR *path)
+{
+    if (!path)
+        return E_POINTER;
+    *path = 0;
+    return E_NOTIMPL;
+}
+
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewHeaderHeight( 
+    /* [in] */ IWebView *webView,
+    /* [retval][out] */ float *result)
+{
+    if (!result)
+        return E_POINTER;
+    *result = 0;
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewFooterHeight( 
+    /* [in] */ IWebView *webView,
+    /* [retval][out] */ float *result)
+{
+    if (!result)
+        return E_POINTER;
+    *result = 0;
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::drawHeaderInRect( 
+    /* [in] */ IWebView *webView,
+    /* [in] */ RECT *rect,
+    /* [in] */ OLE_HANDLE drawingContext)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::drawFooterInRect( 
+    /* [in] */ IWebView *webView,
+    /* [in] */ RECT *rect,
+    /* [in] */ OLE_HANDLE drawingContext,
+    /* [in] */ UINT pageIndex,
+    /* [in] */ UINT pageCount)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewPrintingMarginRect( 
+    /* [in] */ IWebView *webView,
+    /* [retval][out] */ RECT *rect)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::canRunModal( 
+    /* [in] */ IWebView *webView,
+    /* [retval][out] */ BOOL *canRunBoolean)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::createModalDialog( 
+    /* [in] */ IWebView *sender,
+    /* [in] */ IWebURLRequest *request,
+    /* [retval][out] */ IWebView **newWebView)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::runModal( 
+    /* [in] */ IWebView *webView)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::isMenuBarVisible( 
+    /* [in] */ IWebView *webView,
+    /* [retval][out] */ BOOL *visible)
+{
+    if (!visible)
+        return E_POINTER;
+    *visible = false;
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::setMenuBarVisible( 
+    /* [in] */ IWebView *webView,
+    /* [in] */ BOOL visible)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::runDatabaseSizeLimitPrompt( 
+    /* [in] */ IWebView *webView,
+    /* [in] */ BSTR displayName,
+    /* [in] */ IWebFrame *initiatedByFrame,
+    /* [retval][out] */ BOOL *allowed)
+{
+    if (!allowed)
+        return E_POINTER;
+    *allowed = false;
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::paintCustomScrollbar( 
+    /* [in] */ IWebView *webView,
+    /* [in] */ HDC hDC,
+    /* [in] */ RECT rect,
+    /* [in] */ WebScrollBarControlSize size,
+    /* [in] */ WebScrollbarControlState state,
+    /* [in] */ WebScrollbarControlPart pressedPart,
+    /* [in] */ BOOL vertical,
+    /* [in] */ float value,
+    /* [in] */ float proportion,
+    /* [in] */ WebScrollbarControlPartMask parts)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::paintCustomScrollCorner( 
+    /* [in] */ IWebView *webView,
+    /* [in] */ HDC hDC,
+    /* [in] */ RECT rect)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::setFrame( 
+        /* [in] */ IWebView* /*sender*/,
+        /* [in] */ RECT* frame)
+{
+    m_frame = *frame;
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewFrame( 
+        /* [in] */ IWebView* /*sender*/,
+        /* [retval][out] */ RECT* frame)
+{
+    *frame = m_frame;
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptAlertPanelWithMessage( 
+        /* [in] */ IWebView* /*sender*/,
+        /* [in] */ BSTR message)
+{
+    printf("ALERT: %S\n", message ? message : L"");
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptConfirmPanelWithMessage( 
+    /* [in] */ IWebView* sender,
+    /* [in] */ BSTR message,
+    /* [retval][out] */ BOOL* result)
+{
+    printf("CONFIRM: %S\n", message ? message : L"");
+    *result = TRUE;
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::runJavaScriptTextInputPanelWithPrompt( 
+    /* [in] */ IWebView *sender,
+    /* [in] */ BSTR message,
+    /* [in] */ BSTR defaultText,
+    /* [retval][out] */ BSTR *result)
+{
+    printf("PROMPT: %S, default text: %S\n", message ? message : L"", defaultText ? defaultText : L"");
+    *result = SysAllocString(defaultText);
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::runBeforeUnloadConfirmPanelWithMessage( 
+    /* [in] */ IWebView* /*sender*/,
+    /* [in] */ BSTR /*message*/,
+    /* [in] */ IWebFrame* /*initiatedByFrame*/,
+    /* [retval][out] */ BOOL* result)
+{
+    if (!result)
+        return E_POINTER;
+    *result = TRUE;
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewAddMessageToConsole( 
+    /* [in] */ IWebView* sender,
+    /* [in] */ BSTR message,
+    /* [in] */ int lineNumber,
+    /* [in] */ BSTR url,
+    /* [in] */ BOOL isError)
+{
+    wstring newMessage;
+    if (message) {
+        newMessage = message;
+        size_t fileProtocol = newMessage.find(L"file://");
+        if (fileProtocol != wstring::npos)
+            newMessage = newMessage.substr(0, fileProtocol) + urlSuitableForTestResult(newMessage.substr(fileProtocol));
+    }
+
+    printf("CONSOLE MESSAGE: line %d: %s\n", lineNumber, toUTF8(newMessage).c_str());
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::doDragDrop( 
+    /* [in] */ IWebView* sender,
+    /* [in] */ IDataObject* object,
+    /* [in] */ IDropSource* source,
+    /* [in] */ DWORD okEffect,
+    /* [retval][out] */ DWORD* performedEffect)
+{
+    if (!performedEffect)
+        return E_POINTER;
+
+    *performedEffect = 0;
+
+    draggingInfo = new DraggingInfo(object, source);
+    HRESULT oleDragAndDropReturnValue = DRAGDROP_S_CANCEL;
+    replaySavedEvents(&oleDragAndDropReturnValue);
+    if (draggingInfo) {
+        *performedEffect = draggingInfo->performedDropEffect();
+        delete draggingInfo;
+        draggingInfo = 0;
+    }
+    return oleDragAndDropReturnValue;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewGetDlgCode( 
+    /* [in] */ IWebView* /*sender*/,
+    /* [in] */ UINT /*keyCode*/,
+    /* [retval][out] */ LONG_PTR *code)
+{
+    if (!code)
+        return E_POINTER;
+    *code = 0;
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest( 
+        /* [in] */ IWebView *sender,
+        /* [in] */ IWebURLRequest *request,
+        /* [retval][out] */ IWebView **newWebView)
+{
+    if (!::gLayoutTestController->canOpenWindows())
+        return E_FAIL;
+    *newWebView = createWebViewAndOffscreenWindow();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewClose(
+        /* [in] */ IWebView *sender)
+{
+    HWND hostWindow;
+    sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
+    DestroyWindow(hostWindow);
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewFocus( 
+        /* [in] */ IWebView *sender)
+{
+    HWND hostWindow;
+    sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
+    SetForegroundWindow(hostWindow);
+    return S_OK; 
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewUnfocus( 
+        /* [in] */ IWebView *sender)
+{
+    SetForegroundWindow(GetDesktopWindow());
+    return S_OK; 
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewPainted( 
+        /* [in] */ IWebView *sender)
+{
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::exceededDatabaseQuota( 
+        /* [in] */ IWebView *sender,
+        /* [in] */ IWebFrame *frame,
+        /* [in] */ IWebSecurityOrigin *origin,
+        /* [in] */ BSTR databaseIdentifier)
+{
+    BSTR protocol;
+    BSTR host;
+    unsigned short port;
+
+    origin->protocol(&protocol);
+    origin->host(&host);
+    origin->port(&port);
+
+    if (!done && gLayoutTestController->dumpDatabaseCallbacks())
+        printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%S, %S, %i} database:%S\n", protocol, host, port, databaseIdentifier);
+
+    SysFreeString(protocol);
+    SysFreeString(host);
+
+    static const unsigned long long defaultQuota = 5 * 1024 * 1024;
+    origin->setQuota(defaultQuota);
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::embeddedViewWithArguments( 
+    /* [in] */ IWebView *sender,
+    /* [in] */ IWebFrame *frame,
+    /* [in] */ IPropertyBag *arguments,
+    /* [retval][out] */ IWebEmbeddedView **view)
+{
+    if (!view)
+        return E_POINTER;
+    *view = 0;
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewClosing( 
+    /* [in] */ IWebView *sender)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewSetCursor( 
+    /* [in] */ IWebView *sender,
+    /* [in] */ OLE_HANDLE cursor)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::webViewDidInvalidate( 
+    /* [in] */ IWebView *sender)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::setStatusText(IWebView*, BSTR text)
+{ 
+    if (gLayoutTestController->dumpStatusCallbacks())
+        printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", text ? toUTF8(text).c_str() : "");
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::desktopNotificationsDelegate(IWebDesktopNotificationsDelegate** result)
+{
+    m_desktopNotifications.copyRefTo(result);
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::createWebViewWithRequest(IWebView* sender, IWebURLRequest* request, IPropertyBag* windowFeatures, IWebView** newWebView)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::drawBackground(IWebView* sender, OLE_HANDLE hdc, const RECT* dirtyRect)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::decidePolicyForGeolocationRequest(IWebView* sender, IWebFrame* frame, IWebSecurityOrigin* origin, IWebGeolocationPolicyListener* listener)
+{
+    return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE UIDelegate::didPressMissingPluginButton(IDOMElement* element)
+{
+    printf("MISSING PLUGIN BUTTON PRESSED\n");
+    return S_OK;
+}
+