2 * Copyright (C) 2005, 2006, 2007, 2008, 2014 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 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 "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>
52 DRTUndoObject(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
54 , m_actionName(SysAllocString(actionName))
61 SysFreeString(m_actionName);
66 m_target->invoke(m_actionName, m_obj.get());
70 IWebUndoTarget* m_target;
72 COMPtr<IUnknown> m_obj;
77 ~DRTUndoStack() { deprecatedDeleteAllValues(m_undoVector); }
79 bool isEmpty() const { return m_undoVector.isEmpty(); }
80 void clear() { deprecatedDeleteAllValues(m_undoVector); m_undoVector.clear(); }
82 void push(DRTUndoObject* undoObject) { m_undoVector.append(undoObject); }
83 DRTUndoObject* pop() { DRTUndoObject* top = m_undoVector.last(); m_undoVector.removeLast(); return top; }
86 Vector<DRTUndoObject*> m_undoVector;
89 class DRTUndoManager {
93 void removeAllActions();
94 void registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj);
97 bool canRedo() { return !m_redoStack->isEmpty(); }
98 bool canUndo() { return !m_undoStack->isEmpty(); }
101 OwnPtr<DRTUndoStack> m_redoStack;
102 OwnPtr<DRTUndoStack> m_undoStack;
107 DRTUndoManager::DRTUndoManager()
108 : m_redoStack(adoptPtr(new DRTUndoStack))
109 , m_undoStack(adoptPtr(new DRTUndoStack))
115 void DRTUndoManager::removeAllActions()
117 m_redoStack->clear();
118 m_undoStack->clear();
121 void DRTUndoManager::registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* obj)
123 if (!m_isUndoing && !m_isRedoing)
124 m_redoStack->clear();
126 DRTUndoStack* stack = m_isUndoing ? m_redoStack.get() : m_undoStack.get();
127 stack->push(new DRTUndoObject(target, actionName, obj));
130 void DRTUndoManager::redo()
137 DRTUndoObject* redoObject = m_redoStack->pop();
138 redoObject->invoke();
144 void DRTUndoManager::undo()
151 DRTUndoObject* undoObject = m_undoStack->pop();
152 undoObject->invoke();
158 UIDelegate::UIDelegate()
160 , m_undoManager(adoptPtr(new DRTUndoManager))
161 , m_desktopNotifications(new DRTDesktopNotificationPresenter)
169 void UIDelegate::resetUndoManager()
171 m_undoManager = adoptPtr(new DRTUndoManager);
174 HRESULT UIDelegate::QueryInterface(REFIID riid, void** ppvObject)
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);
190 return E_NOINTERFACE;
196 ULONG UIDelegate::AddRef()
201 ULONG UIDelegate::Release()
203 ULONG newRef = --m_refCount;
210 HRESULT UIDelegate::hasCustomMenuImplementation(BOOL* hasCustomMenus)
212 *hasCustomMenus = TRUE;
217 HRESULT UIDelegate::trackCustomPopupMenu(IWebView* /*sender*/, OLE_HANDLE /*menu*/, LPPOINT /*point*/)
223 HRESULT UIDelegate::registerUndoWithTarget(IWebUndoTarget* target, BSTR actionName, IUnknown* actionArg)
225 m_undoManager->registerUndoWithTarget(target, actionName, actionArg);
229 HRESULT UIDelegate::removeAllActionsWithTarget(IWebUndoTarget*)
231 m_undoManager->removeAllActions();
235 HRESULT UIDelegate::setActionTitle(BSTR /*actionTitle*/)
237 // It is not neccessary to implement this for DRT because there is
238 // menu to write out the title to.
242 HRESULT UIDelegate::undo()
244 m_undoManager->undo();
248 HRESULT UIDelegate::redo()
250 m_undoManager->redo();
254 HRESULT UIDelegate::canUndo(BOOL* result)
259 *result = m_undoManager->canUndo();
263 HRESULT UIDelegate::canRedo(BOOL* result)
268 *result = m_undoManager->canRedo();
272 HRESULT UIDelegate::printFrame(IWebView* /*webView*/, IWebFrame* /*frame*/)
277 HRESULT UIDelegate::ftpDirectoryTemplatePath(IWebView* /*webView*/, BSTR* path)
286 HRESULT UIDelegate::webViewHeaderHeight(IWebView* /*webView*/, float* result)
294 HRESULT UIDelegate::webViewFooterHeight(IWebView* /*webView*/, float* result)
302 HRESULT UIDelegate::drawHeaderInRect(IWebView* /*webView*/, RECT* /*rect*/, OLE_HANDLE /*drawingContext*/)
307 HRESULT UIDelegate::drawFooterInRect(IWebView* /*webView*/, RECT* /*rect*/, OLE_HANDLE /*drawingContext*/, UINT /*pageIndex*/, UINT /*pageCount*/)
312 HRESULT UIDelegate::webViewPrintingMarginRect(IWebView* /*webView*/, RECT* /*rect*/)
317 HRESULT UIDelegate::canRunModal(IWebView* /*webView*/, BOOL* /*canRunBoolean*/)
322 HRESULT UIDelegate::createModalDialog(IWebView* /*sender*/, IWebURLRequest* /*request*/, IWebView** /*newWebView*/)
327 HRESULT UIDelegate::runModal(IWebView* /*webView*/)
332 HRESULT UIDelegate::isMenuBarVisible(IWebView* /*webView*/, BOOL* visible)
340 HRESULT UIDelegate::setMenuBarVisible(IWebView* /*webView*/, BOOL /*visible*/)
345 HRESULT UIDelegate::runDatabaseSizeLimitPrompt(IWebView* /*webView*/, BSTR /*displayName*/, IWebFrame* /*initiatedByFrame*/, BOOL* allowed)
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*/)
359 HRESULT UIDelegate::paintCustomScrollCorner(IWebView* /*webView*/, HDC /*hDC*/, RECT /*rect*/)
364 HRESULT UIDelegate::setFrame(IWebView* /*sender*/, RECT* frame)
370 HRESULT UIDelegate::webViewFrame(IWebView* /*sender*/, RECT* frame)
376 HRESULT UIDelegate::runJavaScriptAlertPanelWithMessage(IWebView* /*sender*/, BSTR message)
378 printf("ALERT: %S\n", message ? message : L"");
384 HRESULT UIDelegate::runJavaScriptConfirmPanelWithMessage(IWebView* /*sender*/, BSTR message, BOOL* result)
386 printf("CONFIRM: %S\n", message ? message : L"");
392 HRESULT UIDelegate::runJavaScriptTextInputPanelWithPrompt(IWebView* /*sender*/, BSTR message, BSTR defaultText, BSTR* result)
394 printf("PROMPT: %S, default text: %S\n", message ? message : L"", defaultText ? defaultText : L"");
395 *result = SysAllocString(defaultText);
400 HRESULT UIDelegate::runBeforeUnloadConfirmPanelWithMessage(IWebView* /*sender*/, BSTR message, IWebFrame* /*initiatedByFrame*/, BOOL* result)
404 printf("CONFIRM NAVIGATION: %S\n", message ? message : L"");
405 *result = !gTestRunner->shouldStayOnPageAfterHandlingBeforeUnload();
409 HRESULT UIDelegate::webViewAddMessageToConsole(IWebView* /*sender*/, BSTR message, int lineNumber, BSTR url, BOOL isError)
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));
419 printf("CONSOLE MESSAGE: ");
421 printf("line %d: ", lineNumber);
422 printf("%s\n", toUTF8(newMessage).c_str());
426 HRESULT UIDelegate::doDragDrop(IWebView* /*sender*/, IDataObject* object, IDropSource* source, DWORD /*okEffect*/, DWORD* performedEffect)
428 if (!performedEffect)
431 *performedEffect = 0;
433 draggingInfo = new DraggingInfo(object, source);
434 HRESULT oleDragAndDropReturnValue = DRAGDROP_S_CANCEL;
435 replaySavedEvents(&oleDragAndDropReturnValue);
437 *performedEffect = draggingInfo->performedDropEffect();
441 return oleDragAndDropReturnValue;
444 HRESULT UIDelegate::webViewGetDlgCode(IWebView* /*sender*/, UINT /*keyCode*/, LONG_PTR* code)
452 HRESULT UIDelegate::createWebViewWithRequest(IWebView* /*sender*/, IWebURLRequest* /*request*/, IWebView** newWebView)
454 if (!::gTestRunner->canOpenWindows())
456 *newWebView = createWebViewAndOffscreenWindow();
460 HRESULT UIDelegate::webViewClose(IWebView* sender)
463 sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
464 DestroyWindow(hostWindow);
468 HRESULT UIDelegate::webViewFocus(IWebView* sender)
471 sender->hostWindow(reinterpret_cast<OLE_HANDLE*>(&hostWindow));
472 SetForegroundWindow(hostWindow);
476 HRESULT UIDelegate::webViewUnfocus(IWebView* /*sender*/)
478 SetForegroundWindow(GetDesktopWindow());
482 HRESULT UIDelegate::webViewPainted(IWebView* /*sender*/)
487 HRESULT UIDelegate::exceededDatabaseQuota(IWebView* sender, IWebFrame* frame, IWebSecurityOrigin* origin, BSTR databaseIdentifier)
493 origin->protocol(&protocol.GetBSTR());
494 origin->host(&host.GetBSTR());
497 if (!done && gTestRunner->dumpDatabaseCallbacks())
498 printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%S, %S, %i} database:%S\n", protocol, host, port, databaseIdentifier);
500 unsigned long long defaultQuota = 5 * 1024 * 1024;
501 double testDefaultQuota = gTestRunner->databaseDefaultQuota();
502 if (testDefaultQuota >= 0)
503 defaultQuota = testDefaultQuota;
505 COMPtr<IWebDatabaseManager> databaseManager;
506 COMPtr<IWebDatabaseManager> tmpDatabaseManager;
508 if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager))) {
509 origin->setQuota(defaultQuota);
512 if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager))) {
513 origin->setQuota(defaultQuota);
516 IPropertyBag* detailsBag;
517 if (FAILED(databaseManager->detailsForDatabase(databaseIdentifier, origin, &detailsBag))) {
518 origin->setQuota(defaultQuota);
522 detailsBag->Read(WebDatabaseUsageKey, &var, 0);
523 unsigned long long expectedSize = V_UI8(&var);
524 unsigned long long newQuota = defaultQuota;
526 double maxQuota = gTestRunner->databaseMaxQuota();
528 if (defaultQuota < expectedSize && expectedSize <= maxQuota) {
529 newQuota = expectedSize;
530 printf("UI DELEGATE DATABASE CALLBACK: increased quota to %llu\n", newQuota);
533 origin->setQuota(newQuota);
538 HRESULT UIDelegate::embeddedViewWithArguments(IWebView* /*sender*/, IWebFrame* /*frame*/, IPropertyBag* /*arguments*/, IWebEmbeddedView** view)
546 HRESULT UIDelegate::webViewClosing(IWebView* /*sender*/)
551 HRESULT UIDelegate::webViewSetCursor(IWebView* /*sender*/, OLE_HANDLE /*cursor*/)
556 HRESULT UIDelegate::webViewDidInvalidate(IWebView* /*sender*/)
561 HRESULT UIDelegate::setStatusText(IWebView*, BSTR text)
563 if (gTestRunner->dumpStatusCallbacks())
564 printf("UI DELEGATE STATUS CALLBACK: setStatusText:%S\n", text ? text : L"");
568 HRESULT UIDelegate::desktopNotificationsDelegate(IWebDesktopNotificationsDelegate** result)
570 m_desktopNotifications.copyRefTo(result);
574 HRESULT UIDelegate::createWebViewWithRequest(IWebView* /*sender*/, IWebURLRequest* /*request*/, IPropertyBag* /*windowFeatures*/, IWebView** /*newWebView*/)
579 HRESULT UIDelegate::drawBackground(IWebView* /*sender*/, OLE_HANDLE hdc, const RECT* dirtyRect)
584 HRESULT UIDelegate::decidePolicyForGeolocationRequest(IWebView* /*sender*/, IWebFrame* frame, IWebSecurityOrigin* /*origin*/, IWebGeolocationPolicyListener* /*listener*/)
589 HRESULT UIDelegate::didPressMissingPluginButton(IDOMElement* /*element*/)
591 printf("MISSING PLUGIN BUTTON PRESSED\n");