diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
commit | 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch) | |
tree | 11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebKit/win/WebCoreSupport | |
parent | 648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff) | |
download | external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebKit/win/WebCoreSupport')
-rw-r--r-- | WebKit/win/WebCoreSupport/EmbeddedWidget.cpp | 209 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/EmbeddedWidget.h | 80 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebChromeClient.cpp | 709 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebChromeClient.h | 127 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebContextMenuClient.cpp | 179 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebContextMenuClient.h | 51 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebDragClient.cpp | 269 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebDragClient.h | 46 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebEditorClient.cpp | 762 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebEditorClient.h | 117 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp | 706 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebFrameLoaderClient.h | 120 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebInspectorClient.cpp | 426 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebInspectorClient.h | 100 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebInspectorDelegate.cpp | 66 | ||||
-rw-r--r-- | WebKit/win/WebCoreSupport/WebInspectorDelegate.h | 257 |
16 files changed, 4224 insertions, 0 deletions
diff --git a/WebKit/win/WebCoreSupport/EmbeddedWidget.cpp b/WebKit/win/WebCoreSupport/EmbeddedWidget.cpp new file mode 100644 index 0000000..b18022b --- /dev/null +++ b/WebKit/win/WebCoreSupport/EmbeddedWidget.cpp @@ -0,0 +1,209 @@ +/*
+ * Copyright (C) 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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 "EmbeddedWidget.h"
+
+#include <WebCore/Document.h>
+#include <WebCore/Element.h>
+#include <WebCore/FrameView.h>
+#include <WebCore/RenderObject.h>
+
+using namespace WebCore;
+
+EmbeddedWidget* EmbeddedWidget::create(IWebEmbeddedView* view, Element* element, HWND parentWindow, const IntSize& size)
+{
+ EmbeddedWidget* widget = new EmbeddedWidget(view, element);
+
+ widget->createWindow(parentWindow, size);
+ return widget;
+}
+
+EmbeddedWidget::~EmbeddedWidget()
+{
+ if (m_window)
+ DestroyWindow(m_window);
+}
+
+bool EmbeddedWidget::createWindow(HWND parentWindow, const IntSize& size)
+{
+ ASSERT(!m_window);
+
+ HWND window;
+
+ SIZE pluginSize(size);
+
+ HRESULT hr = m_view->createViewWindow((OLE_HANDLE)parentWindow, &pluginSize, (OLE_HANDLE*)&window);
+
+ if (FAILED(hr) || !window)
+ return false;
+
+ m_window = window;
+ return true;
+}
+
+void EmbeddedWidget::invalidateRect(const IntRect& rect)
+{
+ if (!m_window)
+ return;
+
+ RECT r = rect;
+ ::InvalidateRect(m_window, &r, false);
+}
+
+void EmbeddedWidget::setFrameRect(const IntRect& rect)
+{
+ if (m_element->document()->printing())
+ return;
+
+ if (rect != frameRect())
+ Widget::setFrameRect(rect);
+
+ frameRectsChanged();
+}
+
+void EmbeddedWidget::frameRectsChanged() const
+{
+ if (!parent())
+ return;
+
+ ASSERT(parent()->isFrameView());
+ FrameView* frameView = static_cast<FrameView*>(parent());
+
+ IntRect oldWindowRect = m_windowRect;
+ IntRect oldClipRect = m_clipRect;
+
+ m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
+ m_clipRect = windowClipRect();
+ m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
+
+ if (!m_window)
+ return;
+
+ if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
+ return;
+
+ HRGN rgn;
+
+ // To prevent flashes while scrolling, we disable drawing during the window
+ // update process by clipping the window to the zero rect.
+
+ bool clipToZeroRect = true;
+
+ if (clipToZeroRect) {
+ rgn = ::CreateRectRgn(0, 0, 0, 0);
+ ::SetWindowRgn(m_window, rgn, FALSE);
+ } else {
+ rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.right(), m_clipRect.bottom());
+ ::SetWindowRgn(m_window, rgn, TRUE);
+ }
+
+ if (m_windowRect != oldWindowRect)
+ ::MoveWindow(m_window, m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), TRUE);
+
+ if (clipToZeroRect) {
+ rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.right(), m_clipRect.bottom());
+ ::SetWindowRgn(m_window, rgn, TRUE);
+ }
+}
+
+void EmbeddedWidget::setFocus()
+{
+ if (m_window)
+ SetFocus(m_window);
+
+ Widget::setFocus();
+}
+
+void EmbeddedWidget::show()
+{
+ m_isVisible = true;
+
+ if (m_attachedToWindow && m_window)
+ ShowWindow(m_window, SW_SHOWNA);
+
+ Widget::show();
+}
+
+void EmbeddedWidget::hide()
+{
+ m_isVisible = false;
+
+ if (m_attachedToWindow && m_window)
+ ShowWindow(m_window, SW_HIDE);
+
+ Widget::hide();
+}
+
+IntRect EmbeddedWidget::windowClipRect() const
+{
+ // Start by clipping to our bounds.
+ IntRect clipRect(m_windowRect);
+
+ // Take our element and get the clip rect from the enclosing layer and frame view.
+ RenderLayer* layer = m_element->renderer()->enclosingLayer();
+ FrameView* parentView = m_element->document()->view();
+ clipRect.intersect(parentView->windowClipRectForLayer(layer, true));
+
+ return clipRect;
+}
+
+void EmbeddedWidget::setParent(ScrollView* parent)
+{
+ Widget::setParent(parent);
+
+ if (!m_window)
+ return;
+
+ if (parent)
+ return;
+
+ // If the embedded window or one of its children have the focus, we need to
+ // clear it to prevent the web view window from being focused because that can
+ // trigger a layout while the plugin element is being detached.
+ HWND focusedWindow = ::GetFocus();
+ if (m_window == focusedWindow || ::IsChild(m_window, focusedWindow))
+ ::SetFocus(0);
+}
+
+void EmbeddedWidget::attachToWindow()
+{
+ if (m_attachedToWindow)
+ return;
+
+ m_attachedToWindow = true;
+ if (m_isVisible && m_window)
+ ShowWindow(m_window, SW_SHOWNA);
+}
+
+void EmbeddedWidget::detachFromWindow()
+{
+ if (!m_attachedToWindow)
+ return;
+
+ if (m_isVisible && m_window)
+ ShowWindow(m_window, SW_HIDE);
+ m_attachedToWindow = false;
+}
diff --git a/WebKit/win/WebCoreSupport/EmbeddedWidget.h b/WebKit/win/WebCoreSupport/EmbeddedWidget.h new file mode 100644 index 0000000..ed7c025 --- /dev/null +++ b/WebKit/win/WebCoreSupport/EmbeddedWidget.h @@ -0,0 +1,80 @@ +/*
+ * Copyright (C) 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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.
+ */
+
+#ifndef EmbeddedWidget_h
+#define EmbeddedWidget_h
+
+#include <WebCore/COMPtr.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/Widget.h>
+
+namespace WebCore {
+ class Element;
+ class IntSize;
+}
+
+interface IWebEmbeddedView;
+
+class EmbeddedWidget : public WebCore::Widget {
+public:
+ static EmbeddedWidget* create(IWebEmbeddedView*, WebCore::Element* element, HWND parentWindow, const WebCore::IntSize&);
+ ~EmbeddedWidget();
+
+private:
+ EmbeddedWidget(IWebEmbeddedView* view, WebCore::Element* element)
+ : m_view(view)
+ , m_element(element)
+ , m_window(0)
+ , m_isVisible(false)
+ , m_attachedToWindow(false)
+ {
+ }
+
+ bool createWindow(HWND parentWindow, const WebCore::IntSize& size);
+
+ virtual void invalidateRect(const WebCore::IntRect&);
+ virtual void setFrameRect(const WebCore::IntRect&);
+ virtual void frameRectsChanged() const;
+ virtual void setFocus();
+ virtual void show();
+ virtual void hide();
+ virtual WebCore::IntRect windowClipRect() const;
+ virtual void setParent(WebCore::ScrollView*);
+
+ virtual void attachToWindow();
+ virtual void detachFromWindow();
+
+ COMPtr<IWebEmbeddedView> m_view;
+ WebCore::Element* m_element;
+ HWND m_window;
+
+ bool m_isVisible;
+ bool m_attachedToWindow;
+
+ mutable WebCore::IntRect m_clipRect; // The clip rect to apply to an embedded view.
+ mutable WebCore::IntRect m_windowRect; // Our window rect.
+};
+
+#endif // EmbeddedWidget_h
diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.cpp b/WebKit/win/WebCoreSupport/WebChromeClient.cpp new file mode 100644 index 0000000..dba87e5 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebChromeClient.cpp @@ -0,0 +1,709 @@ +/* + * Copyright (C) 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "WebChromeClient.h" + +#include "WebElementPropertyBag.h" +#include "WebFrame.h" +#include "WebHistory.h" +#include "WebMutableURLRequest.h" +#include "WebSecurityOrigin.h" +#include "WebView.h" +#pragma warning(push, 0) +#include <WebCore/BString.h> +#include <WebCore/ContextMenu.h> +#include <WebCore/FileChooser.h> +#include <WebCore/FloatRect.h> +#include <WebCore/FrameLoadRequest.h> +#include <WebCore/FrameView.h> +#include <WebCore/LocalizedStrings.h> +#include <WebCore/Page.h> +#include <WebCore/WindowFeatures.h> +#pragma warning(pop) + +#include <tchar.h> + +using namespace WebCore; + +// When you call GetOpenFileName, if the size of the buffer is too small, +// MSDN says that the first two bytes of the buffer contain the required size for the file selection, in bytes or characters +// So we can assume the required size can't be more than the maximum value for a short. +static const size_t maxFilePathsListSize = USHRT_MAX; + +WebChromeClient::WebChromeClient(WebView* webView) + : m_webView(webView) +{ +} + +void WebChromeClient::chromeDestroyed() +{ + delete this; +} + +void WebChromeClient::setWindowRect(const FloatRect& r) +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + RECT rect = IntRect(r); + uiDelegate->setFrame(m_webView, &rect); + uiDelegate->Release(); + } +} + +FloatRect WebChromeClient::windowRect() +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + RECT rect; + HRESULT retval = uiDelegate->webViewFrame(m_webView, &rect); + + uiDelegate->Release(); + + if (SUCCEEDED(retval)) + return rect; + } + + return FloatRect(); +} + +FloatRect WebChromeClient::pageRect() +{ + RECT rect; + m_webView->frameRect(&rect); + return rect; +} + +float WebChromeClient::scaleFactor() +{ + // Windows doesn't support UI scaling. + return 1.0; +} + +void WebChromeClient::focus() +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->webViewFocus(m_webView); + uiDelegate->Release(); + } + // Normally this would happen on a timer, but JS might need to know this earlier, so we'll update here. + m_webView->updateActiveState(); +} + +void WebChromeClient::unfocus() +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->webViewUnfocus(m_webView); + uiDelegate->Release(); + } + // Normally this would happen on a timer, but JS might need to know this earlier, so we'll update here. + m_webView->updateActiveState(); +} + +bool WebChromeClient::canTakeFocus(FocusDirection direction) +{ + IWebUIDelegate* uiDelegate = 0; + BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE; + BOOL result = FALSE; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->canTakeFocus(m_webView, bForward, &result); + uiDelegate->Release(); + } + + return !!result; +} + +void WebChromeClient::takeFocus(FocusDirection direction) +{ + IWebUIDelegate* uiDelegate = 0; + BOOL bForward = (direction == FocusDirectionForward) ? TRUE : FALSE; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->takeFocus(m_webView, bForward); + uiDelegate->Release(); + } +} + +Page* WebChromeClient::createWindow(Frame*, const FrameLoadRequest& frameLoadRequest, const WindowFeatures& features) +{ + if (features.dialog) { + COMPtr<IWebUIDelegate3> delegate = uiDelegate3(); + if (!delegate) + return 0; + COMPtr<IWebMutableURLRequest> request(AdoptCOM, WebMutableURLRequest::createInstance(frameLoadRequest.resourceRequest())); + COMPtr<IWebView> dialog; + if (FAILED(delegate->createModalDialog(m_webView, request.get(), &dialog))) + return 0; + return core(dialog.get()); + } + + Page* page = 0; + IWebUIDelegate* uiDelegate = 0; + IWebMutableURLRequest* request = WebMutableURLRequest::createInstance(frameLoadRequest.resourceRequest()); + + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + IWebView* webView = 0; + if (SUCCEEDED(uiDelegate->createWebViewWithRequest(m_webView, request, &webView))) { + page = core(webView); + webView->Release(); + } + + uiDelegate->Release(); + } + + request->Release(); + return page; +} + +void WebChromeClient::show() +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->webViewShow(m_webView); + uiDelegate->Release(); + } +} + +bool WebChromeClient::canRunModal() +{ + BOOL result = FALSE; + if (COMPtr<IWebUIDelegate3> delegate = uiDelegate3()) + delegate->canRunModal(m_webView, &result); + return result; +} + +void WebChromeClient::runModal() +{ + if (COMPtr<IWebUIDelegate3> delegate = uiDelegate3()) + delegate->runModal(m_webView); +} + +void WebChromeClient::setToolbarsVisible(bool visible) +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->setToolbarsVisible(m_webView, visible); + uiDelegate->Release(); + } +} + +bool WebChromeClient::toolbarsVisible() +{ + BOOL result = false; + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->webViewAreToolbarsVisible(m_webView, &result); + uiDelegate->Release(); + } + return result != false; +} + +void WebChromeClient::setStatusbarVisible(bool visible) +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->setStatusBarVisible(m_webView, visible); + uiDelegate->Release(); + } +} + +bool WebChromeClient::statusbarVisible() +{ + BOOL result = false; + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->webViewIsStatusBarVisible(m_webView, &result); + uiDelegate->Release(); + } + return result != false; +} + +void WebChromeClient::setScrollbarsVisible(bool b) +{ + WebFrame* webFrame = m_webView->topLevelFrame(); + if (webFrame) + webFrame->setAllowsScrolling(b); +} + +bool WebChromeClient::scrollbarsVisible() +{ + WebFrame* webFrame = m_webView->topLevelFrame(); + BOOL b = false; + if (webFrame) + webFrame->allowsScrolling(&b); + + return !!b; +} + +void WebChromeClient::setMenubarVisible(bool visible) +{ + COMPtr<IWebUIDelegate3> delegate = uiDelegate3(); + if (!delegate) + return; + delegate->setMenuBarVisible(m_webView, visible); +} + +bool WebChromeClient::menubarVisible() +{ + COMPtr<IWebUIDelegate3> delegate = uiDelegate3(); + if (!delegate) + return true; + BOOL result = true; + delegate->isMenuBarVisible(m_webView, &result); + return result; +} + +void WebChromeClient::setResizable(bool resizable) +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->setResizable(m_webView, resizable); + uiDelegate->Release(); + } +} + +void WebChromeClient::addMessageToConsole(const String& message, unsigned line, const String& url) +{ + COMPtr<IWebUIDelegate> uiDelegate; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + COMPtr<IWebUIDelegatePrivate> uiPrivate; + if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) + uiPrivate->webViewAddMessageToConsole(m_webView, BString(message), line, BString(url), true); + } +} + +bool WebChromeClient::canRunBeforeUnloadConfirmPanel() +{ + IWebUIDelegate* ui; + if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) { + ui->Release(); + return true; + } + return false; +} + +bool WebChromeClient::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) +{ + BOOL result = TRUE; + IWebUIDelegate* ui; + if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) { + WebFrame* webFrame = kit(frame); + ui->runBeforeUnloadConfirmPanelWithMessage(m_webView, BString(message), webFrame, &result); + ui->Release(); + } + return !!result; +} + +void WebChromeClient::closeWindowSoon() +{ + // We need to remove the parent WebView from WebViewSets here, before it actually + // closes, to make sure that JavaScript code that executes before it closes + // can't find it. Otherwise, window.open will select a closed WebView instead of + // opening a new one <rdar://problem/3572585>. + + // We also need to stop the load to prevent further parsing or JavaScript execution + // after the window has torn down <rdar://problem/4161660>. + + // FIXME: This code assumes that the UI delegate will respond to a webViewClose + // message by actually closing the WebView. Safari guarantees this behavior, but other apps might not. + // This approach is an inherent limitation of not making a close execute immediately + // after a call to window.close. + + m_webView->setGroupName(0); + m_webView->stopLoading(0); + m_webView->closeWindowSoon(); +} + +void WebChromeClient::runJavaScriptAlert(Frame*, const String& message) +{ + COMPtr<IWebUIDelegate> ui; + if (SUCCEEDED(m_webView->uiDelegate(&ui))) + ui->runJavaScriptAlertPanelWithMessage(m_webView, BString(message)); +} + +bool WebChromeClient::runJavaScriptConfirm(Frame*, const String& message) +{ + BOOL result = FALSE; + COMPtr<IWebUIDelegate> ui; + if (SUCCEEDED(m_webView->uiDelegate(&ui))) + ui->runJavaScriptConfirmPanelWithMessage(m_webView, BString(message), &result); + return !!result; +} + +bool WebChromeClient::runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result) +{ + COMPtr<IWebUIDelegate> ui; + if (FAILED(m_webView->uiDelegate(&ui))) + return false; + + TimerBase::fireTimersInNestedEventLoop(); + + BSTR resultBSTR = 0; + if (FAILED(ui->runJavaScriptTextInputPanelWithPrompt(m_webView, BString(message), BString(defaultValue), &resultBSTR))) + return false; + + if (resultBSTR) { + result = String(resultBSTR, SysStringLen(resultBSTR)); + SysFreeString(resultBSTR); + return true; + } + + return false; +} + +void WebChromeClient::setStatusbarText(const String& statusText) +{ + COMPtr<IWebUIDelegate> uiDelegate; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->setStatusText(m_webView, BString(statusText)); + } +} + +bool WebChromeClient::shouldInterruptJavaScript() +{ + COMPtr<IWebUIDelegate> uiDelegate; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + COMPtr<IWebUIDelegatePrivate> uiPrivate; + if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) { + BOOL result; + if (SUCCEEDED(uiPrivate->webViewShouldInterruptJavaScript(m_webView, &result))) + return !!result; + } + } + return false; +} + +bool WebChromeClient::tabsToLinks() const +{ + BOOL enabled = FALSE; + IWebPreferences* preferences; + if (SUCCEEDED(m_webView->preferences(&preferences))) + preferences->tabsToLinks(&enabled); + + return !!enabled; +} + +IntRect WebChromeClient::windowResizerRect() const +{ + IntRect intRect; + + IWebUIDelegate* ui; + if (SUCCEEDED(m_webView->uiDelegate(&ui)) && ui) { + IWebUIDelegatePrivate* uiPrivate; + if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) { + RECT r; + if (SUCCEEDED(uiPrivate->webViewResizerRect(m_webView, &r))) + intRect = IntRect(r.left, r.top, r.right-r.left, r.bottom-r.top); + uiPrivate->Release(); + } + ui->Release(); + } + return intRect; +} + +void WebChromeClient::repaint(const IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly) +{ + ASSERT(core(m_webView->topLevelFrame())); + m_webView->repaint(windowRect, contentChanged, immediate, repaintContentOnly); +} + +void WebChromeClient::scroll(const IntSize& delta, const IntRect& scrollViewRect, const IntRect& clipRect) +{ + ASSERT(core(m_webView->topLevelFrame())); + + m_webView->scrollBackingStore(core(m_webView->topLevelFrame())->view(), delta.width(), delta.height(), scrollViewRect, clipRect); +} + +IntRect WebChromeClient::windowToScreen(const IntRect& rect) const +{ + HWND viewWindow; + if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + return rect; + + // Find the top left corner of the Widget's containing window in screen coords, + // and adjust the result rect's position by this amount. + POINT topLeft = {0, 0}; + IntRect result = rect; + ::ClientToScreen(viewWindow, &topLeft); + result.move(topLeft.x, topLeft.y); + + return result; +} + +IntPoint WebChromeClient::screenToWindow(const IntPoint& point) const +{ + POINT result = point; + + HWND viewWindow; + if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + return point; + + ::ScreenToClient(viewWindow, &result); + + return result; +} + +PlatformWidget WebChromeClient::platformWindow() const +{ + HWND viewWindow; + if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + return 0; + return viewWindow; +} + +void WebChromeClient::mouseDidMoveOverElement(const HitTestResult& result, unsigned modifierFlags) +{ + COMPtr<IWebUIDelegate> uiDelegate; + if (FAILED(m_webView->uiDelegate(&uiDelegate))) + return; + + COMPtr<WebElementPropertyBag> element; + element.adoptRef(WebElementPropertyBag::createInstance(result)); + + uiDelegate->mouseDidMoveOverElement(m_webView, element.get(), modifierFlags); +} + +void WebChromeClient::setToolTip(const String& toolTip) +{ + m_webView->setToolTip(toolTip); +} + +void WebChromeClient::print(Frame* frame) +{ + COMPtr<IWebUIDelegate> uiDelegate; + COMPtr<IWebUIDelegate2> uiDelegate2; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) + if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegate2, (void**)&uiDelegate2))) + uiDelegate2->printFrame(m_webView, kit(frame)); +} + +void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& databaseIdentifier) +{ + COMPtr<WebSecurityOrigin> origin(AdoptCOM, WebSecurityOrigin::createInstance(frame->document()->securityOrigin())); + COMPtr<IWebUIDelegate> uiDelegate; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + COMPtr<IWebUIDelegatePrivate3> uiDelegatePrivate3(Query, uiDelegate); + if (uiDelegatePrivate3) + uiDelegatePrivate3->exceededDatabaseQuota(m_webView, kit(frame), origin.get(), BString(databaseIdentifier)); + else { + // FIXME: remove this workaround once shipping Safari has the necessary delegate implemented. + TCHAR path[MAX_PATH]; + HMODULE safariHandle = GetModuleHandle(TEXT("Safari.exe")); + if (!safariHandle) + return; + GetModuleFileName(safariHandle, path, ARRAYSIZE(path)); + DWORD handle; + DWORD versionSize = GetFileVersionInfoSize(path, &handle); + if (!versionSize) + return; + Vector<char> data(versionSize); + if (!GetFileVersionInfo(path, 0, versionSize, data.data())) + return; + + LPCTSTR productVersion; + UINT productVersionLength; + if (!VerQueryValue(data.data(), TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), (void**)&productVersion, &productVersionLength)) + return; + if (_tcsncmp(TEXT("3.1"), productVersion, productVersionLength) > 0) { + const unsigned long long defaultQuota = 5 * 1024 * 1024; // 5 megabytes should hopefully be enough to test storage support. + origin->setQuota(defaultQuota); + } + } + } +} + +void WebChromeClient::populateVisitedLinks() +{ + WebHistory* history = WebHistory::sharedHistory(); + if (!history) + return; + history->addVisitedLinksToPageGroup(m_webView->page()->group()); +} + +bool WebChromeClient::paintCustomScrollbar(GraphicsContext* context, const FloatRect& rect, ScrollbarControlSize size, + ScrollbarControlState state, ScrollbarPart pressedPart, bool vertical, + float value, float proportion, ScrollbarControlPartMask parts) +{ + if (context->paintingDisabled()) + return false; + + COMPtr<IWebUIDelegate4> delegate = uiDelegate4(); + if (!delegate) + return false; + + WebScrollbarControlPartMask webParts = WebNoScrollPart; + if (parts & BackButtonStartPart) // FIXME: Hyatt, what about BackButtonEndPart? + webParts |= WebBackButtonPart; + if (parts & BackTrackPart) + webParts |= WebBackTrackPart; + if (parts & ThumbPart) + webParts |= WebThumbPart; + if (parts & ForwardTrackPart) + webParts |= WebForwardTrackPart; + if (parts & ForwardButtonStartPart) // FIXME: Hyatt, what about ForwardButtonEndPart? + webParts |= WebForwardButtonPart; + + WebScrollbarControlPart webPressedPart = WebNoScrollPart; + switch (pressedPart) { + case BackButtonStartPart: // FIXME: Hyatt, what about BackButtonEndPart? + webPressedPart = WebBackButtonPart; + break; + case BackTrackPart: + webPressedPart = WebBackTrackPart; + break; + case ThumbPart: + webPressedPart = WebThumbPart; + break; + case ForwardTrackPart: + webPressedPart = WebForwardTrackPart; + break; + case ForwardButtonStartPart: // FIXME: Hyatt, what about ForwardButtonEndPart? + webPressedPart = WebForwardButtonPart; + break; + default: + break; + } + + WebScrollBarControlSize webSize; + switch (size) { + case SmallScrollbar: + webSize = WebSmallScrollbar; + break; + case RegularScrollbar: + default: + webSize = WebRegularScrollbar; + } + WebScrollbarControlState webState = 0; + if (state & ActiveScrollbarState) + webState |= WebActiveScrollbarState; + if (state & EnabledScrollbarState) + webState |= WebEnabledScrollbarState; + if (state & PressedScrollbarState) + webState |= WebPressedScrollbarState; + + RECT webRect = enclosingIntRect(rect); + HDC hDC = context->getWindowsContext(webRect); + HRESULT hr = delegate->paintCustomScrollbar(m_webView, hDC, webRect, webSize, webState, webPressedPart, + vertical, value, proportion, webParts); + context->releaseWindowsContext(hDC, webRect); + return SUCCEEDED(hr); +} + +bool WebChromeClient::paintCustomScrollCorner(GraphicsContext* context, const FloatRect& rect) +{ + if (context->paintingDisabled()) + return false; + + COMPtr<IWebUIDelegate4> delegate = uiDelegate4(); + if (!delegate) + return false; + + RECT webRect = enclosingIntRect(rect); + HDC hDC = context->getWindowsContext(webRect); + HRESULT hr = delegate->paintCustomScrollCorner(m_webView, hDC, webRect); + context->releaseWindowsContext(hDC, webRect); + return SUCCEEDED(hr); +} + +void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) +{ + RefPtr<FileChooser> fileChooser = prpFileChooser; + + HWND viewWindow; + if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow)))) + return; + + bool multiFile = fileChooser->allowsMultipleFiles(); + Vector<TCHAR> fileBuf(multiFile ? maxFilePathsListSize : MAX_PATH); + + OPENFILENAME ofn; + + memset(&ofn, 0, sizeof(ofn)); + + // Need to zero out the first char of fileBuf so GetOpenFileName doesn't think it's an initialization string + fileBuf[0] = '\0'; + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = viewWindow; + String allFiles = allFilesText(); + allFiles.append(TEXT("\0*.*\0\0"), 6); + ofn.lpstrFilter = allFiles.charactersWithNullTermination(); + ofn.lpstrFile = fileBuf.data(); + ofn.nMaxFile = fileBuf.size(); + String dialogTitle = uploadFileText(); + ofn.lpstrTitle = dialogTitle.charactersWithNullTermination(); + ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER; + if (multiFile) + ofn.Flags = ofn.Flags | OFN_ALLOWMULTISELECT; + + if (GetOpenFileName(&ofn)) { + TCHAR* files = fileBuf.data(); + Vector<String> fileList; + String file(files); + if (multiFile) { + while (!file.isEmpty()) { + // When using the OFN_EXPLORER flag, the file list is null delimited. + // When you create a String from a ptr to this list, it will use strlen to look for the null character. + // Then we find the next file path string by using the length of the string we just created. + TCHAR* nextFilePtr = files + file.length() + 1; + String nextFile(nextFilePtr); + // If multiple files are selected, there will be a directory name first, which we don't want to add to the vector. + // We know a single file was selected if there is only one filename in the list. + // In that case, we don't want to skip adding the first (and only) name. + if (files != fileBuf.data() || nextFile.isEmpty()) + fileList.append(file); + files = nextFilePtr; + file = nextFile; + } + } else + fileList.append(file); + ASSERT(fileList.size()); + fileChooser->chooseFiles(fileList); + } + // FIXME: Show some sort of error if too many files are selected and the buffer is too small. For now, this will fail silently. +} + +COMPtr<IWebUIDelegate> WebChromeClient::uiDelegate() +{ + COMPtr<IWebUIDelegate> delegate; + m_webView->uiDelegate(&delegate); + return delegate; +} + +COMPtr<IWebUIDelegate2> WebChromeClient::uiDelegate2() +{ + return COMPtr<IWebUIDelegate2>(Query, uiDelegate()); +} + +COMPtr<IWebUIDelegate3> WebChromeClient::uiDelegate3() +{ + return COMPtr<IWebUIDelegate3>(Query, uiDelegate()); +} + +COMPtr<IWebUIDelegate4> WebChromeClient::uiDelegate4() +{ + return COMPtr<IWebUIDelegate4>(Query, uiDelegate()); +} diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.h b/WebKit/win/WebCoreSupport/WebChromeClient.h new file mode 100644 index 0000000..83c5a70 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebChromeClient.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2006, 2007 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 <WebCore/ChromeClient.h> +#include <WebCore/COMPtr.h> +#include <WebCore/GraphicsContext.h> +#include <WebCore/FocusDirection.h> +#include <WebCore/ScrollTypes.h> +#include <wtf/Forward.h> + +class WebView; + +interface IWebUIDelegate; +interface IWebUIDelegate2; +interface IWebUIDelegate3; +interface IWebUIDelegate4; + +class WebChromeClient : public WebCore::ChromeClient { +public: + WebChromeClient(WebView*); + + virtual void chromeDestroyed(); + + virtual void setWindowRect(const WebCore::FloatRect&); + virtual WebCore::FloatRect windowRect(); + + virtual WebCore::FloatRect pageRect(); + + virtual float scaleFactor(); + + virtual void focus(); + virtual void unfocus(); + + virtual bool canTakeFocus(WebCore::FocusDirection); + virtual void takeFocus(WebCore::FocusDirection); + + virtual WebCore::Page* createWindow(WebCore::Frame*, const WebCore::FrameLoadRequest&, const WebCore::WindowFeatures&); + virtual void show(); + + virtual bool canRunModal(); + virtual void runModal(); + + virtual void setToolbarsVisible(bool); + virtual bool toolbarsVisible(); + + virtual void setStatusbarVisible(bool); + virtual bool statusbarVisible(); + + virtual void setScrollbarsVisible(bool); + virtual bool scrollbarsVisible(); + + virtual void setMenubarVisible(bool); + virtual bool menubarVisible(); + + virtual void setResizable(bool); + + virtual void addMessageToConsole(const WebCore::String& message, unsigned line, const WebCore::String& url); + + virtual bool canRunBeforeUnloadConfirmPanel(); + virtual bool runBeforeUnloadConfirmPanel(const WebCore::String& message, WebCore::Frame* frame); + + virtual void closeWindowSoon(); + + virtual void runJavaScriptAlert(WebCore::Frame*, const WebCore::String&); + virtual bool runJavaScriptConfirm(WebCore::Frame*, const WebCore::String&); + virtual bool runJavaScriptPrompt(WebCore::Frame*, const WebCore::String& message, const WebCore::String& defaultValue, WebCore::String& result); + virtual void setStatusbarText(const WebCore::String&); + virtual bool shouldInterruptJavaScript(); + + virtual bool tabsToLinks() const; + virtual WebCore::IntRect windowResizerRect() const; + + virtual void repaint(const WebCore::IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false); + virtual void scroll(const WebCore::IntSize& scrollDelta, const WebCore::IntRect& rectToScroll, const WebCore::IntRect& clipRect); + virtual WebCore::IntPoint screenToWindow(const WebCore::IntPoint& p) const; + virtual WebCore::IntRect windowToScreen(const WebCore::IntRect& r) const; + virtual PlatformWidget platformWindow() const; + + virtual void mouseDidMoveOverElement(const WebCore::HitTestResult&, unsigned modifierFlags); + + virtual void setToolTip(const WebCore::String&); + + virtual void print(WebCore::Frame*); + + virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String&); + + virtual void populateVisitedLinks(); + + virtual bool paintCustomScrollbar(WebCore::GraphicsContext*, const WebCore::FloatRect&, WebCore::ScrollbarControlSize, + WebCore::ScrollbarControlState, WebCore::ScrollbarPart pressedPart, bool vertical, + float value, float proportion, WebCore::ScrollbarControlPartMask); + virtual bool paintCustomScrollCorner(WebCore::GraphicsContext*, const WebCore::FloatRect&); + + virtual void runOpenPanel(WebCore::Frame*, PassRefPtr<WebCore::FileChooser>); + + WebView* webView() const { return m_webView; } + +private: + COMPtr<IWebUIDelegate> uiDelegate(); + COMPtr<IWebUIDelegate2> uiDelegate2(); + COMPtr<IWebUIDelegate3> uiDelegate3(); + COMPtr<IWebUIDelegate4> uiDelegate4(); + + WebView* m_webView; +}; diff --git a/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp b/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp new file mode 100644 index 0000000..be7b483 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2006, 2007 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "WebContextMenuClient.h" + +#include "WebDownload.h" +#include "WebElementPropertyBag.h" +#include "WebLocalizableStrings.h" +#include "WebView.h" + +#pragma warning(push, 0) +#include <WebCore/ContextMenu.h> +#include <WebCore/FrameLoader.h> +#include <WebCore/FrameLoadRequest.h> +#include <WebCore/Page.h> +#include <WebCore/ResourceRequest.h> +#include <WebCore/NotImplemented.h> +#pragma warning(pop) + +#include <tchar.h> + +using namespace WebCore; + +WebContextMenuClient::WebContextMenuClient(WebView* webView) + : m_webView(webView) +{ +} + +void WebContextMenuClient::contextMenuDestroyed() +{ + delete this; +} + +static bool isPreInspectElementTagSafari(IWebUIDelegate* uiDelegate) +{ + if (!uiDelegate) + return false; + + // We assume anyone who implements IWebUIDelegate2 also knows about the Inspect Element item. + COMPtr<IWebUIDelegate2> uiDelegate2; + if (SUCCEEDED(uiDelegate->QueryInterface(IID_IWebUIDelegate2, (void**)&uiDelegate2))) + return false; + + TCHAR modulePath[MAX_PATH]; + DWORD length = ::GetModuleFileName(0, modulePath, _countof(modulePath)); + if (!length) + return false; + + return String(modulePath, length).endsWith("Safari.exe", false); +} + +static HMENU fixMenuReceivedFromOldSafari(IWebUIDelegate* uiDelegate, ContextMenu* originalMenu, HMENU menuFromClient) +{ + ASSERT_ARG(originalMenu, originalMenu); + if (!isPreInspectElementTagSafari(uiDelegate)) + return menuFromClient; + + int count = ::GetMenuItemCount(originalMenu->platformDescription()); + if (count < 1) + return menuFromClient; + + if (::GetMenuItemID(originalMenu->platformDescription(), count - 1) != WebMenuItemTagInspectElement) + return menuFromClient; + + count = ::GetMenuItemCount(menuFromClient); + if (count < 1) + return menuFromClient; + + if (::GetMenuItemID(menuFromClient, count - 1) == WebMenuItemTagInspectElement) + return menuFromClient; + + originalMenu->setPlatformDescription(menuFromClient); + originalMenu->addInspectElementItem(); + return originalMenu->platformDescription(); +} + +HMENU WebContextMenuClient::getCustomMenuFromDefaultItems(ContextMenu* menu) +{ + COMPtr<IWebUIDelegate> uiDelegate; + if (FAILED(m_webView->uiDelegate(&uiDelegate))) + return menu->platformDescription(); + + ASSERT(uiDelegate); + + HMENU newMenu = 0; + COMPtr<WebElementPropertyBag> propertyBag; + propertyBag.adoptRef(WebElementPropertyBag::createInstance(menu->hitTestResult())); + // FIXME: We need to decide whether to do the default before calling this delegate method + if (FAILED(uiDelegate->contextMenuItemsForElement(m_webView, propertyBag.get(), (OLE_HANDLE)(ULONG64)menu->platformDescription(), (OLE_HANDLE*)&newMenu))) + return menu->platformDescription(); + return fixMenuReceivedFromOldSafari(uiDelegate.get(), menu, newMenu); +} + +void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem* item, const ContextMenu* parentMenu) +{ + ASSERT(item->type() == ActionType || item->type() == CheckableActionType); + + COMPtr<IWebUIDelegate> uiDelegate; + if (FAILED(m_webView->uiDelegate(&uiDelegate))) + return; + + ASSERT(uiDelegate); + + COMPtr<WebElementPropertyBag> propertyBag; + propertyBag.adoptRef(WebElementPropertyBag::createInstance(parentMenu->hitTestResult())); + + uiDelegate->contextMenuItemSelected(m_webView, item->releasePlatformDescription(), propertyBag.get()); +} + +void WebContextMenuClient::downloadURL(const KURL& url) +{ + COMPtr<IWebDownloadDelegate> downloadDelegate; + if (FAILED(m_webView->downloadDelegate(&downloadDelegate))) { + // If the WebView doesn't successfully provide a download delegate we'll pass a null one + // into the WebDownload - which may or may not decide to use a DefaultDownloadDelegate + LOG_ERROR("Failed to get downloadDelegate from WebView"); + downloadDelegate = 0; + } + + // Its the delegate's job to ref the WebDownload to keep it alive - otherwise it will be destroyed + // when this method returns + COMPtr<WebDownload> download; + download.adoptRef(WebDownload::createInstance(url, downloadDelegate.get())); + download->start(); +} + +void WebContextMenuClient::searchWithGoogle(const Frame* frame) +{ + String searchString = frame->selectedText(); + searchString.stripWhiteSpace(); + String encoded = encodeWithURLEscapeSequences(searchString); + encoded.replace("%20", "+"); + + String url("http://www.google.com/search?q="); + url.append(encoded); + url.append("&ie=UTF-8&oe=UTF-8"); + + ResourceRequest request = ResourceRequest(url); + if (Page* page = frame->page()) + page->mainFrame()->loader()->urlSelected(FrameLoadRequest(request), 0, false); +} + +void WebContextMenuClient::lookUpInDictionary(Frame*) +{ + notImplemented(); +} + +void WebContextMenuClient::speak(const String&) +{ + notImplemented(); +} + +void WebContextMenuClient::stopSpeaking() +{ + notImplemented(); +} diff --git a/WebKit/win/WebCoreSupport/WebContextMenuClient.h b/WebKit/win/WebCoreSupport/WebContextMenuClient.h new file mode 100644 index 0000000..a981f4e --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebContextMenuClient.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2006, 2007 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 <WebCore/ContextMenuClient.h> +#include <wtf/Forward.h> + +namespace WebCore { + class String; +} +class WebView; + +class WebContextMenuClient : public WebCore::ContextMenuClient { +public: + WebContextMenuClient(WebView*); + + virtual void contextMenuDestroyed(); + + virtual HMENU getCustomMenuFromDefaultItems(WebCore::ContextMenu*); + virtual void contextMenuItemSelected(WebCore::ContextMenuItem*, const WebCore::ContextMenu*); + + virtual void downloadURL(const WebCore::KURL&); + virtual void searchWithGoogle(const WebCore::Frame*); + virtual void lookUpInDictionary(WebCore::Frame*); + virtual void speak(const WebCore::String&); + virtual void stopSpeaking(); + +private: + WebView* m_webView; +}; diff --git a/WebKit/win/WebCoreSupport/WebDragClient.cpp b/WebKit/win/WebCoreSupport/WebDragClient.cpp new file mode 100644 index 0000000..c35991f --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebDragClient.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2007 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "WebDragClient.h" +#include "WebDropSource.h" +#include "WebKitGraphics.h" +#include "WebView.h" + +#include <shlobj.h> +#include <CoreGraphics/CoreGraphics.h> + +#pragma warning(push, 0) +#include <WebCore/ClipboardWin.h> +#include <WebCore/DragData.h> +#include <WebCore/Font.h> +#include <WebCore/FontDescription.h> +#include <WebCore/FontSelector.h> +#include <WebCore/FrameView.h> +#include <WebCore/GraphicsContext.h> +#include <WebCore/Page.h> +#include <WebCore/StringTruncator.h> +#include <WebCore/WebCoreTextRenderer.h> +#pragma warning(pop) + +namespace WebCore { + HBITMAP allocImage(HDC dc, IntSize size, CGContextRef *targetRef); +} + + +#define DRAG_LABEL_BORDER_X 4 +// Keep border_y in synch with DragController::LinkDragBorderInset +#define DRAG_LABEL_BORDER_Y 2 +#define DRAG_LABEL_RADIUS 5 +#define DRAG_LABEL_BORDER_Y_OFFSET 2 + +#define MIN_DRAG_LABEL_WIDTH_BEFORE_CLIP 120 + +// Observation says max size is 200x200 +#define MAX_DRAG_LABEL_WIDTH 200 +#define MAX_DRAG_LABEL_STRING_WIDTH (MAX_DRAG_LABEL_WIDTH - 2 * DRAG_LABEL_BORDER_X) + +#define DRAG_LINK_LABEL_FONT_SIZE 11 +#define DRAG_LINK_URL_FONT_SIZE 10 + +using namespace WebCore; + +WebDragClient::WebDragClient(WebView* webView) + : m_webView(webView) +{ + ASSERT(webView); +} + +DragDestinationAction WebDragClient::actionMaskForDrag(DragData* dragData) +{ + COMPtr<IWebUIDelegate> delegateRef = 0; + //Default behaviour (eg. no delegate, or callback not implemented) is to allow + //any action + WebDragDestinationAction mask = WebDragDestinationActionAny; + if (SUCCEEDED(m_webView->uiDelegate(&delegateRef))) + delegateRef->dragDestinationActionMaskForDraggingInfo(m_webView, dragData->platformData(), &mask); + + return (DragDestinationAction)mask; +} + +void WebDragClient::willPerformDragDestinationAction(DragDestinationAction action, DragData* dragData) +{ + //Default delegate for willPerformDragDestinationAction has no side effects + //so we just call the delegate, and don't worry about whether it's implemented + COMPtr<IWebUIDelegate> delegateRef = 0; + if (SUCCEEDED(m_webView->uiDelegate(&delegateRef))) + delegateRef->willPerformDragDestinationAction(m_webView, (WebDragDestinationAction)action, dragData->platformData()); +} + +DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntPoint& windowPoint) +{ + COMPtr<IWebUIDelegate> delegateRef = 0; + WebDragSourceAction action = WebDragSourceActionAny; + POINT localpt = core(m_webView)->mainFrame()->view()->windowToContents(windowPoint); + if (SUCCEEDED(m_webView->uiDelegate(&delegateRef))) + delegateRef->dragSourceActionMaskForPoint(m_webView, &localpt, &action); + return (DragSourceAction)action; +} + +void WebDragClient::willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*) +{ +} + +void WebDragClient::startDrag(DragImageRef image, const IntPoint& imageOrigin, const IntPoint& dragPoint, Clipboard* clipboard, Frame* frame, bool isLink) +{ + //FIXME: Allow UIDelegate to override behaviour <rdar://problem/5015953> + + //We liberally protect everything, to protect against a load occurring mid-drag + RefPtr<Frame> frameProtector = frame; + COMPtr<IDragSourceHelper> helper; + COMPtr<IDataObject> dataObject; + COMPtr<WebView> viewProtector = m_webView; + COMPtr<IDropSource> source; + if (FAILED(WebDropSource::createInstance(m_webView, &source))) + return; + + dataObject = static_cast<ClipboardWin*>(clipboard)->dataObject(); + if (source && (image || dataObject)) { + if (image) { + if(SUCCEEDED(CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, + IID_IDragSourceHelper,(LPVOID*)&helper))) { + BITMAP b; + GetObject(image, sizeof(BITMAP), &b); + SHDRAGIMAGE sdi; + sdi.sizeDragImage.cx = b.bmWidth; + sdi.sizeDragImage.cy = b.bmHeight; + sdi.crColorKey = 0xffffffff; + sdi.hbmpDragImage = image; + sdi.ptOffset.x = dragPoint.x() - imageOrigin.x(); + sdi.ptOffset.y = dragPoint.y() - imageOrigin.y(); + if (isLink) + sdi.ptOffset.y = b.bmHeight - sdi.ptOffset.y; + + helper->InitializeFromBitmap(&sdi, dataObject.get()); + } + } + + //FIXME: Ensure correct drag ops are available <rdar://problem/5015957> + DWORD okEffect = DROPEFFECT_COPY | DROPEFFECT_LINK | DROPEFFECT_MOVE; + DWORD effect; + COMPtr<IWebUIDelegate> ui; + if (SUCCEEDED(m_webView->uiDelegate(&ui))) { + COMPtr<IWebUIDelegatePrivate> uiPrivate; + if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegatePrivate, (void**)&uiPrivate))) + if (SUCCEEDED(uiPrivate->doDragDrop(m_webView, dataObject.get(), source.get(), okEffect, &effect))) + return; + } + + DoDragDrop(dataObject.get(), source.get(), okEffect, &effect); + } +} + +static Font dragLabelFont(int size, bool bold) +{ + FontDescription desc; + desc.setWeight(bold ? FontWeightBold : FontWeightNormal); + FontFamily family; + family.setFamily("Lucida Grande"); + desc.setFamily(family); + desc.setSpecifiedSize((float)size); + desc.setComputedSize((float)size); + Font result = Font(desc, 0, 0); + result.update(0); + return result; +} + +DragImageRef WebDragClient::createDragImageForLink(KURL& url, const String& inLabel, Frame*) +{ + //This is more or less an exact match for the MacOS code + static const Font labelFont = dragLabelFont(DRAG_LINK_LABEL_FONT_SIZE, true); + static const Font urlFont = dragLabelFont(DRAG_LINK_URL_FONT_SIZE, false); + bool drawURLString = true; + bool clipURLString = false; + bool clipLabelString = false; + + String urlString = url.string(); + String label = inLabel; + if (label.isEmpty()) { + drawURLString = false; + label = urlString; + } + + //First step in drawing the link drag image width + TextRun labelRun(label.impl()); + TextRun urlRun(urlString.impl()); + IntSize labelSize(labelFont.width(labelRun), labelFont.ascent() + labelFont.descent()); + + if (labelSize.width() > MAX_DRAG_LABEL_STRING_WIDTH){ + labelSize.setWidth(MAX_DRAG_LABEL_STRING_WIDTH); + clipLabelString = true; + } + + IntSize urlStringSize; + IntSize imageSize(labelSize.width() + DRAG_LABEL_BORDER_X * 2, + labelSize.height() + DRAG_LABEL_BORDER_Y * 2); + + if (drawURLString) { + urlStringSize.setWidth(urlFont.width(urlRun)); + urlStringSize.setHeight(urlFont.ascent() + urlFont.descent()); + imageSize.setHeight(imageSize.height() + urlStringSize.height()); + if (urlStringSize.width() > MAX_DRAG_LABEL_STRING_WIDTH) { + imageSize.setWidth(MAX_DRAG_LABEL_WIDTH); + clipURLString = true; + } else { + imageSize.setWidth(std::max(labelSize.width(), urlStringSize.width()) + DRAG_LABEL_BORDER_X * 2); + } + } + + // We now know how big the image needs to be, so we create and + // fill the background + HBITMAP image = 0; + HDC dc = GetDC(0); + HDC workingDC = CreateCompatibleDC(dc); + if (!workingDC) { + ReleaseDC(0, dc); + return 0; + } + + CGContextRef contextRef; + image = allocImage(workingDC, imageSize, &contextRef); + if (!image) { + DeleteDC(workingDC); + ReleaseDC(0, dc); + return 0; + } + + ::SelectObject(workingDC, image); + GraphicsContext context(contextRef); + // On Mac alpha is {0.7, 0.7, 0.7, 0.8}, however we can't control alpha + // for drag images on win, so we use 1 + static const Color backgroundColor(140, 140, 140); + static const IntSize radii(DRAG_LABEL_RADIUS, DRAG_LABEL_RADIUS); + context.setFont(labelFont); + IntRect rect(0, 0, imageSize.width(), imageSize.height()); + context.fillRoundedRect(rect, radii, radii, radii, radii, backgroundColor); + + // Draw the text + static const Color topColor(0, 0, 0, 255); //original alpha = 0.75 + static const Color bottomColor(255, 255, 255, 127); //original alpha = 0.5 + if (drawURLString) { + if (clipURLString) + urlString = StringTruncator::rightTruncate(urlString, imageSize.width() - (DRAG_LABEL_BORDER_X * 2.0f), urlFont, false); + IntPoint textPos(DRAG_LABEL_BORDER_X, imageSize.height() - (DRAG_LABEL_BORDER_Y_OFFSET + urlFont.descent())); + WebCoreDrawDoubledTextAtPoint(context, urlString, textPos, urlFont, topColor, bottomColor); + } + + if (clipLabelString) + label = StringTruncator::rightTruncate(label, imageSize.width() - (DRAG_LABEL_BORDER_X * 2.0f), labelFont, false); + + IntPoint textPos(DRAG_LABEL_BORDER_X, DRAG_LABEL_BORDER_Y + labelFont.pixelSize()); + WebCoreDrawDoubledTextAtPoint(context, label, textPos, labelFont, topColor, bottomColor); + + CGContextRelease(contextRef); + DeleteDC(workingDC); + ReleaseDC(0, dc); + return image; +} + +void WebDragClient::dragControllerDestroyed() +{ + delete this; +} diff --git a/WebKit/win/WebCoreSupport/WebDragClient.h b/WebKit/win/WebCoreSupport/WebDragClient.h new file mode 100644 index 0000000..f7ca139 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebDragClient.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007 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 <WebCore/DragClient.h> + +class WebView; + +class WebDragClient : public WebCore::DragClient { +public: + WebDragClient(WebView*); + virtual WebCore::DragDestinationAction actionMaskForDrag(WebCore::DragData*); + virtual void willPerformDragDestinationAction(WebCore::DragDestinationAction, WebCore::DragData*); + virtual void dragControllerDestroyed(); + virtual WebCore::DragSourceAction dragSourceActionMaskForPoint(const WebCore::IntPoint&); + virtual void willPerformDragSourceAction(WebCore::DragSourceAction, const WebCore::IntPoint&, WebCore::Clipboard*); + virtual void startDrag(WebCore::DragImageRef, const WebCore::IntPoint&, const WebCore::IntPoint&, WebCore::Clipboard*, WebCore::Frame*, bool); + virtual WebCore::DragImageRef createDragImageForLink(WebCore::KURL&, const WebCore::String&, WebCore::Frame*); +private: + WebView* m_webView; +}; + diff --git a/WebKit/win/WebCoreSupport/WebEditorClient.cpp b/WebKit/win/WebCoreSupport/WebEditorClient.cpp new file mode 100644 index 0000000..e38cd0d --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebEditorClient.cpp @@ -0,0 +1,762 @@ +/* + * Copyright (C) 2006, 2007 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "WebKitDLL.h" +#include "WebEditorClient.h" + +#include "WebKit.h" +#include "WebLocalizableStrings.h" +#include "WebView.h" +#include "DOMCoreClasses.h" +#pragma warning(push, 0) +#include <WebCore/BString.h> +#include <WebCore/Document.h> +#include <WebCore/EditCommand.h> +#include <WebCore/HTMLElement.h> +#include <WebCore/HTMLInputElement.h> +#include <WebCore/HTMLNames.h> +#include <WebCore/KeyboardEvent.h> +#include <WebCore/PlatformKeyboardEvent.h> +#include <WebCore/NotImplemented.h> +#include <WebCore/Range.h> +#pragma warning(pop) + +using namespace WebCore; +using namespace HTMLNames; + +// {09A11D2B-FAFB-4ca0-A6F7-791EE8932C88} +static const GUID IID_IWebUndoCommand = +{ 0x9a11d2b, 0xfafb, 0x4ca0, { 0xa6, 0xf7, 0x79, 0x1e, 0xe8, 0x93, 0x2c, 0x88 } }; + +class IWebUndoCommand : public IUnknown { +public: + virtual void execute() = 0; +}; + +// WebEditorUndoTarget ------------------------------------------------------------- + +class WebEditorUndoTarget : public IWebUndoTarget +{ +public: + WebEditorUndoTarget(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + + // IWebUndoTarget + virtual HRESULT STDMETHODCALLTYPE invoke( + /* [in] */ BSTR actionName, + /* [in] */ IUnknown *obj); + +private: + ULONG m_refCount; +}; + +WebEditorUndoTarget::WebEditorUndoTarget() +: m_refCount(1) +{ +} + +HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebUndoTarget*>(this); + else if (IsEqualGUID(riid, IID_IWebUndoTarget)) + *ppvObject = static_cast<IWebUndoTarget*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE WebEditorUndoTarget::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE WebEditorUndoTarget::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + +HRESULT STDMETHODCALLTYPE WebEditorUndoTarget::invoke( + /* [in] */ BSTR /*actionName*/, + /* [in] */ IUnknown *obj) +{ + IWebUndoCommand* undoCommand = 0; + if (SUCCEEDED(obj->QueryInterface(IID_IWebUndoCommand, (void**)&undoCommand))) { + undoCommand->execute(); + undoCommand->Release(); + } + return S_OK; +} + +// WebEditorClient ------------------------------------------------------------------ + +WebEditorClient::WebEditorClient(WebView* webView) + : m_webView(webView) + , m_undoTarget(0) +{ + m_undoTarget = new WebEditorUndoTarget(); +} + +WebEditorClient::~WebEditorClient() +{ + if (m_undoTarget) + m_undoTarget->Release(); +} + +void WebEditorClient::pageDestroyed() +{ + delete this; +} + +bool WebEditorClient::isContinuousSpellCheckingEnabled() +{ + BOOL enabled; + if (FAILED(m_webView->isContinuousSpellCheckingEnabled(&enabled))) + return false; + return !!enabled; +} + +void WebEditorClient::toggleContinuousSpellChecking() +{ + m_webView->toggleContinuousSpellChecking(0); +} + +bool WebEditorClient::isGrammarCheckingEnabled() +{ + BOOL enabled; + if (FAILED(m_webView->isGrammarCheckingEnabled(&enabled))) + return false; + return !!enabled; +} + +void WebEditorClient::toggleGrammarChecking() +{ + m_webView->toggleGrammarChecking(0); +} + +static void initViewSpecificSpelling(IWebViewEditing* viewEditing) +{ + // we just use this as a flag to indicate that we've spell checked the document + // and need to close the spell checker out when the view closes. + int tag; + viewEditing->spellCheckerDocumentTag(&tag); +} + +int WebEditorClient::spellCheckerDocumentTag() +{ + // we don't use the concept of spelling tags + notImplemented(); + ASSERT_NOT_REACHED(); + return 0; +} + +bool WebEditorClient::shouldBeginEditing(Range*) +{ + notImplemented(); + return true; +} + +bool WebEditorClient::shouldEndEditing(Range*) +{ + notImplemented(); + return true; +} + +void WebEditorClient::didBeginEditing() +{ + notImplemented(); +} + +void WebEditorClient::respondToChangedContents() +{ + notImplemented(); +} + +void WebEditorClient::respondToChangedSelection() +{ + m_webView->selectionChanged(); +} + +void WebEditorClient::didEndEditing() +{ + notImplemented(); +} + +void WebEditorClient::didWriteSelectionToPasteboard() +{ + notImplemented(); +} + +void WebEditorClient::didSetSelectionTypesForPasteboard() +{ + notImplemented(); +} + +bool WebEditorClient::shouldDeleteRange(Range* /*range*/) +{ + notImplemented(); + return true; + + // FIXME: calling m_webView->editingDelegate() will cause an assertion failure so we don't want to enable this code until that's implemented. + //BOOL result = false; + //IWebViewEditingDelegate* editingDelegate; + //// FIXME: DOMRange needs to be implemented before anything meaningful can be done here + //IDOMRange* domRange(0); + //if (SUCCEEDED(m_webView->editingDelegate(&editingDelegate))) { + // editingDelegate->shouldDeleteDOMRange(m_webView, domRange, &result); + // editingDelegate->Release(); + //} + //return !!result; +} + +bool WebEditorClient::shouldInsertNode(Node* /*node*/, Range* /*replacingRange*/, EditorInsertAction /*givenAction*/) +{ + notImplemented(); + return true; +} + +bool WebEditorClient::shouldInsertText(const String& /*str*/, Range* /* replacingRange */, EditorInsertAction /*givenAction*/) +{ + notImplemented(); + return true; + + // FIXME: calling m_webView->editingDelegate() will cause an assertion failure so we don't want to enable this code until that's implemented. + //BOOL result = false; + //IWebViewEditingDelegate* editingDelegate; + //// FIXME: DOMRange needs to be implemented before anything meaningful can be done here + //IDOMRange* domRange(0); // make a DOMRange from replacingRange + //BString text(str); + //if (SUCCEEDED(m_webView->editingDelegate(&editingDelegate))) { + // editingDelegate->shouldInsertText(m_webView, text, domRange, (WebViewInsertAction) givenAction, &result); + // editingDelegate->Release(); + //} + //return !!result; +} + +//bool WebEditorClient::shouldChangeSelectedRange(Range *currentRange, Range *toProposedRange, SelectionAffinity selectionAffinity, bool stillSelecting) +//{ notImplemented(); return false; } + +bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* /*style*/, Range* /*toElementsInDOMRange*/) +{ notImplemented(); return true; } + +bool WebEditorClient::shouldMoveRangeAfterDelete(Range* /*range*/, Range* /*rangeToBeReplaced*/) +{ notImplemented(); return true; } + +bool WebEditorClient::shouldChangeTypingStyle(CSSStyleDeclaration* /*currentStyle*/, CSSStyleDeclaration* /*toProposedStyle*/) +{ notImplemented(); return false; } + +void WebEditorClient::webViewDidChangeTypingStyle(WebNotification* /*notification*/) +{ notImplemented(); } + +void WebEditorClient::webViewDidChangeSelection(WebNotification* /*notification*/) +{ notImplemented(); } + +bool WebEditorClient::shouldShowDeleteInterface(HTMLElement* /*element*/) +{ notImplemented(); return false; } + +bool WebEditorClient::smartInsertDeleteEnabled(void) +{ + BOOL enabled = FALSE; + m_webView->smartInsertDeleteEnabled(&enabled); + return !!enabled; +} + +bool WebEditorClient::shouldChangeSelectedRange(WebCore::Range*, WebCore::Range*, WebCore::EAffinity, bool) +{ notImplemented(); return true; } + +void WebEditorClient::textFieldDidBeginEditing(Element* e) +{ + IWebFormDelegate* formDelegate; + if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) { + IDOMElement* domElement = DOMElement::createInstance(e); + if (domElement) { + IDOMHTMLInputElement* domInputElement; + if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) { + formDelegate->textFieldDidBeginEditing(domInputElement, kit(e->document()->frame())); + domInputElement->Release(); + } + domElement->Release(); + } + formDelegate->Release(); + } +} + +void WebEditorClient::textFieldDidEndEditing(Element* e) +{ + IWebFormDelegate* formDelegate; + if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) { + IDOMElement* domElement = DOMElement::createInstance(e); + if (domElement) { + IDOMHTMLInputElement* domInputElement; + if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) { + formDelegate->textFieldDidEndEditing(domInputElement, kit(e->document()->frame())); + domInputElement->Release(); + } + domElement->Release(); + } + formDelegate->Release(); + } +} + +void WebEditorClient::textDidChangeInTextField(Element* e) +{ + IWebFormDelegate* formDelegate; + if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) { + IDOMElement* domElement = DOMElement::createInstance(e); + if (domElement) { + IDOMHTMLInputElement* domInputElement; + if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) { + formDelegate->textDidChangeInTextField(domInputElement, kit(e->document()->frame())); + domInputElement->Release(); + } + domElement->Release(); + } + formDelegate->Release(); + } +} + +bool WebEditorClient::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke) +{ + BOOL result = FALSE; + IWebFormDelegate* formDelegate; + if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) { + IDOMElement* domElement = DOMElement::createInstance(e); + if (domElement) { + IDOMHTMLInputElement* domInputElement; + if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) { + String command = m_webView->interpretKeyEvent(ke); + // We allow empty commands here because the app code actually depends on this being called for all key presses. + // We may want to revisit this later because it doesn't really make sense to send an empty command. + formDelegate->doPlatformCommand(domInputElement, BString(command), kit(e->document()->frame()), &result); + domInputElement->Release(); + } + domElement->Release(); + } + formDelegate->Release(); + } + return !!result; +} + +void WebEditorClient::textWillBeDeletedInTextField(Element* e) +{ + // We're using the deleteBackward command for all deletion operations since the autofill code treats all deletions the same way. + IWebFormDelegate* formDelegate; + if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) { + IDOMElement* domElement = DOMElement::createInstance(e); + if (domElement) { + IDOMHTMLInputElement* domInputElement; + if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLInputElement, (void**)&domInputElement))) { + BOOL result; + formDelegate->doPlatformCommand(domInputElement, BString(L"DeleteBackward"), kit(e->document()->frame()), &result); + domInputElement->Release(); + } + domElement->Release(); + } + formDelegate->Release(); + } +} + +void WebEditorClient::textDidChangeInTextArea(Element* e) +{ + IWebFormDelegate* formDelegate; + if (SUCCEEDED(m_webView->formDelegate(&formDelegate)) && formDelegate) { + IDOMElement* domElement = DOMElement::createInstance(e); + if (domElement) { + IDOMHTMLTextAreaElement* domTextAreaElement; + if (SUCCEEDED(domElement->QueryInterface(IID_IDOMHTMLTextAreaElement, (void**)&domTextAreaElement))) { + formDelegate->textDidChangeInTextArea(domTextAreaElement, kit(e->document()->frame())); + domTextAreaElement->Release(); + } + domElement->Release(); + } + formDelegate->Release(); + } +} + +class WebEditorUndoCommand : public IWebUndoCommand +{ +public: + WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo); + void execute(); + + // IUnknown + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(void); + virtual ULONG STDMETHODCALLTYPE Release(void); + +private: + ULONG m_refCount; + RefPtr<EditCommand> m_editCommand; + bool m_isUndo; +}; + +WebEditorUndoCommand::WebEditorUndoCommand(PassRefPtr<EditCommand> editCommand, bool isUndo) + : m_editCommand(editCommand) + , m_isUndo(isUndo) + , m_refCount(1) +{ +} + +void WebEditorUndoCommand::execute() +{ + if (m_isUndo) + m_editCommand->unapply(); + else + m_editCommand->reapply(); +} + +HRESULT STDMETHODCALLTYPE WebEditorUndoCommand::QueryInterface(REFIID riid, void** ppvObject) +{ + *ppvObject = 0; + if (IsEqualGUID(riid, IID_IUnknown)) + *ppvObject = static_cast<IWebUndoCommand*>(this); + else if (IsEqualGUID(riid, IID_IWebUndoCommand)) + *ppvObject = static_cast<IWebUndoCommand*>(this); + else + return E_NOINTERFACE; + + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE WebEditorUndoCommand::AddRef(void) +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE WebEditorUndoCommand::Release(void) +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + +static LPCTSTR undoNameForEditAction(EditAction editAction) +{ + switch (editAction) { + case EditActionUnspecified: return 0; + case EditActionSetColor: return LPCTSTR_UI_STRING_KEY("Set Color", "Set Color (Undo action name)", "Undo action name"); + case EditActionSetBackgroundColor: return LPCTSTR_UI_STRING_KEY("Set Background Color", "Set Background Color (Undo action name)", "Undo action name"); + case EditActionTurnOffKerning: return LPCTSTR_UI_STRING_KEY("Turn Off Kerning", "Turn Off Kerning (Undo action name)", "Undo action name"); + case EditActionTightenKerning: return LPCTSTR_UI_STRING_KEY("Tighten Kerning", "Tighten Kerning (Undo action name)", "Undo action name"); + case EditActionLoosenKerning: return LPCTSTR_UI_STRING_KEY("Loosen Kerning", "Loosen Kerning (Undo action name)", "Undo action name"); + case EditActionUseStandardKerning: return LPCTSTR_UI_STRING_KEY("Use Standard Kerning", "Use Standard Kerning (Undo action name)", "Undo action name"); + case EditActionTurnOffLigatures: return LPCTSTR_UI_STRING_KEY("Turn Off Ligatures", "Turn Off Ligatures (Undo action name)", "Undo action name"); + case EditActionUseStandardLigatures: return LPCTSTR_UI_STRING_KEY("Use Standard Ligatures", "Use Standard Ligatures (Undo action name)", "Undo action name"); + case EditActionUseAllLigatures: return LPCTSTR_UI_STRING_KEY("Use All Ligatures", "Use All Ligatures (Undo action name)", "Undo action name"); + case EditActionRaiseBaseline: return LPCTSTR_UI_STRING_KEY("Raise Baseline", "Raise Baseline (Undo action name)", "Undo action name"); + case EditActionLowerBaseline: return LPCTSTR_UI_STRING_KEY("Lower Baseline", "Lower Baseline (Undo action name)", "Undo action name"); + case EditActionSetTraditionalCharacterShape: return LPCTSTR_UI_STRING_KEY("Set Traditional Character Shape", "Set Traditional Character Shape (Undo action name)", "Undo action name"); + case EditActionSetFont: return LPCTSTR_UI_STRING_KEY("Set Font", "Set Font (Undo action name)", "Undo action name"); + case EditActionChangeAttributes: return LPCTSTR_UI_STRING_KEY("Change Attributes", "Change Attributes (Undo action name)", "Undo action name"); + case EditActionAlignLeft: return LPCTSTR_UI_STRING_KEY("Align Left", "Align Left (Undo action name)", "Undo action name"); + case EditActionAlignRight: return LPCTSTR_UI_STRING_KEY("Align Right", "Align Right (Undo action name)", "Undo action name"); + case EditActionCenter: return LPCTSTR_UI_STRING_KEY("Center", "Center (Undo action name)", "Undo action name"); + case EditActionJustify: return LPCTSTR_UI_STRING_KEY("Justify", "Justify (Undo action name)", "Undo action name"); + case EditActionSetWritingDirection: return LPCTSTR_UI_STRING_KEY("Set Writing Direction", "Set Writing Direction (Undo action name)", "Undo action name"); + case EditActionSubscript: return LPCTSTR_UI_STRING_KEY("Subscript", "Subscript (Undo action name)", "Undo action name"); + case EditActionSuperscript: return LPCTSTR_UI_STRING_KEY("Superscript", "Superscript (Undo action name)", "Undo action name"); + case EditActionUnderline: return LPCTSTR_UI_STRING_KEY("Underline", "Underline (Undo action name)", "Undo action name"); + case EditActionOutline: return LPCTSTR_UI_STRING_KEY("Outline", "Outline (Undo action name)", "Undo action name"); + case EditActionUnscript: return LPCTSTR_UI_STRING_KEY("Unscript", "Unscript (Undo action name)", "Undo action name"); + case EditActionDrag: return LPCTSTR_UI_STRING_KEY("Drag", "Drag (Undo action name)", "Undo action name"); + case EditActionCut: return LPCTSTR_UI_STRING_KEY("Cut", "Cut (Undo action name)", "Undo action name"); + case EditActionPaste: return LPCTSTR_UI_STRING_KEY("Paste", "Paste (Undo action name)", "Undo action name"); + case EditActionPasteFont: return LPCTSTR_UI_STRING_KEY("Paste Font", "Paste Font (Undo action name)", "Undo action name"); + case EditActionPasteRuler: return LPCTSTR_UI_STRING_KEY("Paste Ruler", "Paste Ruler (Undo action name)", "Undo action name"); + case EditActionTyping: return LPCTSTR_UI_STRING_KEY("Typing", "Typing (Undo action name)", "Undo action name"); + case EditActionCreateLink: return LPCTSTR_UI_STRING_KEY("Create Link", "Create Link (Undo action name)", "Undo action name"); + case EditActionUnlink: return LPCTSTR_UI_STRING_KEY("Unlink", "Unlink (Undo action name)", "Undo action name"); + case EditActionInsertList: return LPCTSTR_UI_STRING_KEY("Insert List", "Insert List (Undo action name)", "Undo action name"); + case EditActionFormatBlock: return LPCTSTR_UI_STRING_KEY("Formatting", "Format Block (Undo action name)", "Undo action name"); + case EditActionIndent: return LPCTSTR_UI_STRING_KEY("Indent", "Indent (Undo action name)", "Undo action name"); + case EditActionOutdent: return LPCTSTR_UI_STRING_KEY("Outdent", "Outdent (Undo action name)", "Undo action name"); + } + return 0; +} + +void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command) +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + LPCTSTR actionName = undoNameForEditAction(command->editingAction()); + WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, true); + if (!undoCommand) + return; + uiDelegate->registerUndoWithTarget(m_undoTarget, 0, undoCommand); + undoCommand->Release(); // the undo manager owns the reference + BSTR actionNameBSTR = SysAllocString(actionName); + if (actionNameBSTR) { + uiDelegate->setActionTitle(actionNameBSTR); + SysFreeString(actionNameBSTR); + } + uiDelegate->Release(); + } +} + +void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand> command) +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + WebEditorUndoCommand* undoCommand = new WebEditorUndoCommand(command, false); + if (!undoCommand) + return; + uiDelegate->registerUndoWithTarget(m_undoTarget, 0, undoCommand); + undoCommand->Release(); // the undo manager owns the reference + uiDelegate->Release(); + } +} + +void WebEditorClient::clearUndoRedoOperations() +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->removeAllActionsWithTarget(m_undoTarget); + uiDelegate->Release(); + } +} + +bool WebEditorClient::canUndo() const +{ + BOOL result = FALSE; + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->canUndo(&result); + uiDelegate->Release(); + } + return !!result; +} + +bool WebEditorClient::canRedo() const +{ + BOOL result = FALSE; + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->canRedo(&result); + uiDelegate->Release(); + } + return !!result; +} + +void WebEditorClient::undo() +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->undo(); + uiDelegate->Release(); + } +} + +void WebEditorClient::redo() +{ + IWebUIDelegate* uiDelegate = 0; + if (SUCCEEDED(m_webView->uiDelegate(&uiDelegate))) { + uiDelegate->redo(); + uiDelegate->Release(); + } +} + +void WebEditorClient::handleKeyboardEvent(KeyboardEvent* evt) +{ + if (m_webView->handleEditingKeyboardEvent(evt)) + evt->setDefaultHandled(); +} + +void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* ) +{ +} + +bool WebEditorClient::isEditable() +{ + return false; +} + +void WebEditorClient::ignoreWordInSpellDocument(const String& word) +{ + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + initViewSpecificSpelling(m_webView); + ed->ignoreWordInSpellDocument(m_webView, BString(word)); +} + +void WebEditorClient::learnWord(const String& word) +{ + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + ed->learnWord(BString(word)); +} + +void WebEditorClient::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength) +{ + *misspellingLocation = -1; + *misspellingLength = 0; + + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + initViewSpecificSpelling(m_webView); + ed->checkSpellingOfString(m_webView, text, length, misspellingLocation, misspellingLength); +} + +void WebEditorClient::checkGrammarOfString(const UChar* text, int length, Vector<GrammarDetail>& details, int* badGrammarLocation, int* badGrammarLength) +{ + details.clear(); + *badGrammarLocation = -1; + *badGrammarLength = 0; + + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + initViewSpecificSpelling(m_webView); + COMPtr<IEnumWebGrammarDetails> enumDetailsObj; + if (FAILED(ed->checkGrammarOfString(m_webView, text, length, &enumDetailsObj, badGrammarLocation, badGrammarLength))) + return; + + while (true) { + ULONG fetched; + COMPtr<IWebGrammarDetail> detailObj; + if (enumDetailsObj->Next(1, &detailObj, &fetched) != S_OK) + break; + + GrammarDetail detail; + if (FAILED(detailObj->length(&detail.length))) + continue; + if (FAILED(detailObj->location(&detail.location))) + continue; + BSTR userDesc; + if (FAILED(detailObj->userDescription(&userDesc))) + continue; + detail.userDescription = String(userDesc, SysStringLen(userDesc)); + SysFreeString(userDesc); + + COMPtr<IEnumSpellingGuesses> enumGuessesObj; + if (FAILED(detailObj->guesses(&enumGuessesObj))) + continue; + while (true) { + BSTR guess; + if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK) + break; + detail.guesses.append(String(guess, SysStringLen(guess))); + SysFreeString(guess); + } + + details.append(detail); + } +} + +void WebEditorClient::updateSpellingUIWithGrammarString(const String& string, const WebCore::GrammarDetail& detail) +{ + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + Vector<BSTR> guessesBSTRs; + for (unsigned i = 0; i < detail.guesses.size(); i++) { + BString guess(detail.guesses[i]); + guessesBSTRs.append(guess.release()); + } + BString userDescriptionBSTR(detail.userDescription); + ed->updateSpellingUIWithGrammarString(BString(string), detail.location, detail.length, userDescriptionBSTR, guessesBSTRs.data(), (int)guessesBSTRs.size()); + for (unsigned i = 0; i < guessesBSTRs.size(); i++) + SysFreeString(guessesBSTRs[i]); +} + +void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& word) +{ + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + ed->updateSpellingUIWithMisspelledWord(BString(word)); +} + +void WebEditorClient::showSpellingUI(bool show) +{ + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + ed->showSpellingUI(show); +} + +bool WebEditorClient::spellingUIIsShowing() +{ + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return false; + + BOOL showing; + if (FAILED(ed->spellingUIIsShowing(&showing))) + return false; + + return !!showing; +} + +void WebEditorClient::getGuessesForWord(const String& word, Vector<String>& guesses) +{ + guesses.clear(); + + COMPtr<IWebEditingDelegate> ed; + if (FAILED(m_webView->editingDelegate(&ed)) || !ed.get()) + return; + + COMPtr<IEnumSpellingGuesses> enumGuessesObj; + if (FAILED(ed->guessesForWord(BString(word), &enumGuessesObj))) + return; + + while (true) { + ULONG fetched; + BSTR guess; + if (enumGuessesObj->Next(1, &guess, &fetched) != S_OK) + break; + guesses.append(String(guess, SysStringLen(guess))); + SysFreeString(guess); + } +} + +void WebEditorClient::setInputMethodState(bool enabled) +{ + m_webView->setInputMethodState(enabled); +} diff --git a/WebKit/win/WebCoreSupport/WebEditorClient.h b/WebKit/win/WebCoreSupport/WebEditorClient.h new file mode 100644 index 0000000..8c603f2 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebEditorClient.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2006, 2007 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#ifndef WebEditorClient_H +#define WebEditorClient_H + +#include "WebKit.h" +#pragma warning(push, 0) +#include <WebCore/EditorClient.h> +#include <wtf/OwnPtr.h> +#pragma warning(pop) + +class WebView; +class WebNotification; +class WebEditorUndoTarget; + +class WebEditorClient : public WebCore::EditorClient { +public: + WebEditorClient(WebView*); + ~WebEditorClient(); + + virtual void pageDestroyed(); + + virtual bool isContinuousSpellCheckingEnabled(); + virtual void toggleGrammarChecking(); + virtual bool isGrammarCheckingEnabled(); + virtual void toggleContinuousSpellChecking(); + virtual int spellCheckerDocumentTag(); + + virtual bool isEditable(); + + virtual bool shouldBeginEditing(WebCore::Range*); + virtual bool shouldEndEditing(WebCore::Range*); + virtual bool shouldInsertText(const WebCore::String&, WebCore::Range*, WebCore::EditorInsertAction); + + virtual void didBeginEditing(); + virtual void didEndEditing(); + virtual void didWriteSelectionToPasteboard(); + virtual void didSetSelectionTypesForPasteboard(); + + virtual void respondToChangedContents(); + virtual void respondToChangedSelection(); + + bool shouldShowDeleteInterface(WebCore::HTMLElement*); + bool shouldDeleteRange(WebCore::Range*); + + bool shouldInsertNode(WebCore::Node*, WebCore::Range* replacingRange, WebCore::EditorInsertAction); + bool shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*); + bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*); + bool shouldChangeTypingStyle(WebCore::CSSStyleDeclaration* currentStyle, WebCore::CSSStyleDeclaration* toProposedStyle); + + void webViewDidChangeTypingStyle(WebNotification*); + void webViewDidChangeSelection(WebNotification*); + + bool smartInsertDeleteEnabled(); + + void registerCommandForUndo(PassRefPtr<WebCore::EditCommand>); + void registerCommandForRedo(PassRefPtr<WebCore::EditCommand>); + void clearUndoRedoOperations(); + + bool canUndo() const; + bool canRedo() const; + + void undo(); + void redo(); + + virtual bool shouldChangeSelectedRange(WebCore::Range* fromRange, WebCore::Range* toRange, WebCore::EAffinity, bool stillSelecting); + virtual void textFieldDidBeginEditing(WebCore::Element*); + virtual void textFieldDidEndEditing(WebCore::Element*); + virtual void textDidChangeInTextField(WebCore::Element*); + virtual bool doTextFieldCommandFromEvent(WebCore::Element*, WebCore::KeyboardEvent*); + virtual void textWillBeDeletedInTextField(WebCore::Element* input); + virtual void textDidChangeInTextArea(WebCore::Element*); + + void handleKeyboardEvent(WebCore::KeyboardEvent*); + void handleInputMethodKeydown(WebCore::KeyboardEvent*); + + virtual void ignoreWordInSpellDocument(const WebCore::String&); + virtual void learnWord(const WebCore::String&); + virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); + virtual void checkGrammarOfString(const UChar*, int length, Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); + virtual void updateSpellingUIWithGrammarString(const WebCore::String&, const WebCore::GrammarDetail& detail); + virtual void updateSpellingUIWithMisspelledWord(const WebCore::String&); + virtual void showSpellingUI(bool show); + virtual bool spellingUIIsShowing(); + virtual void getGuessesForWord(const WebCore::String&, Vector<WebCore::String>& guesses); + + virtual void setInputMethodState(bool); + +private: + WebView* m_webView; + WebEditorUndoTarget* m_undoTarget; +}; + +#endif // WebEditorClient_H diff --git a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp new file mode 100644 index 0000000..17bee47 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp @@ -0,0 +1,706 @@ +/* + * Copyright (C) 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 "WebFrameLoaderClient.h" + +#include "CFDictionaryPropertyBag.h" +#include "COMPropertyBag.h" +#include "EmbeddedWidget.h" +#include "MarshallingHelpers.h" +#include "WebCachedPagePlatformData.h" +#include "WebChromeClient.h" +#include "WebDocumentLoader.h" +#include "WebError.h" +#include "WebFrame.h" +#include "WebHistory.h" +#include "WebMutableURLRequest.h" +#include "WebNotificationCenter.h" +#include "WebScriptDebugServer.h" +#include "WebURLAuthenticationChallenge.h" +#include "WebURLResponse.h" +#include "WebView.h" +#pragma warning(push, 0) +#include <WebCore/DocumentLoader.h> +#include <WebCore/FrameLoader.h> +#include <WebCore/FrameTree.h> +#include <WebCore/FrameView.h> +#include <WebCore/HTMLFrameElement.h> +#include <WebCore/HTMLFrameOwnerElement.h> +#include <WebCore/HTMLNames.h> +#include <WebCore/HistoryItem.h> +#include <WebCore/Page.h> +#include <WebCore/PluginPackage.h> +#include <WebCore/PluginView.h> +#include <WebCore/RenderPart.h> +#include <WebCore/ResourceHandle.h> +#pragma warning(pop) + +using namespace WebCore; +using namespace HTMLNames; + +static WebDataSource* getWebDataSource(DocumentLoader* loader) +{ + return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0; +} + +WebFrameLoaderClient::WebFrameLoaderClient(WebFrame* webFrame) + : m_webFrame(webFrame) + , m_pluginView(0) + , m_hasSentResponseToPlugin(false) +{ + ASSERT_ARG(webFrame, webFrame); +} + +WebFrameLoaderClient::~WebFrameLoaderClient() +{ +} + +bool WebFrameLoaderClient::hasWebView() const +{ + return m_webFrame->webView(); +} + +void WebFrameLoaderClient::forceLayout() +{ + core(m_webFrame)->forceLayout(true); +} + +void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return; + + COMPtr<WebMutableURLRequest> webURLRequest(AdoptCOM, WebMutableURLRequest::createInstance(request)); + resourceLoadDelegate->identifierForInitialRequest(webView, webURLRequest.get(), getWebDataSource(loader), identifier); +} + +void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge) +{ + ASSERT(challenge.sourceHandle()); + + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (SUCCEEDED(webView->resourceLoadDelegate(&resourceLoadDelegate))) { + COMPtr<WebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge)); + if (SUCCEEDED(resourceLoadDelegate->didReceiveAuthenticationChallenge(webView, identifier, webChallenge.get(), getWebDataSource(loader)))) + return; + } + + // If the ResourceLoadDelegate doesn't exist or fails to handle the call, we tell the ResourceHandle + // to continue without credential - this is the best approximation of Mac behavior + challenge.sourceHandle()->receivedRequestToContinueWithoutCredential(challenge); +} + +void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return; + + COMPtr<WebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge)); + resourceLoadDelegate->didCancelAuthenticationChallenge(webView, identifier, webChallenge.get(), getWebDataSource(loader)); +} + +void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return; + + COMPtr<WebMutableURLRequest> webURLRequest(AdoptCOM, WebMutableURLRequest::createInstance(request)); + COMPtr<WebURLResponse> webURLRedirectResponse(AdoptCOM, WebURLResponse::createInstance(redirectResponse)); + + COMPtr<IWebURLRequest> newWebURLRequest; + if (FAILED(resourceLoadDelegate->willSendRequest(webView, identifier, webURLRequest.get(), webURLRedirectResponse.get(), getWebDataSource(loader), &newWebURLRequest))) + return; + + if (webURLRequest == newWebURLRequest) + return; + + COMPtr<WebMutableURLRequest> newWebURLRequestImpl(Query, newWebURLRequest); + if (!newWebURLRequestImpl) + return; + + request = newWebURLRequestImpl->resourceRequest(); +} + +void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return; + + COMPtr<WebURLResponse> webURLResponse(AdoptCOM, WebURLResponse::createInstance(response)); + resourceLoadDelegate->didReceiveResponse(webView, identifier, webURLResponse.get(), getWebDataSource(loader)); +} + +void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return; + + resourceLoadDelegate->didReceiveContentLength(webView, identifier, length, getWebDataSource(loader)); +} + +void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return; + + resourceLoadDelegate->didFinishLoadingFromDataSource(webView, identifier, getWebDataSource(loader)); +} + +void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return; + + COMPtr<WebError> webError(AdoptCOM, WebError::createInstance(error)); + resourceLoadDelegate->didFailLoadingWithError(webView, identifier, webError.get(), getWebDataSource(loader)); +} + +void WebFrameLoaderClient::dispatchDidHandleOnloadEvents() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv; + if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv) + frameLoadDelegatePriv->didHandleOnloadEventsForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didReceiveServerRedirectForProvisionalLoadForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidCancelClientRedirect() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didCancelClientRedirectForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->willPerformClientRedirectToURL(webView, BString(url.string()), delay, MarshallingHelpers::CFAbsoluteTimeToDATE(fireDate), m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didChangeLocationWithinPageForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchWillClose() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->willCloseFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidReceiveIcon() +{ + m_webFrame->webView()->dispatchDidReceiveIconFromWebFrame(m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidStartProvisionalLoad() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didStartProvisionalLoadForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title) +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didReceiveTitle(webView, BString(title), m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidCommitLoad() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didCommitLoadForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidFinishDocumentLoad() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv; + if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv) + frameLoadDelegatePriv->didFinishDocumentLoadForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidFinishLoad() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegate> frameLoadDelegate; + if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate))) + frameLoadDelegate->didFinishLoadForFrame(webView, m_webFrame); +} + +void WebFrameLoaderClient::dispatchDidFirstLayout() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv; + if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv) + frameLoadDelegatePriv->didFirstLayoutInFrame(webView, m_webFrame); +} + +Frame* WebFrameLoaderClient::dispatchCreatePage() +{ + WebView* webView = m_webFrame->webView(); + + COMPtr<IWebUIDelegate> ui; + if (FAILED(webView->uiDelegate(&ui))) + return 0; + + COMPtr<IWebView> newWebView; + if (FAILED(ui->createWebViewWithRequest(webView, 0, &newWebView))) + return 0; + + COMPtr<IWebFrame> mainFrame; + if (FAILED(newWebView->mainFrame(&mainFrame))) + return 0; + + COMPtr<WebFrame> mainFrameImpl(Query, mainFrame); + return core(mainFrameImpl.get()); +} + +void WebFrameLoaderClient::dispatchShow() +{ + WebView* webView = m_webFrame->webView(); + COMPtr<IWebUIDelegate> ui; + if (SUCCEEDED(webView->uiDelegate(&ui))) + ui->webViewShow(webView); +} + +void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader*) +{ +} + +void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error) +{ + if (!m_pluginView) + return; + + if (m_pluginView->status() == PluginStatusLoadedSuccessfully) + m_pluginView->didFail(error); + m_pluginView = 0; + m_hasSentResponseToPlugin = false; +} + +void WebFrameLoaderClient::postProgressStartedNotification() +{ + static BSTR progressStartedName = SysAllocString(WebViewProgressStartedNotification); + IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); + notifyCenter->postNotificationName(progressStartedName, static_cast<IWebView*>(m_webFrame->webView()), 0); +} + +void WebFrameLoaderClient::postProgressEstimateChangedNotification() +{ + static BSTR progressEstimateChangedName = SysAllocString(WebViewProgressEstimateChangedNotification); + IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); + notifyCenter->postNotificationName(progressEstimateChangedName, static_cast<IWebView*>(m_webFrame->webView()), 0); +} + +void WebFrameLoaderClient::postProgressFinishedNotification() +{ + static BSTR progressFinishedName = SysAllocString(WebViewProgressFinishedNotification); + IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal(); + notifyCenter->postNotificationName(progressFinishedName, static_cast<IWebView*>(m_webFrame->webView()), 0); +} + +void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length) +{ + // FIXME: This should probably go through the data source. + const String& textEncoding = loader->response().textEncodingName(); + + if (!m_pluginView) + receivedData(data, length, textEncoding); + + if (!m_pluginView || m_pluginView->status() != PluginStatusLoadedSuccessfully) + return; + + if (!m_hasSentResponseToPlugin) { + m_pluginView->didReceiveResponse(core(m_webFrame)->loader()->documentLoader()->response()); + // didReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in + // setting up this stream can cause the main document load to be cancelled, setting m_pluginView + // to null + if (!m_pluginView) + return; + m_hasSentResponseToPlugin = true; + } + m_pluginView->didReceiveData(data, length); +} + +void WebFrameLoaderClient::receivedData(const char* data, int length, const String& textEncoding) +{ + Frame* coreFrame = core(m_webFrame); + if (!coreFrame) + return; + + // Set the encoding. This only needs to be done once, but it's harmless to do it again later. + String encoding = coreFrame->loader()->documentLoader()->overrideEncoding(); + bool userChosen = !encoding.isNull(); + if (encoding.isNull()) + encoding = textEncoding; + coreFrame->loader()->setEncoding(encoding, userChosen); + + coreFrame->loader()->addData(data, length); +} + +void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader) +{ + // Telling the frame we received some data and passing 0 as the data is our + // way to get work done that is normally done when the first bit of data is + // received, even for the case of a document with no data (like about:blank) + if (!m_pluginView) { + committedLoad(loader, 0, 0); + return; + } + + if (m_pluginView->status() == PluginStatusLoadedSuccessfully) + m_pluginView->didFinishLoading(); + m_pluginView = 0; + m_hasSentResponseToPlugin = false; +} + +void WebFrameLoaderClient::updateGlobalHistory(const KURL& url) +{ + WebHistory* history = WebHistory::sharedHistory(); + if (!history) + return; + history->addItem(url, core(m_webFrame)->loader()->documentLoader()->title()); +} + +bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem*) const +{ + return true; +} + +PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) +{ + RefPtr<WebDocumentLoader> loader = WebDocumentLoader::create(request, substituteData); + + COMPtr<WebDataSource> dataSource(AdoptCOM, WebDataSource::createInstance(loader.get())); + + loader->setDataSource(dataSource.get()); + return loader.release(); +} + +void WebFrameLoaderClient::setTitle(const String& title, const KURL& url) +{ + BOOL privateBrowsingEnabled = FALSE; + COMPtr<IWebPreferences> preferences; + if (SUCCEEDED(m_webFrame->webView()->preferences(&preferences))) + preferences->privateBrowsingEnabled(&privateBrowsingEnabled); + if (privateBrowsingEnabled) + return; + + // update title in global history + COMPtr<WebHistory> history = webHistory(); + if (!history) + return; + + COMPtr<IWebHistoryItem> item; + if (FAILED(history->itemForURL(BString(url.string()), &item))) + return; + + COMPtr<IWebHistoryItemPrivate> itemPrivate(Query, item); + if (!itemPrivate) + return; + + itemPrivate->setTitle(BString(title)); +} + +void WebFrameLoaderClient::savePlatformDataToCachedPage(CachedPage* cachedPage) +{ + Frame* coreFrame = core(m_webFrame); + if (!coreFrame) + return; + + ASSERT(coreFrame->loader()->documentLoader() == cachedPage->documentLoader()); + + WebCachedPagePlatformData* webPlatformData = new WebCachedPagePlatformData(static_cast<IWebDataSource*>(getWebDataSource(coreFrame->loader()->documentLoader()))); + cachedPage->setCachedPagePlatformData(webPlatformData); +} + +void WebFrameLoaderClient::transitionToCommittedForNewPage() +{ + Frame* frame = core(m_webFrame); + ASSERT(frame); + + Page* page = frame->page(); + ASSERT(page); + + bool isMainFrame = frame == page->mainFrame(); + + if (isMainFrame && frame->view()) + frame->view()->setParentVisible(false); + + frame->setView(0); + + WebView* webView = m_webFrame->webView(); + + FrameView* frameView; + if (isMainFrame) { + RECT rect; + webView->frameRect(&rect); + frameView = new FrameView(frame, IntRect(rect).size()); + } else + frameView = new FrameView(frame); + + frame->setView(frameView); + frameView->deref(); // FrameViews are created with a ref count of 1. Release this ref since we've assigned it to frame. + + m_webFrame->updateBackground(); + + if (isMainFrame) + frameView->setParentVisible(true); + + if (frame->ownerRenderer()) + frame->ownerRenderer()->setWidget(frameView); + + if (HTMLFrameOwnerElement* owner = frame->ownerElement()) + frame->view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); +} + +bool WebFrameLoaderClient::canCachePage() const +{ + return true; +} + +PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, + const String& referrer, bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/) +{ + RefPtr<Frame> result = createFrame(url, name, ownerElement, referrer); + if (!result) + return 0; + return result.release(); +} + +PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& URL, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer) +{ + Frame* coreFrame = core(m_webFrame); + ASSERT(coreFrame); + + COMPtr<WebFrame> webFrame(AdoptCOM, WebFrame::createInstance()); + + RefPtr<Frame> childFrame = webFrame->init(m_webFrame->webView(), coreFrame->page(), ownerElement); + + coreFrame->tree()->appendChild(childFrame); + childFrame->tree()->setName(name); + childFrame->init(); + + loadURLIntoChild(URL, referrer, webFrame.get()); + + // The frame's onload handler may have removed it from the document. + if (!childFrame->tree()->parent()) + return 0; + + return childFrame.release(); +} + +void WebFrameLoaderClient::loadURLIntoChild(const KURL& originalURL, const String& referrer, WebFrame* childFrame) +{ + ASSERT(childFrame); + ASSERT(core(childFrame)); + + Frame* coreFrame = core(m_webFrame); + ASSERT(coreFrame); + + HistoryItem* parentItem = coreFrame->loader()->currentHistoryItem(); + FrameLoadType loadType = coreFrame->loader()->loadType(); + FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory; + + KURL url = originalURL; + + // If we're moving in the backforward list, we might want to replace the content + // of this child frame with whatever was there at that point. + // Reload will maintain the frame contents, LoadSame will not. + if (parentItem && parentItem->children().size() && + (isBackForwardLoadType(loadType) + || loadType == FrameLoadTypeReload + || loadType == FrameLoadTypeReloadAllowingStaleData)) + { + if (HistoryItem* childItem = parentItem->childItemWithName(core(childFrame)->tree()->name())) { + // Use the original URL to ensure we get all the side-effects, such as + // onLoad handlers, of any redirects that happened. An example of where + // this is needed is Radar 3213556. + url = childItem->originalURL(); + // These behaviors implied by these loadTypes should apply to the child frames + childLoadType = loadType; + + if (isBackForwardLoadType(loadType)) + // For back/forward, remember this item so we can traverse any child items as child frames load + core(childFrame)->loader()->setProvisionalHistoryItem(childItem); + else + // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item + core(childFrame)->loader()->setCurrentHistoryItem(childItem); + } + } + + // FIXME: Handle loading WebArchives here + String frameName = core(childFrame)->tree()->name(); + core(childFrame)->loader()->loadURL(url, referrer, frameName, childLoadType, 0, 0); +} + +Widget* WebFrameLoaderClient::createPlugin(const IntSize& pluginSize, Element* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) +{ + WebView* webView = m_webFrame->webView(); + + COMPtr<IWebUIDelegate> ui; + if (SUCCEEDED(webView->uiDelegate(&ui)) && ui) { + COMPtr<IWebUIDelegatePrivate4> uiPrivate(Query, ui); + + if (uiPrivate) { + // Assemble the view arguments in a property bag. + HashMap<String, String> viewArguments; + for (unsigned i = 0; i < paramNames.size(); i++) + viewArguments.set(paramNames[i], paramValues[i]); + COMPtr<IPropertyBag> viewArgumentsBag(AdoptCOM, COMPropertyBag<String>::adopt(viewArguments)); + + // Now create a new property bag where the view arguments is the only property. + HashMap<String, COMPtr<IUnknown> > arguments; + arguments.set(WebEmbeddedViewAttributesKey, COMPtr<IUnknown>(AdoptCOM, viewArgumentsBag.releaseRef())); + COMPtr<IPropertyBag> argumentsBag(AdoptCOM, COMPropertyBag<COMPtr<IUnknown> >::adopt(arguments)); + + COMPtr<IWebEmbeddedView> view; + HRESULT result = uiPrivate->embeddedViewWithArguments(webView, m_webFrame, argumentsBag.get(), &view); + if (SUCCEEDED(result)) { + HWND parentWindow; + HRESULT hr = webView->viewWindow((OLE_HANDLE*)&parentWindow); + ASSERT(SUCCEEDED(hr)); + + return EmbeddedWidget::create(view.get(), element, parentWindow, pluginSize); + } + } + } + + Frame* frame = core(m_webFrame); + PluginView* pluginView = PluginView::create(frame, pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); + + if (pluginView->status() == PluginStatusLoadedSuccessfully) + return pluginView; + + COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate; + + if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate))) + return pluginView; + + RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + unsigned count = (unsigned)paramNames.size(); + for (unsigned i = 0; i < count; i++) { + if (paramNames[i] == "pluginspage") { + static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInPageURLStringKey); + RetainPtr<CFStringRef> str(AdoptCF, paramValues[i].createCFString()); + CFDictionarySetValue(userInfo.get(), key, str.get()); + break; + } + } + + if (!mimeType.isNull()) { + static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorMIMETypeKey); + + RetainPtr<CFStringRef> str(AdoptCF, mimeType.createCFString()); + CFDictionarySetValue(userInfo.get(), key, str.get()); + } + + String pluginName; + if (pluginView->plugin()) + pluginName = pluginView->plugin()->name(); + if (!pluginName.isNull()) { + static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInNameKey); + RetainPtr<CFStringRef> str(AdoptCF, pluginName.createCFString()); + CFDictionarySetValue(userInfo.get(), key, str.get()); + } + + COMPtr<CFDictionaryPropertyBag> userInfoBag(AdoptCOM, CFDictionaryPropertyBag::createInstance()); + userInfoBag->setDictionary(userInfo.get()); + + int errorCode = 0; + switch (pluginView->status()) { + case PluginStatusCanNotFindPlugin: + errorCode = WebKitErrorCannotFindPlugIn; + break; + case PluginStatusCanNotLoadPlugin: + errorCode = WebKitErrorCannotLoadPlugIn; + break; + default: + ASSERT_NOT_REACHED(); + } + + ResourceError resourceError(String(WebKitErrorDomain), errorCode, url.string(), String()); + COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get())); + + resourceLoadDelegate->plugInFailedWithError(webView, error.get(), getWebDataSource(frame->loader()->documentLoader())); + + return pluginView; +} + +void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) +{ + // Ideally, this function shouldn't be necessary, see <rdar://problem/4852889> + + m_pluginView = static_cast<PluginView*>(pluginWidget); +} + +WebHistory* WebFrameLoaderClient::webHistory() const +{ + if (m_webFrame != m_webFrame->webView()->topLevelFrame()) + return 0; + + return WebHistory::sharedHistory(); +} diff --git a/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h new file mode 100644 index 0000000..b9fd027 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebFrameLoaderClient.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 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. + */ + +#ifndef WebFrameLoaderClient_h +#define WebFrameLoaderClient_h + +#pragma warning(push, 0) +#include <WebCore/FrameLoaderClient.h> +#pragma warning(pop) + +namespace WebCore { + class PluginView; +} + +template <typename T> class COMPtr; +class WebFrame; + +class WebFrameLoaderClient : public WebCore::FrameLoaderClient { +public: + virtual bool hasWebView() const; + + virtual void forceLayout(); + + virtual void assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader*, const WebCore::ResourceRequest&); + + virtual void dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long identifier, WebCore::ResourceRequest&, const WebCore::ResourceResponse& redirectResponse); + virtual void dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::AuthenticationChallenge&); + virtual void dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::AuthenticationChallenge&); + virtual void dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse&); + virtual void dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived); + virtual void dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long identifier); + virtual void dispatchDidFailLoading(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceError&); + + virtual void dispatchDidHandleOnloadEvents(); + virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); + virtual void dispatchDidCancelClientRedirect(); + virtual void dispatchWillPerformClientRedirect(const WebCore::KURL&, double interval, double fireDate); + virtual void dispatchDidChangeLocationWithinPage(); + virtual void dispatchWillClose(); + virtual void dispatchDidReceiveIcon(); + virtual void dispatchDidStartProvisionalLoad(); + virtual void dispatchDidReceiveTitle(const WebCore::String&); + virtual void dispatchDidCommitLoad(); + virtual void dispatchDidFinishDocumentLoad(); + virtual void dispatchDidFinishLoad(); + virtual void dispatchDidFirstLayout(); + + virtual WebCore::Frame* dispatchCreatePage(); + virtual void dispatchShow(); + + virtual void dispatchDidLoadMainResource(WebCore::DocumentLoader*); + virtual void setMainDocumentError(WebCore::DocumentLoader*, const WebCore::ResourceError&); + + virtual void postProgressStartedNotification(); + virtual void postProgressEstimateChangedNotification(); + virtual void postProgressFinishedNotification(); + + virtual void committedLoad(WebCore::DocumentLoader*, const char*, int); + virtual void finishedLoading(WebCore::DocumentLoader*); + + virtual void updateGlobalHistory(const WebCore::KURL&); + virtual bool shouldGoToHistoryItem(WebCore::HistoryItem*) const; + + virtual PassRefPtr<WebCore::DocumentLoader> createDocumentLoader(const WebCore::ResourceRequest&, const WebCore::SubstituteData&); + virtual void setTitle(const WebCore::String& title, const WebCore::KURL&); + + virtual void savePlatformDataToCachedPage(WebCore::CachedPage*); + virtual void transitionToCommittedForNewPage(); + + virtual bool canCachePage() const; + + virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement* ownerElement, + const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); + virtual WebCore::Widget* createPlugin(const WebCore::IntSize&, WebCore::Element*, const WebCore::KURL&, const Vector<WebCore::String>&, const Vector<WebCore::String>&, const WebCore::String&, bool loadManually); + virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget); + +protected: + WebFrameLoaderClient(WebFrame*); + ~WebFrameLoaderClient(); + +private: + PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL&, const WebCore::String& name, WebCore::HTMLFrameOwnerElement*, const WebCore::String& referrer); + void loadURLIntoChild(const WebCore::KURL&, const WebCore::String& referrer, WebFrame* childFrame); + void receivedData(const char*, int, const WebCore::String&); + WebHistory* webHistory() const; + + WebFrame* m_webFrame; + + // Points to the plugin view that data should be redirected to. + WebCore::PluginView* m_pluginView; + + bool m_hasSentResponseToPlugin; +}; + +#endif // WebFrameLoaderClient_h diff --git a/WebKit/win/WebCoreSupport/WebInspectorClient.cpp b/WebKit/win/WebCoreSupport/WebInspectorClient.cpp new file mode 100644 index 0000000..bfbf858 --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebInspectorClient.cpp @@ -0,0 +1,426 @@ +/* + * Copyright (C) 2006, 2007 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 "WebInspectorClient.h" + +#include "WebInspectorDelegate.h" +#include "WebKit.h" +#include "WebMutableURLRequest.h" +#include "WebNodeHighlight.h" +#include "WebView.h" + +#pragma warning(push, 0) +#include <WebCore/BString.h> +#include <WebCore/Element.h> +#include <WebCore/FloatRect.h> +#include <WebCore/FrameView.h> +#include <WebCore/InspectorController.h> +#include <WebCore/Page.h> +#include <WebCore/RenderObject.h> +#include <WebCore/WindowMessageBroadcaster.h> +#pragma warning(pop) + +#include <tchar.h> +#include <wtf/RetainPtr.h> + +using namespace WebCore; + +static LPCTSTR kWebInspectorWindowClassName = TEXT("WebInspectorWindowClass"); +static ATOM registerWindowClass(); +static LPCTSTR kWebInspectorPointerProp = TEXT("WebInspectorPointer"); + +static const unsigned defaultAttachedHeight = 300; + +static const IntRect& defaultWindowRect() +{ + static IntRect rect(60, 200, 750, 650); + return rect; +} + +static CFBundleRef getWebKitBundle() +{ + return CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebKit")); +} + +WebInspectorClient::WebInspectorClient(WebView* webView) + : m_inspectedWebView(webView) + , m_hwnd(0) + , m_webViewHwnd(0) + , m_attached(false) +{ + ASSERT(m_inspectedWebView); + + m_inspectedWebView->viewWindow((OLE_HANDLE*)&m_inspectedWebViewHwnd); + + // FIXME: Implement window size/position save/restore +#if 0 + [self setWindowFrameAutosaveName:@"Web Inspector"]; +#endif +} + +WebInspectorClient::~WebInspectorClient() +{ + if (m_hwnd) + ::DestroyWindow(m_hwnd); +} + +void WebInspectorClient::inspectorDestroyed() +{ + delete this; +} + +Page* WebInspectorClient::createPage() +{ + if (m_webView) + return core(m_webView.get()); + + ASSERT(!m_hwnd); + + registerWindowClass(); + + m_hwnd = ::CreateWindowEx(0, kWebInspectorWindowClassName, 0, WS_OVERLAPPEDWINDOW, + defaultWindowRect().x(), defaultWindowRect().y(), defaultWindowRect().width(), defaultWindowRect().height(), + 0, 0, 0, 0); + + if (!m_hwnd) + return 0; + + ::SetProp(m_hwnd, kWebInspectorPointerProp, reinterpret_cast<HANDLE>(this)); + + m_webView.adoptRef(WebView::createInstance()); + + if (FAILED(m_webView->setHostWindow((OLE_HANDLE)(ULONG64)m_hwnd))) + return 0; + + RECT rect; + GetClientRect(m_hwnd, &rect); + if (FAILED(m_webView->initWithFrame(rect, 0, 0))) + return 0; + + COMPtr<WebInspectorDelegate> delegate(AdoptCOM, WebInspectorDelegate::createInstance()); + if (FAILED(m_webView->setUIDelegate(delegate.get()))) + return 0; + + // Keep preferences separate from the rest of the client, making sure we are using expected preference values. + // One reason this is good is that it keeps the inspector out of history via "private browsing". + // FIXME: It's crazy that we have to do this song and dance to end up with + // a private WebPreferences object, even within WebKit. We should make this + // process simpler, and consider whether we can make it simpler for WebKit + // clients as well. + COMPtr<WebPreferences> tempPreferences(AdoptCOM, WebPreferences::createInstance()); + COMPtr<IWebPreferences> iPreferences; + if (FAILED(tempPreferences->initWithIdentifier(BString(L"WebInspectorPreferences"), &iPreferences))) + return 0; + COMPtr<WebPreferences> preferences(Query, iPreferences); + if (!preferences) + return 0; + if (FAILED(preferences->setAutosaves(FALSE))) + return 0; + if (FAILED(preferences->setPrivateBrowsingEnabled(TRUE))) + return 0; + if (FAILED(preferences->setLoadsImagesAutomatically(TRUE))) + return 0; + if (FAILED(preferences->setAuthorAndUserStylesEnabled(TRUE))) + return 0; + if (FAILED(preferences->setAllowsAnimatedImages(TRUE))) + return 0; + if (FAILED(preferences->setLoadsImagesAutomatically(TRUE))) + return 0; + if (FAILED(preferences->setPlugInsEnabled(FALSE))) + return 0; + if (FAILED(preferences->setJavaEnabled(FALSE))) + return 0; + if (FAILED(preferences->setUserStyleSheetEnabled(FALSE))) + return 0; + if (FAILED(preferences->setTabsToLinks(FALSE))) + return 0; + if (FAILED(preferences->setMinimumFontSize(0))) + return 0; + if (FAILED(preferences->setMinimumLogicalFontSize(9))) + return 0; + + if (FAILED(m_webView->setPreferences(preferences.get()))) + return 0; + + m_webView->setProhibitsMainFrameScrolling(TRUE); + + if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&m_webViewHwnd)))) + return 0; + + COMPtr<WebMutableURLRequest> request; + request.adoptRef(WebMutableURLRequest::createInstance()); + + RetainPtr<CFURLRef> htmlURLRef(AdoptCF, CFBundleCopyResourceURL(getWebKitBundle(), CFSTR("inspector"), CFSTR("html"), CFSTR("inspector"))); + if (!htmlURLRef) + return 0; + + CFStringRef urlStringRef = ::CFURLGetString(htmlURLRef.get()); + if (FAILED(request->initWithURL(BString(urlStringRef), WebURLRequestUseProtocolCachePolicy, 60))) + return 0; + + if (FAILED(m_webView->topLevelFrame()->loadRequest(request.get()))) + return 0; + + return core(m_webView.get()); +} + + +String WebInspectorClient::localizedStringsURL() +{ + RetainPtr<CFURLRef> url(AdoptCF, CFBundleCopyResourceURL(getWebKitBundle(), CFSTR("localizedStrings"), CFSTR("js"), 0)); + if (!url) + return String(); + + return CFURLGetString(url.get()); +} + +void WebInspectorClient::showWindow() +{ + if (!m_hwnd) + return; + + updateWindowTitle(); + ::SetWindowPos(m_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + m_inspectedWebView->page()->inspectorController()->setWindowVisible(true); +} + +void WebInspectorClient::closeWindow() +{ + if (!m_webView) + return; + + ::ShowWindow(m_hwnd, SW_HIDE); + m_inspectedWebView->page()->inspectorController()->setWindowVisible(false); +} + +bool WebInspectorClient::windowVisible() +{ + return !!::IsWindowVisible(m_hwnd); +} + +void WebInspectorClient::attachWindow() +{ + ASSERT(m_hwnd); + ASSERT(m_webView); + ASSERT(m_inspectedWebViewHwnd); + + if (m_attached) + return; + + WindowMessageBroadcaster::addListener(m_inspectedWebViewHwnd, this); + + HWND hostWindow; + if (FAILED(m_inspectedWebView->hostWindow((OLE_HANDLE*)&hostWindow))) + return; + + m_webView->setHostWindow((OLE_HANDLE)(ULONG64)hostWindow); + ::ShowWindow(m_hwnd, SW_HIDE); + m_attached = true; + + ::SendMessage(hostWindow, WM_SIZE, 0, 0); + + if (m_highlight && m_highlight->isShowing()) + m_highlight->update(); +} + +void WebInspectorClient::detachWindow() +{ + if (!m_attached) + return; + + WindowMessageBroadcaster::removeListener(m_inspectedWebViewHwnd, this); + + m_attached = false; + + m_webView->setHostWindow((OLE_HANDLE)(ULONG64)m_hwnd); + ::ShowWindow(m_hwnd, SW_SHOW); + ::SendMessage(m_hwnd, WM_SIZE, 0, 0); + + HWND hostWindow; + if (SUCCEEDED(m_inspectedWebView->hostWindow((OLE_HANDLE*)&hostWindow))) + ::SendMessage(hostWindow, WM_SIZE, 0, 0); + + if (m_highlight && m_highlight->isShowing()) + m_highlight->update(); +} + +void WebInspectorClient::setAttachedWindowHeight(unsigned height) +{ + // FIXME: implement this. +} + +void WebInspectorClient::highlight(Node*) +{ + bool creatingHighlight = !m_highlight; + + if (creatingHighlight) + m_highlight.set(new WebNodeHighlight(m_inspectedWebView)); + + if (m_highlight->isShowing()) + m_highlight->update(); + else + m_highlight->setShowsWhileWebViewIsVisible(true); + + if (creatingHighlight && IsWindowVisible(m_hwnd)) + m_highlight->placeBehindWindow(m_hwnd); +} + +void WebInspectorClient::hideHighlight() +{ + if (m_highlight) + m_highlight->setShowsWhileWebViewIsVisible(false); +} + +void WebInspectorClient::inspectedURLChanged(const String& newURL) +{ + m_inspectedURL = newURL; + updateWindowTitle(); +} + +void WebInspectorClient::updateWindowTitle() +{ + // FIXME: The series of appends should be replaced with a call to String::format() + // when it can be figured out how to get the unicode em-dash to show up. + String title = "Web Inspector "; + title.append((UChar)0x2014); // em-dash + title.append(' '); + title.append(m_inspectedURL); + ::SetWindowText(m_hwnd, title.charactersWithNullTermination()); +} + +LRESULT WebInspectorClient::onGetMinMaxInfo(WPARAM, LPARAM lParam) +{ + MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam); + POINT size = {400, 400}; + info->ptMinTrackSize = size; + + return 0; +} + +LRESULT WebInspectorClient::onSize(WPARAM, LPARAM) +{ + RECT rect; + ::GetClientRect(m_hwnd, &rect); + + ::SetWindowPos(m_webViewHwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); + + return 0; +} + +LRESULT WebInspectorClient::onClose(WPARAM, LPARAM) +{ + ::ShowWindow(m_hwnd, SW_HIDE); + m_inspectedWebView->page()->inspectorController()->setWindowVisible(false); + + hideHighlight(); + + return 0; +} + +LRESULT WebInspectorClient::onSetFocus() +{ + SetFocus(m_webViewHwnd); + return 0; +} + +void WebInspectorClient::onWebViewWindowPosChanging(WPARAM, LPARAM lParam) +{ + ASSERT(m_attached); + + WINDOWPOS* windowPos = reinterpret_cast<WINDOWPOS*>(lParam); + ASSERT_ARG(lParam, windowPos); + + if (windowPos->flags & SWP_NOSIZE) + return; + + windowPos->cy -= defaultAttachedHeight; + + ::SetWindowPos(m_webViewHwnd, 0, windowPos->x, windowPos->y + windowPos->cy, windowPos->cx, defaultAttachedHeight, SWP_NOZORDER); +} + +static LRESULT CALLBACK WebInspectorWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WebInspectorClient* client = reinterpret_cast<WebInspectorClient*>(::GetProp(hwnd, kWebInspectorPointerProp)); + if (!client) + return ::DefWindowProc(hwnd, msg, wParam, lParam); + + switch (msg) { + case WM_GETMINMAXINFO: + return client->onGetMinMaxInfo(wParam, lParam); + case WM_SIZE: + return client->onSize(wParam, lParam); + case WM_CLOSE: + return client->onClose(wParam, lParam); + case WM_SETFOCUS: + return client->onSetFocus(); + default: + break; + } + + return ::DefWindowProc(hwnd, msg, wParam, lParam); +} + +void WebInspectorClient::windowReceivedMessage(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_WINDOWPOSCHANGING: + onWebViewWindowPosChanging(wParam, lParam); + break; + default: + break; + } +} + +static ATOM registerWindowClass() +{ + static bool haveRegisteredWindowClass = false; + + if (haveRegisteredWindowClass) + return true; + + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = 0; + wcex.lpfnWndProc = WebInspectorWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = 0; + wcex.hIcon = 0; + wcex.hCursor = LoadCursor(0, IDC_ARROW); + wcex.hbrBackground = 0; + wcex.lpszMenuName = 0; + wcex.lpszClassName = kWebInspectorWindowClassName; + wcex.hIconSm = 0; + + haveRegisteredWindowClass = true; + + return ::RegisterClassEx(&wcex); +} diff --git a/WebKit/win/WebCoreSupport/WebInspectorClient.h b/WebKit/win/WebCoreSupport/WebInspectorClient.h new file mode 100644 index 0000000..a28507a --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebInspectorClient.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2006, 2007 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. + */ + +#ifndef WebInspectorClient_h +#define WebInspectorClient_h + +#include <WebCore/COMPtr.h> +#include <WebCore/InspectorClient.h> +#include <WebCore/PlatformString.h> +#include <WebCore/WindowMessageListener.h> +#include <wtf/OwnPtr.h> +#include <windows.h> + +class WebNodeHighlight; +class WebView; + +class WebInspectorClient : public WebCore::InspectorClient, WebCore::WindowMessageListener { +public: + WebInspectorClient(WebView*); + + // InspectorClient + virtual void inspectorDestroyed(); + + virtual WebCore::Page* createPage(); + + virtual WebCore::String localizedStringsURL(); + + virtual void showWindow(); + virtual void closeWindow(); + virtual bool windowVisible(); + + virtual void attachWindow(); + virtual void detachWindow(); + + virtual void setAttachedWindowHeight(unsigned height); + + virtual void highlight(WebCore::Node*); + virtual void hideHighlight(); + + virtual void inspectedURLChanged(const WebCore::String& newURL); + + virtual void populateSetting(const WebCore::String& key, WebCore::InspectorController::Setting&); + virtual void storeSetting(const WebCore::String& key, const WebCore::InspectorController::Setting&); + virtual void removeSetting(const WebCore::String& key); + +private: + ~WebInspectorClient(); + + void updateWindowTitle(); + + LRESULT onGetMinMaxInfo(WPARAM, LPARAM); + LRESULT onSize(WPARAM, LPARAM); + LRESULT onClose(WPARAM, LPARAM); + LRESULT onSetFocus(); + + virtual void windowReceivedMessage(HWND, UINT message, WPARAM, LPARAM); + + void onWebViewWindowPosChanging(WPARAM, LPARAM); + + WebView* m_inspectedWebView; + HWND m_inspectedWebViewHwnd; + HWND m_hwnd; + COMPtr<WebView> m_webView; + HWND m_webViewHwnd; + + bool m_attached; + + OwnPtr<WebNodeHighlight> m_highlight; + + WebCore::String m_inspectedURL; + + static friend LRESULT CALLBACK WebInspectorWndProc(HWND, UINT, WPARAM, LPARAM); +}; + +#endif // !defined(WebInspectorClient_h) diff --git a/WebKit/win/WebCoreSupport/WebInspectorDelegate.cpp b/WebKit/win/WebCoreSupport/WebInspectorDelegate.cpp new file mode 100644 index 0000000..3ed8c9d --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebInspectorDelegate.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> + * + * 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 "WebInspectorDelegate.h" + +WebInspectorDelegate::WebInspectorDelegate() + :m_refCount(0) +{ +} + +WebInspectorDelegate* WebInspectorDelegate::createInstance() +{ + WebInspectorDelegate* instance = new WebInspectorDelegate; + instance->AddRef(); + return instance; +} + +ULONG STDMETHODCALLTYPE WebInspectorDelegate::AddRef() +{ + return ++m_refCount; +} + +ULONG STDMETHODCALLTYPE WebInspectorDelegate::Release() +{ + ULONG newRef = --m_refCount; + if (!newRef) + delete(this); + + return newRef; +} + +HRESULT STDMETHODCALLTYPE WebInspectorDelegate::dragDestinationActionMaskForDraggingInfo( + /* [in] */ IWebView*, + /* [in] */ IDataObject*, + /* [retval][out] */ WebDragDestinationAction* action) +{ + *action = WebDragDestinationActionNone; + + return S_OK; +} diff --git a/WebKit/win/WebCoreSupport/WebInspectorDelegate.h b/WebKit/win/WebCoreSupport/WebInspectorDelegate.h new file mode 100644 index 0000000..a14c5fc --- /dev/null +++ b/WebKit/win/WebCoreSupport/WebInspectorDelegate.h @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> + * + * 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. + */ + +#ifndef WebInspectorDelegate_h +#define WebInspectorDelegate_h + +struct IDataObject; +struct IPropertyBag; +struct IWebView; +struct IWebFrame; +struct IWebError; +struct IWebURLRequest; +struct IWebOpenPanelResultListener; + +class WebInspectorDelegate : public IWebUIDelegate { +public: + static WebInspectorDelegate* createInstance(); + + // IUnknown + virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release(); + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**) { return E_NOTIMPL; }; + + // IWebUIDelegate + virtual HRESULT STDMETHODCALLTYPE dragDestinationActionMaskForDraggingInfo( + /* [in] */ IWebView*, + /* [in] */ IDataObject*, + /* [retval][out] */ WebDragDestinationAction* action); + + // Not implemented + virtual HRESULT STDMETHODCALLTYPE createWebViewWithRequest( + /* [in] */ IWebView*, + /* [in] */ IWebURLRequest*, + /* [retval][out] */ IWebView**) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewShow( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewClose( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewFocus( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewUnfocus( + /* [in] */ IWebView*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewFirstResponder( + /* [in] */ IWebView*, + /* [retval][out] */ OLE_HANDLE*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE makeFirstResponder( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setStatusText( + /* [in] */ IWebView*, + /* [in] */ BSTR) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewStatusText( + /* [in] */ IWebView*, + /* [retval][out] */ BSTR*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewAreToolbarsVisible( + /* [in] */ IWebView*, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setToolbarsVisible( + /* [in] */ IWebView*, + /* [in] */ BOOL) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewIsStatusBarVisible( + /* [in] */ IWebView*, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setStatusBarVisible( + /* [in] */ IWebView*, + /* [in] */ BOOL) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewIsResizable( + /* [in] */ IWebView*, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setResizable( + /* [in] */ IWebView*, + /* [in] */ BOOL) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setFrame( + /* [in] */ IWebView*, + /* [in] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewFrame( + /* [in] */ IWebView*, + /* [retval][out] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setContentRect( + /* [in] */ IWebView*, + /* [in] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE webViewContentRect( + /* [in] */ IWebView*, + /* [retval][out] */ RECT*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptAlertPanelWithMessage( + /* [in] */ IWebView*, + /* [in] */ BSTR) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptConfirmPanelWithMessage( + /* [in] */ IWebView*, + /* [in] */ BSTR, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runJavaScriptTextInputPanelWithPrompt( + /* [in] */ IWebView*, + /* [in] */ BSTR /*message*/, + /* [in] */ BSTR /*defaultText*/, + /* [retval][out] */ BSTR*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runBeforeUnloadConfirmPanelWithMessage( + /* [in] */ IWebView*, + /* [in] */ BSTR /*message*/, + /* [in] */ IWebFrame* /*initiatedByFrame*/, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE runOpenPanelForFileButtonWithResultListener( + /* [in] */ IWebView*, + /* [in] */ IWebOpenPanelResultListener*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE mouseDidMoveOverElement( + /* [in] */ IWebView*, + /* [in] */ IPropertyBag*, + /* [in] */ UINT /*modifierFlags*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE contextMenuItemsForElement( + /* [in] */ IWebView*, + /* [in] */ IPropertyBag*, + /* [in] */ OLE_HANDLE, + /* [retval][out] */ OLE_HANDLE*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE validateUserInterfaceItem( + /* [in] */ IWebView*, + /* [in] */ UINT, + /* [in] */ BOOL, + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE shouldPerformAction( + /* [in] */ IWebView*, + /* [in] */ UINT /*itemCommandID*/, + /* [in] */ UINT /*sender*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformDragDestinationAction( + /* [in] */ IWebView*, + /* [in] */ WebDragDestinationAction, + /* [in] */ IDataObject*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE dragSourceActionMaskForPoint( + /* [in] */ IWebView*, + /* [in] */ LPPOINT, + /* [retval][out] */ WebDragSourceAction*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE willPerformDragSourceAction( + /* [in] */ IWebView*, + /* [in] */ WebDragSourceAction, + /* [in] */ LPPOINT, + /* [in] */ IDataObject*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE contextMenuItemSelected( + /* [in] */ IWebView*, + /* [in] */ void* /*item*/, + /* [in] */ IPropertyBag*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE hasCustomMenuImplementation( + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE trackCustomPopupMenu( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE, + /* [in] */ LPPOINT) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE measureCustomMenuItem( + /* [in] */ IWebView*, + /* [in] */ void* /*measureItem*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE drawCustomMenuItem( + /* [in] */ IWebView*, + /* [in] */ void* /*drawItem*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE addCustomMenuDrawingData( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE cleanUpCustomMenuDrawingData( + /* [in] */ IWebView*, + /* [in] */ OLE_HANDLE) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE canTakeFocus( + /* [in] */ IWebView*, + /* [in] */ BOOL /*forward*/, + /* [out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE takeFocus( + /* [in] */ IWebView*, + /* [in] */ BOOL /*forward*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE registerUndoWithTarget( + /* [in] */ IWebUndoTarget*, + /* [in] */ BSTR /*actionName*/, + /* [in] */ IUnknown* /*actionArg*/) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE removeAllActionsWithTarget( + /* [in] */ IWebUndoTarget*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE setActionTitle( + /* [in] */ BSTR) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE undo() { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE redo() { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE canUndo( + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + + virtual HRESULT STDMETHODCALLTYPE canRedo( + /* [retval][out] */ BOOL*) { return E_NOTIMPL; } + +private: + WebInspectorDelegate(); + + ULONG m_refCount; +}; + +#endif // WebInspectorDelegate_h |