diff options
author | Jocelyn Turcotte <jocelyn.turcotte@nokia.com> | 2010-04-06 10:36:47 (GMT) |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@nokia.com> | 2010-04-06 10:36:47 (GMT) |
commit | bb35b65bbfba82e0dd0ac306d3dab54436cdaff6 (patch) | |
tree | 8174cb262a960ff7b2e4aa8f1aaf154db71d2636 /src/3rdparty/webkit/WebCore/page | |
parent | 4b27d0d887269583a0f76e922948f8c25e96ab88 (diff) | |
download | Qt-bb35b65bbfba82e0dd0ac306d3dab54436cdaff6.zip Qt-bb35b65bbfba82e0dd0ac306d3dab54436cdaff6.tar.gz Qt-bb35b65bbfba82e0dd0ac306d3dab54436cdaff6.tar.bz2 |
Update src/3rdparty/webkit from trunk.
Imported from 839d8709327f925aacb3b6362c06152594def97e
in branch qtwebkit-2.0 of repository
git://gitorious.org/+qtwebkit-developers/webkit/qtwebkit.git
Rubber-stamped-by: Simon Hausmann
Diffstat (limited to 'src/3rdparty/webkit/WebCore/page')
106 files changed, 4835 insertions, 1704 deletions
diff --git a/src/3rdparty/webkit/WebCore/page/AbstractView.idl b/src/3rdparty/webkit/WebCore/page/AbstractView.idl index 36865de..290bf48 100644 --- a/src/3rdparty/webkit/WebCore/page/AbstractView.idl +++ b/src/3rdparty/webkit/WebCore/page/AbstractView.idl @@ -28,7 +28,8 @@ module views { // Introduced in DOM Level 2: interface [ - ObjCCustomImplementation + ObjCCustomImplementation, + OmitConstructor ] AbstractView { readonly attribute Document document; readonly attribute Media media; diff --git a/src/3rdparty/webkit/WebCore/page/BarInfo.cpp b/src/3rdparty/webkit/WebCore/page/BarInfo.cpp index 0f6cad5..b6ab686 100644 --- a/src/3rdparty/webkit/WebCore/page/BarInfo.cpp +++ b/src/3rdparty/webkit/WebCore/page/BarInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -60,23 +60,25 @@ bool BarInfo::visible() const { if (!m_frame) return false; + Page* page = m_frame->page(); + if (!page) + return false; switch (m_type) { case Locationbar: - return m_frame->page()->chrome()->toolbarsVisible(); - case Toolbar: - return m_frame->page()->chrome()->toolbarsVisible(); case Personalbar: - return m_frame->page()->chrome()->toolbarsVisible(); + case Toolbar: + return page->chrome()->toolbarsVisible(); case Menubar: - return m_frame->page()->chrome()->menubarVisible(); + return page->chrome()->menubarVisible(); case Scrollbars: - return m_frame->page()->chrome()->scrollbarsVisible(); + return page->chrome()->scrollbarsVisible(); case Statusbar: - return m_frame->page()->chrome()->statusbarVisible(); - default: - return false; + return page->chrome()->statusbarVisible(); } + + ASSERT_NOT_REACHED(); + return false; } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/BarInfo.idl b/src/3rdparty/webkit/WebCore/page/BarInfo.idl index 42041c5..2089895 100644 --- a/src/3rdparty/webkit/WebCore/page/BarInfo.idl +++ b/src/3rdparty/webkit/WebCore/page/BarInfo.idl @@ -28,7 +28,7 @@ module window { - interface BarInfo { + interface [OmitConstructor] BarInfo { readonly attribute boolean visible; }; diff --git a/src/3rdparty/webkit/WebCore/page/Chrome.cpp b/src/3rdparty/webkit/WebCore/page/Chrome.cpp index 96f0fb7..4174695 100644 --- a/src/3rdparty/webkit/WebCore/page/Chrome.cpp +++ b/src/3rdparty/webkit/WebCore/page/Chrome.cpp @@ -67,9 +67,19 @@ Chrome::~Chrome() m_client->chromeDestroyed(); } -void Chrome::repaint(const IntRect& windowRect, bool contentChanged, bool immediate, bool repaintContentOnly) +void Chrome::invalidateWindow(const IntRect& updateRect, bool immediate) { - m_client->repaint(windowRect, contentChanged, immediate, repaintContentOnly); + m_client->invalidateWindow(updateRect, immediate); +} + +void Chrome::invalidateContentsAndWindow(const IntRect& updateRect, bool immediate) +{ + m_client->invalidateContentsAndWindow(updateRect, immediate); +} + +void Chrome::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) +{ + m_client->invalidateContentsForSlowScroll(updateRect, immediate); } void Chrome::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) @@ -147,6 +157,11 @@ void Chrome::takeFocus(FocusDirection direction) const m_client->takeFocus(direction); } +void Chrome::focusedNodeChanged(Node* node) const +{ + m_client->focusedNodeChanged(node); +} + Page* Chrome::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features) const { Page* newPage = m_client->createWindow(frame, request, features); @@ -302,6 +317,16 @@ bool Chrome::shouldInterruptJavaScript() return m_client->shouldInterruptJavaScript(); } +void Chrome::registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title) +{ + m_client->registerProtocolHandler(scheme, baseURL, url, title); +} + +void Chrome::registerContentHandler(const String& mimeType, const String& baseURL, const String& url, const String& title) +{ + m_client->registerContentHandler(mimeType, baseURL, url, title); +} + IntRect Chrome::windowResizerRect() const { return m_client->windowResizerRect(); @@ -312,7 +337,7 @@ void Chrome::mouseDidMoveOverElement(const HitTestResult& result, unsigned modif if (result.innerNode()) { Document* document = result.innerNode()->document(); if (document && document->isDNSPrefetchEnabled()) - prefetchDNS(result.absoluteLinkURL().host()); + ResourceHandle::prepareForURL(result.absoluteLinkURL()); } m_client->mouseDidMoveOverElement(result, modifierFlags); @@ -392,19 +417,24 @@ void Chrome::print(Frame* frame) void Chrome::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation) { - // Defer loads in case the client method runs a new event loop that would - // otherwise cause the load to continue while we're in the middle of executing JavaScript. - PageGroupLoadDeferrer deferrer(m_page, true); - - ASSERT(frame); m_client->requestGeolocationPermissionForFrame(frame, geolocation); } +void Chrome::cancelGeolocationPermissionRequestForFrame(Frame* frame) +{ + m_client->cancelGeolocationPermissionRequestForFrame(frame); +} + void Chrome::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser) { m_client->runOpenPanel(frame, fileChooser); } +void Chrome::chooseIconForFiles(const Vector<String>& filenames, PassRefPtr<FileChooser> fileChooser) +{ + m_client->chooseIconForFiles(filenames, fileChooser); +} + bool Chrome::setCursor(PlatformCursorHandle cursor) { return m_client->setCursor(cursor); diff --git a/src/3rdparty/webkit/WebCore/page/Chrome.h b/src/3rdparty/webkit/WebCore/page/Chrome.h index 033311d..72312bc 100644 --- a/src/3rdparty/webkit/WebCore/page/Chrome.h +++ b/src/3rdparty/webkit/WebCore/page/Chrome.h @@ -42,6 +42,7 @@ namespace WebCore { class Geolocation; class HitTestResult; class IntRect; + class Node; class Page; class String; #if ENABLE(NOTIFICATIONS) @@ -59,8 +60,11 @@ namespace WebCore { ChromeClient* client() { return m_client; } // HostWindow methods. - 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 void invalidateWindow(const IntRect&, bool); + virtual void invalidateContentsAndWindow(const IntRect&, bool); + virtual void invalidateContentsForSlowScroll(const IntRect&, bool); + virtual void scroll(const IntSize&, const IntRect&, const IntRect&); virtual IntPoint screenToWindow(const IntPoint&) const; virtual IntRect windowToScreen(const IntRect&) const; virtual PlatformPageClient platformPageClient() const; @@ -82,6 +86,8 @@ namespace WebCore { bool canTakeFocus(FocusDirection) const; void takeFocus(FocusDirection) const; + void focusedNodeChanged(Node*) const; + Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&) const; void show() const; @@ -114,6 +120,9 @@ namespace WebCore { void setStatusbarText(Frame*, const String&); bool shouldInterruptJavaScript(); + void registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title); + void registerContentHandler(const String& mimeType, const String& baseURL, const String& url, const String& title); + IntRect windowResizerRect() const; void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); @@ -123,8 +132,10 @@ namespace WebCore { void print(Frame*); void requestGeolocationPermissionForFrame(Frame*, Geolocation*); + void cancelGeolocationPermissionRequestForFrame(Frame*); void runOpenPanel(Frame*, PassRefPtr<FileChooser>); + void chooseIconForFiles(const Vector<String>&, PassRefPtr<FileChooser>); bool setCursor(PlatformCursorHandle); diff --git a/src/3rdparty/webkit/WebCore/page/ChromeClient.h b/src/3rdparty/webkit/WebCore/page/ChromeClient.h index 5231603..34e2893 100644 --- a/src/3rdparty/webkit/WebCore/page/ChromeClient.h +++ b/src/3rdparty/webkit/WebCore/page/ChromeClient.h @@ -83,6 +83,8 @@ namespace WebCore { virtual bool canTakeFocus(FocusDirection) = 0; virtual void takeFocus(FocusDirection) = 0; + virtual void focusedNodeChanged(Node*) = 0; + // 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 @@ -121,11 +123,16 @@ namespace WebCore { virtual bool shouldInterruptJavaScript() = 0; virtual bool tabsToLinks() const = 0; + virtual void registerProtocolHandler(const String&, const String&, const String&, const String&) { } + virtual void registerContentHandler(const String&, const String&, const String&, const String&) { } + virtual IntRect windowResizerRect() const = 0; // Methods used by HostWindow. - virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false) = 0; - virtual void scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) = 0; + virtual void invalidateWindow(const IntRect&, bool) = 0; + virtual void invalidateContentsAndWindow(const IntRect&, bool) = 0; + virtual void invalidateContentsForSlowScroll(const IntRect&, bool) = 0; + virtual void scroll(const IntSize&, const IntRect&, const IntRect&) = 0; virtual IntPoint screenToWindow(const IntPoint&) const = 0; virtual IntRect windowToScreen(const IntRect&) const = 0; virtual PlatformPageClient platformPageClient() const = 0; @@ -176,10 +183,13 @@ namespace WebCore { virtual bool paintCustomScrollCorner(GraphicsContext*, const FloatRect&); // This can be either a synchronous or asynchronous call. The ChromeClient can display UI asking the user for permission - // to use Geolococation. The ChromeClient must call Geolocation::setShouldClearCache() appropriately. + // to use Geolocation. virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) = 0; + virtual void cancelGeolocationPermissionRequestForFrame(Frame*) = 0; virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) = 0; + // Asynchronous request to load an icon for specified filenames. + virtual void chooseIconForFiles(const Vector<String>&, PassRefPtr<FileChooser>) = 0; virtual bool setCursor(PlatformCursorHandle) = 0; @@ -216,6 +226,17 @@ namespace WebCore { virtual void willPopUpMenu(NSMenu *) { } #endif +#if ENABLE(TOUCH_EVENTS) + virtual void needTouchEvents(bool) = 0; +#endif + +#if ENABLE(WIDGETS_10_SUPPORT) + virtual bool isDocked() { return false; } + virtual bool isFloating() { return false; } + virtual bool isApplication() { return false; } + virtual bool isFullscreen() { return false; } +#endif + protected: virtual ~ChromeClient() { } }; diff --git a/src/3rdparty/webkit/WebCore/page/Console.cpp b/src/3rdparty/webkit/WebCore/page/Console.cpp index 7d0f697..99b3106 100644 --- a/src/3rdparty/webkit/WebCore/page/Console.cpp +++ b/src/3rdparty/webkit/WebCore/page/Console.cpp @@ -30,6 +30,7 @@ #include "Console.h" #include "CString.h" +#include "Chrome.h" #include "ChromeClient.h" #include "ConsoleMessage.h" #include "Frame.h" @@ -40,11 +41,9 @@ #include "PageGroup.h" #include "PlatformString.h" -#if ENABLE(JAVASCRIPT_DEBUGGER) -#include <profiler/Profiler.h> -#endif - #include "ScriptCallStack.h" +#include "ScriptProfile.h" +#include "ScriptProfiler.h" #include <stdio.h> #include <wtf/UnusedParam.h> @@ -191,7 +190,7 @@ void Console::addMessage(MessageType type, MessageLevel level, ScriptCallStack* for (unsigned i = 0; i < lastCaller.argumentCount(); ++i) { String argAsString; - if (lastCaller.argumentAt(i).getString(argAsString)) + if (lastCaller.argumentAt(i).getString(callStack->state(), argAsString)) printf(" %s", argAsString.utf8().data()); } printf("\n"); @@ -270,6 +269,23 @@ void Console::count(ScriptCallStack* callStack) #endif } +void Console::markTimeline(ScriptCallStack* callStack) +{ +#if ENABLE(INSPECTOR) + Page* page = this->page(); + if (!page) + return; + + const ScriptCallFrame& lastCaller = callStack->at(0); + String message; + getFirstArgumentAsString(callStack->state(), lastCaller, message); + + page->inspectorController()->markTimeline(message); +#else + UNUSED_PARAM(callStack); +#endif +} + #if ENABLE(WML) String Console::lastWMLErrorMessage() const { @@ -298,7 +314,7 @@ String Console::lastWMLErrorMessage() const #if ENABLE(JAVASCRIPT_DEBUGGER) -void Console::profile(const JSC::UString& title, ScriptCallStack* callStack) +void Console::profile(const String& title, ScriptCallStack* callStack) { Page* page = this->page(); if (!page) @@ -311,15 +327,15 @@ void Console::profile(const JSC::UString& title, ScriptCallStack* callStack) return; #endif - JSC::UString resolvedTitle = title; - if (title.isNull()) // no title so give it the next user initiated profile title. + String resolvedTitle = title; + if (title.isNull()) // no title so give it the next user initiated profile title. #if ENABLE(INSPECTOR) resolvedTitle = controller->getCurrentUserInitiatedProfileName(true); #else resolvedTitle = ""; #endif - JSC::Profiler::profiler()->startProfiling(callStack->state(), resolvedTitle); + ScriptProfiler::start(callStack->state(), resolvedTitle); #if ENABLE(INSPECTOR) const ScriptCallFrame& lastCaller = callStack->at(0); @@ -327,22 +343,19 @@ void Console::profile(const JSC::UString& title, ScriptCallStack* callStack) #endif } -void Console::profileEnd(const JSC::UString& title, ScriptCallStack* callStack) +void Console::profileEnd(const String& title, ScriptCallStack* callStack) { Page* page = this->page(); if (!page) return; - if (!this->page()) - return; - #if ENABLE(INSPECTOR) InspectorController* controller = page->inspectorController(); if (!controller->profilerEnabled()) return; #endif - RefPtr<JSC::Profile> profile = JSC::Profiler::profiler()->stopProfiling(callStack->state(), title); + RefPtr<ScriptProfile> profile = ScriptProfiler::stop(callStack->state(), title); if (!profile) return; diff --git a/src/3rdparty/webkit/WebCore/page/Console.h b/src/3rdparty/webkit/WebCore/page/Console.h index 1b93a4a..9a6d88c 100644 --- a/src/3rdparty/webkit/WebCore/page/Console.h +++ b/src/3rdparty/webkit/WebCore/page/Console.h @@ -31,100 +31,99 @@ #include "PlatformString.h" -#if ENABLE(JAVASCRIPT_DEBUGGER) -#include <profiler/Profile.h> -#endif +#include "ScriptProfile.h" -#include <wtf/RefCounted.h> #include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> namespace WebCore { #if ENABLE(JAVASCRIPT_DEBUGGER) - typedef Vector<RefPtr<JSC::Profile> > ProfilesArray; +typedef Vector<RefPtr<ScriptProfile> > ProfilesArray; #endif - class Frame; - class Page; - class String; - class ScriptCallStack; - - // Keep in sync with inspector/front-end/Console.js - enum MessageSource { - HTMLMessageSource, - WMLMessageSource, - XMLMessageSource, - JSMessageSource, - CSSMessageSource, - OtherMessageSource - }; - - enum MessageType { - LogMessageType, - ObjectMessageType, - TraceMessageType, - StartGroupMessageType, - EndGroupMessageType, - AssertMessageType - }; - - enum MessageLevel { - TipMessageLevel, - LogMessageLevel, - WarningMessageLevel, - ErrorMessageLevel, - DebugMessageLevel - }; - - class Console : public RefCounted<Console> { - public: - static PassRefPtr<Console> create(Frame* frame) { return adoptRef(new Console(frame)); } - - Frame* frame() const; - void disconnectFrame(); - - void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL); - - void debug(ScriptCallStack*); - void error(ScriptCallStack*); - void info(ScriptCallStack*); - void log(ScriptCallStack*); - void warn(ScriptCallStack*); - void dir(ScriptCallStack*); - void dirxml(ScriptCallStack*); - void trace(ScriptCallStack*); - void assertCondition(bool condition, ScriptCallStack*); - void count(ScriptCallStack*); +class Frame; +class Page; +class String; +class ScriptCallStack; + +// Keep in sync with inspector/front-end/Console.js +enum MessageSource { + HTMLMessageSource, + WMLMessageSource, + XMLMessageSource, + JSMessageSource, + CSSMessageSource, + OtherMessageSource +}; + +enum MessageType { + LogMessageType, + ObjectMessageType, + TraceMessageType, + StartGroupMessageType, + EndGroupMessageType, + AssertMessageType +}; + +enum MessageLevel { + TipMessageLevel, + LogMessageLevel, + WarningMessageLevel, + ErrorMessageLevel, + DebugMessageLevel +}; + +class Console : public RefCounted<Console> { +public: + static PassRefPtr<Console> create(Frame* frame) { return adoptRef(new Console(frame)); } + + Frame* frame() const; + void disconnectFrame(); + + void addMessage(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL); + + void debug(ScriptCallStack*); + void error(ScriptCallStack*); + void info(ScriptCallStack*); + void log(ScriptCallStack*); + void warn(ScriptCallStack*); + void dir(ScriptCallStack*); + void dirxml(ScriptCallStack*); + void trace(ScriptCallStack*); + void assertCondition(bool condition, ScriptCallStack*); + void count(ScriptCallStack*); + void markTimeline(ScriptCallStack*); #if ENABLE(WML) - String lastWMLErrorMessage() const; + String lastWMLErrorMessage() const; #endif #if ENABLE(JAVASCRIPT_DEBUGGER) - void profile(const JSC::UString&, ScriptCallStack*); - void profileEnd(const JSC::UString&, ScriptCallStack*); + void profile(const String&, ScriptCallStack*); + void profileEnd(const String&, ScriptCallStack*); #endif - void time(const String&); - void timeEnd(const String&, ScriptCallStack*); - void group(ScriptCallStack*); - void groupEnd(); + void time(const String&); + void timeEnd(const String&, ScriptCallStack*); + void group(ScriptCallStack*); + void groupEnd(); - static bool shouldPrintExceptions(); - static void setShouldPrintExceptions(bool); + static bool shouldPrintExceptions(); + static void setShouldPrintExceptions(bool); #if ENABLE(JAVASCRIPT_DEBUGGER) - const ProfilesArray& profiles() const { return m_profiles; } + const ProfilesArray& profiles() const { return m_profiles; } #endif - private: - inline Page* page() const; - void addMessage(MessageType, MessageLevel, ScriptCallStack*, bool acceptNoArguments = false); +private: + inline Page* page() const; + void addMessage(MessageType, MessageLevel, ScriptCallStack*, bool acceptNoArguments = false); - Console(Frame*); + Console(Frame*); - Frame* m_frame; + Frame* m_frame; #if ENABLE(JAVASCRIPT_DEBUGGER) - ProfilesArray m_profiles; + ProfilesArray m_profiles; #endif - }; +}; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Console.idl b/src/3rdparty/webkit/WebCore/page/Console.idl index 0e9f3dc..c08fcc0 100644 --- a/src/3rdparty/webkit/WebCore/page/Console.idl +++ b/src/3rdparty/webkit/WebCore/page/Console.idl @@ -28,9 +28,10 @@ module window { - interface Console { + interface [OmitConstructor] Console { -#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER + // Not enabled in V8 because it requires request-reply style. +#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER && !(defined(V8_BINDING) && V8_BINDING) readonly attribute [CustomGetter] Array profiles; #endif @@ -44,6 +45,7 @@ module window { [CustomArgumentHandling] void trace(); [CustomArgumentHandling, ImplementationFunction=assertCondition] void assert(in boolean condition); [CustomArgumentHandling] void count(); + [CustomArgumentHandling] void markTimeline(); #if defined(ENABLE_WML) && ENABLE_WML [DontEnum] DOMString lastWMLErrorMessage(); diff --git a/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp b/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp index 7d773ca..d384b02 100644 --- a/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp +++ b/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp @@ -31,6 +31,7 @@ #include "Chrome.h" #include "ContextMenu.h" #include "ContextMenuClient.h" +#include "ContextMenuProvider.h" #include "Document.h" #include "DocumentFragment.h" #include "DocumentLoader.h" @@ -79,13 +80,38 @@ ContextMenuController::~ContextMenuController() void ContextMenuController::clearContextMenu() { m_contextMenu.set(0); + if (m_menuProvider) + m_menuProvider->contextMenuCleared(); + m_menuProvider = 0; } void ContextMenuController::handleContextMenuEvent(Event* event) { - ASSERT(event->type() == eventNames().contextmenuEvent); - if (!event->isMouseEvent()) + m_contextMenu.set(createContextMenu(event)); + if (!m_contextMenu) return; + m_contextMenu->populate(); + showContextMenu(event); +} + +void ContextMenuController::showContextMenu(Event* event, PassRefPtr<ContextMenuProvider> menuProvider) +{ + m_menuProvider = menuProvider; + + m_contextMenu.set(createContextMenu(event)); + if (!m_contextMenu) { + clearContextMenu(); + return; + } + + m_menuProvider->populateContextMenu(m_contextMenu.get()); + showContextMenu(event); +} + +ContextMenu* ContextMenuController::createContextMenu(Event* event) +{ + if (!event->isMouseEvent()) + return 0; MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); HitTestResult result(mouseEvent->absoluteLocation()); @@ -93,18 +119,18 @@ void ContextMenuController::handleContextMenuEvent(Event* event) result = frame->eventHandler()->hitTestResultAtPoint(mouseEvent->absoluteLocation(), false); if (!result.innerNonSharedNode()) - return; + return 0; + return new ContextMenu(result); +} - m_contextMenu.set(new ContextMenu(result)); - m_contextMenu->populate(); +void ContextMenuController::showContextMenu(Event* event) +{ #if ENABLE(INSPECTOR) if (m_page->inspectorController()->enabled()) m_contextMenu->addInspectElementItem(); #endif - PlatformMenuDescription customMenu = m_client->getCustomMenuFromDefaultItems(m_contextMenu.get()); m_contextMenu->setPlatformDescription(customMenu); - event->setDefaultHandled(); } @@ -126,6 +152,12 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item) return; } + if (item->action() >= ContextMenuItemBaseCustomTag) { + ASSERT(m_menuProvider); + m_menuProvider->contextMenuItemSelected(item); + return; + } + HitTestResult result = m_contextMenu->hitTestResult(); Frame* frame = result.innerNonSharedNode()->document()->frame(); if (!frame) diff --git a/src/3rdparty/webkit/WebCore/page/ContextMenuController.h b/src/3rdparty/webkit/WebCore/page/ContextMenuController.h index 38095f6..833b909 100644 --- a/src/3rdparty/webkit/WebCore/page/ContextMenuController.h +++ b/src/3rdparty/webkit/WebCore/page/ContextMenuController.h @@ -28,12 +28,15 @@ #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> namespace WebCore { class ContextMenu; class ContextMenuClient; class ContextMenuItem; + class ContextMenuProvider; class Event; class Page; @@ -48,12 +51,18 @@ namespace WebCore { void clearContextMenu(); void handleContextMenuEvent(Event*); + void showContextMenu(Event*, PassRefPtr<ContextMenuProvider>); + void contextMenuItemSelected(ContextMenuItem*); private: + ContextMenu* createContextMenu(Event*); + void showContextMenu(Event*); + Page* m_page; ContextMenuClient* m_client; OwnPtr<ContextMenu> m_contextMenu; + RefPtr<ContextMenuProvider> m_menuProvider; }; } diff --git a/src/3rdparty/webkit/WebCore/page/ContextMenuProvider.h b/src/3rdparty/webkit/WebCore/page/ContextMenuProvider.h new file mode 100644 index 0000000..57598d1 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/ContextMenuProvider.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 ContextMenuProvider_h +#define ContextMenuProvider_h + +#include <wtf/RefCounted.h> + +namespace WebCore { + +class ContextMenu; +class ContextMenuItem; + +class ContextMenuProvider : public RefCounted<ContextMenuProvider> { +public: + virtual ~ContextMenuProvider() { }; + + virtual void populateContextMenu(ContextMenu*) = 0; + virtual void contextMenuItemSelected(ContextMenuItem*) = 0; + virtual void contextMenuCleared() = 0; +}; + +} + +#endif // ContextMenuProvider_h diff --git a/src/3rdparty/webkit/WebCore/page/Coordinates.idl b/src/3rdparty/webkit/WebCore/page/Coordinates.idl index f847325..5a5a141 100644 --- a/src/3rdparty/webkit/WebCore/page/Coordinates.idl +++ b/src/3rdparty/webkit/WebCore/page/Coordinates.idl @@ -25,7 +25,7 @@ module core { - interface Coordinates { + interface [OmitConstructor] Coordinates { readonly attribute double latitude; readonly attribute double longitude; readonly attribute [Custom] double altitude; diff --git a/src/3rdparty/webkit/WebCore/page/DOMSelection.cpp b/src/3rdparty/webkit/WebCore/page/DOMSelection.cpp index 0d21c56..12ae59d 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMSelection.cpp +++ b/src/3rdparty/webkit/WebCore/page/DOMSelection.cpp @@ -326,7 +326,6 @@ void DOMSelection::extend(Node* node, int offset, ExceptionCode& ec) } SelectionController* selection = m_frame->selection(); - selection->expandUsingGranularity(CharacterGranularity); selection->setExtent(VisiblePosition(node, offset, DOWNSTREAM)); } diff --git a/src/3rdparty/webkit/WebCore/page/DOMSelection.idl b/src/3rdparty/webkit/WebCore/page/DOMSelection.idl index be6c2b4..4d0c942 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMSelection.idl +++ b/src/3rdparty/webkit/WebCore/page/DOMSelection.idl @@ -31,7 +31,7 @@ module window { // This is based off of Mozilla's Selection interface // https://developer.mozilla.org/En/DOM/Selection - interface DOMSelection { + interface [OmitConstructor] DOMSelection { readonly attribute Node anchorNode; readonly attribute long anchorOffset; readonly attribute Node focusNode; diff --git a/src/3rdparty/webkit/WebCore/page/DOMTimer.cpp b/src/3rdparty/webkit/WebCore/page/DOMTimer.cpp index 83bcb02..72dc9ac 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMTimer.cpp +++ b/src/3rdparty/webkit/WebCore/page/DOMTimer.cpp @@ -43,7 +43,7 @@ double DOMTimer::s_minTimerInterval = 0.010; // 10 milliseconds static int timerNestingLevel = 0; -DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) +DOMTimer::DOMTimer(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) : ActiveDOMObject(context, this) , m_action(action) , m_nextFireInterval(0) @@ -82,7 +82,7 @@ DOMTimer::~DOMTimer() scriptExecutionContext()->removeTimeout(m_timeoutId); } -int DOMTimer::install(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) +int DOMTimer::install(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) { // DOMTimer constructor links the new timer into a list of ActiveDOMObjects held by the 'context'. // The timer is deleted when context is deleted (DOMTimer::contextDestroyed) or explicitly via DOMTimer::removeById(), @@ -119,8 +119,7 @@ void DOMTimer::fired() timerNestingLevel = m_nestingLevel; #if ENABLE(INSPECTOR) - InspectorTimelineAgent* timelineAgent = InspectorTimelineAgent::retrieve(context); - if (timelineAgent) + if (InspectorTimelineAgent* timelineAgent = InspectorTimelineAgent::retrieve(context)) timelineAgent->willFireTimer(m_timeoutId); #endif @@ -135,7 +134,7 @@ void DOMTimer::fired() // No access to member variables after this point, it can delete the timer. m_action->execute(context); #if ENABLE(INSPECTOR) - if (timelineAgent) + if (InspectorTimelineAgent* timelineAgent = InspectorTimelineAgent::retrieve(context)) timelineAgent->didFireTimer(); #endif return; @@ -149,7 +148,7 @@ void DOMTimer::fired() action->execute(context); #if ENABLE(INSPECTOR) - if (timelineAgent) + if (InspectorTimelineAgent* timelineAgent = InspectorTimelineAgent::retrieve(context)) timelineAgent->didFireTimer(); #endif delete action; diff --git a/src/3rdparty/webkit/WebCore/page/DOMTimer.h b/src/3rdparty/webkit/WebCore/page/DOMTimer.h index 460430f..da38178 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMTimer.h +++ b/src/3rdparty/webkit/WebCore/page/DOMTimer.h @@ -28,20 +28,21 @@ #define DOMTimer_h #include "ActiveDOMObject.h" +#include "ScheduledAction.h" #include "Timer.h" #include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { class InspectorTimelineAgent; - class ScheduledAction; class DOMTimer : public TimerBase, public ActiveDOMObject { public: virtual ~DOMTimer(); // Creates a new timer owned by specified ScriptExecutionContext, starts it // and returns its Id. - static int install(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot); + static int install(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); static void removeById(ScriptExecutionContext*, int timeoutId); // ActiveDOMObject @@ -59,7 +60,7 @@ namespace WebCore { static void setMinTimerInterval(double value) { s_minTimerInterval = value; } private: - DOMTimer(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot); + DOMTimer(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); virtual void fired(); int m_timeoutId; diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp b/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp index c30b6b9..dd90200 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "DOMWindow.h" +#include "Base64.h" #include "BarInfo.h" #include "BeforeUnloadEvent.h" #include "CSSComputedStyleDeclaration.h" @@ -35,6 +36,7 @@ #include "Chrome.h" #include "Console.h" #include "Database.h" +#include "DatabaseCallback.h" #include "DOMApplicationCache.h" #include "DOMSelection.h" #include "DOMTimer.h" @@ -53,6 +55,7 @@ #include "HTMLFrameOwnerElement.h" #include "History.h" #include "InspectorController.h" +#include "InspectorTimelineAgent.h" #include "Location.h" #include "Media.h" #include "MessageEvent.h" @@ -262,7 +265,7 @@ void DOMWindow::dispatchAllPendingUnloadEvents() if (!set.contains(window)) continue; - window->dispatchEvent(PageTransitionEvent::create(EventNames().pagehideEvent, false), window->document()); + window->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, false), window->document()); window->dispatchEvent(Event::create(eventNames().unloadEvent, false, false), window->document()); } @@ -341,8 +344,6 @@ void DOMWindow::parseModalDialogFeatures(const String& featuresArg, HashMap<Stri bool DOMWindow::allowPopUp(Frame* activeFrame) { ASSERT(activeFrame); - if (activeFrame->script()->processingUserGesture()) - return true; Settings* settings = activeFrame->settings(); return settings && settings->javaScriptCanOpenWindowsAutomatically(); } @@ -441,6 +442,10 @@ void DOMWindow::clear() if (m_location) m_location->disconnectFrame(); m_location = 0; + + if (m_media) + m_media->disconnectFrame(); + m_media = 0; #if ENABLE(DOM_STORAGE) if (m_sessionStorage) @@ -459,6 +464,8 @@ void DOMWindow::clear() #endif #if ENABLE(NOTIFICATIONS) + if (m_notifications) + m_notifications->disconnectFrame(); m_notifications = 0; #endif } @@ -573,9 +580,6 @@ Storage* DOMWindow::sessionStorage() const if (!page) return 0; - if (!page->settings()->sessionStorageEnabled()) - return 0; - RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin()); #if ENABLE(INSPECTOR) page->inspectorController()->didUseDOMStorage(storageArea.get(), false, m_frame); @@ -585,7 +589,7 @@ Storage* DOMWindow::sessionStorage() const return m_sessionStorage.get(); } -Storage* DOMWindow::localStorage() const +Storage* DOMWindow::localStorage(ExceptionCode& ec) const { if (m_localStorage) return m_localStorage.get(); @@ -593,6 +597,11 @@ Storage* DOMWindow::localStorage() const Document* document = this->document(); if (!document) return 0; + + if (!document->securityOrigin()->canAccessLocalStorage()) { + ec = SECURITY_ERR; + return 0; + } Page* page = document->page(); if (!page) @@ -625,9 +634,6 @@ NotificationCenter* DOMWindow::webkitNotifications() const if (!page) return 0; - if (!page->settings()->experimentalNotificationsEnabled()) - return 0; - NotificationPresenter* provider = page->chrome()->notificationPresenter(); if (provider) m_notifications = NotificationCenter::create(document, provider); @@ -636,6 +642,13 @@ NotificationCenter* DOMWindow::webkitNotifications() const } #endif +#if ENABLE(INDEXED_DATABASE) +IndexedDatabaseRequest* DOMWindow::indexedDB() const +{ + return 0; +} +#endif + void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec) { MessagePortArray ports; @@ -814,6 +827,57 @@ String DOMWindow::prompt(const String& message, const String& defaultValue) return String(); } +static bool isSafeToConvertCharList(const String& string) +{ + for (unsigned i = 0; i < string.length(); i++) { + if (string[i] > 0xFF) + return false; + } + + return true; +} + +String DOMWindow::btoa(const String& stringToEncode, ExceptionCode& ec) +{ + if (stringToEncode.isNull()) + return String(); + + if (!isSafeToConvertCharList(stringToEncode)) { + ec = INVALID_CHARACTER_ERR; + return String(); + } + + Vector<char> in; + in.append(stringToEncode.characters(), stringToEncode.length()); + Vector<char> out; + + base64Encode(in, out); + + return String(out.data(), out.size()); +} + +String DOMWindow::atob(const String& encodedString, ExceptionCode& ec) +{ + if (encodedString.isNull()) + return String(); + + if (!isSafeToConvertCharList(encodedString)) { + ec = INVALID_CHARACTER_ERR; + return String(); + } + + Vector<char> in; + in.append(encodedString.characters(), encodedString.length()); + Vector<char> out; + + if (!base64Decode(in, out)) { + ec = INVALID_CHARACTER_ERR; + return String(); + } + + return String(out.data(), out.size()); +} + bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const { if (!m_frame) @@ -1050,7 +1114,9 @@ Document* DOMWindow::document() const PassRefPtr<Media> DOMWindow::media() const { - return Media::create(const_cast<DOMWindow*>(this)); + if (!m_media) + m_media = Media::create(m_frame); + return m_media.get(); } PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String&) const @@ -1078,7 +1144,9 @@ PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, { if (!node || !p) return 0; - + + m_frame->document()->updateLayoutIgnorePendingStylesheets(); + FloatPoint pagePoint(p->x(), p->y()); pagePoint = node->convertToPage(pagePoint); return WebKitPoint::create(pagePoint.x(), pagePoint.y()); @@ -1088,7 +1156,9 @@ PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, { if (!node || !p) return 0; - + + m_frame->document()->updateLayoutIgnorePendingStylesheets(); + FloatPoint nodePoint(p->x(), p->y()); nodePoint = node->convertFromPage(nodePoint); return WebKitPoint::create(nodePoint.x(), nodePoint.y()); @@ -1107,18 +1177,21 @@ double DOMWindow::devicePixelRatio() const } #if ENABLE(DATABASE) -PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode& ec) +PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& ec) { if (!m_frame) return 0; - Document* doc = m_frame->document(); + if (!Database::isAvailable()) + return 0; - Settings* settings = m_frame->settings(); - if (!settings || !settings->databasesEnabled()) + Document* document = m_frame->document(); + if (!document->securityOrigin()->canAccessDatabase()) { + ec = SECURITY_ERR; return 0; + } - return Database::openDatabase(doc, name, version, displayName, estimatedSize, ec); + return Database::openDatabase(document, name, version, displayName, estimatedSize, creationCallback, ec); } #endif @@ -1232,24 +1305,40 @@ void DOMWindow::resizeTo(float width, float height) const page->chrome()->setWindowRect(fr); } -int DOMWindow::setTimeout(ScheduledAction* action, int timeout) +int DOMWindow::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec) { - return DOMTimer::install(scriptExecutionContext(), action, timeout, true); + ScriptExecutionContext* context = scriptExecutionContext(); + if (!context) { + ec = INVALID_ACCESS_ERR; + return -1; + } + return DOMTimer::install(context, action, timeout, true); } void DOMWindow::clearTimeout(int timeoutId) { - DOMTimer::removeById(scriptExecutionContext(), timeoutId); + ScriptExecutionContext* context = scriptExecutionContext(); + if (!context) + return; + DOMTimer::removeById(context, timeoutId); } -int DOMWindow::setInterval(ScheduledAction* action, int timeout) +int DOMWindow::setInterval(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec) { - return DOMTimer::install(scriptExecutionContext(), action, timeout, false); + ScriptExecutionContext* context = scriptExecutionContext(); + if (!context) { + ec = INVALID_ACCESS_ERR; + return -1; + } + return DOMTimer::install(context, action, timeout, false); } void DOMWindow::clearInterval(int timeoutId) { - DOMTimer::removeById(scriptExecutionContext(), timeoutId); + ScriptExecutionContext* context = scriptExecutionContext(); + if (!context) + return; + DOMTimer::removeById(context, timeoutId); } bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) @@ -1304,6 +1393,15 @@ void DOMWindow::dispatchLoadEvent() #endif } +#if ENABLE(INSPECTOR) +InspectorTimelineAgent* DOMWindow::inspectorTimelineAgent() +{ + if (frame() && frame()->page()) + return frame()->page()->inspectorTimelineAgent(); + return 0; +} +#endif + bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget> prpTarget) { RefPtr<EventTarget> protect = this; @@ -1313,7 +1411,24 @@ bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget event->setCurrentTarget(this); event->setEventPhase(Event::AT_TARGET); - return fireEventListeners(event.get()); +#if ENABLE(INSPECTOR) + InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(); + bool timelineAgentIsActive = timelineAgent && hasEventListeners(event->type()); + if (timelineAgentIsActive) + timelineAgent->willDispatchEvent(*event); +#endif + + bool result = fireEventListeners(event.get()); + +#if ENABLE(INSPECTOR) + if (timelineAgentIsActive) { + timelineAgent = inspectorTimelineAgent(); + if (timelineAgent) + timelineAgent->didDispatchEvent(); + } +#endif + + return result; } void DOMWindow::removeAllEventListeners() diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.h b/src/3rdparty/webkit/WebCore/page/DOMWindow.h index 25eadc8..a70713b 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.h +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.h @@ -45,6 +45,7 @@ namespace WebCore { class Console; class DOMSelection; class Database; + class DatabaseCallback; class Document; class Element; class Event; @@ -52,6 +53,8 @@ namespace WebCore { class FloatRect; class Frame; class History; + class IndexedDatabaseRequest; + class InspectorTimelineAgent; class Location; class Media; class Navigator; @@ -137,6 +140,8 @@ namespace WebCore { void alert(const String& message); bool confirm(const String& message); String prompt(const String& message, const String& defaultValue); + String btoa(const String& stringToEncode, ExceptionCode&); + String atob(const String& encodedString, ExceptionCode&); bool find(const String&, bool caseSensitive, bool backwards, bool wrap, bool wholeWord, bool searchInFrames, bool showDialog) const; @@ -196,13 +201,13 @@ namespace WebCore { #if ENABLE(DATABASE) // HTML 5 client-side database - PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode&); + PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode&); #endif #if ENABLE(DOM_STORAGE) // HTML 5 key/value storage Storage* sessionStorage() const; - Storage* localStorage() const; + Storage* localStorage(ExceptionCode&) const; #endif Console* console() const; @@ -215,6 +220,10 @@ namespace WebCore { NotificationCenter* webkitNotifications() const; #endif +#if ENABLE(INDEXED_DATABASE) + IndexedDatabaseRequest* indexedDB() const; +#endif + void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, DOMWindow* source, ExceptionCode&); // FIXME: remove this when we update the ObjC bindings (bug #28774). void postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort*, const String& targetOrigin, DOMWindow* source, ExceptionCode&); @@ -231,9 +240,9 @@ namespace WebCore { void resizeTo(float width, float height) const; // Timers - int setTimeout(ScheduledAction*, int timeout); + int setTimeout(PassOwnPtr<ScheduledAction>, int timeout, ExceptionCode&); void clearTimeout(int timeoutId); - int setInterval(ScheduledAction*, int timeout); + int setInterval(PassOwnPtr<ScheduledAction>, int timeout, ExceptionCode&); void clearInterval(int timeoutId); // Events @@ -247,9 +256,13 @@ namespace WebCore { void dispatchLoadEvent(); DEFINE_ATTRIBUTE_EVENT_LISTENER(abort); + DEFINE_ATTRIBUTE_EVENT_LISTENER(beforeunload); DEFINE_ATTRIBUTE_EVENT_LISTENER(blur); + DEFINE_ATTRIBUTE_EVENT_LISTENER(canplay); + DEFINE_ATTRIBUTE_EVENT_LISTENER(canplaythrough); DEFINE_ATTRIBUTE_EVENT_LISTENER(change); DEFINE_ATTRIBUTE_EVENT_LISTENER(click); + DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu); DEFINE_ATTRIBUTE_EVENT_LISTENER(dblclick); DEFINE_ATTRIBUTE_EVENT_LISTENER(drag); DEFINE_ATTRIBUTE_EVENT_LISTENER(dragend); @@ -258,13 +271,22 @@ namespace WebCore { DEFINE_ATTRIBUTE_EVENT_LISTENER(dragover); DEFINE_ATTRIBUTE_EVENT_LISTENER(dragstart); DEFINE_ATTRIBUTE_EVENT_LISTENER(drop); + DEFINE_ATTRIBUTE_EVENT_LISTENER(durationchange); + DEFINE_ATTRIBUTE_EVENT_LISTENER(emptied); + DEFINE_ATTRIBUTE_EVENT_LISTENER(ended); DEFINE_ATTRIBUTE_EVENT_LISTENER(error); DEFINE_ATTRIBUTE_EVENT_LISTENER(focus); DEFINE_ATTRIBUTE_EVENT_LISTENER(hashchange); + DEFINE_ATTRIBUTE_EVENT_LISTENER(input); + DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid); DEFINE_ATTRIBUTE_EVENT_LISTENER(keydown); DEFINE_ATTRIBUTE_EVENT_LISTENER(keypress); DEFINE_ATTRIBUTE_EVENT_LISTENER(keyup); DEFINE_ATTRIBUTE_EVENT_LISTENER(load); + DEFINE_ATTRIBUTE_EVENT_LISTENER(loadeddata); + DEFINE_ATTRIBUTE_EVENT_LISTENER(loadedmetadata); + DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart); + DEFINE_ATTRIBUTE_EVENT_LISTENER(message); DEFINE_ATTRIBUTE_EVENT_LISTENER(mousedown); DEFINE_ATTRIBUTE_EVENT_LISTENER(mousemove); DEFINE_ATTRIBUTE_EVENT_LISTENER(mouseout); @@ -275,39 +297,30 @@ namespace WebCore { DEFINE_ATTRIBUTE_EVENT_LISTENER(online); DEFINE_ATTRIBUTE_EVENT_LISTENER(pagehide); DEFINE_ATTRIBUTE_EVENT_LISTENER(pageshow); + DEFINE_ATTRIBUTE_EVENT_LISTENER(pause); + DEFINE_ATTRIBUTE_EVENT_LISTENER(play); + DEFINE_ATTRIBUTE_EVENT_LISTENER(playing); + DEFINE_ATTRIBUTE_EVENT_LISTENER(popstate); + DEFINE_ATTRIBUTE_EVENT_LISTENER(progress); + DEFINE_ATTRIBUTE_EVENT_LISTENER(ratechange); DEFINE_ATTRIBUTE_EVENT_LISTENER(reset); DEFINE_ATTRIBUTE_EVENT_LISTENER(resize); DEFINE_ATTRIBUTE_EVENT_LISTENER(scroll); DEFINE_ATTRIBUTE_EVENT_LISTENER(search); + DEFINE_ATTRIBUTE_EVENT_LISTENER(seeked); + DEFINE_ATTRIBUTE_EVENT_LISTENER(seeking); DEFINE_ATTRIBUTE_EVENT_LISTENER(select); + DEFINE_ATTRIBUTE_EVENT_LISTENER(stalled); DEFINE_ATTRIBUTE_EVENT_LISTENER(storage); DEFINE_ATTRIBUTE_EVENT_LISTENER(submit); - DEFINE_ATTRIBUTE_EVENT_LISTENER(unload); - DEFINE_ATTRIBUTE_EVENT_LISTENER(beforeunload); - DEFINE_ATTRIBUTE_EVENT_LISTENER(canplay); - DEFINE_ATTRIBUTE_EVENT_LISTENER(canplaythrough); - DEFINE_ATTRIBUTE_EVENT_LISTENER(durationchange); - DEFINE_ATTRIBUTE_EVENT_LISTENER(emptied); - DEFINE_ATTRIBUTE_EVENT_LISTENER(ended); - DEFINE_ATTRIBUTE_EVENT_LISTENER(loadeddata); - DEFINE_ATTRIBUTE_EVENT_LISTENER(loadedmetadata); - DEFINE_ATTRIBUTE_EVENT_LISTENER(pause); - DEFINE_ATTRIBUTE_EVENT_LISTENER(play); - DEFINE_ATTRIBUTE_EVENT_LISTENER(playing); - DEFINE_ATTRIBUTE_EVENT_LISTENER(ratechange); - DEFINE_ATTRIBUTE_EVENT_LISTENER(seeked); - DEFINE_ATTRIBUTE_EVENT_LISTENER(seeking); + DEFINE_ATTRIBUTE_EVENT_LISTENER(suspend); DEFINE_ATTRIBUTE_EVENT_LISTENER(timeupdate); + DEFINE_ATTRIBUTE_EVENT_LISTENER(unload); DEFINE_ATTRIBUTE_EVENT_LISTENER(volumechange); DEFINE_ATTRIBUTE_EVENT_LISTENER(waiting); - DEFINE_ATTRIBUTE_EVENT_LISTENER(loadstart); - DEFINE_ATTRIBUTE_EVENT_LISTENER(progress); - DEFINE_ATTRIBUTE_EVENT_LISTENER(stalled); - DEFINE_ATTRIBUTE_EVENT_LISTENER(suspend); - DEFINE_ATTRIBUTE_EVENT_LISTENER(input); - DEFINE_ATTRIBUTE_EVENT_LISTENER(message); - DEFINE_ATTRIBUTE_EVENT_LISTENER(contextmenu); - DEFINE_ATTRIBUTE_EVENT_LISTENER(invalid); + DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitbeginfullscreen); + DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitendfullscreen); + #if ENABLE(ORIENTATION_EVENTS) DEFINE_ATTRIBUTE_EVENT_LISTENER(orientationchange); #endif @@ -317,6 +330,12 @@ namespace WebCore { DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(webkitanimationend, webkitAnimationEnd); DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(webkittransitionend, webkitTransitionEnd); +#if ENABLE(TOUCH_EVENTS) + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); + DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); +#endif void captureEvents(); void releaseEvents(); @@ -334,6 +353,7 @@ namespace WebCore { Console* optionalConsole() const { return m_console.get(); } Navigator* optionalNavigator() const { return m_navigator.get(); } Location* optionalLocation() const { return m_location.get(); } + Media* optionalMedia() const { return m_media.get(); } #if ENABLE(DOM_STORAGE) Storage* optionalSessionStorage() const { return m_sessionStorage.get(); } Storage* optionalLocalStorage() const { return m_localStorage.get(); } @@ -352,6 +372,7 @@ namespace WebCore { virtual void derefEventTarget() { deref(); } virtual EventTargetData* eventTargetData(); virtual EventTargetData* ensureEventTargetData(); + InspectorTimelineAgent* inspectorTimelineAgent(); RefPtr<SecurityOrigin> m_securityOrigin; KURL m_url; @@ -369,6 +390,7 @@ namespace WebCore { mutable RefPtr<Console> m_console; mutable RefPtr<Navigator> m_navigator; mutable RefPtr<Location> m_location; + mutable RefPtr<Media> m_media; #if ENABLE(DOM_STORAGE) mutable RefPtr<Storage> m_sessionStorage; mutable RefPtr<Storage> m_localStorage; diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.idl b/src/3rdparty/webkit/WebCore/page/DOMWindow.idl index 5addb83..d457bdc 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.idl +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.idl @@ -31,15 +31,15 @@ module window { CustomDefineSetter, CustomDeleteProperty, CustomGetOwnPropertySlot, - CustomGetPropertyAttributes, CustomGetPropertyNames, CustomLookupGetter, CustomLookupSetter, CustomMarkFunction, CustomNativeConverter, CustomPutFunction, - ExtendsDOMGlobalObject, EventTarget, + OmitConstructor, + ExtendsDOMGlobalObject, GenerateNativeConverter, LegacyParent=JSDOMWindowBase ] DOMWindow { @@ -157,19 +157,23 @@ module window { WebKitPoint webkitConvertPointFromNodeToPage(in Node node, in WebKitPoint p); #if defined(ENABLE_OFFLINE_WEB_APPLICATIONS) && ENABLE_OFFLINE_WEB_APPLICATIONS - readonly attribute DOMApplicationCache applicationCache; + readonly attribute [EnabledAtRuntime] DOMApplicationCache applicationCache; #endif #if defined(ENABLE_DATABASE) && ENABLE_DATABASE - [EnabledAtRuntime] Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize) + [EnabledAtRuntime, Custom] Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in DatabaseCallback creationCallback) raises(DOMException); #endif #if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE readonly attribute [EnabledAtRuntime] Storage sessionStorage; - readonly attribute [EnabledAtRuntime] Storage localStorage; + readonly attribute [EnabledAtRuntime] Storage localStorage + getter raises(DOMException); #endif #if defined(ENABLE_NOTIFICATIONS) && ENABLE_NOTIFICATIONS readonly attribute [EnabledAtRuntime] NotificationCenter webkitNotifications; #endif +#if defined(ENABLE_INDEXED_DATABASE) && ENABLE_INDEXED_DATABASE + readonly attribute [EnabledAtRuntime] IndexedDatabaseRequest indexedDB; +#endif #if defined(ENABLE_ORIENTATION_EVENTS) && ENABLE_ORIENTATION_EVENTS // This is the interface orientation in degrees. Some examples are: @@ -201,9 +205,9 @@ module window { void clearInterval(in long handle); // Base64 - [Custom] DOMString atob(in DOMString string) + DOMString atob(in [ConvertNullToNullString] DOMString string) raises(DOMException); - [Custom] DOMString btoa(in DOMString string) + DOMString btoa(in [ConvertNullToNullString] DOMString string) raises(DOMException); // Events @@ -252,6 +256,7 @@ module window { attribute EventListener onpause; attribute EventListener onplay; attribute EventListener onplaying; + attribute EventListener onpopstate; attribute EventListener onprogress; attribute EventListener onratechange; attribute EventListener onresize; @@ -273,7 +278,6 @@ module window { // attribute EventListener onbeforeprint; // attribute EventListener onformchange; // attribute EventListener onforminput; - // attribute EventListener onpopstate; // attribute EventListener onreadystatechange; // attribute EventListener onredo; // attribute EventListener onshow; @@ -289,6 +293,12 @@ module window { #if defined(ENABLE_ORIENTATION_EVENTS) && ENABLE_ORIENTATION_EVENTS attribute EventListener onorientationchange; #endif + #if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS + attribute [DontEnum] EventListener ontouchstart; + attribute [DontEnum] EventListener ontouchmove; + attribute [DontEnum] EventListener ontouchend; + attribute [DontEnum] EventListener ontouchcancel; + #endif // EventTarget interface [Custom] void addEventListener(in DOMString type, @@ -411,6 +421,9 @@ module window { attribute HTMLParagraphElementConstructor HTMLParagraphElement; attribute HTMLParamElementConstructor HTMLParamElement; attribute HTMLPreElementConstructor HTMLPreElement; +#if defined(ENABLE_PROGRESS_TAG) && ENABLE_PROGRESS_TAG + attribute HTMLProgressElementConstructor HTMLProgressElement; +#endif attribute HTMLQuoteElementConstructor HTMLQuoteElement; attribute HTMLScriptElementConstructor HTMLScriptElement; attribute HTMLSelectElementConstructor HTMLSelectElement; @@ -432,17 +445,18 @@ module window { attribute [CustomGetter] HTMLOptionElementConstructor Option; // Usable with new operator attribute CanvasRenderingContext2DConstructor CanvasRenderingContext2D; - attribute [Conditional=3D_CANVAS] CanvasRenderingContext3DConstructor CanvasRenderingContext3D; + attribute ImageDataConstructor ImageData; + attribute [Conditional=3D_CANVAS,EnabledAtRuntime] WebGLRenderingContextConstructor WebGLRenderingContext; attribute TextMetricsConstructor TextMetrics; - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasArrayBufferConstructor CanvasArrayBuffer; // Usable with new operator - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasByteArrayConstructor CanvasByteArray; // Usable with new operator - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasUnsignedByteArrayConstructor CanvasUnsignedByteArray; // Usable with new operator - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasShortArrayConstructor CanvasShortArray; // Usable with new operator - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasUnsignedShortArrayConstructor CanvasUnsignedShortArray; // Usable with new operator - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasIntArrayConstructor CanvasIntArray; // Usable with new operator - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasUnsignedIntArrayConstructor CanvasUnsignedIntArray; // Usable with new operator - attribute [JSCCustomGetter,Conditional=3D_CANVAS] CanvasFloatArrayConstructor CanvasFloatArray; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLArrayBufferConstructor WebGLArrayBuffer; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLByteArrayConstructor WebGLByteArray; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLUnsignedByteArrayConstructor WebGLUnsignedByteArray; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLShortArrayConstructor WebGLShortArray; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLUnsignedShortArrayConstructor WebGLUnsignedShortArray; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLIntArrayConstructor WebGLIntArray; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLUnsignedIntArrayConstructor WebGLUnsignedIntArray; // Usable with new operator + attribute [JSCCustomGetter,Conditional=3D_CANVAS,EnabledAtRuntime] WebGLFloatArrayConstructor WebGLFloatArray; // Usable with new operator attribute EventConstructor Event; attribute BeforeLoadEventConstructor BeforeLoadEvent; @@ -471,6 +485,7 @@ module window { attribute FileConstructor File; attribute FileListConstructor FileList; + attribute BlobConstructor Blob; attribute NodeFilterConstructor NodeFilter; attribute RangeConstructor Range; @@ -537,35 +552,172 @@ module window { #endif #if defined(ENABLE_SVG) && ENABLE_SVG + // Expose all implemented SVG 1.1 interfaces, excluding the SVG MI interfaces: + // SVGAnimatedPathData, SVGAnimatedPoints, SVGExternalResourcesRequired, + // SVGFilterPrimitiveStandardAttributes, SVGFitToViewBox, SVGLangSpace, SVGLocatable + // SVGStylable, SVGTests, SVGTransformable, SVGURIReference, SVGZoomAndPan + attribute SVGAElementConstructor SVGAElement; attribute SVGAngleConstructor SVGAngle; + attribute SVGAnimatedAngleConstructor SVGAnimatedAngle; + attribute SVGAnimatedBooleanConstructor SVGAnimatedBoolean; + attribute SVGAnimatedEnumerationConstructor SVGAnimatedEnumeration; + attribute SVGAnimatedIntegerConstructor SVGAnimatedInteger; + attribute SVGAnimatedLengthConstructor SVGAnimatedLength; + attribute SVGAnimatedLengthListConstructor SVGAnimatedLengthList; + attribute SVGAnimatedNumberConstructor SVGAnimatedNumber; + attribute SVGAnimatedNumberListConstructor SVGAnimatedNumberList; + attribute SVGAnimatedPreserveAspectRatioConstructor SVGAnimatedPreserveAspectRatio; + attribute SVGAnimatedRectConstructor SVGAnimatedRect; + attribute SVGAnimatedStringConstructor SVGAnimatedString; + attribute SVGAnimatedTransformListConstructor SVGAnimatedTransformList; + attribute SVGCircleElementConstructor SVGCircleElement; + attribute SVGClipPathElementConstructor SVGClipPathElement; attribute SVGColorConstructor SVGColor; + attribute SVGCursorElementConstructor SVGCursorElement; // attribute SVGCSSRuleConstructor SVGCSSRule; + attribute SVGDefsElementConstructor SVGDefsElement; + attribute SVGDescElementConstructor SVGDescElement; + attribute SVGDocumentConstructor SVGDocument; + attribute SVGElementConstructor SVGElement; + attribute SVGElementInstanceConstructor SVGElementInstance; + attribute SVGElementInstanceListConstructor SVGElementInstanceList; + attribute SVGEllipseElementConstructor SVGEllipseElement; attribute SVGExceptionConstructor SVGException; + attribute SVGGElementConstructor SVGGElement; attribute SVGGradientElementConstructor SVGGradientElement; + attribute SVGImageElementConstructor SVGImageElement; attribute SVGLengthConstructor SVGLength; + attribute SVGLengthListConstructor SVGLengthList; + attribute SVGLinearGradientElementConstructor SVGLinearGradientElement; + attribute SVGLineElementConstructor SVGLineElement; attribute SVGMarkerElementConstructor SVGMarkerElement; + attribute SVGMaskElementConstructor SVGMaskElement; + attribute SVGMatrixConstructor SVGMatrix; + attribute SVGMetadataElementConstructor SVGMetadataElement; + attribute SVGNumberConstructor SVGNumber; + attribute SVGNumberListConstructor SVGNumberList; attribute SVGPaintConstructor SVGPaint; + attribute SVGPathElementConstructor SVGPathElement; attribute SVGPathSegConstructor SVGPathSeg; + attribute SVGPathSegArcAbsConstructor SVGPathSegArcAbs; + attribute SVGPathSegArcRelConstructor SVGPathSegArcRel; + attribute SVGPathSegClosePathConstructor SVGPathSegClosePath; + attribute SVGPathSegCurvetoCubicAbsConstructor SVGPathSegCurvetoCubicAbs; + attribute SVGPathSegCurvetoCubicRelConstructor SVGPathSegCurvetoCubicRel; + attribute SVGPathSegCurvetoCubicSmoothAbsConstructor SVGPathSegCurvetoCubicSmoothAbs; + attribute SVGPathSegCurvetoCubicSmoothRelConstructor SVGPathSegCurvetoCubicSmoothRel; + attribute SVGPathSegCurvetoQuadraticAbsConstructor SVGPathSegCurvetoQuadraticAbs; + attribute SVGPathSegCurvetoQuadraticRelConstructor SVGPathSegCurvetoQuadraticRel; + attribute SVGPathSegCurvetoQuadraticSmoothAbsConstructor SVGPathSegCurvetoQuadraticSmoothAbs; + attribute SVGPathSegCurvetoQuadraticSmoothRelConstructor SVGPathSegCurvetoQuadraticSmoothRel; + attribute SVGPathSegLinetoAbsConstructor SVGPathSegLinetoAbs; + attribute SVGPathSegLinetoHorizontalAbsConstructor SVGPathSegLinetoHorizontalAbs; + attribute SVGPathSegLinetoHorizontalRelConstructor SVGPathSegLinetoHorizontalRel; + attribute SVGPathSegLinetoRelConstructor SVGPathSegLinetoRel; + attribute SVGPathSegLinetoVerticalAbsConstructor SVGPathSegLinetoVerticalAbs; + attribute SVGPathSegLinetoVerticalRelConstructor SVGPathSegLinetoVerticalRel; + attribute SVGPathSegListConstructor SVGPathSegList; + attribute SVGPathSegMovetoAbsConstructor SVGPathSegMovetoAbs; + attribute SVGPathSegMovetoRelConstructor SVGPathSegMovetoRel; + attribute SVGPatternElementConstructor SVGPatternElement; + attribute SVGPointConstructor SVGPoint; + attribute SVGPointListConstructor SVGPointList; + attribute SVGPolygonElementConstructor SVGPolygonElement; + attribute SVGPolylineElementConstructor SVGPolylineElement; attribute SVGPreserveAspectRatioConstructor SVGPreserveAspectRatio; + attribute SVGRadialGradientElementConstructor SVGRadialGradientElement; + attribute SVGRectConstructor SVGRect; + attribute SVGRectElementConstructor SVGRectElement; attribute SVGRenderingIntentConstructor SVGRenderingIntent; + attribute SVGScriptElementConstructor SVGScriptElement; + attribute SVGStopElementConstructor SVGStopElement; + attribute SVGStringListConstructor SVGStringList; + attribute SVGStyleElementConstructor SVGStyleElement; + attribute SVGSVGElementConstructor SVGSVGElement; + attribute SVGSwitchElementConstructor SVGSwitchElement; + attribute SVGSymbolElementConstructor SVGSymbolElement; attribute SVGTextContentElementConstructor SVGTextContentElement; + attribute SVGTextElementConstructor SVGTextElement; attribute SVGTextPathElementConstructor SVGTextPathElement; + attribute SVGTextPositioningElementConstructor SVGTextPositioningElement; + attribute SVGTitleElementConstructor SVGTitleElement; attribute SVGTransformConstructor SVGTransform; + attribute SVGTransformListConstructor SVGTransformList; + attribute SVGTRefElementConstructor SVGTRefElement; + attribute SVGTSpanElementConstructor SVGTSpanElement; attribute SVGUnitTypesConstructor SVGUnitTypes; -// attribute SVGZoomAndPanConstructor SVGZoomAndPan; + attribute SVGUseElementConstructor SVGUseElement; + attribute SVGViewElementConstructor SVGViewElement; +// attribute SVGViewSpecConstructor SVGViewSpec; + attribute SVGZoomEventConstructor SVGZoomEvent; + +#if defined(ENABLE_SVG_ANIMATION) && ENABLE_SVG_ANIMATION + attribute SVGAnimateColorElementConstructor SVGAnimateColorElement; + attribute SVGAnimateElementConstructor SVGAnimateElement; +// attribute SVGAnimateMotionElementConstructor SVGAnimateMotionElement; + attribute SVGAnimateTransformElementConstructor SVGAnimateTransformElement; +// attribute SVGMPathElementConstructor SVGMPathElement; + attribute SVGSetElementConstructor SVGSetElement; +#endif + +#if ENABLE_SVG_FONTS && ENABLE_SVG_FONTS +// attribute SVGAltGlyphDefElementConstructor SVGAltGlyphDefElement; + attribute SVGAltGlyphElementConstructor SVGAltGlyphElement; +// attribute SVGAltGlyphItemElementConstructor SVGAltGlyphItemElement; +// attribute SVGDefinitionSrcElementConstructor SVGDefinitionSrcElement; + attribute SVGFontElementConstructor SVGFontElement; + attribute SVGFontFaceElementConstructor SVGFontFaceElement; + attribute SVGFontFaceFormatElementConstructor SVGFontFaceFormatElement; + attribute SVGFontFaceNameElementConstructor SVGFontFaceNameElement; + attribute SVGFontFaceSrcElementConstructor SVGFontFaceSrcElement; + attribute SVGFontFaceUriElementConstructor SVGFontFaceUriElement; + attribute SVGGlyphElementConstructor SVGGlyphElement; +// attribute SVGGlyphRefElementConstructor SVGGlyphRefElement; +// attribute SVGHKernElementConstructor SVGHKernElement; + attribute SVGMissingGlyphElementConstructor SVGMissingGlyphElement; +// attribute SVGVKernElementConstructor SVGVKernElement; +#endif + +#if defined(ENABLE_SVG_FOREIGN_OBJECT) && ENABLE_SVG_FOREIGN_OBJECT + attribute SVGForeignObjectElementConstructor SVGForeignObjectElement; +#endif #if defined(ENABLE_FILTERS) && ENABLE_FILTERS attribute SVGComponentTransferFunctionElementConstructor SVGComponentTransferFunctionElement; attribute SVGFEBlendElementConstructor SVGFEBlendElement; attribute SVGFEColorMatrixElementConstructor SVGFEColorMatrixElement; + attribute SVGFEComponentTransferElementConstructor SVGFEComponentTransferElement; attribute SVGFECompositeElementConstructor SVGFECompositeElement; // attribute SVGFEConvolveMatrixElementConstructor SVGFEConvolveMatrixElement; + attribute SVGFEDiffuseLightingElementConstructor SVGFEDiffuseLightingElement; attribute SVGFEDisplacementMapElementConstructor SVGFEDisplacementMapElement; + attribute SVGFEDistantLightElementConstructor SVGFEDistantLightElement; + attribute SVGFEFloodElementConstructor SVGFEFloodElement; + attribute SVGFEFuncAElementConstructor SVGFEFuncAElement; + attribute SVGFEFuncBElementConstructor SVGFEFuncBElement; + attribute SVGFEFuncGElementConstructor SVGFEFuncGElement; + attribute SVGFEFuncRElementConstructor SVGFEFuncRElement; + attribute SVGFEGaussianBlurElementConstructor SVGFEGaussianBlurElement; + attribute SVGFEImageElementConstructor SVGFEImageElement; + attribute SVGFEMergeElementConstructor SVGFEMergeElement; + attribute SVGFEMergeNodeElementConstructor SVGFEMergeNodeElement; attribute SVGFEMorphologyElementConstructor SVGFEMorphologyElement; + attribute SVGFEOffsetElementConstructor SVGFEOffsetElement; + attribute SVGFEPointLightElementConstructor SVGFEPointLightElement; + attribute SVGFESpecularLightingElementConstructor SVGFESpecularLightingElement; + attribute SVGFESpotLightElementConstructor SVGFESpotLightElement; + attribute SVGFETileElementConstructor SVGFETileElement; attribute SVGFETurbulenceElementConstructor SVGFETurbulenceElement; + attribute SVGFilterElementConstructor SVGFilterElement; +#endif #endif + +#if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS + attribute TouchEventConstructor TouchEvent; #endif + attribute DOMFormDataConstructor FormData; + #endif // defined(LANGUAGE_JAVASCRIPT) #if defined(V8_BINDING) && V8_BINDING @@ -575,3 +727,4 @@ module window { }; } + diff --git a/src/3rdparty/webkit/WebCore/page/DragController.cpp b/src/3rdparty/webkit/WebCore/page/DragController.cpp index 634595a..f238b27 100644 --- a/src/3rdparty/webkit/WebCore/page/DragController.cpp +++ b/src/3rdparty/webkit/WebCore/page/DragController.cpp @@ -53,6 +53,7 @@ #include "MoveSelectionCommand.h" #include "Node.h" #include "Page.h" +#include "PlatformKeyboardEvent.h" #include "RenderFileUploadControl.h" #include "RenderImage.h" #include "RenderView.h" @@ -70,10 +71,12 @@ namespace WebCore { static PlatformMouseEvent createMouseEvent(DragData* dragData) { - // FIXME: We should fake modifier keys here. + bool shiftKey, ctrlKey, altKey, metaKey; + shiftKey = ctrlKey = altKey = metaKey = false; + PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey); return PlatformMouseEvent(dragData->clientPosition(), dragData->globalPosition(), - LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); - + LeftButton, MouseEventMoved, 0, shiftKey, ctrlKey, altKey, + metaKey, currentTime()); } DragController::DragController(Page* page, DragClient* client) @@ -429,10 +432,11 @@ bool DragController::concludeEditDrag(DragData* dragData) m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); if (dragIsMove(innerFrame->selection())) { - bool smartMove = innerFrame->selectionGranularity() == WordGranularity - && innerFrame->editor()->smartInsertDeleteEnabled() - && dragData->canSmartReplace(); - applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartMove)); + // NSTextView behavior is to always smart delete on moving a selection, + // but only to smart insert if the selection granularity is word granularity. + bool smartDelete = innerFrame->editor()->smartInsertDeleteEnabled(); + bool smartInsert = smartDelete && innerFrame->selectionGranularity() == WordGranularity && dragData->canSmartReplace(); + applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartInsert, smartDelete)); } else { if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, fragment, true, dragData->canSmartReplace(), chosePlainText)); @@ -486,13 +490,17 @@ static DragOperation defaultOperationForDrag(DragOperation srcOpMask) { // This is designed to match IE's operation fallback for the case where // the page calls preventDefault() in a drag event but doesn't set dropEffect. - if (srcOpMask & DragOperationCopy) - return DragOperationCopy; + if (srcOpMask == DragOperationEvery) + return DragOperationCopy; + if (srcOpMask == DragOperationNone) + return DragOperationNone; if (srcOpMask & DragOperationMove || srcOpMask & DragOperationGeneric) return DragOperationMove; + if (srcOpMask & DragOperationCopy) + return DragOperationCopy; if (srcOpMask & DragOperationLink) return DragOperationLink; - + // FIXME: Does IE really return "generic" even if no operations were allowed by the source? return DragOperationGeneric; } @@ -517,10 +525,10 @@ bool DragController::tryDHTMLDrag(DragData* dragData, DragOperation& operation) return false; } - if (!clipboard->destinationOperation(operation)) { - // The element accepted but they didn't pick an operation, so we pick one (to match IE). + operation = clipboard->destinationOperation(); + if (clipboard->dropEffectIsUninitialized()) operation = defaultOperationForDrag(srcOpMask); - } else if (!(srcOpMask & operation)) { + else if (!(srcOpMask & operation)) { // The element picked an operation which is not supported by the source operation = DragOperationNone; } @@ -529,7 +537,7 @@ bool DragController::tryDHTMLDrag(DragData* dragData, DragOperation& operation) return true; } -bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPoint& framePos) +bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPoint& framePos, Node* node) { ASSERT(frame); ASSERT(frame->settings()); @@ -540,6 +548,8 @@ bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPo HitTestResult mouseDownTarget = HitTestResult(framePos); mouseDownTarget = frame->eventHandler()->hitTestResultAtPoint(framePos, true); + if (node) + mouseDownTarget.setInnerNonSharedNode(node); if (mouseDownTarget.image() && !mouseDownTarget.absoluteImageURL().isEmpty() @@ -549,7 +559,8 @@ bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPo if (!mouseDownTarget.absoluteLinkURL().isEmpty() && m_dragSourceAction & DragSourceActionLink - && mouseDownTarget.isLiveLink()) + && mouseDownTarget.isLiveLink() + && mouseDownTarget.URLElement()->renderer() && mouseDownTarget.URLElement()->renderer()->style()->userDrag() != DRAG_NONE) return true; if (mouseDownTarget.isSelected() @@ -557,7 +568,6 @@ bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPo return true; return false; - } static CachedImage* getCachedImage(Element* element) @@ -573,14 +583,9 @@ static CachedImage* getCachedImage(Element* element) static Image* getImage(Element* element) { ASSERT(element); - RenderObject* renderer = element->renderer(); - if (!renderer || !renderer->isImage()) - return 0; - - RenderImage* image = toRenderImage(renderer); - if (image->cachedImage() && !image->cachedImage()->errorOccurred()) - return image->cachedImage()->image(); - return 0; + CachedImage* cachedImage = getCachedImage(element); + return (cachedImage && !cachedImage->errorOccurred()) ? + cachedImage->image() : 0; } static void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label) @@ -714,10 +719,16 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s } doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true); } else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) { - RefPtr<Range> selectionRange = src->selection()->toNormalizedRange(); - ASSERT(selectionRange); - if (!clipboard->hasData()) - clipboard->writeRange(selectionRange.get(), src); + if (!clipboard->hasData()) { + if (isNodeInTextFormControl(src->selection()->start().node())) + clipboard->writePlainText(src->selectedText()); + else { + RefPtr<Range> selectionRange = src->selection()->toNormalizedRange(); + ASSERT(selectionRange); + + clipboard->writeRange(selectionRange.get(), src); + } + } m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard); if (!dragImage) { dragImage = createDragImageForSelection(src); diff --git a/src/3rdparty/webkit/WebCore/page/DragController.h b/src/3rdparty/webkit/WebCore/page/DragController.h index 9472589..3b2b083 100644 --- a/src/3rdparty/webkit/WebCore/page/DragController.h +++ b/src/3rdparty/webkit/WebCore/page/DragController.h @@ -47,7 +47,7 @@ namespace WebCore { class Range; class SelectionController; - class DragController { + class DragController : public Noncopyable { public: DragController(Page*, DragClient*); ~DragController(); @@ -77,7 +77,7 @@ namespace WebCore { DragDestinationAction dragDestinationAction() const { return m_dragDestinationAction; } DragSourceAction delegateDragSourceAction(const IntPoint& pagePoint); - bool mayStartDragAtEventLocation(const Frame*, const IntPoint& framePos); + bool mayStartDragAtEventLocation(const Frame*, const IntPoint& framePos, Node*); void dragEnded(); void placeDragCaret(const IntPoint&); diff --git a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp index 4e97aba..0a0e8c6 100644 --- a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp +++ b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * * Redistribution and use in source and binary forms, with or without @@ -29,6 +29,7 @@ #include "AXObjectCache.h" #include "CachedImage.h" +#include "Chrome.h" #include "ChromeClient.h" #include "Cursor.h" #include "Document.h" @@ -56,6 +57,7 @@ #include "Page.h" #include "PlatformKeyboardEvent.h" #include "PlatformWheelEvent.h" +#include "PluginDocument.h" #include "RenderFrameSet.h" #include "RenderTextControlSingleLine.h" #include "RenderView.h" @@ -64,7 +66,9 @@ #include "SelectionController.h" #include "Settings.h" #include "TextEvent.h" +#include "WheelEvent.h" #include "htmlediting.h" // for comparePositions() +#include <wtf/CurrentTime.h> #include <wtf/StdLibExtras.h> #if ENABLE(SVG) @@ -74,6 +78,11 @@ #include "SVGUseElement.h" #endif +#if ENABLE(TOUCH_EVENTS) +#include "PlatformTouchEvent.h" +#include "TouchEvent.h" +#endif + namespace WebCore { using namespace HTMLNames; @@ -99,28 +108,36 @@ using namespace SVGNames; // When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth const double autoscrollInterval = 0.05; +const double fakeMouseMoveInterval = 0.1; + static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&); -static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node, Node** stopNode) +static inline bool scrollNode(float delta, WheelEvent::Granularity granularity, ScrollDirection positiveDirection, ScrollDirection negativeDirection, Node* node, Node** stopNode) { if (!delta) - return; - + return false; + + if (!node->renderer()) + return false; + // Find the nearest enclosing box. RenderBox* enclosingBox = node->renderer()->enclosingBox(); - if (e.granularity() == ScrollByPageWheelEvent) { - if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1, stopNode)) - e.accept(); - return; - } + float absDelta = delta > 0 ? delta : -delta; + + if (granularity == WheelEvent::Page) + return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, absDelta, stopNode); + + if (granularity == WheelEvent::Line) + return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByLine, absDelta, stopNode); - float pixelsToScroll = delta > 0 ? delta : -delta; - if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll, stopNode)) - e.accept(); + if (granularity == WheelEvent::Pixel) + return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, absDelta, stopNode); + + return false; } -#if !PLATFORM(MAC) +#if !PLATFORM(MAC) || ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) inline bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) { @@ -155,6 +172,7 @@ EventHandler::EventHandler(Frame* frame) , m_autoscrollInProgress(false) , m_mouseDownMayStartAutoscroll(false) , m_mouseDownWasInSubframe(false) + , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired) #if ENABLE(SVG) , m_svgPan(false) #endif @@ -164,7 +182,7 @@ EventHandler::EventHandler(Frame* frame) , m_mouseDownTimestamp(0) , m_useLatchedWheelEventNode(false) , m_widgetIsLatched(false) -#if PLATFORM(MAC) +#if PLATFORM(MAC) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) , m_mouseDownView(nil) , m_sendingEventToSubview(false) , m_activationEventNumber(0) @@ -174,6 +192,7 @@ EventHandler::EventHandler(Frame* frame) EventHandler::~EventHandler() { + ASSERT(!m_fakeMouseMoveEventTimer.isActive()); } #if ENABLE(DRAG_SUPPORT) @@ -187,6 +206,7 @@ EventHandler::EventHandlerDragState& EventHandler::dragState() void EventHandler::clear() { m_hoverTimer.stop(); + m_fakeMouseMoveEventTimer.stop(); m_resizeLayer = 0; m_nodeUnderMouse = 0; m_lastNodeUnderMouse = 0; @@ -201,6 +221,7 @@ void EventHandler::clear() m_frameSetBeingResized = 0; #if ENABLE(DRAG_SUPPORT) m_dragTarget = 0; + m_shouldOnlyFireDragOverEvent = false; #endif m_currentMousePosition = IntPoint(); m_mousePressNode = 0; @@ -218,20 +239,21 @@ void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) { VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint())); + TextGranularity granularity = CharacterGranularity; if (pos.isNotNull()) { newSelection = VisibleSelection(pos); newSelection.expandUsingGranularity(WordGranularity); } if (newSelection.isRange()) { - m_frame->setSelectionGranularity(WordGranularity); + granularity = WordGranularity; m_beganSelectingText = true; if (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled()) newSelection.appendTrailingWhitespace(); } if (m_frame->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection); + m_frame->selection()->setSelection(newSelection, granularity); } } @@ -249,13 +271,14 @@ void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit if (pos.isNotNull() && pos.deepEquivalent().node()->isDescendantOf(URLElement)) newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement); + TextGranularity granularity = CharacterGranularity; if (newSelection.isRange()) { - m_frame->setSelectionGranularity(WordGranularity); + granularity = WordGranularity; m_beganSelectingText = true; } if (m_frame->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection); + m_frame->selection()->setSelection(newSelection, granularity); } } @@ -292,13 +315,15 @@ bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR newSelection = VisibleSelection(pos); newSelection.expandUsingGranularity(ParagraphGranularity); } + + TextGranularity granularity = CharacterGranularity; if (newSelection.isRange()) { - m_frame->setSelectionGranularity(ParagraphGranularity); + granularity = ParagraphGranularity; m_beganSelectingText = true; } if (m_frame->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection); + m_frame->selection()->setSelection(newSelection, granularity); return true; } @@ -328,6 +353,8 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR Position pos = visiblePos.deepEquivalent(); VisibleSelection newSelection = m_frame->selection()->selection(); + TextGranularity granularity = CharacterGranularity; + if (extendSelection && newSelection.isCaretOrRange()) { m_frame->selection()->setLastChangeWasHorizontalExtension(false); @@ -340,16 +367,17 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR else newSelection = VisibleSelection(start, pos); - if (m_frame->selectionGranularity() != CharacterGranularity) + if (m_frame->selectionGranularity() != CharacterGranularity) { + granularity = m_frame->selectionGranularity(); newSelection.expandUsingGranularity(m_frame->selectionGranularity()); + } + m_beganSelectingText = true; - } else { + } else newSelection = VisibleSelection(visiblePos); - m_frame->setSelectionGranularity(CharacterGranularity); - } if (m_frame->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection); + m_frame->selection()->setSelection(newSelection, granularity); return true; } @@ -361,6 +389,8 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve dragState().m_dragSrc = 0; #endif + cancelFakeMouseMoveEvent(); + if (ScrollView* scrollView = m_frame->view()) { if (scrollView->isPointInScrollbarCorner(event.event().pos())) return false; @@ -562,7 +592,7 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& if (m_frame->shouldChangeSelection(newSelection)) { m_frame->selection()->setLastChangeWasHorizontalExtension(false); - m_frame->selection()->setSelection(newSelection); + m_frame->selection()->setSelection(newSelection, m_frame->selectionGranularity()); } } #endif // ENABLE(DRAG_SUPPORT) @@ -688,6 +718,14 @@ void EventHandler::autoscrollTimerFired(Timer<EventHandler>*) #if ENABLE(PAN_SCROLLING) +void EventHandler::startPanScrolling(RenderObject* renderer) +{ + m_panScrollInProgress = true; + m_panScrollButtonPressed = true; + handleAutoscroll(renderer); + invalidateClick(); +} + void EventHandler::updatePanScrollState() { FrameView* view = m_frame->view(); @@ -1128,6 +1166,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) { RefPtr<FrameView> protector(m_frame->view()); + cancelFakeMouseMoveEvent(); m_mousePressed = true; m_capturesDragging = true; m_currentMousePosition = mouseEvent.pos(); @@ -1187,25 +1226,6 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) invalidateClick(); return true; } - - if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) { - RenderObject* renderer = mev.targetNode()->renderer(); - - while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) { - if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement()) - renderer = renderer->document()->ownerElement()->renderer(); - else - renderer = renderer->parent(); - } - - if (renderer) { - m_panScrollInProgress = true; - m_panScrollButtonPressed = true; - handleAutoscroll(renderer); - invalidateClick(); - return true; - } - } #endif m_clickCount = mouseEvent.clickCount(); @@ -1338,6 +1358,8 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi if (m_hoverTimer.isActive()) m_hoverTimer.stop(); + cancelFakeMouseMoveEvent(); + #if ENABLE(SVG) if (m_svgPan) { static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition); @@ -1400,8 +1422,18 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering. if (Page* page = m_frame->page()) { if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->panScrollInProgress()) { - if (FrameView* view = m_frame->view()) - view->setCursor(selectCursor(mev, scrollbar)); + // Plugins set cursor on their own. The only case WebKit intervenes is resetting cursor to arrow on mouse enter, + // in case the particular plugin doesn't manipulate cursor at all. Thus, even a CSS cursor set on body has no + // effect on plugins (which matches Firefox). + bool overPluginElement = false; + if (mev.targetNode() && mev.targetNode()->isHTMLElement()) { + HTMLElement* el = static_cast<HTMLElement*>(mev.targetNode()); + overPluginElement = el->hasTagName(appletTag) || el->hasTagName(objectTag) || el->hasTagName(embedTag); + } + if (!overPluginElement) { + if (FrameView* view = m_frame->view()) + view->setCursor(selectCursor(mev, scrollbar)); + } } } } @@ -1508,6 +1540,35 @@ bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa return me->defaultPrevented(); } +bool EventHandler::canHandleDragAndDropForTarget(DragAndDropHandleType type, Node* target, const PlatformMouseEvent& event, Clipboard* clipboard, bool* accepted) +{ + bool canHandle = false; + bool wasAccepted = false; + + if (target->hasTagName(frameTag) || target->hasTagName(iframeTag)) { + Frame* frame = static_cast<HTMLFrameElementBase*>(target)->contentFrame(); + if (frame) { + switch (type) { + case UpdateDragAndDrop: + wasAccepted = frame->eventHandler()->updateDragAndDrop(event, clipboard); + break; + case CancelDragAndDrop: + frame->eventHandler()->cancelDragAndDrop(event, clipboard); + break; + case PerformDragAndDrop: + wasAccepted = frame->eventHandler()->performDragAndDrop(event, clipboard); + break; + } + } + } else + canHandle = true; + + if (accepted) + *accepted = wasAccepted; + + return canHandle; +} + bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) { bool accept = false; @@ -1529,28 +1590,34 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* // FIXME: this ordering was explicitly chosen to match WinIE. However, // it is sometimes incorrect when dragging within subframes, as seen with // LayoutTests/fast/events/drag-in-frames.html. - if (newTarget) { - Frame* frame = (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame() : 0; - if (frame) - accept = frame->eventHandler()->updateDragAndDrop(event, clipboard); - else - accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard); + // + // Moreover, this ordering conforms to section 7.9.4 of the HTML 5 spec. <http://dev.w3.org/html5/spec/Overview.html#drag-and-drop-processing-model>. + if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) { + // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event. + if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) { + // for now we don't care if event handler cancels default behavior, since there is none + dispatchDragSrcEvent(eventNames().dragEvent, event); + } + accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard); } - if (m_dragTarget) { - Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0; - if (frame) - accept = frame->eventHandler()->updateDragAndDrop(event, clipboard); - else - dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); + if (m_dragTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, m_dragTarget.get(), event, clipboard, &accept)) + dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); + + if (newTarget) { + // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that + // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function. + m_shouldOnlyFireDragOverEvent = true; } } else { - if (newTarget) { - Frame* frame = (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame() : 0; - if (frame) - accept = frame->eventHandler()->updateDragAndDrop(event, clipboard); - else - accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard); + if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) { + // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier. + if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) { + // for now we don't care if event handler cancels default behavior, since there is none + dispatchDragSrcEvent(eventNames().dragEvent, event); + } + accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard); + m_shouldOnlyFireDragOverEvent = false; } } m_dragTarget = newTarget; @@ -1560,13 +1627,10 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) { - if (m_dragTarget) { - Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) - ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0; - if (frame) - frame->eventHandler()->cancelDragAndDrop(event, clipboard); - else - dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); + if (m_dragTarget && canHandleDragAndDropForTarget(CancelDragAndDrop, m_dragTarget.get(), event, clipboard)) { + if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) + dispatchDragSrcEvent(eventNames().dragEvent, event); + dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); } clearDragState(); } @@ -1574,14 +1638,8 @@ void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) { bool accept = false; - if (m_dragTarget) { - Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) - ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0; - if (frame) - accept = frame->eventHandler()->performDragAndDrop(event, clipboard); - else - accept = dispatchDragEvent(eventNames().dropEvent, m_dragTarget.get(), event, clipboard); - } + if (m_dragTarget && canHandleDragAndDropForTarget(PerformDragAndDrop, m_dragTarget.get(), event, clipboard, &accept)) + dispatchDragEvent(eventNames().dropEvent, m_dragTarget.get(), event, clipboard); clearDragState(); return accept; } @@ -1590,7 +1648,8 @@ void EventHandler::clearDragState() { m_dragTarget = 0; m_capturingMouseEventsNode = 0; -#if PLATFORM(MAC) + m_shouldOnlyFireDragOverEvent = false; +#if PLATFORM(MAC) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) m_sendingEventToSubview = false; #endif } @@ -1763,7 +1822,7 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe return swallowEvent; } -#if !PLATFORM(GTK) +#if !PLATFORM(GTK) && !(PLATFORM(CHROMIUM) && OS(LINUX)) bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&) const { return false; @@ -1832,21 +1891,6 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) node->dispatchWheelEvent(e); if (e.isAccepted()) return true; - - // If we don't have a renderer, send the wheel event to the first node we find with a renderer. - // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll. - while (node && !node->renderer()) - node = node->parent(); - - if (node && node->renderer()) { - // Just break up into two scrolls if we need to. Diagonal movement on - // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set). - Node* stopNode = m_previousWheelScrolledNode.get(); - scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node, &stopNode); - scrollAndAcceptEvent(e.deltaY(), ScrollUp, ScrollDown, e, node, &stopNode); - if (!m_useLatchedWheelEventNode) - m_previousWheelScrolledNode = stopNode; - } } if (e.isAccepted()) @@ -1859,6 +1903,25 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) view->wheelEvent(e); return e.isAccepted(); } + +void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent) +{ + if (!startNode || !wheelEvent) + return; + + Node* stopNode = m_previousWheelScrolledNode.get(); + + // Break up into two scrolls if we need to. Diagonal movement on + // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set). + if (scrollNode(wheelEvent->rawDeltaX(), wheelEvent->granularity(), ScrollLeft, ScrollRight, startNode, &stopNode)) + wheelEvent->setDefaultHandled(); + + if (scrollNode(wheelEvent->rawDeltaY(), wheelEvent->granularity(), ScrollUp, ScrollDown, startNode, &stopNode)) + wheelEvent->setDefaultHandled(); + + if (!m_useLatchedWheelEventNode) + m_previousWheelScrolledNode = stopNode; +} #if ENABLE(CONTEXT_MENUS) bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event) @@ -1899,6 +1962,43 @@ void EventHandler::scheduleHoverStateUpdate() m_hoverTimer.startOneShot(0); } +void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad) +{ + FrameView* view = m_frame->view(); + if (!view) + return; + + if (m_mousePressed || !quad.containsPoint(view->windowToContents(m_currentMousePosition))) + return; + + if (!m_fakeMouseMoveEventTimer.isActive()) + m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveInterval); +} + +void EventHandler::cancelFakeMouseMoveEvent() +{ + m_fakeMouseMoveEventTimer.stop(); +} + +void EventHandler::fakeMouseMoveEventTimerFired(Timer<EventHandler>* timer) +{ + ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer); + ASSERT(!m_mousePressed); + + FrameView* view = m_frame->view(); + if (!view) + return; + + bool shiftKey; + bool ctrlKey; + bool altKey; + bool metaKey; + PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey); + IntPoint globalPoint = view->contentsToScreen(IntRect(view->windowToContents(m_currentMousePosition), IntSize())).location(); + PlatformMouseEvent fakeMouseMoveEvent(m_currentMousePosition, globalPoint, NoButton, MouseEventMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime()); + mouseMoved(fakeMouseMoveEvent); +} + // Whether or not a mouse down can begin the creation of a selection. Fires the selectStart event. bool EventHandler::canMouseDownStartSelect(Node* node) { @@ -1965,6 +2065,10 @@ static Node* eventTargetNodeForDocument(Document* doc) if (!doc) return 0; Node* node = doc->focusedNode(); + if (!node && doc->isPluginDocument()) { + PluginDocument* pluginDocument = static_cast<PluginDocument*>(doc); + node = pluginDocument->pluginNode(); + } if (!node && doc->isHTMLDocument()) node = doc->body(); if (!node) @@ -2133,10 +2237,15 @@ void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event) return; if (event->keyIdentifier() == "U+0009") defaultTabEventHandler(event); + else { + FocusDirection direction = focusDirectionForKey(event->keyIdentifier()); + if (direction != FocusDirectionNone) + defaultArrowEventHandler(direction, event); + } - // provides KB navigation and selection for enhanced accessibility users - if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled()) - handleKeyboardSelectionMovement(event); + // provides KB navigation and selection for enhanced accessibility users + if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled()) + handleKeyboardSelectionMovement(event); } if (event->type() == eventNames().keypressEvent) { m_frame->editor()->handleKeyboardEvent(event); @@ -2147,6 +2256,27 @@ void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event) } } +FocusDirection EventHandler::focusDirectionForKey(const AtomicString& keyIdentifier) const +{ + DEFINE_STATIC_LOCAL(AtomicString, Down, ("Down")); + DEFINE_STATIC_LOCAL(AtomicString, Up, ("Up")); + DEFINE_STATIC_LOCAL(AtomicString, Left, ("Left")); + DEFINE_STATIC_LOCAL(AtomicString, Right, ("Right")); + + FocusDirection retVal = FocusDirectionNone; + + if (keyIdentifier == Down) + retVal = FocusDirectionDown; + else if (keyIdentifier == Up) + retVal = FocusDirectionUp; + else if (keyIdentifier == Left) + retVal = FocusDirectionLeft; + else if (keyIdentifier == Right) + retVal = FocusDirectionRight; + + return retVal; +} + #if ENABLE(DRAG_SUPPORT) bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const { @@ -2184,16 +2314,9 @@ bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const if (!node || !m_frame->view()) return false; Page* page = m_frame->page(); - return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point); -} - -void EventHandler::dragSourceMovedTo(const PlatformMouseEvent& event) -{ - if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) - // for now we don't care if event handler cancels default behavior, since there is none - dispatchDragSrcEvent(eventNames().dragEvent, event); + return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point, node); } - + void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation) { if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) { @@ -2276,9 +2399,11 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll; // We are starting a text/image/url drag, so the cursor should be an arrow - if (FrameView* view = m_frame->view()) + if (FrameView* view = m_frame->view()) { + // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer). view->setCursor(pointerCursor()); - + } + if (!dragHysteresisExceeded(event.event().pos())) return true; @@ -2299,7 +2424,7 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) // FIXME: This doesn't work correctly with transforms. FloatPoint absPos = renderer->localToAbsolute(); IntSize delta = m_mouseDownPos - roundedIntPoint(absPos); - dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint() + delta); + dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), toPoint(delta)); } else { // The renderer has disappeared, this can happen if the onStartDrag handler has hidden // the element in some way. In this case we just kill the drag. @@ -2317,11 +2442,12 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) if (m_mouseDownMayStartDrag) { // gather values from DHTML element, if it set any - dragState().m_dragClipboard->sourceOperation(srcOp); + srcOp = dragState().m_dragClipboard->sourceOperation(); - // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with - // dragImage! Because of that dumb reentrancy, we may think we've not started the - // drag when that happens. So we have to assume it's started before we kick it off. + // Yuck, a draggedImage:moveTo: message can be fired as a result of kicking off the + // drag with dragImage! Because of that dumb reentrancy, we may think we've not + // started the drag when that happens. So we have to assume it's started before we + // kick it off. dragState().m_dragClipboard->setDragHasStarted(); } } @@ -2378,8 +2504,7 @@ bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve return event->defaultHandled(); } - -#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(HAIKU) +#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(HAIKU) && !PLATFORM(EFL) bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const { return false; @@ -2445,6 +2570,27 @@ void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event) #endif +void EventHandler::defaultArrowEventHandler(FocusDirection focusDirection, KeyboardEvent* event) +{ + if (event->ctrlKey() || event->metaKey() || event->altGraphKey() || event->shiftKey()) + return; + + Page* page = m_frame->page(); + if (!page) + return; + + if (!page->settings() || !page->settings()->isSpatialNavigationEnabled()) + return; + + // Arrows and other possible directional navigation keys can be used in design + // mode editing. + if (m_frame->document()->inDesignMode()) + return; + + if (page->focusController()->advanceFocus(focusDirection, event)) + event->setDefaultHandled(); +} + void EventHandler::defaultTabEventHandler(KeyboardEvent* event) { // We should only advance focus on tabs if no special modifier keys are held down. @@ -2517,4 +2663,174 @@ void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setL } } +#if ENABLE(TOUCH_EVENTS) + +static PassRefPtr<TouchList> assembleTargetTouches(Touch* touchTarget, TouchList* touches) +{ + RefPtr<TouchList> targetTouches = TouchList::create(); + + for (unsigned i = 0; i < touches->length(); ++i) { + if (touches->item(i)->target()->toNode()->isSameNode(touchTarget->target()->toNode())) + targetTouches->append(touches->item(i)); + } + + return targetTouches.release(); +} + +bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) +{ + RefPtr<TouchList> touches = TouchList::create(); + RefPtr<TouchList> pressedTouches = TouchList::create(); + RefPtr<TouchList> releasedTouches = TouchList::create(); + RefPtr<TouchList> movedTouches = TouchList::create(); + RefPtr<TouchList> cancelTouches = TouchList::create(); + + const Vector<PlatformTouchPoint>& points = event.touchPoints(); + AtomicString* eventName = 0; + + for (unsigned i = 0; i < points.size(); ++i) { + const PlatformTouchPoint& point = points[i]; + IntPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos()); + HitTestResult result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false); + Node* target = result.innerNode(); + + // Touch events should not go to text nodes + if (target && target->isTextNode()) + target = target->parentNode(); + + Document* doc = target->document(); + if (!doc) + continue; + if (!doc->hasListenerType(Document::TOUCH_LISTENER)) + continue; + + if (m_frame != doc->frame()) { + // pagePoint should always be relative to the target elements containing frame. + pagePoint = documentPointForWindowPoint(doc->frame(), point.pos()); + } + + int adjustedPageX = lroundf(pagePoint.x() / m_frame->pageZoomFactor()); + int adjustedPageY = lroundf(pagePoint.y() / m_frame->pageZoomFactor()); + + // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap. + unsigned touchPointTargetKey = point.id() + 1; + EventTarget* touchTarget = 0; + if (point.state() == PlatformTouchPoint::TouchPressed) { + m_originatingTouchPointTargets.set(touchPointTargetKey, target); + touchTarget = target; + } else if (point.state() == PlatformTouchPoint::TouchReleased || point.state() == PlatformTouchPoint::TouchCancelled) { + // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel + // we also remove it from the map. + touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey).get(); + } else + touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey).get(); + + if (!touchTarget) + continue; + + RefPtr<Touch> touch = Touch::create(doc->frame(), touchTarget, point.id(), + point.screenPos().x(), point.screenPos().y(), + adjustedPageX, adjustedPageY); + + // touches should contain information about every touch currently on the screen. + if (point.state() != PlatformTouchPoint::TouchReleased) + touches->append(touch); + + // Now build up the correct list for changedTouches. + if (point.state() == PlatformTouchPoint::TouchReleased) + releasedTouches->append(touch); + else if (point.state() == PlatformTouchPoint::TouchCancelled) + cancelTouches->append(touch); + else if (point.state() == PlatformTouchPoint::TouchPressed) + pressedTouches->append(touch); + else if (point.state() == PlatformTouchPoint::TouchMoved) + movedTouches->append(touch); + } + + bool defaultPrevented = false; + Touch* changedTouch = 0; + EventTarget* touchEventTarget = 0; + + if (cancelTouches->length() > 0) { + // We dispatch the event to the target of the touch that caused this touch event to be generated, i.e. + // we take it from the list that will be used as the changedTouches property of the event. + // The choice to use the touch at index 0 guarantees that there is a target (as we checked the length + // above). In the case that there are multiple touches in what becomes the changedTouches list, it is + // difficult to say how we should prioritise touches and as such, item 0 is an arbitrary choice. + changedTouch = cancelTouches->item(0); + ASSERT(changedTouch); + touchEventTarget = changedTouch->target(); + ASSERT(touchEventTarget); + + eventName = &eventNames().touchcancelEvent; + RefPtr<TouchEvent> cancelEv = + TouchEvent::create(TouchList::create().get(), TouchList::create().get(), cancelTouches.get(), + *eventName, touchEventTarget->toNode()->document()->defaultView(), + 0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), + event.metaKey()); + ExceptionCode ec = 0; + touchEventTarget->dispatchEvent(cancelEv.get(), ec); + defaultPrevented |= cancelEv->defaultPrevented(); + } + + if (releasedTouches->length() > 0) { + Touch* changedTouch = releasedTouches->item(0); + ASSERT(changedTouch); + touchEventTarget = changedTouch->target(); + ASSERT(touchEventTarget); + + RefPtr<TouchList> targetTouches = assembleTargetTouches(changedTouch, touches.get()); + + eventName = &eventNames().touchendEvent; + RefPtr<TouchEvent> endEv = + TouchEvent::create(touches.get(), targetTouches.get(), releasedTouches.get(), + *eventName, touchEventTarget->toNode()->document()->defaultView(), + 0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), + event.metaKey()); + ExceptionCode ec = 0; + touchEventTarget->dispatchEvent(endEv.get(), ec); + defaultPrevented |= endEv->defaultPrevented(); + } + if (pressedTouches->length() > 0) { + Touch* changedTouch = pressedTouches->item(0); + ASSERT(changedTouch); + touchEventTarget = changedTouch->target(); + ASSERT(touchEventTarget); + + RefPtr<TouchList> targetTouches = assembleTargetTouches(changedTouch, touches.get()); + + eventName = &eventNames().touchstartEvent; + RefPtr<TouchEvent> startEv = + TouchEvent::create(touches.get(), targetTouches.get(), pressedTouches.get(), + *eventName, touchEventTarget->toNode()->document()->defaultView(), + 0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), + event.metaKey()); + ExceptionCode ec = 0; + touchEventTarget->dispatchEvent(startEv.get(), ec); + defaultPrevented |= startEv->defaultPrevented(); + } + + if (movedTouches->length() > 0) { + Touch* changedTouch = movedTouches->item(0); + ASSERT(changedTouch); + touchEventTarget = changedTouch->target(); + ASSERT(touchEventTarget); + + RefPtr<TouchList> targetTouches = assembleTargetTouches(changedTouch, touches.get()); + + eventName = &eventNames().touchmoveEvent; + RefPtr<TouchEvent> moveEv = + TouchEvent::create(touches.get(), targetTouches.get(), movedTouches.get(), + *eventName, touchEventTarget->toNode()->document()->defaultView(), + 0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), + event.metaKey()); + ExceptionCode ec = 0; + touchEventTarget->dispatchEvent(moveEv.get(), ec); + defaultPrevented |= moveEv->defaultPrevented(); + } + + return defaultPrevented; +} +#endif + } diff --git a/src/3rdparty/webkit/WebCore/page/EventHandler.h b/src/3rdparty/webkit/WebCore/page/EventHandler.h index 0221397..282100d 100644 --- a/src/3rdparty/webkit/WebCore/page/EventHandler.h +++ b/src/3rdparty/webkit/WebCore/page/EventHandler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2009, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,7 @@ #define EventHandler_h #include "DragActions.h" +#include "FocusDirection.h" #include "PlatformMouseEvent.h" #include "ScrollTypes.h" #include "Timer.h" @@ -37,13 +38,19 @@ class NSView; #endif +#if ENABLE(TOUCH_EVENTS) +#include <wtf/HashMap.h> +#endif + namespace WebCore { class AtomicString; class Clipboard; class Cursor; class Event; +class EventTarget; class FloatPoint; +class FloatQuad; class Frame; class HitTestRequest; class HitTestResult; @@ -52,6 +59,7 @@ class KeyboardEvent; class MouseEventWithHitTestResults; class Node; class PlatformKeyboardEvent; +class PlatformTouchEvent; class PlatformWheelEvent; class RenderLayer; class RenderObject; @@ -60,6 +68,8 @@ class Scrollbar; class String; class SVGElementInstance; class TextEvent; +class TouchEvent; +class WheelEvent; class Widget; #if ENABLE(DRAG_SUPPORT) @@ -85,6 +95,7 @@ public: Node* mousePressNode() const; void setMousePressNode(PassRefPtr<Node>); + void startPanScrolling(RenderObject*); bool panScrollInProgress() { return m_panScrollInProgress; } void setPanScrollInProgress(bool inProgress) { m_panScrollInProgress = inProgress; } @@ -92,6 +103,8 @@ public: RenderObject* autoscrollRenderer() const; void updateAutoscrollRenderer(); + void dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&); + HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent, bool ignoreClipping = false, HitTestScrollbars scrollbars = DontHitTestScrollbars); bool mousePressed() const { return m_mousePressed; } @@ -138,6 +151,7 @@ public: bool handleMouseMoveEvent(const PlatformMouseEvent&, HitTestResult* hoveredNode = 0); bool handleMouseReleaseEvent(const PlatformMouseEvent&); bool handleWheelEvent(PlatformWheelEvent&); + void defaultWheelEventHandler(Node*, WheelEvent*); #if ENABLE(CONTEXT_MENUS) bool sendContextMenuEvent(const PlatformMouseEvent&); @@ -159,7 +173,6 @@ public: #if ENABLE(DRAG_SUPPORT) bool eventMayStartDrag(const PlatformMouseEvent&) const; - void dragSourceMovedTo(const PlatformMouseEvent&); void dragSourceEndedAt(const PlatformMouseEvent&, DragOperation); #endif @@ -192,9 +205,19 @@ public: static NSEvent *currentNSEvent(); #endif +#if ENABLE(TOUCH_EVENTS) + bool handleTouchEvent(const PlatformTouchEvent&); +#endif + private: #if ENABLE(DRAG_SUPPORT) - struct EventHandlerDragState { + enum DragAndDropHandleType { + UpdateDragAndDrop, + CancelDragAndDrop, + PerformDragAndDrop + }; + + struct EventHandlerDragState : Noncopyable { RefPtr<Node> m_dragSrc; // element that may be a drag source, for the current mouse gesture bool m_dragSrcIsLink; bool m_dragSrcIsImage; @@ -206,6 +229,8 @@ private: }; static EventHandlerDragState& dragState(); static const double TextDragDelay; + + bool canHandleDragAndDropForTarget(DragAndDropHandleType, Node* target, const PlatformMouseEvent&, Clipboard*, bool* accepted = 0); PassRefPtr<Clipboard> createDraggingClipboard() const; #endif // ENABLE(DRAG_SUPPORT) @@ -244,6 +269,9 @@ private: void setAutoscrollRenderer(RenderObject*); void autoscrollTimerFired(Timer<EventHandler>*); + void fakeMouseMoveEventTimerFired(Timer<EventHandler>*); + void cancelFakeMouseMoveEvent(); + void invalidateClick(); Node* nodeUnderMouse() const; @@ -287,6 +315,7 @@ private: void defaultSpaceEventHandler(KeyboardEvent*); void defaultTabEventHandler(KeyboardEvent*); + void defaultArrowEventHandler(FocusDirection, KeyboardEvent*); #if ENABLE(DRAG_SUPPORT) void allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const; @@ -309,9 +338,11 @@ private: void setFrameWasScrolledByUser(); + FocusDirection focusDirectionForKey(const AtomicString&) const; + bool capturesDragging() const { return m_capturesDragging; } -#if PLATFORM(MAC) && defined(__OBJC__) +#if PLATFORM(MAC) && defined(__OBJC__) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) NSView *mouseDownViewIfStillGood(); PlatformMouseEvent currentPlatformMouseEvent() const; @@ -348,6 +379,8 @@ private: bool m_mouseDownMayStartAutoscroll; bool m_mouseDownWasInSubframe; + Timer<EventHandler> m_fakeMouseMoveEventTimer; + #if ENABLE(SVG) bool m_svgPan; RefPtr<SVGElementInstance> m_instanceUnderMouse; @@ -368,6 +401,7 @@ private: #if ENABLE(DRAG_SUPPORT) RefPtr<Node> m_dragTarget; + bool m_shouldOnlyFireDragOverEvent; #endif RefPtr<HTMLFrameSetElement> m_frameSetBeingResized; @@ -386,10 +420,16 @@ private: RefPtr<Node> m_previousWheelScrolledNode; #if PLATFORM(MAC) +#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) NSView *m_mouseDownView; bool m_sendingEventToSubview; +#endif int m_activationEventNumber; #endif +#if ENABLE(TOUCH_EVENTS) + typedef HashMap<int, RefPtr<EventTarget> > TouchTargetMap; + TouchTargetMap m_originatingTouchPointTargets; +#endif }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/EventSource.cpp b/src/3rdparty/webkit/WebCore/page/EventSource.cpp index 2c9a343..9ccccd7 100644 --- a/src/3rdparty/webkit/WebCore/page/EventSource.cpp +++ b/src/3rdparty/webkit/WebCore/page/EventSource.cpp @@ -57,6 +57,7 @@ EventSource::EventSource(const String& url, ScriptExecutionContext* context, Exc : ActiveDOMObject(context, this) , m_state(CONNECTING) , m_reconnectTimer(this, &EventSource::reconnectTimerFired) + , m_discardTrailingNewline(false) , m_failSilently(false) , m_requestInFlight(false) , m_reconnectDelay(defaultReconnectDelay) @@ -210,21 +211,24 @@ void EventSource::parseEventStream() { unsigned int bufPos = 0; unsigned int bufSize = m_receiveBuf.size(); - for (;;) { + while (bufPos < bufSize) { + if (m_discardTrailingNewline) { + if (m_receiveBuf[bufPos] == '\n') + bufPos++; + m_discardTrailingNewline = false; + } + int lineLength = -1; int fieldLength = -1; - int carriageReturn = 0; for (unsigned int i = bufPos; lineLength < 0 && i < bufSize; i++) { switch (m_receiveBuf[i]) { case ':': if (fieldLength < 0) fieldLength = i - bufPos; break; + case '\r': + m_discardTrailingNewline = true; case '\n': - if (i > bufPos && m_receiveBuf[i - 1] == '\r') { - carriageReturn++; - i--; - } lineLength = i - bufPos; break; } @@ -234,7 +238,7 @@ void EventSource::parseEventStream() break; parseEventStreamLine(bufPos, fieldLength, lineLength); - bufPos += lineLength + carriageReturn + 1; + bufPos += lineLength + 1; } if (bufPos == bufSize) @@ -246,8 +250,10 @@ void EventSource::parseEventStream() void EventSource::parseEventStreamLine(unsigned int bufPos, int fieldLength, int lineLength) { if (!lineLength) { - if (!m_data.isEmpty()) + if (!m_data.isEmpty()) { + m_data.removeLast(); dispatchEvent(createMessageEvent()); + } if (!m_eventName.isEmpty()) m_eventName = ""; } else if (fieldLength) { @@ -265,10 +271,9 @@ void EventSource::parseEventStreamLine(unsigned int bufPos, int fieldLength, int int valueLength = lineLength - step; if (field == "data") { - if (m_data.size() > 0) - m_data.append('\n'); if (valueLength) m_data.append(&m_receiveBuf[bufPos], valueLength); + m_data.append('\n'); } else if (field == "event") m_eventName = valueLength ? String(&m_receiveBuf[bufPos], valueLength) : ""; else if (field == "id") diff --git a/src/3rdparty/webkit/WebCore/page/EventSource.h b/src/3rdparty/webkit/WebCore/page/EventSource.h index 5b037a4..d0d45cb 100644 --- a/src/3rdparty/webkit/WebCore/page/EventSource.h +++ b/src/3rdparty/webkit/WebCore/page/EventSource.h @@ -36,7 +36,6 @@ #include "ActiveDOMObject.h" #include "AtomicStringHash.h" -#include "EventListener.h" #include "EventNames.h" #include "EventTarget.h" #include "KURL.h" @@ -115,6 +114,7 @@ namespace WebCore { RefPtr<ThreadableLoader> m_loader; Timer<EventSource> m_reconnectTimer; Vector<UChar> m_receiveBuf; + bool m_discardTrailingNewline; bool m_failSilently; bool m_requestInFlight; diff --git a/src/3rdparty/webkit/WebCore/page/EventSource.idl b/src/3rdparty/webkit/WebCore/page/EventSource.idl index 561bd68..57bd807 100644 --- a/src/3rdparty/webkit/WebCore/page/EventSource.idl +++ b/src/3rdparty/webkit/WebCore/page/EventSource.idl @@ -33,6 +33,7 @@ module window { interface [ Conditional=EVENTSOURCE, + CustomConstructor, EventTarget, NoStaticTables ] EventSource { @@ -52,12 +53,12 @@ module window { void close(); // EventTarget interface - [Custom] void addEventListener(in DOMString type, - in EventListener listener, - in boolean useCapture); - [Custom] void removeEventListener(in DOMString type, + [JSCCustom] void addEventListener(in DOMString type, in EventListener listener, in boolean useCapture); + [JSCCustom] void removeEventListener(in DOMString type, + in EventListener listener, + in boolean useCapture); boolean dispatchEvent(in Event evt) raises(EventException); diff --git a/src/3rdparty/webkit/WebCore/page/FocusController.cpp b/src/3rdparty/webkit/WebCore/page/FocusController.cpp index 5e78c7d..089fb8f 100644 --- a/src/3rdparty/webkit/WebCore/page/FocusController.cpp +++ b/src/3rdparty/webkit/WebCore/page/FocusController.cpp @@ -38,8 +38,8 @@ #include "EventNames.h" #include "ExceptionCode.h" #include "Frame.h" -#include "FrameView.h" #include "FrameTree.h" +#include "FrameView.h" #include "HTMLFrameOwnerElement.h" #include "HTMLNames.h" #include "KeyboardEvent.h" @@ -49,18 +49,26 @@ #include "RenderWidget.h" #include "SelectionController.h" #include "Settings.h" +#include "SpatialNavigation.h" #include "Widget.h" -#include <wtf/Platform.h> namespace WebCore { using namespace HTMLNames; +using namespace std; static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool focused) { // If we have a focused node we should dispatch blur on it before we blur the window. // If we have a focused node we should dispatch focus on it after we focus the window. // https://bugs.webkit.org/show_bug.cgi?id=27105 + + // Do not fire events while modal dialogs are up. See https://bugs.webkit.org/show_bug.cgi?id=33962 + if (Page* page = document->page()) { + if (page->defersLoading()) + return; + } + if (!focused && document->focusedNode()) document->focusedNode()->dispatchBlurEvent(); document->dispatchWindowEvent(Event::create(focused ? eventNames().focusEvent : eventNames().blurEvent, false, false)); @@ -72,14 +80,17 @@ FocusController::FocusController(Page* page) : m_page(page) , m_isActive(false) , m_isFocused(false) + , m_isChangingFocusedFrame(false) { } void FocusController::setFocusedFrame(PassRefPtr<Frame> frame) { - if (m_focusedFrame == frame) + if (m_focusedFrame == frame || m_isChangingFocusedFrame) return; + m_isChangingFocusedFrame = true; + RefPtr<Frame> oldFrame = m_focusedFrame; RefPtr<Frame> newFrame = frame; @@ -95,6 +106,8 @@ void FocusController::setFocusedFrame(PassRefPtr<Frame> frame) newFrame->selection()->setFocused(true); newFrame->document()->dispatchWindowEvent(Event::create(eventNames().focusEvent, false, false)); } + + m_isChangingFocusedFrame = false; } Frame* FocusController::focusedOrMainFrame() @@ -148,6 +161,24 @@ bool FocusController::setInitialFocus(FocusDirection direction, KeyboardEvent* e bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* event, bool initialFocus) { + switch (direction) { + case FocusDirectionForward: + case FocusDirectionBackward: + return advanceFocusInDocumentOrder(direction, event, initialFocus); + case FocusDirectionLeft: + case FocusDirectionRight: + case FocusDirectionUp: + case FocusDirectionDown: + return advanceFocusDirectionally(direction, event); + default: + ASSERT_NOT_REACHED(); + } + + return false; +} + +bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, KeyboardEvent* event, bool initialFocus) +{ Frame* frame = focusedOrMainFrame(); ASSERT(frame); Document* document = frame->document(); @@ -252,6 +283,140 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even return true; } +bool FocusController::advanceFocusDirectionally(FocusDirection direction, KeyboardEvent* event) +{ + Frame* frame = focusedOrMainFrame(); + ASSERT(frame); + Document* focusedDocument = frame->document(); + if (!focusedDocument) + return false; + + Node* focusedNode = focusedDocument->focusedNode(); + if (!focusedNode) { + // Just move to the first focusable node. + FocusDirection tabDirection = (direction == FocusDirectionUp || direction == FocusDirectionLeft) ? + FocusDirectionForward : FocusDirectionBackward; + // 'initialFocus' is set to true so the chrome is not focused. + return advanceFocusInDocumentOrder(tabDirection, event, true); + } + + // Move up in the chain of nested frames. + frame = frame->tree()->top(); + + FocusCandidate focusCandidate; + findFocusableNodeInDirection(frame->document(), focusedNode, direction, event, focusCandidate); + + Node* node = focusCandidate.node; + if (!node || !node->isElementNode()) { + // FIXME: May need a way to focus a document here. + Frame* frame = focusedOrMainFrame(); + scrollInDirection(frame, direction); + return false; + } + + // In order to avoid crazy jump between links that are either far away from each other, + // or just not currently visible, lets do a scroll in the given direction and bail out + // if |node| element is not in the viewport. + if (hasOffscreenRect(node)) { + Frame* frame = node->document()->view()->frame(); + scrollInDirection(frame, direction); + return true; + } + + Document* newDocument = node->document(); + + if (newDocument != focusedDocument) { + // Focus is going away from the originally focused document, so clear the focused node. + focusedDocument->setFocusedNode(0); + } + + if (newDocument) + setFocusedFrame(newDocument->frame()); + + Element* element = static_cast<Element*>(node); + ASSERT(element); + + scrollIntoView(element); + element->focus(false); + return true; +} + +static void updateFocusCandidateIfCloser(Node* focusedNode, Node* candidate, long long distance, FocusCandidate& closestFocusCandidate) +{ + // Bail out if |distance| is bigger than the current closest candidate. + if (distance >= closestFocusCandidate.distance) + return; + + // If |focusedNode| and |candidate| are in the same document AND + // current |closestFocusCandidadte| is not in an {i}frame that is + // preferable to get focused. + if (focusedNode->document() == candidate->document() + && distance < closestFocusCandidate.parentDistance) { + closestFocusCandidate.node = candidate; + closestFocusCandidate.distance = distance; + closestFocusCandidate.parentDistance = maxDistance(); + } else if (focusedNode->document() != candidate->document()) { + // If the |focusedNode| is in an inner document and the |candidate| is + // in a different document, we only consider to change focus if there is + // not another already good focusable candidate in the same document as + // |focusedNode|. + if (!((isInRootDocument(candidate) && !isInRootDocument(focusedNode)) + && focusedNode->document() == closestFocusCandidate.document())) { + closestFocusCandidate.node = candidate; + closestFocusCandidate.distance = distance; + } + } +} + +void FocusController::findFocusableNodeInDirection(Document* document, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate) +{ + ASSERT(document); + + // Walk all the child nodes and update focusCandidate if we find a nearer node. + for (Node* candidate = document->firstChild(); candidate; candidate = candidate->traverseNextNode()) { + // Inner documents case. + if (candidate->isFrameOwnerElement()) + deepFindFocusableNodeInDirection(focusedNode, candidate, direction, event, closestFocusCandidate); + else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) { + long long distance = distanceInDirection(focusedNode, candidate, + direction, closestFocusCandidate); + updateFocusCandidateIfCloser(focusedNode, candidate, distance, closestFocusCandidate); + } + } +} + +void FocusController::deepFindFocusableNodeInDirection(Node* focusedNode, Node* candidate, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate) +{ + HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(candidate); + if (!owner->contentFrame()) + return; + + Document* innerDocument = owner->contentFrame()->document(); + if (!innerDocument) + return; + + if (innerDocument == focusedNode->document()) + findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate); + else { + // Check if the current {i}frame element itself is a good candidate + // to move focus to. If it is, then we traverse its inner nodes. + // Lets pass a copy of the best candidate, to not get fooled by a + // frame without focusable elements. + FocusCandidate focusCandidateCopy = closestFocusCandidate; + long long distance = distanceInDirection(focusedNode, candidate, direction, focusCandidateCopy); + if (distance < focusCandidateCopy.distance) { + focusCandidateCopy.parentAlignment = focusCandidateCopy.alignment; + focusCandidateCopy.parentDistance = distance; + + findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, focusCandidateCopy); + + // If we really have an inner closer focus candidate node, take it. + if (closestFocusCandidate.node != focusCandidateCopy.node) + closestFocusCandidate = focusCandidateCopy; + } + } +} + static bool relinquishesEditingFocus(Node *node) { ASSERT(node); diff --git a/src/3rdparty/webkit/WebCore/page/FocusController.h b/src/3rdparty/webkit/WebCore/page/FocusController.h index 33debf1..75591c7 100644 --- a/src/3rdparty/webkit/WebCore/page/FocusController.h +++ b/src/3rdparty/webkit/WebCore/page/FocusController.h @@ -28,40 +28,50 @@ #include "FocusDirection.h" #include <wtf/Forward.h> +#include <wtf/Noncopyable.h> #include <wtf/RefPtr.h> namespace WebCore { - class Frame; - class KeyboardEvent; - class Node; - class Page; +class Document; +class Frame; +class KeyboardEvent; +class Node; +class Page; +struct FocusCandidate; - class FocusController { - public: - FocusController(Page*); +class FocusController : public Noncopyable { +public: + FocusController(Page*); - void setFocusedFrame(PassRefPtr<Frame>); - Frame* focusedFrame() const { return m_focusedFrame.get(); } - Frame* focusedOrMainFrame(); + void setFocusedFrame(PassRefPtr<Frame>); + Frame* focusedFrame() const { return m_focusedFrame.get(); } + Frame* focusedOrMainFrame(); - bool setInitialFocus(FocusDirection, KeyboardEvent*); - bool advanceFocus(FocusDirection, KeyboardEvent*, bool initialFocus = false); + bool setInitialFocus(FocusDirection, KeyboardEvent*); + bool advanceFocus(FocusDirection, KeyboardEvent*, bool initialFocus = false); - bool setFocusedNode(Node*, PassRefPtr<Frame>); + bool setFocusedNode(Node*, PassRefPtr<Frame>); - void setActive(bool); - bool isActive() const { return m_isActive; } + void setActive(bool); + bool isActive() const { return m_isActive; } - void setFocused(bool); - bool isFocused() const { return m_isFocused; } + void setFocused(bool); + bool isFocused() const { return m_isFocused; } - private: - Page* m_page; - RefPtr<Frame> m_focusedFrame; - bool m_isActive; - bool m_isFocused; - }; +private: + bool advanceFocusDirectionally(FocusDirection, KeyboardEvent*); + bool advanceFocusInDocumentOrder(FocusDirection, KeyboardEvent*, bool initialFocus); + + void findFocusableNodeInDirection(Document*, Node*, FocusDirection, KeyboardEvent*, FocusCandidate&); + void deepFindFocusableNodeInDirection(Node*, Node*, FocusDirection, KeyboardEvent*, FocusCandidate&); + + Page* m_page; + RefPtr<Frame> m_focusedFrame; + bool m_isActive; + bool m_isFocused; + bool m_isChangingFocusedFrame; +}; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/FocusDirection.h b/src/3rdparty/webkit/WebCore/page/FocusDirection.h index 261c745..8a6d51f 100644 --- a/src/3rdparty/webkit/WebCore/page/FocusDirection.h +++ b/src/3rdparty/webkit/WebCore/page/FocusDirection.h @@ -28,8 +28,13 @@ namespace WebCore { enum FocusDirection { - FocusDirectionForward = 0, - FocusDirectionBackward + FocusDirectionNone = 0, + FocusDirectionForward, + FocusDirectionBackward, + FocusDirectionUp, + FocusDirectionDown, + FocusDirectionLeft, + FocusDirectionRight }; } diff --git a/src/3rdparty/webkit/WebCore/page/Frame.cpp b/src/3rdparty/webkit/WebCore/page/Frame.cpp index fab7e3f..614bbb9 100644 --- a/src/3rdparty/webkit/WebCore/page/Frame.cpp +++ b/src/3rdparty/webkit/WebCore/page/Frame.cpp @@ -36,6 +36,7 @@ #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CachedCSSStyleSheet.h" +#include "Chrome.h" #include "DOMWindow.h" #include "DocLoader.h" #include "DocumentType.h" @@ -74,6 +75,7 @@ #include "TextIterator.h" #include "TextResourceDecoder.h" #include "UserContentURLPattern.h" +#include "XMLNSNames.h" #include "XMLNames.h" #include "htmlediting.h" #include "markup.h" @@ -102,6 +104,10 @@ #include "MathMLNames.h" #endif +#if ENABLE(TILED_BACKING_STORE) +#include "TiledBackingStore.h" +#endif + using namespace std; namespace WebCore { @@ -126,9 +132,7 @@ Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* , m_redirectScheduler(this) , m_ownerElement(ownerElement) , m_script(this) - , m_selectionGranularity(CharacterGranularity) , m_selectionController(this) - , m_caretBlinkTimer(this, &Frame::caretBlinkTimerFired) , m_editor(this) , m_eventHandler(this) , m_animationController(this) @@ -136,8 +140,6 @@ Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* #if ENABLE(ORIENTATION_EVENTS) , m_orientation(0) #endif - , m_caretVisible(false) - , m_caretPaint(true) , m_highlightTextMatches(false) , m_inViewSourceMode(false) , m_needsReapplyStyles(false) @@ -165,11 +167,16 @@ Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* MathMLNames::init(); #endif + XMLNSNames::init(); XMLNames::init(); - if (!ownerElement) + if (!ownerElement) { page->setMainFrame(this); - else { +#if ENABLE(TILED_BACKING_STORE) + // Top level frame only for now. + setTiledBackingStoreEnabled(page->settings()->tiledBackingStoreEnabled()); +#endif + } else { page->incrementFrameCount(); // Make sure we will not end up with two frames referencing the same owner element. ASSERT((!(ownerElement->m_contentFrame)) || (ownerElement->m_contentFrame->ownerElement() != ownerElement)); @@ -257,6 +264,11 @@ void Frame::setView(PassRefPtr<FrameView> view) // Since this part may be getting reused as a result of being // pulled from the back/forward cache, reset this flag. loader()->resetMultipleFormSubmissionProtection(); + +#if ENABLE(TILED_BACKING_STORE) + if (m_view && tiledBackingStore()) + m_view->setPaintsEntireContents(true); +#endif } ScriptController* Frame::script() @@ -277,8 +289,7 @@ void Frame::setDocument(PassRefPtr<Document> newDoc) } m_doc = newDoc; - if (m_doc && selection()->isFocusedAndActive()) - setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); + selection()->updateSecureKeyboardEntryIfActive(); if (m_doc && !m_doc->attached()) m_doc->attach(); @@ -292,7 +303,7 @@ void Frame::sendOrientationChangeEvent(int orientation) { m_orientation = orientation; if (Document* doc = document()) - doc->dispatchWindowEvent(eventNames().orientationchangeEvent, false, false); + doc->dispatchWindowEvent(Event::create(eventNames().orientationchangeEvent, false, false)); } #endif // ENABLE(ORIENTATION_EVENTS) @@ -358,12 +369,7 @@ Editor* Frame::editor() const TextGranularity Frame::selectionGranularity() const { - return m_selectionGranularity; -} - -void Frame::setSelectionGranularity(TextGranularity granularity) -{ - m_selectionGranularity = granularity; + return m_selectionController.granularity(); } SelectionController* Frame::dragCaretController() const @@ -411,7 +417,7 @@ static RegularExpression* createRegExpForLabels(const Vector<String>& labels) return new RegularExpression(pattern, TextCaseInsensitive); } -String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell) +String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell, size_t* resultDistanceFromStartOfCell) { RenderObject* cellRenderer = cell->renderer(); @@ -425,23 +431,30 @@ String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellE if (aboveCell) { // search within the above cell we found for a match + size_t lengthSearched = 0; for (Node* n = aboveCell->firstChild(); n; n = n->traverseNextNode(aboveCell)) { if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { // For each text chunk, run the regexp String nodeString = n->nodeValue(); int pos = regExp->searchRev(nodeString); - if (pos >= 0) + if (pos >= 0) { + if (resultDistanceFromStartOfCell) + *resultDistanceFromStartOfCell = lengthSearched; return nodeString.substring(pos, regExp->matchedLength()); + } + lengthSearched += nodeString.length(); } } } } } // Any reason in practice to search all cells in that are above cell? + if (resultDistanceFromStartOfCell) + *resultDistanceFromStartOfCell = notFound; return String(); } -String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element) +String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element* element, size_t* resultDistance, bool* resultIsInCellAbove) { OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); // We stop searching after we've seen this many chars @@ -453,6 +466,11 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element HTMLTableCellElement* startingTableCell = 0; bool searchedCellAbove = false; + if (resultDistance) + *resultDistance = notFound; + if (resultIsInCellAbove) + *resultIsInCellAbove = false; + // walk backwards in the node tree, until another element, or form, or end of tree int unsigned lengthSearched = 0; Node* n; @@ -468,9 +486,12 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element } else if (n->hasTagName(tdTag) && !startingTableCell) { startingTableCell = static_cast<HTMLTableCellElement*>(n); } else if (n->hasTagName(trTag) && startingTableCell) { - String result = searchForLabelsAboveCell(regExp.get(), startingTableCell); - if (!result.isEmpty()) + String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance); + if (!result.isEmpty()) { + if (resultIsInCellAbove) + *resultIsInCellAbove = true; return result; + } searchedCellAbove = true; } else if (n->isTextNode() && n->renderer() && n->renderer()->style()->visibility() == VISIBLE) { // For each text chunk, run the regexp @@ -479,38 +500,48 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element if (lengthSearched + nodeString.length() > maxCharsSearched) nodeString = nodeString.right(charsSearchedThreshold - lengthSearched); int pos = regExp->searchRev(nodeString); - if (pos >= 0) + if (pos >= 0) { + if (resultDistance) + *resultDistance = lengthSearched; return nodeString.substring(pos, regExp->matchedLength()); + } lengthSearched += nodeString.length(); } } // If we started in a cell, but bailed because we found the start of the form or the // previous element, we still might need to search the row above us for a label. - if (startingTableCell && !searchedCellAbove) - return searchForLabelsAboveCell(regExp.get(), startingTableCell); + if (startingTableCell && !searchedCellAbove) { + String result = searchForLabelsAboveCell(regExp.get(), startingTableCell, resultDistance); + if (!result.isEmpty()) { + if (resultIsInCellAbove) + *resultIsInCellAbove = true; + return result; + } + } return String(); } -String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element) +static String matchLabelsAgainstString(const Vector<String>& labels, const String& stringToMatch) { - String name = element->getAttribute(nameAttr); - if (name.isEmpty()) + if (stringToMatch.isEmpty()) return String(); - // Make numbers and _'s in field names behave like word boundaries, e.g., "address2" - replace(name, RegularExpression("\\d", TextCaseSensitive), " "); - name.replace('_', ' '); + String mutableStringToMatch = stringToMatch; + // Make numbers and _'s in field names behave like word boundaries, e.g., "address2" + replace(mutableStringToMatch, RegularExpression("\\d", TextCaseSensitive), " "); + mutableStringToMatch.replace('_', ' '); + OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); - // Use the largest match we can find in the whole name string + // Use the largest match we can find in the whole string int pos; int length; int bestPos = -1; int bestLength = -1; int start = 0; do { - pos = regExp->match(name, start); + pos = regExp->match(mutableStringToMatch, start); if (pos != -1) { length = regExp->matchedLength(); if (length >= bestLength) { @@ -520,11 +551,24 @@ String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* e start = pos + 1; } } while (pos != -1); - + if (bestPos != -1) - return name.substring(bestPos, bestLength); + return mutableStringToMatch.substring(bestPos, bestLength); return String(); } + +String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* element) +{ + // Match against the name element, then against the id element if no match is found for the name element. + // See 7538330 for one popular site that benefits from the id element check. + // FIXME: This code is mirrored in FrameMac.mm. It would be nice to make the Mac code call the platform-agnostic + // code, which would require converting the NSArray of NSStrings to a Vector of Strings somewhere along the way. + String resultFromNameAttribute = matchLabelsAgainstString(labels, element->getAttribute(nameAttr)); + if (!resultFromNameAttribute.isEmpty()) + return resultFromNameAttribute; + + return matchLabelsAgainstString(labels, element->getAttribute(idAttr)); +} const VisibleSelection& Frame::mark() const { @@ -552,31 +596,6 @@ void Frame::notifyRendererOfSelectionChange(bool userTriggered) toRenderTextControl(renderer)->selectionChanged(userTriggered); } -void Frame::invalidateSelection() -{ - selection()->setNeedsLayout(); - selectionLayoutChanged(); -} - -void Frame::setCaretVisible(bool flag) -{ - if (m_caretVisible == flag) - return; - clearCaretRectIfNeeded(); - m_caretVisible = flag; - selectionLayoutChanged(); -} - -void Frame::clearCaretRectIfNeeded() -{ -#if ENABLE(TEXT_CARET) - if (m_caretPaint) { - m_caretPaint = false; - selection()->invalidateCaretRect(); - } -#endif -} - // Helper function that tells whether a particular node is an element that has an entire // Frame and FrameView, a <frame>, <iframe>, or <object>. static bool isFrameElement(const Node *n) @@ -629,87 +648,6 @@ void Frame::setFocusedNodeIfNeeded() page()->focusController()->setFocusedNode(0, this); } -void Frame::selectionLayoutChanged() -{ - bool caretRectChanged = selection()->recomputeCaretRect(); - -#if ENABLE(TEXT_CARET) - bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); - bool shouldBlink = m_caretVisible - && selection()->isCaret() && (selection()->isContentEditable() || caretBrowsing); - - // If the caret moved, stop the blink timer so we can restart with a - // black caret in the new location. - if (caretRectChanged || !shouldBlink) - m_caretBlinkTimer.stop(); - - // Start blinking with a black caret. Be sure not to restart if we're - // already blinking in the right location. - if (shouldBlink && !m_caretBlinkTimer.isActive()) { - if (double blinkInterval = page()->theme()->caretBlinkInterval()) - m_caretBlinkTimer.startRepeating(blinkInterval); - - if (!m_caretPaint) { - m_caretPaint = true; - selection()->invalidateCaretRect(); - } - } -#else - if (!caretRectChanged) - return; -#endif - - RenderView* view = contentRenderer(); - if (!view) - return; - - VisibleSelection selection = this->selection()->selection(); - - if (!selection.isRange()) - view->clearSelection(); - else { - // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection. - // Example: foo <a>bar</a>. Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. If we pass [foo, 3] - // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected - // and will fill the gap before 'bar'. - Position startPos = selection.start(); - if (startPos.downstream().isCandidate()) - startPos = startPos.downstream(); - Position endPos = selection.end(); - if (endPos.upstream().isCandidate()) - endPos = endPos.upstream(); - - // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted - // because we don't yet notify the SelectionController of text removal. - if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) { - RenderObject *startRenderer = startPos.node()->renderer(); - RenderObject *endRenderer = endPos.node()->renderer(); - view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset()); - } - } -} - -void Frame::caretBlinkTimerFired(Timer<Frame>*) -{ -#if ENABLE(TEXT_CARET) - ASSERT(m_caretVisible); - ASSERT(selection()->isCaret()); - bool caretPaint = m_caretPaint; - if (selection()->isCaretBlinkingSuspended() && caretPaint) - return; - m_caretPaint = !caretPaint; - selection()->invalidateCaretRect(); -#endif -} - -void Frame::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const -{ -#if ENABLE(TEXT_CARET) - if (m_caretPaint && m_caretVisible) - selection()->paintCaret(p, tx, ty, clipRect); -#endif -} - void Frame::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const { #if ENABLE(TEXT_CARET) @@ -725,59 +663,51 @@ float Frame::zoomFactor() const return m_zoomFactor; } -bool Frame::isZoomFactorTextOnly() const +ZoomMode Frame::zoomMode() const { - return m_page->settings()->zoomsTextOnly(); + return m_page->settings()->zoomMode(); } bool Frame::shouldApplyTextZoom() const { - if (m_zoomFactor == 1.0f || !isZoomFactorTextOnly()) - return false; -#if ENABLE(SVG) - if (m_doc->isSVGDocument()) - return false; -#endif - return true; + return m_zoomFactor != 1.0f && zoomMode() == ZoomTextOnly; } bool Frame::shouldApplyPageZoom() const { - if (m_zoomFactor == 1.0f || isZoomFactorTextOnly()) - return false; -#if ENABLE(SVG) - if (m_doc->isSVGDocument()) - return false; -#endif - return true; + return m_zoomFactor != 1.0f && zoomMode() == ZoomPage; } -void Frame::setZoomFactor(float percent, bool isTextOnly) +void Frame::setZoomFactor(float percent, ZoomMode mode) { - if (m_zoomFactor == percent && isZoomFactorTextOnly() == isTextOnly) + if (m_zoomFactor == percent && zoomMode() == mode) return; #if ENABLE(SVG) - // SVG doesn't care if the zoom factor is text only. It will always apply a - // zoom to the whole SVG. + // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents. + // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification. if (m_doc->isSVGDocument()) { if (!static_cast<SVGDocument*>(m_doc.get())->zoomAndPanEnabled()) return; - m_zoomFactor = percent; - m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom. if (m_doc->renderer()) - m_doc->renderer()->repaint(); - return; + m_doc->renderer()->setNeedsLayout(true); } #endif + if (mode == ZoomPage) { + // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position. + IntPoint scrollPosition = view()->scrollPosition(); + float percentDifference = (percent / m_zoomFactor); + view()->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference)); + } + m_zoomFactor = percent; - m_page->settings()->setZoomsTextOnly(isTextOnly); + m_page->settings()->setZoomMode(mode); m_doc->recalcStyle(Node::Force); for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->setZoomFactor(m_zoomFactor, isTextOnly); + child->setZoomFactor(m_zoomFactor, mode); if (m_doc->renderer() && m_doc->renderer()->needsLayout() && view()->didFirstLayout()) view()->layout(); @@ -786,7 +716,8 @@ void Frame::setZoomFactor(float percent, bool isTextOnly) void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize) { m_doc->setPrinting(printing); - view()->setMediaType(printing ? "print" : "screen"); + view()->adjustMediaTypeForPrinting(printing); + m_doc->updateStyleSelector(); view()->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize); @@ -870,10 +801,10 @@ void Frame::injectUserScripts(UserScriptInjectionTime injectionTime) return; UserScriptMap::const_iterator end = userScripts->end(); for (UserScriptMap::const_iterator it = userScripts->begin(); it != end; ++it) - injectUserScriptsForWorld(it->first, *it->second, injectionTime); + injectUserScriptsForWorld(it->first.get(), *it->second, injectionTime); } -void Frame::injectUserScriptsForWorld(unsigned worldID, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime) +void Frame::injectUserScriptsForWorld(DOMWrapperWorld* world, const UserScriptVector& userScripts, UserScriptInjectionTime injectionTime) { if (userScripts.isEmpty()) return; @@ -887,9 +818,8 @@ void Frame::injectUserScriptsForWorld(unsigned worldID, const UserScriptVector& for (unsigned i = 0; i < count; ++i) { UserScript* script = userScripts[i].get(); if (script->injectionTime() == injectionTime && UserContentURLPattern::matchesPatterns(doc->url(), script->whitelist(), script->blacklist())) - sourceCode.append(ScriptSourceCode(script->source(), script->url())); + m_script.evaluateInWorld(ScriptSourceCode(script->source(), script->url()), world); } - script()->evaluateInIsolatedWorld(worldID, sourceCode); } bool Frame::shouldChangeSelection(const VisibleSelection& newSelection) const @@ -915,20 +845,6 @@ bool Frame::isContentEditable() const return m_doc->inDesignMode(); } -#if !PLATFORM(MAC) - -void Frame::setUseSecureKeyboardEntry(bool) -{ -} - -#endif - -void Frame::updateSecureKeyboardEntryIfActive() -{ - if (selection()->isFocusedAndActive()) - setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); -} - CSSMutableStyleDeclaration *Frame::typingStyle() const { return m_typingStyle.get(); @@ -1240,7 +1156,7 @@ FloatRect Frame::selectionBounds(bool clipToVisibleContent) const return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect; } -void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleContent) const +void Frame::selectionTextRects(Vector<FloatRect>& rects, SelectionRectRespectTransforms respectTransforms, bool clipToVisibleContent) const { RenderView* root = contentRenderer(); if (!root) @@ -1248,19 +1164,36 @@ void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleConte RefPtr<Range> selectedRange = selection()->toNormalizedRange(); - Vector<IntRect> intRects; - selectedRange->textRects(intRects, true); - - unsigned size = intRects.size(); FloatRect visibleContentRect = m_view->visibleContentRect(); - for (unsigned i = 0; i < size; ++i) - if (clipToVisibleContent) - rects.append(intersection(intRects[i], visibleContentRect)); - else - rects.append(intRects[i]); + + // FIMXE: we are appending empty rects to the list for those that fall outside visibleContentRect. + // We may not want to do that. + if (respectTransforms) { + Vector<FloatQuad> quads; + selectedRange->textQuads(quads, true); + + unsigned size = quads.size(); + for (unsigned i = 0; i < size; ++i) { + IntRect currRect = quads[i].enclosingBoundingBox(); + if (clipToVisibleContent) + rects.append(intersection(currRect, visibleContentRect)); + else + rects.append(currRect); + } + } else { + Vector<IntRect> intRects; + selectedRange->textRects(intRects, true); + + unsigned size = intRects.size(); + for (unsigned i = 0; i < size; ++i) { + if (clipToVisibleContent) + rects.append(intersection(intRects[i], visibleContentRect)); + else + rects.append(intRects[i]); + } + } } - // Scans logically forward from "start", including any child frames static HTMLFormElement *scanForForm(Node *start) { @@ -1523,12 +1456,6 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig continue; } - // A non-collapsed result range can in some funky whitespace cases still not - // advance the range's start position (4509328). Break to avoid infinite loop. - VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); - if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) - break; - // Only treat the result as a match if it is visible if (editor()->insideVisibleArea(resultRange.get())) { ++matchCount; @@ -1539,7 +1466,12 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig if (limit > 0 && matchCount >= limit) break; - setStart(searchRange.get(), newStart); + // Set the new start for the search range to be the end of the previous + // result range. There is no need to use a VisiblePosition here, + // since findPlainText will use a TextIterator to go over the visible + // text nodes. + searchRange->setStart(resultRange->endContainer(exception), resultRange->endOffset(exception), exception); + Node* shadowTreeRoot = searchRange->shadowTreeRootNode(); if (searchRange->collapsed(exception) && shadowTreeRoot) searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception); @@ -1646,6 +1578,54 @@ void Frame::disconnectOwnerElement() m_ownerElement = 0; } +// The frame is moved in DOM, potentially to another page. +void Frame::transferChildFrameToNewDocument() +{ + ASSERT(m_ownerElement); + Frame* newParent = m_ownerElement->document()->frame(); + bool didTransfer = false; + + // Switch page. + Page* newPage = newParent ? newParent->page() : 0; + if (m_page != newPage) { + if (page()->focusController()->focusedFrame() == this) + page()->focusController()->setFocusedFrame(0); + + if (m_page) + m_page->decrementFrameCount(); + + m_page = newPage; + + if (newPage) + newPage->incrementFrameCount(); + + didTransfer = true; + } + + // Update the frame tree. + Frame* oldParent = tree()->parent(); + if (oldParent != newParent) { + if (oldParent) + oldParent->tree()->removeChild(this); + if (newParent) { + newParent->tree()->appendChild(this); + m_ownerElement->setName(); + } + didTransfer = true; + } + + // Avoid unnecessary calls to client and frame subtree if the frame ended + // up on the same page and under the same parent frame. + if (didTransfer) { + // Let external clients update themselves. + loader()->client()->didTransferChildFrameToNewDocument(); + + // Do the same for all the children. + for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) + child->transferChildFrameToNewDocument(); + } +} + String Frame::documentTypeString() const { if (DocumentType* doctype = document()->doctype()) @@ -1827,4 +1807,51 @@ void Frame::createView(const IntSize& viewportSize, view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); } +#if ENABLE(TILED_BACKING_STORE) +void Frame::setTiledBackingStoreEnabled(bool enabled) +{ + if (!enabled) { + m_tiledBackingStore.clear(); + return; + } + if (m_tiledBackingStore) + return; + m_tiledBackingStore.set(new TiledBackingStore(this)); + if (m_view) + m_view->setPaintsEntireContents(true); +} + +void Frame::tiledBackingStorePaintBegin() +{ + if (!m_view) + return; + m_view->layoutIfNeededRecursive(); + m_view->flushDeferredRepaints(); +} + +void Frame::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect) +{ + if (!m_view) + return; + m_view->paintContents(context, rect); +} + +void Frame::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) +{ + if (!m_page || !m_view) + return; + unsigned size = paintedArea.size(); + // Request repaint from the system + for (int n = 0; n < size; ++n) + m_page->chrome()->invalidateContentsAndWindow(m_view->contentsToWindow(paintedArea[n]), false); +} + +IntRect Frame::tiledBackingStoreContentsRect() +{ + if (!m_view) + return IntRect(); + return IntRect(IntPoint(), m_view->contentsSize()); +} +#endif + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Frame.h b/src/3rdparty/webkit/WebCore/page/Frame.h index 6208bbd..65bdeb0 100644 --- a/src/3rdparty/webkit/WebCore/page/Frame.h +++ b/src/3rdparty/webkit/WebCore/page/Frame.h @@ -29,24 +29,25 @@ #define Frame_h #include "AnimationController.h" -#include "Document.h" #include "DragImage.h" -#include "EditAction.h" #include "Editor.h" #include "EventHandler.h" #include "FrameLoader.h" #include "FrameTree.h" -#include "Range.h" #include "ScriptController.h" #include "ScrollBehavior.h" #include "SelectionController.h" -#include "TextGranularity.h" #include "UserScriptTypes.h" +#include "ZoomMode.h" #if PLATFORM(WIN) #include "FrameWin.h" #endif +#if ENABLE(TILED_BACKING_STORE) +#include "TiledBackingStoreClient.h" +#endif + #if PLATFORM(MAC) #ifndef __OBJC__ class NSArray; @@ -64,26 +65,16 @@ typedef struct HBITMAP__* HBITMAP; namespace WebCore { class CSSMutableStyleDeclaration; - class Editor; - class EventHandler; - class FrameLoader; - class RedirectScheduler; - class FrameLoaderClient; - class FrameTree; - class FrameView; - class HTMLFrameOwnerElement; class HTMLTableCellElement; class RegularExpression; class RenderPart; - class ScriptController; - class SelectionController; - class Settings; - class VisibleSelection; - class Widget; - - template <typename T> class Timer; + class TiledBackingStore; - class Frame : public RefCounted<Frame> { + class Frame : public RefCounted<Frame> +#if ENABLE(TILED_BACKING_STORE) + , public TiledBackingStoreClient +#endif + { public: static PassRefPtr<Frame> create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client) { @@ -96,6 +87,8 @@ namespace WebCore { Page* page() const; void detachFromPage(); + void transferChildFrameToNewDocument(); + HTMLFrameOwnerElement* ownerElement() const; void pageDestroyed(); @@ -131,7 +124,7 @@ namespace WebCore { void injectUserScripts(UserScriptInjectionTime); private: - void injectUserScriptsForWorld(unsigned worldID, const UserScriptVector&, UserScriptInjectionTime); + void injectUserScriptsForWorld(DOMWrapperWorld*, const UserScriptVector&, UserScriptInjectionTime); private: Frame(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*); @@ -181,15 +174,20 @@ namespace WebCore { return document() ? document()->displayStringModifiedByEncoding(str) : str; } +#if ENABLE(TILED_BACKING_STORE) + TiledBackingStore* tiledBackingStore() const { return m_tiledBackingStore.get(); } + void setTiledBackingStoreEnabled(bool); +#endif + private: void lifeSupportTimerFired(Timer<Frame>*); // === to be moved into FrameView public: - void setZoomFactor(float scale, bool isTextOnly); + void setZoomFactor(float scale, ZoomMode); float zoomFactor() const; - bool isZoomFactorTextOnly() const; + ZoomMode zoomMode() const; bool shouldApplyTextZoom() const; bool shouldApplyPageZoom() const; float pageZoomFactor() const { return shouldApplyPageZoom() ? zoomFactor() : 1.0f; } @@ -250,59 +248,54 @@ namespace WebCore { public: TextGranularity selectionGranularity() const; - void setSelectionGranularity(TextGranularity); bool shouldChangeSelection(const VisibleSelection&) const; bool shouldDeleteSelection(const VisibleSelection&) const; - void clearCaretRectIfNeeded(); void setFocusedNodeIfNeeded(); - void selectionLayoutChanged(); void notifyRendererOfSelectionChange(bool userTriggered); - void invalidateSelection(); - - void setCaretVisible(bool = true); - void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const; void paintDragCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const; bool isContentEditable() const; // if true, everything in frame is editable - void updateSecureKeyboardEntryIfActive(); - CSSMutableStyleDeclaration* typingStyle() const; void setTypingStyle(CSSMutableStyleDeclaration*); void clearTypingStyle(); FloatRect selectionBounds(bool clipToVisibleContent = true) const; - void selectionTextRects(Vector<FloatRect>&, bool clipToVisibleContent = true) const; + enum SelectionRectRespectTransforms { RespectTransforms = true, IgnoreTransforms = false }; + void selectionTextRects(Vector<FloatRect>&, SelectionRectRespectTransforms respectTransforms, bool clipToVisibleContent = true) const; HTMLFormElement* currentForm() const; void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, bool revealExtent = false); void setSelectionFromNone(); - void setUseSecureKeyboardEntry(bool); - - private: - void caretBlinkTimerFired(Timer<Frame>*); - - public: SelectionController* dragCaretController() const; - String searchForLabelsAboveCell(RegularExpression*, HTMLTableCellElement*); - String searchForLabelsBeforeElement(const Vector<String>& labels, Element*); + String searchForLabelsAboveCell(RegularExpression*, HTMLTableCellElement*, size_t* resultDistanceFromStartOfCell); + String searchForLabelsBeforeElement(const Vector<String>& labels, Element*, size_t* resultDistance, bool* resultIsInCellAbove); String matchLabelsAgainstElement(const Vector<String>& labels, Element*); VisiblePosition visiblePositionForPoint(const IntPoint& framePoint); Document* documentAtPoint(const IntPoint& windowPoint); + + private: +#if ENABLE(TILED_BACKING_STORE) + // TiledBackingStoreClient interface + virtual void tiledBackingStorePaintBegin(); + virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&); + virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea); + virtual IntRect tiledBackingStoreContentsRect(); +#endif #if PLATFORM(MAC) // === undecided, would like to consider moving to another class public: - NSString* searchForNSLabelsAboveCell(RegularExpression*, HTMLTableCellElement*); - NSString* searchForLabelsBeforeElement(NSArray* labels, Element*); + NSString* searchForNSLabelsAboveCell(RegularExpression*, HTMLTableCellElement*, size_t* resultDistanceFromStartOfCell); + NSString* searchForLabelsBeforeElement(NSArray* labels, Element*, size_t* resultDistance, bool* resultIsInCellAbove); NSString* matchLabelsAgainstElement(NSArray* labels, Element*); #if ENABLE(DASHBOARD_SUPPORT) @@ -352,11 +345,8 @@ namespace WebCore { float m_zoomFactor; - TextGranularity m_selectionGranularity; - mutable SelectionController m_selectionController; mutable VisibleSelection m_mark; - Timer<Frame> m_caretBlinkTimer; mutable Editor m_editor; mutable EventHandler m_eventHandler; mutable AnimationController m_animationController; @@ -368,15 +358,16 @@ namespace WebCore { #if ENABLE(ORIENTATION_EVENTS) int m_orientation; #endif - - bool m_caretVisible; - bool m_caretPaint; bool m_highlightTextMatches; bool m_inViewSourceMode; bool m_needsReapplyStyles; bool m_isDisconnected; bool m_excludeFromTextSearch; + +#if ENABLE(TILED_BACKING_STORE) + OwnPtr<TiledBackingStore> m_tiledBackingStore; +#endif }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/FrameTree.cpp b/src/3rdparty/webkit/WebCore/page/FrameTree.cpp index 41caa9c..d6170e1 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameTree.cpp +++ b/src/3rdparty/webkit/WebCore/page/FrameTree.cpp @@ -25,7 +25,6 @@ #include "Page.h" #include "PageGroup.h" #include <stdarg.h> -#include <wtf/Platform.h> #include <wtf/StringExtras.h> #include <wtf/Vector.h> diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.cpp b/src/3rdparty/webkit/WebCore/page/FrameView.cpp index 4c3a0ab..45764de 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameView.cpp +++ b/src/3rdparty/webkit/WebCore/page/FrameView.cpp @@ -29,6 +29,7 @@ #include "AXObjectCache.h" #include "CSSStyleSelector.h" +#include "Chrome.h" #include "ChromeClient.h" #include "DocLoader.h" #include "EventHandler.h" @@ -45,8 +46,8 @@ #include "HTMLNames.h" #include "InspectorTimelineAgent.h" #include "OverflowEvent.h" +#include "RenderEmbeddedObject.h" #include "RenderPart.h" -#include "RenderPartObject.h" #include "RenderScrollbar.h" #include "RenderScrollbarPart.h" #include "RenderTheme.h" @@ -69,6 +70,9 @@ #include "SVGViewSpec.h" #endif +#if ENABLE(TILED_BACKING_STORE) +#include "TiledBackingStore.h" +#endif namespace WebCore { @@ -98,13 +102,14 @@ static const double deferredRepaintDelayIncrementDuringLoading = 0; // The maximum number of updateWidgets iterations that should be done before returning. static const unsigned maxUpdateWidgetsIterations = 2; -struct ScheduledEvent { +struct ScheduledEvent : Noncopyable { RefPtr<Event> m_event; RefPtr<Node> m_eventTarget; }; FrameView::FrameView(Frame* frame) : m_frame(frame) + , m_canHaveScrollbars(true) , m_slowRepaintObjectCount(0) , m_fixedObjectCount(0) , m_layoutTimer(this, &FrameView::layoutTimerFired) @@ -198,7 +203,7 @@ void FrameView::reset() m_deferredRepaintDelay = initialDeferredRepaintDelayDuringLoading; m_deferredRepaintTimer.stop(); m_lastPaintTime = 0; - m_paintRestriction = PaintRestrictionNone; + m_paintBehavior = PaintBehaviorNormal; m_isPainting = false; m_isVisuallyNonEmpty = false; m_firstVisuallyNonEmptyLayoutCallbackPending = true; @@ -220,7 +225,10 @@ void FrameView::resetScrollbars() // Reset the document's scrollbars back to our defaults before we yield the floor. m_firstLayout = true; setScrollbarsSuppressed(true); - setScrollbarModes(ScrollbarAuto, ScrollbarAuto); + if (m_canHaveScrollbars) + setScrollbarModes(ScrollbarAuto, ScrollbarAuto); + else + setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); setScrollbarsSuppressed(false); } @@ -288,7 +296,7 @@ void FrameView::invalidateRect(const IntRect& rect) { if (!parent()) { if (hostWindow()) - hostWindow()->repaint(rect, true); + hostWindow()->invalidateContentsAndWindow(rect, false /*immediate*/); return; } @@ -317,6 +325,40 @@ void FrameView::setMarginHeight(int h) m_margins.setHeight(h); } +bool FrameView::avoidScrollbarCreation() +{ + ASSERT(m_frame); + + // with frame flattening no subframe can have scrollbars + // but we also cannot turn scrollbars of as we determine + // our flattening policy using that. + + if (!m_frame->ownerElement()) + return false; + + if (!m_frame->settings() || m_frame->settings()->frameFlatteningEnabled()) + return true; + + return false; +} + +void FrameView::setCanHaveScrollbars(bool canHaveScrollbars) +{ + m_canHaveScrollbars = canHaveScrollbars; + ScrollView::setCanHaveScrollbars(canHaveScrollbars); +} + +void FrameView::updateCanHaveScrollbars() +{ + ScrollbarMode hMode; + ScrollbarMode vMode; + scrollbarModes(hMode, vMode); + if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff) + m_canHaveScrollbars = false; + else + m_canHaveScrollbars = true; +} + PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation) { // FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles). @@ -325,7 +367,7 @@ PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientatio // Try the <body> element first as a scrollbar source. Element* body = doc ? doc->body() : 0; if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR)) - return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderBox()); + return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()->enclosingBox()); // If the <body> didn't have a custom style, then the root element might. Element* docElement = doc ? doc->documentElement() : 0; @@ -343,6 +385,9 @@ PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientatio void FrameView::setContentsSize(const IntSize& size) { + if (size == contentsSize()) + return; + m_deferSetNeedsLayouts++; ScrollView::setContentsSize(size); @@ -352,7 +397,7 @@ void FrameView::setContentsSize(const IntSize& size) return; page->chrome()->contentsSizeChanged(frame(), size); //notify only - + m_deferSetNeedsLayouts--; if (!m_deferSetNeedsLayouts) @@ -365,6 +410,7 @@ void FrameView::adjustViewSize() RenderView* root = m_frame->contentRenderer(); if (!root) return; + setContentsSize(IntSize(root->rightLayoutOverflow(), root->bottomLayoutOverflow())); } @@ -415,12 +461,12 @@ void FrameView::updateCompositingLayers() return; // This call will make sure the cached hasAcceleratedCompositing is updated from the pref - view->compositor()->cacheAcceleratedCompositingEnabledFlag(); + view->compositor()->cacheAcceleratedCompositingFlags(); if (!view->usesCompositing()) return; - view->compositor()->updateCompositingLayers(); + view->compositor()->updateCompositingLayers(CompositingUpdateAfterLayoutOrStyleChange); } void FrameView::setNeedsOneShotDrawingSynchronization() @@ -458,8 +504,22 @@ bool FrameView::syncCompositingStateRecursive() } } return allSubframesSynced; -#endif // USE(ACCELERATED_COMPOSITING) +#else // USE(ACCELERATED_COMPOSITING) + return true; +#endif +} + +bool FrameView::isSoftwareRenderable() const +{ +#if USE(ACCELERATED_COMPOSITING) + RenderView* view = m_frame->contentRenderer(); + if (!view) + return true; + + return !view->compositor()->has3DContent(); +#else return true; +#endif } void FrameView::didMoveOnscreen() @@ -505,9 +565,8 @@ void FrameView::layout(bool allowSubtree) if (isPainting()) return; -#if ENABLE(INSPECTOR) - InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(); - if (timelineAgent) +#if ENABLE(INSPECTOR) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) timelineAgent->willLayout(); #endif @@ -564,27 +623,42 @@ void FrameView::layout(bool allowSubtree) ScrollbarMode hMode; ScrollbarMode vMode; - scrollbarModes(hMode, vMode); + if (m_canHaveScrollbars) { + hMode = ScrollbarAuto; + vMode = ScrollbarAuto; + } else { + hMode = ScrollbarAlwaysOff; + vMode = ScrollbarAlwaysOff; + } if (!subtree) { - RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0; + Node* documentElement = document->documentElement(); + RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0; Node* body = document->body(); if (body && body->renderer()) { - if (body->hasTagName(framesetTag)) { + if (body->hasTagName(framesetTag) && !m_frame->settings()->frameFlatteningEnabled()) { body->renderer()->setChildNeedsLayout(true); vMode = ScrollbarAlwaysOff; hMode = ScrollbarAlwaysOff; } else if (body->hasTagName(bodyTag)) { - if (!m_firstLayout && m_size.height() != layoutHeight() - && toRenderBox(body->renderer())->stretchesToViewHeight()) + if (!m_firstLayout && m_size.height() != layoutHeight() && body->renderer()->enclosingBox()->stretchesToViewHeight()) body->renderer()->setChildNeedsLayout(true); // It's sufficient to just check the X overflow, // since it's illegal to have visible in only one direction. RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && document->documentElement()->hasTagName(htmlTag) ? body->renderer() : rootRenderer; applyOverflowToViewport(o, hMode, vMode); } - } else if (rootRenderer) + } else if (rootRenderer) { +#if ENABLE(SVG) + if (documentElement->isSVGElement()) { + if (!m_firstLayout && (m_size.width() != layoutWidth() || m_size.height() != layoutHeight())) + rootRenderer->setChildNeedsLayout(true); + } else + applyOverflowToViewport(rootRenderer, hMode, vMode); +#else applyOverflowToViewport(rootRenderer, hMode, vMode); +#endif + } #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (m_firstLayout && !document->ownerElement()) printf("Elapsed time before first layout: %d\n", document->elapsedTime()); @@ -629,8 +703,14 @@ void FrameView::layout(bool allowSubtree) pauseScheduledEvents(); - if (subtree) - root->view()->pushLayoutState(root); + bool disableLayoutState = false; + if (subtree) { + RenderView* view = root->view(); + disableLayoutState = view->shouldDisableLayoutStateForSubtree(root); + view->pushLayoutState(root); + if (disableLayoutState) + view->disableLayoutState(); + } m_midLayout = true; beginDeferredRepaints(); @@ -638,11 +718,16 @@ void FrameView::layout(bool allowSubtree) endDeferredRepaints(); m_midLayout = false; - if (subtree) - root->view()->popLayoutState(); + if (subtree) { + RenderView* view = root->view(); + view->popLayoutState(); + if (disableLayoutState) + view->enableLayoutState(); + } m_layoutRoot = 0; - m_frame->invalidateSelection(); + m_frame->selection()->setNeedsLayout(); + m_frame->selection()->updateAppearance(); m_layoutSchedulingEnabled = true; @@ -697,22 +782,22 @@ void FrameView::layout(bool allowSubtree) } #if ENABLE(INSPECTOR) - if (timelineAgent) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) timelineAgent->didLayout(); #endif m_nestedLayoutCount--; } -void FrameView::addWidgetToUpdate(RenderPartObject* object) +void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object) { if (!m_widgetUpdateSet) - m_widgetUpdateSet.set(new HashSet<RenderPartObject*>); + m_widgetUpdateSet.set(new RenderEmbeddedObjectSet); m_widgetUpdateSet->add(object); } -void FrameView::removeWidgetToUpdate(RenderPartObject* object) +void FrameView::removeWidgetToUpdate(RenderEmbeddedObject* object) { if (!m_widgetUpdateSet) return; @@ -734,11 +819,29 @@ String FrameView::mediaType() const return m_mediaType; } +void FrameView::adjustMediaTypeForPrinting(bool printing) +{ + if (printing) { + if (m_mediaTypeWhenNotPrinting.isNull()) + m_mediaTypeWhenNotPrinting = mediaType(); + setMediaType("print"); + } else { + if (!m_mediaTypeWhenNotPrinting.isNull()) + setMediaType(m_mediaTypeWhenNotPrinting); + m_mediaTypeWhenNotPrinting = String(); + } +} + bool FrameView::useSlowRepaints() const { return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque; } +bool FrameView::useSlowRepaintsIfNotOverlapped() const +{ + return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || !m_contentIsOpaque; +} + void FrameView::setUseSlowRepaints() { m_useSlowRepaints = true; @@ -770,12 +873,12 @@ void FrameView::addFixedObject() void FrameView::removeFixedObject() { ASSERT(m_fixedObjectCount > 0); - m_fixedObjectCount--; + --m_fixedObjectCount; if (!m_fixedObjectCount) setCanBlitOnScroll(!useSlowRepaints()); } -void FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) +bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) { const size_t fixedObjectThreshold = 5; @@ -785,7 +888,7 @@ void FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect if (!positionedObjects || positionedObjects->isEmpty()) { hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); - return; + return true; } // Get the rects of the fixed objects visible in the rectToScroll @@ -814,7 +917,7 @@ void FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect // 1) scroll hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); - // 2) update the area of fixed objets that has been invalidated + // 2) update the area of fixed objects that has been invalidated size_t fixObjectsCount = subRectToUpdate.size(); for (size_t i = 0; i < fixObjectsCount; ++i) { IntRect updateRect = subRectToUpdate[i]; @@ -822,14 +925,13 @@ void FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect scrolledRect.move(scrollDelta); updateRect.unite(scrolledRect); updateRect.intersect(rectToScroll); - hostWindow()->repaint(updateRect, true, false, true); + hostWindow()->invalidateContentsAndWindow(updateRect, false); } - } else { - // the number of fixed objects exceed the threshold, so we repaint everything. - IntRect updateRect = clipRect; - updateRect.intersect(rectToScroll); - hostWindow()->repaint(updateRect, true, false, true); + return true; } + + // the number of fixed objects exceed the threshold, we cannot use the fast path + return false; } void FrameView::setIsOverlapped(bool isOverlapped) @@ -959,16 +1061,18 @@ void FrameView::scrollPositionChanged() { frame()->eventHandler()->sendScrollEvent(); + // For fixed position elements, update widget positions and compositing layers after scrolling, + // but only if we're not inside of layout. + // FIXME: we could skip this if we knew the page had no fixed position elements. + if (!m_nestedLayoutCount) { + if (RenderView* root = m_frame->contentRenderer()) { + root->updateWidgetPositions(); #if USE(ACCELERATED_COMPOSITING) - // We need to update layer positions after scrolling to account for position:fixed layers. - Document* document = m_frame->document(); - if (!document) - return; - - RenderLayer* layer = document->renderer() ? document->renderer()->enclosingLayer() : 0; - if (layer) - layer->updateLayerPositions(RenderLayer::UpdateCompositingLayers); + if (root->usesCompositing()) + root->compositor()->updateCompositingLayers(CompositingUpdateOnScroll); #endif + } + } } HostWindow* FrameView::hostWindow() const @@ -987,9 +1091,10 @@ void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) double delay = adjustedDeferredRepaintDelay(); if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) { - IntRect visibleContent = visibleContentRect(); - visibleContent.intersect(r); - if (visibleContent.isEmpty()) + IntRect paintRect = r; + if (!paintsEntireContents()) + paintRect.intersect(visibleContentRect()); + if (paintRect.isEmpty()) return; if (m_repaintCount == cRepaintRectUnionThreshold) { IntRect unionedRect; @@ -999,9 +1104,9 @@ void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) m_repaintRects.append(unionedRect); } if (m_repaintCount < cRepaintRectUnionThreshold) - m_repaintRects.append(visibleContent); + m_repaintRects.append(paintRect); else - m_repaintRects[0].unite(visibleContent); + m_repaintRects[0].unite(paintRect); m_repaintCount++; if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive()) @@ -1012,6 +1117,12 @@ void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) if (!immediate && isOffscreen() && !shouldUpdateWhileOffscreen()) return; +#if ENABLE(TILED_BACKING_STORE) + if (frame()->tiledBackingStore()) { + frame()->tiledBackingStore()->invalidate(r); + return; + } +#endif ScrollView::repaintContentRectangle(r, immediate); } @@ -1083,8 +1194,15 @@ void FrameView::doDeferredRepaints() return; } unsigned size = m_repaintRects.size(); - for (unsigned i = 0; i < size; i++) + for (unsigned i = 0; i < size; i++) { +#if ENABLE(TILED_BACKING_STORE) + if (frame()->tiledBackingStore()) { + frame()->tiledBackingStore()->invalidate(m_repaintRects[i]); + continue; + } +#endif ScrollView::repaintContentRectangle(m_repaintRects[i], false); + } m_repaintRects.clear(); m_repaintCount = 0; @@ -1154,6 +1272,13 @@ void FrameView::scheduleRelayout() if (!m_frame->document()->shouldScheduleLayout()) return; + // When frame flattening is enabled, the contents of the frame affects layout of the parent frames. + // Also invalidate parent frame starting from the owner element of this frame. + if (m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) { + if (m_frame->ownerElement()->hasTagName(iframeTag) || m_frame->ownerElement()->hasTagName(frameTag)) + m_frame->ownerRenderer()->setNeedsLayout(true, true); + } + int delay = m_frame->document()->minimumLayoutDelay(); if (m_layoutTimer.isActive() && m_delayedLayout && !delay) unscheduleRelayout(); @@ -1363,11 +1488,11 @@ bool FrameView::updateWidgets() if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty()) return true; - Vector<RenderPartObject*> objectVector; + Vector<RenderEmbeddedObject*> objectVector; copyToVector(*m_widgetUpdateSet, objectVector); size_t size = objectVector.size(); for (size_t i = 0; i < size; ++i) { - RenderPartObject* object = objectVector[i]; + RenderEmbeddedObject* object = objectVector[i]; object->updateWidget(false); // updateWidget() can destroy the RenderPartObject, so we need to make sure it's @@ -1519,6 +1644,7 @@ void FrameView::valueChanged(Scrollbar* bar) ScrollView::valueChanged(bar); if (offset != scrollOffset()) frame()->eventHandler()->sendScrollEvent(); + frame()->loader()->client()->didChangeScrollOffset(); } void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect) @@ -1683,9 +1809,8 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) return; #if ENABLE(INSPECTOR) - InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(); - if (timelineAgent) - timelineAgent->willPaint(); + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) + timelineAgent->willPaint(rect); #endif Document* document = frame()->document(); @@ -1698,7 +1823,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) fillWithRed = false; // Subframe, don't fill with red. else if (isTransparent()) fillWithRed = false; // Transparent, don't fill with red. - else if (m_paintRestriction == PaintRestrictionSelectionOnly || m_paintRestriction == PaintRestrictionSelectionOnlyBlackText) + else if (m_paintBehavior & PaintBehaviorSelectionOnly) fillWithRed = false; // Selections are transparent, don't fill with red. else if (m_nodeToDraw) fillWithRed = false; // Element images are transparent, don't fill with red. @@ -1706,7 +1831,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) fillWithRed = true; if (fillWithRed) - p->fillRect(rect, Color(0xFF, 0, 0)); + p->fillRect(rect, Color(0xFF, 0, 0), DeviceColorSpace); #endif bool isTopLevelPainter = !sCurrentPaintTimeStamp; @@ -1736,9 +1861,15 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) // m_nodeToDraw is used to draw only one element (and its descendants) RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; - if (m_paintRestriction == PaintRestrictionNone) + + PaintBehavior paintBehavior = m_paintBehavior; + if (paintBehavior == PaintBehaviorNormal) document->invalidateRenderedRectsForMarkersInRect(rect); - contentRenderer->layer()->paint(p, rect, m_paintRestriction, eltRenderer); + + if (document->printing()) + paintBehavior |= PaintBehaviorFlattenCompositingLayers; + + contentRenderer->layer()->paint(p, rect, paintBehavior, eltRenderer); m_isPainting = false; m_lastPaintTime = currentTime(); @@ -1753,16 +1884,21 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) sCurrentPaintTimeStamp = 0; #if ENABLE(INSPECTOR) - if (timelineAgent) + if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent()) timelineAgent->didPaint(); #endif } -void FrameView::setPaintRestriction(PaintRestriction pr) +void FrameView::setPaintBehavior(PaintBehavior behavior) { - m_paintRestriction = pr; + m_paintBehavior = behavior; } - + +PaintBehavior FrameView::paintBehavior() const +{ + return m_paintBehavior; +} + bool FrameView::isPainting() const { return m_isPainting; diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.h b/src/3rdparty/webkit/WebCore/page/FrameView.h index 5243c02..7371d13 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameView.h +++ b/src/3rdparty/webkit/WebCore/page/FrameView.h @@ -45,7 +45,7 @@ class Node; class PlatformMouseEvent; class RenderLayer; class RenderObject; -class RenderPartObject; +class RenderEmbeddedObject; class ScheduledEvent; class String; @@ -72,8 +72,13 @@ public: void setMarginWidth(int); void setMarginHeight(int); + virtual void setCanHaveScrollbars(bool); + void updateCanHaveScrollbars(); + virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation); + virtual bool avoidScrollbarCreation(); + virtual void setContentsSize(const IntSize&); void layout(bool allowSubtree = true); @@ -87,7 +92,6 @@ public: RenderObject* layoutRoot(bool onlyDuringLayout = false) const; int layoutCount() const { return m_layoutCount; } - // These two helper functions just pass through to the RenderView. bool needsLayout() const; void setNeedsLayout(); @@ -104,6 +108,10 @@ public: // Returns true if the sync was completed. bool syncCompositingStateRecursive(); + // Returns true when a paint with the PaintBehaviorFlattenCompositingLayers flag set gives + // a faithful representation of the content. + bool isSoftwareRenderable() const; + void didMoveOnscreen(); void willMoveOffscreen(); @@ -135,6 +143,7 @@ public: String mediaType() const; void setMediaType(const String&); + void adjustMediaTypeForPrinting(bool printing); void setUseSlowRepaints(); void setIsOverlapped(bool); @@ -166,11 +175,12 @@ public: bool wasScrolledByUser() const; void setWasScrolledByUser(bool); - void addWidgetToUpdate(RenderPartObject*); - void removeWidgetToUpdate(RenderPartObject*); + void addWidgetToUpdate(RenderEmbeddedObject*); + void removeWidgetToUpdate(RenderEmbeddedObject*); virtual void paintContents(GraphicsContext*, const IntRect& damageRect); - void setPaintRestriction(PaintRestriction); + void setPaintBehavior(PaintBehavior); + PaintBehavior paintBehavior() const; bool isPainting() const; void setNodeToDraw(Node*); @@ -200,7 +210,7 @@ public: void invalidateScrollCorner(); protected: - virtual void scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); + virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); private: FrameView(Frame*); @@ -212,6 +222,7 @@ private: friend class RenderWidget; bool useSlowRepaints() const; + bool useSlowRepaintsIfNotOverlapped() const; void applyOverflowToViewport(RenderObject*, ScrollbarMode& hMode, ScrollbarMode& vMode); @@ -258,11 +269,14 @@ private: IntSize m_size; IntSize m_margins; - OwnPtr<HashSet<RenderPartObject*> > m_widgetUpdateSet; + + typedef HashSet<RenderEmbeddedObject*> RenderEmbeddedObjectSet; + OwnPtr<RenderEmbeddedObjectSet> m_widgetUpdateSet; RefPtr<Frame> m_frame; bool m_doFullRepaint; + bool m_canHaveScrollbars; bool m_useSlowRepaints; bool m_isOverlapped; bool m_contentIsOpaque; @@ -289,7 +303,8 @@ private: float m_lastZoomFactor; String m_mediaType; - + String m_mediaTypeWhenNotPrinting; + unsigned m_enqueueEvents; Vector<ScheduledEvent*> m_scheduledEvents; @@ -314,7 +329,7 @@ private: bool m_setNeedsLayoutWasDeferred; RefPtr<Node> m_nodeToDraw; - PaintRestriction m_paintRestriction; + PaintBehavior m_paintBehavior; bool m_isPainting; bool m_isVisuallyNonEmpty; diff --git a/src/3rdparty/webkit/WebCore/page/Geolocation.cpp b/src/3rdparty/webkit/WebCore/page/Geolocation.cpp index de4a9a1..86f6777 100644 --- a/src/3rdparty/webkit/WebCore/page/Geolocation.cpp +++ b/src/3rdparty/webkit/WebCore/page/Geolocation.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. * Copyright (C) 2009 Torch Mobile, Inc. + * Copyright 2010, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,14 +28,54 @@ #include "config.h" #include "Geolocation.h" +#if ENABLE(GEOLOCATION) + #include "Chrome.h" -#include "Document.h" #include "Frame.h" #include "Page.h" +#include <wtf/CurrentTime.h> + +#if ENABLE(CLIENT_BASED_GEOLOCATION) +#include "Coordinates.h" +#include "GeolocationController.h" +#include "GeolocationError.h" +#include "GeolocationPosition.h" +#include "PositionError.h" +#endif namespace WebCore { static const char permissionDeniedErrorMessage[] = "User denied Geolocation"; +static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocation service"; + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + +static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position) +{ + if (!position) + return 0; + + RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(), position->longitude(), position->canProvideAltitude(), position->altitude(), + position->accuracy(), position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(), + position->canProvideHeading(), position->heading(), position->canProvideSpeed(), position->speed()); + return Geoposition::create(coordinates.release(), position->timestamp()); +} + +static PassRefPtr<PositionError> createPositionError(GeolocationError* error) +{ + PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE; + switch (error->code()) { + case GeolocationError::PermissionDenied: + code = PositionError::PERMISSION_DENIED; + break; + case GeolocationError::PositionUnavailable: + code = PositionError::POSITION_UNAVAILABLE; + break; + } + + return PositionError::create(code, error->message()); +} +#endif Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) : m_geolocation(geolocation) @@ -42,6 +83,7 @@ Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassRefPtr<Posit , m_errorCallback(errorCallback) , m_options(options) , m_timer(this, &Geolocation::GeoNotifier::timerFired) + , m_useCachedPosition(false) { ASSERT(m_geolocation); ASSERT(m_successCallback); @@ -58,11 +100,22 @@ void Geolocation::GeoNotifier::setFatalError(PassRefPtr<PositionError> error) m_timer.startOneShot(0); } +void Geolocation::GeoNotifier::setUseCachedPosition() +{ + m_useCachedPosition = true; + m_timer.startOneShot(0); +} + bool Geolocation::GeoNotifier::hasZeroTimeout() const { return m_options->hasTimeout() && m_options->timeout() == 0; } +void Geolocation::GeoNotifier::runSuccessCallback(Geoposition* position) +{ + m_successCallback->handleEvent(position); +} + void Geolocation::GeoNotifier::startTimerIfNeeded() { if (m_options->hasTimeout()) @@ -73,6 +126,10 @@ void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) { m_timer.stop(); + // Protect this GeoNotifier object, since it + // could be deleted by a call to clearWatch in a callback. + RefPtr<GeoNotifier> protect(this); + if (m_fatalError) { if (m_errorCallback) m_errorCallback->handleEvent(m_fatalError.get()); @@ -81,6 +138,14 @@ void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) return; } + if (m_useCachedPosition) { + // Clear the cached position flag in case this is a watch request, which + // will continue to run. + m_useCachedPosition = false; + m_geolocation->requestUsesCachedPosition(this); + return; + } + if (m_errorCallback) { RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timeout expired"); m_errorCallback->handleEvent(error.get()); @@ -88,10 +153,12 @@ void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) m_geolocation->requestTimedOut(this); } -void Geolocation::Watchers::set(int id, PassRefPtr<GeoNotifier> notifier) +void Geolocation::Watchers::set(int id, PassRefPtr<GeoNotifier> prpNotifier) { - m_idToNotifierMap.set(id, notifier); - m_notifierToIdMap.set(notifier, id); + RefPtr<GeoNotifier> notifier = prpNotifier; + + m_idToNotifierMap.set(id, notifier.get()); + m_notifierToIdMap.set(notifier.release(), id); } void Geolocation::Watchers::remove(int id) @@ -112,6 +179,11 @@ void Geolocation::Watchers::remove(GeoNotifier* notifier) m_notifierToIdMap.remove(iter); } +bool Geolocation::Watchers::contains(GeoNotifier* notifier) const +{ + return m_notifierToIdMap.contains(notifier); +} + void Geolocation::Watchers::clear() { m_idToNotifierMap.clear(); @@ -130,9 +202,12 @@ void Geolocation::Watchers::getNotifiersVector(Vector<RefPtr<GeoNotifier> >& cop Geolocation::Geolocation(Frame* frame) : m_frame(frame) +#if !ENABLE(CLIENT_BASED_GEOLOCATION) , m_service(GeolocationService::create(this)) +#endif , m_allowGeolocation(Unknown) , m_shouldClearCache(false) + , m_positionCache(new GeolocationPositionCache) { if (!m_frame) return; @@ -140,19 +215,46 @@ Geolocation::Geolocation(Frame* frame) m_frame->document()->setUsingGeolocation(true); } +Geolocation::~Geolocation() +{ +} + void Geolocation::disconnectFrame() { - m_service->stopUpdating(); - if (m_frame && m_frame->document()) - m_frame->document()->setUsingGeolocation(false); + stopUpdating(); + if (m_frame) { + if (m_frame->document()) + m_frame->document()->setUsingGeolocation(false); + if (m_frame->page() && m_allowGeolocation == InProgress) + m_frame->page()->chrome()->cancelGeolocationPermissionRequestForFrame(m_frame); + } m_frame = 0; } +Geoposition* Geolocation::lastPosition() +{ + ASSERT(isAllowed()); + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + if (!m_frame) + return 0; + + Page* page = m_frame->page(); + if (!page) + return 0; + + m_lastPosition = createGeoposition(page->geolocationController()->lastPosition()); +#else + m_lastPosition = m_service->lastPosition(); +#endif + + return m_lastPosition.get(); +} + void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) { RefPtr<GeoNotifier> notifier = startRequest(successCallback, errorCallback, options); - if (!notifier) - return; + ASSERT(notifier); m_oneShots.add(notifier); } @@ -160,8 +262,7 @@ void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallbac int Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) { RefPtr<GeoNotifier> notifier = startRequest(successCallback, errorCallback, options); - if (!notifier) - return 0; + ASSERT(notifier); static int nextAvailableWatchId = 1; // In case of overflow, make sure the ID remains positive, but reuse the ID values. @@ -179,17 +280,16 @@ PassRefPtr<Geolocation::GeoNotifier> Geolocation::startRequest(PassRefPtr<Positi // the permission state can not change again in the lifetime of this page. if (isDenied()) notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage)); - else { - if (notifier->hasZeroTimeout() || m_service->startUpdating(notifier->m_options.get())) + else if (haveSuitableCachedPosition(notifier->m_options.get())) + notifier->setUseCachedPosition(); + else if (notifier->hasZeroTimeout() || startUpdating(notifier.get())) { +#if ENABLE(CLIENT_BASED_GEOLOCATION) + // Only start timer if we're not waiting for user permission. + if (!m_startRequestPermissionNotifier) +#endif notifier->startTimerIfNeeded(); - else { - if (notifier->m_errorCallback) { - RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, "Unable to Start"); - notifier->m_errorCallback->handleEvent(error.get()); - } - return 0; - } - } + } else + notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage)); return notifier.release(); } @@ -201,49 +301,129 @@ void Geolocation::fatalErrorOccurred(Geolocation::GeoNotifier* notifier) m_watchers.remove(notifier); if (!hasListeners()) - m_service->stopUpdating(); + stopUpdating(); } -void Geolocation::requestTimedOut(GeoNotifier* notifier) +void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) { - // If this is a one-shot request, stop it. - m_oneShots.remove(notifier); + // This is called asynchronously, so the permissions could have been denied + // since we last checked in startRequest. + if (isDenied()) { + notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage)); + return; + } + + m_requestsAwaitingCachedPosition.add(notifier); + + // If permissions are allowed, make the callback + if (isAllowed()) { + makeCachedPositionCallbacks(); + return; + } + + // Request permissions, which may be synchronous or asynchronous. + requestPermission(); +} + +void Geolocation::makeCachedPositionCallbacks() +{ + // All modifications to m_requestsAwaitingCachedPosition are done + // asynchronously, so we don't need to worry about it being modified from + // the callbacks. + GeoNotifierSet::const_iterator end = m_requestsAwaitingCachedPosition.end(); + for (GeoNotifierSet::const_iterator iter = m_requestsAwaitingCachedPosition.begin(); iter != end; ++iter) { + GeoNotifier* notifier = iter->get(); + notifier->runSuccessCallback(m_positionCache->cachedPosition()); + + // If this is a one-shot request, stop it. Otherwise, if the watch still + // exists, start the service to get updates. + if (m_oneShots.contains(notifier)) + m_oneShots.remove(notifier); + else if (m_watchers.contains(notifier)) { + if (notifier->hasZeroTimeout() || startUpdating(notifier)) + notifier->startTimerIfNeeded(); + else + notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage)); + } + } + + m_requestsAwaitingCachedPosition.clear(); if (!hasListeners()) - m_service->stopUpdating(); + stopUpdating(); } -void Geolocation::clearWatch(int watchId) +void Geolocation::requestTimedOut(GeoNotifier* notifier) { - m_watchers.remove(watchId); - + // If this is a one-shot request, stop it. + m_oneShots.remove(notifier); + if (!hasListeners()) - m_service->stopUpdating(); + stopUpdating(); } -void Geolocation::suspend() +bool Geolocation::haveSuitableCachedPosition(PositionOptions* options) { - if (hasListeners()) - m_service->suspend(); + if (!m_positionCache->cachedPosition()) + return false; + if (!options->hasMaximumAge()) + return true; + if (!options->maximumAge()) + return false; + DOMTimeStamp currentTimeMillis = currentTime() * 1000.0; + return m_positionCache->cachedPosition()->timestamp() > currentTimeMillis - options->maximumAge(); } -void Geolocation::resume() +void Geolocation::clearWatch(int watchId) { - if (hasListeners()) - m_service->resume(); + m_watchers.remove(watchId); + + if (!hasListeners()) + stopUpdating(); } void Geolocation::setIsAllowed(bool allowed) { + // This may be due to either a new position from the service, or a cached + // position. m_allowGeolocation = allowed ? Yes : No; - if (isAllowed()) - makeSuccessCallbacks(); - else { +#if ENABLE(CLIENT_BASED_GEOLOCATION) + if (m_startRequestPermissionNotifier) { + if (isAllowed()) { + // Permission request was made during the startUpdating process + m_startRequestPermissionNotifier->startTimerIfNeeded(); + m_startRequestPermissionNotifier = 0; + if (!m_frame) + return; + Page* page = m_frame->page(); + if (!page) + return; + page->geolocationController()->addObserver(this); + } else { + m_startRequestPermissionNotifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage)); + m_oneShots.add(m_startRequestPermissionNotifier); + m_startRequestPermissionNotifier = 0; + } + return; + } +#endif + + if (!isAllowed()) { RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage); error->setIsFatal(true); handleError(error.get()); + m_requestsAwaitingCachedPosition.clear(); + return; } + + // If the service has a last position, use it to call back for all requests. + // If any of the requests are waiting for permission for a cached position, + // the position from the service will be at least as fresh. + if (lastPosition()) + makeSuccessCallbacks(); + else + makeCachedPositionCallbacks(); } void Geolocation::sendError(Vector<RefPtr<GeoNotifier> >& notifiers, PositionError* error) @@ -320,7 +500,7 @@ void Geolocation::handleError(PositionError* error) sendError(watchersCopy, error); if (!hasListeners()) - m_service->stopUpdating(); + stopUpdating(); } void Geolocation::requestPermission() @@ -341,10 +521,11 @@ void Geolocation::requestPermission() page->chrome()->requestGeolocationPermissionForFrame(m_frame, this); } -void Geolocation::geolocationServicePositionChanged(GeolocationService* service) +void Geolocation::positionChanged(PassRefPtr<Geoposition> newPosition) { - ASSERT_UNUSED(service, service == m_service); - ASSERT(m_service->lastPosition()); + m_currentPosition = newPosition; + + m_positionCache->setCachedPosition(m_currentPosition.get()); // Stop all currently running timers. stopTimers(); @@ -363,7 +544,7 @@ void Geolocation::geolocationServicePositionChanged(GeolocationService* service) void Geolocation::makeSuccessCallbacks() { - ASSERT(m_service->lastPosition()); + ASSERT(m_currentPosition); ASSERT(isAllowed()); Vector<RefPtr<GeoNotifier> > oneShotsCopy; @@ -377,18 +558,104 @@ void Geolocation::makeSuccessCallbacks() // further callbacks to these notifiers. m_oneShots.clear(); - sendPosition(oneShotsCopy, m_service->lastPosition()); - sendPosition(watchersCopy, m_service->lastPosition()); + sendPosition(oneShotsCopy, m_currentPosition.get()); + sendPosition(watchersCopy, m_currentPosition.get()); if (!hasListeners()) - m_service->stopUpdating(); + stopUpdating(); +} + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + +void Geolocation::setPosition(GeolocationPosition* position) +{ + positionChanged(createGeoposition(position)); +} + +void Geolocation::setError(GeolocationError* error) +{ + RefPtr<PositionError> positionError = createPositionError(error); + handleError(positionError.get()); +} + +#else + +void Geolocation::geolocationServicePositionChanged(GeolocationService* service) +{ + ASSERT_UNUSED(service, service == m_service); + ASSERT(m_service->lastPosition()); + + positionChanged(m_service->lastPosition()); } void Geolocation::geolocationServiceErrorOccurred(GeolocationService* service) { ASSERT(service->lastError()); - + + // Note that we do not stop timers here. For one-shots, the request is + // cleared in handleError. For watchers, the spec requires that the timer is + // not cleared. handleError(service->lastError()); } +#endif + +bool Geolocation::startUpdating(GeoNotifier* notifier) +{ +#if ENABLE(CLIENT_BASED_GEOLOCATION) + // FIXME: Pass options to client. + + if (!isAllowed()) { + m_startRequestPermissionNotifier = notifier; + requestPermission(); + return true; + } + + if (!m_frame) + return false; + + Page* page = m_frame->page(); + if (!page) + return false; + + page->geolocationController()->addObserver(this); + return true; +#else + return m_service->startUpdating(notifier->m_options.get()); +#endif +} + +void Geolocation::stopUpdating() +{ +#if ENABLE(CLIENT_BASED_GEOLOCATION) + if (!m_frame) + return; + + Page* page = m_frame->page(); + if (!page) + return; + + page->geolocationController()->removeObserver(this); +#else + m_service->stopUpdating(); +#endif + +} + } // namespace WebCore + +#else + +namespace WebCore { + +void Geolocation::disconnectFrame() {} + +Geolocation::Geolocation(Frame*) {} + +Geolocation::~Geolocation() {} + +void Geolocation::setIsAllowed(bool) {} + +} + +#endif // ENABLE(GEOLOCATION) diff --git a/src/3rdparty/webkit/WebCore/page/Geolocation.h b/src/3rdparty/webkit/WebCore/page/Geolocation.h index 4827664..29f3214 100644 --- a/src/3rdparty/webkit/WebCore/page/Geolocation.h +++ b/src/3rdparty/webkit/WebCore/page/Geolocation.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. + * Copyright 2010, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,51 +27,56 @@ #ifndef Geolocation_h #define Geolocation_h +#include "GeolocationPositionCache.h" #include "GeolocationService.h" +#include "Geoposition.h" #include "PositionCallback.h" #include "PositionError.h" #include "PositionErrorCallback.h" #include "PositionOptions.h" #include "Timer.h" -#include <wtf/Platform.h> -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> namespace WebCore { class Frame; -class Geoposition; -class Geolocation : public RefCounted<Geolocation>, public GeolocationServiceClient { +#if ENABLE(CLIENT_BASED_GEOLOCATION) +class GeolocationPosition; +class GeolocationError; +#endif + +class Geolocation : public RefCounted<Geolocation> +#if !ENABLE(CLIENT_BASED_GEOLOCATION) && ENABLE(GEOLOCATION) + , public GeolocationServiceClient +#endif +{ public: static PassRefPtr<Geolocation> create(Frame* frame) { return adoptRef(new Geolocation(frame)); } - virtual ~Geolocation() {} + ~Geolocation(); void disconnectFrame(); - Geoposition* lastPosition() const { return m_service->lastPosition(); } - void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); int watchPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); void clearWatch(int watchId); - void suspend(); - void resume(); - void setIsAllowed(bool); + Frame* frame() const { return m_frame; } + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + void setPosition(GeolocationPosition*); + void setError(GeolocationError*); +#else + GeolocationService* getGeolocationService() const { return m_service.get(); } +#endif + +private: + Geoposition* lastPosition(); + bool isAllowed() const { return m_allowGeolocation == Yes; } bool isDenied() const { return m_allowGeolocation == No; } - void setShouldClearCache(bool shouldClearCache) { m_shouldClearCache = shouldClearCache; } - bool shouldClearCache() const { return m_shouldClearCache; } - -private: Geolocation(Frame*); class GeoNotifier : public RefCounted<GeoNotifier> { @@ -79,6 +85,8 @@ private: void setFatalError(PassRefPtr<PositionError>); bool hasZeroTimeout() const; + void setUseCachedPosition(); + void runSuccessCallback(Geoposition*); void startTimerIfNeeded(); void timerFired(Timer<GeoNotifier>*); @@ -88,6 +96,7 @@ private: RefPtr<PositionOptions> m_options; Timer<GeoNotifier> m_timer; RefPtr<PositionError> m_fatalError; + bool m_useCachedPosition; private: GeoNotifier(Geolocation*, PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); @@ -98,6 +107,7 @@ private: void set(int id, PassRefPtr<GeoNotifier>); void remove(int id); void remove(GeoNotifier*); + bool contains(GeoNotifier*) const; void clear(); bool isEmpty() const; void getNotifiersVector(Vector<RefPtr<GeoNotifier> >&) const; @@ -118,26 +128,41 @@ private: void stopTimersForWatchers(); void stopTimers(); + void positionChanged(PassRefPtr<Geoposition>); void makeSuccessCallbacks(); void handleError(PositionError*); void requestPermission(); + bool startUpdating(GeoNotifier*); + void stopUpdating(); + +#if !ENABLE(CLIENT_BASED_GEOLOCATION) && ENABLE(GEOLOCATION) // GeolocationServiceClient virtual void geolocationServicePositionChanged(GeolocationService*); virtual void geolocationServiceErrorOccurred(GeolocationService*); +#endif PassRefPtr<GeoNotifier> startRequest(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); void fatalErrorOccurred(GeoNotifier*); void requestTimedOut(GeoNotifier*); + void requestUsesCachedPosition(GeoNotifier*); + bool haveSuitableCachedPosition(PositionOptions*); + void makeCachedPositionCallbacks(); typedef HashSet<RefPtr<GeoNotifier> > GeoNotifierSet; GeoNotifierSet m_oneShots; Watchers m_watchers; Frame* m_frame; +#if !ENABLE(CLIENT_BASED_GEOLOCATION) OwnPtr<GeolocationService> m_service; +#else + RefPtr<GeoNotifier> m_startRequestPermissionNotifier; +#endif + RefPtr<Geoposition> m_lastPosition; + RefPtr<Geoposition> m_currentPosition; enum { Unknown, @@ -146,6 +171,11 @@ private: No } m_allowGeolocation; bool m_shouldClearCache; + +#if ENABLE(GEOLOCATION) + OwnPtr<GeolocationPositionCache> m_positionCache; +#endif + GeoNotifierSet m_requestsAwaitingCachedPosition; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Geolocation.idl b/src/3rdparty/webkit/WebCore/page/Geolocation.idl index e125118..aa5b59f 100644 --- a/src/3rdparty/webkit/WebCore/page/Geolocation.idl +++ b/src/3rdparty/webkit/WebCore/page/Geolocation.idl @@ -25,9 +25,7 @@ module core { - interface Geolocation { - readonly attribute Geoposition lastPosition; - + interface [Conditional=GEOLOCATION, OmitConstructor] Geolocation { [Custom] void getCurrentPosition(in PositionCallback successCallback, in PositionErrorCallback errorCallback, in PositionOptions options); [Custom] long watchPosition(in PositionCallback successCallback, in PositionErrorCallback errorCallback, in PositionOptions options); diff --git a/src/3rdparty/webkit/WebCore/page/GeolocationController.cpp b/src/3rdparty/webkit/WebCore/page/GeolocationController.cpp new file mode 100644 index 0000000..fd18b45 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/GeolocationController.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GeolocationController.h" + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + +#include "GeolocationControllerClient.h" + +namespace WebCore { + +GeolocationController::GeolocationController(Page* page, GeolocationControllerClient* client) + : m_page(page) + , m_client(client) +{ +} + +GeolocationController::~GeolocationController() +{ + if (m_client) + m_client->geolocationDestroyed(); +} + +void GeolocationController::addObserver(Geolocation* observer) +{ + ASSERT(!m_observers.contains(observer)); + + bool wasEmpty = m_observers.isEmpty(); + m_observers.add(observer); + if (wasEmpty && m_client) + m_client->startUpdating(); +} + +void GeolocationController::removeObserver(Geolocation* observer) +{ + if (!m_observers.contains(observer)) + return; + + m_observers.remove(observer); + if (m_observers.isEmpty() && m_client) + m_client->stopUpdating(); +} + +void GeolocationController::positionChanged(GeolocationPosition* position) +{ + Vector<RefPtr<Geolocation> > observersVector; + copyToVector(m_observers, observersVector); + for (size_t i = 0; i < observersVector.size(); ++i) + observersVector[i]->setPosition(position); +} + +void GeolocationController::errorOccurred(GeolocationError* error) +{ + Vector<RefPtr<Geolocation> > observersVector; + copyToVector(m_observers, observersVector); + for (size_t i = 0; i < observersVector.size(); ++i) + observersVector[i]->setError(error); +} + +GeolocationPosition* GeolocationController::lastPosition() +{ + if (!m_client) + return 0; + + return m_client->lastPosition(); +} + +} // namespace WebCore + +#endif // ENABLE(CLIENT_BASED_GEOLOCATION) diff --git a/src/3rdparty/webkit/WebCore/page/GeolocationController.h b/src/3rdparty/webkit/WebCore/page/GeolocationController.h new file mode 100644 index 0000000..80f9ca8 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/GeolocationController.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationController_h +#define GeolocationController_h + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + +#include "Geolocation.h" +#include <wtf/HashSet.h> +#include <wtf/Noncopyable.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class GeolocationControllerClient; +class GeolocationError; +class GeolocationPosition; +class Page; + +class GeolocationController : public Noncopyable { +public: + GeolocationController(Page*, GeolocationControllerClient*); + ~GeolocationController(); + + void addObserver(Geolocation*); + void removeObserver(Geolocation*); + + void positionChanged(GeolocationPosition*); + void errorOccurred(GeolocationError*); + + GeolocationPosition* lastPosition(); + +private: + Page* m_page; + GeolocationControllerClient* m_client; + + HashSet<RefPtr<Geolocation> > m_observers; +}; + +} // namespace WebCore + +#endif // ENABLE(CLIENT_BASED_GEOLOCATION) + +#endif // GeolocationController_h diff --git a/src/3rdparty/webkit/WebCore/page/GeolocationControllerClient.h b/src/3rdparty/webkit/WebCore/page/GeolocationControllerClient.h new file mode 100644 index 0000000..cc0e1e4 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/GeolocationControllerClient.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationControllerClient_h +#define GeolocationControllerClient_h + +namespace WebCore { + +class GeolocationPosition; + +class GeolocationControllerClient { +public: + virtual void geolocationDestroyed() = 0; + + virtual void startUpdating() = 0; + virtual void stopUpdating() = 0; + virtual GeolocationPosition* lastPosition() = 0; + +protected: + virtual ~GeolocationControllerClient() { } +}; + +} // namespace WebCore + +#endif // GeolocationControllerClient_h diff --git a/src/3rdparty/webkit/WebCore/page/GeolocationError.h b/src/3rdparty/webkit/WebCore/page/GeolocationError.h new file mode 100644 index 0000000..2a3bad4 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/GeolocationError.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationError_h +#define GeolocationError_h + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + +#include "PlatformString.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class GeolocationError : public RefCounted<GeolocationError> { +public: + enum ErrorCode { + PermissionDenied, + PositionUnavailable + }; + + static PassRefPtr<GeolocationError> create(ErrorCode code, const String& message) { return adoptRef(new GeolocationError(code, message)); } + + ErrorCode code() const { return m_code; } + const String& message() const { return m_message; } + +private: + GeolocationError(ErrorCode code, const String& message) + : m_code(code) + , m_message(message) + { + } + + ErrorCode m_code; + String m_message; +}; + +} // namespace WebCore + +#endif // ENABLE(CLIENT_BASED_GEOLOCATION) + +#endif // GeolocationError_h diff --git a/src/3rdparty/webkit/WebCore/page/GeolocationPosition.h b/src/3rdparty/webkit/WebCore/page/GeolocationPosition.h new file mode 100644 index 0000000..9f25b11 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/GeolocationPosition.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationPosition_h +#define GeolocationPosition_h + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class GeolocationPosition : public RefCounted<GeolocationPosition> { +public: + static PassRefPtr<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy) { return adoptRef(new GeolocationPosition(timestamp, latitude, longitude, accuracy)); } + + static PassRefPtr<GeolocationPosition> create(double timestamp, double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(new GeolocationPosition(timestamp, latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed)); } + + double timestamp() const { return m_timestamp; } + + double latitude() const { return m_latitude; } + double longitude() const { return m_longitude; } + double accuracy() const { return m_accuracy; } + double altitude() const { return m_altitude; } + double altitudeAccuracy() const { return m_altitudeAccuracy; } + double heading() const { return m_heading; } + double speed() const { return m_speed; } + + bool canProvideAltitude() const { return m_canProvideAltitude; } + bool canProvideAltitudeAccuracy() const { return m_canProvideAltitudeAccuracy; } + bool canProvideHeading() const { return m_canProvideHeading; } + bool canProvideSpeed() const { return m_canProvideSpeed; } + +private: + GeolocationPosition(double timestamp, double latitude, double longitude, double accuracy) + : m_timestamp(timestamp) + , m_latitude(latitude) + , m_longitude(longitude) + , m_accuracy(accuracy) + , m_altitude(0) + , m_altitudeAccuracy(0) + , m_heading(0) + , m_speed(0) + , m_canProvideAltitude(false) + , m_canProvideAltitudeAccuracy(false) + , m_canProvideHeading(false) + , m_canProvideSpeed(false) + { + } + + GeolocationPosition(double timestamp, double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) + : m_timestamp(timestamp) + , m_latitude(latitude) + , m_longitude(longitude) + , m_accuracy(accuracy) + , m_altitude(altitude) + , m_altitudeAccuracy(altitudeAccuracy) + , m_heading(heading) + , m_speed(speed) + , m_canProvideAltitude(providesAltitude) + , m_canProvideAltitudeAccuracy(providesAltitudeAccuracy) + , m_canProvideHeading(providesHeading) + , m_canProvideSpeed(providesSpeed) + { + } + + double m_timestamp; + + double m_latitude; + double m_longitude; + double m_accuracy; + double m_altitude; + double m_altitudeAccuracy; + double m_heading; + double m_speed; + + bool m_canProvideAltitude; + bool m_canProvideAltitudeAccuracy; + bool m_canProvideHeading; + bool m_canProvideSpeed; +}; + +} // namespace WebCore + +#endif // ENABLE(CLIENT_BASED_GEOLOCATION) + +#endif // GeolocationPosition_h diff --git a/src/3rdparty/webkit/WebCore/page/GeolocationPositionCache.cpp b/src/3rdparty/webkit/WebCore/page/GeolocationPositionCache.cpp new file mode 100644 index 0000000..06159f4 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/GeolocationPositionCache.cpp @@ -0,0 +1,178 @@ +/* + * Copyright 2010, 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 THE COPYRIGHT OWNER 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 "GeolocationPositionCache.h" + +#if ENABLE(GEOLOCATION) + +#include "Geoposition.h" +#include "SQLValue.h" +#include "SQLiteDatabase.h" +#include "SQLiteFileSystem.h" +#include "SQLiteStatement.h" +#include "SQLiteTransaction.h" + +namespace WebCore { + +static const char* databaseName = "CachedGeoposition.db"; + +int GeolocationPositionCache::s_instances = 0; +RefPtr<Geoposition>* GeolocationPositionCache::s_cachedPosition; +String* GeolocationPositionCache::s_databaseFile = 0; + +GeolocationPositionCache::GeolocationPositionCache() +{ + if (!(s_instances++)) { + s_cachedPosition = new RefPtr<Geoposition>; + *s_cachedPosition = readFromDB(); + } +} + +GeolocationPositionCache::~GeolocationPositionCache() +{ + if (!(--s_instances)) { + if (*s_cachedPosition) + writeToDB(s_cachedPosition->get()); + delete s_cachedPosition; + } +} + +void GeolocationPositionCache::setCachedPosition(Geoposition* cachedPosition) +{ + *s_cachedPosition = cachedPosition; +} + +Geoposition* GeolocationPositionCache::cachedPosition() +{ + return s_cachedPosition->get(); +} + +void GeolocationPositionCache::setDatabasePath(const String& databasePath) +{ + if (!s_databaseFile) + s_databaseFile = new String; + *s_databaseFile = SQLiteFileSystem::appendDatabaseFileNameToPath(databasePath, databaseName); + // If we don't have have a cached position, attempt to read one from the + // DB at the new path. + if (s_instances && !(*s_cachedPosition)) + *s_cachedPosition = readFromDB(); +} + +PassRefPtr<Geoposition> GeolocationPositionCache::readFromDB() +{ + SQLiteDatabase database; + if (!s_databaseFile || !database.open(*s_databaseFile)) + return 0; + + // Create the table here, such that even if we've just created the + // DB, the commands below should succeed. + if (!database.executeCommand("CREATE TABLE IF NOT EXISTS CachedPosition (" + "latitude REAL NOT NULL, " + "longitude REAL NOT NULL, " + "altitude REAL, " + "accuracy REAL NOT NULL, " + "altitudeAccuracy REAL, " + "heading REAL, " + "speed REAL, " + "timestamp INTEGER NOT NULL)")) + return 0; + + SQLiteStatement statement(database, "SELECT * FROM CachedPosition"); + if (statement.prepare() != SQLResultOk) + return 0; + + if (statement.step() != SQLResultRow) + return 0; + + bool providesAltitude = statement.getColumnValue(2).type() != SQLValue::NullValue; + bool providesAltitudeAccuracy = statement.getColumnValue(4).type() != SQLValue::NullValue; + bool providesHeading = statement.getColumnValue(5).type() != SQLValue::NullValue; + bool providesSpeed = statement.getColumnValue(6).type() != SQLValue::NullValue; + RefPtr<Coordinates> coordinates = Coordinates::create(statement.getColumnDouble(0), // latitude + statement.getColumnDouble(1), // longitude + providesAltitude, statement.getColumnDouble(2), // altitude + statement.getColumnDouble(3), // accuracy + providesAltitudeAccuracy, statement.getColumnDouble(4), // altitudeAccuracy + providesHeading, statement.getColumnDouble(5), // heading + providesSpeed, statement.getColumnDouble(6)); // speed + return Geoposition::create(coordinates.release(), statement.getColumnInt64(7)); // timestamp +} + +void GeolocationPositionCache::writeToDB(const Geoposition* position) +{ + ASSERT(position); + + SQLiteDatabase database; + if (!s_databaseFile || !database.open(*s_databaseFile)) + return; + + SQLiteTransaction transaction(database); + + if (!database.executeCommand("DELETE FROM CachedPosition")) + return; + + SQLiteStatement statement(database, "INSERT INTO CachedPosition (" + "latitude, " + "longitude, " + "altitude, " + "accuracy, " + "altitudeAccuracy, " + "heading, " + "speed, " + "timestamp) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); + if (statement.prepare() != SQLResultOk) + return; + + statement.bindDouble(1, position->coords()->latitude()); + statement.bindDouble(2, position->coords()->longitude()); + if (position->coords()->canProvideAltitude()) + statement.bindDouble(3, position->coords()->altitude()); + else + statement.bindNull(3); + statement.bindDouble(4, position->coords()->accuracy()); + if (position->coords()->canProvideAltitudeAccuracy()) + statement.bindDouble(5, position->coords()->altitudeAccuracy()); + else + statement.bindNull(5); + if (position->coords()->canProvideHeading()) + statement.bindDouble(6, position->coords()->heading()); + else + statement.bindNull(6); + if (position->coords()->canProvideSpeed()) + statement.bindDouble(7, position->coords()->speed()); + else + statement.bindNull(7); + statement.bindInt64(8, position->timestamp()); + if (!statement.executeCommand()) + return; + + transaction.commit(); +} + +} // namespace WebCore + +#endif // ENABLE(GEOLOCATION) diff --git a/src/3rdparty/webkit/WebCore/page/GeolocationPositionCache.h b/src/3rdparty/webkit/WebCore/page/GeolocationPositionCache.h new file mode 100644 index 0000000..c7f7e49 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/GeolocationPositionCache.h @@ -0,0 +1,58 @@ +/* + * Copyright 2010, 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 THE COPYRIGHT OWNER 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 GeolocationPositionCache_h +#define GeolocationPositionCache_h + +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + + +namespace WebCore { + +class Geoposition; +class String; + +class GeolocationPositionCache { + public: + GeolocationPositionCache(); + ~GeolocationPositionCache(); + + void setCachedPosition(Geoposition*); + Geoposition* cachedPosition(); + static void setDatabasePath(const String&); + + private: + static PassRefPtr<Geoposition> readFromDB(); + static void writeToDB(const Geoposition*); + + static int s_instances; + static RefPtr<Geoposition>* s_cachedPosition; + static String* s_databaseFile; +}; + +} // namespace WebCore + +#endif // GeolocationPositionCache_h diff --git a/src/3rdparty/webkit/WebCore/page/Geoposition.h b/src/3rdparty/webkit/WebCore/page/Geoposition.h index f3c703b..8b215b1 100644 --- a/src/3rdparty/webkit/WebCore/page/Geoposition.h +++ b/src/3rdparty/webkit/WebCore/page/Geoposition.h @@ -37,8 +37,11 @@ typedef int ExceptionCode; class Geoposition : public RefCounted<Geoposition> { public: - static PassRefPtr<Geoposition> create(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp) { return adoptRef(new Geoposition(coordinates, timestamp)); } - + static PassRefPtr<Geoposition> create(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp) + { + return adoptRef(new Geoposition(coordinates, timestamp)); + } + DOMTimeStamp timestamp() const { return m_timestamp; } Coordinates* coords() const { return m_coordinates.get(); } diff --git a/src/3rdparty/webkit/WebCore/page/Geoposition.idl b/src/3rdparty/webkit/WebCore/page/Geoposition.idl index 3ec8b0b..41a2262 100644 --- a/src/3rdparty/webkit/WebCore/page/Geoposition.idl +++ b/src/3rdparty/webkit/WebCore/page/Geoposition.idl @@ -25,7 +25,7 @@ module core { - interface Geoposition { + interface [Conditional=GEOLOCATION, OmitConstructor] Geoposition { readonly attribute Coordinates coords; readonly attribute DOMTimeStamp timestamp; }; diff --git a/src/3rdparty/webkit/WebCore/page/HaltablePlugin.h b/src/3rdparty/webkit/WebCore/page/HaltablePlugin.h index a5fe0f4..0f4aa41 100644 --- a/src/3rdparty/webkit/WebCore/page/HaltablePlugin.h +++ b/src/3rdparty/webkit/WebCore/page/HaltablePlugin.h @@ -37,6 +37,8 @@ public: virtual void halt() = 0; virtual void restart() = 0; virtual Node* node() const = 0; + virtual bool isWindowed() const = 0; + virtual String pluginName() const = 0; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/History.cpp b/src/3rdparty/webkit/WebCore/page/History.cpp index 9a27f1c..78e8ea6 100644 --- a/src/3rdparty/webkit/WebCore/page/History.cpp +++ b/src/3rdparty/webkit/WebCore/page/History.cpp @@ -26,8 +26,12 @@ #include "config.h" #include "History.h" +#include "ExceptionCode.h" #include "Frame.h" #include "FrameLoader.h" +#include "FrameLoaderClient.h" +#include "HistoryItem.h" +#include "Page.h" namespace WebCore { @@ -76,4 +80,45 @@ void History::go(int distance) m_frame->redirectScheduler()->scheduleHistoryNavigation(distance); } +KURL History::urlForState(const String& urlString) +{ + KURL baseURL = m_frame->loader()->baseURL(); + if (urlString.isEmpty()) + return baseURL; + + KURL absoluteURL(baseURL, urlString); + if (!absoluteURL.isValid()) + return KURL(); + + if (absoluteURL.string().left(absoluteURL.pathStart()) != baseURL.string().left(baseURL.pathStart())) + return KURL(); + + return absoluteURL; +} + +void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const String& title, const String& urlString, StateObjectType stateObjectType, ExceptionCode& ec) +{ + if (!m_frame || !m_frame->page()) + return; + + KURL fullURL = urlForState(urlString); + if (!fullURL.isValid()) { + ec = SECURITY_ERR; + return; + } + + if (stateObjectType == StateObjectPush) + m_frame->loader()->history()->pushState(data, title, fullURL.string()); + else if (stateObjectType == StateObjectReplace) + m_frame->loader()->history()->replaceState(data, title, fullURL.string()); + + if (!urlString.isEmpty()) + m_frame->document()->updateURLForPushOrReplaceState(fullURL); + + if (stateObjectType == StateObjectPush) + m_frame->loader()->client()->dispatchDidPushStateWithinPage(); + else if (stateObjectType == StateObjectReplace) + m_frame->loader()->client()->dispatchDidReplaceStateWithinPage(); +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/History.h b/src/3rdparty/webkit/WebCore/page/History.h index f0df2de..66a6a03 100644 --- a/src/3rdparty/webkit/WebCore/page/History.h +++ b/src/3rdparty/webkit/WebCore/page/History.h @@ -26,30 +26,42 @@ #ifndef History_h #define History_h +#include "KURL.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { - class Frame; +class Frame; +class SerializedScriptValue; +class String; +typedef int ExceptionCode; - class History : public RefCounted<History> { - public: - static PassRefPtr<History> create(Frame* frame) { return adoptRef(new History(frame)); } - - Frame* frame() const; - void disconnectFrame(); +class History : public RefCounted<History> { +public: + static PassRefPtr<History> create(Frame* frame) { return adoptRef(new History(frame)); } + + Frame* frame() const; + void disconnectFrame(); - unsigned length() const; - void back(); - void forward(); - void go(int distance); + unsigned length() const; + void back(); + void forward(); + void go(int distance); - private: - History(Frame*); - - Frame* m_frame; + enum StateObjectType { + StateObjectPush, + StateObjectReplace }; + void stateObjectAdded(PassRefPtr<SerializedScriptValue>, const String& title, const String& url, StateObjectType, ExceptionCode&); + +private: + History(Frame*); + + KURL urlForState(const String& url); + + Frame* m_frame; +}; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/History.idl b/src/3rdparty/webkit/WebCore/page/History.idl index 914d441..d1be5ae 100644 --- a/src/3rdparty/webkit/WebCore/page/History.idl +++ b/src/3rdparty/webkit/WebCore/page/History.idl @@ -32,13 +32,19 @@ module window { DelegatingGetOwnPropertySlot, DelegatingPutFunction, CustomDeleteProperty, - CustomGetPropertyNames + CustomGetPropertyNames, + OmitConstructor ] History { readonly attribute unsigned long length; [DoNotCheckDomainSecurity] void back(); [DoNotCheckDomainSecurity] void forward(); [DoNotCheckDomainSecurity] void go(in long distance); + + [Custom, EnabledAtRuntime] void pushState(in any data, in DOMString title, in optional DOMString url) + raises(DOMException); + [Custom, EnabledAtRuntime] void replaceState(in any data, in DOMString title, in optional DOMString url) + raises(DOMException); }; } diff --git a/src/3rdparty/webkit/WebCore/page/Location.idl b/src/3rdparty/webkit/WebCore/page/Location.idl index 7d680f2..b020267 100644 --- a/src/3rdparty/webkit/WebCore/page/Location.idl +++ b/src/3rdparty/webkit/WebCore/page/Location.idl @@ -38,7 +38,8 @@ module window { CustomGetPropertyNames, CustomDefineGetter, DelegatingPrototypePutFunction, - CustomPrototypeDefineGetter + CustomPrototypeDefineGetter, + OmitConstructor ] Location { attribute [DoNotCheckDomainSecurityOnSet, CustomSetter, V8DisallowShadowing] DOMString href; diff --git a/src/3rdparty/webkit/WebCore/page/android/DragControllerAndroid.cpp b/src/3rdparty/webkit/WebCore/page/MediaCanStartListener.h index 19d02c6..317babf 100644 --- a/src/3rdparty/webkit/WebCore/page/android/DragControllerAndroid.cpp +++ b/src/3rdparty/webkit/WebCore/page/MediaCanStartListener.h @@ -1,6 +1,5 @@ /* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -11,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,35 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "DragController.h" - -#include "DragData.h" -#include "NotImplemented.h" +#ifndef MediaCanStartListener_h +#define MediaCanStartListener_h namespace WebCore { -bool DragController::isCopyKeyDown() -{ - return false; -} - -DragOperation DragController::dragOperation(DragData* dragData) -{ - // FIXME: This logic is incomplete - notImplemented(); - if (dragData->containsURL()) - return DragOperationCopy; - - return DragOperationNone; -} +class MediaCanStartListener { +public: + virtual void mediaCanStart() = 0; +protected: + virtual ~MediaCanStartListener() { } +}; -const float DragController::DragImageAlpha = 1.0f; -static IntSize dummy; -const IntSize& DragController::maxDragImageSize() { return dummy; } -const int DragController::DragIconRightInset = 0; -const int DragController::DragIconBottomInset = 0; -const int DragController::LinkDragBorderInset = 0; -const int DragController::MaxOriginalImageArea = 0; +} -} // namespace WebCore +#endif diff --git a/src/3rdparty/webkit/WebCore/page/MouseEventWithHitTestResults.h b/src/3rdparty/webkit/WebCore/page/MouseEventWithHitTestResults.h index 7330d93..8c28574 100644 --- a/src/3rdparty/webkit/WebCore/page/MouseEventWithHitTestResults.h +++ b/src/3rdparty/webkit/WebCore/page/MouseEventWithHitTestResults.h @@ -1,4 +1,4 @@ -/* This file is part of the KDE project +/* Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> Copyright (C) 2006 Apple Computer, Inc. diff --git a/src/3rdparty/webkit/WebCore/page/Navigator.cpp b/src/3rdparty/webkit/WebCore/page/Navigator.cpp index 4922860..7078454 100644 --- a/src/3rdparty/webkit/WebCore/page/Navigator.cpp +++ b/src/3rdparty/webkit/WebCore/page/Navigator.cpp @@ -23,11 +23,14 @@ #include "config.h" #include "Navigator.h" +#include "Chrome.h" #include "CookieJar.h" +#include "ExceptionCode.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClient.h" #include "Geolocation.h" +#include "KURL.h" #include "Language.h" #include "MimeTypeArray.h" #include "Page.h" @@ -169,4 +172,93 @@ void Navigator::getStorageUpdates() } #endif +static bool verifyCustomHandlerURL(const String& baseURL, const String& url, ExceptionCode& ec) +{ + // The specification requires that it is a SYNTAX_ERR if the the "%s" token is not present. + static const char token[] = "%s"; + int index = url.find(token); + if (-1 == index) { + ec = SYNTAX_ERR; + return false; + } + + // It is also a SYNTAX_ERR if the custom handler URL, as created by removing + // the "%s" token and prepending the base url, does not resolve. + String newURL = url; + newURL.remove(index, sizeof(token) / sizeof(token[0])); + + KURL base(ParsedURLString, baseURL); + KURL kurl(base, newURL); + + if (kurl.isEmpty() || !kurl.isValid()) { + ec = SYNTAX_ERR; + return false; + } + + return true; +} + +static bool verifyProtocolHandlerScheme(const String& scheme, ExceptionCode& ec) +{ + // It is a SECURITY_ERR for these schemes to be handled by a custom handler. + if (equalIgnoringCase(scheme, "http") || equalIgnoringCase(scheme, "https") || equalIgnoringCase(scheme, "file")) { + ec = SECURITY_ERR; + return false; + } + return true; +} + +void Navigator::registerProtocolHandler(const String& scheme, const String& url, const String& title, ExceptionCode& ec) +{ + if (!verifyProtocolHandlerScheme(scheme, ec)) + return; + + if (!m_frame) + return; + + Document* document = m_frame->document(); + if (!document) + return; + + String baseURL = document->baseURL().baseAsString(); + + if (!verifyCustomHandlerURL(baseURL, url, ec)) + return; + + if (Page* page = m_frame->page()) + page->chrome()->registerProtocolHandler(scheme, baseURL, url, m_frame->displayStringModifiedByEncoding(title)); +} + +static bool verifyProtocolHandlerMimeType(const String& type, ExceptionCode& ec) +{ + // It is a SECURITY_ERR for these mime types to be assigned to a custom + // handler. + if (equalIgnoringCase(type, "text/html") || equalIgnoringCase(type, "text/css") || equalIgnoringCase(type, "application/x-javascript")) { + ec = SECURITY_ERR; + return false; + } + return true; +} + +void Navigator::registerContentHandler(const String& mimeType, const String& url, const String& title, ExceptionCode& ec) +{ + if (!verifyProtocolHandlerMimeType(mimeType, ec)) + return; + + if (!m_frame) + return; + + Document* document = m_frame->document(); + if (!document) + return; + + String baseURL = document->baseURL().baseAsString(); + + if (!verifyCustomHandlerURL(baseURL, url, ec)) + return; + + if (Page* page = m_frame->page()) + page->chrome()->registerContentHandler(mimeType, baseURL, url, m_frame->displayStringModifiedByEncoding(title)); +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Navigator.h b/src/3rdparty/webkit/WebCore/page/Navigator.h index 4adebe1..107082b 100644 --- a/src/3rdparty/webkit/WebCore/page/Navigator.h +++ b/src/3rdparty/webkit/WebCore/page/Navigator.h @@ -34,6 +34,8 @@ namespace WebCore { class PluginArray; class String; + typedef int ExceptionCode; + class Navigator : public NavigatorBase, public RefCounted<Navigator> { public: static PassRefPtr<Navigator> create(Frame* frame) { return adoptRef(new Navigator(frame)); } @@ -60,6 +62,9 @@ namespace WebCore { void getStorageUpdates(); #endif + void registerProtocolHandler(const String& scheme, const String& url, const String& title, ExceptionCode& ec); + void registerContentHandler(const String& mimeType, const String& url, const String& title, ExceptionCode& ec); + private: Navigator(Frame*); Frame* m_frame; diff --git a/src/3rdparty/webkit/WebCore/page/Navigator.idl b/src/3rdparty/webkit/WebCore/page/Navigator.idl index 80ef4fb..257ede1 100644 --- a/src/3rdparty/webkit/WebCore/page/Navigator.idl +++ b/src/3rdparty/webkit/WebCore/page/Navigator.idl @@ -20,7 +20,8 @@ module window { interface [ - CustomMarkFunction + CustomMarkFunction, + OmitConstructor ] Navigator { readonly attribute DOMString appCodeName; readonly attribute DOMString appName; @@ -40,12 +41,17 @@ module window { readonly attribute boolean onLine; #if defined(ENABLE_GEOLOCATION) && ENABLE_GEOLOCATION - readonly attribute Geolocation geolocation; + readonly attribute [EnabledAtRuntime] Geolocation geolocation; #endif #if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE void getStorageUpdates(); #endif + + void registerProtocolHandler(in DOMString scheme, in DOMString url, in DOMString title) + raises(DomException); + void registerContentHandler(in DOMString mimeType, in DOMString url, in DOMString title) + raises(DomException); }; } diff --git a/src/3rdparty/webkit/WebCore/page/NavigatorBase.cpp b/src/3rdparty/webkit/WebCore/page/NavigatorBase.cpp index 5b0c5d4..ca51a29 100644 --- a/src/3rdparty/webkit/WebCore/page/NavigatorBase.cpp +++ b/src/3rdparty/webkit/WebCore/page/NavigatorBase.cpp @@ -29,19 +29,19 @@ #include "NetworkStateNotifier.h" #include "PlatformString.h" -#if PLATFORM(LINUX) +#if OS(LINUX) #include "sys/utsname.h" #include <wtf/StdLibExtras.h> #endif #ifndef WEBCORE_NAVIGATOR_PLATFORM -#if PLATFORM(MAC) && (PLATFORM(PPC) || PLATFORM(PPC64)) +#if OS(MAC_OS_X) && (CPU(PPC) || CPU(PPC64)) #define WEBCORE_NAVIGATOR_PLATFORM "MacPPC" -#elif PLATFORM(MAC) && (PLATFORM(X86) || PLATFORM(X86_64)) +#elif OS(MAC_OS_X) && (CPU(X86) || CPU(X86_64)) #define WEBCORE_NAVIGATOR_PLATFORM "MacIntel" -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) #define WEBCORE_NAVIGATOR_PLATFORM "Win32" -#elif PLATFORM(SYMBIAN) +#elif OS(SYMBIAN) #define WEBCORE_NAVIGATOR_PLATFORM "Symbian" #else #define WEBCORE_NAVIGATOR_PLATFORM "" @@ -85,7 +85,7 @@ String NavigatorBase::appVersion() const String NavigatorBase::platform() const { -#if PLATFORM(LINUX) +#if OS(LINUX) if (String("") != WEBCORE_NAVIGATOR_PLATFORM) return WEBCORE_NAVIGATOR_PLATFORM; struct utsname osname; diff --git a/src/3rdparty/webkit/WebCore/page/Page.cpp b/src/3rdparty/webkit/WebCore/page/Page.cpp index 8a685f4..d66e497 100644 --- a/src/3rdparty/webkit/WebCore/page/Page.cpp +++ b/src/3rdparty/webkit/WebCore/page/Page.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All Rights Reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or @@ -21,6 +21,7 @@ #include "config.h" #include "Page.h" +#include "BackForwardList.h" #include "Base64.h" #include "CSSStyleSelector.h" #include "Chrome.h" @@ -29,10 +30,10 @@ #include "ContextMenuController.h" #include "DOMWindow.h" #include "DragController.h" -#include "ExceptionCode.h" #include "EditorClient.h" -#include "EventNames.h" #include "Event.h" +#include "EventNames.h" +#include "ExceptionCode.h" #include "FileSystem.h" #include "FocusController.h" #include "Frame.h" @@ -45,17 +46,20 @@ #include "InspectorController.h" #include "InspectorTimelineAgent.h" #include "Logging.h" +#include "MediaCanStartListener.h" #include "Navigator.h" #include "NetworkStateNotifier.h" #include "PageGroup.h" #include "PluginData.h" #include "PluginHalter.h" +#include "PluginView.h" #include "ProgressTracker.h" -#include "RenderWidget.h" #include "RenderTheme.h" +#include "RenderWidget.h" #include "ScriptController.h" #include "SelectionController.h" #include "Settings.h" +#include "SharedBuffer.h" #include "StringHash.h" #include "TextResourceDecoder.h" #include "Widget.h" @@ -69,13 +73,17 @@ #endif #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "JavaScriptDebugServer.h" +#include "ScriptDebugServer.h" #endif #if ENABLE(WML) #include "WMLPageState.h" #endif +#if ENABLE(CLIENT_BASED_GEOLOCATION) +#include "GeolocationController.h" +#endif + namespace WebCore { static HashSet<Page*>* allPages; @@ -100,7 +108,7 @@ static void networkStateChanged() frames[i]->document()->dispatchWindowEvent(Event::create(eventName, false, false)); } -Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient, PluginHalterClient* pluginHalterClient) +Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient, PluginHalterClient* pluginHalterClient, GeolocationControllerClient* geolocationControllerClient) : m_chrome(new Chrome(this, chromeClient)) , m_dragCaretController(new SelectionController(0, true)) #if ENABLE(DRAG_SUPPORT) @@ -113,6 +121,9 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi #if ENABLE(INSPECTOR) , m_inspectorController(new InspectorController(this, inspectorClient)) #endif +#if ENABLE(CLIENT_BASED_GEOLOCATION) + , m_geolocationController(new GeolocationController(this, geolocationControllerClient)) +#endif , m_settings(new Settings(this)) , m_progress(new ProgressTracker) , m_backForwardList(BackForwardList::create(this)) @@ -127,16 +138,13 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi , m_areMemoryCacheClientCallsEnabled(true) , m_mediaVolume(1) , m_javaScriptURLsAreAllowed(true) -#if ENABLE(INSPECTOR) - , m_parentInspectorController(0) -#endif , m_didLoadUserStyleSheet(false) , m_userStyleSheetModificationTime(0) , m_group(0) , m_debugger(0) , m_customHTMLTokenizerTimeDelay(-1) , m_customHTMLTokenizerChunkSize(-1) - , m_canStartPlugins(true) + , m_canStartMedia(true) { #if !ENABLE(CONTEXT_MENUS) UNUSED_PARAM(contextMenuClient); @@ -147,6 +155,10 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi #if !ENABLE(INSPECTOR) UNUSED_PARAM(inspectorClient); #endif +#if !ENABLE(CLIENT_BASED_GEOLOCATION) + UNUSED_PARAM(geolocationControllerClient); +#endif + if (!allPages) { allPages = new HashSet<Page*>; @@ -162,7 +174,7 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi } #if ENABLE(JAVASCRIPT_DEBUGGER) - JavaScriptDebugServer::shared().pageCreated(this); + ScriptDebugServer::shared().pageCreated(this); #endif #ifndef NDEBUG @@ -181,8 +193,6 @@ Page::~Page() m_editorClient->pageDestroyed(); #if ENABLE(INSPECTOR) - if (m_parentInspectorController) - m_parentInspectorController->pageDestroyed(); m_inspectorController->inspectedPageDestroyed(); #endif @@ -277,26 +287,30 @@ void Page::goBackOrForward(int distance) void Page::goToItem(HistoryItem* item, FrameLoadType type) { - // Abort any current load if we're going to a history item - - // Define what to do with any open database connections. By default we stop them and terminate the database thread. - DatabasePolicy databasePolicy = DatabasePolicyStop; + // Abort any current load unless we're navigating the current document to a new state object + HistoryItem* currentItem = m_mainFrame->loader()->history()->currentItem(); + if (!item->stateObject() || !currentItem || item->documentSequenceNumber() != currentItem->documentSequenceNumber() || item == currentItem) { + // Define what to do with any open database connections. By default we stop them and terminate the database thread. + DatabasePolicy databasePolicy = DatabasePolicyStop; #if ENABLE(DATABASE) - // If we're navigating the history via a fragment on the same document, then we do not want to stop databases. - const KURL& currentURL = m_mainFrame->loader()->url(); - const KURL& newURL = item->url(); - - if (newURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(currentURL, newURL)) - databasePolicy = DatabasePolicyContinue; + // If we're navigating the history via a fragment on the same document, then we do not want to stop databases. + const KURL& currentURL = m_mainFrame->loader()->url(); + const KURL& newURL = item->url(); + + if (newURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(currentURL, newURL)) + databasePolicy = DatabasePolicyContinue; #endif - m_mainFrame->loader()->stopAllLoaders(databasePolicy); + + m_mainFrame->loader()->stopAllLoaders(databasePolicy); + } + m_mainFrame->loader()->history()->goToItem(item, type); } int Page::getHistoryLength() { - return m_backForwardList->backListCount() + 1; + return m_backForwardList->backListCount() + 1 + m_backForwardList->forwardListCount(); } void Page::setGlobalHistoryItem(HistoryItem* item) @@ -372,24 +386,44 @@ void Page::refreshPlugins(bool reload) PluginData* Page::pluginData() const { - if (!settings()->arePluginsEnabled()) + if (!mainFrame()->loader()->allowPlugins(NotAboutToInstantiatePlugin)) return 0; if (!m_pluginData) m_pluginData = PluginData::create(this); return m_pluginData.get(); } -void Page::addUnstartedPlugin(PluginView* view) +void Page::addMediaCanStartListener(MediaCanStartListener* listener) { - ASSERT(!m_canStartPlugins); - m_unstartedPlugins.add(view); + ASSERT(!m_canStartMedia); + ASSERT(!m_mediaCanStartListeners.contains(listener)); + m_mediaCanStartListeners.add(listener); } -void Page::removeUnstartedPlugin(PluginView* view) +void Page::removeMediaCanStartListener(MediaCanStartListener* listener) { - ASSERT(!m_canStartPlugins); - ASSERT(m_unstartedPlugins.contains(view)); - m_unstartedPlugins.remove(view); + ASSERT(!m_canStartMedia); + ASSERT(m_mediaCanStartListeners.contains(listener)); + m_mediaCanStartListeners.remove(listener); +} + +void Page::setCanStartMedia(bool canStartMedia) +{ + if (m_canStartMedia == canStartMedia) + return; + + m_canStartMedia = canStartMedia; + + if (!m_canStartMedia || m_mediaCanStartListeners.isEmpty()) + return; + + Vector<MediaCanStartListener*> listeners; + copyToVector(m_mediaCanStartListeners, listeners); + m_mediaCanStartListeners.clear(); + + size_t size = listeners.size(); + for (size_t i = 0; i < size; ++i) + listeners[i]->mediaCanStart(); } static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag) @@ -463,6 +497,9 @@ const VisibleSelection& Page::selection() const void Page::setDefersLoading(bool defers) { + if (!m_settings->loadDeferringEnabled()) + return; + if (defers == m_defersLoading) return; @@ -542,7 +579,7 @@ void Page::userStyleSheetLocationChanged() Vector<char> styleSheetAsUTF8; if (base64Decode(encodedData, styleSheetAsUTF8)) - m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data()); + m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size()); } for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { @@ -667,7 +704,7 @@ void Page::setDebugger(JSC::Debugger* debugger) StorageNamespace* Page::sessionStorage(bool optionalCreate) { if (!m_sessionStorage && optionalCreate) - m_sessionStorage = StorageNamespace::sessionStorageNamespace(); + m_sessionStorage = StorageNamespace::sessionStorageNamespace(this); return m_sessionStorage.get(); } @@ -735,6 +772,35 @@ InspectorTimelineAgent* Page::inspectorTimelineAgent() const } #endif +void Page::privateBrowsingStateChanged() +{ + bool privateBrowsingEnabled = m_settings->privateBrowsingEnabled(); + + // Collect the PluginViews in to a vector to ensure that action the plug-in takes + // from below privateBrowsingStateChanged does not affect their lifetime. + + Vector<RefPtr<PluginView>, 32> pluginViews; + for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { + FrameView* view = frame->view(); + if (!view) + return; + + const HashSet<RefPtr<Widget> >* children = view->children(); + ASSERT(children); + + HashSet<RefPtr<Widget> >::const_iterator end = children->end(); + for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) { + Widget* widget = (*it).get(); + if (!widget->isPluginView()) + continue; + pluginViews.append(static_cast<PluginView*>(widget)); + } + } + + for (size_t i = 0; i < pluginViews.size(); i++) + pluginViews[i]->privateBrowsingStateChanged(privateBrowsingEnabled); +} + void Page::pluginAllowedRunTimeChanged() { if (m_pluginHalter) @@ -753,4 +819,16 @@ void Page::didStopPlugin(HaltablePlugin* obj) m_pluginHalter->didStopPlugin(obj); } +#if !ASSERT_DISABLED +void Page::checkFrameCountConsistency() const +{ + ASSERT(m_frameCount >= 0); + + int frameCount = 0; + for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) + ++frameCount; + + ASSERT(m_frameCount + 1 == frameCount); +} +#endif } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Page.h b/src/3rdparty/webkit/WebCore/page/Page.h index 4886464..94e6dd5 100644 --- a/src/3rdparty/webkit/WebCore/page/Page.h +++ b/src/3rdparty/webkit/WebCore/page/Page.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or @@ -21,29 +21,23 @@ #ifndef Page_h #define Page_h -#include "BackForwardList.h" -#include "Chrome.h" -#include "ContextMenuController.h" #include "FrameLoaderTypes.h" -#include "LinkHash.h" #include "PlatformString.h" +#include <wtf/Forward.h> #include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> +#include <wtf/Noncopyable.h> #if PLATFORM(MAC) #include "SchedulePair.h" #endif -#if PLATFORM(WIN) || (PLATFORM(WX) && PLATFORM(WIN_OS)) || (PLATFORM(QT) && defined(Q_WS_WIN)) -typedef struct HINSTANCE__* HINSTANCE; -#endif - namespace JSC { class Debugger; } namespace WebCore { + class BackForwardList; class Chrome; class ChromeClient; class ContextMenuClient; @@ -54,30 +48,36 @@ namespace WebCore { class EditorClient; class FocusController; class Frame; + class GeolocationController; + class GeolocationControllerClient; class HaltablePlugin; + class HistoryItem; class InspectorClient; class InspectorController; class InspectorTimelineAgent; + class MediaCanStartListener; class Node; class PageGroup; class PluginData; class PluginHalter; class PluginHalterClient; - class PluginView; class ProgressTracker; class RenderTheme; class VisibleSelection; class SelectionController; class Settings; + #if ENABLE(DOM_STORAGE) class StorageNamespace; #endif -#if ENABLE(WML) - class WMLPageState; -#endif #if ENABLE(NOTIFICATIONS) class NotificationPresenter; #endif +#if ENABLE(WML) + class WMLPageState; +#endif + + typedef uint64_t LinkHash; enum FindDirection { FindDirectionForward, FindDirectionBackward }; @@ -85,7 +85,7 @@ namespace WebCore { public: static void setNeedsReapplyStyles(); - Page(ChromeClient*, ContextMenuClient*, EditorClient*, DragClient*, InspectorClient*, PluginHalterClient*); + Page(ChromeClient*, ContextMenuClient*, EditorClient*, DragClient*, InspectorClient*, PluginHalterClient*, GeolocationControllerClient*); ~Page(); RenderTheme* theme() const { return m_theme.get(); }; @@ -93,10 +93,10 @@ namespace WebCore { static void refreshPlugins(bool reload); PluginData* pluginData() const; - void setCanStartPlugins(bool); - bool canStartPlugins() const { return m_canStartPlugins; } - void addUnstartedPlugin(PluginView*); - void removeUnstartedPlugin(PluginView*); + void setCanStartMedia(bool); + bool canStartMedia() const { return m_canStartMedia; } + void addMediaCanStartListener(MediaCanStartListener*); + void removeMediaCanStartListener(MediaCanStartListener*); EditorClient* editorClient() const { return m_editorClient; } @@ -129,8 +129,8 @@ namespace WebCore { PageGroup* groupPtr() { return m_group; } // can return 0 void incrementFrameCount() { ++m_frameCount; } - void decrementFrameCount() { --m_frameCount; } - int frameCount() const { return m_frameCount; } + void decrementFrameCount() { ASSERT(m_frameCount); --m_frameCount; } + int frameCount() const { checkFrameCountConsistency(); return m_frameCount; } Chrome* chrome() const { return m_chrome.get(); } SelectionController* dragCaretController() const { return m_dragCaretController.get(); } @@ -144,13 +144,11 @@ namespace WebCore { #if ENABLE(INSPECTOR) InspectorController* inspectorController() const { return m_inspectorController.get(); } #endif +#if ENABLE(CLIENT_BASED_GEOLOCATION) + GeolocationController* geolocationController() const { return m_geolocationController.get(); } +#endif Settings* settings() const { return m_settings.get(); } ProgressTracker* progress() const { return m_progress.get(); } - -#if ENABLE(INSPECTOR) - void setParentInspectorController(InspectorController* controller) { m_parentInspectorController = controller; } - InspectorController* parentInspectorController() const { return m_parentInspectorController; } -#endif void setTabKeyCyclesThroughElements(bool b) { m_tabKeyCyclesThroughElements = b; } bool tabKeyCyclesThroughElements() const { return m_tabKeyCyclesThroughElements; } @@ -190,6 +188,8 @@ namespace WebCore { void userStyleSheetLocationChanged(); const String& userStyleSheet() const; + void privateBrowsingStateChanged(); + void didStartPlugin(HaltablePlugin*); void didStopPlugin(HaltablePlugin*); void pluginAllowedRunTimeChanged(); @@ -198,12 +198,6 @@ namespace WebCore { void setDebugger(JSC::Debugger*); JSC::Debugger* debugger() const { return m_debugger; } -#if PLATFORM(WIN) || (PLATFORM(WX) && PLATFORM(WIN_OS)) || (PLATFORM(QT) && defined(Q_WS_WIN)) - // The global DLL or application instance used for all windows. - static void setInstanceHandle(HINSTANCE instanceHandle) { s_instanceHandle = instanceHandle; } - static HINSTANCE instanceHandle() { return s_instanceHandle; } -#endif - static void removeAllVisitedLinks(); static void allVisitedStateChanged(PageGroup*); @@ -238,6 +232,12 @@ namespace WebCore { private: void initGroup(); +#if ASSERT_DISABLED + void checkFrameCountConsistency() const { } +#else + void checkFrameCountConsistency() const; +#endif + OwnPtr<Chrome> m_chrome; OwnPtr<SelectionController> m_dragCaretController; #if ENABLE(DRAG_SUPPORT) @@ -250,6 +250,9 @@ namespace WebCore { #if ENABLE(INSPECTOR) OwnPtr<InspectorController> m_inspectorController; #endif +#if ENABLE(CLIENT_BASED_GEOLOCATION) + OwnPtr<GeolocationController> m_geolocationController; +#endif OwnPtr<Settings> m_settings; OwnPtr<ProgressTracker> m_progress; @@ -278,10 +281,6 @@ namespace WebCore { bool m_javaScriptURLsAreAllowed; -#if ENABLE(INSPECTOR) - InspectorController* m_parentInspectorController; -#endif - String m_userStyleSheetPath; mutable String m_userStyleSheet; mutable bool m_didLoadUserStyleSheet; @@ -295,8 +294,8 @@ namespace WebCore { double m_customHTMLTokenizerTimeDelay; int m_customHTMLTokenizerChunkSize; - bool m_canStartPlugins; - HashSet<PluginView*> m_unstartedPlugins; + bool m_canStartMedia; + HashSet<MediaCanStartListener*> m_mediaCanStartListeners; OwnPtr<PluginHalter> m_pluginHalter; @@ -304,10 +303,6 @@ namespace WebCore { RefPtr<StorageNamespace> m_sessionStorage; #endif -#if PLATFORM(WIN) || (PLATFORM(WX) && defined(__WXMSW__)) || (PLATFORM(QT) && defined(Q_WS_WIN)) - static HINSTANCE s_instanceHandle; -#endif - #if ENABLE(WML) OwnPtr<WMLPageState> m_wmlPageState; #endif diff --git a/src/3rdparty/webkit/WebCore/page/PageGroup.cpp b/src/3rdparty/webkit/WebCore/page/PageGroup.cpp index 427c240..f376d52 100644 --- a/src/3rdparty/webkit/WebCore/page/PageGroup.cpp +++ b/src/3rdparty/webkit/WebCore/page/PageGroup.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "PageGroup.h" +#include "Chrome.h" #include "ChromeClient.h" #include "Document.h" #include "Frame.h" @@ -50,7 +51,7 @@ static unsigned getUniqueIdentifier() // -------- -static bool shouldTrackVisitedLinks; +static bool shouldTrackVisitedLinks = false; PageGroup::PageGroup(const String& name) : m_name(name) @@ -200,29 +201,29 @@ StorageNamespace* PageGroup::localStorage() } #endif -void PageGroup::addUserScriptToWorld(unsigned worldID, const String& source, const KURL& url, PassOwnPtr<Vector<String> > whitelist, +void PageGroup::addUserScriptToWorld(DOMWrapperWorld* world, const String& source, const KURL& url, PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist, UserScriptInjectionTime injectionTime) { - if (worldID == UINT_MAX) - return; - OwnPtr<UserScript> userScript(new UserScript(source, url, whitelist, blacklist, worldID, injectionTime)); + ASSERT_ARG(world, world); + + OwnPtr<UserScript> userScript(new UserScript(source, url, whitelist, blacklist, injectionTime)); if (!m_userScripts) m_userScripts.set(new UserScriptMap); - UserScriptVector*& scriptsInWorld = m_userScripts->add(worldID, 0).first->second; + UserScriptVector*& scriptsInWorld = m_userScripts->add(world, 0).first->second; if (!scriptsInWorld) scriptsInWorld = new UserScriptVector; scriptsInWorld->append(userScript.release()); } -void PageGroup::addUserStyleSheetToWorld(unsigned worldID, const String& source, const KURL& url, PassOwnPtr<Vector<String> > whitelist, +void PageGroup::addUserStyleSheetToWorld(DOMWrapperWorld* world, const String& source, const KURL& url, PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist) { - if (worldID == UINT_MAX) - return; - OwnPtr<UserStyleSheet> userStyleSheet(new UserStyleSheet(source, url, whitelist, blacklist, worldID)); + ASSERT_ARG(world, world); + + OwnPtr<UserStyleSheet> userStyleSheet(new UserStyleSheet(source, url, whitelist, blacklist)); if (!m_userStyleSheets) m_userStyleSheets.set(new UserStyleSheetMap); - UserStyleSheetVector*& styleSheetsInWorld = m_userStyleSheets->add(worldID, 0).first->second; + UserStyleSheetVector*& styleSheetsInWorld = m_userStyleSheets->add(world, 0).first->second; if (!styleSheetsInWorld) styleSheetsInWorld = new UserStyleSheetVector; styleSheetsInWorld->append(userStyleSheet.release()); @@ -235,12 +236,14 @@ void PageGroup::addUserStyleSheetToWorld(unsigned worldID, const String& source, } } -void PageGroup::removeUserScriptFromWorld(unsigned worldID, const KURL& url) +void PageGroup::removeUserScriptFromWorld(DOMWrapperWorld* world, const KURL& url) { + ASSERT_ARG(world, world); + if (!m_userScripts) return; - UserScriptMap::iterator it = m_userScripts->find(worldID); + UserScriptMap::iterator it = m_userScripts->find(world); if (it == m_userScripts->end()) return; @@ -257,12 +260,14 @@ void PageGroup::removeUserScriptFromWorld(unsigned worldID, const KURL& url) m_userScripts->remove(it); } -void PageGroup::removeUserStyleSheetFromWorld(unsigned worldID, const KURL& url) +void PageGroup::removeUserStyleSheetFromWorld(DOMWrapperWorld* world, const KURL& url) { + ASSERT_ARG(world, world); + if (!m_userStyleSheets) return; - UserStyleSheetMap::iterator it = m_userStyleSheets->find(worldID); + UserStyleSheetMap::iterator it = m_userStyleSheets->find(world); bool sheetsChanged = false; if (it == m_userStyleSheets->end()) return; @@ -291,12 +296,14 @@ void PageGroup::removeUserStyleSheetFromWorld(unsigned worldID, const KURL& url) } } -void PageGroup::removeUserScriptsFromWorld(unsigned worldID) +void PageGroup::removeUserScriptsFromWorld(DOMWrapperWorld* world) { + ASSERT_ARG(world, world); + if (!m_userScripts) return; - UserScriptMap::iterator it = m_userScripts->find(worldID); + UserScriptMap::iterator it = m_userScripts->find(world); if (it == m_userScripts->end()) return; @@ -304,12 +311,14 @@ void PageGroup::removeUserScriptsFromWorld(unsigned worldID) m_userScripts->remove(it); } -void PageGroup::removeUserStyleSheetsFromWorld(unsigned worldID) +void PageGroup::removeUserStyleSheetsFromWorld(DOMWrapperWorld* world) { + ASSERT_ARG(world, world); + if (!m_userStyleSheets) return; - UserStyleSheetMap::iterator it = m_userStyleSheets->find(worldID); + UserStyleSheetMap::iterator it = m_userStyleSheets->find(world); if (it == m_userStyleSheets->end()) return; diff --git a/src/3rdparty/webkit/WebCore/page/PageGroup.h b/src/3rdparty/webkit/WebCore/page/PageGroup.h index c233cd1..446f0c7 100644 --- a/src/3rdparty/webkit/WebCore/page/PageGroup.h +++ b/src/3rdparty/webkit/WebCore/page/PageGroup.h @@ -70,17 +70,17 @@ namespace WebCore { bool hasLocalStorage() { return m_localStorage; } #endif - void addUserScriptToWorld(unsigned worldID, const String& source, const KURL&, + void addUserScriptToWorld(DOMWrapperWorld*, const String& source, const KURL&, PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist, UserScriptInjectionTime); - void addUserStyleSheetToWorld(unsigned worldID, const String& source, const KURL&, + void addUserStyleSheetToWorld(DOMWrapperWorld*, const String& source, const KURL&, PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist); - void removeUserScriptFromWorld(unsigned, const KURL&); - void removeUserStyleSheetFromWorld(unsigned, const KURL&); + void removeUserScriptFromWorld(DOMWrapperWorld*, const KURL&); + void removeUserStyleSheetFromWorld(DOMWrapperWorld*, const KURL&); - void removeUserScriptsFromWorld(unsigned); - void removeUserStyleSheetsFromWorld(unsigned); + void removeUserScriptsFromWorld(DOMWrapperWorld*); + void removeUserStyleSheetsFromWorld(DOMWrapperWorld*); void removeAllUserContent(); diff --git a/src/3rdparty/webkit/WebCore/page/PluginHalter.cpp b/src/3rdparty/webkit/WebCore/page/PluginHalter.cpp index 63f5469..c0a6452 100644 --- a/src/3rdparty/webkit/WebCore/page/PluginHalter.cpp +++ b/src/3rdparty/webkit/WebCore/page/PluginHalter.cpp @@ -28,6 +28,7 @@ #include "PluginHalter.h" #include "HaltablePlugin.h" +#include "PlatformString.h" #include <wtf/CurrentTime.h> #include <wtf/Vector.h> @@ -93,7 +94,7 @@ void PluginHalter::timerFired(Timer<PluginHalter>*) continue; } - if (m_client->shouldHaltPlugin(plugins[i]->node())) + if (m_client->shouldHaltPlugin(plugins[i]->node(), plugins[i]->isWindowed(), plugins[i]->pluginName())) plugins[i]->halt(); m_plugins.remove(plugins[i]); diff --git a/src/3rdparty/webkit/WebCore/page/PluginHalter.h b/src/3rdparty/webkit/WebCore/page/PluginHalter.h index eddce34..af8b31e 100644 --- a/src/3rdparty/webkit/WebCore/page/PluginHalter.h +++ b/src/3rdparty/webkit/WebCore/page/PluginHalter.h @@ -35,7 +35,7 @@ namespace WebCore { class HaltablePlugin; -class PluginHalter { +class PluginHalter : public Noncopyable { public: PluginHalter(PluginHalterClient*); diff --git a/src/3rdparty/webkit/WebCore/page/PluginHalterClient.h b/src/3rdparty/webkit/WebCore/page/PluginHalterClient.h index f77091f..0251547 100644 --- a/src/3rdparty/webkit/WebCore/page/PluginHalterClient.h +++ b/src/3rdparty/webkit/WebCore/page/PluginHalterClient.h @@ -29,12 +29,13 @@ namespace WebCore { class Node; +class String; class PluginHalterClient { public: virtual ~PluginHalterClient() { } - virtual bool shouldHaltPlugin(Node*) const = 0; + virtual bool shouldHaltPlugin(Node*, bool isWindowed, const String& pluginName) const = 0; virtual bool enabled() const = 0; }; diff --git a/src/3rdparty/webkit/WebCore/page/PositionCallback.h b/src/3rdparty/webkit/WebCore/page/PositionCallback.h index 9f36d7a..5b7a202 100644 --- a/src/3rdparty/webkit/WebCore/page/PositionCallback.h +++ b/src/3rdparty/webkit/WebCore/page/PositionCallback.h @@ -26,7 +26,6 @@ #ifndef PositionCallback_h #define PositionCallback_h -#include <wtf/Platform.h> #include <wtf/RefCounted.h> namespace WebCore { diff --git a/src/3rdparty/webkit/WebCore/page/PositionError.h b/src/3rdparty/webkit/WebCore/page/PositionError.h index f6f56f0..1467170 100644 --- a/src/3rdparty/webkit/WebCore/page/PositionError.h +++ b/src/3rdparty/webkit/WebCore/page/PositionError.h @@ -35,7 +35,6 @@ namespace WebCore { class PositionError : public RefCounted<PositionError> { public: enum ErrorCode { - UNKNOWN_ERROR = 0, PERMISSION_DENIED = 1, POSITION_UNAVAILABLE = 2, TIMEOUT = 3 diff --git a/src/3rdparty/webkit/WebCore/page/PositionError.idl b/src/3rdparty/webkit/WebCore/page/PositionError.idl index cb2ef5e..5870e0d 100644 --- a/src/3rdparty/webkit/WebCore/page/PositionError.idl +++ b/src/3rdparty/webkit/WebCore/page/PositionError.idl @@ -25,13 +25,10 @@ module core { - interface [ - GenerateConstructor - ] PositionError { + interface [Conditional=GEOLOCATION] PositionError { readonly attribute unsigned short code; readonly attribute DOMString message; - const unsigned short UNKNOWN_ERROR = 0; const unsigned short PERMISSION_DENIED = 1; const unsigned short POSITION_UNAVAILABLE = 2; const unsigned short TIMEOUT = 3; diff --git a/src/3rdparty/webkit/WebCore/page/PositionErrorCallback.h b/src/3rdparty/webkit/WebCore/page/PositionErrorCallback.h index c23e883..e784297 100644 --- a/src/3rdparty/webkit/WebCore/page/PositionErrorCallback.h +++ b/src/3rdparty/webkit/WebCore/page/PositionErrorCallback.h @@ -26,7 +26,6 @@ #ifndef PositionErrorCallback_h #define PositionErrorCallback_h -#include <wtf/Platform.h> #include <wtf/RefCounted.h> namespace WebCore { diff --git a/src/3rdparty/webkit/WebCore/page/PrintContext.cpp b/src/3rdparty/webkit/WebCore/page/PrintContext.cpp index 4d3a839..b6806eb 100644 --- a/src/3rdparty/webkit/WebCore/page/PrintContext.cpp +++ b/src/3rdparty/webkit/WebCore/page/PrintContext.cpp @@ -45,6 +45,11 @@ int PrintContext::pageCount() const return m_pageRects.size(); } +const IntRect& PrintContext::pageRect(int pageNumber) const +{ + return m_pageRects[pageNumber]; +} + void PrintContext::computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight) { m_pageRects.clear(); @@ -60,11 +65,6 @@ void PrintContext::computePageRects(const FloatRect& printRect, float headerHeig return; } - if (userScaleFactor <= 0) { - LOG_ERROR("userScaleFactor has bad value %.2f", userScaleFactor); - return; - } - float ratio = printRect.height() / printRect.width(); float pageWidth = (float)root->rightLayoutOverflow(); @@ -77,14 +77,31 @@ void PrintContext::computePageRects(const FloatRect& printRect, float headerHeig return; } - float currPageHeight = pageHeight / userScaleFactor; + computePageRectsWithPageSize(FloatSize(pageWidth, pageHeight), userScaleFactor); +} + +void PrintContext::computePageRectsWithPageSize(const FloatSize& pageSizeInPixels, float userScaleFactor) +{ + RenderView* root = toRenderView(m_frame->document()->renderer()); + + if (!root) { + LOG_ERROR("document to be printed has no renderer"); + return; + } + + if (userScaleFactor <= 0) { + LOG_ERROR("userScaleFactor has bad value %.2f", userScaleFactor); + return; + } + + float currPageHeight = pageSizeInPixels.height() / userScaleFactor; float docHeight = root->layer()->height(); - float currPageWidth = pageWidth / userScaleFactor; + float currPageWidth = pageSizeInPixels.width() / userScaleFactor; // always return at least one page, since empty files should print a blank page - float printedPagesHeight = 0.0; + float printedPagesHeight = 0; do { - float proposedBottom = std::min(docHeight, printedPagesHeight + pageHeight); + float proposedBottom = std::min(docHeight, printedPagesHeight + pageSizeInPixels.height()); m_frame->view()->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight); currPageHeight = max(1.0f, proposedBottom - printedPagesHeight); @@ -134,4 +151,54 @@ void PrintContext::end() m_frame->setPrinting(false, 0, 0, true); } +static RenderBoxModelObject* enclosingBoxModelObject(RenderObject* object) +{ + + while (object && !object->isBoxModelObject()) + object = object->parent(); + if (!object) + return 0; + return toRenderBoxModelObject(object); +} + +int PrintContext::pageNumberForElement(Element* element, const FloatSize& pageSizeInPixels) +{ + // Make sure the element is not freed during the layout. + RefPtr<Element> elementRef(element); + element->document()->updateLayout(); + + RenderBoxModelObject* box = enclosingBoxModelObject(element->renderer()); + if (!box) + return -1; + + Frame* frame = element->document()->frame(); + FloatRect pageRect(FloatPoint(0, 0), pageSizeInPixels); + PrintContext printContext(frame); + printContext.begin(pageRect.width()); + printContext.computePageRectsWithPageSize(pageSizeInPixels, 1); + + int top = box->offsetTop(); + int left = box->offsetLeft(); + int pageNumber = 0; + for (; pageNumber < printContext.pageCount(); pageNumber++) { + const IntRect& page = printContext.pageRect(pageNumber); + if (page.x() <= left && left < page.right() && page.y() <= top && top < page.bottom()) + break; + } + printContext.end(); + return (pageNumber < printContext.pageCount() ? pageNumber : -1); +} + +int PrintContext::numberOfPages(Frame* frame, const FloatSize& pageSizeInPixels) +{ + frame->document()->updateLayout(); + + FloatRect pageRect(FloatPoint(0, 0), pageSizeInPixels); + PrintContext printContext(frame); + printContext.begin(pageRect.width()); + printContext.computePageRectsWithPageSize(pageSizeInPixels, 1); + printContext.end(); + return printContext.pageCount(); +} + } diff --git a/src/3rdparty/webkit/WebCore/page/PrintContext.h b/src/3rdparty/webkit/WebCore/page/PrintContext.h index 0b3b303..ec15b84 100644 --- a/src/3rdparty/webkit/WebCore/page/PrintContext.h +++ b/src/3rdparty/webkit/WebCore/page/PrintContext.h @@ -25,8 +25,10 @@ namespace WebCore { +class Element; class Frame; class FloatRect; +class FloatSize; class GraphicsContext; class IntRect; @@ -36,6 +38,8 @@ public: ~PrintContext(); int pageCount() const; + const IntRect& pageRect(int pageNumber) const; + const Vector<IntRect>& pageRects() const { return m_pageRects; } void computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight); @@ -47,7 +51,13 @@ public: void end(); + // Used by layout tests. + static int pageNumberForElement(Element*, const FloatSize& pageSizeInPixels); + static int numberOfPages(Frame*, const FloatSize& pageSizeInPixels); + protected: + void computePageRectsWithPageSize(const FloatSize& pageSizeInPixels, float userScaleFactor); + Frame* m_frame; Vector<IntRect> m_pageRects; }; diff --git a/src/3rdparty/webkit/WebCore/page/Screen.idl b/src/3rdparty/webkit/WebCore/page/Screen.idl index ca7d20d..cd181eb 100644 --- a/src/3rdparty/webkit/WebCore/page/Screen.idl +++ b/src/3rdparty/webkit/WebCore/page/Screen.idl @@ -29,7 +29,7 @@ module window { - interface Screen { + interface [OmitConstructor] Screen { readonly attribute unsigned long height; readonly attribute unsigned long width; readonly attribute unsigned long colorDepth; diff --git a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp index 338bf9f..c0b3e22 100644 --- a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp +++ b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp @@ -65,37 +65,37 @@ static URLSchemesMap& localSchemes() return localSchemes; } -static URLSchemesMap& noAccessSchemes() +static URLSchemesMap& secureSchemes() { - DEFINE_STATIC_LOCAL(URLSchemesMap, noAccessSchemes, ()); + DEFINE_STATIC_LOCAL(URLSchemesMap, secureSchemes, ()); - if (noAccessSchemes.isEmpty()) - noAccessSchemes.add("data"); + if (secureSchemes.isEmpty()) { + secureSchemes.add("https"); + secureSchemes.add("about"); + secureSchemes.add("data"); + } - return noAccessSchemes; + return secureSchemes; } -bool SecurityOrigin::isDefaultPortForProtocol(unsigned short port, const String& protocol) +static URLSchemesMap& schemesWithUniqueOrigins() { - if (protocol.isEmpty()) - return false; + DEFINE_STATIC_LOCAL(URLSchemesMap, schemesWithUniqueOrigins, ()); - typedef HashMap<String, unsigned> DefaultPortsMap; - DEFINE_STATIC_LOCAL(DefaultPortsMap, defaultPorts, ()); - if (defaultPorts.isEmpty()) { - defaultPorts.set("http", 80); - defaultPorts.set("https", 443); - defaultPorts.set("ftp", 21); - defaultPorts.set("ftps", 990); - } - return defaultPorts.get(protocol) == port; + // This is a willful violation of HTML5. + // See https://bugs.webkit.org/show_bug.cgi?id=11885 + if (schemesWithUniqueOrigins.isEmpty()) + schemesWithUniqueOrigins.add("data"); + + return schemesWithUniqueOrigins; } -SecurityOrigin::SecurityOrigin(const KURL& url) - : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) +SecurityOrigin::SecurityOrigin(const KURL& url, SandboxFlags sandboxFlags) + : m_sandboxFlags(sandboxFlags) + , m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) , m_host(url.host().isNull() ? "" : url.host().lower()) , m_port(url.port()) - , m_noAccess(false) + , m_isUnique(isSandboxed(SandboxOrigin) || shouldTreatURLSchemeAsNoAccess(m_protocol)) , m_universalAccess(false) , m_domainWasSetInDOM(false) { @@ -103,26 +103,29 @@ SecurityOrigin::SecurityOrigin(const KURL& url) if (m_protocol == "about" || m_protocol == "javascript") m_protocol = ""; - // Some URLs are not allowed access to anything other than themselves. - if (shouldTreatURLSchemeAsNoAccess(m_protocol)) - m_noAccess = true; - // document.domain starts as m_host, but can be set by the DOM. m_domain = m_host; // By default, only local SecurityOrigins can load local resources. m_canLoadLocalResources = isLocal(); + if (m_canLoadLocalResources) { + // Directories should never be readable. + if (!url.hasPath() || url.path().endsWith("/")) + m_isUnique = true; + } if (isDefaultPortForProtocol(m_port, m_protocol)) m_port = 0; } SecurityOrigin::SecurityOrigin(const SecurityOrigin* other) - : m_protocol(other->m_protocol.threadsafeCopy()) + : m_sandboxFlags(other->m_sandboxFlags) + , m_protocol(other->m_protocol.threadsafeCopy()) , m_host(other->m_host.threadsafeCopy()) + , m_encodedHost(other->m_encodedHost.threadsafeCopy()) , m_domain(other->m_domain.threadsafeCopy()) , m_port(other->m_port) - , m_noAccess(other->m_noAccess) + , m_isUnique(other->m_isUnique) , m_universalAccess(other->m_universalAccess) , m_domainWasSetInDOM(other->m_domainWasSetInDOM) , m_canLoadLocalResources(other->m_canLoadLocalResources) @@ -134,11 +137,11 @@ bool SecurityOrigin::isEmpty() const return m_protocol.isEmpty(); } -PassRefPtr<SecurityOrigin> SecurityOrigin::create(const KURL& url) +PassRefPtr<SecurityOrigin> SecurityOrigin::create(const KURL& url, SandboxFlags sandboxFlags) { if (!url.isValid()) - return adoptRef(new SecurityOrigin(KURL())); - return adoptRef(new SecurityOrigin(url)); + return adoptRef(new SecurityOrigin(KURL(), sandboxFlags)); + return adoptRef(new SecurityOrigin(url, sandboxFlags)); } PassRefPtr<SecurityOrigin> SecurityOrigin::createEmpty() @@ -157,20 +160,45 @@ void SecurityOrigin::setDomainFromDOM(const String& newDomain) m_domain = newDomain.lower(); } +static HashSet<String>& schemesForbiddenFromDomainRelaxation() +{ + DEFINE_STATIC_LOCAL(HashSet<String>, schemes, ()); + return schemes; +} + +void SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const String& scheme) +{ + if (scheme.isEmpty()) + return; + + if (forbidden) + schemesForbiddenFromDomainRelaxation().add(scheme); + else + schemesForbiddenFromDomainRelaxation().remove(scheme); +} + +bool SecurityOrigin::isDomainRelaxationForbiddenForURLScheme(const String& scheme) +{ + if (scheme.isEmpty()) + return false; + + return schemesForbiddenFromDomainRelaxation().contains(scheme); +} + bool SecurityOrigin::canAccess(const SecurityOrigin* other) const { if (m_universalAccess) return true; - if (m_noAccess || other->m_noAccess) + if (isUnique() || other->isUnique()) return false; // Here are two cases where we should permit access: // - // 1) Neither document has set document.domain. In this case, we insist + // 1) Neither document has set document.domain. In this case, we insist // that the scheme, host, and port of the URLs match. // - // 2) Both documents have set document.domain. In this case, we insist + // 2) Both documents have set document.domain. In this case, we insist // that the documents have set document.domain to the same value and // that the scheme of the URLs match. // @@ -203,10 +231,12 @@ bool SecurityOrigin::canRequest(const KURL& url) const if (m_universalAccess) return true; - if (m_noAccess) + if (isUnique()) return false; RefPtr<SecurityOrigin> targetOrigin = SecurityOrigin::create(url); + if (targetOrigin->isUnique()) + return false; // We call isSameSchemeHostPort here instead of canAccess because we want // to ignore document.domain effects. @@ -228,11 +258,12 @@ bool SecurityOrigin::taintsCanvas(const KURL& url) const if (canRequest(url)) return false; - // This method exists because we treat data URLs as noAccess, contrary - // to the current (9/19/2009) draft of the HTML5 specification. We still - // want to let folks paint data URLs onto untainted canvases, so we special - // case data URLs below. If we change to match HTML5 w.r.t. data URL - // security, then we can remove this method in favor of !canRequest. + // This function exists because we treat data URLs as having a unique origin, + // contrary to the current (9/19/2009) draft of the HTML5 specification. + // We still want to let folks paint data URLs onto untainted canvases, so + // we special case data URLs below. If we change to match HTML5 w.r.t. + // data URL security, then we can remove this function in favor of + // !canRequest. if (url.protocolIs("data")) return false; @@ -255,8 +286,8 @@ bool SecurityOrigin::canLoad(const KURL& url, const String& referrer, Document* void SecurityOrigin::grantLoadLocalResources() { - // This method exists only to support backwards compatibility with older - // versions of WebKit. Granting privileges to some, but not all, documents + // This function exists only to support backwards compatibility with older + // versions of WebKit. Granting privileges to some, but not all, documents // in a SecurityOrigin is a security hazard because the documents without // the privilege can obtain the privilege by injecting script into the // documents that have been granted the privilege. @@ -269,6 +300,11 @@ void SecurityOrigin::grantUniversalAccess() m_universalAccess = true; } +void SecurityOrigin::makeUnique() +{ + m_isUnique = true; +} + bool SecurityOrigin::isLocal() const { return shouldTreatURLSchemeAsLocal(m_protocol); @@ -289,7 +325,7 @@ String SecurityOrigin::toString() const if (isEmpty()) return "null"; - if (m_noAccess) + if (isUnique()) return "null"; if (m_protocol == "file") @@ -346,13 +382,92 @@ PassRefPtr<SecurityOrigin> SecurityOrigin::createFromDatabaseIdentifier(const St // Split out the 3 sections of data String protocol = databaseIdentifier.substring(0, separator1); String host = databaseIdentifier.substring(separator1 + 1, separator2 - separator1 - 1); + + host = decodeURLEscapeSequences(host); return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(port))); } +// The following lower-ASCII characters need escaping to be used in a filename +// across all systems, including Windows: +// - Unprintable ASCII (00-1F) +// - Space (20) +// - Double quote (22) +// - Percent (25) (escaped because it is our escape character) +// - Asterisk (2A) +// - Slash (2F) +// - Colon (3A) +// - Less-than (3C) +// - Greater-than (3E) +// - Question Mark (3F) +// - Backslash (5C) +// - Pipe (7C) +// - Delete (7F) + +static const bool needsEscaping[128] = { + /* 00-07 */ true, true, true, true, true, true, true, true, + /* 08-0F */ true, true, true, true, true, true, true, true, + + /* 10-17 */ true, true, true, true, true, true, true, true, + /* 18-1F */ true, true, true, true, true, true, true, true, + + /* 20-27 */ true, false, true, false, false, true, false, false, + /* 28-2F */ false, false, true, false, false, false, false, true, + + /* 30-37 */ false, false, false, false, false, false, false, false, + /* 38-3F */ false, false, true, false, true, false, true, true, + + /* 40-47 */ false, false, false, false, false, false, false, false, + /* 48-4F */ false, false, false, false, false, false, false, false, + + /* 50-57 */ false, false, false, false, false, false, false, false, + /* 58-5F */ false, false, false, false, true, false, false, false, + + /* 60-67 */ false, false, false, false, false, false, false, false, + /* 68-6F */ false, false, false, false, false, false, false, false, + + /* 70-77 */ false, false, false, false, false, false, false, false, + /* 78-7F */ false, false, false, false, true, false, false, true, +}; + +static inline bool shouldEscapeUChar(UChar c) +{ + return c > 127 ? false : needsEscaping[c]; +} + +static const char hexDigits[17] = "0123456789ABCDEF"; + +static String encodedHost(const String& host) +{ + unsigned length = host.length(); + Vector<UChar, 512> buffer(length * 3 + 1); + UChar* p = buffer.data(); + + const UChar* str = host.characters(); + const UChar* strEnd = str + length; + + while (str < strEnd) { + UChar c = *str++; + if (shouldEscapeUChar(c)) { + *p++ = '%'; + *p++ = hexDigits[(c >> 4) & 0xF]; + *p++ = hexDigits[c & 0xF]; + } else + *p++ = c; + } + + ASSERT(p - buffer.data() <= static_cast<int>(buffer.size())); + + return String(buffer.data(), p - buffer.data()); +} + String SecurityOrigin::databaseIdentifier() const { - DEFINE_STATIC_LOCAL(String, separatorString, (&SeparatorCharacter, 1)); - return m_protocol + separatorString + m_host + separatorString + String::number(m_port); + String separatorString(&SeparatorCharacter, 1); + + if (m_encodedHost.isEmpty()) + m_encodedHost = encodedHost(m_host); + + return m_protocol + separatorString + m_encodedHost + separatorString + String::number(m_port); } bool SecurityOrigin::equal(const SecurityOrigin* other) const @@ -399,14 +514,10 @@ void SecurityOrigin::removeURLSchemeRegisteredAsLocal(const String& scheme) if (scheme == "applewebdata") return; #endif -#if PLATFORM(QT) - if (scheme == "qrc") - return; -#endif localSchemes().remove(scheme); } -const URLSchemesMap& SecurityOrigin::localURLSchemes() +const URLSchemesMap& SecurityOrigin::localURLSchemes() { return localSchemes(); } @@ -451,12 +562,22 @@ bool SecurityOrigin::shouldTreatURLSchemeAsLocal(const String& scheme) void SecurityOrigin::registerURLSchemeAsNoAccess(const String& scheme) { - noAccessSchemes().add(scheme); + schemesWithUniqueOrigins().add(scheme); } bool SecurityOrigin::shouldTreatURLSchemeAsNoAccess(const String& scheme) { - return noAccessSchemes().contains(scheme); + return schemesWithUniqueOrigins().contains(scheme); +} + +void SecurityOrigin::registerURLSchemeAsSecure(const String& scheme) +{ + secureSchemes().add(scheme); +} + +bool SecurityOrigin::shouldTreatURLSchemeAsSecure(const String& scheme) +{ + return secureSchemes().contains(scheme); } bool SecurityOrigin::shouldHideReferrer(const KURL& url, const String& referrer) diff --git a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.h b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.h index 6d4ce1f..11c213e 100644 --- a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.h +++ b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.h @@ -34,152 +34,184 @@ #include <wtf/PassRefPtr.h> #include <wtf/Threading.h> +#include "FrameLoaderTypes.h" #include "PlatformString.h" #include "StringHash.h" namespace WebCore { - typedef HashSet<String, CaseFoldingHash> URLSchemesMap; - - class Document; - class KURL; - - class SecurityOrigin : public ThreadSafeShared<SecurityOrigin> { - public: - static PassRefPtr<SecurityOrigin> createFromDatabaseIdentifier(const String&); - static PassRefPtr<SecurityOrigin> createFromString(const String&); - static PassRefPtr<SecurityOrigin> create(const KURL&); - static PassRefPtr<SecurityOrigin> createEmpty(); - - // Create a deep copy of this SecurityOrigin. This method is useful - // when marshalling a SecurityOrigin to another thread. - PassRefPtr<SecurityOrigin> threadsafeCopy(); - - // Set the domain property of this security origin to newDomain. This - // function does not check whether newDomain is a suffix of the current - // domain. The caller is responsible for validating newDomain. - void setDomainFromDOM(const String& newDomain); - bool domainWasSetInDOM() const { return m_domainWasSetInDOM; } - - String protocol() const { return m_protocol; } - String host() const { return m_host; } - String domain() const { return m_domain; } - unsigned short port() const { return m_port; } - - // Returns true if this SecurityOrigin can script objects in the given - // SecurityOrigin. For example, call this function before allowing - // script from one security origin to read or write objects from - // another SecurityOrigin. - bool canAccess(const SecurityOrigin*) const; - - // Returns true if this SecurityOrigin can read content retrieved from - // the given URL. For example, call this function before issuing - // XMLHttpRequests. - bool canRequest(const KURL&) const; - - // Returns true if drawing an image from this URL taints a canvas from - // this security origin. For example, call this function before - // drawing an image onto an HTML canvas element with the drawImage API. - bool taintsCanvas(const KURL&) const; - - // Returns true for any non-local URL. If document parameter is supplied, - // its local load policy dictates, otherwise if referrer is non-empty and - // represents a local file, then the local load is allowed. - static bool canLoad(const KURL&, const String& referrer, Document* document); - - // Returns true if this SecurityOrigin can load local resources, such - // as images, iframes, and style sheets, and can link to local URLs. - // For example, call this function before creating an iframe to a - // file:// URL. - // - // Note: A SecurityOrigin might be allowed to load local resources - // without being able to issue an XMLHttpRequest for a local URL. - // To determine whether the SecurityOrigin can issue an - // XMLHttpRequest for a URL, call canRequest(url). - bool canLoadLocalResources() const { return m_canLoadLocalResources; } - - // Explicitly grant the ability to load local resources to this - // SecurityOrigin. - // - // Note: This method exists only to support backwards compatibility - // with older versions of WebKit. - void grantLoadLocalResources(); - - // Explicitly grant the ability to access very other SecurityOrigin. - // - // WARNING: This is an extremely powerful ability. Use with caution! - void grantUniversalAccess(); - - bool isSecureTransitionTo(const KURL&) const; - - // The local SecurityOrigin is the most privileged SecurityOrigin. - // The local SecurityOrigin can script any document, navigate to local - // resources, and can set arbitrary headers on XMLHttpRequests. - bool isLocal() const; - - // The empty SecurityOrigin is the least privileged SecurityOrigin. - bool isEmpty() const; - - // Convert this SecurityOrigin into a string. The string - // representation of a SecurityOrigin is similar to a URL, except it - // lacks a path component. The string representation does not encode - // the value of the SecurityOrigin's domain property. The empty - // SecurityOrigin is represented with the string "null". - String toString() const; - - // Serialize the security origin to a string that could be used as part of - // file names. This format should be used in storage APIs only. - String databaseIdentifier() const; - - // This method checks for equality between SecurityOrigins, not whether - // one origin can access another. It is used for hash table keys. - // For access checks, use canAccess(). - // FIXME: If this method is really only useful for hash table keys, it - // should be refactored into SecurityOriginHash. - bool equal(const SecurityOrigin*) const; - - // This method checks for equality, ignoring the value of document.domain - // (and whether it was set) but considering the host. It is used for postMessage. - bool isSameSchemeHostPort(const SecurityOrigin*) const; - - static void registerURLSchemeAsLocal(const String&); - static void removeURLSchemeRegisteredAsLocal(const String&); - static const URLSchemesMap& localURLSchemes(); - static bool shouldTreatURLAsLocal(const String&); - static bool shouldTreatURLSchemeAsLocal(const String&); - - static bool shouldHideReferrer(const KURL&, const String& referrer); - - enum LocalLoadPolicy { - AllowLocalLoadsForAll, // No restriction on local loads. - AllowLocalLoadsForLocalAndSubstituteData, - AllowLocalLoadsForLocalOnly, - }; - static void setLocalLoadPolicy(LocalLoadPolicy); - static bool restrictAccessToLocal(); - static bool allowSubstituteDataAccessToLocal(); - - static void registerURLSchemeAsNoAccess(const String&); - static bool shouldTreatURLSchemeAsNoAccess(const String&); - - static void whiteListAccessFromOrigin(const SecurityOrigin& sourceOrigin, const String& destinationProtocol, const String& destinationDomains, bool allowDestinationSubdomains); - static void resetOriginAccessWhiteLists(); - - static bool isDefaultPortForProtocol(unsigned short port, const String& protocol); - - private: - explicit SecurityOrigin(const KURL&); - explicit SecurityOrigin(const SecurityOrigin*); - - String m_protocol; - String m_host; - String m_domain; - unsigned short m_port; - bool m_noAccess; - bool m_universalAccess; - bool m_domainWasSetInDOM; - bool m_canLoadLocalResources; +typedef HashSet<String, CaseFoldingHash> URLSchemesMap; + +class Document; +class KURL; + +class SecurityOrigin : public ThreadSafeShared<SecurityOrigin> { +public: + static PassRefPtr<SecurityOrigin> createFromDatabaseIdentifier(const String&); + static PassRefPtr<SecurityOrigin> createFromString(const String&); + static PassRefPtr<SecurityOrigin> create(const KURL&, SandboxFlags = SandboxNone); + static PassRefPtr<SecurityOrigin> createEmpty(); + + // Create a deep copy of this SecurityOrigin. This method is useful + // when marshalling a SecurityOrigin to another thread. + PassRefPtr<SecurityOrigin> threadsafeCopy(); + + // Set the domain property of this security origin to newDomain. This + // function does not check whether newDomain is a suffix of the current + // domain. The caller is responsible for validating newDomain. + void setDomainFromDOM(const String& newDomain); + bool domainWasSetInDOM() const { return m_domainWasSetInDOM; } + + static void setDomainRelaxationForbiddenForURLScheme(bool forbidden, const String&); + static bool isDomainRelaxationForbiddenForURLScheme(const String&); + + String protocol() const { return m_protocol; } + String host() const { return m_host; } + String domain() const { return m_domain; } + unsigned short port() const { return m_port; } + + // Returns true if this SecurityOrigin can script objects in the given + // SecurityOrigin. For example, call this function before allowing + // script from one security origin to read or write objects from + // another SecurityOrigin. + bool canAccess(const SecurityOrigin*) const; + + // Returns true if this SecurityOrigin can read content retrieved from + // the given URL. For example, call this function before issuing + // XMLHttpRequests. + bool canRequest(const KURL&) const; + + // Returns true if drawing an image from this URL taints a canvas from + // this security origin. For example, call this function before + // drawing an image onto an HTML canvas element with the drawImage API. + bool taintsCanvas(const KURL&) const; + + // Returns true for any non-local URL. If document parameter is supplied, + // its local load policy dictates, otherwise if referrer is non-empty and + // represents a local file, then the local load is allowed. + static bool canLoad(const KURL&, const String& referrer, Document* document); + + // Returns true if this SecurityOrigin can load local resources, such + // as images, iframes, and style sheets, and can link to local URLs. + // For example, call this function before creating an iframe to a + // file:// URL. + // + // Note: A SecurityOrigin might be allowed to load local resources + // without being able to issue an XMLHttpRequest for a local URL. + // To determine whether the SecurityOrigin can issue an + // XMLHttpRequest for a URL, call canRequest(url). + bool canLoadLocalResources() const { return m_canLoadLocalResources; } + + // Explicitly grant the ability to load local resources to this + // SecurityOrigin. + // + // Note: This method exists only to support backwards compatibility + // with older versions of WebKit. + void grantLoadLocalResources(); + + // Explicitly grant the ability to access very other SecurityOrigin. + // + // WARNING: This is an extremely powerful ability. Use with caution! + void grantUniversalAccess(); + + bool isSandboxed(SandboxFlags mask) const { return m_sandboxFlags & mask; } + + bool canAccessDatabase() const { return !isUnique(); } + bool canAccessLocalStorage() const { return !isUnique(); } + bool canAccessCookies() const { return !isUnique(); } + + bool isSecureTransitionTo(const KURL&) const; + + // The local SecurityOrigin is the most privileged SecurityOrigin. + // The local SecurityOrigin can script any document, navigate to local + // resources, and can set arbitrary headers on XMLHttpRequests. + bool isLocal() const; + + // The empty SecurityOrigin is the least privileged SecurityOrigin. + bool isEmpty() const; + + // The origin is a globally unique identifier assigned when the Document is + // created. http://www.whatwg.org/specs/web-apps/current-work/#sandboxOrigin + // + // There's a subtle difference between a unique origin and an origin that + // has the SandboxOrigin flag set. The latter implies the former, and, in + // addition, the SandboxOrigin flag is inherited by iframes. + bool isUnique() const { return m_isUnique; } + + // Marks an origin as being unique. + void makeUnique(); + + // Convert this SecurityOrigin into a string. The string + // representation of a SecurityOrigin is similar to a URL, except it + // lacks a path component. The string representation does not encode + // the value of the SecurityOrigin's domain property. + // + // When using the string value, it's important to remember that it might be + // "null". This happens when this SecurityOrigin is unique. For example, + // this SecurityOrigin might have come from a sandboxed iframe, the + // SecurityOrigin might be empty, or we might have explicitly decided that + // we shouldTreatURLSchemeAsNoAccess. + String toString() const; + + // Serialize the security origin to a string that could be used as part of + // file names. This format should be used in storage APIs only. + String databaseIdentifier() const; + + // This method checks for equality between SecurityOrigins, not whether + // one origin can access another. It is used for hash table keys. + // For access checks, use canAccess(). + // FIXME: If this method is really only useful for hash table keys, it + // should be refactored into SecurityOriginHash. + bool equal(const SecurityOrigin*) const; + + // This method checks for equality, ignoring the value of document.domain + // (and whether it was set) but considering the host. It is used for postMessage. + bool isSameSchemeHostPort(const SecurityOrigin*) const; + + static void registerURLSchemeAsLocal(const String&); + static void removeURLSchemeRegisteredAsLocal(const String&); + static const URLSchemesMap& localURLSchemes(); + static bool shouldTreatURLAsLocal(const String&); + static bool shouldTreatURLSchemeAsLocal(const String&); + + // Secure schemes do not trigger mixed content warnings. For example, + // https and data are secure schemes because they cannot be corrupted by + // active network attackers. + static void registerURLSchemeAsSecure(const String&); + static bool shouldTreatURLSchemeAsSecure(const String&); + + static bool shouldHideReferrer(const KURL&, const String& referrer); + + enum LocalLoadPolicy { + AllowLocalLoadsForAll, // No restriction on local loads. + AllowLocalLoadsForLocalAndSubstituteData, + AllowLocalLoadsForLocalOnly, }; + static void setLocalLoadPolicy(LocalLoadPolicy); + static bool restrictAccessToLocal(); + static bool allowSubstituteDataAccessToLocal(); + + static void registerURLSchemeAsNoAccess(const String&); + static bool shouldTreatURLSchemeAsNoAccess(const String&); + + static void whiteListAccessFromOrigin(const SecurityOrigin& sourceOrigin, const String& destinationProtocol, const String& destinationDomains, bool allowDestinationSubdomains); + static void resetOriginAccessWhiteLists(); + +private: + SecurityOrigin(const KURL&, SandboxFlags); + explicit SecurityOrigin(const SecurityOrigin*); + + SandboxFlags m_sandboxFlags; + String m_protocol; + String m_host; + mutable String m_encodedHost; + String m_domain; + unsigned short m_port; + bool m_isUnique; + bool m_universalAccess; + bool m_domainWasSetInDOM; + bool m_canLoadLocalResources; +}; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Settings.cpp b/src/3rdparty/webkit/WebCore/page/Settings.cpp index f528f37..475d373 100644 --- a/src/3rdparty/webkit/WebCore/page/Settings.cpp +++ b/src/3rdparty/webkit/WebCore/page/Settings.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "Settings.h" +#include "BackForwardList.h" +#include "Database.h" #include "Frame.h" #include "FrameTree.h" #include "FrameView.h" @@ -48,7 +50,7 @@ static void setNeedsReapplyStylesInAllFrames(Page* page) bool Settings::gShouldPaintNativeControls = true; #endif -#if PLATFORM(WIN) || (PLATFORM(WIN_OS) && PLATFORM(WX)) +#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX)) bool Settings::gShouldUseHighResolutionTimers = true; #endif @@ -63,17 +65,19 @@ Settings::Settings(Page* page) , m_maximumDecodedImageSize(numeric_limits<size_t>::max()) , m_localStorageQuota(5 * 1024 * 1024) // Suggested by the HTML5 spec. , m_pluginAllowedRunTime(numeric_limits<unsigned>::max()) + , m_zoomMode(ZoomPage) + , m_isSpatialNavigationEnabled(false) , m_isJavaEnabled(false) , m_loadsImagesAutomatically(false) , m_privateBrowsingEnabled(false) , m_caretBrowsingEnabled(false) + , m_areImagesEnabled(true) , m_arePluginsEnabled(false) - , m_databasesEnabled(false) , m_localStorageEnabled(false) - , m_sessionStorageEnabled(true) , m_isJavaScriptEnabled(false) , m_isWebSecurityEnabled(true) , m_allowUniversalAccessFromFileURLs(true) + , m_allowFileAccessFromFileURLs(true) , m_javaScriptCanOpenWindowsAutomatically(false) , m_shouldPrintBackgrounds(false) , m_textAreasAreResizable(false) @@ -94,17 +98,17 @@ Settings::Settings(Page* page) , m_authorAndUserStylesEnabled(true) , m_needsSiteSpecificQuirks(false) , m_fontRenderingMode(0) + , m_frameFlatteningEnabled(false) , m_webArchiveDebugModeEnabled(false) , m_localFileContentSniffingEnabled(false) , m_inApplicationChromeMode(false) , m_offlineWebApplicationCacheEnabled(false) , m_shouldPaintCustomScrollbars(false) - , m_zoomsTextOnly(false) , m_enforceCSSMIMETypeInStrictMode(true) , m_usesEncodingDetector(false) , m_allowScriptsToCloseWindows(false) , m_editingBehavior( -#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) // (PLATFORM(MAC) is always false in Chromium, hence the extra condition.) EditingMacBehavior #else @@ -116,8 +120,12 @@ Settings::Settings(Page* page) , m_downloadableBinaryFontsEnabled(true) , m_xssAuditorEnabled(false) , m_acceleratedCompositingEnabled(true) + , m_showDebugBorders(false) + , m_showRepaintCounter(false) , m_experimentalNotificationsEnabled(false) , m_webGLEnabled(false) + , m_loadDeferringEnabled(true) + , m_tiledBackingStoreEnabled(false) { // A Frame may not have been created yet, so we initialize the AtomicString // hash before trying to use it. @@ -234,19 +242,29 @@ void Settings::setAllowUniversalAccessFromFileURLs(bool allowUniversalAccessFrom m_allowUniversalAccessFromFileURLs = allowUniversalAccessFromFileURLs; } +void Settings::setAllowFileAccessFromFileURLs(bool allowFileAccessFromFileURLs) +{ + m_allowFileAccessFromFileURLs = allowFileAccessFromFileURLs; +} + +void Settings::setSpatialNavigationEnabled(bool isSpatialNavigationEnabled) +{ + m_isSpatialNavigationEnabled = isSpatialNavigationEnabled; +} + void Settings::setJavaEnabled(bool isJavaEnabled) { m_isJavaEnabled = isJavaEnabled; } -void Settings::setPluginsEnabled(bool arePluginsEnabled) +void Settings::setImagesEnabled(bool areImagesEnabled) { - m_arePluginsEnabled = arePluginsEnabled; + m_areImagesEnabled = areImagesEnabled; } -void Settings::setDatabasesEnabled(bool databasesEnabled) +void Settings::setPluginsEnabled(bool arePluginsEnabled) { - m_databasesEnabled = databasesEnabled; + m_arePluginsEnabled = arePluginsEnabled; } void Settings::setLocalStorageEnabled(bool localStorageEnabled) @@ -254,11 +272,6 @@ void Settings::setLocalStorageEnabled(bool localStorageEnabled) m_localStorageEnabled = localStorageEnabled; } -void Settings::setSessionStorageEnabled(bool sessionStorageEnabled) -{ - m_sessionStorageEnabled = sessionStorageEnabled; -} - void Settings::setLocalStorageQuota(unsigned localStorageQuota) { m_localStorageQuota = localStorageQuota; @@ -266,7 +279,11 @@ void Settings::setLocalStorageQuota(unsigned localStorageQuota) void Settings::setPrivateBrowsingEnabled(bool privateBrowsingEnabled) { + if (m_privateBrowsingEnabled == privateBrowsingEnabled) + return; + m_privateBrowsingEnabled = privateBrowsingEnabled; + m_page->privateBrowsingStateChanged(); } void Settings::setJavaScriptCanOpenWindowsAutomatically(bool javaScriptCanOpenWindowsAutomatically) @@ -421,6 +438,11 @@ void Settings::setNeedsSiteSpecificQuirks(bool needsQuirks) m_needsSiteSpecificQuirks = needsQuirks; } +void Settings::setFrameFlatteningEnabled(bool frameFlatteningEnabled) +{ + m_frameFlatteningEnabled = frameFlatteningEnabled; +} + void Settings::setWebArchiveDebugModeEnabled(bool enabled) { m_webArchiveDebugModeEnabled = enabled; @@ -451,12 +473,12 @@ void Settings::setShouldPaintCustomScrollbars(bool shouldPaintCustomScrollbars) m_shouldPaintCustomScrollbars = shouldPaintCustomScrollbars; } -void Settings::setZoomsTextOnly(bool zoomsTextOnly) +void Settings::setZoomMode(ZoomMode mode) { - if (zoomsTextOnly == m_zoomsTextOnly) + if (mode == m_zoomMode) return; - m_zoomsTextOnly = zoomsTextOnly; + m_zoomMode = mode; setNeedsReapplyStylesInAllFrames(m_page); } @@ -506,6 +528,24 @@ void Settings::setAcceleratedCompositingEnabled(bool enabled) setNeedsReapplyStylesInAllFrames(m_page); } +void Settings::setShowDebugBorders(bool enabled) +{ + if (m_showDebugBorders == enabled) + return; + + m_showDebugBorders = enabled; + setNeedsReapplyStylesInAllFrames(m_page); +} + +void Settings::setShowRepaintCounter(bool enabled) +{ + if (m_showRepaintCounter == enabled) + return; + + m_showRepaintCounter = enabled; + setNeedsReapplyStylesInAllFrames(m_page); +} + void Settings::setExperimentalNotificationsEnabled(bool enabled) { m_experimentalNotificationsEnabled = enabled; @@ -517,7 +557,7 @@ void Settings::setPluginAllowedRunTime(unsigned runTime) m_page->pluginAllowedRunTimeChanged(); } -#if PLATFORM(WIN) || (PLATFORM(WIN_OS) && PLATFORM(WX)) +#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX)) void Settings::setShouldUseHighResolutionTimers(bool shouldUseHighResolutionTimers) { gShouldUseHighResolutionTimers = shouldUseHighResolutionTimers; @@ -529,4 +569,18 @@ void Settings::setWebGLEnabled(bool enabled) m_webGLEnabled = enabled; } +void Settings::setLoadDeferringEnabled(bool enabled) +{ + m_loadDeferringEnabled = enabled; +} + +void Settings::setTiledBackingStoreEnabled(bool enabled) +{ + m_tiledBackingStoreEnabled = enabled; +#if ENABLE(TILED_BACKING_STORE) + if (m_page->mainFrame()) + m_page->mainFrame()->setTiledBackingStoreEnabled(enabled); +#endif +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Settings.h b/src/3rdparty/webkit/WebCore/page/Settings.h index 09b5bec..b677712 100644 --- a/src/3rdparty/webkit/WebCore/page/Settings.h +++ b/src/3rdparty/webkit/WebCore/page/Settings.h @@ -30,6 +30,7 @@ #include "AtomicString.h" #include "FontRenderingMode.h" #include "KURL.h" +#include "ZoomMode.h" namespace WebCore { @@ -64,7 +65,7 @@ namespace WebCore { // if possible in the future. enum EditingBehavior { EditingMacBehavior, EditingWindowsBehavior }; - class Settings { + class Settings : public Noncopyable { public: Settings(Page*); @@ -98,10 +99,15 @@ namespace WebCore { void setDefaultFixedFontSize(int); int defaultFixedFontSize() const { return m_defaultFixedFontSize; } + // Unlike areImagesEnabled, this only suppresses the network load of + // the image URL. A cached image will still be rendered if requested. void setLoadsImagesAutomatically(bool); bool loadsImagesAutomatically() const { return m_loadsImagesAutomatically; } void setJavaScriptEnabled(bool); + // Instead of calling isJavaScriptEnabled directly, please consider calling + // ScriptController::canExecuteScripts, which takes things like the + // HTML sandbox attribute into account. bool isJavaScriptEnabled() const { return m_isJavaScriptEnabled; } void setWebSecurityEnabled(bool); @@ -110,24 +116,27 @@ namespace WebCore { void setAllowUniversalAccessFromFileURLs(bool); bool allowUniversalAccessFromFileURLs() const { return m_allowUniversalAccessFromFileURLs; } + void setAllowFileAccessFromFileURLs(bool); + bool allowFileAccessFromFileURLs() const { return m_allowFileAccessFromFileURLs; } + void setJavaScriptCanOpenWindowsAutomatically(bool); bool javaScriptCanOpenWindowsAutomatically() const { return m_javaScriptCanOpenWindowsAutomatically; } + void setSpatialNavigationEnabled(bool); + bool isSpatialNavigationEnabled() const { return m_isSpatialNavigationEnabled; } + void setJavaEnabled(bool); bool isJavaEnabled() const { return m_isJavaEnabled; } + void setImagesEnabled(bool); + bool areImagesEnabled() const { return m_areImagesEnabled; } + void setPluginsEnabled(bool); bool arePluginsEnabled() const { return m_arePluginsEnabled; } - void setDatabasesEnabled(bool); - bool databasesEnabled() const { return m_databasesEnabled; } - void setLocalStorageEnabled(bool); bool localStorageEnabled() const { return m_localStorageEnabled; } - void setSessionStorageEnabled(bool); - bool sessionStorageEnabled() const { return m_sessionStorageEnabled; } - void setLocalStorageQuota(unsigned); unsigned localStorageQuota() const { return m_localStorageQuota; } @@ -198,7 +207,10 @@ namespace WebCore { void setDeveloperExtrasEnabled(bool); bool developerExtrasEnabled() const { return m_developerExtrasEnabled; } - + + void setFrameFlatteningEnabled(bool); + bool frameFlatteningEnabled() const { return m_frameFlatteningEnabled; } + void setAuthorAndUserStylesEnabled(bool); bool authorAndUserStylesEnabled() const { return m_authorAndUserStylesEnabled; } @@ -226,8 +238,8 @@ namespace WebCore { void setShouldPaintCustomScrollbars(bool); bool shouldPaintCustomScrollbars() const { return m_shouldPaintCustomScrollbars; } - void setZoomsTextOnly(bool); - bool zoomsTextOnly() const { return m_zoomsTextOnly; } + void setZoomMode(ZoomMode); + ZoomMode zoomMode() const { return m_zoomMode; } void setEnforceCSSMIMETypeInStrictMode(bool); bool enforceCSSMIMETypeInStrictMode() { return m_enforceCSSMIMETypeInStrictMode; } @@ -256,10 +268,16 @@ namespace WebCore { void setAcceleratedCompositingEnabled(bool); bool acceleratedCompositingEnabled() const { return m_acceleratedCompositingEnabled; } + void setShowDebugBorders(bool); + bool showDebugBorders() const { return m_showDebugBorders; } + + void setShowRepaintCounter(bool); + bool showRepaintCounter() const { return m_showRepaintCounter; } + void setExperimentalNotificationsEnabled(bool); bool experimentalNotificationsEnabled() const { return m_experimentalNotificationsEnabled; } -#if PLATFORM(WIN) || (PLATFORM(WIN_OS) && PLATFORM(WX)) +#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX)) static void setShouldUseHighResolutionTimers(bool); static bool shouldUseHighResolutionTimers() { return gShouldUseHighResolutionTimers; } #endif @@ -270,6 +288,12 @@ namespace WebCore { void setWebGLEnabled(bool); bool webGLEnabled() const { return m_webGLEnabled; } + void setLoadDeferringEnabled(bool); + bool loadDeferringEnabled() const { return m_loadDeferringEnabled; } + + void setTiledBackingStoreEnabled(bool); + bool tiledBackingStoreEnabled() const { return m_tiledBackingStoreEnabled; } + private: Page* m_page; @@ -292,17 +316,19 @@ namespace WebCore { size_t m_maximumDecodedImageSize; unsigned m_localStorageQuota; unsigned m_pluginAllowedRunTime; + ZoomMode m_zoomMode; + bool m_isSpatialNavigationEnabled : 1; bool m_isJavaEnabled : 1; bool m_loadsImagesAutomatically : 1; bool m_privateBrowsingEnabled : 1; bool m_caretBrowsingEnabled : 1; + bool m_areImagesEnabled : 1; bool m_arePluginsEnabled : 1; - bool m_databasesEnabled : 1; bool m_localStorageEnabled : 1; - bool m_sessionStorageEnabled : 1; bool m_isJavaScriptEnabled : 1; bool m_isWebSecurityEnabled : 1; bool m_allowUniversalAccessFromFileURLs: 1; + bool m_allowFileAccessFromFileURLs: 1; bool m_javaScriptCanOpenWindowsAutomatically : 1; bool m_shouldPrintBackgrounds : 1; bool m_textAreasAreResizable : 1; @@ -323,12 +349,12 @@ namespace WebCore { bool m_authorAndUserStylesEnabled : 1; bool m_needsSiteSpecificQuirks : 1; unsigned m_fontRenderingMode : 1; + bool m_frameFlatteningEnabled : 1; bool m_webArchiveDebugModeEnabled : 1; bool m_localFileContentSniffingEnabled : 1; bool m_inApplicationChromeMode : 1; bool m_offlineWebApplicationCacheEnabled : 1; bool m_shouldPaintCustomScrollbars : 1; - bool m_zoomsTextOnly : 1; bool m_enforceCSSMIMETypeInStrictMode : 1; bool m_usesEncodingDetector : 1; bool m_allowScriptsToCloseWindows : 1; @@ -336,13 +362,17 @@ namespace WebCore { bool m_downloadableBinaryFontsEnabled : 1; bool m_xssAuditorEnabled : 1; bool m_acceleratedCompositingEnabled : 1; + bool m_showDebugBorders : 1; + bool m_showRepaintCounter : 1; bool m_experimentalNotificationsEnabled : 1; bool m_webGLEnabled : 1; + bool m_loadDeferringEnabled : 1; + bool m_tiledBackingStoreEnabled : 1; #if USE(SAFARI_THEME) static bool gShouldPaintNativeControls; #endif -#if PLATFORM(WIN) || (PLATFORM(WIN_OS) && PLATFORM(WX)) +#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX)) static bool gShouldUseHighResolutionTimers; #endif }; diff --git a/src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp new file mode 100644 index 0000000..86c9c5d --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.cpp @@ -0,0 +1,503 @@ +/* + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2009 Antonio Gomes <tonikitoo@webkit.org> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SpatialNavigation.h" + +#include "Frame.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "HTMLFrameOwnerElement.h" +#include "IntRect.h" +#include "Node.h" +#include "Page.h" + +namespace WebCore { + +static long long spatialDistance(FocusDirection, const IntRect&, const IntRect&); +static IntRect renderRectRelativeToRootDocument(RenderObject*); +static RectsAlignment alignmentForRects(FocusDirection, const IntRect&, const IntRect&); +static bool areRectsFullyAligned(FocusDirection, const IntRect&, const IntRect&); +static bool areRectsPartiallyAligned(FocusDirection, const IntRect&, const IntRect&); +static bool isRectInDirection(FocusDirection, const IntRect&, const IntRect&); +static void deflateIfOverlapped(IntRect&, IntRect&); + +long long distanceInDirection(Node* start, Node* dest, FocusDirection direction, FocusCandidate& candidate) +{ + RenderObject* startRender = start->renderer(); + if (!startRender) + return maxDistance(); + + RenderObject* destRender = dest->renderer(); + if (!destRender) + return maxDistance(); + + IntRect curRect = renderRectRelativeToRootDocument(startRender); + IntRect targetRect = renderRectRelativeToRootDocument(destRender); + + // The bounding rectangle of two consecutive nodes can overlap. In such cases, + // deflate both. + deflateIfOverlapped(curRect, targetRect); + + if (curRect.isEmpty() || targetRect.isEmpty() + || targetRect.x() < 0 || targetRect.y() < 0) + return maxDistance(); + + if (!isRectInDirection(direction, curRect, targetRect)) + return maxDistance(); + + // The distance between two nodes is not to be considered alone when evaluating/looking + // for the best focus candidate node. Alignment of rects can be also a good point to be + // considered in order to make the algorithm to behavior in a more intuitive way. + RectsAlignment alignment = alignmentForRects(direction, curRect, targetRect); + + bool sameDocument = dest->document() == candidate.document(); + if (sameDocument) { + if (candidate.alignment > alignment || (candidate.parentAlignment && alignment > candidate.parentAlignment)) + return maxDistance(); + } else if (candidate.alignment > alignment && (candidate.parentAlignment && alignment > candidate.parentAlignment)) + return maxDistance(); + + // FIXME_tonikitoo: simplify the logic here ! + if (alignment != None + || (!candidate.isNull() && candidate.parentAlignment >= alignment + && candidate.document() == dest->document())) { + + // If we are now in an higher precedent case, lets reset the current |candidate|'s + // |distance| so we force it to be bigger than the result we will get from + // |spatialDistance| (see below). + if (candidate.alignment < alignment && candidate.parentAlignment < alignment) + candidate.distance = maxDistance(); + + candidate.alignment = alignment; + } + + return spatialDistance(direction, curRect, targetRect); +} + +// FIXME: This function does not behave correctly with transformed frames. +static IntRect renderRectRelativeToRootDocument(RenderObject* render) +{ + ASSERT(render); + + IntRect rect(render->absoluteClippedOverflowRect()); + + // In cases when the |render|'s associated node is in a scrollable inner + // document, we only consider its scrollOffset if it is not offscreen. + Node* node = render->node(); + Document* mainDocument = node->document()->page()->mainFrame()->document(); + bool considerScrollOffset = !(hasOffscreenRect(node) && node->document() != mainDocument); + + if (considerScrollOffset) { + if (FrameView* frameView = render->node()->document()->view()) + rect.move(-frameView->scrollOffset()); + } + + // Handle nested frames. + for (Frame* frame = render->document()->frame(); frame; frame = frame->tree()->parent()) { + if (HTMLFrameOwnerElement* ownerElement = frame->ownerElement()) + rect.move(ownerElement->offsetLeft(), ownerElement->offsetTop()); + } + + return rect; +} + +static RectsAlignment alignmentForRects(FocusDirection direction, const IntRect& curRect, const IntRect& targetRect) +{ + if (areRectsFullyAligned(direction, curRect, targetRect)) + return Full; + + if (areRectsPartiallyAligned(direction, curRect, targetRect)) + return Partial; + + return None; +} + +static inline bool isHorizontalMove(FocusDirection direction) +{ + return direction == FocusDirectionLeft || direction == FocusDirectionRight; +} + +static inline int start(FocusDirection direction, const IntRect& rect) +{ + return isHorizontalMove(direction) ? rect.y() : rect.x(); +} + +static inline int middle(FocusDirection direction, const IntRect& rect) +{ + IntPoint center(rect.center()); + return isHorizontalMove(direction) ? center.y(): center.x(); +} + +static inline int end(FocusDirection direction, const IntRect& rect) +{ + return isHorizontalMove(direction) ? rect.bottom() : rect.right(); +} + +// This method checks if rects |a| and |b| are fully aligned either vertically or +// horizontally. In general, rects whose central point falls between the top or +// bottom of each other are considered fully aligned. +// Rects that match this criteria are preferable target nodes in move focus changing +// operations. +// * a = Current focused node's rect. +// * b = Focus candidate node's rect. +static bool areRectsFullyAligned(FocusDirection direction, const IntRect& a, const IntRect& b) +{ + int aStart, bStart, aEnd, bEnd; + + switch (direction) { + case FocusDirectionLeft: + aStart = a.x(); + bEnd = b.right(); + break; + case FocusDirectionRight: + aStart = b.x(); + bEnd = a.right(); + break; + case FocusDirectionUp: + aStart = a.y(); + bEnd = b.y(); + break; + case FocusDirectionDown: + aStart = b.y(); + bEnd = a.y(); + break; + default: + ASSERT_NOT_REACHED(); + return false; + } + + if (aStart < bEnd) + return false; + + aStart = start(direction, a); + bStart = start(direction, b); + + int aMiddle = middle(direction, a); + int bMiddle = middle(direction, b); + + aEnd = end(direction, a); + bEnd = end(direction, b); + + // Picture of the totally aligned logic: + // + // Horizontal Vertical Horizontal Vertical + // **************************** ***************************** + // * _ * _ _ _ _ * * _ * _ _ * + // * |_| _ * |_|_|_|_| * * _ |_| * |_|_| * + // * |_|....|_| * . * * |_|....|_| * . * + // * |_| |_| (1) . * * |_| |_| (2) . * + // * |_| * _._ * * |_| * _ _._ _ * + // * * |_|_| * * * |_|_|_|_| * + // * * * * * * + // **************************** ***************************** + + // Horizontal Vertical Horizontal Vertical + // **************************** ***************************** + // * _......_ * _ _ _ _ * * _ * _ _ _ _ * + // * |_| |_| * |_|_|_|_| * * |_| _ * |_|_|_|_| * + // * |_| |_| * . * * |_| |_| * . * + // * |_| (3) . * * |_|....|_| (4) . * + // * * ._ _ * * * _ _. * + // * * |_|_| * * * |_|_| * + // * * * * * * + // **************************** ***************************** + + return ((bMiddle >= aStart && bMiddle <= aEnd) // (1) + || (aMiddle >= bStart && aMiddle <= bEnd) // (2) + || (bStart == aStart) // (3) + || (bEnd == aEnd)); // (4) +} + +// This method checks if |start| and |dest| have a partial intersection, either +// horizontally or vertically. +// * a = Current focused node's rect. +// * b = Focus candidate node's rect. +static bool areRectsPartiallyAligned(FocusDirection direction, const IntRect& a, const IntRect& b) +{ + int aStart = start(direction, a); + int bStart = start(direction, b); + int bMiddle = middle(direction, b); + int aEnd = end(direction, a); + int bEnd = end(direction, b); + + // Picture of the partially aligned logic: + // + // Horizontal Vertical + // ******************************** + // * _ * _ _ _ * + // * |_| * |_|_|_| * + // * |_|.... _ * . . * + // * |_| |_| * . . * + // * |_|....|_| * ._._ _ * + // * |_| * |_|_|_| * + // * |_| * * + // * * * + // ******************************** + // + // ... and variants of the above cases. + return ((bStart >= aStart && bStart <= aEnd) + || (bStart >= aStart && bStart <= aEnd) + || (bEnd >= aStart && bEnd <= aEnd) + || (bMiddle >= aStart && bMiddle <= aEnd) + || (bEnd >= aStart && bEnd <= aEnd)); +} + +// Return true if rect |a| is below |b|. False otherwise. +static inline bool below(const IntRect& a, const IntRect& b) +{ + return a.y() > b.bottom(); +} + +// Return true if rect |a| is on the right of |b|. False otherwise. +static inline bool rightOf(const IntRect& a, const IntRect& b) +{ + return a.x() > b.right(); +} + +// * a = Current focused node's rect. +// * b = Focus candidate node's rect. +static long long spatialDistance(FocusDirection direction, const IntRect& a, const IntRect& b) +{ + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; + + if (direction == FocusDirectionLeft) { + // #1 |--| + // + // #2 |--| |--| + // + // #3 |--| + + x1 = a.x(); + x2 = b.right(); + + if (below(a, b)) { + // #1 The a rect is below b. + y1 = a.y(); + y2 = b.bottom(); + } else if (below(b, a)) { + // #3 The b rect is below a. + y1 = a.bottom(); + y2 = b.y(); + } else { + // #2 Both b and a share some common y's. + y1 = 0; + y2 = 0; + } + } else if (direction == FocusDirectionRight) { + // |--| #1 + // + // |--| |--| #2 + // + // |--| #3 + + x1 = a.right(); + x2 = b.x(); + + if (below(a, b)) { + // #1 The b rect is above a. + y1 = a.y(); + y2 = b.bottom(); + } else if (below(b, a)) { + // #3 The b rect is below a. + y1 = a.bottom(); + y2 = b.y(); + } else { + // #2 Both b and a share some common y's. + y1 = 0; + y2 = 0; + } + } else if (direction == FocusDirectionUp) { + // + // #1 #2 #3 + // + // |--| |--| |--| + // + // |--| + + y1 = a.y(); + y2 = b.bottom(); + + if (rightOf(a, b)) { + // #1 The b rect is to the left of a. + x1 = a.x(); + x2 = b.right(); + } else if (rightOf(b, a)) { + // #3 The b rect is to the right of a. + x1 = a.right(); + x2 = b.x(); + } else { + // #2 Both b and a share some common x's. + x1 = 0; + x2 = 0; + } + } else if (direction == FocusDirectionDown) { + // |--| + // + // |--| |--| |--| + // + // #1 #2 #3 + + y1 = a.bottom(); + y2 = b.y(); + + if (rightOf(a, b)) { + // #1 The b rect is to the left of a. + x1 = a.x(); + x2 = b.right(); + } else if (rightOf(b, a)) { + // #3 The b rect is to the right of a + x1 = a.right(); + x2 = b.x(); + } else { + // #2 Both b and a share some common x's. + x1 = 0; + x2 = 0; + } + } + + long long dx = x1 - x2; + long long dy = y1 - y2; + + long long distance = (dx * dx) + (dy * dy); + + if (distance < 0) + distance *= -1; + + return distance; +} + +static bool isRectInDirection(FocusDirection direction, const IntRect& curRect, const IntRect& targetRect) +{ + IntPoint center(targetRect.center()); + int targetMiddle = isHorizontalMove(direction) ? center.x() : center.y(); + + switch (direction) { + case FocusDirectionLeft: + return targetMiddle < curRect.x(); + case FocusDirectionRight: + return targetMiddle > curRect.right(); + case FocusDirectionUp: + return targetMiddle < curRect.y(); + case FocusDirectionDown: + return targetMiddle > curRect.bottom(); + default: + ASSERT_NOT_REACHED(); + } + + return false; +} + +// Checks if |node| is offscreen the visible area (viewport) of its container +// document. In case it is, one can scroll in direction or take any different +// desired action later on. +bool hasOffscreenRect(Node* node) +{ + // Get the FrameView in which |node| is (which means the current viewport if |node| + // is not in an inner document), so we can check if its content rect is visible + // before we actually move the focus to it. + FrameView* frameView = node->document()->view(); + if (!frameView) + return true; + + IntRect containerViewportRect = frameView->visibleContentRect(); + + RenderObject* render = node->renderer(); + if (!render) + return true; + + IntRect rect(render->absoluteClippedOverflowRect()); + return !containerViewportRect.intersects(rect); +} + +// In a bottom-up way, this method tries to scroll |frame| in a given direction +// |direction|, going up in the frame tree hierarchy in case it does not succeed. +bool scrollInDirection(Frame* frame, FocusDirection direction) +{ + if (!frame) + return false; + + ScrollDirection scrollDirection; + + switch (direction) { + case FocusDirectionLeft: + scrollDirection = ScrollLeft; + break; + case FocusDirectionRight: + scrollDirection = ScrollRight; + break; + case FocusDirectionUp: + scrollDirection = ScrollUp; + break; + case FocusDirectionDown: + scrollDirection = ScrollDown; + break; + default: + return false; + } + + return frame->eventHandler()->scrollRecursively(scrollDirection, ScrollByLine); +} + +void scrollIntoView(Element* element) +{ + // NOTE: Element's scrollIntoView method could had been used here, but + // it is preferable to inflate |element|'s bounding rect a bit before + // scrolling it for accurate reason. + // Element's scrollIntoView method does not provide this flexibility. + static const int fudgeFactor = 2; + IntRect bounds = element->getRect(); + bounds.inflate(fudgeFactor); + element->renderer()->enclosingLayer()->scrollRectToVisible(bounds); +} + +bool isInRootDocument(Node* node) +{ + if (!node) + return false; + + Document* rootDocument = node->document()->page()->mainFrame()->document(); + return node->document() == rootDocument; +} + +static void deflateIfOverlapped(IntRect& a, IntRect& b) +{ + if (!a.intersects(b) || a.contains(b) || b.contains(a)) + return; + + static const int fudgeFactor = -2; + + // Avoid negative width or height values. + if ((a.width() + 2 * fudgeFactor > 0) && (a.height() + 2 * fudgeFactor > 0)) + a.inflate(fudgeFactor); + + if ((b.width() + 2 * fudgeFactor > 0) && (b.height() + 2 * fudgeFactor > 0)) + b.inflate(fudgeFactor); +} + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/SpatialNavigation.h b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.h new file mode 100644 index 0000000..7c183df --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/SpatialNavigation.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2009 Antonio Gomes <tonikitoo@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SpatialNavigation_h +#define SpatialNavigation_h + +#include "FocusDirection.h" +#include "Node.h" + +#include <limits> + +namespace WebCore { + +class Element; +class Frame; +class IntRect; +class RenderObject; + +using namespace std; + +inline long long maxDistance() +{ + return numeric_limits<long long>::max(); +} + +// Spatially speaking, two given elements in a web page can be: +// 1) Fully aligned: There is a full intersection between the rects, either +// vertically or horizontally. +// +// * Horizontally * Vertically +// _ +// |_| _ _ _ _ _ _ +// |_|...... _ |_|_|_|_|_|_| +// |_| |_| . . +// |_|......|_| OR . . +// |_| |_| . . +// |_|......|_| _ _ _ _ +// |_| |_|_|_|_| +// +// +// 2) Partially aligned: There is a partial intersection between the rects, either +// vertically or horizontally. +// +// * Horizontally * Vertically +// _ _ _ _ _ _ +// |_| |_|_|_|_|_| +// |_|.... _ OR . . +// |_| |_| . . +// |_|....|_| ._._ _ +// |_| |_|_|_| +// |_| +// +// 3) Or, otherwise, not aligned at all. +// +// * Horizontally * Vertically +// _ _ _ _ _ +// |_| |_|_|_|_| +// |_| . +// |_| . +// . OR . +// _ . ._ _ _ _ _ +// |_| |_|_|_|_|_| +// |_| +// |_| +// +// "Totally Aligned" elements are preferable candidates to move +// focus to over "Partially Aligned" ones, that on its turns are +// more preferable than "Not Aligned". +enum RectsAlignment { + None = 0, + Partial, + Full +}; + +struct FocusCandidate { + FocusCandidate() + : node(0) + , distance(maxDistance()) + , parentDistance(maxDistance()) + , alignment(None) + , parentAlignment(None) + { + } + + FocusCandidate(Node* n) + : node(n) + , distance(maxDistance()) + , parentDistance(maxDistance()) + , alignment(None) + , parentAlignment(None) + { + } + + bool isNull() const { return !node; } + Document* document() const { return node ? node->document() : 0; } + + Node* node; + long long distance; + long long parentDistance; + RectsAlignment alignment; + RectsAlignment parentAlignment; +}; + +long long distanceInDirection(Node*, Node*, FocusDirection, FocusCandidate&); +bool scrollInDirection(Frame*, FocusDirection); +void scrollIntoView(Element*); +bool hasOffscreenRect(Node*); +bool isInRootDocument(Node*); + +} // namspace WebCore + +#endif // SpatialNavigation_h diff --git a/src/3rdparty/webkit/WebCore/page/UserScript.h b/src/3rdparty/webkit/WebCore/page/UserScript.h index dbbb879..8b3703f 100644 --- a/src/3rdparty/webkit/WebCore/page/UserScript.h +++ b/src/3rdparty/webkit/WebCore/page/UserScript.h @@ -34,16 +34,15 @@ namespace WebCore { -class UserScript { +class UserScript : public Noncopyable { public: UserScript(const String& source, const KURL& url, PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist, - unsigned worldID, UserScriptInjectionTime injectionTime) + UserScriptInjectionTime injectionTime) : m_source(source) , m_url(url) , m_whitelist(whitelist) , m_blacklist(blacklist) - , m_worldID(worldID) , m_injectionTime(injectionTime) { } @@ -52,7 +51,6 @@ public: const KURL& url() const { return m_url; } const Vector<String>* whitelist() const { return m_whitelist.get(); } const Vector<String>* blacklist() const { return m_blacklist.get(); } - unsigned worldID() const { return m_worldID; } UserScriptInjectionTime injectionTime() const { return m_injectionTime; } private: @@ -60,7 +58,6 @@ private: KURL m_url; OwnPtr<Vector<String> > m_whitelist; OwnPtr<Vector<String> > m_blacklist; - unsigned m_worldID; UserScriptInjectionTime m_injectionTime; }; diff --git a/src/3rdparty/webkit/WebCore/page/UserScriptTypes.h b/src/3rdparty/webkit/WebCore/page/UserScriptTypes.h index ac37662..ad27e79 100644 --- a/src/3rdparty/webkit/WebCore/page/UserScriptTypes.h +++ b/src/3rdparty/webkit/WebCore/page/UserScriptTypes.h @@ -33,10 +33,11 @@ namespace WebCore { enum UserScriptInjectionTime { InjectAtDocumentStart, InjectAtDocumentEnd }; +class DOMWrapperWorld; class UserScript; typedef Vector<OwnPtr<UserScript> > UserScriptVector; -typedef HashMap<unsigned, UserScriptVector*> UserScriptMap; +typedef HashMap<RefPtr<DOMWrapperWorld>, UserScriptVector*> UserScriptMap; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/UserStyleSheet.h b/src/3rdparty/webkit/WebCore/page/UserStyleSheet.h index 56bec40..610778f 100644 --- a/src/3rdparty/webkit/WebCore/page/UserStyleSheet.h +++ b/src/3rdparty/webkit/WebCore/page/UserStyleSheet.h @@ -34,16 +34,14 @@ namespace WebCore { -class UserStyleSheet { +class UserStyleSheet : public Noncopyable { public: UserStyleSheet(const String& source, const KURL& url, - PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist, - unsigned worldID) + PassOwnPtr<Vector<String> > whitelist, PassOwnPtr<Vector<String> > blacklist) : m_source(source) , m_url(url) , m_whitelist(whitelist) , m_blacklist(blacklist) - , m_worldID(worldID) { } @@ -51,14 +49,12 @@ public: const KURL& url() const { return m_url; } const Vector<String>* whitelist() const { return m_whitelist.get(); } const Vector<String>* blacklist() const { return m_blacklist.get(); } - unsigned worldID() const { return m_worldID; } private: String m_source; KURL m_url; OwnPtr<Vector<String> > m_whitelist; OwnPtr<Vector<String> > m_blacklist; - unsigned m_worldID; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/UserStyleSheetTypes.h b/src/3rdparty/webkit/WebCore/page/UserStyleSheetTypes.h index 094b2cf..ef662f2 100644 --- a/src/3rdparty/webkit/WebCore/page/UserStyleSheetTypes.h +++ b/src/3rdparty/webkit/WebCore/page/UserStyleSheetTypes.h @@ -31,10 +31,11 @@ namespace WebCore { +class DOMWrapperWorld; class UserStyleSheet; typedef Vector<OwnPtr<UserStyleSheet> > UserStyleSheetVector; -typedef HashMap<unsigned, UserStyleSheetVector*> UserStyleSheetMap; +typedef HashMap<RefPtr<DOMWrapperWorld>, UserStyleSheetVector*> UserStyleSheetMap; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/WebKitPoint.idl b/src/3rdparty/webkit/WebCore/page/WebKitPoint.idl index 1eefbc3..fd617b2 100644 --- a/src/3rdparty/webkit/WebCore/page/WebKitPoint.idl +++ b/src/3rdparty/webkit/WebCore/page/WebKitPoint.idl @@ -25,7 +25,7 @@ module window { - interface WebKitPoint { + interface [CustomConstructor] WebKitPoint { attribute float x; attribute float y; }; diff --git a/src/3rdparty/webkit/WebCore/page/WorkerNavigator.idl b/src/3rdparty/webkit/WebCore/page/WorkerNavigator.idl index 195f0bc..ec75f8a 100644 --- a/src/3rdparty/webkit/WebCore/page/WorkerNavigator.idl +++ b/src/3rdparty/webkit/WebCore/page/WorkerNavigator.idl @@ -30,7 +30,8 @@ module threads { interface [ Conditional=WORKERS, - NoStaticTables + NoStaticTables, + OmitConstructor ] WorkerNavigator { readonly attribute DOMString appName; readonly attribute DOMString appVersion; diff --git a/src/3rdparty/webkit/WebCore/page/XSSAuditor.cpp b/src/3rdparty/webkit/WebCore/page/XSSAuditor.cpp index 890c3fa..094f200 100644 --- a/src/3rdparty/webkit/WebCore/page/XSSAuditor.cpp +++ b/src/3rdparty/webkit/WebCore/page/XSSAuditor.cpp @@ -105,7 +105,12 @@ bool XSSAuditor::canEvaluate(const String& code) const if (!isEnabled()) return true; - if (findInRequest(code, false, true)) { + FindTask task; + task.string = code; + task.decodeEntities = false; + task.allowRequestIfNoIllegalURICharacters = true; + + if (findInRequest(task)) { DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n")); m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); return false; @@ -118,7 +123,11 @@ bool XSSAuditor::canEvaluateJavaScriptURL(const String& code) const if (!isEnabled()) return true; - if (findInRequest(code, true, false, true)) { + FindTask task; + task.string = code; + task.decodeURLEscapeSequencesTwice = true; + + if (findInRequest(task)) { DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n")); m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); return false; @@ -131,7 +140,11 @@ bool XSSAuditor::canCreateInlineEventListener(const String&, const String& code) if (!isEnabled()) return true; - if (findInRequest(code, true, true)) { + FindTask task; + task.string = code; + task.allowRequestIfNoIllegalURICharacters = true; + + if (findInRequest(task)) { DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n")); m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); return false; @@ -144,17 +157,14 @@ bool XSSAuditor::canLoadExternalScriptFromSrc(const String& context, const Strin if (!isEnabled()) return true; - // If the script is loaded from the same URL as the enclosing page, it's - // probably not an XSS attack, so we reduce false positives by allowing the - // script. If the script has a query string, we're more suspicious, - // however, because that's pretty rare and the attacker might be able to - // trick a server-side script into doing something dangerous with the query - // string. - KURL scriptURL(m_frame->document()->url(), url); - if (m_frame->document()->url().host() == scriptURL.host() && scriptURL.query().isEmpty()) + if (isSameOriginResource(url)) return true; - if (findInRequest(context + url)) { + FindTask task; + task.context = context; + task.string = url; + + if (findInRequest(task)) { DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n")); m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); return false; @@ -167,8 +177,15 @@ bool XSSAuditor::canLoadObject(const String& url) const if (!isEnabled()) return true; - if (findInRequest(url)) { - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request")); + if (isSameOriginResource(url)) + return true; + + FindTask task; + task.string = url; + task.allowRequestIfNoIllegalURICharacters = true; + + if (findInRequest(task)) { + String consoleMessage = String::format("Refused to load an object. URL found within request: \"%s\".\n", url.utf8().data()); m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); return false; } @@ -179,10 +196,16 @@ bool XSSAuditor::canSetBaseElementURL(const String& url) const { if (!isEnabled()) return true; - - KURL baseElementURL(m_frame->document()->url(), url); - if (m_frame->document()->url().host() != baseElementURL.host() && findInRequest(url)) { - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request")); + + if (isSameOriginResource(url)) + return true; + + FindTask task; + task.string = url; + task.allowRequestIfNoIllegalURICharacters = true; + + if (findInRequest(task)) { + DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to load from document base URL. URL found within request.\n")); m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String()); return false; } @@ -255,20 +278,61 @@ String XSSAuditor::decodeHTMLEntities(const String& string, bool leaveUndecodabl return String::adopt(result); } -bool XSSAuditor::findInRequest(const String& string, bool decodeEntities, bool allowRequestIfNoIllegalURICharacters, - bool decodeURLEscapeSequencesTwice) const +bool XSSAuditor::isSameOriginResource(const String& url) const +{ + // If the resource is loaded from the same URL as the enclosing page, it's + // probably not an XSS attack, so we reduce false positives by allowing the + // request. If the resource has a query string, we're more suspicious, + // however, because that's pretty rare and the attacker might be able to + // trick a server-side script into doing something dangerous with the query + // string. + KURL resourceURL(m_frame->document()->url(), url); + return (m_frame->document()->url().host() == resourceURL.host() && resourceURL.query().isEmpty()); +} + +XSSProtectionDisposition XSSAuditor::xssProtection() const +{ + DEFINE_STATIC_LOCAL(String, XSSProtectionHeader, ("X-XSS-Protection")); + + Frame* frame = m_frame; + if (frame->document()->url() == blankURL()) + frame = m_frame->tree()->parent(); + + return parseXSSProtectionHeader(frame->loader()->documentLoader()->response().httpHeaderField(XSSProtectionHeader)); +} + +bool XSSAuditor::findInRequest(const FindTask& task) const { bool result = false; Frame* parentFrame = m_frame->tree()->parent(); + Frame* blockFrame = parentFrame; if (parentFrame && m_frame->document()->url() == blankURL()) - result = findInRequest(parentFrame, string, decodeEntities, allowRequestIfNoIllegalURICharacters, decodeURLEscapeSequencesTwice); + result = findInRequest(parentFrame, task); + if (!result) { + result = findInRequest(m_frame, task); + blockFrame = m_frame; + } if (!result) - result = findInRequest(m_frame, string, decodeEntities, allowRequestIfNoIllegalURICharacters, decodeURLEscapeSequencesTwice); - return result; + return false; + + switch (xssProtection()) { + case XSSProtectionDisabled: + return false; + case XSSProtectionEnabled: + break; + case XSSProtectionBlockEnabled: + if (blockFrame) { + blockFrame->loader()->stopAllLoaders(); + blockFrame->redirectScheduler()->scheduleLocationChange(blankURL(), String()); + } + break; + default: + ASSERT_NOT_REACHED(); + } + return true; } -bool XSSAuditor::findInRequest(Frame* frame, const String& string, bool decodeEntities, bool allowRequestIfNoIllegalURICharacters, - bool decodeURLEscapeSequencesTwice) const +bool XSSAuditor::findInRequest(Frame* frame, const FindTask& task) const { ASSERT(frame->document()); @@ -277,17 +341,19 @@ bool XSSAuditor::findInRequest(Frame* frame, const String& string, bool decodeEn return false; } - if (string.isEmpty()) + if (task.string.isEmpty()) return false; FormData* formDataObj = frame->loader()->documentLoader()->originalRequest().httpBody(); + const bool hasFormData = formDataObj && !formDataObj->isEmpty(); String pageURL = frame->document()->url().string(); - if (!formDataObj && string.length() >= 2 * pageURL.length()) { + String canonicalizedString; + if (!hasFormData && task.string.length() > 2 * pageURL.length()) { // Q: Why do we bother to do this check at all? // A: Canonicalizing large inline scripts can be expensive. We want to - // bail out before the call to canonicalize below, which could - // result in an unneeded allocation and memcpy. + // reduce the size of the string before we call canonicalize below, + // since it could result in an unneeded allocation and memcpy. // // Q: Why do we multiply by two here? // A: We attempt to detect reflected XSS even when the server @@ -295,39 +361,32 @@ bool XSSAuditor::findInRequest(Frame* frame, const String& string, bool decodeEn // attacker can do get the server to inflate his/her input by a // factor of two by sending " characters, which the server // transforms to \". - return false; - } + canonicalizedString = task.string.substring(0, 2 * pageURL.length()); + } else + canonicalizedString = task.string; if (frame->document()->url().protocolIs("data")) return false; - String canonicalizedString = canonicalize(string); + canonicalizedString = canonicalize(canonicalizedString); if (canonicalizedString.isEmpty()) return false; - if (string.length() < pageURL.length()) { - // The string can actually fit inside the pageURL. - String decodedPageURL = m_cache.canonicalizeURL(pageURL, frame->document()->decoder()->encoding(), decodeEntities, decodeURLEscapeSequencesTwice); + if (!task.context.isEmpty()) + canonicalizedString = task.context + canonicalizedString; - if (allowRequestIfNoIllegalURICharacters && (!formDataObj || formDataObj->isEmpty()) - && decodedPageURL.find(&isIllegalURICharacter, 0) == -1) - return false; // Injection is impossible because the request does not contain any illegal URI characters. + String decodedPageURL = m_pageURLCache.canonicalizeURL(pageURL, frame->document()->decoder()->encoding(), task.decodeEntities, task.decodeURLEscapeSequencesTwice); - if (decodedPageURL.find(canonicalizedString, 0, false) != -1) - return true; // We've found the smoking gun. - } + if (task.allowRequestIfNoIllegalURICharacters && !hasFormData && decodedPageURL.find(&isIllegalURICharacter, 0) == -1) + return false; // Injection is impossible because the request does not contain any illegal URI characters. - if (formDataObj && !formDataObj->isEmpty()) { - String formData = formDataObj->flattenToString(); - if (string.length() < formData.length()) { - // Notice it is sufficient to compare the length of the string to - // the url-encoded POST data because the length of the url-decoded - // code is less than or equal to the length of the url-encoded - // string. - String decodedFormData = m_cache.canonicalizeURL(formData, frame->document()->decoder()->encoding(), decodeEntities, decodeURLEscapeSequencesTwice); - if (decodedFormData.find(canonicalizedString, 0, false) != -1) - return true; // We found the string in the POST data. - } + if (decodedPageURL.find(canonicalizedString, 0, false) != -1) + return true; // We've found the string in the GET data. + + if (hasFormData) { + String decodedFormData = m_formDataCache.canonicalizeURL(formDataObj->flattenToString(), frame->document()->decoder()->encoding(), task.decodeEntities, task.decodeURLEscapeSequencesTwice); + if (decodedFormData.find(canonicalizedString, 0, false) != -1) + return true; // We found the string in the POST data. } return false; diff --git a/src/3rdparty/webkit/WebCore/page/XSSAuditor.h b/src/3rdparty/webkit/WebCore/page/XSSAuditor.h index adfa5c7..a7628f3 100644 --- a/src/3rdparty/webkit/WebCore/page/XSSAuditor.h +++ b/src/3rdparty/webkit/WebCore/page/XSSAuditor.h @@ -27,6 +27,7 @@ #ifndef XSSAuditor_h #define XSSAuditor_h +#include "HTTPParsers.h" #include "PlatformString.h" #include "TextEncoding.h" @@ -36,34 +37,37 @@ namespace WebCore { class ScriptSourceCode; // The XSSAuditor class is used to prevent type 1 cross-site scripting - // vulnerabilites (also known as reflected vulnerabilities). + // vulnerabilities (also known as reflected vulnerabilities). // // More specifically, the XSSAuditor class decides whether the execution of // a script is to be allowed or denied based on the content of any // user-submitted data, including: // - // * the query string of the URL. + // * the URL. // * the HTTP-POST data. // // If the source code of a script resembles any user-submitted data then it // is denied execution. // - // When you instantiate the XSSAuditor you must specify the {@link Frame} - // of the page that you wish to audit. + // When you instantiate the XSSAuditor you must specify the Frame of the + // page that you wish to audit. // // Bindings // - // An XSSAuditor is instantiated within the contructor of a + // An XSSAuditor is instantiated within the constructor of a // ScriptController object and passed the Frame the script originated. The // ScriptController calls back to the XSSAuditor to determine whether a // JavaScript script is safe to execute before executing it. The following // methods call into XSSAuditor: // - // * ScriptController::evaluate - used to evaluate JavaScript scripts. - // * ScriptController::createInlineEventListener - used to create JavaScript event handlers. - // * HTMLTokenizer::scriptHandler - used to load external JavaScript scripts. + // * ScriptController::evaluateInWorld - used to evaluate JavaScript scripts. + // * ScriptController::executeIfJavaScriptURL - used to evaluate JavaScript URLs. + // * ScriptEventListener::createAttributeEventListener - used to create JavaScript event handlers. + // * HTMLBaseElement::process - used to set the document base URL. + // * HTMLTokenizer::parseTag - used to load external JavaScript scripts. + // * FrameLoader::requestObject - used to load <object>/<embed> elements. // - class XSSAuditor { + class XSSAuditor : public Noncopyable { public: XSSAuditor(Frame*); ~XSSAuditor(); @@ -117,21 +121,43 @@ namespace WebCore { String m_cachedCanonicalizedURL; }; + struct FindTask { + FindTask() + : decodeEntities(true) + , allowRequestIfNoIllegalURICharacters(false) + , decodeURLEscapeSequencesTwice(false) + { + } + + String context; + String string; + bool decodeEntities; + bool allowRequestIfNoIllegalURICharacters; + bool decodeURLEscapeSequencesTwice; + }; + static String canonicalize(const String&); static String decodeURL(const String& url, const TextEncoding& encoding, bool decodeEntities, bool decodeURLEscapeSequencesTwice = false); static String decodeHTMLEntities(const String&, bool leaveUndecodableEntitiesUntouched = true); - bool findInRequest(const String&, bool decodeEntities = true, bool allowRequestIfNoIllegalURICharacters = false, - bool decodeURLEscapeSequencesTwice = false) const; - bool findInRequest(Frame*, const String&, bool decodeEntities = true, bool allowRequestIfNoIllegalURICharacters = false, - bool decodeURLEscapeSequencesTwice = false) const; + bool isSameOriginResource(const String& url) const; + bool findInRequest(const FindTask&) const; + bool findInRequest(Frame*, const FindTask&) const; + + XSSProtectionDisposition xssProtection() const; // The frame to audit. Frame* m_frame; // A state store to help us avoid canonicalizing the same URL repeated. - mutable CachingURLCanonicalizer m_cache; + // When a page has form data, we need two caches: one to store the + // canonicalized URL and another to store the cannonicalized form + // data. If we only had one cache, we'd always generate a cache miss + // and load some pages extremely slowly. + // https://bugs.webkit.org/show_bug.cgi?id=35373 + mutable CachingURLCanonicalizer m_pageURLCache; + mutable CachingURLCanonicalizer m_formDataCache; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/ZoomMode.h b/src/3rdparty/webkit/WebCore/page/ZoomMode.h new file mode 100644 index 0000000..3f02184 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/ZoomMode.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Research in Motion Ltd. http://www.rim.com/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef ZoomMode_h +#define ZoomMode_h + +namespace WebCore { + +enum ZoomMode { + ZoomPage, + ZoomTextOnly +}; + +} + +#endif diff --git a/src/3rdparty/webkit/WebCore/page/android/EventHandlerAndroid.cpp b/src/3rdparty/webkit/WebCore/page/android/EventHandlerAndroid.cpp deleted file mode 100644 index cf2acfb..0000000 --- a/src/3rdparty/webkit/WebCore/page/android/EventHandlerAndroid.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Zack Rusin <zack@kde.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#define LOG_TAG "WebCore" - -#include "config.h" -#include "EventHandler.h" - -#include "FocusController.h" -#include "Frame.h" -#include "KeyboardEvent.h" -#include "MouseEventWithHitTestResults.h" -#include "Page.h" -#include "PlatformKeyboardEvent.h" -#include "PlatformWheelEvent.h" -#include "RenderWidget.h" - -namespace WebCore { - -unsigned EventHandler::s_accessKeyModifiers = PlatformKeyboardEvent::AltKey; - -bool EventHandler::tabsToAllControls(KeyboardEvent*) const -{ - return true; -} - -void EventHandler::focusDocumentView() -{ - if (Page* page = m_frame->page()) - page->focusController()->setFocusedFrame(m_frame); -} - -bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event) -{ - // Figure out which view to send the event to. - RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : 0; - if (!target || !target->isWidget()) - return false; - return passMouseDownEventToWidget(toRenderWidget(target)->widget()); -} - -bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget) -{ - return passMouseDownEventToWidget(renderWidget->widget()); -} - -// This function is used to route the mouse down event to the native widgets, it seems like a -// work around for the Mac platform which does not support double clicks, but browsers do. -bool EventHandler::passMouseDownEventToWidget(Widget*) -{ - // return false so the normal propogation handles the event - return false; -} - -bool EventHandler::eventActivatedView(const PlatformMouseEvent&) const -{ - notImplemented(); - return false; -} - -// This function is called for mouse events by FrameView::handleMousePressEvent(). -// It is used to ensure that events are sync'ed correctly between frames. For example -// if the user presses down in one frame and up in another frame, this function will -// returns true, and pass the event to the correct frame. -bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults&, Frame*, HitTestResult*) -{ - notImplemented(); - return false; -} - -// This is called to route wheel events to child widgets when they are RenderWidget -// as the parent usually gets wheel event. Don't have a mouse with a wheel to confirm -// the operation of this function. -bool EventHandler::passWheelEventToWidget(PlatformWheelEvent&, Widget*) -{ - notImplemented(); - return false; -} - -bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) -{ - return passSubframeEventToSubframe(mev, subframe); -} - -bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, - Frame* subframe, HitTestResult*) -{ - return passSubframeEventToSubframe(mev, subframe); -} - -bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) -{ - return passSubframeEventToSubframe(mev, subframe); -} - -class Clipboard : public RefCounted<Clipboard> { -}; - -PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const -{ - return PassRefPtr<Clipboard>(0); -} - -const double EventHandler::TextDragDelay = 0.0; - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/android/InspectorControllerAndroid.cpp b/src/3rdparty/webkit/WebCore/page/android/InspectorControllerAndroid.cpp deleted file mode 100644 index 978bc25..0000000 --- a/src/3rdparty/webkit/WebCore/page/android/InspectorControllerAndroid.cpp +++ /dev/null @@ -1,106 +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. - */ - -#include "config.h" -#include "InspectorController.h" - -#include "Frame.h" -#include "Node.h" -#include "Profile.h" - -// This stub file was created to avoid building and linking in all the -// Inspector codebase. If you would like to enable the Inspector, do the -// following steps: -// 1. Replace this file in WebCore/Android.mk with the common -// implementation, ie page/InsepctorController.cpp -// 2. Add the JS API files to JavaScriptCore/Android.mk: -// ? API/JSBase.cpp \ -// API/JSCallbackConstructor.cpp \ -// API/JSCallbackFunction.cpp \ -// API/JSCallbackObject.cpp \ -// API/JSClassRef.cpp \ -// API/JSContextRef.cpp \ -// API/JSObjectRef.cpp \ -// API/JSStringRef.cpp \ -// API/JSValueRef.cpp -// 3. Add the following LOCAL_C_INCLUDES to JavaScriptCore/Android.mk: -// ?$(LOCAL_PATH)/API \ -// $(LOCAL_PATH)/ForwardingHeaders \ -// $(LOCAL_PATH)/../../WebKit \ -// 4. Rebuild WebKit -// -// Note, for a functional Inspector, you must implement InspectorClientAndroid. - -namespace WebCore { - -struct InspectorResource : public RefCounted<InspectorResource> { -}; - -struct InspectorDatabaseResource : public RefCounted<InspectorDatabaseResource> { -}; - -InspectorController::InspectorController(Page*, InspectorClient*) - : m_startProfiling(this, 0) -{ -} - -InspectorController::~InspectorController() {} - -void InspectorController::windowScriptObjectAvailable() {} -void InspectorController::didCommitLoad(DocumentLoader*) {} -void InspectorController::identifierForInitialRequest(unsigned long, DocumentLoader*, ResourceRequest const&) {} -void InspectorController::willSendRequest(DocumentLoader*, unsigned long, ResourceRequest&, ResourceResponse const&) {} -void InspectorController::didReceiveResponse(DocumentLoader*, unsigned long, ResourceResponse const&) {} -void InspectorController::didReceiveContentLength(DocumentLoader*, unsigned long, int) {} -void InspectorController::didFinishLoading(DocumentLoader*, unsigned long) {} -void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader*, ResourceRequest const&, ResourceResponse const&, int) {} -void InspectorController::frameDetachedFromParent(Frame*) {} - -void InspectorController::addMessageToConsole(MessageSource, MessageLevel, JSC::ExecState*, JSC::ArgList const&, unsigned int, String const&) {} -void InspectorController::addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID) {} -#if ENABLE(DATABASE) -void InspectorController::didOpenDatabase(Database*, String const&, String const&, String const&) {} -#endif -bool InspectorController::enabled() const { return false; } -void InspectorController::inspect(Node*) {} -bool InspectorController::windowVisible() { return false; } -void InspectorController::addProfile(PassRefPtr<JSC::Profile>, unsigned int, const JSC::UString&) {} -void InspectorController::inspectedPageDestroyed() {} -void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, JSC::UString& sourceString) {} - -void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame) {} -void InspectorController::startGroup(MessageSource source, JSC::ExecState* exec, const JSC::ArgList& arguments, unsigned lineNumber, const String& sourceURL) {} -void InspectorController::endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL) {} -void InspectorController::startTiming(const JSC::UString& title) {} -bool InspectorController::stopTiming(const JSC::UString& title, double& elapsed) { return false; } -void InspectorController::count(const JSC::UString& title, unsigned lineNumber, const String& sourceID) {} - -void InspectorController::mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags) {} -void InspectorController::handleMousePressOnNode(Node*) {} -void InspectorController::failedToParseSource(JSC::ExecState* exec, const JSC::SourceCode& source, int errorLine, const JSC::UString& errorMessage) {} -void InspectorController::didParseSource(JSC::ExecState* exec, const JSC::SourceCode& source) {} -void InspectorController::didPause() {} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp index 59797da..c2d70ef 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp @@ -92,10 +92,17 @@ static inline Color blendFunc(const AnimationBase* anim, const Color& from, cons if (progress == 1 && !to.isValid()) return Color(); - return Color(blendFunc(anim, from.red(), to.red(), progress), - blendFunc(anim, from.green(), to.green(), progress), - blendFunc(anim, from.blue(), to.blue(), progress), - blendFunc(anim, from.alpha(), to.alpha(), progress)); + // Contrary to the name, RGBA32 actually stores ARGB, so we can initialize Color directly from premultipliedARGBFromColor(). + // Also, premultipliedARGBFromColor() bails on zero alpha, so special-case that. + Color premultFrom = from.alpha() ? premultipliedARGBFromColor(from) : 0; + Color premultTo = to.alpha() ? premultipliedARGBFromColor(to) : 0; + + Color premultBlended(blendFunc(anim, premultFrom.red(), premultTo.red(), progress), + blendFunc(anim, premultFrom.green(), premultTo.green(), progress), + blendFunc(anim, premultFrom.blue(), premultTo.blue(), progress), + blendFunc(anim, premultFrom.alpha(), premultTo.alpha(), progress)); + + return Color(colorFromPremultipliedARGB(premultBlended.rgb())); } static inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress) @@ -190,7 +197,7 @@ class PropertyWrapperBase; static void addShorthandProperties(); static PropertyWrapperBase* wrapperForProperty(int propertyID); -class PropertyWrapperBase { +class PropertyWrapperBase : public Noncopyable { public: PropertyWrapperBase(int prop) : m_prop(prop) @@ -407,7 +414,7 @@ public: }; template <typename T> -class FillLayerPropertyWrapperGetter : public FillLayerPropertyWrapperBase { +class FillLayerPropertyWrapperGetter : public FillLayerPropertyWrapperBase, public Noncopyable { public: FillLayerPropertyWrapperGetter(T (FillLayer::*getter)() const) : m_getter(getter) @@ -863,7 +870,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) m_pauseTime = -1; m_requestedStartTime = 0; m_nextIterationDuration = -1; - endAnimation(false); + endAnimation(); return; } @@ -875,7 +882,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) m_pauseTime = -1; m_requestedStartTime = 0; m_nextIterationDuration = -1; - endAnimation(false); + endAnimation(); if (!paused()) updateStateMachine(AnimationStateInputStartAnimation, -1); @@ -886,7 +893,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (m_animState == AnimationStateStartWaitStyleAvailable) m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); m_animState = AnimationStateDone; - endAnimation(true); + endAnimation(); return; } @@ -894,7 +901,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (m_animState == AnimationStateStartWaitResponse) { // If we are in AnimationStateStartWaitResponse, the animation will get canceled before // we get a response, so move to the next state. - endAnimation(false); + endAnimation(); updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); } return; @@ -903,7 +910,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (input == AnimationStateInputResumeOverride) { if (m_animState == AnimationStateLooping || m_animState == AnimationStateEnding) { // Start the animation - startAnimation(m_startTime); + startAnimation(beginAnimationUpdateTime() - m_startTime); } return; } @@ -911,8 +918,8 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) // Execute state machine switch (m_animState) { case AnimationStateNew: - ASSERT(input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunnning || input == AnimationStateInputPlayStatePaused); - if (input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunnning) { + ASSERT(input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning || input == AnimationStateInputPlayStatePaused); + if (input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning) { m_requestedStartTime = beginAnimationUpdateTime(); m_animState = AnimationStateStartWaitTimer; } @@ -956,7 +963,12 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); } else { - bool started = startAnimation(0); + double timeOffset = 0; + // If the value for 'animation-delay' is negative then the animation appears to have started in the past. + if (m_animation->delay() < 0) + timeOffset = -m_animation->delay(); + bool started = startAnimation(timeOffset); + m_compAnim->animationController()->addToStartTimeResponseWaitList(this, started); m_fallbackAnimating = !started; } @@ -967,8 +979,12 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (input == AnimationStateInputStartTimeSet) { ASSERT(param >= 0); // We have a start time, set it, unless the startTime is already set - if (m_startTime <= 0) + if (m_startTime <= 0) { m_startTime = param; + // If the value for 'animation-delay' is negative then the animation appears to have started in the past. + if (m_animation->delay() < 0) + m_startTime += m_animation->delay(); + } // Decide whether to go into looping or ending state goIntoEndingOrLoopingState(); @@ -980,7 +996,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) // We are pausing while waiting for a start response. Cancel the animation and wait. When // we unpause, we will act as though the start timer just fired m_pauseTime = -1; - endAnimation(false); + pauseAnimation(beginAnimationUpdateTime() - m_startTime); m_animState = AnimationStatePausedWaitResponse; } break; @@ -997,7 +1013,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) } else { // We are pausing while running. Cancel the animation and wait m_pauseTime = beginAnimationUpdateTime(); - endAnimation(false); + pauseAnimation(beginAnimationUpdateTime() - m_startTime); m_animState = AnimationStatePausedRun; } break; @@ -1005,6 +1021,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) ASSERT(input == AnimationStateInputEndTimerFired || input == AnimationStateInputPlayStatePaused); if (input == AnimationStateInputEndTimerFired) { + ASSERT(param >= 0); // End timer fired, finish up onAnimationEnd(param); @@ -1012,7 +1029,10 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) m_animState = AnimationStateDone; if (m_object) { - resumeOverriddenAnimations(); + if (m_animation->fillsForwards()) + m_animState = AnimationStateFillingForwards; + else + resumeOverriddenAnimations(); // Fire off another style change so we can set the final value m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); @@ -1020,13 +1040,13 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) } else { // We are pausing while running. Cancel the animation and wait m_pauseTime = beginAnimationUpdateTime(); - endAnimation(false); + pauseAnimation(beginAnimationUpdateTime() - m_startTime); m_animState = AnimationStatePausedRun; } // |this| may be deleted here break; case AnimationStatePausedWaitTimer: - ASSERT(input == AnimationStateInputPlayStateRunnning); + ASSERT(input == AnimationStateInputPlayStateRunning); ASSERT(paused()); // Update the times m_startTime += beginAnimationUpdateTime() - m_pauseTime; @@ -1042,7 +1062,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) // AnimationStatePausedWaitResponse, we don't yet have a valid startTime, so we send 0 to startAnimation. // When the AnimationStateInputStartTimeSet comes in and we were in AnimationStatePausedRun, we will notice // that we have already set the startTime and will ignore it. - ASSERT(input == AnimationStateInputPlayStateRunnning || input == AnimationStateInputStartTimeSet); + ASSERT(input == AnimationStateInputPlayStateRunning || input == AnimationStateInputStartTimeSet); ASSERT(paused()); // If we are paused, but we get the callback that notifies us that an accelerated animation started, @@ -1072,11 +1092,12 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); m_fallbackAnimating = true; } else { - bool started = startAnimation(m_startTime); + bool started = startAnimation(beginAnimationUpdateTime() - m_startTime); m_compAnim->animationController()->addToStartTimeResponseWaitList(this, started); m_fallbackAnimating = !started; } break; + case AnimationStateFillingForwards: case AnimationStateDone: // We're done. Stay in this state until we are deleted break; @@ -1136,14 +1157,14 @@ void AnimationBase::fireAnimationEventsIfNeeded() void AnimationBase::updatePlayState(bool run) { if (paused() == run || isNew()) - updateStateMachine(run ? AnimationStateInputPlayStateRunnning : AnimationStateInputPlayStatePaused, -1); + updateStateMachine(run ? AnimationStateInputPlayStateRunning : AnimationStateInputPlayStatePaused, -1); } double AnimationBase::timeToNextService() { // Returns the time at which next service is required. -1 means no service is required. 0 means // service is required now, and > 0 means service is required that many seconds in the future. - if (paused() || isNew()) + if (paused() || isNew() || m_animState == AnimationStateFillingForwards) return -1; if (m_animState == AnimationStateStartWaitTimer) { @@ -1168,8 +1189,10 @@ double AnimationBase::progress(double scale, double offset, const TimingFunction if (m_animation->iterationCount() > 0) dur *= m_animation->iterationCount(); - if (postActive() || !m_animation->duration() || (m_animation->iterationCount() > 0 && elapsedTime >= dur)) + if (postActive() || !m_animation->duration()) return 1.0; + if (m_animation->iterationCount() > 0 && elapsedTime >= dur) + return (m_animation->iterationCount() % 2) ? 1.0 : 0.0; // Compute the fractional time, taking into account direction. // There is no need to worry about iterations, we assume that we would have diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h index 3482f65..a957119 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h @@ -71,7 +71,8 @@ public: AnimationStatePausedWaitTimer, // in pause mode when animation started AnimationStatePausedWaitResponse, // animation paused when in STARTING state AnimationStatePausedRun, // animation paused when in LOOPING or ENDING state - AnimationStateDone // end timer fired, animation finished and removed + AnimationStateDone, // end timer fired, animation finished and removed + AnimationStateFillingForwards // animation has ended and is retaining its final value }; enum AnimStateInput { @@ -85,7 +86,7 @@ public: AnimationStateInputEndTimerFired, // end timer fired AnimationStateInputPauseOverride, // pause an animation due to override AnimationStateInputResumeOverride, // resume an overridden animation - AnimationStateInputPlayStateRunnning, // play state paused -> running + AnimationStateInputPlayStateRunning, // play state paused -> running AnimationStateInputPlayStatePaused, // play state running -> paused AnimationStateInputEndAnimation // force an end from any state }; @@ -186,8 +187,13 @@ protected: virtual void onAnimationStart(double /*elapsedTime*/) { } virtual void onAnimationIteration(double /*elapsedTime*/) { } virtual void onAnimationEnd(double /*elapsedTime*/) { } - virtual bool startAnimation(double /*beginTime*/) { return false; } - virtual void endAnimation(bool /*reset*/) { } + + // timeOffset is an offset from the current time when the animation should start. Negative values are OK. + // Return value indicates whether to expect an asynchronous notifyAnimationStarted() callback. + virtual bool startAnimation(double /*timeOffset*/) { return false; } + // timeOffset is the time at which the animation is being paused. + virtual void pauseAnimation(double /*timeOffset*/) { } + virtual void endAnimation() { } void goIntoEndingOrLoopingState(); diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp index aa5de2c..cb609a5 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp @@ -134,6 +134,9 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*) { + // Protect the frame from getting destroyed in the event handler + RefPtr<Frame> protector = m_frame; + // fire all the events Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end(); for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) { @@ -484,7 +487,7 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend m_data->updateAnimationTimer(); if (blendedStyle != newStyle) { - // If the animations/transitions change opacity or transform, we neeed to update + // If the animations/transitions change opacity or transform, we need to update // the style to impose the stacking rules. Note that this is also // done in CSSStyleSelector::adjustRenderStyle(). if (blendedStyle->hasAutoZIndex() && (blendedStyle->opacity() < 1.0f || blendedStyle->hasTransform())) diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationControllerPrivate.h b/src/3rdparty/webkit/WebCore/page/animation/AnimationControllerPrivate.h index 7db3803..682dd75 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationControllerPrivate.h +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationControllerPrivate.h @@ -49,7 +49,7 @@ class Node; class RenderObject; class RenderStyle; -class AnimationControllerPrivate { +class AnimationControllerPrivate : public Noncopyable { public: AnimationControllerPrivate(Frame*); ~AnimationControllerPrivate(); diff --git a/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.cpp b/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.cpp index 8946d80..34f03c7 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.cpp @@ -57,6 +57,7 @@ void CompositeAnimation::clearRenderer() } } if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* anim = it->second.get(); @@ -186,6 +187,8 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render if (m_keyframeAnimations.isEmpty() && !targetStyle->hasAnimations()) return; + m_keyframeAnimations.checkConsistency(); + AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations())) { @@ -262,6 +265,7 @@ PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, Rend // We don't do any transitions if we don't have a currentStyle (on startup). updateTransitions(renderer, currentStyle, targetStyle); updateKeyframeAnimations(renderer, currentStyle, targetStyle); + m_keyframeAnimations.checkConsistency(); if (currentStyle) { // Now that we have transition objects ready, let them know about the new goal state. We want them @@ -295,6 +299,8 @@ PassRefPtr<RenderStyle> CompositeAnimation::getAnimatedStyle() const implicitAnimation->getAnimatedStyle(resultStyle); } + m_keyframeAnimations.checkConsistency(); + for (Vector<AtomicStringImpl*>::const_iterator it = m_keyframeAnimationOrderMap.begin(); it != m_keyframeAnimationOrderMap.end(); ++it) { RefPtr<KeyframeAnimation> keyframeAnimation = m_keyframeAnimations.get(*it); if (keyframeAnimation) @@ -315,6 +321,7 @@ void CompositeAnimation::setAnimating(bool animating) } } if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* anim = it->second.get(); @@ -341,6 +348,7 @@ double CompositeAnimation::timeToNextService() const } } if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* animation = it->second.get(); @@ -362,6 +370,7 @@ PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int pr // We want to send back the last animation with the property if there are multiples. // So we need to iterate through all animations if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { RefPtr<KeyframeAnimation> anim = it->second; @@ -381,6 +390,7 @@ void CompositeAnimation::suspendAnimations() m_isSuspended = true; if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { if (KeyframeAnimation* anim = it->second.get()) @@ -405,6 +415,7 @@ void CompositeAnimation::resumeAnimations() m_isSuspended = false; if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* anim = it->second.get(); @@ -450,6 +461,7 @@ void CompositeAnimation::resumeOverriddenImplicitAnimations(int property) bool CompositeAnimation::isAnimatingProperty(int property, bool isRunningNow) const { if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* anim = it->second.get(); @@ -474,6 +486,8 @@ bool CompositeAnimation::pauseAnimationAtTime(const AtomicString& name, double t if (!name) return false; + m_keyframeAnimations.checkConsistency(); + RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(name.impl()); if (!keyframeAnim || !keyframeAnim->running()) return false; @@ -509,6 +523,7 @@ unsigned CompositeAnimation::numberOfActiveAnimations() const unsigned count = 0; if (!m_keyframeAnimations.isEmpty()) { + m_keyframeAnimations.checkConsistency(); AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* anim = it->second.get(); diff --git a/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.cpp b/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.cpp index 50fc781..328fe0e 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.cpp @@ -55,7 +55,7 @@ ImplicitAnimation::~ImplicitAnimation() { // // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. if (!postActive()) - endAnimation(true); + endAnimation(); } bool ImplicitAnimation::shouldSendEventForListener(Document::ListenerType inListenerType) const @@ -106,21 +106,21 @@ void ImplicitAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle) blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); } -bool ImplicitAnimation::startAnimation(double beginTime) +bool ImplicitAnimation::startAnimation(double timeOffset) { #if USE(ACCELERATED_COMPOSITING) if (m_object && m_object->hasLayer()) { RenderLayer* layer = toRenderBoxModelObject(m_object)->layer(); if (layer->isComposited()) - return layer->backing()->startTransition(beginTime, m_animatingProperty, m_fromStyle.get(), m_toStyle.get()); + return layer->backing()->startTransition(timeOffset, m_animatingProperty, m_fromStyle.get(), m_toStyle.get()); } #else - UNUSED_PARAM(beginTime); + UNUSED_PARAM(timeOffset); #endif return false; } -void ImplicitAnimation::endAnimation(bool /*reset*/) +void ImplicitAnimation::endAnimation() { #if USE(ACCELERATED_COMPOSITING) if (m_object && m_object->hasLayer()) { @@ -143,7 +143,7 @@ void ImplicitAnimation::onAnimationEnd(double elapsedTime) keyframeAnim->setUnanimatedStyle(m_toStyle); sendTransitionEvent(eventNames().webkitTransitionEndEvent, elapsedTime); - endAnimation(true); + endAnimation(); } bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, double elapsedTime) @@ -161,7 +161,7 @@ bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, doubl if (m_object->node() && m_object->node()->isElementNode()) element = static_cast<Element*>(m_object->node()); - ASSERT(!element || element->document() && !element->document()->inPageCache()); + ASSERT(!element || (element->document() && !element->document()->inPageCache())); if (!element) return false; diff --git a/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.h b/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.h index 7e286d2..be5c197 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.h +++ b/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.h @@ -47,8 +47,9 @@ public: int animatingProperty() const { return m_animatingProperty; } virtual void onAnimationEnd(double elapsedTime); - virtual bool startAnimation(double beginTime); - virtual void endAnimation(bool reset); + virtual bool startAnimation(double timeOffset); + virtual void pauseAnimation(double /*timeOffset*/) { } + virtual void endAnimation(); virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle); virtual void getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle); diff --git a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp index 7e37e5f..0e76ea9 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp @@ -36,6 +36,7 @@ #include "EventNames.h" #include "RenderLayer.h" #include "RenderLayerBacking.h" +#include "RenderStyle.h" #include <wtf/UnusedParam.h> namespace WebCore { @@ -58,7 +59,7 @@ KeyframeAnimation::~KeyframeAnimation() { // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. if (!postActive()) - endAnimation(true); + endAnimation(); } void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const @@ -119,9 +120,11 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render } // If we are waiting for the start timer, we don't want to change the style yet. - // Special case - if the delay time is 0, then we do want to set the first frame of the + // Special case 1 - if the delay time is 0, then we do want to set the first frame of the // animation right away. This avoids a flash when the animation starts. - if (waitingToStart() && m_animation->delay() > 0) + // Special case 2 - if there is a backwards fill mode, then we want to continue + // through to the style blend so that we get the fromStyle. + if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards()) return; // FIXME: we need to be more efficient about determining which keyframes we are animating between. @@ -191,40 +194,54 @@ bool KeyframeAnimation::hasAnimationForProperty(int property) const return false; } -bool KeyframeAnimation::startAnimation(double beginTime) +bool KeyframeAnimation::startAnimation(double timeOffset) { #if USE(ACCELERATED_COMPOSITING) if (m_object && m_object->hasLayer()) { RenderLayer* layer = toRenderBoxModelObject(m_object)->layer(); if (layer->isComposited()) - return layer->backing()->startAnimation(beginTime, m_animation.get(), m_keyframes); + return layer->backing()->startAnimation(timeOffset, m_animation.get(), m_keyframes); } #else - UNUSED_PARAM(beginTime); + UNUSED_PARAM(timeOffset); #endif return false; } -void KeyframeAnimation::endAnimation(bool reset) +void KeyframeAnimation::pauseAnimation(double timeOffset) { - if (m_object) { + if (!m_object) + return; + #if USE(ACCELERATED_COMPOSITING) - if (m_object->hasLayer()) { - RenderLayer* layer = toRenderBoxModelObject(m_object)->layer(); - if (layer->isComposited()) { - if (reset) - layer->backing()->animationFinished(m_keyframes.animationName()); - else - layer->backing()->animationPaused(m_keyframes.animationName()); - } - } + if (m_object->hasLayer()) { + RenderLayer* layer = toRenderBoxModelObject(m_object)->layer(); + if (layer->isComposited()) + layer->backing()->animationPaused(timeOffset, m_keyframes.animationName()); + } #else - UNUSED_PARAM(reset); + UNUSED_PARAM(timeOffset); #endif - // Restore the original (unanimated) style - if (!paused()) - setNeedsStyleRecalc(m_object->node()); + // Restore the original (unanimated) style + if (!paused()) + setNeedsStyleRecalc(m_object->node()); +} + +void KeyframeAnimation::endAnimation() +{ + if (!m_object) + return; + +#if USE(ACCELERATED_COMPOSITING) + if (m_object->hasLayer()) { + RenderLayer* layer = toRenderBoxModelObject(m_object)->layer(); + if (layer->isComposited()) + layer->backing()->animationFinished(m_keyframes.animationName()); } +#endif + // Restore the original (unanimated) style + if (!paused()) + setNeedsStyleRecalc(m_object->node()); } bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const @@ -245,7 +262,10 @@ void KeyframeAnimation::onAnimationIteration(double elapsedTime) void KeyframeAnimation::onAnimationEnd(double elapsedTime) { sendAnimationEvent(eventNames().webkitAnimationEndEvent, elapsedTime); - endAnimation(true); + // End the animation if we don't fill forwards. Forward filling + // animations are ended properly in the class destructor. + if (!m_animation->fillsForwards()) + endAnimation(); } bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double elapsedTime) @@ -266,7 +286,7 @@ bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double if (m_object->node() && m_object->node()->isElementNode()) element = static_cast<Element*>(m_object->node()); - ASSERT(!element || element->document() && !element->document()->inPageCache()); + ASSERT(!element || (element->document() && !element->document()->inPageCache())); if (!element) return false; diff --git a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.h b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.h index 4905fc3..fab0ae8 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.h +++ b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.h @@ -32,10 +32,11 @@ #include "AnimationBase.h" #include "Document.h" #include "KeyframeList.h" -#include "RenderStyle.h" namespace WebCore { +class RenderStyle; + // A KeyframeAnimation tracks the state of an explicit animation // for a single RenderObject. class KeyframeAnimation : public AnimationBase { @@ -63,8 +64,9 @@ protected: virtual void onAnimationStart(double elapsedTime); virtual void onAnimationIteration(double elapsedTime); virtual void onAnimationEnd(double elapsedTime); - virtual bool startAnimation(double beginTime); - virtual void endAnimation(bool reset); + virtual bool startAnimation(double timeOffset); + virtual void pauseAnimation(double timeOffset); + virtual void endAnimation(); virtual void overrideAnimations(); virtual void resumeOverriddenAnimations(); diff --git a/src/3rdparty/webkit/WebCore/page/qt/DragControllerQt.cpp b/src/3rdparty/webkit/WebCore/page/qt/DragControllerQt.cpp index e6c7682..33815b5 100644 --- a/src/3rdparty/webkit/WebCore/page/qt/DragControllerQt.cpp +++ b/src/3rdparty/webkit/WebCore/page/qt/DragControllerQt.cpp @@ -66,6 +66,7 @@ const IntSize& DragController::maxDragImageSize() void DragController::cleanupAfterSystemDrag() { + dragEnded(); } } diff --git a/src/3rdparty/webkit/WebCore/page/qt/EventHandlerQt.cpp b/src/3rdparty/webkit/WebCore/page/qt/EventHandlerQt.cpp index 3425289..d7982fa 100644 --- a/src/3rdparty/webkit/WebCore/page/qt/EventHandlerQt.cpp +++ b/src/3rdparty/webkit/WebCore/page/qt/EventHandlerQt.cpp @@ -132,7 +132,11 @@ bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& unsigned EventHandler::accessKeyModifiers() { - return PlatformKeyboardEvent::CtrlKey; +#if OS(DARWIN) + return PlatformKeyboardEvent::CtrlKey | PlatformKeyboardEvent::AltKey; +#else + return PlatformKeyboardEvent::AltKey; +#endif } } diff --git a/src/3rdparty/webkit/WebCore/page/win/EventHandlerWin.cpp b/src/3rdparty/webkit/WebCore/page/win/EventHandlerWin.cpp index 50e50fb..5511209 100644 --- a/src/3rdparty/webkit/WebCore/page/win/EventHandlerWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/win/EventHandlerWin.cpp @@ -88,7 +88,7 @@ bool EventHandler::eventActivatedView(const PlatformMouseEvent& event) const PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const { -#if PLATFORM(WINCE) +#if OS(WINCE) return 0; #else COMPtr<WCDataObject> dataObject; diff --git a/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp b/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp index 7483627..cce5004 100644 --- a/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp @@ -45,13 +45,16 @@ static void drawRectIntoContext(IntRect rect, FrameView* view, GraphicsContext* rect.move(-offset.width(), -offset.height()); rect = view->convertToContainingWindow(rect); - gc->concatCTM(TransformationMatrix().translate(-rect.x(), -rect.y())); + gc->concatCTM(AffineTransform().translate(-rect.x(), -rect.y())); view->paint(gc, rect); } static HBITMAP imageFromRect(const Frame* frame, IntRect& ir) { + PaintBehavior oldPaintBehavior = frame->view()->paintBehavior(); + frame->view()->setPaintBehavior(oldPaintBehavior | PaintBehaviorFlattenCompositingLayers); + void* bits; HDC hdc = CreateCompatibleDC(0); int w = ir.width(); @@ -74,6 +77,8 @@ static HBITMAP imageFromRect(const Frame* frame, IntRect& ir) SelectObject(hdc, hbmpOld); DeleteDC(hdc); + frame->view()->setPaintBehavior(oldPaintBehavior); + return hbmp; } @@ -81,12 +86,12 @@ HBITMAP imageFromSelection(Frame* frame, bool forceBlackText) { frame->document()->updateLayout(); - frame->view()->setPaintRestriction(forceBlackText ? PaintRestrictionSelectionOnlyBlackText : PaintRestrictionSelectionOnly); + frame->view()->setPaintBehavior(PaintBehaviorSelectionOnly | (forceBlackText ? PaintBehaviorForceBlackText : 0)); FloatRect fr = frame->selectionBounds(); IntRect ir(static_cast<int>(fr.x()), static_cast<int>(fr.y()), static_cast<int>(fr.width()), static_cast<int>(fr.height())); HBITMAP image = imageFromRect(frame, ir); - frame->view()->setPaintRestriction(PaintRestrictionNone); + frame->view()->setPaintBehavior(PaintBehaviorNormal); return image; } diff --git a/src/3rdparty/webkit/WebCore/page/win/FrameCairoWin.cpp b/src/3rdparty/webkit/WebCore/page/win/FrameCairoWin.cpp index f5b832e..3e1fe28 100644 --- a/src/3rdparty/webkit/WebCore/page/win/FrameCairoWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/win/FrameCairoWin.cpp @@ -24,6 +24,7 @@ */ #include "config.h" +#include "Frame.h" #include "FrameWin.h" #include "EditorClient.h" diff --git a/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp b/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp index b15d195..2b5435d 100644 --- a/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp @@ -24,69 +24,25 @@ */ #include "config.h" -#include "runtime.h" #include "FrameWin.h" -#include "TransformationMatrix.h" -#include "FloatRect.h" +#include "Bridge.h" #include "Document.h" +#include "FloatRect.h" +#include "PrintContext.h" #include "RenderView.h" #include "Settings.h" - -using std::min; +#include "TransformationMatrix.h" namespace WebCore { -void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, Vector<IntRect>& pages, int& outPageHeight) +void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, Vector<IntRect>& outPages, int& outPageHeight) { - ASSERT(frame); - - pages.clear(); - outPageHeight = 0; - - if (!frame->document() || !frame->view() || !frame->document()->renderer()) - return; - - RenderView* root = toRenderView(frame->document()->renderer()); - - if (!root) { - LOG_ERROR("document to be printed has no renderer"); - return; - } - - if (userScaleFactor <= 0) { - LOG_ERROR("userScaleFactor has bad value %.2f", userScaleFactor); - return; - } - - float ratio = static_cast<float>(printRect.height()) / static_cast<float>(printRect.width()); - - float pageWidth = static_cast<float>(root->rightLayoutOverflow()); - float pageHeight = pageWidth * ratio; - outPageHeight = static_cast<int>(pageHeight); // this is the height of the page adjusted by margins - pageHeight -= (headerHeight + footerHeight); - - if (pageHeight <= 0) { - LOG_ERROR("pageHeight has bad value %.2f", pageHeight); - return; - } - - float currPageHeight = pageHeight / userScaleFactor; - float docHeight = root->layer()->height(); - float docWidth = root->layer()->width(); - float currPageWidth = pageWidth / userScaleFactor; - - - // always return at least one page, since empty files should print a blank page - float printedPagesHeight = 0.0f; - do { - float proposedBottom = min(docHeight, printedPagesHeight + pageHeight); - frame->view()->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight); - currPageHeight = max(1.0f, proposedBottom - printedPagesHeight); - - pages.append(IntRect(0, printedPagesHeight, currPageWidth, currPageHeight)); - printedPagesHeight += currPageHeight; - } while (printedPagesHeight < docHeight); + PrintContext printContext(frame); + float pageHeight = 0; + printContext.computePageRects(printRect, headerHeight, footerHeight, userScaleFactor, pageHeight); + outPageHeight = static_cast<int>(pageHeight); + outPages = printContext.pageRects(); } DragImageRef Frame::dragImageForSelection() diff --git a/src/3rdparty/webkit/WebCore/page/win/FrameWin.h b/src/3rdparty/webkit/WebCore/page/win/FrameWin.h index 2924291..4c274b7 100644 --- a/src/3rdparty/webkit/WebCore/page/win/FrameWin.h +++ b/src/3rdparty/webkit/WebCore/page/win/FrameWin.h @@ -26,15 +26,18 @@ #ifndef FrameWin_H #define FrameWin_H -#include "Frame.h" +#include <wtf/Vector.h> // Forward declared so we don't need wingdi.h. typedef struct HBITMAP__* HBITMAP; namespace WebCore { + class Frame; + class IntRect; + HBITMAP imageFromSelection(Frame* frame, bool forceWhiteText); - void computePageRectsForFrame(Frame*, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, Vector<IntRect>& pages, int& pageHeight); + void computePageRectsForFrame(Frame*, const IntRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, Vector<IntRect>& outPages, int& outPageHeight); } diff --git a/src/3rdparty/webkit/WebCore/page/win/PageWin.cpp b/src/3rdparty/webkit/WebCore/page/win/PageWin.cpp deleted file mode 100644 index 5d7450c..0000000 --- a/src/3rdparty/webkit/WebCore/page/win/PageWin.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "Page.h" - -#include "Frame.h" -#include "FrameLoaderClient.h" -#include "FrameView.h" -#include "FloatRect.h" -#include "PluginView.h" -#include <windows.h> - -namespace WebCore { - -HINSTANCE Page::s_instanceHandle = 0; - -void Page::setCanStartPlugins(bool canStartPlugins) -{ - if (m_canStartPlugins == canStartPlugins) - return; - - m_canStartPlugins = canStartPlugins; - - if (!m_canStartPlugins || m_unstartedPlugins.isEmpty()) - return; - - Vector<PluginView*> unstartedPlugins; - copyToVector(m_unstartedPlugins, unstartedPlugins); - m_unstartedPlugins.clear(); - - for (size_t i = 0; i < unstartedPlugins.size(); ++i) { - if (unstartedPlugins[i]->start()) - continue; - unstartedPlugins[i]->parentFrame()->loader()->client()->dispatchDidFailToStartPlugin(unstartedPlugins[i]); - } -} - -} // namespace WebCore - |