diff options
Diffstat (limited to 'Source/WebCore/page')
53 files changed, 1583 insertions, 369 deletions
diff --git a/Source/WebCore/page/Chrome.cpp b/Source/WebCore/page/Chrome.cpp index 26ea33b..5881d5e 100644 --- a/Source/WebCore/page/Chrome.cpp +++ b/Source/WebCore/page/Chrome.cpp @@ -88,9 +88,9 @@ void Chrome::scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, con } #if ENABLE(TILED_BACKING_STORE) -void Chrome::delegatedScrollRequested(const IntSize& scrollDelta) +void Chrome::delegatedScrollRequested(const IntPoint& scrollPoint) { - m_client->delegatedScrollRequested(scrollDelta); + m_client->delegatedScrollRequested(scrollPoint); } #endif diff --git a/Source/WebCore/page/Chrome.h b/Source/WebCore/page/Chrome.h index 4d16214..9984a7c 100644 --- a/Source/WebCore/page/Chrome.h +++ b/Source/WebCore/page/Chrome.h @@ -71,7 +71,7 @@ namespace WebCore { virtual void invalidateContentsForSlowScroll(const IntRect&, bool); virtual void scroll(const IntSize&, const IntRect&, const IntRect&); #if ENABLE(TILED_BACKING_STORE) - virtual void delegatedScrollRequested(const IntSize& scrollDelta); + virtual void delegatedScrollRequested(const IntPoint& scrollPoint); #endif virtual IntPoint screenToWindow(const IntPoint&) const; virtual IntRect windowToScreen(const IntRect&) const; diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h index 7fcec2e..73fe904 100644 --- a/Source/WebCore/page/ChromeClient.h +++ b/Source/WebCore/page/ChromeClient.h @@ -49,6 +49,7 @@ namespace WebCore { class FloatRect; class Frame; class Geolocation; + class GraphicsLayer; class HitTestResult; class IntRect; class NavigationAction; @@ -143,7 +144,7 @@ namespace WebCore { virtual void invalidateContentsForSlowScroll(const IntRect&, bool) = 0; virtual void scroll(const IntSize&, const IntRect&, const IntRect&) = 0; #if ENABLE(TILED_BACKING_STORE) - virtual void delegatedScrollRequested(const IntSize&) = 0; + virtual void delegatedScrollRequested(const IntPoint&) = 0; #endif virtual IntPoint screenToWindow(const IntPoint&) const = 0; virtual IntRect windowToScreen(const IntRect&) const = 0; @@ -263,10 +264,11 @@ namespace WebCore { virtual bool requiresFullscreenForVideoPlayback() { return false; } #if ENABLE(FULLSCREEN_API) - virtual bool supportsFullScreenForElement(const Element*) { return false; } + virtual bool supportsFullScreenForElement(const Element*, bool) { return false; } virtual void enterFullScreenForElement(Element*) { } virtual void exitFullScreenForElement(Element*) { } virtual void fullScreenRendererChanged(RenderBox*) { } + virtual void setRootFullScreenLayer(GraphicsLayer*) { } #endif #if ENABLE(TILED_BACKING_STORE) diff --git a/Source/WebCore/page/ContentSecurityPolicy.cpp b/Source/WebCore/page/ContentSecurityPolicy.cpp index 97cd447..6bcf99c 100644 --- a/Source/WebCore/page/ContentSecurityPolicy.cpp +++ b/Source/WebCore/page/ContentSecurityPolicy.cpp @@ -25,28 +25,390 @@ #include "config.h" #include "ContentSecurityPolicy.h" + #include "Document.h" +#include "NotImplemented.h" +#include "SecurityOrigin.h" namespace WebCore { -class CSPDirective { +// Normally WebKit uses "static" for internal linkage, but using "static" for +// these functions causes a compile error because these functions are used as +// template parameters. +namespace { + +bool isDirectiveNameCharacter(UChar c) +{ + return isASCIIAlphanumeric(c) || c == '-'; +} + +bool isDirectiveValueCharacter(UChar c) +{ + return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR +} + +bool isSourceCharacter(UChar c) +{ + return !isASCIISpace(c); +} + +bool isHostCharacter(UChar c) +{ + return isASCIIAlphanumeric(c) || c == '-'; +} + +bool isSchemeContinuationCharacter(UChar c) +{ + return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.'; +} + +} // namespace + +static bool skipExactly(const UChar*& position, const UChar* end, UChar delimiter) +{ + if (position < end && *position == delimiter) { + ++position; + return true; + } + return false; +} + +template<bool characterPredicate(UChar)> +static bool skipExactly(const UChar*& position, const UChar* end) +{ + if (position < end && characterPredicate(*position)) { + ++position; + return true; + } + return false; +} + +static void skipUtil(const UChar*& position, const UChar* end, UChar delimiter) +{ + while (position < end && *position != delimiter) + ++position; +} + +template<bool characterPredicate(UChar)> +static void skipWhile(const UChar*& position, const UChar* end) +{ + while (position < end && characterPredicate(*position)) + ++position; +} + +class CSPSource { public: - explicit CSPDirective(const String& value) - : m_value(value) + CSPSource(const String& scheme, const String& host, int port, bool hostHasWildcard, bool portHasWildcard) + : m_scheme(scheme) + , m_host(host) + , m_port(port) + , m_hostHasWildcard(hostHasWildcard) + , m_portHasWildcard(portHasWildcard) + { + } + + bool matches(const KURL& url) const + { + if (!schemeMatches(url)) + return false; + if (isSchemeOnly()) + return true; + return hostMatches(url) && portMatches(url); + } + +private: + bool schemeMatches(const KURL& url) const + { + return equalIgnoringCase(url.protocol(), m_scheme); + } + + bool hostMatches(const KURL& url) const { + if (m_hostHasWildcard) + notImplemented(); + + return equalIgnoringCase(url.host(), m_host); } - bool allows(const KURL&) + bool portMatches(const KURL& url) const { + if (m_portHasWildcard) + return true; + + // FIXME: Handle explicit default ports correctly. + return url.port() == m_port; + } + + bool isSchemeOnly() const { return m_host.isEmpty(); } + + String m_scheme; + String m_host; + int m_port; + + bool m_hostHasWildcard; + bool m_portHasWildcard; +}; + +class CSPSourceList { +public: + explicit CSPSourceList(SecurityOrigin*); + + void parse(const String&); + bool matches(const KURL&); + +private: + void parse(const UChar* begin, const UChar* end); + + bool parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, bool& hostHasWildcard, bool& portHasWildcard); + bool parseScheme(const UChar* begin, const UChar* end, String& scheme); + bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard); + bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard); + + void addSourceSelf(); + + SecurityOrigin* m_origin; + Vector<CSPSource> m_list; +}; + +CSPSourceList::CSPSourceList(SecurityOrigin* origin) + : m_origin(origin) +{ +} + +void CSPSourceList::parse(const String& value) +{ + parse(value.characters(), value.characters() + value.length()); +} + +bool CSPSourceList::matches(const KURL& url) +{ + for (size_t i = 0; i < m_list.size(); ++i) { + if (m_list[i].matches(url)) + return true; + } + return false; +} + +// source-list = *WSP [ source *( 1*WSP source ) *WSP ] +// / *WSP "'none'" *WSP +// +void CSPSourceList::parse(const UChar* begin, const UChar* end) +{ + const UChar* position = begin; + + bool isFirstSourceInList = true; + while (position < end) { + skipWhile<isASCIISpace>(position, end); + const UChar* beginSource = position; + skipWhile<isSourceCharacter>(position, end); + + if (isFirstSourceInList && equalIgnoringCase("'none'", beginSource, position - beginSource)) + return; // We represent 'none' as an empty m_list. + isFirstSourceInList = false; + + String scheme, host; + int port = 0; + bool hostHasWildcard = false; + bool portHasWildcard = false; + + if (parseSource(beginSource, position, scheme, host, port, hostHasWildcard, portHasWildcard)) { + if (scheme.isEmpty()) + scheme = m_origin->protocol(); + m_list.append(CSPSource(scheme, host, port, hostHasWildcard, portHasWildcard)); + } + + ASSERT(position == end || isASCIISpace(*position)); + } +} + +// source = scheme ":" +// / ( [ scheme "://" ] host [ port ] ) +// / "'self'" +// +bool CSPSourceList::parseSource(const UChar* begin, const UChar* end, + String& scheme, String& host, int& port, + bool& hostHasWildcard, bool& portHasWildcard) +{ + if (begin == end) + return false; + + if (equalIgnoringCase("'self'", begin, end - begin)) { + addSourceSelf(); return false; } + const UChar* position = begin; + + const UChar* beginHost = begin; + skipUtil(position, end, ':'); + + if (position == end) { + // This must be a host-only source. + if (!parseHost(beginHost, position, host, hostHasWildcard)) + return false; + return true; + } + + if (end - position == 1) { + ASSERT(*position == ':'); + // This must be a scheme-only source. + if (!parseScheme(begin, position, scheme)) + return false; + return true; + } + + ASSERT(end - position >= 2); + if (position[1] == '/') { + if (!parseScheme(begin, position, scheme) + || !skipExactly(position, end, ':') + || !skipExactly(position, end, '/') + || !skipExactly(position, end, '/')) + return false; + beginHost = position; + skipUtil(position, end, ':'); + } + + if (position == beginHost) + return false; + + if (!parseHost(beginHost, position, host, hostHasWildcard)) + return false; + + if (position == end) { + port = 0; + return true; + } + + if (!skipExactly(position, end, ':')) + ASSERT_NOT_REACHED(); + + if (!parsePort(position, end, port, portHasWildcard)) + return false; + + return true; +} + +// ; <scheme> production from RFC 3986 +// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) +// +bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& scheme) +{ + ASSERT(begin <= end); + ASSERT(scheme.isEmpty()); + + if (begin == end) + return false; + + const UChar* position = begin; + + if (!skipExactly<isASCIIAlpha>(position, end)) + return false; + + skipWhile<isSchemeContinuationCharacter>(position, end); + + if (position != end) + return false; + + scheme = String(begin, end - begin); + return true; +} + +// host = [ "*." ] 1*host-char *( "." 1*host-char ) +// / "*" +// host-char = ALPHA / DIGIT / "-" +// +bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard) +{ + ASSERT(begin <= end); + ASSERT(host.isEmpty()); + ASSERT(!hostHasWildcard); + + if (begin == end) + return false; + + const UChar* position = begin; + + if (skipExactly(position, end, '*')) { + hostHasWildcard = true; + + if (position == end) + return true; + + if (!skipExactly(position, end, '.')) + return false; + } + + const UChar* hostBegin = position; + + while (position < end) { + if (!skipExactly<isHostCharacter>(position, end)) + return false; + + skipWhile<isHostCharacter>(position, end); + + if (position < end && !skipExactly(position, end, '.')) + return false; + } + + ASSERT(position == end); + host = String(hostBegin, end - hostBegin); + return true; +} + +// port = ":" ( 1*DIGIT / "*" ) +// +bool CSPSourceList::parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard) +{ + ASSERT(begin <= end); + ASSERT(!port); + ASSERT(!portHasWildcard); + + if (begin == end) + return false; + + if (end - begin == 1 && *begin == '*') { + port = 0; + portHasWildcard = true; + return true; + } + + const UChar* position = begin; + skipWhile<isASCIIDigit>(position, end); + + if (position != end) + return false; + + bool ok; + port = charactersToIntStrict(begin, end - begin, &ok); + return ok; +} + +void CSPSourceList::addSourceSelf() +{ + // FIXME: Inherit the scheme, host, and port from the current URL. + notImplemented(); +} + +class CSPDirective { +public: + CSPDirective(const String& value, SecurityOrigin* origin) + : m_sourceList(origin) + { + m_sourceList.parse(value); + } + + bool allows(const KURL& url) + { + return m_sourceList.matches(url); + } + private: - String m_value; + CSPSourceList m_sourceList; }; -ContentSecurityPolicy::ContentSecurityPolicy() +ContentSecurityPolicy::ContentSecurityPolicy(SecurityOrigin* origin) : m_havePolicy(false) + , m_origin(origin) { } @@ -68,11 +430,19 @@ bool ContentSecurityPolicy::allowJavaScriptURLs() const return !m_scriptSrc; } -bool ContentSecurityPolicy::canLoadExternalScriptFromSrc(const String& url) const +bool ContentSecurityPolicy::allowInlineEventHandlers() const +{ + return !m_scriptSrc; +} + +bool ContentSecurityPolicy::allowScriptFromSource(const KURL& url) const { - return !m_scriptSrc || m_scriptSrc->allows(KURL(ParsedURLString, url)); + return !m_scriptSrc || m_scriptSrc->allows(url); } +// policy = directive-list +// directive-list = [ directive *( ";" [ directive ] ) ] +// void ContentSecurityPolicy::parse(const String& policy) { ASSERT(!m_havePolicy); @@ -80,75 +450,75 @@ void ContentSecurityPolicy::parse(const String& policy) if (policy.isEmpty()) return; - const UChar* pos = policy.characters(); - const UChar* end = pos + policy.length(); + const UChar* position = policy.characters(); + const UChar* end = position + policy.length(); - while (pos < end) { - Vector<UChar, 32> name; - Vector<UChar, 64> value; + while (position < end) { + const UChar* directiveBegin = position; + skipUtil(position, end, ';'); - parseDirective(pos, end, name, value); - if (name.isEmpty()) - continue; + String name, value; + if (parseDirective(directiveBegin, position, name, value)) { + ASSERT(!name.isEmpty()); + addDirective(name, value); + } - // We use a copy here instead of String::adopt because we expect - // the name and the value to be relatively short, so the copy will - // be cheaper than the extra malloc. - emitDirective(String(name), String(value)); + ASSERT(position == end || *position == ';'); + skipExactly(position, end, ';'); } } -void ContentSecurityPolicy::parseDirective(const UChar*& pos, const UChar* end, Vector<UChar, 32>& name, Vector<UChar, 64>& value) +// directive = *WSP [ directive-name [ WSP directive-value ] ] +// directive-name = 1*( ALPHA / DIGIT / "-" ) +// directive-value = *( WSP / <VCHAR except ";"> ) +// +bool ContentSecurityPolicy::parseDirective(const UChar* begin, const UChar* end, String& name, String& value) { - ASSERT(pos < end); ASSERT(name.isEmpty()); ASSERT(value.isEmpty()); - enum { - BeforeDirectiveName, - DirectiveName, - AfterDirectiveName, - DirectiveValue, - } state = BeforeDirectiveName; - - while (pos < end) { - UChar currentCharacter = *pos++; - switch (state) { - case BeforeDirectiveName: - if (isASCIISpace(currentCharacter)) - continue; - state = DirectiveName; - // Fall through. - case DirectiveName: - if (!isASCIISpace(currentCharacter)) { - name.append(currentCharacter); - continue; - } - state = AfterDirectiveName; - // Fall through. - case AfterDirectiveName: - if (isASCIISpace(currentCharacter)) - continue; - state = DirectiveValue; - // Fall through. - case DirectiveValue: - if (currentCharacter != ';') { - value.append(currentCharacter); - continue; - } - return; - } - } + const UChar* position = begin; + skipWhile<isASCIISpace>(position, end); + + const UChar* nameBegin = position; + skipWhile<isDirectiveNameCharacter>(position, end); + + // The directive-name must be non-empty. + if (nameBegin == position) + return false; + + name = String(nameBegin, position - nameBegin); + + if (position == end) + return true; + + if (!skipExactly<isASCIISpace>(position, end)) + return false; + + skipWhile<isASCIISpace>(position, end); + + const UChar* valueBegin = position; + skipWhile<isDirectiveValueCharacter>(position, end); + + if (position != end) + return false; + + // The directive-value may be empty. + if (valueBegin == position) + return true; + + value = String(valueBegin, position - valueBegin); + return true; } -void ContentSecurityPolicy::emitDirective(const String& name, const String& value) +void ContentSecurityPolicy::addDirective(const String& name, const String& value) { DEFINE_STATIC_LOCAL(String, scriptSrc, ("script-src")); ASSERT(!name.isEmpty()); if (!m_scriptSrc && equalIgnoringCase(name, scriptSrc)) - m_scriptSrc = adoptPtr(new CSPDirective(value)); + m_scriptSrc = adoptPtr(new CSPDirective(value, m_origin.get())); } } diff --git a/Source/WebCore/page/ContentSecurityPolicy.h b/Source/WebCore/page/ContentSecurityPolicy.h index 0eebd05..a7cd216 100644 --- a/Source/WebCore/page/ContentSecurityPolicy.h +++ b/Source/WebCore/page/ContentSecurityPolicy.h @@ -32,26 +32,32 @@ namespace WebCore { class CSPDirective; +class KURL; +class SecurityOrigin; class ContentSecurityPolicy : public RefCounted<ContentSecurityPolicy> { public: - static PassRefPtr<ContentSecurityPolicy> create() { return adoptRef(new ContentSecurityPolicy); } + static PassRefPtr<ContentSecurityPolicy> create(SecurityOrigin* origin = 0) + { + return adoptRef(new ContentSecurityPolicy(origin)); + } ~ContentSecurityPolicy(); void didReceiveHeader(const String&); bool allowJavaScriptURLs() const; - // FIXME: Rename canLoadExternalScriptFromSrc to allowScriptFromURL. - bool canLoadExternalScriptFromSrc(const String& url) const; + bool allowInlineEventHandlers() const; + bool allowScriptFromSource(const KURL&) const; private: - ContentSecurityPolicy(); + explicit ContentSecurityPolicy(SecurityOrigin*); void parse(const String&); - void parseDirective(const UChar*& pos, const UChar* end, Vector<UChar, 32>& name, Vector<UChar, 64>& value); - void emitDirective(const String& name, const String& value); + bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value); + void addDirective(const String& name, const String& value); bool m_havePolicy; + RefPtr<SecurityOrigin> m_origin; OwnPtr<CSPDirective> m_scriptSrc; }; diff --git a/Source/WebCore/page/ContextMenuController.cpp b/Source/WebCore/page/ContextMenuController.cpp index c807d7a..a0e64b8 100644 --- a/Source/WebCore/page/ContextMenuController.cpp +++ b/Source/WebCore/page/ContextMenuController.cpp @@ -63,6 +63,7 @@ #include "SelectionController.h" #include "Settings.h" #include "TextIterator.h" +#include "UserTypingGestureIndicator.h" #include "WindowFeatures.h" #include "markup.h" #include <wtf/unicode/Unicode.h> @@ -259,10 +260,10 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item) frame->loader()->reload(); break; case ContextMenuItemTagCut: - frame->editor()->cut(); + frame->editor()->command("Cut").execute(); break; case ContextMenuItemTagPaste: - frame->editor()->paste(); + frame->editor()->command("Paste").execute(); break; #if PLATFORM(GTK) case ContextMenuItemTagDelete: @@ -632,6 +633,14 @@ static bool selectionContainsPossibleWord(Frame* frame) return false; } +#if PLATFORM(MAC) +#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) +#define INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM 1 +#else +#define INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM 0 +#endif +#endif + void ContextMenuController::populate() { ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink()); @@ -667,8 +676,6 @@ void ContextMenuController::populate() #if PLATFORM(MAC) ContextMenuItem SearchSpotlightItem(ActionType, ContextMenuItemTagSearchInSpotlight, contextMenuItemTagSearchInSpotlight()); - ContextMenuItem LookInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, - contextMenuItemTagLookUpInDictionary()); #endif #if !PLATFORM(GTK) ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb()); @@ -758,20 +765,31 @@ void ContextMenuController::populate() if (m_hitTestResult.isSelected()) { if (selectionContainsPossibleWord(frame)) { #if PLATFORM(MAC) + String selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText()); + ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString)); + +#if INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM appendItem(SearchSpotlightItem, m_contextMenu.get()); +#else + appendItem(LookUpInDictionaryItem, m_contextMenu.get()); +#endif #endif + #if !PLATFORM(GTK) appendItem(SearchWebItem, m_contextMenu.get()); appendItem(*separatorItem(), m_contextMenu.get()); #endif -#if PLATFORM(MAC) - appendItem(LookInDictionaryItem, m_contextMenu.get()); + +#if PLATFORM(MAC) && INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM + appendItem(LookUpInDictionaryItem, m_contextMenu.get()); appendItem(*separatorItem(), m_contextMenu.get()); #endif } + appendItem(CopyItem, m_contextMenu.get()); #if PLATFORM(MAC) appendItem(*separatorItem(), m_contextMenu.get()); + ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu()); createAndAppendSpeechSubMenu(SpeechMenuItem); appendItem(SpeechMenuItem, m_contextMenu.get()); @@ -813,7 +831,7 @@ void ContextMenuController::populate() SelectionController* selection = frame->selection(); bool inPasswordField = selection->isInPasswordField(); bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node); - + if (!inPasswordField && spellCheckingEnabled) { // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range // is never considered a misspelling and bad grammar at the same time) @@ -873,15 +891,23 @@ void ContextMenuController::populate() if (m_hitTestResult.isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) { #if PLATFORM(MAC) + String selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText()); + ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString)); + +#if INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM appendItem(SearchSpotlightItem, m_contextMenu.get()); +#else + appendItem(LookUpInDictionaryItem, m_contextMenu.get()); +#endif #endif + #if !PLATFORM(GTK) appendItem(SearchWebItem, m_contextMenu.get()); appendItem(*separatorItem(), m_contextMenu.get()); #endif - -#if PLATFORM(MAC) - appendItem(LookInDictionaryItem, m_contextMenu.get()); + +#if PLATFORM(MAC) && INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM + appendItem(LookUpInDictionaryItem, m_contextMenu.get()); appendItem(*separatorItem(), m_contextMenu.get()); #endif } diff --git a/Source/WebCore/page/DOMSelection.cpp b/Source/WebCore/page/DOMSelection.cpp index 67c87d2..31ab956 100644 --- a/Source/WebCore/page/DOMSelection.cpp +++ b/Source/WebCore/page/DOMSelection.cpp @@ -101,7 +101,7 @@ Node* DOMSelection::anchorNode() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->parentNodeGuaranteedHostFree(); - return anchorPosition(visibleSelection()).deprecatedNode(); + return anchorPosition(visibleSelection()).containerNode(); } int DOMSelection::anchorOffset() const @@ -110,7 +110,7 @@ int DOMSelection::anchorOffset() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->nodeIndex(); - return anchorPosition(visibleSelection()).deprecatedEditingOffset(); + return anchorPosition(visibleSelection()).offsetInContainerNode(); } Node* DOMSelection::focusNode() const @@ -119,7 +119,7 @@ Node* DOMSelection::focusNode() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->parentNodeGuaranteedHostFree(); - return focusPosition(visibleSelection()).deprecatedNode(); + return focusPosition(visibleSelection()).containerNode(); } int DOMSelection::focusOffset() const @@ -128,7 +128,7 @@ int DOMSelection::focusOffset() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->nodeIndex(); - return focusPosition(visibleSelection()).deprecatedEditingOffset(); + return focusPosition(visibleSelection()).offsetInContainerNode(); } Node* DOMSelection::baseNode() const @@ -137,7 +137,7 @@ Node* DOMSelection::baseNode() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->parentNodeGuaranteedHostFree(); - return basePosition(visibleSelection()).deprecatedNode(); + return basePosition(visibleSelection()).containerNode(); } int DOMSelection::baseOffset() const @@ -146,7 +146,7 @@ int DOMSelection::baseOffset() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->nodeIndex(); - return basePosition(visibleSelection()).deprecatedEditingOffset(); + return basePosition(visibleSelection()).offsetInContainerNode(); } Node* DOMSelection::extentNode() const @@ -155,7 +155,7 @@ Node* DOMSelection::extentNode() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->parentNodeGuaranteedHostFree(); - return extentPosition(visibleSelection()).deprecatedNode(); + return extentPosition(visibleSelection()).containerNode(); } int DOMSelection::extentOffset() const @@ -164,7 +164,7 @@ int DOMSelection::extentOffset() const return 0; if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) return shadowAncestor->nodeIndex(); - return extentPosition(visibleSelection()).deprecatedEditingOffset(); + return extentPosition(visibleSelection()).offsetInContainerNode(); } bool DOMSelection::isCollapsed() const diff --git a/Source/WebCore/page/DOMTimer.cpp b/Source/WebCore/page/DOMTimer.cpp index eaca8f2..0a94e7e 100644 --- a/Source/WebCore/page/DOMTimer.cpp +++ b/Source/WebCore/page/DOMTimer.cpp @@ -30,6 +30,7 @@ #include "InspectorInstrumentation.h" #include "ScheduledAction.h" #include "ScriptExecutionContext.h" +#include "UserGestureIndicator.h" #include <wtf/HashSet.h> #include <wtf/StdLibExtras.h> @@ -37,29 +38,41 @@ using namespace std; namespace WebCore { +static const int maxIntervalForUserGestureForwarding = 1000; // One second matches Gecko. static const int maxTimerNestingLevel = 5; static const double oneMillisecond = 0.001; double DOMTimer::s_minDefaultTimerInterval = 0.010; // 10 milliseconds static int timerNestingLevel = 0; - -DOMTimer::DOMTimer(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) - : SuspendableTimer(context) - , m_action(action) - , m_originalTimeout(timeout) + +static int timeoutId() { static int lastUsedTimeoutId = 0; ++lastUsedTimeoutId; // Avoid wraparound going negative on us. if (lastUsedTimeoutId <= 0) lastUsedTimeoutId = 1; - m_timeoutId = lastUsedTimeoutId; - - m_nestingLevel = timerNestingLevel + 1; + return lastUsedTimeoutId; +} + +static inline bool shouldForwardUserGesture(int interval, int nestingLevel) +{ + return UserGestureIndicator::processingUserGesture() + && interval <= maxIntervalForUserGestureForwarding + && nestingLevel == 1; // Gestures should not be forwarded to nested timers. +} +DOMTimer::DOMTimer(ScriptExecutionContext* context, PassOwnPtr<ScheduledAction> action, int interval, bool singleShot) + : SuspendableTimer(context) + , m_timeoutId(timeoutId()) + , m_nestingLevel(timerNestingLevel + 1) + , m_action(action) + , m_originalInterval(interval) + , m_shouldForwardUserGesture(shouldForwardUserGesture(interval, m_nestingLevel)) +{ scriptExecutionContext()->addTimeout(m_timeoutId, this); - double intervalMilliseconds = intervalClampedToMinimum(timeout, context->minimumTimerInterval()); + double intervalMilliseconds = intervalClampedToMinimum(interval, context->minimumTimerInterval()); if (singleShot) startOneShot(intervalMilliseconds); else @@ -101,6 +114,11 @@ void DOMTimer::fired() { ScriptExecutionContext* context = scriptExecutionContext(); timerNestingLevel = m_nestingLevel; + + UserGestureIndicator gestureIndicator(m_shouldForwardUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture); + + // Only the first execution of a multi-shot timer should get an affirmative user gesture indicator. + m_shouldForwardUserGesture = false; InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutId); @@ -155,14 +173,14 @@ void DOMTimer::adjustMinimumTimerInterval(double oldMinimumTimerInterval) return; double newMinimumInterval = scriptExecutionContext()->minimumTimerInterval(); - double newClampedInterval = intervalClampedToMinimum(m_originalTimeout, newMinimumInterval); + double newClampedInterval = intervalClampedToMinimum(m_originalInterval, newMinimumInterval); if (repeatInterval()) { augmentRepeatInterval(newClampedInterval - repeatInterval()); return; } - double previousClampedInterval = intervalClampedToMinimum(m_originalTimeout, oldMinimumTimerInterval); + double previousClampedInterval = intervalClampedToMinimum(m_originalInterval, oldMinimumTimerInterval); augmentFireInterval(newClampedInterval - previousClampedInterval); } diff --git a/Source/WebCore/page/DOMTimer.h b/Source/WebCore/page/DOMTimer.h index ba260e0..b917406 100644 --- a/Source/WebCore/page/DOMTimer.h +++ b/Source/WebCore/page/DOMTimer.h @@ -55,7 +55,7 @@ namespace WebCore { void adjustMinimumTimerInterval(double oldMinimumTimerInterval); private: - DOMTimer(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); + DOMTimer(ScriptExecutionContext*, PassOwnPtr<ScheduledAction>, int interval, bool singleShot); virtual void fired(); double intervalClampedToMinimum(int timeout, double minimumTimerInterval) const; @@ -68,7 +68,8 @@ namespace WebCore { int m_timeoutId; int m_nestingLevel; OwnPtr<ScheduledAction> m_action; - int m_originalTimeout; + int m_originalInterval; + bool m_shouldForwardUserGesture; static double s_minDefaultTimerInterval; }; diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp index 269c109..90458ff 100644 --- a/Source/WebCore/page/DOMWindow.cpp +++ b/Source/WebCore/page/DOMWindow.cpp @@ -394,6 +394,7 @@ bool DOMWindow::canShowModalDialogNow(const Frame* frame) DOMWindow::DOMWindow(Frame* frame) : m_shouldPrintWhenFinishedLoading(false) , m_frame(frame) + , m_printTimer(this, &DOMWindow::printTimerFired) { } @@ -711,6 +712,13 @@ void DOMWindow::pageDestroyed() #endif } +void DOMWindow::resetGeolocation() +{ + // Geolocation should cancel activities and permission requests when the page is detached. + if (m_navigator) + m_navigator->resetGeolocation(); +} + #if ENABLE(INDEXED_DATABASE) IDBFactory* DOMWindow::webkitIndexedDB() const { @@ -755,14 +763,14 @@ void DOMWindow::requestFileSystem(int type, long long size, PassRefPtr<FileSyste LocalFileSystem::localFileSystem().requestFileSystem(document, fileSystemType, size, FileSystemCallbacks::create(successCallback, errorCallback, document), false); } -void DOMWindow::resolveLocalFileSystemURI(const String& uri, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback) +void DOMWindow::resolveLocalFileSystemURL(const String& url, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback) { Document* document = this->document(); if (!document) return; SecurityOrigin* securityOrigin = document->securityOrigin(); - KURL completedURL = document->completeURL(uri); + KURL completedURL = document->completeURL(url); if (!AsyncFileSystem::isAvailable() || !securityOrigin->canAccessFileSystem() || !securityOrigin->canRequest(completedURL)) { DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::SECURITY_ERR)); return; @@ -771,7 +779,7 @@ void DOMWindow::resolveLocalFileSystemURI(const String& uri, PassRefPtr<EntryCal AsyncFileSystem::Type type; String filePath; if (!completedURL.isValid() || !DOMFileSystemBase::crackFileSystemURL(completedURL, type, filePath)) { - DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::SYNTAX_ERR)); + DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::ENCODING_ERR)); return; } @@ -943,6 +951,12 @@ void DOMWindow::print() page->chrome()->print(m_frame); } +void DOMWindow::printTimerFired(Timer<DOMWindow>* timer) +{ + ASSERT_UNUSED(timer, timer == &m_printTimer); + print(); +} + void DOMWindow::stop() { if (!m_frame) @@ -1571,11 +1585,8 @@ void DOMWindow::dispatchLoadEvent() // This is a DOM extension and is independent of bubbling/capturing rules of // the DOM. Element* ownerElement = m_frame ? m_frame->ownerElement() : 0; - if (ownerElement) { - RefPtr<Event> ownerEvent = Event::create(eventNames().loadEvent, false, false); - ownerEvent->setTarget(ownerElement); - ownerElement->dispatchGenericEvent(ownerEvent.release()); - } + if (ownerElement) + ownerElement->dispatchEvent(Event::create(eventNames().loadEvent, false, false)); InspectorInstrumentation::loadEventFired(frame(), url()); } @@ -1636,7 +1647,9 @@ void DOMWindow::finishedLoading() { if (m_shouldPrintWhenFinishedLoading) { m_shouldPrintWhenFinishedLoading = false; - print(); + + m_printTimer.stop(); + m_printTimer.startOneShot(0); } } diff --git a/Source/WebCore/page/DOMWindow.h b/Source/WebCore/page/DOMWindow.h index b365f53..404f40f 100644 --- a/Source/WebCore/page/DOMWindow.h +++ b/Source/WebCore/page/DOMWindow.h @@ -30,6 +30,7 @@ #include "KURL.h" #include "MessagePort.h" #include "SecurityOrigin.h" +#include "Timer.h" namespace WebCore { @@ -222,6 +223,7 @@ namespace WebCore { String crossDomainAccessErrorMessage(DOMWindow* activeWindow); void pageDestroyed(); + void resetGeolocation(); void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, DOMWindow* source, ExceptionCode&); // FIXME: remove this when we update the ObjC bindings (bug #28774). @@ -391,7 +393,7 @@ namespace WebCore { PERSISTENT, }; void requestFileSystem(int type, long long size, PassRefPtr<FileSystemCallback>, PassRefPtr<ErrorCallback>); - void resolveLocalFileSystemURI(const String&, PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>); + void resolveLocalFileSystemURL(const String&, PassRefPtr<EntryCallback>, PassRefPtr<ErrorCallback>); #endif #if ENABLE(INDEXED_DATABASE) @@ -436,6 +438,8 @@ namespace WebCore { virtual EventTargetData* eventTargetData(); virtual EventTargetData* ensureEventTargetData(); + void printTimerFired(Timer<DOMWindow>*); + static Frame* createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures&, DOMWindow* activeWindow, Frame* firstFrame, Frame* openerFrame, PrepareDialogFunction = 0, void* functionContext = 0); @@ -461,6 +465,8 @@ namespace WebCore { mutable RefPtr<Location> m_location; mutable RefPtr<StyleMedia> m_media; + Timer<DOMWindow> m_printTimer; + EventTargetData m_eventTargetData; String m_status; diff --git a/Source/WebCore/page/DOMWindow.idl b/Source/WebCore/page/DOMWindow.idl index 530c4ad..8c6e929 100644 --- a/Source/WebCore/page/DOMWindow.idl +++ b/Source/WebCore/page/DOMWindow.idl @@ -195,7 +195,7 @@ module window { const unsigned short TEMPORARY = 0; const unsigned short PERSISTENT = 1; [EnabledAtRuntime=FileSystem] void requestFileSystem(in unsigned short type, in long long size, in [Callback, Optional] FileSystemCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback); - [EnabledAtRuntime=FileSystem] void resolveLocalFileSystemURI(in DOMString uri, in [Callback, Optional] EntryCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback); + [EnabledAtRuntime=FileSystem] void resolveLocalFileSystemURL(in DOMString url, in [Callback, Optional] EntryCallback successCallback, in [Callback, Optional] ErrorCallback errorCallback); attribute [EnabledAtRuntime=FileSystem] FlagsConstructor Flags; #endif @@ -491,15 +491,15 @@ module window { attribute CanvasGradientConstructor CanvasGradient; attribute CanvasRenderingContext2DConstructor CanvasRenderingContext2D; attribute ImageDataConstructor ImageData; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLActiveInfoConstructor WebGLActiveInfo; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLBufferConstructor WebGLBuffer; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLFramebufferConstructor WebGLFramebuffer; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLProgramConstructor WebGLProgram; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLRenderbufferConstructor WebGLRenderbuffer; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLRenderingContextConstructor WebGLRenderingContext; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLShaderConstructor WebGLShader; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLTextureConstructor WebGLTexture; - attribute [Conditional=WEBGL,EnabledAtRuntime] WebGLUniformLocationConstructor WebGLUniformLocation; + attribute [Conditional=WEBGL] WebGLActiveInfoConstructor WebGLActiveInfo; + attribute [Conditional=WEBGL] WebGLBufferConstructor WebGLBuffer; + attribute [Conditional=WEBGL] WebGLFramebufferConstructor WebGLFramebuffer; + attribute [Conditional=WEBGL] WebGLProgramConstructor WebGLProgram; + attribute [Conditional=WEBGL] WebGLRenderbufferConstructor WebGLRenderbuffer; + attribute [Conditional=WEBGL] WebGLRenderingContextConstructor WebGLRenderingContext; + attribute [Conditional=WEBGL] WebGLShaderConstructor WebGLShader; + attribute [Conditional=WEBGL] WebGLTextureConstructor WebGLTexture; + attribute [Conditional=WEBGL] WebGLUniformLocationConstructor WebGLUniformLocation; attribute TextMetricsConstructor TextMetrics; attribute DOMStringMapConstructor DOMStringMap; @@ -606,6 +606,9 @@ module window { attribute [Conditional=VIDEO, EnabledAtRuntime] MediaErrorConstructor MediaError; attribute [Conditional=VIDEO, EnabledAtRuntime] TimeRangesConstructor TimeRanges; + attribute WebKitAnimationConstructor WebKitAnimation; + attribute WebKitAnimationListConstructor WebKitAnimationList; + #if defined(ENABLE_XPATH) && ENABLE_XPATH attribute XPathEvaluatorConstructor XPathEvaluator; attribute XPathResultConstructor XPathResult; @@ -721,7 +724,7 @@ module window { attribute SVGSetElementConstructor SVGSetElement; #endif -#if ENABLE_SVG_FONTS && ENABLE_SVG_FONTS +#if defined(ENABLE_SVG_FONTS) && ENABLE_SVG_FONTS // attribute SVGAltGlyphDefElementConstructor SVGAltGlyphDefElement; attribute SVGAltGlyphElementConstructor SVGAltGlyphElement; // attribute SVGAltGlyphItemElementConstructor SVGAltGlyphItemElement; diff --git a/Source/WebCore/page/DragController.cpp b/Source/WebCore/page/DragController.cpp index 6a4bb70..342ad19 100644 --- a/Source/WebCore/page/DragController.cpp +++ b/Source/WebCore/page/DragController.cpp @@ -353,7 +353,7 @@ DragOperation DragController::operationForLoad(DragData* dragData) { ASSERT(dragData); Document* doc = m_page->mainFrame()->documentAtPoint(dragData->clientPosition()); - if (doc && (m_didInitiateDrag || doc->isPluginDocument() || doc->inDesignMode())) + if (doc && (m_didInitiateDrag || doc->isPluginDocument() || doc->rendererIsEditable())) return DragOperationNone; return dragOperation(dragData); } @@ -371,6 +371,7 @@ static bool setSelectionToDragCaret(Frame* frame, VisibleSelection& dragCaret, R bool DragController::dispatchTextInputEventFor(Frame* innerFrame, DragData* dragData) { + ASSERT(!m_page->dragCaretController()->isNone()); VisibleSelection dragCaret(m_page->dragCaretController()->selection()); String text = dragCaret.isContentRichlyEditable() ? "" : dragData->asPlainText(innerFrame); Node* target = innerFrame->editor()->findEventTargetFrom(dragCaret); @@ -393,7 +394,7 @@ bool DragController::concludeEditDrag(DragData* dragData) Frame* innerFrame = element->ownerDocument()->frame(); ASSERT(innerFrame); - if (!dispatchTextInputEventFor(innerFrame, dragData)) + if (!m_page->dragCaretController()->isNone() && !dispatchTextInputEventFor(innerFrame, dragData)) return true; if (dragData->containsColor()) { @@ -510,7 +511,7 @@ bool DragController::canProcessDrag(DragData* dragData) if (dragData->containsFiles() && asFileInput(result.innerNonSharedNode())) return true; - if (!result.innerNonSharedNode()->isContentEditable()) + if (!result.innerNonSharedNode()->rendererIsEditable()) return false; if (m_didInitiateDrag && m_documentUnderMouse == m_dragInitiator && result.isSelected()) diff --git a/Source/WebCore/page/DragController.h b/Source/WebCore/page/DragController.h index 0f176b1..693189a 100644 --- a/Source/WebCore/page/DragController.h +++ b/Source/WebCore/page/DragController.h @@ -66,7 +66,6 @@ namespace WebCore { void setIsHandlingDrag(bool handling) { m_isHandlingDrag = handling; } bool isHandlingDrag() const { return m_isHandlingDrag; } DragOperation sourceDragOperation() const { return m_sourceDragOperation; } - void setDraggingImageURL(const KURL& url) { m_draggingImageURL = url; } const KURL& draggingImageURL() const { return m_draggingImageURL; } void setDragOffset(const IntPoint& offset) { m_dragOffset = offset; } const IntPoint& dragOffset() const { return m_dragOffset; } diff --git a/Source/WebCore/page/EditorClient.h b/Source/WebCore/page/EditorClient.h index d5de6a4..aeda844 100644 --- a/Source/WebCore/page/EditorClient.h +++ b/Source/WebCore/page/EditorClient.h @@ -158,14 +158,15 @@ public: virtual TextCheckerClient* textChecker() = 0; -#if SUPPORT_AUTOCORRECTION_PANEL enum AutocorrectionResponseType { AutocorrectionEdited, AutocorrectionReverted }; - virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacmentString, const Vector<String>& alternativeReplacementStrings, Editor*) = 0; + +#if SUPPORT_AUTOCORRECTION_PANEL + virtual void showCorrectionPanel(CorrectionPanelInfo::PanelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacmentString, const Vector<String>& alternativeReplacementStrings) = 0; virtual void dismissCorrectionPanel(ReasonForDismissingCorrectionPanel) = 0; - virtual bool isShowingCorrectionPanel() = 0; + virtual String dismissCorrectionPanelSoon(ReasonForDismissingCorrectionPanel) = 0; virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const String& replacedString, const String& replacementString) = 0; #endif diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp index ef2ffb3..de59083 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp @@ -98,6 +98,10 @@ #include "TouchEvent.h" #endif +#if ENABLE(GESTURE_RECOGNIZER) +#include "PlatformGestureRecognizer.h" +#endif + #if defined(ANDROID_PLUGINS) #include "WebViewCore.h" #endif @@ -209,6 +213,9 @@ EventHandler::EventHandler(Frame* frame) #if ENABLE(TOUCH_EVENTS) , m_touchPressed(false) #endif +#if ENABLE(GESTURE_RECOGNIZER) + , m_gestureRecognizer(PlatformGestureRecognizer::create()) +#endif { } @@ -260,6 +267,20 @@ void EventHandler::clear() #endif } +static void setSelectionIfNeeded(SelectionController* selection, const VisibleSelection& newSelection) +{ + ASSERT(selection); + if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection)) + selection->setSelection(newSelection); +} + +static void setNonDirectionalSelectionIfNeeded(SelectionController* selection, const VisibleSelection& newSelection, TextGranularity granularity) +{ + ASSERT(selection); + if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection)) + selection->setSelection(newSelection, granularity, MakeNonDirectionalSelection); +} + void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result) { Node* innerNode = result.targetNode(); @@ -279,9 +300,8 @@ void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe if (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled()) newSelection.appendTrailingWhitespace(); } - - if (m_frame->selection()->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection, granularity, MakeNonDirectionalSelection); + + setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); } } @@ -305,8 +325,7 @@ void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit m_beganSelectingText = true; } - if (m_frame->selection()->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection, granularity, MakeNonDirectionalSelection); + setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); } } @@ -349,9 +368,8 @@ bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR granularity = ParagraphGranularity; m_beganSelectingText = true; } - - if (m_frame->selection()->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection, granularity, MakeNonDirectionalSelection); + + setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); return true; } @@ -416,9 +434,8 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR m_beganSelectingText = true; } else newSelection = VisibleSelection(visiblePos); - - if (m_frame->selection()->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection, granularity, MakeNonDirectionalSelection); + + setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); return true; } @@ -555,7 +572,13 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e m_mouseDownMayStartAutoscroll = false; } - + + if (!m_beganSelectingText) { + HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); + HitTestResult result(m_mouseDownPos); + m_frame->document()->renderView()->layer()->hitTest(request, result); + updateSelectionForMouseDrag(result.innerNode(), result.localPoint()); + } updateSelectionForMouseDrag(targetNode, event.localPoint()); return true; } @@ -653,10 +676,7 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& if (m_frame->selection()->granularity() != CharacterGranularity) newSelection.expandUsingGranularity(m_frame->selection()->granularity()); - if (m_frame->selection()->shouldChangeSelection(newSelection)) { - m_frame->selection()->setIsDirectional(false); - m_frame->selection()->setSelection(newSelection, m_frame->selection()->granularity(), MakeNonDirectionalSelection); - } + setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, m_frame->selection()->granularity()); } #endif // ENABLE(DRAG_SUPPORT) @@ -713,12 +733,12 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e VisibleSelection newSelection; Node* node = event.targetNode(); bool caretBrowsing = m_frame->settings()->caretBrowsingEnabled(); - if (node && (caretBrowsing || node->isContentEditable()) && node->renderer()) { + if (node && (caretBrowsing || node->rendererIsEditable()) && node->renderer()) { VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint()); newSelection = VisibleSelection(pos); } - if (m_frame->selection()->shouldChangeSelection(newSelection)) - m_frame->selection()->setSelection(newSelection); + + setSelectionIfNeeded(m_frame->selection(), newSelection); handled = true; } @@ -1165,7 +1185,7 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scr switch (style ? style->cursor() : CURSOR_AUTO) { case CURSOR_AUTO: { - bool editable = (node && node->isContentEditable()); + bool editable = (node && node->rendererIsEditable()); bool editableLinkEnabled = false; // If the link is editable, then we need to check the settings to see whether or not the link should be followed @@ -1456,6 +1476,22 @@ bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEv return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; } +static RenderLayer* layerForNode(Node* node) +{ + if (!node) + return 0; + + RenderObject* renderer = node->renderer(); + if (!renderer) + return 0; + + RenderLayer* layer = renderer->enclosingLayer(); + if (!layer) + return 0; + + return layer; +} + bool EventHandler::mouseMoved(const PlatformMouseEvent& event) { HitTestResult hoveredNode = HitTestResult(IntPoint()); @@ -1465,6 +1501,11 @@ bool EventHandler::mouseMoved(const PlatformMouseEvent& event) if (!page) return result; + if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) { + if (page->containsScrollableArea(layer)) + layer->scrollAnimator()->mouseMovedInContentArea(); + } + if (FrameView* frameView = m_frame->view()) frameView->scrollAnimator()->mouseMovedInContentArea(); @@ -1889,21 +1930,32 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo // Fire mouseout/mouseover if the mouse has shifted to a different node. if (fireMouseOverOut) { - // FIXME: This code will only correctly handle transitions between frames with scrollbars, - // not transitions between overflow regions, or transitions between two frames - // that don't have scrollbars contained within a frame that does. + RenderLayer* layerForLastNode = layerForNode(m_lastNodeUnderMouse.get()); + RenderLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get()); + Page* page = m_frame->page(); + if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->document() != m_frame->document())) { + // The mouse has moved between frames. if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) { if (FrameView* frameView = frame->view()) frameView->scrollAnimator()->mouseExitedContentArea(); } + } else if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNodeUnderMouse != layerForLastNode))) { + // The mouse has moved between layers. + if (page->containsScrollableArea(layerForLastNode)) + layerForLastNode->scrollAnimator()->mouseExitedContentArea(); } if (m_nodeUnderMouse && (!m_lastNodeUnderMouse || m_lastNodeUnderMouse->document() != m_frame->document())) { + // The mouse has moved between frames. if (Frame* frame = m_nodeUnderMouse->document()->frame()) { if (FrameView* frameView = frame->view()) frameView->scrollAnimator()->mouseEnteredContentArea(); } + } else if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNodeUnderMouse != layerForLastNode))) { + // The mouse has moved between layers. + if (page->containsScrollableArea(layerForNodeUnderMouse)) + layerForNodeUnderMouse->scrollAnimator()->mouseEnteredContentArea(); } if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) { @@ -2360,6 +2412,8 @@ bool EventHandler::needsKeyboardEventDisambiguationQuirks() const bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) { + RefPtr<FrameView> protector(m_frame->view()); + #if ENABLE(PAN_SCROLLING) if (Page* page = m_frame->page()) { if (page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) { @@ -3123,6 +3177,11 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) } } +#if ENABLE(GESTURE_RECOGNIZER) + if (m_gestureRecognizer) + m_gestureRecognizer->processTouchEventForGesture(event, this, defaultPrevented); +#endif + return defaultPrevented; } #endif diff --git a/Source/WebCore/page/EventHandler.h b/Source/WebCore/page/EventHandler.h index e20e43c..70d6194 100644 --- a/Source/WebCore/page/EventHandler.h +++ b/Source/WebCore/page/EventHandler.h @@ -34,6 +34,7 @@ #include "TextEventInputType.h" #include "Timer.h" #include <wtf/Forward.h> +#include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> #if PLATFORM(MAC) && !defined(__OBJC__) @@ -76,6 +77,10 @@ class Widget; class PlatformGestureEvent; #endif +#if ENABLE(GESTURE_RECOGNIZER) +class PlatformGestureRecognizer; +#endif + #if ENABLE(DRAG_SUPPORT) extern const int LinkDragHysteresis; extern const int ImageDragHysteresis; @@ -456,6 +461,9 @@ private: RefPtr<Node> m_capturingTouchEventsNode; #endif #endif +#if ENABLE(GESTURE_RECOGNIZER) + OwnPtr<PlatformGestureRecognizer> m_gestureRecognizer; +#endif }; } // namespace WebCore diff --git a/Source/WebCore/page/FocusController.cpp b/Source/WebCore/page/FocusController.cpp index 10901c5..41cfee4 100644 --- a/Source/WebCore/page/FocusController.cpp +++ b/Source/WebCore/page/FocusController.cpp @@ -301,7 +301,7 @@ bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, Keyb static bool relinquishesEditingFocus(Node *node) { ASSERT(node); - ASSERT(node->isContentEditable()); + ASSERT(node->rendererIsEditable()); Node* root = node->rootEditableElement(); Frame* frame = node->document()->frame(); @@ -410,11 +410,16 @@ void FocusController::setActive(bool active) view->updateLayoutAndStyleIfNeededRecursive(); view->updateControlTints(); } - // FIXME: This should propogate to all ScrollableAreas. - if (!active) - view->scrollAnimator()->contentAreaDidHide(); - else - view->scrollAnimator()->contentAreaDidShow(); + + if (const HashSet<ScrollableArea*>* scrollableAreas = m_page->scrollableAreaSet()) { + HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end(); + for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it) { + if (!active) + (*it)->scrollAnimator()->contentAreaDidHide(); + else + (*it)->scrollAnimator()->contentAreaDidShow(); + } + } } focusedOrMainFrame()->selection()->pageActivationChanged(); diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp index 9a562a1..3652c9a 100644 --- a/Source/WebCore/page/Frame.cpp +++ b/Source/WebCore/page/Frame.cpp @@ -690,8 +690,10 @@ void Frame::pageDestroyed() if (Frame* parent = tree()->parent()) parent->loader()->checkLoadComplete(); - if (m_domWindow) + if (m_domWindow) { + m_domWindow->resetGeolocation(); m_domWindow->pageDestroyed(); + } // FIXME: It's unclear as to why this is called more than once, but it is, // so page() could be NULL. @@ -736,6 +738,13 @@ void Frame::transferChildFrameToNewDocument() m_page->decrementFrameCount(); } + // FIXME: We should ideally allow existing Geolocation activities to continue + // when the Geolocation's iframe is reparented. + // See https://bugs.webkit.org/show_bug.cgi?id=55577 + // and https://bugs.webkit.org/show_bug.cgi?id=52877 + if (m_domWindow) + m_domWindow->resetGeolocation(); + m_page = newPage; if (newPage) @@ -901,7 +910,7 @@ Color Frame::tiledBackingStoreBackgroundColor() const } #endif -String Frame::layerTreeAsText() const +String Frame::layerTreeAsText(bool showDebugInfo) const { #if USE(ACCELERATED_COMPOSITING) document()->updateLayout(); @@ -909,7 +918,7 @@ String Frame::layerTreeAsText() const if (!contentRenderer()) return String(); - return contentRenderer()->compositor()->layerTreeAsText(); + return contentRenderer()->compositor()->layerTreeAsText(showDebugInfo); #else return String(); #endif diff --git a/Source/WebCore/page/Frame.h b/Source/WebCore/page/Frame.h index 25f8aac..f22fcb8 100644 --- a/Source/WebCore/page/Frame.h +++ b/Source/WebCore/page/Frame.h @@ -127,7 +127,7 @@ namespace WebCore { void injectUserScripts(UserScriptInjectionTime); - String layerTreeAsText() const; + String layerTreeAsText(bool showDebugInfo = false) const; // Unlike most accessors in this class, domWindow() always creates a new DOMWindow if m_domWindow is null. // Callers that don't need a new DOMWindow to be created should use existingDOMWindow(). diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp index 8ab19ab..9cf2c57 100644 --- a/Source/WebCore/page/FrameView.cpp +++ b/Source/WebCore/page/FrameView.cpp @@ -141,13 +141,19 @@ FrameView::FrameView(Frame* frame) , m_shouldUpdateWhileOffscreen(true) , m_deferSetNeedsLayouts(0) , m_setNeedsLayoutWasDeferred(false) - , m_isRestoringFromBackForward(false) , m_scrollCorner(0) #if ENABLE(ANDROID_OVERFLOW_SCROLL) , m_hasOverflowScroll(false) #endif { init(); + + if (m_frame) { + if (Page* page = m_frame->page()) { + m_page = page; + m_page->addScrollableArea(this); + } + } } PassRefPtr<FrameView> FrameView::create(Frame* frame) @@ -188,6 +194,9 @@ FrameView::~FrameView() ASSERT(!m_scrollCorner); ASSERT(m_actionScheduler->isEmpty()); + if (m_page) + m_page->removeScrollableArea(this); + if (m_frame) { ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); RenderPart* renderer = m_frame->ownerRenderer(); @@ -229,7 +238,6 @@ void FrameView::reset() m_isPainting = false; m_isVisuallyNonEmpty = false; m_firstVisuallyNonEmptyLayoutCallbackPending = true; - m_isRestoringFromBackForward = false; m_maintainScrollPositionAnchor = 0; } @@ -255,6 +263,15 @@ void FrameView::resetScrollbars() setScrollbarsSuppressed(false); } +void FrameView::resetScrollbarsAndClearContentsSize() +{ + resetScrollbars(); + + setScrollbarsSuppressed(true); + setContentsSize(IntSize()); + setScrollbarsSuppressed(false); +} + void FrameView::init() { reset(); @@ -854,12 +871,7 @@ void FrameView::layout(bool allowSubtree) if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { if (m_firstLayout) { - if (!m_isRestoringFromBackForward) - setScrollbarsSuppressed(true); - else { - setScrollbarsSuppressed(false); - m_isRestoringFromBackForward = false; - } + setScrollbarsSuppressed(true); m_firstLayout = false; m_firstLayoutCallbackPending = true; @@ -931,8 +943,10 @@ void FrameView::layout(bool allowSubtree) // Now update the positions of all layers. beginDeferredRepaints(); IntPoint cachedOffset; - layer->updateLayerPositions((m_doFullRepaint ? RenderLayer::DoFullRepaint : 0) - | RenderLayer::CheckForRepaint + if (m_doFullRepaint) + root->view()->repaint(); // FIXME: This isn't really right, since the RenderView doesn't fully encompass the visibleContentRect(). It just happens + // to work out most of the time, since first layouts and printing don't have you scrolled anywhere. + layer->updateLayerPositions((m_doFullRepaint ? 0 : RenderLayer::CheckForRepaint) | RenderLayer::IsCompositingUpdateRoot | RenderLayer::UpdateCompositingLayers, subtree ? 0 : &cachedOffset); @@ -2125,6 +2139,28 @@ void FrameView::didCompleteRubberBand(const IntSize& initialOverhang) const return page->chrome()->client()->didCompleteRubberBandForMainFrame(initialOverhang); } +void FrameView::scrollbarStyleChanged() +{ + m_frame->page()->setNeedsRecalcStyleInAllFrames(); +} + +bool FrameView::shouldSuspendScrollAnimations() const +{ + return m_frame->loader()->state() != FrameStateComplete; +} + +void FrameView::notifyPageThatContentAreaWillPaint() const +{ + Page* page = m_frame->page(); + const HashSet<ScrollableArea*>* scrollableAreas = page->scrollableAreaSet(); + if (!scrollableAreas) + return; + + HashSet<ScrollableArea*>::const_iterator end = scrollableAreas->end(); + for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(); it != end; ++it) + (*it)->scrollAnimator()->contentAreaWillPaint(); +} + #if ENABLE(DASHBOARD_SUPPORT) void FrameView::updateDashboardRegions() { @@ -2339,8 +2375,12 @@ 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; + RenderLayer* rootLayer = contentRenderer->layer(); - contentRenderer->layer()->paint(p, rect, m_paintBehavior, eltRenderer); + rootLayer->paint(p, rect, m_paintBehavior, eltRenderer); + + if (rootLayer->containsDirtyOverlayScrollbars()) + rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer); m_isPainting = false; @@ -2468,7 +2508,6 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximu root->setLogicalWidth(flooredPageLogicalWidth); root->setNeedsLayoutAndPrefWidthsRecalc(); forceLayout(); - root->clearLayoutOverflow(); int docLogicalHeight = root->style()->isHorizontalWritingMode() ? root->docHeight() : root->docWidth(); int docLogicalTop = root->style()->isHorizontalWritingMode() ? root->docTop() : root->docLeft(); int docLogicalRight = root->style()->isHorizontalWritingMode() ? root->docRight() : root->docBottom(); @@ -2478,6 +2517,7 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, float maximu IntRect overflow(clippedLogicalLeft, docLogicalTop, flooredPageLogicalWidth, docLogicalHeight); if (!root->style()->isHorizontalWritingMode()) overflow = overflow.transposedRect(); + root->clearLayoutOverflow(); root->addLayoutOverflow(overflow); // This is how we clip in case we overflow again. } } diff --git a/Source/WebCore/page/FrameView.h b/Source/WebCore/page/FrameView.h index 8e79a3a..9af0552 100644 --- a/Source/WebCore/page/FrameView.h +++ b/Source/WebCore/page/FrameView.h @@ -138,6 +138,7 @@ public: void willMoveOffscreen(); void resetScrollbars(); + void resetScrollbarsAndClearContentsSize(); void detachCustomScrollbars(); void clear(); @@ -213,6 +214,7 @@ public: void setPaintBehavior(PaintBehavior); PaintBehavior paintBehavior() const; bool isPainting() const; + bool hasEverPainted() const { return m_lastPaintTime; } void setNodeToDraw(Node*); virtual void paintOverhangAreas(GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect); @@ -274,8 +276,7 @@ public: // FIXME: Remove this method once plugin loading is decoupled from layout. void flushAnyPendingPostLayoutTasks(); - void setIsRestoringFromBackForward(bool isRestoring) { m_isRestoringFromBackForward = isRestoring; } - bool isRestoringFromBackForward() const { return m_isRestoringFromBackForward; } + virtual bool shouldSuspendScrollAnimations() const; protected: virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); @@ -322,6 +323,10 @@ private: virtual void getTickmarks(Vector<IntRect>&) const; virtual void scrollTo(const IntSize&); virtual void didCompleteRubberBand(const IntSize&) const; + virtual void scrollbarStyleChanged(); + + virtual void notifyPageThatContentAreaWillPaint() const; + virtual void disconnectFromPage() { m_page = 0; } void deferredRepaintTimerFired(Timer<FrameView>*); void doDeferredRepaints(); @@ -415,13 +420,13 @@ private: bool m_isVisuallyNonEmpty; bool m_firstVisuallyNonEmptyLayoutCallbackPending; - bool m_isRestoringFromBackForward; - RefPtr<Node> m_maintainScrollPositionAnchor; // Renderer to hold our custom scroll corner. RenderScrollbarPart* m_scrollCorner; + Page* m_page; + static double s_deferredRepaintDelay; static double s_initialDeferredRepaintDelayDuringLoading; static double s_maxDeferredRepaintDelayDuringLoading; diff --git a/Source/WebCore/page/Geolocation.cpp b/Source/WebCore/page/Geolocation.cpp index 354dde3..f0dd76a 100644 --- a/Source/WebCore/page/Geolocation.cpp +++ b/Source/WebCore/page/Geolocation.cpp @@ -231,19 +231,35 @@ Geolocation::Geolocation(Frame* frame) Geolocation::~Geolocation() { + ASSERT(m_allowGeolocation != InProgress); + ASSERT(!m_frame); } -void Geolocation::disconnectFrame() +Page* Geolocation::page() const +{ + return m_frame ? m_frame->page() : 0; +} + +void Geolocation::reset() { - if (m_frame && m_frame->page() && m_allowGeolocation == InProgress) { + Page* page = this->page(); + if (page && m_allowGeolocation == InProgress) { #if ENABLE(CLIENT_BASED_GEOLOCATION) - m_frame->page()->geolocationController()->cancelPermissionRequest(this); + page->geolocationController()->cancelPermissionRequest(this); #else - m_frame->page()->chrome()->cancelGeolocationPermissionRequestForFrame(m_frame, this); + page->chrome()->cancelGeolocationPermissionRequestForFrame(m_frame, this); #endif } + // The frame may be moving to a new page and we want to get the permissions from the new page's client. + m_allowGeolocation = Unknown; cancelAllRequests(); stopUpdating(); +} + +void Geolocation::disconnectFrame() +{ + // Once we are disconnected from the Frame, it is no longer possible to perform any operations. + reset(); if (m_frame && m_frame->document()) m_frame->document()->setUsingGeolocation(false); m_frame = 0; @@ -252,10 +268,7 @@ void Geolocation::disconnectFrame() Geoposition* Geolocation::lastPosition() { #if ENABLE(CLIENT_BASED_GEOLOCATION) - if (!m_frame) - return 0; - - Page* page = m_frame->page(); + Page* page = this->page(); if (!page) return 0; @@ -594,10 +607,7 @@ void Geolocation::requestPermission() if (m_allowGeolocation > Unknown) return; - if (!m_frame) - return; - - Page* page = m_frame->page(); + Page* page = this->page(); if (!page) return; @@ -691,10 +701,7 @@ void Geolocation::geolocationServiceErrorOccurred(GeolocationService* service) bool Geolocation::startUpdating(GeoNotifier* notifier) { #if ENABLE(CLIENT_BASED_GEOLOCATION) - if (!m_frame) - return false; - - Page* page = m_frame->page(); + Page* page = this->page(); if (!page) return false; @@ -720,10 +727,7 @@ bool Geolocation::startUpdating(GeoNotifier* notifier) void Geolocation::stopUpdating() { #if ENABLE(CLIENT_BASED_GEOLOCATION) - if (!m_frame) - return; - - Page* page = m_frame->page(); + Page* page = this->page(); if (!page) return; @@ -764,6 +768,8 @@ namespace WebCore { void Geolocation::clearWatch(int) {} +void Geolocation::reset() {} + void Geolocation::disconnectFrame() {} Geolocation::Geolocation(Frame*) {} diff --git a/Source/WebCore/page/Geolocation.h b/Source/WebCore/page/Geolocation.h index 7c06ae4..b52ad45 100644 --- a/Source/WebCore/page/Geolocation.h +++ b/Source/WebCore/page/Geolocation.h @@ -58,6 +58,7 @@ public: ~Geolocation(); + void reset(); void disconnectFrame(); void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); @@ -86,6 +87,8 @@ private: Geolocation(Frame*); + Page* page() const; + class GeoNotifier : public RefCounted<GeoNotifier> { public: static PassRefPtr<GeoNotifier> create(Geolocation* geolocation, PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(new GeoNotifier(geolocation, positionCallback, positionErrorCallback, options)); } diff --git a/Source/WebCore/page/GeolocationController.cpp b/Source/WebCore/page/GeolocationController.cpp index 764b913..b9533ca 100644 --- a/Source/WebCore/page/GeolocationController.cpp +++ b/Source/WebCore/page/GeolocationController.cpp @@ -41,12 +41,10 @@ GeolocationController::GeolocationController(Page* page, GeolocationClient* clie GeolocationController::~GeolocationController() { - if (m_client) { - if (!m_observers.isEmpty()) - m_client->stopUpdating(); + ASSERT(m_observers.isEmpty()); + if (m_client) m_client->geolocationDestroyed(); - } } void GeolocationController::addObserver(Geolocation* observer, bool enableHighAccuracy) diff --git a/Source/WebCore/page/Navigator.cpp b/Source/WebCore/page/Navigator.cpp index 53563b4..9526536 100644 --- a/Source/WebCore/page/Navigator.cpp +++ b/Source/WebCore/page/Navigator.cpp @@ -61,6 +61,12 @@ Navigator::~Navigator() disconnectFrame(); } +void Navigator::resetGeolocation() +{ + if (m_geolocation) + m_geolocation->reset(); +} + void Navigator::disconnectFrame() { if (m_plugins) { diff --git a/Source/WebCore/page/Navigator.h b/Source/WebCore/page/Navigator.h index f7dc543..8514279 100644 --- a/Source/WebCore/page/Navigator.h +++ b/Source/WebCore/page/Navigator.h @@ -49,6 +49,7 @@ public: static PassRefPtr<Navigator> create(Frame* frame) { return adoptRef(new Navigator(frame)); } virtual ~Navigator(); + void resetGeolocation(); void disconnectFrame(); Frame* frame() const { return m_frame; } diff --git a/Source/WebCore/page/NavigatorBase.cpp b/Source/WebCore/page/NavigatorBase.cpp index ca51a29..3ff195a 100644 --- a/Source/WebCore/page/NavigatorBase.cpp +++ b/Source/WebCore/page/NavigatorBase.cpp @@ -57,7 +57,7 @@ #endif // ifndef WEBCORE_NAVIGATOR_PRODUCT_SUB #ifndef WEBCORE_NAVIGATOR_VENDOR -#define WEBCORE_NAVIGATOR_VENDOR "Apple Computer, Inc." +#define WEBCORE_NAVIGATOR_VENDOR "Apple Inc." #endif // ifndef WEBCORE_NAVIGATOR_VENDOR #ifndef WEBCORE_NAVIGATOR_VENDOR_SUB diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp index f8d6168..63227e4 100644 --- a/Source/WebCore/page/Page.cpp +++ b/Source/WebCore/page/Page.cpp @@ -177,6 +177,7 @@ Page::Page(const PageClients& pageClients) , m_canStartMedia(true) , m_viewMode(ViewModeWindowed) , m_minimumTimerInterval(Settings::defaultMinDOMTimerInterval()) + , m_isEditable(false) { if (!allPages) { allPages = new HashSet<Page*>; @@ -209,6 +210,12 @@ Page::~Page() for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) frame->pageDestroyed(); + if (m_scrollableAreaSet) { + ScrollableAreaSet::const_iterator end = m_scrollableAreaSet->end(); + for (ScrollableAreaSet::const_iterator it = m_scrollableAreaSet->begin(); it != end; ++it) + (*it)->disconnectFromPage(); + } + m_editorClient->pageDestroyed(); InspectorInstrumentation::inspectedPageDestroyed(this); @@ -402,6 +409,12 @@ void Page::scheduleForcedStyleRecalcForAllPages() frame->document()->scheduleForcedStyleRecalc(); } +void Page::setNeedsRecalcStyleInAllFrames() +{ + for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) + frame->document()->styleSelectorChanged(DeferRecalcStyle); +} + void Page::updateViewportArguments() { if (!mainFrame() || !mainFrame()->document() || mainFrame()->document()->viewportArguments() == m_viewportArguments) @@ -910,6 +923,27 @@ void Page::didStopPlugin(HaltablePlugin* obj) m_pluginHalter->didStopPlugin(obj); } +void Page::addScrollableArea(ScrollableArea* scrollableArea) +{ + if (!m_scrollableAreaSet) + m_scrollableAreaSet = adoptPtr(new ScrollableAreaSet); + m_scrollableAreaSet->add(scrollableArea); +} + +void Page::removeScrollableArea(ScrollableArea* scrollableArea) +{ + if (!m_scrollableAreaSet) + return; + m_scrollableAreaSet->remove(scrollableArea); +} + +bool Page::containsScrollableArea(ScrollableArea* scrollableArea) const +{ + if (!m_scrollableAreaSet) + return false; + return m_scrollableAreaSet->contains(scrollableArea); +} + #if !ASSERT_DISABLED void Page::checkFrameCountConsistency() const { diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h index 4498d36..8307123 100644 --- a/Source/WebCore/page/Page.h +++ b/Source/WebCore/page/Page.h @@ -70,6 +70,7 @@ namespace WebCore { class ProgressTracker; class RenderTheme; class VisibleSelection; + class ScrollableArea; class SelectionController; class Settings; class SharedGraphicsContext3D; @@ -118,6 +119,8 @@ namespace WebCore { Page(const PageClients&); ~Page(); + void setNeedsRecalcStyleInAllFrames(); + RenderTheme* theme() const { return m_theme.get(); }; ViewportArguments viewportArguments() const { return m_viewportArguments; } @@ -279,11 +282,21 @@ namespace WebCore { void setJavaScriptURLsAreAllowed(bool); bool javaScriptURLsAreAllowed() const; + typedef HashSet<ScrollableArea*> ScrollableAreaSet; + void addScrollableArea(ScrollableArea*); + void removeScrollableArea(ScrollableArea*); + bool containsScrollableArea(ScrollableArea*) const; + const ScrollableAreaSet* scrollableAreaSet() const { return m_scrollableAreaSet.get(); } + // Don't allow more than a certain number of frames in a page. // This seems like a reasonable upper bound, and otherwise mutually // recursive frameset pages can quickly bring the program to its knees // with exponential growth in the number of frames. static const int maxNumberOfFrames = 1000; + + void setEditable(bool isEditable) { m_isEditable = isEditable; } + bool isEditable() { return m_isEditable; } + private: void initGroup(); @@ -386,6 +399,10 @@ namespace WebCore { ViewportArguments m_viewportArguments; double m_minimumTimerInterval; + + OwnPtr<ScrollableAreaSet> m_scrollableAreaSet; + + bool m_isEditable; }; } // namespace WebCore diff --git a/Source/WebCore/page/PageGroup.cpp b/Source/WebCore/page/PageGroup.cpp index 96e7301..969e2a6 100644 --- a/Source/WebCore/page/PageGroup.cpp +++ b/Source/WebCore/page/PageGroup.cpp @@ -33,6 +33,7 @@ #include "GroupSettings.h" #include "IDBFactoryBackendInterface.h" #include "Page.h" +#include "SecurityOrigin.h" #include "Settings.h" #include "StorageNamespace.h" @@ -115,12 +116,57 @@ void PageGroup::closeLocalStorage() #endif } -#if ENABLE(DOM_STORAGE) && defined(ANDROID) -void PageGroup::clearDomStorage() +#if ENABLE(DOM_STORAGE) + +void PageGroup::clearLocalStorageForAllOrigins() { if (!pageGroups) return; + PageGroupMap::iterator end = pageGroups->end(); + for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) { + if (it->second->hasLocalStorage()) + it->second->localStorage()->clearAllOriginsForDeletion(); + } +} + +void PageGroup::clearLocalStorageForOrigin(SecurityOrigin* origin) +{ + if (!pageGroups) + return; + + PageGroupMap::iterator end = pageGroups->end(); + for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) { + if (it->second->hasLocalStorage()) + it->second->localStorage()->clearOriginForDeletion(origin); + } +} + +void PageGroup::syncLocalStorage() +{ + if (!pageGroups) + return; + + PageGroupMap::iterator end = pageGroups->end(); + for (PageGroupMap::iterator it = pageGroups->begin(); it != end; ++it) { + if (it->second->hasLocalStorage()) + it->second->localStorage()->sync(); + } +} + +unsigned PageGroup::numberOfPageGroups() +{ + if (!pageGroups) + return 0; + + return pageGroups->size(); +} + +#if defined(ANDROID) +void PageGroup::clearDomStorage() +{ + if (!pageGroups) + return; PageGroupMap::iterator end = pageGroups->end(); @@ -198,6 +244,8 @@ void PageGroup::removeLocalStorage() m_localStorage = 0; } +#endif // PLATFORM(ANDROID) + #endif void PageGroup::addPage(Page* page) @@ -299,6 +347,7 @@ StorageNamespace* PageGroup::localStorage() return m_localStorage.get(); } + #endif #if ENABLE(INDEXED_DATABASE) diff --git a/Source/WebCore/page/PageGroup.h b/Source/WebCore/page/PageGroup.h index aa600a5..71e22a1 100644 --- a/Source/WebCore/page/PageGroup.h +++ b/Source/WebCore/page/PageGroup.h @@ -39,6 +39,7 @@ namespace WebCore { class GroupSettings; class IDBFactoryBackendInterface; class Page; + class SecurityOrigin; class StorageNamespace; class PageGroup { @@ -49,7 +50,16 @@ namespace WebCore { ~PageGroup(); static PageGroup* pageGroup(const String& groupName); + static void closeLocalStorage(); + +#if ENABLE(DOM_STORAGE) + static void clearLocalStorageForAllOrigins(); + static void clearLocalStorageForOrigin(SecurityOrigin*); + // DumpRenderTree helper that triggers a StorageArea sync. + static void syncLocalStorage(); +#endif + static unsigned numberOfPageGroups(); #if ENABLE(DOM_STORAGE) && defined(ANDROID) static void clearDomStorage(); diff --git a/Source/WebCore/page/PageGroupLoadDeferrer.cpp b/Source/WebCore/page/PageGroupLoadDeferrer.cpp index 292b4cd..dfbb244 100644 --- a/Source/WebCore/page/PageGroupLoadDeferrer.cpp +++ b/Source/WebCore/page/PageGroupLoadDeferrer.cpp @@ -21,11 +21,11 @@ #include "config.h" #include "PageGroupLoadDeferrer.h" -#include "AsyncScriptRunner.h" #include "DocumentParser.h" #include "Frame.h" #include "Page.h" #include "PageGroup.h" +#include "ScriptRunner.h" #include <wtf/HashSet.h> namespace WebCore { @@ -39,8 +39,23 @@ PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf) HashSet<Page*>::const_iterator end = pages.end(); for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) { Page* otherPage = *it; - if ((deferSelf || otherPage != page) && !otherPage->defersLoading()) - m_deferredFrames.append(otherPage->mainFrame()); + if ((deferSelf || otherPage != page)) { + if (!otherPage->defersLoading()) { + m_deferredFrames.append(otherPage->mainFrame()); + + // This code is not logically part of load deferring, but we do not want JS code executed beneath modal + // windows or sheets, which is exactly when PageGroupLoadDeferrer is used. + // NOTE: if PageGroupLoadDeferrer is ever used for tasks other than showing a modal window or sheet, + // the constructor will need to take a ActiveDOMObject::ReasonForSuspension. + for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + frame->document()->suspendScriptedAnimationControllerCallbacks(); + frame->document()->suspendActiveDOMObjects(ActiveDOMObject::WillShowDialog); + frame->document()->scriptRunner()->suspend(); + if (DocumentParser* parser = frame->document()->parser()) + parser->suspendScheduledTasks(); + } + } + } } size_t count = m_deferredFrames.size(); @@ -52,8 +67,17 @@ PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf) PageGroupLoadDeferrer::~PageGroupLoadDeferrer() { for (size_t i = 0; i < m_deferredFrames.size(); ++i) { - if (Page* page = m_deferredFrames[i]->page()) + if (Page* page = m_deferredFrames[i]->page()) { page->setDefersLoading(false); + + for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + frame->document()->resumeActiveDOMObjects(); + frame->document()->resumeScriptedAnimationControllerCallbacks(); + frame->document()->scriptRunner()->resume(); + if (DocumentParser* parser = frame->document()->parser()) + parser->resumeScheduledTasks(); + } + } } } diff --git a/Source/WebCore/page/PrintContext.cpp b/Source/WebCore/page/PrintContext.cpp index da29f0e..6c8b312 100644 --- a/Source/WebCore/page/PrintContext.cpp +++ b/Source/WebCore/page/PrintContext.cpp @@ -282,16 +282,16 @@ String PrintContext::pageProperty(Frame* frame, const char* propertyName, int pa if (!strcmp(propertyName, "margin-left")) { if (style->marginLeft().isAuto()) return String("auto"); - return String::number(style->marginLeft().rawValue()); + return String::number(style->marginLeft().value()); } if (!strcmp(propertyName, "line-height")) - return String::number(style->lineHeight().rawValue()); + return String::number(style->lineHeight().value()); if (!strcmp(propertyName, "font-size")) return String::number(style->fontDescription().computedPixelSize()); if (!strcmp(propertyName, "font-family")) return style->fontDescription().family().family().string(); if (!strcmp(propertyName, "size")) - return makeString(String::number(style->pageSize().width().rawValue()), ' ', String::number(style->pageSize().height().rawValue())); + return makeString(String::number(style->pageSize().width().value()), ' ', String::number(style->pageSize().height().value())); return makeString("pageProperty() unimplemented for: ", propertyName); } diff --git a/Source/WebCore/page/SecurityOrigin.cpp b/Source/WebCore/page/SecurityOrigin.cpp index 977e860..ddd42ea 100644 --- a/Source/WebCore/page/SecurityOrigin.cpp +++ b/Source/WebCore/page/SecurityOrigin.cpp @@ -79,8 +79,17 @@ SecurityOrigin::SecurityOrigin(const KURL& url, SandboxFlags sandboxFlags) if (m_protocol == "about" || m_protocol == "javascript") m_protocol = ""; +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) + bool isBlobOrFileSystemProtocol = false; +#if ENABLE(BLOB) + if (m_protocol == BlobURL::blobProtocol()) + isBlobOrFileSystemProtocol = true; +#endif #if ENABLE(FILE_SYSTEM) - if (m_protocol == "filesystem") { + if (m_protocol == "filesystem") + isBlobOrFileSystemProtocol = true; +#endif + if (isBlobOrFileSystemProtocol) { KURL originURL(ParsedURLString, url.path()); if (originURL.isValid()) { m_protocol = originURL.protocol().lower(); @@ -102,7 +111,13 @@ SecurityOrigin::SecurityOrigin(const KURL& url, SandboxFlags sandboxFlags) m_canLoadLocalResources = isLocal(); if (m_canLoadLocalResources) { // Directories should never be readable. - if (!url.hasPath() || url.path().endsWith("/")) + // Note that we do not do this check for blob or filesystem url because its origin is file:/// when it is created from local file urls. +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) + bool doDirectoryCheck = !isBlobOrFileSystemProtocol; +#else + bool doDirectoryCheck = true; +#endif + if (doDirectoryCheck && (!url.hasPath() || url.path().endsWith("/"))) m_isUnique = true; // Store the path in case we are doing per-file origin checking. m_filePath = url.path(); @@ -137,10 +152,6 @@ PassRefPtr<SecurityOrigin> SecurityOrigin::create(const KURL& url, SandboxFlags { if (!url.isValid()) return adoptRef(new SecurityOrigin(KURL(), sandboxFlags)); -#if ENABLE(BLOB) - if (url.protocolIs(BlobURL::blobProtocol())) - return adoptRef(new SecurityOrigin(BlobURL::getOrigin(url), sandboxFlags)); -#endif return adoptRef(new SecurityOrigin(url, sandboxFlags)); } @@ -253,12 +264,7 @@ bool SecurityOrigin::canRequest(const KURL& url) const RefPtr<SecurityOrigin> targetOrigin = SecurityOrigin::create(url); - bool doUniqueOriginCheck = true; -#if ENABLE(BLOB) - // For blob scheme, we want to ignore this check. - doUniqueOriginCheck = !url.protocolIs(BlobURL::blobProtocol()); -#endif - if (doUniqueOriginCheck && targetOrigin->isUnique()) + if (targetOrigin->isUnique()) return false; // We call isSameSchemeHostPort here instead of canAccess because we want diff --git a/Source/WebCore/page/SecurityOrigin.h b/Source/WebCore/page/SecurityOrigin.h index f27c593..262dd8d 100644 --- a/Source/WebCore/page/SecurityOrigin.h +++ b/Source/WebCore/page/SecurityOrigin.h @@ -31,14 +31,14 @@ #include "FrameLoaderTypes.h" #include "PlatformString.h" -#include <wtf/ThreadSafeShared.h> +#include <wtf/ThreadSafeRefCounted.h> namespace WebCore { class Document; class KURL; -class SecurityOrigin : public ThreadSafeShared<SecurityOrigin> { +class SecurityOrigin : public ThreadSafeRefCounted<SecurityOrigin> { public: static PassRefPtr<SecurityOrigin> createFromDatabaseIdentifier(const String&); static PassRefPtr<SecurityOrigin> createFromString(const String&); diff --git a/Source/WebCore/page/SecurityOriginHash.h b/Source/WebCore/page/SecurityOriginHash.h index c2ebdd1..db3845c 100644 --- a/Source/WebCore/page/SecurityOriginHash.h +++ b/Source/WebCore/page/SecurityOriginHash.h @@ -43,7 +43,7 @@ struct SecurityOriginHash { origin->host().impl() ? origin->host().impl()->hash() : 0, origin->port() }; - return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes); + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); } static unsigned hash(const RefPtr<SecurityOrigin>& origin) { diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp index f0b489a..5cf20d6 100644 --- a/Source/WebCore/page/Settings.cpp +++ b/Source/WebCore/page/Settings.cpp @@ -45,12 +45,6 @@ using namespace std; namespace WebCore { -static void setNeedsRecalcStyleInAllFrames(Page* page) -{ - for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) - frame->document()->styleSelectorChanged(DeferRecalcStyle); -} - static void setLoadsImagesAutomaticallyInAllFrames(Page* page) { for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) @@ -94,6 +88,7 @@ Settings::Settings(Page* page) , m_minimumLogicalFontSize(0) , m_defaultFontSize(0) , m_defaultFixedFontSize(0) + , m_validationMessageTimerMagnification(50) , m_maximumDecodedImageSize(numeric_limits<size_t>::max()) #if ENABLE(DOM_STORAGE) , m_sessionStorageQuota(StorageMap::noQuota) @@ -146,6 +141,7 @@ Settings::Settings(Page* page) , m_enforceCSSMIMETypeInNoQuirksMode(true) , m_usesEncodingDetector(false) , m_allowScriptsToCloseWindows(false) + , m_canvasUsesAcceleratedDrawing(false) , m_acceleratedDrawingEnabled(false) // FIXME: This should really be disabled by default as it makes platforms that don't support the feature download files // they can't use by. Leaving enabled for now to not change existing behavior. @@ -177,6 +173,8 @@ Settings::Settings(Page* page) , m_usePreHTML5ParserQuirks(false) , m_hyperlinkAuditingEnabled(false) , m_crossOriginCheckInGetMatchedCSSRulesDisabled(false) + , m_useQuickLookResourceCachingQuirks(false) + , m_forceCompositingMode(false) #ifdef ANDROID_LAYOUT , m_useWideViewport(false) #endif @@ -208,7 +206,7 @@ void Settings::setStandardFontFamily(const AtomicString& standardFontFamily) return; m_standardFontFamily = standardFontFamily; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setFixedFontFamily(const AtomicString& fixedFontFamily) @@ -217,7 +215,7 @@ void Settings::setFixedFontFamily(const AtomicString& fixedFontFamily) return; m_fixedFontFamily = fixedFontFamily; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setSerifFontFamily(const AtomicString& serifFontFamily) @@ -226,7 +224,7 @@ void Settings::setSerifFontFamily(const AtomicString& serifFontFamily) return; m_serifFontFamily = serifFontFamily; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setSansSerifFontFamily(const AtomicString& sansSerifFontFamily) @@ -235,7 +233,7 @@ void Settings::setSansSerifFontFamily(const AtomicString& sansSerifFontFamily) return; m_sansSerifFontFamily = sansSerifFontFamily; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setCursiveFontFamily(const AtomicString& cursiveFontFamily) @@ -244,7 +242,7 @@ void Settings::setCursiveFontFamily(const AtomicString& cursiveFontFamily) return; m_cursiveFontFamily = cursiveFontFamily; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setFantasyFontFamily(const AtomicString& fantasyFontFamily) @@ -253,7 +251,7 @@ void Settings::setFantasyFontFamily(const AtomicString& fantasyFontFamily) return; m_fantasyFontFamily = fantasyFontFamily; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setMinimumFontSize(int minimumFontSize) @@ -262,7 +260,7 @@ void Settings::setMinimumFontSize(int minimumFontSize) return; m_minimumFontSize = minimumFontSize; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setMinimumLogicalFontSize(int minimumLogicalFontSize) @@ -271,7 +269,7 @@ void Settings::setMinimumLogicalFontSize(int minimumLogicalFontSize) return; m_minimumLogicalFontSize = minimumLogicalFontSize; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setDefaultFontSize(int defaultFontSize) @@ -280,7 +278,7 @@ void Settings::setDefaultFontSize(int defaultFontSize) return; m_defaultFontSize = defaultFontSize; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setDefaultFixedFontSize(int defaultFontSize) @@ -289,7 +287,7 @@ void Settings::setDefaultFixedFontSize(int defaultFontSize) return; m_defaultFixedFontSize = defaultFontSize; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } #ifdef ANDROID_BLOCK_NETWORK_IMAGE @@ -414,7 +412,7 @@ void Settings::setTextAreasAreResizable(bool textAreasAreResizable) return; m_textAreasAreResizable = textAreasAreResizable; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setEditableLinkBehavior(EditableLinkBehavior editableLinkBehavior) @@ -708,7 +706,7 @@ void Settings::setAuthorAndUserStylesEnabled(bool authorAndUserStylesEnabled) return; m_authorAndUserStylesEnabled = authorAndUserStylesEnabled; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setFontRenderingMode(FontRenderingMode mode) @@ -716,7 +714,7 @@ void Settings::setFontRenderingMode(FontRenderingMode mode) if (fontRenderingMode() == mode) return; m_fontRenderingMode = mode; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } FontRenderingMode Settings::fontRenderingMode() const @@ -818,7 +816,12 @@ void Settings::setAcceleratedCompositingEnabled(bool enabled) return; m_acceleratedCompositingEnabled = enabled; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); +} + +void Settings::setCanvasUsesAcceleratedDrawing(bool enabled) +{ + m_canvasUsesAcceleratedDrawing = enabled; } void Settings::setAcceleratedDrawingEnabled(bool enabled) @@ -857,7 +860,7 @@ void Settings::setShowDebugBorders(bool enabled) return; m_showDebugBorders = enabled; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setShowRepaintCounter(bool enabled) @@ -866,7 +869,7 @@ void Settings::setShowRepaintCounter(bool enabled) return; m_showRepaintCounter = enabled; - setNeedsRecalcStyleInAllFrames(m_page); + m_page->setNeedsRecalcStyleInAllFrames(); } void Settings::setExperimentalNotificationsEnabled(bool enabled) diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h index 0e93249..35446c5 100644 --- a/Source/WebCore/page/Settings.h +++ b/Source/WebCore/page/Settings.h @@ -351,6 +351,9 @@ namespace WebCore { void setXSSAuditorEnabled(bool); bool xssAuditorEnabled() const { return m_xssAuditorEnabled; } + void setCanvasUsesAcceleratedDrawing(bool); + bool canvasUsesAcceleratedDrawing() const { return m_canvasUsesAcceleratedDrawing; } + void setAcceleratedDrawingEnabled(bool); bool acceleratedDrawingEnabled() const { return m_acceleratedDrawingEnabled; } @@ -427,6 +430,14 @@ namespace WebCore { // and http://webkit.org/b/40908 void setInteractiveFormValidationEnabled(bool flag) { m_interactiveFormValidation = flag; } bool interactiveFormValidationEnabled() const { return m_interactiveFormValidation; } + + // Sets the maginication value for validation message timer. + // If the maginication value is N, a validation message disappears + // automatically after <message length> * N / 1000 seconds. If N is + // equal to or less than 0, a validation message doesn't disappears + // automaticaly. The default value is 50. + void setValidationMessageTimerMagnification(int newValue) { m_validationMessageTimerMagnification = newValue; } + int validationMessageTimerMaginification() const { return m_validationMessageTimerMagnification; } void setUsePreHTML5ParserQuirks(bool flag) { m_usePreHTML5ParserQuirks = flag; } bool usePreHTML5ParserQuirks() const { return m_usePreHTML5ParserQuirks; } @@ -436,6 +447,12 @@ namespace WebCore { void setCrossOriginCheckInGetMatchedCSSRulesDisabled(bool flag) { m_crossOriginCheckInGetMatchedCSSRulesDisabled = flag; } bool crossOriginCheckInGetMatchedCSSRulesDisabled() const { return m_crossOriginCheckInGetMatchedCSSRulesDisabled; } + + void setUseQuickLookResourceCachingQuirks(bool flag) { m_useQuickLookResourceCachingQuirks = flag; } + bool useQuickLookResourceCachingQuirks() const { return m_useQuickLookResourceCachingQuirks; } + + void setForceCompositingMode(bool flag) { m_forceCompositingMode = flag; } + bool forceCompositingMode() { return m_forceCompositingMode; } #if ENABLE(WEB_AUTOFILL) void setAutoFillEnabled(bool flag) { m_autoFillEnabled = flag; } @@ -461,6 +478,7 @@ namespace WebCore { int m_minimumLogicalFontSize; int m_defaultFontSize; int m_defaultFixedFontSize; + int m_validationMessageTimerMagnification; size_t m_maximumDecodedImageSize; #if ENABLE(DOM_STORAGE) unsigned m_sessionStorageQuota; @@ -527,6 +545,7 @@ namespace WebCore { bool m_enforceCSSMIMETypeInNoQuirksMode : 1; bool m_usesEncodingDetector : 1; bool m_allowScriptsToCloseWindows : 1; + bool m_canvasUsesAcceleratedDrawing : 1; bool m_acceleratedDrawingEnabled : 1; bool m_downloadableBinaryFontsEnabled : 1; bool m_xssAuditorEnabled : 1; @@ -556,6 +575,8 @@ namespace WebCore { bool m_usePreHTML5ParserQuirks: 1; bool m_hyperlinkAuditingEnabled : 1; bool m_crossOriginCheckInGetMatchedCSSRulesDisabled : 1; + bool m_useQuickLookResourceCachingQuirks : 1; + bool m_forceCompositingMode : 1; #ifdef ANDROID_META_SUPPORT // default is yes bool m_viewport_user_scalable : 1; diff --git a/Source/WebCore/page/WebKitAnimation.cpp b/Source/WebCore/page/WebKitAnimation.cpp new file mode 100644 index 0000000..ff7102f --- /dev/null +++ b/Source/WebCore/page/WebKitAnimation.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2011 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 "WebKitAnimation.h" + +#include "Animation.h" +#include "AnimationBase.h" +#include "RenderStyle.h" + +using namespace std; + +namespace WebCore { + +WebKitAnimation::WebKitAnimation(PassRefPtr<KeyframeAnimation> keyframeAnimation) + : m_keyframeAnimation(keyframeAnimation) +{ +} + +String WebKitAnimation::name() const +{ + return m_keyframeAnimation->animation()->name(); +} + +double WebKitAnimation::duration() const +{ + return m_keyframeAnimation->duration(); +} + +double WebKitAnimation::elapsedTime() const +{ + return m_keyframeAnimation->getElapsedTime(); +} + +void WebKitAnimation::setElapsedTime(double time) +{ + m_keyframeAnimation->setElapsedTime(time); +} + +double WebKitAnimation::delay() const +{ + return m_keyframeAnimation->animation()->delay(); +} + +int WebKitAnimation::iterationCount() const +{ + return m_keyframeAnimation->animation()->iterationCount(); +} + +bool WebKitAnimation::paused() const +{ + return m_keyframeAnimation->paused(); +} + +bool WebKitAnimation::ended() const +{ + int iterations = iterationCount(); + if (iterations == Animation::IterationCountInfinite) + return false; + return m_keyframeAnimation->getElapsedTime() > (m_keyframeAnimation->duration() * iterations); +} + +WebKitAnimation::Direction WebKitAnimation::direction() const +{ + if (m_keyframeAnimation->animation()->direction() == Animation::AnimationDirectionNormal) + return DIRECTION_NORMAL; + return DIRECTION_ALTERNATE; +} + +WebKitAnimation::FillMode WebKitAnimation::fillMode() const +{ + switch (m_keyframeAnimation->animation()->fillMode()) { + case AnimationFillModeNone: + return FILL_NONE; + break; + case AnimationFillModeForwards: + return FILL_FORWARDS; + break; + case AnimationFillModeBackwards: + return FILL_BACKWARDS; + break; + default: + return FILL_BOTH; + break; + } +} + +void WebKitAnimation::pause() +{ + m_keyframeAnimation->pause(); +} + +void WebKitAnimation::play() +{ + m_keyframeAnimation->play(); +} + +} diff --git a/Source/WebCore/page/WebKitAnimation.h b/Source/WebCore/page/WebKitAnimation.h new file mode 100644 index 0000000..6bea1e5 --- /dev/null +++ b/Source/WebCore/page/WebKitAnimation.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebKitAnimation_h +#define WebKitAnimation_h + +#include "Animation.h" +#include "AnimationBase.h" +#include "KeyframeAnimation.h" +#include "RenderStyle.h" + +namespace WebCore { + +class WebKitAnimation : public RefCounted<WebKitAnimation> { +public: + + static PassRefPtr<WebKitAnimation> create(PassRefPtr<KeyframeAnimation> keyframeAnimation) + { + return adoptRef(new WebKitAnimation(keyframeAnimation)); + } + + virtual ~WebKitAnimation() { } + + // DOM API + + String name() const; + + double duration() const; + + double elapsedTime() const; + void setElapsedTime(double); + + double delay() const; + int iterationCount() const; + + bool paused() const; + bool ended() const; + + // direction + enum Direction { DIRECTION_NORMAL, DIRECTION_ALTERNATE }; + Direction direction() const; + + // fill mode + enum FillMode { FILL_NONE, FILL_BACKWARDS, FILL_FORWARDS, FILL_BOTH }; + FillMode fillMode() const; + + void play(); + void pause(); + +protected: + WebKitAnimation(PassRefPtr<KeyframeAnimation>); + +private: + RefPtr<KeyframeAnimation> m_keyframeAnimation; +}; + +} // namespace + +#endif diff --git a/Source/WebCore/page/WebKitAnimation.idl b/Source/WebCore/page/WebKitAnimation.idl new file mode 100644 index 0000000..4fba2e8 --- /dev/null +++ b/Source/WebCore/page/WebKitAnimation.idl @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module html { + + interface WebKitAnimation { + + readonly attribute DOMString name; + + readonly attribute double duration; + attribute double elapsedTime; + + readonly attribute double delay; + readonly attribute [Custom] int iterationCount; + + readonly attribute boolean paused; + readonly attribute boolean ended; + + const unsigned short DIRECTION_NORMAL = 0; + const unsigned short DIRECTION_ALTERNATE = 1; + readonly attribute unsigned short direction; + + const unsigned short FILL_NONE = 0; + const unsigned short FILL_BACKWARDS = 1; + const unsigned short FILL_FORWARDS = 2; + const unsigned short FILL_BOTH = 3; + readonly attribute unsigned short fillMode; + + void play(); + void pause(); + }; + +} diff --git a/Source/WebCore/page/WebKitAnimationList.cpp b/Source/WebCore/page/WebKitAnimationList.cpp new file mode 100644 index 0000000..31e46d7 --- /dev/null +++ b/Source/WebCore/page/WebKitAnimationList.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 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 "WebKitAnimationList.h" + +#include "Animation.h" +#include "AnimationBase.h" +#include "RenderStyle.h" +#include "WebKitAnimation.h" + +namespace WebCore { + +WebKitAnimationList::WebKitAnimationList() +{ +} + +WebKitAnimationList::~WebKitAnimationList() +{ +} + +unsigned WebKitAnimationList::length() const +{ + return m_animations.size(); +} + +WebKitAnimation* WebKitAnimationList::item(unsigned index) +{ + if (index < m_animations.size()) + return m_animations[index].get(); + return 0; +} + +void WebKitAnimationList::deleteAnimation(unsigned index) +{ + if (index >= m_animations.size()) + return; + + m_animations.remove(index); +} + +void WebKitAnimationList::append(RefPtr<WebKitAnimation> animation) +{ + m_animations.append(animation); +} + +unsigned WebKitAnimationList::insertAnimation(RefPtr<WebKitAnimation> animation, unsigned index) +{ + if (!animation) + return 0; + + if (index > m_animations.size()) + return 0; + + m_animations.insert(index, animation); + return index; +} + +} // namespace WebCore + diff --git a/Source/WebCore/page/WebKitAnimationList.h b/Source/WebCore/page/WebKitAnimationList.h new file mode 100644 index 0000000..b82e38a --- /dev/null +++ b/Source/WebCore/page/WebKitAnimationList.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebKitAnimationList_h +#define WebKitAnimationList_h + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class WebKitAnimation; + +class WebKitAnimationList : public RefCounted<WebKitAnimationList> { +public: + static PassRefPtr<WebKitAnimationList> create() + { + return adoptRef(new WebKitAnimationList()); + } + ~WebKitAnimationList(); + + unsigned length() const; + WebKitAnimation* item(unsigned index); + + unsigned insertAnimation(RefPtr<WebKitAnimation>, unsigned index); + void deleteAnimation(unsigned index); + void append(RefPtr<WebKitAnimation>); + +private: + WebKitAnimationList(); + + Vector<RefPtr<WebKitAnimation> > m_animations; +}; + +} // namespace WebCore + +#endif // WebKitAnimationList_h diff --git a/Source/WebCore/page/WebKitAnimationList.idl b/Source/WebCore/page/WebKitAnimationList.idl new file mode 100644 index 0000000..4c376e6 --- /dev/null +++ b/Source/WebCore/page/WebKitAnimationList.idl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 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. + */ + +module html { + + interface [ + CustomMarkFunction, + HasIndexGetter + ] WebKitAnimationList { + readonly attribute unsigned long length; + WebKitAnimation item(in unsigned long index); + }; + +} diff --git a/Source/WebCore/page/animation/AnimationBase.cpp b/Source/WebCore/page/animation/AnimationBase.cpp index 9a906e2..0fe98be 100644 --- a/Source/WebCore/page/animation/AnimationBase.cpp +++ b/Source/WebCore/page/animation/AnimationBase.cpp @@ -113,7 +113,7 @@ static inline Color blendFunc(const AnimationBase* anim, const Color& from, cons static inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress) { - return to.blend(from, progress); + return to.blend(from, narrowPrecisionToFloat(progress)); } static inline LengthSize blendFunc(const AnimationBase* anim, const LengthSize& from, const LengthSize& to, double progress) @@ -798,7 +798,6 @@ AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer , m_isAccelerated(false) , m_transformFunctionListValid(false) , m_nextIterationDuration(-1) - , m_next(0) { // Compute the total duration m_totalDuration = -1; @@ -806,12 +805,6 @@ AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer m_totalDuration = m_animation->duration() * m_animation->iterationCount(); } -AnimationBase::~AnimationBase() -{ - m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); - m_compAnim->animationController()->removeFromStartTimeResponseWaitList(this); -} - bool AnimationBase::propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b) { ensurePropertyMap(); @@ -936,7 +929,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) // If we get AnimationStateInputRestartAnimation then we force a new animation, regardless of state. if (input == AnimationStateInputMakeNew) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); m_animState = AnimationStateNew; m_startTime = 0; m_pauseTime = -1; @@ -948,7 +941,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (input == AnimationStateInputRestartAnimation) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); m_animState = AnimationStateNew; m_startTime = 0; m_pauseTime = -1; @@ -963,7 +956,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (input == AnimationStateInputEndAnimation) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); m_animState = AnimationStateDone; endAnimation(); return; @@ -1003,7 +996,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) ASSERT(param >= 0); // Start timer has fired, tell the animation to start and wait for it to respond with start time m_animState = AnimationStateStartWaitStyleAvailable; - m_compAnim->animationController()->addToStyleAvailableWaitList(this); + m_compAnim->animationController()->addToAnimationsWaitingForStyle(this); // Trigger a render so we can start the animation if (m_object) @@ -1038,7 +1031,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) timeOffset = -m_animation->delay(); bool started = startAnimation(timeOffset); - m_compAnim->animationController()->addToStartTimeResponseWaitList(this, started); + m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, started); m_isAccelerated = started; } } else { @@ -1072,7 +1065,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) } else { // 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; + m_pauseTime = beginAnimationUpdateTime(); pauseAnimation(beginAnimationUpdateTime() - m_startTime); m_animState = AnimationStatePausedWaitResponse; } @@ -1167,7 +1160,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) m_isAccelerated = true; } else { bool started = startAnimation(beginAnimationUpdateTime() - m_startTime); - m_compAnim->animationController()->addToStartTimeResponseWaitList(this, started); + m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, started); m_isAccelerated = started; } } @@ -1397,5 +1390,21 @@ double AnimationBase::getElapsedTime() const return beginAnimationUpdateTime() - m_startTime; } - + +void AnimationBase::setElapsedTime(double time) +{ + // FIXME: implement this method + UNUSED_PARAM(time); +} + +void AnimationBase::play() +{ + // FIXME: implement this method +} + +void AnimationBase::pause() +{ + // FIXME: implement this method +} + } // namespace WebCore diff --git a/Source/WebCore/page/animation/AnimationBase.h b/Source/WebCore/page/animation/AnimationBase.h index 877d649..1ab14e3 100644 --- a/Source/WebCore/page/animation/AnimationBase.h +++ b/Source/WebCore/page/animation/AnimationBase.h @@ -51,7 +51,7 @@ class AnimationBase : public RefCounted<AnimationBase> { public: AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim); - virtual ~AnimationBase(); + virtual ~AnimationBase() { } RenderObject* renderer() const { return m_object; } void clearRenderer() { m_object = 0; } @@ -163,13 +163,16 @@ public: // Freeze the animation; used by DumpRenderTree. void freezeAtTime(double t); + + // Play and pause API + void play(); + void pause(); double beginAnimationUpdateTime() const; double getElapsedTime() const; - - AnimationBase* next() const { return m_next; } - void setNext(AnimationBase* animation) { m_next = animation; } + // Setting the elapsed time will adjust the start time and possibly pause time. + void setElapsedTime(double); void styleAvailable() { @@ -182,7 +185,9 @@ public: #endif static HashSet<int> animatableShorthandsAffectingProperty(int property); - + + const Animation* animation() const { return m_animation.get(); } + protected: virtual void overrideAnimations() { } virtual void resumeOverriddenAnimations() { } @@ -230,8 +235,6 @@ protected: bool m_transformFunctionListValid; double m_totalDuration, m_nextIterationDuration; - AnimationBase* m_next; - private: static void ensurePropertyMap(); }; diff --git a/Source/WebCore/page/animation/AnimationController.cpp b/Source/WebCore/page/animation/AnimationController.cpp index dcdea03..5b166d4 100644 --- a/Source/WebCore/page/animation/AnimationController.cpp +++ b/Source/WebCore/page/animation/AnimationController.cpp @@ -37,12 +37,14 @@ #include "Frame.h" #include "RenderView.h" #include "WebKitAnimationEvent.h" +#include "WebKitAnimationList.h" #include "WebKitTransitionEvent.h" #include <wtf/CurrentTime.h> #include <wtf/UnusedParam.h> namespace WebCore { +// FIXME: Why isn't this set to 60fps or something? static const double cAnimationTimerDelay = 0.025; static const double cBeginAnimationUpdateTimeNotSet = -1; @@ -51,11 +53,9 @@ AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) , m_updateStyleIfNeededDispatcher(this, &AnimationControllerPrivate::updateStyleIfNeededDispatcherFired) , m_frame(frame) , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet) - , m_styleAvailableWaiters(0) - , m_lastStyleAvailableWaiter(0) - , m_startTimeResponseWaiters(0) - , m_lastStartTimeResponseWaiter(0) - , m_waitingForStartTimeResponse(false) + , m_animationsWaitingForStyle() + , m_animationsWaitingForStartTimeResponse() + , m_waitingForAsyncStartNotification(false) { } @@ -323,13 +323,13 @@ double AnimationControllerPrivate::beginAnimationUpdateTime() void AnimationControllerPrivate::endAnimationUpdate() { styleAvailable(); - if (!m_waitingForStartTimeResponse) + if (!m_waitingForAsyncStartNotification) startTimeResponse(beginAnimationUpdateTime()); } void AnimationControllerPrivate::receivedStartTimeResponse(double time) { - m_waitingForStartTimeResponse = false; + m_waitingForAsyncStartNotification = false; startTimeResponse(time); } @@ -365,52 +365,31 @@ unsigned AnimationControllerPrivate::numberOfActiveAnimations() const return count; } -void AnimationControllerPrivate::addToStyleAvailableWaitList(AnimationBase* animation) +void AnimationControllerPrivate::addToAnimationsWaitingForStyle(AnimationBase* animation) { - ASSERT(!animation->next()); - - if (m_styleAvailableWaiters) - m_lastStyleAvailableWaiter->setNext(animation); - else - m_styleAvailableWaiters = animation; - - m_lastStyleAvailableWaiter = animation; - animation->setNext(0); -} - -void AnimationControllerPrivate::removeFromStyleAvailableWaitList(AnimationBase* animationToRemove) -{ - AnimationBase* prevAnimation = 0; - for (AnimationBase* animation = m_styleAvailableWaiters; animation; animation = animation->next()) { - if (animation == animationToRemove) { - if (prevAnimation) - prevAnimation->setNext(animation->next()); - else - m_styleAvailableWaiters = animation->next(); - - if (m_lastStyleAvailableWaiter == animation) - m_lastStyleAvailableWaiter = prevAnimation; - - animationToRemove->setNext(0); - } - } + // Make sure this animation is not in the start time waiters + m_animationsWaitingForStartTimeResponse.remove(animation); + + m_animationsWaitingForStyle.add(animation); +} + +void AnimationControllerPrivate::removeFromAnimationsWaitingForStyle(AnimationBase* animationToRemove) +{ + m_animationsWaitingForStyle.remove(animationToRemove); } void AnimationControllerPrivate::styleAvailable() { // Go through list of waiters and send them on their way - for (AnimationBase* animation = m_styleAvailableWaiters; animation; ) { - AnimationBase* nextAnimation = animation->next(); - animation->setNext(0); - animation->styleAvailable(); - animation = nextAnimation; - } - - m_styleAvailableWaiters = 0; - m_lastStyleAvailableWaiter = 0; + WaitingAnimationsSet::const_iterator it = m_animationsWaitingForStyle.begin(); + WaitingAnimationsSet::const_iterator end = m_animationsWaitingForStyle.end(); + for (; it != end; ++it) + (*it)->styleAvailable(); + + m_animationsWaitingForStyle.clear(); } -void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse) +void AnimationControllerPrivate::addToAnimationsWaitingForStartTimeResponse(AnimationBase* animation, bool willGetResponse) { // If willGetResponse is true, it means this animation is actually waiting for a response // (which will come in as a call to notifyAnimationStarted()). @@ -429,54 +408,48 @@ void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* a // This will synchronize all software and accelerated animations started in the same // updateStyleIfNeeded cycle. // - ASSERT(!animation->next()); if (willGetResponse) - m_waitingForStartTimeResponse = true; + m_waitingForAsyncStartNotification = true; - if (m_startTimeResponseWaiters) - m_lastStartTimeResponseWaiter->setNext(animation); - else - m_startTimeResponseWaiters = animation; - - m_lastStartTimeResponseWaiter = animation; - animation->setNext(0); -} - -void AnimationControllerPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animationToRemove) -{ - AnimationBase* prevAnimation = 0; - for (AnimationBase* animation = m_startTimeResponseWaiters; animation; animation = animation->next()) { - if (animation == animationToRemove) { - if (prevAnimation) - prevAnimation->setNext(animation->next()); - else - m_startTimeResponseWaiters = animation->next(); - - if (m_lastStartTimeResponseWaiter == animation) - m_lastStartTimeResponseWaiter = prevAnimation; - - animationToRemove->setNext(0); - } - prevAnimation = animation; - } + m_animationsWaitingForStartTimeResponse.add(animation); +} + +void AnimationControllerPrivate::removeFromAnimationsWaitingForStartTimeResponse(AnimationBase* animationToRemove) +{ + m_animationsWaitingForStartTimeResponse.remove(animationToRemove); - if (!m_startTimeResponseWaiters) - m_waitingForStartTimeResponse = false; + if (m_animationsWaitingForStartTimeResponse.isEmpty()) + m_waitingForAsyncStartNotification = false; } void AnimationControllerPrivate::startTimeResponse(double time) { // Go through list of waiters and send them on their way - for (AnimationBase* animation = m_startTimeResponseWaiters; animation; ) { - AnimationBase* nextAnimation = animation->next(); - animation->setNext(0); - animation->onAnimationStartResponse(time); - animation = nextAnimation; - } + + WaitingAnimationsSet::const_iterator it = m_animationsWaitingForStartTimeResponse.begin(); + WaitingAnimationsSet::const_iterator end = m_animationsWaitingForStartTimeResponse.end(); + for (; it != end; ++it) + (*it)->onAnimationStartResponse(time); - m_startTimeResponseWaiters = 0; - m_lastStartTimeResponseWaiter = 0; + m_animationsWaitingForStartTimeResponse.clear(); + m_waitingForAsyncStartNotification = false; +} + +void AnimationControllerPrivate::animationWillBeRemoved(AnimationBase* animation) +{ + removeFromAnimationsWaitingForStyle(animation); + removeFromAnimationsWaitingForStartTimeResponse(animation); +} + +PassRefPtr<WebKitAnimationList> AnimationControllerPrivate::animationsForRenderer(RenderObject* renderer) const +{ + RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); + + if (!animation) + return 0; + + return animation->animations(); } AnimationController::AnimationController(Frame* frame) @@ -612,4 +585,9 @@ bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID p #endif } +PassRefPtr<WebKitAnimationList> AnimationController::animationsForRenderer(RenderObject* renderer) const +{ + return m_data->animationsForRenderer(renderer); +} + } // namespace WebCore diff --git a/Source/WebCore/page/animation/AnimationController.h b/Source/WebCore/page/animation/AnimationController.h index 5279467..a355f87 100644 --- a/Source/WebCore/page/animation/AnimationController.h +++ b/Source/WebCore/page/animation/AnimationController.h @@ -42,6 +42,7 @@ class Frame; class Node; class RenderObject; class RenderStyle; +class WebKitAnimationList; class AnimationController { public: @@ -73,6 +74,8 @@ public: static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID); + PassRefPtr<WebKitAnimationList> animationsForRenderer(RenderObject*) const; + private: AnimationControllerPrivate* m_data; }; diff --git a/Source/WebCore/page/animation/AnimationControllerPrivate.h b/Source/WebCore/page/animation/AnimationControllerPrivate.h index 186dd7d..1146eba 100644 --- a/Source/WebCore/page/animation/AnimationControllerPrivate.h +++ b/Source/WebCore/page/animation/AnimationControllerPrivate.h @@ -33,6 +33,7 @@ #include "PlatformString.h" #include "Timer.h" #include <wtf/HashMap.h> +#include <wtf/HashSet.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> @@ -48,6 +49,7 @@ class Frame; class Node; class RenderObject; class RenderStyle; +class WebKitAnimationList; class AnimationControllerPrivate { WTF_MAKE_NONCOPYABLE(AnimationControllerPrivate); WTF_MAKE_FAST_ALLOCATED; @@ -87,11 +89,15 @@ public: void endAnimationUpdate(); void receivedStartTimeResponse(double); - void addToStyleAvailableWaitList(AnimationBase*); - void removeFromStyleAvailableWaitList(AnimationBase*); - - void addToStartTimeResponseWaitList(AnimationBase*, bool willGetResponse); - void removeFromStartTimeResponseWaitList(AnimationBase*); + void addToAnimationsWaitingForStyle(AnimationBase*); + void removeFromAnimationsWaitingForStyle(AnimationBase*); + + void addToAnimationsWaitingForStartTimeResponse(AnimationBase*, bool willGetResponse); + void removeFromAnimationsWaitingForStartTimeResponse(AnimationBase*); + + void animationWillBeRemoved(AnimationBase*); + + PassRefPtr<WebKitAnimationList> animationsForRenderer(RenderObject*) const; private: void animationTimerFired(Timer<AnimationControllerPrivate>*); @@ -119,12 +125,11 @@ private: Vector<RefPtr<Node> > m_nodeChangesToDispatch; double m_beginAnimationUpdateTime; - AnimationBase* m_styleAvailableWaiters; - AnimationBase* m_lastStyleAvailableWaiter; - - AnimationBase* m_startTimeResponseWaiters; - AnimationBase* m_lastStartTimeResponseWaiter; - bool m_waitingForStartTimeResponse; + + typedef HashSet<RefPtr<AnimationBase> > WaitingAnimationsSet; + WaitingAnimationsSet m_animationsWaitingForStyle; + WaitingAnimationsSet m_animationsWaitingForStartTimeResponse; + bool m_waitingForAsyncStartNotification; }; } // namespace WebCore diff --git a/Source/WebCore/page/animation/CompositeAnimation.cpp b/Source/WebCore/page/animation/CompositeAnimation.cpp index 602491e..27409d9 100644 --- a/Source/WebCore/page/animation/CompositeAnimation.cpp +++ b/Source/WebCore/page/animation/CompositeAnimation.cpp @@ -36,6 +36,8 @@ #include "KeyframeAnimation.h" #include "RenderObject.h" #include "RenderStyle.h" +#include "WebKitAnimation.h" +#include "WebKitAnimationList.h" namespace WebCore { @@ -54,6 +56,7 @@ void CompositeAnimation::clearRenderer() CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { ImplicitAnimation* transition = it->second.get(); + animationController()->animationWillBeRemoved(transition); transition->clearRenderer(); } } @@ -62,6 +65,7 @@ void CompositeAnimation::clearRenderer() AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* anim = it->second.get(); + animationController()->animationWillBeRemoved(anim); anim->clearRenderer(); } } @@ -173,8 +177,10 @@ void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle* end = m_transitions.end(); for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { ImplicitAnimation* anim = it->second.get(); - if (!anim->active()) + if (!anim->active()) { + animationController()->animationWillBeRemoved(anim); toBeRemoved.append(anim->animatingProperty()); + } } // Now remove the transitions from the list @@ -252,8 +258,11 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render kfend = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { KeyframeAnimation* keyframeAnim = it->second.get(); - if (keyframeAnim->index() < 0) + if (keyframeAnim->index() < 0) { animsToBeRemoved.append(keyframeAnim->name().impl()); + animationController()->animationWillBeRemoved(keyframeAnim); + keyframeAnim->clearRenderer(); + } } // Now remove the animations from the list. @@ -560,4 +569,20 @@ unsigned CompositeAnimation::numberOfActiveAnimations() const return count; } +PassRefPtr<WebKitAnimationList> CompositeAnimation::animations() const +{ + RefPtr<WebKitAnimationList> animations = WebKitAnimationList::create(); + if (!m_keyframeAnimations.isEmpty()) { + 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) { + RefPtr<WebKitAnimation> anim = WebKitAnimation::create(keyframeAnimation); + animations->append(anim); + } + } + } + return animations; +} + } // namespace WebCore diff --git a/Source/WebCore/page/animation/CompositeAnimation.h b/Source/WebCore/page/animation/CompositeAnimation.h index 249f4c3..1bfe585 100644 --- a/Source/WebCore/page/animation/CompositeAnimation.h +++ b/Source/WebCore/page/animation/CompositeAnimation.h @@ -41,6 +41,7 @@ class AnimationControllerPrivate; class AnimationController; class RenderObject; class RenderStyle; +class WebKitAnimationList; // A CompositeAnimation represents a collection of animations that are running // on a single RenderObject, such as a number of properties transitioning at once. @@ -80,6 +81,8 @@ public: bool pauseTransitionAtTime(int property, double t); unsigned numberOfActiveAnimations() const; + PassRefPtr<WebKitAnimationList> animations() const; + private: CompositeAnimation(AnimationControllerPrivate* animationController) : m_animationController(animationController) diff --git a/Source/WebCore/page/mac/WebCoreViewFactory.m b/Source/WebCore/page/mac/WebCoreViewFactory.m index 5398989..17a7a29 100644 --- a/Source/WebCore/page/mac/WebCoreViewFactory.m +++ b/Source/WebCore/page/mac/WebCoreViewFactory.m @@ -37,7 +37,7 @@ static WebCoreViewFactory *sharedFactory; - init { - [super init]; + self = [super init]; ASSERT(!sharedFactory); sharedFactory = [self retain]; |