From 498e5e4ad10920a9cfae6fdb7ffb19a6ed936ba7 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 10 Feb 2009 15:44:00 -0800 Subject: auto import from //branches/cupcake/...@130745 --- WebKit/Android.mk | 13 +- WebKit/android/ChromeClientAndroid.cpp | 257 ----- WebKit/android/ChromeClientAndroid.h | 120 --- WebKit/android/DragClientAndroid.cpp | 45 - WebKit/android/DragClientAndroid.h | 51 - WebKit/android/EditorClientAndroid.cpp | 241 ----- WebKit/android/EditorClientAndroid.h | 113 -- WebKit/android/FrameLoaderClientAndroid.cpp | 1105 -------------------- WebKit/android/FrameLoaderClientAndroid.h | 242 ----- WebKit/android/InspectorClientAndroid.h | 64 -- WebKit/android/RenderSkinCombo.h | 4 +- WebKit/android/RenderSkinRadio.cpp | 77 +- WebKit/android/RenderSkinRadio.h | 34 +- .../android/WebCoreSupport/ChromeClientAndroid.cpp | 257 +++++ .../android/WebCoreSupport/ChromeClientAndroid.h | 120 +++ .../WebCoreSupport/ContextMenuClientAndroid.cpp | 46 + .../WebCoreSupport/ContextMenuClientAndroid.h | 50 + .../android/WebCoreSupport/DragClientAndroid.cpp | 45 + WebKit/android/WebCoreSupport/DragClientAndroid.h | 51 + .../android/WebCoreSupport/EditorClientAndroid.cpp | 241 +++++ .../android/WebCoreSupport/EditorClientAndroid.h | 113 ++ .../WebCoreSupport/FrameLoaderClientAndroid.cpp | 1105 ++++++++++++++++++++ .../WebCoreSupport/FrameLoaderClientAndroid.h | 242 +++++ .../WebCoreSupport/InspectorClientAndroid.h | 64 ++ WebKit/android/jni/PictureSet.cpp | 98 +- WebKit/android/jni/PictureSet.h | 6 +- WebKit/android/jni/WebCoreFrameBridge.cpp | 3 + WebKit/android/jni/WebHistory.cpp | 5 +- WebKit/android/jni/WebViewCore.cpp | 140 +-- WebKit/android/jni/WebViewCore.h | 9 +- WebKit/android/nav/CacheBuilder.cpp | 45 +- WebKit/android/nav/CacheBuilder.h | 5 + WebKit/android/nav/CachedDebug.h | 11 - WebKit/android/nav/CachedFrame.cpp | 12 +- WebKit/android/nav/CachedHistory.cpp | 10 +- WebKit/android/nav/CachedHistory.h | 2 - WebKit/android/nav/CachedNode.cpp | 6 + WebKit/android/nav/CachedNode.h | 4 + WebKit/android/nav/CachedRoot.cpp | 32 +- WebKit/android/nav/CachedRoot.h | 4 +- WebKit/android/nav/WebView.cpp | 53 +- WebKit/android/plugins/ANPCanvasInterface.cpp | 28 + WebKit/android/plugins/ANPMatrixInterface.cpp | 168 +++ WebKit/android/plugins/ANPPaintInterface.cpp | 14 + WebKit/android/plugins/SkANP.cpp | 8 + WebKit/android/plugins/SkANP.h | 5 + WebKit/android/plugins/android_npapi.h | 103 +- WebKit/android/plugins/sample/pluginGraphics.cpp | 5 +- 48 files changed, 2971 insertions(+), 2505 deletions(-) delete mode 100644 WebKit/android/ChromeClientAndroid.cpp delete mode 100644 WebKit/android/ChromeClientAndroid.h delete mode 100644 WebKit/android/DragClientAndroid.cpp delete mode 100644 WebKit/android/DragClientAndroid.h delete mode 100644 WebKit/android/EditorClientAndroid.cpp delete mode 100644 WebKit/android/EditorClientAndroid.h delete mode 100644 WebKit/android/FrameLoaderClientAndroid.cpp delete mode 100644 WebKit/android/FrameLoaderClientAndroid.h delete mode 100644 WebKit/android/InspectorClientAndroid.h create mode 100644 WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/ChromeClientAndroid.h create mode 100644 WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h create mode 100644 WebKit/android/WebCoreSupport/DragClientAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/DragClientAndroid.h create mode 100644 WebKit/android/WebCoreSupport/EditorClientAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/EditorClientAndroid.h create mode 100644 WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h create mode 100644 WebKit/android/WebCoreSupport/InspectorClientAndroid.h create mode 100644 WebKit/android/plugins/ANPMatrixInterface.cpp (limited to 'WebKit') diff --git a/WebKit/Android.mk b/WebKit/Android.mk index e5fa4df..d8e355c 100644 --- a/WebKit/Android.mk +++ b/WebKit/Android.mk @@ -16,15 +16,17 @@ ## LOCAL_SRC_FILES := \ - android/ChromeClientAndroid.cpp \ - android/DragClientAndroid.cpp \ - android/EditorClientAndroid.cpp \ - android/FrameLoaderClientAndroid.cpp \ + android/WebCoreSupport/ChromeClientAndroid.cpp \ + android/WebCoreSupport/ContextMenuClientAndroid.cpp \ + android/WebCoreSupport/DragClientAndroid.cpp \ + android/WebCoreSupport/EditorClientAndroid.cpp \ + android/WebCoreSupport/FrameLoaderClientAndroid.cpp \ + \ android/RenderSkinAndroid.cpp \ android/RenderSkinButton.cpp \ android/RenderSkinCombo.cpp \ android/RenderSkinRadio.cpp \ - android/TimeCounter.cpp \ + android/TimeCounter.cpp \ android/sort.cpp \ \ android/jni/JavaBridge.cpp \ @@ -50,6 +52,7 @@ LOCAL_SRC_FILES := \ \ android/plugins/ANPCanvasInterface.cpp \ android/plugins/ANPLogInterface.cpp \ + android/plugins/ANPMatrixInterface.cpp \ android/plugins/ANPPaintInterface.cpp \ android/plugins/ANPSoundInterface.cpp \ android/plugins/ANPTypefaceInterface.cpp \ diff --git a/WebKit/android/ChromeClientAndroid.cpp b/WebKit/android/ChromeClientAndroid.cpp deleted file mode 100644 index abc6a32..0000000 --- a/WebKit/android/ChromeClientAndroid.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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. - */ - -#define LOG_TAG "WebCore" - -#include "config.h" - -#include "ChromeClientAndroid.h" -#include "CString.h" -#include "Document.h" -#include "PlatformString.h" -#include "FloatRect.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameView.h" -#include "Page.h" -#include "Screen.h" -#include "ScriptController.h" -#include "WebCoreFrameBridge.h" -#include "WebCoreViewBridge.h" -#include "WebViewCore.h" -#include "WindowFeatures.h" -#include "Settings.h" - -namespace android { - -void ChromeClientAndroid::setWebFrame(android::WebFrame* webframe) -{ - Release(m_webFrame); - m_webFrame = webframe; - Retain(m_webFrame); -} - -void ChromeClientAndroid::chromeDestroyed() -{ - Release(m_webFrame); - delete this; -} - -void ChromeClientAndroid::setWindowRect(const FloatRect&) { notImplemented(); } - -FloatRect ChromeClientAndroid::windowRect() { - ASSERT(m_webFrame); - if (!m_webFrame) - return FloatRect(); - FrameView* frameView = m_webFrame->page()->mainFrame()->view(); - if (!frameView) - return FloatRect(); - const WebCoreViewBridge* bridge = frameView->platformWidget(); - const IntRect& rect = bridge->getWindowBounds(); - FloatRect fRect(rect.x(), rect.y(), rect.width(), rect.height()); - return fRect; -} - -FloatRect ChromeClientAndroid::pageRect() { notImplemented(); return FloatRect(); } - -float ChromeClientAndroid::scaleFactor() -{ - // only seems to be used for dashboard regions, so just return 1 - return 1; -} - -void ChromeClientAndroid::focus() { - ASSERT(m_webFrame); - // Ask the application to focus this WebView. - m_webFrame->requestFocus(); -} -void ChromeClientAndroid::unfocus() { notImplemented(); } - -bool ChromeClientAndroid::canTakeFocus(FocusDirection) { notImplemented(); return false; } -void ChromeClientAndroid::takeFocus(FocusDirection) { notImplemented(); } - -Page* ChromeClientAndroid::createWindow(Frame* frame, const FrameLoadRequest&, - const WindowFeatures& features) -{ - ASSERT(frame); -#ifdef ANDROID_MULTIPLE_WINDOWS - if (frame->settings() && !(frame->settings()->supportMultipleWindows())) - // If the client doesn't support multiple windows, just return the current page - return frame->page(); -#endif - - WTF::PassRefPtr screen = WebCore::Screen::create(frame); - bool dialog = features.dialog || !features.resizable - || (features.heightSet && features.height < screen.get()->height() - && features.widthSet && features.width < screen.get()->width()) - || (!features.menuBarVisible && !features.statusBarVisible - && !features.toolBarVisible && !features.locationBarVisible - && !features.scrollbarsVisible); - // fullscreen definitely means no dialog - if (features.fullscreen) - dialog = false; - WebCore::Frame* newFrame = m_webFrame->createWindow(dialog, - frame->script()->processingUserGesture()); - if (newFrame) { - WebCore::Page* page = newFrame->page(); - page->setGroupName(frame->page()->groupName()); - return page; - } - return NULL; -} - -void ChromeClientAndroid::show() { notImplemented(); } - -bool ChromeClientAndroid::canRunModal() { notImplemented(); return false; } -void ChromeClientAndroid::runModal() { notImplemented(); } - -void ChromeClientAndroid::setToolbarsVisible(bool) { notImplemented(); } -bool ChromeClientAndroid::toolbarsVisible() { notImplemented(); return false; } - -void ChromeClientAndroid::setStatusbarVisible(bool) { notImplemented(); } -bool ChromeClientAndroid::statusbarVisible() { notImplemented(); return false; } - -void ChromeClientAndroid::setScrollbarsVisible(bool) { notImplemented(); } -bool ChromeClientAndroid::scrollbarsVisible() { notImplemented(); return false; } - -void ChromeClientAndroid::setMenubarVisible(bool) { notImplemented(); } -bool ChromeClientAndroid::menubarVisible() { notImplemented(); return false; } - -void ChromeClientAndroid::setResizable(bool) { notImplemented(); } - -// This function is called by the JavaScript bindings to print usually an error to -// a message console. -void ChromeClientAndroid::addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID) { - notImplemented(); - LOGD("Console: %s line: %d source: %s\n", message.latin1().data(), lineNumber, sourceID.latin1().data()); -} - -bool ChromeClientAndroid::canRunBeforeUnloadConfirmPanel() { return true; } -bool ChromeClientAndroid::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) { - String url = frame->document()->documentURI(); - return android::WebViewCore::getWebViewCore(frame->view())->jsUnload(url, message); -} - -void ChromeClientAndroid::closeWindowSoon() -{ - ASSERT(m_webFrame); - Page* page = m_webFrame->page(); - Frame* mainFrame = page->mainFrame(); - // This will prevent javascript cross-scripting during unload - page->setGroupName(String()); - // Stop loading but do not send the unload event - mainFrame->loader()->stopLoading(false); - // Cancel all pending loaders - mainFrame->loader()->stopAllLoaders(); - // Remove all event listeners so that no javascript can execute as a result - // of mouse/keyboard events. - mainFrame->document()->removeAllEventListenersFromAllNodes(); - // Close the window. - m_webFrame->closeWindow(android::WebViewCore::getWebViewCore(mainFrame->view())); -} - -void ChromeClientAndroid::runJavaScriptAlert(Frame* frame, const String& message) -{ - String url = frame->document()->documentURI(); - - android::WebViewCore::getWebViewCore(frame->view())->jsAlert(url, message); -} - -bool ChromeClientAndroid::runJavaScriptConfirm(Frame* frame, const String& message) -{ - String url = frame->document()->documentURI(); - - return android::WebViewCore::getWebViewCore(frame->view())->jsConfirm(url, message); -} - -/* This function is called for the javascript method Window.prompt(). A dialog should be shown on - * the screen with an input put box. First param is the text, the second is the default value for - * the input box, third is return param. If the function returns true, the value set in the third parameter - * is provided to javascript, else null is returned to the script. - */ -bool ChromeClientAndroid::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result) -{ - String url = frame->document()->documentURI(); - return android::WebViewCore::getWebViewCore(frame->view())->jsPrompt(url, message, defaultValue, result); -} -void ChromeClientAndroid::setStatusbarText(const String&) { notImplemented(); } - -// This is called by the JavaScript interpreter when a script has been running for a long -// time. A dialog should be shown to the user asking them if they would like to cancel the -// Javascript. If true is returned, the script is cancelled. -// To make a device more responsive, we default to return true to disallow long running script. -// This implies that some of scripts will not be completed. -bool ChromeClientAndroid::shouldInterruptJavaScript() { return true; } - -bool ChromeClientAndroid::tabsToLinks() const { return false; } - -IntRect ChromeClientAndroid::windowResizerRect() const { return IntRect(0, 0, 0, 0); } - -// new to change 38068 (Nov 6, 2008) -void ChromeClientAndroid::repaint(const IntRect& rect, bool contentChanged, - bool immediate, bool repaintContentOnly) { - notImplemented(); -// was in ScrollViewAndroid::update() : needs to be something like: -// android::WebViewCore::getWebViewCore(this)->contentInvalidate(rect); -} - -// new to change 38068 (Nov 6, 2008) -void ChromeClientAndroid::scroll(const IntSize& scrollDelta, - const IntRect& rectToScroll, const IntRect& clipRect) { - notImplemented(); -} - -// new to change 38068 (Nov 6, 2008) -IntPoint ChromeClientAndroid::screenToWindow(const IntPoint&) const { - notImplemented(); - return IntPoint(); -} - -// new to change 38068 (Nov 6, 2008) -IntRect ChromeClientAndroid::windowToScreen(const IntRect&) const { - notImplemented(); - return IntRect(); -} - -// new to change 38068 (Nov 6, 2008) -// in place of view()->containingWindow(), webkit now uses view()->hostWindow()->platformWindow() -PlatformWidget ChromeClientAndroid::platformWindow() const { - Page* page = m_webFrame->page(); - Frame* mainFrame = page->mainFrame(); - FrameView* view = mainFrame->view(); - PlatformWidget viewBridge = view->platformWidget(); - return viewBridge; -} - -void ChromeClientAndroid::mouseDidMoveOverElement(const HitTestResult&, unsigned int) {} -void ChromeClientAndroid::setToolTip(const String&) {} -void ChromeClientAndroid::print(Frame*) {} - -void ChromeClientAndroid::exceededDatabaseQuota(Frame*, const String&) {} - -// new to change 38068 (Nov 6, 2008) -void ChromeClientAndroid::runOpenPanel(Frame*, PassRefPtr) { notImplemented(); } - -} diff --git a/WebKit/android/ChromeClientAndroid.h b/WebKit/android/ChromeClientAndroid.h deleted file mode 100644 index 60b3a8f..0000000 --- a/WebKit/android/ChromeClientAndroid.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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 ChromeClientAndroid_h -#define ChromeClientAndroid_h - -#include "ChromeClient.h" - -using namespace WebCore; - -namespace android { - class WebFrame; - - class ChromeClientAndroid : public ChromeClient { - public: - ChromeClientAndroid() : m_webFrame(NULL) {} - virtual void chromeDestroyed(); - - virtual void setWindowRect(const FloatRect&); - virtual FloatRect windowRect(); - - virtual FloatRect pageRect(); - - virtual float scaleFactor(); - - virtual void focus(); - virtual void unfocus(); - - virtual bool canTakeFocus(FocusDirection); - virtual void takeFocus(FocusDirection); - - // The Frame pointer provides the ChromeClient with context about which - // Frame wants to create the new Page. Also, the newly created window - // should not be shown to the user until the ChromeClient of the newly - // created Page has its show method called. - virtual Page* createWindow(Frame*, const FrameLoadRequest&, const 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 String& message, unsigned int lineNumber, const String& sourceID); - - virtual bool canRunBeforeUnloadConfirmPanel(); - virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame); - - virtual void closeWindowSoon(); - - virtual void runJavaScriptAlert(Frame*, const String&); - virtual bool runJavaScriptConfirm(Frame*, const String&); - virtual bool runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result); - virtual void setStatusbarText(const String&); - virtual bool shouldInterruptJavaScript(); - virtual bool tabsToLinks() const; - - virtual IntRect windowResizerRect() const; - - // Methods used by HostWindow. - virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false); - virtual void scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); - virtual IntPoint screenToWindow(const IntPoint&) const; - virtual IntRect windowToScreen(const IntRect&) const; - virtual PlatformWidget platformWindow() const; - // End methods used by HostWindow. - - virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned int); - - virtual void setToolTip(const String&); - - virtual void print(Frame*); - - virtual void exceededDatabaseQuota(Frame*, const String&); - - virtual void runOpenPanel(Frame*, PassRefPtr); - - // Android-specific - void setWebFrame(android::WebFrame* webframe); - private: - android::WebFrame* m_webFrame; - }; - -} - -#endif diff --git a/WebKit/android/DragClientAndroid.cpp b/WebKit/android/DragClientAndroid.cpp deleted file mode 100644 index 64406e7..0000000 --- a/WebKit/android/DragClientAndroid.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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. - */ -#define LOG_TAG "WebCore" - -#include "config.h" -#include "DragClientAndroid.h" -#include "NotImplemented.h" - -namespace android { - -void DragClientAndroid::dragControllerDestroyed() { notImplemented(); delete this; } - -void DragClientAndroid::willPerformDragDestinationAction(DragDestinationAction, DragData*) { notImplemented(); } - -DragDestinationAction DragClientAndroid::actionMaskForDrag(DragData*) { notImplemented(); return DragDestinationActionNone; } - -DragSourceAction DragClientAndroid::dragSourceActionMaskForPoint(const IntPoint&) { notImplemented(); return DragSourceActionNone; } - -void* DragClientAndroid::createDragImageForLink(KURL&, String const&, Frame*) { return NULL; } -void DragClientAndroid::willPerformDragSourceAction(DragSourceAction, IntPoint const&, Clipboard*) {} -void DragClientAndroid::startDrag(void*, IntPoint const&, IntPoint const&, Clipboard*, Frame*, bool) {} - -} diff --git a/WebKit/android/DragClientAndroid.h b/WebKit/android/DragClientAndroid.h deleted file mode 100644 index 5f0548f..0000000 --- a/WebKit/android/DragClientAndroid.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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 DragClientAndroid_h -#define DragClientAndroid_h - -#include "DragClient.h" - -using namespace WebCore; - -namespace android { - - class DragClientAndroid : public DragClient { - public: - virtual void willPerformDragDestinationAction(DragDestinationAction, DragData*); - virtual void willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*); - virtual DragDestinationAction actionMaskForDrag(DragData*); - //We work in window rather than view coordinates here - virtual DragSourceAction dragSourceActionMaskForPoint(const IntPoint&); - - virtual void startDrag(DragImageRef dragImage, const IntPoint& dragImageOrigin, const IntPoint& eventPos, Clipboard*, Frame*, bool linkDrag = false); - virtual DragImageRef createDragImageForLink(KURL&, const String& label, Frame*); - - virtual void dragControllerDestroyed(); - }; - -} - -#endif diff --git a/WebKit/android/EditorClientAndroid.cpp b/WebKit/android/EditorClientAndroid.cpp deleted file mode 100644 index fb71fa2..0000000 --- a/WebKit/android/EditorClientAndroid.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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. - */ -#define LOG_TAG "WebCore" - -#include "config.h" -#include "Editor.h" -#include "EditorClientAndroid.h" -#include "Event.h" -#include "EventNames.h" -#include "FocusController.h" -#include "Frame.h" -#include "KeyboardCodes.h" -#include "KeyboardEvent.h" -#include "NotImplemented.h" -#include "PlatformKeyboardEvent.h" -#include "PlatformString.h" - -namespace android { - -void EditorClientAndroid::pageDestroyed() { - delete this; -} - -bool EditorClientAndroid::shouldDeleteRange(Range*) { return true; } -bool EditorClientAndroid::shouldShowDeleteInterface(HTMLElement*) { notImplemented(); return false; } -bool EditorClientAndroid::smartInsertDeleteEnabled() { notImplemented(); return false; } -bool EditorClientAndroid::isContinuousSpellCheckingEnabled() { notImplemented(); return false; } -void EditorClientAndroid::toggleContinuousSpellChecking() { notImplemented(); } -bool EditorClientAndroid::isGrammarCheckingEnabled() { notImplemented(); return false; } -void EditorClientAndroid::toggleGrammarChecking() { notImplemented(); } -int EditorClientAndroid::spellCheckerDocumentTag() { notImplemented(); return -1; } - -bool EditorClientAndroid::isEditable() { /* notImplemented(); */ return false; } - -// Following Qt's implementation. For shouldBeginEditing and shouldEndEditing. -// Returning true for these fixes issue http://b/issue?id=735185 -bool EditorClientAndroid::shouldBeginEditing(Range*) -{ - return true; -} - -bool EditorClientAndroid::shouldEndEditing(Range*) -{ - return true; -} - -bool EditorClientAndroid::shouldInsertNode(Node*, Range*, EditorInsertAction) { notImplemented(); return true; } -bool EditorClientAndroid::shouldInsertText(const String&, Range*, EditorInsertAction) { return true; } -bool EditorClientAndroid::shouldApplyStyle(CSSStyleDeclaration*, Range*) { notImplemented(); return true; } - -void EditorClientAndroid::didBeginEditing() { notImplemented(); } - -// This function is called so that the platform can handle changes to content. It is called -// after the contents have been edited or unedited (ie undo) -void EditorClientAndroid::respondToChangedContents() { notImplemented(); } - -void EditorClientAndroid::didEndEditing() { notImplemented(); } -void EditorClientAndroid::didWriteSelectionToPasteboard() { notImplemented(); } -void EditorClientAndroid::didSetSelectionTypesForPasteboard() { notImplemented(); } - -// Copied from the Window's port of WebKit. -static const unsigned AltKey = 1 << 0; -static const unsigned ShiftKey = 1 << 1; - -struct KeyDownEntry { - unsigned virtualKey; - unsigned modifiers; - const char* name; -}; - -struct KeyPressEntry { - unsigned charCode; - unsigned modifiers; - const char* name; -}; - -static const KeyDownEntry keyDownEntries[] = { - { VK_LEFT, 0, "MoveLeft" }, - { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, - { VK_LEFT, AltKey, "MoveWordLeft" }, - { VK_LEFT, AltKey | ShiftKey, "MoveWordLeftAndModifySelection" }, - { VK_RIGHT, 0, "MoveRight" }, - { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, - { VK_RIGHT, AltKey, "MoveWordRight" }, - { VK_RIGHT, AltKey | ShiftKey, "MoveWordRightAndModifySelection" }, - { VK_UP, 0, "MoveUp" }, - { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, - { VK_DOWN, 0, "MoveDown" }, - { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, - - { VK_BACK, 0, "BackwardDelete" }, - { VK_BACK, ShiftKey, "ForwardDelete" }, - { VK_BACK, AltKey, "DeleteWordBackward" }, - { VK_BACK, AltKey | ShiftKey, "DeleteWordForward" }, - - { VK_ESCAPE, 0, "Cancel" }, - { VK_TAB, 0, "InsertTab" }, - { VK_TAB, ShiftKey, "InsertBacktab" }, - { VK_RETURN, 0, "InsertNewline" }, - { VK_RETURN, AltKey, "InsertNewline" }, - { VK_RETURN, AltKey | ShiftKey, "InsertNewline" } -}; - -static const KeyPressEntry keyPressEntries[] = { - { '\t', 0, "InsertTab" }, - { '\t', ShiftKey, "InsertBackTab" }, - { '\r', 0, "InsertNewline" }, - { '\r', AltKey, "InsertNewline" }, - { '\r', AltKey | ShiftKey, "InsertNewline" } -}; - -static const char* interpretKeyEvent(const KeyboardEvent* evt) -{ - const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); - - static HashMap* keyDownCommandsMap = 0; - static HashMap* keyPressCommandsMap = 0; - - if (!keyDownCommandsMap) { - keyDownCommandsMap = new HashMap; - keyPressCommandsMap = new HashMap; - - for (unsigned i = 0; i < sizeof(keyDownEntries)/sizeof(KeyDownEntry); i++) - keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); - - for (unsigned i = 0; i < sizeof(keyPressEntries)/sizeof(KeyPressEntry); i++) - keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); - } - - unsigned modifiers = 0; - if (keyEvent->shiftKey()) - modifiers |= ShiftKey; - if (keyEvent->altKey()) - modifiers |= AltKey; - - if (evt->type() == eventNames().keydownEvent) { - int mapKey = modifiers << 16 | evt->keyCode(); - return mapKey ? keyDownCommandsMap->get(mapKey) : 0; - } - - int mapKey = modifiers << 16 | evt->charCode(); - return mapKey ? keyPressCommandsMap->get(mapKey) : 0; -} - -void EditorClientAndroid::handleKeyboardEvent(KeyboardEvent* event) { - ASSERT(m_page); - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame) - return; - - const PlatformKeyboardEvent* keyEvent = event->keyEvent(); - // TODO: If the event is not coming from Android Java, e.g. from JavaScript, - // PlatformKeyboardEvent is null. We should support this later. - if (!keyEvent) - return; - - Editor::Command command = frame->editor()->command(interpretKeyEvent(event)); - if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) { - if (!command.isTextInsertion() && command.execute(event)) { - // This function mimics the Windows version. However, calling event->setDefaultHandled() - // prevents the javascript key events for the delete key from happening. - // Update: Safari doesn't send delete key events to javascript so - // we will mimic that behavior. - event->setDefaultHandled(); - } - return; - } - - if (command.execute(event)) { - event->setDefaultHandled(); - return; - } - - // Don't insert null or control characters as they can result in unexpected behaviour - if (event->charCode() < ' ') - return; - - if (frame->editor()->insertText(keyEvent->text(), event)) - event->setDefaultHandled(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////// -// we just don't support Undo/Redo at the moment - -void EditorClientAndroid::registerCommandForUndo(PassRefPtr) {} -void EditorClientAndroid::registerCommandForRedo(PassRefPtr) {} -void EditorClientAndroid::clearUndoRedoOperations() {} -bool EditorClientAndroid::canUndo() const { return false; } -bool EditorClientAndroid::canRedo() const { return false; } -void EditorClientAndroid::undo() {} -void EditorClientAndroid::redo() {} - -// functions new to Jun-07 tip of tree merge: -void EditorClientAndroid::showSpellingUI(bool) {} -void EditorClientAndroid::getGuessesForWord(String const&, Vector&) {} -bool EditorClientAndroid::spellingUIIsShowing() { return false; } -void EditorClientAndroid::checkGrammarOfString(unsigned short const*, int, Vector&, int*, int*) {} -void EditorClientAndroid::checkSpellingOfString(unsigned short const*, int, int*, int*) {} -void EditorClientAndroid::textFieldDidEndEditing(Element*) {} -void EditorClientAndroid::textDidChangeInTextArea(Element*) {} -void EditorClientAndroid::textDidChangeInTextField(Element*) {} -void EditorClientAndroid::textFieldDidBeginEditing(Element*) {} -void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {} -void EditorClientAndroid::respondToChangedSelection() {} -bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool) { return m_notFromClick; } -bool EditorClientAndroid::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; } -void EditorClientAndroid::textWillBeDeletedInTextField(Element*) {} -void EditorClientAndroid::updateSpellingUIWithGrammarString(String const&, GrammarDetail const&) {} -void EditorClientAndroid::updateSpellingUIWithMisspelledWord(String const&) {} -void EditorClientAndroid::learnWord(String const&) {} - -// functions new to the Nov-16-08 tip of tree merge: -bool EditorClientAndroid::shouldMoveRangeAfterDelete(Range*, Range*) { return true; } -void EditorClientAndroid::setInputMethodState(bool) {} - -// functions new to Feb-19 tip of tree merge: -void EditorClientAndroid::handleInputMethodKeydown(KeyboardEvent*) {} - -} diff --git a/WebKit/android/EditorClientAndroid.h b/WebKit/android/EditorClientAndroid.h deleted file mode 100644 index fc35761..0000000 --- a/WebKit/android/EditorClientAndroid.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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 EditorClientAndroid_h -#define EditorClientAndroid_h - -#include "EditorClient.h" -#include "Page.h" - -using namespace WebCore; - -namespace android { - -class EditorClientAndroid : public EditorClient { -public: - EditorClientAndroid() { m_notFromClick = true; } - virtual void pageDestroyed(); - - virtual bool shouldDeleteRange(Range*); - virtual bool shouldShowDeleteInterface(HTMLElement*); - virtual bool smartInsertDeleteEnabled(); - virtual bool isContinuousSpellCheckingEnabled(); - virtual void toggleContinuousSpellChecking(); - virtual bool isGrammarCheckingEnabled(); - virtual void toggleGrammarChecking(); - virtual int spellCheckerDocumentTag(); - - virtual bool isEditable(); - - virtual bool shouldBeginEditing(Range*); - virtual bool shouldEndEditing(Range*); - virtual bool shouldInsertNode(Node*, Range*, EditorInsertAction); - virtual bool shouldInsertText(const String&, Range*, EditorInsertAction); - virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting); - - virtual bool shouldApplyStyle(CSSStyleDeclaration*, Range*); -// virtual bool shouldChangeTypingStyle(CSSStyleDeclaration* fromStyle, CSSStyleDeclaration* toStyle); -// virtual bool doCommandBySelector(SEL selector); - - virtual void didBeginEditing(); - virtual void respondToChangedContents(); - virtual void respondToChangedSelection(); - virtual void didEndEditing(); - virtual void didWriteSelectionToPasteboard(); - virtual void didSetSelectionTypesForPasteboard(); -// virtual void didChangeTypingStyle:(NSNotification *)notification; -// virtual void didChangeSelection:(NSNotification *)notification; -// virtual NSUndoManager* undoManager:(WebView *)webView; - - virtual void registerCommandForUndo(PassRefPtr); - virtual void registerCommandForRedo(PassRefPtr); - virtual void clearUndoRedoOperations(); - - virtual bool canUndo() const; - virtual bool canRedo() const; - - virtual void undo(); - virtual void redo(); - - virtual void textFieldDidBeginEditing(Element*); - virtual void textFieldDidEndEditing(Element*); - virtual void textDidChangeInTextField(Element*); - virtual bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*); - virtual void textWillBeDeletedInTextField(Element*); - virtual void textDidChangeInTextArea(Element*); - - virtual void ignoreWordInSpellDocument(const String&); - virtual void learnWord(const String&); - virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); - virtual void checkGrammarOfString(const UChar*, int length, Vector&, int* badGrammarLocation, int* badGrammarLength); - virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail); - virtual void updateSpellingUIWithMisspelledWord(const String&); - virtual void showSpellingUI(bool show); - virtual bool spellingUIIsShowing(); - virtual void getGuessesForWord(const String&, Vector& guesses); - virtual bool shouldMoveRangeAfterDelete(Range*, Range*); - virtual void setInputMethodState(bool); - - virtual void handleKeyboardEvent(KeyboardEvent*); - virtual void handleInputMethodKeydown(KeyboardEvent*); - // Android specific: - void setPage(Page* page) { m_page = page; } - void setFromClick(bool fromClick) { m_notFromClick = !fromClick; } -private: - Page* m_page; - bool m_notFromClick; -}; - -} - -#endif diff --git a/WebKit/android/FrameLoaderClientAndroid.cpp b/WebKit/android/FrameLoaderClientAndroid.cpp deleted file mode 100644 index 93dcdf4..0000000 --- a/WebKit/android/FrameLoaderClientAndroid.cpp +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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. - */ -#define LOG_TAG "WebCore" - -#include "config.h" - -#include "android_graphics.h" -#include "CString.h" -#include "DocumentLoader.h" -#include "FrameLoader.h" -#include "FrameLoaderClientAndroid.h" -#include "FrameTree.h" -#include "GraphicsContext.h" -// HTMLFormElement needed for a bad include -#include "HTMLFormElement.h" -#include "HTMLFrameOwnerElement.h" -#include "IconDatabase.h" -#include "MIMETypeRegistry.h" -#include "NotImplemented.h" -#include "Page.h" -#include "PlatformGraphicsContext.h" -#include "PlatformString.h" -#include "PluginDatabase.h" -#include "PluginView.h" -#ifdef ANDROID_PLUGINS -// Removed. -#else -#include "PluginViewBridgeAndroid.h" -#endif -#include "ProgressTracker.h" -#include "RenderPart.h" -#include "ResourceError.h" -#include "SelectionController.h" -#include "SkCanvas.h" -#include "SkRect.h" -#include "TextEncoding.h" -#include "Document.h" -#include "FrameView.h" -#include "HistoryItem.h" -#include "ResourceHandle.h" -#include "ResourceHandleInternal.h" -#include "WebCoreFrameBridge.h" -#include "WebCoreResourceLoader.h" -#include "WebHistory.h" -#include "WebIconDatabase.h" -#include "WebFrameView.h" -#include "WebViewCore.h" -#include "Settings.h" - -#include - -extern android::AssetManager* globalAssetManager(); - -namespace android { - -static const int EXTRA_LAYOUT_DELAY = 1000; - -// FIXME: Need some data for how big this should be. -#define MAX_SESSION_HISTORY 50 -static WTF::Vector gSessionHistory; - -bool historyContains(const UChar* chars, unsigned len) { - const KURL url(String(chars, len)); - WTF::Vector::const_iterator end = gSessionHistory.end(); - for (WTF::Vector::const_iterator i = gSessionHistory.begin(); i != end; ++i) { - if (equalIgnoringRef(url, *i)) - return true; - } - return false; -} - -FrameLoaderClientAndroid::FrameLoaderClientAndroid(WebFrame* webframe) - : m_frame(NULL) - , m_webFrame(webframe) { - Retain(m_webFrame); -} - -FrameLoaderClientAndroid* FrameLoaderClientAndroid::get(const WebCore::Frame* frame) -{ - return static_cast (frame->loader()->client()); -} - -void FrameLoaderClientAndroid::frameLoaderDestroyed() { - registerForIconNotification(false); - m_frame = 0; - Release(m_webFrame); - delete this; -} - -bool FrameLoaderClientAndroid::hasWebView() const { - // FIXME, - // there is one web view per page, or top frame. - // as android's view is created from Java side, it is always there. - return true; -} - -bool FrameLoaderClientAndroid::hasFrameView() const { - // FIXME, - // need to revisit for sub-frame case - return true; -} - -bool FrameLoaderClientAndroid::privateBrowsingEnabled() const { - // FIXME, are we going to support private browsing? - notImplemented(); - return false; -} - -void FrameLoaderClientAndroid::makeRepresentation(DocumentLoader*) { - // don't use representation - verifiedOk(); -} - -void FrameLoaderClientAndroid::forceLayout() { - ASSERT(m_frame); - m_frame->forceLayout(); - // FIXME, should we adjust view size here? - m_frame->view()->adjustViewSize(); -} - -void FrameLoaderClientAndroid::forceLayoutForNonHTML() { - notImplemented(); -} - -void FrameLoaderClientAndroid::setCopiesOnScroll() { - // this is a hint about whether we need to force redraws, or can - // just copy the scrolled content. Since we always force a redraw - // anyways, we can ignore this call. - verifiedOk(); -} - -void FrameLoaderClientAndroid::detachedFromParent2() { - // FIXME, ready to detach frame from view -} - -void FrameLoaderClientAndroid::detachedFromParent3() { - // FIXME, ready to release view - notImplemented(); -} - -void FrameLoaderClientAndroid::detachedFromParent4() { - // FIXME, ready to release view - notImplemented(); -} - -void FrameLoaderClientAndroid::loadedFromPageCache() { - // don't support page cache - verifiedOk(); -} - -// This function is responsible for associating the "id" with a given -// subresource load. The following functions that accept an "id" are -// called for each subresource, so they should not be dispatched to the m_frame. -void FrameLoaderClientAndroid::assignIdentifierToInitialRequest(unsigned long id, - DocumentLoader*, const ResourceRequest&) { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchWillSendRequest(DocumentLoader*, unsigned long id, - ResourceRequest&, const ResourceResponse&) { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, - unsigned long id, const AuthenticationChallenge&) { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, - unsigned long id, const AuthenticationChallenge&) { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidReceiveResponse(DocumentLoader*, - unsigned long id, const ResourceResponse&) { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidReceiveContentLength(DocumentLoader*, - unsigned long id, int lengthReceived) { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidFinishLoading(DocumentLoader*, - unsigned long id) { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidFailLoading(DocumentLoader* docLoader, - unsigned long id, const ResourceError&) { - lowPriority_notImplemented(); -} - -bool FrameLoaderClientAndroid::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, - const ResourceRequest&, const ResourceResponse&, int length) { - notImplemented(); - return false; -} - -void FrameLoaderClientAndroid::dispatchDidHandleOnloadEvents() { -} - -void FrameLoaderClientAndroid::dispatchDidReceiveServerRedirectForProvisionalLoad() { - ASSERT(m_frame); - // Tell the load it was a redirect. - m_webFrame->loadStarted(m_frame); -} - -void FrameLoaderClientAndroid::dispatchDidCancelClientRedirect() { - notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchWillPerformClientRedirect(const KURL&, - double interval, double fireDate) { - notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidChangeLocationWithinPage() { - notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchWillClose() { - notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidReceiveIcon() { - ASSERT(m_frame); - if (m_frame->tree() && m_frame->tree()->parent()) - return; - WebCore::String url(m_frame->loader()->url().string()); - // Try to obtain the icon image. - WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL( - url, WebCore::IntSize(16, 16)); - // If the request fails, try the original request url. - if (!icon) - icon = WebCore::iconDatabase()->iconForPageURL( - m_frame->loader()->originalRequestURL().string(), - WebCore::IntSize(16, 16)); - // There is a bug in webkit where cancelling an icon load is treated as a - // failure. When this is fixed, we can ASSERT again that we have an icon. - if (icon) { - LOGV("Received icon (%p) for %s", icon, - url.utf8().data()); - m_webFrame->didReceiveIcon(icon); - } else { - LOGV("Icon data for %s unavailable, registering for notification...", - url.utf8().data()); - registerForIconNotification(); - } -} - -void FrameLoaderClientAndroid::dispatchDidStartProvisionalLoad() { - notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidReceiveTitle(const String& title) { - ASSERT(m_frame); - // Used to check for FrameLoadTypeStandard but we only want to send the title for - // the top frame and not sub-frames. - if (!m_frame->tree() || !m_frame->tree()->parent()) { - m_webFrame->setTitle(title); - } -} - -void FrameLoaderClientAndroid::dispatchDidCommitLoad() { - ASSERT(m_frame); - WebViewCore::getWebViewCore(m_frame->view())->updateFrameGeneration(m_frame); -} - -static void loadDataIntoFrame(Frame* frame, const String& url, - const String& data) { - ResourceRequest request(url); - CString cstr = data.utf8(); - RefPtr buf = WebCore::SharedBuffer::create(cstr.data(), cstr.length()); - SubstituteData subData(buf, String("text/html"), String("utf-8"), - request.url()); - frame->loader()->load(request, subData); -} - -void FrameLoaderClientAndroid::dispatchDidFailProvisionalLoad(const ResourceError& error) { - ASSERT(m_frame); - // Ignore ErrorInterrupted since it is due to a policy interruption. This - // is caused by a decision to download the main resource rather than - // display it. - if (error.errorCode() == InternalErrorInterrupted - || error.errorCode() == InternalErrorCancelled) { - // If we decided to download the main resource or if the user cancelled - // it, make sure we report that the load is done. - didFinishLoad(); - return; - } - - AssetManager* am = globalAssetManager(); - - // Check to see if the error code was not generated internally - WebFrame::RAW_RES_ID id = WebFrame::NODOMAIN; - if ((error.errorCode() == ErrorFile || - error.errorCode() == ErrorFileNotFound) && - (!error.localizedDescription().isEmpty())) { - id = WebFrame::LOADERROR; - } - String filename = m_webFrame->getRawResourceFilename(id); - if (filename.isEmpty()) - return; - - // Grab the error page from the asset manager - Asset* a = am->openNonAsset( - filename.utf8().data(), Asset::ACCESS_BUFFER); - if (!a) - return; - - // Take the failing url and encode html entities so javascript urls are not - // executed. - CString failingUrl = error.failingURL().utf8(); - WTF::Vector url; - int len = failingUrl.length(); - const char* data = failingUrl.data(); - for (int i = 0; i < len; i++) { - char c = data[i]; - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9')) - url.append(c); - else { - char buf[16]; - int res = sprintf(buf, "&#%d;", c); - buf[res] = 0; - url.append(buf, res); - } - } - - // Replace all occurances of %s with the failing url. - String s = UTF8Encoding().decode((const char*)a->getBuffer(false), a->getLength()); - s = s.replace("%s", String(url.data(), url.size())); - - // Replace all occurances of %e with the error text - s = s.replace("%e", error.localizedDescription()); - - // Create the request and the substitute data and tell the FrameLoader to - // load with the replacement data. - loadDataIntoFrame(m_frame, error.failingURL(), s); - - // Delete the asset. - delete a; -} - -void FrameLoaderClientAndroid::dispatchDidFailLoad(const ResourceError&) { - // called when page is completed with error - didFinishLoad(); -} - -void FrameLoaderClientAndroid::dispatchDidFinishDocumentLoad() { - // called when finishedParsing - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDidFinishLoad() { - didFinishLoad(); -} - -void FrameLoaderClientAndroid::dispatchDidFirstLayout() { - ASSERT(m_frame); - m_frame->document()->setExtraLayoutDelay(EXTRA_LAYOUT_DELAY); - // FIXME: Need to figure out if we need didLayout or didFirstLayout - // see WebViewCore::didLayout - if (!m_frame->tree()->parent()) { - // Only need to notify Java side for the top frame - WebViewCore::getWebViewCore(m_frame->view())->didFirstLayout(); - } -} - -Frame* FrameLoaderClientAndroid::dispatchCreatePage() { - ASSERT(m_frame); -#ifdef ANDROID_MULTIPLE_WINDOWS - if (m_frame->settings() && m_frame->settings()->supportMultipleWindows()) - // Always a user gesture since window.open maps to - // ChromeClientAndroid::createWindow - return m_webFrame->createWindow(false, true); - else -#endif - // If the client doesn't support multiple windows, just replace the - // current frame's contents. - return m_frame; -} - -void FrameLoaderClientAndroid::dispatchShow() { - ASSERT(m_frame); - m_frame->view()->invalidate(); -} - - -static bool TreatAsAttachment(const String& content_disposition) { - // Some broken sites just send - // Content-Disposition: ; filename="file" - // screen those out here. - if (content_disposition.startsWith(";")) - return false; - - if (content_disposition.startsWith("inline", false)) - return false; - - // Some broken sites just send - // Content-Disposition: filename="file" - // without a disposition token... screen those out. - if (content_disposition.startsWith("filename", false)) - return false; - - // Also in use is Content-Disposition: name="file" - if (content_disposition.startsWith("name", false)) - return false; - - // We have a content-disposition of "attachment" or unknown. - // RFC 2183, section 2.8 says that an unknown disposition - // value should be treated as "attachment" - return true; -} - -void FrameLoaderClientAndroid::dispatchDecidePolicyForMIMEType(FramePolicyFunction func, - const String& MIMEType, const ResourceRequest&) { - ASSERT(m_frame); - ASSERT(func); - // Default to Use (display internally). - PolicyAction action = PolicyUse; - // Check if we should Download instead. - const ResourceResponse& response = m_frame->loader()->activeDocumentLoader()->response(); - const String& content_disposition = response.httpHeaderField("Content-Disposition"); - if (!content_disposition.isEmpty()) { - // Server wants to override our normal policy. - if (TreatAsAttachment(content_disposition)) { - // Check to see if we are a sub frame (main frame has no owner element) - if (m_frame->ownerElement() != 0) - action = PolicyIgnore; - else - action = PolicyDownload; - } - } else { - // Ask if it can be handled internally. - if (!canShowMIMEType(MIMEType)) { - // Check to see if we are a sub frame (main frame has no owner element) - if (m_frame->ownerElement() != 0) - action = PolicyIgnore; - else - action = PolicyDownload; - } - } - // A status code of 204 indicates no content change. Ignore the result. - WebCore::DocumentLoader* docLoader = m_frame->loader()->activeDocumentLoader(); - if (docLoader->response().httpStatusCode() == 204) - action = PolicyIgnore; - (m_frame->loader()->*func)(action); -} - -void FrameLoaderClientAndroid::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction func, - const NavigationAction&, const ResourceRequest& req, - PassRefPtr formState, const String& frameName) { - ASSERT(m_frame); - // If we get to this point it means that a link has a target that was not - // found by the frame tree. Instead of creating a new frame, return the - // current frame in dispatchCreatePage. - if (canHandleRequest(req)) - (m_frame->loader()->*func)(PolicyUse); - else - (m_frame->loader()->*func)(PolicyIgnore); -} - -void FrameLoaderClientAndroid::cancelPolicyCheck() { - lowPriority_notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchUnableToImplementPolicy(const ResourceError&) { - notImplemented(); -} - -void FrameLoaderClientAndroid::dispatchDecidePolicyForNavigationAction(FramePolicyFunction func, - const NavigationAction& action, const ResourceRequest& request, - PassRefPtr formState) { - ASSERT(m_frame); - ASSERT(func); - if (action.type() == NavigationTypeFormResubmitted) { - m_webFrame->decidePolicyForFormResubmission(func); - return; - } else { - (m_frame->loader()->*func)(PolicyUse); - } -} - -void FrameLoaderClientAndroid::dispatchWillSubmitForm(FramePolicyFunction func, PassRefPtr) { - ASSERT(m_frame); - ASSERT(func); - (m_frame->loader()->*func)(PolicyUse); -} - -void FrameLoaderClientAndroid::dispatchDidLoadMainResource(DocumentLoader*) { - notImplemented(); -} - -void FrameLoaderClientAndroid::revertToProvisionalState(DocumentLoader*) { - notImplemented(); -} - -void FrameLoaderClientAndroid::setMainDocumentError(DocumentLoader* docLoader, const ResourceError& error) { - ASSERT(m_frame); - if (!error.isNull() && error.errorCode() >= InternalErrorLast) - m_webFrame->reportError(error.errorCode(), - error.localizedDescription(), error.failingURL()); -} - -void FrameLoaderClientAndroid::clearUnarchivingState(DocumentLoader*) { - notImplemented(); -} - -// This function is called right before the progress is updated. -void FrameLoaderClientAndroid::willChangeEstimatedProgress() { - verifiedOk(); -} - -// This function is called after the progress has been updated. The bad part -// about this is that when a page is completed, this function is called after -// the progress has been reset to 0. -void FrameLoaderClientAndroid::didChangeEstimatedProgress() { - verifiedOk(); -} - -// This will give us the initial estimate when the page first starts to load. -void FrameLoaderClientAndroid::postProgressStartedNotification() { - ASSERT(m_frame); - if (m_frame->page()) - m_webFrame->setProgress(m_frame->page()->progress()->estimatedProgress()); -} - -// This will give us any updated progress including the final progress. -void FrameLoaderClientAndroid::postProgressEstimateChangedNotification() { - ASSERT(m_frame); - if (m_frame->page()) - m_webFrame->setProgress(m_frame->page()->progress()->estimatedProgress()); -} - -// This is just a notification that the progress has finished. Don't call -// setProgress(1) because postProgressEstimateChangedNotification will do so. -void FrameLoaderClientAndroid::postProgressFinishedNotification() { - if (!m_frame->tree()->parent()) { - // only need to notify Java for the top frame - WebViewCore::getWebViewCore(m_frame->view())->notifyProgressFinished(); - } -} - -void FrameLoaderClientAndroid::setMainFrameDocumentReady(bool) { - // this is only interesting once we provide an external API for the DOM - notImplemented(); -} - -void FrameLoaderClientAndroid::startDownload(const ResourceRequest&) { - notImplemented(); -} - -void FrameLoaderClientAndroid::willChangeTitle(DocumentLoader*) { - verifiedOk(); -} - -void FrameLoaderClientAndroid::didChangeTitle(DocumentLoader* loader) { - verifiedOk(); -} - -void FrameLoaderClientAndroid::finishedLoading(DocumentLoader* docLoader) { - // 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) - committedLoad(docLoader, 0, 0); -} - -void FrameLoaderClientAndroid::finalSetupForReplace(DocumentLoader*) { - notImplemented(); -} - -void FrameLoaderClientAndroid::updateGlobalHistoryForStandardLoad(const KURL& url) { - ASSERT(m_frame); - const String& str = url.string(); - if (!historyContains(str.characters(), str.length())) { - if (gSessionHistory.size() == MAX_SESSION_HISTORY) - gSessionHistory.remove(0); - gSessionHistory.append(url); - } - m_webFrame->updateVisitedHistory(url, false); -} - -void FrameLoaderClientAndroid::updateGlobalHistoryForReload(const KURL& url) { - ASSERT(m_frame); - m_webFrame->updateVisitedHistory(url, true); -} - -bool FrameLoaderClientAndroid::shouldGoToHistoryItem(HistoryItem* item) const { - // hmmm, seems like we might do a more thoughtful check - ASSERT(m_frame); - return item != NULL; -} - -void FrameLoaderClientAndroid::committedLoad(DocumentLoader* loader, const char* data, int length) { - ASSERT(m_frame); - String encoding = loader->overrideEncoding(); - bool userChosen = !encoding.isNull(); - if (encoding.isNull()) - encoding = loader->response().textEncodingName(); - loader->frameLoader()->setEncoding(encoding, userChosen); - Document *doc = m_frame->document(); - if (doc) { - loader->frameLoader()->addData(data, length); - } -} - -ResourceError FrameLoaderClientAndroid::cancelledError(const ResourceRequest& request) { - return ResourceError(String(), InternalErrorCancelled, String(), String()); -} - -ResourceError FrameLoaderClientAndroid::cannotShowURLError(const ResourceRequest& request) { - return ResourceError(String(), InternalErrorCannotShowUrl, String(), String()); -} - -ResourceError FrameLoaderClientAndroid::interruptForPolicyChangeError(const ResourceRequest& request) { - return ResourceError(String(), InternalErrorInterrupted, String(), String()); -} - -ResourceError FrameLoaderClientAndroid::cannotShowMIMETypeError(const ResourceResponse& request) { - return ResourceError(String(), InternalErrorCannotShowMimeType, String(), String()); -} - -ResourceError FrameLoaderClientAndroid::fileDoesNotExistError(const ResourceResponse& request) { - return ResourceError(String(), InternalErrorFileDoesNotExist, String(), String()); -} - -ResourceError FrameLoaderClientAndroid::pluginWillHandleLoadError(const ResourceResponse& request) { - return ResourceError(String(), InternalErrorPluginWillHandleLoadError, String(), String()); -} - -bool FrameLoaderClientAndroid::shouldFallBack(const ResourceError&) { - notImplemented(); - return false; -} - -void FrameLoaderClientAndroid::setDefersLoading(bool) { - notImplemented(); -} - -bool FrameLoaderClientAndroid::willUseArchive(ResourceLoader*, const ResourceRequest&, - const KURL& originalURL) const { - lowPriority_notImplemented(); - return false; -} - -bool FrameLoaderClientAndroid::isArchiveLoadPending(ResourceLoader*) const { - lowPriority_notImplemented(); - return false; -} - -void FrameLoaderClientAndroid::cancelPendingArchiveLoad(ResourceLoader*) { - notImplemented(); -} - -void FrameLoaderClientAndroid::clearArchivedResources() { - notImplemented(); -} - -bool FrameLoaderClientAndroid::canHandleRequest(const ResourceRequest& request) const { - ASSERT(m_frame); - // Don't allow hijacking of intrapage navigation - if (WebCore::equalIgnoringRef(request.url(), m_frame->loader()->url())) - return true; - - // Don't allow hijacking of iframe urls that are http or https - if (request.url().protocol().startsWith("http", false) && - m_frame->tree() && m_frame->tree()->parent()) - return true; - - if (m_webFrame->canHandleRequest(request)) { -#ifdef ANDROID_META_SUPPORT - // reset metadata settings for the top frame as they are not preserved cross page - if (!m_frame->tree()->parent() && m_frame->settings()) - m_frame->settings()->resetMetadataSettings(); -#endif - return true; - } - return false; -} - -bool FrameLoaderClientAndroid::canShowMIMEType(const String& mimeType) const { - // FIXME: This looks like it has to do with whether or not a type can be - // shown "internally" (i.e. inside the browser) regardless of whether - // or not the browser is doing the rendering, e.g. a full page plugin. - if (MIMETypeRegistry::isSupportedImageResourceMIMEType(mimeType) || - MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType) || - MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) || - PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) - return true; - return false; -} - -bool FrameLoaderClientAndroid::representationExistsForURLScheme(const String&) const { - // don't use representation - verifiedOk(); - return false; -} - -String FrameLoaderClientAndroid::generatedMIMETypeForURLScheme(const String& URLScheme) const { - // FIXME, copy from Apple's port - String mimetype("x-apple-web-kit/"); - mimetype.append(URLScheme.lower()); - return mimetype; -} - -void FrameLoaderClientAndroid::frameLoadCompleted() { - // copied from Apple port, without this back with sub-frame will trigger ASSERT - ASSERT(m_frame); - m_frame->loader()->setPreviousHistoryItem(0); -} - -void FrameLoaderClientAndroid::saveViewStateToItem(HistoryItem* item) { -#ifdef ANDROID_HISTORY_CLIENT - ASSERT(m_frame); - ASSERT(item); - // We should have added a bridge when the child item was added to its - // parent. - WebHistoryItem* bridge = item->bridge(); - ASSERT(bridge); - // store the current scale (only) for the top frame - if (!m_frame->tree()->parent()) { - bridge->setScale(WebViewCore::getWebViewCore(m_frame->view())->scale()); - } - - WebCore::notifyHistoryItemChanged(item); -#endif -} - -void FrameLoaderClientAndroid::restoreViewState() { -#ifdef ANDROID_HISTORY_CLIENT - WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view()); - HistoryItem* item = m_frame->loader()->currentHistoryItem(); - // restore the scale (only) for the top frame - if (!m_frame->tree()->parent()) { - webViewCore->restoreScale(item->bridge()->scale()); - } -#endif -} - -#ifdef ANDROID_HISTORY_CLIENT -void FrameLoaderClientAndroid::dispatchDidAddHistoryItem(HistoryItem* item) const { - ASSERT(m_frame); - m_webFrame->addHistoryItem(item); -} - -void FrameLoaderClientAndroid::dispatchDidRemoveHistoryItem(HistoryItem* item, int index) const { - ASSERT(m_frame); - m_webFrame->removeHistoryItem(index); -} - -void FrameLoaderClientAndroid::dispatchDidChangeHistoryIndex( - BackForwardList* list) const { - ASSERT(m_frame); - m_webFrame->updateHistoryIndex(list->backListCount()); -} -#endif - -void FrameLoaderClientAndroid::provisionalLoadStarted() { - ASSERT(m_frame); - m_webFrame->loadStarted(m_frame); -} - -void FrameLoaderClientAndroid::didFinishLoad() { - ASSERT(m_frame); - m_frame->document()->setExtraLayoutDelay(0); - m_webFrame->didFinishLoad(m_frame); -} - -void FrameLoaderClientAndroid::prepareForDataSourceReplacement() { - ASSERT(m_frame); - m_frame->loader()->detachChildren(); -} - -PassRefPtr FrameLoaderClientAndroid::createDocumentLoader( - const ResourceRequest& request, const SubstituteData& data) { - RefPtr loader = DocumentLoader::create(request, data); - return loader.release(); -} - -void FrameLoaderClientAndroid::setTitle(const String& title, const KURL& url) { - // Not needed. dispatchDidReceiveTitle is called immediately after this. - // url is used to update the Apple port history items. - verifiedOk(); -} - -String FrameLoaderClientAndroid::userAgent(const KURL& u) { - return m_webFrame->userAgentForURL(&u); -} - -bool FrameLoaderClientAndroid::canCachePage() const { - return true; -} - -void FrameLoaderClientAndroid::download(ResourceHandle* handle, const ResourceRequest&, - const ResourceRequest&, const ResourceResponse&) { - // Get the C++ side of the load listener and tell it to handle the download - WebCoreResourceLoader* loader = handle->getInternal()->m_loader; - loader->downloadFile(); -} - -WTF::PassRefPtr FrameLoaderClientAndroid::createFrame(const KURL& url, const String& name, - HTMLFrameOwnerElement* ownerElement, const String& referrer, - bool allowsScrolling, int marginWidth, int marginHeight) -{ - Frame* parent = ownerElement->document()->frame(); - FrameLoaderClientAndroid* loaderC = new FrameLoaderClientAndroid(m_webFrame); - RefPtr pFrame = Frame::create(parent->page(), ownerElement, loaderC); - Frame* newFrame = pFrame.get(); - loaderC->setFrame(newFrame); - // Append the subframe to the parent and set the name of the subframe. The name must be set after - // appending the child so that the name becomes unique. - parent->tree()->appendChild(newFrame); - newFrame->tree()->setName(name); - // Create a new FrameView and WebFrameView for the child frame to draw into. - FrameView* frameView = new WebCore::FrameView(newFrame); - WebFrameView* webFrameView = new WebFrameView(frameView, - WebViewCore::getWebViewCore(parent->view())); - // frameView Retains webFrameView, so call Release for webFrameView - Release(webFrameView); - // Attach the frameView to the newFrame. - newFrame->setView(frameView); - // setView() refs the frameView so call deref on the frameView - frameView->deref(); - newFrame->init(); - newFrame->selection()->setFocused(true); - LOGV("::WebCore:: createSubFrame returning %p", newFrame); - - // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. - if (!pFrame->page()) - return 0; - - parent->loader()->loadURLIntoChildFrame(url, referrer, pFrame.get()); - - // onLoad may cuase the frame to be removed from the document. Allow the RefPtr to delete the child frame. - if (!pFrame->tree()->parent()) - return NULL; - - return pFrame.release(); -} - -// YouTube flash url path starts with /v/ -static const char slash_v_slash[] = { '/', 'v', '/' }; - -static bool isValidYouTubeVideo(const String& path) -{ - if (!charactersAreAllASCII(path.characters(), path.length())) - return false; - unsigned int len = path.length(); - if (len <= sizeof(slash_v_slash)) // check for more than just /v/ - return false; - CString str = path.lower().utf8(); - const char* data = str.data(); - if (memcmp(data, slash_v_slash, sizeof(slash_v_slash)) != 0) - return false; - // Start after /v/ - for (unsigned int i = sizeof(slash_v_slash); i < len; i++) { - char c = data[i]; - // Check for alpha-numeric characters only. - if (WTF::isASCIIAlphanumeric(c)) - continue; - // The url can have more parameters such as &hl=en after the video id. - // Once we start seeing extra parameters we can return true. - return c == '&' && i > sizeof(slash_v_slash); - } - return true; -} - -static bool isYouTubeUrl(const KURL& url, const String& mimeType) -{ - return url.host().endsWith("youtube.com") && isValidYouTubeVideo(url.path()) - && equalIgnoringCase(mimeType, "application/x-shockwave-flash"); -} - -Widget* FrameLoaderClientAndroid::createPlugin( - const IntSize& size, - Element* element, - const KURL& url, - const WTF::Vector& names, - const WTF::Vector& values, - const String& mimeType, - bool loadManually) { - // Create an iframe for youtube urls. - if (isYouTubeUrl(url, mimeType)) { - RefPtr frame = createFrame(KURL(), String(), - static_cast(element), - String(), false, 0, 0); - if (frame) { - // grab everything after /v/ - String videoId = url.path().substring(sizeof(slash_v_slash)); - // Extract just the video id - unsigned videoIdEnd = 0; - for (; videoIdEnd < videoId.length(); videoIdEnd++) { - if (videoId[videoIdEnd] == '&') { - videoId = videoId.left(videoIdEnd); - break; - } - } - AssetManager* am = globalAssetManager(); - Asset* a = am->open("webkit/youtube.html", - Asset::ACCESS_BUFFER); - if (!a) - return NULL; - String s = String((const char*)a->getBuffer(false), a->getLength()); - s = s.replace("VIDEO_ID", videoId); - delete a; - loadDataIntoFrame(frame.get(), - "file:///android_asset/webkit/", s); - return frame->view(); - } - return NULL; - } -#ifdef ANDROID_PLUGINS - return PluginView::create(m_frame, - size, - element, - url, - names, - values, - mimeType, - loadManually); -#else - return NULL; -#endif -} - -void FrameLoaderClientAndroid::redirectDataToPlugin(Widget* pluginWidget) { - // don't support plugin yet - notImplemented(); -} - -Widget* FrameLoaderClientAndroid::createJavaAppletWidget(const IntSize&, Element*, - const KURL& baseURL, const WTF::Vector& paramNames, - const WTF::Vector& paramValues) { - // don't support widget yet - notImplemented(); - return 0; -} - -// This function is used by the element to determine the type of -// the contents and work out if it can render it. -ObjectContentType FrameLoaderClientAndroid::objectContentType(const KURL& url, - const String& mimeType) { - if (mimeType.length() == 0) - { - // Guess the mimeType from the extension - if (url.hasPath()) - { - String path = url.path(); - int lastIndex = path.reverseFind('.'); - static const String image("image/"); - if (lastIndex >= 0) - { - String mime(path.substring(lastIndex + 1)); - mime.insert(image, 0); - if (Image::supportsType(mime)) - return ObjectContentImage; - } - } - return ObjectContentFrame; - } - if (equalIgnoringCase(mimeType, "text/html") || - equalIgnoringCase(mimeType, "text/xml") || - equalIgnoringCase(mimeType, "text/") || - equalIgnoringCase(mimeType, "application/xml") || - equalIgnoringCase(mimeType, "application/xhtml+xml") || - equalIgnoringCase(mimeType, "application/x-javascript")) - return ObjectContentFrame; - if (Image::supportsType(mimeType)) - return ObjectContentImage; - return ObjectContentNone; -} - -// This function allows the application to set the correct CSS media -// style. Android could use it to set the media style 'handheld'. Safari -// may use it to set the media style to 'print' when the user wants to print -// a particular web page. -String FrameLoaderClientAndroid::overrideMediaType() const { - lowPriority_notImplemented(); - return String(); -} - -// This function is used to re-attach Javascript<->native code classes. -void FrameLoaderClientAndroid::windowObjectCleared() { - ASSERT(m_frame); - LOGV("::WebCore:: windowObjectCleared called on frame %p for %s\n", - m_frame, m_frame->loader()->url().string().ascii().data()); - m_webFrame->windowObjectCleared(m_frame); -} - -// functions new to Jun-07 tip of tree merge: -ResourceError FrameLoaderClientAndroid::blockedError(ResourceRequest const& request) { - return ResourceError(String(), InternalErrorFileDoesNotExist, String(), String()); -} - -// functions new to Nov-07 tip of tree merge: -void FrameLoaderClientAndroid::didPerformFirstNavigation() const { - // This seems to be just a notification that the UI can listen to, to - // know if the user has performed first navigation action. - // It is called from - // void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip) - // "Navigation" here means a transition from one page to another that - // ends up in the back/forward list. -} - -void FrameLoaderClientAndroid::registerForIconNotification(bool listen) { - if (listen) - WebIconDatabase::RegisterForIconNotification(this); - else - WebIconDatabase::UnregisterForIconNotification(this); -} - -// This is the WebIconDatabaseClient method for receiving a notification when we -// get the icon for the page. -void FrameLoaderClientAndroid::didAddIconForPageUrl(const String& pageUrl) { - // This call must happen before dispatchDidReceiveIcon since that method - // may register for icon notifications again since the icon data may have - // to be read from disk. - registerForIconNotification(false); - KURL u(pageUrl); - if (equalIgnoringRef(u, m_frame->loader()->url())) { - dispatchDidReceiveIcon(); - } -} - -// functions new to Feb-19 tip of tree merge: -// According to the changelog: -// The very Mac-centric "makeDocumentView", "setDocumentViewFromCachedPage", -// and "saveDocumentViewToCachedPage" become "transitionToCommittedForNewPage", -// "transitionToCommittedFromCachedPage", and "savePlatformDataToCachedPage" -// accordingly -void FrameLoaderClientAndroid::savePlatformDataToCachedPage(CachedPage*) { - // don't support page cache - verifiedOk(); -} - -void FrameLoaderClientAndroid::transitionToCommittedFromCachedPage(CachedPage*) { - // don't support page cache - verifiedOk(); -} - -void FrameLoaderClientAndroid::transitionToCommittedForNewPage() { - ASSERT(m_frame); - if (m_frame->settings() && !m_frame->settings()->usesPageCache()) { - m_webFrame->transitionToCommitted(m_frame); - return; - } - - // Remember the old WebFrameView - WebFrameView* webFrameView = static_cast ( - m_frame->view()->platformWidget()); - Retain(webFrameView); - - // Remove the old FrameView - m_frame->setView(NULL); - - // Create a new FrameView and associate it with the saved webFrameView - FrameView* view = new FrameView(m_frame); - webFrameView->setView(view); - - Release(webFrameView); - - // Give the new FrameView to the Frame - m_frame->setView(view); - - // Deref since FrameViews are created with a ref of 1 - view->deref(); - - if (m_frame->ownerRenderer()) - m_frame->ownerRenderer()->setWidget(view); - - m_frame->view()->initScrollbars(); - - m_webFrame->transitionToCommitted(m_frame); -} - -// new as of webkit 34152 -void FrameLoaderClientAndroid::updateGlobalHistory(const KURL& url) { - m_webFrame->updateVisitedHistory(url, false); -} - -} diff --git a/WebKit/android/FrameLoaderClientAndroid.h b/WebKit/android/FrameLoaderClientAndroid.h deleted file mode 100644 index 58b296e..0000000 --- a/WebKit/android/FrameLoaderClientAndroid.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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 FrameLoaderClientAndroid_h -#define FrameLoaderClientAndroid_h - -#include "CacheBuilder.h" -#include "FrameLoaderClient.h" -#include "ResourceResponse.h" -#include "WebIconDatabase.h" - -using namespace WebCore; - -namespace android { - class WebFrame; - - class FrameLoaderClientAndroid : public FrameLoaderClient, - WebIconDatabaseClient { - public: - FrameLoaderClientAndroid(WebFrame* webframe); - - Frame* getFrame() { return m_frame; } - static FrameLoaderClientAndroid* get(const Frame* frame); - - void setFrame(Frame* frame) { m_frame = frame; } - WebFrame* webFrame() const { return m_webFrame; } - - virtual void frameLoaderDestroyed(); - - virtual bool hasWebView() const; // mainly for assertions - virtual bool hasFrameView() const; // ditto - - virtual bool privateBrowsingEnabled() const; - - virtual void makeRepresentation(DocumentLoader*); - virtual void forceLayout(); - virtual void forceLayoutForNonHTML(); - - virtual void setCopiesOnScroll(); - - virtual void detachedFromParent2(); - virtual void detachedFromParent3(); - virtual void detachedFromParent4(); - - virtual void loadedFromPageCache(); - - virtual void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); - - virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); - virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); - virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); - virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); - virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived); - virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier); - virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&); - virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length); - - virtual void dispatchDidHandleOnloadEvents(); - virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); - virtual void dispatchDidCancelClientRedirect(); - virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate); - virtual void dispatchDidChangeLocationWithinPage(); - virtual void dispatchWillClose(); - virtual void dispatchDidReceiveIcon(); - virtual void dispatchDidStartProvisionalLoad(); - virtual void dispatchDidReceiveTitle(const String& title); - virtual void dispatchDidCommitLoad(); - virtual void dispatchDidFailProvisionalLoad(const ResourceError&); - virtual void dispatchDidFailLoad(const ResourceError&); - virtual void dispatchDidFinishDocumentLoad(); - virtual void dispatchDidFinishLoad(); - virtual void dispatchDidFirstLayout(); - - virtual Frame* dispatchCreatePage(); - virtual void dispatchShow(); - - virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction, const String& MIMEType, const ResourceRequest&); - virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr, const String& frameName); - virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr); - virtual void cancelPolicyCheck(); - - virtual void dispatchUnableToImplementPolicy(const ResourceError&); - - virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr); - - virtual void dispatchDidLoadMainResource(DocumentLoader*); - virtual void revertToProvisionalState(DocumentLoader*); - virtual void setMainDocumentError(DocumentLoader*, const ResourceError&); - virtual void clearUnarchivingState(DocumentLoader*); - - virtual void willChangeEstimatedProgress(); - virtual void didChangeEstimatedProgress(); - virtual void postProgressStartedNotification(); - virtual void postProgressEstimateChangedNotification(); - virtual void postProgressFinishedNotification(); - - virtual void setMainFrameDocumentReady(bool); - - virtual void startDownload(const ResourceRequest&); - - virtual void willChangeTitle(DocumentLoader*); - virtual void didChangeTitle(DocumentLoader*); - - virtual void committedLoad(DocumentLoader*, const char*, int); - virtual void finishedLoading(DocumentLoader*); - virtual void finalSetupForReplace(DocumentLoader*); - - virtual void updateGlobalHistory(const KURL&); - virtual void updateGlobalHistoryForStandardLoad(const KURL&); - virtual void updateGlobalHistoryForReload(const KURL&); - virtual bool shouldGoToHistoryItem(HistoryItem*) const; -#ifdef ANDROID_HISTORY_CLIENT - virtual void dispatchDidAddHistoryItem(HistoryItem*) const; - virtual void dispatchDidRemoveHistoryItem(HistoryItem*, int) const; - virtual void dispatchDidChangeHistoryIndex(BackForwardList*) const; -#endif - - virtual ResourceError cancelledError(const ResourceRequest&); - virtual ResourceError blockedError(const ResourceRequest&); - virtual ResourceError cannotShowURLError(const ResourceRequest&); - virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&); - - virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&); - virtual ResourceError fileDoesNotExistError(const ResourceResponse&); - virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&); - - virtual bool shouldFallBack(const ResourceError&); - - virtual void setDefersLoading(bool); - - virtual bool willUseArchive(ResourceLoader*, const ResourceRequest&, const KURL& originalURL) const; - virtual bool isArchiveLoadPending(ResourceLoader*) const; - virtual void cancelPendingArchiveLoad(ResourceLoader*); - virtual void clearArchivedResources(); - - virtual bool canHandleRequest(const ResourceRequest&) const; - virtual bool canShowMIMEType(const String& MIMEType) const; - virtual bool representationExistsForURLScheme(const String& URLScheme) const; - virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const; - - virtual void frameLoadCompleted(); - virtual void saveViewStateToItem(HistoryItem*); - virtual void restoreViewState(); - virtual void provisionalLoadStarted(); - virtual void didFinishLoad(); - virtual void prepareForDataSourceReplacement(); - - virtual PassRefPtr createDocumentLoader(const ResourceRequest&, const SubstituteData&); - virtual void setTitle(const String& title, const KURL&); - - virtual String userAgent(const KURL&); - - virtual bool canCachePage() const; - virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&); - - virtual WTF::PassRefPtr createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, - const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); - virtual Widget* createPlugin(const IntSize&, Element*, const KURL&, - const WTF::Vector&, const WTF::Vector&, - const String&, bool); - virtual void redirectDataToPlugin(Widget* pluginWidget); - - virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, const Vector& paramNames, const Vector& paramValues); - - virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType); - virtual String overrideMediaType() const; - - virtual void windowObjectCleared(); - - virtual void didPerformFirstNavigation() const; - virtual void registerForIconNotification(bool listen = true); - - virtual void savePlatformDataToCachedPage(CachedPage*); - virtual void transitionToCommittedFromCachedPage(CachedPage*); - virtual void transitionToCommittedForNewPage(); - - // WebIconDatabaseClient api - virtual void didAddIconForPageUrl(const String& pageUrl); - - // FIXME: this doesn't really go here, but it's better than Frame - CacheBuilder& getCacheBuilder() { return m_cacheBuilder; } - private: - CacheBuilder m_cacheBuilder; - Frame* m_frame; - WebFrame* m_webFrame; - - enum ResourceErrors { - InternalErrorCancelled = -99, - InternalErrorCannotShowUrl, - InternalErrorInterrupted, - InternalErrorCannotShowMimeType, - InternalErrorFileDoesNotExist, - InternalErrorPluginWillHandleLoadError, - InternalErrorLast - }; - - /* XXX: These must match android.net.http.EventHandler */ - enum EventHandlerErrors { - Error = -1, - ErrorLookup = -2, - ErrorUnsupportedAuthScheme = -3, - ErrorAuth = -4, - ErrorProxyAuth = -5, - ErrorConnect = -6, - ErrorIO = -7, - ErrorTimeout = -8, - ErrorRedirectLoop = -9, - ErrorUnsupportedScheme = -10, - ErrorFailedSslHandshake = -11, - ErrorBadUrl = -12, - ErrorFile = -13, - ErrorFileNotFound = -14, - ErrorTooManyRequests = -15 - }; - friend class CacheBuilder; - }; - -} - -#endif diff --git a/WebKit/android/InspectorClientAndroid.h b/WebKit/android/InspectorClientAndroid.h deleted file mode 100644 index 9eb85e5..0000000 --- a/WebKit/android/InspectorClientAndroid.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2007, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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 THE COPYRIGHT HOLDERS ``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 InspectorClientAndroid_h -#define InspectorClientAndroid_h - -#include "InspectorClient.h" - -namespace android { - -class InspectorClientAndroid : public InspectorClient { -public: - virtual ~InspectorClientAndroid() { } - - virtual void inspectorDestroyed() { delete this; } - - virtual Page* createPage() { return NULL; } - - virtual String localizedStringsURL() { return String(); } - - virtual void showWindow() {} - virtual void closeWindow() {} - - virtual void attachWindow() {} - virtual void detachWindow() {} - - virtual void setAttachedWindowHeight(unsigned height) {} - - virtual void highlight(Node*) {} - virtual void hideHighlight() {} - - virtual void inspectedURLChanged(const String& newURL) {} - - // new as of 38068 - virtual void populateSetting(const String&, InspectorController::Setting&) {} - virtual void storeSetting(const String&, const InspectorController::Setting&) {} - virtual void removeSetting(const String&) {} -}; - -} - -#endif diff --git a/WebKit/android/RenderSkinCombo.h b/WebKit/android/RenderSkinCombo.h index 0970b6b..b5321ff 100644 --- a/WebKit/android/RenderSkinCombo.h +++ b/WebKit/android/RenderSkinCombo.h @@ -52,12 +52,12 @@ public: */ static bool Draw(SkCanvas* , Node* , int x, int y, int w, int h); - // The image is an extra 30 pixels wider than the RenderObject, so this accounts for that. + // The image is wider than the RenderObject, so this accounts for that. static int extraWidth() { return arrowMargin; } private: - static const int arrowMargin = 30; + static const int arrowMargin = 22; }; } // WebCore diff --git a/WebKit/android/RenderSkinRadio.cpp b/WebKit/android/RenderSkinRadio.cpp index 847de03..2fca175 100644 --- a/WebKit/android/RenderSkinRadio.cpp +++ b/WebKit/android/RenderSkinRadio.cpp @@ -24,11 +24,16 @@ */ #include "config.h" +#include "RenderSkinRadio.h" + +#include "android_graphics.h" #include "Document.h" +#include "IntRect.h" #include "Node.h" -#include "PlatformGraphicsContext.h" -#include "RenderSkinRadio.h" +#include "RenderSkinAndroid.h" +#include "SkBitmap.h" #include "SkCanvas.h" +#include "SkRect.h" static const char* checks[] = { "res/drawable/checkbox_off_background.png", "res/drawable/checkbox_on_background.png", "res/drawable/radiobutton_off_background.png", "res/drawable/radiobutton_on_background.png"}; @@ -36,55 +41,45 @@ static const SkScalar SIZE = SkIntToScalar(19); // Default height and width - co namespace WebCore { -SkBitmap RenderSkinRadio::m_bitmap[4]; -bool RenderSkinRadio::m_decoded; - -RenderSkinRadio::RenderSkinRadio(bool isCheckBox) -{ - m_checked = false; - m_enabled = true; - m_isCheckBox = isCheckBox; -} +static SkBitmap s_bitmap[4]; +static bool s_decoded; void RenderSkinRadio::Init(android::AssetManager* am) { - if (m_decoded) + if (s_decoded) return; - m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[0], &m_bitmap[0]); - m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[1], &m_bitmap[1]) && m_decoded; - m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[2], &m_bitmap[2]) && m_decoded; - m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[3], &m_bitmap[3]) && m_decoded; + s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[0], &s_bitmap[0]); + s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[1], &s_bitmap[1]) && s_decoded; + s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[2], &s_bitmap[2]) && s_decoded; + s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[3], &s_bitmap[3]) && s_decoded; } - -bool RenderSkinRadio::draw(PlatformGraphicsContext* pgc) +void RenderSkinRadio::Draw(SkCanvas* canvas, Node* element, const IntRect& ir, + bool isCheckBox) { - if (!m_decoded) // Seems like an unnecessary slowdown, since it should always decode - return false; - SkCanvas* canvas = pgc->mCanvas; - if (!m_enabled) { - SkRect r; - r.set(0, 0, m_size, m_size); - canvas->saveLayerAlpha(&r, 0x80); - } else { - canvas->save(); + if (!s_decoded || !element) { + return; } - if (SIZE != m_size) { - SkScalar scale = SkScalarDiv(m_size, SIZE); - canvas->scale(scale, scale); + SkRect r; + android_setrect(&r, ir); + int saveLayerCount = 0; + int saveScaleCount = 0; + if (!element->isEnabled()) { + saveLayerCount = canvas->saveLayerAlpha(&r, 0x80); } - canvas->drawBitmap(m_bitmap[m_checked + 2*(!m_isCheckBox)], 0, 0, &m_paint); - canvas->restore(); - return false; // True if we need to redraw -} - -void RenderSkinRadio::notifyState(Node* element) -{ - if (!element) { - return; + SkScalar width = r.width(); + if (SIZE != width) { + SkScalar scale = SkScalarDiv(width, SIZE); + saveScaleCount = canvas->scale(scale, scale); + } + canvas->drawBitmap(s_bitmap[element->isChecked() + 2*(!isCheckBox)], + r.fLeft, r.fTop, NULL); + if (saveLayerCount != 0) { + canvas->restoreToCount(saveLayerCount); + } else if (saveScaleCount != 0) { + canvas->restoreToCount(saveScaleCount); } - m_checked = element->isChecked(); - m_enabled = element->isEnabled(); + return; } } //WebCore diff --git a/WebKit/android/RenderSkinRadio.h b/WebKit/android/RenderSkinRadio.h index a1ca999..f70098f 100644 --- a/WebKit/android/RenderSkinRadio.h +++ b/WebKit/android/RenderSkinRadio.h @@ -26,41 +26,33 @@ #ifndef RenderSkinRadio_h #define RenderSkinRadio_h -#include "RenderSkinAndroid.h" -#include "SkBitmap.h" -#include "SkPaint.h" -#include "SkRect.h" +class SkCanvas; + +namespace android { + class AssetManager; +} namespace WebCore { class Node; +class IntRect; /* RenderSkin for a radio button or a checkbox */ -class RenderSkinRadio : public RenderSkinAndroid +class RenderSkinRadio { public: - /* This skin represents a checkbox if isCheckBox is true, otherwise it is a radio button */ - RenderSkinRadio(bool isCheckBox); - virtual ~RenderSkinRadio() {} - /** * Initialize the class before use. Uses the AssetManager to initialize any bitmaps the class may use. */ static void Init(android::AssetManager*); - virtual bool draw(PlatformGraphicsContext*); - virtual void notifyState(Node* element); - virtual void setDim(int width, int height) { RenderSkinAndroid::setDim(width, height); m_size = SkIntToScalar(height); } - -protected: - static SkBitmap m_bitmap[4]; // Bitmaps representing all states - static bool m_decoded; // True if all assets were decoded. - bool m_isCheckBox; - bool m_checked; - bool m_enabled; - SkPaint m_paint; - SkScalar m_size; + /** + * Draw the element to the canvas at the specified size and location. + * param isCheckBox If true, draws a checkbox. Else, draw a radio button. + */ + static void Draw(SkCanvas* canvas, Node* element, const IntRect&, + bool isCheckBox); }; } // WebCore diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp new file mode 100644 index 0000000..abc6a32 --- /dev/null +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -0,0 +1,257 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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. + */ + +#define LOG_TAG "WebCore" + +#include "config.h" + +#include "ChromeClientAndroid.h" +#include "CString.h" +#include "Document.h" +#include "PlatformString.h" +#include "FloatRect.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameView.h" +#include "Page.h" +#include "Screen.h" +#include "ScriptController.h" +#include "WebCoreFrameBridge.h" +#include "WebCoreViewBridge.h" +#include "WebViewCore.h" +#include "WindowFeatures.h" +#include "Settings.h" + +namespace android { + +void ChromeClientAndroid::setWebFrame(android::WebFrame* webframe) +{ + Release(m_webFrame); + m_webFrame = webframe; + Retain(m_webFrame); +} + +void ChromeClientAndroid::chromeDestroyed() +{ + Release(m_webFrame); + delete this; +} + +void ChromeClientAndroid::setWindowRect(const FloatRect&) { notImplemented(); } + +FloatRect ChromeClientAndroid::windowRect() { + ASSERT(m_webFrame); + if (!m_webFrame) + return FloatRect(); + FrameView* frameView = m_webFrame->page()->mainFrame()->view(); + if (!frameView) + return FloatRect(); + const WebCoreViewBridge* bridge = frameView->platformWidget(); + const IntRect& rect = bridge->getWindowBounds(); + FloatRect fRect(rect.x(), rect.y(), rect.width(), rect.height()); + return fRect; +} + +FloatRect ChromeClientAndroid::pageRect() { notImplemented(); return FloatRect(); } + +float ChromeClientAndroid::scaleFactor() +{ + // only seems to be used for dashboard regions, so just return 1 + return 1; +} + +void ChromeClientAndroid::focus() { + ASSERT(m_webFrame); + // Ask the application to focus this WebView. + m_webFrame->requestFocus(); +} +void ChromeClientAndroid::unfocus() { notImplemented(); } + +bool ChromeClientAndroid::canTakeFocus(FocusDirection) { notImplemented(); return false; } +void ChromeClientAndroid::takeFocus(FocusDirection) { notImplemented(); } + +Page* ChromeClientAndroid::createWindow(Frame* frame, const FrameLoadRequest&, + const WindowFeatures& features) +{ + ASSERT(frame); +#ifdef ANDROID_MULTIPLE_WINDOWS + if (frame->settings() && !(frame->settings()->supportMultipleWindows())) + // If the client doesn't support multiple windows, just return the current page + return frame->page(); +#endif + + WTF::PassRefPtr screen = WebCore::Screen::create(frame); + bool dialog = features.dialog || !features.resizable + || (features.heightSet && features.height < screen.get()->height() + && features.widthSet && features.width < screen.get()->width()) + || (!features.menuBarVisible && !features.statusBarVisible + && !features.toolBarVisible && !features.locationBarVisible + && !features.scrollbarsVisible); + // fullscreen definitely means no dialog + if (features.fullscreen) + dialog = false; + WebCore::Frame* newFrame = m_webFrame->createWindow(dialog, + frame->script()->processingUserGesture()); + if (newFrame) { + WebCore::Page* page = newFrame->page(); + page->setGroupName(frame->page()->groupName()); + return page; + } + return NULL; +} + +void ChromeClientAndroid::show() { notImplemented(); } + +bool ChromeClientAndroid::canRunModal() { notImplemented(); return false; } +void ChromeClientAndroid::runModal() { notImplemented(); } + +void ChromeClientAndroid::setToolbarsVisible(bool) { notImplemented(); } +bool ChromeClientAndroid::toolbarsVisible() { notImplemented(); return false; } + +void ChromeClientAndroid::setStatusbarVisible(bool) { notImplemented(); } +bool ChromeClientAndroid::statusbarVisible() { notImplemented(); return false; } + +void ChromeClientAndroid::setScrollbarsVisible(bool) { notImplemented(); } +bool ChromeClientAndroid::scrollbarsVisible() { notImplemented(); return false; } + +void ChromeClientAndroid::setMenubarVisible(bool) { notImplemented(); } +bool ChromeClientAndroid::menubarVisible() { notImplemented(); return false; } + +void ChromeClientAndroid::setResizable(bool) { notImplemented(); } + +// This function is called by the JavaScript bindings to print usually an error to +// a message console. +void ChromeClientAndroid::addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID) { + notImplemented(); + LOGD("Console: %s line: %d source: %s\n", message.latin1().data(), lineNumber, sourceID.latin1().data()); +} + +bool ChromeClientAndroid::canRunBeforeUnloadConfirmPanel() { return true; } +bool ChromeClientAndroid::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) { + String url = frame->document()->documentURI(); + return android::WebViewCore::getWebViewCore(frame->view())->jsUnload(url, message); +} + +void ChromeClientAndroid::closeWindowSoon() +{ + ASSERT(m_webFrame); + Page* page = m_webFrame->page(); + Frame* mainFrame = page->mainFrame(); + // This will prevent javascript cross-scripting during unload + page->setGroupName(String()); + // Stop loading but do not send the unload event + mainFrame->loader()->stopLoading(false); + // Cancel all pending loaders + mainFrame->loader()->stopAllLoaders(); + // Remove all event listeners so that no javascript can execute as a result + // of mouse/keyboard events. + mainFrame->document()->removeAllEventListenersFromAllNodes(); + // Close the window. + m_webFrame->closeWindow(android::WebViewCore::getWebViewCore(mainFrame->view())); +} + +void ChromeClientAndroid::runJavaScriptAlert(Frame* frame, const String& message) +{ + String url = frame->document()->documentURI(); + + android::WebViewCore::getWebViewCore(frame->view())->jsAlert(url, message); +} + +bool ChromeClientAndroid::runJavaScriptConfirm(Frame* frame, const String& message) +{ + String url = frame->document()->documentURI(); + + return android::WebViewCore::getWebViewCore(frame->view())->jsConfirm(url, message); +} + +/* This function is called for the javascript method Window.prompt(). A dialog should be shown on + * the screen with an input put box. First param is the text, the second is the default value for + * the input box, third is return param. If the function returns true, the value set in the third parameter + * is provided to javascript, else null is returned to the script. + */ +bool ChromeClientAndroid::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result) +{ + String url = frame->document()->documentURI(); + return android::WebViewCore::getWebViewCore(frame->view())->jsPrompt(url, message, defaultValue, result); +} +void ChromeClientAndroid::setStatusbarText(const String&) { notImplemented(); } + +// This is called by the JavaScript interpreter when a script has been running for a long +// time. A dialog should be shown to the user asking them if they would like to cancel the +// Javascript. If true is returned, the script is cancelled. +// To make a device more responsive, we default to return true to disallow long running script. +// This implies that some of scripts will not be completed. +bool ChromeClientAndroid::shouldInterruptJavaScript() { return true; } + +bool ChromeClientAndroid::tabsToLinks() const { return false; } + +IntRect ChromeClientAndroid::windowResizerRect() const { return IntRect(0, 0, 0, 0); } + +// new to change 38068 (Nov 6, 2008) +void ChromeClientAndroid::repaint(const IntRect& rect, bool contentChanged, + bool immediate, bool repaintContentOnly) { + notImplemented(); +// was in ScrollViewAndroid::update() : needs to be something like: +// android::WebViewCore::getWebViewCore(this)->contentInvalidate(rect); +} + +// new to change 38068 (Nov 6, 2008) +void ChromeClientAndroid::scroll(const IntSize& scrollDelta, + const IntRect& rectToScroll, const IntRect& clipRect) { + notImplemented(); +} + +// new to change 38068 (Nov 6, 2008) +IntPoint ChromeClientAndroid::screenToWindow(const IntPoint&) const { + notImplemented(); + return IntPoint(); +} + +// new to change 38068 (Nov 6, 2008) +IntRect ChromeClientAndroid::windowToScreen(const IntRect&) const { + notImplemented(); + return IntRect(); +} + +// new to change 38068 (Nov 6, 2008) +// in place of view()->containingWindow(), webkit now uses view()->hostWindow()->platformWindow() +PlatformWidget ChromeClientAndroid::platformWindow() const { + Page* page = m_webFrame->page(); + Frame* mainFrame = page->mainFrame(); + FrameView* view = mainFrame->view(); + PlatformWidget viewBridge = view->platformWidget(); + return viewBridge; +} + +void ChromeClientAndroid::mouseDidMoveOverElement(const HitTestResult&, unsigned int) {} +void ChromeClientAndroid::setToolTip(const String&) {} +void ChromeClientAndroid::print(Frame*) {} + +void ChromeClientAndroid::exceededDatabaseQuota(Frame*, const String&) {} + +// new to change 38068 (Nov 6, 2008) +void ChromeClientAndroid::runOpenPanel(Frame*, PassRefPtr) { notImplemented(); } + +} diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h new file mode 100644 index 0000000..60b3a8f --- /dev/null +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h @@ -0,0 +1,120 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 ChromeClientAndroid_h +#define ChromeClientAndroid_h + +#include "ChromeClient.h" + +using namespace WebCore; + +namespace android { + class WebFrame; + + class ChromeClientAndroid : public ChromeClient { + public: + ChromeClientAndroid() : m_webFrame(NULL) {} + virtual void chromeDestroyed(); + + virtual void setWindowRect(const FloatRect&); + virtual FloatRect windowRect(); + + virtual FloatRect pageRect(); + + virtual float scaleFactor(); + + virtual void focus(); + virtual void unfocus(); + + virtual bool canTakeFocus(FocusDirection); + virtual void takeFocus(FocusDirection); + + // The Frame pointer provides the ChromeClient with context about which + // Frame wants to create the new Page. Also, the newly created window + // should not be shown to the user until the ChromeClient of the newly + // created Page has its show method called. + virtual Page* createWindow(Frame*, const FrameLoadRequest&, const 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 String& message, unsigned int lineNumber, const String& sourceID); + + virtual bool canRunBeforeUnloadConfirmPanel(); + virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame); + + virtual void closeWindowSoon(); + + virtual void runJavaScriptAlert(Frame*, const String&); + virtual bool runJavaScriptConfirm(Frame*, const String&); + virtual bool runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result); + virtual void setStatusbarText(const String&); + virtual bool shouldInterruptJavaScript(); + virtual bool tabsToLinks() const; + + virtual IntRect windowResizerRect() const; + + // Methods used by HostWindow. + virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false); + virtual void scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); + virtual IntPoint screenToWindow(const IntPoint&) const; + virtual IntRect windowToScreen(const IntRect&) const; + virtual PlatformWidget platformWindow() const; + // End methods used by HostWindow. + + virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned int); + + virtual void setToolTip(const String&); + + virtual void print(Frame*); + + virtual void exceededDatabaseQuota(Frame*, const String&); + + virtual void runOpenPanel(Frame*, PassRefPtr); + + // Android-specific + void setWebFrame(android::WebFrame* webframe); + private: + android::WebFrame* m_webFrame; + }; + +} + +#endif diff --git a/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp new file mode 100644 index 0000000..7aabfc9 --- /dev/null +++ b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp @@ -0,0 +1,46 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 "ContextMenuClientAndroid.h" + +#include "NotImplemented.h" +#include + +namespace WebCore { + +void ContextMenuClientAndroid::contextMenuDestroyed() { delete this; } + +PlatformMenuDescription ContextMenuClientAndroid::getCustomMenuFromDefaultItems(ContextMenu*) { notImplemented(); return 0; } +void ContextMenuClientAndroid::contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) { notImplemented(); } + +void ContextMenuClientAndroid::downloadURL(const KURL& url) { notImplemented(); } +void ContextMenuClientAndroid::copyImageToClipboard(const HitTestResult&) { notImplemented(); } +void ContextMenuClientAndroid::searchWithGoogle(const Frame*) { notImplemented(); } +void ContextMenuClientAndroid::lookUpInDictionary(Frame*) { notImplemented(); } +void ContextMenuClientAndroid::speak(const String&) { notImplemented(); } +void ContextMenuClientAndroid::stopSpeaking() { notImplemented(); } + +} diff --git a/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h new file mode 100644 index 0000000..1860e4e --- /dev/null +++ b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h @@ -0,0 +1,50 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 ContextMenuClientAndroid_h +#define ContextMenuClientAndroid_h + +#include "ContextMenuClient.h" + +namespace WebCore { + +class ContextMenuClientAndroid : public ContextMenuClient { +public: + virtual void contextMenuDestroyed(); + + virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*); + virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*); + + virtual void downloadURL(const KURL& url); + virtual void copyImageToClipboard(const HitTestResult&); + virtual void searchWithGoogle(const Frame*); + virtual void lookUpInDictionary(Frame*); + virtual void speak(const String&); + virtual void stopSpeaking(); +}; + +} // namespace WebCore + +#endif // ContextMenuClientAndroid_h diff --git a/WebKit/android/WebCoreSupport/DragClientAndroid.cpp b/WebKit/android/WebCoreSupport/DragClientAndroid.cpp new file mode 100644 index 0000000..64406e7 --- /dev/null +++ b/WebKit/android/WebCoreSupport/DragClientAndroid.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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. + */ +#define LOG_TAG "WebCore" + +#include "config.h" +#include "DragClientAndroid.h" +#include "NotImplemented.h" + +namespace android { + +void DragClientAndroid::dragControllerDestroyed() { notImplemented(); delete this; } + +void DragClientAndroid::willPerformDragDestinationAction(DragDestinationAction, DragData*) { notImplemented(); } + +DragDestinationAction DragClientAndroid::actionMaskForDrag(DragData*) { notImplemented(); return DragDestinationActionNone; } + +DragSourceAction DragClientAndroid::dragSourceActionMaskForPoint(const IntPoint&) { notImplemented(); return DragSourceActionNone; } + +void* DragClientAndroid::createDragImageForLink(KURL&, String const&, Frame*) { return NULL; } +void DragClientAndroid::willPerformDragSourceAction(DragSourceAction, IntPoint const&, Clipboard*) {} +void DragClientAndroid::startDrag(void*, IntPoint const&, IntPoint const&, Clipboard*, Frame*, bool) {} + +} diff --git a/WebKit/android/WebCoreSupport/DragClientAndroid.h b/WebKit/android/WebCoreSupport/DragClientAndroid.h new file mode 100644 index 0000000..5f0548f --- /dev/null +++ b/WebKit/android/WebCoreSupport/DragClientAndroid.h @@ -0,0 +1,51 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 DragClientAndroid_h +#define DragClientAndroid_h + +#include "DragClient.h" + +using namespace WebCore; + +namespace android { + + class DragClientAndroid : public DragClient { + public: + virtual void willPerformDragDestinationAction(DragDestinationAction, DragData*); + virtual void willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*); + virtual DragDestinationAction actionMaskForDrag(DragData*); + //We work in window rather than view coordinates here + virtual DragSourceAction dragSourceActionMaskForPoint(const IntPoint&); + + virtual void startDrag(DragImageRef dragImage, const IntPoint& dragImageOrigin, const IntPoint& eventPos, Clipboard*, Frame*, bool linkDrag = false); + virtual DragImageRef createDragImageForLink(KURL&, const String& label, Frame*); + + virtual void dragControllerDestroyed(); + }; + +} + +#endif diff --git a/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp new file mode 100644 index 0000000..fb71fa2 --- /dev/null +++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp @@ -0,0 +1,241 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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. + */ +#define LOG_TAG "WebCore" + +#include "config.h" +#include "Editor.h" +#include "EditorClientAndroid.h" +#include "Event.h" +#include "EventNames.h" +#include "FocusController.h" +#include "Frame.h" +#include "KeyboardCodes.h" +#include "KeyboardEvent.h" +#include "NotImplemented.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformString.h" + +namespace android { + +void EditorClientAndroid::pageDestroyed() { + delete this; +} + +bool EditorClientAndroid::shouldDeleteRange(Range*) { return true; } +bool EditorClientAndroid::shouldShowDeleteInterface(HTMLElement*) { notImplemented(); return false; } +bool EditorClientAndroid::smartInsertDeleteEnabled() { notImplemented(); return false; } +bool EditorClientAndroid::isContinuousSpellCheckingEnabled() { notImplemented(); return false; } +void EditorClientAndroid::toggleContinuousSpellChecking() { notImplemented(); } +bool EditorClientAndroid::isGrammarCheckingEnabled() { notImplemented(); return false; } +void EditorClientAndroid::toggleGrammarChecking() { notImplemented(); } +int EditorClientAndroid::spellCheckerDocumentTag() { notImplemented(); return -1; } + +bool EditorClientAndroid::isEditable() { /* notImplemented(); */ return false; } + +// Following Qt's implementation. For shouldBeginEditing and shouldEndEditing. +// Returning true for these fixes issue http://b/issue?id=735185 +bool EditorClientAndroid::shouldBeginEditing(Range*) +{ + return true; +} + +bool EditorClientAndroid::shouldEndEditing(Range*) +{ + return true; +} + +bool EditorClientAndroid::shouldInsertNode(Node*, Range*, EditorInsertAction) { notImplemented(); return true; } +bool EditorClientAndroid::shouldInsertText(const String&, Range*, EditorInsertAction) { return true; } +bool EditorClientAndroid::shouldApplyStyle(CSSStyleDeclaration*, Range*) { notImplemented(); return true; } + +void EditorClientAndroid::didBeginEditing() { notImplemented(); } + +// This function is called so that the platform can handle changes to content. It is called +// after the contents have been edited or unedited (ie undo) +void EditorClientAndroid::respondToChangedContents() { notImplemented(); } + +void EditorClientAndroid::didEndEditing() { notImplemented(); } +void EditorClientAndroid::didWriteSelectionToPasteboard() { notImplemented(); } +void EditorClientAndroid::didSetSelectionTypesForPasteboard() { notImplemented(); } + +// Copied from the Window's port of WebKit. +static const unsigned AltKey = 1 << 0; +static const unsigned ShiftKey = 1 << 1; + +struct KeyDownEntry { + unsigned virtualKey; + unsigned modifiers; + const char* name; +}; + +struct KeyPressEntry { + unsigned charCode; + unsigned modifiers; + const char* name; +}; + +static const KeyDownEntry keyDownEntries[] = { + { VK_LEFT, 0, "MoveLeft" }, + { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, + { VK_LEFT, AltKey, "MoveWordLeft" }, + { VK_LEFT, AltKey | ShiftKey, "MoveWordLeftAndModifySelection" }, + { VK_RIGHT, 0, "MoveRight" }, + { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, + { VK_RIGHT, AltKey, "MoveWordRight" }, + { VK_RIGHT, AltKey | ShiftKey, "MoveWordRightAndModifySelection" }, + { VK_UP, 0, "MoveUp" }, + { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, + { VK_DOWN, 0, "MoveDown" }, + { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, + + { VK_BACK, 0, "BackwardDelete" }, + { VK_BACK, ShiftKey, "ForwardDelete" }, + { VK_BACK, AltKey, "DeleteWordBackward" }, + { VK_BACK, AltKey | ShiftKey, "DeleteWordForward" }, + + { VK_ESCAPE, 0, "Cancel" }, + { VK_TAB, 0, "InsertTab" }, + { VK_TAB, ShiftKey, "InsertBacktab" }, + { VK_RETURN, 0, "InsertNewline" }, + { VK_RETURN, AltKey, "InsertNewline" }, + { VK_RETURN, AltKey | ShiftKey, "InsertNewline" } +}; + +static const KeyPressEntry keyPressEntries[] = { + { '\t', 0, "InsertTab" }, + { '\t', ShiftKey, "InsertBackTab" }, + { '\r', 0, "InsertNewline" }, + { '\r', AltKey, "InsertNewline" }, + { '\r', AltKey | ShiftKey, "InsertNewline" } +}; + +static const char* interpretKeyEvent(const KeyboardEvent* evt) +{ + const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); + + static HashMap* keyDownCommandsMap = 0; + static HashMap* keyPressCommandsMap = 0; + + if (!keyDownCommandsMap) { + keyDownCommandsMap = new HashMap; + keyPressCommandsMap = new HashMap; + + for (unsigned i = 0; i < sizeof(keyDownEntries)/sizeof(KeyDownEntry); i++) + keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); + + for (unsigned i = 0; i < sizeof(keyPressEntries)/sizeof(KeyPressEntry); i++) + keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); + } + + unsigned modifiers = 0; + if (keyEvent->shiftKey()) + modifiers |= ShiftKey; + if (keyEvent->altKey()) + modifiers |= AltKey; + + if (evt->type() == eventNames().keydownEvent) { + int mapKey = modifiers << 16 | evt->keyCode(); + return mapKey ? keyDownCommandsMap->get(mapKey) : 0; + } + + int mapKey = modifiers << 16 | evt->charCode(); + return mapKey ? keyPressCommandsMap->get(mapKey) : 0; +} + +void EditorClientAndroid::handleKeyboardEvent(KeyboardEvent* event) { + ASSERT(m_page); + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + const PlatformKeyboardEvent* keyEvent = event->keyEvent(); + // TODO: If the event is not coming from Android Java, e.g. from JavaScript, + // PlatformKeyboardEvent is null. We should support this later. + if (!keyEvent) + return; + + Editor::Command command = frame->editor()->command(interpretKeyEvent(event)); + if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) { + if (!command.isTextInsertion() && command.execute(event)) { + // This function mimics the Windows version. However, calling event->setDefaultHandled() + // prevents the javascript key events for the delete key from happening. + // Update: Safari doesn't send delete key events to javascript so + // we will mimic that behavior. + event->setDefaultHandled(); + } + return; + } + + if (command.execute(event)) { + event->setDefaultHandled(); + return; + } + + // Don't insert null or control characters as they can result in unexpected behaviour + if (event->charCode() < ' ') + return; + + if (frame->editor()->insertText(keyEvent->text(), event)) + event->setDefaultHandled(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +// we just don't support Undo/Redo at the moment + +void EditorClientAndroid::registerCommandForUndo(PassRefPtr) {} +void EditorClientAndroid::registerCommandForRedo(PassRefPtr) {} +void EditorClientAndroid::clearUndoRedoOperations() {} +bool EditorClientAndroid::canUndo() const { return false; } +bool EditorClientAndroid::canRedo() const { return false; } +void EditorClientAndroid::undo() {} +void EditorClientAndroid::redo() {} + +// functions new to Jun-07 tip of tree merge: +void EditorClientAndroid::showSpellingUI(bool) {} +void EditorClientAndroid::getGuessesForWord(String const&, Vector&) {} +bool EditorClientAndroid::spellingUIIsShowing() { return false; } +void EditorClientAndroid::checkGrammarOfString(unsigned short const*, int, Vector&, int*, int*) {} +void EditorClientAndroid::checkSpellingOfString(unsigned short const*, int, int*, int*) {} +void EditorClientAndroid::textFieldDidEndEditing(Element*) {} +void EditorClientAndroid::textDidChangeInTextArea(Element*) {} +void EditorClientAndroid::textDidChangeInTextField(Element*) {} +void EditorClientAndroid::textFieldDidBeginEditing(Element*) {} +void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {} +void EditorClientAndroid::respondToChangedSelection() {} +bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool) { return m_notFromClick; } +bool EditorClientAndroid::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; } +void EditorClientAndroid::textWillBeDeletedInTextField(Element*) {} +void EditorClientAndroid::updateSpellingUIWithGrammarString(String const&, GrammarDetail const&) {} +void EditorClientAndroid::updateSpellingUIWithMisspelledWord(String const&) {} +void EditorClientAndroid::learnWord(String const&) {} + +// functions new to the Nov-16-08 tip of tree merge: +bool EditorClientAndroid::shouldMoveRangeAfterDelete(Range*, Range*) { return true; } +void EditorClientAndroid::setInputMethodState(bool) {} + +// functions new to Feb-19 tip of tree merge: +void EditorClientAndroid::handleInputMethodKeydown(KeyboardEvent*) {} + +} diff --git a/WebKit/android/WebCoreSupport/EditorClientAndroid.h b/WebKit/android/WebCoreSupport/EditorClientAndroid.h new file mode 100644 index 0000000..fc35761 --- /dev/null +++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.h @@ -0,0 +1,113 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 EditorClientAndroid_h +#define EditorClientAndroid_h + +#include "EditorClient.h" +#include "Page.h" + +using namespace WebCore; + +namespace android { + +class EditorClientAndroid : public EditorClient { +public: + EditorClientAndroid() { m_notFromClick = true; } + virtual void pageDestroyed(); + + virtual bool shouldDeleteRange(Range*); + virtual bool shouldShowDeleteInterface(HTMLElement*); + virtual bool smartInsertDeleteEnabled(); + virtual bool isContinuousSpellCheckingEnabled(); + virtual void toggleContinuousSpellChecking(); + virtual bool isGrammarCheckingEnabled(); + virtual void toggleGrammarChecking(); + virtual int spellCheckerDocumentTag(); + + virtual bool isEditable(); + + virtual bool shouldBeginEditing(Range*); + virtual bool shouldEndEditing(Range*); + virtual bool shouldInsertNode(Node*, Range*, EditorInsertAction); + virtual bool shouldInsertText(const String&, Range*, EditorInsertAction); + virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting); + + virtual bool shouldApplyStyle(CSSStyleDeclaration*, Range*); +// virtual bool shouldChangeTypingStyle(CSSStyleDeclaration* fromStyle, CSSStyleDeclaration* toStyle); +// virtual bool doCommandBySelector(SEL selector); + + virtual void didBeginEditing(); + virtual void respondToChangedContents(); + virtual void respondToChangedSelection(); + virtual void didEndEditing(); + virtual void didWriteSelectionToPasteboard(); + virtual void didSetSelectionTypesForPasteboard(); +// virtual void didChangeTypingStyle:(NSNotification *)notification; +// virtual void didChangeSelection:(NSNotification *)notification; +// virtual NSUndoManager* undoManager:(WebView *)webView; + + virtual void registerCommandForUndo(PassRefPtr); + virtual void registerCommandForRedo(PassRefPtr); + virtual void clearUndoRedoOperations(); + + virtual bool canUndo() const; + virtual bool canRedo() const; + + virtual void undo(); + virtual void redo(); + + virtual void textFieldDidBeginEditing(Element*); + virtual void textFieldDidEndEditing(Element*); + virtual void textDidChangeInTextField(Element*); + virtual bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*); + virtual void textWillBeDeletedInTextField(Element*); + virtual void textDidChangeInTextArea(Element*); + + virtual void ignoreWordInSpellDocument(const String&); + virtual void learnWord(const String&); + virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength); + virtual void checkGrammarOfString(const UChar*, int length, Vector&, int* badGrammarLocation, int* badGrammarLength); + virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail); + virtual void updateSpellingUIWithMisspelledWord(const String&); + virtual void showSpellingUI(bool show); + virtual bool spellingUIIsShowing(); + virtual void getGuessesForWord(const String&, Vector& guesses); + virtual bool shouldMoveRangeAfterDelete(Range*, Range*); + virtual void setInputMethodState(bool); + + virtual void handleKeyboardEvent(KeyboardEvent*); + virtual void handleInputMethodKeydown(KeyboardEvent*); + // Android specific: + void setPage(Page* page) { m_page = page; } + void setFromClick(bool fromClick) { m_notFromClick = !fromClick; } +private: + Page* m_page; + bool m_notFromClick; +}; + +} + +#endif diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp new file mode 100644 index 0000000..93dcdf4 --- /dev/null +++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp @@ -0,0 +1,1105 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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. + */ +#define LOG_TAG "WebCore" + +#include "config.h" + +#include "android_graphics.h" +#include "CString.h" +#include "DocumentLoader.h" +#include "FrameLoader.h" +#include "FrameLoaderClientAndroid.h" +#include "FrameTree.h" +#include "GraphicsContext.h" +// HTMLFormElement needed for a bad include +#include "HTMLFormElement.h" +#include "HTMLFrameOwnerElement.h" +#include "IconDatabase.h" +#include "MIMETypeRegistry.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PlatformGraphicsContext.h" +#include "PlatformString.h" +#include "PluginDatabase.h" +#include "PluginView.h" +#ifdef ANDROID_PLUGINS +// Removed. +#else +#include "PluginViewBridgeAndroid.h" +#endif +#include "ProgressTracker.h" +#include "RenderPart.h" +#include "ResourceError.h" +#include "SelectionController.h" +#include "SkCanvas.h" +#include "SkRect.h" +#include "TextEncoding.h" +#include "Document.h" +#include "FrameView.h" +#include "HistoryItem.h" +#include "ResourceHandle.h" +#include "ResourceHandleInternal.h" +#include "WebCoreFrameBridge.h" +#include "WebCoreResourceLoader.h" +#include "WebHistory.h" +#include "WebIconDatabase.h" +#include "WebFrameView.h" +#include "WebViewCore.h" +#include "Settings.h" + +#include + +extern android::AssetManager* globalAssetManager(); + +namespace android { + +static const int EXTRA_LAYOUT_DELAY = 1000; + +// FIXME: Need some data for how big this should be. +#define MAX_SESSION_HISTORY 50 +static WTF::Vector gSessionHistory; + +bool historyContains(const UChar* chars, unsigned len) { + const KURL url(String(chars, len)); + WTF::Vector::const_iterator end = gSessionHistory.end(); + for (WTF::Vector::const_iterator i = gSessionHistory.begin(); i != end; ++i) { + if (equalIgnoringRef(url, *i)) + return true; + } + return false; +} + +FrameLoaderClientAndroid::FrameLoaderClientAndroid(WebFrame* webframe) + : m_frame(NULL) + , m_webFrame(webframe) { + Retain(m_webFrame); +} + +FrameLoaderClientAndroid* FrameLoaderClientAndroid::get(const WebCore::Frame* frame) +{ + return static_cast (frame->loader()->client()); +} + +void FrameLoaderClientAndroid::frameLoaderDestroyed() { + registerForIconNotification(false); + m_frame = 0; + Release(m_webFrame); + delete this; +} + +bool FrameLoaderClientAndroid::hasWebView() const { + // FIXME, + // there is one web view per page, or top frame. + // as android's view is created from Java side, it is always there. + return true; +} + +bool FrameLoaderClientAndroid::hasFrameView() const { + // FIXME, + // need to revisit for sub-frame case + return true; +} + +bool FrameLoaderClientAndroid::privateBrowsingEnabled() const { + // FIXME, are we going to support private browsing? + notImplemented(); + return false; +} + +void FrameLoaderClientAndroid::makeRepresentation(DocumentLoader*) { + // don't use representation + verifiedOk(); +} + +void FrameLoaderClientAndroid::forceLayout() { + ASSERT(m_frame); + m_frame->forceLayout(); + // FIXME, should we adjust view size here? + m_frame->view()->adjustViewSize(); +} + +void FrameLoaderClientAndroid::forceLayoutForNonHTML() { + notImplemented(); +} + +void FrameLoaderClientAndroid::setCopiesOnScroll() { + // this is a hint about whether we need to force redraws, or can + // just copy the scrolled content. Since we always force a redraw + // anyways, we can ignore this call. + verifiedOk(); +} + +void FrameLoaderClientAndroid::detachedFromParent2() { + // FIXME, ready to detach frame from view +} + +void FrameLoaderClientAndroid::detachedFromParent3() { + // FIXME, ready to release view + notImplemented(); +} + +void FrameLoaderClientAndroid::detachedFromParent4() { + // FIXME, ready to release view + notImplemented(); +} + +void FrameLoaderClientAndroid::loadedFromPageCache() { + // don't support page cache + verifiedOk(); +} + +// This function is responsible for associating the "id" with a given +// subresource load. The following functions that accept an "id" are +// called for each subresource, so they should not be dispatched to the m_frame. +void FrameLoaderClientAndroid::assignIdentifierToInitialRequest(unsigned long id, + DocumentLoader*, const ResourceRequest&) { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchWillSendRequest(DocumentLoader*, unsigned long id, + ResourceRequest&, const ResourceResponse&) { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, + unsigned long id, const AuthenticationChallenge&) { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, + unsigned long id, const AuthenticationChallenge&) { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidReceiveResponse(DocumentLoader*, + unsigned long id, const ResourceResponse&) { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidReceiveContentLength(DocumentLoader*, + unsigned long id, int lengthReceived) { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidFinishLoading(DocumentLoader*, + unsigned long id) { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidFailLoading(DocumentLoader* docLoader, + unsigned long id, const ResourceError&) { + lowPriority_notImplemented(); +} + +bool FrameLoaderClientAndroid::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, + const ResourceRequest&, const ResourceResponse&, int length) { + notImplemented(); + return false; +} + +void FrameLoaderClientAndroid::dispatchDidHandleOnloadEvents() { +} + +void FrameLoaderClientAndroid::dispatchDidReceiveServerRedirectForProvisionalLoad() { + ASSERT(m_frame); + // Tell the load it was a redirect. + m_webFrame->loadStarted(m_frame); +} + +void FrameLoaderClientAndroid::dispatchDidCancelClientRedirect() { + notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchWillPerformClientRedirect(const KURL&, + double interval, double fireDate) { + notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidChangeLocationWithinPage() { + notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchWillClose() { + notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidReceiveIcon() { + ASSERT(m_frame); + if (m_frame->tree() && m_frame->tree()->parent()) + return; + WebCore::String url(m_frame->loader()->url().string()); + // Try to obtain the icon image. + WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL( + url, WebCore::IntSize(16, 16)); + // If the request fails, try the original request url. + if (!icon) + icon = WebCore::iconDatabase()->iconForPageURL( + m_frame->loader()->originalRequestURL().string(), + WebCore::IntSize(16, 16)); + // There is a bug in webkit where cancelling an icon load is treated as a + // failure. When this is fixed, we can ASSERT again that we have an icon. + if (icon) { + LOGV("Received icon (%p) for %s", icon, + url.utf8().data()); + m_webFrame->didReceiveIcon(icon); + } else { + LOGV("Icon data for %s unavailable, registering for notification...", + url.utf8().data()); + registerForIconNotification(); + } +} + +void FrameLoaderClientAndroid::dispatchDidStartProvisionalLoad() { + notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidReceiveTitle(const String& title) { + ASSERT(m_frame); + // Used to check for FrameLoadTypeStandard but we only want to send the title for + // the top frame and not sub-frames. + if (!m_frame->tree() || !m_frame->tree()->parent()) { + m_webFrame->setTitle(title); + } +} + +void FrameLoaderClientAndroid::dispatchDidCommitLoad() { + ASSERT(m_frame); + WebViewCore::getWebViewCore(m_frame->view())->updateFrameGeneration(m_frame); +} + +static void loadDataIntoFrame(Frame* frame, const String& url, + const String& data) { + ResourceRequest request(url); + CString cstr = data.utf8(); + RefPtr buf = WebCore::SharedBuffer::create(cstr.data(), cstr.length()); + SubstituteData subData(buf, String("text/html"), String("utf-8"), + request.url()); + frame->loader()->load(request, subData); +} + +void FrameLoaderClientAndroid::dispatchDidFailProvisionalLoad(const ResourceError& error) { + ASSERT(m_frame); + // Ignore ErrorInterrupted since it is due to a policy interruption. This + // is caused by a decision to download the main resource rather than + // display it. + if (error.errorCode() == InternalErrorInterrupted + || error.errorCode() == InternalErrorCancelled) { + // If we decided to download the main resource or if the user cancelled + // it, make sure we report that the load is done. + didFinishLoad(); + return; + } + + AssetManager* am = globalAssetManager(); + + // Check to see if the error code was not generated internally + WebFrame::RAW_RES_ID id = WebFrame::NODOMAIN; + if ((error.errorCode() == ErrorFile || + error.errorCode() == ErrorFileNotFound) && + (!error.localizedDescription().isEmpty())) { + id = WebFrame::LOADERROR; + } + String filename = m_webFrame->getRawResourceFilename(id); + if (filename.isEmpty()) + return; + + // Grab the error page from the asset manager + Asset* a = am->openNonAsset( + filename.utf8().data(), Asset::ACCESS_BUFFER); + if (!a) + return; + + // Take the failing url and encode html entities so javascript urls are not + // executed. + CString failingUrl = error.failingURL().utf8(); + WTF::Vector url; + int len = failingUrl.length(); + const char* data = failingUrl.data(); + for (int i = 0; i < len; i++) { + char c = data[i]; + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9')) + url.append(c); + else { + char buf[16]; + int res = sprintf(buf, "&#%d;", c); + buf[res] = 0; + url.append(buf, res); + } + } + + // Replace all occurances of %s with the failing url. + String s = UTF8Encoding().decode((const char*)a->getBuffer(false), a->getLength()); + s = s.replace("%s", String(url.data(), url.size())); + + // Replace all occurances of %e with the error text + s = s.replace("%e", error.localizedDescription()); + + // Create the request and the substitute data and tell the FrameLoader to + // load with the replacement data. + loadDataIntoFrame(m_frame, error.failingURL(), s); + + // Delete the asset. + delete a; +} + +void FrameLoaderClientAndroid::dispatchDidFailLoad(const ResourceError&) { + // called when page is completed with error + didFinishLoad(); +} + +void FrameLoaderClientAndroid::dispatchDidFinishDocumentLoad() { + // called when finishedParsing + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDidFinishLoad() { + didFinishLoad(); +} + +void FrameLoaderClientAndroid::dispatchDidFirstLayout() { + ASSERT(m_frame); + m_frame->document()->setExtraLayoutDelay(EXTRA_LAYOUT_DELAY); + // FIXME: Need to figure out if we need didLayout or didFirstLayout + // see WebViewCore::didLayout + if (!m_frame->tree()->parent()) { + // Only need to notify Java side for the top frame + WebViewCore::getWebViewCore(m_frame->view())->didFirstLayout(); + } +} + +Frame* FrameLoaderClientAndroid::dispatchCreatePage() { + ASSERT(m_frame); +#ifdef ANDROID_MULTIPLE_WINDOWS + if (m_frame->settings() && m_frame->settings()->supportMultipleWindows()) + // Always a user gesture since window.open maps to + // ChromeClientAndroid::createWindow + return m_webFrame->createWindow(false, true); + else +#endif + // If the client doesn't support multiple windows, just replace the + // current frame's contents. + return m_frame; +} + +void FrameLoaderClientAndroid::dispatchShow() { + ASSERT(m_frame); + m_frame->view()->invalidate(); +} + + +static bool TreatAsAttachment(const String& content_disposition) { + // Some broken sites just send + // Content-Disposition: ; filename="file" + // screen those out here. + if (content_disposition.startsWith(";")) + return false; + + if (content_disposition.startsWith("inline", false)) + return false; + + // Some broken sites just send + // Content-Disposition: filename="file" + // without a disposition token... screen those out. + if (content_disposition.startsWith("filename", false)) + return false; + + // Also in use is Content-Disposition: name="file" + if (content_disposition.startsWith("name", false)) + return false; + + // We have a content-disposition of "attachment" or unknown. + // RFC 2183, section 2.8 says that an unknown disposition + // value should be treated as "attachment" + return true; +} + +void FrameLoaderClientAndroid::dispatchDecidePolicyForMIMEType(FramePolicyFunction func, + const String& MIMEType, const ResourceRequest&) { + ASSERT(m_frame); + ASSERT(func); + // Default to Use (display internally). + PolicyAction action = PolicyUse; + // Check if we should Download instead. + const ResourceResponse& response = m_frame->loader()->activeDocumentLoader()->response(); + const String& content_disposition = response.httpHeaderField("Content-Disposition"); + if (!content_disposition.isEmpty()) { + // Server wants to override our normal policy. + if (TreatAsAttachment(content_disposition)) { + // Check to see if we are a sub frame (main frame has no owner element) + if (m_frame->ownerElement() != 0) + action = PolicyIgnore; + else + action = PolicyDownload; + } + } else { + // Ask if it can be handled internally. + if (!canShowMIMEType(MIMEType)) { + // Check to see if we are a sub frame (main frame has no owner element) + if (m_frame->ownerElement() != 0) + action = PolicyIgnore; + else + action = PolicyDownload; + } + } + // A status code of 204 indicates no content change. Ignore the result. + WebCore::DocumentLoader* docLoader = m_frame->loader()->activeDocumentLoader(); + if (docLoader->response().httpStatusCode() == 204) + action = PolicyIgnore; + (m_frame->loader()->*func)(action); +} + +void FrameLoaderClientAndroid::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction func, + const NavigationAction&, const ResourceRequest& req, + PassRefPtr formState, const String& frameName) { + ASSERT(m_frame); + // If we get to this point it means that a link has a target that was not + // found by the frame tree. Instead of creating a new frame, return the + // current frame in dispatchCreatePage. + if (canHandleRequest(req)) + (m_frame->loader()->*func)(PolicyUse); + else + (m_frame->loader()->*func)(PolicyIgnore); +} + +void FrameLoaderClientAndroid::cancelPolicyCheck() { + lowPriority_notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchUnableToImplementPolicy(const ResourceError&) { + notImplemented(); +} + +void FrameLoaderClientAndroid::dispatchDecidePolicyForNavigationAction(FramePolicyFunction func, + const NavigationAction& action, const ResourceRequest& request, + PassRefPtr formState) { + ASSERT(m_frame); + ASSERT(func); + if (action.type() == NavigationTypeFormResubmitted) { + m_webFrame->decidePolicyForFormResubmission(func); + return; + } else { + (m_frame->loader()->*func)(PolicyUse); + } +} + +void FrameLoaderClientAndroid::dispatchWillSubmitForm(FramePolicyFunction func, PassRefPtr) { + ASSERT(m_frame); + ASSERT(func); + (m_frame->loader()->*func)(PolicyUse); +} + +void FrameLoaderClientAndroid::dispatchDidLoadMainResource(DocumentLoader*) { + notImplemented(); +} + +void FrameLoaderClientAndroid::revertToProvisionalState(DocumentLoader*) { + notImplemented(); +} + +void FrameLoaderClientAndroid::setMainDocumentError(DocumentLoader* docLoader, const ResourceError& error) { + ASSERT(m_frame); + if (!error.isNull() && error.errorCode() >= InternalErrorLast) + m_webFrame->reportError(error.errorCode(), + error.localizedDescription(), error.failingURL()); +} + +void FrameLoaderClientAndroid::clearUnarchivingState(DocumentLoader*) { + notImplemented(); +} + +// This function is called right before the progress is updated. +void FrameLoaderClientAndroid::willChangeEstimatedProgress() { + verifiedOk(); +} + +// This function is called after the progress has been updated. The bad part +// about this is that when a page is completed, this function is called after +// the progress has been reset to 0. +void FrameLoaderClientAndroid::didChangeEstimatedProgress() { + verifiedOk(); +} + +// This will give us the initial estimate when the page first starts to load. +void FrameLoaderClientAndroid::postProgressStartedNotification() { + ASSERT(m_frame); + if (m_frame->page()) + m_webFrame->setProgress(m_frame->page()->progress()->estimatedProgress()); +} + +// This will give us any updated progress including the final progress. +void FrameLoaderClientAndroid::postProgressEstimateChangedNotification() { + ASSERT(m_frame); + if (m_frame->page()) + m_webFrame->setProgress(m_frame->page()->progress()->estimatedProgress()); +} + +// This is just a notification that the progress has finished. Don't call +// setProgress(1) because postProgressEstimateChangedNotification will do so. +void FrameLoaderClientAndroid::postProgressFinishedNotification() { + if (!m_frame->tree()->parent()) { + // only need to notify Java for the top frame + WebViewCore::getWebViewCore(m_frame->view())->notifyProgressFinished(); + } +} + +void FrameLoaderClientAndroid::setMainFrameDocumentReady(bool) { + // this is only interesting once we provide an external API for the DOM + notImplemented(); +} + +void FrameLoaderClientAndroid::startDownload(const ResourceRequest&) { + notImplemented(); +} + +void FrameLoaderClientAndroid::willChangeTitle(DocumentLoader*) { + verifiedOk(); +} + +void FrameLoaderClientAndroid::didChangeTitle(DocumentLoader* loader) { + verifiedOk(); +} + +void FrameLoaderClientAndroid::finishedLoading(DocumentLoader* docLoader) { + // 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) + committedLoad(docLoader, 0, 0); +} + +void FrameLoaderClientAndroid::finalSetupForReplace(DocumentLoader*) { + notImplemented(); +} + +void FrameLoaderClientAndroid::updateGlobalHistoryForStandardLoad(const KURL& url) { + ASSERT(m_frame); + const String& str = url.string(); + if (!historyContains(str.characters(), str.length())) { + if (gSessionHistory.size() == MAX_SESSION_HISTORY) + gSessionHistory.remove(0); + gSessionHistory.append(url); + } + m_webFrame->updateVisitedHistory(url, false); +} + +void FrameLoaderClientAndroid::updateGlobalHistoryForReload(const KURL& url) { + ASSERT(m_frame); + m_webFrame->updateVisitedHistory(url, true); +} + +bool FrameLoaderClientAndroid::shouldGoToHistoryItem(HistoryItem* item) const { + // hmmm, seems like we might do a more thoughtful check + ASSERT(m_frame); + return item != NULL; +} + +void FrameLoaderClientAndroid::committedLoad(DocumentLoader* loader, const char* data, int length) { + ASSERT(m_frame); + String encoding = loader->overrideEncoding(); + bool userChosen = !encoding.isNull(); + if (encoding.isNull()) + encoding = loader->response().textEncodingName(); + loader->frameLoader()->setEncoding(encoding, userChosen); + Document *doc = m_frame->document(); + if (doc) { + loader->frameLoader()->addData(data, length); + } +} + +ResourceError FrameLoaderClientAndroid::cancelledError(const ResourceRequest& request) { + return ResourceError(String(), InternalErrorCancelled, String(), String()); +} + +ResourceError FrameLoaderClientAndroid::cannotShowURLError(const ResourceRequest& request) { + return ResourceError(String(), InternalErrorCannotShowUrl, String(), String()); +} + +ResourceError FrameLoaderClientAndroid::interruptForPolicyChangeError(const ResourceRequest& request) { + return ResourceError(String(), InternalErrorInterrupted, String(), String()); +} + +ResourceError FrameLoaderClientAndroid::cannotShowMIMETypeError(const ResourceResponse& request) { + return ResourceError(String(), InternalErrorCannotShowMimeType, String(), String()); +} + +ResourceError FrameLoaderClientAndroid::fileDoesNotExistError(const ResourceResponse& request) { + return ResourceError(String(), InternalErrorFileDoesNotExist, String(), String()); +} + +ResourceError FrameLoaderClientAndroid::pluginWillHandleLoadError(const ResourceResponse& request) { + return ResourceError(String(), InternalErrorPluginWillHandleLoadError, String(), String()); +} + +bool FrameLoaderClientAndroid::shouldFallBack(const ResourceError&) { + notImplemented(); + return false; +} + +void FrameLoaderClientAndroid::setDefersLoading(bool) { + notImplemented(); +} + +bool FrameLoaderClientAndroid::willUseArchive(ResourceLoader*, const ResourceRequest&, + const KURL& originalURL) const { + lowPriority_notImplemented(); + return false; +} + +bool FrameLoaderClientAndroid::isArchiveLoadPending(ResourceLoader*) const { + lowPriority_notImplemented(); + return false; +} + +void FrameLoaderClientAndroid::cancelPendingArchiveLoad(ResourceLoader*) { + notImplemented(); +} + +void FrameLoaderClientAndroid::clearArchivedResources() { + notImplemented(); +} + +bool FrameLoaderClientAndroid::canHandleRequest(const ResourceRequest& request) const { + ASSERT(m_frame); + // Don't allow hijacking of intrapage navigation + if (WebCore::equalIgnoringRef(request.url(), m_frame->loader()->url())) + return true; + + // Don't allow hijacking of iframe urls that are http or https + if (request.url().protocol().startsWith("http", false) && + m_frame->tree() && m_frame->tree()->parent()) + return true; + + if (m_webFrame->canHandleRequest(request)) { +#ifdef ANDROID_META_SUPPORT + // reset metadata settings for the top frame as they are not preserved cross page + if (!m_frame->tree()->parent() && m_frame->settings()) + m_frame->settings()->resetMetadataSettings(); +#endif + return true; + } + return false; +} + +bool FrameLoaderClientAndroid::canShowMIMEType(const String& mimeType) const { + // FIXME: This looks like it has to do with whether or not a type can be + // shown "internally" (i.e. inside the browser) regardless of whether + // or not the browser is doing the rendering, e.g. a full page plugin. + if (MIMETypeRegistry::isSupportedImageResourceMIMEType(mimeType) || + MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType) || + MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) || + PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) + return true; + return false; +} + +bool FrameLoaderClientAndroid::representationExistsForURLScheme(const String&) const { + // don't use representation + verifiedOk(); + return false; +} + +String FrameLoaderClientAndroid::generatedMIMETypeForURLScheme(const String& URLScheme) const { + // FIXME, copy from Apple's port + String mimetype("x-apple-web-kit/"); + mimetype.append(URLScheme.lower()); + return mimetype; +} + +void FrameLoaderClientAndroid::frameLoadCompleted() { + // copied from Apple port, without this back with sub-frame will trigger ASSERT + ASSERT(m_frame); + m_frame->loader()->setPreviousHistoryItem(0); +} + +void FrameLoaderClientAndroid::saveViewStateToItem(HistoryItem* item) { +#ifdef ANDROID_HISTORY_CLIENT + ASSERT(m_frame); + ASSERT(item); + // We should have added a bridge when the child item was added to its + // parent. + WebHistoryItem* bridge = item->bridge(); + ASSERT(bridge); + // store the current scale (only) for the top frame + if (!m_frame->tree()->parent()) { + bridge->setScale(WebViewCore::getWebViewCore(m_frame->view())->scale()); + } + + WebCore::notifyHistoryItemChanged(item); +#endif +} + +void FrameLoaderClientAndroid::restoreViewState() { +#ifdef ANDROID_HISTORY_CLIENT + WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view()); + HistoryItem* item = m_frame->loader()->currentHistoryItem(); + // restore the scale (only) for the top frame + if (!m_frame->tree()->parent()) { + webViewCore->restoreScale(item->bridge()->scale()); + } +#endif +} + +#ifdef ANDROID_HISTORY_CLIENT +void FrameLoaderClientAndroid::dispatchDidAddHistoryItem(HistoryItem* item) const { + ASSERT(m_frame); + m_webFrame->addHistoryItem(item); +} + +void FrameLoaderClientAndroid::dispatchDidRemoveHistoryItem(HistoryItem* item, int index) const { + ASSERT(m_frame); + m_webFrame->removeHistoryItem(index); +} + +void FrameLoaderClientAndroid::dispatchDidChangeHistoryIndex( + BackForwardList* list) const { + ASSERT(m_frame); + m_webFrame->updateHistoryIndex(list->backListCount()); +} +#endif + +void FrameLoaderClientAndroid::provisionalLoadStarted() { + ASSERT(m_frame); + m_webFrame->loadStarted(m_frame); +} + +void FrameLoaderClientAndroid::didFinishLoad() { + ASSERT(m_frame); + m_frame->document()->setExtraLayoutDelay(0); + m_webFrame->didFinishLoad(m_frame); +} + +void FrameLoaderClientAndroid::prepareForDataSourceReplacement() { + ASSERT(m_frame); + m_frame->loader()->detachChildren(); +} + +PassRefPtr FrameLoaderClientAndroid::createDocumentLoader( + const ResourceRequest& request, const SubstituteData& data) { + RefPtr loader = DocumentLoader::create(request, data); + return loader.release(); +} + +void FrameLoaderClientAndroid::setTitle(const String& title, const KURL& url) { + // Not needed. dispatchDidReceiveTitle is called immediately after this. + // url is used to update the Apple port history items. + verifiedOk(); +} + +String FrameLoaderClientAndroid::userAgent(const KURL& u) { + return m_webFrame->userAgentForURL(&u); +} + +bool FrameLoaderClientAndroid::canCachePage() const { + return true; +} + +void FrameLoaderClientAndroid::download(ResourceHandle* handle, const ResourceRequest&, + const ResourceRequest&, const ResourceResponse&) { + // Get the C++ side of the load listener and tell it to handle the download + WebCoreResourceLoader* loader = handle->getInternal()->m_loader; + loader->downloadFile(); +} + +WTF::PassRefPtr FrameLoaderClientAndroid::createFrame(const KURL& url, const String& name, + HTMLFrameOwnerElement* ownerElement, const String& referrer, + bool allowsScrolling, int marginWidth, int marginHeight) +{ + Frame* parent = ownerElement->document()->frame(); + FrameLoaderClientAndroid* loaderC = new FrameLoaderClientAndroid(m_webFrame); + RefPtr pFrame = Frame::create(parent->page(), ownerElement, loaderC); + Frame* newFrame = pFrame.get(); + loaderC->setFrame(newFrame); + // Append the subframe to the parent and set the name of the subframe. The name must be set after + // appending the child so that the name becomes unique. + parent->tree()->appendChild(newFrame); + newFrame->tree()->setName(name); + // Create a new FrameView and WebFrameView for the child frame to draw into. + FrameView* frameView = new WebCore::FrameView(newFrame); + WebFrameView* webFrameView = new WebFrameView(frameView, + WebViewCore::getWebViewCore(parent->view())); + // frameView Retains webFrameView, so call Release for webFrameView + Release(webFrameView); + // Attach the frameView to the newFrame. + newFrame->setView(frameView); + // setView() refs the frameView so call deref on the frameView + frameView->deref(); + newFrame->init(); + newFrame->selection()->setFocused(true); + LOGV("::WebCore:: createSubFrame returning %p", newFrame); + + // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. + if (!pFrame->page()) + return 0; + + parent->loader()->loadURLIntoChildFrame(url, referrer, pFrame.get()); + + // onLoad may cuase the frame to be removed from the document. Allow the RefPtr to delete the child frame. + if (!pFrame->tree()->parent()) + return NULL; + + return pFrame.release(); +} + +// YouTube flash url path starts with /v/ +static const char slash_v_slash[] = { '/', 'v', '/' }; + +static bool isValidYouTubeVideo(const String& path) +{ + if (!charactersAreAllASCII(path.characters(), path.length())) + return false; + unsigned int len = path.length(); + if (len <= sizeof(slash_v_slash)) // check for more than just /v/ + return false; + CString str = path.lower().utf8(); + const char* data = str.data(); + if (memcmp(data, slash_v_slash, sizeof(slash_v_slash)) != 0) + return false; + // Start after /v/ + for (unsigned int i = sizeof(slash_v_slash); i < len; i++) { + char c = data[i]; + // Check for alpha-numeric characters only. + if (WTF::isASCIIAlphanumeric(c)) + continue; + // The url can have more parameters such as &hl=en after the video id. + // Once we start seeing extra parameters we can return true. + return c == '&' && i > sizeof(slash_v_slash); + } + return true; +} + +static bool isYouTubeUrl(const KURL& url, const String& mimeType) +{ + return url.host().endsWith("youtube.com") && isValidYouTubeVideo(url.path()) + && equalIgnoringCase(mimeType, "application/x-shockwave-flash"); +} + +Widget* FrameLoaderClientAndroid::createPlugin( + const IntSize& size, + Element* element, + const KURL& url, + const WTF::Vector& names, + const WTF::Vector& values, + const String& mimeType, + bool loadManually) { + // Create an iframe for youtube urls. + if (isYouTubeUrl(url, mimeType)) { + RefPtr frame = createFrame(KURL(), String(), + static_cast(element), + String(), false, 0, 0); + if (frame) { + // grab everything after /v/ + String videoId = url.path().substring(sizeof(slash_v_slash)); + // Extract just the video id + unsigned videoIdEnd = 0; + for (; videoIdEnd < videoId.length(); videoIdEnd++) { + if (videoId[videoIdEnd] == '&') { + videoId = videoId.left(videoIdEnd); + break; + } + } + AssetManager* am = globalAssetManager(); + Asset* a = am->open("webkit/youtube.html", + Asset::ACCESS_BUFFER); + if (!a) + return NULL; + String s = String((const char*)a->getBuffer(false), a->getLength()); + s = s.replace("VIDEO_ID", videoId); + delete a; + loadDataIntoFrame(frame.get(), + "file:///android_asset/webkit/", s); + return frame->view(); + } + return NULL; + } +#ifdef ANDROID_PLUGINS + return PluginView::create(m_frame, + size, + element, + url, + names, + values, + mimeType, + loadManually); +#else + return NULL; +#endif +} + +void FrameLoaderClientAndroid::redirectDataToPlugin(Widget* pluginWidget) { + // don't support plugin yet + notImplemented(); +} + +Widget* FrameLoaderClientAndroid::createJavaAppletWidget(const IntSize&, Element*, + const KURL& baseURL, const WTF::Vector& paramNames, + const WTF::Vector& paramValues) { + // don't support widget yet + notImplemented(); + return 0; +} + +// This function is used by the element to determine the type of +// the contents and work out if it can render it. +ObjectContentType FrameLoaderClientAndroid::objectContentType(const KURL& url, + const String& mimeType) { + if (mimeType.length() == 0) + { + // Guess the mimeType from the extension + if (url.hasPath()) + { + String path = url.path(); + int lastIndex = path.reverseFind('.'); + static const String image("image/"); + if (lastIndex >= 0) + { + String mime(path.substring(lastIndex + 1)); + mime.insert(image, 0); + if (Image::supportsType(mime)) + return ObjectContentImage; + } + } + return ObjectContentFrame; + } + if (equalIgnoringCase(mimeType, "text/html") || + equalIgnoringCase(mimeType, "text/xml") || + equalIgnoringCase(mimeType, "text/") || + equalIgnoringCase(mimeType, "application/xml") || + equalIgnoringCase(mimeType, "application/xhtml+xml") || + equalIgnoringCase(mimeType, "application/x-javascript")) + return ObjectContentFrame; + if (Image::supportsType(mimeType)) + return ObjectContentImage; + return ObjectContentNone; +} + +// This function allows the application to set the correct CSS media +// style. Android could use it to set the media style 'handheld'. Safari +// may use it to set the media style to 'print' when the user wants to print +// a particular web page. +String FrameLoaderClientAndroid::overrideMediaType() const { + lowPriority_notImplemented(); + return String(); +} + +// This function is used to re-attach Javascript<->native code classes. +void FrameLoaderClientAndroid::windowObjectCleared() { + ASSERT(m_frame); + LOGV("::WebCore:: windowObjectCleared called on frame %p for %s\n", + m_frame, m_frame->loader()->url().string().ascii().data()); + m_webFrame->windowObjectCleared(m_frame); +} + +// functions new to Jun-07 tip of tree merge: +ResourceError FrameLoaderClientAndroid::blockedError(ResourceRequest const& request) { + return ResourceError(String(), InternalErrorFileDoesNotExist, String(), String()); +} + +// functions new to Nov-07 tip of tree merge: +void FrameLoaderClientAndroid::didPerformFirstNavigation() const { + // This seems to be just a notification that the UI can listen to, to + // know if the user has performed first navigation action. + // It is called from + // void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip) + // "Navigation" here means a transition from one page to another that + // ends up in the back/forward list. +} + +void FrameLoaderClientAndroid::registerForIconNotification(bool listen) { + if (listen) + WebIconDatabase::RegisterForIconNotification(this); + else + WebIconDatabase::UnregisterForIconNotification(this); +} + +// This is the WebIconDatabaseClient method for receiving a notification when we +// get the icon for the page. +void FrameLoaderClientAndroid::didAddIconForPageUrl(const String& pageUrl) { + // This call must happen before dispatchDidReceiveIcon since that method + // may register for icon notifications again since the icon data may have + // to be read from disk. + registerForIconNotification(false); + KURL u(pageUrl); + if (equalIgnoringRef(u, m_frame->loader()->url())) { + dispatchDidReceiveIcon(); + } +} + +// functions new to Feb-19 tip of tree merge: +// According to the changelog: +// The very Mac-centric "makeDocumentView", "setDocumentViewFromCachedPage", +// and "saveDocumentViewToCachedPage" become "transitionToCommittedForNewPage", +// "transitionToCommittedFromCachedPage", and "savePlatformDataToCachedPage" +// accordingly +void FrameLoaderClientAndroid::savePlatformDataToCachedPage(CachedPage*) { + // don't support page cache + verifiedOk(); +} + +void FrameLoaderClientAndroid::transitionToCommittedFromCachedPage(CachedPage*) { + // don't support page cache + verifiedOk(); +} + +void FrameLoaderClientAndroid::transitionToCommittedForNewPage() { + ASSERT(m_frame); + if (m_frame->settings() && !m_frame->settings()->usesPageCache()) { + m_webFrame->transitionToCommitted(m_frame); + return; + } + + // Remember the old WebFrameView + WebFrameView* webFrameView = static_cast ( + m_frame->view()->platformWidget()); + Retain(webFrameView); + + // Remove the old FrameView + m_frame->setView(NULL); + + // Create a new FrameView and associate it with the saved webFrameView + FrameView* view = new FrameView(m_frame); + webFrameView->setView(view); + + Release(webFrameView); + + // Give the new FrameView to the Frame + m_frame->setView(view); + + // Deref since FrameViews are created with a ref of 1 + view->deref(); + + if (m_frame->ownerRenderer()) + m_frame->ownerRenderer()->setWidget(view); + + m_frame->view()->initScrollbars(); + + m_webFrame->transitionToCommitted(m_frame); +} + +// new as of webkit 34152 +void FrameLoaderClientAndroid::updateGlobalHistory(const KURL& url) { + m_webFrame->updateVisitedHistory(url, false); +} + +} diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h new file mode 100644 index 0000000..58b296e --- /dev/null +++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h @@ -0,0 +1,242 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 FrameLoaderClientAndroid_h +#define FrameLoaderClientAndroid_h + +#include "CacheBuilder.h" +#include "FrameLoaderClient.h" +#include "ResourceResponse.h" +#include "WebIconDatabase.h" + +using namespace WebCore; + +namespace android { + class WebFrame; + + class FrameLoaderClientAndroid : public FrameLoaderClient, + WebIconDatabaseClient { + public: + FrameLoaderClientAndroid(WebFrame* webframe); + + Frame* getFrame() { return m_frame; } + static FrameLoaderClientAndroid* get(const Frame* frame); + + void setFrame(Frame* frame) { m_frame = frame; } + WebFrame* webFrame() const { return m_webFrame; } + + virtual void frameLoaderDestroyed(); + + virtual bool hasWebView() const; // mainly for assertions + virtual bool hasFrameView() const; // ditto + + virtual bool privateBrowsingEnabled() const; + + virtual void makeRepresentation(DocumentLoader*); + virtual void forceLayout(); + virtual void forceLayoutForNonHTML(); + + virtual void setCopiesOnScroll(); + + virtual void detachedFromParent2(); + virtual void detachedFromParent3(); + virtual void detachedFromParent4(); + + virtual void loadedFromPageCache(); + + virtual void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); + + virtual void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); + virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); + virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&); + virtual void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); + virtual void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived); + virtual void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier); + virtual void dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&); + virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length); + + virtual void dispatchDidHandleOnloadEvents(); + virtual void dispatchDidReceiveServerRedirectForProvisionalLoad(); + virtual void dispatchDidCancelClientRedirect(); + virtual void dispatchWillPerformClientRedirect(const KURL&, double interval, double fireDate); + virtual void dispatchDidChangeLocationWithinPage(); + virtual void dispatchWillClose(); + virtual void dispatchDidReceiveIcon(); + virtual void dispatchDidStartProvisionalLoad(); + virtual void dispatchDidReceiveTitle(const String& title); + virtual void dispatchDidCommitLoad(); + virtual void dispatchDidFailProvisionalLoad(const ResourceError&); + virtual void dispatchDidFailLoad(const ResourceError&); + virtual void dispatchDidFinishDocumentLoad(); + virtual void dispatchDidFinishLoad(); + virtual void dispatchDidFirstLayout(); + + virtual Frame* dispatchCreatePage(); + virtual void dispatchShow(); + + virtual void dispatchDecidePolicyForMIMEType(FramePolicyFunction, const String& MIMEType, const ResourceRequest&); + virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr, const String& frameName); + virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr); + virtual void cancelPolicyCheck(); + + virtual void dispatchUnableToImplementPolicy(const ResourceError&); + + virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr); + + virtual void dispatchDidLoadMainResource(DocumentLoader*); + virtual void revertToProvisionalState(DocumentLoader*); + virtual void setMainDocumentError(DocumentLoader*, const ResourceError&); + virtual void clearUnarchivingState(DocumentLoader*); + + virtual void willChangeEstimatedProgress(); + virtual void didChangeEstimatedProgress(); + virtual void postProgressStartedNotification(); + virtual void postProgressEstimateChangedNotification(); + virtual void postProgressFinishedNotification(); + + virtual void setMainFrameDocumentReady(bool); + + virtual void startDownload(const ResourceRequest&); + + virtual void willChangeTitle(DocumentLoader*); + virtual void didChangeTitle(DocumentLoader*); + + virtual void committedLoad(DocumentLoader*, const char*, int); + virtual void finishedLoading(DocumentLoader*); + virtual void finalSetupForReplace(DocumentLoader*); + + virtual void updateGlobalHistory(const KURL&); + virtual void updateGlobalHistoryForStandardLoad(const KURL&); + virtual void updateGlobalHistoryForReload(const KURL&); + virtual bool shouldGoToHistoryItem(HistoryItem*) const; +#ifdef ANDROID_HISTORY_CLIENT + virtual void dispatchDidAddHistoryItem(HistoryItem*) const; + virtual void dispatchDidRemoveHistoryItem(HistoryItem*, int) const; + virtual void dispatchDidChangeHistoryIndex(BackForwardList*) const; +#endif + + virtual ResourceError cancelledError(const ResourceRequest&); + virtual ResourceError blockedError(const ResourceRequest&); + virtual ResourceError cannotShowURLError(const ResourceRequest&); + virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&); + + virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&); + virtual ResourceError fileDoesNotExistError(const ResourceResponse&); + virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&); + + virtual bool shouldFallBack(const ResourceError&); + + virtual void setDefersLoading(bool); + + virtual bool willUseArchive(ResourceLoader*, const ResourceRequest&, const KURL& originalURL) const; + virtual bool isArchiveLoadPending(ResourceLoader*) const; + virtual void cancelPendingArchiveLoad(ResourceLoader*); + virtual void clearArchivedResources(); + + virtual bool canHandleRequest(const ResourceRequest&) const; + virtual bool canShowMIMEType(const String& MIMEType) const; + virtual bool representationExistsForURLScheme(const String& URLScheme) const; + virtual String generatedMIMETypeForURLScheme(const String& URLScheme) const; + + virtual void frameLoadCompleted(); + virtual void saveViewStateToItem(HistoryItem*); + virtual void restoreViewState(); + virtual void provisionalLoadStarted(); + virtual void didFinishLoad(); + virtual void prepareForDataSourceReplacement(); + + virtual PassRefPtr createDocumentLoader(const ResourceRequest&, const SubstituteData&); + virtual void setTitle(const String& title, const KURL&); + + virtual String userAgent(const KURL&); + + virtual bool canCachePage() const; + virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&); + + virtual WTF::PassRefPtr createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, + const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight); + virtual Widget* createPlugin(const IntSize&, Element*, const KURL&, + const WTF::Vector&, const WTF::Vector&, + const String&, bool); + virtual void redirectDataToPlugin(Widget* pluginWidget); + + virtual Widget* createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL, const Vector& paramNames, const Vector& paramValues); + + virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType); + virtual String overrideMediaType() const; + + virtual void windowObjectCleared(); + + virtual void didPerformFirstNavigation() const; + virtual void registerForIconNotification(bool listen = true); + + virtual void savePlatformDataToCachedPage(CachedPage*); + virtual void transitionToCommittedFromCachedPage(CachedPage*); + virtual void transitionToCommittedForNewPage(); + + // WebIconDatabaseClient api + virtual void didAddIconForPageUrl(const String& pageUrl); + + // FIXME: this doesn't really go here, but it's better than Frame + CacheBuilder& getCacheBuilder() { return m_cacheBuilder; } + private: + CacheBuilder m_cacheBuilder; + Frame* m_frame; + WebFrame* m_webFrame; + + enum ResourceErrors { + InternalErrorCancelled = -99, + InternalErrorCannotShowUrl, + InternalErrorInterrupted, + InternalErrorCannotShowMimeType, + InternalErrorFileDoesNotExist, + InternalErrorPluginWillHandleLoadError, + InternalErrorLast + }; + + /* XXX: These must match android.net.http.EventHandler */ + enum EventHandlerErrors { + Error = -1, + ErrorLookup = -2, + ErrorUnsupportedAuthScheme = -3, + ErrorAuth = -4, + ErrorProxyAuth = -5, + ErrorConnect = -6, + ErrorIO = -7, + ErrorTimeout = -8, + ErrorRedirectLoop = -9, + ErrorUnsupportedScheme = -10, + ErrorFailedSslHandshake = -11, + ErrorBadUrl = -12, + ErrorFile = -13, + ErrorFileNotFound = -14, + ErrorTooManyRequests = -15 + }; + friend class CacheBuilder; + }; + +} + +#endif diff --git a/WebKit/android/WebCoreSupport/InspectorClientAndroid.h b/WebKit/android/WebCoreSupport/InspectorClientAndroid.h new file mode 100644 index 0000000..9eb85e5 --- /dev/null +++ b/WebKit/android/WebCoreSupport/InspectorClientAndroid.h @@ -0,0 +1,64 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 InspectorClientAndroid_h +#define InspectorClientAndroid_h + +#include "InspectorClient.h" + +namespace android { + +class InspectorClientAndroid : public InspectorClient { +public: + virtual ~InspectorClientAndroid() { } + + virtual void inspectorDestroyed() { delete this; } + + virtual Page* createPage() { return NULL; } + + virtual String localizedStringsURL() { return String(); } + + virtual void showWindow() {} + virtual void closeWindow() {} + + virtual void attachWindow() {} + virtual void detachWindow() {} + + virtual void setAttachedWindowHeight(unsigned height) {} + + virtual void highlight(Node*) {} + virtual void hideHighlight() {} + + virtual void inspectedURLChanged(const String& newURL) {} + + // new as of 38068 + virtual void populateSetting(const String&, InspectorController::Setting&) {} + virtual void storeSetting(const String&, const InspectorController::Setting&) {} + virtual void removeSetting(const String&) {} +}; + +} + +#endif diff --git a/WebKit/android/jni/PictureSet.cpp b/WebKit/android/jni/PictureSet.cpp index 6f57c67..410769e 100644 --- a/WebKit/android/jni/PictureSet.cpp +++ b/WebKit/android/jni/PictureSet.cpp @@ -76,9 +76,9 @@ void PictureSet::add(const Pictures* temp) void PictureSet::add(const SkRegion& area, SkPicture* picture, uint32_t elapsed, bool split) { - DBG_SET_LOGD("%p {%d,%d,r=%d,b=%d} elapsed=%d split=%d", this, + DBG_SET_LOGD("%p area={%d,%d,r=%d,b=%d} pict=%p elapsed=%d split=%d", this, area.getBounds().fLeft, area.getBounds().fTop, - area.getBounds().fRight, area.getBounds().fBottom, + area.getBounds().fRight, area.getBounds().fBottom, picture, elapsed, split); picture->safeRef(); /* if nothing is drawn beneath part of the new picture, mark it as a base */ @@ -207,7 +207,7 @@ void PictureSet::checkDimensions(int width, int height, SkRegion* inval) void PictureSet::clear() { - // dump(__FUNCTION__); + DBG_SET_LOG(""); Pictures* last = mPictures.end(); for (Pictures* working = mPictures.begin(); working != last; working++) { working->mArea.setEmpty(); @@ -219,7 +219,6 @@ void PictureSet::clear() bool PictureSet::draw(SkCanvas* canvas) { - DBG_SET_LOG(""); validate(__FUNCTION__); Pictures* first = mPictures.begin(); Pictures* last = mPictures.end(); @@ -242,7 +241,7 @@ bool PictureSet::draw(SkCanvas* canvas) break; } } - DBG_SET_LOGD("first=%d last=%d", first - mPictures.begin(), + DBG_SET_LOGD("%p first=%d last=%d", this, first - mPictures.begin(), last - mPictures.begin()); uint32_t maxElapsed = 0; for (working = first; working != last; working++) { @@ -309,20 +308,32 @@ bool PictureSet::draw(SkCanvas* canvas) void PictureSet::dump(const char* label) const { #if PICTURE_SET_DUMP - DBG_SET_LOGD("%p %s (%d)", this, label, mPictures.size()); + DBG_SET_LOGD("%p %s (%d) (w=%d,h=%d)", this, label, mPictures.size(), + mWidth, mHeight); const Pictures* last = mPictures.end(); for (const Pictures* working = mPictures.begin(); working != last; working++) { const SkIRect& bounds = working->mArea.getBounds(); + const SkIRect& unsplit = working->mUnsplit; MeasureStream measure; if (working->mPicture != NULL) working->mPicture->serialize(&measure); - LOGD(" [%d] {%d,%d,r=%d,b=%d} elapsed=%d split=%s" - " wroteElapsed=%s base=%s pictSize=%d", + LOGD(" [%d]" + " mArea.bounds={%d,%d,r=%d,b=%d}" + " mPicture=%p" + " mUnsplit={%d,%d,r=%d,b=%d}" + " mElapsed=%d" + " mSplit=%s" + " mWroteElapsed=%s" + " mBase=%s" + " pict-size=%d", working - mPictures.begin(), bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, + working->mPicture, + unsplit.fLeft, unsplit.fTop, unsplit.fRight, unsplit.fBottom, working->mElapsed, working->mSplit ? "true" : "false", - working->mWroteElapsed ? "true" : "false", - working->mBase ? "true" : "false", measure.mTotal); + working->mWroteElapsed ? "true" : "false", + working->mBase ? "true" : "false", + measure.mTotal); } #endif } @@ -465,7 +476,7 @@ bool PictureSet::reuseSubdivided(const SkRegion& inval) void PictureSet::set(const PictureSet& src) { - DBG_SET_LOG("start"); + DBG_SET_LOGD("start %p src=%p", this, &src); clear(); mWidth = src.mWidth; mHeight = src.mHeight; @@ -514,55 +525,35 @@ void PictureSet::setPicture(size_t i, SkPicture* p) void PictureSet::split(PictureSet* out) const { dump(__FUNCTION__); + DBG_SET_LOGD("%p", this); SkIRect totalBounds; out->mWidth = mWidth; out->mHeight = mHeight; totalBounds.set(0, 0, mWidth, mHeight); SkRegion* total = new SkRegion(totalBounds); const Pictures* last = mPictures.end(); + const Pictures* working; uint32_t balance = 0; - bool firstTime = true; - const Pictures* singleton = NULL; - int singleOut = -1; - for (const Pictures* working = mPictures.begin(); working != last; working++) { + int multiUnsplitFastPictures = 0; // > 1 has more than 1 + for (working = mPictures.begin(); working != last; working++) { + if (working->mElapsed >= MAX_DRAW_TIME || working->mSplit) + continue; + if (++multiUnsplitFastPictures > 1) + break; + } + for (working = mPictures.begin(); working != last; working++) { uint32_t elapsed = working->mElapsed; if (elapsed < MAX_DRAW_TIME) { - if (working->mSplit) { + bool split = working->mSplit; + DBG_SET_LOGD("elapsed=%d working=%p total->getBounds()=" + "{%d,%d,r=%d,b=%d} split=%s", elapsed, working, + total->getBounds().fLeft, total->getBounds().fTop, + total->getBounds().fRight, total->getBounds().fBottom, + split ? "true" : "false"); + if (multiUnsplitFastPictures <= 1 || split) { total->op(working->mArea, SkRegion::kDifference_Op); - DBG_SET_LOGD("%p total->getBounds()={%d,%d,r=%d,b=%d", this, - total->getBounds().fLeft, total->getBounds().fTop, - total->getBounds().fRight, total->getBounds().fBottom); - singleOut = out->mPictures.end() - out->mPictures.begin(); - out->add(working->mArea, working->mPicture, elapsed, true); - continue; - } - if (firstTime) { - singleton = working; - DBG_SET_LOGD("%p firstTime working=%p working->mArea=" - "{%d,%d,r=%d,b=%d}", this, working, - working->mArea.getBounds().fLeft, - working->mArea.getBounds().fTop, - working->mArea.getBounds().fRight, - working->mArea.getBounds().fBottom); - out->add(working->mArea, working->mPicture, elapsed, false); - firstTime = false; - } else { - if (singleOut >= 0) { - Pictures& outWork = out->mPictures[singleOut]; - DBG_SET_LOGD("%p clear singleton outWork=%p outWork->mArea=" - "{%d,%d,r=%d,b=%d}", this, &outWork, - outWork.mArea.getBounds().fLeft, - outWork.mArea.getBounds().fTop, - outWork.mArea.getBounds().fRight, - outWork.mArea.getBounds().fBottom); - outWork.mArea.setEmpty(); - outWork.mPicture->safeUnref(); - outWork.mPicture = NULL; - singleOut = -1; - } - singleton = NULL; - } - if (balance < elapsed) + out->add(working->mArea, working->mPicture, elapsed, split); + } else if (balance < elapsed) balance = elapsed; continue; } @@ -600,9 +591,10 @@ void PictureSet::split(PictureSet* out) const top = bottom; } } - DBG_SET_LOGD("%p w=%d h=%d total->isEmpty()=%s singleton=%p", - this, mWidth, mHeight, total->isEmpty() ? "true" : "false", singleton); - if (total->isEmpty() == false && singleton == NULL) + DBG_SET_LOGD("%p w=%d h=%d total->isEmpty()=%s multiUnsplitFastPictures=%d", + this, mWidth, mHeight, total->isEmpty() ? "true" : "false", + multiUnsplitFastPictures); + if (!total->isEmpty() && multiUnsplitFastPictures > 1) out->add(*total, NULL, balance, false); delete total; validate(__FUNCTION__); diff --git a/WebKit/android/jni/PictureSet.h b/WebKit/android/jni/PictureSet.h index 17a7b25..ce94fc0 100644 --- a/WebKit/android/jni/PictureSet.h +++ b/WebKit/android/jni/PictureSet.h @@ -57,7 +57,7 @@ namespace android { virtual ~PictureSet(); void add(const SkRegion& area, SkPicture* picture, uint32_t elapsed, bool split); - const SkIRect& bounds(size_t i) { + const SkIRect& bounds(size_t i) const { return mPictures[i].mArea.getBounds(); } bool build(); // Update mWidth/mHeight, and adds any additional inval region @@ -71,10 +71,10 @@ namespace android { void set(const PictureSet& ); void setDrawTimes(const PictureSet& ); void setPicture(size_t i, SkPicture* p); - size_t size() { return mPictures.size(); } + size_t size() const { return mPictures.size(); } void split(PictureSet* result) const; void toPicture(SkPicture* ) const; - bool upToDate(size_t i) { return mPictures[i].mPicture != NULL; } + bool upToDate(size_t i) const { return mPictures[i].mPicture != NULL; } int width() const { return mWidth; } void dump(const char* label) const; bool validate(const char* label) const; diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index 860109b..e14a534 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -687,6 +687,9 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss InspectorClientAndroid* inspectorC = new InspectorClientAndroid; // Create a new page WebCore::Page* page = new WebCore::Page(chromeC, contextMenuC, editorC, dragC, inspectorC); + // css files without explicit MIMETYPE is treated as generic text files in + // the Java side. So we can't enforce CSS MIMETYPE. + page->settings()->setEnforceCSSMIMETypeInStrictMode(false); /* TODO: Don't turn on PageCache until we can restore the ScrollView State. * This caused bug http://b/issue?id=1202983 page->settings()->setUsesPageCache(true); diff --git a/WebKit/android/jni/WebHistory.cpp b/WebKit/android/jni/WebHistory.cpp index 028d62e..8a75230 100644 --- a/WebKit/android/jni/WebHistory.cpp +++ b/WebKit/android/jni/WebHistory.cpp @@ -231,10 +231,7 @@ jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector& v, WebCore::Histo return NULL; // Write our flattened data to the java array. - jbyte* bytes = env->GetByteArrayElements(b, NULL); - if (bytes) - memcpy(bytes, v.data(), v.size()); - env->ReleaseByteArrayElements(b, bytes, 0); + env->SetByteArrayRegion(b, 0, v.size(), (const jbyte*)v.data()); return b; } diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 64bfd8f..12dc9ef 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -280,6 +280,7 @@ void WebViewCore::reset(bool fromConstructor) m_useReplay = false; m_skipContentDraw = false; m_findIsUp = false; + m_domtree_version = 0; } static bool layoutIfNeededRecursive(WebCore::Frame* f) @@ -382,16 +383,19 @@ void WebViewCore::recordPictureSet(PictureSet* content) m_frameCacheOutOfDate = true; WebCore::IntRect oldBounds = oldFocusNode ? oldFocusNode->getRect() : WebCore::IntRect(0,0,0,0); - DBG_NAV_LOGD_THROTTLE("m_lastFocused=%p oldFocusNode=%p" + DBG_NAV_LOGD("m_lastFocused=%p oldFocusNode=%p" " m_lastFocusedBounds={%d,%d,%d,%d} oldBounds={%d,%d,%d,%d}", m_lastFocused, oldFocusNode, m_lastFocusedBounds.x(), m_lastFocusedBounds.y(), m_lastFocusedBounds.width(), m_lastFocusedBounds.height(), oldBounds.x(), oldBounds.y(), oldBounds.width(), oldBounds.height()); + unsigned latestVersion = m_mainFrame->document()->domTreeVersion(); if (m_lastFocused != oldFocusNode || m_lastFocusedBounds != oldBounds - || m_findIsUp) { + || m_findIsUp || latestVersion != m_domtree_version) { m_lastFocused = oldFocusNode; m_lastFocusedBounds = oldBounds; - DBG_NAV_LOG("call updateFrameCache"); + DBG_NAV_LOGD("call updateFrameCache m_domtree_version=%d latest=%d", + m_domtree_version, latestVersion); + m_domtree_version = latestVersion; updateFrameCache(); } } @@ -508,8 +512,8 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet) if (pictureSet->upToDate(index)) continue; const SkIRect& inval = pictureSet->bounds(index); - DBG_SET_LOGD("draw [%d] {%d,%d,w=%d,h=%d}", index, inval.fLeft, - inval.fTop, inval.width(), inval.height()); + DBG_SET_LOGD("pictSet=%p [%d] {%d,%d,w=%d,h=%d}", pictureSet, index, + inval.fLeft, inval.fTop, inval.width(), inval.height()); pictureSet->setPicture(index, rebuildPicture(inval)); } pictureSet->validate(__FUNCTION__); @@ -599,21 +603,13 @@ void WebViewCore::sendRecomputeFocus() checkException(env); } -void WebViewCore::viewInvalidate(const SkIRect& rect) -{ - LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendViewInvalidate, - rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); - checkException(env); -} - void WebViewCore::viewInvalidate(const WebCore::IntRect& rect) -{ +{ LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendViewInvalidate, - rect.x(), rect.y(), rect.right(), rect.bottom()); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_sendViewInvalidate, + rect.x(), rect.y(), rect.right(), rect.bottom()); checkException(env); } @@ -749,12 +745,12 @@ void WebViewCore::setScrollOffset(int dx, int dy) if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) { m_scrollOffsetX = dx; m_scrollOffsetY = dy; - m_mainFrame->sendScrollEvent(); // The visible rect is located within our coordinate space so it // contains the actual scroll position. Setting the location makes hit // testing work correctly. m_mainFrame->view()->platformWidget()->setLocation(m_scrollOffsetX, m_scrollOffsetY); + m_mainFrame->sendScrollEvent(); } } @@ -1011,7 +1007,10 @@ void WebViewCore::drawPlugins() if (!inval.isEmpty()) { // inval.getBounds() is our rectangle - this->viewInvalidate(inval.getBounds()); + const SkIRect& bounds = inval.getBounds(); + WebCore::IntRect r(bounds.fLeft, bounds.fTop, + bounds.width(), bounds.height()); + this->viewInvalidate(r); } } @@ -1021,7 +1020,7 @@ void WebViewCore::setFinalFocus(WebCore::Frame* frame, WebCore::Node* node, int x, int y, bool block) { DBG_NAV_LOGD("frame=%p node=%p x=%d y=%d", frame, node, x, y); - bool result = finalKitFocus(frame, node, x, y); + bool result = finalKitFocus(frame, node, x, y, false); if (block) { m_blockFocusChange = true; if (!result && node) @@ -1082,12 +1081,16 @@ bool WebViewCore::commonKitFocus(int generation, int buildGeneration, releaseFrameCache(newCache); if (!node && ignoreNullFocus) return true; - finalKitFocus(frame, node, x, y); + finalKitFocus(frame, node, x, y, false); return true; } +// Update mouse position and may change focused node. +// If donotChangeDOMFocus is true, the function does not changed focused node +// in the DOM tree. Changing the focus in DOM may trigger onblur event +// handler on the current focused node before firing mouse up and down events. bool WebViewCore::finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, - int x, int y) + int x, int y, bool donotChangeDOMFocus) { if (!frame) frame = m_mainFrame; @@ -1103,41 +1106,48 @@ bool WebViewCore::finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, WebCore::MouseEventMoved, 1, false, false, false, false, WebCore::currentTime()); frame->eventHandler()->handleMouseMoveEvent(mouseEvent); } - WebCore::Document* oldDoc = oldFocusNode ? oldFocusNode->document() : 0; - if (!node) { - if (oldFocusNode) - oldDoc->setFocusedNode(0); - return false; - } else if (!valid) { - DBG_NAV_LOGD("sendMarkNodeInvalid node=%p", node); - sendMarkNodeInvalid(node); - if (oldFocusNode) + + if (!donotChangeDOMFocus) { + WebCore::Document* oldDoc = oldFocusNode ? oldFocusNode->document() : 0; + if (!node) { + if (oldFocusNode) + oldDoc->setFocusedNode(0); + return false; + } else if (!valid) { + DBG_NAV_LOGD("sendMarkNodeInvalid node=%p", node); + sendMarkNodeInvalid(node); + if (oldFocusNode) + oldDoc->setFocusedNode(0); + return false; + } + // If we jump frames (docs), kill the focus on the old doc + if (oldFocusNode && node->document() != oldDoc) { oldDoc->setFocusedNode(0); - return false; - } - // If we jump frames (docs), kill the focus on the old doc - builder.setLastFocus(node); - if (oldFocusNode && node->document() != oldDoc) { - oldDoc->setFocusedNode(0); - } - if (!node->isTextNode()) - static_cast(node)->focus(false); - if (node->document()->focusedNode() != node) { - // This happens when Element::focus() fails as we may try to set the - // focus to a node which WebCore doesn't recognize as a focusable node. - // So we need to do some extra work, as it does in Element::focus(), - // besides calling Document::setFocusedNode. - if (oldFocusNode) { - // copied from clearSelectionIfNeeded in FocusController.cpp - WebCore::SelectionController* s = oldDoc->frame()->selection(); - if (!s->isNone()) - s->clear(); } - //setFocus on things that WebCore doesn't recognize as supporting focus - //for instance, if there is an onclick element that does not support focus - node->document()->setFocusedNode(node); + if (!node->isTextNode()) + static_cast(node)->focus(false); + if (node->document()->focusedNode() != node) { + // This happens when Element::focus() fails as we may try to set the + // focus to a node which WebCore doesn't recognize as a focusable node. + // So we need to do some extra work, as it does in Element::focus(), + // besides calling Document::setFocusedNode. + if (oldFocusNode) { + // copied from clearSelectionIfNeeded in FocusController.cpp + WebCore::SelectionController* s = oldDoc->frame()->selection(); + if (!s->isNone()) + s->clear(); + } + //setFocus on things that WebCore doesn't recognize as supporting focus + //for instance, if there is an onclick element that does not support focus + node->document()->setFocusedNode(node); + } + } else { // !donotChangeDOMFocus + if (!node || !valid) + return false; } + DBG_NAV_LOGD("setFocusedNode node=%p", node); + builder.setLastFocus(node); m_lastFocused = node; m_lastFocusedBounds = node->getRect(); return true; @@ -1175,7 +1185,7 @@ WebCore::Frame* WebViewCore::changedKitFocus(WebCore::Frame* frame, WebCore::Node* current = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().currentFocus(); if (current == node) return frame; - return finalKitFocus(frame, node, x, y) ? frame : m_mainFrame; + return finalKitFocus(frame, node, x, y, false) ? frame : m_mainFrame; } static int findTextBoxIndex(WebCore::Node* node, const WebCore::IntPoint& pt) @@ -1470,6 +1480,10 @@ public: // index is listIndex of the selected item, or -1 if nothing is selected. virtual void replyInt(int index) { + if (-2 == index) { + // Special value for cancel. Do nothing. + return; + } // If the select element no longer exists, do to a page change, etc, silently return. if (!m_select || !FrameLoaderClientAndroid::get(m_viewImpl->m_mainFrame)->getCacheBuilder().validNode(m_frame, m_select)) return; @@ -1493,8 +1507,8 @@ public: } // Response if the listbox allows multiple selection. array stores the listIndices - // of selected positions. - virtual void replyIntArray(const int* array, int count) + // of selected positions. + virtual void replyIntArray(const int* array, int count) { // If the select element no longer exists, do to a page change, etc, silently return. if (!m_select || !FrameLoaderClientAndroid::get(m_viewImpl->m_mainFrame)->getCacheBuilder().validNode(m_frame, m_select)) @@ -1540,9 +1554,9 @@ static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount, bool multiple, const int selected[], size_t selectedCountOrSelection) { - // Reuse m_popupReply - Release(m_popupReply); - m_popupReply = 0; + // If m_popupReply is not null, then we already have a list showing. + if (m_popupReply != 0) + return; LOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!"); @@ -1661,7 +1675,7 @@ void WebViewCore::touchUp(int touchGeneration, int buildGeneration, return; // short circuit if a newer touch has been generated } if (retry) - finalKitFocus(frame, node, x, y); + finalKitFocus(frame, node, x, y, true); // don't change DOM focus else if (!commonKitFocus(touchGeneration, buildGeneration, frame, node, x, y, false)) { return; @@ -1692,7 +1706,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node // so when attempting to get the default, the point chosen would be follow the wrong link. if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) { webFrame->setUserInitiatedClick(true); - WebCore::EventTargetNodeCast(nodePtr)->dispatchSimulatedClick(0, + WebCore::EventTargetNodeCast(nodePtr)->dispatchSimulatedClick(0, true, true); webFrame->setUserInitiatedClick(false); return true; @@ -1940,7 +1954,7 @@ static void SetScrollOffset(JNIEnv *env, jobject obj, jint dx, jint dy) viewImpl->setScrollOffset(dx, dy); } -static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h, +static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h, jint v) { WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); @@ -1949,7 +1963,7 @@ static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h, viewImpl->setGlobalBounds(x, y, h, v); } -static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar, +static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar, jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isDown) { #ifdef ANDROID_INSTRUMENT diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index fcd5574..29bdf37 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -119,9 +119,11 @@ namespace android { */ void contentDraw(); - // invalidate the view/display, NOT the content/DOM + /** Invalidate the view/screen, NOT the content/DOM, but expressed in + * content/DOM coordinates (i.e. they need to eventually be scaled, + * by webview into view.java coordinates + */ void viewInvalidate(const WebCore::IntRect& rect); - void viewInvalidate(const SkIRect& rect); /** * Invalidate part of the content that may be offscreen at the moment @@ -381,6 +383,7 @@ namespace android { WebCore::Node* m_snapAnchorNode; int m_screenWidth; int m_scale; + unsigned m_domtree_version; SkTDArray m_plugins; WebCore::Timer m_pluginInvalTimer; @@ -393,7 +396,7 @@ namespace android { bool commonKitFocus(int generation, int buildGeneration, WebCore::Frame* frame, WebCore::Node* node, int x, int y, bool ignoreNullFocus); - bool finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, int x, int y); + bool finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, int x, int y, bool donotChangeDOMFocus); void doMaxScroll(CacheBuilder::Direction dir); SkPicture* rebuildPicture(const SkIRect& inval); void rebuildPictureSet(PictureSet* ); diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index 1323581..9efcbd7 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -453,14 +453,16 @@ void CacheBuilder::Debug::groups() { } else print("\"\""); RenderObject* renderer = node->renderer(); + int tabindex = node->isElementNode() ? node->tabIndex() : 0; if (renderer) { const IntRect& absB = renderer->absoluteBoundingBoxRect(); - snprintf(scratch, sizeof(scratch), ", {%d, %d, %d, %d}, %s},", - absB.x(), absB.y(), absB.width(), absB.height(), - renderer->hasOverflowClip() ? "true" : "false"); + snprintf(scratch, sizeof(scratch), ", {%d, %d, %d, %d}, %s" + ", %d},",absB.x(), absB.y(), absB.width(), absB.height(), + renderer->hasOverflowClip() ? "true" : "false", tabindex); print(scratch); } else - print(", {0, 0, 0, 0}, false},"); + print(", {0, 0, 0, 0}, false, 0},"); + flush(); snprintf(scratch, sizeof(scratch), "// %d: ", count); mPrefix = "\n// "; @@ -945,6 +947,11 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, ClipColumnTracker* baseTracker = clipTracker.data(); // sentinel bzero(baseTracker, sizeof(ClipColumnTracker)); } + WTF::Vector tabIndexTracker(1); + { + TabIndexTracker* baseTracker = tabIndexTracker.data(); // sentinel + bzero(baseTracker, sizeof(TabIndexTracker)); + } #if DUMP_NAV_CACHE char* frameNamePtr = cachedFrame->mDebug.mFrameName; Builder(frame)->mDebug.frameName(frameNamePtr, frameNamePtr + @@ -964,8 +971,10 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, Node* node = parent; int cacheIndex = 1; Node* focused = doc->focusedNode(); - if (focused) + if (focused) { setLastFocus(focused); + cachedRoot->setFocusBounds(mLastKnownFocusBounds); + } int globalOffsetX, globalOffsetY; GetGlobalOffset(frame, &globalOffsetX, &globalOffsetY); while (walk.mMore || (node = node->traverseNextNode()) != NULL) { @@ -989,6 +998,12 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, break; clipTracker.removeLast(); } while (true); + do { + const TabIndexTracker* lastTabIndex = &tabIndexTracker.last(); + if (node != lastTabIndex->mLastChild) + break; + tabIndexTracker.removeLast(); + } while (true); Frame* child = HasFrame(node); CachedNode cachedNode; if (child != NULL) { @@ -1014,6 +1029,17 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, BuildFrame(root, child, cachedRoot, childPtr); continue; } + int tabIndex = node->tabIndex(); + Node* lastChild = node->lastChild(); + if (tabIndex <= 0) + tabIndex = tabIndexTracker.last().mTabIndex; + else if (tabIndex > 0 && lastChild) { + DBG_NAV_LOGD("tabIndex=%d node=%p", tabIndex, node); + tabIndexTracker.grow(tabIndexTracker.size() + 1); + TabIndexTracker& indexTracker = tabIndexTracker.last(); + indexTracker.mTabIndex = tabIndex; + indexTracker.mLastChild = OneAfter(lastChild); + } RenderObject* nodeRenderer = node->renderer(); bool isTransparent = false; bool hasFocusRing = true; @@ -1066,7 +1092,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, CachedNodeType type = NORMAL_CACHEDNODETYPE; IntRect bounds; IntRect absBounds; - Node* lastChild = node->lastChild(); WTF::Vector* columns = NULL; if (isArea) { HTMLAreaElement* area = static_cast(node); @@ -1171,7 +1196,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, else if (node->hasTagName(HTMLNames::aTag)) { const HTMLAnchorElement* anchorNode = (const HTMLAnchorElement*) node; - if (anchorNode->isFocusable() == false) + if (!anchorNode->isFocusable() && !HasTriggerEvent(node)) continue; EventTargetNode* target = (EventTargetNode*) node; if (target->disabled()) @@ -1290,6 +1315,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, if (last->mParentLastChild == NULL) last->mParentLastChild = OneAfter(node->parentNode()->lastChild()); cachedNode.setParentGroup(last->mParentLastChild); + cachedNode.setTabIndex(tabIndex); cachedNode.setTextSize(textSize); cachedNode.setType(type); cachedNode.setWantsKeyEvents(wantsKeyEvents); @@ -1316,8 +1342,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, } } cacheIndex++; -tryNextNode: - ; } while (tracker.size() > 1) { Tracker* last = &tracker.last(); @@ -2961,7 +2985,8 @@ bool CacheBuilder::ConstructPartRects(Node* node, const IntRect& bounds, clip.mNode = test; } while (test != last && (test = test->traverseNextNode()) != NULL); } - if (result->size() == 0) { + if (result->size() == 0 || focusBounds->width() < MINIMUM_FOCUSABLE_WIDTH + || focusBounds->height() < MINIMUM_FOCUSABLE_HEIGHT) { if (bounds.width() < MINIMUM_FOCUSABLE_WIDTH) return false; if (bounds.height() < MINIMUM_FOCUSABLE_HEIGHT) diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h index 7d5404d..07040e2 100644 --- a/WebKit/android/nav/CacheBuilder.h +++ b/WebKit/android/nav/CacheBuilder.h @@ -177,8 +177,13 @@ private: TextDirection mDirection; bool mHasClip; }; + struct TabIndexTracker { + int mTabIndex; + Node* mLastChild; + }; struct Tracker { int mCachedNodeIndex; + int mTabIndex; Node* mLastChild; Node* mParentLastChild; bool mSomeParentTakesFocus; diff --git a/WebKit/android/nav/CachedDebug.h b/WebKit/android/nav/CachedDebug.h index 42c6363..3127112 100644 --- a/WebKit/android/nav/CachedDebug.h +++ b/WebKit/android/nav/CachedDebug.h @@ -43,19 +43,8 @@ #endif #if DEBUG_NAV_UI -#define DBG_NAV_LOGD_NO_PARAM 0 /* needed so we can call (format, ...) */ -#define DBG_NAV_LOG_THROTTLE_INTERVAL 1000 #define DBG_NAV_LOG(message) LOGD("%s %s", __FUNCTION__, message) #define DBG_NAV_LOGD(format, ...) LOGD("%s " format, __FUNCTION__, __VA_ARGS__) -#define DBG_NAV_LOGD_THROTTLE(format, ...) \ -do { \ - static uint32_t gPrevLogTime = 0; \ - uint32_t curTime = SkTime::GetMSecs(); \ - if (curTime - gPrevLogTime > DBG_NAV_LOG_THROTTLE_INTERVAL) { \ - LOGD("%s " format, __FUNCTION__, __VA_ARGS__); \ - gPrevLogTime = curTime; \ - } \ -} while (false) #define DEBUG_NAV_UI_LOGD(...) LOGD(__VA_ARGS__) #else #define DBG_NAV_LOG(message) ((void)0) diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp index 0231394..4db9e40 100644 --- a/WebKit/android/nav/CachedFrame.cpp +++ b/WebKit/android/nav/CachedFrame.cpp @@ -125,6 +125,14 @@ void CachedFrame::clearFocus() // returns 0 if test is preferable to best, 1 if not preferable, or -1 if unknown int CachedFrame::compare(BestData& testData, const BestData& bestData, const CachedNode* focus) const { + if (testData.mNode->tabIndex() != bestData.mNode->tabIndex()) { + if (testData.mNode->tabIndex() < bestData.mNode->tabIndex() + || (focus && focus->tabIndex() < bestData.mNode->tabIndex())) { + testData.mNode->setCondition(CachedNode::HIGHER_TAB_INDEX); + return REJECT_TEST; + } + return TEST_IS_BEST; + } // start here; // if the test minor axis line intersects the line segment between focus center and best center, choose it // give more weight to exact major axis alignment (rows, columns) @@ -662,7 +670,7 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, Bes testData.mNode->setCondition(CachedNode::NOT_FOCUS_NODE); return REJECT_TEST; } -// if (test->bounds().contains(history()->focusBounds())) { +// if (test->bounds().contains(mRoot->focusBounds())) { // testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); // return REJECT_TEST; // } @@ -733,7 +741,7 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, Bes int CachedFrame::framePartCommon(BestData& testData, const CachedNode* test, BestData* bestData, const CachedNode* focus) const { - if (testData.mNodeBounds.contains(history()->focusBounds())) { + if (testData.mNodeBounds.contains(mRoot->focusBounds())) { testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS); return REJECT_TEST; } diff --git a/WebKit/android/nav/CachedHistory.cpp b/WebKit/android/nav/CachedHistory.cpp index ba94c72..f75f237 100644 --- a/WebKit/android/nav/CachedHistory.cpp +++ b/WebKit/android/nav/CachedHistory.cpp @@ -82,7 +82,7 @@ void CachedHistory::reset() { memset(mVisited, 0, sizeof(mVisited)); // mLastScroll = 0; - mPriorBounds = mFocusBounds = WebCore::IntRect(0, 0, 0, 0); + mPriorBounds = WebCore::IntRect(0, 0, 0, 0); mDirectionChange = false; mFocusIsInput = false; mPriorIsInput = false; @@ -107,12 +107,11 @@ void CachedHistory::setWorking(CachedFrame::Direction newMove, if (focus != NULL) { WebCore::IntRect focusBounds; focus->getBounds(&focusBounds); - if (focusBounds.isEmpty() == false && focusBounds != mFocusBounds) - mNavBounds = mFocusBounds = focusBounds; + if (focusBounds.isEmpty() == false) + mNavBounds = focusBounds; mPriorIsInput = mFocusIsInput; mFocusIsInput = focus->isInput(); // focus->localName() == "input"; - } else - mFocusBounds = WebCore::IntRect(0, 0, 0, 0); + } if (change) { // uninitialized or change in direction if (lastAxis != CachedFrame::LEFT && navBounds->height() > 0) { mMinWorkingHorizontal = navBounds->y(); @@ -177,7 +176,6 @@ void CachedHistory::Debug::print(CachedRoot* root) const } DUMP_NAV_LOGD("// };\n"); // DUMP_NAV_LOGD("// int mLastScroll=%d;\n", b->mLastScroll); - DEBUG_PRINT_RECT(mFocusBounds); DEBUG_PRINT_RECT(mNavBounds); DEBUG_PRINT_RECT(mPriorBounds); DEBUG_PRINT_BOOL(mDirectionChange); diff --git a/WebKit/android/nav/CachedHistory.h b/WebKit/android/nav/CachedHistory.h index 490ed67..e48d44b 100644 --- a/WebKit/android/nav/CachedHistory.h +++ b/WebKit/android/nav/CachedHistory.h @@ -43,7 +43,6 @@ public: bool checkVisited(const CachedNode* , CachedFrame::Direction ) const; bool didFirstLayout() const { return mDidFirstLayout; } bool directionChange() const { return mDirectionChange; } - const WebCore::IntRect& focusBounds() const { return mFocusBounds; } int minWorkingHorizontal() const { return mMinWorkingHorizontal; } int minWorkingVertical() const { return mMinWorkingVertical; } int maxWorkingHorizontal() const { return mMaxWorkingHorizontal; } @@ -61,7 +60,6 @@ private: const CachedNode* mNode; CachedFrame::Direction mDirection; } mVisited[NAVIGATION_VISIT_DEPTH]; - WebCore::IntRect mFocusBounds; // chosen focus ring WebCore::IntRect mMouseBounds; // constricted bounds, if focus ring is partially visible WebCore::IntRect mNavBounds; // focus ring bounds plus optional keystroke movement WebCore::IntRect mPriorBounds; // prior chosen focus ring (for reversing narrowing) diff --git a/WebKit/android/nav/CachedNode.cpp b/WebKit/android/nav/CachedNode.cpp index e6ade3e..b786677 100644 --- a/WebKit/android/nav/CachedNode.cpp +++ b/WebKit/android/nav/CachedNode.cpp @@ -263,6 +263,7 @@ const char* CachedNode::Debug::condition(Condition t) const case BEST_DIRECTION: return "BEST_DIRECTION"; break; case CHILD: return "CHILD"; break; case DISABLED: return "DISABLED"; break; + case HIGHER_TAB_INDEX: return "HIGHER_TAB_INDEX"; break; case IN_FOCUS: return "IN_FOCUS"; break; case IN_FOCUS_CHILDREN: return "IN_FOCUS_CHILDREN"; break; case NOT_ENCLOSING_FOCUS: return "NOT_ENCLOSING_FOCUS"; break; @@ -300,6 +301,7 @@ void CachedNode::Debug::print() const scratch[index++] = *ch++; DUMP_NAV_LOGD("%.*s\"\n", index, scratch); DEBUG_PRINT_RECT(mBounds); + DEBUG_PRINT_RECT(mHitBounds); const WTF::Vector& rects = b->focusRings(); size_t size = rects.size(); DUMP_NAV_LOGD("// IntRect focusRings={ // size=%d\n", size); @@ -315,11 +317,13 @@ void CachedNode::Debug::print() const DUMP_NAV_LOGD("// int mNavableRects=%d;\n", b->mNavableRects); DUMP_NAV_LOGD("// int mParentIndex=%d;\n", b->mParentIndex); DUMP_NAV_LOGD("// int mTextSize=%d;\n", b->mTextSize); + DUMP_NAV_LOGD("// int mTabIndex=%d;\n", b->mTabIndex); DUMP_NAV_LOGD("// Condition mCondition=%s;\n", condition(b->mCondition)); DUMP_NAV_LOGD("// Type mType=%s;\n", type(b->mType)); DEBUG_PRINT_BOOL(mClippedOut); DEBUG_PRINT_BOOL(mDisabled); DEBUG_PRINT_BOOL(mFixedUpFocusRects); + DEBUG_PRINT_BOOL(mHasFocusRing); DEBUG_PRINT_BOOL(mHasMouseOver); DEBUG_PRINT_BOOL(mIsAnchor); DEBUG_PRINT_BOOL(mIsArea); @@ -327,11 +331,13 @@ void CachedNode::Debug::print() const DEBUG_PRINT_BOOL(mIsInput); DEBUG_PRINT_BOOL(mIsParentAnchor); DEBUG_PRINT_BOOL(mIsPassword); + DEBUG_PRINT_BOOL(mIsRtlText); DEBUG_PRINT_BOOL(mIsTextArea); DEBUG_PRINT_BOOL(mIsTextField); DEBUG_PRINT_BOOL(mIsTransparent); DEBUG_PRINT_BOOL(mIsUnclipped); DEBUG_PRINT_BOOL(mLast); + DEBUG_PRINT_BOOL(mWantsKeyEvents); DUMP_NAV_LOGD("\n"); } diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h index 6cb1ca3..aa64982 100644 --- a/WebKit/android/nav/CachedNode.h +++ b/WebKit/android/nav/CachedNode.h @@ -69,6 +69,7 @@ public: BEST_DIRECTION, // can be reached by another direction CHILD, DISABLED, + HIGHER_TAB_INDEX, IN_FOCUS, IN_FOCUS_CHILDREN, NOT_ENCLOSING_FOCUS, @@ -160,9 +161,11 @@ public: void setNavableRects() { mNavableRects = mFocusRing.size(); } void setParentGroup(void* group) { mParentGroup = group; } void setParentIndex(int parent) { mParentIndex = parent; } + void setTabIndex(int index) { mTabIndex = index; } void setTextSize(int textSize) { mTextSize = textSize; } void setType(CachedNodeType type) { mType = type; } void setWantsKeyEvents(bool wantsKeys) { mWantsKeyEvents = wantsKeys; } + int tabIndex() const { return mTabIndex; } const CachedNode* traverseNextNode() const { return mLast ? NULL : &this[1]; } int textSize() const { return mTextSize; } CachedNodeType type() const { return mType; } @@ -180,6 +183,7 @@ private: int mNavableRects; // FIXME: could be bitfield once I limit max number of rects int mParentIndex; int mTextSize; + int mTabIndex; mutable Condition mCondition : 5; // why the node was not chosen on the first pass CachedNodeType mType : 3; bool mClippedOut : 1; diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index 8e0833d..4a50c80 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -670,8 +670,8 @@ bool CachedRoot::innerDown(const CachedNode* test, BestData* bestData) const mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll); int testTop = mScrolledBounds.y(); int viewBottom = mViewBounds.bottom(); - if (mHistory->mFocusBounds.isEmpty() == false && - mHistory->mFocusBounds.bottom() > viewBottom && viewBottom < mContents.height()) + if (mFocusBounds.isEmpty() == false && + mFocusBounds.bottom() > viewBottom && viewBottom < mContents.height()) return false; if (mHistory->mNavBounds.isEmpty() == false) { int navTop = mHistory->mNavBounds.y(); @@ -694,8 +694,8 @@ bool CachedRoot::innerLeft(const CachedNode* test, BestData* bestData) const mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll); int testRight = mScrolledBounds.right(); int viewLeft = mViewBounds.x(); - if (mHistory->mFocusBounds.isEmpty() == false && - mHistory->mFocusBounds.x() < viewLeft && viewLeft > mContents.x()) + if (mFocusBounds.isEmpty() == false && + mFocusBounds.x() < viewLeft && viewLeft > mContents.x()) return false; if (mHistory->mNavBounds.isEmpty() == false) { int navRight = mHistory->mNavBounds.right(); @@ -721,7 +721,11 @@ void CachedRoot::innerMove(const CachedNode* node, BestData* bestData, #endif if (firstTime) mHistory->reset(); - mHistory->setWorking(direction, currentFocus(), mViewBounds); + const CachedNode* focus = currentFocus(); + mHistory->setWorking(direction, focus, mViewBounds); + mFocusBounds = WebCore::IntRect(0, 0, 0, 0); + if (focus != NULL) + focus->getBounds(&mFocusBounds); bool findClosest = false; if (mScrollOnly == false) { switch (direction) { @@ -761,7 +765,7 @@ void CachedRoot::innerMove(const CachedNode* node, BestData* bestData, return; if (bestData->mNode != NULL) { mHistory->addToVisited(bestData->mNode, direction); - mHistory->mNavBounds = mHistory->mFocusBounds = bestData->mNodeBounds; + mHistory->mNavBounds = mFocusBounds = bestData->mNodeBounds; mHistory->mMouseBounds = bestData->mMouseBounds; } else if (scroll->x() != 0 || scroll->y() != 0) { WebCore::IntRect newBounds = mHistory->mNavBounds; @@ -790,8 +794,8 @@ bool CachedRoot::innerRight(const CachedNode* test, BestData* bestData) const mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll); int testLeft = mScrolledBounds.x(); int viewRight = mViewBounds.right(); - if (mHistory->mFocusBounds.isEmpty() == false && - mHistory->mFocusBounds.right() > viewRight && viewRight < mContents.width()) + if (mFocusBounds.isEmpty() == false && + mFocusBounds.right() > viewRight && viewRight < mContents.width()) return false; if (mHistory->mNavBounds.isEmpty() == false) { int navLeft = mHistory->mNavBounds.x(); @@ -814,8 +818,8 @@ bool CachedRoot::innerUp(const CachedNode* test, BestData* bestData) const mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll); int testBottom = mScrolledBounds.bottom(); int viewTop = mViewBounds.y(); - if (mHistory->mFocusBounds.isEmpty() == false && - mHistory->mFocusBounds.y() < viewTop && viewTop > mContents.y()) + if (mFocusBounds.isEmpty() == false && + mFocusBounds.y() < viewTop && viewTop > mContents.y()) return false; if (mHistory->mNavBounds.isEmpty() == false) { int navBottom = mHistory->mNavBounds.bottom(); @@ -972,7 +976,7 @@ void CachedRoot::reset() mMaxXScroll = mMaxYScroll = 0; mSelectionStart = mSelectionEnd = -1; mScrollOnly = false; -// resetNavClipBounds(); + mFocusBounds = WebCore::IntRect(0, 0, 0, 0); } bool CachedRoot::scrollDelta(WebCore::IntRect& newOutset, Direction direction, int* delta) @@ -1046,6 +1050,11 @@ void CachedRoot::setupScrolledBounds() const #define DEBUG_PRINT_BOOL(field) \ DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false") +#define DEBUG_PRINT_RECT(field) \ + { const WebCore::IntRect& r = b->field; \ + DUMP_NAV_LOGD("// IntRect " #field "={%d, %d, %d, %d};\n", \ + r.x(), r.y(), r.width(), r.height()); } + CachedRoot* CachedRoot::Debug::base() const { CachedRoot* nav = (CachedRoot*) ((char*) this - OFFSETOF(CachedRoot, mDebug)); return nav; @@ -1061,6 +1070,7 @@ void CachedRoot::Debug::print() const CachedRoot* b = base(); b->CachedFrame::mDebug.print(); b->mHistory->mDebug.print(b); + DEBUG_PRINT_RECT(mFocusBounds); DUMP_NAV_LOGD("// int mMaxXScroll=%d, mMaxYScroll=%d;\n", b->mMaxXScroll, b->mMaxYScroll); DEBUG_PRINT_BOOL(mFocusChild); diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h index 85ddf95..ab1b823 100644 --- a/WebKit/android/nav/CachedRoot.h +++ b/WebKit/android/nav/CachedRoot.h @@ -47,6 +47,7 @@ public: int documentWidth() { return mContents.width(); } const CachedNode* findAt(const WebCore::IntRect& , const CachedFrame** , int* x, int* y) const; + const WebCore::IntRect& focusBounds() const { return mFocusBounds; } bool focusChild() const { return mFocusChild; } WebCore::IntPoint focusLocation() const; int generation() const { return mGeneration; } @@ -72,6 +73,7 @@ public: bool scrollDelta(WebCore::IntRect& focusRingBounds, Direction , int* delta); const WebCore::IntRect& scrolledBounds() const { return mScrolledBounds; } void setCachedFocus(CachedFrame* , CachedNode* ); + void setFocusBounds(const WebCore::IntRect& r) { mFocusBounds = r; } void setGeneration(int generation) { mGeneration = generation; } void setTextGeneration(int textGeneration) { mTextGeneration = textGeneration; } void setFocusChild(bool state) const { mFocusChild = state; } @@ -87,7 +89,7 @@ public: private: CachedHistory* mHistory; SkPicture* mPicture; - // WebCore::IntRect mClippedBounds; + WebCore::IntRect mFocusBounds; // chosen focus ring mutable WebCore::IntRect mScrolledBounds; // view bounds + amount visible as result of scroll int mGeneration; int mTextGeneration; diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 64876ab..fc34c84 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -191,8 +191,11 @@ int count() m_start += triggerSize(); if (m_start == m_end) break; - if (m_start >= limit) - m_start -= sizeof(m_buffer); + if (m_start < limit) + continue; + m_start -= sizeof(m_buffer); + if (m_start == m_end) + break; } m_start = saveStart; DBG_NAV_LOGD("count=%d", result); @@ -671,24 +674,23 @@ void drawFocusRing(SkCanvas* canvas) { const CachedRoot* root = getFrameCache(AllowNewer); if (!root) { - DBG_NAV_LOGD_THROTTLE("!root", DBG_NAV_LOGD_NO_PARAM); + DBG_NAV_LOG("!root"); m_followedLink = false; return; } const CachedNode* node = root->currentFocus(); if (!node) { - DBG_NAV_LOGD_THROTTLE("!node", DBG_NAV_LOGD_NO_PARAM); + DBG_NAV_LOG("!node"); m_followedLink = false; return; } if (!node->hasFocusRing()) { - DBG_NAV_LOGD_THROTTLE("!node->hasFocusRing()", - DBG_NAV_LOGD_NO_PARAM); + DBG_NAV_LOG("!node->hasFocusRing()"); return; } const WTF::Vector& rings = node->focusRings(); if (!rings.size()) { - DBG_NAV_LOGD_THROTTLE("!rings.size()", DBG_NAV_LOGD_NO_PARAM); + DBG_NAV_LOG("!rings.size()"); return; } @@ -714,7 +716,8 @@ void drawFocusRing(SkCanvas* canvas) SkRect sbounds; android_setrect(&sbounds, bounds); if (canvas->quickReject(sbounds, SkCanvas::kAA_EdgeType)) { - DBG_NAV_LOGD_THROTTLE("canvas->quickReject", DBG_NAV_LOGD_NO_PARAM); + DBG_NAV_LOG("canvas->quickReject"); + m_followedLink = false; return; } FocusRing::Flavor flavor = FocusRing::NORMAL_FLAVOR; @@ -727,7 +730,7 @@ void drawFocusRing(SkCanvas* canvas) } #if DEBUG_NAV_UI const WebCore::IntRect& ring = rings[0]; - DBG_NAV_LOGD_THROTTLE("cachedFocusNode=%d (nodePointer=%p) flavor=%s rings=%d" + DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p) flavor=%s rings=%d" " (%d, %d, %d, %d)", node->index(), node->nodePointer(), flavor == FocusRing::FAKE_FLAVOR ? "FAKE_FLAVOR" : flavor == FocusRing::INVALID_FLAVOR ? "INVALID_FLAVOR" : @@ -773,9 +776,16 @@ OutOfFocusFix fixOutOfDateFocus(bool useReplay) if (uiWidth != webWidth) { DBG_NAV_LOGD("uiWidth=%d webWidth=%d", uiWidth, webWidth); } else { - const WebCore::IntRect& cachedBounds = m_frameCacheUI->rootHistory()->focusBounds(); + const WebCore::IntRect& cachedBounds = m_frameCacheUI->focusBounds(); const CachedFrame* webFrame = 0; const CachedNode* webFocusNode = webRoot->currentFocus(&webFrame); + DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) cachedFrame=%p (%d)" + " webFocusNode=%p (%d) webFrame=%p (%d)", + cachedBounds.x(), cachedBounds.y(), + cachedBounds.width(), cachedBounds.height(), + cachedFrame, cachedFrame ? cachedFrame->indexInParent() : -1, + webFocusNode, webFocusNode ? webFocusNode->index() : -1, + webFrame, webFrame ? webFrame->indexInParent() : -1); if (webFocusNode && webFrame && webFrame->sameFrame(cachedFrame)) { if (useReplay && !m_replay.count()) { DBG_NAV_LOG("!m_replay.count()"); @@ -785,7 +795,10 @@ OutOfFocusFix fixOutOfDateFocus(bool useReplay) DBG_NAV_LOG("index =="); return DoNothing; } - const WebCore::IntRect& webBounds = webRoot->rootHistory()->focusBounds(); + const WebCore::IntRect& webBounds = webRoot->focusBounds(); + DBG_NAV_LOGD("webBounds=(%d,%d,w=%d,h=%d)", + webBounds.x(), webBounds.y(), + webBounds.width(), webBounds.height()); if (cachedBounds.contains(webBounds)) { DBG_NAV_LOG("contains"); return DoNothing; @@ -794,18 +807,7 @@ OutOfFocusFix fixOutOfDateFocus(bool useReplay) DBG_NAV_LOG("webBounds contains"); return DoNothing; } - DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) webBounds=(%d,%d,w=%d," - "%h=d)", cachedBounds.x(), cachedBounds.y(), - cachedBounds.width(), cachedBounds.height(), webBounds.x(), - webBounds.y(), webBounds.width(), webBounds.height()); - } else - DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) cachedFrame=%p (%d)" - " webFocusNode=%p (%d) webFrame=%p (%d)", - cachedBounds.x(), cachedBounds.y(), - cachedBounds.width(), cachedBounds.height(), - cachedFrame, cachedFrame ? cachedFrame->indexInParent() : -1, - webFocusNode, webFocusNode ? webFocusNode->index() : -1, - webFrame, webFrame ? webFrame->indexInParent() : -1); + } const CachedFrame* foundFrame = 0; int x, y; const CachedNode* found = findAt(webRoot, cachedBounds, &foundFrame, &x, &y); @@ -1023,7 +1025,8 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval, int dx = 0; int dy = 0; int counter = count; - root->setScrollOnly(m_followedLink); + if (!focus || !focus->isInput() || !m_followedLink) + root->setScrollOnly(m_followedLink); while (--counter >= 0) { WebCore::IntPoint scroll = WebCore::IntPoint(0, 0); cachedNode = root->moveFocus(direction, &cachedFrame, &scroll); @@ -1086,7 +1089,7 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval, m_replay.add(params.d.d, sizeof(params)); } } else { - if (visibleRect.intersects(root->rootHistory()->focusBounds()) == false) { + if (visibleRect.intersects(root->focusBounds()) == false) { setFocusData(root->generation(), 0, 0, 0, 0, true); sendKitFocus(); // will build cache and retry } diff --git a/WebKit/android/plugins/ANPCanvasInterface.cpp b/WebKit/android/plugins/ANPCanvasInterface.cpp index 96498ef..ba79691 100644 --- a/WebKit/android/plugins/ANPCanvasInterface.cpp +++ b/WebKit/android/plugins/ANPCanvasInterface.cpp @@ -69,6 +69,31 @@ static void anp_clipPath(ANPCanvas* canvas, const ANPPath* path) { canvas->skcanvas->clipPath(*path); } +static void anp_getTotalMatrix(ANPCanvas* canvas, ANPMatrix* matrix) { + const SkMatrix& src = canvas->skcanvas->getTotalMatrix(); + *matrix = *reinterpret_cast(&src); +} + +static bool anp_getLocalClipBounds(ANPCanvas* canvas, ANPRectF* r, + bool antialias) { + SkRect bounds; + if (canvas->skcanvas->getClipBounds(&bounds, + antialias ? SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) { + SkANP::SetRect(r, bounds); + return true; + } + return false; +} + +static bool anp_getDeviceClipBounds(ANPCanvas* canvas, ANPRectI* r) { + const SkRegion& clip = canvas->skcanvas->getTotalClip(); + if (!clip.isEmpty()) { + SkANP::SetRect(r, clip.getBounds()); + return true; + } + return false; +} + static void anp_drawColor(ANPCanvas* canvas, ANPColor color) { canvas->skcanvas->drawColor(color); } @@ -146,6 +171,9 @@ void ANPCanvasInterfaceV0_Init(ANPInterface* value) { ASSIGN(i, skew); ASSIGN(i, clipRect); ASSIGN(i, clipPath); + ASSIGN(i, getTotalMatrix); + ASSIGN(i, getLocalClipBounds); + ASSIGN(i, getDeviceClipBounds); ASSIGN(i, drawColor); ASSIGN(i, drawPaint); ASSIGN(i, drawRect); diff --git a/WebKit/android/plugins/ANPMatrixInterface.cpp b/WebKit/android/plugins/ANPMatrixInterface.cpp new file mode 100644 index 0000000..815b954 --- /dev/null +++ b/WebKit/android/plugins/ANPMatrixInterface.cpp @@ -0,0 +1,168 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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. + */ + +// must include config.h first for webkit to fiddle with new/delete +#include "config.h" +#include "SkANP.h" + +#ifdef SK_SCALAR_IS_FIXED +static void fromFloat(SkScalar dst[], const float src[], int n) { + for (int i = 0; i < n; i++) { + dst[i] = SkFloatToScalar(src[i]); + } +} + +static void toFloat(float dst[], const SkScalar src[], int n) { + for (int i = 0; i < n; i++) { + dst[i] = SkScalarToFloat(src[i]); + } +} +#endif + +static ANPMatrix* anp_newMatrix() { + return new ANPMatrix; +} + +static void anp_deleteMatrix(ANPMatrix* matrix) { + delete matrix; +} + +static ANPMatrixFlag anp_getFlags(const ANPMatrix* matrix) { + return matrix->getType(); +} + +static void anp_copy(ANPMatrix* dst, const ANPMatrix* src) { + *dst = *src; +} + +static void anp_get3x3(const ANPMatrix* matrix, float dst[9]) { + for (int i = 0; i < 9; i++) { + dst[i] = SkScalarToFloat(matrix->get(i)); + } +} + +static void anp_set3x3(ANPMatrix* matrix, const float src[9]) { + for (int i = 0; i < 9; i++) { + matrix->set(i, SkFloatToScalar(src[i])); + } +} + +static void anp_setIdentity(ANPMatrix* matrix) { + matrix->reset(); +} + +static void anp_preTranslate(ANPMatrix* matrix, float tx, float ty) { + matrix->preTranslate(SkFloatToScalar(tx), SkFloatToScalar(ty)); +} + +static void anp_postTranslate(ANPMatrix* matrix, float tx, float ty) { + matrix->postTranslate(SkFloatToScalar(tx), SkFloatToScalar(ty)); +} + +static void anp_preScale(ANPMatrix* matrix, float sx, float sy) { + matrix->preScale(SkFloatToScalar(sx), SkFloatToScalar(sy)); +} + +static void anp_postScale(ANPMatrix* matrix, float sx, float sy) { + matrix->postScale(SkFloatToScalar(sx), SkFloatToScalar(sy)); +} + +static void anp_preSkew(ANPMatrix* matrix, float kx, float ky) { + matrix->preSkew(SkFloatToScalar(kx), SkFloatToScalar(ky)); +} + +static void anp_postSkew(ANPMatrix* matrix, float kx, float ky) { + matrix->postSkew(SkFloatToScalar(kx), SkFloatToScalar(ky)); +} + +static void anp_preRotate(ANPMatrix* matrix, float degrees) { + matrix->preRotate(SkFloatToScalar(degrees)); +} + +static void anp_postRotate(ANPMatrix* matrix, float degrees) { + matrix->postRotate(SkFloatToScalar(degrees)); +} + +static void anp_preConcat(ANPMatrix* matrix, const ANPMatrix* other) { + matrix->preConcat(*other); +} + +static void anp_postConcat(ANPMatrix* matrix, const ANPMatrix* other) { + matrix->postConcat(*other); +} + +static bool anp_invert(ANPMatrix* dst, const ANPMatrix* src) { + return src->invert(dst); +} + +static void anp_mapPoints(ANPMatrix* matrix, float dst[], const float src[], + int32_t count) { +#ifdef SK_SCALAR_IS_FLOAT + matrix->mapPoints(reinterpret_cast(dst), + reinterpret_cast(src), count); +#else + const int N = 64; + SkPoint tmp[N]; + do { + int n = count; + if (n > N) { + n = N; + } + fromFloat(&tmp[0].fX, src, n*2); + matrix->mapPoints(tmp, n); + toFloat(dst, &tmp[0].fX, n*2); + count -= n; + } while (count > 0); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// + +#define ASSIGN(obj, name) (obj)->name = anp_##name + +void ANPMatrixInterfaceV0_Init(ANPInterface* value) { + ANPMatrixInterfaceV0* i = reinterpret_cast(value); + + ASSIGN(i, newMatrix); + ASSIGN(i, deleteMatrix); + ASSIGN(i, getFlags); + ASSIGN(i, copy); + ASSIGN(i, get3x3); + ASSIGN(i, set3x3); + ASSIGN(i, setIdentity); + ASSIGN(i, preTranslate); + ASSIGN(i, postTranslate); + ASSIGN(i, preScale); + ASSIGN(i, postScale); + ASSIGN(i, preSkew); + ASSIGN(i, postSkew); + ASSIGN(i, preRotate); + ASSIGN(i, postRotate); + ASSIGN(i, preConcat); + ASSIGN(i, postConcat); + ASSIGN(i, invert); + ASSIGN(i, mapPoints); +} + diff --git a/WebKit/android/plugins/ANPPaintInterface.cpp b/WebKit/android/plugins/ANPPaintInterface.cpp index 2a74b7f..4b561f0 100644 --- a/WebKit/android/plugins/ANPPaintInterface.cpp +++ b/WebKit/android/plugins/ANPPaintInterface.cpp @@ -158,6 +158,19 @@ static int anp_getTextWidths(ANPPaint* paint, const void* text, reinterpret_cast(bounds)); } +static float anp_getFontMetrics(ANPPaint* paint, ANPFontMetrics* metrics) { + SkPaint::FontMetrics fm; + SkScalar spacing = paint->getFontMetrics(&fm); + if (metrics) { + metrics->fTop = SkScalarToFloat(fm.fTop); + metrics->fAscent = SkScalarToFloat(fm.fAscent); + metrics->fDescent = SkScalarToFloat(fm.fDescent); + metrics->fBottom = SkScalarToFloat(fm.fBottom); + metrics->fLeading = SkScalarToFloat(fm.fLeading); + } + return SkScalarToFloat(spacing); +} + /////////////////////////////////////////////////////////////////////////////// #define ASSIGN(obj, name) (obj)->name = anp_##name @@ -195,5 +208,6 @@ void ANPPaintInterfaceV0_Init(ANPInterface* value) { ASSIGN(i, setTypeface); ASSIGN(i, measureText); ASSIGN(i, getTextWidths); + ASSIGN(i, getFontMetrics); } diff --git a/WebKit/android/plugins/SkANP.cpp b/WebKit/android/plugins/SkANP.cpp index 276dd8d..3912f99 100644 --- a/WebKit/android/plugins/SkANP.cpp +++ b/WebKit/android/plugins/SkANP.cpp @@ -48,6 +48,14 @@ ANPRectI* SkANP::SetRect(ANPRectI* dst, const SkIRect& src) { return dst; } +ANPRectF* SkANP::SetRect(ANPRectF* dst, const SkRect& src) { + dst->left = SkScalarToFloat(src.fLeft); + dst->top = SkScalarToFloat(src.fTop); + dst->right = SkScalarToFloat(src.fRight); + dst->bottom = SkScalarToFloat(src.fBottom); + return dst; +} + SkBitmap* SkANP::SetBitmap(SkBitmap* dst, const ANPBitmap& src) { SkBitmap::Config config = SkBitmap::kNo_Config; diff --git a/WebKit/android/plugins/SkANP.h b/WebKit/android/plugins/SkANP.h index 2389f0d..f319c9b 100644 --- a/WebKit/android/plugins/SkANP.h +++ b/WebKit/android/plugins/SkANP.h @@ -28,10 +28,14 @@ #include "android_npapi.h" #include "SkCanvas.h" +#include "SkMatrix.h" #include "SkPaint.h" #include "SkPath.h" #include "SkTypeface.h" +struct ANPMatrix : SkMatrix { +}; + struct ANPPath : SkPath { }; @@ -65,6 +69,7 @@ public: static SkRect* SetRect(SkRect* dst, const ANPRectF& src); static SkIRect* SetRect(SkIRect* dst, const ANPRectI& src); static ANPRectI* SetRect(ANPRectI* dst, const SkIRect& src); + static ANPRectF* SetRect(ANPRectF* dst, const SkRect& src); static SkBitmap* SetBitmap(SkBitmap* dst, const ANPBitmap& src); static bool SetBitmap(ANPBitmap* dst, const SkBitmap& src); diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h index 8b05d0a..f64c8ce 100644 --- a/WebKit/android/plugins/android_npapi.h +++ b/WebKit/android/plugins/android_npapi.h @@ -72,11 +72,21 @@ struct ANPRectI { }; struct ANPCanvas; +struct ANPMatrix; struct ANPPaint; struct ANPPath; struct ANPRegion; struct ANPTypeface; +enum ANPMatrixFlags { + kIdentity_ANPMatrixFlag = 0, + kTranslate_ANPMatrixFlag = 0x01, + kScale_ANPMatrixFlag = 0x02, + kAffine_ANPMatrixFlag = 0x04, + kPerspective_ANPMatrixFlag = 0x08, +}; +typedef uint32_t ANPMatrixFlag; + /////////////////////////////////////////////////////////////////////////////// // NPN_GetValue @@ -89,9 +99,10 @@ struct ANPTypeface; #define kLogInterfaceV0_ANPGetValue ((NPNVariable)1000) #define kAudioTrackInterfaceV0_ANPGetValue ((NPNVariable)1001) #define kCanvasInterfaceV0_ANPGetValue ((NPNVariable)1002) -#define kPaintInterfaceV0_ANPGetValue ((NPNVariable)1003) -#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1004) -#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1005) +#define kMatrixInterfaceV0_ANPGetValue ((NPNVariable)1003) +#define kPaintInterfaceV0_ANPGetValue ((NPNVariable)1004) +#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1005) +#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1006) /* queries for which drawing model is desired (for the draw event) @@ -148,6 +159,59 @@ struct ANPLogInterfaceV0 : ANPInterface { void (*log)(NPP instance, ANPLogType, const char format[], ...); }; +struct ANPMatrixInterfaceV0 : ANPInterface { + /* Return a new identity matrix + */ + ANPMatrix* (*newMatrix)(); + /* Delete a matrix previously allocated by newMatrix() + */ + void (*deleteMatrix)(ANPMatrix*); + + ANPMatrixFlag (*getFlags)(const ANPMatrix*); + + void (*copy)(ANPMatrix* dst, const ANPMatrix* src); + + /* Return the matrix values in a float array (allcoated by the caller), + where the values are treated as follows: + w = x * [6] + y * [7] + [8]; + x' = (x * [0] + y * [1] + [2]) / w; + y' = (x * [3] + y * [4] + [5]) / w; + */ + void (*get3x3)(const ANPMatrix*, float[9]); + /* Initialize the matrix from values in a float array, + where the values are treated as follows: + w = x * [6] + y * [7] + [8]; + x' = (x * [0] + y * [1] + [2]) / w; + y' = (x * [3] + y * [4] + [5]) / w; + */ + void (*set3x3)(ANPMatrix*, const float[9]); + + void (*setIdentity)(ANPMatrix*); + void (*preTranslate)(ANPMatrix*, float tx, float ty); + void (*postTranslate)(ANPMatrix*, float tx, float ty); + void (*preScale)(ANPMatrix*, float sx, float sy); + void (*postScale)(ANPMatrix*, float sx, float sy); + void (*preSkew)(ANPMatrix*, float kx, float ky); + void (*postSkew)(ANPMatrix*, float kx, float ky); + void (*preRotate)(ANPMatrix*, float degrees); + void (*postRotate)(ANPMatrix*, float degrees); + void (*preConcat)(ANPMatrix*, const ANPMatrix*); + void (*postConcat)(ANPMatrix*, const ANPMatrix*); + + /* Return true if src is invertible, and if so, return its inverse in dst. + If src is not invertible, return false and ignore dst. + */ + bool (*invert)(ANPMatrix* dst, const ANPMatrix* src); + + /* Transform the x,y pairs in src[] by this matrix, and store the results + in dst[]. The count parameter is treated as the number of pairs in the + array. It is legal for src and dst to point to the same memory, but + illegal for the two arrays to partially overlap. + */ + void (*mapPoints)(ANPMatrix*, float dst[], const float src[], + int32_t count); +}; + typedef uint32_t ANPColor; #define ANP_MAKE_COLOR(a, r, g, b) \ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) @@ -202,6 +266,19 @@ enum ANPTypefaceStyles { }; typedef uint32_t ANPTypefaceStyle; +struct ANPFontMetrics { + //! The greatest distance above the baseline for any glyph (will be <= 0) + float fTop; + //! The recommended distance above the baseline (will be <= 0) + float fAscent; + //! The recommended distance below the baseline (will be >= 0) + float fDescent; + //! The greatest distance below the baseline for any glyph (will be >= 0) + float fBottom; + //! The recommended distance to add between lines of text (will be >= 0) + float fLeading; +}; + struct ANPTypefaceInterfaceV0 : ANPInterface { /** Return a new reference to the typeface that most closely matches the requested name and style. Pass null as the name to return @@ -311,6 +388,12 @@ struct ANPPaintInterfaceV0 : ANPInterface { */ int (*getTextWidths)(ANPPaint*, const void* text, uint32_t byteLength, float widths[], ANPRectF bounds[]); + + /** Return in metrics the spacing values for text, respecting the paint's + typeface and pointsize, and return the spacing between lines + (descent - ascent + leading). If metrics is NULL, it will be ignored. + */ + float (*getFontMetrics)(ANPPaint*, ANPFontMetrics* metrics); }; struct ANPCanvasInterfaceV0 : ANPInterface { @@ -334,8 +417,22 @@ struct ANPCanvasInterfaceV0 : ANPInterface { void (*scale)(ANPCanvas*, float sx, float sy); void (*rotate)(ANPCanvas*, float degrees); void (*skew)(ANPCanvas*, float kx, float ky); + void (*concat)(ANPCanvas*, const ANPMatrix*); void (*clipRect)(ANPCanvas*, const ANPRectF*); void (*clipPath)(ANPCanvas*, const ANPPath*); + + /* Return the current matrix on the canvas + */ + void (*getTotalMatrix)(ANPCanvas*, ANPMatrix*); + /* Return the current clip bounds in local coordinates, expanding it to + account for antialiasing edge effects if aa is true. If the + current clip is empty, return false and ignore the bounds argument. + */ + bool (*getLocalClipBounds)(ANPCanvas*, ANPRectF* bounds, bool aa); + /* Return the current clip bounds in device coordinates in bounds. If the + current clip is empty, return false and ignore the bounds argument. + */ + bool (*getDeviceClipBounds)(ANPCanvas*, ANPRectI* bounds); void (*drawColor)(ANPCanvas*, ANPColor); void (*drawPaint)(ANPCanvas*, const ANPPaint*); diff --git a/WebKit/android/plugins/sample/pluginGraphics.cpp b/WebKit/android/plugins/sample/pluginGraphics.cpp index 4c0e6f8..ffa43e5 100644 --- a/WebKit/android/plugins/sample/pluginGraphics.cpp +++ b/WebKit/android/plugins/sample/pluginGraphics.cpp @@ -145,9 +145,12 @@ void BallAnimation::draw(ANPCanvas* canvas) { bounce(&m_y, &m_dy, obj->window->height - OH); if (obj->mUnichar) { + ANPFontMetrics fm; + gPaintI.getFontMetrics(m_paint, &fm); + gPaintI.setColor(m_paint, 0xFF0000FF); char c = static_cast(obj->mUnichar); - gCanvasI.drawText(canvas, &c, 1, 10, 30, m_paint); + gCanvasI.drawText(canvas, &c, 1, 10, -fm.fTop, m_paint); } } -- cgit v1.1