| /* |
| * Copyright (C) 2005-2020 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 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 "DRTDesktopNotificationPresenter.h" |
| #include "TestRunner.h" |
| #include <WebCore/COMPtr.h> |
| #include <wtf/Assertions.h> |
| #include <wtf/Platform.h> |
| #include <wtf/Vector.h> |
| #include <JavaScriptCore/JavaScriptCore.h> |
| #include <WebKitLegacy/WebKit.h> |
| #include <WebKitLegacy/WebKitCOMAPI.h> |
| #include <comutil.h> |
| #include <stdio.h> |
| |
| using std::wstring; |
| |
| class DRTUndoObject { |
| WTF_MAKE_FAST_ALLOCATED; |
| public: |
| DRTUndoObject(IWebUndoTarget* target, BSTR actionName, IUnknown* obj) |
| : m_target(target) |
| , m_actionName(actionName) |
| , m_obj(obj) |
| { |
| } |
| |
| ~DRTUndoObject() |
| { |
| } |
| |
| void invoke() |
| { |
| m_target->invoke(m_actionName, m_obj.get()); |
| } |
| |
| private: |
| IWebUndoTarget* m_target; |
| _bstr_t m_actionName; |
| COMPtr<IUnknown> m_obj; |
| }; |
| |
| class DRTUndoStack { |
| WTF_MAKE_FAST_ALLOCATED; |
| public: |
| bool isEmpty() const { return m_undoVector.isEmpty(); } |
| void clear() { m_undoVector.clear(); } |
| |
| void push(DRTUndoObject* undoObject) { m_undoVector.append(undoObject); } |
| std::unique_ptr<DRTUndoObject> pop() { return m_undoVector.takeLast(); } |
| |
| private: |
| Vector<std::unique_ptr<DRTUndoObject>> m_undoVector; |
| }; |
| |
| class DRTUndoManager { |
| WTF_MAKE_FAST_ALLOCATED; |
| 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: |
| std::unique_ptr<DRTUndoStack> m_redoStack; |
| std::unique_ptr<DRTUndoStack> m_undoStack; |
| bool m_isRedoing { false }; |
| bool m_isUndoing { false }; |
| }; |
| |
| DRTUndoManager::DRTUndoManager() |
| : m_redoStack(makeUnique<DRTUndoStack>()) |
| , m_undoStack(makeUnique<DRTUndoStack>()) |
| { |
| } |
| |
| 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; |
| |
| m_redoStack->pop()->invoke(); |
| |
| m_isRedoing = false; |
| } |
| |
| void DRTUndoManager::undo() |
| { |
| if (!canUndo()) |
| return; |
| |
| m_isUndoing = true; |
| |
| m_undoStack->pop()->invoke(); |
| |
| m_isUndoing = false; |
| } |
| |
| UIDelegate::UIDelegate() |
| : m_undoManager(makeUnique<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 = makeUnique<DRTUndoManager>(); |
| } |
| |
| HRESULT UIDelegate::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject) |
| { |
| if (!ppvObject) |
| return E_POINTER; |
| *ppvObject = nullptr; |
| 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 UIDelegate::AddRef() |
| { |
| return ++m_refCount; |
| } |
| |
| ULONG UIDelegate::Release() |
| { |
| ULONG newRef = --m_refCount; |
| if (!newRef) |
| delete(this); |
| |
| return newRef; |
| } |
| |
| HRESULT UIDelegate::willPerformDragSourceAction(_In_opt_ IWebView*, WebDragSourceAction, _In_ LPPOINT, _In_opt_ IDataObject* pasteboard, _COM_Outptr_opt_ IDataObject** newPasteboard) |
| { |
| if (!newPasteboard) |
| return E_POINTER; |
| *newPasteboard = nullptr; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::hasCustomMenuImplementation(_Out_ BOOL* hasCustomMenus) |
| { |
| *hasCustomMenus = TRUE; |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::trackCustomPopupMenu(_In_opt_ IWebView* /*sender*/, _In_ HMENU /*menu*/, _In_ LPPOINT /*point*/) |
| { |
| // Do nothing |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::registerUndoWithTarget(_In_opt_ IWebUndoTarget* target, _In_ BSTR actionName, _In_opt_ IUnknown* actionArg) |
| { |
| m_undoManager->registerUndoWithTarget(target, actionName, actionArg); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::removeAllActionsWithTarget(_In_opt_ IWebUndoTarget*) |
| { |
| m_undoManager->removeAllActions(); |
| return S_OK; |
| } |
| |
| HRESULT 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 UIDelegate::undo() |
| { |
| m_undoManager->undo(); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::redo() |
| { |
| m_undoManager->redo(); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::canUndo(_Out_ BOOL* result) |
| { |
| if (!result) |
| return E_POINTER; |
| |
| *result = m_undoManager->canUndo(); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::canRedo(_Out_ BOOL* result) |
| { |
| if (!result) |
| return E_POINTER; |
| |
| *result = m_undoManager->canRedo(); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::printFrame(_In_opt_ IWebView*, _In_opt_ IWebFrame*) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::ftpDirectoryTemplatePath(_In_opt_ IWebView*, __deref_opt_out BSTR* path) |
| { |
| if (!path) |
| return E_POINTER; |
| *path = nullptr; |
| return E_NOTIMPL; |
| } |
| |
| |
| HRESULT UIDelegate::webViewHeaderHeight(_In_opt_ IWebView*, _Out_ float* result) |
| { |
| if (!result) |
| return E_POINTER; |
| *result = 0; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::webViewFooterHeight(_In_opt_ IWebView*, _Out_ float* result) |
| { |
| if (!result) |
| return E_POINTER; |
| *result = 0; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::drawHeaderInRect(_In_opt_ IWebView*, _In_ RECT*, ULONG_PTR /*drawingContext*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::drawFooterInRect(_In_opt_ IWebView*, _In_ RECT*, ULONG_PTR /*drawingContext*/, UINT /*pageIndex*/, UINT /*pageCount*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::webViewPrintingMarginRect(_In_opt_ IWebView*, _Out_ RECT*) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::canRunModal(_In_opt_ IWebView*, _Out_ BOOL* canRunBoolean) |
| { |
| if (!canRunBoolean) |
| return E_POINTER; |
| *canRunBoolean = TRUE; |
| return S_OK; |
| } |
| |
| static HWND getHandleFromWebView(IWebView* webView) |
| { |
| COMPtr<IWebViewPrivate2> webViewPrivate; |
| HRESULT hr = webView->QueryInterface(&webViewPrivate); |
| if (FAILED(hr)) |
| return nullptr; |
| |
| HWND webViewWindow = nullptr; |
| hr = webViewPrivate->viewWindow(&webViewWindow); |
| if (FAILED(hr)) |
| return nullptr; |
| |
| return webViewWindow; |
| } |
| |
| HRESULT UIDelegate::createModalDialog(_In_opt_ IWebView* sender, _In_opt_ IWebURLRequest*, _COM_Outptr_opt_ IWebView** newWebView) |
| { |
| if (!newWebView) |
| return E_POINTER; |
| |
| COMPtr<IWebView> webView; |
| HRESULT hr = WebKitCreateInstance(CLSID_WebView, 0, IID_IWebView, (void**)&webView); |
| if (FAILED(hr)) |
| return hr; |
| |
| m_modalDialogParent = ::CreateWindow(L"STATIC", L"ModalDialog", WS_OVERLAPPED | WS_VISIBLE, 0, 0, 0, 0, getHandleFromWebView(sender), nullptr, nullptr, nullptr); |
| |
| hr = webView->setHostWindow(m_modalDialogParent); |
| if (FAILED(hr)) |
| return hr; |
| |
| RECT clientRect = { 0, 0, 0, 0 }; |
| hr = webView->initWithFrame(clientRect, 0, _bstr_t(L"")); |
| if (FAILED(hr)) |
| return hr; |
| |
| COMPtr<IWebUIDelegate> uiDelegate; |
| hr = sender->uiDelegate(&uiDelegate); |
| if (FAILED(hr)) |
| return hr; |
| |
| hr = webView->setUIDelegate(uiDelegate.get()); |
| if (FAILED(hr)) |
| return hr; |
| |
| COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; |
| hr = sender->frameLoadDelegate(&frameLoadDelegate); |
| if (FAILED(hr)) |
| return hr; |
| |
| hr = webView.get()->setFrameLoadDelegate(frameLoadDelegate.get()); |
| if (FAILED(hr)) |
| return hr; |
| |
| *newWebView = webView.leakRef(); |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::runModal(_In_opt_ IWebView* webView) |
| { |
| COMPtr<IWebView> protector(webView); |
| |
| auto modalDialogOwner = ::GetWindow(m_modalDialogParent, GW_OWNER); |
| auto topLevelParent = ::GetAncestor(modalDialogOwner, GA_ROOT); |
| |
| ::EnableWindow(topLevelParent, FALSE); |
| |
| while (::IsWindow(getHandleFromWebView(webView))) { |
| #if USE(CF) |
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); |
| #endif |
| MSG msg; |
| if (!::GetMessage(&msg, 0, 0, 0)) |
| break; |
| |
| ::TranslateMessage(&msg); |
| ::DispatchMessage(&msg); |
| } |
| |
| ::EnableWindow(topLevelParent, TRUE); |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::isMenuBarVisible(_In_opt_ IWebView*, _Out_ BOOL* visible) |
| { |
| if (!visible) |
| return E_POINTER; |
| *visible = false; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::setMenuBarVisible(_In_opt_ IWebView*, BOOL /*visible*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::runDatabaseSizeLimitPrompt(_In_opt_ IWebView*, _In_ BSTR /*displayName*/, _In_opt_ IWebFrame* /*initiatedByFrame*/, _Out_ BOOL* allowed) |
| { |
| if (!allowed) |
| return E_POINTER; |
| *allowed = false; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::paintCustomScrollbar(_In_opt_ IWebView*, _In_ HDC, RECT, WebScrollBarControlSize, WebScrollbarControlState, |
| WebScrollbarControlPart /*pressedPart*/, BOOL /*vertical*/, float /*value*/, float /*proportion*/, WebScrollbarControlPartMask) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::paintCustomScrollCorner(_In_opt_ IWebView*, _In_ HDC, RECT) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::setFrame(_In_opt_ IWebView* /*sender*/, _In_ RECT* frame) |
| { |
| m_frame = *frame; |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::webViewFrame(_In_opt_ IWebView* /*sender*/, _Out_ RECT* frame) |
| { |
| *frame = m_frame; |
| return S_OK; |
| } |
| |
| static std::string stripTrailingSpaces(const std::string& string) |
| { |
| auto result = string; |
| std::wstring::size_type spacePosition; |
| while ((spacePosition = result.find(" \n")) != std::wstring::npos) |
| result.erase(spacePosition, 1); |
| while (!result.empty() && result.back() == ' ') |
| result.pop_back(); |
| return result; |
| } |
| |
| static std::string addLeadingSpaceStripTrailingSpaces(const std::string& string) |
| { |
| auto result = stripTrailingSpaces(string); |
| return (result.empty() || result.front() == '\n') ? result : ' ' + result; |
| } |
| |
| static std::string addLeadingSpaceStripTrailingSpaces(const std::wstring& string) |
| { |
| return addLeadingSpaceStripTrailingSpaces(toUTF8(string)); |
| } |
| |
| std::string toMessage(BSTR message) |
| { |
| auto length = SysStringLen(message); |
| if (!length) |
| return ""; |
| // Return "(null)" for an invalid UTF-16 sequence to align with WebKitTestRunner. |
| // FIXME: Could probably take advantage of WC_ERR_INVALID_CHARS and avoid converting to UTF-8 twice. |
| if (!StringView(ucharFrom(message), length).tryGetUtf8(StrictConversion)) |
| return "(null)"; |
| return toUTF8(message); |
| } |
| |
| static std::string addLeadingSpaceStripTrailingSpaces(BSTR message) |
| { |
| return addLeadingSpaceStripTrailingSpaces(toMessage(message)); |
| } |
| |
| static std::string stripTrailingSpaces(BSTR message) |
| { |
| return stripTrailingSpaces(toMessage(message)); |
| } |
| |
| HRESULT UIDelegate::runJavaScriptAlertPanelWithMessage(_In_opt_ IWebView* /*sender*/, _In_ BSTR message) |
| { |
| if (!done) { |
| fprintf(testResult, "ALERT:%s\n", addLeadingSpaceStripTrailingSpaces(message).c_str()); |
| fflush(testResult); |
| } |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::runJavaScriptConfirmPanelWithMessage(_In_opt_ IWebView* /*sender*/, _In_ BSTR message, _Out_ BOOL* result) |
| { |
| if (!done) |
| fprintf(testResult, "CONFIRM:%s\n", addLeadingSpaceStripTrailingSpaces(message).c_str()); |
| |
| *result = TRUE; |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::runJavaScriptTextInputPanelWithPrompt(_In_opt_ IWebView* /*sender*/, _In_ BSTR message, _In_ BSTR defaultText, __deref_opt_out BSTR* result) |
| { |
| if (!done) |
| fprintf(testResult, "PROMPT: %s, default text:%s\n", toMessage(message).c_str(), addLeadingSpaceStripTrailingSpaces(defaultText).c_str()); |
| |
| *result = SysAllocString(defaultText); |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::runBeforeUnloadConfirmPanelWithMessage(_In_opt_ IWebView* /*sender*/, _In_ BSTR message, _In_opt_ IWebFrame* /*initiatedByFrame*/, _Out_ BOOL* result) |
| { |
| if (!result) |
| return E_POINTER; |
| |
| if (!done) |
| fprintf(testResult, "CONFIRM NAVIGATION:%s\n", addLeadingSpaceStripTrailingSpaces(message).c_str()); |
| |
| *result = !gTestRunner->shouldStayOnPageAfterHandlingBeforeUnload(); |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::webViewAddMessageToConsole(_In_opt_ IWebView* /*sender*/, _In_ BSTR message, int /* lineNumber */ , _In_ BSTR url, BOOL isError) |
| { |
| if (done) |
| return S_OK; |
| |
| wstring newMessage; |
| if (message) { |
| newMessage = message; |
| const std::wstring fileURL(L"file://"); |
| size_t fileProtocol = newMessage.find(fileURL); |
| if (fileProtocol != wstring::npos) |
| newMessage = newMessage.substr(0, fileProtocol) + lastPathComponent(newMessage.substr(fileProtocol + fileURL.size())); |
| } |
| |
| auto out = gTestRunner->dumpJSConsoleLogInStdErr() ? stderr : testResult; |
| fprintf(out, "CONSOLE MESSAGE:%s\n", addLeadingSpaceStripTrailingSpaces(newMessage).c_str()); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::doDragDrop(_In_opt_ IWebView* /*sender*/, _In_opt_ IDataObject* object, _In_opt_ IDropSource* source, DWORD /*okEffect*/, _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 UIDelegate::webViewGetDlgCode(_In_opt_ IWebView* /*sender*/, UINT /*keyCode*/, _Out_ LONG_PTR* code) |
| { |
| if (!code) |
| return E_POINTER; |
| *code = 0; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::createWebViewWithRequest(_In_opt_ IWebView* /*sender*/, _In_opt_ IWebURLRequest* /*request*/, _COM_Outptr_opt_ IWebView** newWebView) |
| { |
| if (!newWebView) |
| return E_POINTER; |
| *newWebView = nullptr; |
| |
| if (!::gTestRunner->canOpenWindows()) |
| return E_FAIL; |
| |
| *newWebView = createWebViewAndOffscreenWindow(); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::webViewClose(_In_opt_ IWebView* sender) |
| { |
| HWND hostWindow; |
| sender->hostWindow(&hostWindow); |
| DestroyWindow(hostWindow); |
| if (hostWindow == m_modalDialogParent) |
| m_modalDialogParent = nullptr; |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::webViewFocus(_In_opt_ IWebView* sender) |
| { |
| HWND hostWindow; |
| sender->hostWindow(&hostWindow); |
| SetForegroundWindow(hostWindow); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::webViewUnfocus(_In_opt_ IWebView* /*sender*/) |
| { |
| SetForegroundWindow(GetDesktopWindow()); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::webViewPainted(_In_opt_ IWebView* /*sender*/) |
| { |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::exceededDatabaseQuota(_In_opt_ IWebView* sender, _In_opt_ IWebFrame* frame, _In_opt_ IWebSecurityOrigin* origin, _In_ BSTR databaseIdentifier) |
| { |
| _bstr_t protocol; |
| _bstr_t host; |
| unsigned short port; |
| |
| origin->protocol(&protocol.GetBSTR()); |
| origin->host(&host.GetBSTR()); |
| origin->port(&port); |
| |
| if (!done && gTestRunner->dumpDatabaseCallbacks()) |
| fprintf(testResult, "UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%S\n", static_cast<const char*>(protocol), static_cast<const char*>(host), port, databaseIdentifier); |
| |
| unsigned long long defaultQuota = 5 * 1024 * 1024; |
| double testDefaultQuota = gTestRunner->databaseDefaultQuota(); |
| if (testDefaultQuota >= 0) |
| defaultQuota = testDefaultQuota; |
| |
| COMPtr<IWebDatabaseManager> databaseManager; |
| COMPtr<IWebDatabaseManager> tmpDatabaseManager; |
| |
| if (FAILED(WebKitCreateInstance(CLSID_WebDatabaseManager, 0, IID_IWebDatabaseManager, (void**)&tmpDatabaseManager))) { |
| origin->setQuota(defaultQuota); |
| return S_OK; |
| } |
| if (FAILED(tmpDatabaseManager->sharedWebDatabaseManager(&databaseManager))) { |
| origin->setQuota(defaultQuota); |
| return S_OK; |
| } |
| IPropertyBag* detailsBag; |
| if (FAILED(databaseManager->detailsForDatabase(databaseIdentifier, origin, &detailsBag))) { |
| origin->setQuota(defaultQuota); |
| return S_OK; |
| } |
| _variant_t var; |
| detailsBag->Read(WebDatabaseUsageKey, &var.GetVARIANT(), nullptr); |
| unsigned long long expectedSize = V_UI8(&var); |
| unsigned long long newQuota = defaultQuota; |
| |
| double maxQuota = gTestRunner->databaseMaxQuota(); |
| if (maxQuota >= 0) { |
| if (defaultQuota < expectedSize && expectedSize <= maxQuota) { |
| newQuota = expectedSize; |
| fprintf(testResult, "UI DELEGATE DATABASE CALLBACK: increased quota to %llu\n", newQuota); |
| } |
| } |
| origin->setQuota(newQuota); |
| |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::embeddedViewWithArguments(_In_opt_ IWebView* /*sender*/, _In_opt_ IWebFrame* /*frame*/, _In_opt_ IPropertyBag* /*arguments*/, _COM_Outptr_opt_ IWebEmbeddedView** view) |
| { |
| if (!view) |
| return E_POINTER; |
| *view = nullptr; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::webViewClosing(_In_opt_ IWebView* /*sender*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::webViewSetCursor(_In_opt_ IWebView* /*sender*/, _In_ HCURSOR /*cursor*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::webViewDidInvalidate(_In_opt_ IWebView* /*sender*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::setStatusText(_In_opt_ IWebView*, _In_ BSTR text) |
| { |
| if (!done && gTestRunner->dumpStatusCallbacks()) |
| fprintf(testResult, "UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", stripTrailingSpaces(text).c_str()); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::desktopNotificationsDelegate(_COM_Outptr_opt_ IWebDesktopNotificationsDelegate** result) |
| { |
| if (!result) |
| return E_POINTER; |
| *result = nullptr; |
| m_desktopNotifications.copyRefTo(result); |
| return S_OK; |
| } |
| |
| HRESULT UIDelegate::createWebViewWithRequest(_In_opt_ IWebView* /*sender*/, _In_opt_ IWebURLRequest* /*request*/, _In_opt_ IPropertyBag* /*windowFeatures*/, _COM_Outptr_opt_ IWebView** newWebView) |
| { |
| if (!newWebView) |
| return E_POINTER; |
| *newWebView = nullptr; |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::drawBackground(_In_opt_ IWebView* /*sender*/, _In_ HDC, _In_ const RECT* /*dirtyRect*/) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::decidePolicyForGeolocationRequest(_In_opt_ IWebView* /*sender*/, _In_opt_ IWebFrame*, _In_opt_ IWebSecurityOrigin*, _In_opt_ IWebGeolocationPolicyListener*) |
| { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT UIDelegate::didPressMissingPluginButton(_In_opt_ IDOMElement* /*element*/) |
| { |
| fprintf(testResult, "MISSING PLUGIN BUTTON PRESSED\n"); |
| return S_OK; |
| } |