diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/frame | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/frame')
131 files changed, 8656 insertions, 10536 deletions
diff --git a/chromium/third_party/WebKit/Source/core/frame/AdjustViewSizeOrNot.h b/chromium/third_party/WebKit/Source/core/frame/AdjustViewSizeOrNot.h deleted file mode 100644 index 0137ad9102c..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/AdjustViewSizeOrNot.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AdjustViewSizeOrNot_h -#define AdjustViewSizeOrNot_h - -namespace WebCore { - -enum AdjustViewSizeOrNot { - DoNotAdjustViewSize, - AdjustViewSize -}; - -} // namespace WebCore - -#endif // AdjustViewSizeOrNot_h diff --git a/chromium/third_party/WebKit/Source/core/frame/BarProp.cpp b/chromium/third_party/WebKit/Source/core/frame/BarProp.cpp index cc987187cd7..e4de0eaaca5 100644 --- a/chromium/third_party/WebKit/Source/core/frame/BarProp.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/BarProp.cpp @@ -30,42 +30,37 @@ #include "core/frame/BarProp.h" #include "core/page/Chrome.h" -#include "core/frame/Frame.h" -#include "core/page/Page.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -BarProp::BarProp(Frame* frame, Type type) +BarProp::BarProp(LocalFrame* frame, Type type) : DOMWindowProperty(frame) , m_type(type) { ScriptWrappable::init(this); } -BarProp::Type BarProp::type() const -{ - return m_type; -} - bool BarProp::visible() const { if (!m_frame) return false; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return false; switch (m_type) { case Locationbar: case Personalbar: case Toolbar: - return page->chrome().toolbarsVisible(); + return host->chrome().toolbarsVisible(); case Menubar: - return page->chrome().menubarVisible(); + return host->chrome().menubarVisible(); case Scrollbars: - return page->chrome().scrollbarsVisible(); + return host->chrome().scrollbarsVisible(); case Statusbar: - return page->chrome().statusbarVisible(); + return host->chrome().statusbarVisible(); } ASSERT_NOT_REACHED(); diff --git a/chromium/third_party/WebKit/Source/core/frame/BarProp.h b/chromium/third_party/WebKit/Source/core/frame/BarProp.h index 1d188e14a84..534a4c6373e 100644 --- a/chromium/third_party/WebKit/Source/core/frame/BarProp.h +++ b/chromium/third_party/WebKit/Source/core/frame/BarProp.h @@ -31,24 +31,29 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/frame/DOMWindowProperty.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { - class Frame; + class LocalFrame; - class BarProp : public ScriptWrappable, public RefCounted<BarProp>, public DOMWindowProperty { + class BarProp FINAL : public RefCountedWillBeGarbageCollectedFinalized<BarProp>, public ScriptWrappable, public DOMWindowProperty { public: enum Type { Locationbar, Menubar, Personalbar, Scrollbars, Statusbar, Toolbar }; - static PassRefPtr<BarProp> create(Frame* frame, Type type) { return adoptRef(new BarProp(frame, type)); } + static PassRefPtrWillBeRawPtr<BarProp> create(LocalFrame* frame, Type type) + { + return adoptRefWillBeNoop(new BarProp(frame, type)); + } - Type type() const; bool visible() const; + void trace(Visitor*) { } + private: - BarProp(Frame*, Type); + BarProp(LocalFrame*, Type); Type m_type; }; diff --git a/chromium/third_party/WebKit/Source/core/frame/BarProp.idl b/chromium/third_party/WebKit/Source/core/frame/BarProp.idl index cc9ce71cedf..a7be530c7ac 100644 --- a/chromium/third_party/WebKit/Source/core/frame/BarProp.idl +++ b/chromium/third_party/WebKit/Source/core/frame/BarProp.idl @@ -26,7 +26,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -interface BarProp { +[ + WillBeGarbageCollected, +] interface BarProp { readonly attribute boolean visible; }; diff --git a/chromium/third_party/WebKit/Source/core/frame/Console.cpp b/chromium/third_party/WebKit/Source/core/frame/Console.cpp index 12cff31d383..ef2759ec1af 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Console.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/Console.cpp @@ -31,23 +31,22 @@ #include "bindings/v8/ScriptCallStackFactory.h" #include "core/frame/ConsoleTypes.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/inspector/ConsoleAPITypes.h" #include "core/inspector/ScriptArguments.h" #include "core/inspector/ScriptCallStack.h" #include "core/page/Chrome.h" #include "core/page/ChromeClient.h" -#include "core/frame/Frame.h" -#include "core/page/Page.h" -#include "core/page/PageConsole.h" #include "core/timing/MemoryInfo.h" +#include "platform/TraceEvent.h" #include "wtf/text/CString.h" #include "wtf/text/WTFString.h" -#include "platform/TraceEvent.h" - namespace WebCore { -Console::Console(Frame* frame) +Console::Console(LocalFrame* frame) : DOMWindowProperty(frame) { ScriptWrappable::init(this); @@ -64,24 +63,24 @@ ExecutionContext* Console::context() return m_frame->document(); } -void Console::reportMessageToClient(MessageLevel level, const String& message, PassRefPtr<ScriptCallStack> callStack) +void Console::reportMessageToClient(MessageLevel level, const String& message, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) { - if (!m_frame || !m_frame->page() || !callStack.get()) + if (!m_frame || !m_frame->host() || !callStack.get()) return; String stackTrace; - if (m_frame->page()->chrome().client().shouldReportDetailedMessageForSource(callStack->at(0).sourceURL())) { - RefPtr<ScriptCallStack> fullStack = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture); - stackTrace = PageConsole::formatStackTraceString(message, fullStack); + if (m_frame->chromeClient().shouldReportDetailedMessageForSource(callStack->at(0).sourceURL())) { + RefPtrWillBeRawPtr<ScriptCallStack> fullStack = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture); + stackTrace = FrameConsole::formatStackTraceString(message, fullStack); } - m_frame->page()->chrome().client().addMessageToConsole(ConsoleAPIMessageSource, level, message, callStack->at(0).lineNumber(), callStack->at(0).sourceURL(), stackTrace); + m_frame->chromeClient().addMessageToConsole(m_frame, ConsoleAPIMessageSource, level, message, callStack->at(0).lineNumber(), callStack->at(0).sourceURL(), stackTrace); } -PassRefPtr<MemoryInfo> Console::memory() const +PassRefPtrWillBeRawPtr<MemoryInfo> Console::memory() const { // FIXME: Because we create a new object here each time, // console.memory !== console.memory, which seems wrong. - return MemoryInfo::create(m_frame); + return MemoryInfo::create(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/Console.h b/chromium/third_party/WebKit/Source/core/frame/Console.h index 0cdfffdc5e3..1406aa3e8a1 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Console.h +++ b/chromium/third_party/WebKit/Source/core/frame/Console.h @@ -29,41 +29,39 @@ #ifndef Console_h #define Console_h -#include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptWrappable.h" #include "core/frame/ConsoleBase.h" #include "core/frame/DOMWindowProperty.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class Frame; +class LocalFrame; class MemoryInfo; class Page; class ScriptArguments; -class Console : public RefCounted<Console>, public ConsoleBase, public ScriptWrappable, public DOMWindowProperty { +class Console FINAL : public ConsoleBase, public ScriptWrappable, public DOMWindowProperty { public: - using RefCounted<Console>::ref; - using RefCounted<Console>::deref; - - static PassRefPtr<Console> create(Frame* frame) { return adoptRef(new Console(frame)); } + static PassRefPtrWillBeRawPtr<Console> create(LocalFrame* frame) + { + return adoptRefWillBeNoop(new Console(frame)); + } virtual ~Console(); - PassRefPtr<MemoryInfo> memory() const; + PassRefPtrWillBeRawPtr<MemoryInfo> memory() const; + + virtual void trace(Visitor* visitor) OVERRIDE { ConsoleBase::trace(visitor); } protected: - virtual ExecutionContext* context(); - virtual void reportMessageToClient(MessageLevel, const String& message, PassRefPtr<ScriptCallStack>) OVERRIDE; + virtual ExecutionContext* context() OVERRIDE; + virtual void reportMessageToClient(MessageLevel, const String& message, PassRefPtrWillBeRawPtr<ScriptCallStack>) OVERRIDE; private: - explicit Console(Frame*); - inline Page* page() const; - - virtual void refConsole() { ref(); } - virtual void derefConsole() { deref(); } + explicit Console(LocalFrame*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.cpp b/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.cpp index 8f54d86c0d1..d33525eb883 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.cpp @@ -43,67 +43,67 @@ ConsoleBase::~ConsoleBase() { } -void ConsoleBase::debug(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::debug(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(LogMessageType, DebugMessageLevel, state, arguments); + internalAddMessage(LogMessageType, DebugMessageLevel, scriptState, arguments); } -void ConsoleBase::error(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::error(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(LogMessageType, ErrorMessageLevel, state, arguments); + internalAddMessage(LogMessageType, ErrorMessageLevel, scriptState, arguments); } -void ConsoleBase::info(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::info(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(LogMessageType, InfoMessageLevel, state, arguments); + internalAddMessage(LogMessageType, InfoMessageLevel, scriptState, arguments); } -void ConsoleBase::log(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::log(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(LogMessageType, LogMessageLevel, state, arguments); + internalAddMessage(LogMessageType, LogMessageLevel, scriptState, arguments); } -void ConsoleBase::warn(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::warn(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(LogMessageType, WarningMessageLevel, state, arguments); + internalAddMessage(LogMessageType, WarningMessageLevel, scriptState, arguments); } -void ConsoleBase::dir(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::dir(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(DirMessageType, LogMessageLevel, state, arguments); + internalAddMessage(DirMessageType, LogMessageLevel, scriptState, arguments); } -void ConsoleBase::dirxml(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::dirxml(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(DirXMLMessageType, LogMessageLevel, state, arguments); + internalAddMessage(DirXMLMessageType, LogMessageLevel, scriptState, arguments); } -void ConsoleBase::table(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::table(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(TableMessageType, LogMessageLevel, state, arguments); + internalAddMessage(TableMessageType, LogMessageLevel, scriptState, arguments); } -void ConsoleBase::clear(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::clear(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, ClearMessageType, LogMessageLevel, String(), state, arguments); + InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, ClearMessageType, LogMessageLevel, String(), scriptState, arguments); } -void ConsoleBase::trace(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::trace(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - internalAddMessage(TraceMessageType, LogMessageLevel, state, arguments, true, true); + internalAddMessage(TraceMessageType, LogMessageLevel, scriptState, arguments, true, true); } -void ConsoleBase::assertCondition(ScriptState* state, PassRefPtr<ScriptArguments> arguments, bool condition) +void ConsoleBase::assertCondition(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments, bool condition) { if (condition) return; - internalAddMessage(AssertMessageType, ErrorMessageLevel, state, arguments, true); + internalAddMessage(AssertMessageType, ErrorMessageLevel, scriptState, arguments, true); } -void ConsoleBase::count(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::count(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - InspectorInstrumentation::consoleCount(context(), state, arguments); + InspectorInstrumentation::consoleCount(context(), scriptState, arguments); } void ConsoleBase::markTimeline(const String& title) @@ -111,14 +111,14 @@ void ConsoleBase::markTimeline(const String& title) InspectorInstrumentation::consoleTimeStamp(context(), title); } -void ConsoleBase::profile(ScriptState* state, const String& title) +void ConsoleBase::profile(ScriptState* scriptState, const String& title) { - InspectorInstrumentation::consoleProfile(context(), title, state); + InspectorInstrumentation::consoleProfile(context(), title, scriptState); } -void ConsoleBase::profileEnd(ScriptState* state, const String& title) +void ConsoleBase::profileEnd(ScriptState* scriptState, const String& title) { - InspectorInstrumentation::consoleProfileEnd(context(), title); + InspectorInstrumentation::consoleProfileEnd(context(), title, scriptState); } void ConsoleBase::time(const String& title) @@ -127,10 +127,10 @@ void ConsoleBase::time(const String& title) TRACE_EVENT_COPY_ASYNC_BEGIN0("webkit.console", title.utf8().data(), this); } -void ConsoleBase::timeEnd(ScriptState* state, const String& title) +void ConsoleBase::timeEnd(ScriptState* scriptState, const String& title) { TRACE_EVENT_COPY_ASYNC_END0("webkit.console", title.utf8().data(), this); - InspectorInstrumentation::consoleTimeEnd(context(), title, state); + InspectorInstrumentation::consoleTimeEnd(context(), title, scriptState); } void ConsoleBase::timeStamp(const String& title) @@ -138,46 +138,46 @@ void ConsoleBase::timeStamp(const String& title) InspectorInstrumentation::consoleTimeStamp(context(), title); } -void ConsoleBase::timeline(ScriptState* state, const String& title) +void ConsoleBase::timeline(ScriptState* scriptState, const String& title) { - InspectorInstrumentation::consoleTimeline(context(), title, state); + InspectorInstrumentation::consoleTimeline(context(), title, scriptState); } -void ConsoleBase::timelineEnd(ScriptState* state, const String& title) +void ConsoleBase::timelineEnd(ScriptState* scriptState, const String& title) { - InspectorInstrumentation::consoleTimelineEnd(context(), title, state); + InspectorInstrumentation::consoleTimelineEnd(context(), title, scriptState); } -void ConsoleBase::group(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::group(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, StartGroupMessageType, LogMessageLevel, String(), state, arguments); + InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, StartGroupMessageType, LogMessageLevel, String(), scriptState, arguments); } -void ConsoleBase::groupCollapsed(ScriptState* state, PassRefPtr<ScriptArguments> arguments) +void ConsoleBase::groupCollapsed(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> arguments) { - InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, StartGroupCollapsedMessageType, LogMessageLevel, String(), state, arguments); + InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, StartGroupCollapsedMessageType, LogMessageLevel, String(), scriptState, arguments); } void ConsoleBase::groupEnd() { - InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, EndGroupMessageType, LogMessageLevel, String(), 0); + InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, EndGroupMessageType, LogMessageLevel, String(), nullptr); } -void ConsoleBase::internalAddMessage(MessageType type, MessageLevel level, ScriptState* state, PassRefPtr<ScriptArguments> scriptArguments, bool acceptNoArguments, bool printTrace) +void ConsoleBase::internalAddMessage(MessageType type, MessageLevel level, ScriptState* scriptState, PassRefPtrWillBeRawPtr<ScriptArguments> scriptArguments, bool acceptNoArguments, bool printTrace) { if (!context()) return; - RefPtr<ScriptArguments> arguments = scriptArguments; + RefPtrWillBeRawPtr<ScriptArguments> arguments = scriptArguments; if (!acceptNoArguments && !arguments->argumentCount()) return; size_t stackSize = printTrace ? ScriptCallStack::maxCallStackSizeToCapture : 1; - RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(stackSize)); + RefPtrWillBeRawPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(scriptState, stackSize)); String message; bool gotStringMessage = arguments->getFirstArgumentAsString(message); - InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, type, level, message, state, arguments); + InspectorInstrumentation::addMessageToConsole(context(), ConsoleAPIMessageSource, type, level, message, scriptState, arguments); if (gotStringMessage) reportMessageToClient(level, message, callStack); } diff --git a/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.h b/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.h index 30858d02731..7fc36680628 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.h +++ b/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.h @@ -36,6 +36,7 @@ #include "core/inspector/ScriptCallStack.h" #include "core/frame/ConsoleTypes.h" #include "core/frame/DOMWindowProperty.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -44,23 +45,20 @@ namespace WebCore { class ScriptArguments; -class ConsoleBase { +class ConsoleBase : public RefCountedWillBeGarbageCollectedFinalized<ConsoleBase> { public: - void ref() { refConsole(); } - void deref() { derefConsole(); } - - void debug(ScriptState*, PassRefPtr<ScriptArguments>); - void error(ScriptState*, PassRefPtr<ScriptArguments>); - void info(ScriptState*, PassRefPtr<ScriptArguments>); - void log(ScriptState*, PassRefPtr<ScriptArguments>); - void clear(ScriptState*, PassRefPtr<ScriptArguments>); - void warn(ScriptState*, PassRefPtr<ScriptArguments>); - void dir(ScriptState*, PassRefPtr<ScriptArguments>); - void dirxml(ScriptState*, PassRefPtr<ScriptArguments>); - void table(ScriptState*, PassRefPtr<ScriptArguments>); - void trace(ScriptState*, PassRefPtr<ScriptArguments>); - void assertCondition(ScriptState*, PassRefPtr<ScriptArguments>, bool condition); - void count(ScriptState*, PassRefPtr<ScriptArguments>); + void debug(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void error(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void info(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void log(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void clear(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void warn(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void dir(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void dirxml(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void table(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void trace(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void assertCondition(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>, bool condition); + void count(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); void markTimeline(const String&); void profile(ScriptState*, const String&); void profileEnd(ScriptState*, const String&); @@ -69,20 +67,20 @@ public: void timeStamp(const String&); void timeline(ScriptState*, const String&); void timelineEnd(ScriptState*, const String&); - void group(ScriptState*, PassRefPtr<ScriptArguments>); - void groupCollapsed(ScriptState*, PassRefPtr<ScriptArguments>); + void group(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); + void groupCollapsed(ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>); void groupEnd(); -protected: + virtual void trace(Visitor*) { } + virtual ~ConsoleBase(); + +protected: virtual ExecutionContext* context() = 0; - virtual void reportMessageToClient(MessageLevel, const String& message, PassRefPtr<ScriptCallStack>) = 0; + virtual void reportMessageToClient(MessageLevel, const String& message, PassRefPtrWillBeRawPtr<ScriptCallStack>) = 0; private: - virtual void refConsole() = 0; - virtual void derefConsole() = 0; - - void internalAddMessage(MessageType, MessageLevel, ScriptState*, PassRefPtr<ScriptArguments>, bool acceptNoArguments = false, bool printTrace = false); + void internalAddMessage(MessageType, MessageLevel, ScriptState*, PassRefPtrWillBeRawPtr<ScriptArguments>, bool acceptNoArguments = false, bool printTrace = false); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.idl b/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.idl index b63a7f5aca2..355cb597334 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.idl +++ b/chromium/third_party/WebKit/Source/core/frame/ConsoleBase.idl @@ -29,6 +29,7 @@ [ NoInterfaceObject, + WillBeGarbageCollected, ] interface ConsoleBase { [CallWith=ScriptArguments&ScriptState] void debug(); [CallWith=ScriptArguments&ScriptState] void error(); @@ -41,17 +42,17 @@ [CallWith=ScriptArguments&ScriptState] void trace(); [CallWith=ScriptArguments&ScriptState, ImplementedAs=assertCondition] void assert([Default=Undefined] optional boolean condition); [CallWith=ScriptArguments&ScriptState] void count(); - [DeprecateAs=ConsoleMarkTimeline] void markTimeline([Default=NullString] optional DOMString title); + [DeprecateAs=ConsoleMarkTimeline] void markTimeline(optional DOMString title = null); - [CallWith=ScriptState] void profile([Default=NullString] optional DOMString title); - [CallWith=ScriptState] void profileEnd([Default=NullString] optional DOMString title); + [CallWith=ScriptState] void profile(optional DOMString title = null); + [CallWith=ScriptState] void profileEnd(optional DOMString title = null); - void time([Default=NullString] optional DOMString title); - [CallWith=ScriptState] void timeEnd([Default=NullString] optional DOMString title); - void timeStamp([Default=NullString] optional DOMString title); + void time(optional DOMString title = null); + [CallWith=ScriptState] void timeEnd(optional DOMString title = null); + void timeStamp(optional DOMString title = null); - [CallWith=ScriptState] void timeline([Default=NullString] optional DOMString title); - [CallWith=ScriptState] void timelineEnd([Default=NullString] optional DOMString title); + [CallWith=ScriptState] void timeline(optional DOMString title = null); + [CallWith=ScriptState] void timelineEnd(optional DOMString title = null); [CallWith=ScriptArguments&ScriptState] void group(); [CallWith=ScriptArguments&ScriptState] void groupCollapsed(); diff --git a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicy.cpp b/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicy.cpp deleted file mode 100644 index 4c3cbe42472..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicy.cpp +++ /dev/null @@ -1,2032 +0,0 @@ -/* - * Copyright (C) 2011 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 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 GOOGLE 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 "core/frame/ContentSecurityPolicy.h" - -#include "RuntimeEnabledFeatures.h" -#include "bindings/v8/ScriptCallStackFactory.h" -#include "bindings/v8/ScriptController.h" -#include "core/dom/DOMStringList.h" -#include "core/dom/Document.h" -#include "core/events/SecurityPolicyViolationEvent.h" -#include "core/frame/ContentSecurityPolicyResponseHeaders.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" -#include "core/inspector/InspectorInstrumentation.h" -#include "core/inspector/ScriptCallStack.h" -#include "core/loader/DocumentLoader.h" -#include "core/loader/PingLoader.h" -#include "core/frame/UseCounter.h" -#include "platform/JSONValues.h" -#include "platform/NotImplemented.h" -#include "platform/ParsingUtilities.h" -#include "platform/network/FormData.h" -#include "platform/network/ResourceResponse.h" -#include "platform/weborigin/KURL.h" -#include "platform/weborigin/KnownPorts.h" -#include "platform/weborigin/SchemeRegistry.h" -#include "platform/weborigin/SecurityOrigin.h" -#include "wtf/SHA1.h" -#include "wtf/StringHasher.h" -#include "wtf/text/Base64.h" -#include "wtf/text/StringBuilder.h" - -namespace WTF { - -struct VectorIntHash { - static unsigned hash(const Vector<uint8_t>& v) { return StringHasher::computeHash(v.data(), v.size()); } - static bool equal(const Vector<uint8_t>& a, const Vector<uint8_t>& b) { return a == b; }; - static const bool safeToCompareToEmptyOrDeleted = true; -}; -template<> struct DefaultHash<Vector<uint8_t> > { - typedef VectorIntHash Hash; -}; - -} // namespace WTF - -namespace WebCore { - -typedef std::pair<unsigned, Vector<uint8_t> > SourceHashValue; - -// 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 -} - -// Only checks for general Base64 encoded chars, not '=' chars since '=' is -// positional and may only appear at the end of a Base64 encoded string. -bool isBase64EncodedCharacter(UChar c) -{ - return isASCIIAlphanumeric(c) || c == '+' || c == '/'; -} - -bool isNonceCharacter(UChar c) -{ - return isBase64EncodedCharacter(c) || c == '='; -} - -bool isSourceCharacter(UChar c) -{ - return !isASCIISpace(c); -} - -bool isPathComponentCharacter(UChar c) -{ - return c != '?' && c != '#'; -} - -bool isHostCharacter(UChar c) -{ - return isASCIIAlphanumeric(c) || c == '-'; -} - -bool isSchemeContinuationCharacter(UChar c) -{ - return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.'; -} - -bool isNotASCIISpace(UChar c) -{ - return !isASCIISpace(c); -} - -bool isNotColonOrSlash(UChar c) -{ - return c != ':' && c != '/'; -} - -bool isMediaTypeCharacter(UChar c) -{ - return !isASCIISpace(c) && c != '/'; -} - -// CSP 1.0 Directives -static const char connectSrc[] = "connect-src"; -static const char defaultSrc[] = "default-src"; -static const char fontSrc[] = "font-src"; -static const char frameSrc[] = "frame-src"; -static const char imgSrc[] = "img-src"; -static const char mediaSrc[] = "media-src"; -static const char objectSrc[] = "object-src"; -static const char reportURI[] = "report-uri"; -static const char sandbox[] = "sandbox"; -static const char scriptSrc[] = "script-src"; -static const char styleSrc[] = "style-src"; - -// CSP 1.1 Directives -static const char baseURI[] = "base-uri"; -static const char formAction[] = "form-action"; -static const char pluginTypes[] = "plugin-types"; -static const char reflectedXSS[] = "reflected-xss"; - -bool isDirectiveName(const String& name) -{ - return (equalIgnoringCase(name, connectSrc) - || equalIgnoringCase(name, defaultSrc) - || equalIgnoringCase(name, fontSrc) - || equalIgnoringCase(name, frameSrc) - || equalIgnoringCase(name, imgSrc) - || equalIgnoringCase(name, mediaSrc) - || equalIgnoringCase(name, objectSrc) - || equalIgnoringCase(name, reportURI) - || equalIgnoringCase(name, sandbox) - || equalIgnoringCase(name, scriptSrc) - || equalIgnoringCase(name, styleSrc) - || equalIgnoringCase(name, baseURI) - || equalIgnoringCase(name, formAction) - || equalIgnoringCase(name, pluginTypes) - || equalIgnoringCase(name, reflectedXSS) - ); -} - -UseCounter::Feature getUseCounterType(ContentSecurityPolicy::HeaderType type) -{ - switch (type) { - case ContentSecurityPolicy::Enforce: - return UseCounter::ContentSecurityPolicy; - case ContentSecurityPolicy::Report: - return UseCounter::ContentSecurityPolicyReportOnly; - } - ASSERT_NOT_REACHED(); - return UseCounter::NumberOfFeatures; -} - -} // namespace - -static bool isSourceListNone(const UChar* begin, const UChar* end) -{ - skipWhile<UChar, isASCIISpace>(begin, end); - - const UChar* position = begin; - skipWhile<UChar, isSourceCharacter>(position, end); - if (!equalIgnoringCase("'none'", begin, position - begin)) - return false; - - skipWhile<UChar, isASCIISpace>(position, end); - if (position != end) - return false; - - return true; -} - -class CSPSource { -public: - CSPSource(ContentSecurityPolicy* policy, const String& scheme, const String& host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard) - : m_policy(policy) - , m_scheme(scheme) - , m_host(host) - , m_port(port) - , m_path(path) - , 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) && pathMatches(url); - } - -private: - bool schemeMatches(const KURL& url) const - { - if (m_scheme.isEmpty()) { - String protectedResourceScheme(m_policy->securityOrigin()->protocol()); - if (equalIgnoringCase("http", protectedResourceScheme)) - return url.protocolIs("http") || url.protocolIs("https"); - return equalIgnoringCase(url.protocol(), protectedResourceScheme); - } - return equalIgnoringCase(url.protocol(), m_scheme); - } - - bool hostMatches(const KURL& url) const - { - const String& host = url.host(); - if (equalIgnoringCase(host, m_host)) - return true; - return m_hostHasWildcard && host.endsWith("." + m_host, false); - - } - - bool pathMatches(const KURL& url) const - { - if (m_path.isEmpty()) - return true; - - String path = decodeURLEscapeSequences(url.path()); - - if (m_path.endsWith("/")) - return path.startsWith(m_path, false); - - return path == m_path; - } - - bool portMatches(const KURL& url) const - { - if (m_portHasWildcard) - return true; - - int port = url.port(); - - if (port == m_port) - return true; - - if (!port) - return isDefaultPortForProtocol(m_port, url.protocol()); - - if (!m_port) - return isDefaultPortForProtocol(port, url.protocol()); - - return false; - } - - bool isSchemeOnly() const { return m_host.isEmpty(); } - - ContentSecurityPolicy* m_policy; - String m_scheme; - String m_host; - int m_port; - String m_path; - - bool m_hostHasWildcard; - bool m_portHasWildcard; -}; - -class CSPSourceList { -public: - CSPSourceList(ContentSecurityPolicy*, const String& directiveName); - - void parse(const UChar* begin, const UChar* end); - - bool matches(const KURL&); - bool allowInline() const { return m_allowInline; } - bool allowEval() const { return m_allowEval; } - bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_nonces.contains(nonce); } - bool allowHash(const SourceHashValue& hashValue) const { return m_hashes.contains(hashValue); } - uint8_t hashAlgorithmsUsed() const { return m_hashAlgorithmsUsed; } - -private: - bool parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, 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); - bool parsePath(const UChar* begin, const UChar* end, String& path); - bool parseNonce(const UChar* begin, const UChar* end, String& nonce); - bool parseHash(const UChar* begin, const UChar* end, Vector<uint8_t>& hash, ContentSecurityPolicy::HashAlgorithms&); - - void addSourceSelf(); - void addSourceStar(); - void addSourceUnsafeInline(); - void addSourceUnsafeEval(); - void addSourceNonce(const String& nonce); - void addSourceHash(const ContentSecurityPolicy::HashAlgorithms&, const Vector<uint8_t>& hash); - - ContentSecurityPolicy* m_policy; - Vector<CSPSource> m_list; - String m_directiveName; - bool m_allowStar; - bool m_allowInline; - bool m_allowEval; - HashSet<String> m_nonces; - HashSet<SourceHashValue> m_hashes; - uint8_t m_hashAlgorithmsUsed; -}; - -CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& directiveName) - : m_policy(policy) - , m_directiveName(directiveName) - , m_allowStar(false) - , m_allowInline(false) - , m_allowEval(false) - , m_hashAlgorithmsUsed(0) -{ -} - -bool CSPSourceList::matches(const KURL& url) -{ - if (m_allowStar) - return true; - - KURL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin::extractInnerURL(url) : url; - - for (size_t i = 0; i < m_list.size(); ++i) { - if (m_list[i].matches(effectiveURL)) - return true; - } - - return false; -} - -// source-list = *WSP [ source *( 1*WSP source ) *WSP ] -// / *WSP "'none'" *WSP -// -void CSPSourceList::parse(const UChar* begin, const UChar* end) -{ - // We represent 'none' as an empty m_list. - if (isSourceListNone(begin, end)) - return; - - const UChar* position = begin; - while (position < end) { - skipWhile<UChar, isASCIISpace>(position, end); - if (position == end) - return; - - const UChar* beginSource = position; - skipWhile<UChar, isSourceCharacter>(position, end); - - String scheme, host, path; - int port = 0; - bool hostHasWildcard = false; - bool portHasWildcard = false; - - if (parseSource(beginSource, position, scheme, host, port, path, hostHasWildcard, portHasWildcard)) { - // Wildcard hosts and keyword sources ('self', 'unsafe-inline', - // etc.) aren't stored in m_list, but as attributes on the source - // list itself. - if (scheme.isEmpty() && host.isEmpty()) - continue; - if (isDirectiveName(host)) - m_policy->reportDirectiveAsSourceExpression(m_directiveName, host); - m_list.append(CSPSource(m_policy, scheme, host, port, path, hostHasWildcard, portHasWildcard)); - } else { - m_policy->reportInvalidSourceExpression(m_directiveName, String(beginSource, position - beginSource)); - } - - ASSERT(position == end || isASCIISpace(*position)); - } -} - -// source = scheme ":" -// / ( [ scheme "://" ] host [ port ] [ path ] ) -// / "'self'" -bool CSPSourceList::parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard) -{ - if (begin == end) - return false; - - if (equalIgnoringCase("'none'", begin, end - begin)) - return false; - - if (end - begin == 1 && *begin == '*') { - addSourceStar(); - return true; - } - - if (equalIgnoringCase("'self'", begin, end - begin)) { - addSourceSelf(); - return true; - } - - if (equalIgnoringCase("'unsafe-inline'", begin, end - begin)) { - addSourceUnsafeInline(); - return true; - } - - if (equalIgnoringCase("'unsafe-eval'", begin, end - begin)) { - addSourceUnsafeEval(); - return true; - } - - if (m_policy->experimentalFeaturesEnabled()) { - String nonce; - if (!parseNonce(begin, end, nonce)) - return false; - - if (!nonce.isNull()) { - addSourceNonce(nonce); - return true; - } - - Vector<uint8_t> hash; - ContentSecurityPolicy::HashAlgorithms algorithm = ContentSecurityPolicy::HashAlgorithmsNone; - if (!parseHash(begin, end, hash, algorithm)) - return false; - - if (hash.size() > 0) { - addSourceHash(algorithm, hash); - return true; - } - } - - const UChar* position = begin; - const UChar* beginHost = begin; - const UChar* beginPath = end; - const UChar* beginPort = 0; - - skipWhile<UChar, isNotColonOrSlash>(position, end); - - if (position == end) { - // host - // ^ - return parseHost(beginHost, position, host, hostHasWildcard); - } - - if (position < end && *position == '/') { - // host/path || host/ || / - // ^ ^ ^ - return parseHost(beginHost, position, host, hostHasWildcard) && parsePath(position, end, path); - } - - if (position < end && *position == ':') { - if (end - position == 1) { - // scheme: - // ^ - return parseScheme(begin, position, scheme); - } - - if (position[1] == '/') { - // scheme://host || scheme:// - // ^ ^ - if (!parseScheme(begin, position, scheme) - || !skipExactly<UChar>(position, end, ':') - || !skipExactly<UChar>(position, end, '/') - || !skipExactly<UChar>(position, end, '/')) - return false; - if (position == end) - return true; - beginHost = position; - skipWhile<UChar, isNotColonOrSlash>(position, end); - } - - if (position < end && *position == ':') { - // host:port || scheme://host:port - // ^ ^ - beginPort = position; - skipUntil<UChar>(position, end, '/'); - } - } - - if (position < end && *position == '/') { - // scheme://host/path || scheme://host:port/path - // ^ ^ - if (position == beginHost) - return false; - beginPath = position; - } - - if (!parseHost(beginHost, beginPort ? beginPort : beginPath, host, hostHasWildcard)) - return false; - - if (beginPort) { - if (!parsePort(beginPort, beginPath, port, portHasWildcard)) - return false; - } else { - port = 0; - } - - if (beginPath != end) { - if (!parsePath(beginPath, end, path)) - return false; - } - - return true; -} - -// nonce-source = "'nonce-" nonce-value "'" -// nonce-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" ) -// -bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& nonce) -{ - DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); - - if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length())) - return true; - - const UChar* position = begin + noncePrefix.length(); - const UChar* nonceBegin = position; - - skipWhile<UChar, isNonceCharacter>(position, end); - ASSERT(nonceBegin <= position); - - if ((position + 1) != end || *position != '\'' || !(position - nonceBegin)) - return false; - - nonce = String(nonceBegin, position - nonceBegin); - return true; -} - -// hash-source = "'" hash-algorithm "-" hash-value "'" -// hash-algorithm = "sha1" / "sha256" -// hash-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" ) -// -bool CSPSourceList::parseHash(const UChar* begin, const UChar* end, Vector<uint8_t>& hash, ContentSecurityPolicy::HashAlgorithms& hashAlgorithm) -{ - DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("'sha1-")); - DEFINE_STATIC_LOCAL(const String, sha256Prefix, ("'sha256-")); - - String prefix; - if (equalIgnoringCase(sha1Prefix.characters8(), begin, sha1Prefix.length())) { - prefix = sha1Prefix; - hashAlgorithm = ContentSecurityPolicy::HashAlgorithmsSha1; - } else if (equalIgnoringCase(sha256Prefix.characters8(), begin, sha256Prefix.length())) { - notImplemented(); - } else { - return true; - } - - const UChar* position = begin + prefix.length(); - const UChar* hashBegin = position; - - skipWhile<UChar, isBase64EncodedCharacter>(position, end); - ASSERT(hashBegin <= position); - - // Base64 encodings may end with exactly one or two '=' characters - skipExactly<UChar>(position, position + 1, '='); - skipExactly<UChar>(position, position + 1, '='); - - if ((position + 1) != end || *position != '\'' || !(position - hashBegin)) - return false; - - Vector<char> hashVector; - base64Decode(hashBegin, position - hashBegin, hashVector); - hash.append(reinterpret_cast<uint8_t*>(hashVector.data()), hashVector.size()); - 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<UChar, isASCIIAlpha>(position, end)) - return false; - - skipWhile<UChar, 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<UChar>(position, end, '*')) { - hostHasWildcard = true; - - if (position == end) - return true; - - if (!skipExactly<UChar>(position, end, '.')) - return false; - } - - const UChar* hostBegin = position; - - while (position < end) { - if (!skipExactly<UChar, isHostCharacter>(position, end)) - return false; - - skipWhile<UChar, isHostCharacter>(position, end); - - if (position < end && !skipExactly<UChar>(position, end, '.')) - return false; - } - - ASSERT(position == end); - host = String(hostBegin, end - hostBegin); - return true; -} - -bool CSPSourceList::parsePath(const UChar* begin, const UChar* end, String& path) -{ - ASSERT(begin <= end); - ASSERT(path.isEmpty()); - - const UChar* position = begin; - skipWhile<UChar, isPathComponentCharacter>(position, end); - // path/to/file.js?query=string || path/to/file.js#anchor - // ^ ^ - if (position < end) - m_policy->reportInvalidPathCharacter(m_directiveName, String(begin, end - begin), *position); - - path = decodeURLEscapeSequences(String(begin, position - begin)); - - ASSERT(position <= end); - ASSERT(position == end || (*position == '#' || *position == '?')); - 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 (!skipExactly<UChar>(begin, end, ':')) - ASSERT_NOT_REACHED(); - - if (begin == end) - return false; - - if (end - begin == 1 && *begin == '*') { - port = 0; - portHasWildcard = true; - return true; - } - - const UChar* position = begin; - skipWhile<UChar, isASCIIDigit>(position, end); - - if (position != end) - return false; - - bool ok; - port = charactersToIntStrict(begin, end - begin, &ok); - return ok; -} - -void CSPSourceList::addSourceSelf() -{ - m_list.append(CSPSource(m_policy, m_policy->securityOrigin()->protocol(), m_policy->securityOrigin()->host(), m_policy->securityOrigin()->port(), String(), false, false)); -} - -void CSPSourceList::addSourceStar() -{ - m_allowStar = true; -} - -void CSPSourceList::addSourceUnsafeInline() -{ - m_allowInline = true; -} - -void CSPSourceList::addSourceUnsafeEval() -{ - m_allowEval = true; -} - -void CSPSourceList::addSourceNonce(const String& nonce) -{ - m_nonces.add(nonce); -} - -void CSPSourceList::addSourceHash(const ContentSecurityPolicy::HashAlgorithms& algorithm, const Vector<uint8_t>& hash) -{ - m_hashes.add(SourceHashValue(algorithm, hash)); - m_hashAlgorithmsUsed |= algorithm; -} - -class CSPDirective { -public: - CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy) - : m_name(name) - , m_text(name + ' ' + value) - , m_policy(policy) - { - } - - const String& text() const { return m_text; } - -protected: - const ContentSecurityPolicy* policy() const { return m_policy; } - -private: - String m_name; - String m_text; - ContentSecurityPolicy* m_policy; -}; - -class MediaListDirective : public CSPDirective { -public: - MediaListDirective(const String& name, const String& value, ContentSecurityPolicy* policy) - : CSPDirective(name, value, policy) - { - Vector<UChar> characters; - value.appendTo(characters); - parse(characters.data(), characters.data() + characters.size()); - } - - bool allows(const String& type) - { - return m_pluginTypes.contains(type); - } - -private: - void parse(const UChar* begin, const UChar* end) - { - const UChar* position = begin; - - // 'plugin-types ____;' OR 'plugin-types;' - if (position == end) { - policy()->reportInvalidPluginTypes(String()); - return; - } - - while (position < end) { - // _____ OR _____mime1/mime1 - // ^ ^ - skipWhile<UChar, isASCIISpace>(position, end); - if (position == end) - return; - - // mime1/mime1 mime2/mime2 - // ^ - begin = position; - if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { - skipWhile<UChar, isNotASCIISpace>(position, end); - policy()->reportInvalidPluginTypes(String(begin, position - begin)); - continue; - } - skipWhile<UChar, isMediaTypeCharacter>(position, end); - - // mime1/mime1 mime2/mime2 - // ^ - if (!skipExactly<UChar>(position, end, '/')) { - skipWhile<UChar, isNotASCIISpace>(position, end); - policy()->reportInvalidPluginTypes(String(begin, position - begin)); - continue; - } - - // mime1/mime1 mime2/mime2 - // ^ - if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { - skipWhile<UChar, isNotASCIISpace>(position, end); - policy()->reportInvalidPluginTypes(String(begin, position - begin)); - continue; - } - skipWhile<UChar, isMediaTypeCharacter>(position, end); - - // mime1/mime1 mime2/mime2 OR mime1/mime1 OR mime1/mime1/error - // ^ ^ ^ - if (position < end && isNotASCIISpace(*position)) { - skipWhile<UChar, isNotASCIISpace>(position, end); - policy()->reportInvalidPluginTypes(String(begin, position - begin)); - continue; - } - m_pluginTypes.add(String(begin, position - begin)); - - ASSERT(position == end || isASCIISpace(*position)); - } - } - - HashSet<String> m_pluginTypes; -}; - -class SourceListDirective : public CSPDirective { -public: - SourceListDirective(const String& name, const String& value, ContentSecurityPolicy* policy) - : CSPDirective(name, value, policy) - , m_sourceList(policy, name) - { - Vector<UChar> characters; - value.appendTo(characters); - - m_sourceList.parse(characters.data(), characters.data() + characters.size()); - } - - bool allows(const KURL& url) - { - return m_sourceList.matches(url.isEmpty() ? policy()->url() : url); - } - - bool allowInline() const { return m_sourceList.allowInline(); } - bool allowEval() const { return m_sourceList.allowEval(); } - bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce(nonce.stripWhiteSpace()); } - bool allowHash(const SourceHashValue& hashValue) const { return m_sourceList.allowHash(hashValue); } - - uint8_t hashAlgorithmsUsed() const { return m_sourceList.hashAlgorithmsUsed(); } - -private: - CSPSourceList m_sourceList; -}; - -class CSPDirectiveList { - WTF_MAKE_FAST_ALLOCATED; -public: - static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UChar* begin, const UChar* end, ContentSecurityPolicy::HeaderType); - - void parse(const UChar* begin, const UChar* end); - - const String& header() const { return m_header; } - ContentSecurityPolicy::HeaderType headerType() const { return m_headerType; } - - bool allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; - bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; - bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; - bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; - bool allowEval(ScriptState*, ContentSecurityPolicy::ReportingStatus) const; - bool allowPluginType(const String& type, const String& typeAttribute, const KURL&, ContentSecurityPolicy::ReportingStatus) const; - - bool allowScriptFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowObjectFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const; - bool allowScriptNonce(const String&) const; - bool allowStyleNonce(const String&) const; - bool allowScriptHash(const SourceHashValue&) const; - - void gatherReportURIs(DOMStringList&) const; - const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; } - ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflectedXSSDisposition; } - bool isReportOnly() const { return m_reportOnly; } - const Vector<KURL>& reportURIs() const { return m_reportURIs; } - -private: - CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); - - bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value); - void parseReportURI(const String& name, const String& value); - void parsePluginTypes(const String& name, const String& value); - void parseReflectedXSS(const String& name, const String& value); - void addDirective(const String& name, const String& value); - void applySandboxPolicy(const String& name, const String& sandboxPolicy); - - template <class CSPDirectiveType> - void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>&); - - SourceListDirective* operativeDirective(SourceListDirective*) const; - void reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL) const; - void reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const; - void reportViolationWithState(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptState*) const; - - bool checkEval(SourceListDirective*) const; - bool checkInline(SourceListDirective*) const; - bool checkNonce(SourceListDirective*, const String&) const; - bool checkHash(SourceListDirective*, const SourceHashValue&) const; - bool checkSource(SourceListDirective*, const KURL&) const; - bool checkMediaType(MediaListDirective*, const String& type, const String& typeAttribute) const; - - void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisabledErrorMessage = errorMessage; } - - bool checkEvalAndReportViolation(SourceListDirective*, const String& consoleMessage, ScriptState*) const; - bool checkInlineAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const; - - bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; - bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& type, const String& typeAttribute, const String& consoleMessage) const; - - bool denyIfEnforcingPolicy() const { return m_reportOnly; } - - ContentSecurityPolicy* m_policy; - - String m_header; - ContentSecurityPolicy::HeaderType m_headerType; - - bool m_reportOnly; - bool m_haveSandboxPolicy; - ReflectedXSSDisposition m_reflectedXSSDisposition; - - OwnPtr<MediaListDirective> m_pluginTypes; - OwnPtr<SourceListDirective> m_baseURI; - OwnPtr<SourceListDirective> m_connectSrc; - OwnPtr<SourceListDirective> m_defaultSrc; - OwnPtr<SourceListDirective> m_fontSrc; - OwnPtr<SourceListDirective> m_formAction; - OwnPtr<SourceListDirective> m_frameSrc; - OwnPtr<SourceListDirective> m_imgSrc; - OwnPtr<SourceListDirective> m_mediaSrc; - OwnPtr<SourceListDirective> m_objectSrc; - OwnPtr<SourceListDirective> m_scriptSrc; - OwnPtr<SourceListDirective> m_styleSrc; - - Vector<KURL> m_reportURIs; - - String m_evalDisabledErrorMessage; -}; - -CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurityPolicy::HeaderType type) - : m_policy(policy) - , m_headerType(type) - , m_reportOnly(false) - , m_haveSandboxPolicy(false) - , m_reflectedXSSDisposition(ReflectedXSSUnset) -{ - m_reportOnly = type == ContentSecurityPolicy::Report; -} - -PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* policy, const UChar* begin, const UChar* end, ContentSecurityPolicy::HeaderType type) -{ - OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy, type)); - directives->parse(begin, end); - - if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) { - String message = "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_scriptSrc.get())->text() + "\".\n"; - directives->setEvalDisabledErrorMessage(message); - } - - if (directives->isReportOnly() && directives->reportURIs().isEmpty()) - policy->reportMissingReportURI(String(begin, end - begin)); - - return directives.release(); -} - -void CSPDirectiveList::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL) const -{ - String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage; - m_policy->client()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message); - m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header); -} - -void CSPDirectiveList::reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const -{ - String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage; - m_policy->client()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message, contextURL, contextLine.oneBasedInt()); - m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header); -} - -void CSPDirectiveList::reportViolationWithState(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptState* state) const -{ - String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage; - m_policy->client()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message, state); - m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header); -} - -bool CSPDirectiveList::checkEval(SourceListDirective* directive) const -{ - return !directive || directive->allowEval(); -} - -bool CSPDirectiveList::checkInline(SourceListDirective* directive) const -{ - return !directive || directive->allowInline(); -} - -bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const -{ - return !directive || directive->allowNonce(nonce); -} - -bool CSPDirectiveList::checkHash(SourceListDirective* directive, const SourceHashValue& hashValue) const -{ - return !directive || directive->allowHash(hashValue); -} - -bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& url) const -{ - return !directive || directive->allows(url); -} - -bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const -{ - if (!directive) - return true; - if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) - return false; - return directive->allows(type); -} - -SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive) const -{ - return directive ? directive : m_defaultSrc.get(); -} - -bool CSPDirectiveList::checkEvalAndReportViolation(SourceListDirective* directive, const String& consoleMessage, ScriptState* state) const -{ - if (checkEval(directive)) - return true; - - String suffix = String(); - if (directive == m_defaultSrc) - suffix = " Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback."; - - reportViolationWithState(directive->text(), scriptSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), state); - if (!m_reportOnly) { - m_policy->reportBlockedScriptExecutionToInspector(directive->text()); - return false; - } - return true; -} - -bool CSPDirectiveList::checkMediaTypeAndReportViolation(MediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const -{ - if (checkMediaType(directive, type, typeAttribute)) - return true; - - String message = consoleMessage + "\'" + directive->text() + "\'."; - if (typeAttribute.isEmpty()) - message = message + " When enforcing the 'plugin-types' directive, the plugin's media type must be explicitly declared with a 'type' attribute on the containing element (e.g. '<object type=\"[TYPE GOES HERE]\" ...>')."; - - reportViolation(directive->text(), pluginTypes, message + "\n", KURL()); - return denyIfEnforcingPolicy(); -} - -bool CSPDirectiveList::checkInlineAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const -{ - if (checkInline(directive)) - return true; - - String suffix = String(); - if (directive == m_defaultSrc) - suffix = " Note that '" + String(isScript ? "script" : "style") + "-src' was not explicitly set, so 'default-src' is used as a fallback."; - - reportViolationWithLocation(directive->text(), isScript ? scriptSrc : styleSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), contextURL, contextLine); - - if (!m_reportOnly) { - if (isScript) - m_policy->reportBlockedScriptExecutionToInspector(directive->text()); - return false; - } - return true; -} - -bool CSPDirectiveList::checkSourceAndReportViolation(SourceListDirective* directive, const KURL& url, const String& effectiveDirective) const -{ - if (checkSource(directive, url)) - return true; - - String prefix; - if (baseURI == effectiveDirective) - prefix = "Refused to set the document's base URI to '"; - else if (connectSrc == effectiveDirective) - prefix = "Refused to connect to '"; - else if (fontSrc == effectiveDirective) - prefix = "Refused to load the font '"; - else if (formAction == effectiveDirective) - prefix = "Refused to send form data to '"; - else if (frameSrc == effectiveDirective) - prefix = "Refused to frame '"; - else if (imgSrc == effectiveDirective) - prefix = "Refused to load the image '"; - else if (mediaSrc == effectiveDirective) - prefix = "Refused to load media from '"; - else if (objectSrc == effectiveDirective) - prefix = "Refused to load plugin data from '"; - else if (scriptSrc == effectiveDirective) - prefix = "Refused to load the script '"; - else if (styleSrc == effectiveDirective) - prefix = "Refused to load the stylesheet '"; - - String suffix = String(); - if (directive == m_defaultSrc) - suffix = " Note that '" + effectiveDirective + "' was not explicitly set, so 'default-src' is used as a fallback."; - - reportViolation(directive->text(), effectiveDirective, prefix + url.elidedString() + "' because it violates the following Content Security Policy directive: \"" + directive->text() + "\"." + suffix + "\n", url); - return denyIfEnforcingPolicy(); -} - -bool CSPDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: ")); - if (reportingStatus == ContentSecurityPolicy::SendReport) - return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true); - - return checkInline(operativeDirective(m_scriptSrc.get())); -} - -bool CSPDirectiveList::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline event handler because it violates the following Content Security Policy directive: ")); - if (reportingStatus == ContentSecurityPolicy::SendReport) - return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true); - return checkInline(operativeDirective(m_scriptSrc.get())); -} - -bool CSPDirectiveList::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline script because it violates the following Content Security Policy directive: ")); - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true) : - checkInline(operativeDirective(m_scriptSrc.get())); -} - -bool CSPDirectiveList::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to apply inline style because it violates the following Content Security Policy directive: ")); - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkInlineAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, contextURL, contextLine, false) : - checkInline(operativeDirective(m_styleSrc.get())); -} - -bool CSPDirectiveList::allowEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: ")); - - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, state) : - checkEval(operativeDirective(m_scriptSrc.get())); -} - -bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.elidedString() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ") : - checkMediaType(m_pluginTypes.get(), type, typeAttribute); -} - -bool CSPDirectiveList::allowScriptFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_scriptSrc.get()), url, scriptSrc) : - checkSource(operativeDirective(m_scriptSrc.get()), url); -} - -bool CSPDirectiveList::allowObjectFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - if (url.isBlankURL()) - return true; - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_objectSrc.get()), url, objectSrc) : - checkSource(operativeDirective(m_objectSrc.get()), url); -} - -bool CSPDirectiveList::allowChildFrameFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - if (url.isBlankURL()) - return true; - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_frameSrc.get()), url, frameSrc) : - checkSource(operativeDirective(m_frameSrc.get()), url); -} - -bool CSPDirectiveList::allowImageFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_imgSrc.get()), url, imgSrc) : - checkSource(operativeDirective(m_imgSrc.get()), url); -} - -bool CSPDirectiveList::allowStyleFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_styleSrc.get()), url, styleSrc) : - checkSource(operativeDirective(m_styleSrc.get()), url); -} - -bool CSPDirectiveList::allowFontFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_fontSrc.get()), url, fontSrc) : - checkSource(operativeDirective(m_fontSrc.get()), url); -} - -bool CSPDirectiveList::allowMediaFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_mediaSrc.get()), url, mediaSrc) : - checkSource(operativeDirective(m_mediaSrc.get()), url); -} - -bool CSPDirectiveList::allowConnectToSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(operativeDirective(m_connectSrc.get()), url, connectSrc) : - checkSource(operativeDirective(m_connectSrc.get()), url); -} - -void CSPDirectiveList::gatherReportURIs(DOMStringList& list) const -{ - for (size_t i = 0; i < m_reportURIs.size(); ++i) - list.append(m_reportURIs[i].string()); -} - -bool CSPDirectiveList::allowFormAction(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(m_formAction.get(), url, formAction) : - checkSource(m_formAction.get(), url); -} - -bool CSPDirectiveList::allowBaseURI(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return reportingStatus == ContentSecurityPolicy::SendReport ? - checkSourceAndReportViolation(m_baseURI.get(), url, baseURI) : - checkSource(m_baseURI.get(), url); -} - -bool CSPDirectiveList::allowScriptNonce(const String& nonce) const -{ - return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); -} - -bool CSPDirectiveList::allowStyleNonce(const String& nonce) const -{ - return checkNonce(operativeDirective(m_styleSrc.get()), nonce); -} - -bool CSPDirectiveList::allowScriptHash(const SourceHashValue& hashValue) const -{ - return checkHash(operativeDirective(m_scriptSrc.get()), hashValue); -} - -// policy = directive-list -// directive-list = [ directive *( ";" [ directive ] ) ] -// -void CSPDirectiveList::parse(const UChar* begin, const UChar* end) -{ - m_header = String(begin, end - begin); - - if (begin == end) - return; - - const UChar* position = begin; - while (position < end) { - const UChar* directiveBegin = position; - skipUntil<UChar>(position, end, ';'); - - String name, value; - if (parseDirective(directiveBegin, position, name, value)) { - ASSERT(!name.isEmpty()); - addDirective(name, value); - } - - ASSERT(position == end || *position == ';'); - skipExactly<UChar>(position, end, ';'); - } -} - -// directive = *WSP [ directive-name [ WSP directive-value ] ] -// directive-name = 1*( ALPHA / DIGIT / "-" ) -// directive-value = *( WSP / <VCHAR except ";"> ) -// -bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value) -{ - ASSERT(name.isEmpty()); - ASSERT(value.isEmpty()); - - const UChar* position = begin; - skipWhile<UChar, isASCIISpace>(position, end); - - // Empty directive (e.g. ";;;"). Exit early. - if (position == end) - return false; - - const UChar* nameBegin = position; - skipWhile<UChar, isDirectiveNameCharacter>(position, end); - - // The directive-name must be non-empty. - if (nameBegin == position) { - skipWhile<UChar, isNotASCIISpace>(position, end); - m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin)); - return false; - } - - name = String(nameBegin, position - nameBegin); - - if (position == end) - return true; - - if (!skipExactly<UChar, isASCIISpace>(position, end)) { - skipWhile<UChar, isNotASCIISpace>(position, end); - m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin)); - return false; - } - - skipWhile<UChar, isASCIISpace>(position, end); - - const UChar* valueBegin = position; - skipWhile<UChar, isDirectiveValueCharacter>(position, end); - - if (position != end) { - m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin)); - return false; - } - - // The directive-value may be empty. - if (valueBegin == position) - return true; - - value = String(valueBegin, position - valueBegin); - return true; -} - -void CSPDirectiveList::parseReportURI(const String& name, const String& value) -{ - if (!m_reportURIs.isEmpty()) { - m_policy->reportDuplicateDirective(name); - return; - } - - Vector<UChar> characters; - value.appendTo(characters); - - const UChar* position = characters.data(); - const UChar* end = position + characters.size(); - - while (position < end) { - skipWhile<UChar, isASCIISpace>(position, end); - - const UChar* urlBegin = position; - skipWhile<UChar, isNotASCIISpace>(position, end); - - if (urlBegin < position) { - String url = String(urlBegin, position - urlBegin); - m_reportURIs.append(m_policy->completeURL(url)); - } - } -} - - -template<class CSPDirectiveType> -void CSPDirectiveList::setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>& directive) -{ - if (directive) { - m_policy->reportDuplicateDirective(name); - return; - } - directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); -} - -void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy) -{ - if (m_haveSandboxPolicy) { - m_policy->reportDuplicateDirective(name); - return; - } - m_haveSandboxPolicy = true; - String invalidTokens; - m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidTokens)); - if (!invalidTokens.isNull()) - m_policy->reportInvalidSandboxFlags(invalidTokens); -} - -void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value) -{ - if (m_reflectedXSSDisposition != ReflectedXSSUnset) { - m_policy->reportDuplicateDirective(name); - m_reflectedXSSDisposition = ReflectedXSSInvalid; - return; - } - - if (value.isEmpty()) { - m_reflectedXSSDisposition = ReflectedXSSInvalid; - m_policy->reportInvalidReflectedXSS(value); - return; - } - - Vector<UChar> characters; - value.appendTo(characters); - - const UChar* position = characters.data(); - const UChar* end = position + characters.size(); - - skipWhile<UChar, isASCIISpace>(position, end); - const UChar* begin = position; - skipWhile<UChar, isNotASCIISpace>(position, end); - - // value1 - // ^ - if (equalIgnoringCase("allow", begin, position - begin)) { - m_reflectedXSSDisposition = AllowReflectedXSS; - } else if (equalIgnoringCase("filter", begin, position - begin)) { - m_reflectedXSSDisposition = FilterReflectedXSS; - } else if (equalIgnoringCase("block", begin, position - begin)) { - m_reflectedXSSDisposition = BlockReflectedXSS; - } else { - m_reflectedXSSDisposition = ReflectedXSSInvalid; - m_policy->reportInvalidReflectedXSS(value); - return; - } - - skipWhile<UChar, isASCIISpace>(position, end); - if (position == end && m_reflectedXSSDisposition != ReflectedXSSUnset) - return; - - // value1 value2 - // ^ - m_reflectedXSSDisposition = ReflectedXSSInvalid; - m_policy->reportInvalidReflectedXSS(value); -} - -void CSPDirectiveList::addDirective(const String& name, const String& value) -{ - ASSERT(!name.isEmpty()); - - if (equalIgnoringCase(name, defaultSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); - } else if (equalIgnoringCase(name, scriptSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); - m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed()); - } else if (equalIgnoringCase(name, objectSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_objectSrc); - } else if (equalIgnoringCase(name, frameSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_frameSrc); - } else if (equalIgnoringCase(name, imgSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_imgSrc); - } else if (equalIgnoringCase(name, styleSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_styleSrc); - } else if (equalIgnoringCase(name, fontSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_fontSrc); - } else if (equalIgnoringCase(name, mediaSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_mediaSrc); - } else if (equalIgnoringCase(name, connectSrc)) { - setCSPDirective<SourceListDirective>(name, value, m_connectSrc); - } else if (equalIgnoringCase(name, sandbox)) { - applySandboxPolicy(name, value); - } else if (equalIgnoringCase(name, reportURI)) { - parseReportURI(name, value); - } else if (m_policy->experimentalFeaturesEnabled()) { - if (equalIgnoringCase(name, baseURI)) - setCSPDirective<SourceListDirective>(name, value, m_baseURI); - else if (equalIgnoringCase(name, formAction)) - setCSPDirective<SourceListDirective>(name, value, m_formAction); - else if (equalIgnoringCase(name, pluginTypes)) - setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); - else if (equalIgnoringCase(name, reflectedXSS)) - parseReflectedXSS(name, value); - else - m_policy->reportUnsupportedDirective(name); - } else { - m_policy->reportUnsupportedDirective(name); - } -} - -ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContextClient* client) - : m_client(client) - , m_overrideInlineStyleAllowed(false) - , m_sourceHashAlgorithmsUsed(HashAlgorithmsNone) -{ -} - -ContentSecurityPolicy::~ContentSecurityPolicy() -{ -} - -void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other) -{ - ASSERT(m_policies.isEmpty()); - for (CSPDirectiveListVector::const_iterator iter = other->m_policies.begin(); iter != other->m_policies.end(); ++iter) - addPolicyFromHeaderValue((*iter)->header(), (*iter)->headerType()); -} - -void ContentSecurityPolicy::didReceiveHeaders(const ContentSecurityPolicyResponseHeaders& headers) -{ - if (!headers.contentSecurityPolicy().isEmpty()) - didReceiveHeader(headers.contentSecurityPolicy(), ContentSecurityPolicy::Enforce); - if (!headers.contentSecurityPolicyReportOnly().isEmpty()) - didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecurityPolicy::Report); - - // FIXME: Remove this reporting (and the 'xWebKitCSP*' methods) after the next release branch. - if (m_client->isDocument()) { - Document* document = static_cast<Document*>(m_client); - if (!headers.xWebKitCSP().isEmpty()) - UseCounter::countDeprecation(*document, UseCounter::PrefixedContentSecurityPolicy); - if (!headers.xWebKitCSPReportOnly().isEmpty()) - UseCounter::countDeprecation(*document, UseCounter::PrefixedContentSecurityPolicyReportOnly); - } -} - -void ContentSecurityPolicy::didReceiveHeader(const String& header, HeaderType type) -{ - addPolicyFromHeaderValue(header, type); -} - -void ContentSecurityPolicy::addPolicyFromHeaderValue(const String& header, HeaderType type) -{ - if (m_client->isDocument()) { - Document* document = static_cast<Document*>(m_client); - UseCounter::count(*document, getUseCounterType(type)); - } - - Vector<UChar> characters; - header.appendTo(characters); - - const UChar* begin = characters.data(); - const UChar* end = begin + characters.size(); - - // RFC2616, section 4.2 specifies that headers appearing multiple times can - // be combined with a comma. Walk the header string, and parse each comma - // separated chunk as a separate header. - const UChar* position = begin; - while (position < end) { - skipUntil<UChar>(position, end, ','); - - // header1,header2 OR header1 - // ^ ^ - OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin, position, type); - - // We disable 'eval()' even in the case of report-only policies, and rely on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread callback to determine whether the call should execute or not. - if (!policy->allowEval(0, SuppressReport)) - m_client->disableEval(policy->evalDisabledErrorMessage()); - - m_policies.append(policy.release()); - - // Skip the comma, and begin the next header from the current position. - ASSERT(position == end || *position == ','); - skipExactly<UChar>(position, end, ','); - begin = position; - } -} - -void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) -{ - m_overrideInlineStyleAllowed = value; -} - -const String& ContentSecurityPolicy::deprecatedHeader() const -{ - return m_policies.isEmpty() ? emptyString() : m_policies[0]->header(); -} - -ContentSecurityPolicy::HeaderType ContentSecurityPolicy::deprecatedHeaderType() const -{ - return m_policies.isEmpty() ? Enforce : m_policies[0]->headerType(); -} - -template<bool (CSPDirectiveList::*allowed)(ContentSecurityPolicy::ReportingStatus) const> -bool isAllowedByAll(const CSPDirectiveListVector& policies, ContentSecurityPolicy::ReportingStatus reportingStatus) -{ - for (size_t i = 0; i < policies.size(); ++i) { - if (!(policies[i].get()->*allowed)(reportingStatus)) - return false; - } - return true; -} - -template<bool (CSPDirectiveList::*allowed)(ScriptState* state, ContentSecurityPolicy::ReportingStatus) const> -bool isAllowedByAllWithState(const CSPDirectiveListVector& policies, ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) -{ - for (size_t i = 0; i < policies.size(); ++i) { - if (!(policies[i].get()->*allowed)(state, reportingStatus)) - return false; - } - return true; -} - -template<bool (CSPDirectiveList::*allowed)(const String&, const WTF::OrdinalNumber&, ContentSecurityPolicy::ReportingStatus) const> -bool isAllowedByAllWithContext(const CSPDirectiveListVector& policies, const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) -{ - for (size_t i = 0; i < policies.size(); ++i) { - if (!(policies[i].get()->*allowed)(contextURL, contextLine, reportingStatus)) - return false; - } - return true; -} - -template<bool (CSPDirectiveList::*allowed)(const String&) const> -bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const String& nonce) -{ - for (size_t i = 0; i < policies.size(); ++i) { - if (!(policies[i].get()->*allowed)(nonce)) - return false; - } - return true; -} - -template<bool (CSPDirectiveList::*allowed)(const SourceHashValue&) const> -bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, const SourceHashValue& hashValue) -{ - for (size_t i = 0; i < policies.size(); ++i) { - if (!(policies[i].get()->*allowed)(hashValue)) - return false; - } - return true; -} - -template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPolicy::ReportingStatus) const> -bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) -{ - if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) - return true; - - for (size_t i = 0; i < policies.size(); ++i) { - if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) - return false; - } - return true; -} - -bool ContentSecurityPolicy::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithContext<&CSPDirectiveList::allowJavaScriptURLs>(m_policies, contextURL, contextLine, reportingStatus); -} - -bool ContentSecurityPolicy::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineEventHandlers>(m_policies, contextURL, contextLine, reportingStatus); -} - -bool ContentSecurityPolicy::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineScript>(m_policies, contextURL, contextLine, reportingStatus); -} - -bool ContentSecurityPolicy::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - if (m_overrideInlineStyleAllowed) - return true; - return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus); -} - -bool ContentSecurityPolicy::allowEval(ScriptState* state, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithState<&CSPDirectiveList::allowEval>(m_policies, state, reportingStatus); -} - -String ContentSecurityPolicy::evalDisabledErrorMessage() const -{ - for (size_t i = 0; i < m_policies.size(); ++i) { - if (!m_policies[i]->allowEval(0, SuppressReport)) - return m_policies[i]->evalDisabledErrorMessage(); - } - return String(); -} - -bool ContentSecurityPolicy::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - for (size_t i = 0; i < m_policies.size(); ++i) { - if (!m_policies[i]->allowPluginType(type, typeAttribute, url, reportingStatus)) - return false; - } - return true; -} - -bool ContentSecurityPolicy::allowScriptFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const -{ - return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_policies, nonce); -} - -bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const -{ - return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policies, nonce); -} - -bool ContentSecurityPolicy::allowScriptHash(const String& source) const -{ - // TODO(jww) We don't currently have a WTF SHA256 implementation. Once we - // have that, we should implement a proper check for sha256 hash values here. - if (HashAlgorithmsSha1 & m_sourceHashAlgorithmsUsed) { - Vector<uint8_t, 20> digest; - SHA1 sourceSha1; - sourceSha1.addBytes(UTF8Encoding().normalizeAndEncode(source, WTF::EntitiesForUnencodables)); - sourceSha1.computeHash(digest); - - if (isAllowedByAllWithHash<&CSPDirectiveList::allowScriptHash>(m_policies, SourceHashValue(HashAlgorithmsSha1, Vector<uint8_t>(digest)))) - return true; - } - - return false; -} - -void ContentSecurityPolicy::usesScriptHashAlgorithms(uint8_t algorithms) -{ - m_sourceHashAlgorithmsUsed |= algorithms; -} - -bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowImageFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowImageFromSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowStyleFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowStyleFromSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowFontFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowFontFromSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowMediaFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowMediaFromSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowConnectToSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowConnectToSource>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowFormAction(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowFormAction>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::allowBaseURI(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const -{ - return isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>(m_policies, url, reportingStatus); -} - -bool ContentSecurityPolicy::isActive() const -{ - return !m_policies.isEmpty(); -} - -ReflectedXSSDisposition ContentSecurityPolicy::reflectedXSSDisposition() const -{ - ReflectedXSSDisposition disposition = ReflectedXSSUnset; - for (size_t i = 0; i < m_policies.size(); ++i) { - if (m_policies[i]->reflectedXSSDisposition() > disposition) - disposition = std::max(disposition, m_policies[i]->reflectedXSSDisposition()); - } - return disposition; -} - -void ContentSecurityPolicy::gatherReportURIs(DOMStringList& list) const -{ - for (size_t i = 0; i < m_policies.size(); ++i) - m_policies[i]->gatherReportURIs(list); -} - -SecurityOrigin* ContentSecurityPolicy::securityOrigin() const -{ - return m_client->securityContext().securityOrigin(); -} - -const KURL ContentSecurityPolicy::url() const -{ - return m_client->contextURL(); -} - -KURL ContentSecurityPolicy::completeURL(const String& url) const -{ - return m_client->contextCompleteURL(url); -} - -void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const -{ - if (m_client->isDocument()) - static_cast<Document*>(m_client)->enforceSandboxFlags(mask); -} - -static String stripURLForUseInReport(Document* document, const KURL& url) -{ - if (!url.isValid()) - return String(); - if (!url.isHierarchical() || url.protocolIs("file")) - return url.protocol(); - return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsReferrer() : SecurityOrigin::create(url)->toString(); -} - -static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventInit& init, Document* document, const String& directiveText, const String& effectiveDirective, const KURL& blockedURL, const String& header) -{ - init.documentURI = document->url().string(); - init.referrer = document->referrer(); - init.blockedURI = stripURLForUseInReport(document, blockedURL); - init.violatedDirective = directiveText; - init.effectiveDirective = effectiveDirective; - init.originalPolicy = header; - init.sourceFile = String(); - init.lineNumber = 0; - init.columnNumber = 0; - init.statusCode = 0; - - if (!SecurityOrigin::isSecure(document->url()) && document->loader()) - init.statusCode = document->loader()->response().httpStatusCode(); - - RefPtr<ScriptCallStack> stack = createScriptCallStack(1, false); - if (!stack) - return; - - const ScriptCallFrame& callFrame = stack->at(0); - - if (callFrame.lineNumber()) { - KURL source = KURL(ParsedURLString, callFrame.sourceURL()); - init.sourceFile = stripURLForUseInReport(document, source); - init.lineNumber = callFrame.lineNumber(); - init.columnNumber = callFrame.columnNumber(); - } -} - -void ContentSecurityPolicy::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const Vector<KURL>& reportURIs, const String& header) -{ - // FIXME: Support sending reports from worker. - if (!m_client->isDocument()) - return; - - Document* document = static_cast<Document*>(m_client); - Frame* frame = document->frame(); - if (!frame) - return; - - SecurityPolicyViolationEventInit violationData; - gatherSecurityPolicyViolationEventData(violationData, document, directiveText, effectiveDirective, blockedURL, header); - - if (experimentalFeaturesEnabled()) - frame->domWindow()->enqueueDocumentEvent(SecurityPolicyViolationEvent::create(EventTypeNames::securitypolicyviolation, violationData)); - - if (reportURIs.isEmpty()) - return; - - // We need to be careful here when deciding what information to send to the - // report-uri. Currently, we send only the current document's URL and the - // directive that was violated. The document's URL is safe to send because - // it's the document itself that's requesting that it be sent. You could - // make an argument that we shouldn't send HTTPS document URLs to HTTP - // report-uris (for the same reasons that we supress the Referer in that - // case), but the Referer is sent implicitly whereas this request is only - // sent explicitly. As for which directive was violated, that's pretty - // harmless information. - - RefPtr<JSONObject> cspReport = JSONObject::create(); - cspReport->setString("document-uri", violationData.documentURI); - cspReport->setString("referrer", violationData.referrer); - cspReport->setString("violated-directive", violationData.violatedDirective); - if (experimentalFeaturesEnabled()) - cspReport->setString("effective-directive", violationData.effectiveDirective); - cspReport->setString("original-policy", violationData.originalPolicy); - cspReport->setString("blocked-uri", violationData.blockedURI); - if (!violationData.sourceFile.isEmpty() && violationData.lineNumber) { - cspReport->setString("source-file", violationData.sourceFile); - cspReport->setNumber("line-number", violationData.lineNumber); - cspReport->setNumber("column-number", violationData.columnNumber); - } - cspReport->setNumber("status-code", violationData.statusCode); - - RefPtr<JSONObject> reportObject = JSONObject::create(); - reportObject->setObject("csp-report", cspReport.release()); - String stringifiedReport = reportObject->toJSONString(); - - if (!shouldSendViolationReport(stringifiedReport)) - return; - - RefPtr<FormData> report = FormData::create(stringifiedReport.utf8()); - - for (size_t i = 0; i < reportURIs.size(); ++i) - PingLoader::sendViolationReport(frame, reportURIs[i], report, PingLoader::ContentSecurityPolicyViolationReport); - - didSendViolationReport(stringifiedReport); -} - -void ContentSecurityPolicy::reportUnsupportedDirective(const String& name) const -{ - DEFINE_STATIC_LOCAL(String, allow, ("allow")); - DEFINE_STATIC_LOCAL(String, options, ("options")); - DEFINE_STATIC_LOCAL(String, policyURI, ("policy-uri")); - DEFINE_STATIC_LOCAL(String, allowMessage, ("The 'allow' directive has been replaced with 'default-src'. Please use that directive instead, as 'allow' has no effect.")); - DEFINE_STATIC_LOCAL(String, optionsMessage, ("The 'options' directive has been replaced with 'unsafe-inline' and 'unsafe-eval' source expressions for the 'script-src' and 'style-src' directives. Please use those directives instead, as 'options' has no effect.")); - DEFINE_STATIC_LOCAL(String, policyURIMessage, ("The 'policy-uri' directive has been removed from the specification. Please specify a complete policy via the Content-Security-Policy header.")); - - String message = "Unrecognized Content-Security-Policy directive '" + name + "'.\n"; - if (equalIgnoringCase(name, allow)) - message = allowMessage; - else if (equalIgnoringCase(name, options)) - message = optionsMessage; - else if (equalIgnoringCase(name, policyURI)) - message = policyURIMessage; - - logToConsole(message); -} - -void ContentSecurityPolicy::reportDirectiveAsSourceExpression(const String& directiveName, const String& sourceExpression) const -{ - String message = "The Content Security Policy directive '" + directiveName + "' contains '" + sourceExpression + "' as a source expression. Did you mean '" + directiveName + " ...; " + sourceExpression + "...' (note the semicolon)?"; - logToConsole(message); -} - -void ContentSecurityPolicy::reportDuplicateDirective(const String& name) const -{ - String message = "Ignoring duplicate Content-Security-Policy directive '" + name + "'.\n"; - logToConsole(message); -} - -void ContentSecurityPolicy::reportInvalidPluginTypes(const String& pluginType) const -{ - String message; - if (pluginType.isNull()) - message = "'plugin-types' Content Security Policy directive is empty; all plugins will be blocked.\n"; - else - message = "Invalid plugin type in 'plugin-types' Content Security Policy directive: '" + pluginType + "'.\n"; - logToConsole(message); -} - -void ContentSecurityPolicy::reportInvalidSandboxFlags(const String& invalidFlags) const -{ - logToConsole("Error while parsing the 'sandbox' Content Security Policy directive: " + invalidFlags); -} - -void ContentSecurityPolicy::reportInvalidReflectedXSS(const String& invalidValue) const -{ - logToConsole("The 'reflected-xss' Content Security Policy directive has the invalid value \"" + invalidValue + "\". Valid values are \"allow\", \"filter\", and \"block\"."); -} - -void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter(const String& directiveName, const String& value) const -{ - String message = "The value for Content Security Policy directive '" + directiveName + "' contains an invalid character: '" + value + "'. Non-whitespace characters outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC 3986, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1."; - logToConsole(message); -} - -void ContentSecurityPolicy::reportInvalidPathCharacter(const String& directiveName, const String& value, const char invalidChar) const -{ - ASSERT(invalidChar == '#' || invalidChar == '?'); - - String ignoring = "The fragment identifier, including the '#', will be ignored."; - if (invalidChar == '?') - ignoring = "The query component, including the '?', will be ignored."; - String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring; - logToConsole(message); -} - -void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiveName, const String& source) const -{ - String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ignored."; - if (equalIgnoringCase(source, "'none'")) - message = message + " Note that 'none' has no effect unless it is the only expression in the source list."; - logToConsole(message); -} - -void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const -{ - logToConsole("The Content Security Policy '" + policy + "' was delivered in report-only mode, but does not specify a 'report-uri'; the policy will have no effect. Please either add a 'report-uri' directive, or deliver the policy via the 'Content-Security-Policy' header."); -} - -void ContentSecurityPolicy::logToConsole(const String& message) const -{ - m_client->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message); -} - -void ContentSecurityPolicy::reportBlockedScriptExecutionToInspector(const String& directiveText) const -{ - m_client->reportBlockedScriptExecutionToInspector(directiveText); -} - -bool ContentSecurityPolicy::experimentalFeaturesEnabled() const -{ - return RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnabled(); -} - -bool ContentSecurityPolicy::shouldBypassMainWorld(ExecutionContext* context) -{ - if (context && context->isDocument()) { - Document* document = toDocument(context); - if (document->frame()) - return document->frame()->script().shouldBypassMainWorldContentSecurityPolicy(); - } - return false; -} - -bool ContentSecurityPolicy::shouldSendViolationReport(const String& report) const -{ - // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report. - return !m_violationReportsSent.contains(report.impl()->hash()); -} - -void ContentSecurityPolicy::didSendViolationReport(const String& report) -{ - m_violationReportsSent.add(report.impl()->hash()); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicyResponseHeaders.cpp b/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicyResponseHeaders.cpp deleted file mode 100644 index 1b58eac6c72..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicyResponseHeaders.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 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 GOOGLE 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 "core/frame/ContentSecurityPolicyResponseHeaders.h" - -#include "platform/network/ResourceResponse.h" - -namespace WebCore { - -ContentSecurityPolicyResponseHeaders::ContentSecurityPolicyResponseHeaders(const ResourceResponse& response) - : m_contentSecurityPolicy(response.httpHeaderField("Content-Security-Policy")) - , m_contentSecurityPolicyReportOnly(response.httpHeaderField("Content-Security-Policy-Report-Only")) - , m_xWebKitCSP(response.httpHeaderField("X-WebKit-CSP")) - , m_xWebKitCSPReportOnly(response.httpHeaderField("X-WebKit-CSP-Report-Only")) -{ -} - -} diff --git a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicyResponseHeaders.h b/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicyResponseHeaders.h deleted file mode 100644 index d5076d4a062..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicyResponseHeaders.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 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 GOOGLE 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 ContentSecurityPolicyResponseHeaders_h -#define ContentSecurityPolicyResponseHeaders_h - -#include "wtf/text/WTFString.h" - -namespace WebCore { - -class ResourceResponse; - -class ContentSecurityPolicyResponseHeaders { -public: - ContentSecurityPolicyResponseHeaders() { } - explicit ContentSecurityPolicyResponseHeaders(const ResourceResponse&); - - const String& contentSecurityPolicy() const { return m_contentSecurityPolicy; } - const String& contentSecurityPolicyReportOnly() const { return m_contentSecurityPolicyReportOnly; } - const String& xWebKitCSP() const { return m_xWebKitCSP; } - const String& xWebKitCSPReportOnly() const { return m_xWebKitCSPReportOnly; } - -private: - String m_contentSecurityPolicy; - String m_contentSecurityPolicyReportOnly; - String m_xWebKitCSP; - String m_xWebKitCSPReportOnly; -}; - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMPoint.h b/chromium/third_party/WebKit/Source/core/frame/DOMPoint.h index ae8478b25af..bbf2e5bbeff 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMPoint.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMPoint.h @@ -27,20 +27,21 @@ #define DOMPoint_h #include "bindings/v8/ScriptWrappable.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class DOMPoint : public RefCounted<DOMPoint>, public ScriptWrappable { +class DOMPoint FINAL : public RefCountedWillBeGarbageCollectedFinalized<DOMPoint>, public ScriptWrappable { public: - static PassRefPtr<DOMPoint> create() + static PassRefPtrWillBeRawPtr<DOMPoint> create() { - return adoptRef(new DOMPoint()); + return adoptRefWillBeNoop(new DOMPoint()); } - static PassRefPtr<DOMPoint> create(float x, float y) + static PassRefPtrWillBeRawPtr<DOMPoint> create(float x, float y) { - return adoptRef(new DOMPoint(x, y)); + return adoptRefWillBeNoop(new DOMPoint(x, y)); } float x() const { return m_x; } @@ -49,6 +50,8 @@ public: void setX(float x) { m_x = x; } void setY(float y) { m_y = y; } + void trace(Visitor*) { } + private: DOMPoint(float x = 0, float y = 0) : m_x(x) diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMSecurityPolicy.cpp b/chromium/third_party/WebKit/Source/core/frame/DOMSecurityPolicy.cpp deleted file mode 100644 index c60cdadc168..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/DOMSecurityPolicy.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2012 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 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 GOOGLE 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 "core/frame/DOMSecurityPolicy.h" - -#include "core/dom/DOMStringList.h" -#include "core/dom/ExecutionContext.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "wtf/text/TextPosition.h" - -namespace WebCore { - -namespace { - -bool isPolicyActiveInContext(ExecutionContext* context) -{ - // If the ExecutionContext has been destroyed, there's no active policy. - if (!context) - return false; - - return context->contentSecurityPolicy()->isActive(); -} - -template<bool (ContentSecurityPolicy::*allowWithType)(const String&, const String&, const KURL&, ContentSecurityPolicy::ReportingStatus) const> -bool isAllowedWithType(ExecutionContext* context, const String& type) -{ - if (!isPolicyActiveInContext(context)) - return true; - - return (context->contentSecurityPolicy()->*allowWithType)(type, type, KURL(), ContentSecurityPolicy::SuppressReport); -} - -template<bool (ContentSecurityPolicy::*allowWithURL)(const KURL&, ContentSecurityPolicy::ReportingStatus) const> -bool isAllowedWithURL(ExecutionContext* context, const String& url) -{ - if (!isPolicyActiveInContext(context)) - return true; - - KURL parsedURL = context->completeURL(url); - if (!parsedURL.isValid()) - return false; // FIXME: Figure out how to throw a JavaScript error. - - return (context->contentSecurityPolicy()->*allowWithURL)(parsedURL, ContentSecurityPolicy::SuppressReport); -} - -template<bool (ContentSecurityPolicy::*allowWithContext)(const String&, const WTF::OrdinalNumber&, ContentSecurityPolicy::ReportingStatus) const> -bool isAllowed(ExecutionContext* context) -{ - if (!isPolicyActiveInContext(context)) - return true; - - return (context->contentSecurityPolicy()->*allowWithContext)(String(), WTF::OrdinalNumber::beforeFirst(), ContentSecurityPolicy::SuppressReport); -} - -} // namespace - -DOMSecurityPolicy::DOMSecurityPolicy(ExecutionContext* context) - : ContextLifecycleObserver(context) -{ - ScriptWrappable::init(this); -} - -DOMSecurityPolicy::~DOMSecurityPolicy() -{ -} - -bool DOMSecurityPolicy::isActive() const -{ - return isPolicyActiveInContext(executionContext()); -} - -PassRefPtr<DOMStringList> DOMSecurityPolicy::reportURIs() const -{ - RefPtr<DOMStringList> result = DOMStringList::create(); - - if (isActive()) - executionContext()->contentSecurityPolicy()->gatherReportURIs(*result.get()); - - return result.release(); -} - -bool DOMSecurityPolicy::allowsInlineScript() const -{ - return isAllowed<&ContentSecurityPolicy::allowInlineScript>(executionContext()); -} - -bool DOMSecurityPolicy::allowsInlineStyle() const -{ - return isAllowed<&ContentSecurityPolicy::allowInlineStyle>(executionContext()); -} - -bool DOMSecurityPolicy::allowsEval() const -{ - if (!isActive()) - return true; - - return executionContext()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport); -} - - -bool DOMSecurityPolicy::allowsConnectionTo(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowConnectToSource>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsFontFrom(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowFontFromSource>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsFormAction(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowFormAction>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsFrameFrom(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowChildFrameFromSource>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsImageFrom(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowImageFromSource>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsMediaFrom(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowMediaFromSource>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsObjectFrom(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowObjectFromSource>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsPluginType(const String& type) const -{ - return isAllowedWithType<&ContentSecurityPolicy::allowPluginType>(executionContext(), type); -} - -bool DOMSecurityPolicy::allowsScriptFrom(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowScriptFromSource>(executionContext(), url); -} - -bool DOMSecurityPolicy::allowsStyleFrom(const String& url) const -{ - return isAllowedWithURL<&ContentSecurityPolicy::allowStyleFromSource>(executionContext(), url); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMSecurityPolicy.h b/chromium/third_party/WebKit/Source/core/frame/DOMSecurityPolicy.h deleted file mode 100644 index 78813013993..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/DOMSecurityPolicy.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 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 GOOGLE 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 DOMSecurityPolicy_h -#define DOMSecurityPolicy_h - -#include "bindings/v8/ScriptWrappable.h" -#include "core/dom/ContextLifecycleObserver.h" -#include "wtf/RefCounted.h" -#include "wtf/text/WTFString.h" - -namespace WebCore { - -class ContentSecurityPolicy; -class DOMStringList; -class Frame; - -class DOMSecurityPolicy : public RefCounted<DOMSecurityPolicy>, public ScriptWrappable, public ContextLifecycleObserver { -public: - static PassRefPtr<DOMSecurityPolicy> create(ExecutionContext* context) - { - return adoptRef(new DOMSecurityPolicy(context)); - } - ~DOMSecurityPolicy(); - - bool isActive() const; - PassRefPtr<DOMStringList> reportURIs() const; - - bool allowsInlineScript() const; - bool allowsInlineStyle() const; - bool allowsEval() const; - - bool allowsConnectionTo(const String& url) const; - bool allowsFontFrom(const String& url) const; - bool allowsFormAction(const String& url) const; - bool allowsFrameFrom(const String& url) const; - bool allowsImageFrom(const String& url) const; - bool allowsMediaFrom(const String& url) const; - bool allowsObjectFrom(const String& url) const; - bool allowsPluginType(const String& type) const; - bool allowsScriptFrom(const String& url) const; - bool allowsStyleFrom(const String& url) const; - -private: - explicit DOMSecurityPolicy(ExecutionContext*); -}; - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMTimer.cpp b/chromium/third_party/WebKit/Source/core/frame/DOMTimer.cpp index a41845ddc25..4d9b76a27ff 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMTimer.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/DOMTimer.cpp @@ -29,10 +29,10 @@ #include "core/dom/ExecutionContext.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" +#include "platform/TraceEvent.h" #include "wtf/CurrentTime.h" -using namespace std; - namespace WebCore { static const int maxIntervalForUserGestureForwarding = 1000; // One second matches Gecko. @@ -70,6 +70,9 @@ double DOMTimer::visiblePageAlignmentInterval() int DOMTimer::install(ExecutionContext* context, PassOwnPtr<ScheduledAction> action, int timeout, bool singleShot) { int timeoutID = context->installNewTimeout(action, timeout, singleShot); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "TimerInstall", "data", InspectorTimerInstallEvent::data(context, timeoutID, timeout, singleShot)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didInstallTimer(context, timeoutID, timeout, singleShot); return timeoutID; } @@ -77,6 +80,9 @@ int DOMTimer::install(ExecutionContext* context, PassOwnPtr<ScheduledAction> act void DOMTimer::removeByID(ExecutionContext* context, int timeoutID) { context->removeTimeoutByID(timeoutID); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "TimerRemove", "data", InspectorTimerRemoveEvent::data(context, timeoutID)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didRemoveTimer(context, timeoutID); } @@ -90,13 +96,13 @@ DOMTimer::DOMTimer(ExecutionContext* context, PassOwnPtr<ScheduledAction> action if (shouldForwardUserGesture(interval, m_nestingLevel)) m_userGestureToken = UserGestureIndicator::currentToken(); - double intervalMilliseconds = max(oneMillisecond, interval * oneMillisecond); + double intervalMilliseconds = std::max(oneMillisecond, interval * oneMillisecond); if (intervalMilliseconds < minimumInterval && m_nestingLevel >= maxTimerNestingLevel) intervalMilliseconds = minimumInterval; if (singleShot) - startOneShot(intervalMilliseconds); + startOneShot(intervalMilliseconds, FROM_HERE); else - startRepeating(intervalMilliseconds); + startRepeating(intervalMilliseconds, FROM_HERE); } DOMTimer::~DOMTimer() @@ -116,6 +122,8 @@ void DOMTimer::fired() // Only the first execution of a multi-shot timer should get an affirmative user gesture indicator. UserGestureIndicator gestureIndicator(m_userGestureToken.release()); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "TimerFire", "data", InspectorTimerFireEvent::data(context, m_timeoutID)); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutID); // Simple case for non-one-shot timers. @@ -143,6 +151,7 @@ void DOMTimer::fired() action->execute(context); InspectorInstrumentation::didFireTimer(cookie); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); timerNestingLevel = 0; } diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMTimer.h b/chromium/third_party/WebKit/Source/core/frame/DOMTimer.h index 95c094b0605..19c22d22c78 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMTimer.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMTimer.h @@ -38,7 +38,7 @@ namespace WebCore { class ExecutionContext; -class DOMTimer : public SuspendableTimer { +class DOMTimer FINAL : public SuspendableTimer { public: // Creates a new timer owned by the ExecutionContext, starts it and returns its ID. static int install(ExecutionContext*, PassOwnPtr<ScheduledAction>, int timeout, bool singleShot); @@ -66,10 +66,10 @@ private: } DOMTimer(ExecutionContext*, PassOwnPtr<ScheduledAction>, int interval, bool singleShot, int timeoutID); - virtual void fired(); + virtual void fired() OVERRIDE; // Retuns timer fire time rounded to the next multiple of timer alignment interval. - virtual double alignedFireTime(double) const; + virtual double alignedFireTime(double) const OVERRIDE; int m_timeoutID; int m_nestingLevel; diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.cpp b/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.cpp index 2f43d507a77..81e3a4be945 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.cpp @@ -40,9 +40,7 @@ namespace WebCore { -namespace DOMWindowBase64 { - -String btoa(void*, const String& stringToEncode, ExceptionState& exceptionState) +String DOMWindowBase64::btoa(const String& stringToEncode, ExceptionState& exceptionState) { if (stringToEncode.isNull()) return String(); @@ -55,7 +53,7 @@ String btoa(void*, const String& stringToEncode, ExceptionState& exceptionState) return base64Encode(stringToEncode.latin1()); } -String atob(void*, const String& encodedString, ExceptionState& exceptionState) +String DOMWindowBase64::atob(const String& encodedString, ExceptionState& exceptionState) { if (encodedString.isNull()) return String(); @@ -73,6 +71,4 @@ String atob(void*, const String& encodedString, ExceptionState& exceptionState) return String(out.data(), out.size()); } -} // namespace DOMWindowBase64 - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.h b/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.h index 21001e0bf62..55ccfb71f5d 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowBase64.h @@ -39,10 +39,11 @@ namespace WebCore { class ExceptionState; -namespace DOMWindowBase64 { -String btoa(void*, const String& stringToEncode, ExceptionState&); -String atob(void*, const String& encodedString, ExceptionState&); -} +class DOMWindowBase64 { +public: + String btoa(const String& stringToEncode, ExceptionState&); + String atob(const String& encodedString, ExceptionState&); +}; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h b/chromium/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h index bf897717772..fbacb01a7f6 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowEventHandlers.h @@ -37,13 +37,13 @@ namespace WebCore { namespace DOMWindowEventHandlers { DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(beforeunload); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(hashchange); +DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(languagechange); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(message); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(offline); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(online); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(pagehide); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(pageshow); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(popstate); -DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(resize); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(storage); DEFINE_STATIC_WINDOW_ATTRIBUTE_EVENT_LISTENER(unload); } diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.cpp b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.cpp index 92fafea2796..e503f37f780 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.cpp @@ -29,8 +29,8 @@ namespace WebCore { -DOMWindowLifecycleNotifier::DOMWindowLifecycleNotifier(DOMWindow* context) - : LifecycleNotifier<DOMWindow>(context) +DOMWindowLifecycleNotifier::DOMWindowLifecycleNotifier(LocalDOMWindow* context) + : LifecycleNotifier<LocalDOMWindow>(context) { } @@ -41,7 +41,7 @@ void DOMWindowLifecycleNotifier::addObserver(DOMWindowLifecycleNotifier::Observe m_windowObservers.add(static_cast<DOMWindowLifecycleObserver*>(observer)); } - LifecycleNotifier<DOMWindow>::addObserver(observer); + LifecycleNotifier<LocalDOMWindow>::addObserver(observer); } void DOMWindowLifecycleNotifier::removeObserver(DOMWindowLifecycleNotifier::Observer* observer) @@ -51,29 +51,29 @@ void DOMWindowLifecycleNotifier::removeObserver(DOMWindowLifecycleNotifier::Obse m_windowObservers.remove(static_cast<DOMWindowLifecycleObserver*>(observer)); } - LifecycleNotifier<DOMWindow>::removeObserver(observer); + LifecycleNotifier<LocalDOMWindow>::removeObserver(observer); } -PassOwnPtr<DOMWindowLifecycleNotifier> DOMWindowLifecycleNotifier::create(DOMWindow* context) +PassOwnPtr<DOMWindowLifecycleNotifier> DOMWindowLifecycleNotifier::create(LocalDOMWindow* context) { return adoptPtr(new DOMWindowLifecycleNotifier(context)); } -void DOMWindowLifecycleNotifier::notifyAddEventListener(DOMWindow* window, const AtomicString& eventType) +void DOMWindowLifecycleNotifier::notifyAddEventListener(LocalDOMWindow* window, const AtomicString& eventType) { TemporaryChange<IterationType> scope(this->m_iterating, IteratingOverDOMWindowObservers); for (DOMWindowObserverSet::iterator it = m_windowObservers.begin(); it != m_windowObservers.end(); ++it) (*it)->didAddEventListener(window, eventType); } -void DOMWindowLifecycleNotifier::notifyRemoveEventListener(DOMWindow* window, const AtomicString& eventType) +void DOMWindowLifecycleNotifier::notifyRemoveEventListener(LocalDOMWindow* window, const AtomicString& eventType) { TemporaryChange<IterationType> scope(this->m_iterating, IteratingOverDOMWindowObservers); for (DOMWindowObserverSet::iterator it = m_windowObservers.begin(); it != m_windowObservers.end(); ++it) (*it)->didRemoveEventListener(window, eventType); } -void DOMWindowLifecycleNotifier::notifyRemoveAllEventListeners(DOMWindow* window) +void DOMWindowLifecycleNotifier::notifyRemoveAllEventListeners(LocalDOMWindow* window) { TemporaryChange<IterationType> scope(this->m_iterating, IteratingOverDOMWindowObservers); for (DOMWindowObserverSet::iterator it = m_windowObservers.begin(); it != m_windowObservers.end(); ++it) diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.h b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.h index 7db48593e52..e652e99d9e5 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleNotifier.h @@ -34,21 +34,21 @@ namespace WebCore { -class DOMWindow; +class LocalDOMWindow; -class DOMWindowLifecycleNotifier : public LifecycleNotifier<DOMWindow> { +class DOMWindowLifecycleNotifier FINAL : public LifecycleNotifier<LocalDOMWindow> { public: - static PassOwnPtr<DOMWindowLifecycleNotifier> create(DOMWindow*); + static PassOwnPtr<DOMWindowLifecycleNotifier> create(LocalDOMWindow*); - void notifyAddEventListener(DOMWindow*, const AtomicString& eventType); - void notifyRemoveEventListener(DOMWindow*, const AtomicString& eventType); - void notifyRemoveAllEventListeners(DOMWindow*); + void notifyAddEventListener(LocalDOMWindow*, const AtomicString& eventType); + void notifyRemoveEventListener(LocalDOMWindow*, const AtomicString& eventType); + void notifyRemoveAllEventListeners(LocalDOMWindow*); virtual void addObserver(Observer*) OVERRIDE; virtual void removeObserver(Observer*) OVERRIDE; private: - explicit DOMWindowLifecycleNotifier(DOMWindow*); + explicit DOMWindowLifecycleNotifier(LocalDOMWindow*); typedef HashSet<DOMWindowLifecycleObserver*> DOMWindowObserverSet; DOMWindowObserverSet m_windowObservers; diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.cpp b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.cpp index aa4f97b8661..8f08ea0fdf0 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.cpp @@ -27,22 +27,22 @@ #include "config.h" #include "core/frame/DOMWindowLifecycleObserver.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" namespace WebCore { -template<> void observerContext(DOMWindow* context, LifecycleObserver<DOMWindow>* observer) +template<> void observerContext(LocalDOMWindow* context, LifecycleObserver<LocalDOMWindow>* observer) { context->wasObservedBy(observer); } -template<> void unobserverContext(DOMWindow* context, LifecycleObserver<DOMWindow>* observer) +template<> void unobserverContext(LocalDOMWindow* context, LifecycleObserver<LocalDOMWindow>* observer) { context->wasUnobservedBy(observer); } -DOMWindowLifecycleObserver::DOMWindowLifecycleObserver(DOMWindow* window) - : LifecycleObserver<DOMWindow>(window, DOMWindowLifecycleObserverType) +DOMWindowLifecycleObserver::DOMWindowLifecycleObserver(LocalDOMWindow* window) + : LifecycleObserver<LocalDOMWindow>(window, DOMWindowLifecycleObserverType) { } @@ -50,9 +50,9 @@ DOMWindowLifecycleObserver::~DOMWindowLifecycleObserver() { } -DOMWindow* DOMWindowLifecycleObserver::window() const +LocalDOMWindow* DOMWindowLifecycleObserver::window() const { - return static_cast<DOMWindow*>(lifecycleContext()); + return static_cast<LocalDOMWindow*>(lifecycleContext()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.h b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.h index de49449697a..eb7b7b071ef 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowLifecycleObserver.h @@ -32,21 +32,21 @@ namespace WebCore { -class DOMWindow; +class LocalDOMWindow; -template<> void observerContext(DOMWindow*, LifecycleObserver<DOMWindow>*); -template<> void unobserverContext(DOMWindow*, LifecycleObserver<DOMWindow>*); +template<> void observerContext(LocalDOMWindow*, LifecycleObserver<LocalDOMWindow>*); +template<> void unobserverContext(LocalDOMWindow*, LifecycleObserver<LocalDOMWindow>*); -class DOMWindowLifecycleObserver : public LifecycleObserver<DOMWindow> { +class DOMWindowLifecycleObserver : public LifecycleObserver<LocalDOMWindow> { public: - explicit DOMWindowLifecycleObserver(DOMWindow*); + explicit DOMWindowLifecycleObserver(LocalDOMWindow*); virtual ~DOMWindowLifecycleObserver(); - DOMWindow* window() const; + LocalDOMWindow* window() const; - virtual void didAddEventListener(DOMWindow*, const AtomicString&) { } - virtual void didRemoveEventListener(DOMWindow*, const AtomicString&) { } - virtual void didRemoveAllEventListeners(DOMWindow*) { } + virtual void didAddEventListener(LocalDOMWindow*, const AtomicString&) { } + virtual void didRemoveEventListener(LocalDOMWindow*, const AtomicString&) { } + virtual void didRemoveAllEventListeners(LocalDOMWindow*) { } }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp b/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp index 6649a2f7947..785b61519eb 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp @@ -28,12 +28,12 @@ #include "core/frame/DOMWindowProperty.h" #include "core/dom/Document.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -DOMWindowProperty::DOMWindowProperty(Frame* frame) +DOMWindowProperty::DOMWindowProperty(LocalFrame* frame) : m_frame(frame) , m_associatedDOMWindow(0) { @@ -57,12 +57,12 @@ DOMWindowProperty::~DOMWindowProperty() void DOMWindowProperty::willDestroyGlobalObjectInFrame() { - // If the property is getting this callback it must have been created with a Frame/DOMWindow and it should still have them. + // If the property is getting this callback it must have been created with a LocalFrame/LocalDOMWindow and it should still have them. ASSERT(m_frame); ASSERT(m_associatedDOMWindow); - // DOMWindowProperty lifetime isn't tied directly to the DOMWindow itself so it is important that it unregister - // itself from any DOMWindow it is associated with if that DOMWindow is going away. + // DOMWindowProperty lifetime isn't tied directly to the LocalDOMWindow itself so it is important that it unregister + // itself from any LocalDOMWindow it is associated with if that LocalDOMWindow is going away. if (m_associatedDOMWindow) m_associatedDOMWindow->unregisterProperty(this); m_associatedDOMWindow = 0; @@ -71,7 +71,7 @@ void DOMWindowProperty::willDestroyGlobalObjectInFrame() void DOMWindowProperty::willDetachGlobalObjectFromFrame() { - // If the property is getting this callback it must have been created with a Frame/DOMWindow and it should still have them. + // If the property is getting this callback it must have been created with a LocalFrame/LocalDOMWindow and it should still have them. ASSERT(m_frame); ASSERT(m_associatedDOMWindow); } diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.h b/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.h index 3a4645c9081..495d715a7ac 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowProperty.h @@ -28,23 +28,23 @@ namespace WebCore { -class DOMWindow; -class Frame; +class LocalDOMWindow; +class LocalFrame; class DOMWindowProperty { public: - explicit DOMWindowProperty(Frame*); + explicit DOMWindowProperty(LocalFrame*); virtual void willDestroyGlobalObjectInFrame(); virtual void willDetachGlobalObjectFromFrame(); - Frame* frame() const { return m_frame; } + LocalFrame* frame() const { return m_frame; } protected: virtual ~DOMWindowProperty(); - Frame* m_frame; - DOMWindow* m_associatedDOMWindow; + LocalFrame* m_frame; + LocalDOMWindow* m_associatedDOMWindow; }; } diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.cpp b/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.cpp index b0e082c27ed..af3e06b94fb 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.cpp @@ -40,25 +40,25 @@ namespace WebCore { namespace DOMWindowTimers { -int setTimeout(EventTarget* eventTarget, PassOwnPtr<ScheduledAction> action, int timeout) +int setTimeout(EventTarget& eventTarget, PassOwnPtr<ScheduledAction> action, int timeout) { - return DOMTimer::install(eventTarget->executionContext(), action, timeout, true); + return DOMTimer::install(eventTarget.executionContext(), action, timeout, true); } -int setInterval(EventTarget* eventTarget, PassOwnPtr<ScheduledAction> action, int timeout) +int setInterval(EventTarget& eventTarget, PassOwnPtr<ScheduledAction> action, int timeout) { - return DOMTimer::install(eventTarget->executionContext(), action, timeout, false); + return DOMTimer::install(eventTarget.executionContext(), action, timeout, false); } -void clearTimeout(EventTarget* eventTarget, int timeoutID) +void clearTimeout(EventTarget& eventTarget, int timeoutID) { - if (ExecutionContext* context = eventTarget->executionContext()) + if (ExecutionContext* context = eventTarget.executionContext()) DOMTimer::removeByID(context, timeoutID); } -void clearInterval(EventTarget* eventTarget, int timeoutID) +void clearInterval(EventTarget& eventTarget, int timeoutID) { - if (ExecutionContext* context = eventTarget->executionContext()) + if (ExecutionContext* context = eventTarget.executionContext()) DOMTimer::removeByID(context, timeoutID); } diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.h b/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.h index 2a28f81810c..0465cf27570 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.h +++ b/chromium/third_party/WebKit/Source/core/frame/DOMWindowTimers.h @@ -41,10 +41,10 @@ class EventTarget; class ScheduledAction; namespace DOMWindowTimers { -int setTimeout(EventTarget*, PassOwnPtr<ScheduledAction>, int timeout); -int setInterval(EventTarget*, PassOwnPtr<ScheduledAction>, int timeout); -void clearTimeout(EventTarget*, int timeoutId); -void clearInterval(EventTarget*, int timeoutId); +int setTimeout(EventTarget&, PassOwnPtr<ScheduledAction>, int timeout); +int setInterval(EventTarget&, PassOwnPtr<ScheduledAction>, int timeout); +void clearTimeout(EventTarget&, int timeoutId); +void clearInterval(EventTarget&, int timeoutId); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DeprecatedScheduleStyleRecalcDuringLayout.cpp b/chromium/third_party/WebKit/Source/core/frame/DeprecatedScheduleStyleRecalcDuringLayout.cpp new file mode 100644 index 00000000000..88f35ae44ee --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeprecatedScheduleStyleRecalcDuringLayout.cpp @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h" + +#include "wtf/Assertions.h" + +namespace WebCore { + +DeprecatedScheduleStyleRecalcDuringLayout::DeprecatedScheduleStyleRecalcDuringLayout(DocumentLifecycle& lifecycle) + : m_lifecycle(lifecycle) + , m_deprecatedTransition(DocumentLifecycle::InPerformLayout, DocumentLifecycle::VisualUpdatePending) + , m_wasInPerformLayout(lifecycle.state() == DocumentLifecycle::InPerformLayout) +{ +} + +DeprecatedScheduleStyleRecalcDuringLayout::~DeprecatedScheduleStyleRecalcDuringLayout() +{ + // This block of code is intended to restore the state machine to the + // proper state. The style recalc will still have been schedule, however. + if (m_wasInPerformLayout && m_lifecycle.state() != DocumentLifecycle::InPerformLayout) { + ASSERT(m_lifecycle.state() == DocumentLifecycle::VisualUpdatePending); + m_lifecycle.advanceTo(DocumentLifecycle::InPerformLayout); + } +} + +} diff --git a/chromium/third_party/WebKit/Source/core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h b/chromium/third_party/WebKit/Source/core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h new file mode 100644 index 00000000000..90b9223f8ca --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeprecatedScheduleStyleRecalcDuringLayout_h +#define DeprecatedScheduleStyleRecalcDuringLayout_h + +#include "core/dom/DocumentLifecycle.h" + +namespace WebCore { + +class DeprecatedScheduleStyleRecalcDuringLayout { + WTF_MAKE_NONCOPYABLE(DeprecatedScheduleStyleRecalcDuringLayout); +public: + explicit DeprecatedScheduleStyleRecalcDuringLayout(DocumentLifecycle&); + ~DeprecatedScheduleStyleRecalcDuringLayout(); + +private: + DocumentLifecycle& m_lifecycle; + DocumentLifecycle::DeprecatedTransition m_deprecatedTransition; + bool m_wasInPerformLayout; +}; + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/DeviceEventControllerBase.cpp b/chromium/third_party/WebKit/Source/core/frame/DeviceEventControllerBase.cpp new file mode 100644 index 00000000000..f5f5eab4a0f --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeviceEventControllerBase.cpp @@ -0,0 +1,70 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/DeviceEventControllerBase.h" + +#include "core/page/Page.h" + +namespace WebCore { + +DeviceEventControllerBase::DeviceEventControllerBase(Page* page) + : PageLifecycleObserver(page) + , m_hasEventListener(false) + , m_isActive(false) + , m_timer(this, &DeviceEventControllerBase::oneShotCallback) +{ +} + +DeviceEventControllerBase::~DeviceEventControllerBase() +{ +} + +void DeviceEventControllerBase::oneShotCallback(Timer<DeviceEventControllerBase>* timer) +{ + ASSERT_UNUSED(timer, timer == &m_timer); + ASSERT(hasLastData()); + ASSERT(!m_timer.isActive()); + + didUpdateData(); +} + +void DeviceEventControllerBase::startUpdating() +{ + if (m_isActive) + return; + + if (hasLastData() && !m_timer.isActive()) { + // Make sure to fire the data as soon as possible. + m_timer.startOneShot(0, FROM_HERE); + } + + registerWithDispatcher(); + m_isActive = true; +} + +void DeviceEventControllerBase::stopUpdating() +{ + if (!m_isActive) + return; + + if (m_timer.isActive()) + m_timer.stop(); + + unregisterWithDispatcher(); + m_isActive = false; +} + +void DeviceEventControllerBase::pageVisibilityChanged() +{ + if (!m_hasEventListener) + return; + + if (page()->visibilityState() == PageVisibilityStateVisible) + startUpdating(); + else + stopUpdating(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DeviceEventControllerBase.h b/chromium/third_party/WebKit/Source/core/frame/DeviceEventControllerBase.h new file mode 100644 index 00000000000..9d2902a47d2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeviceEventControllerBase.h @@ -0,0 +1,49 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeviceEventControllerBase_h +#define DeviceEventControllerBase_h + +#include "core/page/PageLifecycleObserver.h" +#include "platform/Timer.h" + +namespace WebCore { + +// Base controller class for registering controllers with a dispatcher. +// It watches page visibility and calls stopUpdating when page is not visible. +// It provides a didUpdateData() callback method which is called when new data +// it available. +class DeviceEventControllerBase : public PageLifecycleObserver { +public: + void startUpdating(); + void stopUpdating(); + + // This is called when new data becomes available. + virtual void didUpdateData() = 0; + +protected: + explicit DeviceEventControllerBase(Page*); + virtual ~DeviceEventControllerBase(); + + virtual void registerWithDispatcher() = 0; + virtual void unregisterWithDispatcher() = 0; + + // When true initiates a one-shot didUpdateData() when startUpdating() is called. + virtual bool hasLastData() = 0; + + bool m_hasEventListener; + +private: + // Inherited from PageLifecycleObserver. + virtual void pageVisibilityChanged() OVERRIDE FINAL; + + void oneShotCallback(Timer<DeviceEventControllerBase>*); + + bool m_isActive; + Timer<DeviceEventControllerBase> m_timer; +}; + +} // namespace WebCore + +#endif // DeviceEventControllerBase_h diff --git a/chromium/third_party/WebKit/Source/core/frame/DeviceEventDispatcherBase.cpp b/chromium/third_party/WebKit/Source/core/frame/DeviceEventDispatcherBase.cpp new file mode 100644 index 00000000000..4f01bf52cde --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeviceEventDispatcherBase.cpp @@ -0,0 +1,87 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/DeviceEventDispatcherBase.h" + +#include "core/frame/DeviceEventControllerBase.h" +#include "wtf/TemporaryChange.h" + +namespace WebCore { + +DeviceEventDispatcherBase::DeviceEventDispatcherBase() + : m_needsPurge(false) + , m_isDispatching(false) +{ +} + +DeviceEventDispatcherBase::~DeviceEventDispatcherBase() +{ +} + +void DeviceEventDispatcherBase::addController(DeviceEventControllerBase* controller) +{ + bool wasEmpty = m_controllers.isEmpty(); + if (!m_controllers.contains(controller)) + m_controllers.append(controller); + if (wasEmpty) + startListening(); +} + +void DeviceEventDispatcherBase::removeController(DeviceEventControllerBase* controller) +{ + // Do not actually remove the controller from the vector, instead zero them out. + // The zeros are removed in these two cases: + // 1. either immediately if we are not dispatching any events, + // 2. or after events to all controllers have dispatched (see notifyControllers()). + // This is to correctly handle the re-entrancy case when a controller is destroyed + // while the events are still being dispatched. + size_t index = m_controllers.find(controller); + if (index == kNotFound) + return; + + m_controllers[index] = 0; + m_needsPurge = true; + + if (!m_isDispatching) + purgeControllers(); +} + +void DeviceEventDispatcherBase::purgeControllers() +{ + ASSERT(m_needsPurge); + + size_t i = 0; + while (i < m_controllers.size()) { + if (!m_controllers[i]) { + m_controllers[i] = m_controllers.last(); + m_controllers.removeLast(); + } else { + ++i; + } + } + + m_needsPurge = false; + + if (m_controllers.isEmpty()) + stopListening(); +} + +void DeviceEventDispatcherBase::notifyControllers() +{ + { + TemporaryChange<bool> changeIsDispatching(m_isDispatching, true); + // Don't notify controllers removed or added during event dispatch. + size_t size = m_controllers.size(); + for (size_t i = 0; i < size; ++i) { + if (m_controllers[i]) + m_controllers[i]->didUpdateData(); + } + } + + if (m_needsPurge) + purgeControllers(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DeviceEventDispatcherBase.h b/chromium/third_party/WebKit/Source/core/frame/DeviceEventDispatcherBase.h new file mode 100644 index 00000000000..94b226698a9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeviceEventDispatcherBase.h @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeviceEventDispatcherBase_h +#define DeviceEventDispatcherBase_h + +#include "wtf/Vector.h" + +namespace WebCore { +class DeviceEventControllerBase; + +class DeviceEventDispatcherBase { +public: + void addController(DeviceEventControllerBase*); + void removeController(DeviceEventControllerBase*); + +protected: + DeviceEventDispatcherBase(); + virtual ~DeviceEventDispatcherBase(); + + void notifyControllers(); + + virtual void startListening() = 0; + virtual void stopListening() = 0; + +private: + void purgeControllers(); + + Vector<DeviceEventControllerBase*> m_controllers; + bool m_needsPurge; + bool m_isDispatching; +}; + +} // namespace WebCore + +#endif // DeviceEventDispatcherBase_h diff --git a/chromium/third_party/WebKit/Source/core/frame/DeviceSingleWindowEventController.cpp b/chromium/third_party/WebKit/Source/core/frame/DeviceSingleWindowEventController.cpp new file mode 100644 index 00000000000..b0f6c30ce48 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeviceSingleWindowEventController.cpp @@ -0,0 +1,73 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/DeviceSingleWindowEventController.h" + +#include "core/dom/Document.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/page/Page.h" + +namespace WebCore { + +DeviceSingleWindowEventController::DeviceSingleWindowEventController(Document& document) + : DeviceEventControllerBase(document.page()) + , DOMWindowLifecycleObserver(document.domWindow()) + , m_needsCheckingNullEvents(true) + , m_document(document) +{ +} + +DeviceSingleWindowEventController::~DeviceSingleWindowEventController() +{ +} + +void DeviceSingleWindowEventController::didUpdateData() +{ + dispatchDeviceEvent(lastEvent()); +} + +void DeviceSingleWindowEventController::dispatchDeviceEvent(PassRefPtrWillBeRawPtr<Event> prpEvent) +{ + if (!m_document.domWindow() || m_document.activeDOMObjectsAreSuspended() || m_document.activeDOMObjectsAreStopped()) + return; + + RefPtrWillBeRawPtr<Event> event = prpEvent; + m_document.domWindow()->dispatchEvent(event); + + if (m_needsCheckingNullEvents) { + if (isNullEvent(event.get())) + stopUpdating(); + else + m_needsCheckingNullEvents = false; + } +} + +void DeviceSingleWindowEventController::didAddEventListener(LocalDOMWindow* window, const AtomicString& eventType) +{ + if (eventType != eventTypeName()) + return; + + if (page() && page()->visibilityState() == PageVisibilityStateVisible) + startUpdating(); + + m_hasEventListener = true; +} + +void DeviceSingleWindowEventController::didRemoveEventListener(LocalDOMWindow* window, const AtomicString& eventType) +{ + if (eventType != eventTypeName() || window->hasEventListeners(eventTypeName())) + return; + + stopUpdating(); + m_hasEventListener = false; +} + +void DeviceSingleWindowEventController::didRemoveAllEventListeners(LocalDOMWindow*) +{ + stopUpdating(); + m_hasEventListener = false; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DeviceSingleWindowEventController.h b/chromium/third_party/WebKit/Source/core/frame/DeviceSingleWindowEventController.h new file mode 100644 index 00000000000..d28d46dd3e6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/DeviceSingleWindowEventController.h @@ -0,0 +1,44 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DeviceSingleWindowEventController_h +#define DeviceSingleWindowEventController_h + +#include "core/frame/DOMWindowLifecycleObserver.h" +#include "core/frame/DeviceEventControllerBase.h" +#include "platform/heap/Handle.h" + +namespace WebCore { + +class Document; +class Event; + +class DeviceSingleWindowEventController : public DeviceEventControllerBase, public DOMWindowLifecycleObserver { +public: + // Inherited from DeviceEventControllerBase. + virtual void didUpdateData() OVERRIDE; + + // Inherited from DOMWindowLifecycleObserver. + virtual void didAddEventListener(LocalDOMWindow*, const AtomicString&) OVERRIDE; + virtual void didRemoveEventListener(LocalDOMWindow*, const AtomicString&) OVERRIDE; + virtual void didRemoveAllEventListeners(LocalDOMWindow*) OVERRIDE; + +protected: + explicit DeviceSingleWindowEventController(Document&); + virtual ~DeviceSingleWindowEventController(); + + void dispatchDeviceEvent(const PassRefPtrWillBeRawPtr<Event>); + + virtual PassRefPtrWillBeRawPtr<Event> lastEvent() const = 0; + virtual const AtomicString& eventTypeName() const = 0; + virtual bool isNullEvent(Event*) const = 0; + +private: + bool m_needsCheckingNullEvents; + Document& m_document; +}; + +} // namespace WebCore + +#endif // DeviceSingleWindowEventController_h diff --git a/chromium/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp b/chromium/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp new file mode 100644 index 00000000000..014e94eac5b --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp @@ -0,0 +1,255 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/EventHandlerRegistry.h" + +#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/html/HTMLFrameOwnerElement.h" +#include "core/page/Page.h" +#include "core/page/scrolling/ScrollingCoordinator.h" + +namespace WebCore { + +EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost) + : m_frameHost(frameHost) +{ +} + +EventHandlerRegistry::~EventHandlerRegistry() +{ + checkConsistency(); +} + +bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result) +{ + if (eventType == EventTypeNames::scroll) { + *result = ScrollEvent; + } else if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) { + *result = WheelEvent; +#if ASSERT_ENABLED + } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) { + *result = EventsForTesting; +#endif + } else { + return false; + } + return true; +} + +const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const +{ + checkConsistency(); + return &m_targets[handlerClass]; +} + +bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const +{ + return m_targets[handlerClass].size(); +} + +bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target) +{ + EventTargetSet* targets = &m_targets[handlerClass]; + if (op == Add) { + if (!targets->add(target).isNewEntry) { + // Just incremented refcount, no real change. + return false; + } + } else { + ASSERT(op == Remove || op == RemoveAll); + ASSERT(op == RemoveAll || targets->contains(target)); + + if (op == RemoveAll) { + if (!targets->contains(target)) + return false; + targets->removeAll(target); + } else { + if (!targets->remove(target)) { + // Just decremented refcount, no real update. + return false; + } + } + } + return true; +} + +void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target) +{ + bool hadHandlers = hasEventHandlers(handlerClass); + updateEventHandlerTargets(op, handlerClass, target); + bool hasHandlers = hasEventHandlers(handlerClass); + + if (hadHandlers != hasHandlers) { + notifyHasHandlersChanged(handlerClass, hasHandlers); + } + checkConsistency(); +} + +void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target) +{ + EventHandlerClass handlerClass; + if (!eventTypeToClass(eventType, &handlerClass)) + return; + updateEventHandlerInternal(op, handlerClass, target); +} + +void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType) +{ + updateEventHandlerOfType(Add, eventType, &target); +} + +void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType) +{ + updateEventHandlerOfType(Remove, eventType, &target); +} + +void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass) +{ + updateEventHandlerInternal(Add, handlerClass, &target); +} + +void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass) +{ + updateEventHandlerInternal(Remove, handlerClass, &target); +} + +void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target) +{ + updateAllEventHandlers(Add, target); +} + +void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target) +{ + updateAllEventHandlers(RemoveAll, target); +} + +void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target) +{ + for (size_t i = 0; i < EventHandlerClassCount; ++i) { + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); + updateEventHandlerInternal(RemoveAll, handlerClass, &target); + } +} + +void EventHandlerRegistry::updateAllEventHandlers(ChangeOperation op, EventTarget& target) +{ + if (!target.hasEventListeners()) + return; + + Vector<AtomicString> eventTypes = target.eventTypes(); + for (size_t i = 0; i < eventTypes.size(); ++i) { + EventHandlerClass handlerClass; + if (!eventTypeToClass(eventTypes[i], &handlerClass)) + continue; + if (op == RemoveAll) { + updateEventHandlerInternal(op, handlerClass, &target); + continue; + } + for (unsigned count = target.getEventListeners(eventTypes[i]).size(); count > 0; --count) + updateEventHandlerInternal(op, handlerClass, &target); + } +} + +void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers) +{ + ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoordinator(); + + switch (handlerClass) { + case ScrollEvent: + if (scrollingCoordinator) + scrollingCoordinator->updateHaveScrollEventHandlers(); + break; + case WheelEvent: + if (scrollingCoordinator) + scrollingCoordinator->updateHaveWheelEventHandlers(); + break; +#if ASSERT_ENABLED + case EventsForTesting: + break; +#endif + default: + ASSERT_NOT_REACHED(); + break; + } +} + +void EventHandlerRegistry::trace(Visitor* visitor) +{ + visitor->registerWeakMembers<EventHandlerRegistry, &EventHandlerRegistry::clearWeakMembers>(this); +} + +void EventHandlerRegistry::clearWeakMembers(Visitor* visitor) +{ + Vector<EventTarget*> deadTargets; + for (size_t i = 0; i < EventHandlerClassCount; ++i) { + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); + const EventTargetSet* targets = &m_targets[handlerClass]; + for (EventTargetSet::const_iterator it = targets->begin(); it != targets->end(); ++it) { + Node* node = it->key->toNode(); + LocalDOMWindow* window = it->key->toDOMWindow(); + if (node && !visitor->isAlive(node)) { + deadTargets.append(node); + } else if (window && !visitor->isAlive(window)) { + deadTargets.append(window); + } + } + } + for (size_t i = 0; i < deadTargets.size(); ++i) + didRemoveAllEventHandlers(*deadTargets[i]); +} + +void EventHandlerRegistry::documentDetached(Document& document) +{ + // Remove all event targets under the detached document. + for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCount; ++handlerClassIndex) { + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerClassIndex); + Vector<EventTarget*> targetsToRemove; + const EventTargetSet* targets = &m_targets[handlerClass]; + for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) { + if (Node* node = iter->key->toNode()) { + for (Document* doc = &node->document(); doc; doc = doc->ownerElement() ? &doc->ownerElement()->document() : 0) { + if (doc == &document) { + targetsToRemove.append(iter->key); + break; + } + } + } else if (iter->key->toDOMWindow()) { + // DOMWindows may outlive their documents, so we shouldn't remove their handlers + // here. + } else { + ASSERT_NOT_REACHED(); + } + } + for (size_t i = 0; i < targetsToRemove.size(); ++i) + updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]); + } +} + +void EventHandlerRegistry::checkConsistency() const +{ +#if ASSERT_ENABLED + for (size_t i = 0; i < EventHandlerClassCount; ++i) { + EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i); + const EventTargetSet* targets = &m_targets[handlerClass]; + for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) { + if (Node* node = iter->key->toNode()) { + // See the comment for |documentDetached| if either of these assertions fails. + ASSERT(node->document().frameHost()); + ASSERT(node->document().frameHost() == &m_frameHost); + } else if (LocalDOMWindow* window = iter->key->toDOMWindow()) { + // If any of these assertions fail, LocalDOMWindow failed to unregister its handlers + // properly. + ASSERT(window->frame()); + ASSERT(window->frame()->host()); + ASSERT(window->frame()->host() == &m_frameHost); + } + } + } +#endif // ASSERT_ENABLED +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h b/chromium/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h new file mode 100644 index 00000000000..4d53b31def1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h @@ -0,0 +1,96 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EventHandlerRegistry_h +#define EventHandlerRegistry_h + +#include "core/events/Event.h" +#include "core/frame/FrameHost.h" +#include "wtf/HashCountedSet.h" + +namespace WebCore { + +typedef HashCountedSet<EventTarget*> EventTargetSet; + +// Registry for keeping track of event handlers. Note that only handlers on +// documents that can be rendered or can receive input (i.e., are attached to a +// FrameHost) are registered here. +class EventHandlerRegistry FINAL : public NoBaseWillBeGarbageCollectedFinalized<EventHandlerRegistry> { +public: + explicit EventHandlerRegistry(FrameHost&); + virtual ~EventHandlerRegistry(); + + // Supported event handler classes. Note that each one may correspond to + // multiple event types. + enum EventHandlerClass { + ScrollEvent, + WheelEvent, +#if ASSERT_ENABLED + // Additional event categories for verifying handler tracking logic. + EventsForTesting, +#endif + EventHandlerClassCount, // Must be the last entry. + }; + + // Returns true if the FrameHost has event handlers of the specified class. + bool hasEventHandlers(EventHandlerClass) const; + + // Returns a set of EventTargets which have registered handlers of the given class. + const EventTargetSet* eventHandlerTargets(EventHandlerClass) const; + + // Registration and management of event handlers attached to EventTargets. + void didAddEventHandler(EventTarget&, const AtomicString& eventType); + void didAddEventHandler(EventTarget&, EventHandlerClass); + void didRemoveEventHandler(EventTarget&, const AtomicString& eventType); + void didRemoveEventHandler(EventTarget&, EventHandlerClass); + void didRemoveAllEventHandlers(EventTarget&); + void didMoveIntoFrameHost(EventTarget&); + void didMoveOutOfFrameHost(EventTarget&); + + // Either |documentDetached| or |didMoveOutOfFrameHost| must be called + // whenever the FrameHost that is associated with a registered event target + // changes. This ensures the registry does not end up with stale references + // to handlers that are no longer related to it. + void documentDetached(Document&); + + void trace(Visitor*); + void clearWeakMembers(Visitor*); + +private: + enum ChangeOperation { + Add, // Add a new event handler. + Remove, // Remove an existing event handler. + RemoveAll // Remove any and all existing event handlers for a given target. + }; + + // Returns true if |eventType| belongs to a class this registry tracks. + static bool eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result); + + // Returns true if the operation actually added a new target or completely + // removed an existing one. + bool updateEventHandlerTargets(ChangeOperation, EventHandlerClass, EventTarget*); + + // Called on the EventHandlerRegistry of the root Document to notify + // clients when we have added the first handler or removed the last one for + // a given event class. |hasActiveHandlers| can be used to distinguish + // between the two cases. + void notifyHasHandlersChanged(EventHandlerClass, bool hasActiveHandlers); + + // Record a change operation to a given event handler class and notify any + // parent registry and other clients accordingly. + void updateEventHandlerOfType(ChangeOperation, const AtomicString& eventType, EventTarget*); + + void updateEventHandlerInternal(ChangeOperation, EventHandlerClass, EventTarget*); + + void updateAllEventHandlers(ChangeOperation, EventTarget&); + + void checkConsistency() const; + + FrameHost& m_frameHost; + EventTargetSet m_targets[EventHandlerClassCount]; +}; + +} // namespace WebCore + +#endif // EventHandlerRegistry_h diff --git a/chromium/third_party/WebKit/Source/core/frame/Frame.cpp b/chromium/third_party/WebKit/Source/core/frame/Frame.cpp index cac41bdafc9..52813512bdd 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Frame.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/Frame.cpp @@ -30,23 +30,12 @@ #include "config.h" #include "core/frame/Frame.h" -#include "RuntimeEnabledFeatures.h" -#include "bindings/v8/ScriptController.h" #include "core/dom/DocumentType.h" -#include "core/dom/WheelController.h" -#include "core/editing/Editor.h" -#include "core/editing/FrameSelection.h" -#include "core/editing/InputMethodController.h" -#include "core/editing/SpellChecker.h" -#include "core/editing/htmlediting.h" -#include "core/editing/markup.h" #include "core/events/Event.h" -#include "core/fetch/ResourceFetcher.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "core/frame/FrameDestructionObserver.h" -#include "core/frame/FrameView.h" +#include "core/frame/FrameHost.h" #include "core/frame/Settings.h" -#include "core/frame/animation/AnimationController.h" #include "core/html/HTMLFrameElementBase.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/loader/EmptyClients.h" @@ -56,21 +45,10 @@ #include "core/page/EventHandler.h" #include "core/page/FocusController.h" #include "core/page/Page.h" -#include "core/page/scrolling/ScrollingCoordinator.h" -#include "core/platform/DragImage.h" -#include "core/rendering/HitTestResult.h" -#include "core/rendering/RenderLayerCompositor.h" #include "core/rendering/RenderPart.h" -#include "core/rendering/RenderView.h" -#include "core/svg/SVGDocument.h" -#include "platform/graphics/GraphicsContext.h" -#include "platform/graphics/ImageBuffer.h" #include "public/platform/WebLayer.h" #include "wtf/PassOwnPtr.h" #include "wtf/RefCountedLeakCounter.h" -#include "wtf/StdLibExtras.h" - -using namespace std; namespace WebCore { @@ -78,75 +56,32 @@ using namespace HTMLNames; DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame")); -static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement) -{ - if (!ownerElement) - return 0; - return ownerElement->document().frame(); -} - -static inline float parentPageZoomFactor(Frame* frame) -{ - Frame* parent = frame->tree().parent(); - if (!parent) - return 1; - return parent->pageZoomFactor(); -} - -static inline float parentTextZoomFactor(Frame* frame) -{ - Frame* parent = frame->tree().parent(); - if (!parent) - return 1; - return parent->textZoomFactor(); -} - -inline Frame::Frame(PassRefPtr<FrameInit> frameInit) - : m_page(frameInit->page()) - , m_treeNode(this, parentFromOwnerElement(frameInit->ownerElement())) - , m_loader(this, frameInit->frameLoaderClient()) - , m_navigationScheduler(this) - , m_script(adoptPtr(new ScriptController(this))) - , m_editor(Editor::create(*this)) - , m_spellChecker(SpellChecker::create(*this)) - , m_selection(adoptPtr(new FrameSelection(this))) - , m_eventHandler(adoptPtr(new EventHandler(this))) - , m_animationController(adoptPtr(new AnimationController(this))) - , m_inputMethodController(InputMethodController::create(*this)) - , m_frameInit(frameInit) - , m_pageZoomFactor(parentPageZoomFactor(this)) - , m_textZoomFactor(parentTextZoomFactor(this)) -#if ENABLE(ORIENTATION_EVENTS) - , m_orientation(0) -#endif - , m_inViewSourceMode(false) +Frame::Frame(FrameClient* client, FrameHost* host, FrameOwner* owner) + : m_treeNode(this) + , m_host(host) + , m_owner(owner) + , m_client(client) , m_remotePlatformLayer(0) { - ASSERT(m_page); - - if (ownerElement()) { - m_page->incrementSubframeCount(); - ownerElement()->setContentFrame(*this); - } + ASSERT(page()); #ifndef NDEBUG frameCounter.increment(); #endif -} -PassRefPtr<Frame> Frame::create(PassRefPtr<FrameInit> frameInit) -{ - RefPtr<Frame> frame = adoptRef(new Frame(frameInit)); - if (!frame->ownerElement()) - frame->page()->setMainFrame(frame); - InspectorInstrumentation::frameAttachedToParent(frame.get()); - return frame.release(); + if (m_owner) { + page()->incrementSubframeCount(); + if (m_owner->isLocal()) + toHTMLFrameOwnerElement(m_owner)->setContentFrame(*this); + } else { + page()->setMainFrame(this); + } } Frame::~Frame() { - setView(0); - loader().clear(ClearScriptObjects | ClearWindowObject); + disconnectOwnerElement(); + setDOMWindow(nullptr); // FIXME: We should not be doing all this work inside the destructor @@ -154,25 +89,11 @@ Frame::~Frame() frameCounter.decrement(); #endif - disconnectOwnerElement(); - HashSet<FrameDestructionObserver*>::iterator stop = m_destructionObservers.end(); for (HashSet<FrameDestructionObserver*>::iterator it = m_destructionObservers.begin(); it != stop; ++it) (*it)->frameDestroyed(); } -bool Frame::inScope(TreeScope* scope) const -{ - ASSERT(scope); - Document* doc = document(); - if (!doc) - return false; - HTMLFrameOwnerElement* owner = doc->ownerElement(); - if (!owner) - return false; - return owner->treeScope() == scope; -} - void Frame::addDestructionObserver(FrameDestructionObserver* observer) { m_destructionObservers.add(observer); @@ -183,99 +104,29 @@ void Frame::removeDestructionObserver(FrameDestructionObserver* observer) m_destructionObservers.remove(observer); } -void Frame::setView(PassRefPtr<FrameView> view) +FrameHost* Frame::host() const { - // We the custom scroll bars as early as possible to prevent m_doc->detach() - // from messing with the view such that its scroll bars won't be torn down. - // FIXME: We should revisit this. - if (m_view) - m_view->prepareForDetach(); - - // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is - // notified. If we wait until the view is destroyed, then things won't be hooked up enough for - // these calls to work. - if (!view && document() && document()->isActive()) { - // FIXME: We don't call willRemove here. Why is that OK? - document()->prepareForDestruction(); - } - - if (m_view) - m_view->unscheduleRelayout(); - - eventHandler().clear(); - - m_view = view; - - if (m_view && isMainFrame()) - m_view->setVisibleContentScaleFactor(m_page->pageScaleFactor()); + return m_host; } -#if ENABLE(ORIENTATION_EVENTS) -void Frame::sendOrientationChangeEvent(int orientation) +Page* Frame::page() const { - m_orientation = orientation; - if (DOMWindow* window = domWindow()) - window->dispatchEvent(Event::create(EventTypeNames::orientationchange)); + if (m_host) + return &m_host->page(); + return 0; } -#endif // ENABLE(ORIENTATION_EVENTS) Settings* Frame::settings() const { - return m_page ? &m_page->settings() : 0; -} - -void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize) -{ - // In setting printing, we should not validate resources already cached for the document. - // See https://bugs.webkit.org/show_bug.cgi?id=43704 - ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher()); - - document()->setPrinting(printing); - view()->adjustMediaTypeForPrinting(printing); - - document()->styleResolverChanged(RecalcStyleImmediately); - if (shouldUsePrintingLayout()) { - view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize); - } else { - view()->forceLayout(); - if (shouldAdjustViewSize == AdjustViewSize) - view()->adjustViewSize(); - } - - // Subframes of the one we're printing don't lay out to the page size. - for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) - child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize); -} - -bool Frame::shouldUsePrintingLayout() const -{ - // Only top frame being printed should be fit to page size. - // Subframes should be constrained by parents only. - return document()->printing() && (!tree().parent() || !tree().parent()->document()->printing()); -} - -FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize) -{ - FloatSize resultSize; - if (!contentRenderer()) - return FloatSize(); - - if (contentRenderer()->style()->isHorizontalWritingMode()) { - ASSERT(fabs(originalSize.width()) > numeric_limits<float>::epsilon()); - float ratio = originalSize.height() / originalSize.width(); - resultSize.setWidth(floorf(expectedSize.width())); - resultSize.setHeight(floorf(resultSize.width() * ratio)); - } else { - ASSERT(fabs(originalSize.height()) > numeric_limits<float>::epsilon()); - float ratio = originalSize.width() / originalSize.height(); - resultSize.setHeight(floorf(expectedSize.height())); - resultSize.setWidth(floorf(resultSize.height() * ratio)); - } - return resultSize; + if (m_host) + return &m_host->settings(); + return 0; } -void Frame::setDOMWindow(PassRefPtr<DOMWindow> domWindow) +void Frame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow) { + if (m_domWindow) + m_domWindow->reset(); m_domWindow = domWindow; } @@ -292,21 +143,11 @@ ChromeClient& Frame::chromeClient() const return emptyChromeClient(); } -Document* Frame::document() const -{ - return m_domWindow ? m_domWindow->document() : 0; -} - -RenderView* Frame::contentRenderer() const -{ - return document() ? document()->renderView() : 0; -} - RenderPart* Frame::ownerRenderer() const { - if (!ownerElement()) + if (!deprecatedLocalOwner()) return 0; - RenderObject* object = ownerElement()->renderer(); + RenderObject* object = deprecatedLocalOwner()->renderer(); if (!object) return 0; // FIXME: If <object> is ever fixed to disassociate itself from frames @@ -318,391 +159,45 @@ RenderPart* Frame::ownerRenderer() const return toRenderPart(object); } -void Frame::dispatchVisibilityStateChangeEvent() -{ - if (document()) - document()->dispatchVisibilityStateChangeEvent(); - - Vector<RefPtr<Frame> > childFrames; - for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) - childFrames.append(child); - - for (size_t i = 0; i < childFrames.size(); ++i) - childFrames[i]->dispatchVisibilityStateChangeEvent(); -} -void Frame::willDetachPage() +void Frame::willDetachFrameHost() { - // We should never be detatching the page during a Layout. - RELEASE_ASSERT(!m_view || !m_view->isInLayout()); - - if (Frame* parent = tree().parent()) - parent->loader().checkLoadComplete(); - HashSet<FrameDestructionObserver*>::iterator stop = m_destructionObservers.end(); for (HashSet<FrameDestructionObserver*>::iterator it = m_destructionObservers.begin(); it != stop; ++it) - (*it)->willDetachPage(); + (*it)->willDetachFrameHost(); + // FIXME: Page should take care of updating focus/scrolling instead of Frame. // FIXME: It's unclear as to why this is called more than once, but it is, - // so page() could be NULL. + // so page() could be null. if (page() && page()->focusController().focusedFrame() == this) - page()->focusController().setFocusedFrame(0); - - if (page() && page()->scrollingCoordinator() && m_view) - page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get()); - - script().clearScriptObjects(); + page()->focusController().setFocusedFrame(nullptr); } -void Frame::detachFromPage() -{ - // We should never be detatching the page during a Layout. - RELEASE_ASSERT(!m_view || !m_view->isInLayout()); - m_page = 0; -} - -void Frame::disconnectOwnerElement() +void Frame::detachFromFrameHost() { - if (ownerElement()) { - if (Document* doc = document()) - doc->topDocument()->clearAXObjectCache(); - ownerElement()->clearContentFrame(); - if (m_page) - m_page->decrementSubframeCount(); - } - m_frameInit->setOwnerElement(0); + m_host = 0; } bool Frame::isMainFrame() const { - return m_page && this == m_page->mainFrame(); -} - -String Frame::documentTypeString() const -{ - if (DocumentType* doctype = document()->doctype()) - return createMarkup(doctype); - - return String(); -} - -String Frame::selectedText() const -{ - return selection().selectedText(); -} - -String Frame::selectedTextForClipboard() const -{ - return selection().selectedTextForClipboard(); -} - -VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint) -{ - HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint); - Node* node = result.innerNonSharedNode(); - if (!node) - return VisiblePosition(); - RenderObject* renderer = node->renderer(); - if (!renderer) - return VisiblePosition(); - VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint())); - if (visiblePos.isNull()) - visiblePos = firstPositionInOrBeforeNode(node); - return visiblePos; -} - -Document* Frame::documentAtPoint(const IntPoint& point) -{ - if (!view()) - return 0; - - IntPoint pt = view()->windowToContents(point); - HitTestResult result = HitTestResult(pt); - - if (contentRenderer()) - result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); - return result.innerNode() ? &result.innerNode()->document() : 0; -} - -PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint) -{ - VisiblePosition position = visiblePositionForPoint(framePoint); - if (position.isNull()) - return 0; - - VisiblePosition previous = position.previous(); - if (previous.isNotNull()) { - RefPtr<Range> previousCharacterRange = makeRange(previous, position); - LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get()); - if (rect.contains(framePoint)) - return previousCharacterRange.release(); - } - - VisiblePosition next = position.next(); - if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) { - LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get()); - if (rect.contains(framePoint)) - return nextCharacterRange.release(); - } - - return 0; -} - -void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent, - ScrollbarMode horizontalScrollbarMode, bool horizontalLock, - ScrollbarMode verticalScrollbarMode, bool verticalLock) -{ - ASSERT(this); - ASSERT(m_page); - - bool isMainFrame = this->isMainFrame(); - - if (isMainFrame && view()) - view()->setParentVisible(false); - - setView(0); - - RefPtr<FrameView> frameView; - if (isMainFrame) { - frameView = FrameView::create(this, viewportSize); - - // The layout size is set by WebViewImpl to support @viewport - frameView->setLayoutSizeFixedToFrameSize(false); - } else - frameView = FrameView::create(this); - - frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock); - - setView(frameView); - - if (backgroundColor.isValid()) - frameView->updateBackgroundRecursively(backgroundColor, transparent); - - if (isMainFrame) - frameView->setParentVisible(true); - - if (ownerRenderer()) - ownerRenderer()->setWidget(frameView); - - if (HTMLFrameOwnerElement* owner = ownerElement()) - view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); -} - -String Frame::layerTreeAsText(unsigned flags) const -{ - document()->updateLayout(); - - if (!contentRenderer()) - return String(); - - return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags)); -} - -String Frame::trackedRepaintRectsAsText() const -{ - if (!m_view) - return String(); - return m_view->trackedRepaintRectsAsText(); -} - -void Frame::setPageZoomFactor(float factor) -{ - setPageAndTextZoomFactors(factor, m_textZoomFactor); -} - -void Frame::setTextZoomFactor(float factor) -{ - setPageAndTextZoomFactors(m_pageZoomFactor, factor); -} - -void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor) -{ - if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor) - return; - Page* page = this->page(); - if (!page) - return; - - Document* document = this->document(); - if (!document) - return; - - // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents. - // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification. - if (document->isSVGDocument()) { - if (!toSVGDocument(document)->zoomAndPanEnabled()) - return; - } - - if (m_pageZoomFactor != pageZoomFactor) { - if (FrameView* view = this->view()) { - // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position. - LayoutPoint scrollPosition = view->scrollPosition(); - float percentDifference = (pageZoomFactor / m_pageZoomFactor); - view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference)); - } - } - - m_pageZoomFactor = pageZoomFactor; - m_textZoomFactor = textZoomFactor; - - document->recalcStyle(Force); - - for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) - child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor); - - if (FrameView* view = this->view()) { - if (document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout()) - view->layout(); - } -} - -void Frame::deviceOrPageScaleFactorChanged() -{ - document()->mediaQueryAffectingValueChanged(); - for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) - child->deviceOrPageScaleFactorChanged(); -} - -void Frame::notifyChromeClientWheelEventHandlerCountChanged() const -{ - // Ensure that this method is being called on the main frame of the page. - ASSERT(isMainFrame()); - - unsigned count = 0; - for (const Frame* frame = this; frame; frame = frame->tree().traverseNext()) { - if (frame->document()) - count += WheelController::from(frame->document())->wheelEventHandlerCount(); - } - - m_page->chrome().client().numWheelEventHandlersChanged(count); + return page && this == page->mainFrame(); } -bool Frame::isURLAllowed(const KURL& url) const +void Frame::disconnectOwnerElement() { - // We allow one level of self-reference because some sites depend on that, - // but we don't allow more than one. - if (m_page->subframeCount() >= Page::maxNumberOfFrames) - return false; - bool foundSelfReference = false; - for (const Frame* frame = this; frame; frame = frame->tree().parent()) { - if (equalIgnoringFragmentIdentifier(frame->document()->url(), url)) { - if (foundSelfReference) - return false; - foundSelfReference = true; - } + if (m_owner) { + if (m_owner->isLocal()) + toHTMLFrameOwnerElement(m_owner)->clearContentFrame(); + if (page()) + page()->decrementSubframeCount(); } - return true; -} - -struct ScopedFramePaintingState { - ScopedFramePaintingState(Frame* frame, Node* node) - : frame(frame) - , node(node) - , paintBehavior(frame->view()->paintBehavior()) - , backgroundColor(frame->view()->baseBackgroundColor()) - { - ASSERT(!node || node->renderer()); - if (node) - node->renderer()->updateDragState(true); - } - - ~ScopedFramePaintingState() - { - if (node && node->renderer()) - node->renderer()->updateDragState(false); - frame->view()->setPaintBehavior(paintBehavior); - frame->view()->setBaseBackgroundColor(backgroundColor); - frame->view()->setNodeToDraw(0); - } - - Frame* frame; - Node* node; - PaintBehavior paintBehavior; - Color backgroundColor; -}; - -PassOwnPtr<DragImage> Frame::nodeImage(Node* node) -{ - if (!node->renderer()) - return nullptr; - - const ScopedFramePaintingState state(this, node); - - m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers); - - // When generating the drag image for an element, ignore the document background. - m_view->setBaseBackgroundColor(Color::transparent); - document()->updateLayout(); - m_view->setNodeToDraw(node); // Enable special sub-tree drawing mode. - - // Document::updateLayout may have blown away the original RenderObject. - RenderObject* renderer = node->renderer(); - if (!renderer) - return nullptr; - - LayoutRect topLevelRect; - IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect)); - - float deviceScaleFactor = 1; - if (m_page) - deviceScaleFactor = m_page->deviceScaleFactor(); - paintingRect.setWidth(paintingRect.width() * deviceScaleFactor); - paintingRect.setHeight(paintingRect.height() * deviceScaleFactor); - - OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size()); - if (!buffer) - return nullptr; - buffer->context()->scale(FloatSize(deviceScaleFactor, deviceScaleFactor)); - buffer->context()->translate(-paintingRect.x(), -paintingRect.y()); - buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY())); - - m_view->paintContents(buffer->context(), paintingRect); - - RefPtr<Image> image = buffer->copyImage(); - return DragImage::create(image.get(), renderer->shouldRespectImageOrientation(), deviceScaleFactor); + m_owner = 0; } -PassOwnPtr<DragImage> Frame::dragImageForSelection() +HTMLFrameOwnerElement* Frame::deprecatedLocalOwner() const { - if (!selection().isRange()) - return nullptr; - - const ScopedFramePaintingState state(this, 0); - m_view->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers); - document()->updateLayout(); - - IntRect paintingRect = enclosingIntRect(selection().bounds()); - - float deviceScaleFactor = 1; - if (m_page) - deviceScaleFactor = m_page->deviceScaleFactor(); - paintingRect.setWidth(paintingRect.width() * deviceScaleFactor); - paintingRect.setHeight(paintingRect.height() * deviceScaleFactor); - - OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size()); - if (!buffer) - return nullptr; - buffer->context()->scale(FloatSize(deviceScaleFactor, deviceScaleFactor)); - buffer->context()->translate(-paintingRect.x(), -paintingRect.y()); - buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY())); - - m_view->paintContents(buffer->context(), paintingRect); - - RefPtr<Image> image = buffer->copyImage(); - return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor); -} - -double Frame::devicePixelRatio() const -{ - if (!m_page) - return 0; - - double ratio = m_page->deviceScaleFactor(); - if (RuntimeEnabledFeatures::devicePixelRatioIncludesZoomEnabled()) - ratio *= pageZoomFactor(); - return ratio; + return m_owner && m_owner->isLocal() ? toHTMLFrameOwnerElement(m_owner) : 0; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/Frame.h b/chromium/third_party/WebKit/Source/core/frame/Frame.h index 3c669f7db3d..c6cb1f96cfc 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Frame.h +++ b/chromium/third_party/WebKit/Source/core/frame/Frame.h @@ -28,13 +28,10 @@ #ifndef Frame_h #define Frame_h -#include "core/loader/FrameLoader.h" -#include "core/loader/NavigationScheduler.h" -#include "core/frame/AdjustViewSizeOrNot.h" #include "core/page/FrameTree.h" -#include "platform/geometry/IntSize.h" -#include "platform/scroll/ScrollTypes.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" +#include "wtf/HashSet.h" #include "wtf/RefCounted.h" namespace blink { @@ -43,295 +40,112 @@ class WebLayer; namespace WebCore { - class AnimationController; - class ChromeClient; - class Color; - class DOMWindow; - class Document; - class DragImage; - class Editor; - class Element; - class EventHandler; - class FetchContext; - class FloatSize; - class FrameDestructionObserver; - class FrameSelection; - class FrameView; - class HTMLFrameOwnerElement; - class HTMLTableCellElement; - class InputMethodController; - class IntPoint; - class Node; - class Range; - class RenderPart; - class RenderView; - class TreeScope; - class ScriptController; - class Settings; - class SpellChecker; - class TreeScope; - class VisiblePosition; - class Widget; - - class FrameInit : public RefCounted<FrameInit> { - public: - // For creating a dummy Frame - static PassRefPtr<FrameInit> create(int64_t frameID, Page* page, FrameLoaderClient* client) - { - return adoptRef(new FrameInit(frameID, page, client)); - } - - void setFrameLoaderClient(FrameLoaderClient* client) { m_client = client; } - FrameLoaderClient* frameLoaderClient() const { return m_client; } - - int64_t frameID() const { return m_frameID; } - - void setPage(Page* page) { m_page = page; } - Page* page() const { return m_page; } - - void setOwnerElement(HTMLFrameOwnerElement* ownerElement) { m_ownerElement = ownerElement; } - HTMLFrameOwnerElement* ownerElement() const { return m_ownerElement; } - - protected: - FrameInit(int64_t frameID, Page* page = 0, FrameLoaderClient* client = 0) - : m_frameID(frameID) - , m_client(client) - , m_page(page) - , m_ownerElement(0) - { - } - - private: - int64_t m_frameID; - FrameLoaderClient* m_client; - Page* m_page; - HTMLFrameOwnerElement* m_ownerElement; - }; - - class Frame : public RefCounted<Frame> { - public: - static PassRefPtr<Frame> create(PassRefPtr<FrameInit>); - - void init(); - void setView(PassRefPtr<FrameView>); - void createView(const IntSize&, const Color&, bool, - ScrollbarMode = ScrollbarAuto, bool horizontalLock = false, - ScrollbarMode = ScrollbarAuto, bool verticalLock = false); - - ~Frame(); - - void addDestructionObserver(FrameDestructionObserver*); - void removeDestructionObserver(FrameDestructionObserver*); - - void willDetachPage(); - void detachFromPage(); - void disconnectOwnerElement(); - - Page* page() const; - HTMLFrameOwnerElement* ownerElement() const; - bool isMainFrame() const; - - void setDOMWindow(PassRefPtr<DOMWindow>); - DOMWindow* domWindow() const; - Document* document() const; - FrameView* view() const; - - ChromeClient& chromeClient() const; - Editor& editor() const; - EventHandler& eventHandler() const; - FrameLoader& loader() const; - NavigationScheduler& navigationScheduler() const; - FrameSelection& selection() const; - FrameTree& tree() const; - AnimationController& animation() const; - InputMethodController& inputMethodController() const; - FetchContext& fetchContext() const { return loader().fetchContext(); } - ScriptController& script(); - SpellChecker& spellChecker() const; - - RenderView* contentRenderer() const; // Root of the render tree for the document contained in this frame. - RenderPart* ownerRenderer() const; // Renderer for the element that contains this frame. - - void dispatchVisibilityStateChangeEvent(); - - int64_t frameID() const { return m_frameInit->frameID(); } - - void setRemotePlatformLayer(blink::WebLayer* remotePlatformLayer) { m_remotePlatformLayer = remotePlatformLayer; } - blink::WebLayer* remotePlatformLayer() const { return m_remotePlatformLayer; } - - // ======== All public functions below this point are candidates to move out of Frame into another class. ======== - - bool inScope(TreeScope*) const; - - // See GraphicsLayerClient.h for accepted flags. - String layerTreeAsText(unsigned flags = 0) const; - String trackedRepaintRectsAsText() const; +class ChromeClient; +class FrameClient; +class FrameDestructionObserver; +class FrameHost; +class FrameOwner; +class HTMLFrameOwnerElement; +class LocalDOMWindow; +class Page; +class RenderPart; +class Settings; - Settings* settings() const; // can be NULL +class Frame : public RefCounted<Frame> { +public: + virtual bool isLocalFrame() const { return false; } + virtual bool isRemoteFrame() const { return false; } - void setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot); - bool shouldUsePrintingLayout() const; - FloatSize resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize); + virtual ~Frame(); - bool inViewSourceMode() const; - void setInViewSourceMode(bool = true); + void addDestructionObserver(FrameDestructionObserver*); + void removeDestructionObserver(FrameDestructionObserver*); - void setPageZoomFactor(float factor); - float pageZoomFactor() const { return m_pageZoomFactor; } - void setTextZoomFactor(float factor); - float textZoomFactor() const { return m_textZoomFactor; } - void setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor); + virtual void willDetachFrameHost(); + virtual void detachFromFrameHost(); - void deviceOrPageScaleFactorChanged(); - double devicePixelRatio() const; + FrameClient* client() const; + void clearClient(); -#if ENABLE(ORIENTATION_EVENTS) - // Orientation is the interface orientation in degrees. Some examples are: - // 0 is straight up; -90 is when the device is rotated 90 clockwise; - // 90 is when rotated counter clockwise. - void sendOrientationChangeEvent(int orientation); - int orientation() const { return m_orientation; } -#endif - - String documentTypeString() const; - - PassOwnPtr<DragImage> nodeImage(Node*); - PassOwnPtr<DragImage> dragImageForSelection(); + // NOTE: Page is moving out of Blink up into the browser process as + // part of the site-isolation (out of process iframes) work. + // FrameHost should be used instead where possible. + Page* page() const; + FrameHost* host() const; // Null when the frame is detached. - String selectedText() const; - String selectedTextForClipboard() const; + bool isMainFrame() const; - VisiblePosition visiblePositionForPoint(const IntPoint& framePoint); - Document* documentAtPoint(const IntPoint& windowPoint); - PassRefPtr<Range> rangeForPoint(const IntPoint& framePoint); + virtual void disconnectOwnerElement(); - // Should only be called on the main frame of a page. - void notifyChromeClientWheelEventHandlerCountChanged() const; + FrameOwner* owner() const; + HTMLFrameOwnerElement* deprecatedLocalOwner() const; - bool isURLAllowed(const KURL&) const; + // FIXME: LocalDOMWindow and Document should both be moved to LocalFrame + // after RemoteFrame is complete enough to exist without them. + virtual void setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow>); + LocalDOMWindow* domWindow() const; - // ======== + FrameTree& tree() const; + ChromeClient& chromeClient() const; - private: - Frame(PassRefPtr<FrameInit>); + RenderPart* ownerRenderer() const; // Renderer for the element that contains this frame. - HashSet<FrameDestructionObserver*> m_destructionObservers; + // FIXME: These should move to RemoteFrame when that is instantiated. + void setRemotePlatformLayer(blink::WebLayer* remotePlatformLayer) { m_remotePlatformLayer = remotePlatformLayer; } + blink::WebLayer* remotePlatformLayer() const { return m_remotePlatformLayer; } - Page* m_page; - mutable FrameTree m_treeNode; - mutable FrameLoader m_loader; - mutable NavigationScheduler m_navigationScheduler; + Settings* settings() const; // can be null - RefPtr<FrameView> m_view; - RefPtr<DOMWindow> m_domWindow; - - OwnPtr<ScriptController> m_script; - const OwnPtr<Editor> m_editor; - const OwnPtr<SpellChecker> m_spellChecker; - const OwnPtr<FrameSelection> m_selection; - const OwnPtr<EventHandler> m_eventHandler; - OwnPtr<AnimationController> m_animationController; - OwnPtr<InputMethodController> m_inputMethodController; - - RefPtr<FrameInit> m_frameInit; - - float m_pageZoomFactor; - float m_textZoomFactor; - -#if ENABLE(ORIENTATION_EVENTS) - int m_orientation; -#endif + // FIXME: This method identifies a LocalFrame that is acting as a RemoteFrame. + // It is necessary only until we can instantiate a RemoteFrame, at which point + // it can be removed and its callers can be converted to use the isRemoteFrame() + // method. + bool isRemoteFrameTemporary() const { return m_remotePlatformLayer; } - bool m_inViewSourceMode; +protected: + Frame(FrameClient*, FrameHost*, FrameOwner*); - blink::WebLayer* m_remotePlatformLayer; - }; + mutable FrameTree m_treeNode; - inline void Frame::init() - { - m_loader.init(); - } + FrameHost* m_host; + FrameOwner* m_owner; - inline FrameLoader& Frame::loader() const - { - return m_loader; - } - - inline NavigationScheduler& Frame::navigationScheduler() const - { - return m_navigationScheduler; - } - - inline FrameView* Frame::view() const - { - return m_view.get(); - } - - inline ScriptController& Frame::script() - { - return *m_script; - } - - inline DOMWindow* Frame::domWindow() const - { - return m_domWindow.get(); - } - - inline FrameSelection& Frame::selection() const - { - return *m_selection; - } - - inline Editor& Frame::editor() const - { - return *m_editor; - } - - inline SpellChecker& Frame::spellChecker() const - { - return *m_spellChecker; - } - - inline AnimationController& Frame::animation() const - { - return *m_animationController; - } - - inline InputMethodController& Frame::inputMethodController() const - { - return *m_inputMethodController; - } - - inline HTMLFrameOwnerElement* Frame::ownerElement() const - { - return m_frameInit->ownerElement(); - } - - inline bool Frame::inViewSourceMode() const - { - return m_inViewSourceMode; - } - - inline void Frame::setInViewSourceMode(bool mode) - { - m_inViewSourceMode = mode; - } - - inline FrameTree& Frame::tree() const - { - return m_treeNode; - } - - inline Page* Frame::page() const - { - return m_page; - } - - inline EventHandler& Frame::eventHandler() const - { - ASSERT(m_eventHandler); - return *m_eventHandler; - } + RefPtrWillBePersistent<LocalDOMWindow> m_domWindow; + +private: + FrameClient* m_client; + HashSet<FrameDestructionObserver*> m_destructionObservers; + + blink::WebLayer* m_remotePlatformLayer; +}; + +inline FrameClient* Frame::client() const +{ + return m_client; +} + +inline void Frame::clearClient() +{ + m_client = 0; +} + +inline LocalDOMWindow* Frame::domWindow() const +{ + return m_domWindow.get(); +} + +inline FrameOwner* Frame::owner() const +{ + return m_owner; +} + +inline FrameTree& Frame::tree() const +{ + return m_treeNode; +} + +// Allow equality comparisons of Frames by reference or pointer, interchangeably. +DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES_REFCOUNTED(Frame) } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameClient.h b/chromium/third_party/WebKit/Source/core/frame/FrameClient.h new file mode 100644 index 00000000000..79968742ec1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/FrameClient.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FrameClient_h +#define FrameClient_h + +namespace WebCore { + +class Frame; + +class FrameClient { +public: + virtual Frame* opener() const = 0; + virtual void setOpener(Frame*) = 0; + + virtual Frame* parent() const = 0; + virtual Frame* top() const = 0; + virtual Frame* previousSibling() const = 0; + virtual Frame* nextSibling() const = 0; + virtual Frame* firstChild() const = 0; + virtual Frame* lastChild() const = 0; + + virtual ~FrameClient() { } +}; + +} // namespace WebCore + +#endif // FrameClient_h diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameConsole.cpp b/chromium/third_party/WebKit/Source/core/frame/FrameConsole.cpp new file mode 100644 index 00000000000..bc1a1106605 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/FrameConsole.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/frame/FrameConsole.h" + +#include "core/dom/Document.h" +#include "core/frame/FrameHost.h" +#include "core/inspector/ConsoleAPITypes.h" +#include "core/inspector/InspectorConsoleInstrumentation.h" +#include "core/page/Chrome.h" +#include "core/page/ChromeClient.h" +#include "core/page/Page.h" +#include "wtf/text/StringBuilder.h" + +namespace WebCore { + +namespace { + +int muteCount = 0; + +} + +FrameConsole::FrameConsole(LocalFrame& frame) + : m_frame(frame) +{ +} + +void FrameConsole::addMessage(MessageSource source, MessageLevel level, const String& message) +{ + addMessage(source, level, message, String(), 0, 0, nullptr, 0, 0); +} + +void FrameConsole::addMessage(MessageSource source, MessageLevel level, const String& message, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) +{ + addMessage(source, level, message, String(), 0, 0, callStack, 0); +} + +void FrameConsole::addMessage(MessageSource source, MessageLevel level, const String& message, const String& url, unsigned lineNumber, unsigned columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack, ScriptState* scriptState, unsigned long requestIdentifier) +{ + if (muteCount) + return; + + // FIXME: This should not need to reach for the main-frame. + // Inspector code should just take the current frame and know how to walk itself. + ExecutionContext* context = m_frame.document(); + if (!context) + return; + + String messageURL; + if (callStack) { + messageURL = callStack->at(0).sourceURL(); + InspectorInstrumentation::addMessageToConsole(context, source, LogMessageType, level, message, callStack, requestIdentifier); + } else { + messageURL = url; + InspectorInstrumentation::addMessageToConsole(context, source, LogMessageType, level, message, url, lineNumber, columnNumber, scriptState, requestIdentifier); + } + + if (source == CSSMessageSource) + return; + + String stackTrace; + if (callStack && m_frame.chromeClient().shouldReportDetailedMessageForSource(messageURL)) + stackTrace = FrameConsole::formatStackTraceString(message, callStack); + + m_frame.chromeClient().addMessageToConsole(&m_frame, source, level, message, lineNumber, messageURL, stackTrace); +} + +String FrameConsole::formatStackTraceString(const String& originalMessage, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack) +{ + StringBuilder stackTrace; + for (size_t i = 0; i < callStack->size(); ++i) { + const ScriptCallFrame& frame = callStack->at(i); + stackTrace.append("\n at " + (frame.functionName().length() ? frame.functionName() : "(anonymous function)")); + stackTrace.append(" ("); + stackTrace.append(frame.sourceURL()); + stackTrace.append(':'); + stackTrace.append(String::number(frame.lineNumber())); + stackTrace.append(':'); + stackTrace.append(String::number(frame.columnNumber())); + stackTrace.append(')'); + } + + return stackTrace.toString(); +} + +void FrameConsole::mute() +{ + muteCount++; +} + +void FrameConsole::unmute() +{ + ASSERT(muteCount > 0); + muteCount--; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.h b/chromium/third_party/WebKit/Source/core/frame/FrameConsole.h index 6ffd75c1a83..05146e003d3 100644 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.h +++ b/chromium/third_party/WebKit/Source/core/frame/FrameConsole.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,29 +26,39 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CSSPropertyAnimation_h -#define CSSPropertyAnimation_h +#ifndef FrameConsole_h +#define FrameConsole_h -#include "CSSPropertyNames.h" +#include "bindings/v8/ScriptState.h" +#include "core/frame/ConsoleTypes.h" +#include "core/inspector/ScriptCallStack.h" +#include "wtf/Forward.h" +#include "wtf/PassOwnPtr.h" namespace WebCore { -class AnimationBase; -class RenderStyle; +class FrameHost; -class CSSPropertyAnimation { +// FrameConsole takes per-frame console messages and routes them up through the FrameHost to the ChromeClient and Inspector. +// It's meant as an abstraction around ChromeClient calls and the way that Blink core/ can add messages to the console. +class FrameConsole FINAL { public: - static bool animationOfPropertyIsAccelerated(CSSPropertyID); - static bool propertiesEqual(CSSPropertyID, const RenderStyle* a, const RenderStyle* b); - static CSSPropertyID getPropertyAtIndex(int, bool& isShorthand); - static int getNumProperties(); + static PassOwnPtr<FrameConsole> create(LocalFrame& frame) { return adoptPtr(new FrameConsole(frame)); } + + void addMessage(MessageSource, MessageLevel, const String& message); + void addMessage(MessageSource, MessageLevel, const String& message, const String& sourceURL, unsigned lineNumber, unsigned columnNumber = 0, PassRefPtrWillBeRawPtr<ScriptCallStack> = nullptr, ScriptState* = 0, unsigned long requestIdentifier = 0); + void addMessage(MessageSource, MessageLevel, const String& message, PassRefPtrWillBeRawPtr<ScriptCallStack>); + static String formatStackTraceString(const String& originalMessage, PassRefPtrWillBeRawPtr<ScriptCallStack>); + + static void mute(); + static void unmute(); - // Return true if we need to start software animation timers - static bool blendProperties(const AnimationBase*, CSSPropertyID, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress); private: - static void ensurePropertyMap(); + explicit FrameConsole(LocalFrame&); + + LocalFrame& m_frame; }; } // namespace WebCore -#endif // CSSPropertyAnimation_h +#endif // FrameConsole_h diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.cpp b/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.cpp index ea3923e5cdc..7ab5868c9a4 100644 --- a/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.cpp @@ -26,11 +26,11 @@ #include "config.h" #include "core/frame/FrameDestructionObserver.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -FrameDestructionObserver::FrameDestructionObserver(Frame* frame) +FrameDestructionObserver::FrameDestructionObserver(LocalFrame* frame) : m_frame(0) { observeFrame(frame); @@ -42,7 +42,7 @@ FrameDestructionObserver::~FrameDestructionObserver() } -void FrameDestructionObserver::observeFrame(Frame* frame) +void FrameDestructionObserver::observeFrame(LocalFrame* frame) { if (m_frame) m_frame->removeDestructionObserver(this); @@ -58,7 +58,7 @@ void FrameDestructionObserver::frameDestroyed() m_frame = 0; } -void FrameDestructionObserver::willDetachPage() +void FrameDestructionObserver::willDetachFrameHost() { // Subclasses should override this function to handle this notification. } diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.h b/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.h index 8989e4a9f53..db7341f1dae 100644 --- a/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.h +++ b/chromium/third_party/WebKit/Source/core/frame/FrameDestructionObserver.h @@ -28,22 +28,22 @@ namespace WebCore { -class Frame; +class LocalFrame; class FrameDestructionObserver { public: - explicit FrameDestructionObserver(Frame*); + explicit FrameDestructionObserver(LocalFrame*); virtual void frameDestroyed(); - virtual void willDetachPage(); + virtual void willDetachFrameHost(); - Frame* frame() const { return m_frame; } + LocalFrame* frame() const { return m_frame; } protected: virtual ~FrameDestructionObserver(); - void observeFrame(Frame*); + void observeFrame(LocalFrame*); - Frame* m_frame; + LocalFrame* m_frame; }; } diff --git a/chromium/third_party/WebKit/Source/core/frame/GraphicsLayerDebugInfo.h b/chromium/third_party/WebKit/Source/core/frame/FrameHost.cpp index 26d2fce117a..cc562c9076f 100644 --- a/chromium/third_party/WebKit/Source/core/frame/GraphicsLayerDebugInfo.h +++ b/chromium/third_party/WebKit/Source/core/frame/FrameHost.cpp @@ -28,23 +28,67 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GraphicsLayerDebugInfo_h -#define GraphicsLayerDebugInfo_h +#include "config.h" +#include "core/frame/FrameHost.h" -#include "platform/geometry/LayoutRect.h" -#include "public/platform/WebGraphicsLayerDebugInfo.h" - -#include "wtf/Vector.h" +#include "core/frame/EventHandlerRegistry.h" +#include "core/page/Chrome.h" +#include "core/page/ChromeClient.h" +#include "core/page/Page.h" namespace WebCore { -class GraphicsLayerDebugInfo FINAL : public blink::WebGraphicsLayerDebugInfo { -public: - virtual void appendAsTraceFormat(blink::WebString* out) const OVERRIDE; - virtual ~GraphicsLayerDebugInfo() { }; - Vector<LayoutRect> m_currentLayoutRects; -}; +PassOwnPtrWillBeRawPtr<FrameHost> FrameHost::create(Page& page) +{ + return adoptPtrWillBeNoop(new FrameHost(page)); +} + +FrameHost::FrameHost(Page& page) + : m_page(&page) + , m_pinchViewport(adoptPtr(new PinchViewport(*this))) + , m_eventHandlerRegistry(adoptPtrWillBeNoop(new EventHandlerRegistry(*this))) +{ +} + +// Explicitly in the .cpp to avoid default constructor in .h +FrameHost::~FrameHost() +{ +} + +Settings& FrameHost::settings() const +{ + return m_page->settings(); +} + +Chrome& FrameHost::chrome() const +{ + return m_page->chrome(); +} + +UseCounter& FrameHost::useCounter() const +{ + return m_page->useCounter(); +} + +float FrameHost::deviceScaleFactor() const +{ + return m_page->deviceScaleFactor(); +} + +PinchViewport& FrameHost::pinchViewport() const +{ + return *m_pinchViewport; +} + +EventHandlerRegistry& FrameHost::eventHandlerRegistry() const +{ + return *m_eventHandlerRegistry; +} -} // namespace WebCore +void FrameHost::trace(Visitor* visitor) +{ + visitor->trace(m_page); + visitor->trace(m_eventHandlerRegistry); +} -#endif +} diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameHost.h b/chromium/third_party/WebKit/Source/core/frame/FrameHost.h new file mode 100644 index 00000000000..494e17161d9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/FrameHost.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FrameHost_h +#define FrameHost_h + +#include "core/frame/PinchViewport.h" +#include "platform/heap/Handle.h" +#include "wtf/FastAllocBase.h" +#include "wtf/Noncopyable.h" +#include "wtf/OwnPtr.h" +#include "wtf/PassOwnPtr.h" + +namespace WebCore { + +class Chrome; +class EventHandlerRegistry; +class Page; +class PinchViewport; +class Settings; +class UseCounter; +class Visitor; + +// FrameHost is the set of global data shared between multiple frames +// and is provided by the embedder to each frame when created. +// FrameHost currently corresponds to the Page object in core/page +// however the concept of a Page is moving up out of Blink. +// In an out-of-process iframe world, a single Page may have +// multiple frames in different process, thus Page becomes a +// browser-level concept and Blink core/ only knows about its LocalFrame (and FrameHost). +// Separating Page from the rest of core/ through this indirection +// allows us to slowly refactor Page without breaking the rest of core. +class FrameHost FINAL : public NoBaseWillBeGarbageCollectedFinalized<FrameHost> { + WTF_MAKE_NONCOPYABLE(FrameHost); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; +public: + static PassOwnPtrWillBeRawPtr<FrameHost> create(Page&); + ~FrameHost(); + + // Careful: This function will eventually be removed. + Page& page() const { return *m_page; } + Settings& settings() const; + Chrome& chrome() const; + UseCounter& useCounter() const; + + // Corresponds to pixel density of the device where this Page is + // being displayed. In multi-monitor setups this can vary between pages. + // This value does not account for Page zoom, use LocalFrame::devicePixelRatio instead. + float deviceScaleFactor() const; + + PinchViewport& pinchViewport() const; + EventHandlerRegistry& eventHandlerRegistry() const; + + void trace(Visitor*); + +private: + explicit FrameHost(Page&); + + RawPtrWillBeMember<Page> m_page; + const OwnPtr<PinchViewport> m_pinchViewport; + const OwnPtrWillBeMember<EventHandlerRegistry> m_eventHandlerRegistry; +}; + +} + +#endif // FrameHost_h diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameOwner.h b/chromium/third_party/WebKit/Source/core/frame/FrameOwner.h new file mode 100644 index 00000000000..f8c7d1d7788 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/FrameOwner.h @@ -0,0 +1,24 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FrameOwner_h +#define FrameOwner_h + +#include "core/dom/SandboxFlags.h" + +namespace WebCore { + +class FrameOwner { +public: + virtual ~FrameOwner() { } + + virtual bool isLocal() const = 0; + + virtual SandboxFlags sandboxFlags() const = 0; + virtual void dispatchLoad() = 0; +}; + +} // namespace WebCore + +#endif // FrameOwner_h diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameView.cpp b/chromium/third_party/WebKit/Source/core/frame/FrameView.cpp index 5bb9474eec3..c7e788df777 100644 --- a/chromium/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/FrameView.cpp @@ -27,26 +27,24 @@ #include "config.h" #include "core/frame/FrameView.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" +#include "core/HTMLNames.h" #include "core/accessibility/AXObjectCache.h" -#include "core/animation/DocumentAnimations.h" #include "core/css/FontFaceSet.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/DocumentMarkerController.h" +#include "core/dom/ScriptForbiddenScope.h" #include "core/editing/FrameSelection.h" #include "core/events/OverflowEvent.h" #include "core/fetch/ResourceFetcher.h" #include "core/fetch/ResourceLoadPriorityOptimizer.h" -#include "core/fetch/TextResourceDecoder.h" -#include "core/frame/Frame.h" -#include "core/frame/GraphicsLayerDebugInfo.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" -#include "core/frame/animation/AnimationController.h" #include "core/html/HTMLFrameElement.h" -#include "core/html/HTMLHtmlElement.h" #include "core/html/HTMLPlugInElement.h" +#include "core/html/parser/TextResourceDecoder.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" #include "core/page/Chrome.h" @@ -55,26 +53,30 @@ #include "core/page/FocusController.h" #include "core/page/FrameTree.h" #include "core/page/scrolling/ScrollingCoordinator.h" -#include "core/rendering/CompositedLayerMapping.h" -#include "core/rendering/LayoutIndicator.h" +#include "core/rendering/FastTextAutosizer.h" #include "core/rendering/RenderCounter.h" #include "core/rendering/RenderEmbeddedObject.h" #include "core/rendering/RenderLayer.h" -#include "core/rendering/RenderLayerCompositor.h" +#include "core/rendering/RenderListBox.h" #include "core/rendering/RenderPart.h" #include "core/rendering/RenderScrollbar.h" #include "core/rendering/RenderScrollbarPart.h" #include "core/rendering/RenderTheme.h" #include "core/rendering/RenderView.h" +#include "core/rendering/RenderWidget.h" #include "core/rendering/TextAutosizer.h" +#include "core/rendering/compositing/CompositedLayerMapping.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" #include "core/rendering/style/RenderStyle.h" #include "core/rendering/svg/RenderSVGRoot.h" -#include "core/svg/SVGDocument.h" +#include "core/svg/SVGDocumentExtensions.h" #include "core/svg/SVGSVGElement.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" #include "platform/fonts/FontCache.h" #include "platform/geometry/FloatRect.h" #include "platform/graphics/GraphicsContext.h" +#include "platform/graphics/GraphicsLayerDebugInfo.h" #include "platform/scroll/ScrollAnimator.h" #include "platform/scroll/ScrollbarTheme.h" #include "platform/text/TextStream.h" @@ -88,88 +90,26 @@ using namespace HTMLNames; double FrameView::s_currentFrameTimeStamp = 0.0; bool FrameView::s_inPaintContents = false; - -// REPAINT_THROTTLING now chooses default values for throttling parameters. -// Should be removed when applications start using runtime configuration. -#if ENABLE(REPAINT_THROTTLING) -// Normal delay -double FrameView::s_normalDeferredRepaintDelay = 0.016; -// Negative value would mean that first few repaints happen without a delay -double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; -// The delay grows on each repaint to this maximum value -double FrameView::s_maxDeferredRepaintDelayDuringLoading = 2.5; -// On each repaint the delay increses by this amount -double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0.5; -#else -// FIXME: Repaint throttling could be good to have on all platform. -// The balance between CPU use and repaint frequency will need some tuning for desktop. -// More hooks may be needed to reset the delay on things like GIF and CSS animations. -double FrameView::s_normalDeferredRepaintDelay = 0; -double FrameView::s_initialDeferredRepaintDelayDuringLoading = 0; -double FrameView::s_maxDeferredRepaintDelayDuringLoading = 0; -double FrameView::s_deferredRepaintDelayIncrementDuringLoading = 0; -#endif - // The maximum number of updateWidgets iterations that should be done before returning. static const unsigned maxUpdateWidgetsIterations = 2; +static const double resourcePriorityUpdateDelayAfterScroll = 0.250; -static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullRepaint) +static RenderLayer::UpdateLayerPositionsFlags updateLayerPositionFlags(RenderLayer* layer, bool isRelayoutingSubtree, bool didFullPaintInvalidation) { - RenderLayer::UpdateLayerPositionsFlags flags = RenderLayer::defaultFlags; + RenderLayer::UpdateLayerPositionsFlags flags = didFullPaintInvalidation ? RenderLayer::NeedsFullRepaintInBacking : RenderLayer::CheckForRepaint; - if (didFullRepaint) { - flags &= ~RenderLayer::CheckForRepaint; - flags |= RenderLayer::NeedsFullRepaintInBacking; - } - if (isRelayoutingSubtree && layer->isPaginated()) + if (isRelayoutingSubtree && (layer->isPaginated() || layer->enclosingPaginationLayer())) flags |= RenderLayer::UpdatePagination; - return flags; -} - -Pagination::Mode paginationModeForRenderStyle(RenderStyle* style) -{ - EOverflow overflow = style->overflowY(); - if (overflow != OPAGEDX && overflow != OPAGEDY) - return Pagination::Unpaginated; - - bool isHorizontalWritingMode = style->isHorizontalWritingMode(); - TextDirection textDirection = style->direction(); - WritingMode writingMode = style->writingMode(); - // paged-x always corresponds to LeftToRightPaginated or RightToLeftPaginated. If the WritingMode - // is horizontal, then we use TextDirection to choose between those options. If the WritingMode - // is vertical, then the direction of the verticality dictates the choice. - if (overflow == OPAGEDX) { - if ((isHorizontalWritingMode && textDirection == LTR) || writingMode == LeftToRightWritingMode) - return Pagination::LeftToRightPaginated; - return Pagination::RightToLeftPaginated; - } - - // paged-y always corresponds to TopToBottomPaginated or BottomToTopPaginated. If the WritingMode - // is horizontal, then the direction of the horizontality dictates the choice. If the WritingMode - // is vertical, then we use TextDirection to choose between those options. - if (writingMode == TopToBottomWritingMode || (!isHorizontalWritingMode && textDirection == RTL)) - return Pagination::TopToBottomPaginated; - return Pagination::BottomToTopPaginated; -} - -FrameView::DeferredRepaintScope::DeferredRepaintScope(FrameView& view) - : m_view(&view) -{ - m_view->beginDeferredRepaints(); -} - -FrameView::DeferredRepaintScope::~DeferredRepaintScope() -{ - m_view->endDeferredRepaints(); + return flags; } -FrameView::FrameView(Frame* frame) +FrameView::FrameView(LocalFrame* frame) : m_frame(frame) , m_canHaveScrollbars(true) , m_slowRepaintObjectCount(0) - , m_layoutTimer(this, &FrameView::layoutTimerFired) - , m_layoutRoot(0) + , m_hasPendingLayout(false) + , m_layoutSubtreeRoot(0) , m_inSynchronousPostLayout(false) , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) , m_updateWidgetsTimer(this, &FrameView::updateWidgetsTimerFired) @@ -181,9 +121,7 @@ FrameView::FrameView(Frame* frame) , m_wasScrolledByUser(false) , m_inProgrammaticScroll(false) , m_safeToPropagateScrollToParent(true) - , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired) - , m_isTrackingRepaints(false) - , m_shouldUpdateWhileOffscreen(true) + , m_isTrackingPaintInvalidations(false) , m_scrollCorner(0) , m_shouldAutoSize(false) , m_inAutoSize(false) @@ -191,27 +129,27 @@ FrameView::FrameView(Frame* frame) , m_hasSoftwareFilters(false) , m_visibleContentScaleFactor(1) , m_inputEventsScaleFactorForEmulation(1) - , m_partialLayout() , m_layoutSizeFixedToFrameSize(true) + , m_didScrollTimer(this, &FrameView::didScrollTimerFired) { ASSERT(m_frame); init(); - if (!isMainFrame()) + if (!m_frame->isMainFrame()) return; ScrollableArea::setVerticalScrollElasticity(ScrollElasticityAllowed); ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityAllowed); } -PassRefPtr<FrameView> FrameView::create(Frame* frame) +PassRefPtr<FrameView> FrameView::create(LocalFrame* frame) { RefPtr<FrameView> view = adoptRef(new FrameView(frame)); view->show(); return view.release(); } -PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize) +PassRefPtr<FrameView> FrameView::create(LocalFrame* frame, const IntSize& initialSize) { RefPtr<FrameView> view = adoptRef(new FrameView(frame)); view->Widget::setFrameRect(IntRect(view->location(), initialSize)); @@ -226,6 +164,9 @@ FrameView::~FrameView() if (m_postLayoutTasksTimer.isActive()) m_postLayoutTasksTimer.stop(); + if (m_didScrollTimer.isActive()) + m_didScrollTimer.stop(); + removeFromAXObjectCache(); resetScrollbars(); @@ -240,9 +181,10 @@ FrameView::~FrameView() ASSERT(m_frame); ASSERT(m_frame->view() != this || !m_frame->contentRenderer()); - RenderPart* renderer = m_frame->ownerRenderer(); - if (renderer && renderer->widget() == this) - renderer->setWidget(0); + // FIXME: Do we need to do something here for OOPI? + HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner(); + if (ownerElement && ownerElement->ownedWidget() == this) + ownerElement->setWidget(nullptr); } void FrameView::reset() @@ -250,15 +192,12 @@ void FrameView::reset() m_cannotBlitToWindow = false; m_isOverlapped = false; m_contentIsOpaque = false; - m_borderX = 30; - m_borderY = 30; - m_layoutTimer.stop(); - m_layoutRoot = 0; - m_delayedLayout = false; - m_doFullRepaint = true; + m_hasPendingLayout = false; + m_layoutSubtreeRoot = 0; + m_doFullPaintInvalidation = false; m_layoutSchedulingEnabled = true; - m_inLayout = false; - m_doingPreLayoutStyleUpdate = false; + m_inPerformLayout = false; + m_canInvalidatePaintDuringPerformLayout = false; m_inSynchronousPostLayout = false; m_layoutCount = 0; m_nestedLayoutCount = 0; @@ -270,13 +209,8 @@ void FrameView::reset() m_safeToPropagateScrollToParent = true; m_lastViewportSize = IntSize(); m_lastZoomFactor = 1.0f; - m_deferringRepaints = 0; - m_repaintCount = 0; - m_repaintRects.clear(); - m_deferredRepaintDelay = s_initialDeferredRepaintDelayDuringLoading; - m_deferredRepaintTimer.stop(); - m_isTrackingRepaints = false; - m_trackedRepaintRects.clear(); + m_isTrackingPaintInvalidations = false; + m_trackedPaintInvalidationRects.clear(); m_lastPaintTime = 0; m_paintBehavior = PaintBehaviorNormal; m_isPainting = false; @@ -284,8 +218,7 @@ void FrameView::reset() m_visuallyNonEmptyPixelCount = 0; m_isVisuallyNonEmpty = false; m_firstVisuallyNonEmptyLayoutCallbackPending = true; - m_maintainScrollPositionAnchor = 0; - m_partialLayout.reset(); + m_maintainScrollPositionAnchor = nullptr; m_viewportConstrainedObjects.clear(); } @@ -311,27 +244,21 @@ void FrameView::init() { reset(); - m_margins = LayoutSize(-1, -1); // undefined m_size = LayoutSize(); // Propagate the marginwidth/height and scrolling modes to the view. - Element* ownerElement = m_frame->ownerElement(); - if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) { + // FIXME: Do we need to do this for OOPI? + Element* ownerElement = m_frame->deprecatedLocalOwner(); + if (ownerElement && (isHTMLFrameElement(*ownerElement) || isHTMLIFrameElement(*ownerElement))) { HTMLFrameElementBase* frameElt = toHTMLFrameElementBase(ownerElement); if (frameElt->scrollingMode() == ScrollbarAlwaysOff) setCanHaveScrollbars(false); - LayoutUnit marginWidth = frameElt->marginWidth(); - LayoutUnit marginHeight = frameElt->marginHeight(); - if (marginWidth != -1) - setMarginWidth(marginWidth); - if (marginHeight != -1) - setMarginHeight(marginHeight); } } void FrameView::prepareForDetach() { - RELEASE_ASSERT(!isInLayout()); + RELEASE_ASSERT(!isInPerformLayout()); if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) scrollAnimator->cancelAnimations(); @@ -369,15 +296,13 @@ void FrameView::recalculateScrollbarOverlayStyle() ScrollbarOverlayStyle overlayStyle = ScrollbarOverlayStyleDefault; Color backgroundColor = documentBackgroundColor(); - if (backgroundColor.isValid()) { - // Reduce the background color from RGB to a lightness value - // and determine which scrollbar style to use based on a lightness - // heuristic. - double hue, saturation, lightness; - backgroundColor.getHSL(hue, saturation, lightness); - if (lightness <= .5) - overlayStyle = ScrollbarOverlayStyleLight; - } + // Reduce the background color from RGB to a lightness value + // and determine which scrollbar style to use based on a lightness + // heuristic. + double hue, saturation, lightness; + backgroundColor.getHSL(hue, saturation, lightness); + if (lightness <= .5) + overlayStyle = ScrollbarOverlayStyleLight; if (oldOverlayStyle != overlayStyle) setScrollbarOverlayStyle(overlayStyle); @@ -385,13 +310,7 @@ void FrameView::recalculateScrollbarOverlayStyle() void FrameView::clear() { - setCanBlitOnScroll(true); - reset(); - - if (RenderPart* renderer = m_frame->ownerRenderer()) - renderer->viewCleared(); - setScrollbarsSuppressed(true); } @@ -412,10 +331,10 @@ void FrameView::invalidateRect(const IntRect& rect) if (!renderer) return; - IntRect repaintRect = rect; - repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(), + IntRect paintInvalidationRect = rect; + paintInvalidationRect.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop()); - renderer->repaintRectangle(repaintRect); + renderer->invalidatePaintRectangle(paintInvalidationRect); } void FrameView::setFrameRect(const IntRect& newRect) @@ -425,12 +344,14 @@ void FrameView::setFrameRect(const IntRect& newRect) return; // Autosized font sizes depend on the width of the viewing area. + bool autosizerNeedsUpdating = false; if (newRect.width() != oldRect.width()) { - Page* page = m_frame->page(); - if (isMainFrame() && page->settings().textAutosizingEnabled()) { - TextAutosizer* textAutosizer = m_frame->document()->textAutosizer(); - if (textAutosizer) { - for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) + if (m_frame->isMainFrame() && m_frame->settings()->textAutosizingEnabled()) { + autosizerNeedsUpdating = true; + for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext()) { + if (!frame->isLocalFrame()) + continue; + if (TextAutosizer* textAutosizer = toLocalFrame(frame)->document()->textAutosizer()) textAutosizer->recalculateMultipliers(); } } @@ -440,10 +361,23 @@ void FrameView::setFrameRect(const IntRect& newRect) updateScrollableAreaSet(); + if (autosizerNeedsUpdating) { + // This needs to be after the call to ScrollView::setFrameRect, because it reads the new width. + if (FastTextAutosizer* textAutosizer = m_frame->document()->fastTextAutosizer()) + textAutosizer->updatePageInfoInAllFrames(); + } + if (RenderView* renderView = this->renderView()) { if (renderView->usesCompositing()) renderView->compositor()->frameViewDidChangeSize(); } + + viewportConstrainedVisibleContentSizeChanged(newRect.width() != oldRect.width(), newRect.height() != oldRect.height()); + + if (oldRect.size() != newRect.size() + && m_frame->isMainFrame() + && m_frame->settings()->pinchVirtualViewportEnabled()) + page()->frameHost().pinchViewport().mainFrameDidChangeSize(); } bool FrameView::scheduleAnimation() @@ -455,21 +389,14 @@ bool FrameView::scheduleAnimation() return false; } -RenderView* FrameView::renderView() const -{ - return frame().contentRenderer(); -} - -void FrameView::setMarginWidth(LayoutUnit w) +Page* FrameView::page() const { - // make it update the rendering area when set - m_margins.setWidth(w); + return frame().page(); } -void FrameView::setMarginHeight(LayoutUnit h) +RenderView* FrameView::renderView() const { - // make it update the rendering area when set - m_margins.setHeight(h); + return frame().contentRenderer(); } void FrameView::setCanHaveScrollbars(bool canHaveScrollbars) @@ -478,24 +405,13 @@ void FrameView::setCanHaveScrollbars(bool canHaveScrollbars) ScrollView::setCanHaveScrollbars(canHaveScrollbars); } -void FrameView::updateCanHaveScrollbars() -{ - ScrollbarMode hMode; - ScrollbarMode vMode; - scrollbarModes(hMode, vMode); - if (hMode == ScrollbarAlwaysOff && vMode == ScrollbarAlwaysOff) - setCanHaveScrollbars(false); - else - setCanHaveScrollbars(true); -} - -bool FrameView::shouldUseCustomScrollbars(Element*& customScrollbarElement, Frame*& customScrollbarFrame) +bool FrameView::shouldUseCustomScrollbars(Element*& customScrollbarElement, LocalFrame*& customScrollbarFrame) { customScrollbarElement = 0; customScrollbarFrame = 0; if (Settings* settings = m_frame->settings()) { - if (!settings->allowCustomScrollbarInMainFrame() && isMainFrame()) + if (!settings->allowCustomScrollbarInMainFrame() && m_frame->isMainFrame()) return false; } @@ -516,7 +432,7 @@ bool FrameView::shouldUseCustomScrollbars(Element*& customScrollbarElement, Fram return true; } - // If we have an owning ipage/Frame element, then it can set the custom scrollbar also. + // If we have an owning ipage/LocalFrame element, then it can set the custom scrollbar also. RenderPart* frameRenderer = m_frame->ownerRenderer(); if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR)) { customScrollbarFrame = m_frame.get(); @@ -529,7 +445,7 @@ bool FrameView::shouldUseCustomScrollbars(Element*& customScrollbarElement, Fram PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation) { Element* customScrollbarElement = 0; - Frame* customScrollbarFrame = 0; + LocalFrame* customScrollbarFrame = 0; if (shouldUseCustomScrollbars(customScrollbarElement, customScrollbarFrame)) return RenderScrollbar::createCustomScrollbar(this, orientation, customScrollbarElement, customScrollbarFrame); @@ -554,6 +470,20 @@ void FrameView::setContentsSize(const IntSize& size) page->chrome().contentsSizeChanged(m_frame.get(), size); } +IntPoint FrameView::clampOffsetAtScale(const IntPoint& offset, float scale) const +{ + IntPoint maxScrollExtent(contentsSize().width() - scrollOrigin().x(), contentsSize().height() - scrollOrigin().y()); + FloatSize scaledSize = unscaledVisibleContentSize(); + if (scale) + scaledSize.scale(1 / scale); + + IntPoint clampedOffset = offset; + clampedOffset = clampedOffset.shrunkTo(maxScrollExtent - expandedIntSize(scaledSize)); + clampedOffset = clampedOffset.expandedTo(-scrollOrigin()); + + return clampedOffset; +} + void FrameView::adjustViewSize() { RenderView* renderView = this->renderView(); @@ -569,7 +499,7 @@ void FrameView::adjustViewSize() setContentsSize(size); } -void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode) +void FrameView::applyOverflowToViewportAndSetRenderer(RenderObject* o, ScrollbarMode& hMode, ScrollbarMode& vMode) { // Handle the overflow:hidden/scroll case for the body/html elements. WinIE treats // overflow:hidden and overflow:scroll on <body> as applying to the document's @@ -580,11 +510,16 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S EOverflow overflowY = o->style()->overflowY(); if (o->isSVGRoot()) { - // overflow is ignored in stand-alone SVG documents. - if (!toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument()) + // Don't allow overflow to affect <img> and css backgrounds + if (toRenderSVGRoot(o)->isEmbeddedThroughSVGImage()) return; - overflowX = OHIDDEN; - overflowY = OHIDDEN; + + // FIXME: evaluate if we can allow overflow for these cases too. + // Overflow is always hidden when stand-alone SVG documents are embedded. + if (toRenderSVGRoot(o)->isEmbeddedThroughFrameContainingSVGDocument()) { + overflowX = OHIDDEN; + overflowY = OHIDDEN; + } } bool ignoreOverflowHidden = false; @@ -619,46 +554,19 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S vMode = ScrollbarAuto; break; default: - // Don't set it at all. Values of OPAGEDX and OPAGEDY are handled by applyPaginationToViewPort(). + // Don't set it at all. ; } m_viewportRenderer = o; } -void FrameView::applyPaginationToViewport() -{ - Document* document = m_frame->document(); - Node* documentElement = document->documentElement(); - RenderObject* documentRenderer = documentElement ? documentElement->renderer() : 0; - RenderObject* documentOrBodyRenderer = documentRenderer; - Node* body = document->body(); - if (body && body->renderer()) { - if (body->hasTagName(bodyTag)) - documentOrBodyRenderer = documentRenderer->style()->overflowX() == OVISIBLE && isHTMLHtmlElement(documentElement) ? body->renderer() : documentRenderer; - } - - Pagination pagination; - - if (!documentOrBodyRenderer) { - setPagination(pagination); - return; - } - - EOverflow overflowY = documentOrBodyRenderer->style()->overflowY(); - if (overflowY == OPAGEDX || overflowY == OPAGEDY) { - pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style()); - pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style()->columnGap()); - } - - setPagination(pagination); -} - -void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy) +void FrameView::calculateScrollbarModesForLayoutAndSetViewportRenderer(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy strategy) { m_viewportRenderer = 0; - const HTMLFrameOwnerElement* owner = m_frame->ownerElement(); + // FIXME: How do we handle this for OOPI? + const HTMLFrameOwnerElement* owner = m_frame->deprecatedLocalOwner(); if (owner && (owner->scrollingMode() == ScrollbarAlwaysOff)) { hMode = ScrollbarAlwaysOff; vMode = ScrollbarAlwaysOff; @@ -667,71 +575,61 @@ void FrameView::calculateScrollbarModesForLayout(ScrollbarMode& hMode, Scrollbar if (m_canHaveScrollbars || strategy == RulesFromWebContentOnly) { hMode = ScrollbarAuto; - // Seamless documents begin with heights of 0; we special case that here - // to correctly render documents that don't need scrollbars. - IntSize fullVisibleSize = visibleContentRect(IncludeScrollbars).size(); - bool isSeamlessDocument = frame().document() && frame().document()->shouldDisplaySeamlesslyWithParent(); - vMode = (isSeamlessDocument && !fullVisibleSize.height()) ? ScrollbarAlwaysOff : ScrollbarAuto; + vMode = ScrollbarAuto; } else { hMode = ScrollbarAlwaysOff; vMode = ScrollbarAlwaysOff; } - if (!m_layoutRoot) { + if (!isSubtreeLayout()) { Document* document = m_frame->document(); - Node* documentElement = document->documentElement(); - RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0; Node* body = document->body(); - if (body && body->renderer()) { - if (body->hasTagName(framesetTag)) { - vMode = ScrollbarAlwaysOff; - hMode = ScrollbarAlwaysOff; - } else if (body->hasTagName(bodyTag)) { - // It's sufficient to just check the X overflow, - // since it's illegal to have visible in only one direction. - RenderObject* o = rootRenderer->style()->overflowX() == OVISIBLE && isHTMLHtmlElement(document->documentElement()) ? body->renderer() : rootRenderer; - if (o->style()) - applyOverflowToViewport(o, hMode, vMode); + if (isHTMLFrameSetElement(body) && body->renderer()) { + vMode = ScrollbarAlwaysOff; + hMode = ScrollbarAlwaysOff; + } else if (Element* viewportElement = document->viewportDefiningElement()) { + if (RenderObject* viewportRenderer = viewportElement->renderer()) { + if (viewportRenderer->style()) + applyOverflowToViewportAndSetRenderer(viewportRenderer, hMode, vMode); } - } else if (rootRenderer) - applyOverflowToViewport(rootRenderer, hMode, vMode); + } } } -void FrameView::updateCompositingLayersAfterStyleChange() +void FrameView::updateAcceleratedCompositingSettings() +{ + if (RenderView* renderView = this->renderView()) + renderView->compositor()->updateAcceleratedCompositingSettings(); +} + +void FrameView::recalcOverflowAfterStyleChange() { - TRACE_EVENT0("webkit", "FrameView::updateCompositingLayersAfterStyleChange"); RenderView* renderView = this->renderView(); - if (!renderView) + ASSERT(renderView); + if (!renderView->needsOverflowRecalcAfterStyleChange()) return; - // If we expect to update compositing after an incipient layout, don't do so here. - if (m_doingPreLayoutStyleUpdate || layoutPending() || renderView->needsLayout()) - return; + renderView->recalcOverflowAfterStyleChange(); - // This call will make sure the cached hasAcceleratedCompositing is updated from the pref - renderView->compositor()->cacheAcceleratedCompositingFlags(); + if (needsLayout()) + return; - // Sometimes we will change a property (for example, z-index) that will not - // cause a layout, but will require us to update compositing state. We only - // need to do this if a layout is not already scheduled. - if (!needsLayout()) - renderView->compositor()->updateCompositingRequirementsState(); + InUpdateScrollbarsScope inUpdateScrollbarsScope(this); - renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterStyleChange); -} + bool shouldHaveHorizontalScrollbar = false; + bool shouldHaveVerticalScrollbar = false; + computeScrollbarExistence(shouldHaveHorizontalScrollbar, shouldHaveVerticalScrollbar); -void FrameView::updateCompositingLayersAfterLayout() -{ - TRACE_EVENT0("webkit", "FrameView::updateCompositingLayersAfterLayout"); - RenderView* renderView = this->renderView(); - if (!renderView) + bool hasHorizontalScrollbar = horizontalScrollbar(); + bool hasVerticalScrollbar = verticalScrollbar(); + if (hasHorizontalScrollbar != shouldHaveHorizontalScrollbar + || hasVerticalScrollbar != shouldHaveVerticalScrollbar) { + setNeedsLayout(); return; + } - // This call will make sure the cached hasAcceleratedCompositing is updated from the pref - renderView->compositor()->cacheAcceleratedCompositingFlags(); - renderView->compositor()->updateCompositingRequirementsState(); - renderView->compositor()->updateCompositingLayers(CompositingUpdateAfterLayout); + adjustViewSize(); + updateScrollbarGeometry(); } bool FrameView::usesCompositedScrolling() const @@ -740,7 +638,7 @@ bool FrameView::usesCompositedScrolling() const if (!renderView) return false; if (m_frame->settings() && m_frame->settings()->compositedScrollingForFramesEnabled()) - return renderView->compositor()->inForcedCompositingMode(); + return renderView->compositor()->inCompositingMode(); return false; } @@ -778,15 +676,19 @@ GraphicsLayer* FrameView::layerForScrollCorner() const bool FrameView::hasCompositedContent() const { + // FIXME: change to inCompositingMode. Fails fast/repaint/iframe-scroll-repaint.html. if (RenderView* renderView = this->renderView()) - return renderView->compositor()->inCompositingMode(); + return renderView->compositor()->staleInCompositingMode(); return false; } bool FrameView::isEnclosedInCompositingLayer() const { + // FIXME: It's a bug that compositing state isn't always up to date when this is called. crbug.com/366314 + DisableCompositingQueryAsserts disabler; + RenderObject* frameOwnerRenderer = m_frame->ownerRenderer(); - if (frameOwnerRenderer && frameOwnerRenderer->containerForRepaint()) + if (frameOwnerRenderer && frameOwnerRenderer->enclosingLayer()->enclosingCompositingLayerForRepaint()) return true; if (FrameView* parentView = parentFrameView()) @@ -795,28 +697,9 @@ bool FrameView::isEnclosedInCompositingLayer() const return false; } -bool FrameView::isSoftwareRenderable() const -{ - RenderView* renderView = this->renderView(); - return !renderView || !renderView->compositor()->has3DContent(); -} - RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const { - return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot; -} - -static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews) -{ - const HashSet<RefPtr<Widget> >* viewChildren = frameView->children(); - ASSERT(viewChildren); - - const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end(); - for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) { - Widget* widget = (*current).get(); - if (widget->isFrameView()) - frameViews.append(toFrameView(widget)); - } + return onlyDuringLayout && layoutPending() ? 0 : m_layoutSubtreeRoot; } inline void FrameView::forceLayoutParentViewIfNeeded() @@ -843,7 +726,7 @@ inline void FrameView::forceLayoutParentViewIfNeeded() RefPtr<FrameView> frameView = ownerRenderer->frame()->view(); // Mark the owner renderer as needing layout. - ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc(); + ownerRenderer->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); // Synchronously enter layout, to layout the view containing the host object/embed/iframe. ASSERT(frameView); @@ -852,20 +735,25 @@ inline void FrameView::forceLayoutParentViewIfNeeded() void FrameView::performPreLayoutTasks() { + TRACE_EVENT0("webkit", "FrameView::performPreLayoutTasks"); + lifecycle().advanceTo(DocumentLifecycle::InPreLayout); + // Don't schedule more layouts, we're in one. TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false); - if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive() && !frame().document()->shouldDisplaySeamlesslyWithParent()) { + if (!m_nestedLayoutCount && !m_inSynchronousPostLayout && m_postLayoutTasksTimer.isActive()) { // This is a new top-level layout. If there are any remaining tasks from the previous layout, finish them now. m_inSynchronousPostLayout = true; performPostLayoutTasks(); m_inSynchronousPostLayout = false; } - // Viewport-dependent media queries may cause us to need completely different style information. Document* document = m_frame->document(); - if (!document->styleResolver() || document->styleResolver()->affectedByViewportChange()) { - document->styleResolverChanged(RecalcStyleDeferred); + document->notifyResizeForViewportUnits(); + + // Viewport-dependent media queries may cause us to need completely different style information. + if (!document->styleResolver() || document->styleResolver()->mediaQueryAffectedByViewportChange()) { + document->styleResolverChanged(); document->mediaQueryAffectingValueChanged(); // FIXME: This instrumentation event is not strictly accurate since cached media query results @@ -875,65 +763,50 @@ void FrameView::performPreLayoutTasks() document->evaluateMediaQueryList(); } - // If there is any pagination to apply, it will affect the RenderView's style, so we should - // take care of that now. - applyPaginationToViewport(); - - // Always ensure our style info is up-to-date. This can happen in situations where - // the layout beats any sort of style recalc update that needs to occur. - TemporaryChange<bool> changeDoingPreLayoutStyleUpdate(m_doingPreLayoutStyleUpdate, true); - document->updateStyleIfNeeded(); + document->updateRenderTreeIfNeeded(); + lifecycle().advanceTo(DocumentLifecycle::StyleClean); } void FrameView::performLayout(RenderObject* rootForThisLayout, bool inSubtreeLayout) { + TRACE_EVENT0("webkit", "FrameView::performLayout"); + + ScriptForbiddenScope forbidScript; + + ASSERT(!isInPerformLayout()); + lifecycle().advanceTo(DocumentLifecycle::InPerformLayout); + + TemporaryChange<bool> changeInPerformLayout(m_inPerformLayout, true); + // performLayout is the actual guts of layout(). // FIXME: The 300 other lines in layout() probably belong in other helper functions // so that a single human could understand what layout() is actually doing. - FrameView::DeferredRepaintScope deferRepaints(*this); - { - bool disableLayoutState = false; - if (inSubtreeLayout) { - RenderView* view = rootForThisLayout->view(); - disableLayoutState = view->shouldDisableLayoutStateForSubtree(rootForThisLayout); - view->pushLayoutState(rootForThisLayout); - } - LayoutStateDisabler layoutStateDisabler(disableLayoutState ? rootForThisLayout->view() : 0); + LayoutState layoutState(*rootForThisLayout); - m_inLayout = true; + forceLayoutParentViewIfNeeded(); - forceLayoutParentViewIfNeeded(); + // FIXME (crbug.com/256657): Do not do two layouts for text autosizing. + rootForThisLayout->layout(); + gatherDebugLayoutRects(rootForThisLayout); - // Text Autosizing requires two-pass layout which is incompatible with partial layout. - // If enabled, only do partial layout for the second layout. - // FIXME (crbug.com/256657): Do not do two layouts for text autosizing. - PartialLayoutDisabler partialLayoutDisabler(partialLayout(), m_frame->settings() && m_frame->settings()->textAutosizingEnabled()); - - LayoutIndicator layoutIndicator; - rootForThisLayout->layout(); - gatherDebugLayoutRects(rootForThisLayout); + ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities(); - ResourceLoadPriorityOptimizer modifier; - rootForThisLayout->didLayout(modifier); + TextAutosizer* textAutosizer = frame().document()->textAutosizer(); + bool autosized; + { + AllowPaintInvalidationScope paintInvalidationAllowed(this); + autosized = textAutosizer && textAutosizer->processSubtree(rootForThisLayout); } - TextAutosizer* textAutosizer = frame().document()->textAutosizer(); - bool autosized = textAutosizer && textAutosizer->processSubtree(rootForThisLayout); if (autosized && rootForThisLayout->needsLayout()) { TRACE_EVENT0("webkit", "2nd layout due to Text Autosizing"); - LayoutIndicator layoutIndicator; + UseCounter::count(*frame().document(), UseCounter::TextAutosizingLayout); rootForThisLayout->layout(); gatherDebugLayoutRects(rootForThisLayout); - - ResourceLoadPriorityOptimizer modifier; - rootForThisLayout->didLayout(modifier); } - m_inLayout = false; - - if (inSubtreeLayout) - rootForThisLayout->view()->popLayoutState(rootForThisLayout); + lifecycle().advanceTo(DocumentLifecycle::AfterPerformLayout); } void FrameView::scheduleOrPerformPostLayoutTasks() @@ -941,47 +814,34 @@ void FrameView::scheduleOrPerformPostLayoutTasks() if (m_postLayoutTasksTimer.isActive()) return; - // Partial layouts should not happen with synchronous post layouts. - ASSERT(!(m_inSynchronousPostLayout && partialLayout().isStopping())); - if (!m_inSynchronousPostLayout) { - if (frame().document()->shouldDisplaySeamlesslyWithParent()) { - if (RenderView* renderView = this->renderView()) - renderView->updateWidgetPositions(); - } else { - m_inSynchronousPostLayout = true; - // Calls resumeScheduledEvents() - performPostLayoutTasks(); - m_inSynchronousPostLayout = false; - } + m_inSynchronousPostLayout = true; + // Calls resumeScheduledEvents() + performPostLayoutTasks(); + m_inSynchronousPostLayout = false; } - if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout || frame().document()->shouldDisplaySeamlesslyWithParent())) { + if (!m_postLayoutTasksTimer.isActive() && (needsLayout() || m_inSynchronousPostLayout)) { // If we need layout or are already in a synchronous call to postLayoutTasks(), // defer widget updates and event dispatch until after we return. postLayoutTasks() // can make us need to update again, and we can get stuck in a nasty cycle unless // we call it through the timer here. - m_postLayoutTasksTimer.startOneShot(0); - if (!partialLayout().isStopping() && needsLayout()) + m_postLayoutTasksTimer.startOneShot(0, FROM_HERE); + if (needsLayout()) layout(); } } void FrameView::layout(bool allowSubtree) { - // We should never layout a Document which is not in a Frame. + // We should never layout a Document which is not in a LocalFrame. ASSERT(m_frame); ASSERT(m_frame->view() == this); ASSERT(m_frame->page()); - if (m_inLayout) + if (isInPerformLayout() || !m_frame->document()->isActive()) return; - if (!m_frame->document()->isActive()) - return; - - ASSERT(!partialLayout().isStopping()); - TRACE_EVENT0("webkit", "FrameView::layout"); TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "Layout"); @@ -991,23 +851,19 @@ void FrameView::layout(bool allowSubtree) // Every scroll that happens during layout is programmatic. TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true); - m_layoutTimer.stop(); - m_delayedLayout = false; + m_hasPendingLayout = false; + DocumentLifecycle::Scope lifecycleScope(lifecycle(), DocumentLifecycle::LayoutClean); - // we shouldn't enter layout() while painting - ASSERT(!isPainting()); - if (isPainting()) - return; - - // Store the current maximal outline size to use when computing the old/new - // outline rects for repainting. - renderView()->setOldMaximalOutlineSize(renderView()->maximalOutlineSize()); + RELEASE_ASSERT(!isPainting()); + TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Layout", "beginData", InspectorLayoutEvent::beginData(this)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willLayout(m_frame.get()); - if (!allowSubtree && m_layoutRoot) { - m_layoutRoot->markContainingBlocksForLayout(false); - m_layoutRoot = 0; + if (!allowSubtree && isSubtreeLayout()) { + m_layoutSubtreeRoot->markContainingBlocksForLayout(false); + m_layoutSubtreeRoot = 0; } performPreLayoutTasks(); @@ -1018,29 +874,27 @@ void FrameView::layout(bool allowSubtree) return; Document* document = m_frame->document(); - bool inSubtreeLayout = m_layoutRoot; - RenderObject* rootForThisLayout = inSubtreeLayout ? m_layoutRoot : document->renderer(); + bool inSubtreeLayout = isSubtreeLayout(); + RenderObject* rootForThisLayout = inSubtreeLayout ? m_layoutSubtreeRoot : document->renderView(); if (!rootForThisLayout) { // FIXME: Do we need to set m_size here? ASSERT_NOT_REACHED(); return; } - bool isPartialLayout = partialLayout().isPartialLayout(); - FontCachePurgePreventer fontCachePurgePreventer; RenderLayer* layer; { TemporaryChange<bool> changeSchedulingEnabled(m_layoutSchedulingEnabled, false); m_nestedLayoutCount++; - if (!m_layoutRoot) { + if (!inSubtreeLayout) { Document* document = m_frame->document(); Node* body = document->body(); if (body && body->renderer()) { - if (body->hasTagName(framesetTag)) { + if (isHTMLFrameSetElement(*body)) { body->renderer()->setChildNeedsLayout(); - } else if (body->hasTagName(bodyTag)) { + } else if (isHTMLBodyElement(*body)) { if (!m_firstLayout && m_size.height() != layoutSize().height() && body->renderer()->enclosingBox()->stretchesToViewport()) body->renderer()->setChildNeedsLayout(); } @@ -1051,121 +905,109 @@ void FrameView::layout(bool allowSubtree) ScrollbarMode hMode; ScrollbarMode vMode; - calculateScrollbarModesForLayout(hMode, vMode); - - m_doFullRepaint = !inSubtreeLayout && !isPartialLayout && (m_firstLayout || toRenderView(rootForThisLayout)->document().printing()); + calculateScrollbarModesForLayoutAndSetViewportRenderer(hMode, vMode); - if (!inSubtreeLayout && !isPartialLayout) { + if (!inSubtreeLayout) { // Now set our scrollbar state for the layout. ScrollbarMode currentHMode = horizontalScrollbarMode(); ScrollbarMode currentVMode = verticalScrollbarMode(); - if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { - if (m_firstLayout) { - setScrollbarsSuppressed(true); - - m_firstLayout = false; - m_firstLayoutCallbackPending = true; - m_lastViewportSize = layoutSize(IncludeScrollbars); - m_lastZoomFactor = rootForThisLayout->style()->zoom(); - - // Set the initial vMode to AlwaysOn if we're auto. - if (vMode == ScrollbarAuto) - setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. - // Set the initial hMode to AlwaysOff if we're auto. - if (hMode == ScrollbarAuto) - setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear. - - setScrollbarModes(hMode, vMode); - setScrollbarsSuppressed(false, true); - } else - setScrollbarModes(hMode, vMode); + if (m_firstLayout) { + setScrollbarsSuppressed(true); + + m_doFullPaintInvalidation = true; + m_firstLayout = false; + m_firstLayoutCallbackPending = true; + m_lastViewportSize = layoutSize(IncludeScrollbars); + m_lastZoomFactor = rootForThisLayout->style()->zoom(); + + // Set the initial vMode to AlwaysOn if we're auto. + if (vMode == ScrollbarAuto) + setVerticalScrollbarMode(ScrollbarAlwaysOn); // This causes a vertical scrollbar to appear. + // Set the initial hMode to AlwaysOff if we're auto. + if (hMode == ScrollbarAuto) + setHorizontalScrollbarMode(ScrollbarAlwaysOff); // This causes a horizontal scrollbar to disappear. + + setScrollbarModes(hMode, vMode); + setScrollbarsSuppressed(false, true); + } else if (hMode != currentHMode || vMode != currentVMode) { + setScrollbarModes(hMode, vMode); } LayoutSize oldSize = m_size; m_size = LayoutSize(layoutSize().width(), layoutSize().height()); - if (oldSize != m_size) { - m_doFullRepaint = true; - if (!m_firstLayout) { - RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0; - RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0; - if (bodyRenderer && bodyRenderer->stretchesToViewport()) - bodyRenderer->setChildNeedsLayout(); - else if (rootRenderer && rootRenderer->stretchesToViewport()) - rootRenderer->setChildNeedsLayout(); - } + if (oldSize != m_size && !m_firstLayout) { + RenderBox* rootRenderer = document->documentElement() ? document->documentElement()->renderBox() : 0; + RenderBox* bodyRenderer = rootRenderer && document->body() ? document->body()->renderBox() : 0; + if (bodyRenderer && bodyRenderer->stretchesToViewport()) + bodyRenderer->setChildNeedsLayout(); + else if (rootRenderer && rootRenderer->stretchesToViewport()) + rootRenderer->setChildNeedsLayout(); } + + // We need to set m_doFullPaintInvalidation before triggering layout as RenderObject::checkForPaintInvalidation + // checks the boolean to disable local paint invalidations. + m_doFullPaintInvalidation |= renderView()->shouldDoFullRepaintForNextLayout(); } layer = rootForThisLayout->enclosingLayer(); performLayout(rootForThisLayout, inSubtreeLayout); - m_layoutRoot = 0; + m_layoutSubtreeRoot = 0; } // Reset m_layoutSchedulingEnabled to its previous value. - bool neededFullRepaint = m_doFullRepaint; - - if (!inSubtreeLayout && !isPartialLayout && !toRenderView(rootForThisLayout)->document().printing()) + if (!inSubtreeLayout && !toRenderView(rootForThisLayout)->document().printing()) adjustViewSize(); - m_doFullRepaint = neededFullRepaint; - - { - // FIXME: Can this scope just encompass this entire function? - FrameView::DeferredRepaintScope deferRepaints(*this); - - if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) { - if (m_doFullRepaint) - renderView()->setShouldDoFullRepaintAfterLayout(true); - - if (m_doFullRepaint || !partialLayout().isStopping()) - repaintTree(rootForThisLayout); - - } else if (m_doFullRepaint) { - // 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. - renderView()->repaint(); - } - layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, inSubtreeLayout, m_doFullRepaint)); - } - updateCompositingLayersAfterLayout(); + layer->updateLayerPositionsAfterLayout(renderView()->layer(), updateLayerPositionFlags(layer, inSubtreeLayout, m_doFullPaintInvalidation)); + renderView()->compositor()->didLayout(); m_layoutCount++; - if (AXObjectCache* cache = rootForThisLayout->document().existingAXObjectCache()) - cache->postNotification(rootForThisLayout, AXObjectCache::AXLayoutComplete, true); + if (AXObjectCache* cache = rootForThisLayout->document().axObjectCache()) { + const KURL& url = rootForThisLayout->document().url(); + if (url.isValid() && !url.isAboutBlankURL()) + cache->handleLayoutComplete(rootForThisLayout); + } updateAnnotatedRegions(); - ASSERT(partialLayout().isStopping() || !rootForThisLayout->needsLayout()); - - updateCanBlitOnScrollRecursively(); + ASSERT(!rootForThisLayout->needsLayout()); if (document->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) updateOverflowStatus(layoutSize().width() < contentsWidth(), layoutSize().height() < contentsHeight()); scheduleOrPerformPostLayoutTasks(); + TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Layout", "endData", InspectorLayoutEvent::endData(rootForThisLayout)); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didLayout(cookie, rootForThisLayout); m_nestedLayoutCount--; if (m_nestedLayoutCount) return; - if (partialLayout().isStopping()) - return; + if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) { + invalidateTree(rootForThisLayout); + } else if (m_doFullPaintInvalidation) { + // 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. + renderView()->paintInvalidationForWholeRenderer(); + } + + m_doFullPaintInvalidation = false; #ifndef NDEBUG // Post-layout assert that nobody was re-marked as needing layout during layout. - document->renderer()->assertSubtreeIsLaidOut(); + document->renderView()->assertSubtreeIsLaidOut(); #endif // FIXME: It should be not possible to remove the FrameView from the frame/page during layout - // however m_inLayout is not set for most of this function, so none of our RELEASE_ASSERTS - // in Frame/Page will fire. One of the post-layout tasks is disconnecting the Frame from + // however m_inPerformLayout is not set for most of this function, so none of our RELEASE_ASSERTS + // in LocalFrame/Page will fire. One of the post-layout tasks is disconnecting the LocalFrame from // the page in fast/frames/crash-remove-iframe-during-object-beforeload-2.html // necessitating this check here. // ASSERT(frame()->page()); @@ -1173,46 +1015,39 @@ void FrameView::layout(bool allowSubtree) frame().page()->chrome().client().layoutUpdated(m_frame.get()); } -// The plan is to move to compositor-queried repainting, in which case this +// The plan is to move to compositor-queried paint invalidation, in which case this // method would setNeedsRedraw on the GraphicsLayers with invalidations and // let the compositor pick which to actually draw. // See http://crbug.com/306706 -void FrameView::repaintTree(RenderObject* root) +void FrameView::invalidateTree(RenderObject* root) { ASSERT(RuntimeEnabledFeatures::repaintAfterLayoutEnabled()); ASSERT(!root->needsLayout()); + // We should only invalidate paints for the outer most layout. This works as + // we continue to track paint invalidation rects until this function is called. + ASSERT(!m_nestedLayoutCount); - for (RenderObject* renderer = root; renderer; renderer = renderer->nextInPreOrder()) { - const LayoutRect& oldRepaintRect = renderer->oldRepaintRect(); - const LayoutRect& newRepaintRect = renderer->newRepaintRect(); - - LayoutRect oldOutlineRect = oldRepaintRect; - oldOutlineRect.inflate(renderView()->oldMaximalOutlineSize()); - - LayoutRect newOutlineRect = newRepaintRect; - newOutlineRect.inflate(renderView()->maximalOutlineSize()); - - // FIXME: Currently renderers with layers will get repainted when we call updateLayerPositionsAfterLayout. - // That call should be broken apart to position the layers be done before - // the repaintTree call so this will repaint everything. - bool didFullRepaint = false; - if (!renderer->hasLayer()) { - if (!renderer->layoutDidGetCalled()) { - if (renderer->shouldDoFullRepaintAfterLayout()) { - renderer->repaint(); - didFullRepaint = true; - } + TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", root->debugName().ascii()); - } else { - didFullRepaint = renderer->repaintAfterLayoutIfNeeded(renderer->containerForRepaint(), renderer->shouldDoFullRepaintAfterLayout(), - oldRepaintRect, oldOutlineRect, &newRepaintRect, &newOutlineRect); - } - } - if (!didFullRepaint && renderer->shouldRepaintOverflowIfNeeded()) - renderer->repaintOverflow(); - renderer->clearRepaintRects(); - } - renderView()->setOldMaximalOutlineSize(0); + // FIXME: really, we're in the paint invalidation phase here, and the compositing queries are legal. + // Until those states are fully fledged, I'll just disable the ASSERTS. + DisableCompositingQueryAsserts compositingQueryAssertsDisabler; + + LayoutState rootLayoutState(*root); + + root->invalidateTreeAfterLayout(*root->containerForPaintInvalidation()); + + // Invalidate the paint of the frameviews scrollbars if needed + if (hasVerticalBarDamage()) + invalidateRect(verticalBarDamage()); + if (hasHorizontalBarDamage()) + invalidateRect(horizontalBarDamage()); + resetScrollbarDamage(); +} + +DocumentLifecycle& FrameView::lifecycle() const +{ + return m_frame->document()->lifecycle(); } void FrameView::gatherDebugLayoutRects(RenderObject* layoutRoot) @@ -1227,19 +1062,19 @@ void FrameView::gatherDebugLayoutRects(RenderObject* layoutRoot) if (!graphicsLayer) return; - GraphicsLayerDebugInfo* debugInfo = new GraphicsLayerDebugInfo(); + GraphicsLayerDebugInfo& debugInfo = graphicsLayer->debugInfo(); + + debugInfo.currentLayoutRects().clear(); for (RenderObject* renderer = layoutRoot; renderer; renderer = renderer->nextInPreOrder()) { if (renderer->layoutDidGetCalled()) { - LayoutRect rect = renderer->newRepaintRect(); - debugInfo->m_currentLayoutRects.append(rect); + FloatQuad quad = renderer->localToAbsoluteQuad(FloatQuad(renderer->previousPaintInvalidationRect())); + LayoutRect rect = quad.enclosingBoundingBox(); + debugInfo.currentLayoutRects().append(rect); renderer->setLayoutDidGetCalled(false); } } - - graphicsLayer->setDebugInfo(debugInfo); } - RenderBox* FrameView::embeddedContentBox() const { RenderView* renderView = this->renderView(); @@ -1257,11 +1092,38 @@ RenderBox* FrameView::embeddedContentBox() const return 0; } + +void FrameView::addWidget(RenderWidget* object) +{ + m_widgets.add(object); +} + +void FrameView::removeWidget(RenderWidget* object) +{ + m_widgets.remove(object); +} + +void FrameView::updateWidgetPositions() +{ + Vector<RefPtr<RenderWidget> > widgets; + copyToVector(m_widgets, widgets); + + // Script or plugins could detach the frame so abort processing if that happens. + + for (size_t i = 0; i < widgets.size() && renderView(); ++i) + widgets[i]->updateWidgetPosition(); + + for (size_t i = 0; i < widgets.size() && renderView(); ++i) + widgets[i]->widgetPositionsUpdated(); +} + void FrameView::addWidgetToUpdate(RenderEmbeddedObject& object) { + ASSERT(isInPerformLayout()); // Tell the DOM element that it needs a widget update. Node* node = object.node(); - if (node->hasTagName(objectTag) || node->hasTagName(embedTag)) + ASSERT(node); + if (isHTMLObjectElement(*node) || isHTMLEmbedElement(*node)) toHTMLPlugInElement(node)->setNeedsWidgetUpdate(true); m_widgetUpdateSet.add(&object); @@ -1280,7 +1142,7 @@ AtomicString FrameView::mediaType() const String overrideType; InspectorInstrumentation::applyEmulatedMedia(m_frame.get(), &overrideType); if (!overrideType.isNull()) - return overrideType; + return AtomicString(overrideType); return m_mediaType; } @@ -1299,19 +1161,28 @@ void FrameView::adjustMediaTypeForPrinting(bool printing) bool FrameView::useSlowRepaints(bool considerOverlap) const { - bool mustBeSlow = m_slowRepaintObjectCount > 0; + // FIXME: It is incorrect to determine blit-scrolling eligibility using dirty compositing state. + // https://code.google.com/p/chromium/issues/detail?id=357345 + DisableCompositingQueryAsserts disabler; + + if (m_slowRepaintObjectCount > 0) + return true; if (contentsInCompositedLayer()) - return mustBeSlow; + return false; // The chromium compositor does not support scrolling a non-composited frame within a composited page through // the fast scrolling path, so force slow scrolling in that case. - if (m_frame->ownerElement() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->view()->hasCompositedContent()) + if (m_frame->owner() && !hasCompositedContent() && m_frame->page() && m_frame->page()->mainFrame()->isLocalFrame() && m_frame->page()->deprecatedLocalMainFrame()->view()->hasCompositedContent()) + return true; + + if (m_isOverlapped && considerOverlap) return true; - bool isOverlapped = m_isOverlapped && considerOverlap; + if (m_cannotBlitToWindow) + return true; - if (mustBeSlow || m_cannotBlitToWindow || isOverlapped || !m_contentIsOpaque) + if (!m_contentIsOpaque) return true; if (FrameView* parentView = parentFrameView()) @@ -1325,12 +1196,9 @@ bool FrameView::useSlowRepaintsIfNotOverlapped() const return useSlowRepaints(false); } -void FrameView::updateCanBlitOnScrollRecursively() +bool FrameView::shouldAttemptToScrollUsingFastPath() const { - for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) { - if (FrameView* view = frame->view()) - view->setCanBlitOnScroll(!view->useSlowRepaints()); - } + return !useSlowRepaints(); } bool FrameView::contentsInCompositedLayer() const @@ -1348,14 +1216,11 @@ bool FrameView::contentsInCompositedLayer() const void FrameView::setCannotBlitToWindow() { m_cannotBlitToWindow = true; - updateCanBlitOnScrollRecursively(); } void FrameView::addSlowRepaintObject() { if (!m_slowRepaintObjectCount++) { - updateCanBlitOnScrollRecursively(); - if (Page* page = m_frame->page()) { if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this); @@ -1368,8 +1233,6 @@ void FrameView::removeSlowRepaintObject() ASSERT(m_slowRepaintObjectCount > 0); m_slowRepaintObjectCount--; if (!m_slowRepaintObjectCount) { - updateCanBlitOnScrollRecursively(); - if (Page* page = m_frame->page()) { if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) scrollingCoordinator->frameViewHasSlowRepaintObjectsDidChange(this); @@ -1396,14 +1259,11 @@ void FrameView::removeViewportConstrainedObject(RenderObject* object) { if (m_viewportConstrainedObjects && m_viewportConstrainedObjects->contains(object)) { m_viewportConstrainedObjects->remove(object); + if (Page* page = m_frame->page()) { if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) scrollingCoordinator->frameViewFixedObjectsDidChange(this); } - - // FIXME: In addFixedObject() we only call this if there's a platform widget, - // why isn't the same check being made here? - updateCanBlitOnScrollRecursively(); } } @@ -1415,6 +1275,39 @@ LayoutRect FrameView::viewportConstrainedVisibleContentRect() const return viewportRect; } +void FrameView::viewportConstrainedVisibleContentSizeChanged(bool widthChanged, bool heightChanged) +{ + if (!hasViewportConstrainedObjects()) + return; + + // If viewport is not enabled, frameRect change will cause layout size change and then layout. + // Otherwise, viewport constrained objects need their layout flags set separately to ensure + // they are positioned correctly. In the virtual-viewport pinch mode frame rect changes wont + // necessarily cause a layout size change so only take this early-out if we're in old-style + // pinch. + if (m_frame->settings() + && !m_frame->settings()->viewportEnabled() + && !m_frame->settings()->pinchVirtualViewportEnabled()) + return; + + ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); + for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { + RenderObject* renderer = *it; + RenderStyle* style = renderer->style(); + if (widthChanged) { + if (style->width().isFixed() && (style->left().isAuto() || style->right().isAuto())) + renderer->setNeedsPositionedMovementLayout(); + else + renderer->setNeedsLayoutAndFullPaintInvalidation(); + } + if (heightChanged) { + if (style->height().isFixed() && (style->top().isAuto() || style->bottom().isAuto())) + renderer->setNeedsPositionedMovementLayout(); + else + renderer->setNeedsLayoutAndFullPaintInvalidation(); + } + } +} IntSize FrameView::scrollOffsetForFixedPosition() const { @@ -1429,7 +1322,27 @@ IntPoint FrameView::lastKnownMousePosition() const bool FrameView::shouldSetCursor() const { Page* page = frame().page(); - return page && page->visibilityState() != PageVisibilityStateHidden && page->focusController().isActive(); + return page && page->visibilityState() != PageVisibilityStateHidden && page->focusController().isActive() && page->settings().deviceSupportsMouse(); +} + +void FrameView::scrollContentsIfNeededRecursive() +{ + scrollContentsIfNeeded(); + + for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) { + if (!child->isLocalFrame()) + continue; + if (FrameView* view = toLocalFrame(child)->view()) + view->scrollContentsIfNeededRecursive(); + } +} + +void FrameView::scrollContentsIfNeeded() +{ + bool didScroll = !pendingScrollDelta().isZero(); + ScrollView::scrollContentsIfNeeded(); + if (didScroll) + updateFixedElementPaintInvalidationRectsAfterScroll(); } bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) @@ -1446,16 +1359,16 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { RenderObject* renderer = *it; - if (!renderer->style()->hasViewportConstrainedPosition()) - continue; + // m_viewportConstrainedObjects should not contain non-viewport constrained objects. + ASSERT(renderer->style()->hasViewportConstrainedPosition()); // Fixed items should always have layers. ASSERT(renderer->hasLayer()); RenderLayer* layer = toRenderBoxModelObject(renderer)->layer(); // Layers that paint into their ancestor or into a grouped backing will still need - // to apply a repaint invalidation. If the layer paints into its own backing, then - // it does not need repainting just to scroll. + // to apply a paint invalidation. If the layer paints into its own backing, then + // it does not need paint invalidation just to scroll. if (layer->compositingState() == PaintsIntoOwnBacking) continue; @@ -1473,19 +1386,21 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect IntRect updateRect = pixelSnappedIntRect(layer->repainter().repaintRectIncludingNonCompositingDescendants()); - RenderLayer* enclosingCompositingLayer = layer->enclosingCompositingLayer(false); - if (enclosingCompositingLayer && !enclosingCompositingLayer->renderer()->isRenderView()) { + const RenderLayerModelObject* repaintContainer = layer->renderer()->containerForPaintInvalidation(); + if (repaintContainer && !repaintContainer->isRenderView()) { // If the fixed-position layer is contained by a composited layer that is not its containing block, - // then we have to invlidate that enclosing layer, not the RenderView. + // then we have to invalidate that enclosing layer, not the RenderView. + // FIXME: Why do we need to issue this invalidation? Won't the fixed position element just scroll + // with the enclosing layer. updateRect.moveBy(scrollPosition()); IntRect previousRect = updateRect; previousRect.move(scrollDelta); updateRect.unite(previousRect); - enclosingCompositingLayer->repainter().setBackingNeedsRepaintInRect(updateRect); + layer->renderer()->invalidatePaintUsingContainer(repaintContainer, updateRect, InvalidationScroll); } else { - // Coalesce the repaints that will be issued to the renderView. + // Coalesce the paint invalidations that will be issued to the renderView. updateRect = contentsToRootView(updateRect); - if (!isCompositedContentLayer && clipsRepaints()) + if (!isCompositedContentLayer && clipsPaintInvalidations()) updateRect.intersect(rectToScroll); if (!updateRect.isEmpty()) regionToUpdate.unite(updateRect); @@ -1501,7 +1416,7 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect for (size_t i = 0; i < viewportConstrainedObjectsCount; ++i) { IntRect updateRect = subRectsToUpdate[i]; IntRect scrolledRect = updateRect; - scrolledRect.move(scrollDelta); + scrolledRect.move(-scrollDelta); updateRect.unite(scrolledRect); if (isCompositedContentLayer) { updateRect = rootViewToContents(updateRect); @@ -1509,7 +1424,7 @@ bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect renderView()->layer()->repainter().setBackingNeedsRepaintInRect(updateRect); continue; } - if (clipsRepaints()) + if (clipsPaintInvalidations()) updateRect.intersect(rectToScroll); hostWindow()->invalidateContentsAndRootView(updateRect); } @@ -1529,7 +1444,7 @@ void FrameView::scrollContentsSlowPath(const IntRect& updateRect) LayoutRect rect(frameRenderer->borderLeft() + frameRenderer->paddingLeft(), frameRenderer->borderTop() + frameRenderer->paddingTop(), visibleWidth(), visibleHeight()); - frameRenderer->repaintRectangle(rect); + frameRenderer->invalidatePaintRectangle(rect); return; } } @@ -1540,33 +1455,12 @@ void FrameView::scrollContentsSlowPath(const IntRect& updateRect) // Note that this gets called at painting time. void FrameView::setIsOverlapped(bool isOverlapped) { - if (isOverlapped == m_isOverlapped) - return; - m_isOverlapped = isOverlapped; - updateCanBlitOnScrollRecursively(); -} - -bool FrameView::isOverlappedIncludingAncestors() const -{ - if (isOverlapped()) - return true; - - if (FrameView* parentView = parentFrameView()) { - if (parentView->isOverlapped()) - return true; - } - - return false; } void FrameView::setContentIsOpaque(bool contentIsOpaque) { - if (contentIsOpaque == m_contentIsOpaque) - return; - m_contentIsOpaque = contentIsOpaque; - updateCanBlitOnScrollRecursively(); } void FrameView::restoreScrollbar() @@ -1578,7 +1472,7 @@ bool FrameView::scrollToFragment(const KURL& url) { // If our URL has no ref, then we have no place we need to jump to. // OTOH If CSS target was set previously, we want to set it to 0, recalc - // and possibly repaint because :target pseudo class may have been + // and possibly paint invalidation because :target pseudo class may have been // set (see bug 11321). if (!url.hasFragmentIdentifier() && !m_frame->document()->cssTarget()) return false; @@ -1598,7 +1492,7 @@ bool FrameView::scrollToAnchor(const String& name) { ASSERT(m_frame->document()); - if (!m_frame->document()->haveStylesheetsLoaded()) { + if (!m_frame->document()->isRenderingReady()) { m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); return false; } @@ -1611,7 +1505,7 @@ bool FrameView::scrollToAnchor(const String& name) m_frame->document()->setCSSTarget(anchorNode); if (m_frame->document()->isSVGDocument()) { - if (SVGSVGElement* svg = toSVGDocument(m_frame->document())->rootElement()) { + if (SVGSVGElement* svg = SVGDocumentExtensions::rootElement(*m_frame->document())) { svg->setupInitialView(name, anchorNode); if (!anchorNode) return true; @@ -1639,7 +1533,7 @@ void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode) // We need to update the layout before scrolling, otherwise we could // really mess things up if an anchor scroll comes at a bad moment. - m_frame->document()->updateStyleIfNeeded(); + m_frame->document()->updateRenderTreeIfNeeded(); // Only do a layout if changes have occurred that make it necessary. RenderView* renderView = this->renderView(); if (renderView && renderView->needsLayout()) @@ -1650,18 +1544,42 @@ void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode) void FrameView::scrollElementToRect(Element* element, const IntRect& rect) { + // FIXME(http://crbug.com/371896) - This method shouldn't be manually doing + // coordinate transformations to the PinchViewport. + IntRect targetRect(rect); + m_frame->document()->updateLayoutIgnorePendingStylesheets(); + bool pinchVirtualViewportEnabled = m_frame->settings()->pinchVirtualViewportEnabled(); + + if (pinchVirtualViewportEnabled) { + PinchViewport& pinchViewport = m_frame->page()->frameHost().pinchViewport(); + + IntSize pinchViewportSize = expandedIntSize(pinchViewport.visibleRect().size()); + targetRect.moveBy(ceiledIntPoint(pinchViewport.visibleRect().location())); + targetRect.setSize(pinchViewportSize.shrunkTo(targetRect.size())); + } + LayoutRect bounds = element->boundingBox(); - int centeringOffsetX = (rect.width() - bounds.width()) / 2; - int centeringOffsetY = (rect.height() - bounds.height()) / 2; - setScrollPosition(IntPoint(bounds.x() - centeringOffsetX - rect.x(), bounds.y() - centeringOffsetY - rect.y())); + int centeringOffsetX = (targetRect.width() - bounds.width()) / 2; + int centeringOffsetY = (targetRect.height() - bounds.height()) / 2; + + IntPoint targetOffset( + bounds.x() - centeringOffsetX - targetRect.x(), + bounds.y() - centeringOffsetY - targetRect.y()); + + setScrollPosition(targetOffset); + + if (pinchVirtualViewportEnabled) { + IntPoint remainder = IntPoint(targetOffset - scrollPosition()); + m_frame->page()->frameHost().pinchViewport().move(remainder); + } } void FrameView::setScrollPosition(const IntPoint& scrollPoint) { TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true); - m_maintainScrollPositionAnchor = 0; + m_maintainScrollPositionAnchor = nullptr; IntPoint newScrollPosition = adjustScrollPositionWithinRange(scrollPoint); @@ -1682,18 +1600,6 @@ void FrameView::setScrollPositionNonProgrammatically(const IntPoint& scrollPoint notifyScrollPositionChanged(newScrollPosition); } -void FrameView::setViewportConstrainedObjectsNeedLayout() -{ - if (!hasViewportConstrainedObjects()) - return; - - ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); - for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { - RenderObject* renderer = *it; - renderer->setNeedsLayout(); - } -} - IntSize FrameView::layoutSize(IncludeScrollbarsInRect scrollbarInclusion) const { return scrollbarInclusion == ExcludeScrollbars ? excludeScrollbars(m_layoutSize) : m_layoutSize; @@ -1720,38 +1626,73 @@ void FrameView::scrollPositionChanged() renderView->compositor()->frameViewDidScroll(); } - if (m_frame->document() && m_frame->document()->renderer()) { - ResourceLoadPriorityOptimizer modifier; - m_frame->document()->renderer()->didScroll(modifier); + if (m_didScrollTimer.isActive()) + m_didScrollTimer.stop(); + m_didScrollTimer.startOneShot(resourcePriorityUpdateDelayAfterScroll, FROM_HERE); + + if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache()) + cache->handleScrollPositionChanged(this); + + frame().loader().saveScrollState(); +} + +void FrameView::didScrollTimerFired(Timer<FrameView>*) +{ + if (m_frame->document() && m_frame->document()->renderView()) { + ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->updateAllImageResourcePriorities(); } } -void FrameView::repaintFixedElementsAfterScrolling() +void FrameView::updateLayersAndCompositingAfterScrollIfNeeded() { - // For fixed position elements, update widget positions and compositing layers after scrolling, - // but only if we're not inside of layout. - if (!m_nestedLayoutCount && hasViewportConstrainedObjects()) { + // Nothing to do after scrolling if there are no fixed position elements. + if (!hasViewportConstrainedObjects()) + return; + + RefPtr<FrameView> protect(this); + + // If there fixed position elements, scrolling may cause compositing layers to change. + // Update widget and layer positions after scrolling, but only if we're not inside of + // layout. + if (!m_nestedLayoutCount) { + updateWidgetPositions(); if (RenderView* renderView = this->renderView()) { - renderView->updateWidgetPositions(); renderView->layer()->updateLayerPositionsAfterDocumentScroll(); + renderView->layer()->setNeedsCompositingInputsUpdate(); + renderView->compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange); } } } -void FrameView::updateFixedElementsAfterScrolling() +void FrameView::updateFixedElementPaintInvalidationRectsAfterScroll() { - if (m_nestedLayoutCount <= 1 && hasViewportConstrainedObjects()) { - if (RenderView* renderView = this->renderView()) - renderView->compositor()->updateCompositingLayers(CompositingUpdateOnScroll); - } -} + if (!hasViewportConstrainedObjects()) + return; -bool FrameView::shouldRubberBandInDirection(ScrollDirection direction) const -{ - Page* page = frame().page(); - if (!page) - return ScrollView::shouldRubberBandInDirection(direction); - return page->chrome().client().shouldRubberBandInDirection(direction); + // Update the paint invalidation rects for fixed elements after scrolling and invalidation to reflect + // the new scroll position. + ViewportConstrainedObjectSet::const_iterator end = m_viewportConstrainedObjects->end(); + for (ViewportConstrainedObjectSet::const_iterator it = m_viewportConstrainedObjects->begin(); it != end; ++it) { + RenderObject* renderer = *it; + // m_viewportConstrainedObjects should not contain non-viewport constrained objects. + ASSERT(renderer->style()->hasViewportConstrainedPosition()); + + // Fixed items should always have layers. + ASSERT(renderer->hasLayer()); + + RenderLayer* layer = toRenderBoxModelObject(renderer)->layer(); + + // Don't need to do this for composited fixed items. + if (layer->compositingState() == PaintsIntoOwnBacking) + continue; + + // Also don't need to do this for invisible items. + if (layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForBoundsOutOfView + || layer->viewportConstrainedNotCompositedReason() == RenderLayer::NotCompositedForNoVisibleContent) + continue; + + layer->repainter().computeRepaintRectsIncludingNonCompositingDescendants(); + } } bool FrameView::isRubberBandInProgress() const @@ -1775,52 +1716,31 @@ HostWindow* FrameView::hostWindow() const return &page->chrome(); } -const unsigned cRepaintRectUnionThreshold = 25; - -void FrameView::repaintContentRectangle(const IntRect& r) +void FrameView::contentRectangleForPaintInvalidation(const IntRect& r) { - ASSERT(!m_frame->ownerElement()); - - if (m_isTrackingRepaints) { - IntRect repaintRect = r; - repaintRect.move(-scrollOffset()); - m_trackedRepaintRects.append(repaintRect); - } - - double delay = m_deferringRepaints ? 0 : adjustedDeferredRepaintDelay(); - if (m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) { - IntRect paintRect = r; - if (clipsRepaints() && !paintsEntireContents()) - paintRect.intersect(visibleContentRect()); - if (paintRect.isEmpty()) - return; - if (m_repaintCount == cRepaintRectUnionThreshold) { - IntRect unionedRect; - for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i) - unionedRect.unite(pixelSnappedIntRect(m_repaintRects[i])); - m_repaintRects.clear(); - m_repaintRects.append(unionedRect); - } - if (m_repaintCount < cRepaintRectUnionThreshold) - m_repaintRects.append(paintRect); - else - m_repaintRects[0].unite(paintRect); - m_repaintCount++; + ASSERT(paintInvalidationIsAllowed()); + ASSERT(!m_frame->owner()); - if (!m_deferringRepaints) - startDeferredRepaintTimer(delay); - - return; + if (m_isTrackingPaintInvalidations) { + IntRect paintInvalidationRect = r; + paintInvalidationRect.move(-scrollOffset()); + m_trackedPaintInvalidationRects.append(paintInvalidationRect); + // FIXME: http://crbug.com/368518. Eventually, invalidateContentRectangleForPaint + // is going away entirely once all layout tests are FCM. In the short + // term, no code should be tracking non-composited FrameView paint invalidations. + RELEASE_ASSERT_NOT_REACHED(); } - if (!shouldUpdate()) - return; - - ScrollView::repaintContentRectangle(r); + ScrollView::contentRectangleForPaintInvalidation(r); } void FrameView::contentsResized() { + if (m_frame->isMainFrame() && m_frame->document()) { + if (FastTextAutosizer* textAutosizer = m_frame->document()->fastTextAutosizer()) + textAutosizer->updatePageInfoInAllFrames(); + } + ScrollView::contentsResized(); setNeedsLayout(); } @@ -1828,7 +1748,7 @@ void FrameView::contentsResized() void FrameView::scrollbarExistenceDidChange() { // We check to make sure the view is attached to a frame() as this method can - // be triggered before the view is attached by Frame::createView(...) setting + // be triggered before the view is attached by LocalFrame::createView(...) setting // various values such as setScrollBarModes(...) for example. An ASSERT is // triggered when a view is layout before being attached to a frame(). if (!frame().view()) @@ -1852,151 +1772,20 @@ void FrameView::scrollbarExistenceDidChange() } } -void FrameView::beginDeferredRepaints() -{ - Page* page = m_frame->page(); - ASSERT(page); - - if (!isMainFrame()) { - page->mainFrame()->view()->beginDeferredRepaints(); - return; - } - - m_deferringRepaints++; -} - -void FrameView::endDeferredRepaints() -{ - Page* page = m_frame->page(); - ASSERT(page); - - if (!isMainFrame()) { - page->mainFrame()->view()->endDeferredRepaints(); - return; - } - - ASSERT(m_deferringRepaints > 0); - - if (--m_deferringRepaints) - return; - - if (m_deferredRepaintTimer.isActive()) - return; - - if (double delay = adjustedDeferredRepaintDelay()) { - startDeferredRepaintTimer(delay); - return; - } - - doDeferredRepaints(); -} - -void FrameView::startDeferredRepaintTimer(double delay) -{ - if (m_deferredRepaintTimer.isActive()) - return; - - m_deferredRepaintTimer.startOneShot(delay); -} - void FrameView::handleLoadCompleted() { // Once loading has completed, allow autoSize one last opportunity to // reduce the size of the frame. autoSizeIfEnabled(); - if (shouldUseLoadTimeDeferredRepaintDelay()) - return; - m_deferredRepaintDelay = s_normalDeferredRepaintDelay; - flushDeferredRepaints(); -} - -void FrameView::flushDeferredRepaints() -{ - if (!m_deferredRepaintTimer.isActive()) - return; - m_deferredRepaintTimer.stop(); - doDeferredRepaints(); -} - -void FrameView::doDeferredRepaints() -{ - ASSERT(!m_deferringRepaints); - if (!shouldUpdate()) { - m_repaintRects.clear(); - m_repaintCount = 0; - return; - } - unsigned size = m_repaintRects.size(); - for (unsigned i = 0; i < size; i++) { - ScrollView::repaintContentRectangle(pixelSnappedIntRect(m_repaintRects[i])); - } - m_repaintRects.clear(); - m_repaintCount = 0; - - updateDeferredRepaintDelayAfterRepaint(); -} - -bool FrameView::shouldUseLoadTimeDeferredRepaintDelay() const -{ - // Don't defer after the initial load of the page has been completed. - if (m_frame->tree().top()->document()->loadEventFinished()) - return false; - Document* document = m_frame->document(); - if (!document) - return false; - if (document->parsing()) - return true; - if (document->fetcher()->requestCount()) - return true; - return false; -} - -void FrameView::updateDeferredRepaintDelayAfterRepaint() -{ - if (!shouldUseLoadTimeDeferredRepaintDelay()) { - m_deferredRepaintDelay = s_normalDeferredRepaintDelay; - return; - } - double incrementedRepaintDelay = m_deferredRepaintDelay + s_deferredRepaintDelayIncrementDuringLoading; - m_deferredRepaintDelay = std::min(incrementedRepaintDelay, s_maxDeferredRepaintDelayDuringLoading); -} - -void FrameView::resetDeferredRepaintDelay() -{ - m_deferredRepaintDelay = 0; - if (m_deferredRepaintTimer.isActive()) { - m_deferredRepaintTimer.stop(); - if (!m_deferringRepaints) - doDeferredRepaints(); - } -} - -double FrameView::adjustedDeferredRepaintDelay() const -{ - ASSERT(!m_deferringRepaints); - if (!m_deferredRepaintDelay) - return 0; - double timeSinceLastPaint = currentTime() - m_lastPaintTime; - return max(0., m_deferredRepaintDelay - timeSinceLastPaint); -} - -void FrameView::deferredRepaintTimerFired(Timer<FrameView>*) -{ - doDeferredRepaints(); -} - -void FrameView::layoutTimerFired(Timer<FrameView>*) -{ - layout(); } void FrameView::scheduleRelayout() { ASSERT(m_frame->view() == this); - if (m_layoutRoot) { - m_layoutRoot->markContainingBlocksForLayout(false); - m_layoutRoot = 0; + if (isSubtreeLayout()) { + m_layoutSubtreeRoot->markContainingBlocksForLayout(false); + m_layoutSubtreeRoot = 0; } if (!m_layoutSchedulingEnabled) return; @@ -2004,21 +1793,17 @@ void FrameView::scheduleRelayout() return; if (!m_frame->document()->shouldScheduleLayout()) return; + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "InvalidateLayout", "frame", m_frame.get()); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::didInvalidateLayout(m_frame.get()); - // When frame seamless is enabled, the contents of the frame could affect the layout of the parent frames. - // Also invalidate parent frame starting from the owner element of this frame. - if (m_frame->ownerRenderer() && m_frame->document()->shouldDisplaySeamlesslyWithParent()) - m_frame->ownerRenderer()->setNeedsLayout(); - - int delay = m_frame->document()->minimumLayoutDelay(); - if (m_layoutTimer.isActive() && m_delayedLayout && !delay) - unscheduleRelayout(); - if (m_layoutTimer.isActive()) + if (m_hasPendingLayout) return; + m_hasPendingLayout = true; - m_delayedLayout = delay != 0; - m_layoutTimer.startOneShot(delay * 0.001); + page()->animator().scheduleVisualUpdate(); + lifecycle().ensureStateAtMost(DocumentLifecycle::StyleClean); } static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant) @@ -2034,6 +1819,10 @@ void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) { ASSERT(m_frame->view() == this); + // FIXME: Should this call shouldScheduleLayout instead? + if (!m_frame->document()->isActive()) + return; + RenderView* renderView = this->renderView(); if (renderView && renderView->needsLayout()) { if (relayoutRoot) @@ -2042,39 +1831,48 @@ void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) } if (layoutPending() || !m_layoutSchedulingEnabled) { - if (m_layoutRoot != relayoutRoot) { - if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) { + if (m_layoutSubtreeRoot != relayoutRoot) { + if (isObjectAncestorContainerOf(m_layoutSubtreeRoot, relayoutRoot)) { // Keep the current root - relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot); - ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); - } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) { + relayoutRoot->markContainingBlocksForLayout(false, m_layoutSubtreeRoot); + ASSERT(!m_layoutSubtreeRoot->container() || !m_layoutSubtreeRoot->container()->needsLayout()); + } else if (isSubtreeLayout() && isObjectAncestorContainerOf(relayoutRoot, m_layoutSubtreeRoot)) { // Re-root at relayoutRoot - m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot); - m_layoutRoot = relayoutRoot; - ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); - InspectorInstrumentation::didInvalidateLayout(m_frame.get()); + m_layoutSubtreeRoot->markContainingBlocksForLayout(false, relayoutRoot); + m_layoutSubtreeRoot = relayoutRoot; + ASSERT(!m_layoutSubtreeRoot->container() || !m_layoutSubtreeRoot->container()->needsLayout()); } else { // Just do a full relayout - if (m_layoutRoot) - m_layoutRoot->markContainingBlocksForLayout(false); - m_layoutRoot = 0; + if (isSubtreeLayout()) + m_layoutSubtreeRoot->markContainingBlocksForLayout(false); + m_layoutSubtreeRoot = 0; relayoutRoot->markContainingBlocksForLayout(false); - InspectorInstrumentation::didInvalidateLayout(m_frame.get()); } } } else if (m_layoutSchedulingEnabled) { - int delay = m_frame->document()->minimumLayoutDelay(); - m_layoutRoot = relayoutRoot; - ASSERT(!m_layoutRoot->container() || !m_layoutRoot->container()->needsLayout()); - InspectorInstrumentation::didInvalidateLayout(m_frame.get()); - m_delayedLayout = delay != 0; - m_layoutTimer.startOneShot(delay * 0.001); + m_layoutSubtreeRoot = relayoutRoot; + ASSERT(!m_layoutSubtreeRoot->container() || !m_layoutSubtreeRoot->container()->needsLayout()); + m_hasPendingLayout = true; + + page()->animator().scheduleVisualUpdate(); + lifecycle().ensureStateAtMost(DocumentLifecycle::StyleClean); } + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "InvalidateLayout", "frame", m_frame.get()); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentation::didInvalidateLayout(m_frame.get()); } bool FrameView::layoutPending() const { - return m_layoutTimer.isActive(); + // FIXME: This should check Document::lifecycle instead. + return m_hasPendingLayout; +} + +bool FrameView::isInPerformLayout() const +{ + ASSERT(m_inPerformLayout == (lifecycle().state() == DocumentLifecycle::InPerformLayout)); + return m_inPerformLayout; } bool FrameView::needsLayout() const @@ -2086,7 +1884,7 @@ bool FrameView::needsLayout() const RenderView* renderView = this->renderView(); return layoutPending() || (renderView && renderView->needsLayout()) - || m_layoutRoot; + || isSubtreeLayout(); } void FrameView::setNeedsLayout() @@ -2095,33 +1893,6 @@ void FrameView::setNeedsLayout() renderView->setNeedsLayout(); } -void FrameView::unscheduleRelayout() -{ - if (!m_layoutTimer.isActive()) - return; - - m_layoutTimer.stop(); - m_delayedLayout = false; -} - -void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime) -{ - for (RefPtr<Frame> frame = m_frame; frame; frame = frame->tree().traverseNext()) { - frame->view()->serviceScrollAnimations(); - if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) - frame->animation().serviceAnimations(); - - DocumentAnimations::serviceOnAnimationFrame(*frame->document(), monotonicAnimationStartTime); - } - - Vector<RefPtr<Document> > documents; - for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext()) - documents.append(frame->document()); - - for (size_t i = 0; i < documents.size(); ++i) - documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime); -} - bool FrameView::isTransparent() const { return m_isTransparent; @@ -2130,6 +1901,7 @@ bool FrameView::isTransparent() const void FrameView::setTransparent(bool isTransparent) { m_isTransparent = isTransparent; + DisableCompositingQueryAsserts disabler; if (renderView() && renderView()->layer()->hasCompositedLayerMapping()) renderView()->layer()->compositedLayerMapping()->updateContentsOpaque(); } @@ -2146,10 +1918,7 @@ Color FrameView::baseBackgroundColor() const void FrameView::setBaseBackgroundColor(const Color& backgroundColor) { - if (!backgroundColor.isValid()) - m_baseBackgroundColor = Color::white; - else - m_baseBackgroundColor = backgroundColor; + m_baseBackgroundColor = backgroundColor; if (renderView() && renderView()->layer()->hasCompositedLayerMapping()) { CompositedLayerMappingPtr compositedLayerMapping = renderView()->layer()->compositedLayerMapping(); @@ -2163,33 +1932,18 @@ void FrameView::setBaseBackgroundColor(const Color& backgroundColor) void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent) { for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) { - if (FrameView* view = frame->view()) { + if (!frame->isLocalFrame()) + continue; + if (FrameView* view = toLocalFrame(frame)->view()) { view->setTransparent(transparent); view->setBaseBackgroundColor(backgroundColor); } } } -bool FrameView::shouldUpdateWhileOffscreen() const -{ - return m_shouldUpdateWhileOffscreen; -} - -void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen) -{ - m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen; -} - -bool FrameView::shouldUpdate() const -{ - if (isOffscreen() && !shouldUpdateWhileOffscreen()) - return false; - return true; -} - void FrameView::scrollToAnchor() { - RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor; + RefPtrWillBeRawPtr<Node> anchorNode = m_maintainScrollPositionAnchor; if (!anchorNode) return; @@ -2213,6 +1967,10 @@ void FrameView::scrollToAnchor() bool FrameView::updateWidgets() { + // This is always called from updateWidgetsTimerFired. + // m_updateWidgetsTimer should only be scheduled if we have widgets to update. + // Thus I believe we can stop checking isEmpty here, and just ASSERT isEmpty: + ASSERT(!m_widgetUpdateSet.isEmpty()); if (m_nestedLayoutCount > 1 || m_widgetUpdateSet.isEmpty()) return true; @@ -2247,6 +2005,7 @@ bool FrameView::updateWidgets() void FrameView::updateWidgetsTimerFired(Timer<FrameView>*) { + ASSERT(!isInPerformLayout()); RefPtr<FrameView> protect(this); m_updateWidgetsTimer.stop(); for (unsigned i = 0; i < maxUpdateWidgetsIterations; ++i) { @@ -2257,27 +2016,45 @@ void FrameView::updateWidgetsTimerFired(Timer<FrameView>*) void FrameView::flushAnyPendingPostLayoutTasks() { + ASSERT(!isInPerformLayout()); if (m_postLayoutTasksTimer.isActive()) performPostLayoutTasks(); if (m_updateWidgetsTimer.isActive()) updateWidgetsTimerFired(0); } +void FrameView::scheduleUpdateWidgetsIfNecessary() +{ + ASSERT(!isInPerformLayout()); + if (m_updateWidgetsTimer.isActive() || m_widgetUpdateSet.isEmpty()) + return; + m_updateWidgetsTimer.startOneShot(0, FROM_HERE); +} + void FrameView::performPostLayoutTasks() { + // FIXME: We can reach here, even when the page is not active! + // http/tests/inspector/elements/html-link-import.html and many other + // tests hit that case. + // We should ASSERT(isActive()); or at least return early if we can! + ASSERT(!isInPerformLayout()); // Always before or after performLayout(), part of the highest-level layout() call. TRACE_EVENT0("webkit", "FrameView::performPostLayoutTasks"); RefPtr<FrameView> protect(this); m_postLayoutTasksTimer.stop(); m_frame->selection().setCaretRectNeedsUpdate(); - m_frame->selection().updateAppearance(); + { + // Hits in compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html + DisableCompositingQueryAsserts disabler; + m_frame->selection().updateAppearance(); + } + + ASSERT(m_frame->document()); if (m_nestedLayoutCount <= 1) { - if (m_firstLayoutCallbackPending) { + if (m_firstLayoutCallbackPending) m_firstLayoutCallbackPending = false; - m_frame->loader().didFirstLayout(); - } // Ensure that we always send this eventually. if (!m_frame->document()->parsing() && m_frame->loader().stateMachine()->committedFirstRealDocumentLoad()) @@ -2292,14 +2069,15 @@ void FrameView::performPostLayoutTasks() } } - FontFaceSet::didLayout(m_frame->document()); + FontFaceSet::didLayout(*m_frame->document()); - RenderView* renderView = this->renderView(); - if (renderView) - renderView->updateWidgetPositions(); + updateWidgetPositions(); + + // Plugins could have torn down the page inside updateWidgetPositions(). + if (!renderView()) + return; - if (!m_updateWidgetsTimer.isActive()) - m_updateWidgetsTimer.startOneShot(0); + scheduleUpdateWidgetsIfNecessary(); if (Page* page = m_frame->page()) { if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) @@ -2332,7 +2110,7 @@ void FrameView::sendResizeEventIfNeeded() m_frame->document()->enqueueResizeEvent(); - if (isMainFrame()) + if (m_frame->isMainFrame()) InspectorInstrumentation::didResizeMainFrame(m_frame->page()); } @@ -2366,16 +2144,11 @@ void FrameView::autoSizeIfEnabled() TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true); Document* document = frame().document(); - if (!document) + if (!document || !document->isActive()) return; - RenderView* documentView = document->renderView(); Element* documentElement = document->documentElement(); - if (!documentView || !documentElement) - return; - - RenderBox* documentRenderBox = documentElement->renderBox(); - if (!documentRenderBox) + if (!documentElement) return; // If this is the first time we run autosize, start from small height and @@ -2390,7 +2163,17 @@ void FrameView::autoSizeIfEnabled() for (int i = 0; i < 2; i++) { // Update various sizes including contentsSize, scrollHeight, etc. document->updateLayoutIgnorePendingStylesheets(); - int width = documentView->minPreferredLogicalWidth(); + + RenderView* renderView = document->renderView(); + if (!renderView) + return; + + int width = renderView->minPreferredLogicalWidth(); + + RenderBox* documentRenderBox = documentElement->renderBox(); + if (!documentRenderBox) + return; + int height = documentRenderBox->scrollHeight(); IntSize newSize(width, height); @@ -2471,35 +2254,14 @@ void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverf m_horizontalOverflow = horizontalOverflow; m_verticalOverflow = verticalOverflow; - RefPtr<OverflowEvent> event = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow); + RefPtrWillBeRawPtr<OverflowEvent> event = OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow); event->setTarget(m_viewportRenderer->node()); m_frame->document()->enqueueAnimationFrameEvent(event.release()); } } -const Pagination& FrameView::pagination() const -{ - if (m_pagination != Pagination()) - return m_pagination; - - if (isMainFrame()) - return m_frame->page()->pagination(); - - return m_pagination; -} - -void FrameView::setPagination(const Pagination& pagination) -{ - if (m_pagination == pagination) - return; - - m_pagination = pagination; - - m_frame->document()->styleResolverChanged(RecalcStyleDeferred); -} - -IntRect FrameView::windowClipRect(bool clipToContents) const +IntRect FrameView::windowClipRect(IncludeScrollbarsInRect scrollbarInclusion) const { ASSERT(m_frame->view() == this); @@ -2507,19 +2269,20 @@ IntRect FrameView::windowClipRect(bool clipToContents) const return IntRect(IntPoint(), contentsSize()); // Set our clip rect to be our contents. - IntRect clipRect = contentsToWindow(visibleContentRect(clipToContents ? ExcludeScrollbars : IncludeScrollbars)); - if (!m_frame->ownerElement()) + IntRect clipRect = contentsToWindow(visibleContentRect(scrollbarInclusion)); + if (!m_frame->deprecatedLocalOwner()) return clipRect; // Take our owner element and get its clip rect. - HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement(); + // FIXME: Do we need to do this for remote frames? + HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner(); FrameView* parentView = ownerElement->document().view(); if (parentView) - clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement, true)); + clipRect.intersect(parentView->windowClipRectForFrameOwner(ownerElement)); return clipRect; } -IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement, bool clipToLayerContents) const +IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* ownerElement) const { // The renderer can sometimes be null when style="display:none" interacts // with external content and plugins. @@ -2531,13 +2294,12 @@ IntRect FrameView::windowClipRectForFrameOwner(const HTMLFrameOwnerElement* owne if (!enclosingLayer) return windowClipRect(); + // FIXME: childrenClipRect relies on compositingState, which is not necessarily up to date. + // https://code.google.com/p/chromium/issues/detail?id=343769 + DisableCompositingQueryAsserts disabler; + // Apply the clip from the layer. - IntRect clipRect; - if (clipToLayerContents) - clipRect = pixelSnappedIntRect(enclosingLayer->childrenClipRect()); - else - clipRect = pixelSnappedIntRect(enclosingLayer->selfClipRect()); - clipRect = contentsToWindow(clipRect); + IntRect clipRect = contentsToWindow(pixelSnappedIntRect(enclosingLayer->clipper().childrenClipRect())); return intersection(clipRect, windowClipRect()); } @@ -2551,8 +2313,10 @@ void FrameView::scrollTo(const IntSize& newOffset) { LayoutSize offset = scrollOffset(); ScrollView::scrollTo(newOffset); - if (offset != scrollOffset()) + if (offset != scrollOffset()) { + updateLayersAndCompositingAfterScrollIfNeeded(); scrollPositionChanged(); + } frame().loader().client()->didChangeScrollOffset(); } @@ -2561,12 +2325,26 @@ void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rec // Add in our offset within the FrameView. IntRect dirtyRect = rect; dirtyRect.moveBy(scrollbar->location()); - invalidateRect(dirtyRect); + + if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && isInPerformLayout()) { + if (scrollbar == verticalScrollbar()) { + m_verticalBarDamage = dirtyRect; + m_hasVerticalBarDamage = true; + } else { + m_horizontalBarDamage = dirtyRect; + m_hasHorizontalBarDamage = true; + } + } else { + invalidateRect(dirtyRect); + } } void FrameView::getTickmarks(Vector<IntRect>& tickmarks) const { - tickmarks = frame().document()->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch); + if (!m_tickmarks.isEmpty()) + tickmarks = m_tickmarks; + else + tickmarks = frame().document()->markers().renderedRectsForMarkers(DocumentMarker::TextMatch); } IntRect FrameView::windowResizerRect() const @@ -2599,7 +2377,10 @@ IntSize FrameView::inputEventsOffsetForEmulation() const float FrameView::inputEventsScaleFactor() const { - return visibleContentScaleFactor() * m_inputEventsScaleFactorForEmulation; + float pageScale = m_frame->settings()->pinchVirtualViewportEnabled() + ? m_frame->page()->frameHost().pinchViewport().scale() + : visibleContentScaleFactor(); + return pageScale * m_inputEventsScaleFactorForEmulation; } bool FrameView::scrollbarsCanBeActive() const @@ -2610,12 +2391,6 @@ bool FrameView::scrollbarsCanBeActive() const return !!m_frame->document(); } -ScrollableArea* FrameView::enclosingScrollableArea() const -{ - // FIXME: Walk up the frame tree and look for a scrollable parent frame or RenderLayer. - return 0; -} - IntRect FrameView::scrollableAreaBoundingBox() const { RenderPart* ownerRenderer = frame().ownerRenderer(); @@ -2640,14 +2415,15 @@ bool FrameView::isScrollable() return false; // Covers #2. - HTMLFrameOwnerElement* owner = m_frame->ownerElement(); + // FIXME: Do we need to fix this for OOPI? + HTMLFrameOwnerElement* owner = m_frame->deprecatedLocalOwner(); if (owner && (!owner->renderer() || !owner->renderer()->visibleToHitTesting())) return false; // Cover #3 and #4. ScrollbarMode horizontalMode; ScrollbarMode verticalMode; - calculateScrollbarModesForLayout(horizontalMode, verticalMode, RulesFromWebContentOnly); + calculateScrollbarModesForLayoutAndSetViewportRenderer(horizontalMode, verticalMode, RulesFromWebContentOnly); if (horizontalMode == ScrollbarAlwaysOff && verticalMode == ScrollbarAlwaysOff) return false; @@ -2674,33 +2450,12 @@ bool FrameView::shouldSuspendScrollAnimations() const return m_frame->loader().state() != FrameStateComplete; } -void FrameView::scrollbarStyleChanged(int newStyle, bool forceUpdate) -{ - if (!isMainFrame()) - return; - - if (forceUpdate) - ScrollView::scrollbarStyleChanged(newStyle, forceUpdate); -} - -void FrameView::setAnimatorsAreActive() +void FrameView::scrollbarStyleChanged() { - Page* page = m_frame->page(); - if (!page) - return; - - if (ScrollAnimator* scrollAnimator = existingScrollAnimator()) - scrollAnimator->setIsActive(); - - if (!m_scrollableAreas) + // FIXME: Why does this only apply to the main frame? + if (!m_frame->isMainFrame()) return; - - for (HashSet<ScrollableArea*>::const_iterator it = m_scrollableAreas->begin(), end = m_scrollableAreas->end(); it != end; ++it) { - ScrollableArea* scrollableArea = *it; - - ASSERT(scrollableArea->scrollbarsCanBeActive()); - scrollableArea->scrollAnimator()->setIsActive(); - } + ScrollView::scrollbarStyleChanged(); } void FrameView::notifyPageThatContentAreaWillPaint() const @@ -2726,9 +2481,7 @@ void FrameView::notifyPageThatContentAreaWillPaint() const bool FrameView::scrollAnimatorEnabled() const { - if (m_frame->settings()) - return m_frame->settings()->scrollAnimatorEnabled(); - return false; + return m_frame->settings() && m_frame->settings()->scrollAnimatorEnabled(); } void FrameView::updateAnnotatedRegions() @@ -2767,7 +2520,7 @@ void FrameView::updateScrollCorner() } if (!cornerStyle) { - // If we have an owning ipage/Frame element, then it can set the custom scrollbar also. + // If we have an owning ipage/LocalFrame element, then it can set the custom scrollbar also. if (RenderPart* renderer = m_frame->ownerRenderer()) cornerStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), renderer->style()); } @@ -2794,7 +2547,7 @@ void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& corne } if (m_scrollCorner) { - bool needsBackgorund = isMainFrame(); + bool needsBackgorund = m_frame->isMainFrame(); if (needsBackgorund) context->fillRect(cornerRect, baseBackgroundColor()); m_scrollCorner->paintIntoRect(context, cornerRect.location(), cornerRect); @@ -2806,7 +2559,7 @@ void FrameView::paintScrollCorner(GraphicsContext* context, const IntRect& corne void FrameView::paintScrollbar(GraphicsContext* context, Scrollbar* bar, const IntRect& rect) { - bool needsBackgorund = bar->isCustomScrollbar() && isMainFrame(); + bool needsBackgorund = bar->isCustomScrollbar() && m_frame->isMainFrame(); if (needsBackgorund) { IntRect toFill = bar->frameRect(); toFill.intersect(rect); @@ -2822,30 +2575,13 @@ Color FrameView::documentBackgroundColor() const // the document and the body against the base background color of the frame view. // Background images are unfortunately impractical to include. - // Return invalid Color objects whenever there is insufficient information. + Color result = baseBackgroundColor(); if (!frame().document()) - return Color(); + return result; Element* htmlElement = frame().document()->documentElement(); Element* bodyElement = frame().document()->body(); - // Start with invalid colors. - Color htmlBackgroundColor; - Color bodyBackgroundColor; - if (htmlElement && htmlElement->renderer()) - htmlBackgroundColor = htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor); - if (bodyElement && bodyElement->renderer()) - bodyBackgroundColor = bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor); - - if (!bodyBackgroundColor.isValid()) { - if (!htmlBackgroundColor.isValid()) - return Color(); - return baseBackgroundColor().blend(htmlBackgroundColor); - } - - if (!htmlBackgroundColor.isValid()) - return baseBackgroundColor().blend(bodyBackgroundColor); - // We take the aggregate of the base background color // the <html> background color, and the <body> // background color to find the document color. The @@ -2853,7 +2589,12 @@ Color FrameView::documentBackgroundColor() const // technically part of the document background, but it // otherwise poses problems when the aggregate is not // fully opaque. - return baseBackgroundColor().blend(htmlBackgroundColor).blend(bodyBackgroundColor); + if (htmlElement && htmlElement->renderer()) + result = result.blend(htmlElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor)); + if (bodyElement && bodyElement->renderer()) + result = result.blend(bodyElement->renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor)); + + return result; } bool FrameView::hasCustomScrollbars() const @@ -2880,8 +2621,9 @@ FrameView* FrameView::parentFrameView() const if (!parent()) return 0; - if (Frame* parentFrame = m_frame->tree().parent()) - return parentFrame->view(); + Frame* parentFrame = m_frame->tree().parent(); + if (parentFrame && parentFrame->isLocalFrame()) + return toLocalFrame(parentFrame)->view(); return 0; } @@ -2897,14 +2639,14 @@ void FrameView::updateControlTints() if (m_frame->document()->url().isEmpty()) return; - if (RenderTheme::theme().supportsControlTints() || hasCustomScrollbars()) - paintControlTints(); -} + // FIXME: We shouldn't rely on the paint code to implement :window-inactive on custom scrollbars. + if (!RenderTheme::theme().supportsControlTints() && !hasCustomScrollbars()) + return; + + // Updating layout can run script, which can tear down the FrameView. + RefPtr<FrameView> protector(this); + updateLayoutAndStyleForPainting(); -void FrameView::paintControlTints() -{ - if (needsLayout()) - layout(); // FIXME: The use of paint seems like overkill: crbug.com/236892 GraphicsContext context(0); // NULL canvas to get a non-painting context. context.setUpdatingControlTints(true); @@ -2920,7 +2662,7 @@ void FrameView::setWasScrolledByUser(bool wasScrolledByUser) { if (m_inProgrammaticScroll) return; - m_maintainScrollPositionAnchor = 0; + m_maintainScrollPositionAnchor = nullptr; m_wasScrolledByUser = wasScrolledByUser; } @@ -2932,7 +2674,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) bool fillWithRed; if (document->printing()) fillWithRed = false; // Printing, don't fill with red (can't remember why). - else if (m_frame->ownerElement()) + else if (m_frame->owner()) fillWithRed = false; // Subframe, don't fill with red. else if (isTransparent()) fillWithRed = false; // Transparent, don't fill with red. @@ -2957,6 +2699,9 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) if (needsLayout()) return; + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(renderView, rect, 0)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::willPaint(renderView, 0); bool isTopLevelPainter = !s_inPaintContents; @@ -2972,7 +2717,7 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) } if (m_paintBehavior == PaintBehaviorNormal) - document->markers()->invalidateRenderedRectsForMarkersInRect(rect); + document->markers().invalidateRenderedRectsForMarkersInRect(rect); if (document->printing()) m_paintBehavior |= PaintBehaviorFlattenCompositingLayers; @@ -2981,19 +2726,18 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) m_isPainting = true; // m_nodeToDraw is used to draw only one element (and its descendants) - RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; + RenderObject* renderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; RenderLayer* rootLayer = renderView->layer(); #ifndef NDEBUG renderView->assertSubtreeIsLaidOut(); - RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(rootLayer->renderer()); + RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->renderer()); #endif - RenderObject* enclosingLayerRenderer = eltRenderer->enclosingLayer() ? eltRenderer->enclosingLayer()->renderer() : eltRenderer; - rootLayer->paint(p, rect, m_paintBehavior, enclosingLayerRenderer); + rootLayer->paint(p, rect, m_paintBehavior, renderer); if (rootLayer->containsDirtyOverlayScrollbars()) - rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, eltRenderer); + rootLayer->paintOverlayScrollbars(p, rect, m_paintBehavior, renderer); m_isPainting = false; @@ -3042,7 +2786,7 @@ void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& hori if (m_frame->document()->printing()) return; - if (isMainFrame()) { + if (m_frame->isMainFrame()) { if (m_frame->page()->chrome().client().paintCustomOverhangArea(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect)) return; } @@ -3050,6 +2794,27 @@ void FrameView::paintOverhangAreas(GraphicsContext* context, const IntRect& hori ScrollView::paintOverhangAreas(context, horizontalOverhangArea, verticalOverhangArea, dirtyRect); } +void FrameView::updateLayoutAndStyleForPainting() +{ + // Updating layout can run script, which can tear down the FrameView. + RefPtr<FrameView> protector(this); + + updateLayoutAndStyleIfNeededRecursive(); + + if (RenderView* view = renderView()) { + InspectorInstrumentation::willUpdateLayerTree(view->frame()); + + view->compositor()->updateIfNeededRecursive(); + + if (view->compositor()->inCompositingMode() && m_frame->isMainFrame()) + m_frame->page()->scrollingCoordinator()->updateAfterCompositingChangeIfNeeded(); + + InspectorInstrumentation::didUpdateLayerTree(view->frame()); + } + + scrollContentsIfNeededRecursive(); +} + void FrameView::updateLayoutAndStyleIfNeededRecursive() { // We have to crawl our entire tree looking for any FrameViews that need @@ -3061,29 +2826,43 @@ void FrameView::updateLayoutAndStyleIfNeededRecursive() // region but then become included later by the second frame adding rects to the dirty region // when it lays out. - m_frame->document()->updateStyleIfNeeded(); + m_frame->document()->updateRenderTreeIfNeeded(); if (needsLayout()) layout(); - // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive - // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars - // and thus mutates the children() set. + // FIXME: Calling layout() shouldn't trigger scripe execution or have any + // observable effects on the frame tree but we're not quite there yet. Vector<RefPtr<FrameView> > frameViews; - collectFrameViewChildren(this, frameViews); + for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) { + if (!child->isLocalFrame()) + continue; + if (FrameView* view = toLocalFrame(child)->view()) + frameViews.append(view); + } const Vector<RefPtr<FrameView> >::iterator end = frameViews.end(); for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it) (*it)->updateLayoutAndStyleIfNeededRecursive(); - // updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before - // painting, so we need to flush out any deferred repaints too. - flushDeferredRepaints(); + // When an <iframe> gets composited, it triggers an extra style recalc in its containing FrameView. + // To avoid pushing an invalid tree for display, we have to check for this case and do another + // style recalc. The extra style recalc needs to happen after our child <iframes> were updated. + // FIXME: We shouldn't be triggering an extra style recalc in the first place. + if (m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate()) { + m_frame->document()->updateRenderTreeIfNeeded(); + + if (needsLayout()) + layout(); + } - // When seamless is on, child frame can mark parent frame dirty. In such case, child frame - // needs to call layout on parent frame recursively. - // This assert ensures that parent frames are clean, when child frames finished updating layout and style. + // These asserts ensure that parent frames are clean, when child frames finished updating layout and style. ASSERT(!needsLayout()); + ASSERT(!m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate()); +#ifndef NDEBUG + m_frame->document()->renderView()->assertRendererLaidOut(); +#endif + } void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize) @@ -3118,7 +2897,7 @@ void FrameView::forceLayout(bool allowSubtree) layout(allowSubtree); } -void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot shouldAdjustViewSize) +void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor) { // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see // the state of things before and after the layout @@ -3130,7 +2909,7 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatS LayoutUnit flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight); renderView->setLogicalWidth(flooredPageLogicalWidth); renderView->setPageLogicalHeight(flooredPageLogicalHeight); - renderView->setNeedsLayoutAndPrefWidthsRecalc(); + renderView->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); forceLayout(); // If we don't fit in the given page width, we'll lay out again. If we don't fit in the @@ -3141,9 +2920,8 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatS const LayoutRect& documentRect = renderView->documentRect(); LayoutUnit docLogicalWidth = horizontalWritingMode ? documentRect.width() : documentRect.height(); if (docLogicalWidth > pageLogicalWidth) { - int expectedPageWidth = std::min<float>(documentRect.width(), pageSize.width() * maximumShrinkFactor); - int expectedPageHeight = std::min<float>(documentRect.height(), pageSize.height() * maximumShrinkFactor); - FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), FloatSize(expectedPageWidth, expectedPageHeight)); + FloatSize expectedPageSize(std::min<float>(documentRect.width().toFloat(), pageSize.width() * maximumShrinkFactor), std::min<float>(documentRect.height().toFloat(), pageSize.height() * maximumShrinkFactor)); + FloatSize maxPageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(originalPageSize.width(), originalPageSize.height()), expectedPageSize); pageLogicalWidth = horizontalWritingMode ? maxPageSize.width() : maxPageSize.height(); pageLogicalHeight = horizontalWritingMode ? maxPageSize.height() : maxPageSize.width(); @@ -3151,7 +2929,7 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatS flooredPageLogicalHeight = static_cast<LayoutUnit>(pageLogicalHeight); renderView->setLogicalWidth(flooredPageLogicalWidth); renderView->setPageLogicalHeight(flooredPageLogicalHeight); - renderView->setNeedsLayoutAndPrefWidthsRecalc(); + renderView->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); forceLayout(); const LayoutRect& updatedDocumentRect = renderView->documentRect(); @@ -3170,13 +2948,12 @@ void FrameView::forceLayoutForPagination(const FloatSize& pageSize, const FloatS } } - if (shouldAdjustViewSize) - adjustViewSize(); + adjustViewSize(); } -IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRect& rendererRect) const +IntRect FrameView::convertFromRenderer(const RenderObject& renderer, const IntRect& rendererRect) const { - IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer->localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox())); + IntRect rect = pixelSnappedIntRect(enclosingLayoutRect(renderer.localToAbsoluteQuad(FloatRect(rendererRect)).boundingBox())); // Convert from page ("absolute") to FrameView coordinates. rect.moveBy(-scrollPosition()); @@ -3184,7 +2961,7 @@ IntRect FrameView::convertFromRenderer(const RenderObject* renderer, const IntRe return rect; } -IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect& viewRect) const +IntRect FrameView::convertToRenderer(const RenderObject& renderer, const IntRect& viewRect) const { IntRect rect = viewRect; @@ -3193,27 +2970,27 @@ IntRect FrameView::convertToRenderer(const RenderObject* renderer, const IntRect // FIXME: we don't have a way to map an absolute rect down to a local quad, so just // move the rect for now. - rect.setLocation(roundedIntPoint(renderer->absoluteToLocal(rect.location(), UseTransforms))); + rect.setLocation(roundedIntPoint(renderer.absoluteToLocal(rect.location(), UseTransforms))); return rect; } -IntPoint FrameView::convertFromRenderer(const RenderObject* renderer, const IntPoint& rendererPoint) const +IntPoint FrameView::convertFromRenderer(const RenderObject& renderer, const IntPoint& rendererPoint) const { - IntPoint point = roundedIntPoint(renderer->localToAbsolute(rendererPoint, UseTransforms)); + IntPoint point = roundedIntPoint(renderer.localToAbsolute(rendererPoint, UseTransforms)); // Convert from page ("absolute") to FrameView coordinates. point.moveBy(-scrollPosition()); return point; } -IntPoint FrameView::convertToRenderer(const RenderObject* renderer, const IntPoint& viewPoint) const +IntPoint FrameView::convertToRenderer(const RenderObject& renderer, const IntPoint& viewPoint) const { IntPoint point = viewPoint; // Convert from FrameView coords into page ("absolute") coordinates. point += IntSize(scrollX(), scrollY()); - return roundedIntPoint(renderer->absoluteToLocal(point, UseTransforms)); + return roundedIntPoint(renderer.absoluteToLocal(point, UseTransforms)); } IntRect FrameView::convertToContainingView(const IntRect& localRect) const @@ -3230,7 +3007,7 @@ IntRect FrameView::convertToContainingView(const IntRect& localRect) const // Add borders and padding?? rect.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop()); - return parentView->convertFromRenderer(renderer, rect); + return parentView->convertFromRenderer(*renderer, rect); } return Widget::convertToContainingView(localRect); @@ -3250,7 +3027,7 @@ IntRect FrameView::convertFromContainingView(const IntRect& parentRect) const if (!renderer) return parentRect; - IntRect rect = parentView->convertToRenderer(renderer, parentRect); + IntRect rect = parentView->convertToRenderer(*renderer, parentRect); // Subtract borders and padding rect.move(-renderer->borderLeft() - renderer->paddingLeft(), -renderer->borderTop() - renderer->paddingTop()); @@ -3279,7 +3056,7 @@ IntPoint FrameView::convertToContainingView(const IntPoint& localPoint) const // Add borders and padding point.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop()); - return parentView->convertFromRenderer(renderer, point); + return parentView->convertFromRenderer(*renderer, point); } return Widget::convertToContainingView(localPoint); @@ -3299,7 +3076,7 @@ IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const if (!renderer) return parentPoint; - IntPoint point = parentView->convertToRenderer(renderer, parentPoint); + IntPoint point = parentView->convertToRenderer(*renderer, parentPoint); // Subtract borders and padding point.move(-renderer->borderLeft() - renderer->paddingLeft(), -renderer->borderTop() - renderer->paddingTop()); @@ -3312,107 +3089,74 @@ IntPoint FrameView::convertFromContainingView(const IntPoint& parentPoint) const return parentPoint; } -// Normal delay -void FrameView::setRepaintThrottlingDeferredRepaintDelay(double p) -{ - s_normalDeferredRepaintDelay = p; -} - -// Negative value would mean that first few repaints happen without a delay -void FrameView::setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double p) +void FrameView::setTracksPaintInvalidations(bool trackPaintInvalidations) { - s_initialDeferredRepaintDelayDuringLoading = p; -} - -// The delay grows on each repaint to this maximum value -void FrameView::setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double p) -{ - s_maxDeferredRepaintDelayDuringLoading = p; -} - -// On each repaint the delay increases by this amount -void FrameView::setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double p) -{ - s_deferredRepaintDelayIncrementDuringLoading = p; -} - -void FrameView::setTracksRepaints(bool trackRepaints) -{ - if (trackRepaints == m_isTrackingRepaints) + if (trackPaintInvalidations == m_isTrackingPaintInvalidations) return; for (Frame* frame = m_frame->tree().top(); frame; frame = frame->tree().traverseNext()) { - if (RenderView* renderView = frame->contentRenderer()) - renderView->compositor()->setTracksRepaints(trackRepaints); + if (!frame->isLocalFrame()) + continue; + if (RenderView* renderView = toLocalFrame(frame)->contentRenderer()) + renderView->compositor()->setTracksRepaints(trackPaintInvalidations); } - resetTrackedRepaints(); - m_isTrackingRepaints = trackRepaints; + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"), + "FrameView::setTracksPaintInvalidations", "enabled", trackPaintInvalidations); + + resetTrackedPaintInvalidations(); + m_isTrackingPaintInvalidations = trackPaintInvalidations; } -void FrameView::resetTrackedRepaints() +void FrameView::resetTrackedPaintInvalidations() { - m_trackedRepaintRects.clear(); + m_trackedPaintInvalidationRects.clear(); if (RenderView* renderView = this->renderView()) renderView->compositor()->resetTrackedRepaintRects(); } -String FrameView::trackedRepaintRectsAsText() const +String FrameView::trackedPaintInvalidationRectsAsText() const { TextStream ts; - if (!m_trackedRepaintRects.isEmpty()) { + if (!m_trackedPaintInvalidationRects.isEmpty()) { ts << "(repaint rects\n"; - for (size_t i = 0; i < m_trackedRepaintRects.size(); ++i) - ts << " (rect " << m_trackedRepaintRects[i].x() << " " << m_trackedRepaintRects[i].y() << " " << m_trackedRepaintRects[i].width() << " " << m_trackedRepaintRects[i].height() << ")\n"; + for (size_t i = 0; i < m_trackedPaintInvalidationRects.size(); ++i) + ts << " (rect " << m_trackedPaintInvalidationRects[i].x() << " " << m_trackedPaintInvalidationRects[i].y() << " " << m_trackedPaintInvalidationRects[i].width() << " " << m_trackedPaintInvalidationRects[i].height() << ")\n"; ts << ")\n"; } return ts.release(); } -void FrameView::addResizerArea(RenderBox* resizerBox) +void FrameView::addResizerArea(RenderBox& resizerBox) { if (!m_resizerAreas) m_resizerAreas = adoptPtr(new ResizerAreaSet); - m_resizerAreas->add(resizerBox); + m_resizerAreas->add(&resizerBox); } -void FrameView::removeResizerArea(RenderBox* resizerBox) +void FrameView::removeResizerArea(RenderBox& resizerBox) { if (!m_resizerAreas) return; - ResizerAreaSet::iterator it = m_resizerAreas->find(resizerBox); + ResizerAreaSet::iterator it = m_resizerAreas->find(&resizerBox); if (it != m_resizerAreas->end()) m_resizerAreas->remove(it); } -bool FrameView::addScrollableArea(ScrollableArea* scrollableArea) +void FrameView::addScrollableArea(ScrollableArea* scrollableArea) { ASSERT(scrollableArea); if (!m_scrollableAreas) m_scrollableAreas = adoptPtr(new ScrollableAreaSet); - return m_scrollableAreas->add(scrollableArea).isNewEntry; + m_scrollableAreas->add(scrollableArea); } -bool FrameView::removeScrollableArea(ScrollableArea* scrollableArea) +void FrameView::removeScrollableArea(ScrollableArea* scrollableArea) { if (!m_scrollableAreas) - return false; - - ScrollableAreaSet::iterator it = m_scrollableAreas->find(scrollableArea); - if (it == m_scrollableAreas->end()) - return false; - - m_scrollableAreas->remove(it); - return true; -} - -bool FrameView::containsScrollableArea(const ScrollableArea* scrollableArea) const -{ - ASSERT(scrollableArea); - if (!m_scrollableAreas || !scrollableArea) - return false; - return m_scrollableAreas->contains(const_cast<ScrollableArea*>(scrollableArea)); + return; + m_scrollableAreas->remove(scrollableArea); } void FrameView::removeChild(Widget* widget) @@ -3425,18 +3169,24 @@ void FrameView::removeChild(Widget* widget) bool FrameView::wheelEvent(const PlatformWheelEvent& wheelEvent) { + bool allowScrolling = userInputScrollable(HorizontalScrollbar) || userInputScrollable(VerticalScrollbar); + // Note that to allow for rubber-band over-scroll behavior, even non-scrollable views // should handle wheel events. #if !USE(RUBBER_BANDING) if (!isScrollable()) - return false; + allowScrolling = false; #endif - // We don't allow mouse wheeling to happen in a ScrollView that has had its scrollbars explicitly disabled. - if (!canHaveScrollbars()) - return false; + if (allowScrolling && ScrollableArea::handleWheelEvent(wheelEvent)) + return true; - return ScrollableArea::handleWheelEvent(wheelEvent); + // If the frame didn't handle the event, give the pinch-zoom viewport a chance to + // process the scroll event. + if (m_frame->settings()->pinchVirtualViewportEnabled() && m_frame->isMainFrame()) + return page()->frameHost().pinchViewport().handleWheelEvent(wheelEvent); + + return false; } bool FrameView::isVerticalDocument() const @@ -3467,16 +3217,11 @@ AXObjectCache* FrameView::axObjectCache() const void FrameView::setCursor(const Cursor& cursor) { Page* page = frame().page(); - if (!page) + if (!page || !page->settings().deviceSupportsMouse()) return; page->chrome().setCursor(cursor); } -bool FrameView::isMainFrame() const -{ - return m_frame->isMainFrame(); -} - void FrameView::frameRectsChanged() { if (layoutSizeFixedToFrameSize()) diff --git a/chromium/third_party/WebKit/Source/core/frame/FrameView.h b/chromium/third_party/WebKit/Source/core/frame/FrameView.h index e408b984c70..9585f6c9e98 100644 --- a/chromium/third_party/WebKit/Source/core/frame/FrameView.h +++ b/chromium/third_party/WebKit/Source/core/frame/FrameView.h @@ -25,10 +25,8 @@ #ifndef FrameView_h #define FrameView_h -#include "core/frame/AdjustViewSizeOrNot.h" -#include "core/rendering/Pagination.h" #include "core/rendering/PaintPhase.h" -#include "core/rendering/PartialLayoutState.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/geometry/LayoutRect.h" #include "platform/graphics/Color.h" #include "platform/scroll/ScrollView.h" @@ -39,9 +37,12 @@ namespace WebCore { class AXObjectCache; +class DocumentLifecycle; +class Cursor; class Element; class FloatSize; -class Frame; +class HTMLFrameOwnerElement; +class LocalFrame; class KURL; class Node; class Page; @@ -50,60 +51,56 @@ class RenderEmbeddedObject; class RenderObject; class RenderScrollbarPart; class RenderStyle; - -Pagination::Mode paginationModeForRenderStyle(RenderStyle*); +class RenderView; +class RenderWidget; typedef unsigned long long DOMTimeStamp; -class FrameView : public ScrollView { +class FrameView FINAL : public ScrollView { public: friend class RenderView; friend class Internals; - static PassRefPtr<FrameView> create(Frame*); - static PassRefPtr<FrameView> create(Frame*, const IntSize& initialSize); + static PassRefPtr<FrameView> create(LocalFrame*); + static PassRefPtr<FrameView> create(LocalFrame*, const IntSize& initialSize); virtual ~FrameView(); - virtual HostWindow* hostWindow() const; + virtual HostWindow* hostWindow() const OVERRIDE; - virtual void invalidateRect(const IntRect&); - virtual void setFrameRect(const IntRect&); + virtual void invalidateRect(const IntRect&) OVERRIDE; + virtual void setFrameRect(const IntRect&) OVERRIDE; - virtual bool scheduleAnimation(); + virtual bool scheduleAnimation() OVERRIDE; - Frame& frame() const { return *m_frame; } + LocalFrame& frame() const { return *m_frame; } + Page* page() const; RenderView* renderView() const; - LayoutUnit marginWidth() const { return m_margins.width(); } // -1 means default - LayoutUnit marginHeight() const { return m_margins.height(); } // -1 means default - void setMarginWidth(LayoutUnit); - void setMarginHeight(LayoutUnit); - - virtual void setCanHaveScrollbars(bool); - void updateCanHaveScrollbars(); + virtual void setCanHaveScrollbars(bool) OVERRIDE; - virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation); + virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation) OVERRIDE; - virtual void setContentsSize(const IntSize&); + virtual void setContentsSize(const IntSize&) OVERRIDE; + IntPoint clampOffsetAtScale(const IntPoint& offset, float scale) const; void layout(bool allowSubtree = true); bool didFirstLayout() const; - void layoutTimerFired(Timer<FrameView>*); void scheduleRelayout(); void scheduleRelayoutOfSubtree(RenderObject*); - void unscheduleRelayout(); bool layoutPending() const; - bool isInLayout() const { return m_inLayout; } + bool isInPerformLayout() const; + + void setCanInvalidatePaintDuringPerformLayout(bool b) { m_canInvalidatePaintDuringPerformLayout = b; } + bool canInvalidatePaintDuringPerformLayout() const { return m_canInvalidatePaintDuringPerformLayout; } RenderObject* layoutRoot(bool onlyDuringLayout = false) const; - void clearLayoutRoot() { m_layoutRoot = 0; } + void clearLayoutSubtreeRoot() { m_layoutSubtreeRoot = 0; } int layoutCount() const { return m_layoutCount; } bool needsLayout() const; void setNeedsLayout(); - void setViewportConstrainedObjectsNeedLayout(); // Methods for getting/setting the size Blink should use to layout the contents. IntSize layoutSize(IncludeScrollbarsInRect = ExcludeScrollbars) const; @@ -114,20 +111,15 @@ public: void setLayoutSizeFixedToFrameSize(bool isFixed) { m_layoutSizeFixedToFrameSize = isFixed; } bool layoutSizeFixedToFrameSize() { return m_layoutSizeFixedToFrameSize; } - bool needsFullRepaint() const { return m_doFullRepaint; } + bool needsFullPaintInvalidation() const { return m_doFullPaintInvalidation; } - void serviceScriptedAnimations(double monotonicAnimationStartTime); + void updateAcceleratedCompositingSettings(); - void updateCompositingLayersAfterStyleChange(); - void updateCompositingLayersAfterLayout(); + void recalcOverflowAfterStyleChange(); bool hasCompositedContent() const; bool isEnclosedInCompositingLayer() const; - // Returns true when a paint with the PaintBehaviorFlattenCompositingLayers flag set gives - // a faithful representation of the content. - bool isSoftwareRenderable() const; - void resetScrollbars(); void prepareForDetach(); void detachCustomScrollbars(); @@ -145,16 +137,12 @@ public: void setBaseBackgroundColor(const Color&); void updateBackgroundRecursively(const Color&, bool); - bool shouldUpdateWhileOffscreen() const; - void setShouldUpdateWhileOffscreen(bool); - bool shouldUpdate() const; - void adjustViewSize(); - virtual IntRect windowClipRect(bool clipToContents = true) const; - IntRect windowClipRectForFrameOwner(const HTMLFrameOwnerElement*, bool clipToLayerContents) const; + virtual IntRect windowClipRect(IncludeScrollbarsInRect = ExcludeScrollbars) const OVERRIDE; + IntRect windowClipRectForFrameOwner(const HTMLFrameOwnerElement*) const; - virtual IntRect windowResizerRect() const; + virtual IntRect windowResizerRect() const OVERRIDE; virtual float visibleContentScaleFactor() const OVERRIDE { return m_visibleContentScaleFactor; } void setVisibleContentScaleFactor(float); @@ -164,15 +152,13 @@ public: void setInputEventsTransformForEmulation(const IntSize&, float); virtual void setScrollPosition(const IntPoint&) OVERRIDE; - virtual void repaintFixedElementsAfterScrolling(); - virtual void updateFixedElementsAfterScrolling(); - virtual bool shouldRubberBandInDirection(ScrollDirection) const; virtual bool isRubberBandInProgress() const OVERRIDE; void setScrollPositionNonProgrammatically(const IntPoint&); // This is different than visibleContentRect() in that it ignores negative (or overly positive) // offsets from rubber-banding, and it takes zooming into account. LayoutRect viewportConstrainedVisibleContentRect() const; + void viewportConstrainedVisibleContentSizeChanged(bool widthChanged, bool heightChanged); AtomicString mediaType() const; void setMediaType(const AtomicString&); @@ -181,7 +167,6 @@ public: void setCannotBlitToWindow(); void setIsOverlapped(bool); bool isOverlapped() const { return m_isOverlapped; } - bool isOverlappedIncludingAncestors() const; void setContentIsOpaque(bool); void addSlowRepaintObject(); @@ -196,7 +181,6 @@ public: bool hasViewportConstrainedObjects() const { return m_viewportConstrainedObjects && m_viewportConstrainedObjects->size() > 0; } void handleLoadCompleted(); - void resetDeferredRepaintDelay(); void updateAnnotatedRegions(); void updateControlTints(); @@ -211,63 +195,58 @@ public: bool safeToPropagateScrollToParent() const { return m_safeToPropagateScrollToParent; } void setSafeToPropagateScrollToParent(bool isSafe) { m_safeToPropagateScrollToParent = isSafe; } + void addWidget(RenderWidget*); + void removeWidget(RenderWidget*); + void updateWidgetPositions(); + void addWidgetToUpdate(RenderEmbeddedObject&); - virtual void paintContents(GraphicsContext*, const IntRect& damageRect); + virtual void paintContents(GraphicsContext*, const IntRect& damageRect) OVERRIDE; void setPaintBehavior(PaintBehavior); PaintBehavior paintBehavior() const; bool isPainting() const; bool hasEverPainted() const { return m_lastPaintTime; } - void setLastPaintTime(double lastPaintTime) { m_lastPaintTime = lastPaintTime; } void setNodeToDraw(Node*); - virtual void paintOverhangAreas(GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect); - virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect); + virtual void paintOverhangAreas(GraphicsContext*, const IntRect& horizontalOverhangArea, const IntRect& verticalOverhangArea, const IntRect& dirtyRect) OVERRIDE; + virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect) OVERRIDE; virtual void paintScrollbar(GraphicsContext*, Scrollbar*, const IntRect&) OVERRIDE; Color documentBackgroundColor() const; static double currentFrameTimeStamp() { return s_currentFrameTimeStamp; } + void updateLayoutAndStyleForPainting(); void updateLayoutAndStyleIfNeededRecursive(); void incrementVisuallyNonEmptyCharacterCount(unsigned); void incrementVisuallyNonEmptyPixelCount(const IntSize&); void setIsVisuallyNonEmpty() { m_isVisuallyNonEmpty = true; } - bool isVisuallyNonEmpty() const { return m_isVisuallyNonEmpty; } void enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize); void forceLayout(bool allowSubtree = false); - void forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot); + void forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor); bool scrollToFragment(const KURL&); bool scrollToAnchor(const String&); void maintainScrollPositionAtAnchor(Node*); void scrollElementToRect(Element*, const IntRect&); + void scrollContentsIfNeededRecursive(); // Methods to convert points and rects between the coordinate space of the renderer, and this view. - virtual IntRect convertFromRenderer(const RenderObject*, const IntRect&) const; - virtual IntRect convertToRenderer(const RenderObject*, const IntRect&) const; - virtual IntPoint convertFromRenderer(const RenderObject*, const IntPoint&) const; - virtual IntPoint convertToRenderer(const RenderObject*, const IntPoint&) const; + IntRect convertFromRenderer(const RenderObject&, const IntRect&) const; + IntRect convertToRenderer(const RenderObject&, const IntRect&) const; + IntPoint convertFromRenderer(const RenderObject&, const IntPoint&) const; + IntPoint convertToRenderer(const RenderObject&, const IntPoint&) const; bool isFrameViewScrollCorner(RenderScrollbarPart* scrollCorner) const { return m_scrollCorner == scrollCorner; } bool isScrollable(); enum ScrollbarModesCalculationStrategy { RulesFromWebContentOnly, AnyRule }; - void calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy = AnyRule); - - // Normal delay - static void setRepaintThrottlingDeferredRepaintDelay(double); - // Negative value would mean that first few repaints happen without a delay - static void setRepaintThrottlingnInitialDeferredRepaintDelayDuringLoading(double); - // The delay grows on each repaint to this maximum value - static void setRepaintThrottlingMaxDeferredRepaintDelayDuringLoading(double); - // On each repaint the delay increses by this amount - static void setRepaintThrottlingDeferredRepaintDelayIncrementDuringLoading(double); - - virtual IntPoint lastKnownMousePosition() const; + void calculateScrollbarModesForLayoutAndSetViewportRenderer(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy = AnyRule); + + virtual IntPoint lastKnownMousePosition() const OVERRIDE; bool shouldSetCursor() const; void setCursor(const Cursor&); @@ -277,33 +256,27 @@ public: // FIXME: Remove this method once plugin loading is decoupled from layout. void flushAnyPendingPostLayoutTasks(); - virtual bool shouldSuspendScrollAnimations() const; - virtual void scrollbarStyleChanged(int newStyle, bool forceUpdate); - - void setAnimatorsAreActive(); + virtual bool shouldSuspendScrollAnimations() const OVERRIDE; + virtual void scrollbarStyleChanged() OVERRIDE; RenderBox* embeddedContentBox() const; - void setTracksRepaints(bool); - bool isTrackingRepaints() const { return m_isTrackingRepaints; } - void resetTrackedRepaints(); - const Vector<IntRect>& trackedRepaintRects() const { return m_trackedRepaintRects; } - String trackedRepaintRectsAsText() const; + void setTracksPaintInvalidations(bool); + bool isTrackingPaintInvalidations() const { return m_isTrackingPaintInvalidations; } + void resetTrackedPaintInvalidations(); + String trackedPaintInvalidationRectsAsText() const; typedef HashSet<ScrollableArea*> ScrollableAreaSet; - // Returns whether the scrollable area has just been newly added. - bool addScrollableArea(ScrollableArea*); - // Returns whether the scrollable area has just been removed. - bool removeScrollableArea(ScrollableArea*); - bool containsScrollableArea(const ScrollableArea*) const; + void addScrollableArea(ScrollableArea*); + void removeScrollableArea(ScrollableArea*); const ScrollableAreaSet* scrollableAreas() const { return m_scrollableAreas.get(); } // With CSS style "resize:" enabled, a little resizer handle will appear at the bottom // right of the object. We keep track of these resizer areas for checking if touches // (implemented using Scroll gesture) are targeting the resizer. typedef HashSet<RenderBox*> ResizerAreaSet; - void addResizerArea(RenderBox*); - void removeResizerArea(RenderBox*); + void addResizerArea(RenderBox&); + void removeResizerArea(RenderBox&); const ResizerAreaSet* resizerAreas() const { return m_resizerAreas.get(); } virtual void removeChild(Widget*) OVERRIDE; @@ -313,15 +286,6 @@ public: // we need this function in order to do the scroll ourselves. bool wheelEvent(const PlatformWheelEvent&); - // Page and FrameView both store a Pagination value. Page::pagination() is set only by API, - // and FrameView::pagination() is set only by CSS. Page::pagination() will affect all - // FrameViews in the page cache, but FrameView::pagination() only affects the current - // FrameView. FrameView::pagination() will return m_pagination if it has been set. Otherwise, - // it will return Page::pagination() since currently there are no callers that need to - // distinguish between the two. - const Pagination& pagination() const; - void setPagination(const Pagination&); - bool inProgrammaticScroll() const { return m_inProgrammaticScroll; } void setInProgrammaticScroll(bool programmaticScroll) { m_inProgrammaticScroll = programmaticScroll; } @@ -333,54 +297,59 @@ public: // DEPRECATED: Use viewportConstrainedVisibleContentRect() instead. IntSize scrollOffsetForFixedPosition() const; - PartialLayoutState& partialLayout() { return m_partialLayout; } - // Override scrollbar notifications to update the AXObject cache. virtual void didAddScrollbar(Scrollbar*, ScrollbarOrientation) OVERRIDE; virtual void willRemoveScrollbar(Scrollbar*, ScrollbarOrientation) OVERRIDE; - class DeferredRepaintScope { - public: - DeferredRepaintScope(FrameView&); - ~DeferredRepaintScope(); - private: - RefPtr<FrameView> m_view; - }; + virtual bool shouldAttemptToScrollUsingFastPath() const OVERRIDE; + // FIXME: This should probably be renamed as the 'inSubtreeLayout' parameter + // passed around the FrameView layout methods can be true while this returns + // false. + bool isSubtreeLayout() const { return !!m_layoutSubtreeRoot; } + + // Sets the tickmarks for the FrameView, overriding the default behavior + // which is to display the tickmarks corresponding to find results. + // If |m_tickmarks| is empty, the default behavior is restored. + void setTickmarks(const Vector<IntRect>& tickmarks) { m_tickmarks = tickmarks; } + + // ScrollableArea interface + virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) OVERRIDE; + virtual void getTickmarks(Vector<IntRect>&) const OVERRIDE; + virtual void scrollTo(const IntSize&) OVERRIDE; + virtual IntRect scrollableAreaBoundingBox() const OVERRIDE; + virtual bool scrollAnimatorEnabled() const OVERRIDE; + virtual bool usesCompositedScrolling() const OVERRIDE; + virtual GraphicsLayer* layerForScrolling() const OVERRIDE; + virtual GraphicsLayer* layerForHorizontalScrollbar() const OVERRIDE; + virtual GraphicsLayer* layerForVerticalScrollbar() const OVERRIDE; + virtual GraphicsLayer* layerForScrollCorner() const OVERRIDE; protected: - virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); - virtual void scrollContentsSlowPath(const IntRect& updateRect); + virtual void scrollContentsIfNeeded(); + virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) OVERRIDE; + virtual void scrollContentsSlowPath(const IntRect& updateRect) OVERRIDE; - virtual bool isVerticalDocument() const; - virtual bool isFlippedDocument() const; + virtual bool isVerticalDocument() const OVERRIDE; + virtual bool isFlippedDocument() const OVERRIDE; private: - explicit FrameView(Frame*); - - void beginDeferredRepaints(); - void endDeferredRepaints(); - void flushDeferredRepaints(); - void startDeferredRepaintTimer(double delay); + explicit FrameView(LocalFrame*); void reset(); void init(); - virtual void frameRectsChanged(); + virtual void frameRectsChanged() OVERRIDE; virtual bool isFrameView() const OVERRIDE { return true; } friend class RenderWidget; bool useSlowRepaints(bool considerOverlap = true) const; bool useSlowRepaintsIfNotOverlapped() const; - void updateCanBlitOnScrollRecursively(); - bool contentsInCompositedLayer() const; - void applyOverflowToViewport(RenderObject*, ScrollbarMode& hMode, ScrollbarMode& vMode); - void applyPaginationToViewport(); + bool contentsInCompositedLayer() const; + void applyOverflowToViewportAndSetRenderer(RenderObject*, ScrollbarMode& hMode, ScrollbarMode& vMode); void updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow); - void paintControlTints(); - void updateCounters(); void autoSizeIfEnabled(); void forceLayoutParentViewIfNeeded(); @@ -389,13 +358,15 @@ private: void scheduleOrPerformPostLayoutTasks(); void performPostLayoutTasks(); - void repaintTree(RenderObject* root); + void invalidateTree(RenderObject* root); + + void gatherDebugLayoutRects(RenderObject* layoutRoot); - virtual void gatherDebugLayoutRects(RenderObject* layoutRoot); + DocumentLifecycle& lifecycle() const; - virtual void repaintContentRectangle(const IntRect&); + virtual void contentRectangleForPaintInvalidation(const IntRect&) OVERRIDE; virtual void contentsResized() OVERRIDE; - virtual void scrollbarExistenceDidChange(); + virtual void scrollbarExistenceDidChange() OVERRIDE; // Override ScrollView methods to do point conversion via renderers, in order to // take transforms into account. @@ -404,79 +375,70 @@ private: virtual IntPoint convertToContainingView(const IntPoint&) const OVERRIDE; virtual IntPoint convertFromContainingView(const IntPoint&) const OVERRIDE; - // ScrollableArea interface - virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) OVERRIDE; - virtual void getTickmarks(Vector<IntRect>&) const OVERRIDE; - virtual void scrollTo(const IntSize&) OVERRIDE; - virtual ScrollableArea* enclosingScrollableArea() const OVERRIDE; - virtual IntRect scrollableAreaBoundingBox() const OVERRIDE; - virtual bool scrollAnimatorEnabled() const OVERRIDE; - virtual bool usesCompositedScrolling() const OVERRIDE; - virtual GraphicsLayer* layerForScrolling() const OVERRIDE; - virtual GraphicsLayer* layerForHorizontalScrollbar() const OVERRIDE; - virtual GraphicsLayer* layerForVerticalScrollbar() const OVERRIDE; - virtual GraphicsLayer* layerForScrollCorner() const OVERRIDE; - void sendResizeEventIfNeeded(); void updateScrollableAreaSet(); - virtual void notifyPageThatContentAreaWillPaint() const; - - bool shouldUseLoadTimeDeferredRepaintDelay() const; - void deferredRepaintTimerFired(Timer<FrameView>*); - void doDeferredRepaints(); - void updateDeferredRepaintDelayAfterRepaint(); - double adjustedDeferredRepaintDelay() const; + virtual void notifyPageThatContentAreaWillPaint() const OVERRIDE; + void scheduleUpdateWidgetsIfNecessary(); void updateWidgetsTimerFired(Timer<FrameView>*); bool updateWidgets(); void scrollToAnchor(); void scrollPositionChanged(); + void didScrollTimerFired(Timer<FrameView>*); + + void updateLayersAndCompositingAfterScrollIfNeeded(); + void updateFixedElementPaintInvalidationRectsAfterScroll(); bool hasCustomScrollbars() const; - bool shouldUseCustomScrollbars(Element*& customScrollbarElement, Frame*& customScrollbarFrame); + bool shouldUseCustomScrollbars(Element*& customScrollbarElement, LocalFrame*& customScrollbarFrame); - virtual void updateScrollCorner(); + virtual void updateScrollCorner() OVERRIDE; FrameView* parentFrameView() const; - virtual AXObjectCache* axObjectCache() const; + AXObjectCache* axObjectCache() const; void removeFromAXObjectCache(); - bool isMainFrame() const; - void setLayoutSizeInternal(const IntSize&); + bool paintInvalidationIsAllowed() const + { + if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) + return true; + + return !isInPerformLayout() || canInvalidatePaintDuringPerformLayout(); + } + static double s_currentFrameTimeStamp; // used for detecting decoded resource thrash in the cache static bool s_inPaintContents; LayoutSize m_size; - LayoutSize m_margins; typedef HashSet<RefPtr<RenderEmbeddedObject> > EmbeddedObjectSet; EmbeddedObjectSet m_widgetUpdateSet; - RefPtr<Frame> m_frame; + // FIXME: These are just "children" of the FrameView and should be RefPtr<Widget> instead. + HashSet<RefPtr<RenderWidget> > m_widgets; + + RefPtr<LocalFrame> m_frame; - bool m_doFullRepaint; + bool m_doFullPaintInvalidation; bool m_canHaveScrollbars; bool m_cannotBlitToWindow; bool m_isOverlapped; bool m_contentIsOpaque; unsigned m_slowRepaintObjectCount; - int m_borderX; - int m_borderY; - Timer<FrameView> m_layoutTimer; - bool m_delayedLayout; - RenderObject* m_layoutRoot; + bool m_hasPendingLayout; + RenderObject* m_layoutSubtreeRoot; bool m_layoutSchedulingEnabled; - bool m_inLayout; - bool m_doingPreLayoutStyleUpdate; + bool m_inPerformLayout; + bool m_canInvalidatePaintDuringPerformLayout; bool m_inSynchronousPostLayout; int m_layoutCount; unsigned m_nestedLayoutCount; @@ -498,25 +460,16 @@ private: bool m_verticalOverflow; RenderObject* m_viewportRenderer; - Pagination m_pagination; - bool m_wasScrolledByUser; bool m_inProgrammaticScroll; bool m_safeToPropagateScrollToParent; - unsigned m_deferringRepaints; - unsigned m_repaintCount; - Vector<LayoutRect> m_repaintRects; - Timer<FrameView> m_deferredRepaintTimer; - double m_deferredRepaintDelay; double m_lastPaintTime; - bool m_isTrackingRepaints; // Used for testing. - Vector<IntRect> m_trackedRepaintRects; - - bool m_shouldUpdateWhileOffscreen; + bool m_isTrackingPaintInvalidations; // Used for testing. + Vector<IntRect> m_trackedPaintInvalidationRects; - RefPtr<Node> m_nodeToDraw; + RefPtrWillBePersistent<Node> m_nodeToDraw; PaintBehavior m_paintBehavior; bool m_isPainting; @@ -525,7 +478,7 @@ private: bool m_isVisuallyNonEmpty; bool m_firstVisuallyNonEmptyLayoutCallbackPending; - RefPtr<Node> m_maintainScrollPositionAnchor; + RefPtrWillBePersistent<Node> m_maintainScrollPositionAnchor; // Renderer to hold our custom scroll corner. RenderScrollbarPart* m_scrollCorner; @@ -544,20 +497,18 @@ private: OwnPtr<ResizerAreaSet> m_resizerAreas; OwnPtr<ViewportConstrainedObjectSet> m_viewportConstrainedObjects; - static double s_normalDeferredRepaintDelay; - static double s_initialDeferredRepaintDelayDuringLoading; - static double s_maxDeferredRepaintDelayDuringLoading; - static double s_deferredRepaintDelayIncrementDuringLoading; - bool m_hasSoftwareFilters; float m_visibleContentScaleFactor; IntSize m_inputEventsOffsetForEmulation; float m_inputEventsScaleFactorForEmulation; - PartialLayoutState m_partialLayout; IntSize m_layoutSize; bool m_layoutSizeFixedToFrameSize; + + Timer<FrameView> m_didScrollTimer; + + Vector<IntRect> m_tickmarks; }; inline void FrameView::incrementVisuallyNonEmptyCharacterCount(unsigned count) @@ -585,6 +536,30 @@ inline void FrameView::incrementVisuallyNonEmptyPixelCount(const IntSize& size) DEFINE_TYPE_CASTS(FrameView, Widget, widget, widget->isFrameView(), widget.isFrameView()); +class AllowPaintInvalidationScope { +public: + explicit AllowPaintInvalidationScope(FrameView* view) + : m_view(view) + , m_originalValue(view ? view->canInvalidatePaintDuringPerformLayout() : false) + { + if (!m_view) + return; + + m_view->setCanInvalidatePaintDuringPerformLayout(true); + } + + ~AllowPaintInvalidationScope() + { + if (!m_view) + return; + + m_view->setCanInvalidatePaintDuringPerformLayout(m_originalValue); + } +private: + FrameView* m_view; + bool m_originalValue; +}; + } // namespace WebCore #endif // FrameView_h diff --git a/chromium/third_party/WebKit/Source/core/frame/GraphicsLayerDebugInfo.cpp b/chromium/third_party/WebKit/Source/core/frame/GraphicsLayerDebugInfo.cpp deleted file mode 100644 index 51470a2210e..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/GraphicsLayerDebugInfo.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include "core/frame/GraphicsLayerDebugInfo.h" - -#include "platform/JSONValues.h" -#include "wtf/text/CString.h" - -namespace WebCore { - -void GraphicsLayerDebugInfo::appendAsTraceFormat(blink::WebString* out) const -{ - RefPtr<JSONArray> jsonArray = JSONArray::create(); - for (size_t i = 0; i < m_currentLayoutRects.size(); i++) { - const LayoutRect& rect = m_currentLayoutRects[i]; - RefPtr<JSONObject> rectContainer = JSONObject::create(); - RefPtr<JSONArray> rectArray = JSONArray::create(); - rectArray->pushNumber(rect.x().toFloat()); - rectArray->pushNumber(rect.y().toFloat()); - rectArray->pushNumber(rect.maxX().toFloat()); - rectArray->pushNumber(rect.maxY().toFloat()); - rectContainer->setArray("geometry_rect", rectArray); - jsonArray->pushObject(rectContainer); - } - *out = jsonArray->toJSONString(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/History.cpp b/chromium/third_party/WebKit/Source/core/frame/History.cpp index 863c93683ca..492a69d08a8 100644 --- a/chromium/third_party/WebKit/Source/core/frame/History.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/History.cpp @@ -29,11 +29,11 @@ #include "bindings/v8/ExceptionState.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/history/HistoryItem.h" +#include "core/frame/LocalFrame.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" +#include "core/loader/HistoryItem.h" #include "core/page/BackForwardClient.h" #include "core/page/Page.h" #include "platform/weborigin/KURL.h" @@ -42,9 +42,9 @@ namespace WebCore { -History::History(Frame* frame) +History::History(LocalFrame* frame) : DOMWindowProperty(frame) - , m_lastStateObjectRequested(0) + , m_lastStateObjectRequested(nullptr) { ScriptWrappable::init(this); } @@ -105,7 +105,7 @@ void History::go(ExecutionContext* context, int distance) if (!activeDocument) return; - if (!activeDocument->canNavigate(m_frame)) + if (!activeDocument->canNavigate(*m_frame)) return; m_frame->navigationScheduler().scheduleHistoryNavigation(distance); @@ -123,9 +123,9 @@ KURL History::urlForState(const String& urlString) return KURL(document->baseURL(), urlString); } -void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const String& /* title */, const String& urlString, SameDocumentNavigationSource sameDocumentNavigationSource, ExceptionState& exceptionState) +void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const String& /* title */, const String& urlString, FrameLoadType type, ExceptionState& exceptionState) { - if (!m_frame || !m_frame->page()) + if (!m_frame || !m_frame->page() || !m_frame->loader().documentLoader()) return; KURL fullURL = urlForState(urlString); @@ -134,7 +134,7 @@ void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const Str exceptionState.throwSecurityError("A history state object with URL '" + fullURL.elidedString() + "' cannot be created in a document with origin '" + m_frame->document()->securityOrigin()->toString() + "'."); return; } - m_frame->loader().updateForSameDocumentNavigation(fullURL, sameDocumentNavigationSource, data, FrameLoader::DoNotUpdateBackForwardList); + m_frame->loader().updateForSameDocumentNavigation(fullURL, SameDocumentNavigationHistoryApi, data, type); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/History.h b/chromium/third_party/WebKit/Source/core/frame/History.h index 42ec3456a02..e4211486b37 100644 --- a/chromium/third_party/WebKit/Source/core/frame/History.h +++ b/chromium/third_party/WebKit/Source/core/frame/History.h @@ -30,20 +30,24 @@ #include "bindings/v8/SerializedScriptValue.h" #include "core/loader/FrameLoaderTypes.h" #include "core/frame/DOMWindowProperty.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class Frame; +class LocalFrame; class KURL; class ExecutionContext; class ExceptionState; -class History : public ScriptWrappable, public RefCounted<History>, public DOMWindowProperty { +class History FINAL : public RefCountedWillBeGarbageCollectedFinalized<History>, public ScriptWrappable, public DOMWindowProperty { public: - static PassRefPtr<History> create(Frame* frame) { return adoptRef(new History(frame)); } + static PassRefPtrWillBeRawPtr<History> create(LocalFrame* frame) + { + return adoptRefWillBeNoop(new History(frame)); + } unsigned length() const; SerializedScriptValue* state(); @@ -55,10 +59,12 @@ public: bool stateChanged() const; bool isSameAsCurrentState(SerializedScriptValue*) const; - void stateObjectAdded(PassRefPtr<SerializedScriptValue>, const String& title, const String& url, SameDocumentNavigationSource, ExceptionState&); + void stateObjectAdded(PassRefPtr<SerializedScriptValue>, const String& title, const String& url, FrameLoadType, ExceptionState&); + + void trace(Visitor*) { } private: - explicit History(Frame*); + explicit History(LocalFrame*); KURL urlForState(const String& url); diff --git a/chromium/third_party/WebKit/Source/core/frame/History.idl b/chromium/third_party/WebKit/Source/core/frame/History.idl index 6bd64396230..40606047612 100644 --- a/chromium/third_party/WebKit/Source/core/frame/History.idl +++ b/chromium/third_party/WebKit/Source/core/frame/History.idl @@ -23,7 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -interface History { +[ + WillBeGarbageCollected, +] interface History { readonly attribute unsigned long length; [Custom=Getter] readonly attribute SerializedScriptValue state; diff --git a/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.cpp index ec54c645533..bbd9e0fd5d8 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.cpp @@ -14,23 +14,21 @@ #include "platform/graphics/ImageBuffer.h" #include "wtf/RefPtr.h" -using namespace std; - namespace WebCore { static inline IntRect normalizeRect(const IntRect& rect) { - return IntRect(min(rect.x(), rect.maxX()), - min(rect.y(), rect.maxY()), - max(rect.width(), -rect.width()), - max(rect.height(), -rect.height())); + return IntRect(std::min(rect.x(), rect.maxX()), + std::min(rect.y(), rect.maxY()), + std::max(rect.width(), -rect.width()), + std::max(rect.height(), -rect.height())); } static inline PassRefPtr<Image> cropImage(Image* image, const IntRect& cropRect) { IntRect intersectRect = intersection(IntRect(IntPoint(), image->size()), cropRect); if (!intersectRect.width() || !intersectRect.height()) - return 0; + return nullptr; SkBitmap cropped; image->nativeImageForCurrentFrame()->bitmap().extractSubset(&cropped, intersectRect); @@ -39,15 +37,15 @@ static inline PassRefPtr<Image> cropImage(Image* image, const IntRect& cropRect) ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect) : m_imageElement(image) - , m_bitmap(0) + , m_bitmap(nullptr) , m_cropRect(cropRect) { IntRect srcRect = intersection(cropRect, IntRect(0, 0, image->width(), image->height())); - m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size()); + m_bitmapRect = IntRect(IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())), srcRect.size()); m_bitmapOffset = srcRect.location(); if (!srcRect.width() || !srcRect.height()) - m_imageElement = 0; + m_imageElement = nullptr; else m_imageElement->addClient(this); @@ -55,11 +53,16 @@ ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect) } ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect) - : m_imageElement(0) + : m_imageElement(nullptr) , m_cropRect(cropRect) , m_bitmapOffset(IntPoint()) { - IntRect videoRect = IntRect(IntPoint(), video->player()->naturalSize()); + IntSize playerSize; + + if (video->webMediaPlayer()) + playerSize = video->webMediaPlayer()->naturalSize(); + + IntRect videoRect = IntRect(IntPoint(), playerSize); IntRect srcRect = intersection(cropRect, videoRect); IntRect dstRect(IntPoint(), srcRect.size()); @@ -71,13 +74,13 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect) c->translate(-srcRect.x(), -srcRect.y()); video->paintCurrentFrameInContext(c, videoRect); m_bitmap = buf->copyImage(DontCopyBackingStore); - m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size()); + m_bitmapRect = IntRect(IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())), srcRect.size()); ScriptWrappable::init(this); } ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect) - : m_imageElement(0) + : m_imageElement(nullptr) , m_cropRect(cropRect) , m_bitmapOffset(IntPoint()) { @@ -86,14 +89,14 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect) sourceContext->paintRenderingResultsToCanvas(); IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), canvas->size())); - m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size()); + m_bitmapRect = IntRect(IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())), srcRect.size()); m_bitmap = cropImage(canvas->buffer()->copyImage(CopyBackingStore).get(), cropRect); ScriptWrappable::init(this); } ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect) - : m_imageElement(0) + : m_imageElement(nullptr) , m_cropRect(cropRect) , m_bitmapOffset(IntPoint()) { @@ -103,23 +106,23 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect) if (!buf) return; if (srcRect.width() > 0 && srcRect.height() > 0) - buf->putByteArray(Premultiplied, data->data(), data->size(), srcRect, IntPoint(min(0, -cropRect.x()), min(0, -cropRect.y()))); + buf->putByteArray(Premultiplied, data->data(), data->size(), srcRect, IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRect.y()))); m_bitmap = buf->copyImage(DontCopyBackingStore); - m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size()); + m_bitmapRect = IntRect(IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())), srcRect.size()); ScriptWrappable::init(this); } ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect) : m_imageElement(bitmap->imageElement()) - , m_bitmap(0) + , m_bitmap(nullptr) , m_cropRect(cropRect) , m_bitmapOffset(IntPoint()) { IntRect oldBitmapRect = bitmap->bitmapRect(); IntRect srcRect = intersection(cropRect, oldBitmapRect); - m_bitmapRect = IntRect(IntPoint(max(0, oldBitmapRect.x() - cropRect.x()), max(0, oldBitmapRect.y() - cropRect.y())), srcRect.size()); + m_bitmapRect = IntRect(IntPoint(std::max(0, oldBitmapRect.x() - cropRect.x()), std::max(0, oldBitmapRect.y() - cropRect.y())), srcRect.size()); if (m_imageElement) { m_imageElement->addClient(this); @@ -133,63 +136,65 @@ ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect) } ImageBitmap::ImageBitmap(Image* image, const IntRect& cropRect) - : m_imageElement(0) + : m_imageElement(nullptr) , m_cropRect(cropRect) { IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), image->size())); m_bitmap = cropImage(image, cropRect); - m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size()); + m_bitmapRect = IntRect(IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())), srcRect.size()); ScriptWrappable::init(this); } ImageBitmap::~ImageBitmap() { +#if !ENABLE(OILPAN) if (m_imageElement) m_imageElement->removeClient(this); +#endif } -PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLImageElement* image, const IntRect& cropRect) +PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(HTMLImageElement* image, const IntRect& cropRect) { IntRect normalizedCropRect = normalizeRect(cropRect); - return adoptRef(new ImageBitmap(image, normalizedCropRect)); + return adoptRefWillBeNoop(new ImageBitmap(image, normalizedCropRect)); } -PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLVideoElement* video, const IntRect& cropRect) +PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(HTMLVideoElement* video, const IntRect& cropRect) { IntRect normalizedCropRect = normalizeRect(cropRect); - return adoptRef(new ImageBitmap(video, normalizedCropRect)); + return adoptRefWillBeNoop(new ImageBitmap(video, normalizedCropRect)); } -PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLCanvasElement* canvas, const IntRect& cropRect) +PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(HTMLCanvasElement* canvas, const IntRect& cropRect) { IntRect normalizedCropRect = normalizeRect(cropRect); - return adoptRef(new ImageBitmap(canvas, normalizedCropRect)); + return adoptRefWillBeNoop(new ImageBitmap(canvas, normalizedCropRect)); } -PassRefPtr<ImageBitmap> ImageBitmap::create(ImageData* data, const IntRect& cropRect) +PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(ImageData* data, const IntRect& cropRect) { IntRect normalizedCropRect = normalizeRect(cropRect); - return adoptRef(new ImageBitmap(data, normalizedCropRect)); + return adoptRefWillBeNoop(new ImageBitmap(data, normalizedCropRect)); } -PassRefPtr<ImageBitmap> ImageBitmap::create(ImageBitmap* bitmap, const IntRect& cropRect) +PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(ImageBitmap* bitmap, const IntRect& cropRect) { IntRect normalizedCropRect = normalizeRect(cropRect); - return adoptRef(new ImageBitmap(bitmap, normalizedCropRect)); + return adoptRefWillBeNoop(new ImageBitmap(bitmap, normalizedCropRect)); } -PassRefPtr<ImageBitmap> ImageBitmap::create(Image* image, const IntRect& cropRect) +PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(Image* image, const IntRect& cropRect) { IntRect normalizedCropRect = normalizeRect(cropRect); - return adoptRef(new ImageBitmap(image, normalizedCropRect)); + return adoptRefWillBeNoop(new ImageBitmap(image, normalizedCropRect)); } void ImageBitmap::notifyImageSourceChanged() { m_bitmap = cropImage(m_imageElement->cachedImage()->image(), m_cropRect); m_bitmapOffset = IntPoint(); - m_imageElement = 0; + m_imageElement = nullptr; } PassRefPtr<Image> ImageBitmap::bitmapImage() const @@ -200,4 +205,34 @@ PassRefPtr<Image> ImageBitmap::bitmapImage() const return m_bitmap; } +PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageMode, SourceImageStatus* status) const +{ + *status = NormalSourceImageStatus; + return bitmapImage(); +} + +void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const +{ + FloatRect intersectRect = intersection(m_bitmapRect, *srcRect); + FloatRect newSrcRect = intersectRect; + newSrcRect.move(m_bitmapOffset - m_bitmapRect.location()); + FloatRect newDstRect(FloatPoint(intersectRect.location() - srcRect->location()), m_bitmapRect.size()); + newDstRect.scale(dstRect->width() / srcRect->width() * intersectRect.width() / m_bitmapRect.width(), + dstRect->height() / srcRect->height() * intersectRect.height() / m_bitmapRect.height()); + newDstRect.moveBy(dstRect->location()); + *srcRect = newSrcRect; + *dstRect = newDstRect; +} + +FloatSize ImageBitmap::sourceSize() const +{ + return FloatSize(width(), height()); +} + +void ImageBitmap::trace(Visitor* visitor) +{ + visitor->trace(m_imageElement); + ImageLoaderClient::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.h b/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.h index 8c9229d5102..653a82b8e35 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.h +++ b/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.h @@ -7,8 +7,10 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/HTMLImageElement.h" +#include "core/html/canvas/CanvasImageSource.h" #include "platform/geometry/IntRect.h" #include "platform/graphics/Image.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -18,21 +20,20 @@ class HTMLCanvasElement; class HTMLVideoElement; class ImageData; -class ImageBitmap : public RefCounted<ImageBitmap>, public ScriptWrappable, public ImageLoaderClient { - +class ImageBitmap FINAL : public RefCountedWillBeGarbageCollectedFinalized<ImageBitmap>, public ScriptWrappable, public ImageLoaderClient, public CanvasImageSource { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ImageBitmap); public: - static PassRefPtr<ImageBitmap> create(HTMLImageElement*, const IntRect&); - static PassRefPtr<ImageBitmap> create(HTMLVideoElement*, const IntRect&); - static PassRefPtr<ImageBitmap> create(HTMLCanvasElement*, const IntRect&); - static PassRefPtr<ImageBitmap> create(ImageData*, const IntRect&); - static PassRefPtr<ImageBitmap> create(ImageBitmap*, const IntRect&); - static PassRefPtr<ImageBitmap> create(Image*, const IntRect&); + static PassRefPtrWillBeRawPtr<ImageBitmap> create(HTMLImageElement*, const IntRect&); + static PassRefPtrWillBeRawPtr<ImageBitmap> create(HTMLVideoElement*, const IntRect&); + static PassRefPtrWillBeRawPtr<ImageBitmap> create(HTMLCanvasElement*, const IntRect&); + static PassRefPtrWillBeRawPtr<ImageBitmap> create(ImageData*, const IntRect&); + static PassRefPtrWillBeRawPtr<ImageBitmap> create(ImageBitmap*, const IntRect&); + static PassRefPtrWillBeRawPtr<ImageBitmap> create(Image*, const IntRect&); PassRefPtr<Image> bitmapImage() const; - PassRefPtr<HTMLImageElement> imageElement() const { return m_imageElement; } + PassRefPtrWillBeRawPtr<HTMLImageElement> imageElement() const { return m_imageElement; } IntRect bitmapRect() const { return m_bitmapRect; } - IntPoint bitmapOffset() const { return m_bitmapOffset; } int width() const { return m_cropRect.width(); } int height() const { return m_cropRect.height(); } @@ -40,6 +41,14 @@ public: virtual ~ImageBitmap(); + // CanvasImageSource implementation + virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus*) const OVERRIDE; + virtual bool wouldTaintOrigin(SecurityOrigin*) const OVERRIDE { return false; }; + virtual void adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const OVERRIDE; + virtual FloatSize sourceSize() const OVERRIDE; + + virtual void trace(Visitor*); + private: ImageBitmap(HTMLImageElement*, const IntRect&); ImageBitmap(HTMLVideoElement*, const IntRect&); @@ -49,12 +58,12 @@ private: ImageBitmap(Image*, const IntRect&); // ImageLoaderClient - virtual void notifyImageSourceChanged(); - virtual bool requestsHighLiveResourceCachePriority() { return true; } + virtual void notifyImageSourceChanged() OVERRIDE; + virtual bool requestsHighLiveResourceCachePriority() OVERRIDE { return true; } // ImageBitmaps constructed from HTMLImageElements hold a reference to the HTMLImageElement until // the image source changes. - RefPtr<HTMLImageElement> m_imageElement; + RefPtrWillBeMember<HTMLImageElement> m_imageElement; RefPtr<Image> m_bitmap; IntRect m_bitmapRect; // The rect where the underlying Image should be placed in reference to the ImageBitmap. diff --git a/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.idl b/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.idl index 903a2d7421f..b211d6ec29b 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.idl +++ b/chromium/third_party/WebKit/Source/core/frame/ImageBitmap.idl @@ -3,6 +3,7 @@ // found in the LICENSE file. [ + WillBeGarbageCollected, ] interface ImageBitmap { readonly attribute long width; readonly attribute long height; diff --git a/chromium/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp b/chromium/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp index 6a6626ae7ab..ad2e9fdcab1 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "core/frame/ImageBitmap.h" -#include "SkPixelRef.h" +#include "SkPixelRef.h" // FIXME: qualify this skia header file. #include "core/dom/Document.h" #include "core/fetch/ImageResource.h" #include "core/fetch/MemoryCache.h" @@ -42,6 +42,7 @@ #include "core/html/canvas/CanvasRenderingContext2D.h" #include "platform/graphics/BitmapImage.h" #include "platform/graphics/skia/NativeImageSkia.h" +#include "platform/heap/Handle.h" #include "platform/network/ResourceRequest.h" #include "wtf/OwnPtr.h" @@ -53,12 +54,10 @@ class ImageBitmapTest : public ::testing::Test { protected: virtual void SetUp() { - m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10); - m_bitmap.allocPixels(); + ASSERT_TRUE(m_bitmap.allocN32Pixels(10, 10)); m_bitmap.eraseColor(0xFFFFFFFF); - m_bitmap2.setConfig(SkBitmap::kARGB_8888_Config, 5, 5); - m_bitmap2.allocPixels(); + ASSERT_TRUE(m_bitmap2.allocN32Pixels(5, 5)); m_bitmap2.eraseColor(0xAAAAAAAA); // Save the global memory cache to restore it upon teardown. @@ -69,6 +68,11 @@ protected: } virtual void TearDown() { + // Garbage collection is required prior to switching out the + // test's memory cache; image resources are released, evicting + // them from the cache. + Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); + // Regain the ownership of testing memory cache, so that it will be // destroyed. m_testingMemoryCache = adoptPtr(memoryCache()); @@ -85,13 +89,13 @@ protected: // one held by the HTMLImageElement. TEST_F(ImageBitmapTest, ImageResourceConsistency) { - RefPtr<HTMLImageElement> imageElement = HTMLImageElement::create(*Document::create().get()); + RefPtrWillBeRawPtr<HTMLImageElement> imageElement = HTMLImageElement::create(*Document::create().get()); imageElement->setImageResource(new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get())); - RefPtr<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageElement.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); - RefPtr<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageElement.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width() / 2, m_bitmap.height() / 2)); - RefPtr<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageElement.get(), IntRect(-m_bitmap.width() / 2, -m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); - RefPtr<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageElement.get(), IntRect(-m_bitmap.width(), -m_bitmap.height(), m_bitmap.width(), m_bitmap.height())); + RefPtrWillBeRawPtr<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageElement.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); + RefPtrWillBeRawPtr<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageElement.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width() / 2, m_bitmap.height() / 2)); + RefPtrWillBeRawPtr<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageElement.get(), IntRect(-m_bitmap.width() / 2, -m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); + RefPtrWillBeRawPtr<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageElement.get(), IntRect(-m_bitmap.width(), -m_bitmap.height(), m_bitmap.width(), m_bitmap.height())); ASSERT_EQ(imageBitmapNoCrop->bitmapImage().get(), imageElement->cachedImage()->image()); ASSERT_EQ(imageBitmapInteriorCrop->bitmapImage().get(), imageElement->cachedImage()->image()); @@ -105,20 +109,20 @@ TEST_F(ImageBitmapTest, ImageResourceConsistency) // ImageBitmaps that have crop rects outside of the bounds of the HTMLImageElement do not have elevated CacheLiveResourcePriority. TEST_F(ImageBitmapTest, ImageBitmapLiveResourcePriority) { - RefPtr<HTMLImageElement> imageNoCrop = HTMLImageElement::create(*Document::create().get()); - ResourcePtr<ImageResource> cachedImageNoCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); + RefPtrWillBePersistent<HTMLImageElement> imageNoCrop = HTMLImageElement::create(*Document::create().get()); + ResourcePtr<ImageResource> cachedImageNoCrop = new ImageResource(ResourceRequest("http://foo.com/1"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageNoCrop->setImageResource(cachedImageNoCrop.get()); - RefPtr<HTMLImageElement> imageInteriorCrop = HTMLImageElement::create(*Document::create().get()); - ResourcePtr<ImageResource> cachedImageInteriorCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); + RefPtrWillBePersistent<HTMLImageElement> imageInteriorCrop = HTMLImageElement::create(*Document::create().get()); + ResourcePtr<ImageResource> cachedImageInteriorCrop = new ImageResource(ResourceRequest("http://foo.com/2"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageInteriorCrop->setImageResource(cachedImageInteriorCrop.get()); - RefPtr<HTMLImageElement> imageExteriorCrop = HTMLImageElement::create(*Document::create().get()); - ResourcePtr<ImageResource> cachedImageExteriorCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); + RefPtrWillBePersistent<HTMLImageElement> imageExteriorCrop = HTMLImageElement::create(*Document::create().get()); + ResourcePtr<ImageResource> cachedImageExteriorCrop = new ImageResource(ResourceRequest("http://foo.com/3"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageExteriorCrop->setImageResource(cachedImageExteriorCrop.get()); - RefPtr<HTMLImageElement> imageOutsideCrop = HTMLImageElement::create(*Document::create().get()); - ResourcePtr<ImageResource> cachedImageOutsideCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); + RefPtrWillBePersistent<HTMLImageElement> imageOutsideCrop = HTMLImageElement::create(*Document::create().get()); + ResourcePtr<ImageResource> cachedImageOutsideCrop = new ImageResource(ResourceRequest("http://foo.com/4"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageOutsideCrop->setImageResource(cachedImageOutsideCrop.get()); MockImageResourceClient mockClient1, mockClient2, mockClient3, mockClient4; @@ -131,50 +135,53 @@ TEST_F(ImageBitmapTest, ImageBitmapLiveResourcePriority) memoryCache()->add(cachedImageInteriorCrop.get()); memoryCache()->add(cachedImageExteriorCrop.get()); memoryCache()->add(cachedImageOutsideCrop.get()); - memoryCache()->insertInLiveDecodedResourcesList(cachedImageNoCrop.get()); - memoryCache()->insertInLiveDecodedResourcesList(cachedImageInteriorCrop.get()); - memoryCache()->insertInLiveDecodedResourcesList(cachedImageExteriorCrop.get()); - memoryCache()->insertInLiveDecodedResourcesList(cachedImageOutsideCrop.get()); + memoryCache()->updateDecodedResource(cachedImageNoCrop.get(), UpdateForPropertyChange); + memoryCache()->updateDecodedResource(cachedImageInteriorCrop.get(), UpdateForPropertyChange); + memoryCache()->updateDecodedResource(cachedImageExteriorCrop.get(), UpdateForPropertyChange); + memoryCache()->updateDecodedResource(cachedImageOutsideCrop.get(), UpdateForPropertyChange); // HTMLImageElements should default to CacheLiveResourcePriorityLow. - ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); - ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); - ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); - ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); - RefPtr<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); + RefPtrWillBePersistent<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); { - RefPtr<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageNoCrop.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); - RefPtr<ImageBitmap> imageBitmapInteriorCrop2 = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); - RefPtr<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageExteriorCrop.get(), IntRect(-m_bitmap.width() / 2, -m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); - RefPtr<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageOutsideCrop.get(), IntRect(-m_bitmap.width(), -m_bitmap.height(), m_bitmap.width(), m_bitmap.height())); + RefPtrWillBePersistent<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageNoCrop.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); + RefPtrWillBePersistent<ImageBitmap> imageBitmapInteriorCrop2 = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); + RefPtrWillBePersistent<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageExteriorCrop.get(), IntRect(-m_bitmap.width() / 2, -m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); + RefPtrWillBePersistent<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageOutsideCrop.get(), IntRect(-m_bitmap.width(), -m_bitmap.height(), m_bitmap.width(), m_bitmap.height())); // Images that are referenced by ImageBitmaps have CacheLiveResourcePriorityHigh. - ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); - ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); - ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); + ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); + ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); + ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); // ImageBitmaps that do not contain any of the source image do not elevate CacheLiveResourcePriority. - ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); } + // Force a garbage collection to sweep out the local ImageBitmaps. + Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); // CacheLiveResourcePriroity should return to CacheLiveResourcePriorityLow when no ImageBitmaps reference the image. - ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); - ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); - ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); + ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); // There is still an ImageBitmap that references this image. - ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); + ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); + imageBitmapInteriorCrop = nullptr; } // Verifies that ImageBitmaps constructed from HTMLImageElements hold a reference to the original Image if the HTMLImageElement src is changed. TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) { - RefPtr<HTMLImageElement> image = HTMLImageElement::create(*Document::create().get()); + RefPtrWillBeRawPtr<HTMLImageElement> image = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> originalImageResource = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); image->setImageResource(originalImageResource.get()); - RefPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); + RefPtrWillBeRawPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); ASSERT_EQ(imageBitmap->bitmapImage().get(), originalImageResource->image()); ResourcePtr<ImageResource> newImageResource = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap2)).get()); @@ -193,12 +200,12 @@ TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) // Verifies that ImageBitmaps constructed from ImageBitmaps hold onto their own Image. TEST_F(ImageBitmapTest, ImageResourceLifetime) { - RefPtr<HTMLCanvasElement> canvasElement = HTMLCanvasElement::create(*Document::create().get()); + RefPtrWillBeRawPtr<HTMLCanvasElement> canvasElement = HTMLCanvasElement::create(*Document::create().get()); canvasElement->setHeight(40); canvasElement->setWidth(40); - RefPtr<ImageBitmap> imageBitmapDerived; + RefPtrWillBeRawPtr<ImageBitmap> imageBitmapDerived = nullptr; { - RefPtr<ImageBitmap> imageBitmapFromCanvas = ImageBitmap::create(canvasElement.get(), IntRect(0, 0, canvasElement->width(), canvasElement->height())); + RefPtrWillBeRawPtr<ImageBitmap> imageBitmapFromCanvas = ImageBitmap::create(canvasElement.get(), IntRect(0, 0, canvasElement->width(), canvasElement->height())); imageBitmapDerived = ImageBitmap::create(imageBitmapFromCanvas.get(), IntRect(0, 0, 20, 20)); } CanvasRenderingContext* context = canvasElement->getContext("2d"); diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindow.cpp b/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp index bc36d37e3fe..135263cd6d4 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindow.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp @@ -25,10 +25,8 @@ */ #include "config.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" -#include <algorithm> -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" @@ -48,6 +46,7 @@ #include "core/dom/Element.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" +#include "core/dom/NoEventDispatchAssertion.h" #include "core/dom/RequestAnimationFrameCallback.h" #include "core/editing/Editor.h" #include "core/events/DOMWindowEventQueue.h" @@ -56,25 +55,29 @@ #include "core/events/MessageEvent.h" #include "core/events/PageTransitionEvent.h" #include "core/events/PopStateEvent.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/frame/BarProp.h" #include "core/frame/Console.h" #include "core/frame/DOMPoint.h" #include "core/frame/DOMWindowLifecycleNotifier.h" -#include "core/frame/Frame.h" +#include "core/frame/EventHandlerRegistry.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/History.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Location.h" #include "core/frame/Navigator.h" #include "core/frame/Screen.h" #include "core/frame/Settings.h" #include "core/html/HTMLFrameOwnerElement.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/inspector/ScriptCallStack.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoadRequest.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" +#include "core/loader/MixedContentChecker.h" #include "core/loader/SinkDocument.h" #include "core/loader/appcache/ApplicationCache.h" #include "core/page/BackForwardClient.h" @@ -84,8 +87,6 @@ #include "core/page/EventHandler.h" #include "core/page/FrameTree.h" #include "core/page/Page.h" -#include "core/page/PageConsole.h" -#include "core/page/PageGroup.h" #include "core/page/WindowFeatures.h" #include "core/page/WindowFocusAllowedIndicator.h" #include "core/page/scrolling/ScrollingCoordinator.h" @@ -94,6 +95,7 @@ #include "core/storage/StorageNamespace.h" #include "core/timing/Performance.h" #include "platform/PlatformScreen.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/UserGestureIndicator.h" #include "platform/geometry/FloatRect.h" #include "platform/graphics/media/MediaPlayer.h" @@ -104,47 +106,55 @@ #include "wtf/MainThread.h" #include "wtf/MathExtras.h" #include "wtf/text/WTFString.h" +#include <algorithm> using std::min; using std::max; namespace WebCore { -class PostMessageTimer : public TimerBase { +class PostMessageTimer FINAL : public SuspendableTimer { public: - PostMessageTimer(DOMWindow* window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin, PassRefPtr<ScriptCallStack> stackTrace) - : m_window(window) + PostMessageTimer(LocalDOMWindow& window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtrWillBeRawPtr<LocalDOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin, PassRefPtrWillBeRawPtr<ScriptCallStack> stackTrace, UserGestureToken* userGestureToken) + : SuspendableTimer(window.document()) + , m_window(&window) , m_message(message) , m_origin(sourceOrigin) , m_source(source) , m_channels(channels) , m_targetOrigin(targetOrigin) , m_stackTrace(stackTrace) + , m_userGestureToken(userGestureToken) { } - PassRefPtr<MessageEvent> event() + PassRefPtrWillBeRawPtr<MessageEvent> event() { - return MessageEvent::create(m_channels.release(), m_message, m_origin, String(), m_source); + return MessageEvent::create(m_channels.release(), m_message, m_origin, String(), m_source.get()); } SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); } ScriptCallStack* stackTrace() const { return m_stackTrace.get(); } + UserGestureToken* userGestureToken() const { return m_userGestureToken.get(); } private: - virtual void fired() + virtual void fired() OVERRIDE { - m_window->postMessageTimerFired(adoptPtr(this)); + m_window->postMessageTimerFired(this); // This object is deleted now. } - RefPtr<DOMWindow> m_window; + // FIXME: Oilpan: This raw pointer is safe because the PostMessageTimer is + // owned by the LocalDOMWindow. Ideally PostMessageTimer should be moved to + // the heap and use Member<LocalDOMWindow>. + LocalDOMWindow* m_window; RefPtr<SerializedScriptValue> m_message; String m_origin; - RefPtr<DOMWindow> m_source; + RefPtrWillBePersistent<LocalDOMWindow> m_source; OwnPtr<MessagePortChannelArray> m_channels; RefPtr<SecurityOrigin> m_targetOrigin; - RefPtr<ScriptCallStack> m_stackTrace; + RefPtrWillBePersistent<ScriptCallStack> m_stackTrace; + RefPtr<UserGestureToken> m_userGestureToken; }; static void disableSuddenTermination() @@ -157,7 +167,7 @@ static void enableSuddenTermination() blink::Platform::current()->suddenTerminationChanged(true); } -typedef HashCountedSet<DOMWindow*> DOMWindowSet; +typedef HashCountedSet<LocalDOMWindow*> DOMWindowSet; static DOMWindowSet& windowsWithUnloadEventListeners() { @@ -171,7 +181,7 @@ static DOMWindowSet& windowsWithBeforeUnloadEventListeners() return windowsWithBeforeUnloadEventListeners; } -static void addUnloadEventListener(DOMWindow* domWindow) +static void addUnloadEventListener(LocalDOMWindow* domWindow) { DOMWindowSet& set = windowsWithUnloadEventListeners(); if (set.isEmpty()) @@ -179,7 +189,7 @@ static void addUnloadEventListener(DOMWindow* domWindow) set.add(domWindow); } -static void removeUnloadEventListener(DOMWindow* domWindow) +static void removeUnloadEventListener(LocalDOMWindow* domWindow) { DOMWindowSet& set = windowsWithUnloadEventListeners(); DOMWindowSet::iterator it = set.find(domWindow); @@ -190,7 +200,7 @@ static void removeUnloadEventListener(DOMWindow* domWindow) enableSuddenTermination(); } -static void removeAllUnloadEventListeners(DOMWindow* domWindow) +static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow) { DOMWindowSet& set = windowsWithUnloadEventListeners(); DOMWindowSet::iterator it = set.find(domWindow); @@ -201,7 +211,7 @@ static void removeAllUnloadEventListeners(DOMWindow* domWindow) enableSuddenTermination(); } -static void addBeforeUnloadEventListener(DOMWindow* domWindow) +static void addBeforeUnloadEventListener(LocalDOMWindow* domWindow) { DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); if (set.isEmpty()) @@ -209,7 +219,7 @@ static void addBeforeUnloadEventListener(DOMWindow* domWindow) set.add(domWindow); } -static void removeBeforeUnloadEventListener(DOMWindow* domWindow) +static void removeBeforeUnloadEventListener(LocalDOMWindow* domWindow) { DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); DOMWindowSet::iterator it = set.find(domWindow); @@ -220,7 +230,7 @@ static void removeBeforeUnloadEventListener(DOMWindow* domWindow) enableSuddenTermination(); } -static void removeAllBeforeUnloadEventListeners(DOMWindow* domWindow) +static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow) { DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); DOMWindowSet::iterator it = set.find(domWindow); @@ -231,18 +241,18 @@ static void removeAllBeforeUnloadEventListeners(DOMWindow* domWindow) enableSuddenTermination(); } -static bool allowsBeforeUnloadListeners(DOMWindow* window) +static bool allowsBeforeUnloadListeners(LocalDOMWindow* window) { ASSERT_ARG(window, window); - Frame* frame = window->frame(); + LocalFrame* frame = window->frame(); if (!frame) return false; return frame->isMainFrame(); } -unsigned DOMWindow::pendingUnloadEventListeners() const +unsigned LocalDOMWindow::pendingUnloadEventListeners() const { - return windowsWithUnloadEventListeners().count(const_cast<DOMWindow*>(this)); + return windowsWithUnloadEventListeners().count(const_cast<LocalDOMWindow*>(this)); } // This function: @@ -251,12 +261,13 @@ unsigned DOMWindow::pendingUnloadEventListeners() const // 3) Constrains the window rect to within the top and left boundaries of the available screen rect. // 4) Constrains the window rect to within the bottom and right boundaries of the available screen rect. // 5) Translate the window rect coordinates to be within the coordinate space of the screen. -FloatRect DOMWindow::adjustWindowRect(Page* page, const FloatRect& pendingChanges) +FloatRect LocalDOMWindow::adjustWindowRect(LocalFrame& frame, const FloatRect& pendingChanges) { - ASSERT(page); + FrameHost* host = frame.host(); + ASSERT(host); - FloatRect screen = screenAvailableRect(page->mainFrame()->view()); - FloatRect window = page->chrome().windowRect(); + FloatRect screen = screenAvailableRect(frame.view()); + FloatRect window = host->chrome().windowRect(); // Make sure we're in a valid state before adjusting dimensions. ASSERT(std::isfinite(screen.x())); @@ -278,7 +289,7 @@ FloatRect DOMWindow::adjustWindowRect(Page* page, const FloatRect& pendingChange if (!std::isnan(pendingChanges.height())) window.setHeight(pendingChanges.height()); - FloatSize minimumSize = page->chrome().client().minimumWindowSize(); + FloatSize minimumSize = host->chrome().client().minimumWindowSize(); // Let size 0 pass through, since that indicates default size, not minimum size. if (window.width()) window.setWidth(min(max(minimumSize.width(), window.width()), screen.width())); @@ -292,51 +303,41 @@ FloatRect DOMWindow::adjustWindowRect(Page* page, const FloatRect& pendingChange return window; } -bool DOMWindow::allowPopUp(Frame* firstFrame) +bool LocalDOMWindow::allowPopUp(LocalFrame& firstFrame) { - ASSERT(firstFrame); - if (UserGestureIndicator::processingUserGesture()) return true; - Settings* settings = firstFrame->settings(); + Settings* settings = firstFrame.settings(); return settings && settings->javaScriptCanOpenWindowsAutomatically(); } -bool DOMWindow::allowPopUp() +bool LocalDOMWindow::allowPopUp() { - return m_frame && allowPopUp(m_frame); + return m_frame && allowPopUp(*m_frame); } -bool DOMWindow::canShowModalDialog(const Frame* frame) +bool LocalDOMWindow::canShowModalDialogNow(const LocalFrame* frame) { if (!frame) return false; - Page* page = frame->page(); - if (!page) + FrameHost* host = frame->host(); + if (!host) return false; - return page->chrome().canRunModal(); + return host->chrome().canRunModalNow(); } -bool DOMWindow::canShowModalDialogNow(const Frame* frame) -{ - if (!frame) - return false; - Page* page = frame->page(); - if (!page) - return false; - return page->chrome().canRunModalNow(); -} - -DOMWindow::DOMWindow(Frame* frame) - : FrameDestructionObserver(frame) +LocalDOMWindow::LocalDOMWindow(LocalFrame& frame) + : FrameDestructionObserver(&frame) , m_shouldPrintWhenFinishedLoading(false) +#if ASSERT_ENABLED + , m_hasBeenReset(false) +#endif { - ASSERT(frame); ScriptWrappable::init(this); } -void DOMWindow::clearDocument() +void LocalDOMWindow::clearDocument() { if (!m_document) return; @@ -351,14 +352,14 @@ void DOMWindow::clearDocument() m_document->detach(); } - // FIXME: This should be part of ActiveDOM Object shutdown + // FIXME: This should be part of ActiveDOMObject shutdown clearEventQueue(); m_document->clearDOMWindow(); - m_document = 0; + m_document = nullptr; } -void DOMWindow::clearEventQueue() +void LocalDOMWindow::clearEventQueue() { if (!m_eventQueue) return; @@ -366,9 +367,17 @@ void DOMWindow::clearEventQueue() m_eventQueue.clear(); } -PassRefPtr<Document> DOMWindow::createDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML) +void LocalDOMWindow::acceptLanguagesChanged() { - RefPtr<Document> document; + if (m_navigator) + m_navigator->setLanguagesChanged(); + + dispatchEvent(Event::create(EventTypeNames::languagechange)); +} + +PassRefPtrWillBeRawPtr<Document> LocalDOMWindow::createDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML) +{ + RefPtrWillBeRawPtr<Document> document = nullptr; if (forceXHTML) { // This is a hack for XSLTProcessor. See XSLTProcessor::createDocumentFromSource(). document = Document::create(init); @@ -381,7 +390,7 @@ PassRefPtr<Document> DOMWindow::createDocument(const String& mimeType, const Doc return document.release(); } -PassRefPtr<Document> DOMWindow::installNewDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML) +PassRefPtrWillBeRawPtr<Document> LocalDOMWindow::installNewDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML) { ASSERT(init.frame() == m_frame); @@ -391,8 +400,10 @@ PassRefPtr<Document> DOMWindow::installNewDocument(const String& mimeType, const m_eventQueue = DOMWindowEventQueue::create(m_document.get()); m_document->attach(); - if (!m_frame) - return m_document; + if (!m_frame) { + // FIXME: Oilpan: Remove .get() when m_document becomes Member<>. + return m_document.get(); + } m_frame->script().updateDocument(); m_document->updateViewportDescription(); @@ -408,20 +419,20 @@ PassRefPtr<Document> DOMWindow::installNewDocument(const String& mimeType, const m_frame->selection().updateSecureKeyboardEntryIfActive(); if (m_frame->isMainFrame()) { - m_frame->page()->mainFrame()->notifyChromeClientWheelEventHandlerCountChanged(); if (m_document->hasTouchEventHandlers()) - m_frame->page()->chrome().client().needTouchEvents(true); + m_frame->host()->chrome().client().needTouchEvents(true); } - return m_document; + // FIXME: Oilpan: Remove .get() when m_document becomes Member<>. + return m_document.get(); } -EventQueue* DOMWindow::eventQueue() const +EventQueue* LocalDOMWindow::eventQueue() const { return m_eventQueue.get(); } -void DOMWindow::enqueueWindowEvent(PassRefPtr<Event> event) +void LocalDOMWindow::enqueueWindowEvent(PassRefPtrWillBeRawPtr<Event> event) { if (!m_eventQueue) return; @@ -429,48 +440,51 @@ void DOMWindow::enqueueWindowEvent(PassRefPtr<Event> event) m_eventQueue->enqueueEvent(event); } -void DOMWindow::enqueueDocumentEvent(PassRefPtr<Event> event) +void LocalDOMWindow::enqueueDocumentEvent(PassRefPtrWillBeRawPtr<Event> event) { if (!m_eventQueue) return; - event->setTarget(m_document); + event->setTarget(m_document.get()); m_eventQueue->enqueueEvent(event); } -void DOMWindow::dispatchWindowLoadEvent() +void LocalDOMWindow::dispatchWindowLoadEvent() { ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); dispatchLoadEvent(); } -void DOMWindow::documentWasClosed() +void LocalDOMWindow::documentWasClosed() { dispatchWindowLoadEvent(); enqueuePageshowEvent(PageshowEventNotPersisted); - enqueuePopstateEvent(m_pendingStateObject ? m_pendingStateObject.release() : SerializedScriptValue::nullValue()); + if (m_pendingStateObject) + enqueuePopstateEvent(m_pendingStateObject.release()); } -void DOMWindow::enqueuePageshowEvent(PageshowEventPersistence persisted) +void LocalDOMWindow::enqueuePageshowEvent(PageshowEventPersistence persisted) { // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously. + // As per spec pageshow must be triggered asynchronously. + // However to be compatible with other browsers blink fires pageshow synchronously. dispatchEvent(PageTransitionEvent::create(EventTypeNames::pageshow, persisted), m_document.get()); } -void DOMWindow::enqueueHashchangeEvent(const String& oldURL, const String& newURL) +void LocalDOMWindow::enqueueHashchangeEvent(const String& oldURL, const String& newURL) { enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL)); } -void DOMWindow::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject) +void LocalDOMWindow::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject) { if (!ContextFeatures::pushStateEnabled(document())) return; // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously - dispatchEvent(PopStateEvent::create(stateObject, history())); + dispatchEvent(PopStateEvent::create(stateObject, &history())); } -void DOMWindow::statePopped(PassRefPtr<SerializedScriptValue> stateObject) +void LocalDOMWindow::statePopped(PassRefPtr<SerializedScriptValue> stateObject) { if (!frame()) return; @@ -483,237 +497,217 @@ void DOMWindow::statePopped(PassRefPtr<SerializedScriptValue> stateObject) m_pendingStateObject = stateObject; } -DOMWindow::~DOMWindow() -{ - ASSERT(!m_screen); - ASSERT(!m_history); - ASSERT(!m_locationbar); - ASSERT(!m_menubar); - ASSERT(!m_personalbar); - ASSERT(!m_scrollbars); - ASSERT(!m_statusbar); - ASSERT(!m_toolbar); - ASSERT(!m_console); - ASSERT(!m_navigator); - ASSERT(!m_performance); - ASSERT(!m_location); - ASSERT(!m_media); - ASSERT(!m_sessionStorage); - ASSERT(!m_localStorage); - ASSERT(!m_applicationCache); - +LocalDOMWindow::~LocalDOMWindow() +{ + ASSERT(m_hasBeenReset); reset(); - removeAllEventListeners(); +#if ENABLE(OILPAN) + // Oilpan: the frame host and document objects are + // also garbage collected; cannot notify these + // when removing event listeners. + removeAllEventListenersInternal(DoNotBroadcastListenerRemoval); + + // Cleared when detaching document. + ASSERT(!m_eventQueue); +#else + removeAllEventListenersInternal(DoBroadcastListenerRemoval); ASSERT(m_document->isStopped()); clearDocument(); +#endif } -const AtomicString& DOMWindow::interfaceName() const +const AtomicString& LocalDOMWindow::interfaceName() const { - return EventTargetNames::DOMWindow; + return EventTargetNames::LocalDOMWindow; } -ExecutionContext* DOMWindow::executionContext() const +ExecutionContext* LocalDOMWindow::executionContext() const { return m_document.get(); } -DOMWindow* DOMWindow::toDOMWindow() +LocalDOMWindow* LocalDOMWindow::toDOMWindow() { return this; } -PassRefPtr<MediaQueryList> DOMWindow::matchMedia(const String& media) +PassRefPtrWillBeRawPtr<MediaQueryList> LocalDOMWindow::matchMedia(const String& media) { - return document() ? document()->mediaQueryMatcher().matchMedia(media) : 0; + return document() ? document()->mediaQueryMatcher().matchMedia(media) : nullptr; } -Page* DOMWindow::page() +Page* LocalDOMWindow::page() { return frame() ? frame()->page() : 0; } -void DOMWindow::frameDestroyed() +void LocalDOMWindow::frameDestroyed() { FrameDestructionObserver::frameDestroyed(); reset(); } -void DOMWindow::willDetachPage() +void LocalDOMWindow::willDetachFrameHost() { + m_frame->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); InspectorInstrumentation::frameWindowDiscarded(m_frame, this); } -void DOMWindow::willDestroyDocumentInFrame() +void LocalDOMWindow::willDestroyDocumentInFrame() { // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may - // unregister themselves from the DOMWindow as a result of the call to willDestroyGlobalObjectInFrame. + // unregister themselves from the LocalDOMWindow as a result of the call to willDestroyGlobalObjectInFrame. Vector<DOMWindowProperty*> properties; copyToVector(m_properties, properties); for (size_t i = 0; i < properties.size(); ++i) properties[i]->willDestroyGlobalObjectInFrame(); } -void DOMWindow::willDetachDocumentFromFrame() +void LocalDOMWindow::willDetachDocumentFromFrame() { // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may - // unregister themselves from the DOMWindow as a result of the call to willDetachGlobalObjectFromFrame. + // unregister themselves from the LocalDOMWindow as a result of the call to willDetachGlobalObjectFromFrame. Vector<DOMWindowProperty*> properties; copyToVector(m_properties, properties); for (size_t i = 0; i < properties.size(); ++i) properties[i]->willDetachGlobalObjectFromFrame(); } -void DOMWindow::registerProperty(DOMWindowProperty* property) +void LocalDOMWindow::registerProperty(DOMWindowProperty* property) { m_properties.add(property); } -void DOMWindow::unregisterProperty(DOMWindowProperty* property) +void LocalDOMWindow::unregisterProperty(DOMWindowProperty* property) { m_properties.remove(property); } -void DOMWindow::reset() +void LocalDOMWindow::reset() { willDestroyDocumentInFrame(); resetDOMWindowProperties(); } -void DOMWindow::resetDOMWindowProperties() +void LocalDOMWindow::resetDOMWindowProperties() { m_properties.clear(); - m_screen = 0; - m_history = 0; - m_locationbar = 0; - m_menubar = 0; - m_personalbar = 0; - m_scrollbars = 0; - m_statusbar = 0; - m_toolbar = 0; - m_console = 0; - m_navigator = 0; - m_performance = 0; - m_location = 0; - m_media = 0; - m_sessionStorage = 0; - m_localStorage = 0; - m_applicationCache = 0; + m_screen = nullptr; + m_history = nullptr; + m_locationbar = nullptr; + m_menubar = nullptr; + m_personalbar = nullptr; + m_scrollbars = nullptr; + m_statusbar = nullptr; + m_toolbar = nullptr; + m_console = nullptr; + m_navigator = nullptr; + m_performance = nullptr; + m_location = nullptr; + m_media = nullptr; + m_sessionStorage = nullptr; + m_localStorage = nullptr; + m_applicationCache = nullptr; +#if ASSERT_ENABLED + m_hasBeenReset = true; +#endif } -bool DOMWindow::isCurrentlyDisplayedInFrame() const +bool LocalDOMWindow::isCurrentlyDisplayedInFrame() const { - return m_frame && m_frame->domWindow() == this; + return m_frame && m_frame->domWindow() == this && m_frame->host(); } -#if ENABLE(ORIENTATION_EVENTS) -int DOMWindow::orientation() const +int LocalDOMWindow::orientation() const { + ASSERT(RuntimeEnabledFeatures::orientationEventEnabled()); + if (!m_frame) return 0; - return m_frame->orientation(); + int orientation = screenOrientationAngle(m_frame->view()); + // For backward compatibility, we want to return a value in the range of + // [-90; 180] instead of [0; 360[ because window.orientation used to behave + // like that in WebKit (this is a WebKit proprietary API). + if (orientation == 270) + return -90; + return orientation; } -#endif -Screen* DOMWindow::screen() const +Screen& LocalDOMWindow::screen() const { - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_screen) m_screen = Screen::create(m_frame); - return m_screen.get(); + return *m_screen; } -History* DOMWindow::history() const +History& LocalDOMWindow::history() const { - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_history) m_history = History::create(m_frame); - return m_history.get(); + return *m_history; } -BarProp* DOMWindow::locationbar() const +BarProp& LocalDOMWindow::locationbar() const { - UseCounter::count(this, UseCounter::BarPropLocationbar); - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_locationbar) m_locationbar = BarProp::create(m_frame, BarProp::Locationbar); - return m_locationbar.get(); + return *m_locationbar; } -BarProp* DOMWindow::menubar() const +BarProp& LocalDOMWindow::menubar() const { - UseCounter::count(this, UseCounter::BarPropMenubar); - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_menubar) m_menubar = BarProp::create(m_frame, BarProp::Menubar); - return m_menubar.get(); + return *m_menubar; } -BarProp* DOMWindow::personalbar() const +BarProp& LocalDOMWindow::personalbar() const { - UseCounter::count(this, UseCounter::BarPropPersonalbar); - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_personalbar) m_personalbar = BarProp::create(m_frame, BarProp::Personalbar); - return m_personalbar.get(); + return *m_personalbar; } -BarProp* DOMWindow::scrollbars() const +BarProp& LocalDOMWindow::scrollbars() const { - UseCounter::count(this, UseCounter::BarPropScrollbars); - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_scrollbars) m_scrollbars = BarProp::create(m_frame, BarProp::Scrollbars); - return m_scrollbars.get(); + return *m_scrollbars; } -BarProp* DOMWindow::statusbar() const +BarProp& LocalDOMWindow::statusbar() const { - UseCounter::count(this, UseCounter::BarPropStatusbar); - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_statusbar) m_statusbar = BarProp::create(m_frame, BarProp::Statusbar); - return m_statusbar.get(); + return *m_statusbar; } -BarProp* DOMWindow::toolbar() const +BarProp& LocalDOMWindow::toolbar() const { - UseCounter::count(this, UseCounter::BarPropToolbar); - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_toolbar) m_toolbar = BarProp::create(m_frame, BarProp::Toolbar); - return m_toolbar.get(); + return *m_toolbar; } -Console* DOMWindow::console() const +Console& LocalDOMWindow::console() const { - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_console) m_console = Console::create(m_frame); - return m_console.get(); + return *m_console; } -PageConsole* DOMWindow::pageConsole() const +FrameConsole* LocalDOMWindow::frameConsole() const { if (!isCurrentlyDisplayedInFrame()) return 0; - return m_frame->page() ? &m_frame->page()->console() : 0; + return &m_frame->console(); } -ApplicationCache* DOMWindow::applicationCache() const +ApplicationCache* LocalDOMWindow::applicationCache() const { if (!isCurrentlyDisplayedInFrame()) return 0; @@ -722,34 +716,28 @@ ApplicationCache* DOMWindow::applicationCache() const return m_applicationCache.get(); } -Navigator* DOMWindow::navigator() const +Navigator& LocalDOMWindow::navigator() const { - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_navigator) m_navigator = Navigator::create(m_frame); - return m_navigator.get(); + return *m_navigator; } -Performance* DOMWindow::performance() const +Performance& LocalDOMWindow::performance() const { - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_performance) m_performance = Performance::create(m_frame); - return m_performance.get(); + return *m_performance; } -Location* DOMWindow::location() const +Location& LocalDOMWindow::location() const { - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_location) m_location = Location::create(m_frame); - return m_location.get(); + return *m_location; } -Storage* DOMWindow::sessionStorage(ExceptionState& exceptionState) const +Storage* LocalDOMWindow::sessionStorage(ExceptionState& exceptionState) const { if (!isCurrentlyDisplayedInFrame()) return 0; @@ -781,7 +769,7 @@ Storage* DOMWindow::sessionStorage(ExceptionState& exceptionState) const if (!page) return 0; - OwnPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin()); + OwnPtrWillBeRawPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin()); if (!storageArea->canAccessStorage(m_frame)) { exceptionState.throwSecurityError(accessDeniedMessage); return 0; @@ -791,7 +779,7 @@ Storage* DOMWindow::sessionStorage(ExceptionState& exceptionState) const return m_sessionStorage.get(); } -Storage* DOMWindow::localStorage(ExceptionState& exceptionState) const +Storage* LocalDOMWindow::localStorage(ExceptionState& exceptionState) const { if (!isCurrentlyDisplayedInFrame()) return 0; @@ -819,14 +807,12 @@ Storage* DOMWindow::localStorage(ExceptionState& exceptionState) const return m_localStorage.get(); } - Page* page = document->page(); - if (!page) + // FIXME: Seems this check should be much higher? + FrameHost* host = document->frameHost(); + if (!host || !host->settings().localStorageEnabled()) return 0; - if (!page->settings().localStorageEnabled()) - return 0; - - OwnPtr<StorageArea> storageArea = StorageNamespace::localStorageArea(document->securityOrigin()); + OwnPtrWillBeRawPtr<StorageArea> storageArea = StorageNamespace::localStorageArea(document->securityOrigin()); if (!storageArea->canAccessStorage(m_frame)) { exceptionState.throwSecurityError(accessDeniedMessage); return 0; @@ -836,7 +822,7 @@ Storage* DOMWindow::localStorage(ExceptionState& exceptionState) const return m_localStorage.get(); } -void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow* source, ExceptionState& exceptionState) +void LocalDOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, LocalDOMWindow* source, ExceptionState& exceptionState) { if (!isCurrentlyDisplayedInFrame()) return; @@ -870,42 +856,54 @@ void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const Mes return; String sourceOrigin = sourceDocument->securityOrigin()->toString(); + if (MixedContentChecker::isMixedContent(sourceDocument->securityOrigin(), document()->url())) + UseCounter::count(document(), UseCounter::PostMessageFromSecureToInsecure); + else if (MixedContentChecker::isMixedContent(document()->securityOrigin(), sourceDocument->url())) + UseCounter::count(document(), UseCounter::PostMessageFromInsecureToSecure); + // Capture stack trace only when inspector front-end is loaded as it may be time consuming. - RefPtr<ScriptCallStack> stackTrace; + RefPtrWillBeRawPtr<ScriptCallStack> stackTrace = nullptr; if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument)) stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true); // Schedule the message. - PostMessageTimer* timer = new PostMessageTimer(this, message, sourceOrigin, source, channels.release(), target.get(), stackTrace.release()); - timer->startOneShot(0); + OwnPtr<PostMessageTimer> timer = adoptPtr(new PostMessageTimer(*this, message, sourceOrigin, source, channels.release(), target.get(), stackTrace.release(), UserGestureIndicator::currentToken())); + timer->startOneShot(0, FROM_HERE); + timer->suspendIfNeeded(); + m_postMessageTimers.add(timer.release()); } -void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t) +void LocalDOMWindow::postMessageTimerFired(PostMessageTimer* timer) { - OwnPtr<PostMessageTimer> timer(t); - - if (!document() || !isCurrentlyDisplayedInFrame()) + if (!isCurrentlyDisplayedInFrame()) { + m_postMessageTimers.remove(timer); return; + } - RefPtr<MessageEvent> event = timer->event(); + RefPtrWillBeRawPtr<MessageEvent> event = timer->event(); // Give the embedder a chance to intercept this postMessage because this - // DOMWindow might be a proxy for another in browsers that support + // LocalDOMWindow might be a proxy for another in browsers that support // postMessage calls across WebKit instances. - if (m_frame->loader().client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get())) + if (m_frame->loader().client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get())) { + m_postMessageTimers.remove(timer); return; + } + + UserGestureIndicator gestureIndicator(timer->userGestureToken()); event->entangleMessagePorts(document()); dispatchMessageEventWithOriginCheck(timer->targetOrigin(), event, timer->stackTrace()); + m_postMessageTimers.remove(timer); } -void DOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtr<Event> event, PassRefPtr<ScriptCallStack> stackTrace) +void LocalDOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtrWillBeRawPtr<Event> event, PassRefPtrWillBeRawPtr<ScriptCallStack> stackTrace) { if (intendedTargetOrigin) { // Check target origin now since the target document may have changed since the timer was scheduled. if (!intendedTargetOrigin->isSameSchemeHostPort(document()->securityOrigin())) { String message = ExceptionMessages::failedToExecute("postMessage", "DOMWindow", "The target origin provided ('" + intendedTargetOrigin->toString() + "') does not match the recipient window's origin ('" + document()->securityOrigin()->toString() + "')."); - pageConsole()->addMessage(SecurityMessageSource, ErrorMessageLevel, message, stackTrace); + frameConsole()->addMessage(SecurityMessageSource, ErrorMessageLevel, message, stackTrace); return; } } @@ -913,7 +911,7 @@ void DOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTarg dispatchEvent(event); } -DOMSelection* DOMWindow::getSelection() +DOMSelection* LocalDOMWindow::getSelection() { if (!isCurrentlyDisplayedInFrame() || !m_frame) return 0; @@ -921,21 +919,23 @@ DOMSelection* DOMWindow::getSelection() return m_frame->document()->getSelection(); } -Element* DOMWindow::frameElement() const +Element* LocalDOMWindow::frameElement() const { if (!m_frame) return 0; - return m_frame->ownerElement(); + // The bindings security check should ensure we're same origin... + ASSERT(!m_frame->owner() || m_frame->owner()->isLocal()); + return m_frame->deprecatedLocalOwner(); } -void DOMWindow::focus(ExecutionContext* context) +void LocalDOMWindow::focus(ExecutionContext* context) { if (!m_frame) return; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return; bool allowFocus = WindowFocusAllowedIndicator::windowFocusAllowed(); @@ -948,7 +948,7 @@ void DOMWindow::focus(ExecutionContext* context) // If we're a top level window, bring the window to the front. if (m_frame->isMainFrame() && allowFocus) - page->chrome().focus(); + host->chrome().focus(); if (!m_frame) return; @@ -956,29 +956,26 @@ void DOMWindow::focus(ExecutionContext* context) m_frame->eventHandler().focusDocumentView(); } -void DOMWindow::blur() +void LocalDOMWindow::blur() { } -void DOMWindow::close(ExecutionContext* context) +void LocalDOMWindow::close(ExecutionContext* context) { - if (!m_frame) + if (!m_frame || !m_frame->isMainFrame()) return; Page* page = m_frame->page(); if (!page) return; - if (m_frame != page->mainFrame()) - return; - if (context) { ASSERT(isMainThread()); Document* activeDocument = toDocument(context); if (!activeDocument) return; - if (!activeDocument->canNavigate(m_frame)) + if (!activeDocument->canNavigate(*m_frame)) return; } @@ -986,7 +983,7 @@ void DOMWindow::close(ExecutionContext* context) bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows(); if (!(page->openedByDOM() || page->backForward().backForwardListCount() <= 1 || allowScriptsToCloseWindows)) { - pageConsole()->addMessage(JSMessageSource, WarningMessageLevel, "Scripts may close only the windows that were opened by it."); + frameConsole()->addMessage(JSMessageSource, WarningMessageLevel, "Scripts may close only the windows that were opened by it."); return; } @@ -996,123 +993,123 @@ void DOMWindow::close(ExecutionContext* context) page->chrome().closeWindowSoon(); } -void DOMWindow::print() +void LocalDOMWindow::print() { if (!m_frame) return; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return; - if (m_frame->loader().activeDocumentLoader()->isLoading()) { + if (m_frame->loader().state() != FrameStateComplete) { m_shouldPrintWhenFinishedLoading = true; return; } m_shouldPrintWhenFinishedLoading = false; - page->chrome().print(m_frame); + host->chrome().print(m_frame); } -void DOMWindow::stop() +void LocalDOMWindow::stop() { if (!m_frame) return; m_frame->loader().stopAllLoaders(); } -void DOMWindow::alert(const String& message) +void LocalDOMWindow::alert(const String& message) { if (!m_frame) return; - m_frame->document()->updateStyleIfNeeded(); + m_frame->document()->updateRenderTreeIfNeeded(); - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return; - page->chrome().runJavaScriptAlert(m_frame, message); + host->chrome().runJavaScriptAlert(m_frame, message); } -bool DOMWindow::confirm(const String& message) +bool LocalDOMWindow::confirm(const String& message) { if (!m_frame) return false; - m_frame->document()->updateStyleIfNeeded(); + m_frame->document()->updateRenderTreeIfNeeded(); - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return false; - return page->chrome().runJavaScriptConfirm(m_frame, message); + return host->chrome().runJavaScriptConfirm(m_frame, message); } -String DOMWindow::prompt(const String& message, const String& defaultValue) +String LocalDOMWindow::prompt(const String& message, const String& defaultValue) { if (!m_frame) return String(); - m_frame->document()->updateStyleIfNeeded(); + m_frame->document()->updateRenderTreeIfNeeded(); - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return String(); String returnValue; - if (page->chrome().runJavaScriptPrompt(m_frame, message, defaultValue, returnValue)) + if (host->chrome().runJavaScriptPrompt(m_frame, message, defaultValue, returnValue)) return returnValue; return String(); } -bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const +bool LocalDOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const { if (!isCurrentlyDisplayedInFrame()) return false; // |m_frame| can be destructed during |Editor::findString()| via // |Document::updateLayou()|, e.g. event handler removes a frame. - RefPtr<Frame> protectFrame(m_frame); + RefPtr<LocalFrame> protectFrame(m_frame); // FIXME (13016): Support wholeWord, searchInFrames and showDialog return m_frame->editor().findString(string, !backwards, caseSensitive, wrap, false); } -bool DOMWindow::offscreenBuffering() const +bool LocalDOMWindow::offscreenBuffering() const { return true; } -int DOMWindow::outerHeight() const +int LocalDOMWindow::outerHeight() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return 0; - if (page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(page->chrome().windowRect().height() * page->deviceScaleFactor()); - return static_cast<int>(page->chrome().windowRect().height()); + if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(host->chrome().windowRect().height() * host->deviceScaleFactor()); + return static_cast<int>(host->chrome().windowRect().height()); } -int DOMWindow::outerWidth() const +int LocalDOMWindow::outerWidth() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return 0; - if (page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(page->chrome().windowRect().width() * page->deviceScaleFactor()); - return static_cast<int>(page->chrome().windowRect().width()); + if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(host->chrome().windowRect().width() * host->deviceScaleFactor()); + return static_cast<int>(host->chrome().windowRect().width()); } -int DOMWindow::innerHeight() const +int LocalDOMWindow::innerHeight() const { if (!m_frame) return 0; @@ -1122,13 +1119,15 @@ int DOMWindow::innerHeight() const return 0; // FIXME: This is potentially too much work. We really only need to know the dimensions of the parent frame's renderer. - if (Frame* parent = m_frame->tree().parent()) - parent->document()->updateLayoutIgnorePendingStylesheets(); + if (Frame* parent = m_frame->tree().parent()) { + if (parent && parent->isLocalFrame()) + toLocalFrame(parent)->document()->updateLayoutIgnorePendingStylesheets(); + } - return adjustForAbsoluteZoom(view->visibleContentRect(ScrollableArea::IncludeScrollbars).height(), m_frame->pageZoomFactor()); + return adjustForAbsoluteZoom(view->visibleContentRect(IncludeScrollbars).height(), m_frame->pageZoomFactor()); } -int DOMWindow::innerWidth() const +int LocalDOMWindow::innerWidth() const { if (!m_frame) return 0; @@ -1138,41 +1137,43 @@ int DOMWindow::innerWidth() const return 0; // FIXME: This is potentially too much work. We really only need to know the dimensions of the parent frame's renderer. - if (Frame* parent = m_frame->tree().parent()) - parent->document()->updateLayoutIgnorePendingStylesheets(); + if (Frame* parent = m_frame->tree().parent()) { + if (parent && parent->isLocalFrame()) + toLocalFrame(parent)->document()->updateLayoutIgnorePendingStylesheets(); + } - return adjustForAbsoluteZoom(view->visibleContentRect(ScrollableArea::IncludeScrollbars).width(), m_frame->pageZoomFactor()); + return adjustForAbsoluteZoom(view->visibleContentRect(IncludeScrollbars).width(), m_frame->pageZoomFactor()); } -int DOMWindow::screenX() const +int LocalDOMWindow::screenX() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return 0; - if (page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(page->chrome().windowRect().x() * page->deviceScaleFactor()); - return static_cast<int>(page->chrome().windowRect().x()); + if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(host->chrome().windowRect().x() * host->deviceScaleFactor()); + return static_cast<int>(host->chrome().windowRect().x()); } -int DOMWindow::screenY() const +int LocalDOMWindow::screenY() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return 0; - if (page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(page->chrome().windowRect().y() * page->deviceScaleFactor()); - return static_cast<int>(page->chrome().windowRect().y()); + if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(host->chrome().windowRect().y() * host->deviceScaleFactor()); + return static_cast<int>(host->chrome().windowRect().y()); } -int DOMWindow::scrollX() const +int LocalDOMWindow::scrollX() const { if (!m_frame) return 0; @@ -1186,7 +1187,7 @@ int DOMWindow::scrollX() const return adjustForAbsoluteZoom(view->scrollX(), m_frame->pageZoomFactor()); } -int DOMWindow::scrollY() const +int LocalDOMWindow::scrollY() const { if (!m_frame) return 0; @@ -1200,12 +1201,12 @@ int DOMWindow::scrollY() const return adjustForAbsoluteZoom(view->scrollY(), m_frame->pageZoomFactor()); } -bool DOMWindow::closed() const +bool LocalDOMWindow::closed() const { return !m_frame; } -unsigned DOMWindow::length() const +unsigned LocalDOMWindow::length() const { if (!isCurrentlyDisplayedInFrame()) return 0; @@ -1213,54 +1214,55 @@ unsigned DOMWindow::length() const return m_frame->tree().scopedChildCount(); } -const AtomicString& DOMWindow::name() const +const AtomicString& LocalDOMWindow::name() const { - if (!m_frame) + if (!isCurrentlyDisplayedInFrame()) return nullAtom; return m_frame->tree().name(); } -void DOMWindow::setName(const AtomicString& name) +void LocalDOMWindow::setName(const AtomicString& name) { - if (!m_frame) + if (!isCurrentlyDisplayedInFrame()) return; m_frame->tree().setName(name); + ASSERT(m_frame->loader().client()); m_frame->loader().client()->didChangeName(name); } -void DOMWindow::setStatus(const String& string) +void LocalDOMWindow::setStatus(const String& string) { m_status = string; if (!m_frame) return; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return; ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state. - page->chrome().setStatusbarText(m_frame, m_status); + host->chrome().setStatusbarText(m_frame, m_status); } -void DOMWindow::setDefaultStatus(const String& string) +void LocalDOMWindow::setDefaultStatus(const String& string) { m_defaultStatus = string; if (!m_frame) return; - Page* page = m_frame->page(); - if (!page) + FrameHost* host = m_frame->host(); + if (!host) return; ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state. - page->chrome().setStatusbarText(m_frame, m_defaultStatus); + host->chrome().setStatusbarText(m_frame, m_defaultStatus); } -DOMWindow* DOMWindow::self() const +LocalDOMWindow* LocalDOMWindow::self() const { if (!m_frame) return 0; @@ -1268,19 +1270,19 @@ DOMWindow* DOMWindow::self() const return m_frame->domWindow(); } -DOMWindow* DOMWindow::opener() const +LocalDOMWindow* LocalDOMWindow::opener() const { if (!m_frame) return 0; - Frame* opener = m_frame->loader().opener(); + LocalFrame* opener = m_frame->loader().opener(); if (!opener) return 0; return opener->domWindow(); } -DOMWindow* DOMWindow::parent() const +LocalDOMWindow* LocalDOMWindow::parent() const { if (!m_frame) return 0; @@ -1292,70 +1294,59 @@ DOMWindow* DOMWindow::parent() const return m_frame->domWindow(); } -DOMWindow* DOMWindow::top() const +LocalDOMWindow* LocalDOMWindow::top() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (!page) - return 0; - return m_frame->tree().top()->domWindow(); } -Document* DOMWindow::document() const +Document* LocalDOMWindow::document() const { return m_document.get(); } -PassRefPtr<StyleMedia> DOMWindow::styleMedia() const +StyleMedia& LocalDOMWindow::styleMedia() const { - if (!isCurrentlyDisplayedInFrame()) - return 0; if (!m_media) m_media = StyleMedia::create(m_frame); - return m_media.get(); + return *m_media; } -PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const +PassRefPtrWillBeRawPtr<CSSStyleDeclaration> LocalDOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const { if (!elt) - return 0; + return nullptr; return CSSComputedStyleDeclaration::create(elt, false, pseudoElt); } -PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement, bool authorOnly) const +PassRefPtrWillBeRawPtr<CSSRuleList> LocalDOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement) const { - UseCounter::count(this, UseCounter::GetMatchedCSSRules); if (!element) - return 0; + return nullptr; if (!isCurrentlyDisplayedInFrame()) - return 0; + return nullptr; unsigned colonStart = pseudoElement[0] == ':' ? (pseudoElement[1] == ':' ? 2 : 1) : 0; CSSSelector::PseudoType pseudoType = CSSSelector::parsePseudoType(AtomicString(pseudoElement.substring(colonStart))); if (pseudoType == CSSSelector::PseudoUnknown && !pseudoElement.isEmpty()) - return 0; + return nullptr; unsigned rulesToInclude = StyleResolver::AuthorCSSRules; - if (!authorOnly) - rulesToInclude |= StyleResolver::UAAndUserCSSRules; - PseudoId pseudoId = CSSSelector::pseudoId(pseudoType); - return m_frame->document()->ensureStyleResolver().pseudoCSSRulesForElement(element, pseudoId, rulesToInclude); } -PassRefPtr<DOMPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, const DOMPoint* p) const +PassRefPtrWillBeRawPtr<DOMPoint> LocalDOMWindow::webkitConvertPointFromNodeToPage(Node* node, const DOMPoint* p) const { if (!node || !p) - return 0; + return nullptr; if (!document()) - return 0; + return nullptr; document()->updateLayoutIgnorePendingStylesheets(); @@ -1364,13 +1355,13 @@ PassRefPtr<DOMPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, con return DOMPoint::create(pagePoint.x(), pagePoint.y()); } -PassRefPtr<DOMPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, const DOMPoint* p) const +PassRefPtrWillBeRawPtr<DOMPoint> LocalDOMWindow::webkitConvertPointFromPageToNode(Node* node, const DOMPoint* p) const { if (!node || !p) - return 0; + return nullptr; if (!document()) - return 0; + return nullptr; document()->updateLayoutIgnorePendingStylesheets(); @@ -1379,7 +1370,7 @@ PassRefPtr<DOMPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, con return DOMPoint::create(nodePoint.x(), nodePoint.y()); } -double DOMWindow::devicePixelRatio() const +double LocalDOMWindow::devicePixelRatio() const { if (!m_frame) return 0.0; @@ -1387,7 +1378,22 @@ double DOMWindow::devicePixelRatio() const return m_frame->devicePixelRatio(); } -void DOMWindow::scrollBy(int x, int y) const +static bool scrollBehaviorFromScrollOptions(const Dictionary& scrollOptions, ScrollBehavior& scrollBehavior, ExceptionState& exceptionState) +{ + String scrollBehaviorString; + if (!scrollOptions.get("behavior", scrollBehaviorString)) { + scrollBehavior = ScrollBehaviorAuto; + return true; + } + + if (ScrollableArea::scrollBehaviorFromString(scrollBehaviorString, scrollBehavior)) + return true; + + exceptionState.throwTypeError("The ScrollBehavior provided is invalid."); + return false; +} + +void LocalDOMWindow::scrollBy(int x, int y) const { if (!isCurrentlyDisplayedInFrame()) return; @@ -1398,12 +1404,20 @@ void DOMWindow::scrollBy(int x, int y) const if (!view) return; - IntSize scaledOffset(x * m_frame->pageZoomFactor(), y * m_frame->pageZoomFactor()); + // FIXME: Use scrollBehavior to decide whether to scroll smoothly or instantly. view->scrollBy(scaledOffset); } -void DOMWindow::scrollTo(int x, int y) const +void LocalDOMWindow::scrollBy(int x, int y, const Dictionary& scrollOptions, ExceptionState &exceptionState) const +{ + ScrollBehavior scrollBehavior = ScrollBehaviorAuto; + if (!scrollBehaviorFromScrollOptions(scrollOptions, scrollBehavior, exceptionState)) + return; + scrollBy(x, y); +} + +void LocalDOMWindow::scrollTo(int x, int y) const { if (!isCurrentlyDisplayedInFrame()) return; @@ -1415,83 +1429,79 @@ void DOMWindow::scrollTo(int x, int y) const return; IntPoint layoutPos(x * m_frame->pageZoomFactor(), y * m_frame->pageZoomFactor()); + // FIXME: Use scrollBehavior to decide whether to scroll smoothly or instantly. view->setScrollPosition(layoutPos); } -void DOMWindow::moveBy(float x, float y) const +void LocalDOMWindow::scrollTo(int x, int y, const Dictionary& scrollOptions, ExceptionState& exceptionState) const { - if (!m_frame) + ScrollBehavior scrollBehavior = ScrollBehaviorAuto; + if (!scrollBehaviorFromScrollOptions(scrollOptions, scrollBehavior, exceptionState)) return; + scrollTo(x, y); +} - Page* page = m_frame->page(); - if (!page) +void LocalDOMWindow::moveBy(float x, float y) const +{ + if (!m_frame || !m_frame->isMainFrame()) return; - if (m_frame != page->mainFrame()) + FrameHost* host = m_frame->host(); + if (!host) return; - FloatRect fr = page->chrome().windowRect(); - FloatRect update = fr; - update.move(x, y); + FloatRect windowRect = host->chrome().windowRect(); + windowRect.move(x, y); // Security check (the spec talks about UniversalBrowserWrite to disable this check...) - page->chrome().setWindowRect(adjustWindowRect(page, update)); + host->chrome().setWindowRect(adjustWindowRect(*m_frame, windowRect)); } -void DOMWindow::moveTo(float x, float y) const +void LocalDOMWindow::moveTo(float x, float y) const { - if (!m_frame) - return; - - Page* page = m_frame->page(); - if (!page) + if (!m_frame || !m_frame->isMainFrame()) return; - if (m_frame != page->mainFrame()) + FrameHost* host = m_frame->host(); + if (!host) return; - FloatRect update = page->chrome().windowRect(); - update.setLocation(FloatPoint(x, y)); + FloatRect windowRect = host->chrome().windowRect(); + windowRect.setLocation(FloatPoint(x, y)); // Security check (the spec talks about UniversalBrowserWrite to disable this check...) - page->chrome().setWindowRect(adjustWindowRect(page, update)); + host->chrome().setWindowRect(adjustWindowRect(*m_frame, windowRect)); } -void DOMWindow::resizeBy(float x, float y) const +void LocalDOMWindow::resizeBy(float x, float y) const { - if (!m_frame) - return; - - Page* page = m_frame->page(); - if (!page) + if (!m_frame || !m_frame->isMainFrame()) return; - if (m_frame != page->mainFrame()) + FrameHost* host = m_frame->host(); + if (!host) return; - FloatRect fr = page->chrome().windowRect(); + FloatRect fr = host->chrome().windowRect(); FloatSize dest = fr.size() + FloatSize(x, y); FloatRect update(fr.location(), dest); - page->chrome().setWindowRect(adjustWindowRect(page, update)); + host->chrome().setWindowRect(adjustWindowRect(*m_frame, update)); } -void DOMWindow::resizeTo(float width, float height) const +void LocalDOMWindow::resizeTo(float width, float height) const { - if (!m_frame) - return; - - Page* page = m_frame->page(); - if (!page) + if (!m_frame || !m_frame->isMainFrame()) return; - if (m_frame != page->mainFrame()) + FrameHost* host = m_frame->host(); + if (!host) return; - FloatRect fr = page->chrome().windowRect(); + FloatRect fr = host->chrome().windowRect(); FloatSize dest = FloatSize(width, height); FloatRect update(fr.location(), dest); - page->chrome().setWindowRect(adjustWindowRect(page, update)); + host->chrome().setWindowRect(adjustWindowRect(*m_frame, update)); } -int DOMWindow::requestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback) +int LocalDOMWindow::requestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback) { callback->m_useLegacyTimeBase = false; if (Document* d = document()) @@ -1499,7 +1509,7 @@ int DOMWindow::requestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> c return 0; } -int DOMWindow::webkitRequestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback) +int LocalDOMWindow::webkitRequestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback) { callback->m_useLegacyTimeBase = true; if (Document* d = document()) @@ -1507,20 +1517,20 @@ int DOMWindow::webkitRequestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallb return 0; } -void DOMWindow::cancelAnimationFrame(int id) +void LocalDOMWindow::cancelAnimationFrame(int id) { if (Document* d = document()) d->cancelAnimationFrame(id); } -DOMWindowCSS* DOMWindow::css() +DOMWindowCSS& LocalDOMWindow::css() const { if (!m_css) m_css = DOMWindowCSS::create(); - return m_css.get(); + return *m_css; } -static void didAddStorageEventListener(DOMWindow* window) +static void didAddStorageEventListener(LocalDOMWindow* window) { // Creating these WebCore::Storage objects informs the system that we'd like to receive // notifications about storage events that might be triggered in other processes. Rather @@ -1530,11 +1540,14 @@ static void didAddStorageEventListener(DOMWindow* window) window->sessionStorage(IGNORE_EXCEPTION); } -bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) +bool LocalDOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) { if (!EventTarget::addEventListener(eventType, listener, useCapture)) return false; + if (m_frame && m_frame->host()) + m_frame->host()->eventHandlerRegistry().didAddEventHandler(*this, eventType); + if (Document* document = this->document()) { document->addListenerTypeIfNeeded(eventType); if (isTouchEventType(eventType)) @@ -1546,10 +1559,10 @@ bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<Event lifecycleNotifier().notifyAddEventListener(this, eventType); if (eventType == EventTypeNames::unload) { - UseCounter::count(this, UseCounter::DocumentUnloadRegistered); + UseCounter::count(document(), UseCounter::DocumentUnloadRegistered); addUnloadEventListener(this); } else if (eventType == EventTypeNames::beforeunload) { - UseCounter::count(this, UseCounter::DocumentBeforeUnloadRegistered); + UseCounter::count(document(), UseCounter::DocumentBeforeUnloadRegistered); if (allowsBeforeUnloadListeners(this)) { // This is confusingly named. It doesn't actually add the listener. It just increments a count // so that we know we have listeners registered for the purposes of determining if we can @@ -1557,18 +1570,21 @@ bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<Event addBeforeUnloadEventListener(this); } else { // Subframes return false from allowsBeforeUnloadListeners. - UseCounter::count(this, UseCounter::SubFrameBeforeUnloadRegistered); + UseCounter::count(document(), UseCounter::SubFrameBeforeUnloadRegistered); } } return true; } -bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) +bool LocalDOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) { if (!EventTarget::removeEventListener(eventType, listener, useCapture)) return false; + if (m_frame && m_frame->host()) + m_frame->host()->eventHandlerRegistry().didRemoveEventHandler(*this, eventType); + if (Document* document = this->document()) { if (isTouchEventType(eventType)) document->didRemoveTouchEventHandler(document); @@ -1585,9 +1601,9 @@ bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener return true; } -void DOMWindow::dispatchLoadEvent() +void LocalDOMWindow::dispatchLoadEvent() { - RefPtr<Event> loadEvent(Event::create(EventTypeNames::load)); + RefPtrWillBeRawPtr<Event> loadEvent(Event::create(EventTypeNames::load)); if (m_frame && m_frame->loader().documentLoader() && !m_frame->loader().documentLoader()->timing()->loadEventStart()) { // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed while dispatching // the event, so protect it to prevent writing the end time into freed memory. @@ -1602,24 +1618,28 @@ void DOMWindow::dispatchLoadEvent() // For load events, send a separate load event to the enclosing frame only. // 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) - ownerElement->dispatchEvent(Event::create(EventTypeNames::load)); + FrameOwner* owner = m_frame ? m_frame->owner() : 0; + if (owner) + owner->dispatchLoad(); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "MarkLoad", "data", InspectorMarkLoadEvent::data(frame())); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentation::loadEventFired(frame()); } -bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget> prpTarget) +bool LocalDOMWindow::dispatchEvent(PassRefPtrWillBeRawPtr<Event> prpEvent, PassRefPtrWillBeRawPtr<EventTarget> prpTarget) { ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); - RefPtr<EventTarget> protect = this; - RefPtr<Event> event = prpEvent; + RefPtrWillBeRawPtr<EventTarget> protect(this); + RefPtrWillBeRawPtr<Event> event = prpEvent; event->setTarget(prpTarget ? prpTarget : this); event->setCurrentTarget(this); event->setEventPhase(Event::AT_TARGET); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EventDispatch", "type", event->type().ascii()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), *event, this); bool result = fireEventListeners(event.get()); @@ -1629,20 +1649,30 @@ bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget return result; } -void DOMWindow::removeAllEventListeners() +void LocalDOMWindow::removeAllEventListenersInternal(BroadcastListenerRemoval mode) { EventTarget::removeAllEventListeners(); lifecycleNotifier().notifyRemoveAllEventListeners(this); - if (Document* document = this->document()) - document->didRemoveEventTargetNode(document); + if (mode == DoBroadcastListenerRemoval) { + if (m_frame && m_frame->host()) + m_frame->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); + + if (Document* document = this->document()) + document->didClearTouchEventHandlers(document); + } removeAllUnloadEventListeners(this); removeAllBeforeUnloadEventListeners(this); } -void DOMWindow::finishedLoading() +void LocalDOMWindow::removeAllEventListeners() +{ + removeAllEventListenersInternal(DoBroadcastListenerRemoval); +} + +void LocalDOMWindow::finishedLoading() { if (m_shouldPrintWhenFinishedLoading) { m_shouldPrintWhenFinishedLoading = false; @@ -1650,19 +1680,20 @@ void DOMWindow::finishedLoading() } } -void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow, SetLocationLocking locking) +void LocalDOMWindow::setLocation(const String& urlString, LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, SetLocationLocking locking) { if (!isCurrentlyDisplayedInFrame()) return; - Document* activeDocument = activeWindow->document(); + Document* activeDocument = callingWindow->document(); if (!activeDocument) return; - if (!activeDocument->canNavigate(m_frame)) + ASSERT(m_frame); + if (!activeDocument->canNavigate(*m_frame)) return; - Frame* firstFrame = firstWindow->frame(); + LocalFrame* firstFrame = enteredWindow->frame(); if (!firstFrame) return; @@ -1670,22 +1701,22 @@ void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DO if (completedURL.isNull()) return; - if (isInsecureScriptAccess(activeWindow, completedURL)) + if (isInsecureScriptAccess(*callingWindow, completedURL)) return; // We want a new history item if we are processing a user gesture. m_frame->navigationScheduler().scheduleLocationChange(activeDocument, // FIXME: What if activeDocument()->frame() is 0? - completedURL, activeDocument->outgoingReferrer(), + completedURL, Referrer(activeDocument->outgoingReferrer(), activeDocument->referrerPolicy()), locking != LockHistoryBasedOnGestureState); } -void DOMWindow::printErrorMessage(const String& message) +void LocalDOMWindow::printErrorMessage(const String& message) { if (message.isEmpty()) return; - pageConsole()->addMessage(JSMessageSource, ErrorMessageLevel, message); + frameConsole()->addMessage(JSMessageSource, ErrorMessageLevel, message); } // FIXME: Once we're throwing exceptions for cross-origin access violations, we will always sanitize the target @@ -1693,18 +1724,18 @@ void DOMWindow::printErrorMessage(const String& message) // exactly which details may be exposed to JavaScript. // // http://crbug.com/17325 -String DOMWindow::sanitizedCrossDomainAccessErrorMessage(DOMWindow* activeWindow) +String LocalDOMWindow::sanitizedCrossDomainAccessErrorMessage(LocalDOMWindow* callingWindow) { - if (!activeWindow || !activeWindow->document()) + if (!callingWindow || !callingWindow->document()) return String(); - const KURL& activeWindowURL = activeWindow->document()->url(); - if (activeWindowURL.isNull()) + const KURL& callingWindowURL = callingWindow->document()->url(); + if (callingWindowURL.isNull()) return String(); - ASSERT(!activeWindow->document()->securityOrigin()->canAccess(document()->securityOrigin())); + ASSERT(!callingWindow->document()->securityOrigin()->canAccess(document()->securityOrigin())); - SecurityOrigin* activeOrigin = activeWindow->document()->securityOrigin(); + SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a cross-origin frame."; // FIXME: Evaluate which details from 'crossDomainAccessErrorMessage' may safely be reported to JavaScript. @@ -1712,28 +1743,28 @@ String DOMWindow::sanitizedCrossDomainAccessErrorMessage(DOMWindow* activeWindow return message; } -String DOMWindow::crossDomainAccessErrorMessage(DOMWindow* activeWindow) +String LocalDOMWindow::crossDomainAccessErrorMessage(LocalDOMWindow* callingWindow) { - if (!activeWindow || !activeWindow->document()) + if (!callingWindow || !callingWindow->document()) return String(); - const KURL& activeWindowURL = activeWindow->document()->url(); - if (activeWindowURL.isNull()) + const KURL& callingWindowURL = callingWindow->document()->url(); + if (callingWindowURL.isNull()) return String(); - ASSERT(!activeWindow->document()->securityOrigin()->canAccess(document()->securityOrigin())); + ASSERT(!callingWindow->document()->securityOrigin()->canAccess(document()->securityOrigin())); // FIXME: This message, and other console messages, have extra newlines. Should remove them. - SecurityOrigin* activeOrigin = activeWindow->document()->securityOrigin(); + SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); SecurityOrigin* targetOrigin = document()->securityOrigin(); String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a frame with origin \"" + targetOrigin->toString() + "\". "; // Sandbox errors: Use the origin of the frames' location, rather than their actual origin (since we know that at least one will be "null"). - KURL activeURL = activeWindow->document()->url(); + KURL activeURL = callingWindow->document()->url(); KURL targetURL = document()->url(); - if (document()->isSandboxed(SandboxOrigin) || activeWindow->document()->isSandboxed(SandboxOrigin)) { + if (document()->isSandboxed(SandboxOrigin) || callingWindow->document()->isSandboxed(SandboxOrigin)) { message = "Blocked a frame at \"" + SecurityOrigin::create(activeURL)->toString() + "\" from accessing a frame at \"" + SecurityOrigin::create(targetURL)->toString() + "\". "; - if (document()->isSandboxed(SandboxOrigin) && activeWindow->document()->isSandboxed(SandboxOrigin)) + if (document()->isSandboxed(SandboxOrigin) && callingWindow->document()->isSandboxed(SandboxOrigin)) return "Sandbox access violation: " + message + " Both frames are sandboxed and lack the \"allow-same-origin\" flag."; if (document()->isSandboxed(SandboxOrigin)) return "Sandbox access violation: " + message + " The frame being accessed is sandboxed and lacks the \"allow-same-origin\" flag."; @@ -1756,47 +1787,47 @@ String DOMWindow::crossDomainAccessErrorMessage(DOMWindow* activeWindow) return message + "Protocols, domains, and ports must match."; } -bool DOMWindow::isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString) +bool LocalDOMWindow::isInsecureScriptAccess(LocalDOMWindow& callingWindow, const String& urlString) { if (!protocolIsJavaScript(urlString)) return false; - // If this DOMWindow isn't currently active in the Frame, then there's no + // If this LocalDOMWindow isn't currently active in the LocalFrame, then there's no // way we should allow the access. - // FIXME: Remove this check if we're able to disconnect DOMWindow from - // Frame on navigation: https://bugs.webkit.org/show_bug.cgi?id=62054 + // FIXME: Remove this check if we're able to disconnect LocalDOMWindow from + // LocalFrame on navigation: https://bugs.webkit.org/show_bug.cgi?id=62054 if (isCurrentlyDisplayedInFrame()) { - // FIXME: Is there some way to eliminate the need for a separate "activeWindow == this" check? - if (activeWindow == this) + // FIXME: Is there some way to eliminate the need for a separate "callingWindow == this" check? + if (&callingWindow == this) return false; // FIXME: The name canAccess seems to be a roundabout way to ask "can execute script". // Can we name the SecurityOrigin function better to make this more clear? - if (activeWindow->document()->securityOrigin()->canAccess(document()->securityOrigin())) + if (callingWindow.document()->securityOrigin()->canAccess(document()->securityOrigin())) return false; } - printErrorMessage(crossDomainAccessErrorMessage(activeWindow)); + printErrorMessage(crossDomainAccessErrorMessage(&callingWindow)); return true; } -PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString, - DOMWindow* activeWindow, DOMWindow* firstWindow) +PassRefPtrWillBeRawPtr<LocalDOMWindow> LocalDOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString, + LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow) { if (!isCurrentlyDisplayedInFrame()) - return 0; - Document* activeDocument = activeWindow->document(); + return nullptr; + Document* activeDocument = callingWindow->document(); if (!activeDocument) - return 0; - Frame* firstFrame = firstWindow->frame(); + return nullptr; + LocalFrame* firstFrame = enteredWindow->frame(); if (!firstFrame) - return 0; + return nullptr; - if (!firstWindow->allowPopUp()) { + if (!enteredWindow->allowPopUp()) { // Because FrameTree::find() returns true for empty strings, we must check for empty frame names. // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker. if (frameName.isEmpty() || !m_frame->tree().find(frameName)) - return 0; + return nullptr; } // Get the target frame for the special cases of _top and _parent. @@ -1810,13 +1841,14 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin else targetFrame = m_frame; } - if (targetFrame) { - if (!activeDocument->canNavigate(targetFrame)) - return 0; + // FIXME: Navigating RemoteFrames is not yet supported. + if (targetFrame && targetFrame->isLocalFrame()) { + if (!activeDocument->canNavigate(*targetFrame)) + return nullptr; KURL completedURL = firstFrame->document()->completeURL(urlString); - if (targetFrame->domWindow()->isInsecureScriptAccess(activeWindow, completedURL)) + if (targetFrame->domWindow()->isInsecureScriptAccess(*callingWindow, completedURL)) return targetFrame->domWindow(); if (urlString.isEmpty()) @@ -1824,48 +1856,48 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin // For whatever reason, Firefox uses the first window rather than the active window to // determine the outgoing referrer. We replicate that behavior here. - targetFrame->navigationScheduler().scheduleLocationChange( + toLocalFrame(targetFrame)->navigationScheduler().scheduleLocationChange( activeDocument, completedURL, - firstFrame->document()->outgoingReferrer(), + Referrer(firstFrame->document()->outgoingReferrer(), firstFrame->document()->referrerPolicy()), false); return targetFrame->domWindow(); } WindowFeatures windowFeatures(windowFeaturesString); - Frame* result = createWindow(urlString, frameName, windowFeatures, activeWindow, firstFrame, m_frame); + LocalFrame* result = createWindow(urlString, frameName, windowFeatures, *callingWindow, *firstFrame, *m_frame); return result ? result->domWindow() : 0; } -void DOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString, - DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction function, void* functionContext) +void LocalDOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString, + LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, PrepareDialogFunction function, void* functionContext) { if (!isCurrentlyDisplayedInFrame()) return; - Frame* activeFrame = activeWindow->frame(); + LocalFrame* activeFrame = callingWindow->frame(); if (!activeFrame) return; - Frame* firstFrame = firstWindow->frame(); + LocalFrame* firstFrame = enteredWindow->frame(); if (!firstFrame) return; - if (!canShowModalDialogNow(m_frame) || !firstWindow->allowPopUp()) + if (!canShowModalDialogNow(m_frame) || !enteredWindow->allowPopUp()) return; UseCounter::countDeprecation(this, UseCounter::ShowModalDialog); WindowFeatures windowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view())); - Frame* dialogFrame = createWindow(urlString, emptyAtom, windowFeatures, - activeWindow, firstFrame, m_frame, function, functionContext); + LocalFrame* dialogFrame = createWindow(urlString, emptyAtom, windowFeatures, + *callingWindow, *firstFrame, *m_frame, function, functionContext); if (!dialogFrame) return; UserGestureIndicatorDisabler disabler; - dialogFrame->page()->chrome().runModal(); + dialogFrame->host()->chrome().runModal(); } -DOMWindow* DOMWindow::anonymousIndexedGetter(uint32_t index) +LocalDOMWindow* LocalDOMWindow::anonymousIndexedGetter(uint32_t index) { - Frame* frame = this->frame(); + LocalFrame* frame = this->frame(); if (!frame) return 0; @@ -1876,15 +1908,39 @@ DOMWindow* DOMWindow::anonymousIndexedGetter(uint32_t index) return 0; } -DOMWindowLifecycleNotifier& DOMWindow::lifecycleNotifier() +DOMWindowLifecycleNotifier& LocalDOMWindow::lifecycleNotifier() { - return static_cast<DOMWindowLifecycleNotifier&>(LifecycleContext<DOMWindow>::lifecycleNotifier()); + return static_cast<DOMWindowLifecycleNotifier&>(LifecycleContext<LocalDOMWindow>::lifecycleNotifier()); } -PassOwnPtr<LifecycleNotifier<DOMWindow> > DOMWindow::createLifecycleNotifier() +PassOwnPtr<LifecycleNotifier<LocalDOMWindow> > LocalDOMWindow::createLifecycleNotifier() { return DOMWindowLifecycleNotifier::create(this); } +void LocalDOMWindow::trace(Visitor* visitor) +{ + visitor->trace(m_document); + visitor->trace(m_screen); + visitor->trace(m_history); + visitor->trace(m_locationbar); + visitor->trace(m_menubar); + visitor->trace(m_personalbar); + visitor->trace(m_scrollbars); + visitor->trace(m_statusbar); + visitor->trace(m_toolbar); + visitor->trace(m_console); + visitor->trace(m_navigator); + visitor->trace(m_location); + visitor->trace(m_media); + visitor->trace(m_sessionStorage); + visitor->trace(m_localStorage); + visitor->trace(m_applicationCache); + visitor->trace(m_performance); + visitor->trace(m_css); + visitor->trace(m_eventQueue); + WillBeHeapSupplementable<LocalDOMWindow>::trace(visitor); + EventTargetWithInlineData::trace(visitor); +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/DOMWindow.h b/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.h index f4590573794..82394787576 100644 --- a/chromium/third_party/WebKit/Source/core/frame/DOMWindow.h +++ b/chromium/third_party/WebKit/Source/core/frame/LocalDOMWindow.h @@ -27,11 +27,14 @@ #ifndef DOMWindow_h #define DOMWindow_h +#include "bindings/v8/Dictionary.h" #include "bindings/v8/ScriptWrappable.h" #include "core/events/EventTarget.h" +#include "core/frame/DOMWindowBase64.h" #include "core/frame/FrameDestructionObserver.h" #include "platform/LifecycleContext.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" @@ -56,16 +59,16 @@ namespace WebCore { class EventQueue; class ExceptionState; class FloatRect; - class Frame; + class FrameConsole; class History; class IDBFactory; + class LocalFrame; class Location; class MediaQueryList; class MessageEvent; class Navigator; class Node; class Page; - class PageConsole; class Performance; class PostMessageTimer; class RequestAnimationFrameCallback; @@ -89,51 +92,54 @@ enum PageshowEventPersistence { enum SetLocationLocking { LockHistoryBasedOnGestureState, LockHistoryAndBackForwardList }; - class DOMWindow : public RefCounted<DOMWindow>, public ScriptWrappable, public EventTargetWithInlineData, public FrameDestructionObserver, public Supplementable<DOMWindow>, public LifecycleContext<DOMWindow> { - REFCOUNTED_EVENT_TARGET(DOMWindow); + class LocalDOMWindow FINAL : public RefCountedWillBeRefCountedGarbageCollected<LocalDOMWindow>, public ScriptWrappable, public EventTargetWithInlineData, public DOMWindowBase64, public FrameDestructionObserver, public WillBeHeapSupplementable<LocalDOMWindow>, public LifecycleContext<LocalDOMWindow> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(LocalDOMWindow); + REFCOUNTED_EVENT_TARGET(LocalDOMWindow); public: - static PassRefPtr<Document> createDocument(const String& mimeType, const DocumentInit&, bool forceXHTML); - static PassRefPtr<DOMWindow> create(Frame* frame) { return adoptRef(new DOMWindow(frame)); } - virtual ~DOMWindow(); + static PassRefPtrWillBeRawPtr<Document> createDocument(const String& mimeType, const DocumentInit&, bool forceXHTML); + static PassRefPtrWillBeRawPtr<LocalDOMWindow> create(LocalFrame& frame) + { + return adoptRefWillBeRefCountedGarbageCollected(new LocalDOMWindow(frame)); + } + virtual ~LocalDOMWindow(); - PassRefPtr<Document> installNewDocument(const String& mimeType, const DocumentInit&, bool forceXHTML = false); + PassRefPtrWillBeRawPtr<Document> installNewDocument(const String& mimeType, const DocumentInit&, bool forceXHTML = false); virtual const AtomicString& interfaceName() const OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE; - virtual DOMWindow* toDOMWindow(); + virtual LocalDOMWindow* toDOMWindow() OVERRIDE; void registerProperty(DOMWindowProperty*); void unregisterProperty(DOMWindowProperty*); void reset(); - PassRefPtr<MediaQueryList> matchMedia(const String&); + PassRefPtrWillBeRawPtr<MediaQueryList> matchMedia(const String&); unsigned pendingUnloadEventListeners() const; - static FloatRect adjustWindowRect(Page*, const FloatRect& pendingChanges); + static FloatRect adjustWindowRect(LocalFrame&, const FloatRect& pendingChanges); bool allowPopUp(); // Call on first window, not target window. - static bool allowPopUp(Frame* firstFrame); - static bool canShowModalDialog(const Frame*); - static bool canShowModalDialogNow(const Frame*); + static bool allowPopUp(LocalFrame& firstFrame); + static bool canShowModalDialogNow(const LocalFrame*); // DOM Level 0 - Screen* screen() const; - History* history() const; - BarProp* locationbar() const; - BarProp* menubar() const; - BarProp* personalbar() const; - BarProp* scrollbars() const; - BarProp* statusbar() const; - BarProp* toolbar() const; - Navigator* navigator() const; - Navigator* clientInformation() const { return navigator(); } - - Location* location() const; - void setLocation(const String& location, DOMWindow* activeWindow, DOMWindow* firstWindow, + Screen& screen() const; + History& history() const; + BarProp& locationbar() const; + BarProp& menubar() const; + BarProp& personalbar() const; + BarProp& scrollbars() const; + BarProp& statusbar() const; + BarProp& toolbar() const; + Navigator& navigator() const; + Navigator& clientInformation() const { return navigator(); } + + Location& location() const; + void setLocation(const String& location, LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, SetLocationLocking = LockHistoryBasedOnGestureState); DOMSelection* getSelection(); @@ -146,14 +152,14 @@ enum PageshowEventPersistence { void print(); void stop(); - PassRefPtr<DOMWindow> open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString, - DOMWindow* activeWindow, DOMWindow* firstWindow); + PassRefPtrWillBeRawPtr<LocalDOMWindow> open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString, + LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow); - typedef void (*PrepareDialogFunction)(DOMWindow*, void* context); + typedef void (*PrepareDialogFunction)(LocalDOMWindow*, void* context); void showModalDialog(const String& urlString, const String& dialogFeaturesString, - DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction, void* functionContext); + LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, PrepareDialogFunction, void* functionContext); - void alert(const String& message); + void alert(const String& message = String()); bool confirm(const String& message); String prompt(const String& message, const String& defaultValue); @@ -188,13 +194,13 @@ enum PageshowEventPersistence { // Self-referential attributes - DOMWindow* self() const; - DOMWindow* window() const { return self(); } - DOMWindow* frames() const { return self(); } + LocalDOMWindow* self() const; + LocalDOMWindow* window() const { return self(); } + LocalDOMWindow* frames() const { return self(); } - DOMWindow* opener() const; - DOMWindow* parent() const; - DOMWindow* top() const; + LocalDOMWindow* opener() const; + LocalDOMWindow* parent() const; + LocalDOMWindow* top() const; // DOM Level 2 AbstractView Interface @@ -202,34 +208,37 @@ enum PageshowEventPersistence { // CSSOM View Module - PassRefPtr<StyleMedia> styleMedia() const; + StyleMedia& styleMedia() const; // DOM Level 2 Style Interface - PassRefPtr<CSSStyleDeclaration> getComputedStyle(Element*, const String& pseudoElt) const; + PassRefPtrWillBeRawPtr<CSSStyleDeclaration> getComputedStyle(Element*, const String& pseudoElt) const; // WebKit extensions - PassRefPtr<CSSRuleList> getMatchedCSSRules(Element*, const String& pseudoElt, bool authorOnly = true) const; + PassRefPtrWillBeRawPtr<CSSRuleList> getMatchedCSSRules(Element*, const String& pseudoElt) const; double devicePixelRatio() const; - PassRefPtr<DOMPoint> webkitConvertPointFromPageToNode(Node*, const DOMPoint*) const; - PassRefPtr<DOMPoint> webkitConvertPointFromNodeToPage(Node*, const DOMPoint*) const; + PassRefPtrWillBeRawPtr<DOMPoint> webkitConvertPointFromPageToNode(Node*, const DOMPoint*) const; + PassRefPtrWillBeRawPtr<DOMPoint> webkitConvertPointFromNodeToPage(Node*, const DOMPoint*) const; - Console* console() const; - PageConsole* pageConsole() const; + Console& console() const; + FrameConsole* frameConsole() const; void printErrorMessage(const String&); - String crossDomainAccessErrorMessage(DOMWindow* activeWindow); - String sanitizedCrossDomainAccessErrorMessage(DOMWindow* activeWindow); + String crossDomainAccessErrorMessage(LocalDOMWindow* callingWindow); + String sanitizedCrossDomainAccessErrorMessage(LocalDOMWindow* callingWindow); - void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, DOMWindow* source, ExceptionState&); - void postMessageTimerFired(PassOwnPtr<PostMessageTimer>); - void dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtr<Event>, PassRefPtr<ScriptCallStack>); + void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, LocalDOMWindow* source, ExceptionState&); + void postMessageTimerFired(PostMessageTimer*); + void dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtrWillBeRawPtr<Event>, PassRefPtrWillBeRawPtr<ScriptCallStack>); void scrollBy(int x, int y) const; + void scrollBy(int x, int y, const Dictionary& scrollOptions, ExceptionState&) const; void scrollTo(int x, int y) const; + void scrollTo(int x, int y, const Dictionary& scrollOptions, ExceptionState&) const; void scroll(int x, int y) const { scrollTo(x, y); } + void scroll(int x, int y, const Dictionary& scrollOptions, ExceptionState& exceptionState) const { scrollTo(x, y, scrollOptions, exceptionState); } void moveBy(float x, float y) const; void moveTo(float x, float y) const; @@ -242,16 +251,16 @@ enum PageshowEventPersistence { int webkitRequestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback>); void cancelAnimationFrame(int id); - DOMWindowCSS* css(); + DOMWindowCSS& css() const; // Events // EventTarget API - virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture) OVERRIDE; - virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture) OVERRIDE; + virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture = false) OVERRIDE; + virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture = false) OVERRIDE; virtual void removeAllEventListeners() OVERRIDE; using EventTarget::dispatchEvent; - bool dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget> prpTarget); + bool dispatchEvent(PassRefPtrWillBeRawPtr<Event> prpEvent, PassRefPtrWillBeRawPtr<EventTarget> prpTarget); void dispatchLoadEvent(); @@ -272,9 +281,6 @@ enum PageshowEventPersistence { void finishedLoading(); - DEFINE_ATTRIBUTE_EVENT_LISTENER(devicemotion); - DEFINE_ATTRIBUTE_EVENT_LISTENER(deviceorientation); - // HTML 5 key/value storage Storage* sessionStorage(ExceptionState&) const; Storage* localStorage(ExceptionState&) const; @@ -284,38 +290,35 @@ enum PageshowEventPersistence { ApplicationCache* applicationCache() const; ApplicationCache* optionalApplicationCache() const { return m_applicationCache.get(); } -#if ENABLE(ORIENTATION_EVENTS) // This is the interface orientation in degrees. Some examples are: // 0 is straight up; -90 is when the device is rotated 90 clockwise; // 90 is when rotated counter clockwise. int orientation() const; DEFINE_ATTRIBUTE_EVENT_LISTENER(orientationchange); -#endif - DEFINE_ATTRIBUTE_EVENT_LISTENER(touchstart); DEFINE_ATTRIBUTE_EVENT_LISTENER(touchmove); DEFINE_ATTRIBUTE_EVENT_LISTENER(touchend); DEFINE_ATTRIBUTE_EVENT_LISTENER(touchcancel); - Performance* performance() const; + Performance& performance() const; - // FIXME: When this DOMWindow is no longer the active DOMWindow (i.e., + // FIXME: When this LocalDOMWindow is no longer the active LocalDOMWindow (i.e., // when its document is no longer the document that is displayed in its // frame), we would like to zero out m_frame to avoid being confused // by the document that is currently active in m_frame. bool isCurrentlyDisplayedInFrame() const; void willDetachDocumentFromFrame(); - DOMWindow* anonymousIndexedGetter(uint32_t); + LocalDOMWindow* anonymousIndexedGetter(uint32_t); - bool isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString); + bool isInsecureScriptAccess(LocalDOMWindow& callingWindow, const String& urlString); - PassOwnPtr<LifecycleNotifier<DOMWindow> > createLifecycleNotifier(); + PassOwnPtr<LifecycleNotifier<LocalDOMWindow> > createLifecycleNotifier(); EventQueue* eventQueue() const; - void enqueueWindowEvent(PassRefPtr<Event>); - void enqueueDocumentEvent(PassRefPtr<Event>); + void enqueueWindowEvent(PassRefPtrWillBeRawPtr<Event>); + void enqueueDocumentEvent(PassRefPtrWillBeRawPtr<Event>); void enqueuePageshowEvent(PageshowEventPersistence); void enqueueHashchangeEvent(const String& oldURL, const String& newURL); void enqueuePopstateEvent(PassRefPtr<SerializedScriptValue>); @@ -323,64 +326,85 @@ enum PageshowEventPersistence { void documentWasClosed(); void statePopped(PassRefPtr<SerializedScriptValue>); - // FIXME: This shouldn't be public once DOMWindow becomes ExecutionContext. + // FIXME: This shouldn't be public once LocalDOMWindow becomes ExecutionContext. void clearEventQueue(); + void acceptLanguagesChanged(); + + virtual void trace(Visitor*) OVERRIDE; + protected: DOMWindowLifecycleNotifier& lifecycleNotifier(); private: - explicit DOMWindow(Frame*); + explicit LocalDOMWindow(LocalFrame&); Page* page(); virtual void frameDestroyed() OVERRIDE; - virtual void willDetachPage() OVERRIDE; + virtual void willDetachFrameHost() OVERRIDE; void clearDocument(); void resetDOMWindowProperties(); void willDestroyDocumentInFrame(); - RefPtr<Document> m_document; + // FIXME: Oilpan: the need for this internal method will fall + // away when EventTargets are no longer using refcounts and + // window properties are also on the heap. Inline the minimal + // do-not-broadcast handling then and remove the enum + + // removeAllEventListenersInternal(). + enum BroadcastListenerRemoval { + DoNotBroadcastListenerRemoval, + DoBroadcastListenerRemoval + }; + + void removeAllEventListenersInternal(BroadcastListenerRemoval); + + RefPtrWillBeMember<Document> m_document; bool m_shouldPrintWhenFinishedLoading; +#if ASSERT_ENABLED + bool m_hasBeenReset; +#endif HashSet<DOMWindowProperty*> m_properties; - mutable RefPtr<Screen> m_screen; - mutable RefPtr<History> m_history; - mutable RefPtr<BarProp> m_locationbar; - mutable RefPtr<BarProp> m_menubar; - mutable RefPtr<BarProp> m_personalbar; - mutable RefPtr<BarProp> m_scrollbars; - mutable RefPtr<BarProp> m_statusbar; - mutable RefPtr<BarProp> m_toolbar; - mutable RefPtr<Console> m_console; - mutable RefPtr<Navigator> m_navigator; - mutable RefPtr<Location> m_location; - mutable RefPtr<StyleMedia> m_media; + mutable RefPtrWillBeMember<Screen> m_screen; + mutable RefPtrWillBeMember<History> m_history; + mutable RefPtrWillBeMember<BarProp> m_locationbar; + mutable RefPtrWillBeMember<BarProp> m_menubar; + mutable RefPtrWillBeMember<BarProp> m_personalbar; + mutable RefPtrWillBeMember<BarProp> m_scrollbars; + mutable RefPtrWillBeMember<BarProp> m_statusbar; + mutable RefPtrWillBeMember<BarProp> m_toolbar; + mutable RefPtrWillBeMember<Console> m_console; + mutable RefPtrWillBeMember<Navigator> m_navigator; + mutable RefPtrWillBeMember<Location> m_location; + mutable RefPtrWillBeMember<StyleMedia> m_media; String m_status; String m_defaultStatus; - mutable RefPtr<Storage> m_sessionStorage; - mutable RefPtr<Storage> m_localStorage; - mutable RefPtr<ApplicationCache> m_applicationCache; + mutable RefPtrWillBeMember<Storage> m_sessionStorage; + mutable RefPtrWillBeMember<Storage> m_localStorage; + mutable RefPtrWillBeMember<ApplicationCache> m_applicationCache; - mutable RefPtr<Performance> m_performance; + mutable RefPtrWillBeMember<Performance> m_performance; - mutable RefPtr<DOMWindowCSS> m_css; + mutable RefPtrWillBeMember<DOMWindowCSS> m_css; - RefPtr<DOMWindowEventQueue> m_eventQueue; + RefPtrWillBeMember<DOMWindowEventQueue> m_eventQueue; RefPtr<SerializedScriptValue> m_pendingStateObject; + + HashSet<OwnPtr<PostMessageTimer> > m_postMessageTimers; }; - inline String DOMWindow::status() const + inline String LocalDOMWindow::status() const { return m_status; } - inline String DOMWindow::defaultStatus() const + inline String LocalDOMWindow::defaultStatus() const { return m_defaultStatus; } diff --git a/chromium/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/chromium/third_party/WebKit/Source/core/frame/LocalFrame.cpp new file mode 100644 index 00000000000..7fedecbd984 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/LocalFrame.cpp @@ -0,0 +1,660 @@ +/* + * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + * 1999 Lars Knoll <knoll@kde.org> + * 1999 Antti Koivisto <koivisto@kde.org> + * 2000 Simon Hausmann <hausmann@kde.org> + * 2000 Stefan Schimanski <1Stein@gmx.de> + * 2001 George Staikos <staikos@kde.org> + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2008 Google Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "core/frame/LocalFrame.h" + +#include "bindings/v8/ScriptController.h" +#include "core/dom/DocumentType.h" +#include "core/editing/Editor.h" +#include "core/editing/FrameSelection.h" +#include "core/editing/InputMethodController.h" +#include "core/editing/SpellChecker.h" +#include "core/editing/htmlediting.h" +#include "core/editing/markup.h" +#include "core/events/Event.h" +#include "core/fetch/ResourceFetcher.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/EventHandlerRegistry.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/FrameView.h" +#include "core/frame/Settings.h" +#include "core/html/HTMLFrameElementBase.h" +#include "core/inspector/InspectorInstrumentation.h" +#include "core/loader/FrameLoaderClient.h" +#include "core/page/Chrome.h" +#include "core/page/EventHandler.h" +#include "core/page/FocusController.h" +#include "core/page/scrolling/ScrollingCoordinator.h" +#include "core/rendering/HitTestResult.h" +#include "core/rendering/RenderLayer.h" +#include "core/rendering/RenderView.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" +#include "core/svg/SVGDocumentExtensions.h" +#include "platform/DragImage.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/graphics/GraphicsContext.h" +#include "platform/graphics/ImageBuffer.h" +#include "platform/text/TextStream.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/StdLibExtras.h" + +namespace WebCore { + +using namespace HTMLNames; + +static inline float parentPageZoomFactor(LocalFrame* frame) +{ + Frame* parent = frame->tree().parent(); + if (!parent || !parent->isLocalFrame()) + return 1; + return toLocalFrame(parent)->pageZoomFactor(); +} + +static inline float parentTextZoomFactor(LocalFrame* frame) +{ + Frame* parent = frame->tree().parent(); + if (!parent || !parent->isLocalFrame()) + return 1; + return toLocalFrame(parent)->textZoomFactor(); +} + +inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner) + : Frame(client, host, owner) + , m_loader(this) + , m_navigationScheduler(this) + , m_script(adoptPtr(new ScriptController(this))) + , m_editor(Editor::create(*this)) + , m_spellChecker(SpellChecker::create(*this)) + , m_selection(FrameSelection::create(this)) + , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this))) + , m_console(FrameConsole::create(*this)) + , m_inputMethodController(InputMethodController::create(*this)) + , m_pageZoomFactor(parentPageZoomFactor(this)) + , m_textZoomFactor(parentTextZoomFactor(this)) + , m_inViewSourceMode(false) +{ +} + +PassRefPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner) +{ + RefPtr<LocalFrame> frame = adoptRef(new LocalFrame(client, host, owner)); + InspectorInstrumentation::frameAttachedToParent(frame.get()); + return frame.release(); +} + +LocalFrame::~LocalFrame() +{ + setView(nullptr); + loader().clear(); + setDOMWindow(nullptr); +} + +bool LocalFrame::inScope(TreeScope* scope) const +{ + ASSERT(scope); + Document* doc = document(); + if (!doc) + return false; + // FIXME: This check is broken in for OOPI. + HTMLFrameOwnerElement* owner = doc->ownerElement(); + if (!owner) + return false; + return owner->treeScope() == scope; +} + +void LocalFrame::setView(PassRefPtr<FrameView> view) +{ + // We the custom scroll bars as early as possible to prevent m_doc->detach() + // from messing with the view such that its scroll bars won't be torn down. + // FIXME: We should revisit this. + if (m_view) + m_view->prepareForDetach(); + + // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is + // notified. If we wait until the view is destroyed, then things won't be hooked up enough for + // these calls to work. + if (!view && document() && document()->isActive()) { + // FIXME: We don't call willRemove here. Why is that OK? + document()->prepareForDestruction(); + } + + eventHandler().clear(); + + m_view = view; + + if (m_view && isMainFrame()) { + if (settings()->pinchVirtualViewportEnabled()) + m_host->pinchViewport().mainFrameDidChangeSize(); + else + m_view->setVisibleContentScaleFactor(page()->pageScaleFactor()); + } +} + +void LocalFrame::sendOrientationChangeEvent() +{ + if (!RuntimeEnabledFeatures::orientationEventEnabled() && !RuntimeEnabledFeatures::screenOrientationEnabled()) + return; + + if (page()->visibilityState() != PageVisibilityStateVisible) + return; + + LocalDOMWindow* window = domWindow(); + if (!window) + return; + window->dispatchEvent(Event::create(EventTypeNames::orientationchange)); + + // Notify subframes. + Vector<RefPtr<LocalFrame> > childFrames; + for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) { + if (child->isLocalFrame()) + childFrames.append(toLocalFrame(child)); + } + + for (size_t i = 0; i < childFrames.size(); ++i) + childFrames[i]->sendOrientationChangeEvent(); +} + +void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio) +{ + // In setting printing, we should not validate resources already cached for the document. + // See https://bugs.webkit.org/show_bug.cgi?id=43704 + ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher()); + + document()->setPrinting(printing); + view()->adjustMediaTypeForPrinting(printing); + + document()->styleResolverChanged(); + if (shouldUsePrintingLayout()) { + view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio); + } else { + view()->forceLayout(); + view()->adjustViewSize(); + } + + // Subframes of the one we're printing don't lay out to the page size. + for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) { + if (child->isLocalFrame()) + toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0); + } +} + +bool LocalFrame::shouldUsePrintingLayout() const +{ + // Only top frame being printed should be fit to page size. + // Subframes should be constrained by parents only. + return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing()); +} + +FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize) +{ + FloatSize resultSize; + if (!contentRenderer()) + return FloatSize(); + + if (contentRenderer()->style()->isHorizontalWritingMode()) { + ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon()); + float ratio = originalSize.height() / originalSize.width(); + resultSize.setWidth(floorf(expectedSize.width())); + resultSize.setHeight(floorf(resultSize.width() * ratio)); + } else { + ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon()); + float ratio = originalSize.width() / originalSize.height(); + resultSize.setHeight(floorf(expectedSize.height())); + resultSize.setWidth(floorf(resultSize.height() * ratio)); + } + return resultSize; +} + +void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow) +{ + InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get()); + if (domWindow) + script().clearWindowShell(); + Frame::setDOMWindow(domWindow); +} + +void LocalFrame::didChangeVisibilityState() +{ + if (document()) + document()->didChangeVisibilityState(); + + Vector<RefPtr<LocalFrame> > childFrames; + for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) { + if (child->isLocalFrame()) + childFrames.append(toLocalFrame(child)); + } + + for (size_t i = 0; i < childFrames.size(); ++i) + childFrames[i]->didChangeVisibilityState(); +} + +void LocalFrame::willDetachFrameHost() +{ + // We should never be detatching the page during a Layout. + RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout()); + + Frame* parent = tree().parent(); + if (parent && parent->isLocalFrame()) + toLocalFrame(parent)->loader().checkLoadComplete(); + + Frame::willDetachFrameHost(); + script().clearScriptObjects(); + + if (page() && page()->scrollingCoordinator() && m_view) + page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get()); +} + +void LocalFrame::detachFromFrameHost() +{ + // We should never be detatching the page during a Layout. + RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout()); + Frame::detachFromFrameHost(); +} + +String LocalFrame::documentTypeString() const +{ + if (DocumentType* doctype = document()->doctype()) + return createMarkup(doctype); + + return String(); +} + +String LocalFrame::selectedText() const +{ + return selection().selectedText(); +} + +String LocalFrame::selectedTextForClipboard() const +{ + return selection().selectedTextForClipboard(); +} + +VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint) +{ + HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint); + Node* node = result.innerNonSharedNode(); + if (!node) + return VisiblePosition(); + RenderObject* renderer = node->renderer(); + if (!renderer) + return VisiblePosition(); + VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint())); + if (visiblePos.isNull()) + visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node)); + return visiblePos; +} + +RenderView* LocalFrame::contentRenderer() const +{ + return document() ? document()->renderView() : 0; +} + +Document* LocalFrame::document() const +{ + return m_domWindow ? m_domWindow->document() : 0; +} + +Document* LocalFrame::documentAtPoint(const IntPoint& point) +{ + if (!view()) + return 0; + + IntPoint pt = view()->windowToContents(point); + HitTestResult result = HitTestResult(pt); + + if (contentRenderer()) + result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); + return result.innerNode() ? &result.innerNode()->document() : 0; +} + +PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint) +{ + VisiblePosition position = visiblePositionForPoint(framePoint); + if (position.isNull()) + return nullptr; + + VisiblePosition previous = position.previous(); + if (previous.isNotNull()) { + RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position); + LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get()); + if (rect.contains(framePoint)) + return previousCharacterRange.release(); + } + + VisiblePosition next = position.next(); + if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) { + LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get()); + if (rect.contains(framePoint)) + return nextCharacterRange.release(); + } + + return nullptr; +} + +void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent, + ScrollbarMode horizontalScrollbarMode, bool horizontalLock, + ScrollbarMode verticalScrollbarMode, bool verticalLock) +{ + ASSERT(this); + ASSERT(page()); + + bool isMainFrame = this->isMainFrame(); + + if (isMainFrame && view()) + view()->setParentVisible(false); + + setView(nullptr); + + RefPtr<FrameView> frameView; + if (isMainFrame) { + frameView = FrameView::create(this, viewportSize); + + // The layout size is set by WebViewImpl to support @viewport + frameView->setLayoutSizeFixedToFrameSize(false); + } else + frameView = FrameView::create(this); + + frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock); + + setView(frameView); + + frameView->updateBackgroundRecursively(backgroundColor, transparent); + + if (isMainFrame) + frameView->setParentVisible(true); + + // FIXME: Not clear what the right thing for OOPI is here. + if (ownerRenderer()) { + HTMLFrameOwnerElement* owner = deprecatedLocalOwner(); + ASSERT(owner); + owner->setWidget(frameView); + } + + if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner()) + view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); +} + + +void LocalFrame::countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial) +{ + RenderObject* root = view()->layoutRoot(); + isPartial = true; + if (!root) { + isPartial = false; + root = contentRenderer(); + } + + needsLayoutObjects = 0; + totalObjects = 0; + + for (RenderObject* o = root; o; o = o->nextInPreOrder(root)) { + ++totalObjects; + if (o->needsLayout()) + ++needsLayoutObjects; + } +} + +String LocalFrame::layerTreeAsText(LayerTreeFlags flags) const +{ + TextStream textStream; + textStream << localLayerTreeAsText(flags); + + for (Frame* child = tree().firstChild(); child; child = child->tree().traverseNext(this)) { + if (!child->isLocalFrame()) + continue; + String childLayerTree = toLocalFrame(child)->localLayerTreeAsText(flags); + if (!childLayerTree.length()) + continue; + + textStream << "\n\n--------\nFrame: '"; + textStream << child->tree().uniqueName(); + textStream << "'\n--------\n"; + textStream << childLayerTree; + } + + return textStream.release(); +} + +String LocalFrame::localLayerTreeAsText(unsigned flags) const +{ + if (!contentRenderer()) + return String(); + + return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags)); +} + +String LocalFrame::trackedRepaintRectsAsText() const +{ + if (!m_view) + return String(); + return m_view->trackedPaintInvalidationRectsAsText(); +} + +void LocalFrame::setPageZoomFactor(float factor) +{ + setPageAndTextZoomFactors(factor, m_textZoomFactor); +} + +void LocalFrame::setTextZoomFactor(float factor) +{ + setPageAndTextZoomFactors(m_pageZoomFactor, factor); +} + +void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor) +{ + if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor) + return; + + Page* page = this->page(); + if (!page) + return; + + Document* document = this->document(); + if (!document) + return; + + // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents. + // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification. + if (document->isSVGDocument()) { + if (!document->accessSVGExtensions().zoomAndPanEnabled()) + return; + } + + if (m_pageZoomFactor != pageZoomFactor) { + if (FrameView* view = this->view()) { + // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position. + LayoutPoint scrollPosition = view->scrollPosition(); + float percentDifference = (pageZoomFactor / m_pageZoomFactor); + view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference)); + } + } + + m_pageZoomFactor = pageZoomFactor; + m_textZoomFactor = textZoomFactor; + + for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) { + if (child->isLocalFrame()) + toLocalFrame(child.get())->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor); + } + + document->setNeedsStyleRecalc(SubtreeStyleChange); + document->updateLayoutIgnorePendingStylesheets(); +} + +void LocalFrame::deviceOrPageScaleFactorChanged() +{ + document()->mediaQueryAffectingValueChanged(); + for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) { + if (child->isLocalFrame()) + toLocalFrame(child.get())->deviceOrPageScaleFactorChanged(); + } +} + +bool LocalFrame::isURLAllowed(const KURL& url) const +{ + // We allow one level of self-reference because some sites depend on that, + // but we don't allow more than one. + if (page()->subframeCount() >= Page::maxNumberOfFrames) + return false; + bool foundSelfReference = false; + for (const Frame* frame = this; frame; frame = frame->tree().parent()) { + if (!frame->isLocalFrame()) + continue; + if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) { + if (foundSelfReference) + return false; + foundSelfReference = true; + } + } + return true; +} + +struct ScopedFramePaintingState { + ScopedFramePaintingState(LocalFrame* frame, Node* node) + : frame(frame) + , node(node) + , paintBehavior(frame->view()->paintBehavior()) + { + ASSERT(!node || node->renderer()); + if (node) + node->renderer()->updateDragState(true); + } + + ~ScopedFramePaintingState() + { + if (node && node->renderer()) + node->renderer()->updateDragState(false); + frame->view()->setPaintBehavior(paintBehavior); + frame->view()->setNodeToDraw(0); + } + + LocalFrame* frame; + Node* node; + PaintBehavior paintBehavior; +}; + +PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node) +{ + if (!node.renderer()) + return nullptr; + + const ScopedFramePaintingState state(this, &node); + + m_view->updateLayoutAndStyleForPainting(); + + m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers); + + m_view->setNodeToDraw(&node); // Enable special sub-tree drawing mode. + + // Document::updateLayout may have blown away the original RenderObject. + RenderObject* renderer = node.renderer(); + if (!renderer) + return nullptr; + + LayoutRect topLevelRect; + IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect)); + + ASSERT(document()->isActive()); + float deviceScaleFactor = m_host->deviceScaleFactor(); + paintingRect.setWidth(paintingRect.width() * deviceScaleFactor); + paintingRect.setHeight(paintingRect.height() * deviceScaleFactor); + + OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size()); + if (!buffer) + return nullptr; + buffer->context()->scale(deviceScaleFactor, deviceScaleFactor); + buffer->context()->translate(-paintingRect.x(), -paintingRect.y()); + buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY())); + + m_view->paintContents(buffer->context(), paintingRect); + + RefPtr<Image> image = buffer->copyImage(); + return DragImage::create(image.get(), renderer->shouldRespectImageOrientation(), deviceScaleFactor); +} + +PassOwnPtr<DragImage> LocalFrame::dragImageForSelection() +{ + if (!selection().isRange()) + return nullptr; + + const ScopedFramePaintingState state(this, 0); + m_view->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers); + document()->updateLayout(); + + IntRect paintingRect = enclosingIntRect(selection().bounds()); + + ASSERT(document()->isActive()); + float deviceScaleFactor = m_host->deviceScaleFactor(); + paintingRect.setWidth(paintingRect.width() * deviceScaleFactor); + paintingRect.setHeight(paintingRect.height() * deviceScaleFactor); + + OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size()); + if (!buffer) + return nullptr; + buffer->context()->scale(deviceScaleFactor, deviceScaleFactor); + buffer->context()->translate(-paintingRect.x(), -paintingRect.y()); + buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY())); + + m_view->paintContents(buffer->context(), paintingRect); + + RefPtr<Image> image = buffer->copyImage(); + return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor); +} + +double LocalFrame::devicePixelRatio() const +{ + if (!m_host) + return 0; + + double ratio = m_host->deviceScaleFactor(); + ratio *= pageZoomFactor(); + return ratio; +} + +void LocalFrame::disconnectOwnerElement() +{ + if (owner()) { + if (Document* doc = document()) + doc->topDocument().clearAXObjectCache(); + } + Frame::disconnectOwnerElement(); +} + +LocalFrame* LocalFrame::localFrameRoot() +{ + LocalFrame* curFrame = this; + while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame()) + curFrame = toLocalFrame(curFrame->tree().parent()); + + return curFrame; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/LocalFrame.h b/chromium/third_party/WebKit/Source/core/frame/LocalFrame.h new file mode 100644 index 00000000000..61c98f9b255 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/LocalFrame.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + * 1999-2001 Lars Knoll <knoll@kde.org> + * 1999-2001 Antti Koivisto <koivisto@kde.org> + * 2000-2001 Simon Hausmann <hausmann@kde.org> + * 2000-2001 Dirk Mueller <mueller@kde.org> + * 2000 Stefan Schimanski <1Stein@gmx.de> + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef LocalFrame_h +#define LocalFrame_h + +#include "core/frame/Frame.h" +#include "core/loader/FrameLoader.h" +#include "core/loader/NavigationScheduler.h" +#include "core/page/FrameTree.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" +#include "platform/scroll/ScrollTypes.h" + +namespace WebCore { + + class Color; + class Document; + class DragImage; + class Editor; + class EventHandler; + class FetchContext; + class FloatSize; + class FrameConsole; + class FrameSelection; + class FrameView; + class InputMethodController; + class IntPoint; + class IntSize; + class Node; + class Range; + class RenderView; + class TreeScope; + class ScriptController; + class SpellChecker; + class TreeScope; + class VisiblePosition; + + class LocalFrame : public Frame, public WillBePersistentHeapSupplementable<LocalFrame> { + public: + static PassRefPtr<LocalFrame> create(FrameLoaderClient*, FrameHost*, FrameOwner*); + + virtual bool isLocalFrame() const OVERRIDE { return true; } + + void init(); + void setView(PassRefPtr<FrameView>); + void createView(const IntSize&, const Color&, bool, + ScrollbarMode = ScrollbarAuto, bool horizontalLock = false, + ScrollbarMode = ScrollbarAuto, bool verticalLock = false); + + virtual ~LocalFrame(); + + virtual void willDetachFrameHost() OVERRIDE; + virtual void detachFromFrameHost() OVERRIDE; + + virtual void disconnectOwnerElement() OVERRIDE; + + virtual void setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow>) OVERRIDE; + FrameView* view() const; + Document* document() const; + + RenderView* contentRenderer() const; // Root of the render tree for the document contained in this frame. + + Editor& editor() const; + EventHandler& eventHandler() const; + FrameLoader& loader() const; + NavigationScheduler& navigationScheduler() const; + FrameSelection& selection() const; + InputMethodController& inputMethodController() const; + FetchContext& fetchContext() const { return loader().fetchContext(); } + ScriptController& script(); + SpellChecker& spellChecker() const; + FrameConsole& console() const; + + void didChangeVisibilityState(); + + // FIXME: This method is only used by EventHandler to get the highest level + // LocalFrame in this frame's in-process subtree. When user gesture tokens + // are synchronized across processes this method should be removed. + LocalFrame* localFrameRoot(); + + // ======== All public functions below this point are candidates to move out of LocalFrame into another class. ======== + + bool inScope(TreeScope*) const; + + void countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial); + + // See GraphicsLayerClient.h for accepted flags. + String layerTreeAsText(unsigned flags = 0) const; + String trackedRepaintRectsAsText() const; + + void setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio); + bool shouldUsePrintingLayout() const; + FloatSize resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize); + + bool inViewSourceMode() const; + void setInViewSourceMode(bool = true); + + void setPageZoomFactor(float factor); + float pageZoomFactor() const { return m_pageZoomFactor; } + void setTextZoomFactor(float factor); + float textZoomFactor() const { return m_textZoomFactor; } + void setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor); + + void deviceOrPageScaleFactorChanged(); + double devicePixelRatio() const; + + void sendOrientationChangeEvent(); + + String documentTypeString() const; + + PassOwnPtr<DragImage> nodeImage(Node&); + PassOwnPtr<DragImage> dragImageForSelection(); + + String selectedText() const; + String selectedTextForClipboard() const; + + VisiblePosition visiblePositionForPoint(const IntPoint& framePoint); + Document* documentAtPoint(const IntPoint& windowPoint); + PassRefPtrWillBeRawPtr<Range> rangeForPoint(const IntPoint& framePoint); + + bool isURLAllowed(const KURL&) const; + + // ======== + + private: + LocalFrame(FrameLoaderClient*, FrameHost*, FrameOwner*); + + String localLayerTreeAsText(unsigned flags) const; + + mutable FrameLoader m_loader; + mutable NavigationScheduler m_navigationScheduler; + + RefPtr<FrameView> m_view; + + OwnPtr<ScriptController> m_script; + const OwnPtrWillBePersistent<Editor> m_editor; + const OwnPtr<SpellChecker> m_spellChecker; + const OwnPtrWillBePersistent<FrameSelection> m_selection; + const OwnPtrWillBePersistent<EventHandler> m_eventHandler; + const OwnPtr<FrameConsole> m_console; + OwnPtr<InputMethodController> m_inputMethodController; + + float m_pageZoomFactor; + float m_textZoomFactor; + + bool m_inViewSourceMode; + }; + + inline void LocalFrame::init() + { + m_loader.init(); + } + + inline FrameLoader& LocalFrame::loader() const + { + return m_loader; + } + + inline NavigationScheduler& LocalFrame::navigationScheduler() const + { + return m_navigationScheduler; + } + + inline FrameView* LocalFrame::view() const + { + return m_view.get(); + } + + inline ScriptController& LocalFrame::script() + { + return *m_script; + } + + inline FrameSelection& LocalFrame::selection() const + { + return *m_selection; + } + + inline Editor& LocalFrame::editor() const + { + return *m_editor; + } + + inline SpellChecker& LocalFrame::spellChecker() const + { + return *m_spellChecker; + } + + inline FrameConsole& LocalFrame::console() const + { + return *m_console; + } + + inline InputMethodController& LocalFrame::inputMethodController() const + { + return *m_inputMethodController; + } + + inline bool LocalFrame::inViewSourceMode() const + { + return m_inViewSourceMode; + } + + inline void LocalFrame::setInViewSourceMode(bool mode) + { + m_inViewSourceMode = mode; + } + + inline EventHandler& LocalFrame::eventHandler() const + { + ASSERT(m_eventHandler); + return *m_eventHandler; + } + + DEFINE_TYPE_CASTS(LocalFrame, Frame, localFrame, localFrame->isLocalFrame(), localFrame.isLocalFrame()); + +} // namespace WebCore + +// During refactoring, there are some places where we need to do type conversions that +// will not be needed once all instances of LocalFrame and RemoteFrame are sorted out. +// At that time this #define will be removed and all the uses of it will need to be corrected. +#define toLocalFrameTemporary toLocalFrame + +#endif // LocalFrame_h diff --git a/chromium/third_party/WebKit/Source/core/frame/Location.cpp b/chromium/third_party/WebKit/Source/core/frame/Location.cpp index e38b2fde82e..42851fd2c7c 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Location.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/Location.cpp @@ -33,15 +33,15 @@ #include "core/dom/DOMURLUtilsReadOnly.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" #include "core/loader/FrameLoader.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/SecurityOrigin.h" namespace WebCore { -Location::Location(Frame* frame) +Location::Location(LocalFrame* frame) : DOMWindowProperty(frame) { ScriptWrappable::init(this); @@ -115,13 +115,16 @@ String Location::origin() const return DOMURLUtilsReadOnly::origin(url()); } -PassRefPtr<DOMStringList> Location::ancestorOrigins() const +PassRefPtrWillBeRawPtr<DOMStringList> Location::ancestorOrigins() const { - RefPtr<DOMStringList> origins = DOMStringList::create(); + RefPtrWillBeRawPtr<DOMStringList> origins = DOMStringList::create(); if (!m_frame) return origins.release(); - for (Frame* frame = m_frame->tree().parent(); frame; frame = frame->tree().parent()) - origins->append(frame->document()->securityOrigin()->toString()); + // FIXME: We do not yet have access to remote frame's origin. + for (Frame* frame = m_frame->tree().parent(); frame; frame = frame->tree().parent()) { + if (frame->isLocalFrame()) + origins->append(toLocalFrame(frame)->document()->securityOrigin()->toString()); + } return origins.release(); } @@ -133,14 +136,14 @@ String Location::hash() const return DOMURLUtilsReadOnly::hash(url()); } -void Location::setHref(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& url) +void Location::setHref(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& url) { if (!m_frame) return; - setLocation(url, activeWindow, firstWindow); + setLocation(url, callingWindow, enteredWindow); } -void Location::setProtocol(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& protocol, ExceptionState& exceptionState) +void Location::setProtocol(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& protocol, ExceptionState& exceptionState) { if (!m_frame) return; @@ -149,55 +152,55 @@ void Location::setProtocol(DOMWindow* activeWindow, DOMWindow* firstWindow, cons exceptionState.throwDOMException(SyntaxError, "'" + protocol + "' is an invalid protocol."); return; } - setLocation(url.string(), activeWindow, firstWindow); + setLocation(url.string(), callingWindow, enteredWindow); } -void Location::setHost(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& host) +void Location::setHost(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& host) { if (!m_frame) return; KURL url = m_frame->document()->url(); url.setHostAndPort(host); - setLocation(url.string(), activeWindow, firstWindow); + setLocation(url.string(), callingWindow, enteredWindow); } -void Location::setHostname(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& hostname) +void Location::setHostname(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& hostname) { if (!m_frame) return; KURL url = m_frame->document()->url(); url.setHost(hostname); - setLocation(url.string(), activeWindow, firstWindow); + setLocation(url.string(), callingWindow, enteredWindow); } -void Location::setPort(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& portString) +void Location::setPort(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& portString) { if (!m_frame) return; KURL url = m_frame->document()->url(); url.setPort(portString); - setLocation(url.string(), activeWindow, firstWindow); + setLocation(url.string(), callingWindow, enteredWindow); } -void Location::setPathname(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& pathname) +void Location::setPathname(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& pathname) { if (!m_frame) return; KURL url = m_frame->document()->url(); url.setPath(pathname); - setLocation(url.string(), activeWindow, firstWindow); + setLocation(url.string(), callingWindow, enteredWindow); } -void Location::setSearch(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& search) +void Location::setSearch(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& search) { if (!m_frame) return; KURL url = m_frame->document()->url(); url.setQuery(search); - setLocation(url.string(), activeWindow, firstWindow); + setLocation(url.string(), callingWindow, enteredWindow); } -void Location::setHash(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& hash) +void Location::setHash(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& hash) { if (!m_frame) return; @@ -212,25 +215,25 @@ void Location::setHash(DOMWindow* activeWindow, DOMWindow* firstWindow, const St // cases where fragment identifiers are ignored or invalid. if (equalIgnoringNullity(oldFragmentIdentifier, url.fragmentIdentifier())) return; - setLocation(url.string(), activeWindow, firstWindow); + setLocation(url.string(), callingWindow, enteredWindow); } -void Location::assign(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& url) +void Location::assign(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& url) { if (!m_frame) return; - setLocation(url, activeWindow, firstWindow); + setLocation(url, callingWindow, enteredWindow); } -void Location::replace(DOMWindow* activeWindow, DOMWindow* firstWindow, const String& url) +void Location::replace(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String& url) { if (!m_frame) return; - // Note: We call DOMWindow::setLocation directly here because replace() always operates on the current frame. - m_frame->domWindow()->setLocation(url, activeWindow, firstWindow, LockHistoryAndBackForwardList); + // Note: We call LocalDOMWindow::setLocation directly here because replace() always operates on the current frame. + m_frame->domWindow()->setLocation(url, callingWindow, enteredWindow, LockHistoryAndBackForwardList); } -void Location::reload(DOMWindow* activeWindow) +void Location::reload(LocalDOMWindow* callingWindow) { if (!m_frame) return; @@ -239,14 +242,13 @@ void Location::reload(DOMWindow* activeWindow) m_frame->navigationScheduler().scheduleRefresh(); } -void Location::setLocation(const String& url, DOMWindow* activeWindow, DOMWindow* firstWindow) +void Location::setLocation(const String& url, LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow) { ASSERT(m_frame); - // We call findFrameForNavigation to handle the case of a seamless iframe correctly. - Frame* frame = m_frame->loader().findFrameForNavigation(String(), activeWindow->document()); + LocalFrame* frame = m_frame->loader().findFrameForNavigation(nullAtom, callingWindow->document()); if (!frame) return; - frame->domWindow()->setLocation(url, activeWindow, firstWindow); + frame->domWindow()->setLocation(url, callingWindow, enteredWindow); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/Location.h b/chromium/third_party/WebKit/Source/core/frame/Location.h index 50b4b23cd87..d029b9727d0 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Location.h +++ b/chromium/third_party/WebKit/Source/core/frame/Location.h @@ -38,44 +38,49 @@ namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class ExceptionState; -class Frame; +class LocalFrame; class KURL; -class Location : public ScriptWrappable, public RefCounted<Location>, public DOMWindowProperty { +class Location FINAL : public RefCountedWillBeGarbageCollectedFinalized<Location>, public ScriptWrappable, public DOMWindowProperty { public: - static PassRefPtr<Location> create(Frame* frame) { return adoptRef(new Location(frame)); } + static PassRefPtrWillBeRawPtr<Location> create(LocalFrame* frame) + { + return adoptRefWillBeNoop(new Location(frame)); + } - void setHref(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); + void setHref(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String href() const; - void assign(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); - void replace(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); - void reload(DOMWindow* activeWindow); + void assign(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); + void replace(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); + void reload(LocalDOMWindow* callingWindow); - void setProtocol(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&, ExceptionState&); + void setProtocol(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&, ExceptionState&); String protocol() const; - void setHost(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); + void setHost(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String host() const; - void setHostname(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); + void setHostname(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String hostname() const; - void setPort(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); + void setPort(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String port() const; - void setPathname(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); + void setPathname(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String pathname() const; - void setSearch(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); + void setSearch(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String search() const; - void setHash(DOMWindow* activeWindow, DOMWindow* firstWindow, const String&); + void setHash(LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, const String&); String hash() const; String origin() const; - PassRefPtr<DOMStringList> ancestorOrigins() const; + PassRefPtrWillBeRawPtr<DOMStringList> ancestorOrigins() const; + + void trace(Visitor*) { } private: - explicit Location(Frame*); + explicit Location(LocalFrame*); - void setLocation(const String&, DOMWindow* activeWindow, DOMWindow* firstWindow); + void setLocation(const String&, LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow); const KURL& url() const; }; diff --git a/chromium/third_party/WebKit/Source/core/frame/Location.idl b/chromium/third_party/WebKit/Source/core/frame/Location.idl index 5ce29901ece..88aa1b79638 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Location.idl +++ b/chromium/third_party/WebKit/Source/core/frame/Location.idl @@ -28,6 +28,7 @@ [ CheckSecurity=Frame, + WillBeGarbageCollected, ] interface Location { // |assign|, |replace|, and *writing* |href| do not require a security // check, as they *change* the page, and thus these do not change any @@ -36,8 +37,8 @@ // problem, since that allows tracking navigation. [SetterCallWith=ActiveWindow&FirstWindow, DoNotCheckSecurity=Setter, Unforgeable] attribute DOMString href; - [CallWith=ActiveWindow&FirstWindow, DoNotCheckSecurity, Unforgeable, ReadOnly, PerWorldBindings, ActivityLogging=ForIsolatedWorlds] void assign(DOMString url); - [CallWith=ActiveWindow&FirstWindow, DoNotCheckSecurity, Unforgeable, ReadOnly, PerWorldBindings, ActivityLogging=ForIsolatedWorlds] void replace(DOMString url); + [CallWith=ActiveWindow&FirstWindow, DoNotCheckSecurity, Unforgeable, ReadOnly, LogActivity] void assign(DOMString url); + [CallWith=ActiveWindow&FirstWindow, DoNotCheckSecurity, Unforgeable, ReadOnly, LogActivity] void replace(DOMString url); [CallWith=ActiveWindow, Unforgeable, ReadOnly] void reload(); // URI decomposition attributes diff --git a/chromium/third_party/WebKit/Source/core/frame/Navigator.cpp b/chromium/third_party/WebKit/Source/core/frame/Navigator.cpp index 37b0b6f4121..08059baa407 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Navigator.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/Navigator.cpp @@ -25,11 +25,14 @@ #include "bindings/v8/ScriptController.h" #include "core/dom/Document.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/frame/NavigatorID.h" +#include "core/frame/Settings.h" #include "core/loader/CookieJar.h" #include "core/loader/FrameLoader.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" +#include "core/page/Chrome.h" +#include "core/page/ChromeClient.h" #include "core/plugins/DOMMimeTypeArray.h" #include "core/plugins/DOMPluginArray.h" #include "platform/Language.h" @@ -48,7 +51,7 @@ namespace WebCore { -Navigator::Navigator(Frame* frame) +Navigator::Navigator(LocalFrame* frame) : DOMWindowProperty(frame) { ScriptWrappable::init(this); @@ -58,38 +61,6 @@ Navigator::~Navigator() { } -// If this function returns true, we need to hide the substring "4." that would otherwise -// appear in the appVersion string. This is to avoid problems with old versions of a -// library called OpenCube QuickMenu, which as of this writing is still being used on -// sites such as nwa.com -- the library thinks Safari is Netscape 4 if we don't do this! -static bool shouldHideFourDot(Frame* frame) -{ - const String* sourceURL = frame->script().sourceURL(); - if (!sourceURL) - return false; - if (!(sourceURL->endsWith("/dqm_script.js") || sourceURL->endsWith("/dqm_loader.js") || sourceURL->endsWith("/tdqm_loader.js"))) - return false; - Settings* settings = frame->settings(); - if (!settings) - return false; - return settings->needsSiteSpecificQuirks(); -} - -String Navigator::appVersion() const -{ - if (!m_frame) - return String(); - String appVersion = NavigatorID::appVersion(this); - if (shouldHideFourDot(m_frame)) - appVersion.replace("4.", "4_"); - return appVersion; -} - -String Navigator::language() const -{ - return defaultLanguage(); -} - String Navigator::productSub() const { return WEBCORE_NAVIGATOR_PRODUCT_SUB; @@ -156,4 +127,36 @@ void Navigator::getStorageUpdates() // FIXME: Remove this method or rename to yieldForStorageUpdates. } +Vector<String> Navigator::languages() +{ + Vector<String> languages; + + if (!m_frame || !m_frame->host()) { + languages.append(defaultLanguage()); + return languages; + } + + String acceptLanguages = m_frame->host()->chrome().client().acceptLanguages(); + acceptLanguages.split(",", languages); + + // Sanitizing tokens. We could do that more extensively but we should assume + // that the accept languages are already sane and support BCP47. It is + // likely a waste of time to make sure the tokens matches that spec here. + for (size_t i = 0; i < languages.size(); ++i) { + String& token = languages[i]; + token = token.stripWhiteSpace(); + if (token.length() >= 3 && token[2] == '_') + token.replace(2, 1, "-"); + } + + return languages; +} + +void Navigator::trace(Visitor* visitor) +{ + visitor->trace(m_plugins); + visitor->trace(m_mimeTypes); + WillBeHeapSupplementable<Navigator>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/Navigator.h b/chromium/third_party/WebKit/Source/core/frame/Navigator.h index 0f289b3910e..44f8038d0b9 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Navigator.h +++ b/chromium/third_party/WebKit/Source/core/frame/Navigator.h @@ -22,8 +22,12 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/frame/DOMWindowProperty.h" -#include "core/frame/NavigatorBase.h" +#include "core/frame/NavigatorCPU.h" +#include "core/frame/NavigatorID.h" +#include "core/frame/NavigatorLanguage.h" +#include "core/frame/NavigatorOnLine.h" #include "platform/Supplementable.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -33,18 +37,29 @@ namespace WebCore { class DOMMimeTypeArray; class DOMPluginArray; -class Frame; +class LocalFrame; class PluginData; typedef int ExceptionCode; -class Navigator : public NavigatorBase, public ScriptWrappable, public RefCounted<Navigator>, public DOMWindowProperty, public Supplementable<Navigator> { +class Navigator FINAL + : public RefCountedWillBeGarbageCollectedFinalized<Navigator> + , public NavigatorCPU + , public NavigatorID + , public NavigatorLanguage + , public NavigatorOnLine + , public ScriptWrappable + , public DOMWindowProperty + , public WillBeHeapSupplementable<Navigator> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(Navigator); public: - static PassRefPtr<Navigator> create(Frame* frame) { return adoptRef(new Navigator(frame)); } + static PassRefPtrWillBeRawPtr<Navigator> create(LocalFrame* frame) + { + return adoptRefWillBeNoop(new Navigator(frame)); + } + virtual ~Navigator(); - String appVersion() const; - String language() const; DOMPluginArray* plugins() const; DOMMimeTypeArray* mimeTypes() const; bool cookieEnabled() const; @@ -59,11 +74,16 @@ public: // Relinquishes the storage lock, if one exists. void getStorageUpdates(); + // NavigatorLanguage + virtual Vector<String> languages() OVERRIDE; + + virtual void trace(Visitor*); + private: - explicit Navigator(Frame*); + explicit Navigator(LocalFrame*); - mutable RefPtr<DOMPluginArray> m_plugins; - mutable RefPtr<DOMMimeTypeArray> m_mimeTypes; + mutable RefPtrWillBeMember<DOMPluginArray> m_plugins; + mutable RefPtrWillBeMember<DOMMimeTypeArray> m_mimeTypes; }; } diff --git a/chromium/third_party/WebKit/Source/core/frame/Navigator.idl b/chromium/third_party/WebKit/Source/core/frame/Navigator.idl index 546e3e0f809..07fb6a2f08b 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Navigator.idl +++ b/chromium/third_party/WebKit/Source/core/frame/Navigator.idl @@ -17,12 +17,16 @@ Boston, MA 02110-1301, USA. */ -interface Navigator { - readonly attribute DOMString language; +// http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#navigator + +[ + WillBeGarbageCollected, +] interface Navigator { + // FIXME: move these 3 to NavigatorPlugins readonly attribute PluginArray plugins; readonly attribute MimeTypeArray mimeTypes; - readonly attribute boolean cookieEnabled; boolean javaEnabled(); + readonly attribute boolean cookieEnabled; // FIXME: move to NavigatorStorageUtils void getStorageUpdates(); // FIXME: Remove this method or rename to yieldForStorageUpdates. @@ -32,5 +36,7 @@ interface Navigator { [MeasureAs=NavigatorVendorSub] readonly attribute DOMString vendorSub; }; +Navigator implements NavigatorCPU; Navigator implements NavigatorID; +Navigator implements NavigatorLanguage; Navigator implements NavigatorOnLine; diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorBase.h b/chromium/third_party/WebKit/Source/core/frame/NavigatorBase.h deleted file mode 100644 index 38ae2660553..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/NavigatorBase.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE 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 NavigatorBase_h -#define NavigatorBase_h - -#include "wtf/Forward.h" - -namespace WebCore { - -class NavigatorBase { -public: - virtual String userAgent() const = 0; - -protected: - virtual ~NavigatorBase() { } -}; - -} // namespace WebCore - -#endif // NavigatorBase_h diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.cpp b/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.cpp new file mode 100644 index 00000000000..a5bee3d1fc7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.cpp @@ -0,0 +1,17 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/NavigatorCPU.h" + +#include "public/platform/Platform.h" + +namespace WebCore { + +unsigned NavigatorCPU::hardwareConcurrency() const +{ + return blink::Platform::current()->numberOfProcessors(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.h b/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.h new file mode 100644 index 00000000000..1bf35d9e463 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.h @@ -0,0 +1,17 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NavigatorCPU_h +#define NavigatorCPU_h + +namespace WebCore { + +class NavigatorCPU { +public: + unsigned hardwareConcurrency() const; +}; + +} // namespace WebCore + +#endif // NavigatorCPU_h diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.idl b/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.idl new file mode 100644 index 00000000000..8ec502c58fc --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorCPU.idl @@ -0,0 +1,9 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, +] interface NavigatorCPU { + readonly attribute unsigned long hardwareConcurrency; +}; diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorID.cpp b/chromium/third_party/WebKit/Source/core/frame/NavigatorID.cpp index 1b771dd1488..f3c04fdbcd0 100644 --- a/chromium/third_party/WebKit/Source/core/frame/NavigatorID.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorID.cpp @@ -30,9 +30,7 @@ */ #include "config.h" -#include "NavigatorID.h" - -#include "core/frame/NavigatorBase.h" +#include "core/frame/NavigatorID.h" #if !defined(WEBCORE_NAVIGATOR_PLATFORM) && OS(POSIX) && !OS(MACOSX) #include "wtf/StdLibExtras.h" @@ -45,24 +43,24 @@ namespace WebCore { -String NavigatorID::appName(const NavigatorBase*) +String NavigatorID::appCodeName() { - return "Netscape"; + return "Mozilla"; } -String NavigatorID::appVersion(const NavigatorBase* navigator) +String NavigatorID::appName() { - // Version is everything in the user agent string past the "Mozilla/" prefix. - const String& agent = navigator->userAgent(); - return agent.substring(agent.find('/') + 1); + return "Netscape"; } -String NavigatorID::userAgent(const NavigatorBase* navigator) +String NavigatorID::appVersion() { - return navigator->userAgent(); + // Version is everything in the user agent string past the "Mozilla/" prefix. + const String& agent = userAgent(); + return agent.substring(agent.find('/') + 1); } -String NavigatorID::platform(const NavigatorBase*) +String NavigatorID::platform() { #if defined(WEBCORE_NAVIGATOR_PLATFORM) return WEBCORE_NAVIGATOR_PLATFORM; @@ -79,12 +77,7 @@ String NavigatorID::platform(const NavigatorBase*) #endif } -String NavigatorID::appCodeName(const NavigatorBase*) -{ - return "Mozilla"; -} - -String NavigatorID::product(const NavigatorBase*) +String NavigatorID::product() { return WEBCORE_NAVIGATOR_PRODUCT; } diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorID.h b/chromium/third_party/WebKit/Source/core/frame/NavigatorID.h index 9e31d3100ee..fa383d6d732 100644 --- a/chromium/third_party/WebKit/Source/core/frame/NavigatorID.h +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorID.h @@ -35,16 +35,14 @@ namespace WebCore { -class NavigatorBase; - class NavigatorID { public: - static String appName(const NavigatorBase*); - static String appVersion(const NavigatorBase*); - static String userAgent(const NavigatorBase*); - static String platform(const NavigatorBase*); - static String appCodeName(const NavigatorBase*); - static String product(const NavigatorBase*); + String appCodeName(); + String appName(); + String appVersion(); + String platform(); + String product(); + virtual String userAgent() const = 0; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorID.idl b/chromium/third_party/WebKit/Source/core/frame/NavigatorID.idl index c581ad98bf2..a23bcb12a76 100644 --- a/chromium/third_party/WebKit/Source/core/frame/NavigatorID.idl +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorID.idl @@ -28,13 +28,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/#navigatorid + [ - NoInterfaceObject + NoInterfaceObject, // Always used on target of 'implements' ] interface NavigatorID { + readonly attribute DOMString appCodeName; // constant "Mozilla" readonly attribute DOMString appName; readonly attribute DOMString appVersion; readonly attribute DOMString platform; + readonly attribute DOMString product; // constant "Gecko" readonly attribute DOMString userAgent; - readonly attribute DOMString appCodeName; - readonly attribute DOMString product; }; diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.cpp b/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.cpp new file mode 100644 index 00000000000..ad520541539 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.cpp @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/NavigatorLanguage.h" + +#include "platform/Language.h" + +namespace WebCore { + +NavigatorLanguage::NavigatorLanguage() + : m_languagesChanged(true) +{ +} + +AtomicString NavigatorLanguage::language(bool& isNull) +{ + isNull = false; + return defaultLanguage(); +} + +bool NavigatorLanguage::hasLanguagesChanged() +{ + if (!m_languagesChanged) + return false; + + m_languagesChanged = false; + return true; +} + +void NavigatorLanguage::setLanguagesChanged() +{ + m_languagesChanged = true; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.h b/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.h new file mode 100644 index 00000000000..71515fe7f00 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.h @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NavigatorLanguage_h +#define NavigatorLanguage_h + +#include "wtf/text/AtomicString.h" + +namespace WebCore { + +class NavigatorLanguage { +public: + NavigatorLanguage(); + + AtomicString language(bool&); + virtual Vector<String> languages() = 0; + bool hasLanguagesChanged(); + void setLanguagesChanged(); + +private: + bool m_languagesChanged; +}; + +} // namespace WebCore + +#endif // NavigatorLanguage_h diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.idl b/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.idl new file mode 100644 index 00000000000..fe689f6c0d7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorLanguage.idl @@ -0,0 +1,10 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, +] interface NavigatorLanguage { + readonly attribute DOMString? language; + [CachedAttribute=hasLanguagesChanged] readonly attribute DOMString[] languages; +}; diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.h b/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.h index 5ae204d437c..5a99e84cbb4 100644 --- a/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.h +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.h @@ -37,7 +37,7 @@ namespace WebCore { class NavigatorOnLine { public: - static bool onLine(void*) + bool onLine() { return networkStateNotifier().onLine(); } diff --git a/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.idl b/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.idl index db4b08c1e0f..9268e63c126 100644 --- a/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.idl +++ b/chromium/third_party/WebKit/Source/core/frame/NavigatorOnLine.idl @@ -28,8 +28,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/#navigatoronline + [ - NoInterfaceObject + NoInterfaceObject, // Always used on target of 'implements' ] interface NavigatorOnLine { readonly attribute boolean onLine; }; diff --git a/chromium/third_party/WebKit/Source/core/frame/PRESUBMIT.py b/chromium/third_party/WebKit/Source/core/frame/PRESUBMIT.py new file mode 100644 index 00000000000..eba4c2f6642 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/PRESUBMIT.py @@ -0,0 +1,57 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Blink frame presubmit script + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into gcl. +""" + + +def _RunUseCounterChecks(input_api, output_api): + for f in input_api.AffectedFiles(): + if f.LocalPath().endswith('UseCounter.cpp'): + useCounterCpp = f + break + else: + return [] + + largestFoundBucket = 0 + maximumBucket = 0 + # Looking for a line like "case CSSPropertyGrid: return 453;" + bucketFinder = input_api.re.compile(r'.*CSSProperty.*return\s*([0-9]+).*') + # Looking for a line like "static int maximumCSSSampleId() { return 452; }" + maximumFinder = input_api.re.compile( + r'static int maximumCSSSampleId\(\) { return ([0-9]+)') + for line in useCounterCpp.NewContents(): + bucketMatch = bucketFinder.match(line) + if bucketMatch: + bucket = int(bucketMatch.group(1)) + largestFoundBucket = max(largestFoundBucket, bucket) + else: + maximumMatch = maximumFinder.match(line) + if maximumMatch: + maximumBucket = int(maximumMatch.group(1)) + + if largestFoundBucket != maximumBucket: + if input_api.is_committing: + message_type = output_api.PresubmitError + else: + message_type = output_api.PresubmitPromptWarning + + return [message_type( + 'Largest found CSSProperty bucket Id (%d) does not match ' + 'maximumCSSSampleId (%d)' % + (largestFoundBucket, maximumBucket), + items=[useCounterCpp.LocalPath()])] + + return [] + + +def CheckChangeOnUpload(input_api, output_api): + return _RunUseCounterChecks(input_api, output_api) + + +def CheckChangeOnCommit(input_api, output_api): + return _RunUseCounterChecks(input_api, output_api) diff --git a/chromium/third_party/WebKit/Source/core/frame/PinchViewport.cpp b/chromium/third_party/WebKit/Source/core/frame/PinchViewport.cpp new file mode 100644 index 00000000000..09947a9b41d --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/PinchViewport.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "core/frame/PinchViewport.h" + +#include "core/frame/FrameHost.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/page/Chrome.h" +#include "core/page/ChromeClient.h" +#include "core/page/Page.h" +#include "core/page/scrolling/ScrollingCoordinator.h" +#include "core/rendering/RenderView.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" +#include "platform/TraceEvent.h" +#include "platform/geometry/FloatSize.h" +#include "platform/graphics/GraphicsLayer.h" +#include "platform/graphics/GraphicsLayerFactory.h" +#include "platform/scroll/Scrollbar.h" +#include "public/platform/Platform.h" +#include "public/platform/WebCompositorSupport.h" +#include "public/platform/WebLayer.h" +#include "public/platform/WebLayerTreeView.h" +#include "public/platform/WebScrollbar.h" +#include "public/platform/WebScrollbarLayer.h" + +using blink::WebLayer; +using blink::WebLayerTreeView; +using blink::WebScrollbar; +using blink::WebScrollbarLayer; +using WebCore::FrameHost; +using WebCore::GraphicsLayer; +using WebCore::GraphicsLayerFactory; + +namespace WebCore { + +PinchViewport::PinchViewport(FrameHost& owner) + : m_frameHost(owner) + , m_scale(1) +{ + reset(); +} + +PinchViewport::~PinchViewport() { } + +void PinchViewport::setSize(const IntSize& size) +{ + if (m_size == size) + return; + + TRACE_EVENT2("webkit", "PinchViewport::setSize", "width", size.width(), "height", size.height()); + m_size = size; + + // Make sure we clamp the offset to within the new bounds. + setLocation(m_offset); + + if (m_innerViewportContainerLayer) { + m_innerViewportContainerLayer->setSize(m_size); + + // Need to re-compute sizes for the overlay scrollbars. + setupScrollbar(WebScrollbar::Horizontal); + setupScrollbar(WebScrollbar::Vertical); + } +} + +void PinchViewport::reset() +{ + setLocation(FloatPoint()); + setScale(1); +} + +void PinchViewport::mainFrameDidChangeSize() +{ + TRACE_EVENT0("webkit", "PinchViewport::mainFrameDidChangeSize"); + + // In unit tests we may not have initialized the layer tree. + if (m_innerViewportScrollLayer) + m_innerViewportScrollLayer->setSize(contentsSize()); + + // Make sure the viewport's offset is clamped within the newly sized main frame. + setLocation(m_offset); +} + +FloatRect PinchViewport::visibleRect() const +{ + FloatSize scaledSize(m_size); + scaledSize.scale(1 / m_scale); + return FloatRect(m_offset, scaledSize); +} + +FloatRect PinchViewport::visibleRectInDocument() const +{ + if (!mainFrame() || !mainFrame()->view()) + return FloatRect(); + + FloatRect viewRect = mainFrame()->view()->visibleContentRect(); + FloatRect pinchRect = visibleRect(); + pinchRect.moveBy(viewRect.location()); + return pinchRect; +} + +void PinchViewport::scrollIntoView(const FloatRect& rect) +{ + if (!mainFrame() || !mainFrame()->view()) + return; + + FrameView* view = mainFrame()->view(); + + float centeringOffsetX = (visibleRect().width() - rect.width()) / 2; + float centeringOffsetY = (visibleRect().height() - rect.height()) / 2; + + FloatPoint targetOffset( + rect.x() - centeringOffsetX - visibleRect().x(), + rect.y() - centeringOffsetY - visibleRect().y()); + + view->setScrollPosition(flooredIntPoint(targetOffset)); + + FloatPoint remainder = FloatPoint(targetOffset - view->scrollPosition()); + move(remainder); +} + +void PinchViewport::setLocation(const FloatPoint& newLocation) +{ + FloatPoint clampedOffset(clampOffsetToBoundaries(newLocation)); + + if (clampedOffset == m_offset) + return; + + m_offset = clampedOffset; + + ScrollingCoordinator* coordinator = m_frameHost.page().scrollingCoordinator(); + ASSERT(coordinator); + coordinator->scrollableAreaScrollLayerDidChange(this); + + mainFrame()->loader().saveScrollState(); +} + +void PinchViewport::move(const FloatPoint& delta) +{ + setLocation(m_offset + delta); +} + +void PinchViewport::setScale(float scale) +{ + if (scale == m_scale) + return; + + m_scale = scale; + + if (mainFrame()) + mainFrame()->loader().saveScrollState(); + + // Old-style pinch sets scale here but we shouldn't call into the + // clamping code below. + if (!m_innerViewportScrollLayer) + return; + + // Ensure we clamp so we remain within the bounds. + setLocation(visibleRect().location()); + + // TODO: We should probably be calling scaleDidChange type functions here. + // see Page::setPageScaleFactor. +} + +// Modifies the top of the graphics layer tree to add layers needed to support +// the inner/outer viewport fixed-position model for pinch zoom. When finished, +// the tree will look like this (with * denoting added layers): +// +// *rootTransformLayer +// +- *innerViewportContainerLayer (fixed pos container) +// +- *pageScaleLayer +// | +- *innerViewportScrollLayer +// | +-- overflowControlsHostLayer (root layer) +// | +-- outerViewportContainerLayer (fixed pos container) [frame container layer in RenderLayerCompositor] +// | | +-- outerViewportScrollLayer [frame scroll layer in RenderLayerCompositor] +// | | +-- content layers ... +// | +-- horizontal ScrollbarLayer (non-overlay) +// | +-- verticalScrollbarLayer (non-overlay) +// | +-- scroll corner (non-overlay) +// +- *horizontalScrollbarLayer (overlay) +// +- *verticalScrollbarLayer (overlay) +// +void PinchViewport::attachToLayerTree(GraphicsLayer* currentLayerTreeRoot, GraphicsLayerFactory* graphicsLayerFactory) +{ + TRACE_EVENT1("webkit", "PinchViewport::attachToLayerTree", "currentLayerTreeRoot", (bool)currentLayerTreeRoot); + if (!currentLayerTreeRoot) { + m_innerViewportScrollLayer->removeAllChildren(); + return; + } + + if (currentLayerTreeRoot->parent() && currentLayerTreeRoot->parent() == m_innerViewportScrollLayer) + return; + + if (!m_innerViewportScrollLayer) { + ASSERT(!m_overlayScrollbarHorizontal + && !m_overlayScrollbarVertical + && !m_pageScaleLayer + && !m_innerViewportContainerLayer); + + // FIXME: The root transform layer should only be created on demand. + m_rootTransformLayer = GraphicsLayer::create(graphicsLayerFactory, this); + m_innerViewportContainerLayer = GraphicsLayer::create(graphicsLayerFactory, this); + m_pageScaleLayer = GraphicsLayer::create(graphicsLayerFactory, this); + m_innerViewportScrollLayer = GraphicsLayer::create(graphicsLayerFactory, this); + m_overlayScrollbarHorizontal = GraphicsLayer::create(graphicsLayerFactory, this); + m_overlayScrollbarVertical = GraphicsLayer::create(graphicsLayerFactory, this); + + WebCore::ScrollingCoordinator* coordinator = m_frameHost.page().scrollingCoordinator(); + ASSERT(coordinator); + coordinator->setLayerIsContainerForFixedPositionLayers(m_innerViewportScrollLayer.get(), true); + + // Set masks to bounds so the compositor doesn't clobber a manually + // set inner viewport container layer size. + m_innerViewportContainerLayer->setMasksToBounds(m_frameHost.settings().mainFrameClipsContent()); + m_innerViewportContainerLayer->setSize(m_size); + + m_innerViewportScrollLayer->platformLayer()->setScrollClipLayer( + m_innerViewportContainerLayer->platformLayer()); + m_innerViewportScrollLayer->platformLayer()->setUserScrollable(true, true); + + m_rootTransformLayer->addChild(m_innerViewportContainerLayer.get()); + m_innerViewportContainerLayer->addChild(m_pageScaleLayer.get()); + m_pageScaleLayer->addChild(m_innerViewportScrollLayer.get()); + m_innerViewportContainerLayer->addChild(m_overlayScrollbarHorizontal.get()); + m_innerViewportContainerLayer->addChild(m_overlayScrollbarVertical.get()); + + // Ensure this class is set as the scroll layer's ScrollableArea. + coordinator->scrollableAreaScrollLayerDidChange(this); + + // Setup the inner viewport overlay scrollbars. + setupScrollbar(WebScrollbar::Horizontal); + setupScrollbar(WebScrollbar::Vertical); + } + + m_innerViewportScrollLayer->removeAllChildren(); + m_innerViewportScrollLayer->addChild(currentLayerTreeRoot); + + // We only need to disable the existing (outer viewport) scrollbars + // if the existing ones are already overlay. + // FIXME: If we knew in advance before the overflowControlsHostLayer goes + // away, we would re-enable the drawing of these scrollbars. + // FIXME: This doesn't seem to work (at least on Android). Commenting out for now until + // I figure out how to access RenderLayerCompositor from here. + // if (GraphicsLayer* scrollbar = m_frameHost->compositor()->layerForHorizontalScrollbar()) + // scrollbar->setDrawsContent(!page->mainFrame()->view()->hasOverlayScrollbars()); + // if (GraphicsLayer* scrollbar = m_frameHost->compositor()->layerForVerticalScrollbar()) + // scrollbar->setDrawsContent(!page->mainFrame()->view()->hasOverlayScrollbars()); +} + +void PinchViewport::setupScrollbar(WebScrollbar::Orientation orientation) +{ + bool isHorizontal = orientation == WebScrollbar::Horizontal; + GraphicsLayer* scrollbarGraphicsLayer = isHorizontal ? + m_overlayScrollbarHorizontal.get() : m_overlayScrollbarVertical.get(); + OwnPtr<WebScrollbarLayer>& webScrollbarLayer = isHorizontal ? + m_webOverlayScrollbarHorizontal : m_webOverlayScrollbarVertical; + + const int overlayScrollbarThickness = m_frameHost.settings().pinchOverlayScrollbarThickness(); + + if (!webScrollbarLayer) { + ScrollingCoordinator* coordinator = m_frameHost.page().scrollingCoordinator(); + ASSERT(coordinator); + ScrollbarOrientation webcoreOrientation = isHorizontal ? HorizontalScrollbar : VerticalScrollbar; + webScrollbarLayer = coordinator->createSolidColorScrollbarLayer(webcoreOrientation, overlayScrollbarThickness, 0, false); + + webScrollbarLayer->setClipLayer(m_innerViewportContainerLayer->platformLayer()); + scrollbarGraphicsLayer->setContentsToPlatformLayer(webScrollbarLayer->layer()); + scrollbarGraphicsLayer->setDrawsContent(false); + } + + int xPosition = isHorizontal ? 0 : m_innerViewportContainerLayer->size().width() - overlayScrollbarThickness; + int yPosition = isHorizontal ? m_innerViewportContainerLayer->size().height() - overlayScrollbarThickness : 0; + int width = isHorizontal ? m_innerViewportContainerLayer->size().width() - overlayScrollbarThickness : overlayScrollbarThickness; + int height = isHorizontal ? overlayScrollbarThickness : m_innerViewportContainerLayer->size().height() - overlayScrollbarThickness; + + // Use the GraphicsLayer to position the scrollbars. + scrollbarGraphicsLayer->setPosition(IntPoint(xPosition, yPosition)); + scrollbarGraphicsLayer->setSize(IntSize(width, height)); + scrollbarGraphicsLayer->setContentsRect(IntRect(0, 0, width, height)); +} + +void PinchViewport::registerLayersWithTreeView(WebLayerTreeView* layerTreeView) const +{ + TRACE_EVENT0("webkit", "PinchViewport::registerLayersWithTreeView"); + ASSERT(layerTreeView); + ASSERT(m_frameHost.page().mainFrame()); + ASSERT(m_frameHost.page().mainFrame()->isLocalFrame()); + ASSERT(m_frameHost.page().deprecatedLocalMainFrame()->contentRenderer()); + + RenderLayerCompositor* compositor = m_frameHost.page().deprecatedLocalMainFrame()->contentRenderer()->compositor(); + // Get the outer viewport scroll layer. + WebLayer* scrollLayer = compositor->scrollLayer()->platformLayer(); + + m_webOverlayScrollbarHorizontal->setScrollLayer(scrollLayer); + m_webOverlayScrollbarVertical->setScrollLayer(scrollLayer); + + ASSERT(compositor); + layerTreeView->registerViewportLayers( + m_pageScaleLayer->platformLayer(), + m_innerViewportScrollLayer->platformLayer(), + scrollLayer); +} + +void PinchViewport::clearLayersForTreeView(WebLayerTreeView* layerTreeView) const +{ + ASSERT(layerTreeView); + + layerTreeView->clearViewportLayers(); +} + +int PinchViewport::scrollSize(ScrollbarOrientation orientation) const +{ + IntSize scrollDimensions = maximumScrollPosition() - minimumScrollPosition(); + return (orientation == HorizontalScrollbar) ? scrollDimensions.width() : scrollDimensions.height(); +} + +IntPoint PinchViewport::minimumScrollPosition() const +{ + return IntPoint(); +} + +IntPoint PinchViewport::maximumScrollPosition() const +{ + return flooredIntPoint(FloatSize(contentsSize()) - visibleRect().size()); +} + +IntRect PinchViewport::scrollableAreaBoundingBox() const +{ + // This method should return the bounding box in the parent view's coordinate + // space; however, PinchViewport technically isn't a child of any Frames. + // Nonetheless, the PinchViewport always occupies the entire main frame so just + // return that. + LocalFrame* frame = mainFrame(); + + if (!frame || !frame->view()) + return IntRect(); + + return frame->view()->frameRect(); +} + +IntSize PinchViewport::contentsSize() const +{ + LocalFrame* frame = mainFrame(); + + if (!frame || !frame->view()) + return IntSize(); + + ASSERT(frame->view()->visibleContentScaleFactor() == 1); + return frame->view()->visibleContentRect(IncludeScrollbars).size(); +} + +void PinchViewport::invalidateScrollbarRect(Scrollbar*, const IntRect&) +{ + // Do nothing. Pinch scrollbars live on the compositor thread and will + // be updated when the viewport is synced to the CC. +} + +void PinchViewport::setScrollOffset(const IntPoint& offset) +{ + setLocation(offset); +} + +GraphicsLayer* PinchViewport::layerForContainer() const +{ + return m_innerViewportContainerLayer.get(); +} + +GraphicsLayer* PinchViewport::layerForScrolling() const +{ + return m_innerViewportScrollLayer.get(); +} + +GraphicsLayer* PinchViewport::layerForHorizontalScrollbar() const +{ + return m_overlayScrollbarHorizontal.get(); +} + +GraphicsLayer* PinchViewport::layerForVerticalScrollbar() const +{ + return m_overlayScrollbarVertical.get(); +} + +void PinchViewport::notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) +{ +} + +void PinchViewport::paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) +{ +} + +LocalFrame* PinchViewport::mainFrame() const +{ + return m_frameHost.page().mainFrame() && m_frameHost.page().mainFrame()->isLocalFrame() ? m_frameHost.page().deprecatedLocalMainFrame() : 0; +} + +FloatPoint PinchViewport::clampOffsetToBoundaries(const FloatPoint& offset) +{ + FloatPoint clampedOffset(offset); + clampedOffset = clampedOffset.shrunkTo(FloatPoint(maximumScrollPosition())); + clampedOffset = clampedOffset.expandedTo(FloatPoint(minimumScrollPosition())); + return clampedOffset; +} + +String PinchViewport::debugName(const GraphicsLayer* graphicsLayer) +{ + String name; + if (graphicsLayer == m_innerViewportContainerLayer.get()) { + name = "Inner Viewport Container Layer"; + } else if (graphicsLayer == m_pageScaleLayer.get()) { + name = "Page Scale Layer"; + } else if (graphicsLayer == m_innerViewportScrollLayer.get()) { + name = "Inner Viewport Scroll Layer"; + } else if (graphicsLayer == m_overlayScrollbarHorizontal.get()) { + name = "Overlay Scrollbar Horizontal Layer"; + } else if (graphicsLayer == m_overlayScrollbarVertical.get()) { + name = "Overlay Scrollbar Vertical Layer"; + } else { + ASSERT_NOT_REACHED(); + } + + return name; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/PinchViewport.h b/chromium/third_party/WebKit/Source/core/frame/PinchViewport.h new file mode 100644 index 00000000000..2dbc16f5707 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/PinchViewport.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PinchViewport_h +#define PinchViewport_h + +#include "platform/geometry/FloatPoint.h" +#include "platform/geometry/FloatRect.h" +#include "platform/geometry/IntSize.h" +#include "platform/graphics/GraphicsLayerClient.h" +#include "platform/scroll/ScrollableArea.h" +#include "public/platform/WebScrollbar.h" +#include "public/platform/WebSize.h" +#include "wtf/OwnPtr.h" +#include "wtf/PassOwnPtr.h" + +namespace blink { +class WebLayerTreeView; +class WebScrollbarLayer; +} + +namespace WebCore { + +class FrameHost; +class GraphicsContext; +class GraphicsLayer; +class GraphicsLayerFactory; +class IntRect; +class IntSize; +class LocalFrame; + +// Represents the pinch-to-zoom viewport the user is currently seeing the page through. This +// class corresponds to the InnerViewport on the compositor. It is a ScrollableArea; it's +// offset is set through the GraphicsLayer <-> CC sync mechanisms. Its contents is the page's +// main FrameView, which corresponds to the outer viewport. The inner viewport is always contained +// in the outer viewport and can pan within it. +class PinchViewport FINAL : public GraphicsLayerClient, public ScrollableArea { +public: + explicit PinchViewport(FrameHost&); + virtual ~PinchViewport(); + + void attachToLayerTree(GraphicsLayer*, GraphicsLayerFactory*); + GraphicsLayer* rootGraphicsLayer() + { + return m_rootTransformLayer.get(); + } + GraphicsLayer* containerLayer() + { + return m_innerViewportContainerLayer.get(); + } + + // Sets the location of the inner viewport relative to the outer viewport. The + // coordinates are in partial CSS pixels. + void setLocation(const FloatPoint&); + void move(const FloatPoint&); + + // Sets the size of the inner viewport when unscaled in CSS pixels. + // This will be clamped to the size of the outer viewport (the main frame). + void setSize(const IntSize&); + IntSize size() const { return m_size; } + + // Resets the viewport to initial state. + void reset(); + + // Let the viewport know that the main frame changed size (either through screen + // rotation on Android or window resize elsewhere). + void mainFrameDidChangeSize(); + + void setScale(float); + float scale() const { return m_scale; } + + void registerLayersWithTreeView(blink::WebLayerTreeView*) const; + void clearLayersForTreeView(blink::WebLayerTreeView*) const; + + // The portion of the unzoomed frame visible in the inner "pinch" viewport, + // in partial CSS pixels. Relative to the main frame. + FloatRect visibleRect() const; + + // The viewport rect relative to the document origin, in partial CSS pixels. + FloatRect visibleRectInDocument() const; + + // Scroll the main frame and pinch viewport so that the given rect in the + // top-level document is centered in the viewport. This method will avoid + // scrolling the pinch viewport unless necessary. + void scrollIntoView(const FloatRect&); +private: + // ScrollableArea implementation + virtual bool isActive() const OVERRIDE { return false; } + virtual int scrollSize(ScrollbarOrientation) const OVERRIDE; + virtual bool isScrollCornerVisible() const OVERRIDE { return false; } + virtual IntRect scrollCornerRect() const OVERRIDE { return IntRect(); } + virtual IntPoint scrollPosition() const OVERRIDE { return flooredIntPoint(m_offset); } + virtual IntPoint minimumScrollPosition() const OVERRIDE; + virtual IntPoint maximumScrollPosition() const OVERRIDE; + virtual int visibleHeight() const OVERRIDE { return visibleRect().height(); }; + virtual int visibleWidth() const OVERRIDE { return visibleRect().width(); }; + virtual IntSize contentsSize() const OVERRIDE; + virtual bool scrollbarsCanBeActive() const OVERRIDE { return false; } + virtual IntRect scrollableAreaBoundingBox() const OVERRIDE; + virtual bool userInputScrollable(ScrollbarOrientation) const OVERRIDE { return true; } + virtual bool shouldPlaceVerticalScrollbarOnLeft() const OVERRIDE { return false; } + virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) OVERRIDE; + virtual void invalidateScrollCornerRect(const IntRect&) OVERRIDE { } + virtual void setScrollOffset(const IntPoint&) OVERRIDE; + virtual GraphicsLayer* layerForContainer() const OVERRIDE; + virtual GraphicsLayer* layerForScrolling() const OVERRIDE; + virtual GraphicsLayer* layerForHorizontalScrollbar() const OVERRIDE; + virtual GraphicsLayer* layerForVerticalScrollbar() const OVERRIDE; + + // GraphicsLayerClient implementation. + virtual void notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) OVERRIDE; + virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) OVERRIDE; + virtual String debugName(const GraphicsLayer*) OVERRIDE; + + void setupScrollbar(blink::WebScrollbar::Orientation); + FloatPoint clampOffsetToBoundaries(const FloatPoint&); + + LocalFrame* mainFrame() const; + + FrameHost& m_frameHost; + OwnPtr<GraphicsLayer> m_rootTransformLayer; + OwnPtr<GraphicsLayer> m_innerViewportContainerLayer; + OwnPtr<GraphicsLayer> m_pageScaleLayer; + OwnPtr<GraphicsLayer> m_innerViewportScrollLayer; + OwnPtr<GraphicsLayer> m_overlayScrollbarHorizontal; + OwnPtr<GraphicsLayer> m_overlayScrollbarVertical; + OwnPtr<blink::WebScrollbarLayer> m_webOverlayScrollbarHorizontal; + OwnPtr<blink::WebScrollbarLayer> m_webOverlayScrollbarVertical; + + // Offset of the pinch viewport from the main frame's origin, in CSS pixels. + FloatPoint m_offset; + float m_scale; + IntSize m_size; +}; + +} // namespace WebCore + +#endif // PinchViewport_h diff --git a/chromium/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/chromium/third_party/WebKit/Source/core/frame/RemoteFrame.cpp new file mode 100644 index 00000000000..f4c9176abab --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/RemoteFrame.cpp @@ -0,0 +1,46 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/RemoteFrame.h" + +#include "core/frame/RemoteFrameView.h" +#include "core/html/HTMLFrameOwnerElement.h" + +namespace WebCore { + +inline RemoteFrame::RemoteFrame(FrameClient* client, FrameHost* host, FrameOwner* owner) + : Frame(client, host, owner) +{ +} + +PassRefPtr<RemoteFrame> RemoteFrame::create(FrameClient* client, FrameHost* host, FrameOwner* owner) +{ + RefPtr<RemoteFrame> frame = adoptRef(new RemoteFrame(client, host, owner)); + return frame.release(); +} + +RemoteFrame::~RemoteFrame() +{ + setView(nullptr); +} + +void RemoteFrame::setView(PassRefPtr<RemoteFrameView> view) +{ + m_view = view; +} + +void RemoteFrame::createView() +{ + RefPtr<RemoteFrameView> view = RemoteFrameView::create(this); + setView(view); + + if (ownerRenderer()) { + HTMLFrameOwnerElement* owner = deprecatedLocalOwner(); + ASSERT(owner); + owner->setWidget(view); + } +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/RemoteFrame.h b/chromium/third_party/WebKit/Source/core/frame/RemoteFrame.h new file mode 100644 index 00000000000..d8ec29be138 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/RemoteFrame.h @@ -0,0 +1,41 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RemoteFrame_h +#define RemoteFrame_h + +#include "core/frame/Frame.h" + +namespace WebCore { + +class RemoteFrameView; + +class RemoteFrame: public Frame { +public: + static PassRefPtr<RemoteFrame> create(FrameClient*, FrameHost*, FrameOwner*); + virtual bool isRemoteFrame() const OVERRIDE { return true; } + + virtual ~RemoteFrame(); + + void setView(PassRefPtr<RemoteFrameView>); + void createView(); + + RemoteFrameView* view() const; + +private: + RemoteFrame(FrameClient*, FrameHost*, FrameOwner*); + + RefPtr<RemoteFrameView> m_view; +}; + +inline RemoteFrameView* RemoteFrame::view() const +{ + return m_view.get(); +} + +DEFINE_TYPE_CASTS(RemoteFrame, Frame, remoteFrame, remoteFrame->isRemoteFrame(), remoteFrame.isRemoteFrame()); + +} // namespace WebCore + +#endif // RemoteFrame_h diff --git a/chromium/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp b/chromium/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp new file mode 100644 index 00000000000..bd4e7c85c0d --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp @@ -0,0 +1,59 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/RemoteFrameView.h" + +#include "core/frame/RemoteFrame.h" +#include "core/rendering/RenderPart.h" + +namespace WebCore { + +RemoteFrameView::RemoteFrameView(RemoteFrame* remoteFrame) + : m_remoteFrame(remoteFrame) +{ + ASSERT(remoteFrame); +} + +RemoteFrameView::~RemoteFrameView() +{ +} + +PassRefPtr<RemoteFrameView> RemoteFrameView::create(RemoteFrame* remoteFrame) +{ + RefPtr<RemoteFrameView> view = adoptRef(new RemoteFrameView(remoteFrame)); + view->show(); + return view.release(); +} + +void RemoteFrameView::invalidateRect(const IntRect& rect) +{ + RenderPart* renderer = m_remoteFrame->ownerRenderer(); + if (!renderer) + return; + + IntRect repaintRect = rect; + repaintRect.move(renderer->borderLeft() + renderer->paddingLeft(), + renderer->borderTop() + renderer->paddingTop()); + renderer->invalidatePaintRectangle(repaintRect); +} + +void RemoteFrameView::setFrameRect(const IntRect& newRect) +{ + IntRect oldRect = frameRect(); + + if (newRect == oldRect) + return; + + Widget::setFrameRect(newRect); + + frameRectsChanged(); +} + +void RemoteFrameView::frameRectsChanged() +{ + // FIXME: Notify embedder via WebLocalFrameClient when that is possible. +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/RemoteFrameView.h b/chromium/third_party/WebKit/Source/core/frame/RemoteFrameView.h new file mode 100644 index 00000000000..a8d31f2e21e --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/RemoteFrameView.h @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RemoteFrameView_h +#define RemoteFrameView_h + +#include "platform/Widget.h" +#include "platform/geometry/IntRect.h" + +namespace WebCore { + +class RemoteFrame; + +class RemoteFrameView : public Widget { +public: + static PassRefPtr<RemoteFrameView> create(RemoteFrame*); + + virtual ~RemoteFrameView(); + + virtual bool isRemoteFrameView() const OVERRIDE { return true; } + + RemoteFrame& frame() const { return *m_remoteFrame; } + + // Override to notify remote frame that its viewport size has changed. + virtual void frameRectsChanged() OVERRIDE; + + virtual void invalidateRect(const IntRect&) OVERRIDE; + + virtual void setFrameRect(const IntRect&) OVERRIDE; + +private: + explicit RemoteFrameView(RemoteFrame*); + + RefPtr<RemoteFrame> m_remoteFrame; +}; + +DEFINE_TYPE_CASTS(RemoteFrameView, Widget, widget, widget->isRemoteFrameView(), widget.isRemoteFrameView()); + +} // namespace WebCore + +#endif // RemoteFrameView_h diff --git a/chromium/third_party/WebKit/Source/core/frame/Screen.cpp b/chromium/third_party/WebKit/Source/core/frame/Screen.cpp index 18b22d63503..13523f46223 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Screen.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/Screen.cpp @@ -30,17 +30,17 @@ #include "config.h" #include "core/frame/Screen.h" -#include "core/inspector/InspectorInstrumentation.h" -#include "core/frame/Frame.h" +#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" -#include "core/page/Page.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/inspector/InspectorInstrumentation.h" #include "platform/PlatformScreen.h" #include "platform/geometry/FloatRect.h" namespace WebCore { -Screen::Screen(Frame* frame) +Screen::Screen(LocalFrame* frame) : DOMWindowProperty(frame) { ScriptWrappable::init(this); @@ -50,9 +50,9 @@ unsigned Screen::height() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (page && page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(screenRect(m_frame->view()).height() * page->deviceScaleFactor()); + FrameHost* host = m_frame->host(); + if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(screenRect(m_frame->view()).height() * host->deviceScaleFactor()); return static_cast<unsigned>(screenRect(m_frame->view()).height()); } @@ -60,9 +60,9 @@ unsigned Screen::width() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (page && page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(screenRect(m_frame->view()).width() * page->deviceScaleFactor()); + FrameHost* host = m_frame->host(); + if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(screenRect(m_frame->view()).width() * host->deviceScaleFactor()); return static_cast<unsigned>(screenRect(m_frame->view()).width()); } @@ -84,9 +84,9 @@ int Screen::availLeft() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (page && page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(screenAvailableRect(m_frame->view()).x() * page->deviceScaleFactor()); + FrameHost* host = m_frame->host(); + if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(screenAvailableRect(m_frame->view()).x() * host->deviceScaleFactor()); return static_cast<int>(screenAvailableRect(m_frame->view()).x()); } @@ -94,9 +94,9 @@ int Screen::availTop() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (page && page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(screenAvailableRect(m_frame->view()).y() * page->deviceScaleFactor()); + FrameHost* host = m_frame->host(); + if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(screenAvailableRect(m_frame->view()).y() * host->deviceScaleFactor()); return static_cast<int>(screenAvailableRect(m_frame->view()).y()); } @@ -104,9 +104,9 @@ unsigned Screen::availHeight() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (page && page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(screenAvailableRect(m_frame->view()).height() * page->deviceScaleFactor()); + FrameHost* host = m_frame->host(); + if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(screenAvailableRect(m_frame->view()).height() * host->deviceScaleFactor()); return static_cast<unsigned>(screenAvailableRect(m_frame->view()).height()); } @@ -114,10 +114,15 @@ unsigned Screen::availWidth() const { if (!m_frame) return 0; - Page* page = m_frame->page(); - if (page && page->settings().reportScreenSizeInPhysicalPixelsQuirk()) - return lroundf(screenAvailableRect(m_frame->view()).width() * page->deviceScaleFactor()); + FrameHost* host = m_frame->host(); + if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) + return lroundf(screenAvailableRect(m_frame->view()).width() * host->deviceScaleFactor()); return static_cast<unsigned>(screenAvailableRect(m_frame->view()).width()); } +void Screen::trace(Visitor* visitor) +{ + WillBeHeapSupplementable<Screen>::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/Screen.h b/chromium/third_party/WebKit/Source/core/frame/Screen.h index 7b2036b677e..99514918f28 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Screen.h +++ b/chromium/third_party/WebKit/Source/core/frame/Screen.h @@ -32,16 +32,22 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/frame/DOMWindowProperty.h" +#include "platform/Supplementable.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { - class Frame; + class LocalFrame; - class Screen : public ScriptWrappable, public RefCounted<Screen>, public DOMWindowProperty { + class Screen FINAL : public RefCountedWillBeGarbageCollectedFinalized<Screen>, public ScriptWrappable, public DOMWindowProperty, public WillBeHeapSupplementable<Screen> { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(Screen); public: - static PassRefPtr<Screen> create(Frame *frame) { return adoptRef(new Screen(frame)); } + static PassRefPtrWillBeRawPtr<Screen> create(LocalFrame* frame) + { + return adoptRefWillBeNoop(new Screen(frame)); + } unsigned height() const; unsigned width() const; @@ -52,8 +58,10 @@ namespace WebCore { unsigned availHeight() const; unsigned availWidth() const; + void trace(Visitor*); + private: - explicit Screen(Frame*); + explicit Screen(LocalFrame*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/Screen.idl b/chromium/third_party/WebKit/Source/core/frame/Screen.idl index 184a863c4d9..a0b6385676f 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Screen.idl +++ b/chromium/third_party/WebKit/Source/core/frame/Screen.idl @@ -27,7 +27,9 @@ */ -interface Screen { +[ + WillBeGarbageCollected, +] interface Screen { readonly attribute unsigned long height; readonly attribute unsigned long width; readonly attribute unsigned long colorDepth; diff --git a/chromium/third_party/WebKit/Source/core/frame/SecurityPolicy.idl b/chromium/third_party/WebKit/Source/core/frame/SecurityPolicy.idl deleted file mode 100644 index f5651dac093..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/SecurityPolicy.idl +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -[ - ImplementedAs=DOMSecurityPolicy -] interface SecurityPolicy { - readonly attribute boolean allowsEval; - readonly attribute boolean allowsInlineScript; - readonly attribute boolean allowsInlineStyle; - readonly attribute boolean isActive; - - readonly attribute DOMStringList reportURIs; - - boolean allowsConnectionTo(DOMString url); - boolean allowsFontFrom(DOMString url); - boolean allowsFormAction(DOMString url); - boolean allowsFrameFrom(DOMString url); - boolean allowsImageFrom(DOMString url); - boolean allowsMediaFrom(DOMString url); - boolean allowsObjectFrom(DOMString url); - boolean allowsPluginType(DOMString type); - boolean allowsScriptFrom(DOMString url); - boolean allowsStyleFrom(DOMString url); -}; diff --git a/chromium/third_party/WebKit/Source/core/frame/Settings.cpp b/chromium/third_party/WebKit/Source/core/frame/Settings.cpp index b7d8d76b6ab..b4f209e29b3 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Settings.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/Settings.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/frame/Settings.h" -#include "core/inspector/InspectorInstrumentation.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/scroll/ScrollbarTheme.h" namespace WebCore { @@ -65,7 +65,7 @@ static const bool defaultSelectTrailingWhitespaceEnabled = false; #endif Settings::Settings() - : m_deviceScaleAdjustment(1.0f) + : m_openGLMultisamplingEnabled(false) #if HACK_FORCE_TEXT_AUTOSIZING_ON_DESKTOP , m_textAutosizingWindowSizeOverride(320, 480) , m_textAutosizingEnabled(true) @@ -73,8 +73,6 @@ Settings::Settings() , m_textAutosizingEnabled(false) #endif SETTINGS_INITIALIZER_LIST - , m_isScriptEnabled(false) - , m_openGLMultisamplingEnabled(false) { } @@ -96,26 +94,13 @@ void Settings::invalidate(SettingsDelegate::ChangeType changeType) m_delegate->settingsChanged(changeType); } -// This is a total hack and should be removed. -Page* Settings::pageOfShame() const -{ - if (!m_delegate) - return 0; - return m_delegate->page(); -} - void Settings::setTextAutosizingEnabled(bool textAutosizingEnabled) { if (m_textAutosizingEnabled == textAutosizingEnabled) return; m_textAutosizingEnabled = textAutosizingEnabled; - invalidate(SettingsDelegate::StyleChange); -} - -bool Settings::textAutosizingEnabled() const -{ - return InspectorInstrumentation::overrideTextAutosizing(pageOfShame(), m_textAutosizingEnabled); + invalidate(SettingsDelegate::TextAutosizingChange); } // FIXME: Move to Settings.in once make_settings can understand IntSize. @@ -125,26 +110,9 @@ void Settings::setTextAutosizingWindowSizeOverride(const IntSize& textAutosizing return; m_textAutosizingWindowSizeOverride = textAutosizingWindowSizeOverride; - invalidate(SettingsDelegate::StyleChange); -} - -void Settings::setDeviceScaleAdjustment(float deviceScaleAdjustment) -{ - m_deviceScaleAdjustment = deviceScaleAdjustment; invalidate(SettingsDelegate::TextAutosizingChange); } -float Settings::deviceScaleAdjustment() const -{ - return InspectorInstrumentation::overrideFontScaleFactor(pageOfShame(), m_deviceScaleAdjustment); -} - -void Settings::setScriptEnabled(bool isScriptEnabled) -{ - m_isScriptEnabled = isScriptEnabled; - InspectorInstrumentation::scriptsEnabled(pageOfShame(), m_isScriptEnabled); -} - void Settings::setMockScrollbarsEnabled(bool flag) { ScrollbarTheme::setMockScrollbarsEnabled(flag); diff --git a/chromium/third_party/WebKit/Source/core/frame/Settings.h b/chromium/third_party/WebKit/Source/core/frame/Settings.h index 76f5ac5097f..13a03394c0e 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Settings.h +++ b/chromium/third_party/WebKit/Source/core/frame/Settings.h @@ -27,7 +27,7 @@ #ifndef Settings_h #define Settings_h -#include "SettingsMacros.h" +#include "core/SettingsMacros.h" #include "core/editing/EditingBehaviorTypes.h" #include "core/frame/SettingsDelegate.h" #include "platform/Timer.h" @@ -39,42 +39,21 @@ namespace WebCore { -class Page; // For inspector, remove after http://crbug.com/327476 - -enum EditableLinkBehavior { - EditableLinkDefaultBehavior, - EditableLinkAlwaysLive, - EditableLinkOnlyLiveWithShiftKey, - EditableLinkLiveWhenNotFocused, - EditableLinkNeverLive -}; - class Settings { WTF_MAKE_NONCOPYABLE(Settings); WTF_MAKE_FAST_ALLOCATED; public: static PassOwnPtr<Settings> create(); GenericFontFamilySettings& genericFontFamilySettings() { return m_genericFontFamilySettings; } + void notifyGenericFontFamilyChange() { invalidate(SettingsDelegate::FontFamilyChange); } void setTextAutosizingEnabled(bool); - bool textAutosizingEnabled() const; - - // Compensates for poor text legibility on mobile devices. This value is - // multiplied by the font scale factor when performing text autosizing of - // websites that do not set an explicit viewport description. - void setDeviceScaleAdjustment(float); - float deviceScaleAdjustment() const; + bool textAutosizingEnabled() const { return m_textAutosizingEnabled; } // Only set by Layout Tests, and only used if textAutosizingEnabled() returns true. void setTextAutosizingWindowSizeOverride(const IntSize&); const IntSize& textAutosizingWindowSizeOverride() const { return m_textAutosizingWindowSizeOverride; } - // Clients that execute script should call ScriptController::canExecuteScripts() - // instead of this function. ScriptController::canExecuteScripts() checks the - // HTML sandbox, plug-in sandboxing, and other important details. - bool isScriptEnabled() const { return m_isScriptEnabled; } - void setScriptEnabled(bool); - SETTINGS_GETTERS_AND_SETTERS // FIXME: This does not belong here. @@ -93,21 +72,14 @@ private: void invalidate(SettingsDelegate::ChangeType); - // FIXME: pageOfShame() is a hack for the inspector code: - // http://crbug.com/327476 - Page* pageOfShame() const; - SettingsDelegate* m_delegate; GenericFontFamilySettings m_genericFontFamilySettings; - float m_deviceScaleAdjustment; + bool m_openGLMultisamplingEnabled : 1; IntSize m_textAutosizingWindowSizeOverride; bool m_textAutosizingEnabled : 1; SETTINGS_MEMBER_VARIABLES - - bool m_isScriptEnabled : 1; - bool m_openGLMultisamplingEnabled : 1; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/Settings.in b/chromium/third_party/WebKit/Source/core/frame/Settings.in index b45c89ad2cd..20b73637afd 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Settings.in +++ b/chromium/third_party/WebKit/Source/core/frame/Settings.in @@ -25,7 +25,6 @@ # FIXME: Add support for custom getters/setters. defaultTextEncodingName type=String -editableLinkBehavior type=EditableLinkBehavior, initial=EditableLinkDefaultBehavior # Do not hide chars typed in password fields immediately, but let the last char stay # visible for N seconds, configured by the passwordEchoDurationInSeconds setting @@ -51,10 +50,6 @@ validationMessageTimerMagnification type=int, initial=50 # draw canvas in software. minimumAccelerated2dCanvasSize type=int, initial=257*256 -# The layout width used with --enable-viewport when no viewport meta tag was defined. -# FIXME: This should get the value from the @viewport UA sheet instead. -layoutFallbackWidth type=int, initial=980 - minimumFontSize type=int, initial=0, invalidate=Style minimumLogicalFontSize type=int, initial=0, invalidate=Style defaultFontSize type=int, initial=0, invalidate=Style @@ -73,10 +68,7 @@ shouldPrintBackgrounds initial=false shouldClearDocumentBackground initial=true textAreasAreResizable initial=false, invalidate=Style -acceleratedCompositingEnabled initial=true, invalidate=Style - -# Debugging feature used for accelerated compositing layers. -showRepaintCounter initial=false, invalidate=Style +acceleratedCompositingEnabled initial=true, invalidate=AcceleratedCompositing shrinksStandaloneImagesToFit initial=true @@ -87,9 +79,11 @@ needsSiteSpecificQuirks initial=false offlineWebApplicationCacheEnabled initial=false usesEncodingDetector initial=false allowScriptsToCloseWindows initial=false -acceleratedFiltersEnabled initial=false +deferredFiltersEnabled initial=true regionBasedColumnsEnabled initial=false +containerCullingEnabled initial=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. @@ -99,29 +93,18 @@ xssAuditorEnabled initial=false unsafePluginPastingEnabled initial=true treatIPAddressAsDomain initial=false -acceleratedCompositingFor3DTransformsEnabled initial=true -acceleratedCompositingForVideoEnabled initial=true -acceleratedCompositingForPluginsEnabled initial=true -acceleratedCompositingForCanvasEnabled initial=true -acceleratedCompositingForAnimationEnabled initial=true -acceleratedCompositingForFiltersEnabled initial=false -acceleratedCompositingForFixedPositionEnabled initial=false -acceleratedCompositingForOverflowScrollEnabled initial=false -acceleratedCompositingForTransitionEnabled initial=false +acceleratedCompositingForVideoEnabled initial=true, invalidate=AcceleratedCompositing +acceleratedCompositingForCanvasEnabled initial=true, invalidate=AcceleratedCompositing +acceleratedCompositingForFiltersEnabled initial=false, invalidate=AcceleratedCompositing +acceleratedCompositingForFixedPositionEnabled initial=false, invalidate=AcceleratedCompositing +acceleratedCompositingForOverflowScrollEnabled initial=false, invalidate=AcceleratedCompositing acceleratedCompositingForFixedRootBackgroundEnabled initial=false - -forceCompositingMode initial=false - -# Works only in conjunction with forceCompositingMode. -# crbug.com/304900 tracks removal once enabled on all platforms. -acceleratedCompositingForScrollableFramesEnabled initial=false -compositedScrollingForFramesEnabled initial=false +compositedScrollingForFramesEnabled initial=false, invalidate=AcceleratedCompositing # 3D canvas (WebGL) support. webGLEnabled initial=false webGLErrorsToConsoleEnabled initial=true -privilegedWebGLExtensionsEnabled initial=false accelerated2dCanvasEnabled initial=false antialiased2dCanvasEnabled initial=true accelerated2dCanvasMSAASampleCount type=int, initial=0 @@ -129,21 +112,17 @@ accelerated2dCanvasMSAASampleCount type=int, initial=0 # WebAudio support. webAudioEnabled initial=false -fullScreenEnabled initial=false asynchronousSpellCheckingEnabled initial=false -memoryInfoEnabled initial=false hyperlinkAuditingEnabled initial=false allowDisplayOfInsecureContent initial=true allowRunningOfInsecureContent initial=true +# FIXME: Remove this temporary flag. See crbug.com/366483 for the target +# milestone. +allowConnectingInsecureWebSocket initial=false +mediaControlsOverlayPlayButtonEnabled initial=false mediaPlaybackRequiresUserGesture initial=false -mediaFullscreenRequiresUserGesture initial=true -visualWordMovementEnabled initial=false -shouldDisplaySubtitles initial=false -shouldDisplayCaptions initial=false -shouldDisplayTextDescriptions initial=false -scrollingCoordinatorEnabled initial=false scrollAnimatorEnabled initial=true shouldRespectImageOrientation initial=false @@ -172,17 +151,11 @@ touchAdjustmentEnabled initial=true # A mostly-stable performance optimization. crbug.com/304518 tracks removal. compositorTouchHitTesting initial=true -fixedPositionCreatesStackingContext initial=false syncXHRInDocumentsEnabled initial=true cookieEnabled initial=true -mediaEnabled initial=true +navigateOnDragDrop initial=true DOMPasteAllowed initial=false -threadedHTMLParser initial=false -useThreadedHTMLParserForDataURLs initial=false - -applyPageScaleFactorInCompositor initial=false - allowCustomScrollbarInMainFrame initial=true webSecurityEnabled initial=true @@ -234,8 +207,6 @@ wideViewportQuirkEnabled initial=false # crbug.com/304873 tracks removal once it's been enabled on all platforms. touchEditingEnabled initial=false -experimentalWebSocketEnabled initial=false - # Settings for experimental desktop pinch-zoom support (with semantics # optimized for large screens). Pinch-zoom generally is implemented mainly # outside of blink (in the compositor) and doesn't require any settings. @@ -244,13 +215,10 @@ experimentalWebSocketEnabled initial=false # crbug.com/304869 tracks removal. pinchVirtualViewportEnabled initial=false useSolidColorScrollbars initial=false +pinchOverlayScrollbarThickness type=int, initial=0 mainFrameClipsContent initial=true -# Enable decoration shadow nodes to test password genration feature -# crbug.com/114092. This flag should not be enabled for production. -passwordGenerationDecorationEnabled initial=false - # Presumably used by LayoutTests? Unclear. useWideViewport initial=true, invalidate=ViewportDescription @@ -277,13 +245,31 @@ viewportMetaEnabled initial=false dnsPrefetchingEnabled initial=false, invalidate=DNSPrefetching -touchEventEmulationEnabled initial=false - # FIXME: This is a temporary flag and should be removed once # accelerated overflow scroll is ready (crbug.com/254111). -compositorDrivenAcceleratedScrollingEnabled initial=false +compositorDrivenAcceleratedScrollingEnabled initial=false, invalidate=AcceleratedCompositing # FIXME: This is a temporary flag and should be removed # when squashing is ready. (crbug.com/261605) layerSquashingEnabled initial=false + +# Clients that execute script should call ScriptController::canExecuteScripts() +# instead of this function. ScriptController::canExecuteScripts() checks the +# HTML sandbox, plug-in sandboxing, and other important details. +scriptEnabled initial=false, invalidate=ScriptEnable + +# Compensates for poor text legibility on mobile devices. This value is +# multiplied by the font scale factor when performing text autosizing of +# websites that do not set an explicit viewport description. +deviceScaleAdjustment type=double, initial=1.0, invalidate=TextAutosizing + +# This value indicates the maximum number of bytes a document is allowed +# to transmit in Beacons (via navigator.sendBeacon()) -- Beacons are +# intended to be smaller payloads transmitted as a page is unloading, not +# a general (one-way) network transmission API. +# The spec ( https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/Beacon/Overview.html ) +# does not proscribe an upper limit, but allows for it -- the underlying +# API will return 'false' in that case. +maxBeaconTransmission type=int, initial=16384 + diff --git a/chromium/third_party/WebKit/Source/core/frame/SettingsDelegate.h b/chromium/third_party/WebKit/Source/core/frame/SettingsDelegate.h index 2ea0bf2fe07..9c22ee9be57 100644 --- a/chromium/third_party/WebKit/Source/core/frame/SettingsDelegate.h +++ b/chromium/third_party/WebKit/Source/core/frame/SettingsDelegate.h @@ -56,14 +56,13 @@ public: MultisamplingChange, ImageLoadingChange, TextAutosizingChange, + ScriptEnableChange, + FontFamilyChange, + AcceleratedCompositingChange, }; virtual void settingsChanged(ChangeType) = 0; - // FIXME: This is a hack until the Inspector code can - // be removed from Settings. http://crbug.com/327476 - virtual Page* page() = 0; - protected: OwnPtr<Settings> const m_settings; }; diff --git a/chromium/third_party/WebKit/Source/core/frame/SmartClip.cpp b/chromium/third_party/WebKit/Source/core/frame/SmartClip.cpp index 52f9b03dabd..40c773edf13 100644 --- a/chromium/third_party/WebKit/Source/core/frame/SmartClip.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/SmartClip.cpp @@ -34,10 +34,11 @@ #include "core/dom/ContainerNode.h" #include "core/dom/Document.h" #include "core/dom/NodeTraversal.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "core/frame/FrameView.h" #include "core/html/HTMLFrameOwnerElement.h" #include "core/page/Page.h" +#include "core/rendering/RenderObject.h" #include "wtf/text/StringBuilder.h" namespace WebCore { @@ -69,7 +70,7 @@ static Node* nodeInsideFrame(Node* node) // read/write code in one place! String SmartClipData::toString() { - if (!m_node) + if (m_isEmpty) return emptyString(); const UChar fieldSeparator = 0xFFFE; @@ -89,7 +90,7 @@ String SmartClipData::toString() return result.toString(); } -SmartClip::SmartClip(PassRefPtr<Frame> frame) +SmartClip::SmartClip(PassRefPtr<LocalFrame> frame) : m_frame(frame) { } @@ -108,10 +109,10 @@ SmartClipData SmartClip::dataForRect(const IntRect& cropRect) bestNode = bestNodeInFrame; } - Vector<Node*> hitNodes; + WillBeHeapVector<RawPtrWillBeMember<Node> > hitNodes; collectOverlappingChildNodes(bestNode, resizedCropRect, hitNodes); - if (hitNodes.isEmpty() || hitNodes.size() == bestNode->childNodeCount()) { + if (hitNodes.isEmpty() || hitNodes.size() == bestNode->countChildren()) { hitNodes.clear(); hitNodes.append(bestNode); } @@ -220,8 +221,9 @@ Node* SmartClip::findBestOverlappingNode(Node* rootNode, const IntRect& cropRect // CSS background images but to skip actual backgrounds. bool SmartClip::shouldSkipBackgroundImage(Node* node) { + ASSERT(node); // Apparently we're only interested in background images on spans and divs. - if (!node->hasTagName(HTMLNames::spanTag) && !node->hasTagName(HTMLNames::divTag)) + if (!isHTMLSpanElement(*node) && !isHTMLDivElement(*node)) return true; // This check actually makes a bit of sense. If you're going to sprite an @@ -235,7 +237,7 @@ bool SmartClip::shouldSkipBackgroundImage(Node* node) return false; } -void SmartClip::collectOverlappingChildNodes(Node* parentNode, const IntRect& cropRect, Vector<Node*>& hitNodes) +void SmartClip::collectOverlappingChildNodes(Node* parentNode, const IntRect& cropRect, WillBeHeapVector<RawPtrWillBeMember<Node> >& hitNodes) { if (!parentNode) return; diff --git a/chromium/third_party/WebKit/Source/core/frame/SmartClip.h b/chromium/third_party/WebKit/Source/core/frame/SmartClip.h index 7481b2a3879..21955a2b3ea 100644 --- a/chromium/third_party/WebKit/Source/core/frame/SmartClip.h +++ b/chromium/third_party/WebKit/Source/core/frame/SmartClip.h @@ -32,18 +32,19 @@ #define SmartClip_h #include "core/dom/Node.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" namespace WebCore { class SmartClipData { public: SmartClipData() + : m_isEmpty(true) { } SmartClipData(Node* node, IntRect rect, String string) - : m_node(node) + : m_isEmpty(!node) , m_rect(rect) , m_string(string) { @@ -52,7 +53,7 @@ public: String toString(); private: - RefPtr<Node> m_node; + bool m_isEmpty; IntRect m_rect; String m_string; }; @@ -64,7 +65,7 @@ private: // selection followed by a copy operation. class SmartClip { public: - explicit SmartClip(PassRefPtr<Frame>); + explicit SmartClip(PassRefPtr<LocalFrame>); SmartClipData dataForRect(const IntRect&); @@ -74,11 +75,11 @@ private: Node* minNodeContainsNodes(Node* minNode, Node* newNode); Node* findBestOverlappingNode(Node*, const IntRect& cropRect); bool shouldSkipBackgroundImage(Node*); - void collectOverlappingChildNodes(Node* parentNode, const IntRect& cropRect, Vector<Node*>& overlappingNodeInfoTable); + void collectOverlappingChildNodes(Node* parentNode, const IntRect& cropRect, WillBeHeapVector<RawPtrWillBeMember<Node> >& overlappingNodeInfoTable); IntRect convertRectToWindow(const IntRect& nodeRect); String extractTextFromNode(Node*); - RefPtr<Frame> m_frame; + RefPtr<LocalFrame> m_frame; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.cpp b/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.cpp index e3ffcf819ae..afbf6275677 100644 --- a/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.cpp @@ -34,7 +34,7 @@ SuspendableTimer::SuspendableTimer(ExecutionContext* context) , m_nextFireInterval(0) , m_repeatInterval(0) , m_active(false) -#if !ASSERT_DISABLED +#if ASSERT_ENABLED , m_suspended(false) #endif { @@ -56,7 +56,7 @@ void SuspendableTimer::stop() void SuspendableTimer::suspend() { -#if !ASSERT_DISABLED +#if ASSERT_ENABLED ASSERT(!m_suspended); m_suspended = true; #endif @@ -70,12 +70,13 @@ void SuspendableTimer::suspend() void SuspendableTimer::resume() { -#if !ASSERT_DISABLED +#if ASSERT_ENABLED ASSERT(m_suspended); m_suspended = false; #endif + // FIXME: FROM_HERE is wrong here. if (m_active) - start(m_nextFireInterval, m_repeatInterval); + start(m_nextFireInterval, m_repeatInterval, FROM_HERE); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.h b/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.h index 3981ab7e077..9b92b6372bc 100644 --- a/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.h +++ b/chromium/third_party/WebKit/Source/core/frame/SuspendableTimer.h @@ -38,10 +38,10 @@ public: virtual ~SuspendableTimer(); // ActiveDOMObject - virtual bool hasPendingActivity() const; - virtual void stop(); - virtual void suspend(); - virtual void resume(); + virtual bool hasPendingActivity() const OVERRIDE FINAL; + virtual void stop() OVERRIDE; + virtual void suspend() OVERRIDE FINAL; + virtual void resume() OVERRIDE FINAL; private: virtual void fired() = 0; @@ -49,7 +49,7 @@ private: double m_nextFireInterval; double m_repeatInterval; bool m_active; -#if !ASSERT_DISABLED +#if ASSERT_ENABLED bool m_suspended; #endif }; diff --git a/chromium/third_party/WebKit/Source/core/frame/UseCounter.cpp b/chromium/third_party/WebKit/Source/core/frame/UseCounter.cpp index 667e5f9313d..a0ce4057a5c 100644 --- a/chromium/third_party/WebKit/Source/core/frame/UseCounter.cpp +++ b/chromium/third_party/WebKit/Source/core/frame/UseCounter.cpp @@ -31,15 +31,19 @@ #include "core/css/StyleSheetContents.h" #include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" -#include "core/frame/DOMWindow.h" -#include "core/page/Page.h" -#include "core/page/PageConsole.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" +#include "core/workers/WorkerGlobalScope.h" #include "public/platform/Platform.h" namespace WebCore { static int totalPagesMeasuredCSSSampleId() { return 1; } +int UseCounter::m_muteCount = 0; + // FIXME : This mapping should be autogenerated. This function should // be moved to a separate file and a script run at build time // to detect new values in CSSPropertyID and add them to the @@ -64,7 +68,7 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyWebkitFontFeatureSettings: return 12; case CSSPropertyFontKerning: return 13; case CSSPropertyWebkitFontSmoothing: return 14; - case CSSPropertyWebkitFontVariantLigatures: return 15; + case CSSPropertyFontVariantLigatures: return 15; case CSSPropertyWebkitLocale: return 16; case CSSPropertyWebkitTextOrientation: return 17; case CSSPropertyWebkitWritingMode: return 18; @@ -262,13 +266,13 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyWebkitBoxPack: return 210; case CSSPropertyWebkitBoxReflect: return 211; case CSSPropertyWebkitBoxShadow: return 212; - case CSSPropertyWebkitColumnAxis: return 214; + // CSSPropertyWebkitColumnAxis was 214 case CSSPropertyWebkitColumnBreakAfter: return 215; case CSSPropertyWebkitColumnBreakBefore: return 216; case CSSPropertyWebkitColumnBreakInside: return 217; case CSSPropertyWebkitColumnCount: return 218; case CSSPropertyWebkitColumnGap: return 219; - case CSSPropertyWebkitColumnProgression: return 220; + // CSSPropertyWebkitColumnProgression was 220 case CSSPropertyWebkitColumnRule: return 221; case CSSPropertyWebkitColumnRuleColor: return 222; case CSSPropertyWebkitColumnRuleStyle: return 223; @@ -294,8 +298,8 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyFlexWrap: return 239; case CSSPropertyJustifyContent: return 240; case CSSPropertyWebkitFontSizeDelta: return 241; - case CSSPropertyGridDefinitionColumns: return 242; - case CSSPropertyGridDefinitionRows: return 243; + case CSSPropertyGridTemplateColumns: return 242; + case CSSPropertyGridTemplateRows: return 243; case CSSPropertyGridColumnStart: return 244; case CSSPropertyGridColumnEnd: return 245; case CSSPropertyGridRowStart: return 246; @@ -306,11 +310,11 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyWebkitHighlight: return 251; case CSSPropertyWebkitHyphenateCharacter: return 252; case CSSPropertyWebkitLineBoxContain: return 257; - case CSSPropertyWebkitLineAlign: return 258; + // case CSSPropertyWebkitLineAlign: return 258; case CSSPropertyWebkitLineBreak: return 259; case CSSPropertyWebkitLineClamp: return 260; - case CSSPropertyWebkitLineGrid: return 261; - case CSSPropertyWebkitLineSnap: return 262; + // case CSSPropertyWebkitLineGrid: return 261; + // case CSSPropertyWebkitLineSnap: return 262; case CSSPropertyWebkitLogicalWidth: return 263; case CSSPropertyWebkitLogicalHeight: return 264; case CSSPropertyWebkitMarginAfterCollapse: return 265; @@ -384,16 +388,16 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyWebkitUserDrag: return 337; case CSSPropertyWebkitUserModify: return 338; case CSSPropertyWebkitUserSelect: return 339; - case CSSPropertyWebkitFlowInto: return 340; - case CSSPropertyWebkitFlowFrom: return 341; - case CSSPropertyWebkitRegionFragment: return 342; - case CSSPropertyWebkitRegionBreakAfter: return 343; - case CSSPropertyWebkitRegionBreakBefore: return 344; - case CSSPropertyWebkitRegionBreakInside: return 345; - case CSSPropertyShapeInside: return 346; + // case CSSPropertyWebkitFlowInto: return 340; + // case CSSPropertyWebkitFlowFrom: return 341; + // case CSSPropertyWebkitRegionFragment: return 342; + // case CSSPropertyWebkitRegionBreakAfter: return 343; + // case CSSPropertyWebkitRegionBreakBefore: return 344; + // case CSSPropertyWebkitRegionBreakInside: return 345; + // case CSSPropertyShapeInside: return 346; case CSSPropertyShapeOutside: return 347; case CSSPropertyShapeMargin: return 348; - case CSSPropertyShapePadding: return 349; + // case CSSPropertyShapePadding: return 349; case CSSPropertyWebkitWrapFlow: return 350; case CSSPropertyWebkitWrapThrough: return 351; // CSSPropertyWebkitWrap was 352. @@ -415,7 +419,7 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyStopOpacity: return 364; case CSSPropertyColorInterpolation: return 365; case CSSPropertyColorInterpolationFilters: return 366; - case CSSPropertyColorProfile: return 367; + // case CSSPropertyColorProfile: return 367; case CSSPropertyColorRendering: return 368; case CSSPropertyFill: return 369; case CSSPropertyFillOpacity: return 370; @@ -439,7 +443,7 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyDominantBaseline: return 388; case CSSPropertyGlyphOrientationHorizontal: return 389; case CSSPropertyGlyphOrientationVertical: return 390; - case CSSPropertyKerning: return 391; + // CSSPropertyKerning has been removed, was return 391; case CSSPropertyTextAnchor: return 392; case CSSPropertyVectorEffect: return 393; case CSSPropertyWritingMode: return 394; @@ -475,7 +479,7 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyMixBlendMode: return 420; case CSSPropertyTouchAction: return 421; case CSSPropertyGridArea: return 422; - case CSSPropertyGridTemplate: return 423; + case CSSPropertyGridTemplateAreas: return 423; case CSSPropertyAnimation: return 424; case CSSPropertyAnimationDelay: return 425; case CSSPropertyAnimationDirection: return 426; @@ -495,9 +499,24 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyColumnFill: return 440; case CSSPropertyTextJustify: return 441; case CSSPropertyTouchActionDelay: return 442; - - // Add new features above this line (don't change the assigned numbers of the existing - // items) and update maximumCSSSampleId() with the new maximum value. + case CSSPropertyJustifySelf: return 443; + case CSSPropertyScrollBehavior: return 444; + case CSSPropertyWillChange: return 445; + case CSSPropertyTransform: return 446; + case CSSPropertyTransformOrigin: return 447; + case CSSPropertyTransformStyle: return 448; + case CSSPropertyPerspective: return 449; + case CSSPropertyPerspectiveOrigin: return 450; + case CSSPropertyBackfaceVisibility: return 451; + case CSSPropertyGridTemplate: return 452; + case CSSPropertyGrid: return 453; + case CSSPropertyAll: return 454; + + // 1. Add new features above this line (don't change the assigned numbers of the existing + // items). + // 2. Update maximumCSSSampleId() with the new maximum value. + // 3. Run the update_use_counter_css.py script in + // chromium/src/tools/metrics/histograms to update the UMA histogram names. // Internal properties should not be counted. case CSSPropertyInternalMarqueeDirection: @@ -506,7 +525,6 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) case CSSPropertyInternalMarqueeSpeed: case CSSPropertyInternalMarqueeStyle: case CSSPropertyInvalid: - case CSSPropertyVariable: ASSERT_NOT_REACHED(); return 0; } @@ -515,7 +533,17 @@ int UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(int id) return 0; } -static int maximumCSSSampleId() { return 442; } +static int maximumCSSSampleId() { return 454; } + +void UseCounter::muteForInspector() +{ + UseCounter::m_muteCount++; +} + +void UseCounter::unmuteForInspector() +{ + UseCounter::m_muteCount--; +} UseCounter::UseCounter() { @@ -569,30 +597,39 @@ void UseCounter::didCommitLoad() void UseCounter::count(const Document& document, Feature feature) { - Page* page = document.page(); - if (!page) + FrameHost* host = document.frameHost(); + if (!host) return; - ASSERT(page->useCounter().deprecationMessage(feature).isEmpty()); - page->useCounter().recordMeasurement(feature); + ASSERT(host->useCounter().deprecationMessage(feature).isEmpty()); + host->useCounter().recordMeasurement(feature); } -void UseCounter::count(const DOMWindow* domWindow, Feature feature) +void UseCounter::count(const ExecutionContext* context, Feature feature) { - ASSERT(domWindow); - if (!domWindow->document()) + if (!context) + return; + if (context->isDocument()) { + count(*toDocument(context), feature); return; - count(*domWindow->document(), feature); + } + if (context->isWorkerGlobalScope()) + toWorkerGlobalScope(context)->countFeature(feature); } void UseCounter::countDeprecation(ExecutionContext* context, Feature feature) { - if (!context || !context->isDocument()) + if (!context) + return; + if (context->isDocument()) { + UseCounter::countDeprecation(*toDocument(context), feature); return; - UseCounter::countDeprecation(*toDocument(context), feature); + } + if (context->isWorkerGlobalScope()) + toWorkerGlobalScope(context)->countDeprecation(feature); } -void UseCounter::countDeprecation(const DOMWindow* window, Feature feature) +void UseCounter::countDeprecation(const LocalDOMWindow* window, Feature feature) { if (!window || !window->document()) return; @@ -601,86 +638,115 @@ void UseCounter::countDeprecation(const DOMWindow* window, Feature feature) void UseCounter::countDeprecation(const Document& document, Feature feature) { - Page* page = document.page(); - if (!page) + FrameHost* host = document.frameHost(); + LocalFrame* frame = document.frame(); + if (!host || !frame) return; - if (page->useCounter().recordMeasurement(feature)) { - ASSERT(!page->useCounter().deprecationMessage(feature).isEmpty()); - page->console().addMessage(DeprecationMessageSource, WarningMessageLevel, page->useCounter().deprecationMessage(feature)); + if (host->useCounter().recordMeasurement(feature)) { + ASSERT(!host->useCounter().deprecationMessage(feature).isEmpty()); + frame->console().addMessage(DeprecationMessageSource, WarningMessageLevel, host->useCounter().deprecationMessage(feature)); } } String UseCounter::deprecationMessage(Feature feature) { switch (feature) { - // Content Security Policy - case PrefixedContentSecurityPolicy: - case PrefixedContentSecurityPolicyReportOnly: - return "The 'X-WebKit-CSP' headers are no longer supported. Please consider using the canonical 'Content-Security-Policy' header instead."; - - // HTMLMediaElement - case PrefixedMediaGenerateKeyRequest: - return "'HTMLMediaElement.webkitGenerateKeyRequest()' is deprecated. Please use 'MediaKeys.createSession()' instead."; - // Quota - case StorageInfo: + case PrefixedStorageInfo: return "'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead."; - // Performance - case PrefixedPerformanceTimeline: - return "'window.performance.webkitGet*' methods have been deprecated. Please use the unprefixed 'performance.get*' methods instead."; - case PrefixedUserTiming: - return "'window.performance.webkit*' methods have been deprecated. Please use the unprefixed 'window.performance.*' methods instead."; + // Keyboard Event (DOM Level 3) + case KeyboardEventKeyLocation: + return "'KeyboardEvent.keyLocation' is deprecated. Please use 'KeyboardEvent.location' instead."; + + case ConsoleMarkTimeline: + return "console.markTimeline is deprecated. Please use the console.timeStamp instead."; + + case FileError: + return "FileError is deprecated. Please use the 'name' or 'message' attributes of DOMError rather than 'code'."; + + case ShowModalDialog: + return "showModalDialog is deprecated. Please use window.open and postMessage instead."; - // Web Audio - case WebAudioLooping: - return "AudioBufferSourceNode 'looping' attribute is deprecated. Use 'loop' instead."; + case CSSStyleSheetInsertRuleOptionalArg: + return "Calling CSSStyleSheet.insertRule() with one argument is deprecated. Please pass the index argument as well: insertRule(x, 0)."; - case DocumentClear: - return "document.clear() is deprecated. This method doesn't do anything."; + case PrefixedVideoSupportsFullscreen: + return "'HTMLVideoElement.webkitSupportsFullscreen' is deprecated. Its value is true if the video is loaded."; - case PrefixedTransitionMediaFeature: - return "The '(-webkit-transition)' media query feature is deprecated; please consider using the more exact conditional \"@supports('(transition-property: prop_name)')\" instead."; + case PrefixedVideoDisplayingFullscreen: + return "'HTMLVideoElement.webkitDisplayingFullscreen' is deprecated. Please use the 'fullscreenchange' and 'webkitfullscreenchange' events instead."; - // Web Components - case HTMLShadowElementOlderShadowRoot: - return "HTMLShadowElement.olderShadowRoot is deprecated."; + case PrefixedVideoEnterFullscreen: + return "'HTMLVideoElement.webkitEnterFullscreen()' is deprecated. Please use 'Element.requestFullscreen()' and 'Element.webkitRequestFullscreen()' instead."; - // HTML Media Capture - case CaptureAttributeAsEnum: - return "Using the 'capture' attribute as an enum is deprecated. Please use it as a boolean and specify the media types that should be accepted in the 'accept' attribute."; + case PrefixedVideoExitFullscreen: + return "'HTMLVideoElement.webkitExitFullscreen()' is deprecated. Please use 'Document.exitFullscreen()' and 'Document.webkitExitFullscreen()' instead."; - // Keyboard Event (DOM Level 3) - case KeyboardEventKeyLocation: - return "'KeyboardEvent.keyLocation'' is deprecated. Please use 'KeyboardEvent.location' instead."; + case PrefixedVideoEnterFullScreen: + return "'HTMLVideoElement.webkitEnterFullScreen()' is deprecated. Please use 'Element.requestFullscreen()' and 'Element.webkitRequestFullscreen()' instead."; - case CaptureEvents: - return "captureEvents() is deprecated. This method doesn't do anything."; + case PrefixedVideoExitFullScreen: + return "'HTMLVideoElement.webkitExitFullScreen()' is deprecated. Please use 'Document.exitFullscreen()' and 'Document.webkitExitFullscreen()' instead."; - case ReleaseEvents: - return "releaseEvents() is deprecated. This method doesn't do anything."; + case MediaErrorEncrypted: + return "'MediaError.MEDIA_ERR_ENCRYPTED' is deprecated. This error code is never used."; - case ConsoleMarkTimeline: - return "console.markTimeline is deprecated. Please use the console.timeStamp instead."; + case PrefixedGamepad: + return "'navigator.webkitGetGamepads' is deprecated. Please use 'navigator.getGamepads' instead."; - case FileError: - return "FileError is deprecated. Please use the 'name' or 'message' attributes of DOMError rather than 'code'."; + case PrefixedRequestAnimationFrame: + return "'webkitRequestAnimationFrame' is vendor-specific. Please use the standard 'requestAnimationFrame' instead."; - case EventReturnValue: - return "event.returnValue is deprecated. Please use the standard event.preventDefault() instead."; + case PrefixedCancelAnimationFrame: + return "'webkitCancelAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead."; - case ScrollTopBodyNotQuirksMode: - return "body.scrollTop is deprecated in strict mode. Please use 'documentElement.scrollTop' if in strict mode and 'body.scrollTop' only if in quirks mode."; + case PrefixedCancelRequestAnimationFrame: + return "'webkitCancelRequestAnimationFrame' is vendor-specific. Please use the standard 'cancelAnimationFrame' instead."; - case ScrollLeftBodyNotQuirksMode: - return "body.scrollLeft is deprecated in strict mode. Please use 'documentElement.scrollLeft' if in strict mode and 'body.scrollLeft' only if in quirks mode."; + case DocumentCreateAttributeNS: + return "'Document.createAttributeNS' is deprecated and has been removed from DOM4 (http://w3.org/tr/dom)."; - case ShowModalDialog: - return "Chromium is considering deprecating showModalDialog. Please use window.open and postMessage instead."; + case AttributeOwnerElement: + return "'Attr.ownerElement' is deprecated and has been removed from DOM4 (http://w3.org/tr/dom)."; - case CSSStyleSheetInsertRuleOptionalArg: - return "Calling CSSStyleSheet.insertRule() with one argument is deprecated. Please pass the index argument as well: insertRule(x, 0)."; + case ElementSetAttributeNodeNS: + return "'Element.setAttributeNodeNS' is deprecated and has been removed from DOM4 (http://w3.org/tr/dom)."; + + case NodeIteratorDetach: + return "'NodeIterator.detach' is now a no-op, as per DOM (http://dom.spec.whatwg.org/#dom-nodeiterator-detach)."; + + case AttrNodeValue: + return "'Attr.nodeValue' is deprecated. Please use 'value' instead."; + + case AttrTextContent: + return "'Attr.textContent' is deprecated. Please use 'value' instead."; + + case NodeIteratorExpandEntityReferences: + return "'NodeIterator.expandEntityReferences' is deprecated and has been removed from DOM. It always returns false."; + + case TreeWalkerExpandEntityReferences: + return "'TreeWalker.expandEntityReferences' is deprecated and has been removed from DOM. It always returns false."; + + case RangeDetach: + return "'Range.detach' is now a no-op, as per DOM (http://dom.spec.whatwg.org/#dom-range-detach)."; + + case DocumentImportNodeOptionalArgument: + return "The behavior of importNode() with no boolean argument is about to change from doing a deep clone to doing a shallow clone. " + "Make sure to pass an explicit boolean argument to keep your current behavior."; + + case OverflowChangedEvent: + return "The 'overflowchanged' event is deprecated and may be removed. Please do not use it."; + + case HTMLHeadElementProfile: + return "'HTMLHeadElement.profile' is deprecated. The reflected attribute has no effect."; + + case ElementSetPrefix: + return "Setting 'Element.prefix' is deprecated, as it is read-only per DOM (http://dom.spec.whatwg.org/#element)."; + + case SyncXHRWithCredentials: + return "Setting 'XMLHttpRequest.withCredentials' for synchronous requests is deprecated."; // Features that aren't deprecated don't have a deprecation message. default: @@ -708,8 +774,8 @@ void UseCounter::count(Feature feature) UseCounter* UseCounter::getFrom(const Document* document) { - if (document && document->page()) - return &document->page()->useCounter(); + if (document && document->frameHost()) + return &document->frameHost()->useCounter(); return 0; } diff --git a/chromium/third_party/WebKit/Source/core/frame/UseCounter.h b/chromium/third_party/WebKit/Source/core/frame/UseCounter.h index 4f0c2fde527..9e9abca6d1d 100644 --- a/chromium/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/chromium/third_party/WebKit/Source/core/frame/UseCounter.h @@ -26,7 +26,7 @@ #ifndef UseCounter_h #define UseCounter_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" #include "wtf/BitVector.h" #include "wtf/Noncopyable.h" #include "wtf/OwnPtr.h" @@ -36,7 +36,7 @@ namespace WebCore { class CSSStyleSheet; -class DOMWindow; +class LocalDOMWindow; class Document; class ExecutionContext; class StyleSheetContents; @@ -59,245 +59,442 @@ public: ~UseCounter(); enum Feature { - PageDestruction, - LegacyNotifications, - MultipartMainResource, - PrefixedIndexedDB, - WorkerStart, - SharedWorkerStart, - LegacyWebAudio, - WebAudioStart, - PrefixedContentSecurityPolicy, - UnprefixedIndexedDB, - OpenWebDatabase, - UnusedSlot01, // Prior to 7/2013, we used this slot for LegacyHTMLNotifications. - LegacyTextNotifications, - UnprefixedRequestAnimationFrame, - PrefixedRequestAnimationFrame, - ContentSecurityPolicy, - ContentSecurityPolicyReportOnly, - PrefixedContentSecurityPolicyReportOnly, - PrefixedTransitionEndEvent, - UnprefixedTransitionEndEvent, - PrefixedAndUnprefixedTransitionEndEvent, - AutoFocusAttribute, - UnusedSlot02, // Prior to 4/2013, we used this slot for AutoSaveAttribute. - DataListElement, - FormAttribute, - IncrementalAttribute, - InputTypeColor, - InputTypeDate, - InputTypeDateTime, - InputTypeDateTimeFallback, - InputTypeDateTimeLocal, - InputTypeEmail, - InputTypeMonth, - InputTypeNumber, - InputTypeRange, - InputTypeSearch, - InputTypeTel, - InputTypeTime, - InputTypeURL, - InputTypeWeek, - InputTypeWeekFallback, - ListAttribute, - MaxAttribute, - MinAttribute, - PatternAttribute, - PlaceholderAttribute, - PrecisionAttribute, - PrefixedDirectoryAttribute, - PrefixedSpeechAttribute, - RequiredAttribute, - ResultsAttribute, - StepAttribute, - PageVisits, - HTMLMarqueeElement, - UnusedSlot03, // Removed, was tracking overflow: -webkit-marquee. - Reflection, - CursorVisibility, // Removed, was -webkit-cursor-visibility. - StorageInfo, - XFrameOptions, - XFrameOptionsSameOrigin, - XFrameOptionsSameOriginWithBadAncestorChain, - DeprecatedFlexboxWebContent, - DeprecatedFlexboxChrome, - DeprecatedFlexboxChromeExtension, - UnusedSlot04, - UnprefixedPerformanceTimeline, - PrefixedPerformanceTimeline, - UnprefixedUserTiming, - PrefixedUserTiming, - WindowEvent, - ContentSecurityPolicyWithBaseElement, - PrefixedMediaAddKey, - PrefixedMediaGenerateKeyRequest, - WebAudioLooping, - DocumentClear, - PrefixedTransitionMediaFeature, - SVGFontElement, - XMLDocument, - XSLProcessingInstruction, - XSLTProcessor, - SVGSwitchElement, - UnusedSlot05, // Removed, was document.webkitRegister - HTMLShadowElementOlderShadowRoot, - DocumentAll, - FormElement, - DemotedFormElement, - CaptureAttributeAsEnum, - ShadowDOMPrefixedPseudo, - ShadowDOMPrefixedCreateShadowRoot, - ShadowDOMPrefixedShadowRoot, - SVGAnimationElement, - KeyboardEventKeyLocation, - CaptureEvents, - ReleaseEvents, - CSSDisplayRunIn, - CSSDisplayCompact, - LineClamp, - SubFrameBeforeUnloadRegistered, - SubFrameBeforeUnloadFired, - CSSPseudoElementPrefixedDistributed, - TextReplaceWholeText, - PrefixedShadowRootConstructor, - ConsoleMarkTimeline, - CSSPseudoElementUserAgentCustomPseudo, - DocumentTypeEntities, // Removed from DOM4. - DocumentTypeInternalSubset, // Removed from DOM4. - DocumentTypeNotations, // Removed from DOM4. - ElementGetAttributeNode, // Removed from DOM4. - ElementSetAttributeNode, // Removed from DOM4. - ElementRemoveAttributeNode, // Removed from DOM4. - ElementGetAttributeNodeNS, // Removed from DOM4. - DocumentCreateAttribute, // Removed from DOM4. - DocumentCreateAttributeNS, // Removed from DOM4. - DocumentCreateCDATASection, // Removed from DOM4. - DocumentInputEncoding, // Removed from DOM4. - DocumentXMLEncoding, // Removed from DOM4. - DocumentXMLStandalone, // Removed from DOM4. - DocumentXMLVersion, // Removed from DOM4. - NodeIsSameNode, // Removed from DOM4. - NodeIsSupported, // Removed from DOM4. - NodeNamespaceURI, // Removed from DOM4. - NodePrefix, // Removed from DOM4. - NodeLocalName, // Removed from DOM4. - NavigatorProductSub, - NavigatorVendor, - NavigatorVendorSub, - FileError, - DocumentCharset, // Documented as IE extensions, from KHTML days. - PrefixedAnimationEndEvent, - UnprefixedAnimationEndEvent, - PrefixedAndUnprefixedAnimationEndEvent, - PrefixedAnimationStartEvent, - UnprefixedAnimationStartEvent, - PrefixedAndUnprefixedAnimationStartEvent, - PrefixedAnimationIterationEvent, - UnprefixedAnimationIterationEvent, - PrefixedAndUnprefixedAnimationIterationEvent, - EventReturnValue, // Legacy IE extension. - SVGSVGElement, - SVGAnimateColorElement, - InsertAdjacentText, - InsertAdjacentElement, - HasAttributes, // Removed from DOM4. - DOMSubtreeModifiedEvent, - DOMNodeInsertedEvent, - DOMNodeRemovedEvent, - DOMNodeRemovedFromDocumentEvent, - DOMNodeInsertedIntoDocumentEvent, - DOMCharacterDataModifiedEvent, - DocumentAllTags, - DocumentAllLegacyCall, - HTMLAppletElementLegacyCall, - HTMLEmbedElementLegacyCall, - HTMLObjectElementLegacyCall, - BeforeLoadEvent, - GetMatchedCSSRules, - SVGFontInCSS, - ScrollTopBodyNotQuirksMode, - ScrollLeftBodyNotQuirksMode, - AttributeIsId, // Removed in DOM4. - AttributeOwnerElement, // Removed in DOM4. - AttributeSetPrefix, // Attribute prefix is readonly in DOM4. - AttributeSpecified, // Removed in DOM4. - BeforeLoadEventInIsolatedWorld, - PrefixedAudioDecodedByteCount, - PrefixedVideoDecodedByteCount, - PrefixedVideoSupportsFullscreen, - PrefixedVideoDisplayingFullscreen, - PrefixedVideoEnterFullscreen, - PrefixedVideoExitFullscreen, - PrefixedVideoEnterFullScreen, - PrefixedVideoExitFullScreen, - PrefixedVideoDecodedFrameCount, - PrefixedVideoDroppedFrameCount, - SourceElementCandidate, - SourceElementNonMatchingMedia, - PrefixedElementRequestFullscreen, - PrefixedElementRequestFullScreen, - BarPropLocationbar, - BarPropMenubar, - BarPropPersonalbar, - BarPropScrollbars, - BarPropStatusbar, - BarPropToolbar, - InputTypeEmailMultiple, - InputTypeEmailMaxLength, - InputTypeEmailMultipleMaxLength, - TextTrackCueConstructor, - CSSStyleDeclarationPropertyName, // Removed in CSSOM. - CSSStyleDeclarationFloatPropertyName, // Pending removal in CSSOM. - InputTypeText, - InputTypeTextMaxLength, - InputTypePassword, - InputTypePasswordMaxLength, - SVGInstanceRoot, - ShowModalDialog, - PrefixedPageVisibility, - HTMLFrameElementLocation, - CSSStyleSheetInsertRuleOptionalArg, // Inconsistent with the specification and other browsers. - CSSWebkitRegionAtRule, // @region rule changed to ::region() - DocumentBeforeUnloadRegistered, - DocumentBeforeUnloadFired, - DocumentUnloadRegistered, - DocumentUnloadFired, - SVGLocatableNearestViewportElement, - SVGLocatableFarthestViewportElement, - IsIndexElement, - HTMLHeadElementProfile, - OverflowChangedEvent, - SVGPointMatrixTransform, - HTMLHtmlElementManifest, - DOMFocusInOutEvent, - FileGetLastModifiedDate, - HTMLElementInnerText, - HTMLElementOuterText, - ReplaceDocumentViaJavaScriptURL, - ElementSetAttributeNodeNS, // Removed from DOM4. - ElementPrefixedMatchesSelector, - DOMImplementationCreateCSSStyleSheet, - CSSStyleSheetRules, - CSSStyleSheetAddRule, - CSSStyleSheetRemoveRule, + // Do not change assigned numbers of existing items: add new features + // to the end of the list. + PageDestruction = 0, + PrefixedIndexedDB = 3, + WorkerStart = 4, + SharedWorkerStart = 5, + UnprefixedIndexedDB = 9, + OpenWebDatabase = 10, + UnprefixedRequestAnimationFrame = 13, + PrefixedRequestAnimationFrame = 14, + ContentSecurityPolicy = 15, + ContentSecurityPolicyReportOnly = 16, + PrefixedTransitionEndEvent = 18, + UnprefixedTransitionEndEvent = 19, + PrefixedAndUnprefixedTransitionEndEvent = 20, + AutoFocusAttribute = 21, + DataListElement = 23, + FormAttribute = 24, + IncrementalAttribute = 25, + InputTypeColor = 26, + InputTypeDate = 27, + InputTypeDateTimeFallback = 29, + InputTypeDateTimeLocal = 30, + InputTypeEmail = 31, + InputTypeMonth = 32, + InputTypeNumber = 33, + InputTypeRange = 34, + InputTypeSearch = 35, + InputTypeTel = 36, + InputTypeTime = 37, + InputTypeURL = 38, + InputTypeWeek = 39, + InputTypeWeekFallback = 40, + ListAttribute = 41, + MaxAttribute = 42, + MinAttribute = 43, + PatternAttribute = 44, + PlaceholderAttribute = 45, + PrefixedDirectoryAttribute = 47, + RequiredAttribute = 49, + ResultsAttribute = 50, + StepAttribute = 51, + PageVisits = 52, + HTMLMarqueeElement = 53, + Reflection = 55, + PrefixedStorageInfo = 57, + XFrameOptions = 58, + XFrameOptionsSameOrigin = 59, + XFrameOptionsSameOriginWithBadAncestorChain = 60, + DeprecatedFlexboxWebContent = 61, + DeprecatedFlexboxChrome = 62, + DeprecatedFlexboxChromeExtension = 63, + UnprefixedPerformanceTimeline = 65, + UnprefixedUserTiming = 67, + WindowEvent = 69, + ContentSecurityPolicyWithBaseElement = 70, + PrefixedMediaAddKey = 71, + PrefixedMediaGenerateKeyRequest = 72, + DocumentClear = 74, + SVGFontElement = 76, + XMLDocument = 77, + XSLProcessingInstruction = 78, + XSLTProcessor = 79, + SVGSwitchElement = 80, + DocumentAll = 83, + FormElement = 84, + DemotedFormElement = 85, + SVGAnimationElement = 90, + KeyboardEventKeyLocation = 91, + LineClamp = 96, + SubFrameBeforeUnloadRegistered = 97, + SubFrameBeforeUnloadFired = 98, + TextReplaceWholeText = 100, + ConsoleMarkTimeline = 102, + CSSPseudoElementUserAgentCustomPseudo = 103, + ElementGetAttributeNode = 107, // Removed from DOM4. + ElementSetAttributeNode = 108, // Removed from DOM4. + ElementRemoveAttributeNode = 109, // Removed from DOM4. + ElementGetAttributeNodeNS = 110, // Removed from DOM4. + DocumentCreateAttribute = 111, // Removed from DOM4. + DocumentCreateAttributeNS = 112, // Removed from DOM4. + DocumentCreateCDATASection = 113, // Removed from DOM4. + DocumentInputEncoding = 114, // Removed from DOM4. + DocumentXMLEncoding = 115, // Removed from DOM4. + DocumentXMLStandalone = 116, // Removed from DOM4. + DocumentXMLVersion = 117, // Removed from DOM4. + NodeIsSameNode = 118, // Removed from DOM4. + NodeNamespaceURI = 120, // Removed from DOM4. + NodeLocalName = 122, // Removed from DOM4. + NavigatorProductSub = 123, + NavigatorVendor = 124, + NavigatorVendorSub = 125, + FileError = 126, + DocumentCharset = 127, // Documented as IE extensions = 0, from KHTML days. + PrefixedAnimationEndEvent = 128, + UnprefixedAnimationEndEvent = 129, + PrefixedAndUnprefixedAnimationEndEvent = 130, + PrefixedAnimationStartEvent = 131, + UnprefixedAnimationStartEvent = 132, + PrefixedAndUnprefixedAnimationStartEvent = 133, + PrefixedAnimationIterationEvent = 134, + UnprefixedAnimationIterationEvent = 135, + PrefixedAndUnprefixedAnimationIterationEvent = 136, + EventReturnValue = 137, // Legacy IE extension. + SVGSVGElement = 138, + InsertAdjacentText = 140, + InsertAdjacentElement = 141, + HasAttributes = 142, // Removed from DOM4. + DOMSubtreeModifiedEvent = 143, + DOMNodeInsertedEvent = 144, + DOMNodeRemovedEvent = 145, + DOMNodeRemovedFromDocumentEvent = 146, + DOMNodeInsertedIntoDocumentEvent = 147, + DOMCharacterDataModifiedEvent = 148, + DocumentAllLegacyCall = 150, + HTMLAppletElementLegacyCall = 151, + HTMLEmbedElementLegacyCall = 152, + HTMLObjectElementLegacyCall = 153, + GetMatchedCSSRules = 155, + SVGFontInCSS = 156, + AttributeOwnerElement = 160, // Removed in DOM4. + AttributeSpecified = 162, // Removed in DOM4. + PrefixedAudioDecodedByteCount = 164, + PrefixedVideoDecodedByteCount = 165, + PrefixedVideoSupportsFullscreen = 166, + PrefixedVideoDisplayingFullscreen = 167, + PrefixedVideoEnterFullscreen = 168, + PrefixedVideoExitFullscreen = 169, + PrefixedVideoEnterFullScreen = 170, + PrefixedVideoExitFullScreen = 171, + PrefixedVideoDecodedFrameCount = 172, + PrefixedVideoDroppedFrameCount = 173, + PrefixedElementRequestFullscreen = 176, + PrefixedElementRequestFullScreen = 177, + BarPropLocationbar = 178, + BarPropMenubar = 179, + BarPropPersonalbar = 180, + BarPropScrollbars = 181, + BarPropStatusbar = 182, + BarPropToolbar = 183, + InputTypeEmailMultiple = 184, + InputTypeEmailMaxLength = 185, + InputTypeEmailMultipleMaxLength = 186, + InputTypeText = 190, + InputTypeTextMaxLength = 191, + InputTypePassword = 192, + InputTypePasswordMaxLength = 193, + SVGInstanceRoot = 194, + ShowModalDialog = 195, + PrefixedPageVisibility = 196, + CSSStyleSheetInsertRuleOptionalArg = 198, // Inconsistent with the specification and other browsers. + DocumentBeforeUnloadRegistered = 200, + DocumentBeforeUnloadFired = 201, + DocumentUnloadRegistered = 202, + DocumentUnloadFired = 203, + SVGLocatableNearestViewportElement = 204, + SVGLocatableFarthestViewportElement = 205, + HTMLHeadElementProfile = 207, + OverflowChangedEvent = 208, + SVGPointMatrixTransform = 209, + DOMFocusInOutEvent = 211, + FileGetLastModifiedDate = 212, + HTMLElementInnerText = 213, + HTMLElementOuterText = 214, + ReplaceDocumentViaJavaScriptURL = 215, + ElementSetAttributeNodeNS = 216, // Removed from DOM4. + ElementPrefixedMatchesSelector = 217, + CSSStyleSheetRules = 219, + CSSStyleSheetAddRule = 220, + CSSStyleSheetRemoveRule = 221, + // The above items are available in M33 branch. + + InitMessageEvent = 222, + ElementSetPrefix = 224, // Element.prefix is readonly in DOM4. + CSSStyleDeclarationGetPropertyCSSValue = 225, + PrefixedMediaCancelKeyRequest = 229, + DOMImplementationHasFeature = 230, + DOMImplementationHasFeatureReturnFalse = 231, + CanPlayTypeKeySystem = 232, + PrefixedDevicePixelRatioMediaFeature = 233, + PrefixedMaxDevicePixelRatioMediaFeature = 234, + PrefixedMinDevicePixelRatioMediaFeature = 235, + PrefixedTransform3dMediaFeature = 237, + PrefixedStorageQuota = 240, + ContentSecurityPolicyReportOnlyInMeta = 241, + ResetReferrerPolicy = 243, + CaseInsensitiveAttrSelectorMatch = 244, // Case-insensitivity dropped from specification. + FormNameAccessForImageElement = 246, + FormNameAccessForPastNamesMap = 247, + FormAssociationByParser = 248, + SVGSVGElementInDocument = 250, + SVGDocumentRootElement = 251, + MediaErrorEncrypted = 253, + EventSourceURL = 254, + WebSocketURL = 255, + WorkerSubjectToCSP = 257, + WorkerAllowedByChildBlockedByScript = 258, + DeprecatedWebKitGradient = 260, + DeprecatedWebKitLinearGradient = 261, + DeprecatedWebKitRepeatingLinearGradient = 262, + DeprecatedWebKitRadialGradient = 263, + DeprecatedWebKitRepeatingRadialGradient = 264, + PrefixedImageSmoothingEnabled = 267, + UnprefixedImageSmoothingEnabled = 268, + PromiseConstructor = 270, + PromiseCast = 271, + PromiseReject = 272, + PromiseResolve = 273, + // The above items are available in M34 branch. + + TextAutosizing = 274, + TextAutosizingLayout = 275, + HTMLAnchorElementPingAttribute = 276, + InsertAdjacentHTML = 278, + SVGClassName = 279, + HTMLAppletElement = 280, + HTMLMediaElementSeekToFragmentStart = 281, + HTMLMediaElementPauseAtFragmentEnd = 282, + PrefixedWindowURL = 283, + PrefixedWorkerURL = 284, // This didn't work because of crbug.com/376039. Available since M37. + WindowOrientation = 285, + DOMStringListContains = 286, + DocumentCaptureEvents = 287, + DocumentReleaseEvents = 288, + WindowCaptureEvents = 289, + WindowReleaseEvents = 290, + PrefixedGamepad = 291, + ElementAnimateKeyframeListEffectObjectTiming = 292, + ElementAnimateKeyframeListEffectDoubleTiming = 293, + ElementAnimateKeyframeListEffectNoTiming = 294, + DocumentXPathCreateExpression = 295, + DocumentXPathCreateNSResolver = 296, + DocumentXPathEvaluate = 297, + AttrGetValue = 298, + AttrSetValue = 299, + AnimationConstructorKeyframeListEffectObjectTiming = 300, + AnimationConstructorKeyframeListEffectDoubleTiming = 301, + AnimationConstructorKeyframeListEffectNoTiming = 302, + AttrSetValueWithElement = 303, + PrefixedCancelAnimationFrame = 304, + PrefixedCancelRequestAnimationFrame = 305, + NamedNodeMapGetNamedItem = 306, + NamedNodeMapSetNamedItem = 307, + NamedNodeMapRemoveNamedItem = 308, + NamedNodeMapItem = 309, + NamedNodeMapGetNamedItemNS = 310, + NamedNodeMapSetNamedItemNS = 311, + NamedNodeMapRemoveNamedItemNS = 312, + OpenWebDatabaseInWorker = 313, // This didn't work because of crbug.com/376039. Available since M37. + OpenWebDatabaseSyncInWorker = 314, // This didn't work because of crbug.com/376039. Available since M37. + PrefixedAllowFullscreenAttribute = 315, + XHRProgressEventPosition = 316, + XHRProgressEventTotalSize = 317, + PrefixedDocumentIsFullscreen = 318, + PrefixedDocumentFullScreenKeyboardInputAllowed = 319, + PrefixedDocumentCurrentFullScreenElement = 320, + PrefixedDocumentCancelFullScreen = 321, + PrefixedDocumentFullscreenEnabled = 322, + PrefixedDocumentFullscreenElement = 323, + PrefixedDocumentExitFullscreen = 324, + // The above items are available in M35 branch. + + SVGForeignObjectElement = 325, + PrefixedElementRequestPointerLock = 326, + SelectionSetPosition = 327, + AnimationPlayerFinishEvent = 328, + SVGSVGElementInXMLDocument = 329, + CanvasRenderingContext2DSetAlpha = 330, + CanvasRenderingContext2DSetCompositeOperation = 331, + CanvasRenderingContext2DSetLineWidth = 332, + CanvasRenderingContext2DSetLineCap = 333, + CanvasRenderingContext2DSetLineJoin = 334, + CanvasRenderingContext2DSetMiterLimit = 335, + CanvasRenderingContext2DClearShadow = 336, + CanvasRenderingContext2DSetStrokeColor = 337, + CanvasRenderingContext2DSetFillColor = 338, + CanvasRenderingContext2DDrawImageFromRect = 339, + CanvasRenderingContext2DSetShadow = 340, + PrefixedPerformanceClearResourceTimings = 341, + PrefixedPerformanceSetResourceTimingBufferSize = 342, + EventSrcElement = 343, + EventCancelBubble = 344, + EventPath = 345, + EventClipboardData = 346, + NodeIteratorDetach = 347, + AttrNodeValue = 348, + AttrTextContent = 349, + EventGetReturnValueTrue = 350, + EventGetReturnValueFalse = 351, + EventSetReturnValueTrue = 352, + EventSetReturnValueFalse = 353, + NodeIteratorExpandEntityReferences = 354, + TreeWalkerExpandEntityReferences = 355, + WindowOffscreenBuffering = 356, + WindowDefaultStatus = 357, + WindowDefaultstatus = 358, + PrefixedConvertPointFromPageToNode = 359, + PrefixedConvertPointFromNodeToPage = 360, + PrefixedTransitionEventConstructor = 361, + PrefixedMutationObserverConstructor = 362, + PrefixedIDBCursorConstructor = 363, + PrefixedIDBDatabaseConstructor = 364, + PrefixedIDBFactoryConstructor = 365, + PrefixedIDBIndexConstructor = 366, + PrefixedIDBKeyRangeConstructor = 367, + PrefixedIDBObjectStoreConstructor = 368, + PrefixedIDBRequestConstructor = 369, + PrefixedIDBTransactionConstructor = 370, + NotificationPermission = 371, + RangeDetach = 372, + DocumentImportNodeOptionalArgument = 373, + HTMLTableElementVspace = 374, + HTMLTableElementHspace = 375, + PrefixedDocumentExitPointerLock = 376, + PrefixedDocumentPointerLockElement = 377, + PrefixedTouchRadiusX = 378, + PrefixedTouchRadiusY = 379, + PrefixedTouchRotationAngle = 380, + PrefixedTouchForce = 381, + PrefixedMouseEventMovementX = 382, + PrefixedMouseEventMovementY = 383, + PrefixedWheelEventDirectionInvertedFromDevice = 384, + PrefixedWheelEventInit = 385, + PrefixedFileRelativePath = 386, + DocumentCaretRangeFromPoint = 387, + DocumentGetCSSCanvasContext = 388, + ElementScrollIntoViewIfNeeded = 389, + ElementScrollByLines = 390, + ElementScrollByPages = 391, + RangeCompareNode = 392, + RangeExpand = 393, + HTMLFrameElementWidth = 394, + HTMLFrameElementHeight = 395, + HTMLImageElementX = 396, + HTMLImageElementY = 397, + HTMLOptionsCollectionRemoveElement = 398, + HTMLPreElementWrap = 399, + SelectionBaseNode = 400, + SelectionBaseOffset = 401, + SelectionExtentNode = 402, + SelectionExtentOffset = 403, + SelectionType = 404, + SelectionModify = 405, + SelectionSetBaseAndExtent = 406, + SelectionEmpty = 407, + SVGFEMorphologyElementSetRadius = 408, + VTTCue = 409, + VTTCueRender = 410, + VTTCueRenderVertical = 411, + VTTCueRenderSnapToLinesFalse = 412, + VTTCueRenderLineNotAuto = 413, + VTTCueRenderPositionNot50 = 414, + VTTCueRenderSizeNot100 = 415, + VTTCueRenderAlignNotMiddle = 416, + // The above items are available in M36 branch. + + ElementRequestPointerLock = 417, + VTTCueRenderRtl = 418, + PostMessageFromSecureToInsecure = 419, + PostMessageFromInsecureToSecure = 420, + DocumentExitPointerLock = 421, + DocumentPointerLockElement = 422, + PrefixedCursorZoomIn = 424, + PrefixedCursorZoomOut = 425, + CSSCharsetRuleEncoding = 426, + DocumentSetCharset = 427, + DocumentDefaultCharset = 428, + TextEncoderConstructor = 429, + TextEncoderEncode = 430, + TextDecoderConstructor = 431, + TextDecoderDecode= 432, + FocusInOutEvent = 433, + MouseEventMovementX = 434, + MouseEventMovementY = 435, + MixedContentTextTrack = 436, + MixedContentRaw = 437, + MixedContentImage = 438, + MixedContentMedia = 439, + DocumentFonts = 440, + MixedContentFormsSubmitted = 441, + FormsSubmitted = 442, + TextInputEventOnInput = 443, + TextInputEventOnTextArea = 444, + TextInputEventOnContentEditable= 445, + TextInputEventOnNotNode = 446, + WebkitBeforeTextInsertedOnInput = 447, + WebkitBeforeTextInsertedOnTextArea = 448, + WebkitBeforeTextInsertedOnContentEditable = 449, + WebkitBeforeTextInsertedOnNotNode = 450, + WebkitEditableContentChangedOnInput = 451, + WebkitEditableContentChangedOnTextArea = 452, + WebkitEditableContentChangedOnContentEditable = 453, + WebkitEditableContentChangedOnNotNode = 454, + HTMLImports = 455, + ElementCreateShadowRoot = 456, + DocumentRegisterElement = 457, + EditingAppleInterchangeNewline = 458, + EditingAppleConvertedSpace = 459, + EditingApplePasteAsQuotation = 460, + EditingAppleStyleSpanClass = 461, + EditingAppleTabSpanClass = 462, + HTMLImportsAsyncAttribute = 463, + FontFaceSetReady = 464, + XMLHttpRequestSynchronous = 465, + CSSSelectorPseudoUnresolved = 466, + CSSSelectorPseudoShadow = 467, + CSSSelectorPseudoContent = 468, + CSSSelectorPseudoHost = 469, + CSSSelectorPseudoHostContext = 470, + CSSDeepCombinator = 471, + SyncXHRWithCredentials = 472, // Add new features immediately above this line. Don't change assigned - // numbers of each items, and don't reuse unused slots. + // numbers of any item, and don't reuse removed slots. + // Also, run update_use_counter_feature_enum.py in chromium/src/tools/metrics/histograms/ + // to update the UMA mapping. NumberOfFeatures, // This enum value must be last. }; // "count" sets the bit for this feature to 1. Repeated calls are ignored. static void count(const Document&, Feature); - static void count(const DOMWindow*, Feature); + // This doesn't count for ExecutionContexts for shared workers and service + // workers. + static void count(const ExecutionContext*, Feature); void count(CSSParserContext, CSSPropertyID); void count(Feature); // "countDeprecation" sets the bit for this feature to 1, and sends a deprecation // warning to the console. Repeated calls are ignored. // - // Be considerate to developers' consoles: features should only send deprecation warnings - // when we're actively interested in removing them from the platform. - static void countDeprecation(const DOMWindow*, Feature); + // Be considerate to developers' consoles: features should only send + // deprecation warnings when we're actively interested in removing them from + // the platform. + // + // The ExecutionContext* overload doesn't work for shared workers and + // service workers. + static void countDeprecation(const LocalDOMWindow*, Feature); static void countDeprecation(ExecutionContext*, Feature); static void countDeprecation(const Document&, Feature); String deprecationMessage(Feature); @@ -310,9 +507,16 @@ public: static int mapCSSPropertyIdToCSSSampleIdForHistogram(int id); + static void muteForInspector(); + static void unmuteForInspector(); + private: + static int m_muteCount; + bool recordMeasurement(Feature feature) { + if (UseCounter::m_muteCount) + return false; ASSERT(feature != PageDestruction); // PageDestruction is reserved as a scaling factor. ASSERT(feature < NumberOfFeatures); if (!m_countBits) { diff --git a/chromium/third_party/WebKit/Source/core/frame/WebKitPoint.idl b/chromium/third_party/WebKit/Source/core/frame/WebKitPoint.idl index 88b4be2a4ad..bddd6759e0b 100644 --- a/chromium/third_party/WebKit/Source/core/frame/WebKitPoint.idl +++ b/chromium/third_party/WebKit/Source/core/frame/WebKitPoint.idl @@ -27,6 +27,7 @@ CustomConstructor, CustomConstructor(float x, float y), ImplementedAs=DOMPoint, + WillBeGarbageCollected, ] interface WebKitPoint { attribute float x; attribute float y; diff --git a/chromium/third_party/WebKit/Source/core/frame/Window.idl b/chromium/third_party/WebKit/Source/core/frame/Window.idl index 632e3a26b45..3e75b0b9529 100644 --- a/chromium/third_party/WebKit/Source/core/frame/Window.idl +++ b/chromium/third_party/WebKit/Source/core/frame/Window.idl @@ -30,20 +30,22 @@ [ CheckSecurity=Frame, Custom=ToV8, - ImplementedAs=DOMWindow, + ImplementedAs=LocalDOMWindow, + PrimaryGlobal, + WillBeGarbageCollected, ] interface Window : EventTarget { // DOM Level 0 - [Replaceable] readonly attribute Screen screen; - [Replaceable] readonly attribute History history; - [Replaceable] readonly attribute BarProp locationbar; - [Replaceable] readonly attribute BarProp menubar; - [Replaceable] readonly attribute BarProp personalbar; - [Replaceable] readonly attribute BarProp scrollbars; - [Replaceable] readonly attribute BarProp statusbar; - [Replaceable] readonly attribute BarProp toolbar; - [Replaceable, PerWorldBindings, ActivityLogging=GetterForIsolatedWorlds] readonly attribute Navigator navigator; + readonly attribute Screen screen; + readonly attribute History history; + [Replaceable, MeasureAs=BarPropLocationbar] readonly attribute BarProp locationbar; + [Replaceable, MeasureAs=BarPropMenubar] readonly attribute BarProp menubar; + [Replaceable, MeasureAs=BarPropPersonalbar] readonly attribute BarProp personalbar; + [Replaceable, MeasureAs=BarPropScrollbars] readonly attribute BarProp scrollbars; + [Replaceable, MeasureAs=BarPropStatusbar] readonly attribute BarProp statusbar; + [Replaceable, MeasureAs=BarPropToolbar] readonly attribute BarProp toolbar; + [LogActivity=GetterOnly] readonly attribute Navigator navigator; [Replaceable] readonly attribute Navigator clientInformation; - [DoNotCheckSecurity, Unforgeable, Replaceable, PerWorldBindings, ActivityLogging=ForIsolatedWorlds, PutForwards=href] readonly attribute Location location; + [DoNotCheckSecurity, Unforgeable, Replaceable, LogActivity, PutForwards=href] readonly attribute Location location; [Custom, MeasureAs=WindowEvent, NotEnumerable] attribute Event event; Selection getSelection(); @@ -61,14 +63,15 @@ DOMString name, optional DOMString options); - [Custom] any showModalDialog(DOMString url, + [RuntimeEnabled=ShowModalDialog, Custom] any showModalDialog(DOMString url, optional any dialogArgs, optional DOMString featureArgs); - void alert([Default=Undefined] optional DOMString message); - boolean confirm([Default=Undefined] optional DOMString message); - [TreatReturnedNullStringAs=Null] DOMString prompt([Default=Undefined] optional DOMString message, - [TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString defaultValue); + void alert(); + void alert(DOMString message); + boolean confirm(optional DOMString message = null); + [TreatReturnedNullStringAs=Null] DOMString prompt(optional DOMString message = null, + optional DOMString defaultValue = null); boolean find([Default=Undefined] optional DOMString string, [Default=Undefined] optional boolean caseSensitive, @@ -78,7 +81,7 @@ [Default=Undefined] optional boolean searchInFrames, [Default=Undefined] optional boolean showDialog); - [Replaceable] readonly attribute boolean offscreenBuffering; + [Replaceable, MeasureAs=WindowOffscreenBuffering] readonly attribute boolean offscreenBuffering; [Replaceable] readonly attribute long outerHeight; [Replaceable] readonly attribute long outerWidth; @@ -93,9 +96,14 @@ readonly attribute long pageXOffset; readonly attribute long pageYOffset; + // Overloading can be replaced by optional if RuntimeEnabled is removed, by + // changing the third argument to *optional* Dictionary scrollOptions void scrollBy(long x, long y); + [RuntimeEnabled=CSSOMSmoothScroll, RaisesException] void scrollBy(long x, long y, Dictionary scrollOptions); void scrollTo(long x, long y); + [RuntimeEnabled=CSSOMSmoothScroll, RaisesException] void scrollTo(long x, long y, Dictionary scrollOptions); void scroll(long x, long y); + [RuntimeEnabled=CSSOMSmoothScroll, RaisesException] void scroll(long x, long y, Dictionary scrollOptions); void moveBy([Default=Undefined] optional float x, [Default=Undefined] optional float y); // FIXME: this should take longs not floats. void moveTo([Default=Undefined] optional float x, [Default=Undefined] optional float y); // FIXME: this should take longs not floats. void resizeBy([Default=Undefined] optional float x, [Default=Undefined] optional float y); // FIXME: this should take longs not floats. @@ -108,9 +116,9 @@ attribute DOMString name; attribute DOMString status; - attribute DOMString defaultStatus; + [MeasureAs=WindowDefaultStatus] attribute DOMString defaultStatus; // This attribute is an alias of defaultStatus and is necessary for legacy uses. - [ImplementedAs=defaultStatus] attribute DOMString defaultstatus; + [ImplementedAs=defaultStatus, MeasureAs=WindowDefaultstatus] attribute DOMString defaultstatus; // Self referential attributes [Replaceable, DoNotCheckSecurity] readonly attribute Window self; @@ -131,42 +139,42 @@ readonly attribute StyleMedia styleMedia; // DOM Level 2 Style Interface - [PerWorldBindings] CSSStyleDeclaration getComputedStyle([Default=Undefined] optional Element element, - [TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString pseudoElement); + CSSStyleDeclaration getComputedStyle([Default=Undefined] optional Element element, + [TreatNullAs=NullString, TreatUndefinedAs=NullString, Default=Undefined] optional DOMString pseudoElement); // WebKit extensions - CSSRuleList getMatchedCSSRules([Default=Undefined] optional Element element, - [TreatNullAs=NullString, TreatUndefinedAs=NullString,Default=Undefined] optional DOMString pseudoElement); + [MeasureAs=GetMatchedCSSRules] CSSRuleList getMatchedCSSRules([Default=Undefined] optional Element element, + [TreatNullAs=NullString, TreatUndefinedAs=NullString, Default=Undefined] optional DOMString pseudoElement); [Replaceable] readonly attribute double devicePixelRatio; - WebKitPoint webkitConvertPointFromPageToNode([Default=Undefined] optional Node node, - [Default=Undefined] optional WebKitPoint p); - WebKitPoint webkitConvertPointFromNodeToPage([Default=Undefined] optional Node node, - [Default=Undefined] optional WebKitPoint p); + [MeasureAs=PrefixedConvertPointFromPageToNode] WebKitPoint webkitConvertPointFromPageToNode([Default=Undefined] optional Node node, + [Default=Undefined] optional WebKitPoint p); + [MeasureAs=PrefixedConvertPointFromNodeToPage] WebKitPoint webkitConvertPointFromNodeToPage([Default=Undefined] optional Node node, + [Default=Undefined] optional WebKitPoint p); - [RuntimeEnabled=ApplicationCache, PerWorldBindings, ActivityLogging=GetterForIsolatedWorlds] readonly attribute ApplicationCache applicationCache; + [RuntimeEnabled=ApplicationCache, LogActivity=GetterOnly] readonly attribute ApplicationCache applicationCache; - [RuntimeEnabled=SessionStorage, PerWorldBindings, ActivityLogging=GetterForIsolatedWorlds, RaisesException=Getter] readonly attribute Storage sessionStorage; - [RuntimeEnabled=LocalStorage, PerWorldBindings, ActivityLogging=GetterForIsolatedWorlds, RaisesException=Getter] readonly attribute Storage localStorage; + [RuntimeEnabled=SessionStorage, LogActivity=GetterOnly, RaisesException=Getter] readonly attribute Storage sessionStorage; + [RuntimeEnabled=LocalStorage, LogActivity=GetterOnly, RaisesException=Getter] readonly attribute Storage localStorage; // This is the interface orientation in degrees. Some examples are: // 0 is straight up; -90 is when the device is rotated 90 clockwise; // 90 is when rotated counter clockwise. - [Conditional=ORIENTATION_EVENTS] readonly attribute long orientation; + [RuntimeEnabled=OrientationEvent, MeasureAs=WindowOrientation] readonly attribute long orientation; [Replaceable] readonly attribute Console console; // cross-document messaging - [DoNotCheckSecurity, Custom, RaisesException] void postMessage(SerializedScriptValue message, DOMString targetOrigin, optional Array messagePorts); + [DoNotCheckSecurity, Custom, RaisesException] void postMessage(SerializedScriptValue message, DOMString targetOrigin, optional MessagePort[] messagePorts); [Replaceable] readonly attribute Performance performance; [MeasureAs=UnprefixedRequestAnimationFrame] long requestAnimationFrame(RequestAnimationFrameCallback callback); void cancelAnimationFrame(long id); - [MeasureAs=PrefixedRequestAnimationFrame] long webkitRequestAnimationFrame(RequestAnimationFrameCallback callback); - [ImplementedAs=cancelAnimationFrame] void webkitCancelAnimationFrame(long id); - [ImplementedAs=cancelAnimationFrame] void webkitCancelRequestAnimationFrame(long id); // This is a deprecated alias for webkitCancelAnimationFrame(). Remove this when removing vendor prefix. + [DeprecateAs=PrefixedRequestAnimationFrame] long webkitRequestAnimationFrame(RequestAnimationFrameCallback callback); + [DeprecateAs=PrefixedCancelAnimationFrame, ImplementedAs=cancelAnimationFrame] void webkitCancelAnimationFrame(long id); + [DeprecateAs=PrefixedCancelRequestAnimationFrame, ImplementedAs=cancelAnimationFrame] void webkitCancelRequestAnimationFrame(long id); [Replaceable] readonly attribute CSS CSS; @@ -174,9 +182,7 @@ [RuntimeEnabled=CSSAnimationUnprefixed] attribute EventHandler onanimationend; [RuntimeEnabled=CSSAnimationUnprefixed] attribute EventHandler onanimationiteration; [RuntimeEnabled=CSSAnimationUnprefixed] attribute EventHandler onanimationstart; - [RuntimeEnabled=DeviceMotion] attribute EventHandler ondevicemotion; - [RuntimeEnabled=DeviceOrientation] attribute EventHandler ondeviceorientation; - [Conditional=ORIENTATION_EVENTS] attribute EventHandler onorientationchange; + [RuntimeEnabled=OrientationEvent] attribute EventHandler onorientationchange; attribute EventHandler onsearch; [RuntimeEnabled=Touch] attribute EventHandler ontouchcancel; [RuntimeEnabled=Touch] attribute EventHandler ontouchend; @@ -187,57 +193,25 @@ attribute EventHandler onwebkitanimationiteration; attribute EventHandler onwebkitanimationstart; attribute EventHandler onwebkittransitionend; - [PerWorldBindings, ActivityLogging=SetterForIsolatedWorlds] attribute EventHandler onwheel; + [LogActivity=SetterOnly] attribute EventHandler onwheel; - [DeprecateAs=CaptureEvents] void captureEvents(); - [DeprecateAs=ReleaseEvents] void releaseEvents(); + [MeasureAs=WindowCaptureEvents] void captureEvents(); + [MeasureAs=WindowReleaseEvents] void releaseEvents(); // Additional constructors. - attribute TransitionEventConstructor WebKitTransitionEvent; + [MeasureAs=PrefixedTransitionEventConstructor] attribute TransitionEventConstructor WebKitTransitionEvent; [RuntimeEnabled=CSSAnimationUnprefixed] attribute WebKitAnimationEventConstructor AnimationEvent; - // Mozilla has a separate XMLDocument object for XML documents. - // We just use Document for this. - attribute DocumentConstructor XMLDocument; - attribute URLConstructor webkitURL; // FIXME: deprecate this. - attribute MutationObserverConstructor WebKitMutationObserver; // FIXME: Add metrics to determine when we can remove this. - attribute IDBCursorConstructor webkitIDBCursor; - attribute IDBDatabaseConstructor webkitIDBDatabase; - attribute IDBFactoryConstructor webkitIDBFactory; - attribute IDBIndexConstructor webkitIDBIndex; - attribute IDBKeyRangeConstructor webkitIDBKeyRange; - attribute IDBObjectStoreConstructor webkitIDBObjectStore; - attribute IDBRequestConstructor webkitIDBRequest; - attribute IDBTransactionConstructor webkitIDBTransaction; - - // Constructors whose name does not match the interface name. - // FIXME: Remove these once [ImplementedAs] is used and once constructor names match interface names. - [RuntimeEnabled=MediaStream] attribute MediaStreamConstructor webkitMediaStream; - [Conditional=WEB_AUDIO, RuntimeEnabled=WebAudio] attribute AudioContextConstructor webkitAudioContext; - [Conditional=WEB_AUDIO, RuntimeEnabled=WebAudio] attribute OfflineAudioContextConstructor webkitOfflineAudioContext; - [RuntimeEnabled=PeerConnection] attribute RTCPeerConnectionConstructor webkitRTCPeerConnection; - [RuntimeEnabled=ScriptedSpeech] attribute SpeechGrammarConstructor webkitSpeechGrammar; - [RuntimeEnabled=ScriptedSpeech] attribute SpeechGrammarListConstructor webkitSpeechGrammarList; - [RuntimeEnabled=ScriptedSpeech] attribute SpeechRecognitionConstructor webkitSpeechRecognition; - [RuntimeEnabled=ScriptedSpeech] attribute SpeechRecognitionErrorConstructor webkitSpeechRecognitionError; - [RuntimeEnabled=ScriptedSpeech] attribute SpeechRecognitionEventConstructor webkitSpeechRecognitionEvent; - [Conditional=WEB_AUDIO] attribute PannerNodeConstructor webkitAudioPannerNode; - - // Prefixed ShadowRoot constructor should be phased out eventually, but for the moment it must be always exposed. - // Unprefixed ShadowRoot constructor should be visible when the feature flag is enabled. - // FIXME: When it's ready to remove WebKitShadowRoot, get rid of both constructors from Window.idl and remove - // [NoInterfaceObject] from ShadowRoot interface definition. - [RuntimeEnabled=ShadowDOM] attribute ShadowRootConstructor ShadowRoot; - [MeasureAs=PrefixedShadowRootConstructor] attribute ShadowRootConstructor WebKitShadowRoot; + [MeasureAs=PrefixedWindowURL] attribute URLConstructor webkitURL; // FIXME: deprecate this. + [MeasureAs=PrefixedMutationObserverConstructor] attribute MutationObserverConstructor WebKitMutationObserver; // window.toString() requires special handling in V8 [DoNotCheckSignature, DoNotCheckSecurity, Custom, NotEnumerable] DOMString toString(); - [ImplementedAs=anonymousIndexedGetter, NotEnumerable] getter Window(unsigned long index); + [NotEnumerable] getter Window (unsigned long index); [Custom, NotEnumerable] getter Window (DOMString name); }; Window implements GlobalEventHandlers; -Window implements ImageBitmapFactories; Window implements WindowBase64; Window implements WindowEventHandlers; Window implements WindowTimers; diff --git a/chromium/third_party/WebKit/Source/core/frame/WindowBase64.idl b/chromium/third_party/WebKit/Source/core/frame/WindowBase64.idl index 134018ddc3e..c5ed3a6b248 100644 --- a/chromium/third_party/WebKit/Source/core/frame/WindowBase64.idl +++ b/chromium/third_party/WebKit/Source/core/frame/WindowBase64.idl @@ -25,10 +25,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#windowbase64 + [ - ImplementedAs=DOMWindowBase64, - NoInterfaceObject, + NoInterfaceObject, // Always used on target of 'implements' ] interface WindowBase64 { - [RaisesException] DOMString atob(DOMString string); [RaisesException] DOMString btoa(DOMString string); + [RaisesException] DOMString atob(DOMString string); }; diff --git a/chromium/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl b/chromium/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl index b7634ae98bf..95de525822a 100644 --- a/chromium/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl +++ b/chromium/third_party/WebKit/Source/core/frame/WindowEventHandlers.idl @@ -27,21 +27,24 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#windoweventhandlers + [ - NoInterfaceObject, - ImplementedAs=DOMWindowEventHandlers + ImplementedAs=DOMWindowEventHandlers, + LegacyTreatAsPartialInterface, + NoInterfaceObject, // Always used on target of 'implements' ] interface WindowEventHandlers { //attribute EventHandler onafterprint; //attribute EventHandler onbeforeprint; attribute EventHandler onbeforeunload; attribute EventHandler onhashchange; + attribute EventHandler onlanguagechange; attribute EventHandler onmessage; attribute EventHandler onoffline; attribute EventHandler ononline; attribute EventHandler onpagehide; attribute EventHandler onpageshow; attribute EventHandler onpopstate; - attribute EventHandler onresize; attribute EventHandler onstorage; attribute EventHandler onunload; }; diff --git a/chromium/third_party/WebKit/Source/core/frame/WindowTimers.idl b/chromium/third_party/WebKit/Source/core/frame/WindowTimers.idl index 744567d39e1..47f394fc249 100644 --- a/chromium/third_party/WebKit/Source/core/frame/WindowTimers.idl +++ b/chromium/third_party/WebKit/Source/core/frame/WindowTimers.idl @@ -25,13 +25,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#windowtimers + [ - NoInterfaceObject, - ImplementedAs=DOMWindowTimers + ImplementedAs=DOMWindowTimers, + LegacyTreatAsPartialInterface, + NoInterfaceObject, // Always used on target of 'implements' ] interface WindowTimers { + // FIXME: currently using [Custom] and |any| because overload algorithm + // can't handle Function/DOMString overload properly + // http://crbug.com/293561 + // FIXME: would be clearer as a union type, like: + // typedef (Function or DOMString) Handler + // Needs spec update and better union support: http://crbug.com/240176 [Custom] long setTimeout(any handler, [Default=Undefined] optional long timeout); void clearTimeout([Default=Undefined] optional long handle); [Custom] long setInterval(any handler, [Default=Undefined] optional long timeout); void clearInterval([Default=Undefined] optional long handle); }; - diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.cpp deleted file mode 100644 index 5dafb2de2fd..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/AnimationBase.h" - -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/platform/animation/TimingFunction.h" -#include "core/rendering/RenderBox.h" -#include "platform/animation/AnimationUtilities.h" -#include <algorithm> - -using namespace std; - -namespace WebCore { - -AnimationBase::AnimationBase(const CSSAnimationData* transition, RenderObject& renderer, CompositeAnimation* compAnim) - : m_animState(AnimationStateNew) - , m_isAccelerated(false) - , m_transformFunctionListValid(false) - , m_filterFunctionListsMatch(false) - , m_startTime(0) - , m_pauseTime(-1) - , m_requestedStartTime(0) - , m_totalDuration(-1) - , m_nextIterationDuration(-1) - , m_object(&renderer) - , m_animation(const_cast<CSSAnimationData*>(transition)) - , m_compAnim(compAnim) -{ - // Compute the total duration - if (m_animation->iterationCount() > 0) - m_totalDuration = m_animation->duration() * m_animation->iterationCount(); -} - -void AnimationBase::setNeedsStyleRecalc(Node* node) -{ - if (node) - node->setNeedsStyleRecalc(LocalStyleChange); -} - -double AnimationBase::duration() const -{ - return m_animation->duration(); -} - -bool AnimationBase::playStatePlaying() const -{ - return m_animation->playState() == AnimPlayStatePlaying; -} - -void AnimationBase::updateStateMachine(AnimStateInput input, double param) -{ - if (!m_compAnim) - return; - - // If we get AnimationStateInputRestartAnimation then we force a new animation, regardless of state. - if (input == AnimationStateInputMakeNew) { - if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); - m_animState = AnimationStateNew; - m_startTime = 0; - m_pauseTime = -1; - m_requestedStartTime = 0; - m_nextIterationDuration = -1; - endAnimation(); - return; - } - - if (input == AnimationStateInputRestartAnimation) { - if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); - m_animState = AnimationStateNew; - m_startTime = 0; - m_pauseTime = -1; - m_requestedStartTime = 0; - m_nextIterationDuration = -1; - endAnimation(); - - if (!paused()) - updateStateMachine(AnimationStateInputStartAnimation, -1); - return; - } - - if (input == AnimationStateInputEndAnimation) { - if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); - m_animState = AnimationStateDone; - endAnimation(); - return; - } - - if (input == AnimationStateInputPauseOverride) { - if (m_animState == AnimationStateStartWaitResponse) { - // If we are in AnimationStateStartWaitResponse, the animation will get canceled before - // we get a response, so move to the next state. - endAnimation(); - updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); - } - return; - } - - if (input == AnimationStateInputResumeOverride) { - if (m_animState == AnimationStateLooping || m_animState == AnimationStateEnding) { - // Start the animation - startAnimation(beginAnimationUpdateTime() - m_startTime); - } - return; - } - - // Execute state machine - switch (m_animState) { - case AnimationStateNew: - ASSERT(input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning || input == AnimationStateInputPlayStatePaused); - if (input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning) { - m_requestedStartTime = beginAnimationUpdateTime(); - m_animState = AnimationStateStartWaitTimer; - } - break; - case AnimationStateStartWaitTimer: - ASSERT(input == AnimationStateInputStartTimerFired || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputStartTimerFired) { - 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()->addToAnimationsWaitingForStyle(this); - - // Trigger a render so we can start the animation - if (m_object) - m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); - } else { - ASSERT(!paused()); - // We're waiting for the start timer to fire and we got a pause. Cancel the timer, pause and wait - m_pauseTime = beginAnimationUpdateTime(); - m_animState = AnimationStatePausedWaitTimer; - } - break; - case AnimationStateStartWaitStyleAvailable: - ASSERT(input == AnimationStateInputStyleAvailable || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputStyleAvailable) { - // Start timer has fired, tell the animation to start and wait for it to respond with start time - m_animState = AnimationStateStartWaitResponse; - - overrideAnimations(); - - // Start the animation - if (overridden()) { - m_animState = AnimationStateStartWaitResponse; - updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); - } else { - double timeOffset = 0; - // If the value for 'animation-delay' is negative then the animation appears to have started in the past. - if (m_animation->delay() < 0) - timeOffset = -m_animation->delay(); - startAnimation(timeOffset); - m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, isAccelerated()); - } - } else { - // We're waiting for the style to be available and we got a pause. Pause and wait - m_pauseTime = beginAnimationUpdateTime(); - m_animState = AnimationStatePausedWaitStyleAvailable; - } - break; - case AnimationStateStartWaitResponse: - ASSERT(input == AnimationStateInputStartTimeSet || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputStartTimeSet) { - ASSERT(param >= 0); - // We have a start time, set it, unless the startTime is already set - if (m_startTime <= 0) { - m_startTime = param; - // If the value for 'animation-delay' is negative then the animation appears to have started in the past. - if (m_animation->delay() < 0) - m_startTime += m_animation->delay(); - } - - // Now that we know the start time, fire the start event. - onAnimationStart(0); // The elapsedTime is 0. - - // Decide whether to go into looping or ending state - goIntoEndingOrLoopingState(); - - // Dispatch updateStyleIfNeeded so we can start the animation - if (m_object) - m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); - } 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 = beginAnimationUpdateTime(); - pauseAnimation(beginAnimationUpdateTime() - m_startTime); - m_animState = AnimationStatePausedWaitResponse; - } - break; - case AnimationStateLooping: - ASSERT(input == AnimationStateInputLoopTimerFired || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputLoopTimerFired) { - ASSERT(param >= 0); - // Loop timer fired, loop again or end. - onAnimationIteration(param); - - // Decide whether to go into looping or ending state - goIntoEndingOrLoopingState(); - } else { - // We are pausing while running. Cancel the animation and wait - m_pauseTime = beginAnimationUpdateTime(); - pauseAnimation(beginAnimationUpdateTime() - m_startTime); - m_animState = AnimationStatePausedRun; - } - break; - case AnimationStateEnding: -#if !LOG_DISABLED - if (input != AnimationStateInputEndTimerFired && input != AnimationStateInputPlayStatePaused) - WTF_LOG_ERROR("State is AnimationStateEnding, but input is not AnimationStateInputEndTimerFired or AnimationStateInputPlayStatePaused. It is %d.", input); -#endif - if (input == AnimationStateInputEndTimerFired) { - - ASSERT(param >= 0); - // End timer fired, finish up - onAnimationEnd(param); - - m_animState = AnimationStateDone; - - if (m_object) { - if (m_animation->fillsForwards()) - m_animState = AnimationStateFillingForwards; - else - resumeOverriddenAnimations(); - - // Fire off another style change so we can set the final value - m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); - } - } else { - // We are pausing while running. Cancel the animation and wait - m_pauseTime = beginAnimationUpdateTime(); - pauseAnimation(beginAnimationUpdateTime() - m_startTime); - m_animState = AnimationStatePausedRun; - } - // |this| may be deleted here - break; - case AnimationStatePausedWaitTimer: - ASSERT(input == AnimationStateInputPlayStateRunning); - ASSERT(paused()); - // Update the times - m_startTime += beginAnimationUpdateTime() - m_pauseTime; - m_pauseTime = -1; - - // we were waiting for the start timer to fire, go back and wait again - m_animState = AnimationStateNew; - updateStateMachine(AnimationStateInputStartAnimation, 0); - break; - case AnimationStatePausedWaitResponse: - case AnimationStatePausedWaitStyleAvailable: - case AnimationStatePausedRun: - // We treat these two cases the same. The only difference is that, when we are in - // AnimationStatePausedWaitResponse, we don't yet have a valid startTime, so we send 0 to startAnimation. - // When the AnimationStateInputStartTimeSet comes in and we were in AnimationStatePausedRun, we will notice - // that we have already set the startTime and will ignore it. - ASSERT(input == AnimationStateInputPlayStateRunning || input == AnimationStateInputStartTimeSet || input == AnimationStateInputStyleAvailable); - ASSERT(paused()); - - if (input == AnimationStateInputPlayStateRunning) { - // Update the times - if (m_animState == AnimationStatePausedRun) - m_startTime += beginAnimationUpdateTime() - m_pauseTime; - else - m_startTime = 0; - m_pauseTime = -1; - - if (m_animState == AnimationStatePausedWaitStyleAvailable) - m_animState = AnimationStateStartWaitStyleAvailable; - else { - // We were either running or waiting for a begin time response from the animation. - // Either way we need to restart the animation (possibly with an offset if we - // had already been running) and wait for it to start. - m_animState = AnimationStateStartWaitResponse; - - // Start the animation - if (overridden()) { - updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); - } else { - startAnimation(beginAnimationUpdateTime() - m_startTime); - m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, isAccelerated()); - } - } - break; - } - - if (input == AnimationStateInputStartTimeSet) { - ASSERT(m_animState == AnimationStatePausedWaitResponse); - - // We are paused but we got the callback that notifies us that an accelerated animation started. - // We ignore the start time and just move into the paused-run state. - m_animState = AnimationStatePausedRun; - ASSERT(m_startTime == 0); - m_startTime = param; - m_pauseTime += m_startTime; - break; - } - - ASSERT(m_animState == AnimationStatePausedWaitStyleAvailable); - // We are paused but we got the callback that notifies us that style has been updated. - // We move to the AnimationStatePausedWaitResponse state - m_animState = AnimationStatePausedWaitResponse; - overrideAnimations(); - break; - case AnimationStateFillingForwards: - case AnimationStateDone: - // We're done. Stay in this state until we are deleted - break; - } -} - -void AnimationBase::fireAnimationEventsIfNeeded() -{ - if (!m_compAnim) - return; - - // If we are waiting for the delay time to expire and it has, go to the next state - if (m_animState != AnimationStateStartWaitTimer && m_animState != AnimationStateLooping && m_animState != AnimationStateEnding) - return; - - // We have to make sure to keep a ref to the this pointer, because it could get destroyed - // during an animation callback that might get called. Since the owner is a CompositeAnimation - // and it ref counts this object, we will keep a ref to that instead. That way the AnimationBase - // can still access the resources of its CompositeAnimation as needed. - RefPtr<AnimationBase> protector(this); - RefPtr<CompositeAnimation> compProtector(m_compAnim); - - // Check for start timeout - if (m_animState == AnimationStateStartWaitTimer) { - if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->delay()) - updateStateMachine(AnimationStateInputStartTimerFired, 0); - return; - } - - double elapsedDuration = getElapsedTime(); - - // Check for end timeout - if (m_totalDuration >= 0 && elapsedDuration >= m_totalDuration) { - // We may still be in AnimationStateLooping if we've managed to skip a - // whole iteration, in which case we should jump to the end state. - m_animState = AnimationStateEnding; - - // Fire an end event - updateStateMachine(AnimationStateInputEndTimerFired, m_totalDuration); - } else { - // Check for iteration timeout - if (m_nextIterationDuration < 0) { - // Hasn't been set yet, set it - double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); - m_nextIterationDuration = elapsedDuration + durationLeft; - } - - if (elapsedDuration >= m_nextIterationDuration) { - // Set to the next iteration - double previous = m_nextIterationDuration; - double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); - m_nextIterationDuration = elapsedDuration + durationLeft; - - // Send the event - updateStateMachine(AnimationStateInputLoopTimerFired, previous); - } - } -} - -void AnimationBase::updatePlayState(EAnimPlayState playState) -{ - if (!m_compAnim) - return; - - // Set the state machine to the desired state. - bool pause = playState == AnimPlayStatePaused; - - if (pause == paused() && !isNew()) - return; - - updateStateMachine(pause ? AnimationStateInputPlayStatePaused : AnimationStateInputPlayStateRunning, -1); -} - -double AnimationBase::timeToNextService() -{ - // Returns the time at which next service is required. -1 means no service is required. 0 means - // service is required now, and > 0 means service is required that many seconds in the future. - if (paused() || isNew() || m_animState == AnimationStateFillingForwards) - return -1; - - if (m_animState == AnimationStateStartWaitTimer) { - double timeFromNow = m_animation->delay() - (beginAnimationUpdateTime() - m_requestedStartTime); - return max(timeFromNow, 0.0); - } - - fireAnimationEventsIfNeeded(); - - // In all other cases, we need service right away. - return 0; -} - -// Compute the fractional time, taking into account direction. -// There is no need to worry about iterations, we assume that we would have -// short circuited above if we were done. - -double AnimationBase::fractionalTime(double scale, double elapsedTime, double offset) const -{ - double fractionalTime = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1; - // FIXME: startTime can be before the current animation "frame" time. This is to sync with the frame time - // concept in AnimationTimeController. So we need to somehow sync the two. Until then, the possible - // error is small and will probably not be noticeable. Until we fix this, remove the assert. - // https://bugs.webkit.org/show_bug.cgi?id=52037 - // ASSERT(fractionalTime >= 0); - if (fractionalTime < 0) - fractionalTime = 0; - - int integralTime = static_cast<int>(fractionalTime); - const int integralIterationCount = static_cast<int>(m_animation->iterationCount()); - const bool iterationCountHasFractional = m_animation->iterationCount() - integralIterationCount; - if (m_animation->iterationCount() != CSSAnimationData::IterationCountInfinite && !iterationCountHasFractional) - integralTime = min(integralTime, integralIterationCount - 1); - - fractionalTime -= integralTime; - - // Thie method can be called with an elapsedTime which very slightly - // exceeds the end of the animation. In this case, clamp the - // fractionalTime. - if (fractionalTime > 1) - fractionalTime = 1; - ASSERT(fractionalTime >= 0 && fractionalTime <= 1); - - if (((m_animation->direction() == CSSAnimationData::AnimationDirectionAlternate) && (integralTime & 1)) - || ((m_animation->direction() == CSSAnimationData::AnimationDirectionAlternateReverse) && !(integralTime & 1)) - || m_animation->direction() == CSSAnimationData::AnimationDirectionReverse) - fractionalTime = 1 - fractionalTime; - - fractionalTime -= offset; - // Note that if fractionalTime == 0 here, scale may be infinity, but in - // this case we don't need to apply scale anyway. - if (scale != 1.0 && fractionalTime) { - ASSERT(scale >= 0 && !std::isinf(scale)); - fractionalTime *= scale; - } - - ASSERT(fractionalTime >= 0 && fractionalTime <= 1); - return fractionalTime; -} - -double AnimationBase::progress(double scale, double offset, const TimingFunction* timingFunction) const -{ - if (preActive()) - return 0; - - double dur = m_animation->duration(); - if (m_animation->iterationCount() > 0) - dur *= m_animation->iterationCount(); - - if (postActive() || !m_animation->duration()) - return 1.0; - - double elapsedTime = getElapsedTime(); - if (m_animation->iterationCount() > 0 && elapsedTime >= dur) { - const int integralIterationCount = static_cast<int>(m_animation->iterationCount()); - const bool iterationCountHasFractional = m_animation->iterationCount() - integralIterationCount; - return (integralIterationCount % 2 || iterationCountHasFractional) ? 1.0 : 0.0; - } - - const double fractionalTime = this->fractionalTime(scale, elapsedTime, offset); - - if (!timingFunction) - timingFunction = m_animation->timingFunction(); - - return timingFunction->evaluate(fractionalTime, accuracyForDuration(m_animation->duration())); -} - -void AnimationBase::getTimeToNextEvent(double& time, bool& isLooping) const -{ - if (postActive()) { - time = -1; - isLooping = false; - return; - } - - // Decide when the end or loop event needs to fire - const double elapsedDuration = getElapsedTime(); - double durationLeft = 0; - double nextIterationTime = m_totalDuration; - - if (m_totalDuration < 0 || elapsedDuration < m_totalDuration) { - durationLeft = m_animation->duration() > 0 ? (m_animation->duration() - fmod(elapsedDuration, m_animation->duration())) : 0; - nextIterationTime = elapsedDuration + durationLeft; - } - - if (m_totalDuration < 0 || nextIterationTime < m_totalDuration) { - // We are not at the end yet - ASSERT(m_totalDuration < 0 || nextIterationTime > 0); - isLooping = true; - } else { - // We are at the end - isLooping = false; - } - - time = durationLeft; -} - -void AnimationBase::goIntoEndingOrLoopingState() -{ - double t; - bool isLooping; - getTimeToNextEvent(t, isLooping); - m_animState = isLooping ? AnimationStateLooping : AnimationStateEnding; -} - -void AnimationBase::freezeAtTime(double t) -{ - if (!m_compAnim) - return; - - if (!m_startTime) { - // If we haven't started yet, make it as if we started. - m_animState = AnimationStateStartWaitResponse; - onAnimationStartResponse(beginAnimationUpdateTime()); - } - - ASSERT(m_startTime); // if m_startTime is zero, we haven't started yet, so we'll get a bad pause time. - if (t <= m_animation->delay()) - m_pauseTime = m_startTime; - else - m_pauseTime = m_startTime + t - m_animation->delay(); - - // It is possible that m_isAccelerated is true and m_object->compositingState() is NotComposited, because of style change. - // So, both conditions need to be checked. - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - pauseAnimation(t); -} - -double AnimationBase::beginAnimationUpdateTime() const -{ - if (!m_compAnim) - return 0; - - return m_compAnim->animationController()->beginAnimationUpdateTime(); -} - -double AnimationBase::getElapsedTime() const -{ - ASSERT(!postActive()); - if (paused()) - return m_pauseTime - m_startTime; - if (m_startTime <= 0) - return 0; - - double elapsedTime = beginAnimationUpdateTime() - m_startTime; - // It's possible for the start time to be ahead of the last update time - // if the compositor has just sent notification for the start of an - // accelerated animation. - return max(elapsedTime, 0.0); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.h b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.h deleted file mode 100644 index 6ab1d5801e4..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AnimationBase_h -#define AnimationBase_h - -#include "CSSPropertyNames.h" -#include "core/platform/animation/CSSAnimationData.h" -#include "core/rendering/style/RenderStyleConstants.h" -#include "wtf/RefCounted.h" - -namespace WebCore { - -class AnimationBase; -class AnimationController; -class CompositeAnimation; -class Element; -class Node; -class RenderObject; -class RenderStyle; -class TimingFunction; - -class AnimationBase : public RefCounted<AnimationBase> { - friend class CompositeAnimation; - friend class CSSPropertyAnimation; - -public: - AnimationBase(const CSSAnimationData* transition, RenderObject& renderer, CompositeAnimation* compAnim); - virtual ~AnimationBase() { } - - RenderObject* renderer() const { return m_object; } - void clear() - { - endAnimation(); - m_object = 0; - m_compAnim = 0; - } - - double duration() const; - - // Animations and Transitions go through the states below. When entering the STARTED state - // the animation is started. This may or may not require deferred response from the animator. - // If so, we stay in this state until that response is received (and it returns the start time). - // Otherwise, we use the current time as the start time and go immediately to AnimationStateLooping - // or AnimationStateEnding. - enum AnimState { - AnimationStateNew, // animation just created, animation not running yet - AnimationStateStartWaitTimer, // start timer running, waiting for fire - AnimationStateStartWaitStyleAvailable, // waiting for style setup so we can start animations - AnimationStateStartWaitResponse, // animation started, waiting for response - AnimationStateLooping, // response received, animation running, loop timer running, waiting for fire - AnimationStateEnding, // received, animation running, end timer running, waiting for fire - AnimationStatePausedWaitTimer, // in pause mode when animation started - AnimationStatePausedWaitStyleAvailable, // in pause mode when waiting for style setup - AnimationStatePausedWaitResponse, // animation paused when in STARTING state - AnimationStatePausedRun, // animation paused when in LOOPING or ENDING state - AnimationStateDone, // end timer fired, animation finished and removed - AnimationStateFillingForwards // animation has ended and is retaining its final value - }; - - enum AnimStateInput { - AnimationStateInputMakeNew, // reset back to new from any state - AnimationStateInputStartAnimation, // animation requests a start - AnimationStateInputRestartAnimation, // force a restart from any state - AnimationStateInputStartTimerFired, // start timer fired - AnimationStateInputStyleAvailable, // style is setup, ready to start animating - AnimationStateInputStartTimeSet, // m_startTime was set - AnimationStateInputLoopTimerFired, // loop timer fired - AnimationStateInputEndTimerFired, // end timer fired - AnimationStateInputPauseOverride, // pause an animation due to override - AnimationStateInputResumeOverride, // resume an overridden animation - AnimationStateInputPlayStateRunning, // play state paused -> running - AnimationStateInputPlayStatePaused, // play state running -> paused - AnimationStateInputEndAnimation // force an end from any state - }; - - // Called when animation is in AnimationStateNew to start animation - void updateStateMachine(AnimStateInput, double param); - - // Animation has actually started, at passed time - void onAnimationStartResponse(double startTime) - { - updateStateMachine(AnimationBase::AnimationStateInputStartTimeSet, startTime); - } - - // Called to change to or from paused state - void updatePlayState(EAnimPlayState); - bool playStatePlaying() const; - - bool waitingToStart() const { return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer; } - bool preActive() const - { - return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer || m_animState == AnimationStateStartWaitStyleAvailable || m_animState == AnimationStateStartWaitResponse; - } - - bool postActive() const { return m_animState == AnimationStateDone; } - bool active() const { return !postActive() && !preActive(); } - bool running() const { return !isNew() && !postActive(); } - bool paused() const { return m_pauseTime >= 0; } - bool isNew() const { return m_animState == AnimationStateNew; } - bool waitingForStartTime() const { return m_animState == AnimationStateStartWaitResponse; } - bool waitingForStyleAvailable() const { return m_animState == AnimationStateStartWaitStyleAvailable; } - - virtual double timeToNextService(); - - double progress(double scale, double offset, const TimingFunction*) const; - - virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* /*currentStyle*/, RenderStyle* /*targetStyle*/, RefPtr<RenderStyle>& /*animatedStyle*/) = 0; - virtual void getAnimatedStyle(RefPtr<RenderStyle>& /*animatedStyle*/) = 0; - - virtual bool shouldFireEvents() const { return false; } - - void fireAnimationEventsIfNeeded(); - - void setAnimation(const CSSAnimationData* anim) { m_animation = const_cast<CSSAnimationData*>(anim); } - - // Return true if this animation is overridden. This will only be the case for - // ImplicitAnimations and is used to determine whether or not we should force - // set the start time. If an animation is overridden, it will probably not get - // back the AnimationStateInputStartTimeSet input. - virtual bool overridden() const { return false; } - - // Does this animation/transition involve the given property? - virtual bool affectsProperty(CSSPropertyID /*property*/) const { return false; } - - bool isAnimatingProperty(CSSPropertyID property, bool acceleratedOnly, bool isRunningNow) const - { - if (acceleratedOnly && !m_isAccelerated) - return false; - - if (isRunningNow) - return (!waitingToStart() && !postActive()) && affectsProperty(property); - - return !postActive() && affectsProperty(property); - } - - // FIXME: rename this using the "lists match" terminology. - bool isTransformFunctionListValid() const { return m_transformFunctionListValid; } - bool filterFunctionListsMatch() const { return m_filterFunctionListsMatch; } - - // Freeze the animation; used by DumpRenderTree. - void freezeAtTime(double t); - - double beginAnimationUpdateTime() const; - - double getElapsedTime() const; - - void styleAvailable() - { - ASSERT(waitingForStyleAvailable()); - updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1); - } - - const CSSAnimationData* animation() const { return m_animation.get(); } - -protected: - virtual void overrideAnimations() { } - virtual void resumeOverriddenAnimations() { } - - CompositeAnimation* compositeAnimation() { return m_compAnim; } - - // These are called when the corresponding timer fires so subclasses can do any extra work - virtual void onAnimationStart(double /*elapsedTime*/) { } - virtual void onAnimationIteration(double /*elapsedTime*/) { } - virtual void onAnimationEnd(double /*elapsedTime*/) { } - - // timeOffset is an offset from the current time when the animation should start. Negative values are OK. - virtual void startAnimation(double /*timeOffset*/) { } - // timeOffset is the time at which the animation is being paused. - virtual void pauseAnimation(double /*timeOffset*/) { } - virtual void endAnimation() { } - - void goIntoEndingOrLoopingState(); - - bool isAccelerated() const { return m_isAccelerated; } - - static void setNeedsStyleRecalc(Node*); - - void getTimeToNextEvent(double& time, bool& isLooping) const; - - double fractionalTime(double scale, double elapsedTime, double offset) const; - - AnimState m_animState; - - bool m_isAccelerated; - bool m_transformFunctionListValid; - bool m_filterFunctionListsMatch; - double m_startTime; - double m_pauseTime; - double m_requestedStartTime; - - double m_totalDuration; - double m_nextIterationDuration; - - RenderObject* m_object; - - RefPtr<CSSAnimationData> m_animation; - CompositeAnimation* m_compAnim; -}; - -} // namespace WebCore - -#endif // AnimationBase_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.cpp deleted file mode 100644 index 8521e139a08..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/AnimationController.h" - -#include "core/dom/PseudoElement.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/events/TransitionEvent.h" -#include "core/events/WebKitAnimationEvent.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" -#include "core/page/Page.h" -#include "core/frame/animation/AnimationBase.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/rendering/RenderView.h" -#include "wtf/CurrentTime.h" - -namespace WebCore { - -static const double cBeginAnimationUpdateTimeNotSet = -1; - -AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) - : m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired) - , m_updateStyleIfNeededDispatcher(this, &AnimationControllerPrivate::updateStyleIfNeededDispatcherFired) - , m_frame(frame) - , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet) - , m_animationsWaitingForStyle() - , m_animationsWaitingForStartTimeResponse() - , m_animationsWaitingForAsyncStartNotification() -{ -} - -AnimationControllerPrivate::~AnimationControllerPrivate() -{ -} - -PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimation(RenderObject& renderer) -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(&renderer); - if (!animation) { - animation = CompositeAnimation::create(this); - m_compositeAnimations.set(&renderer, animation); - } - return animation; -} - -bool AnimationControllerPrivate::clear(RenderObject* renderer) -{ - // Return false if we didn't do anything. - PassRefPtr<CompositeAnimation> animation = m_compositeAnimations.take(renderer); - if (!animation) - return false; - animation->clearRenderer(); - return true; -} - -void AnimationControllerPrivate::updateAnimations(double& timeToNextService, double& timeToNextEvent, SetNeedsStyleRecalc callSetNeedsStyleRecalc/* = DoNotCallSetNeedsStyleRecalc*/) -{ - double minTimeToNextService = -1; - double minTimeToNextEvent = -1; - bool updateStyleNeeded = false; - - RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); - for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { - CompositeAnimation* compAnim = it->value.get(); - if (compAnim->hasAnimations()) { - double t = compAnim->timeToNextService(); - if (t != -1 && (t < minTimeToNextService || minTimeToNextService == -1)) - minTimeToNextService = t; - double nextEvent = compAnim->timeToNextEvent(); - if (nextEvent != -1 && (nextEvent < minTimeToNextEvent || minTimeToNextEvent == -1)) - minTimeToNextEvent = nextEvent; - if (callSetNeedsStyleRecalc == CallSetNeedsStyleRecalc) { - if (!t) { - Node* node = it->key->node(); - node->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - updateStyleNeeded = true; - } - } else if (!minTimeToNextService && !minTimeToNextEvent) { - // Found the minimum values and do not need to mark for style recalc. - break; - } - } - } - - if (updateStyleNeeded) - m_frame->document()->updateStyleIfNeeded(); - - timeToNextService = minTimeToNextService; - timeToNextEvent = minTimeToNextEvent; -} - -void AnimationControllerPrivate::scheduleServiceForRenderer(RenderObject& renderer) -{ - double timeToNextService = -1; - double timeToNextEvent = -1; - - RefPtr<CompositeAnimation> compAnim = m_compositeAnimations.get(&renderer); - if (compAnim->hasAnimations()) { - timeToNextService = compAnim->timeToNextService(); - timeToNextEvent = compAnim->timeToNextEvent(); - } - - if (timeToNextService >= 0) - scheduleService(timeToNextService, timeToNextEvent); -} - -void AnimationControllerPrivate::scheduleService() -{ - double timeToNextService = -1; - double timeToNextEvent = -1; - updateAnimations(timeToNextService, timeToNextEvent, DoNotCallSetNeedsStyleRecalc); - scheduleService(timeToNextService, timeToNextEvent); -} - -void AnimationControllerPrivate::scheduleService(double timeToNextService, double timeToNextEvent) -{ - if (!m_frame->page()) - return; - - bool visible = m_frame->page()->visibilityState() == WebCore::PageVisibilityStateVisible; - - // This std::max to 1 second limits how often we service animations on background tabs. - // Without this, plus and gmail were recalculating style as every 200ms or even more - // often, burning CPU needlessly for background tabs. - // FIXME: Do we want to fire events at all on background tabs? - if (!visible) - timeToNextService = std::max(timeToNextEvent, 1.0); - - if (visible && !timeToNextService) { - m_frame->document()->view()->scheduleAnimation(); - if (m_animationTimer.isActive()) - m_animationTimer.stop(); - return; - } - - if (timeToNextService < 0) { - if (m_animationTimer.isActive()) - m_animationTimer.stop(); - return; - } - - if (m_animationTimer.isActive() && m_animationTimer.nextFireInterval() <= timeToNextService) - return; - - m_animationTimer.startOneShot(timeToNextService); -} - -void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*) -{ - fireEventsAndUpdateStyle(); -} - -void AnimationControllerPrivate::fireEventsAndUpdateStyle() -{ - // Protect the frame from getting destroyed in the event handler - RefPtr<Frame> protector = m_frame; - - bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_nodeChangesToDispatch.isEmpty(); - - // fire all the events - Vector<EventToDispatch> eventsToDispatch = m_eventsToDispatch; - m_eventsToDispatch.clear(); - Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = eventsToDispatch.end(); - for (Vector<EventToDispatch>::const_iterator it = eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) { - Element* element = it->element.get(); - if (it->eventType == EventTypeNames::transitionend) - element->dispatchEvent(TransitionEvent::create(it->eventType, it->name, it->elapsedTime, PseudoElement::pseudoElementNameForEvents(element->pseudoId()))); - else - element->dispatchEvent(WebKitAnimationEvent::create(it->eventType, it->name, it->elapsedTime)); - } - - // call setChanged on all the elements - Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end(); - for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it) - (*it)->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - - m_nodeChangesToDispatch.clear(); - - if (updateStyle && m_frame) - m_frame->document()->updateStyleIfNeeded(); -} - -void AnimationControllerPrivate::startUpdateStyleIfNeededDispatcher() -{ - if (!m_updateStyleIfNeededDispatcher.isActive()) - m_updateStyleIfNeededDispatcher.startOneShot(0); -} - -void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime) -{ - m_eventsToDispatch.grow(m_eventsToDispatch.size()+1); - EventToDispatch& event = m_eventsToDispatch[m_eventsToDispatch.size()-1]; - event.element = element; - event.eventType = eventType; - event.name = name; - event.elapsedTime = elapsedTime; - - startUpdateStyleIfNeededDispatcher(); -} - -void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node) -{ - if (!node) - return; - - m_nodeChangesToDispatch.append(node); - startUpdateStyleIfNeededDispatcher(); -} - -void AnimationControllerPrivate::serviceAnimations() -{ - double timeToNextService = -1; - double timeToNextEvent = -1; - updateAnimations(timeToNextService, timeToNextEvent, CallSetNeedsStyleRecalc); - scheduleService(timeToNextService, timeToNextEvent); - - // Fire events right away, to avoid a flash of unanimated style after an animation completes, and before - // the 'end' event fires. - fireEventsAndUpdateStyle(); -} - -void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*) -{ - // Make sure animationUpdateTime is updated, so that it is current even if no - // styleChange has happened (e.g. accelerated animations) - setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); - serviceAnimations(); -} - -bool AnimationControllerPrivate::isRunningAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); - if (!animation) - return false; - - return animation->isAnimatingProperty(property, false, isRunningNow); -} - -bool AnimationControllerPrivate::isRunningAcceleratableAnimationOnRenderer(RenderObject *renderer) const -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); - if (!animation) - return false; - - bool acceleratedOnly = false; - bool isRunningNow = true; - return animation->isAnimatingProperty(CSSPropertyOpacity, acceleratedOnly, isRunningNow) - || animation->isAnimatingProperty(CSSPropertyWebkitTransform, acceleratedOnly, isRunningNow) - || animation->isAnimatingProperty(CSSPropertyWebkitFilter, acceleratedOnly, isRunningNow); -} - -bool AnimationControllerPrivate::isRunningAcceleratedAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); - if (!animation) - return false; - - return animation->isAnimatingProperty(property, true, isRunningNow); -} - -void AnimationControllerPrivate::pauseAnimationsForTesting(double t) -{ - RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); - for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { - it->value->pauseAnimationsForTesting(t); - it->key->node()->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - } -} - -double AnimationControllerPrivate::beginAnimationUpdateTime() -{ - if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet) - m_beginAnimationUpdateTime = currentTime(); - return m_beginAnimationUpdateTime; -} - -void AnimationControllerPrivate::endAnimationUpdate() -{ - styleAvailable(); - if (m_animationsWaitingForAsyncStartNotification.isEmpty()) - startTimeResponse(beginAnimationUpdateTime()); -} - -void AnimationControllerPrivate::receivedStartTimeResponse(double time) -{ - startTimeResponse(time); -} - -PassRefPtr<RenderStyle> AnimationControllerPrivate::getAnimatedStyleForRenderer(RenderObject* renderer) -{ - if (!renderer) - return 0; - - RefPtr<CompositeAnimation> rendererAnimations = m_compositeAnimations.get(renderer); - if (!rendererAnimations) - return renderer->style(); - - RefPtr<RenderStyle> animatingStyle = rendererAnimations->getAnimatedStyle(); - if (!animatingStyle) - animatingStyle = renderer->style(); - - return animatingStyle.release(); -} - -unsigned AnimationControllerPrivate::numberOfActiveAnimations(Document* document) const -{ - unsigned count = 0; - - RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); - for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { - RenderObject* renderer = it->key; - CompositeAnimation* compAnim = it->value.get(); - if (renderer->document() == document) - count += compAnim->numberOfActiveAnimations(); - } - - return count; -} - -void AnimationControllerPrivate::addToAnimationsWaitingForStyle(AnimationBase* animation) -{ - // Make sure this animation is not in the start time waiters - m_animationsWaitingForStartTimeResponse.remove(animation); - m_animationsWaitingForAsyncStartNotification.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 - 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::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()). - // In that case we don't need to add it to this list. We just set a waitingForAResponse flag - // which says we are waiting for the response. If willGetResponse is false, this animation - // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for - // another animation to which it will sync. - // - // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is - // true. If so, we just return and will do our work when the first notifyXXXStarted() call - // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will - // do our work right away. In both cases we call the onAnimationStartResponse() method - // on each animation. In the first case we send in the time we got from notifyXXXStarted(). - // In the second case, we just pass in the beginAnimationUpdateTime(). - // - // This will synchronize all software and accelerated animations started in the same - // updateStyleIfNeeded cycle. - // - - if (willGetResponse) - m_animationsWaitingForAsyncStartNotification.add(animation); - - m_animationsWaitingForStartTimeResponse.add(animation); -} - -void AnimationControllerPrivate::removeFromAnimationsWaitingForStartTimeResponse(AnimationBase* animationToRemove) -{ - m_animationsWaitingForStartTimeResponse.remove(animationToRemove); - m_animationsWaitingForAsyncStartNotification.remove(animationToRemove); -} - -void AnimationControllerPrivate::startTimeResponse(double time) -{ - // Go through list of waiters and send them on their way - - WaitingAnimationsSet::const_iterator it = m_animationsWaitingForStartTimeResponse.begin(); - WaitingAnimationsSet::const_iterator end = m_animationsWaitingForStartTimeResponse.end(); - for (; it != end; ++it) - (*it)->onAnimationStartResponse(time); - - m_animationsWaitingForStartTimeResponse.clear(); - m_animationsWaitingForAsyncStartNotification.clear(); -} - -void AnimationControllerPrivate::animationWillBeRemoved(AnimationBase* animation) -{ - removeFromAnimationsWaitingForStyle(animation); - removeFromAnimationsWaitingForStartTimeResponse(animation); -} - -AnimationController::AnimationController(Frame* frame) - : m_data(adoptPtr(new AnimationControllerPrivate(frame))) - , m_beginAnimationUpdateCount(0) -{ -} - -AnimationController::~AnimationController() -{ -} - -void AnimationController::cancelAnimations(RenderObject* renderer) -{ - if (!m_data->hasAnimations()) - return; - - if (m_data->clear(renderer)) { - if (Node* node = renderer->node()) - node->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - } -} - -PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject& renderer, RenderStyle& newStyle) -{ - RenderStyle* oldStyle = renderer.style(); - - if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle.animations() && !newStyle.transitions())) - return PassRefPtr<RenderStyle>(newStyle); - - // Don't run transitions when printing. - if (renderer.view()->document().printing()) - return PassRefPtr<RenderStyle>(newStyle); - - // Fetch our current set of implicit animations from a hashtable. We then compare them - // against the animations in the style and make sure we're in sync. If destination values - // have changed, we reset the animation. We then do a blend to get new values and we return - // a new style. - - // We don't support anonymous pseudo elements like :first-line or :first-letter. - ASSERT(renderer.node()); - - RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer); - RefPtr<RenderStyle> blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle); - - if (renderer.parent() || newStyle.animations() || (oldStyle && oldStyle->animations())) { - m_data->scheduleServiceForRenderer(renderer); - } - - if (blendedStyle != &newStyle) { - // If the animations/transitions change opacity or transform, we need to update - // the style to impose the stacking rules. Note that this is also - // done in StyleResolver::adjustRenderStyle(). - if (blendedStyle->hasAutoZIndex() && (blendedStyle->opacity() < 1.0f || blendedStyle->hasTransform())) - blendedStyle->setZIndex(0); - } - return blendedStyle.release(); -} - -PassRefPtr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderObject* renderer) -{ - return m_data->getAnimatedStyleForRenderer(renderer); -} - -void AnimationController::notifyAnimationStarted(RenderObject*, double startTime) -{ - m_data->receivedStartTimeResponse(startTime); -} - -void AnimationController::pauseAnimationsForTesting(double t) -{ - m_data->pauseAnimationsForTesting(t); -} - -unsigned AnimationController::numberOfActiveAnimations(Document* document) const -{ - return m_data->numberOfActiveAnimations(document); -} - -bool AnimationController::isRunningAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - return m_data->isRunningAnimationOnRenderer(renderer, property, isRunningNow); -} - -bool AnimationController::isRunningAcceleratableAnimationOnRenderer(RenderObject* renderer) const -{ - return m_data->isRunningAcceleratableAnimationOnRenderer(renderer); -} - -bool AnimationController::isRunningAcceleratedAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - return m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property, isRunningNow); -} - -void AnimationController::serviceAnimations() -{ - m_data->serviceAnimations(); -} - -void AnimationController::beginAnimationUpdate() -{ - if (!m_beginAnimationUpdateCount) - m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); - ++m_beginAnimationUpdateCount; -} - -void AnimationController::endAnimationUpdate() -{ - ASSERT(m_beginAnimationUpdateCount > 0); - --m_beginAnimationUpdateCount; - if (!m_beginAnimationUpdateCount) - m_data->endAnimationUpdate(); -} - -bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property) -{ - return CSSPropertyAnimation::animationOfPropertyIsAccelerated(property); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.h b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.h deleted file mode 100644 index 01cf32699ba..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AnimationController_h -#define AnimationController_h - -#include "CSSPropertyNames.h" -#include "wtf/Forward.h" -#include "wtf/OwnPtr.h" - -namespace WebCore { - -class AnimationBase; -class AnimationControllerPrivate; -class Document; -class Element; -class Frame; -class Node; -class RenderObject; -class RenderStyle; - -class AnimationController { -public: - AnimationController(Frame*); - ~AnimationController(); - - void cancelAnimations(RenderObject*); - PassRefPtr<RenderStyle> updateAnimations(RenderObject&, RenderStyle& newStyle); - PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderObject*); - - // This is called when an accelerated animation or transition has actually started to animate. - void notifyAnimationStarted(RenderObject*, double startTime); - - void pauseAnimationsForTesting(double t); - unsigned numberOfActiveAnimations(Document*) const; // To be used only for testing - - bool isRunningAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const; - bool isRunningAcceleratableAnimationOnRenderer(RenderObject*) const; - bool isRunningAcceleratedAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const; - - void serviceAnimations(); - - void beginAnimationUpdate(); - void endAnimationUpdate(); - - static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID); - -private: - OwnPtr<AnimationControllerPrivate> m_data; - int m_beginAnimationUpdateCount; -}; - -class AnimationUpdateBlock { -public: - explicit AnimationUpdateBlock(AnimationController* animationController) - : m_animationController(animationController) - { - if (m_animationController) - m_animationController->beginAnimationUpdate(); - } - - explicit AnimationUpdateBlock(AnimationController& animationController) - : m_animationController(&animationController) - { - m_animationController->beginAnimationUpdate(); - } - - ~AnimationUpdateBlock() - { - if (m_animationController) - m_animationController->endAnimationUpdate(); - } - - AnimationController* m_animationController; -}; - -} // namespace WebCore - -#endif // AnimationController_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationControllerPrivate.h b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationControllerPrivate.h deleted file mode 100644 index 671ec89b573..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationControllerPrivate.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AnimationControllerPrivate_h -#define AnimationControllerPrivate_h - -#include "CSSPropertyNames.h" -#include "platform/Timer.h" -#include "wtf/HashMap.h" -#include "wtf/HashSet.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefPtr.h" -#include "wtf/Vector.h" -#include "wtf/text/AtomicString.h" -#include "wtf/text/WTFString.h" - -namespace WebCore { - -class AnimationBase; -class CompositeAnimation; -class Document; -class Element; -class Frame; -class Node; -class RenderObject; -class RenderStyle; - -enum SetNeedsStyleRecalc { - DoNotCallSetNeedsStyleRecalc = 0, - CallSetNeedsStyleRecalc = 1 -}; - -class AnimationControllerPrivate { - WTF_MAKE_NONCOPYABLE(AnimationControllerPrivate); WTF_MAKE_FAST_ALLOCATED; -public: - AnimationControllerPrivate(Frame*); - ~AnimationControllerPrivate(); - - void updateAnimations(double& timeToNextService, double& timeToNextEvent, SetNeedsStyleRecalc callSetNeedsStyleRecalc = DoNotCallSetNeedsStyleRecalc); - void scheduleService(); - - PassRefPtr<CompositeAnimation> accessCompositeAnimation(RenderObject&); - bool clear(RenderObject*); - - void updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*); - void startUpdateStyleIfNeededDispatcher(); - void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime); - void addNodeChangeToDispatch(PassRefPtr<Node>); - - bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); } - - void serviceAnimations(); - - bool isRunningAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow) const; - bool isRunningAcceleratableAnimationOnRenderer(RenderObject*) const; - bool isRunningAcceleratedAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow) const; - - void pauseAnimationsForTesting(double t); - unsigned numberOfActiveAnimations(Document*) const; - - PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderObject* renderer); - - double beginAnimationUpdateTime(); - void setBeginAnimationUpdateTime(double t) { m_beginAnimationUpdateTime = t; } - void endAnimationUpdate(); - void receivedStartTimeResponse(double); - - void addToAnimationsWaitingForStyle(AnimationBase*); - void removeFromAnimationsWaitingForStyle(AnimationBase*); - - void addToAnimationsWaitingForStartTimeResponse(AnimationBase*, bool willGetResponse); - void removeFromAnimationsWaitingForStartTimeResponse(AnimationBase*); - - void animationWillBeRemoved(AnimationBase*); - - void scheduleServiceForRenderer(RenderObject&); - -private: - void animationTimerFired(Timer<AnimationControllerPrivate>*); - - void scheduleService(double timeToNextService, double timeToNextEvent); - - void styleAvailable(); - void fireEventsAndUpdateStyle(); - void startTimeResponse(double t); - - typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap; - - RenderObjectAnimationMap m_compositeAnimations; - Timer<AnimationControllerPrivate> m_animationTimer; - Timer<AnimationControllerPrivate> m_updateStyleIfNeededDispatcher; - Frame* m_frame; - - class EventToDispatch { - public: - RefPtr<Element> element; - AtomicString eventType; - String name; - double elapsedTime; - }; - - Vector<EventToDispatch> m_eventsToDispatch; - Vector<RefPtr<Node> > m_nodeChangesToDispatch; - - double m_beginAnimationUpdateTime; - - typedef HashSet<RefPtr<AnimationBase> > WaitingAnimationsSet; - WaitingAnimationsSet m_animationsWaitingForStyle; - WaitingAnimationsSet m_animationsWaitingForStartTimeResponse; - WaitingAnimationsSet m_animationsWaitingForAsyncStartNotification; -}; - -} // namespace WebCore - -#endif // AnimationControllerPrivate_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.cpp deleted file mode 100644 index 4d07ebf1e86..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.cpp +++ /dev/null @@ -1,1153 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/CSSPropertyAnimation.h" - -#include <algorithm> -#include "StylePropertyShorthand.h" -#include "core/animation/css/CSSAnimations.h" -#include "core/css/CSSCrossfadeValue.h" -#include "core/css/CSSImageValue.h" -#include "core/css/CSSPrimitiveValue.h" -#include "core/fetch/ImageResource.h" -#include "core/frame/animation/AnimationBase.h" -#include "core/rendering/ClipPathOperation.h" -#include "core/rendering/RenderBox.h" -#include "core/rendering/style/RenderStyle.h" -#include "core/rendering/style/ShadowList.h" -#include "core/rendering/style/StyleFetchedImage.h" -#include "core/rendering/style/StyleGeneratedImage.h" -#include "platform/FloatConversion.h" -#include "wtf/Noncopyable.h" - -namespace WebCore { - -template <typename T> -static inline T blendFunc(const AnimationBase*, T from, T to, double progress) -{ - return blend(from, to, progress); -} - -static inline float blendFunc(const AnimationBase*, float from, float to, double progress) -{ - return narrowPrecisionToFloat(from + (to - from) * progress); -} - -static inline Color blendFunc(const AnimationBase*, const Color& from, const Color& to, double progress) -{ - return blend(from, to, progress); -} - -static inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress) -{ - return to.blend(from, progress, ValueRangeAll); -} - -static inline BorderImageLength blendFunc(const AnimationBase* anim, const BorderImageLength& from, const BorderImageLength& to, double progress) -{ - if (from.isNumber() && to.isNumber()) - return BorderImageLength(blendFunc(anim, from.number(), to.number(), progress)); - - if (from.isLength() && to.isLength()) - return BorderImageLength(blendFunc(anim, from.length(), to.length(), progress)); - - // FIXME: Converting numbers to lengths using the computed border - // width would make it possible to interpolate between numbers and - // lengths. - // https://code.google.com/p/chromium/issues/detail?id=316164 - return to; -} - -static inline BorderImageLengthBox blendFunc(const AnimationBase* anim, const BorderImageLengthBox& from, - const BorderImageLengthBox& to, double progress) -{ - return BorderImageLengthBox(blendFunc(anim, from.top(), to.top(), progress), - blendFunc(anim, from.right(), to.right(), progress), - blendFunc(anim, from.bottom(), to.bottom(), progress), - blendFunc(anim, from.left(), to.left(), progress)); -} - -static inline LengthSize blendFunc(const AnimationBase* anim, const LengthSize& from, const LengthSize& to, double progress) -{ - return LengthSize(blendFunc(anim, from.width(), to.width(), progress), - blendFunc(anim, from.height(), to.height(), progress)); -} - -static inline LengthPoint blendFunc(const AnimationBase* anim, const LengthPoint& from, const LengthPoint& to, double progress) -{ - return LengthPoint(blendFunc(anim, from.x(), to.x(), progress), blendFunc(anim, from.y(), to.y(), progress)); -} - -static inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress) -{ - if (anim->isTransformFunctionListValid()) - return to.blendByMatchingOperations(from, progress); - return to.blendByUsingMatrixInterpolation(from, progress); -} - -static inline PassRefPtr<ClipPathOperation> blendFunc(const AnimationBase*, ClipPathOperation* from, ClipPathOperation* to, double progress) -{ - // Other clip-path operations than BasicShapes can not be animated. - if (!from || !to || from->type() != ClipPathOperation::SHAPE || to->type() != ClipPathOperation::SHAPE) - return to; - - const BasicShape* fromShape = toShapeClipPathOperation(from)->basicShape(); - const BasicShape* toShape = toShapeClipPathOperation(to)->basicShape(); - - if (!fromShape->canBlend(toShape)) - return to; - - return ShapeClipPathOperation::create(toShape->blend(fromShape, progress)); -} - -static inline PassRefPtr<ShapeValue> blendFunc(const AnimationBase*, ShapeValue* from, ShapeValue* to, double progress) -{ - // FIXME Bug 102723: Shape-inside should be able to animate a value of 'outside-shape' when shape-outside is set to a BasicShape - if (!from || !to || from->type() != ShapeValue::Shape || to->type() != ShapeValue::Shape) - return to; - - const BasicShape* fromShape = from->shape(); - const BasicShape* toShape = to->shape(); - - if (!fromShape->canBlend(toShape)) - return to; - - return ShapeValue::createShapeValue(toShape->blend(fromShape, progress)); -} - -static inline FilterOperations blendFunc(const AnimationBase* anim, const FilterOperations& from, const FilterOperations& to, double progress) -{ - FilterOperations result; - - // If we have a filter function list, use that to do a per-function animation. - if (anim->filterFunctionListsMatch()) { - size_t fromSize = from.operations().size(); - size_t toSize = to.operations().size(); - size_t size = max(fromSize, toSize); - for (size_t i = 0; i < size; i++) { - const FilterOperation* fromOp = (i < fromSize) ? from.operations()[i].get() : 0; - const FilterOperation* toOp = (i < toSize) ? to.operations()[i].get() : 0; - RefPtr<FilterOperation> blendedOp = FilterOperation::blend(fromOp, toOp, progress); - if (blendedOp) - result.operations().append(blendedOp); - else - ASSERT_NOT_REACHED(); - } - } else { - // If the filter function lists don't match, we could try to cross-fade, but don't yet have a way to represent that in CSS. - // For now we'll just fail to animate. - result = to; - } - - return result; -} - -static inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from, EVisibility to, double progress) -{ - // Any non-zero result means we consider the object to be visible. Only at 0 do we consider the object to be - // invisible. The invisible value we use (HIDDEN vs. COLLAPSE) depends on the specified from/to values. - double fromVal = from == VISIBLE ? 1. : 0.; - double toVal = to == VISIBLE ? 1. : 0.; - if (fromVal == toVal) - return to; - double result = blendFunc(anim, fromVal, toVal, progress); - return result > 0. ? VISIBLE : (to != VISIBLE ? to : from); -} - -static inline LengthBox blendFunc(const AnimationBase* anim, const LengthBox& from, const LengthBox& to, double progress) -{ - // Length types have to match to animate - if (from.top().type() != to.top().type() - || from.right().type() != to.right().type() - || from.bottom().type() != to.bottom().type() - || from.left().type() != to.left().type()) - return to; - - LengthBox result(blendFunc(anim, from.top(), to.top(), progress), - blendFunc(anim, from.right(), to.right(), progress), - blendFunc(anim, from.bottom(), to.bottom(), progress), - blendFunc(anim, from.left(), to.left(), progress)); - return result; -} - -static inline SVGLength blendFunc(const AnimationBase*, const SVGLength& from, const SVGLength& to, double progress) -{ - return to.blend(from, narrowPrecisionToFloat(progress)); -} - -static inline Vector<SVGLength> blendFunc(const AnimationBase*, const Vector<SVGLength>& from, const Vector<SVGLength>& to, double progress) -{ - size_t fromLength = from.size(); - size_t toLength = to.size(); - if (!fromLength) - return !progress ? from : to; - if (!toLength) - return progress == 1 ? from : to; - - size_t resultLength = fromLength; - if (fromLength != toLength) { - if (!(fromLength % toLength)) - resultLength = fromLength; - else if (!(toLength % fromLength)) - resultLength = toLength; - else - resultLength = fromLength * toLength; - } - Vector<SVGLength> result(resultLength); - for (size_t i = 0; i < resultLength; ++i) - result[i] = to[i % toLength].blend(from[i % fromLength], narrowPrecisionToFloat(progress)); - return result; -} - -static inline PassRefPtr<StyleImage> crossfadeBlend(const AnimationBase*, StyleFetchedImage* fromStyleImage, StyleFetchedImage* toStyleImage, double progress) -{ - // If progress is at one of the extremes, we want getComputedStyle to show the image, - // not a completed cross-fade, so we hand back one of the existing images. - if (!progress) - return fromStyleImage; - if (progress == 1) - return toStyleImage; - - ImageResource* fromImageResource = static_cast<ImageResource*>(fromStyleImage->data()); - ImageResource* toImageResource = static_cast<ImageResource*>(toStyleImage->data()); - - RefPtr<CSSImageValue> fromImageValue = CSSImageValue::create(fromImageResource->url(), fromStyleImage); - RefPtr<CSSImageValue> toImageValue = CSSImageValue::create(toImageResource->url(), toStyleImage); - RefPtr<CSSCrossfadeValue> crossfadeValue = CSSCrossfadeValue::create(fromImageValue, toImageValue); - - crossfadeValue->setPercentage(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER)); - - return StyleGeneratedImage::create(crossfadeValue.get()); -} - -static inline PassRefPtr<StyleImage> blendFunc(const AnimationBase* anim, StyleImage* from, StyleImage* to, double progress) -{ - if (!from || !to) - return to; - - if (from->isImageResource() && to->isImageResource()) - return crossfadeBlend(anim, toStyleFetchedImage(from), toStyleFetchedImage(to), progress); - - // FIXME: Support transitioning generated images as well. (gradients, etc.) - - return to; -} - -class AnimationPropertyWrapperBase { - WTF_MAKE_NONCOPYABLE(AnimationPropertyWrapperBase); - WTF_MAKE_FAST_ALLOCATED; -public: - AnimationPropertyWrapperBase(CSSPropertyID prop) - : m_prop(prop) - { - } - - virtual ~AnimationPropertyWrapperBase() { } - - virtual bool isShorthandWrapper() const { return false; } - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0; - virtual void blend(const AnimationBase*, RenderStyle*, const RenderStyle*, const RenderStyle*, double) const = 0; - - CSSPropertyID property() const { return m_prop; } - - virtual bool animationIsAccelerated() const { return false; } - -private: - CSSPropertyID m_prop; -}; - -static int gPropertyWrapperMap[numCSSProperties]; -static const int cInvalidPropertyWrapperIndex = -1; -static Vector<AnimationPropertyWrapperBase*>* gPropertyWrappers = 0; - -static void addPropertyWrapper(CSSPropertyID propertyID, AnimationPropertyWrapperBase* wrapper) -{ - int propIndex = propertyID - firstCSSProperty; - - ASSERT(gPropertyWrapperMap[propIndex] == cInvalidPropertyWrapperIndex); - - unsigned wrapperIndex = gPropertyWrappers->size(); - gPropertyWrappers->append(wrapper); - gPropertyWrapperMap[propIndex] = wrapperIndex; -} - -static AnimationPropertyWrapperBase* wrapperForProperty(CSSPropertyID propertyID) -{ - int propIndex = propertyID - firstCSSProperty; - if (propIndex >= 0 && propIndex < numCSSProperties) { - int wrapperIndex = gPropertyWrapperMap[propIndex]; - if (wrapperIndex >= 0) - return (*gPropertyWrappers)[wrapperIndex]; - } - return 0; -} - -template <typename T> -class PropertyWrapperGetter : public AnimationPropertyWrapperBase { -public: - PropertyWrapperGetter(CSSPropertyID prop, T (RenderStyle::*getter)() const) - : AnimationPropertyWrapperBase(prop) - , m_getter(getter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if ((!a && !b) || a == b) - return true; - if (!a || !b) - return false; - return (a->*m_getter)() == (b->*m_getter)(); - } - -protected: - T (RenderStyle::*m_getter)() const; -}; - -template <typename T> -class PropertyWrapper : public PropertyWrapperGetter<T> { -public: - PropertyWrapper(CSSPropertyID prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T)) - : PropertyWrapperGetter<T>(prop, getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T>::m_getter)(), (b->*PropertyWrapperGetter<T>::m_getter)(), progress)); - } - -protected: - void (RenderStyle::*m_setter)(T); -}; - -class NonNegativeLengthWrapper : public PropertyWrapper<Length> { -public: - NonNegativeLengthWrapper(CSSPropertyID prop, Length (RenderStyle::*getter)() const, void (RenderStyle::*setter)(Length)) - : PropertyWrapper<Length>(prop, getter, setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - Length from = (a->*PropertyWrapperGetter<Length>::m_getter)(); - Length to = (b->*PropertyWrapperGetter<Length>::m_getter)(); - (dst->*PropertyWrapper<Length>::m_setter)(to.blend(from, progress, ValueRangeNonNegative)); - } -}; - -template <typename T> -class RefCountedPropertyWrapper : public PropertyWrapperGetter<T*> { -public: - RefCountedPropertyWrapper(CSSPropertyID prop, T* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<T>)) - : PropertyWrapperGetter<T*>(prop, getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T*>::m_getter)(), (b->*PropertyWrapperGetter<T*>::m_getter)(), progress)); - } - -protected: - void (RenderStyle::*m_setter)(PassRefPtr<T>); -}; - - -class PropertyWrapperClipPath : public RefCountedPropertyWrapper<ClipPathOperation> { -public: - PropertyWrapperClipPath(CSSPropertyID prop, ClipPathOperation* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ClipPathOperation>)) - : RefCountedPropertyWrapper<ClipPathOperation>(prop, getter, setter) - { - } -}; - -class PropertyWrapperShape : public RefCountedPropertyWrapper<ShapeValue> { -public: - PropertyWrapperShape(CSSPropertyID prop, ShapeValue* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShapeValue>)) - : RefCountedPropertyWrapper<ShapeValue>(prop, getter, setter) - { - } -}; - -class StyleImagePropertyWrapper : public RefCountedPropertyWrapper<StyleImage> { -public: - StyleImagePropertyWrapper(CSSPropertyID prop, StyleImage* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<StyleImage>)) - : RefCountedPropertyWrapper<StyleImage>(prop, getter, setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if (a == b) - return true; - if (!a || !b) - return false; - - StyleImage* imageA = (a->*m_getter)(); - StyleImage* imageB = (b->*m_getter)(); - return StyleImage::imagesEquivalent(imageA, imageB); - } -}; - -class PropertyWrapperColor : public PropertyWrapperGetter<Color> { -public: - PropertyWrapperColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) - : PropertyWrapperGetter<Color>(prop, getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<Color>::m_getter)(), (b->*PropertyWrapperGetter<Color>::m_getter)(), progress)); - } - -protected: - void (RenderStyle::*m_setter)(const Color&); -}; - -class PropertyWrapperAcceleratedOpacity : public PropertyWrapper<float> { -public: - PropertyWrapperAcceleratedOpacity() - : PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity) - { - } - - virtual bool animationIsAccelerated() const { return true; } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - float fromOpacity = a->opacity(); - - // This makes sure we put the object being animated into a RenderLayer during the animation - dst->setOpacity(blendFunc(anim, (fromOpacity == 1) ? 0.999999f : fromOpacity, b->opacity(), progress)); - } -}; - -class PropertyWrapperAcceleratedTransform : public PropertyWrapper<const TransformOperations&> { -public: - PropertyWrapperAcceleratedTransform() - : PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform) - { - } - - virtual bool animationIsAccelerated() const { return true; } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - dst->setTransform(blendFunc(anim, a->transform(), b->transform(), progress)); - } -}; - -class PropertyWrapperAcceleratedFilter : public PropertyWrapper<const FilterOperations&> { -public: - PropertyWrapperAcceleratedFilter() - : PropertyWrapper<const FilterOperations&>(CSSPropertyWebkitFilter, &RenderStyle::filter, &RenderStyle::setFilter) - { - } - - virtual bool animationIsAccelerated() const { return true; } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - dst->setFilter(blendFunc(anim, a->filter(), b->filter(), progress)); - } -}; - -class PropertyWrapperShadow : public AnimationPropertyWrapperBase { -public: - PropertyWrapperShadow(CSSPropertyID prop, ShadowList* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShadowList>)) - : AnimationPropertyWrapperBase(prop) - , m_getter(getter) - , m_setter(setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - const ShadowList* shadowA = (a->*m_getter)(); - const ShadowList* shadowB = (b->*m_getter)(); - if (shadowA == shadowB) - return true; - if (shadowA && shadowB) - return *shadowA == *shadowB; - return false; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(ShadowList::blend((a->*m_getter)(), (b->*m_getter)(), progress)); - } - - ShadowList* (RenderStyle::*m_getter)() const; - void (RenderStyle::*m_setter)(PassRefPtr<ShadowList>); -}; - -class PropertyWrapperMaybeInvalidColor : public AnimationPropertyWrapperBase { -public: - PropertyWrapperMaybeInvalidColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_getter(getter) - , m_setter(setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return true; - - if (!fromColor.isValid()) - fromColor = a->color(); - if (!toColor.isValid()) - toColor = b->color(); - - return fromColor == toColor; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return; - - if (!fromColor.isValid()) - fromColor = a->color(); - if (!toColor.isValid()) - toColor = b->color(); - (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress)); - } - -private: - Color (RenderStyle::*m_getter)() const; - void (RenderStyle::*m_setter)(const Color&); -}; - - -enum MaybeInvalidColorTag { MaybeInvalidColor }; -class PropertyWrapperVisitedAffectedColor : public AnimationPropertyWrapperBase { -public: - PropertyWrapperVisitedAffectedColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&), - Color (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_wrapper(adoptPtr(new PropertyWrapperColor(prop, getter, setter))) - , m_visitedWrapper(adoptPtr(new PropertyWrapperColor(prop, visitedGetter, visitedSetter))) - { - } - PropertyWrapperVisitedAffectedColor(CSSPropertyID prop, MaybeInvalidColorTag, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&), - Color (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_wrapper(adoptPtr(new PropertyWrapperMaybeInvalidColor(prop, getter, setter))) - , m_visitedWrapper(adoptPtr(new PropertyWrapperMaybeInvalidColor(prop, visitedGetter, visitedSetter))) - { - } - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - return m_wrapper->equals(a, b) && m_visitedWrapper->equals(a, b); - } - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - m_wrapper->blend(anim, dst, a, b, progress); - m_visitedWrapper->blend(anim, dst, a, b, progress); - } - -private: - OwnPtr<AnimationPropertyWrapperBase> m_wrapper; - OwnPtr<AnimationPropertyWrapperBase> m_visitedWrapper; -}; - -// Wrapper base class for an animatable property in a FillLayer -class FillLayerAnimationPropertyWrapperBase { -public: - FillLayerAnimationPropertyWrapperBase() - { - } - - virtual ~FillLayerAnimationPropertyWrapperBase() { } - - virtual bool equals(const FillLayer*, const FillLayer*) const = 0; - virtual void blend(const AnimationBase*, FillLayer*, const FillLayer*, const FillLayer*, double) const = 0; -}; - -template <typename T> -class FillLayerPropertyWrapperGetter : public FillLayerAnimationPropertyWrapperBase { - WTF_MAKE_NONCOPYABLE(FillLayerPropertyWrapperGetter); -public: - FillLayerPropertyWrapperGetter(T (FillLayer::*getter)() const) - : m_getter(getter) - { - } - - virtual bool equals(const FillLayer* a, const FillLayer* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if ((!a && !b) || a == b) - return true; - if (!a || !b) - return false; - return (a->*m_getter)() == (b->*m_getter)(); - } - -protected: - T (FillLayer::*m_getter)() const; -}; - -template <typename T> -class FillLayerPropertyWrapper : public FillLayerPropertyWrapperGetter<T> { -public: - FillLayerPropertyWrapper(T (FillLayer::*getter)() const, void (FillLayer::*setter)(T)) - : FillLayerPropertyWrapperGetter<T>(getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T>::m_getter)(), progress)); - } - -protected: - void (FillLayer::*m_setter)(T); -}; - -template <typename T> -class FillLayerRefCountedPropertyWrapper : public FillLayerPropertyWrapperGetter<T*> { -public: - FillLayerRefCountedPropertyWrapper(T* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<T>)) - : FillLayerPropertyWrapperGetter<T*>(getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), progress)); - } - -protected: - void (FillLayer::*m_setter)(PassRefPtr<T>); -}; - -class FillLayerStyleImagePropertyWrapper : public FillLayerRefCountedPropertyWrapper<StyleImage> { -public: - FillLayerStyleImagePropertyWrapper(StyleImage* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<StyleImage>)) - : FillLayerRefCountedPropertyWrapper<StyleImage>(getter, setter) - { - } - - virtual bool equals(const FillLayer* a, const FillLayer* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if (a == b) - return true; - if (!a || !b) - return false; - - StyleImage* imageA = (a->*m_getter)(); - StyleImage* imageB = (b->*m_getter)(); - return StyleImage::imagesEquivalent(imageA, imageB); - } -}; - - -class FillLayersPropertyWrapper : public AnimationPropertyWrapperBase { -public: - typedef const FillLayer* (RenderStyle::*LayersGetter)() const; - typedef FillLayer* (RenderStyle::*LayersAccessor)(); - - FillLayersPropertyWrapper(CSSPropertyID prop, LayersGetter getter, LayersAccessor accessor) - : AnimationPropertyWrapperBase(prop) - , m_layersGetter(getter) - , m_layersAccessor(accessor) - { - switch (prop) { - case CSSPropertyBackgroundPositionX: - case CSSPropertyWebkitMaskPositionX: - m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::xPosition, &FillLayer::setXPosition); - break; - case CSSPropertyBackgroundPositionY: - case CSSPropertyWebkitMaskPositionY: - m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::yPosition, &FillLayer::setYPosition); - break; - case CSSPropertyBackgroundSize: - case CSSPropertyWebkitBackgroundSize: - case CSSPropertyWebkitMaskSize: - m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<LengthSize>(&FillLayer::sizeLength, &FillLayer::setSizeLength); - break; - case CSSPropertyBackgroundImage: - m_fillLayerPropertyWrapper = new FillLayerStyleImagePropertyWrapper(&FillLayer::image, &FillLayer::setImage); - break; - default: - break; - } - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - const FillLayer* fromLayer = (a->*m_layersGetter)(); - const FillLayer* toLayer = (b->*m_layersGetter)(); - - while (fromLayer && toLayer) { - if (!m_fillLayerPropertyWrapper->equals(fromLayer, toLayer)) - return false; - - fromLayer = fromLayer->next(); - toLayer = toLayer->next(); - } - - return true; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - const FillLayer* aLayer = (a->*m_layersGetter)(); - const FillLayer* bLayer = (b->*m_layersGetter)(); - FillLayer* dstLayer = (dst->*m_layersAccessor)(); - - while (aLayer && bLayer && dstLayer) { - m_fillLayerPropertyWrapper->blend(anim, dstLayer, aLayer, bLayer, progress); - aLayer = aLayer->next(); - bLayer = bLayer->next(); - dstLayer = dstLayer->next(); - } - } - -private: - FillLayerAnimationPropertyWrapperBase* m_fillLayerPropertyWrapper; - - LayersGetter m_layersGetter; - LayersAccessor m_layersAccessor; -}; - -class ShorthandPropertyWrapper : public AnimationPropertyWrapperBase { -public: - ShorthandPropertyWrapper(CSSPropertyID property, const StylePropertyShorthand& shorthand) - : AnimationPropertyWrapperBase(property) - { - for (unsigned i = 0; i < shorthand.length(); ++i) { - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(shorthand.properties()[i]); - if (wrapper) - m_propertyWrappers.append(wrapper); - } - } - - virtual bool isShorthandWrapper() const { return true; } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); - for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) { - if (!(*it)->equals(a, b)) - return false; - } - return true; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); - for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) - (*it)->blend(anim, dst, a, b, progress); - } - - const Vector<AnimationPropertyWrapperBase*> propertyWrappers() const { return m_propertyWrappers; } - -private: - Vector<AnimationPropertyWrapperBase*> m_propertyWrappers; -}; - -class PropertyWrapperFlex : public AnimationPropertyWrapperBase { -public: - PropertyWrapperFlex() - : AnimationPropertyWrapperBase(CSSPropertyFlex) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if ((!a && !b) || a == b) - return true; - if (!a || !b) - return false; - - return a->flexBasis() == b->flexBasis() && a->flexGrow() == b->flexGrow() && a->flexShrink() == b->flexShrink(); - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - dst->setFlexBasis(blendFunc(anim, a->flexBasis(), b->flexBasis(), progress)); - dst->setFlexGrow(blendFunc(anim, a->flexGrow(), b->flexGrow(), progress)); - dst->setFlexShrink(blendFunc(anim, a->flexShrink(), b->flexShrink(), progress)); - } -}; - -class PropertyWrapperSVGPaint : public AnimationPropertyWrapperBase { -public: - PropertyWrapperSVGPaint(CSSPropertyID prop, const SVGPaint::SVGPaintType& (RenderStyle::*paintTypeGetter)() const, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_paintTypeGetter(paintTypeGetter) - , m_getter(getter) - , m_setter(setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - if ((a->*m_paintTypeGetter)() != (b->*m_paintTypeGetter)()) - return false; - - // We only support animations between SVGPaints that are pure Color values. - // For everything else we must return true for this method, otherwise - // we will try to animate between values forever. - if ((a->*m_paintTypeGetter)() == SVGPaint::SVG_PAINTTYPE_RGBCOLOR) { - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return true; - - if (!fromColor.isValid()) - fromColor = Color(); - if (!toColor.isValid()) - toColor = Color(); - - return fromColor == toColor; - } - return true; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - if ((a->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR - || (b->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR) - return; - - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return; - - if (!fromColor.isValid()) - fromColor = Color(); - if (!toColor.isValid()) - toColor = Color(); - (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress)); - } - -private: - const SVGPaint::SVGPaintType& (RenderStyle::*m_paintTypeGetter)() const; - Color (RenderStyle::*m_getter)() const; - void (RenderStyle::*m_setter)(const Color&); -}; - -static void addShorthandProperties() -{ - static const CSSPropertyID animatableShorthandProperties[] = { - CSSPropertyBackground, // for background-color, background-position, background-image - CSSPropertyBackgroundPosition, - CSSPropertyFont, // for font-size, font-weight - CSSPropertyWebkitMask, // for mask-position - CSSPropertyWebkitMaskPosition, - CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft, - CSSPropertyBorderColor, - CSSPropertyBorderRadius, - CSSPropertyBorderWidth, - CSSPropertyBorder, - CSSPropertyBorderImage, - CSSPropertyBorderSpacing, - CSSPropertyListStyle, // for list-style-image - CSSPropertyMargin, - CSSPropertyOutline, - CSSPropertyPadding, - CSSPropertyWebkitTextStroke, - CSSPropertyWebkitColumnRule, - CSSPropertyWebkitBorderRadius, - CSSPropertyWebkitTransformOrigin - }; - - for (size_t i = 0; i < WTF_ARRAY_LENGTH(animatableShorthandProperties); ++i) { - CSSPropertyID propertyID = animatableShorthandProperties[i]; - StylePropertyShorthand shorthand = shorthandForProperty(propertyID); - if (shorthand.length() > 0) - addPropertyWrapper(propertyID, new ShorthandPropertyWrapper(propertyID, shorthand)); - } -} - -void CSSPropertyAnimation::ensurePropertyMap() -{ - // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed? - if (gPropertyWrappers) - return; - - gPropertyWrappers = new Vector<AnimationPropertyWrapperBase*>(); - - // build the list of property wrappers to do the comparisons and blends - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom)); - - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth)); - - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight)); - - if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) - gPropertyWrappers->append(new PropertyWrapperFlex()); - - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth)); - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth)); - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth)); - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderBottomWidth, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyColor, &RenderStyle::color, &RenderStyle::setColor, &RenderStyle::visitedLinkColor, &RenderStyle::setVisitedLinkColor)); - - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor, &RenderStyle::visitedLinkBackgroundColor, &RenderStyle::setVisitedLinkBackgroundColor)); - - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundImage, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyListStyleImage, &RenderStyle::listStyleImage, &RenderStyle::setListStyleImage)); - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskImage, &RenderStyle::maskImage, &RenderStyle::setMaskImage)); - - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyBorderImageSource, &RenderStyle::borderImageSource, &RenderStyle::setBorderImageSource)); - gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyBorderImageSlice, &RenderStyle::borderImageSlices, &RenderStyle::setBorderImageSlices)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageWidth, &RenderStyle::borderImageWidth, &RenderStyle::setBorderImageWidth)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageOutset, &RenderStyle::borderImageOutset, &RenderStyle::setBorderImageOutset)); - - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskBoxImageSource, &RenderStyle::maskBoxImageSource, &RenderStyle::setMaskBoxImageSource)); - gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyWebkitMaskBoxImageSlice, &RenderStyle::maskBoxImageSlices, &RenderStyle::setMaskBoxImageSlices)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageWidth, &RenderStyle::maskBoxImageWidth, &RenderStyle::setMaskBoxImageWidth)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageOutset, &RenderStyle::maskBoxImageOutset, &RenderStyle::setMaskBoxImageOutset)); - - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionX, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionY, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionX, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionY, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskSize, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); - - gPropertyWrappers->append(new PropertyWrapper<LengthPoint>(CSSPropertyObjectPosition, &RenderStyle::objectPosition, &RenderStyle::setObjectPosition)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFontSize, - // Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size - // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same). - // FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to - // enable text zoom rather than Text Autosizing? See http://crbug.com/227545. - &RenderStyle::specifiedFontSize, - &RenderStyle::setFontSize)); - gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap)); - gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderVerticalSpacing, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing)); - gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyOrphans, &RenderStyle::orphans, &RenderStyle::setOrphans)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWidows, &RenderStyle::widows, &RenderStyle::setWidows)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight)); - gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset)); - gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius)); - gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoomWithoutReturnValue)); - - gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyClip, &RenderStyle::clip, &RenderStyle::setClip)); - - gPropertyWrappers->append(new PropertyWrapperAcceleratedOpacity()); - gPropertyWrappers->append(new PropertyWrapperAcceleratedTransform()); - gPropertyWrappers->append(new PropertyWrapperAcceleratedFilter()); - - gPropertyWrappers->append(new PropertyWrapperClipPath(CSSPropertyWebkitClipPath, &RenderStyle::clipPath, &RenderStyle::setClipPath)); - - gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeInside, &RenderStyle::shapeInside, &RenderStyle::setShapeInside)); - gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeOutside, &RenderStyle::shapeOutside, &RenderStyle::setShapeOutside)); - gPropertyWrappers->append(new NonNegativeLengthWrapper(CSSPropertyShapeMargin, &RenderStyle::shapeMargin, &RenderStyle::setShapeMargin)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyShapeImageThreshold, &RenderStyle::shapeImageThreshold, &RenderStyle::setShapeImageThreshold)); - - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitColumnRuleColor, MaybeInvalidColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor, &RenderStyle::visitedLinkColumnRuleColor, &RenderStyle::setVisitedLinkColumnRuleColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitTextStrokeColor, MaybeInvalidColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor, &RenderStyle::visitedLinkTextStrokeColor, &RenderStyle::setVisitedLinkTextStrokeColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderLeftColor, MaybeInvalidColor, &RenderStyle::borderLeftColor, &RenderStyle::setBorderLeftColor, &RenderStyle::visitedLinkBorderLeftColor, &RenderStyle::setVisitedLinkBorderLeftColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderRightColor, MaybeInvalidColor, &RenderStyle::borderRightColor, &RenderStyle::setBorderRightColor, &RenderStyle::visitedLinkBorderRightColor, &RenderStyle::setVisitedLinkBorderRightColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderTopColor, MaybeInvalidColor, &RenderStyle::borderTopColor, &RenderStyle::setBorderTopColor, &RenderStyle::visitedLinkBorderTopColor, &RenderStyle::setVisitedLinkBorderTopColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderBottomColor, MaybeInvalidColor, &RenderStyle::borderBottomColor, &RenderStyle::setBorderBottomColor, &RenderStyle::visitedLinkBorderBottomColor, &RenderStyle::setVisitedLinkBorderBottomColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyOutlineColor, MaybeInvalidColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor, &RenderStyle::visitedLinkOutlineColor, &RenderStyle::setVisitedLinkOutlineColor)); - - gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow)); - gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow)); - gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow)); - - gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyFill, &RenderStyle::fillPaintType, &RenderStyle::fillPaintColor, &RenderStyle::setFillPaintColor)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFillOpacity, &RenderStyle::fillOpacity, &RenderStyle::setFillOpacity)); - - gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyStroke, &RenderStyle::strokePaintType, &RenderStyle::strokePaintColor, &RenderStyle::setStrokePaintColor)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity)); - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeWidth, &RenderStyle::strokeWidth, &RenderStyle::setStrokeWidth)); - gPropertyWrappers->append(new PropertyWrapper< Vector<SVGLength> >(CSSPropertyStrokeDasharray, &RenderStyle::strokeDashArray, &RenderStyle::setStrokeDashArray)); - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeDashoffset, &RenderStyle::strokeDashOffset, &RenderStyle::setStrokeDashOffset)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeMiterlimit, &RenderStyle::strokeMiterLimit, &RenderStyle::setStrokeMiterLimit)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFloodOpacity, &RenderStyle::floodOpacity, &RenderStyle::setFloodOpacity)); - gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyFloodColor, &RenderStyle::floodColor, &RenderStyle::setFloodColor)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStopOpacity, &RenderStyle::stopOpacity, &RenderStyle::setStopOpacity)); - gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyStopColor, &RenderStyle::stopColor, &RenderStyle::setStopColor)); - - gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyLightingColor, &RenderStyle::lightingColor, &RenderStyle::setLightingColor)); - - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyBaselineShift, &RenderStyle::baselineShiftValue, &RenderStyle::setBaselineShiftValue)); - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyKerning, &RenderStyle::kerning, &RenderStyle::setKerning)); - - if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()) { - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexGrow, &RenderStyle::flexGrow, &RenderStyle::setFlexGrow)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexShrink, &RenderStyle::flexShrink, &RenderStyle::setFlexShrink)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyFlexBasis, &RenderStyle::flexBasis, &RenderStyle::setFlexBasis)); - } - - // TODO: - // - // CSSPropertyVerticalAlign - // - // Compound properties that have components that should be animatable: - // - // CSSPropertyWebkitColumns - // CSSPropertyWebkitBoxReflect - - // Make sure unused slots have a value - for (unsigned int i = 0; i < static_cast<unsigned int>(numCSSProperties); ++i) - gPropertyWrapperMap[i] = cInvalidPropertyWrapperIndex; - - // First we put the non-shorthand property wrappers into the map, so the shorthand-building - // code can find them. - size_t n = gPropertyWrappers->size(); - for (unsigned int i = 0; i < n; ++i) { - CSSPropertyID property = (*gPropertyWrappers)[i]->property(); - ASSERT_WITH_MESSAGE(RuntimeEnabledFeatures::webAnimationsCSSEnabled() || CSSAnimations::isAnimatableProperty(property), "%s is not whitelisted for animation", getPropertyNameString(property).utf8().data()); - ASSERT(property - firstCSSProperty < numCSSProperties); - gPropertyWrapperMap[property - firstCSSProperty] = i; - } - - // Now add the shorthand wrappers. - addShorthandProperties(); -} - -// Returns true if we need to start animation timers -bool CSSPropertyAnimation::blendProperties(const AnimationBase* anim, CSSPropertyID prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) -{ - ASSERT(prop != CSSPropertyInvalid); - - ensurePropertyMap(); - - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); - if (wrapper) { - wrapper->blend(anim, dst, a, b, progress); - return !wrapper->animationIsAccelerated() || !anim->isAccelerated(); - } - - return false; -} - -bool CSSPropertyAnimation::animationOfPropertyIsAccelerated(CSSPropertyID prop) -{ - ensurePropertyMap(); - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); - return wrapper ? wrapper->animationIsAccelerated() : false; -} - -bool CSSPropertyAnimation::propertiesEqual(CSSPropertyID prop, const RenderStyle* a, const RenderStyle* b) -{ - ensurePropertyMap(); - - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); - if (wrapper) - return wrapper->equals(a, b); - return true; -} - -CSSPropertyID CSSPropertyAnimation::getPropertyAtIndex(int i, bool& isShorthand) -{ - ensurePropertyMap(); - - if (i < 0 || i >= getNumProperties()) - return CSSPropertyInvalid; - - AnimationPropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; - isShorthand = wrapper->isShorthandWrapper(); - return wrapper->property(); -} - -int CSSPropertyAnimation::getNumProperties() -{ - ensurePropertyMap(); - - return gPropertyWrappers->size(); -} - -} diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.cpp deleted file mode 100644 index f20f6856683..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/CompositeAnimation.h" - -#include "CSSPropertyNames.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/rendering/style/RenderStyle.h" - -namespace WebCore { - -CompositeAnimation::~CompositeAnimation() -{ - // Toss the refs to all animations, but make sure we remove them from - // any waiting lists first. - - clearRenderer(); - m_transitions.clear(); - m_keyframeAnimations.clear(); -} - -void CompositeAnimation::clearRenderer() -{ - if (!m_transitions.isEmpty()) { - // Clear the renderers from all running animations, in case we are in the middle of - // an animation callback (see https://bugs.webkit.org/show_bug.cgi?id=22052) - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->value.get(); - animationController()->animationWillBeRemoved(transition); - transition->clear(); - } - } - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->value.get(); - animationController()->animationWillBeRemoved(anim); - anim->clear(); - } - } -} - -void CompositeAnimation::updateTransitions(RenderObject& renderer, RenderStyle* currentStyle, RenderStyle& targetStyle) -{ - // If currentStyle is null or there are no old or new transitions, just skip it - if (!currentStyle || (!targetStyle.transitions() && m_transitions.isEmpty())) - return; - - // Mark all existing transitions as no longer active. We will mark the still active ones - // in the next loop and then toss the ones that didn't get marked. - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) - it->value->setActive(false); - - RefPtr<RenderStyle> modifiedCurrentStyle; - - // Check to see if we need to update the active transitions - if (targetStyle.transitions()) { - for (size_t i = 0; i < targetStyle.transitions()->size(); ++i) { - const CSSAnimationData* anim = targetStyle.transitions()->animation(i); - bool isActiveTransition = anim->duration() || anim->delay() > 0; - - CSSAnimationData::AnimationMode mode = anim->animationMode(); - if (mode == CSSAnimationData::AnimateNone) - continue; - - CSSPropertyID prop = anim->property(); - - bool all = mode == CSSAnimationData::AnimateAll; - - // Handle both the 'all' and single property cases. For the single prop case, we make only one pass - // through the loop. - for (int propertyIndex = 0; propertyIndex < CSSPropertyAnimation::getNumProperties(); ++propertyIndex) { - if (all) { - // Get the next property which is not a shorthand. - bool isShorthand; - prop = CSSPropertyAnimation::getPropertyAtIndex(propertyIndex, isShorthand); - if (isShorthand) - continue; - } - - // ImplicitAnimations are always hashed by actual properties, never animateAll. - ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties)); - - // If there is a running animation for this property, the transition is overridden - // and we have to use the unanimatedStyle from the animation. We do the test - // against the unanimated style here, but we "override" the transition later. - RefPtr<KeyframeAnimation> keyframeAnim = getAnimationForProperty(prop); - RenderStyle* fromStyle = keyframeAnim ? keyframeAnim->unanimatedStyle() : currentStyle; - - // See if there is a current transition for this prop - ImplicitAnimation* implAnim = m_transitions.get(prop); - bool equal = true; - - if (implAnim) { - // If we are post active don't bother setting the active flag. This will cause - // this animation to get removed at the end of this function. - if (!implAnim->postActive()) - implAnim->setActive(true); - - // This might be a transition that is just finishing. That would be the case - // if it were postActive. But we still need to check for equality because - // it could be just finishing AND changing to a new goal state. - // - // This implAnim might also not be an already running transition. It might be - // newly added to the list in a previous iteration. This would happen if - // you have both an explicit transition-property and 'all' in the same - // list. In this case, the latter one overrides the earlier one, so we - // behave as though this is a running animation being replaced. - if (!implAnim->isTargetPropertyEqual(prop, &targetStyle)) { - // For accelerated animations we need to return a new RenderStyle with the _current_ value - // of the property, so that restarted transitions use the correct starting point. - if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(prop) && implAnim->isAccelerated()) { - if (!modifiedCurrentStyle) - modifiedCurrentStyle = RenderStyle::clone(currentStyle); - - implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get()); - } - animationController()->animationWillBeRemoved(implAnim); - m_transitions.remove(prop); - equal = false; - } - } else { - // We need to start a transition if it is active and the properties don't match - equal = !isActiveTransition || CSSPropertyAnimation::propertiesEqual(prop, fromStyle, &targetStyle); - } - - // We can be in this loop with an inactive transition (!isActiveTransition). We need - // to do that to check to see if we are canceling a transition. But we don't want to - // start one of the inactive transitions. So short circuit that here. (See - // <https://bugs.webkit.org/show_bug.cgi?id=24787> - if (!equal && isActiveTransition) { - // Add the new transition - m_transitions.set(prop, ImplicitAnimation::create(const_cast<CSSAnimationData*>(anim), prop, renderer, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle)); - } - - // We only need one pass for the single prop case - if (!all) - break; - } - } - } - - // Make a list of transitions to be removed - Vector<int> toBeRemoved; - end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (!anim->active()) { - animationController()->animationWillBeRemoved(anim); - toBeRemoved.append(anim->animatingProperty()); - } - } - - // Now remove the transitions from the list - for (size_t j = 0; j < toBeRemoved.size(); ++j) - m_transitions.remove(toBeRemoved[j]); -} - -void CompositeAnimation::updateKeyframeAnimations(RenderObject& renderer, RenderStyle* currentStyle, RenderStyle& targetStyle) -{ - // Nothing to do if we don't have any animations, and didn't have any before - if (m_keyframeAnimations.isEmpty() && !targetStyle.hasAnimations()) - return; - - AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); - - if (currentStyle && currentStyle->hasAnimations() && targetStyle.hasAnimations() && *(currentStyle->animations()) == *(targetStyle.animations())) { - // The current and target animations are the same so we just need to toss any - // animation which is finished (postActive). - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { - if (it->value->postActive()) - it->value->setIndex(-1); - } - } else { - // Mark all existing animations as no longer active. - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) - it->value->setIndex(-1); - - // Toss the animation order map. - m_keyframeAnimationOrderList.clear(); - - DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::ConstructFromLiteral)); - - // Now mark any still active animations as active and add any new animations. - if (targetStyle.animations()) { - int numAnims = targetStyle.animations()->size(); - for (int i = 0; i < numAnims; ++i) { - const CSSAnimationData* anim = targetStyle.animations()->animation(i); - if (!anim->isValidAnimation()) - continue; - - // See if there is a current animation for this name. - AtomicString name(anim->name()); - RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(name); - if (keyframeAnim) { - // If this animation is postActive, skip it so it gets removed at the end of this function. - if (keyframeAnim->postActive()) - continue; - - // This one is still active. - - // Animations match, but play states may differ. Update if needed. - keyframeAnim->updatePlayState(anim->playState()); - - // Set the saved animation to this new one, just in case the play state has changed. - keyframeAnim->setAnimation(anim); - keyframeAnim->setIndex(i); - } else if ((anim->duration() || anim->delay()) && anim->iterationCount() && name != none) { - keyframeAnim = KeyframeAnimation::create(const_cast<CSSAnimationData*>(anim), renderer, i, this, targetStyle); - m_keyframeAnimations.set(name, keyframeAnim); - } - - // Add this to the animation order map. - if (keyframeAnim) - m_keyframeAnimationOrderList.append(name); - } - } - } - - // Make a list of animations to be removed. - Vector<AtomicString> animsToBeRemoved; - kfend = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { - KeyframeAnimation* keyframeAnim = it->value.get(); - if (keyframeAnim->index() < 0) { - animsToBeRemoved.append(keyframeAnim->name()); - animationController()->animationWillBeRemoved(keyframeAnim); - keyframeAnim->clear(); - } - } - - // Now remove the animations from the list, and keep stale keys out of the order list. - if (animsToBeRemoved.size()) { - for (size_t j = 0; j < animsToBeRemoved.size(); ++j) { - ASSERT(m_keyframeAnimations.contains(animsToBeRemoved[j])); - m_keyframeAnimations.remove(animsToBeRemoved[j]); - } - Vector<AtomicString> newOrderList; - for (size_t j = 0; j < m_keyframeAnimationOrderList.size(); ++j) { - AtomicString key = m_keyframeAnimationOrderList[j]; - if (m_keyframeAnimations.contains(key)) - newOrderList.append(key); - } - m_keyframeAnimationOrderList.swap(newOrderList); - } -} - -PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject& renderer, RenderStyle* currentStyle, RenderStyle& targetStyle) -{ - RefPtr<RenderStyle> resultStyle; - - // We don't do any transitions if we don't have a currentStyle (on startup). - updateTransitions(renderer, currentStyle, targetStyle); - updateKeyframeAnimations(renderer, currentStyle, targetStyle); - - if (currentStyle) { - // Now that we have transition objects ready, let them know about the new goal state. We want them - // to fill in a RenderStyle*& only if needed. - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - if (ImplicitAnimation* anim = it->value.get()) - anim->animate(this, &renderer, currentStyle, &targetStyle, resultStyle); - } - } - } - - // Now that we have animation objects ready, let them know about the new goal state. We want them - // to fill in a RenderStyle*& only if needed. - for (Vector<AtomicString>::const_iterator it = m_keyframeAnimationOrderList.begin(); it != m_keyframeAnimationOrderList.end(); ++it) { - RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(*it); - ASSERT(keyframeAnim); - keyframeAnim->animate(this, &renderer, currentStyle, &targetStyle, resultStyle); - } - - return resultStyle ? resultStyle.release() : PassRefPtr<RenderStyle>(targetStyle); -} - -PassRefPtr<RenderStyle> CompositeAnimation::getAnimatedStyle() const -{ - RefPtr<RenderStyle> resultStyle; - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - if (ImplicitAnimation* implicitAnimation = it->value.get()) - implicitAnimation->getAnimatedStyle(resultStyle); - } - - for (Vector<AtomicString>::const_iterator it = m_keyframeAnimationOrderList.begin(); it != m_keyframeAnimationOrderList.end(); ++it) { - RefPtr<KeyframeAnimation> keyframeAnimation = m_keyframeAnimations.get(*it); - ASSERT(keyframeAnimation); - keyframeAnimation->getAnimatedStyle(resultStyle); - } - - return resultStyle; -} - -double CompositeAnimation::timeToNextService() const -{ - // Returns the time at which next service is required. -1 means no service is required. 0 means - // service is required now, and > 0 means service is required that many seconds in the future. - double minT = -1; - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->value.get(); - double t = transition ? transition->timeToNextService() : -1; - if (t < minT || minT == -1) - minT = t; - if (minT == 0) - return 0; - } - } - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* animation = it->value.get(); - double t = animation ? animation->timeToNextService() : -1; - if (t < minT || minT == -1) - minT = t; - if (minT == 0) - return 0; - } - } - - return minT; -} - -double CompositeAnimation::timeToNextEvent() const -{ - // Returns the time at which next service to trigger events is required. -1 means no service is required. 0 means - // service is required now, and > 0 means service is required that many seconds in the future. - double minT = -1; - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->value.get(); - double t = -1; - bool isLooping; - if (transition) - transition->getTimeToNextEvent(t, isLooping); - if (t < minT || minT == -1) - minT = t; - if (!minT) - return 0; - } - } - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* animation = it->value.get(); - double t = -1; - bool isLooping; - if (animation) - animation->getTimeToNextEvent(t, isLooping); - if (t < minT || minT == -1) - minT = t; - if (!minT) - return 0; - } - } - - return minT; -} - -PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(CSSPropertyID property) const -{ - RefPtr<KeyframeAnimation> retval; - - // We want to send back the last animation with the property if there are multiples. - // So we need to iterate through all animations - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - RefPtr<KeyframeAnimation> anim = it->value; - if (anim->hasAnimationForProperty(property)) - retval = anim; - } - } - - return retval; -} - -void CompositeAnimation::overrideImplicitAnimations(CSSPropertyID property) -{ - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - if (!m_transitions.isEmpty()) { - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim && anim->animatingProperty() == property) - anim->setOverridden(true); - } - } -} - -void CompositeAnimation::resumeOverriddenImplicitAnimations(CSSPropertyID property) -{ - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim && anim->animatingProperty() == property) - anim->setOverridden(false); - } - } -} - -bool CompositeAnimation::isAnimatingProperty(CSSPropertyID property, bool acceleratedOnly, bool isRunningNow) const -{ - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->value.get(); - if (anim && anim->isAnimatingProperty(property, acceleratedOnly, isRunningNow)) - return true; - } - } - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim && anim->isAnimatingProperty(property, acceleratedOnly, isRunningNow)) - return true; - } - } - return false; -} - -void CompositeAnimation::pauseAnimationsForTesting(double t) -{ - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - RefPtr<KeyframeAnimation> keyframeAnim = it->value; - if (!keyframeAnim || !keyframeAnim->running()) - continue; - - double count = keyframeAnim->m_animation->iterationCount(); - if ((t >= 0.0) && ((count == CSSAnimationData::IterationCountInfinite) || (t <= count * keyframeAnim->duration()))) - keyframeAnim->freezeAtTime(t); - } - - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - RefPtr<ImplicitAnimation> implAnim = it->value; - - if (!implAnim->running()) - continue; - - if ((t >= 0.0) && (t <= implAnim->duration())) - implAnim->freezeAtTime(t); - } -} - -unsigned CompositeAnimation::numberOfActiveAnimations() const -{ - unsigned count = 0; - - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->value.get(); - if (anim->running()) - ++count; - } - } - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim->running()) - ++count; - } - } - - return count; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.h b/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.h deleted file mode 100644 index ee0bd467288..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CompositeAnimation_h -#define CompositeAnimation_h - -#include "core/frame/animation/ImplicitAnimation.h" -#include "core/frame/animation/KeyframeAnimation.h" -#include "wtf/HashMap.h" - -namespace WebCore { - -class AnimationControllerPrivate; -class AnimationController; -class RenderObject; -class RenderStyle; - -// A CompositeAnimation represents a collection of animations that are running -// on a single RenderObject, such as a number of properties transitioning at once. -class CompositeAnimation : public RefCounted<CompositeAnimation> { -public: - static PassRefPtr<CompositeAnimation> create(AnimationControllerPrivate* animationController) - { - return adoptRef(new CompositeAnimation(animationController)); - }; - - ~CompositeAnimation(); - - void clearRenderer(); - - PassRefPtr<RenderStyle> animate(RenderObject&, RenderStyle* currentStyle, RenderStyle& targetStyle); - PassRefPtr<RenderStyle> getAnimatedStyle() const; - - double timeToNextService() const; - double timeToNextEvent() const; - - AnimationControllerPrivate* animationController() const { return m_animationController; } - - bool hasAnimations() const { return !m_transitions.isEmpty() || !m_keyframeAnimations.isEmpty(); } - - bool isAnimatingProperty(CSSPropertyID, bool acceleratedOnly, bool isRunningNow) const; - - PassRefPtr<KeyframeAnimation> getAnimationForProperty(CSSPropertyID) const; - - void overrideImplicitAnimations(CSSPropertyID); - void resumeOverriddenImplicitAnimations(CSSPropertyID); - - void pauseAnimationsForTesting(double t); - unsigned numberOfActiveAnimations() const; - -private: - CompositeAnimation(AnimationControllerPrivate* animationController) - : m_animationController(animationController) - { - } - - void updateTransitions(RenderObject&, RenderStyle* currentStyle, RenderStyle& targetStyle); - void updateKeyframeAnimations(RenderObject&, RenderStyle* currentStyle, RenderStyle& targetStyle); - - typedef HashMap<int, RefPtr<ImplicitAnimation> > CSSPropertyTransitionsMap; - typedef HashMap<AtomicString, RefPtr<KeyframeAnimation> > AnimationNameMap; - - AnimationControllerPrivate* m_animationController; - CSSPropertyTransitionsMap m_transitions; - AnimationNameMap m_keyframeAnimations; - Vector<AtomicString> m_keyframeAnimationOrderList; -}; - -} // namespace WebCore - -#endif // CompositeAnimation_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.cpp deleted file mode 100644 index 2cf82b64b2b..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/UseCounter.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/frame/animation/ImplicitAnimation.h" -#include "core/frame/animation/KeyframeAnimation.h" -#include "core/rendering/RenderBoxModelObject.h" -#include "public/platform/Platform.h" - -namespace WebCore { - -ImplicitAnimation::ImplicitAnimation(const CSSAnimationData* transition, CSSPropertyID animatingProperty, RenderObject& renderer, CompositeAnimation* compAnim, RenderStyle* fromStyle) - : AnimationBase(transition, renderer, compAnim) - , m_transitionProperty(transition->property()) - , m_animatingProperty(animatingProperty) - , m_overridden(false) - , m_active(true) - , m_fromStyle(fromStyle) -{ - ASSERT(animatingProperty != CSSPropertyInvalid); - blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(m_animatingProperty)); -} - -ImplicitAnimation::~ImplicitAnimation() -{ - // // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. - if (!postActive()) - endAnimation(); -} - -bool ImplicitAnimation::shouldSendEventForListener(Document::ListenerType inListenerType) const -{ - return m_object->document().hasListenerType(inListenerType); -} - -void ImplicitAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) -{ - // If we get this far and the animation is done, it means we are cleaning up a just finished animation. - // So just return. Everything is already all cleaned up. - if (postActive()) - return; - - // Reset to start the transition if we are new - if (isNew()) - reset(targetStyle); - - // Run a cycle of animation. - // We know we will need a new render style, so make one if needed - if (!animatedStyle) - animatedStyle = RenderStyle::clone(targetStyle); - - bool needsAnim = CSSPropertyAnimation::blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); - // FIXME: we also need to detect cases where we have to software animate for other reasons, - // such as a child using inheriting the transform. https://bugs.webkit.org/show_bug.cgi?id=23902 - if (!needsAnim) - // If we are running an accelerated animation, set a flag in the style which causes the style - // to compare as different to any other style. This ensures that changes to the property - // that is animating are correctly detected during the animation (e.g. when a transition - // gets interrupted). - animatedStyle->setIsRunningAcceleratedAnimation(); - - // Fire the start timeout if needed - fireAnimationEventsIfNeeded(); -} - -void ImplicitAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle) -{ - if (!animatedStyle) - animatedStyle = RenderStyle::clone(m_toStyle.get()); - - CSSPropertyAnimation::blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); -} - -void ImplicitAnimation::startAnimation(double timeOffset) -{ - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking) - m_isAccelerated = toRenderBoxModelObject(m_object)->startTransition(timeOffset, m_animatingProperty, m_fromStyle.get(), m_toStyle.get()); -} - -void ImplicitAnimation::pauseAnimation(double timeOffset) -{ - if (!m_object) - return; - - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->transitionPaused(timeOffset, m_animatingProperty); - - // Restore the original (unanimated) style - if (!paused()) - setNeedsStyleRecalc(m_object->node()); -} - -void ImplicitAnimation::endAnimation() -{ - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->transitionFinished(m_animatingProperty); - m_isAccelerated = false; -} - -void ImplicitAnimation::onAnimationEnd(double elapsedTime) -{ - // If we have a keyframe animation on this property, this transition is being overridden. The keyframe - // animation keeps an unanimated style in case a transition starts while the keyframe animation is - // running. But now that the transition has completed, we need to update this style with its new - // destination. If we didn't, the next time through we would think a transition had started - // (comparing the old unanimated style with the new final style of the transition). - RefPtr<KeyframeAnimation> keyframeAnim = m_compAnim->getAnimationForProperty(m_animatingProperty); - if (keyframeAnim) - keyframeAnim->setUnanimatedStyle(m_toStyle); - - sendTransitionEvent(EventTypeNames::transitionend, elapsedTime); - endAnimation(); -} - -bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, double elapsedTime) -{ - if (eventType == EventTypeNames::transitionend) { - Document::ListenerType listenerType = Document::TRANSITIONEND_LISTENER; - - if (shouldSendEventForListener(listenerType)) { - String propertyName = getPropertyNameString(m_animatingProperty); - - // Dispatch the event - RefPtr<Element> element = 0; - if (m_object->node() && m_object->node()->isElementNode()) - element = toElement(m_object->node()); - - if (!element) - return false; - - // Schedule event handling - m_compAnim->animationController()->addEventToDispatch(element, eventType, propertyName, elapsedTime); - - // Restore the original (unanimated) style - if (eventType == EventTypeNames::transitionend && element->renderer()) - setNeedsStyleRecalc(element.get()); - - return true; // Did dispatch an event - } - } - - return false; // Didn't dispatch an event -} - -void ImplicitAnimation::reset(RenderStyle* to) -{ - ASSERT(to); - ASSERT(m_fromStyle); - - m_toStyle = to; - - // Restart the transition - if (m_fromStyle && m_toStyle) - updateStateMachine(AnimationStateInputRestartAnimation, -1); - - // set the transform animation list - validateTransformFunctionList(); - checkForMatchingFilterFunctionLists(); -} - -void ImplicitAnimation::setOverridden(bool b) -{ - if (b == m_overridden) - return; - - m_overridden = b; - updateStateMachine(m_overridden ? AnimationStateInputPauseOverride : AnimationStateInputResumeOverride, -1); -} - -bool ImplicitAnimation::affectsProperty(CSSPropertyID property) const -{ - return (m_animatingProperty == property); -} - -bool ImplicitAnimation::isTargetPropertyEqual(CSSPropertyID prop, const RenderStyle* targetStyle) -{ - // We can get here for a transition that has not started yet. This would make m_toStyle unset and null. - // So we check that here (see <https://bugs.webkit.org/show_bug.cgi?id=26706>) - if (!m_toStyle) - return false; - return CSSPropertyAnimation::propertiesEqual(prop, m_toStyle.get(), targetStyle); -} - -void ImplicitAnimation::blendPropertyValueInStyle(CSSPropertyID prop, RenderStyle* currentStyle) -{ - // We should never add a transition with a 0 duration and delay. But if we ever did - // it would have a null toStyle. So just in case, let's check that here. (See - // <https://bugs.webkit.org/show_bug.cgi?id=24787> - if (!m_toStyle) - return; - - CSSPropertyAnimation::blendProperties(this, prop, currentStyle, m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); -} - -void ImplicitAnimation::validateTransformFunctionList() -{ - m_transformFunctionListValid = false; - - if (!m_fromStyle || !m_toStyle) - return; - - const TransformOperations* val = &m_fromStyle->transform(); - const TransformOperations* toVal = &m_toStyle->transform(); - - if (val->operations().isEmpty()) - val = toVal; - - if (val->operations().isEmpty()) - return; - - // An emtpy transform list matches anything. - if (val != toVal && !toVal->operations().isEmpty() && !val->operationsMatch(*toVal)) - return; - - // Transform lists match. - m_transformFunctionListValid = true; -} - -void ImplicitAnimation::checkForMatchingFilterFunctionLists() -{ - m_filterFunctionListsMatch = false; - - if (!m_fromStyle || !m_toStyle) - return; - - const FilterOperations* val = &m_fromStyle->filter(); - const FilterOperations* toVal = &m_toStyle->filter(); - - if (!val->canInterpolateWith(*toVal)) - return; - - // Filter lists match. - m_filterFunctionListsMatch = true; -} - -double ImplicitAnimation::timeToNextService() -{ - double t = AnimationBase::timeToNextService(); - if (t != 0 || preActive()) - return t; - - // A return value of 0 means we need service. But if this is an accelerated animation we - // only need service at the end of the transition. - if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(m_animatingProperty) && isAccelerated()) { - bool isLooping; - getTimeToNextEvent(t, isLooping); - } - - return t; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.h b/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.h deleted file mode 100644 index c531b36a81d..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ImplicitAnimation_h -#define ImplicitAnimation_h - -#include "CSSPropertyNames.h" -#include "core/dom/Document.h" -#include "core/frame/animation/AnimationBase.h" - -namespace WebCore { - -// An ImplicitAnimation tracks the state of a transition of a specific CSS property -// for a single RenderObject. -class ImplicitAnimation : public AnimationBase { -public: - static PassRefPtr<ImplicitAnimation> create(const CSSAnimationData* animation, CSSPropertyID animatingProperty, RenderObject& renderer, CompositeAnimation* compositeAnimation, RenderStyle* fromStyle) - { - return adoptRef(new ImplicitAnimation(animation, animatingProperty, renderer, compositeAnimation, fromStyle)); - }; - - CSSPropertyID transitionProperty() const { return m_transitionProperty; } - CSSPropertyID animatingProperty() const { return m_animatingProperty; } - - virtual void onAnimationEnd(double elapsedTime); - virtual void startAnimation(double timeOffset); - virtual void pauseAnimation(double /*timeOffset*/); - virtual void endAnimation(); - - virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle); - virtual void getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle); - virtual void reset(RenderStyle* to); - - void setOverridden(bool); - virtual bool overridden() const { return m_overridden; } - - virtual bool affectsProperty(CSSPropertyID) const; - - bool hasStyle() const { return m_fromStyle && m_toStyle; } - - bool isTargetPropertyEqual(CSSPropertyID, const RenderStyle*); - - void blendPropertyValueInStyle(CSSPropertyID, RenderStyle*); - - virtual double timeToNextService(); - - bool active() const { return m_active; } - void setActive(bool b) { m_active = b; } - -protected: - bool shouldSendEventForListener(Document::ListenerType) const; - bool sendTransitionEvent(const AtomicString&, double elapsedTime); - - void validateTransformFunctionList(); - void checkForMatchingFilterFunctionLists(); - -private: - ImplicitAnimation(const CSSAnimationData*, CSSPropertyID, RenderObject&, CompositeAnimation*, RenderStyle*); - virtual ~ImplicitAnimation(); - - CSSPropertyID m_transitionProperty; // Transition property as specified in the RenderStyle. - CSSPropertyID m_animatingProperty; // Specific property for this ImplicitAnimation - bool m_overridden; // true when there is a keyframe animation that overrides the transitioning property - bool m_active; // used for culling the list of transitions - - // The two styles that we are blending. - RefPtr<RenderStyle> m_fromStyle; - RefPtr<RenderStyle> m_toStyle; -}; - -} // namespace WebCore - -#endif // ImplicitAnimation_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.cpp deleted file mode 100644 index 948ca03ce42..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (C) 2007, 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/KeyframeAnimation.h" - -#include "CSSPropertyNames.h" -#include "core/css/resolver/StyleResolver.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/UseCounter.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/rendering/RenderBoxModelObject.h" -#include "core/rendering/style/RenderStyle.h" -#include "public/platform/Platform.h" - -using namespace std; - -namespace WebCore { - -KeyframeAnimation::KeyframeAnimation(const CSSAnimationData* animation, RenderObject& renderer, int index, CompositeAnimation* compAnim, RenderStyle& unanimatedStyle) - : AnimationBase(animation, renderer, compAnim) - , m_keyframes(renderer, animation->name()) - , m_index(index) - , m_startEventDispatched(false) - , m_unanimatedStyle(unanimatedStyle) -{ - // Get the keyframe RenderStyles - if (m_object && m_object->node() && m_object->node()->isElementNode()) - m_object->document().ensureStyleResolver().keyframeStylesForAnimation(toElement(m_object->node()), unanimatedStyle, m_keyframes); - - // Update the m_transformFunctionListValid flag based on whether the function lists in the keyframes match. - validateTransformFunctionList(); - checkForMatchingFilterFunctionLists(); - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) - blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(*it)); -} - -KeyframeAnimation::~KeyframeAnimation() -{ - // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. - if (!postActive()) - endAnimation(); -} - -void KeyframeAnimation::fetchIntervalEndpointsForProperty(CSSPropertyID property, const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const -{ - // Find the first key - double elapsedTime = getElapsedTime(); - if (m_animation->duration() && m_animation->iterationCount() != CSSAnimationData::IterationCountInfinite) - elapsedTime = min(elapsedTime, m_animation->duration() * m_animation->iterationCount()); - - const double fractionalTime = this->fractionalTime(1, elapsedTime, 0); - - size_t numKeyframes = m_keyframes.size(); - if (!numKeyframes) - return; - - ASSERT(!m_keyframes[0].key()); - ASSERT(m_keyframes[m_keyframes.size() - 1].key() == 1); - - size_t currentIndex = 0; - size_t firstIndex = 0; - size_t lastIndex = numKeyframes - 1; - size_t distance = numKeyframes; - - // Find keyframe that is closest to elapsed time. - while (distance > 1) { - currentIndex = (lastIndex + firstIndex) >> 1; - double key = m_keyframes[currentIndex].key(); - distance = lastIndex - currentIndex; - - if (key < fractionalTime) { - if (distance < 2) - currentIndex++; - firstIndex = currentIndex; - } else { - lastIndex = currentIndex; - } - } - - int prevIndex = -1; - int nextIndex = -1; - - // Iterate forward to find next keyframe that is used to animate CSS property. - for (size_t i = currentIndex; i < numKeyframes; ++i) { - const KeyframeValue& keyFrame = m_keyframes[i]; - if (keyFrame.key() > fractionalTime && keyFrame.containsProperty(property)) { - nextIndex = i; - break; - } - } - - // Iterate backward to find previous keyframe. - for (int i = currentIndex; i >= 0; --i) { - const KeyframeValue& keyFrame = m_keyframes[i]; - if (keyFrame.key() <= fractionalTime && keyFrame.containsProperty(property)) { - prevIndex = i; - break; - } - } - - double scale = 1; - double offset = 0; - - if (prevIndex == -1) - prevIndex = 0; - - if (nextIndex == -1) - nextIndex = numKeyframes - 1; - - const KeyframeValue& prevKeyframe = m_keyframes[prevIndex]; - const KeyframeValue& nextKeyframe = m_keyframes[nextIndex]; - - fromStyle = prevKeyframe.style(); - toStyle = nextKeyframe.style(); - - offset = prevKeyframe.key(); - scale = 1.0 / (nextKeyframe.key() - prevKeyframe.key()); - // A scale of infinity is handled in AnimationBase::fractionalTime(). - ASSERT(scale >= 0 && (!std::isinf(scale) || prevIndex == nextIndex)); - - prog = progress(scale, offset, KeyframeValue::timingFunction(*prevKeyframe.style())); -} - -void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) -{ - // Fire the start timeout if needed - fireAnimationEventsIfNeeded(); - - // If we have not yet started, we will not have a valid start time, so just start the animation if needed. - if (isNew() && m_animation->playState() == AnimPlayStatePlaying) - updateStateMachine(AnimationStateInputStartAnimation, -1); - - // If we get this far and the animation is done, it means we are cleaning up a just finished animation. - // If so, we need to send back the targetStyle. - if (postActive()) { - if (!animatedStyle) - animatedStyle = const_cast<RenderStyle*>(targetStyle); - return; - } - - // If we are waiting for the start timer, we don't want to change the style yet. - // Special case 1 - if the delay time is 0, then we do want to set the first frame of the - // animation right away. This avoids a flash when the animation starts. - // Special case 2 - if there is a backwards fill mode, then we want to continue - // through to the style blend so that we get the fromStyle. - if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards()) - return; - - // If we have no keyframes, don't animate. - if (!m_keyframes.size()) { - updateStateMachine(AnimationStateInputEndAnimation, -1); - return; - } - - // Run a cycle of animation. - // We know we will need a new render style, so make one if needed. - if (!animatedStyle) - animatedStyle = RenderStyle::clone(targetStyle); - - // FIXME: we need to be more efficient about determining which keyframes we are animating between. - // We should cache the last pair or something. - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { - // Get the from/to styles and progress between - const RenderStyle* fromStyle = 0; - const RenderStyle* toStyle = 0; - double progress = 0.0; - fetchIntervalEndpointsForProperty(*it, fromStyle, toStyle, progress); - - bool needsAnim = CSSPropertyAnimation::blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress); - if (!needsAnim) - // If we are running an accelerated animation, set a flag in the style - // to indicate it. This can be used to make sure we get an updated - // style for hit testing, etc. - animatedStyle->setIsRunningAcceleratedAnimation(); - } -} - -void KeyframeAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle) -{ - // If we're in the delay phase and we're not backwards filling, tell the caller - // to use the current style. - if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards()) - return; - - if (!m_keyframes.size()) - return; - - if (!animatedStyle) - animatedStyle = RenderStyle::clone(m_object->style()); - - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { - // Get the from/to styles and progress between - const RenderStyle* fromStyle = 0; - const RenderStyle* toStyle = 0; - double progress = 0.0; - fetchIntervalEndpointsForProperty(*it, fromStyle, toStyle, progress); - - CSSPropertyAnimation::blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress); - } -} - -bool KeyframeAnimation::hasAnimationForProperty(CSSPropertyID property) const -{ - return m_keyframes.containsProperty(property); -} - -void KeyframeAnimation::startAnimation(double timeOffset) -{ - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking) - m_isAccelerated = toRenderBoxModelObject(m_object)->startAnimation(timeOffset, m_animation.get(), m_keyframes); -} - -void KeyframeAnimation::pauseAnimation(double timeOffset) -{ - if (!m_object) - return; - - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->animationPaused(timeOffset, m_keyframes.animationName()); - - // Restore the original (unanimated) style - if (!paused()) - setNeedsStyleRecalc(m_object->node()); -} - -void KeyframeAnimation::endAnimation() -{ - if (!m_object) - return; - - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->animationFinished(m_keyframes.animationName()); - m_isAccelerated = false; - - // Restore the original (unanimated) style - if (!paused()) - setNeedsStyleRecalc(m_object->node()); -} - -bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const -{ - return m_object->document().hasListenerType(listenerType); -} - -void KeyframeAnimation::onAnimationStart(double elapsedTime) -{ - sendAnimationEvent(EventTypeNames::animationstart, elapsedTime); -} - -void KeyframeAnimation::onAnimationIteration(double elapsedTime) -{ - sendAnimationEvent(EventTypeNames::animationiteration, elapsedTime); -} - -void KeyframeAnimation::onAnimationEnd(double elapsedTime) -{ - sendAnimationEvent(EventTypeNames::animationend, elapsedTime); - // End the animation if we don't fill forwards. Forward filling - // animations are ended properly in the class destructor. - if (!m_animation->fillsForwards()) - endAnimation(); -} - -bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double elapsedTime) -{ - Document::ListenerType listenerType; - if (eventType == EventTypeNames::animationiteration) - listenerType = Document::ANIMATIONITERATION_LISTENER; - else if (eventType == EventTypeNames::animationend) - listenerType = Document::ANIMATIONEND_LISTENER; - else { - ASSERT(eventType == EventTypeNames::animationstart); - if (m_startEventDispatched) - return false; - m_startEventDispatched = true; - listenerType = Document::ANIMATIONSTART_LISTENER; - } - - if (shouldSendEventForListener(listenerType)) { - // Dispatch the event - RefPtr<Element> element; - if (m_object->node() && m_object->node()->isElementNode()) - element = toElement(m_object->node()); - - if (!element) - return false; - - // Schedule event handling - m_compAnim->animationController()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime); - - // Restore the original (unanimated) style - if (eventType == EventTypeNames::animationend && element->renderer()) - setNeedsStyleRecalc(element.get()); - - return true; // Did dispatch an event - } - - return false; // Did not dispatch an event -} - -void KeyframeAnimation::overrideAnimations() -{ - // This will override implicit animations that match the properties in the keyframe animation - HashSet<CSSPropertyID>::const_iterator end = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != end; ++it) - compositeAnimation()->overrideImplicitAnimations(*it); -} - -void KeyframeAnimation::resumeOverriddenAnimations() -{ - // This will resume overridden implicit animations - HashSet<CSSPropertyID>::const_iterator end = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != end; ++it) - compositeAnimation()->resumeOverriddenImplicitAnimations(*it); -} - -bool KeyframeAnimation::affectsProperty(CSSPropertyID property) const -{ - return m_keyframes.containsProperty(property); -} - -void KeyframeAnimation::validateTransformFunctionList() -{ - m_transformFunctionListValid = false; - - if (m_keyframes.size() < 2 || !m_keyframes.containsProperty(CSSPropertyWebkitTransform)) - return; - - // Empty transforms match anything, so find the first non-empty entry as the reference - size_t numKeyframes = m_keyframes.size(); - size_t firstNonEmptyTransformKeyframeIndex = numKeyframes; - - for (size_t i = 0; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - if (currentKeyframe.style()->transform().operations().size()) { - firstNonEmptyTransformKeyframeIndex = i; - break; - } - } - - if (firstNonEmptyTransformKeyframeIndex == numKeyframes) - return; - - const TransformOperations* firstVal = &m_keyframes[firstNonEmptyTransformKeyframeIndex].style()->transform(); - - // See if the keyframes are valid - for (size_t i = firstNonEmptyTransformKeyframeIndex + 1; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - const TransformOperations* val = ¤tKeyframe.style()->transform(); - - // An emtpy transform list matches anything. - if (val->operations().isEmpty()) - continue; - - if (!firstVal->operationsMatch(*val)) - return; - } - - // Keyframes are valid - m_transformFunctionListValid = true; -} - -void KeyframeAnimation::checkForMatchingFilterFunctionLists() -{ - m_filterFunctionListsMatch = false; - - if (m_keyframes.size() < 2 || !m_keyframes.containsProperty(CSSPropertyWebkitFilter)) - return; - - // Empty filters match anything, so find the first non-empty entry as the reference - size_t numKeyframes = m_keyframes.size(); - size_t firstNonEmptyFilterKeyframeIndex = numKeyframes; - - for (size_t i = 0; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - if (currentKeyframe.style()->filter().operations().size()) { - firstNonEmptyFilterKeyframeIndex = i; - break; - } - } - - if (firstNonEmptyFilterKeyframeIndex == numKeyframes) - return; - - const FilterOperations* firstVal = &m_keyframes[firstNonEmptyFilterKeyframeIndex].style()->filter(); - - for (size_t i = firstNonEmptyFilterKeyframeIndex + 1; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - const FilterOperations* val = ¤tKeyframe.style()->filter(); - - if (!firstVal->canInterpolateWith(*val)) - return; - } - - m_filterFunctionListsMatch = true; -} - -double KeyframeAnimation::timeToNextService() -{ - double t = AnimationBase::timeToNextService(); - if (t != 0 || preActive()) - return t; - - // A return value of 0 means we need service. But if we only have accelerated animations we - // only need service at the end of the transition - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - bool acceleratedPropertiesOnly = true; - - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { - if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(*it) || !isAccelerated()) { - acceleratedPropertiesOnly = false; - break; - } - } - - if (acceleratedPropertiesOnly) { - bool isLooping; - getTimeToNextEvent(t, isLooping); - } - - return t; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.h b/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.h deleted file mode 100644 index 93334d93c62..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef KeyframeAnimation_h -#define KeyframeAnimation_h - -#include "core/dom/Document.h" -#include "core/frame/animation/AnimationBase.h" -#include "core/rendering/style/KeyframeList.h" - -namespace WebCore { - -class RenderStyle; - -// A KeyframeAnimation tracks the state of an explicit animation -// for a single RenderObject. -class KeyframeAnimation : public AnimationBase { -public: - static PassRefPtr<KeyframeAnimation> create(const CSSAnimationData* animation, RenderObject& renderer, int index, CompositeAnimation* compositeAnimation, RenderStyle& unanimatedStyle) - { - return adoptRef(new KeyframeAnimation(animation, renderer, index, compositeAnimation, unanimatedStyle)); - }; - - virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle); - virtual void getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle); - - const AtomicString& name() const { return m_keyframes.animationName(); } - int index() const { return m_index; } - void setIndex(int i) { m_index = i; } - - bool hasAnimationForProperty(CSSPropertyID) const; - - void setUnanimatedStyle(PassRefPtr<RenderStyle> style) { m_unanimatedStyle = style; } - RenderStyle* unanimatedStyle() const { return m_unanimatedStyle.get(); } - - virtual double timeToNextService(); - -protected: - virtual void onAnimationStart(double elapsedTime); - virtual void onAnimationIteration(double elapsedTime); - virtual void onAnimationEnd(double elapsedTime); - virtual void startAnimation(double timeOffset); - virtual void pauseAnimation(double timeOffset); - virtual void endAnimation(); - - virtual void overrideAnimations(); - virtual void resumeOverriddenAnimations(); - - bool shouldSendEventForListener(Document::ListenerType inListenerType) const; - bool sendAnimationEvent(const AtomicString&, double elapsedTime); - - virtual bool affectsProperty(CSSPropertyID) const; - - void validateTransformFunctionList(); - void checkForMatchingFilterFunctionLists(); - -private: - KeyframeAnimation(const CSSAnimationData*, RenderObject&, int index, CompositeAnimation*, RenderStyle& unanimatedStyle); - virtual ~KeyframeAnimation(); - - // Get the styles for the given property surrounding the current animation time and the progress between them. - void fetchIntervalEndpointsForProperty(CSSPropertyID, const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& progress) const; - - // The keyframes that we are blending. - KeyframeList m_keyframes; - - // The order in which this animation appears in the animation-name style. - int m_index; - bool m_startEventDispatched; - - // The style just before we started animation - RefPtr<RenderStyle> m_unanimatedStyle; -}; - -} // namespace WebCore - -#endif // KeyframeAnimation_h diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirective.h b/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirective.h new file mode 100644 index 00000000000..e870ccb9c94 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirective.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CSPDirective_h +#define CSPDirective_h + +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ContentSecurityPolicy; +class KURL; + +class CSPDirective { + WTF_MAKE_NONCOPYABLE(CSPDirective); +public: + CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy) + : m_name(name) + , m_text(name + ' ' + value) + , m_policy(policy) + { + } + + const String& text() const { return m_text; } + +protected: + const ContentSecurityPolicy* policy() const { return m_policy; } + +private: + String m_name; + String m_text; + ContentSecurityPolicy* m_policy; +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp b/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp new file mode 100644 index 00000000000..a453dfdeb6c --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp @@ -0,0 +1,679 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/csp/CSPDirectiveList.h" + +#include "core/frame/LocalFrame.h" +#include "platform/ParsingUtilities.h" +#include "platform/weborigin/KURL.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) + : m_policy(policy) + , m_headerType(type) + , m_headerSource(source) + , m_reportOnly(false) + , m_haveSandboxPolicy(false) + , m_reflectedXSSDisposition(ReflectedXSSUnset) + , m_didSetReferrerPolicy(false) + , m_referrerPolicy(ReferrerPolicyDefault) +{ + m_reportOnly = type == ContentSecurityPolicyHeaderTypeReport; +} + +PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* policy, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) +{ + OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy, type, source)); + directives->parse(begin, end); + + if (!directives->checkEval(directives->operativeDirective(directives->m_scriptSrc.get()))) { + String message = "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: \"" + directives->operativeDirective(directives->m_scriptSrc.get())->text() + "\".\n"; + directives->setEvalDisabledErrorMessage(message); + } + + if (directives->isReportOnly() && directives->reportURIs().isEmpty()) + policy->reportMissingReportURI(String(begin, end - begin)); + + return directives.release(); +} + +void CSPDirectiveList::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL) const +{ + String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage; + m_policy->executionContext()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message); + m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header); +} + +void CSPDirectiveList::reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const +{ + String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage; + m_policy->executionContext()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message, contextURL, contextLine.oneBasedInt()); + m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header); +} + +void CSPDirectiveList::reportViolationWithState(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptState* scriptState) const +{ + String message = m_reportOnly ? "[Report Only] " + consoleMessage : consoleMessage; + m_policy->executionContext()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message, scriptState); + m_policy->reportViolation(directiveText, effectiveDirective, message, blockedURL, m_reportURIs, m_header); +} + +bool CSPDirectiveList::checkEval(SourceListDirective* directive) const +{ + return !directive || directive->allowEval(); +} + +bool CSPDirectiveList::checkInline(SourceListDirective* directive) const +{ + return !directive || (directive->allowInline() && !directive->isHashOrNoncePresent()); +} + +bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const +{ + return !directive || directive->allowNonce(nonce); +} + +bool CSPDirectiveList::checkHash(SourceListDirective* directive, const CSPHashValue& hashValue) const +{ + return !directive || directive->allowHash(hashValue); +} + +bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& url) const +{ + return !directive || directive->allows(url); +} + +bool CSPDirectiveList::checkAncestors(SourceListDirective* directive, LocalFrame* frame) const +{ + if (!frame || !directive) + return true; + + for (Frame* current = frame->tree().parent(); current; current = current->tree().parent()) { + // FIXME: To make this work for out-of-process iframes, we need to propagate URL information of ancestor frames across processes. + if (!current->isLocalFrame() || !directive->allows(toLocalFrame(current)->document()->url())) + return false; + } + return true; +} + +bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const +{ + if (!directive) + return true; + if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) + return false; + return directive->allows(type); +} + +SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive) const +{ + return directive ? directive : m_defaultSrc.get(); +} + +SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* directive, SourceListDirective* override) const +{ + return directive ? directive : override; +} + +bool CSPDirectiveList::checkEvalAndReportViolation(SourceListDirective* directive, const String& consoleMessage, ScriptState* scriptState) const +{ + if (checkEval(directive)) + return true; + + String suffix = String(); + if (directive == m_defaultSrc) + suffix = " Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback."; + + reportViolationWithState(directive->text(), ContentSecurityPolicy::ScriptSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), scriptState); + if (!m_reportOnly) { + m_policy->reportBlockedScriptExecutionToInspector(directive->text()); + return false; + } + return true; +} + +bool CSPDirectiveList::checkMediaTypeAndReportViolation(MediaListDirective* directive, const String& type, const String& typeAttribute, const String& consoleMessage) const +{ + if (checkMediaType(directive, type, typeAttribute)) + return true; + + String message = consoleMessage + "\'" + directive->text() + "\'."; + if (typeAttribute.isEmpty()) + message = message + " When enforcing the 'plugin-types' directive, the plugin's media type must be explicitly declared with a 'type' attribute on the containing element (e.g. '<object type=\"[TYPE GOES HERE]\" ...>')."; + + reportViolation(directive->text(), ContentSecurityPolicy::PluginTypes, message + "\n", KURL()); + return denyIfEnforcingPolicy(); +} + +bool CSPDirectiveList::checkInlineAndReportViolation(SourceListDirective* directive, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const +{ + if (checkInline(directive)) + return true; + + String suffix = String(); + if (directive->allowInline() && directive->isHashOrNoncePresent()) { + // If inline is allowed, but a hash or nonce is present, we ignore 'unsafe-inline'. Throw a reasonable error. + suffix = " Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list."; + } else { + suffix = " Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution."; + if (directive == m_defaultSrc) + suffix = suffix + " Note also that '" + String(isScript ? "script" : "style") + "-src' was not explicitly set, so 'default-src' is used as a fallback."; + } + + reportViolationWithLocation(directive->text(), isScript ? ContentSecurityPolicy::ScriptSrc : ContentSecurityPolicy::StyleSrc, consoleMessage + "\"" + directive->text() + "\"." + suffix + "\n", KURL(), contextURL, contextLine); + + if (!m_reportOnly) { + if (isScript) + m_policy->reportBlockedScriptExecutionToInspector(directive->text()); + return false; + } + return true; +} + +bool CSPDirectiveList::checkSourceAndReportViolation(SourceListDirective* directive, const KURL& url, const String& effectiveDirective) const +{ + if (checkSource(directive, url)) + return true; + + String prefix; + if (ContentSecurityPolicy::BaseURI == effectiveDirective) + prefix = "Refused to set the document's base URI to '"; + else if (ContentSecurityPolicy::ChildSrc == effectiveDirective) + prefix = "Refused to create a child context containing '"; + else if (ContentSecurityPolicy::ConnectSrc == effectiveDirective) + prefix = "Refused to connect to '"; + else if (ContentSecurityPolicy::FontSrc == effectiveDirective) + prefix = "Refused to load the font '"; + else if (ContentSecurityPolicy::FormAction == effectiveDirective) + prefix = "Refused to send form data to '"; + else if (ContentSecurityPolicy::FrameSrc == effectiveDirective) + prefix = "Refused to frame '"; + else if (ContentSecurityPolicy::ImgSrc == effectiveDirective) + prefix = "Refused to load the image '"; + else if (ContentSecurityPolicy::MediaSrc == effectiveDirective) + prefix = "Refused to load media from '"; + else if (ContentSecurityPolicy::ObjectSrc == effectiveDirective) + prefix = "Refused to load plugin data from '"; + else if (ContentSecurityPolicy::ScriptSrc == effectiveDirective) + prefix = "Refused to load the script '"; + else if (ContentSecurityPolicy::StyleSrc == effectiveDirective) + prefix = "Refused to load the stylesheet '"; + + String suffix = String(); + if (directive == m_defaultSrc) + suffix = " Note that '" + effectiveDirective + "' was not explicitly set, so 'default-src' is used as a fallback."; + + reportViolation(directive->text(), effectiveDirective, prefix + url.elidedString() + "' because it violates the following Content Security Policy directive: \"" + directive->text() + "\"." + suffix + "\n", url); + return denyIfEnforcingPolicy(); +} + +bool CSPDirectiveList::checkAncestorsAndReportViolation(SourceListDirective* directive, LocalFrame* frame) const +{ + if (checkAncestors(directive, frame)) + return true; + + reportViolation(directive->text(), "frame-ancestors", "Refused to display '" + frame->document()->url().elidedString() + " in a frame because an ancestor violates the following Content Security Policy directive: \"" + directive->text() + "\".", frame->document()->url()); + return denyIfEnforcingPolicy(); +} + +bool CSPDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: ")); + if (reportingStatus == ContentSecurityPolicy::SendReport) + return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true); + + return checkInline(operativeDirective(m_scriptSrc.get())); +} + +bool CSPDirectiveList::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline event handler because it violates the following Content Security Policy directive: ")); + if (reportingStatus == ContentSecurityPolicy::SendReport) + return checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true); + return checkInline(operativeDirective(m_scriptSrc.get())); +} + +bool CSPDirectiveList::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute inline script because it violates the following Content Security Policy directive: ")); + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkInlineAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, contextURL, contextLine, true) : + checkInline(operativeDirective(m_scriptSrc.get())); +} + +bool CSPDirectiveList::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to apply inline style because it violates the following Content Security Policy directive: ")); + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkInlineAndReportViolation(operativeDirective(m_styleSrc.get()), consoleMessage, contextURL, contextLine, false) : + checkInline(operativeDirective(m_styleSrc.get())); +} + +bool CSPDirectiveList::allowEval(ScriptState* scriptState, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: ")); + + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkEvalAndReportViolation(operativeDirective(m_scriptSrc.get()), consoleMessage, scriptState) : + checkEval(operativeDirective(m_scriptSrc.get())); +} + +bool CSPDirectiveList::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkMediaTypeAndReportViolation(m_pluginTypes.get(), type, typeAttribute, "Refused to load '" + url.elidedString() + "' (MIME type '" + typeAttribute + "') because it violates the following Content Security Policy Directive: ") : + checkMediaType(m_pluginTypes.get(), type, typeAttribute); +} + +bool CSPDirectiveList::allowScriptFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_scriptSrc.get()), url, ContentSecurityPolicy::ScriptSrc) : + checkSource(operativeDirective(m_scriptSrc.get()), url); +} + +bool CSPDirectiveList::allowObjectFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + if (url.protocolIsAbout()) + return true; + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_objectSrc.get()), url, ContentSecurityPolicy::ObjectSrc) : + checkSource(operativeDirective(m_objectSrc.get()), url); +} + +bool CSPDirectiveList::allowChildFrameFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + if (url.protocolIsAbout()) + return true; + + // 'frame-src' is the only directive which overrides something other than the default sources. + // It overrides 'child-src', which overrides the default sources. So, we do this nested set + // of calls to 'operativeDirective()' to grab 'frame-src' if it exists, 'child-src' if it + // doesn't, and 'defaut-src' if neither are available. + // + // All of this only applies, of course, if we're in CSP 1.1. In CSP 1.0, 'frame-src' + // overrides 'default-src' directly. + SourceListDirective* whichDirective = m_policy->experimentalFeaturesEnabled() ? + operativeDirective(m_frameSrc.get(), operativeDirective(m_childSrc.get())) : + operativeDirective(m_frameSrc.get()); + + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(whichDirective, url, ContentSecurityPolicy::FrameSrc) : + checkSource(whichDirective, url); +} + +bool CSPDirectiveList::allowImageFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_imgSrc.get()), url, ContentSecurityPolicy::ImgSrc) : + checkSource(operativeDirective(m_imgSrc.get()), url); +} + +bool CSPDirectiveList::allowStyleFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_styleSrc.get()), url, ContentSecurityPolicy::StyleSrc) : + checkSource(operativeDirective(m_styleSrc.get()), url); +} + +bool CSPDirectiveList::allowFontFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_fontSrc.get()), url, ContentSecurityPolicy::FontSrc) : + checkSource(operativeDirective(m_fontSrc.get()), url); +} + +bool CSPDirectiveList::allowMediaFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_mediaSrc.get()), url, ContentSecurityPolicy::MediaSrc) : + checkSource(operativeDirective(m_mediaSrc.get()), url); +} + +bool CSPDirectiveList::allowConnectToSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_connectSrc.get()), url, ContentSecurityPolicy::ConnectSrc) : + checkSource(operativeDirective(m_connectSrc.get()), url); +} + +bool CSPDirectiveList::allowFormAction(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(m_formAction.get(), url, ContentSecurityPolicy::FormAction) : + checkSource(m_formAction.get(), url); +} + +bool CSPDirectiveList::allowBaseURI(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(m_baseURI.get(), url, ContentSecurityPolicy::BaseURI) : + checkSource(m_baseURI.get(), url); +} + +bool CSPDirectiveList::allowAncestors(LocalFrame* frame, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkAncestorsAndReportViolation(m_frameAncestors.get(), frame) : + checkAncestors(m_frameAncestors.get(), frame); +} + +bool CSPDirectiveList::allowChildContextFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return reportingStatus == ContentSecurityPolicy::SendReport ? + checkSourceAndReportViolation(operativeDirective(m_childSrc.get()), url, ContentSecurityPolicy::ChildSrc) : + checkSource(operativeDirective(m_childSrc.get()), url); +} + +bool CSPDirectiveList::allowScriptNonce(const String& nonce) const +{ + return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); +} + +bool CSPDirectiveList::allowStyleNonce(const String& nonce) const +{ + return checkNonce(operativeDirective(m_styleSrc.get()), nonce); +} + +bool CSPDirectiveList::allowScriptHash(const CSPHashValue& hashValue) const +{ + return checkHash(operativeDirective(m_scriptSrc.get()), hashValue); +} + +bool CSPDirectiveList::allowStyleHash(const CSPHashValue& hashValue) const +{ + return checkHash(operativeDirective(m_styleSrc.get()), hashValue); +} + +// policy = directive-list +// directive-list = [ directive *( ";" [ directive ] ) ] +// +void CSPDirectiveList::parse(const UChar* begin, const UChar* end) +{ + m_header = String(begin, end - begin); + + if (begin == end) + return; + + const UChar* position = begin; + while (position < end) { + const UChar* directiveBegin = position; + skipUntil<UChar>(position, end, ';'); + + String name, value; + if (parseDirective(directiveBegin, position, name, value)) { + ASSERT(!name.isEmpty()); + addDirective(name, value); + } + + ASSERT(position == end || *position == ';'); + skipExactly<UChar>(position, end, ';'); + } +} + +// directive = *WSP [ directive-name [ WSP directive-value ] ] +// directive-name = 1*( ALPHA / DIGIT / "-" ) +// directive-value = *( WSP / <VCHAR except ";"> ) +// +bool CSPDirectiveList::parseDirective(const UChar* begin, const UChar* end, String& name, String& value) +{ + ASSERT(name.isEmpty()); + ASSERT(value.isEmpty()); + + const UChar* position = begin; + skipWhile<UChar, isASCIISpace>(position, end); + + // Empty directive (e.g. ";;;"). Exit early. + if (position == end) + return false; + + const UChar* nameBegin = position; + skipWhile<UChar, isCSPDirectiveNameCharacter>(position, end); + + // The directive-name must be non-empty. + if (nameBegin == position) { + skipWhile<UChar, isNotASCIISpace>(position, end); + m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin)); + return false; + } + + name = String(nameBegin, position - nameBegin); + + if (position == end) + return true; + + if (!skipExactly<UChar, isASCIISpace>(position, end)) { + skipWhile<UChar, isNotASCIISpace>(position, end); + m_policy->reportUnsupportedDirective(String(nameBegin, position - nameBegin)); + return false; + } + + skipWhile<UChar, isASCIISpace>(position, end); + + const UChar* valueBegin = position; + skipWhile<UChar, isCSPDirectiveValueCharacter>(position, end); + + if (position != end) { + m_policy->reportInvalidDirectiveValueCharacter(name, String(valueBegin, end - valueBegin)); + return false; + } + + // The directive-value may be empty. + if (valueBegin == position) + return true; + + value = String(valueBegin, position - valueBegin); + return true; +} + +void CSPDirectiveList::parseReportURI(const String& name, const String& value) +{ + if (!m_reportURIs.isEmpty()) { + m_policy->reportDuplicateDirective(name); + return; + } + + Vector<UChar> characters; + value.appendTo(characters); + + const UChar* position = characters.data(); + const UChar* end = position + characters.size(); + + while (position < end) { + skipWhile<UChar, isASCIISpace>(position, end); + + const UChar* urlBegin = position; + skipWhile<UChar, isNotASCIISpace>(position, end); + + if (urlBegin < position) { + String url = String(urlBegin, position - urlBegin); + m_reportURIs.append(m_policy->completeURL(url)); + } + } +} + + +template<class CSPDirectiveType> +void CSPDirectiveList::setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>& directive) +{ + if (directive) { + m_policy->reportDuplicateDirective(name); + return; + } + directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); +} + +void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sandboxPolicy) +{ + if (m_reportOnly) { + m_policy->reportInvalidInReportOnly(name); + return; + } + if (m_haveSandboxPolicy) { + m_policy->reportDuplicateDirective(name); + return; + } + m_haveSandboxPolicy = true; + String invalidTokens; + m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidTokens)); + if (!invalidTokens.isNull()) + m_policy->reportInvalidSandboxFlags(invalidTokens); +} + +void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value) +{ + if (m_reflectedXSSDisposition != ReflectedXSSUnset) { + m_policy->reportDuplicateDirective(name); + m_reflectedXSSDisposition = ReflectedXSSInvalid; + return; + } + + if (value.isEmpty()) { + m_reflectedXSSDisposition = ReflectedXSSInvalid; + m_policy->reportInvalidReflectedXSS(value); + return; + } + + Vector<UChar> characters; + value.appendTo(characters); + + const UChar* position = characters.data(); + const UChar* end = position + characters.size(); + + skipWhile<UChar, isASCIISpace>(position, end); + const UChar* begin = position; + skipWhile<UChar, isNotASCIISpace>(position, end); + + // value1 + // ^ + if (equalIgnoringCase("allow", begin, position - begin)) { + m_reflectedXSSDisposition = AllowReflectedXSS; + } else if (equalIgnoringCase("filter", begin, position - begin)) { + m_reflectedXSSDisposition = FilterReflectedXSS; + } else if (equalIgnoringCase("block", begin, position - begin)) { + m_reflectedXSSDisposition = BlockReflectedXSS; + } else { + m_reflectedXSSDisposition = ReflectedXSSInvalid; + m_policy->reportInvalidReflectedXSS(value); + return; + } + + skipWhile<UChar, isASCIISpace>(position, end); + if (position == end && m_reflectedXSSDisposition != ReflectedXSSUnset) + return; + + // value1 value2 + // ^ + m_reflectedXSSDisposition = ReflectedXSSInvalid; + m_policy->reportInvalidReflectedXSS(value); +} + +void CSPDirectiveList::parseReferrer(const String& name, const String& value) +{ + if (m_didSetReferrerPolicy) { + m_policy->reportDuplicateDirective(name); + m_referrerPolicy = ReferrerPolicyNever; + return; + } + + m_didSetReferrerPolicy = true; + + if (value.isEmpty()) { + m_policy->reportInvalidReferrer(value); + m_referrerPolicy = ReferrerPolicyNever; + return; + } + + Vector<UChar> characters; + value.appendTo(characters); + + const UChar* position = characters.data(); + const UChar* end = position + characters.size(); + + skipWhile<UChar, isASCIISpace>(position, end); + const UChar* begin = position; + skipWhile<UChar, isNotASCIISpace>(position, end); + + // value1 + // ^ + if (equalIgnoringCase("always", begin, position - begin)) { + m_referrerPolicy = ReferrerPolicyAlways; + } else if (equalIgnoringCase("default", begin, position - begin)) { + m_referrerPolicy = ReferrerPolicyDefault; + } else if (equalIgnoringCase("never", begin, position - begin)) { + m_referrerPolicy = ReferrerPolicyNever; + } else if (equalIgnoringCase("origin", begin, position - begin)) { + m_referrerPolicy = ReferrerPolicyOrigin; + } else { + m_referrerPolicy = ReferrerPolicyNever; + m_policy->reportInvalidReferrer(value); + return; + } + + skipWhile<UChar, isASCIISpace>(position, end); + if (position == end) + return; + + // value1 value2 + // ^ + m_referrerPolicy = ReferrerPolicyNever; + m_policy->reportInvalidReferrer(value); + +} + +void CSPDirectiveList::addDirective(const String& name, const String& value) +{ + ASSERT(!name.isEmpty()); + + if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); + m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed()); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::ObjectSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_objectSrc); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::FrameAncestors)) { + setCSPDirective<SourceListDirective>(name, value, m_frameAncestors); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::FrameSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_frameSrc); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::ImgSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_imgSrc); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::StyleSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_styleSrc); + m_policy->usesStyleHashAlgorithms(m_styleSrc->hashAlgorithmsUsed()); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::FontSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_fontSrc); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::MediaSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_mediaSrc); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::ConnectSrc)) { + setCSPDirective<SourceListDirective>(name, value, m_connectSrc); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::Sandbox)) { + applySandboxPolicy(name, value); + } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReportURI)) { + parseReportURI(name, value); + } else if (m_policy->experimentalFeaturesEnabled()) { + if (equalIgnoringCase(name, ContentSecurityPolicy::BaseURI)) + setCSPDirective<SourceListDirective>(name, value, m_baseURI); + else if (equalIgnoringCase(name, ContentSecurityPolicy::ChildSrc)) + setCSPDirective<SourceListDirective>(name, value, m_childSrc); + else if (equalIgnoringCase(name, ContentSecurityPolicy::FormAction)) + setCSPDirective<SourceListDirective>(name, value, m_formAction); + else if (equalIgnoringCase(name, ContentSecurityPolicy::PluginTypes)) + setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); + else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) + parseReflectedXSS(name, value); + else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) + parseReferrer(name, value); + else + m_policy->reportUnsupportedDirective(name); + } else { + m_policy->reportUnsupportedDirective(name); + } +} + + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.h b/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.h new file mode 100644 index 00000000000..b33b18693ad --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.h @@ -0,0 +1,141 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CSPDirectiveList_h +#define CSPDirectiveList_h + +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/frame/csp/MediaListDirective.h" +#include "core/frame/csp/SourceListDirective.h" +#include "platform/network/ContentSecurityPolicyParsers.h" +#include "platform/network/HTTPParsers.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/ReferrerPolicy.h" +#include "wtf/OwnPtr.h" +#include "wtf/Vector.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ContentSecurityPolicy; + +class CSPDirectiveList { + WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(CSPDirectiveList); +public: + static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType, ContentSecurityPolicyHeaderSource); + + void parse(const UChar* begin, const UChar* end); + + const String& header() const { return m_header; } + ContentSecurityPolicyHeaderType headerType() const { return m_headerType; } + ContentSecurityPolicyHeaderSource headerSource() const { return m_headerSource; } + + bool allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; + bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; + bool allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; + bool allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus) const; + bool allowEval(ScriptState*, ContentSecurityPolicy::ReportingStatus) const; + bool allowPluginType(const String& type, const String& typeAttribute, const KURL&, ContentSecurityPolicy::ReportingStatus) const; + + bool allowScriptFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowObjectFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowAncestors(LocalFrame*, ContentSecurityPolicy::ReportingStatus) const; + bool allowChildContextFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const; + bool allowScriptNonce(const String&) const; + bool allowStyleNonce(const String&) const; + bool allowScriptHash(const CSPHashValue&) const; + bool allowStyleHash(const CSPHashValue&) const; + + const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; } + ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflectedXSSDisposition; } + ReferrerPolicy referrerPolicy() const { return m_referrerPolicy; } + bool didSetReferrerPolicy() const { return m_didSetReferrerPolicy; } + bool isReportOnly() const { return m_reportOnly; } + const Vector<KURL>& reportURIs() const { return m_reportURIs; } + +private: + CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicyHeaderType, ContentSecurityPolicyHeaderSource); + + bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value); + void parseReportURI(const String& name, const String& value); + void parsePluginTypes(const String& name, const String& value); + void parseReflectedXSS(const String& name, const String& value); + void parseReferrer(const String& name, const String& value); + void addDirective(const String& name, const String& value); + void applySandboxPolicy(const String& name, const String& sandboxPolicy); + + template <class CSPDirectiveType> + void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDirectiveType>&); + + SourceListDirective* operativeDirective(SourceListDirective*) const; + SourceListDirective* operativeDirective(SourceListDirective*, SourceListDirective* override) const; + void reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL) const; + void reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const; + void reportViolationWithState(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptState*) const; + + bool checkEval(SourceListDirective*) const; + bool checkInline(SourceListDirective*) const; + bool checkNonce(SourceListDirective*, const String&) const; + bool checkHash(SourceListDirective*, const CSPHashValue&) const; + bool checkSource(SourceListDirective*, const KURL&) const; + bool checkMediaType(MediaListDirective*, const String& type, const String& typeAttribute) const; + bool checkAncestors(SourceListDirective*, LocalFrame*) const; + + void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisabledErrorMessage = errorMessage; } + + bool checkEvalAndReportViolation(SourceListDirective*, const String& consoleMessage, ScriptState*) const; + bool checkInlineAndReportViolation(SourceListDirective*, const String& consoleMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const; + + bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; + bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& type, const String& typeAttribute, const String& consoleMessage) const; + bool checkAncestorsAndReportViolation(SourceListDirective*, LocalFrame*) const; + + bool denyIfEnforcingPolicy() const { return m_reportOnly; } + + ContentSecurityPolicy* m_policy; + + String m_header; + ContentSecurityPolicyHeaderType m_headerType; + ContentSecurityPolicyHeaderSource m_headerSource; + + bool m_reportOnly; + bool m_haveSandboxPolicy; + ReflectedXSSDisposition m_reflectedXSSDisposition; + + bool m_didSetReferrerPolicy; + ReferrerPolicy m_referrerPolicy; + + OwnPtr<MediaListDirective> m_pluginTypes; + OwnPtr<SourceListDirective> m_baseURI; + OwnPtr<SourceListDirective> m_childSrc; + OwnPtr<SourceListDirective> m_connectSrc; + OwnPtr<SourceListDirective> m_defaultSrc; + OwnPtr<SourceListDirective> m_fontSrc; + OwnPtr<SourceListDirective> m_formAction; + OwnPtr<SourceListDirective> m_frameAncestors; + OwnPtr<SourceListDirective> m_frameSrc; + OwnPtr<SourceListDirective> m_imgSrc; + OwnPtr<SourceListDirective> m_mediaSrc; + OwnPtr<SourceListDirective> m_objectSrc; + OwnPtr<SourceListDirective> m_scriptSrc; + OwnPtr<SourceListDirective> m_styleSrc; + + Vector<KURL> m_reportURIs; + + String m_evalDisabledErrorMessage; +}; + + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp new file mode 100644 index 00000000000..863addc09ce --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp @@ -0,0 +1,93 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/csp/CSPSource.h" + +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/KnownPorts.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +CSPSource::CSPSource(ContentSecurityPolicy* policy, const String& scheme, const String& host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard) + : m_policy(policy) + , m_scheme(scheme) + , m_host(host) + , m_port(port) + , m_path(path) + , m_hostHasWildcard(hostHasWildcard) + , m_portHasWildcard(portHasWildcard) +{ +} + +bool CSPSource::matches(const KURL& url) const +{ + if (!schemeMatches(url)) + return false; + if (isSchemeOnly()) + return true; + return hostMatches(url) && portMatches(url) && pathMatches(url); +} + +bool CSPSource::schemeMatches(const KURL& url) const +{ + if (m_scheme.isEmpty()) { + String protectedResourceScheme(m_policy->securityOrigin()->protocol()); + if (equalIgnoringCase("http", protectedResourceScheme)) + return url.protocolIs("http") || url.protocolIs("https"); + return equalIgnoringCase(url.protocol(), protectedResourceScheme); + } + return equalIgnoringCase(url.protocol(), m_scheme); +} + +bool CSPSource::hostMatches(const KURL& url) const +{ + const String& host = url.host(); + if (equalIgnoringCase(host, m_host)) + return true; + return m_hostHasWildcard && host.endsWith("." + m_host, false); + +} + +bool CSPSource::pathMatches(const KURL& url) const +{ + if (m_path.isEmpty()) + return true; + + String path = decodeURLEscapeSequences(url.path()); + + if (m_path.endsWith("/")) + return path.startsWith(m_path, false); + + return path == m_path; +} + +bool CSPSource::portMatches(const KURL& url) const +{ + if (m_portHasWildcard) + return true; + + int port = url.port(); + + if (port == m_port) + return true; + + if (!port) + return isDefaultPortForProtocol(m_port, url.protocol()); + + if (!m_port) + return isDefaultPortForProtocol(port, url.protocol()); + + return false; +} + +bool CSPSource::isSchemeOnly() const +{ + return m_host.isEmpty(); +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/CSPSource.h b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSource.h new file mode 100644 index 00000000000..9088b196b3f --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSource.h @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CSPSource_h +#define CSPSource_h + +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ContentSecurityPolicy; +class KURL; + +class CSPSource { +public: + CSPSource(ContentSecurityPolicy*, const String& scheme, const String& host, int port, const String& path, bool hostHasWildcard, bool portHasWildcard); + bool matches(const KURL&) const; + +private: + bool schemeMatches(const KURL&) const; + bool hostMatches(const KURL&) const; + bool pathMatches(const KURL&) const; + bool portMatches(const KURL&) const; + bool isSchemeOnly() const; + + ContentSecurityPolicy* m_policy; + String m_scheme; + String m_host; + int m_port; + String m_path; + + bool m_hostHasWildcard; + bool m_portHasWildcard; +}; + +} // namespace + +#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/CSPSourceList.cpp b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSourceList.cpp new file mode 100644 index 00000000000..bff7146dab0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSourceList.cpp @@ -0,0 +1,485 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/csp/CSPSourceList.h" + +#include "core/frame/csp/CSPSource.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "platform/ParsingUtilities.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "wtf/HashSet.h" +#include "wtf/text/Base64.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +static bool isSourceListNone(const UChar* begin, const UChar* end) +{ + skipWhile<UChar, isASCIISpace>(begin, end); + + const UChar* position = begin; + skipWhile<UChar, isSourceCharacter>(position, end); + if (!equalIgnoringCase("'none'", begin, position - begin)) + return false; + + skipWhile<UChar, isASCIISpace>(position, end); + if (position != end) + return false; + + return true; +} + +CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& directiveName) + : m_policy(policy) + , m_directiveName(directiveName) + , m_allowStar(false) + , m_allowInline(false) + , m_allowEval(false) + , m_hashAlgorithmsUsed(0) +{ +} + +bool CSPSourceList::matches(const KURL& url) const +{ + if (m_allowStar) + return true; + + KURL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin::extractInnerURL(url) : url; + + for (size_t i = 0; i < m_list.size(); ++i) { + if (m_list[i].matches(effectiveURL)) + return true; + } + + return false; +} + +bool CSPSourceList::allowInline() const +{ + return m_allowInline; +} + +bool CSPSourceList::allowEval() const +{ + return m_allowEval; +} + +bool CSPSourceList::allowNonce(const String& nonce) const +{ + return !nonce.isNull() && m_nonces.contains(nonce); +} + +bool CSPSourceList::allowHash(const CSPHashValue& hashValue) const +{ + return m_hashes.contains(hashValue); +} + +uint8_t CSPSourceList::hashAlgorithmsUsed() const +{ + return m_hashAlgorithmsUsed; +} + +bool CSPSourceList::isHashOrNoncePresent() const +{ + return !m_nonces.isEmpty() || m_hashAlgorithmsUsed != ContentSecurityPolicyHashAlgorithmNone; +} + +// source-list = *WSP [ source *( 1*WSP source ) *WSP ] +// / *WSP "'none'" *WSP +// +void CSPSourceList::parse(const UChar* begin, const UChar* end) +{ + // We represent 'none' as an empty m_list. + if (isSourceListNone(begin, end)) + return; + + const UChar* position = begin; + while (position < end) { + skipWhile<UChar, isASCIISpace>(position, end); + if (position == end) + return; + + const UChar* beginSource = position; + skipWhile<UChar, isSourceCharacter>(position, end); + + String scheme, host, path; + int port = 0; + bool hostHasWildcard = false; + bool portHasWildcard = false; + + if (parseSource(beginSource, position, scheme, host, port, path, hostHasWildcard, portHasWildcard)) { + // Wildcard hosts and keyword sources ('self', 'unsafe-inline', + // etc.) aren't stored in m_list, but as attributes on the source + // list itself. + if (scheme.isEmpty() && host.isEmpty()) + continue; + if (m_policy->isDirectiveName(host)) + m_policy->reportDirectiveAsSourceExpression(m_directiveName, host); + m_list.append(CSPSource(m_policy, scheme, host, port, path, hostHasWildcard, portHasWildcard)); + } else { + m_policy->reportInvalidSourceExpression(m_directiveName, String(beginSource, position - beginSource)); + } + + ASSERT(position == end || isASCIISpace(*position)); + } +} + +// source = scheme ":" +// / ( [ scheme "://" ] host [ port ] [ path ] ) +// / "'self'" +bool CSPSourceList::parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard) +{ + if (begin == end) + return false; + + if (equalIgnoringCase("'none'", begin, end - begin)) + return false; + + if (end - begin == 1 && *begin == '*') { + addSourceStar(); + return true; + } + + if (equalIgnoringCase("'self'", begin, end - begin)) { + addSourceSelf(); + return true; + } + + if (equalIgnoringCase("'unsafe-inline'", begin, end - begin)) { + addSourceUnsafeInline(); + return true; + } + + if (equalIgnoringCase("'unsafe-eval'", begin, end - begin)) { + addSourceUnsafeEval(); + return true; + } + + String nonce; + if (!parseNonce(begin, end, nonce)) + return false; + + if (!nonce.isNull()) { + addSourceNonce(nonce); + return true; + } + + DigestValue hash; + ContentSecurityPolicyHashAlgorithm algorithm = ContentSecurityPolicyHashAlgorithmNone; + if (!parseHash(begin, end, hash, algorithm)) + return false; + + if (hash.size() > 0) { + addSourceHash(algorithm, hash); + return true; + } + + const UChar* position = begin; + const UChar* beginHost = begin; + const UChar* beginPath = end; + const UChar* beginPort = 0; + + skipWhile<UChar, isNotColonOrSlash>(position, end); + + if (position == end) { + // host + // ^ + return parseHost(beginHost, position, host, hostHasWildcard); + } + + if (position < end && *position == '/') { + // host/path || host/ || / + // ^ ^ ^ + return parseHost(beginHost, position, host, hostHasWildcard) && parsePath(position, end, path); + } + + if (position < end && *position == ':') { + if (end - position == 1) { + // scheme: + // ^ + return parseScheme(begin, position, scheme); + } + + if (position[1] == '/') { + // scheme://host || scheme:// + // ^ ^ + if (!parseScheme(begin, position, scheme) + || !skipExactly<UChar>(position, end, ':') + || !skipExactly<UChar>(position, end, '/') + || !skipExactly<UChar>(position, end, '/')) + return false; + if (position == end) + return true; + beginHost = position; + skipWhile<UChar, isNotColonOrSlash>(position, end); + } + + if (position < end && *position == ':') { + // host:port || scheme://host:port + // ^ ^ + beginPort = position; + skipUntil<UChar>(position, end, '/'); + } + } + + if (position < end && *position == '/') { + // scheme://host/path || scheme://host:port/path + // ^ ^ + if (position == beginHost) + return false; + beginPath = position; + } + + if (!parseHost(beginHost, beginPort ? beginPort : beginPath, host, hostHasWildcard)) + return false; + + if (beginPort) { + if (!parsePort(beginPort, beginPath, port, portHasWildcard)) + return false; + } else { + port = 0; + } + + if (beginPath != end) { + if (!parsePath(beginPath, end, path)) + return false; + } + + return true; +} + +// nonce-source = "'nonce-" nonce-value "'" +// nonce-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" ) +// +bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& nonce) +{ + DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); + + if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length())) + return true; + + const UChar* position = begin + noncePrefix.length(); + const UChar* nonceBegin = position; + + skipWhile<UChar, isNonceCharacter>(position, end); + ASSERT(nonceBegin <= position); + + if ((position + 1) != end || *position != '\'' || !(position - nonceBegin)) + return false; + + nonce = String(nonceBegin, position - nonceBegin); + return true; +} + +// hash-source = "'" hash-algorithm "-" hash-value "'" +// hash-algorithm = "sha1" / "sha256" / "sha384" / "sha512" +// hash-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" ) +// +bool CSPSourceList::parseHash(const UChar* begin, const UChar* end, DigestValue& hash, ContentSecurityPolicyHashAlgorithm& hashAlgorithm) +{ + // Any additions or subtractions from this struct should also modify the + // respective entries in the kAlgorithmMap array in checkDigest(). + static const struct { + const char* prefix; + ContentSecurityPolicyHashAlgorithm algorithm; + } kSupportedPrefixes[] = { + { "'sha1-", ContentSecurityPolicyHashAlgorithmSha1 }, + { "'sha256-", ContentSecurityPolicyHashAlgorithmSha256 }, + { "'sha384-", ContentSecurityPolicyHashAlgorithmSha384 }, + { "'sha512-", ContentSecurityPolicyHashAlgorithmSha512 } + }; + + String prefix; + hashAlgorithm = ContentSecurityPolicyHashAlgorithmNone; + + // Instead of this sizeof() calculation to get the length of this array, + // it would be preferable to use WTF_ARRAY_LENGTH for simplicity and to + // guarantee a compile time calculation. Unfortunately, on some + // compliers, the call to WTF_ARRAY_LENGTH fails on arrays of anonymous + // stucts, so, for now, it is necessary to resort to this sizeof + // calculation. + for (size_t i = 0; i < (sizeof(kSupportedPrefixes) / sizeof(kSupportedPrefixes[0])); i++) { + if (equalIgnoringCase(kSupportedPrefixes[i].prefix, begin, strlen(kSupportedPrefixes[i].prefix))) { + prefix = kSupportedPrefixes[i].prefix; + hashAlgorithm = kSupportedPrefixes[i].algorithm; + break; + } + } + + if (hashAlgorithm == ContentSecurityPolicyHashAlgorithmNone) + return true; + + const UChar* position = begin + prefix.length(); + const UChar* hashBegin = position; + + skipWhile<UChar, isBase64EncodedCharacter>(position, end); + ASSERT(hashBegin <= position); + + // Base64 encodings may end with exactly one or two '=' characters + skipExactly<UChar>(position, position + 1, '='); + skipExactly<UChar>(position, position + 1, '='); + + if ((position + 1) != end || *position != '\'' || !(position - hashBegin)) + return false; + + Vector<char> hashVector; + base64Decode(hashBegin, position - hashBegin, hashVector); + if (hashVector.size() > kMaxDigestSize) + return false; + hash.append(reinterpret_cast<uint8_t*>(hashVector.data()), hashVector.size()); + 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<UChar, isASCIIAlpha>(position, end)) + return false; + + skipWhile<UChar, 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<UChar>(position, end, '*')) { + hostHasWildcard = true; + + if (position == end) + return true; + + if (!skipExactly<UChar>(position, end, '.')) + return false; + } + + const UChar* hostBegin = position; + + while (position < end) { + if (!skipExactly<UChar, isHostCharacter>(position, end)) + return false; + + skipWhile<UChar, isHostCharacter>(position, end); + + if (position < end && !skipExactly<UChar>(position, end, '.')) + return false; + } + + ASSERT(position == end); + host = String(hostBegin, end - hostBegin); + return true; +} + +bool CSPSourceList::parsePath(const UChar* begin, const UChar* end, String& path) +{ + ASSERT(begin <= end); + ASSERT(path.isEmpty()); + + const UChar* position = begin; + skipWhile<UChar, isPathComponentCharacter>(position, end); + // path/to/file.js?query=string || path/to/file.js#anchor + // ^ ^ + if (position < end) + m_policy->reportInvalidPathCharacter(m_directiveName, String(begin, end - begin), *position); + + path = decodeURLEscapeSequences(String(begin, position - begin)); + + ASSERT(position <= end); + ASSERT(position == end || (*position == '#' || *position == '?')); + 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 (!skipExactly<UChar>(begin, end, ':')) + ASSERT_NOT_REACHED(); + + if (begin == end) + return false; + + if (end - begin == 1 && *begin == '*') { + port = 0; + portHasWildcard = true; + return true; + } + + const UChar* position = begin; + skipWhile<UChar, isASCIIDigit>(position, end); + + if (position != end) + return false; + + bool ok; + port = charactersToIntStrict(begin, end - begin, &ok); + return ok; +} + +void CSPSourceList::addSourceSelf() +{ + m_list.append(CSPSource(m_policy, m_policy->securityOrigin()->protocol(), m_policy->securityOrigin()->host(), m_policy->securityOrigin()->port(), String(), false, false)); +} + +void CSPSourceList::addSourceStar() +{ + m_allowStar = true; +} + +void CSPSourceList::addSourceUnsafeInline() +{ + m_allowInline = true; +} + +void CSPSourceList::addSourceUnsafeEval() +{ + m_allowEval = true; +} + +void CSPSourceList::addSourceNonce(const String& nonce) +{ + m_nonces.add(nonce); +} + +void CSPSourceList::addSourceHash(const ContentSecurityPolicyHashAlgorithm& algorithm, const DigestValue& hash) +{ + m_hashes.add(CSPHashValue(algorithm, hash)); + m_hashAlgorithmsUsed |= algorithm; +} + + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/CSPSourceList.h b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSourceList.h new file mode 100644 index 00000000000..c982fe68ac7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/CSPSourceList.h @@ -0,0 +1,65 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CSPSourceList_h +#define CSPSourceList_h + +#include "core/frame/csp/CSPSource.h" +#include "platform/Crypto.h" +#include "platform/network/ContentSecurityPolicyParsers.h" +#include "wtf/HashSet.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ContentSecurityPolicy; +class KURL; + +class CSPSourceList { + WTF_MAKE_NONCOPYABLE(CSPSourceList); +public: + CSPSourceList(ContentSecurityPolicy*, const String& directiveName); + + void parse(const UChar* begin, const UChar* end); + + bool matches(const KURL&) const; + bool allowInline() const; + bool allowEval() const; + bool allowNonce(const String&) const; + bool allowHash(const CSPHashValue&) const; + uint8_t hashAlgorithmsUsed() const; + + bool isHashOrNoncePresent() const; + +private: + bool parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, String& path, 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); + bool parsePath(const UChar* begin, const UChar* end, String& path); + bool parseNonce(const UChar* begin, const UChar* end, String& nonce); + bool parseHash(const UChar* begin, const UChar* end, DigestValue& hash, ContentSecurityPolicyHashAlgorithm&); + + void addSourceSelf(); + void addSourceStar(); + void addSourceUnsafeInline(); + void addSourceUnsafeEval(); + void addSourceNonce(const String& nonce); + void addSourceHash(const ContentSecurityPolicyHashAlgorithm&, const DigestValue& hash); + + ContentSecurityPolicy* m_policy; + Vector<CSPSource> m_list; + String m_directiveName; + bool m_allowStar; + bool m_allowInline; + bool m_allowEval; + HashSet<String> m_nonces; + HashSet<CSPHashValue> m_hashes; + uint8_t m_hashAlgorithmsUsed; +}; + + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/chromium/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp new file mode 100644 index 00000000000..cdd5d063a27 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp @@ -0,0 +1,786 @@ +/* + * Copyright (C) 2011 Google, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 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 GOOGLE 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 "core/frame/csp/ContentSecurityPolicy.h" + +#include "bindings/v8/ScriptCallStackFactory.h" +#include "bindings/v8/ScriptController.h" +#include "core/dom/DOMStringList.h" +#include "core/dom/Document.h" +#include "core/events/SecurityPolicyViolationEvent.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/UseCounter.h" +#include "core/frame/csp/CSPDirectiveList.h" +#include "core/frame/csp/CSPSource.h" +#include "core/frame/csp/CSPSourceList.h" +#include "core/frame/csp/MediaListDirective.h" +#include "core/frame/csp/SourceListDirective.h" +#include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/ScriptCallStack.h" +#include "core/loader/DocumentLoader.h" +#include "core/loader/PingLoader.h" +#include "platform/Crypto.h" +#include "platform/JSONValues.h" +#include "platform/NotImplemented.h" +#include "platform/ParsingUtilities.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/network/ContentSecurityPolicyParsers.h" +#include "platform/network/ContentSecurityPolicyResponseHeaders.h" +#include "platform/network/FormData.h" +#include "platform/network/ResourceResponse.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/KnownPorts.h" +#include "platform/weborigin/SchemeRegistry.h" +#include "platform/weborigin/SecurityOrigin.h" +#include "public/platform/Platform.h" +#include "public/platform/WebArrayBuffer.h" +#include "public/platform/WebCrypto.h" +#include "public/platform/WebCryptoAlgorithm.h" +#include "wtf/StringHasher.h" +#include "wtf/text/StringBuilder.h" +#include "wtf/text/StringUTF8Adaptor.h" + +namespace WebCore { + +// CSP 1.0 Directives +const char ContentSecurityPolicy::ConnectSrc[] = "connect-src"; +const char ContentSecurityPolicy::DefaultSrc[] = "default-src"; +const char ContentSecurityPolicy::FontSrc[] = "font-src"; +const char ContentSecurityPolicy::FrameSrc[] = "frame-src"; +const char ContentSecurityPolicy::ImgSrc[] = "img-src"; +const char ContentSecurityPolicy::MediaSrc[] = "media-src"; +const char ContentSecurityPolicy::ObjectSrc[] = "object-src"; +const char ContentSecurityPolicy::ReportURI[] = "report-uri"; +const char ContentSecurityPolicy::Sandbox[] = "sandbox"; +const char ContentSecurityPolicy::ScriptSrc[] = "script-src"; +const char ContentSecurityPolicy::StyleSrc[] = "style-src"; + +// CSP 1.1 Directives +const char ContentSecurityPolicy::BaseURI[] = "base-uri"; +const char ContentSecurityPolicy::ChildSrc[] = "child-src"; +const char ContentSecurityPolicy::FormAction[] = "form-action"; +const char ContentSecurityPolicy::FrameAncestors[] = "frame-ancestors"; +const char ContentSecurityPolicy::PluginTypes[] = "plugin-types"; +const char ContentSecurityPolicy::ReflectedXSS[] = "reflected-xss"; +const char ContentSecurityPolicy::Referrer[] = "referrer"; + +bool ContentSecurityPolicy::isDirectiveName(const String& name) +{ + return (equalIgnoringCase(name, ConnectSrc) + || equalIgnoringCase(name, DefaultSrc) + || equalIgnoringCase(name, FontSrc) + || equalIgnoringCase(name, FrameSrc) + || equalIgnoringCase(name, ImgSrc) + || equalIgnoringCase(name, MediaSrc) + || equalIgnoringCase(name, ObjectSrc) + || equalIgnoringCase(name, ReportURI) + || equalIgnoringCase(name, Sandbox) + || equalIgnoringCase(name, ScriptSrc) + || equalIgnoringCase(name, StyleSrc) + || equalIgnoringCase(name, BaseURI) + || equalIgnoringCase(name, ChildSrc) + || equalIgnoringCase(name, FormAction) + || equalIgnoringCase(name, FrameAncestors) + || equalIgnoringCase(name, PluginTypes) + || equalIgnoringCase(name, ReflectedXSS) + || equalIgnoringCase(name, Referrer) + ); +} + +static UseCounter::Feature getUseCounterType(ContentSecurityPolicyHeaderType type) +{ + switch (type) { + case ContentSecurityPolicyHeaderTypeEnforce: + return UseCounter::ContentSecurityPolicy; + case ContentSecurityPolicyHeaderTypeReport: + return UseCounter::ContentSecurityPolicyReportOnly; + } + ASSERT_NOT_REACHED(); + return UseCounter::NumberOfFeatures; +} + +static ReferrerPolicy mergeReferrerPolicies(ReferrerPolicy a, ReferrerPolicy b) +{ + if (a != b) + return ReferrerPolicyNever; + return a; +} + +ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContext* executionContext) + : m_executionContext(executionContext) + , m_overrideInlineStyleAllowed(false) + , m_scriptHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) + , m_styleHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) +{ +} + +ContentSecurityPolicy::~ContentSecurityPolicy() +{ +} + +void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other) +{ + ASSERT(m_policies.isEmpty()); + for (CSPDirectiveListVector::const_iterator iter = other->m_policies.begin(); iter != other->m_policies.end(); ++iter) + addPolicyFromHeaderValue((*iter)->header(), (*iter)->headerType(), (*iter)->headerSource()); +} + +void ContentSecurityPolicy::didReceiveHeaders(const ContentSecurityPolicyResponseHeaders& headers) +{ + if (!headers.contentSecurityPolicy().isEmpty()) + didReceiveHeader(headers.contentSecurityPolicy(), ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); + if (!headers.contentSecurityPolicyReportOnly().isEmpty()) + didReceiveHeader(headers.contentSecurityPolicyReportOnly(), ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); +} + +void ContentSecurityPolicy::didReceiveHeader(const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) +{ + addPolicyFromHeaderValue(header, type, source); +} + +void ContentSecurityPolicy::addPolicyFromHeaderValue(const String& header, ContentSecurityPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) +{ + Document* document = this->document(); + if (document) { + UseCounter::count(*document, getUseCounterType(type)); + + // CSP 1.1 defines report-only in a <meta> element as invalid. Measure for now, disable in experimental mode. + if (source == ContentSecurityPolicyHeaderSourceMeta && type == ContentSecurityPolicyHeaderTypeReport) { + UseCounter::count(*document, UseCounter::ContentSecurityPolicyReportOnlyInMeta); + if (experimentalFeaturesEnabled()) { + reportReportOnlyInMeta(header); + return; + } + } + } + + + Vector<UChar> characters; + header.appendTo(characters); + + const UChar* begin = characters.data(); + const UChar* end = begin + characters.size(); + + // RFC2616, section 4.2 specifies that headers appearing multiple times can + // be combined with a comma. Walk the header string, and parse each comma + // separated chunk as a separate header. + const UChar* position = begin; + while (position < end) { + skipUntil<UChar>(position, end, ','); + + // header1,header2 OR header1 + // ^ ^ + OwnPtr<CSPDirectiveList> policy = CSPDirectiveList::create(this, begin, position, type, source); + + // We disable 'eval()' even in the case of report-only policies, and rely on the check in the V8Initializer::codeGenerationCheckCallbackInMainThread callback to determine whether the call should execute or not. + if (!policy->allowEval(0, SuppressReport)) + m_executionContext->disableEval(policy->evalDisabledErrorMessage()); + + m_policies.append(policy.release()); + + // Skip the comma, and begin the next header from the current position. + ASSERT(position == end || *position == ','); + skipExactly<UChar>(position, end, ','); + begin = position; + } + + if (document && type != ContentSecurityPolicyHeaderTypeReport && didSetReferrerPolicy()) + document->setReferrerPolicy(referrerPolicy()); +} + +void ContentSecurityPolicy::setOverrideAllowInlineStyle(bool value) +{ + m_overrideInlineStyleAllowed = value; +} + +const String& ContentSecurityPolicy::deprecatedHeader() const +{ + return m_policies.isEmpty() ? emptyString() : m_policies[0]->header(); +} + +ContentSecurityPolicyHeaderType ContentSecurityPolicy::deprecatedHeaderType() const +{ + return m_policies.isEmpty() ? ContentSecurityPolicyHeaderTypeEnforce : m_policies[0]->headerType(); +} + +template<bool (CSPDirectiveList::*allowed)(ContentSecurityPolicy::ReportingStatus) const> +bool isAllowedByAll(const CSPDirectiveListVector& policies, ContentSecurityPolicy::ReportingStatus reportingStatus) +{ + for (size_t i = 0; i < policies.size(); ++i) { + if (!(policies[i].get()->*allowed)(reportingStatus)) + return false; + } + return true; +} + +template<bool (CSPDirectiveList::*allowed)(ScriptState* scriptState, ContentSecurityPolicy::ReportingStatus) const> +bool isAllowedByAllWithState(const CSPDirectiveListVector& policies, ScriptState* scriptState, ContentSecurityPolicy::ReportingStatus reportingStatus) +{ + for (size_t i = 0; i < policies.size(); ++i) { + if (!(policies[i].get()->*allowed)(scriptState, reportingStatus)) + return false; + } + return true; +} + +template<bool (CSPDirectiveList::*allowed)(const String&, const WTF::OrdinalNumber&, ContentSecurityPolicy::ReportingStatus) const> +bool isAllowedByAllWithContext(const CSPDirectiveListVector& policies, const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) +{ + for (size_t i = 0; i < policies.size(); ++i) { + if (!(policies[i].get()->*allowed)(contextURL, contextLine, reportingStatus)) + return false; + } + return true; +} + +template<bool (CSPDirectiveList::*allowed)(const String&) const> +bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const String& nonce) +{ + for (size_t i = 0; i < policies.size(); ++i) { + if (!(policies[i].get()->*allowed)(nonce)) + return false; + } + return true; +} + +template<bool (CSPDirectiveList::*allowed)(const CSPHashValue&) const> +bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, const CSPHashValue& hashValue) +{ + for (size_t i = 0; i < policies.size(); ++i) { + if (!(policies[i].get()->*allowed)(hashValue)) + return false; + } + return true; +} + +template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPolicy::ReportingStatus) const> +bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) +{ + if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) + return true; + + for (size_t i = 0; i < policies.size(); ++i) { + if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) + return false; + } + return true; +} + +template<bool (CSPDirectiveList::*allowed)(LocalFrame*, ContentSecurityPolicy::ReportingStatus) const> +bool isAllowedByAllWithFrame(const CSPDirectiveListVector& policies, LocalFrame* frame, ContentSecurityPolicy::ReportingStatus reportingStatus) +{ + for (size_t i = 0; i < policies.size(); ++i) { + if (!(policies[i].get()->*allowed)(frame, reportingStatus)) + return false; + } + return true; +} + +template<bool (CSPDirectiveList::*allowed)(const CSPHashValue&) const> +bool checkDigest(const String& source, uint8_t hashAlgorithmsUsed, const CSPDirectiveListVector& policies) +{ + // Any additions or subtractions from this struct should also modify the + // respective entries in the kSupportedPrefixes array in + // CSPSourceList::parseHash(). + static const struct { + ContentSecurityPolicyHashAlgorithm cspHashAlgorithm; + HashAlgorithm algorithm; + } kAlgorithmMap[] = { + { ContentSecurityPolicyHashAlgorithmSha1, HashAlgorithmSha1 }, + { ContentSecurityPolicyHashAlgorithmSha256, HashAlgorithmSha256 }, + { ContentSecurityPolicyHashAlgorithmSha384, HashAlgorithmSha384 }, + { ContentSecurityPolicyHashAlgorithmSha512, HashAlgorithmSha512 } + }; + + // Only bother normalizing the source/computing digests if there are any checks to be done. + if (hashAlgorithmsUsed == ContentSecurityPolicyHashAlgorithmNone) + return false; + + StringUTF8Adaptor normalizedSource(source, StringUTF8Adaptor::Normalize, WTF::EntitiesForUnencodables); + + // See comment in CSPSourceList::parseHash about why we are using this sizeof + // calculation instead of WTF_ARRAY_LENGTH. + for (size_t i = 0; i < (sizeof(kAlgorithmMap) / sizeof(kAlgorithmMap[0])); i++) { + DigestValue digest; + if (kAlgorithmMap[i].cspHashAlgorithm & hashAlgorithmsUsed) { + bool digestSuccess = computeDigest(kAlgorithmMap[i].algorithm, normalizedSource.data(), normalizedSource.length(), digest); + if (digestSuccess && isAllowedByAllWithHash<allowed>(policies, CSPHashValue(kAlgorithmMap[i].cspHashAlgorithm, digest))) + return true; + } + } + + return false; +} + +bool ContentSecurityPolicy::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithContext<&CSPDirectiveList::allowJavaScriptURLs>(m_policies, contextURL, contextLine, reportingStatus); +} + +bool ContentSecurityPolicy::allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineEventHandlers>(m_policies, contextURL, contextLine, reportingStatus); +} + +bool ContentSecurityPolicy::allowInlineScript(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineScript>(m_policies, contextURL, contextLine, reportingStatus); +} + +bool ContentSecurityPolicy::allowInlineStyle(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + if (m_overrideInlineStyleAllowed) + return true; + return isAllowedByAllWithContext<&CSPDirectiveList::allowInlineStyle>(m_policies, contextURL, contextLine, reportingStatus); +} + +bool ContentSecurityPolicy::allowEval(ScriptState* scriptState, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithState<&CSPDirectiveList::allowEval>(m_policies, scriptState, reportingStatus); +} + +String ContentSecurityPolicy::evalDisabledErrorMessage() const +{ + for (size_t i = 0; i < m_policies.size(); ++i) { + if (!m_policies[i]->allowEval(0, SuppressReport)) + return m_policies[i]->evalDisabledErrorMessage(); + } + return String(); +} + +bool ContentSecurityPolicy::allowPluginType(const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + for (size_t i = 0; i < m_policies.size(); ++i) { + if (!m_policies[i]->allowPluginType(type, typeAttribute, url, reportingStatus)) + return false; + } + return true; +} + +bool ContentSecurityPolicy::allowScriptFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const +{ + return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_policies, nonce); +} + +bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const +{ + return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policies, nonce); +} + +bool ContentSecurityPolicy::allowScriptHash(const String& source) const +{ + return checkDigest<&CSPDirectiveList::allowScriptHash>(source, m_scriptHashAlgorithmsUsed, m_policies); +} + +bool ContentSecurityPolicy::allowStyleHash(const String& source) const +{ + return checkDigest<&CSPDirectiveList::allowStyleHash>(source, m_styleHashAlgorithmsUsed, m_policies); +} + +void ContentSecurityPolicy::usesScriptHashAlgorithms(uint8_t algorithms) +{ + m_scriptHashAlgorithmsUsed |= algorithms; +} + +void ContentSecurityPolicy::usesStyleHashAlgorithms(uint8_t algorithms) +{ + m_styleHashAlgorithmsUsed |= algorithms; +} + +bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowImageFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowImageFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowStyleFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowStyleFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowFontFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowFontFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowMediaFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowMediaFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowConnectToSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowConnectToSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowFormAction(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowFormAction>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowBaseURI(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowAncestors(LocalFrame* frame, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithFrame<&CSPDirectiveList::allowAncestors>(m_policies, frame, reportingStatus); +} + +bool ContentSecurityPolicy::allowChildContextFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + return isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::allowWorkerContextFromSource(const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const +{ + // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure the impact of this backwards-incompatible change. + if (m_executionContext->isDocument()) { + Document* document = static_cast<Document*>(m_executionContext); + UseCounter::count(*document, UseCounter::WorkerSubjectToCSP); + if (isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, SuppressReport) && !isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, SuppressReport)) + UseCounter::count(*document, UseCounter::WorkerAllowedByChildBlockedByScript); + } + + return experimentalFeaturesEnabled() ? + isAllowedByAllWithURL<&CSPDirectiveList::allowChildContextFromSource>(m_policies, url, reportingStatus) : + isAllowedByAllWithURL<&CSPDirectiveList::allowScriptFromSource>(m_policies, url, reportingStatus); +} + +bool ContentSecurityPolicy::isActive() const +{ + return !m_policies.isEmpty(); +} + +ReflectedXSSDisposition ContentSecurityPolicy::reflectedXSSDisposition() const +{ + ReflectedXSSDisposition disposition = ReflectedXSSUnset; + for (size_t i = 0; i < m_policies.size(); ++i) { + if (m_policies[i]->reflectedXSSDisposition() > disposition) + disposition = std::max(disposition, m_policies[i]->reflectedXSSDisposition()); + } + return disposition; +} + +ReferrerPolicy ContentSecurityPolicy::referrerPolicy() const +{ + ReferrerPolicy policy = ReferrerPolicyDefault; + bool first = true; + for (size_t i = 0; i < m_policies.size(); ++i) { + if (m_policies[i]->didSetReferrerPolicy()) { + if (first) + policy = m_policies[i]->referrerPolicy(); + else + policy = mergeReferrerPolicies(policy, m_policies[i]->referrerPolicy()); + } + } + return policy; +} + +bool ContentSecurityPolicy::didSetReferrerPolicy() const +{ + for (size_t i = 0; i < m_policies.size(); ++i) { + if (m_policies[i]->didSetReferrerPolicy()) + return true; + } + return false; +} + +SecurityOrigin* ContentSecurityPolicy::securityOrigin() const +{ + return m_executionContext->securityContext().securityOrigin(); +} + +const KURL ContentSecurityPolicy::url() const +{ + return m_executionContext->contextURL(); +} + +KURL ContentSecurityPolicy::completeURL(const String& url) const +{ + return m_executionContext->contextCompleteURL(url); +} + +void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const +{ + if (Document* document = this->document()) + document->enforceSandboxFlags(mask); +} + +static String stripURLForUseInReport(Document* document, const KURL& url) +{ + if (!url.isValid()) + return String(); + if (!url.isHierarchical() || url.protocolIs("file")) + return url.protocol(); + return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsReferrer() : SecurityOrigin::create(url)->toString(); +} + +static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventInit& init, Document* document, const String& directiveText, const String& effectiveDirective, const KURL& blockedURL, const String& header) +{ + init.documentURI = document->url().string(); + init.referrer = document->referrer(); + init.blockedURI = stripURLForUseInReport(document, blockedURL); + init.violatedDirective = directiveText; + init.effectiveDirective = effectiveDirective; + init.originalPolicy = header; + init.sourceFile = String(); + init.lineNumber = 0; + init.columnNumber = 0; + init.statusCode = 0; + + if (!SecurityOrigin::isSecure(document->url()) && document->loader()) + init.statusCode = document->loader()->response().httpStatusCode(); + + RefPtrWillBeRawPtr<ScriptCallStack> stack = createScriptCallStack(1, false); + if (!stack) + return; + + const ScriptCallFrame& callFrame = stack->at(0); + + if (callFrame.lineNumber()) { + KURL source = KURL(ParsedURLString, callFrame.sourceURL()); + init.sourceFile = stripURLForUseInReport(document, source); + init.lineNumber = callFrame.lineNumber(); + init.columnNumber = callFrame.columnNumber(); + } +} + +void ContentSecurityPolicy::reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const Vector<KURL>& reportURIs, const String& header) +{ + // FIXME: Support sending reports from worker. + if (!m_executionContext->isDocument()) + return; + + Document* document = this->document(); + LocalFrame* frame = document->frame(); + if (!frame) + return; + + SecurityPolicyViolationEventInit violationData; + gatherSecurityPolicyViolationEventData(violationData, document, directiveText, effectiveDirective, blockedURL, header); + + if (experimentalFeaturesEnabled()) + frame->domWindow()->enqueueDocumentEvent(SecurityPolicyViolationEvent::create(EventTypeNames::securitypolicyviolation, violationData)); + + if (reportURIs.isEmpty()) + return; + + // We need to be careful here when deciding what information to send to the + // report-uri. Currently, we send only the current document's URL and the + // directive that was violated. The document's URL is safe to send because + // it's the document itself that's requesting that it be sent. You could + // make an argument that we shouldn't send HTTPS document URLs to HTTP + // report-uris (for the same reasons that we supress the Referer in that + // case), but the Referer is sent implicitly whereas this request is only + // sent explicitly. As for which directive was violated, that's pretty + // harmless information. + + RefPtr<JSONObject> cspReport = JSONObject::create(); + cspReport->setString("document-uri", violationData.documentURI); + cspReport->setString("referrer", violationData.referrer); + cspReport->setString("violated-directive", violationData.violatedDirective); + if (experimentalFeaturesEnabled()) + cspReport->setString("effective-directive", violationData.effectiveDirective); + cspReport->setString("original-policy", violationData.originalPolicy); + cspReport->setString("blocked-uri", violationData.blockedURI); + if (!violationData.sourceFile.isEmpty() && violationData.lineNumber) { + cspReport->setString("source-file", violationData.sourceFile); + cspReport->setNumber("line-number", violationData.lineNumber); + cspReport->setNumber("column-number", violationData.columnNumber); + } + cspReport->setNumber("status-code", violationData.statusCode); + + RefPtr<JSONObject> reportObject = JSONObject::create(); + reportObject->setObject("csp-report", cspReport.release()); + String stringifiedReport = reportObject->toJSONString(); + + if (!shouldSendViolationReport(stringifiedReport)) + return; + + RefPtr<FormData> report = FormData::create(stringifiedReport.utf8()); + + for (size_t i = 0; i < reportURIs.size(); ++i) + PingLoader::sendViolationReport(frame, reportURIs[i], report, PingLoader::ContentSecurityPolicyViolationReport); + + didSendViolationReport(stringifiedReport); +} + +void ContentSecurityPolicy::reportInvalidReferrer(const String& invalidValue) const +{ + logToConsole("The 'referrer' Content Security Policy directive has the invalid value \"" + invalidValue + "\". Valid values are \"always\", \"default\", \"never\", and \"origin\"."); +} + +void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) const +{ + logToConsole("The report-only Content Security Policy '" + header + "' was delivered via a <meta> element, which is disallowed. The policy has been ignored."); +} + +void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) const +{ + logToConsole("The Content Security Policy '" + header + "' was delivered via a <meta> element outside the document's <head>, which is disallowed. The policy has been ignored."); +} + +void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) const +{ + logToConsole("The Content Security Policy directive '" + name + "' is ignored when delivered in a report-only policy."); +} + +void ContentSecurityPolicy::reportUnsupportedDirective(const String& name) const +{ + DEFINE_STATIC_LOCAL(String, allow, ("allow")); + DEFINE_STATIC_LOCAL(String, options, ("options")); + DEFINE_STATIC_LOCAL(String, policyURI, ("policy-uri")); + DEFINE_STATIC_LOCAL(String, allowMessage, ("The 'allow' directive has been replaced with 'default-src'. Please use that directive instead, as 'allow' has no effect.")); + DEFINE_STATIC_LOCAL(String, optionsMessage, ("The 'options' directive has been replaced with 'unsafe-inline' and 'unsafe-eval' source expressions for the 'script-src' and 'style-src' directives. Please use those directives instead, as 'options' has no effect.")); + DEFINE_STATIC_LOCAL(String, policyURIMessage, ("The 'policy-uri' directive has been removed from the specification. Please specify a complete policy via the Content-Security-Policy header.")); + + String message = "Unrecognized Content-Security-Policy directive '" + name + "'.\n"; + if (equalIgnoringCase(name, allow)) + message = allowMessage; + else if (equalIgnoringCase(name, options)) + message = optionsMessage; + else if (equalIgnoringCase(name, policyURI)) + message = policyURIMessage; + + logToConsole(message); +} + +void ContentSecurityPolicy::reportDirectiveAsSourceExpression(const String& directiveName, const String& sourceExpression) const +{ + String message = "The Content Security Policy directive '" + directiveName + "' contains '" + sourceExpression + "' as a source expression. Did you mean '" + directiveName + " ...; " + sourceExpression + "...' (note the semicolon)?"; + logToConsole(message); +} + +void ContentSecurityPolicy::reportDuplicateDirective(const String& name) const +{ + String message = "Ignoring duplicate Content-Security-Policy directive '" + name + "'.\n"; + logToConsole(message); +} + +void ContentSecurityPolicy::reportInvalidPluginTypes(const String& pluginType) const +{ + String message; + if (pluginType.isNull()) + message = "'plugin-types' Content Security Policy directive is empty; all plugins will be blocked.\n"; + else + message = "Invalid plugin type in 'plugin-types' Content Security Policy directive: '" + pluginType + "'.\n"; + logToConsole(message); +} + +void ContentSecurityPolicy::reportInvalidSandboxFlags(const String& invalidFlags) const +{ + logToConsole("Error while parsing the 'sandbox' Content Security Policy directive: " + invalidFlags); +} + +void ContentSecurityPolicy::reportInvalidReflectedXSS(const String& invalidValue) const +{ + logToConsole("The 'reflected-xss' Content Security Policy directive has the invalid value \"" + invalidValue + "\". Valid values are \"allow\", \"filter\", and \"block\"."); +} + +void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter(const String& directiveName, const String& value) const +{ + String message = "The value for Content Security Policy directive '" + directiveName + "' contains an invalid character: '" + value + "'. Non-whitespace characters outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC 3986, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1."; + logToConsole(message); +} + +void ContentSecurityPolicy::reportInvalidPathCharacter(const String& directiveName, const String& value, const char invalidChar) const +{ + ASSERT(invalidChar == '#' || invalidChar == '?'); + + String ignoring = "The fragment identifier, including the '#', will be ignored."; + if (invalidChar == '?') + ignoring = "The query component, including the '?', will be ignored."; + String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring; + logToConsole(message); +} + +void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiveName, const String& source) const +{ + String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ignored."; + if (equalIgnoringCase(source, "'none'")) + message = message + " Note that 'none' has no effect unless it is the only expression in the source list."; + logToConsole(message); +} + +void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const +{ + logToConsole("The Content Security Policy '" + policy + "' was delivered in report-only mode, but does not specify a 'report-uri'; the policy will have no effect. Please either add a 'report-uri' directive, or deliver the policy via the 'Content-Security-Policy' header."); +} + +void ContentSecurityPolicy::logToConsole(const String& message) const +{ + m_executionContext->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, message); +} + +void ContentSecurityPolicy::reportBlockedScriptExecutionToInspector(const String& directiveText) const +{ + m_executionContext->reportBlockedScriptExecutionToInspector(directiveText); +} + +bool ContentSecurityPolicy::experimentalFeaturesEnabled() const +{ + return RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnabled(); +} + +bool ContentSecurityPolicy::shouldBypassMainWorld(ExecutionContext* context) +{ + if (context && context->isDocument()) { + Document* document = toDocument(context); + if (document->frame()) + return document->frame()->script().shouldBypassMainWorldContentSecurityPolicy(); + } + return false; +} + +bool ContentSecurityPolicy::shouldSendViolationReport(const String& report) const +{ + // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report. + return !m_violationReportsSent.contains(report.impl()->hash()); +} + +void ContentSecurityPolicy::didSendViolationReport(const String& report) +{ + m_violationReportsSent.add(report.impl()->hash()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicy.h b/chromium/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h index 0720123a02d..5d07921bfef 100644 --- a/chromium/third_party/WebKit/Source/core/frame/ContentSecurityPolicy.h +++ b/chromium/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h @@ -27,9 +27,15 @@ #define ContentSecurityPolicy_h #include "bindings/v8/ScriptState.h" +#include "core/dom/Document.h" +#include "core/dom/ExecutionContext.h" +#include "platform/network/ContentSecurityPolicyParsers.h" #include "platform/network/HTTPParsers.h" +#include "platform/weborigin/ReferrerPolicy.h" #include "wtf/HashSet.h" #include "wtf/PassOwnPtr.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefCounted.h" #include "wtf/Vector.h" #include "wtf/text/StringHash.h" #include "wtf/text/TextPosition.h" @@ -46,46 +52,56 @@ class CSPDirectiveList; class DOMStringList; class JSONObject; class KURL; -class ExecutionContextClient; class SecurityOrigin; typedef int SandboxFlags; typedef Vector<OwnPtr<CSPDirectiveList> > CSPDirectiveListVector; -class ContentSecurityPolicy { +class ContentSecurityPolicy : public RefCounted<ContentSecurityPolicy> { WTF_MAKE_FAST_ALLOCATED; public: - static PassOwnPtr<ContentSecurityPolicy> create(ExecutionContextClient* client) + // CSP 1.0 Directives + static const char ConnectSrc[]; + static const char DefaultSrc[]; + static const char FontSrc[]; + static const char FrameSrc[]; + static const char ImgSrc[]; + static const char MediaSrc[]; + static const char ObjectSrc[]; + static const char ReportURI[]; + static const char Sandbox[]; + static const char ScriptSrc[]; + static const char StyleSrc[]; + + // CSP 1.1 Directives + static const char BaseURI[]; + static const char ChildSrc[]; + static const char FormAction[]; + static const char FrameAncestors[]; + static const char PluginTypes[]; + static const char ReflectedXSS[]; + static const char Referrer[]; + + static PassRefPtr<ContentSecurityPolicy> create(ExecutionContext* executionContext) { - return adoptPtr(new ContentSecurityPolicy(client)); + return adoptRef(new ContentSecurityPolicy(executionContext)); } ~ContentSecurityPolicy(); void copyStateFrom(const ContentSecurityPolicy*); - enum HeaderType { - Report, - Enforce, - }; - enum ReportingStatus { SendReport, SuppressReport }; - enum HashAlgorithms { - HashAlgorithmsNone = 0, - HashAlgorithmsSha1 = 1 << 1, - HashAlgorithmsSha256 = 1 << 2 - }; - void didReceiveHeaders(const ContentSecurityPolicyResponseHeaders&); - void didReceiveHeader(const String&, HeaderType); + void didReceiveHeader(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicyHeaderSource); // These functions are wrong because they assume that there is only one header. // FIXME: Replace them with functions that return vectors. const String& deprecatedHeader() const; - HeaderType deprecatedHeaderType() const; + ContentSecurityPolicyHeaderType deprecatedHeaderType() const; bool allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ReportingStatus = SendReport) const; bool allowInlineEventHandlers(const String& contextURL, const WTF::OrdinalNumber& contextLine, ReportingStatus = SendReport) const; @@ -104,20 +120,28 @@ public: bool allowConnectToSource(const KURL&, ReportingStatus = SendReport) const; bool allowFormAction(const KURL&, ReportingStatus = SendReport) const; bool allowBaseURI(const KURL&, ReportingStatus = SendReport) const; + bool allowAncestors(LocalFrame*, ReportingStatus = SendReport) const; + bool allowChildContextFromSource(const KURL&, ReportingStatus = SendReport) const; + bool allowWorkerContextFromSource(const KURL&, ReportingStatus = SendReport) const; + // The nonce and hash allow functions are guaranteed to not have any side // effects, including reporting. bool allowScriptNonce(const String& nonce) const; bool allowStyleNonce(const String& nonce) const; bool allowScriptHash(const String& source) const; + bool allowStyleHash(const String& source) const; - void usesScriptHashAlgorithms(uint8_t HashAlgorithms); + void usesScriptHashAlgorithms(uint8_t ContentSecurityPolicyHashAlgorithm); + void usesStyleHashAlgorithms(uint8_t ContentSecurityPolicyHashAlgorithm); ReflectedXSSDisposition reflectedXSSDisposition() const; + ReferrerPolicy referrerPolicy() const; + bool didSetReferrerPolicy() const; + void setOverrideAllowInlineStyle(bool); bool isActive() const; - void gatherReportURIs(DOMStringList&) const; void reportDirectiveAsSourceExpression(const String& directiveName, const String& sourceExpression) const; void reportDuplicateDirective(const String&) const; @@ -129,6 +153,10 @@ public: void reportInvalidReflectedXSS(const String&) const; void reportMissingReportURI(const String&) const; void reportUnsupportedDirective(const String&) const; + void reportInvalidInReportOnly(const String&) const; + void reportInvalidReferrer(const String&) const; + void reportReportOnlyInMeta(const String&) const; + void reportMetaOutsideHead(const String&) const; void reportViolation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const Vector<KURL>& reportURIs, const String& header); void reportBlockedScriptExecutionToInspector(const String& directiveText) const; @@ -143,27 +171,31 @@ public: static bool shouldBypassMainWorld(ExecutionContext*); - ExecutionContextClient* client() { return m_client; } + static bool isDirectiveName(const String&); + + ExecutionContext* executionContext() const { return m_executionContext; } + Document* document() const { return m_executionContext->isDocument() ? toDocument(m_executionContext) : 0; } private: - explicit ContentSecurityPolicy(ExecutionContextClient*); + explicit ContentSecurityPolicy(ExecutionContext*); void logToConsole(const String& message) const; - void addPolicyFromHeaderValue(const String&, HeaderType); + void addPolicyFromHeaderValue(const String&, ContentSecurityPolicyHeaderType, ContentSecurityPolicyHeaderSource); bool shouldSendViolationReport(const String&) const; void didSendViolationReport(const String&); - ExecutionContextClient* m_client; + ExecutionContext* m_executionContext; bool m_overrideInlineStyleAllowed; CSPDirectiveListVector m_policies; HashSet<unsigned, AlreadyHashed> m_violationReportsSent; // We put the hash functions used on the policy object so that we only need - // to calculate a script hash once and then distribute it to all of the - // directives for validation. - uint8_t m_sourceHashAlgorithmsUsed; + // to calculate a hash once and then distribute it to all of the directives + // for validation. + uint8_t m_scriptHashAlgorithmsUsed; + uint8_t m_styleHashAlgorithmsUsed; }; } diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/MediaListDirective.cpp b/chromium/third_party/WebKit/Source/core/frame/csp/MediaListDirective.cpp new file mode 100644 index 00000000000..434c779dfd8 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/MediaListDirective.cpp @@ -0,0 +1,86 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/csp/MediaListDirective.h" + +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "platform/ParsingUtilities.h" +#include "platform/network/ContentSecurityPolicyParsers.h" +#include "wtf/HashSet.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +MediaListDirective::MediaListDirective(const String& name, const String& value, ContentSecurityPolicy* policy) + : CSPDirective(name, value, policy) +{ + Vector<UChar> characters; + value.appendTo(characters); + parse(characters.data(), characters.data() + characters.size()); +} + +bool MediaListDirective::allows(const String& type) +{ + return m_pluginTypes.contains(type); +} + +void MediaListDirective::parse(const UChar* begin, const UChar* end) +{ + const UChar* position = begin; + + // 'plugin-types ____;' OR 'plugin-types;' + if (position == end) { + policy()->reportInvalidPluginTypes(String()); + return; + } + + while (position < end) { + // _____ OR _____mime1/mime1 + // ^ ^ + skipWhile<UChar, isASCIISpace>(position, end); + if (position == end) + return; + + // mime1/mime1 mime2/mime2 + // ^ + begin = position; + if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { + skipWhile<UChar, isNotASCIISpace>(position, end); + policy()->reportInvalidPluginTypes(String(begin, position - begin)); + continue; + } + skipWhile<UChar, isMediaTypeCharacter>(position, end); + + // mime1/mime1 mime2/mime2 + // ^ + if (!skipExactly<UChar>(position, end, '/')) { + skipWhile<UChar, isNotASCIISpace>(position, end); + policy()->reportInvalidPluginTypes(String(begin, position - begin)); + continue; + } + + // mime1/mime1 mime2/mime2 + // ^ + if (!skipExactly<UChar, isMediaTypeCharacter>(position, end)) { + skipWhile<UChar, isNotASCIISpace>(position, end); + policy()->reportInvalidPluginTypes(String(begin, position - begin)); + continue; + } + skipWhile<UChar, isMediaTypeCharacter>(position, end); + + // mime1/mime1 mime2/mime2 OR mime1/mime1 OR mime1/mime1/error + // ^ ^ ^ + if (position < end && isNotASCIISpace(*position)) { + skipWhile<UChar, isNotASCIISpace>(position, end); + policy()->reportInvalidPluginTypes(String(begin, position - begin)); + continue; + } + m_pluginTypes.add(String(begin, position - begin)); + + ASSERT(position == end || isASCIISpace(*position)); + } +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/MediaListDirective.h b/chromium/third_party/WebKit/Source/core/frame/csp/MediaListDirective.h new file mode 100644 index 00000000000..9f230ce987e --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/MediaListDirective.h @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaListDirective_h +#define MediaListDirective_h + +#include "core/frame/csp/CSPDirective.h" +#include "platform/network/ContentSecurityPolicyParsers.h" +#include "wtf/HashSet.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ContentSecurityPolicy; + +class MediaListDirective FINAL : public CSPDirective { + WTF_MAKE_NONCOPYABLE(MediaListDirective); +public: + MediaListDirective(const String& name, const String& value, ContentSecurityPolicy*); + bool allows(const String& type); + +private: + void parse(const UChar* begin, const UChar* end); + + HashSet<String> m_pluginTypes; +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp b/chromium/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp new file mode 100644 index 00000000000..ccf8c37d792 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp @@ -0,0 +1,62 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/frame/csp/SourceListDirective.h" + +#include "core/frame/csp/CSPSourceList.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "platform/network/ContentSecurityPolicyParsers.h" +#include "platform/weborigin/KURL.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +SourceListDirective::SourceListDirective(const String& name, const String& value, ContentSecurityPolicy* policy) + : CSPDirective(name, value, policy) + , m_sourceList(policy, name) +{ + Vector<UChar> characters; + value.appendTo(characters); + + m_sourceList.parse(characters.data(), characters.data() + characters.size()); +} + +bool SourceListDirective::allows(const KURL& url) const +{ + return m_sourceList.matches(url.isEmpty() ? policy()->url() : url); +} + +bool SourceListDirective::allowInline() const +{ + return m_sourceList.allowInline(); +} + +bool SourceListDirective::allowEval() const +{ + return m_sourceList.allowEval(); +} + +bool SourceListDirective::allowNonce(const String& nonce) const +{ + return m_sourceList.allowNonce(nonce.stripWhiteSpace()); +} + +bool SourceListDirective::allowHash(const CSPHashValue& hashValue) const +{ + return m_sourceList.allowHash(hashValue); +} + +bool SourceListDirective::isHashOrNoncePresent() const +{ + return m_sourceList.isHashOrNoncePresent(); +} + +uint8_t SourceListDirective::hashAlgorithmsUsed() const +{ + return m_sourceList.hashAlgorithmsUsed(); +} + +} // namespace WebCore + diff --git a/chromium/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h b/chromium/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h new file mode 100644 index 00000000000..38005d13833 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SourceListDirective_h +#define SourceListDirective_h + +#include "core/frame/csp/CSPDirective.h" +#include "core/frame/csp/CSPSourceList.h" +#include "platform/network/ContentSecurityPolicyParsers.h" +#include "wtf/HashSet.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class ContentSecurityPolicy; +class KURL; + +class SourceListDirective FINAL : public CSPDirective { + WTF_MAKE_NONCOPYABLE(SourceListDirective); +public: + SourceListDirective(const String& name, const String& value, ContentSecurityPolicy*); + + bool allows(const KURL&) const; + bool allowInline() const; + bool allowEval() const; + bool allowNonce(const String& nonce) const; + bool allowHash(const CSPHashValue&) const; + bool isHashOrNoncePresent() const; + uint8_t hashAlgorithmsUsed() const; + +private: + CSPSourceList m_sourceList; +}; + +} // namespace WebCore + +#endif |