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