Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / Document.cpp
index e319911..13a6cc2 100644 (file)
 #include "core/dom/Comment.h"
 #include "core/dom/ContextFeatures.h"
 #include "core/dom/DOMImplementation.h"
-#include "core/dom/DOMNamedFlowCollection.h"
 #include "core/dom/DocumentFragment.h"
 #include "core/dom/DocumentLifecycleNotifier.h"
 #include "core/dom/DocumentLifecycleObserver.h"
 #include "core/dom/DocumentMarkerController.h"
-#include "core/dom/DocumentSharedObjectPool.h"
 #include "core/dom/DocumentType.h"
 #include "core/dom/Element.h"
+#include "core/dom/ElementDataCache.h"
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/ExceptionCode.h"
 #include "core/dom/ExecutionContextTask.h"
 #include "core/dom/MainThreadTaskRunner.h"
-#include "core/dom/NamedFlowCollection.h"
+#include "core/dom/MutationObserver.h"
 #include "core/dom/NodeChildRemovalTracker.h"
 #include "core/dom/NodeFilter.h"
 #include "core/dom/NodeIterator.h"
 #include "core/frame/History.h"
 #include "core/frame/PageConsole.h"
 #include "core/frame/Settings.h"
-#include "core/frame/animation/AnimationController.h"
 #include "core/html/HTMLAllCollection.h"
 #include "core/html/HTMLAnchorElement.h"
 #include "core/html/HTMLCanvasElement.h"
 #include "core/html/HTMLImport.h"
 #include "core/html/HTMLInputElement.h"
 #include "core/html/HTMLLinkElement.h"
+#include "core/html/HTMLMetaElement.h"
 #include "core/html/HTMLNameCollection.h"
 #include "core/html/HTMLScriptElement.h"
 #include "core/html/HTMLStyleElement.h"
@@ -343,36 +342,6 @@ static void printNavigationErrorMessage(const Frame& frame, const KURL& activeUR
 
 uint64_t Document::s_globalTreeVersion = 0;
 
-// This class should be passed only to Document::postTask.
-class CheckFocusedElementTask FINAL : public ExecutionContextTask {
-public:
-    static PassOwnPtr<CheckFocusedElementTask> create()
-    {
-        return adoptPtr(new CheckFocusedElementTask());
-    }
-    virtual ~CheckFocusedElementTask() { }
-
-private:
-    CheckFocusedElementTask() { }
-    virtual void performTask(ExecutionContext* context) OVERRIDE
-    {
-        ASSERT(context->isDocument());
-        Document* document = toDocument(context);
-        document->didRunCheckFocusedElementTask();
-        Element* element = document->focusedElement();
-        if (!element)
-            return;
-        if (document->childNeedsStyleRecalc()) {
-            document->setNeedsFocusedElementCheck();
-            return;
-        }
-        if (element->renderer() && element->renderer()->needsLayout())
-            return;
-        if (!element->isFocusable())
-            document->setFocusedElement(0);
-    }
-};
-
 // This class doesn't work with non-Document ExecutionContext.
 class AutofocusTask FINAL : public ExecutionContextTask {
 public:
@@ -394,6 +363,39 @@ private:
     }
 };
 
+DocumentVisibilityObserver::DocumentVisibilityObserver(Document& document)
+    : m_document(0)
+{
+    registerObserver(document);
+}
+
+DocumentVisibilityObserver::~DocumentVisibilityObserver()
+{
+    unregisterObserver();
+}
+
+void DocumentVisibilityObserver::unregisterObserver()
+{
+    if (m_document) {
+        m_document->unregisterVisibilityObserver(this);
+        m_document = 0;
+    }
+}
+
+void DocumentVisibilityObserver::registerObserver(Document& document)
+{
+    ASSERT(!m_document);
+    m_document = &document;
+    if (m_document)
+        m_document->registerVisibilityObserver(this);
+}
+
+void DocumentVisibilityObserver::setObservedDocument(Document& document)
+{
+    unregisterObserver();
+    registerObserver(document);
+}
+
 Document::Document(const DocumentInit& initializer, DocumentClassFlags documentClasses)
     : ContainerNode(0, CreateDocument)
     , TreeScope(*this)
@@ -411,17 +413,15 @@ Document::Document(const DocumentInit& initializer, DocumentClassFlags documentC
     , m_paginatedForScreen(false)
     , m_compatibilityMode(NoQuirksMode)
     , m_compatibilityModeLocked(false)
-    , m_didPostCheckFocusedElementTask(false)
     , m_hasAutofocused(false)
+    , m_clearFocusedElementTimer(this, &Document::clearFocusedElementTimerFired)
     , m_domTreeVersion(++s_globalTreeVersion)
     , m_listenerTypes(0)
     , m_mutationObserverTypes(0)
     , m_visitedLinkState(VisitedLinkState::create(*this))
     , m_visuallyOrdered(false)
     , m_readyState(Complete)
-    , m_bParsing(false)
-    , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired)
-    , m_inStyleRecalc(false)
+    , m_isParsing(false)
     , m_gotoAnchorNeededAfterStylesheetsLoad(false)
     , m_containsValidityStyleRules(false)
     , m_updateFocusAppearanceRestoresSelection(false)
@@ -433,7 +433,6 @@ Document::Document(const DocumentInit& initializer, DocumentClassFlags documentC
     , m_cssTarget(0)
     , m_loadEventProgress(LoadEventNotRun)
     , m_startTime(currentTime())
-    , m_overMinimumLayoutThreshold(false)
     , m_scriptRunner(ScriptRunner::create(this))
     , m_xmlVersion("1.0")
     , m_xmlStandalone(StandaloneUnspecified)
@@ -453,6 +452,7 @@ Document::Document(const DocumentInit& initializer, DocumentClassFlags documentC
     , m_hasFullscreenElementStack(false)
     , m_loadEventDelayCount(0)
     , m_loadEventDelayTimer(this, &Document::loadEventDelayTimerFired)
+    , m_pluginLoadingTimer(this, &Document::pluginLoadingTimerFired)
     , m_didSetReferrerPolicy(false)
     , m_referrerPolicy(ReferrerPolicyDefault)
     , m_directionSetOnDocumentElement(false)
@@ -462,7 +462,7 @@ Document::Document(const DocumentInit& initializer, DocumentClassFlags documentC
     , m_lastHandledUserGestureTimestamp(0)
     , m_taskRunner(MainThreadTaskRunner::create(this))
     , m_registrationContext(initializer.registrationContext(this))
-    , m_sharedObjectPoolClearTimer(this, &Document::sharedObjectPoolClearTimerFired)
+    , m_elementDataCacheClearTimer(this, &Document::elementDataCacheClearTimerFired)
 #ifndef NDEBUG
     , m_didDispatchViewportPropertiesChanged(false)
 #endif
@@ -516,12 +516,10 @@ Document::~Document()
     ASSERT(m_ranges.isEmpty());
     ASSERT(!parentTreeScope());
     ASSERT(!hasGuardRefCount());
+    ASSERT(m_visibilityObservers.isEmpty());
 
     if (m_templateDocument)
-        m_templateDocument->setTemplateDocumentHost(0); // balanced in templateDocument().
-
-    if (Document* ownerDocument = this->ownerDocument())
-        ownerDocument->didRemoveEventTargetNode(this);
+        m_templateDocument->m_templateDocumentHost = 0; // balanced in ensureTemplateDocument().
 
     m_scriptRunner.clear();
 
@@ -547,6 +545,14 @@ Document::~Document()
         m_import = 0;
     }
 
+    if (m_timeline) {
+        m_timeline->detachFromDocument();
+    }
+
+    if (m_transitionTimeline) {
+        m_transitionTimeline->detachFromDocument();
+    }
+
     m_styleEngine.clear(); // We need to destory CSSFontSelector before destroying m_fetcher.
 
     if (m_elemSheet)
@@ -713,7 +719,7 @@ PassRefPtr<Element> Document::createElement(const AtomicString& name, ExceptionS
     if (isXHTMLDocument() || isHTMLDocument())
         return HTMLElementFactory::createHTMLElement(isHTMLDocument() ? name.lower() : name, *this, 0, false);
 
-    return createElement(QualifiedName(nullAtom, name, nullAtom), false);
+    return Element::create(QualifiedName(nullAtom, name, nullAtom), this);
 }
 
 PassRefPtr<Element> Document::createElement(const AtomicString& localName, const AtomicString& typeExtension, ExceptionState& exceptionState)
@@ -725,7 +731,7 @@ PassRefPtr<Element> Document::createElement(const AtomicString& localName, const
 
     RefPtr<Element> element;
 
-    if (RuntimeEnabledFeatures::customElementsEnabled() && CustomElement::isValidName(localName) && registrationContext()) {
+    if (CustomElement::isValidName(localName) && registrationContext()) {
         element = registrationContext()->createCustomTagElement(*this, QualifiedName(nullAtom, localName, xhtmlNamespaceURI));
     } else {
         element = createElement(localName, exceptionState);
@@ -733,34 +739,49 @@ PassRefPtr<Element> Document::createElement(const AtomicString& localName, const
             return 0;
     }
 
-    if (RuntimeEnabledFeatures::customElementsEnabled() && !typeExtension.isNull() && !typeExtension.isEmpty())
+    if (!typeExtension.isEmpty())
         CustomElementRegistrationContext::setIsAttributeAndTypeExtension(element.get(), typeExtension);
 
     return element;
 }
 
-PassRefPtr<Element> Document::createElementNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& typeExtension, ExceptionState& exceptionState)
+static inline QualifiedName createQualifiedName(const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState& exceptionState)
 {
     AtomicString prefix, localName;
-    if (!parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
-        return 0;
+    if (!Document::parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
+        return nullQName();
 
     QualifiedName qName(prefix, localName, namespaceURI);
-    if (!hasValidNamespaceForElements(qName)) {
+    if (!Document::hasValidNamespaceForElements(qName)) {
         exceptionState.throwDOMException(NamespaceError, "The namespace URI provided ('" + namespaceURI + "') is not valid for the qualified name provided ('" + qualifiedName + "').");
-        return 0;
+        return nullQName();
     }
 
+    return qName;
+}
+
+PassRefPtr<Element> Document::createElementNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState& exceptionState)
+{
+    QualifiedName qName(createQualifiedName(namespaceURI, qualifiedName, exceptionState));
+    if (qName == nullQName())
+        return 0;
+
+    return createElement(qName, false);
+}
+
+PassRefPtr<Element> Document::createElementNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, const AtomicString& typeExtension, ExceptionState& exceptionState)
+{
+    QualifiedName qName(createQualifiedName(namespaceURI, qualifiedName, exceptionState));
+    if (qName == nullQName())
+        return 0;
+
     RefPtr<Element> element;
-    if (CustomElement::isValidName(qName.localName()) && registrationContext()) {
+    if (CustomElement::isValidName(qName.localName()) && registrationContext())
         element = registrationContext()->createCustomTagElement(*this, qName);
-    } else {
-        element = createElementNS(namespaceURI, qualifiedName, exceptionState);
-        if (exceptionState.hadException())
-            return 0;
-    }
+    else
+        element = createElement(qName, false);
 
-    if (!typeExtension.isNull() && !typeExtension.isEmpty())
+    if (!typeExtension.isEmpty())
         CustomElementRegistrationContext::setIsAttributeAndTypeExtension(element.get(), typeExtension);
 
     return element;
@@ -796,7 +817,7 @@ void Document::didLoadAllImports()
 
 bool Document::haveImportsLoaded() const
 {
-    return !m_import || !m_import->isStateBlockedFromRunningScript();
+    return !m_import || !m_import->state().shouldBlockScriptExecution();
 }
 
 DOMWindow* Document::executingWindow()
@@ -1037,39 +1058,6 @@ bool Document::regionBasedColumnsEnabled() const
     return settings() && settings()->regionBasedColumnsEnabled();
 }
 
-PassRefPtr<DOMNamedFlowCollection> Document::webkitGetNamedFlows()
-{
-    if (!RuntimeEnabledFeatures::cssRegionsEnabled() || !renderView())
-        return 0;
-
-    updateStyleIfNeeded();
-
-    return namedFlows()->createCSSOMSnapshot();
-}
-
-NamedFlowCollection* Document::namedFlows()
-{
-    if (!m_namedFlows)
-        m_namedFlows = NamedFlowCollection::create(this);
-
-    return m_namedFlows.get();
-}
-
-PassRefPtr<Element> Document::createElementNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState& exceptionState)
-{
-    AtomicString prefix, localName;
-    if (!parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
-        return 0;
-
-    QualifiedName qName(prefix, localName, namespaceURI);
-    if (!hasValidNamespaceForElements(qName)) {
-        exceptionState.throwDOMException(NamespaceError, "The namespace URI provided ('" + namespaceURI + "') is not valid for the qualified name provided ('" + qualifiedName + "').");
-        return 0;
-    }
-
-    return createElement(qName, false);
-}
-
 String Document::readyState() const
 {
     DEFINE_STATIC_LOCAL(const String, loading, ("loading"));
@@ -1098,8 +1086,7 @@ void Document::setReadyState(ReadyState readyState)
     case Loading:
         if (!m_documentTiming.domLoading) {
             m_documentTiming.domLoading = monotonicallyIncreasingTime();
-            if (RuntimeEnabledFeatures::webAnimationsCSSEnabled())
-                m_timeline->setZeroTime(m_documentTiming.domLoading);
+            m_timeline->setZeroTime(m_documentTiming.domLoading);
         }
         break;
     case Interactive:
@@ -1156,7 +1143,7 @@ void Document::setContentLanguage(const AtomicString& language)
     m_contentLanguage = language;
 
     // Document's style depends on the content language.
-    setNeedsStyleRecalc();
+    setNeedsStyleRecalc(SubtreeStyleChange);
 }
 
 void Document::setXMLVersion(const String& version, ExceptionState& exceptionState)
@@ -1337,7 +1324,7 @@ void Document::setTitle(const String& title)
         m_titleElement = 0;
     else if (!m_titleElement) {
         if (HTMLElement* headElement = head()) {
-            m_titleElement = createElement(titleTag, false);
+            m_titleElement = HTMLTitleElement::create(*this);
             headElement->appendChild(m_titleElement);
         }
     }
@@ -1371,7 +1358,7 @@ void Document::removeTitle(Element* titleElement)
     // FIXME: This is broken for SVG.
     // Update title based on first title element in the head, if one exists.
     if (HTMLElement* headElement = head()) {
-        for (Element* element = headElement->firstElementChild(); element; element = element->nextElementSibling()) {
+        for (Element* element = ElementTraversal::firstWithin(*headElement); element; element = ElementTraversal::nextSibling(*element)) {
             if (!element->hasTagName(titleTag))
                 continue;
             HTMLTitleElement* title = toHTMLTitleElement(element);
@@ -1405,11 +1392,28 @@ bool Document::hidden() const
     return pageVisibilityState() != PageVisibilityStateVisible;
 }
 
-void Document::dispatchVisibilityStateChangeEvent()
+void Document::didChangeVisibilityState()
 {
     dispatchEvent(Event::create(EventTypeNames::visibilitychange));
     // Also send out the deprecated version until it can be removed.
     dispatchEvent(Event::create(EventTypeNames::webkitvisibilitychange));
+
+    PageVisibilityState state = pageVisibilityState();
+    HashSet<DocumentVisibilityObserver*>::const_iterator observerEnd = m_visibilityObservers.end();
+    for (HashSet<DocumentVisibilityObserver*>::const_iterator it = m_visibilityObservers.begin(); it != observerEnd; ++it)
+        (*it)->didChangeVisibilityState(state);
+}
+
+void Document::registerVisibilityObserver(DocumentVisibilityObserver* observer)
+{
+    ASSERT(!m_visibilityObservers.contains(observer));
+    m_visibilityObservers.add(observer);
+}
+
+void Document::unregisterVisibilityObserver(DocumentVisibilityObserver* observer)
+{
+    ASSERT(m_visibilityObservers.contains(observer));
+    m_visibilityObservers.remove(observer);
 }
 
 String Document::nodeName() const
@@ -1528,38 +1532,44 @@ PassRefPtr<TreeWalker> Document::createTreeWalker(Node* root, unsigned whatToSho
 
 bool Document::shouldCallRecalcStyleForDocument()
 {
-    return needsStyleRecalc() || childNeedsStyleRecalc() || childNeedsDistributionRecalc() || !m_useElementsNeedingUpdate.isEmpty();
+    if (!isActive() || !view())
+        return false;
+    return needsStyleRecalc() || childNeedsStyleRecalc() || childNeedsDistributionRecalc() || !m_useElementsNeedingUpdate.isEmpty() || childNeedsStyleInvalidation();
 }
 
-void Document::scheduleStyleRecalc()
+bool Document::shouldScheduleStyleRecalc()
 {
     if (!isActive())
-        return;
+        return false;
+    if (hasPendingStyleRecalc())
+        return false;
+    if (inStyleRecalc())
+        return false;
+    // InPreLayout will recalc style itself. There's no reason to schedule another recalc.
+    if (m_lifecycle.state() == DocumentLifecycle::InPreLayout)
+        return false;
+    if (!shouldScheduleLayout())
+        return false;
+    return true;
+}
 
-    if (m_styleRecalcTimer.isActive() || !shouldScheduleLayout())
+void Document::scheduleStyleRecalc()
+{
+    if (!shouldScheduleStyleRecalc())
         return;
 
     ASSERT(shouldCallRecalcStyleForDocument());
 
-    m_styleRecalcTimer.startOneShot(0);
+    if (!view()->isServicingAnimations())
+        view()->scheduleAnimation();
+    m_lifecycle.advanceTo(DocumentLifecycle::StyleRecalcPending);
 
     InspectorInstrumentation::didScheduleStyleRecalculation(this);
 }
 
-void Document::unscheduleStyleRecalc()
-{
-    ASSERT(!isActive() || (!needsStyleRecalc() && !childNeedsStyleRecalc()));
-    m_styleRecalcTimer.stop();
-}
-
 bool Document::hasPendingForcedStyleRecalc() const
 {
-    return m_styleRecalcTimer.isActive() && !m_inStyleRecalc && styleChangeType() >= SubtreeStyleChange;
-}
-
-void Document::styleRecalcTimerFired(Timer<Document>*)
-{
-    updateStyleIfNeeded();
+    return hasPendingStyleRecalc() && !inStyleRecalc() && styleChangeType() >= SubtreeStyleChange;
 }
 
 void Document::updateDistributionIfNeeded()
@@ -1570,6 +1580,21 @@ void Document::updateDistributionIfNeeded()
     recalcDistribution();
 }
 
+void Document::updateStyleInvalidationIfNeeded()
+{
+    if (!childNeedsStyleInvalidation())
+        return;
+    TRACE_EVENT0("webkit", "Document::computeNeedsStyleRecalcState");
+    if (!styleResolver()) {
+        clearChildNeedsStyleInvalidation();
+        return;
+    }
+
+    // FIXME: the style resolver can be deleted at present. Either resolve
+    // crbug.com/335964 or move the invalidation data elsewhere.
+    styleResolver()->ensureRuleFeatureSet().computeStyleInvalidation(*this);
+}
+
 void Document::updateDistributionForNodeIfNeeded(Node* node)
 {
     if (node->inDocument()) {
@@ -1585,16 +1610,8 @@ void Document::updateDistributionForNodeIfNeeded(Node* node)
         root->recalcDistribution();
 }
 
-void Document::setStyleDependentState(RenderStyle* documentStyle)
+void Document::setupFontBuilder(RenderStyle* documentStyle)
 {
-    const Pagination& pagination = view()->pagination();
-    if (pagination.mode != Pagination::Unpaginated) {
-        Pagination::setStylesForPaginationMode(pagination.mode, documentStyle);
-        documentStyle->setColumnGap(pagination.gap);
-        if (renderView()->hasColumns())
-            renderView()->updateColumnInfoFromStyle(documentStyle);
-    }
-
     FontBuilder fontBuilder;
     fontBuilder.initForStyleResolve(*this, documentStyle, isSVGDocument());
     RefPtr<CSSFontSelector> selector = m_styleEngine->fontSelector();
@@ -1612,10 +1629,11 @@ void Document::inheritHtmlAndBodyElementStyles(StyleRecalcChange change)
 
     WritingMode rootWritingMode = documentElementStyle->writingMode();
     TextDirection rootDirection = documentElementStyle->direction();
-    HTMLElement* body = this->body();
 
+    HTMLElement* body = this->body();
+    RefPtr<RenderStyle> bodyStyle;
     if (body) {
-        RefPtr<RenderStyle> bodyStyle = body->renderStyle();
+        bodyStyle = body->renderStyle();
         if (!bodyStyle || body->needsStyleRecalc() || documentElement()->needsStyleRecalc() || change == Force)
             bodyStyle = ensureStyleResolver().styleForElement(body, documentElementStyle.get());
         if (!writingModeSetOnDocumentElement())
@@ -1624,6 +1642,16 @@ void Document::inheritHtmlAndBodyElementStyles(StyleRecalcChange change)
             rootDirection = bodyStyle->direction();
     }
 
+    RefPtr<RenderStyle> overflowStyle;
+    if (Element* element = viewportDefiningElement(documentElementStyle.get())) {
+        if (element == body) {
+            overflowStyle = bodyStyle;
+        } else {
+            ASSERT(element == documentElement());
+            overflowStyle = documentElementStyle;
+        }
+    }
+
     // Resolved rem units are stored in the matched properties cache so we need to make sure to
     // invalidate the cache if the documentElement needed to reattach or the font size changed
     // and then trigger a full document recalc. We also need to clear it here since the
@@ -1633,50 +1661,84 @@ void Document::inheritHtmlAndBodyElementStyles(StyleRecalcChange change)
     // rare and just invalidate the cache for now.
     if (styleEngine()->usesRemUnits() && (documentElement()->needsAttach() || documentElement()->computedStyle()->fontSize() != documentElementStyle->fontSize())) {
         ensureStyleResolver().invalidateMatchedPropertiesCache();
-        documentElement()->setNeedsStyleRecalc();
+        documentElement()->setNeedsStyleRecalc(SubtreeStyleChange);
     }
 
     RefPtr<RenderStyle> documentStyle = renderView()->style();
-    if (documentStyle->writingMode() != rootWritingMode || documentStyle->direction() != rootDirection) {
+    if (documentStyle->writingMode() != rootWritingMode
+        || documentStyle->direction() != rootDirection
+        || (overflowStyle && (documentStyle->overflowX() != overflowStyle->overflowX() || documentStyle->overflowY() != overflowStyle->overflowY()))) {
         RefPtr<RenderStyle> newStyle = RenderStyle::clone(documentStyle.get());
         newStyle->setWritingMode(rootWritingMode);
         newStyle->setDirection(rootDirection);
+        EOverflow overflowX = OAUTO;
+        EOverflow overflowY = OAUTO;
+        if (overflowStyle) {
+            overflowX = overflowStyle->overflowX();
+            overflowY = overflowStyle->overflowY();
+            // Visible overflow on the viewport is meaningless, and the spec says to treat it as 'auto':
+            if (overflowX == OVISIBLE)
+                overflowX = OAUTO;
+            if (overflowY == OVISIBLE)
+                overflowY = OAUTO;
+
+            // Column-gap is (ab)used by the current paged overflow implementation (in lack of other
+            // ways to specify gaps between pages), so we have to propagate it too.
+            newStyle->setColumnGap(overflowStyle->columnGap());
+        }
+        newStyle->setOverflowX(overflowX);
+        newStyle->setOverflowY(overflowY);
         renderView()->setStyle(newStyle);
-        setStyleDependentState(newStyle.get());
+        setupFontBuilder(newStyle.get());
     }
 
     if (body) {
         if (RenderStyle* style = body->renderStyle()) {
             if (style->direction() != rootDirection || style->writingMode() != rootWritingMode)
-                body->setNeedsStyleRecalc();
+                body->setNeedsStyleRecalc(SubtreeStyleChange);
         }
     }
 
     if (RenderStyle* style = documentElement()->renderStyle()) {
         if (style->direction() != rootDirection || style->writingMode() != rootWritingMode)
-            documentElement()->setNeedsStyleRecalc();
+            documentElement()->setNeedsStyleRecalc(SubtreeStyleChange);
     }
 }
 
-void Document::recalcStyle(StyleRecalcChange change)
+void Document::updateStyleIfNeeded()
 {
-    // we should not enter style recalc while painting
-    RELEASE_ASSERT(!view() || !view()->isPainting());
+    updateStyle(NoChange);
+}
 
-    // FIXME: We should never enter here without a FrameView or with an inactive document.
-    if (!isActive() || !view())
+// FIXME: We need a better name than updateStyleIfNeeded. It's performing style invalidation,
+// style recalc, distribution and <use> shadow tree creation.
+void Document::updateStyle(StyleRecalcChange change)
+{
+    ASSERT(isMainThread());
+
+    if (!shouldCallRecalcStyleForDocument())
         return;
 
-    if (m_inStyleRecalc)
+    if (inStyleRecalc())
         return;
 
+    // Entering here from inside layout or paint would be catastrophic since recalcStyle can
+    // tear down the render tree or (unfortunately) run script. Kill the whole renderer if
+    // someone managed to get into here from inside layout or paint.
+    RELEASE_ASSERT(!view()->isInPerformLayout());
+    RELEASE_ASSERT(!view()->isPainting());
+
+    // Script can run below in PostAttachCallbacks or WidgetUpdates, so protect the Frame.
+    RefPtr<Frame> protect(m_frame);
+
     TRACE_EVENT0("webkit", "Document::recalcStyle");
     TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "RecalcStyle");
 
     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willRecalculateStyle(this);
 
     updateDistributionIfNeeded();
-    updateUseShadowTrees();
+    updateUseShadowTreesIfNeeded();
+    updateStyleInvalidationIfNeeded();
 
     if (m_evaluateMediaQueriesOnStyleRecalc) {
         m_evaluateMediaQueriesOnStyleRecalc = false;
@@ -1696,7 +1758,7 @@ void Document::recalcStyle(StyleRecalcChange change)
     {
         PostAttachCallbacks::SuspendScope suspendPostAttachCallbacks;
         RenderWidget::UpdateSuspendScope suspendWidgetHierarchyUpdates;
-        TemporaryChange<bool> changeInStyleRecalc(m_inStyleRecalc, true);
+        m_lifecycle.advanceTo(DocumentLifecycle::InStyleRecalc);
 
         if (styleChangeType() >= SubtreeStyleChange)
             change = Force;
@@ -1736,7 +1798,6 @@ void Document::recalcStyle(StyleRecalcChange change)
         view()->updateCompositingLayersAfterStyleChange();
 
         clearChildNeedsStyleRecalc();
-        unscheduleStyleRecalc();
 
         if (m_styleEngine->hasResolver()) {
             // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
@@ -1744,29 +1805,25 @@ void Document::recalcStyle(StyleRecalcChange change)
             m_styleEngine->resetCSSFeatureFlags(resolver.ensureRuleFeatureSet());
             resolver.clearStyleSharingList();
         }
-    }
 
-    InspectorInstrumentation::didRecalculateStyle(cookie);
+        ASSERT(!needsStyleRecalc());
+        ASSERT(!childNeedsStyleRecalc());
+        ASSERT(inStyleRecalc());
+        m_lifecycle.advanceTo(DocumentLifecycle::StyleClean);
+    }
 
     // As a result of the style recalculation, the currently hovered element might have been
     // detached (for example, by setting display:none in the :hover style), schedule another mouseMove event
     // to check if any other elements ended up under the mouse pointer due to re-layout.
     if (hoverNode() && !hoverNode()->renderer() && frame())
         frame()->eventHandler().dispatchFakeMouseMoveEventSoon();
-}
-
-void Document::updateStyleIfNeeded()
-{
-    ASSERT(isMainThread());
-    ASSERT(!view() || (!view()->isInPerformLayout() && !view()->isPainting()));
 
-    if (!shouldCallRecalcStyleForDocument())
-        return;
+    if (m_focusedElement && !m_focusedElement->isFocusable())
+        clearFocusedElementSoon();
 
-    RefPtr<Frame> holder(m_frame);
-    AnimationUpdateBlock animationUpdateBlock(m_frame ? &m_frame->animation() : 0);
-    recalcStyle(NoChange);
     DocumentAnimations::serviceAfterStyleRecalc(*this);
+
+    InspectorInstrumentation::didRecalculateStyle(cookie);
 }
 
 void Document::updateStyleForNodeIfNeeded(Node* node)
@@ -1779,7 +1836,7 @@ void Document::updateStyleForNodeIfNeeded(Node* node)
     // the path from 'node' to the root needs style recalc.
 
     // Global needed.
-    bool needsRecalc = needsStyleRecalc() || childNeedsDistributionRecalc() || !m_useElementsNeedingUpdate.isEmpty();
+    bool needsRecalc = needsStyleRecalc() || childNeedsDistributionRecalc() || !m_useElementsNeedingUpdate.isEmpty() || childNeedsStyleInvalidation();
 
     // On the path.
     for (Node* ancestor = node; ancestor && !needsRecalc; ancestor = ancestor->parentOrShadowHostNode())
@@ -1810,17 +1867,26 @@ void Document::updateLayout()
 
     if (isActive() && frameView)
         frameView->partialLayout().reset();
-
-    setNeedsFocusedElementCheck();
 }
 
 void Document::setNeedsFocusedElementCheck()
 {
-    // FIXME: Using a Task doesn't look a good idea.
-    if (!m_focusedElement || m_didPostCheckFocusedElementTask)
-        return;
-    m_taskRunner->postTask(CheckFocusedElementTask::create());
-    m_didPostCheckFocusedElementTask = true;
+    setNeedsStyleRecalc(LocalStyleChange);
+}
+
+void Document::clearFocusedElementSoon()
+{
+    if (!m_clearFocusedElementTimer.isActive())
+        m_clearFocusedElementTimer.startOneShot(0);
+}
+
+void Document::clearFocusedElementTimerFired(Timer<Document>*)
+{
+    updateStyleIfNeeded();
+    m_clearFocusedElementTimer.stop();
+
+    if (m_focusedElement && !m_focusedElement->isFocusable())
+        setFocusedElement(0);
 }
 
 void Document::recalcStyleForLayoutIgnoringPendingStylesheets()
@@ -1845,7 +1911,7 @@ void Document::recalcStyleForLayoutIgnoringPendingStylesheets()
         // If new nodes have been added or style recalc has been done with style sheets still
         // pending, some nodes may not have had their real style calculated yet. Normally this
         // gets cleaned when style sheets arrive but here we need up-to-date style immediately.
-        recalcStyle(Force);
+        updateStyle(Force);
     }
 }
 
@@ -1972,7 +2038,7 @@ void Document::unscheduleUseShadowTreeUpdate(SVGUseElement& element)
     m_useElementsNeedingUpdate.remove(&element);
 }
 
-void Document::updateUseShadowTrees()
+void Document::updateUseShadowTreesIfNeeded()
 {
     if (m_useElementsNeedingUpdate.isEmpty())
         return;
@@ -2013,11 +2079,9 @@ void Document::attach(const AttachContext& context)
     m_renderView->setStyle(StyleResolver::styleForDocument(*this));
     view()->updateCompositingLayersAfterStyleChange();
 
-    m_styleEngine->didAttach();
-
     ContainerNode::attach(context);
 
-    m_lifecycle.advanceTo(DocumentLifecycle::Active);
+    m_lifecycle.advanceTo(DocumentLifecycle::StyleClean);
 }
 
 void Document::detach(const AttachContext& context)
@@ -2071,15 +2135,13 @@ void Document::detach(const AttachContext& context)
 
     ContainerNode::detach(context);
 
-    unscheduleStyleRecalc();
-
     m_styleEngine->didDetach();
 
     if (renderView)
         renderView->destroy();
 
-    if (m_touchEventTargets && m_touchEventTargets->size() && parentDocument())
-        parentDocument()->didRemoveEventTargetNode(this);
+    if (Document* parentDoc = parentDocument())
+        parentDoc->didClearTouchEventHandlers(this);
 
     // This is required, as our Frame might delete itself as soon as it detaches
     // us. However, this violates Node::detach() semantics, as it's never
@@ -2111,7 +2173,7 @@ void Document::prepareForDestruction()
 
 void Document::removeAllEventListeners()
 {
-    EventTarget::removeAllEventListeners();
+    ContainerNode::removeAllEventListeners();
 
     if (DOMWindow* domWindow = this->domWindow())
         domWindow->removeAllEventListeners();
@@ -2310,6 +2372,28 @@ HTMLHeadElement* Document::head()
     return 0;
 }
 
+Element* Document::viewportDefiningElement(RenderStyle* rootStyle) const
+{
+    // If a BODY element sets non-visible overflow, it is to be propagated to the viewport, as long
+    // as the following conditions are all met:
+    // (1) The root element is HTML.
+    // (2) It is the primary BODY element (we only assert for this, expecting callers to behave).
+    // (3) The root element has visible overflow.
+    // Otherwise it's the root element's properties that are to be propagated.
+    Element* rootElement = documentElement();
+    Element* bodyElement = body();
+    if (!rootElement)
+        return 0;
+    if (!rootStyle) {
+        rootStyle = rootElement->renderStyle();
+        if (!rootStyle)
+            return 0;
+    }
+    if (bodyElement && rootStyle->isOverflowVisible() && rootElement->hasTagName(htmlTag))
+        return bodyElement;
+    return rootElement;
+}
+
 void Document::close()
 {
     // FIXME: We should follow the specification more closely:
@@ -2402,14 +2486,12 @@ void Document::implicitClose()
         // Just bail out. Before or during the onload we were shifted to another page.
         // The old i-Bench suite does this. When this happens don't bother painting or laying out.
         m_loadEventProgress = LoadEventCompleted;
-        view()->unscheduleRelayout();
         return;
     }
 
     // We used to force a synchronous display and flush here.  This really isn't
     // necessary and can in fact be actively harmful if pages are loading at a rate of > 60fps
     // (if your platform is syncing flushes and limiting them to 60fps).
-    m_overMinimumLayoutThreshold = true;
     if (!ownerElement() || (ownerElement()->renderer() && !ownerElement()->renderer()->needsLayout())) {
         updateStyleIfNeeded();
 
@@ -2532,13 +2614,10 @@ Document::PageDismissalType Document::pageDismissalEventBeingDispatched() const
 
 void Document::setParsing(bool b)
 {
-    m_bParsing = b;
+    m_isParsing = b;
 
-    if (m_bParsing && !m_sharedObjectPool)
-        m_sharedObjectPool = DocumentSharedObjectPool::create();
-
-    if (!m_bParsing && view())
-        view()->scheduleRelayout();
+    if (m_isParsing && !m_elementDataCache)
+        m_elementDataCache = ElementDataCache::create();
 }
 
 bool Document::shouldScheduleLayout()
@@ -2555,19 +2634,7 @@ bool Document::shouldScheduleLayout()
 
 bool Document::shouldParserYieldAgressivelyBeforeScriptExecution()
 {
-    return view() && view()->layoutPending() && !minimumLayoutDelay();
-}
-
-int Document::minimumLayoutDelay()
-{
-    if (m_overMinimumLayoutThreshold)
-        return 0;
-
-    int elapsed = elapsedTime();
-    m_overMinimumLayoutThreshold = elapsed > cLayoutScheduleThreshold;
-
-    // We'll want to schedule the timer to fire at the minimum layout threshold.
-    return max(0, cLayoutScheduleThreshold - elapsed);
+    return view() && view()->layoutPending();
 }
 
 int Document::elapsedTime() const
@@ -2846,27 +2913,28 @@ CSSStyleSheet* Document::elementSheet()
     return m_elemSheet.get();
 }
 
-void Document::processHttpEquiv(const AtomicString& equiv, const AtomicString& content)
+void Document::processHttpEquiv(const AtomicString& equiv, const AtomicString& content, bool inDocumentHeadElement)
 {
     ASSERT(!equiv.isNull() && !content.isNull());
 
-    if (equalIgnoringCase(equiv, "default-style"))
+    if (equalIgnoringCase(equiv, "default-style")) {
         processHttpEquivDefaultStyle(content);
-    else if (equalIgnoringCase(equiv, "refresh"))
+    } else if (equalIgnoringCase(equiv, "refresh")) {
         processHttpEquivRefresh(content);
-    else if (equalIgnoringCase(equiv, "set-cookie"))
+    } else if (equalIgnoringCase(equiv, "set-cookie")) {
         processHttpEquivSetCookie(content);
-    else if (equalIgnoringCase(equiv, "content-language"))
+    } else if (equalIgnoringCase(equiv, "content-language")) {
         setContentLanguage(content);
-    else if (equalIgnoringCase(equiv, "x-dns-prefetch-control"))
+    } else if (equalIgnoringCase(equiv, "x-dns-prefetch-control")) {
         parseDNSPrefetchControlHeader(content);
-    else if (equalIgnoringCase(equiv, "x-frame-options"))
+    } else if (equalIgnoringCase(equiv, "x-frame-options")) {
         processHttpEquivXFrameOptions(content);
-    else if (equalIgnoringCase(equiv, "content-security-policy")
-        || equalIgnoringCase(equiv, "content-security-policy-report-only")
-        || equalIgnoringCase(equiv, "x-webkit-csp")
-        || equalIgnoringCase(equiv, "x-webkit-csp-report-only"))
-        processHttpEquivContentSecurityPolicy(equiv, content);
+    } else if (equalIgnoringCase(equiv, "content-security-policy") || equalIgnoringCase(equiv, "content-security-policy-report-only")) {
+        if (inDocumentHeadElement)
+            processHttpEquivContentSecurityPolicy(equiv, content);
+        else
+            contentSecurityPolicy()->reportMetaOutsideHead(content);
+    }
 }
 
 void Document::processHttpEquivContentSecurityPolicy(const AtomicString& equiv, const AtomicString& content)
@@ -2875,11 +2943,6 @@ void Document::processHttpEquivContentSecurityPolicy(const AtomicString& equiv,
         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Enforce, ContentSecurityPolicy::HeaderSourceMeta);
     else if (equalIgnoringCase(equiv, "content-security-policy-report-only"))
         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Report, ContentSecurityPolicy::HeaderSourceMeta);
-    // FIXME: Remove deprecation messages after the next release branch.
-    else if (equalIgnoringCase(equiv, "x-webkit-csp"))
-        UseCounter::countDeprecation(this, UseCounter::PrefixedContentSecurityPolicy);
-    else if (equalIgnoringCase(equiv, "x-webkit-csp-report-only"))
-        UseCounter::countDeprecation(this, UseCounter::PrefixedContentSecurityPolicyReportOnly);
     else
         ASSERT_NOT_REACHED();
 }
@@ -2954,7 +3017,7 @@ void Document::processHttpEquivXFrameOptions(const AtomicString& content)
         // Stopping the loader isn't enough, as we're already parsing the document; to honor the header's
         // intent, we must navigate away from the possibly partially-rendered document to a location that
         // doesn't inherit the parent's SecurityOrigin.
-        frame->navigationScheduler().scheduleLocationChange(this, SecurityOrigin::urlWithUniqueSecurityOrigin(), String());
+        frame->navigationScheduler().scheduleLocationChange(this, SecurityOrigin::urlWithUniqueSecurityOrigin(), Referrer());
         addConsoleMessageWithRequestIdentifier(SecurityMessageSource, ErrorMessageLevel, message, requestIdentifier);
     }
 }
@@ -3253,7 +3316,7 @@ void Document::styleResolverChanged(RecalcStyleTime updateTime, StyleResolverUpd
         return;
 
     m_evaluateMediaQueriesOnStyleRecalc = true;
-    setNeedsStyleRecalc();
+    setNeedsStyleRecalc(SubtreeStyleChange);
 
     if (updateTime == RecalcStyleImmediately)
         updateStyleIfNeeded();
@@ -3335,8 +3398,10 @@ void Document::setAnnotatedRegions(const Vector<AnnotatedRegionValue>& regions)
     setAnnotatedRegionsDirty(false);
 }
 
-bool Document::setFocusedElement(PassRefPtr<Element> prpNewFocusedElement, FocusDirection direction)
+bool Document::setFocusedElement(PassRefPtr<Element> prpNewFocusedElement, FocusType type)
 {
+    m_clearFocusedElementTimer.stop();
+
     RefPtr<Element> newFocusedElement = prpNewFocusedElement;
 
     // Make sure newFocusedNode is actually in this document
@@ -3362,10 +3427,6 @@ bool Document::setFocusedElement(PassRefPtr<Element> prpNewFocusedElement, Focus
 
         oldFocusedElement->setFocus(false);
 
-        // Dispatch a change event for text fields or textareas that have been edited
-        if (oldFocusedElement->wasChangedSinceLastFormControlChangeEvent())
-            oldFocusedElement->dispatchFormControlChangeEvent();
-
         // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
         // If page lost focus, blur event will have already been dispatched
         if (page() && (page()->focusController().isFocused())) {
@@ -3410,7 +3471,7 @@ bool Document::setFocusedElement(PassRefPtr<Element> prpNewFocusedElement, Focus
         // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
         // If page lost focus, event will be dispatched on page focus, don't duplicate
         if (page() && (page()->focusController().isFocused())) {
-            m_focusedElement->dispatchFocusEvent(oldFocusedElement.get(), direction);
+            m_focusedElement->dispatchFocusEvent(oldFocusedElement.get(), type);
 
 
             if (m_focusedElement != newFocusedElement) {
@@ -3489,8 +3550,6 @@ void Document::setCSSTarget(Element* n)
 
 void Document::registerNodeList(LiveNodeListBase* list)
 {
-    if (list->hasIdNameCache())
-        m_nodeListCounts[InvalidateOnIdNameAttrChange]++;
     m_nodeListCounts[list->invalidationType()]++;
     if (list->isRootedAtDocument())
         m_listsInvalidatedAtDocument.add(list);
@@ -3498,8 +3557,6 @@ void Document::registerNodeList(LiveNodeListBase* list)
 
 void Document::unregisterNodeList(LiveNodeListBase* list)
 {
-    if (list->hasIdNameCache())
-        m_nodeListCounts[InvalidateOnIdNameAttrChange]--;
     m_nodeListCounts[list->invalidationType()]--;
     if (list->isRootedAtDocument()) {
         ASSERT(m_listsInvalidatedAtDocument.contains(list));
@@ -3637,20 +3694,20 @@ void Document::didSplitTextNode(Text* oldNode)
     // FIXME: This should update markers for spelling and grammar checking.
 }
 
-void Document::setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, DOMWrapperWorld* isolatedWorld)
+void Document::setWindowAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener)
 {
     DOMWindow* domWindow = this->domWindow();
     if (!domWindow)
         return;
-    domWindow->setAttributeEventListener(eventType, listener, isolatedWorld);
+    domWindow->setAttributeEventListener(eventType, listener);
 }
 
-EventListener* Document::getWindowAttributeEventListener(const AtomicString& eventType, DOMWrapperWorld* isolatedWorld)
+EventListener* Document::getWindowAttributeEventListener(const AtomicString& eventType)
 {
     DOMWindow* domWindow = this->domWindow();
     if (!domWindow)
         return 0;
-    return domWindow->getAttributeEventListener(eventType, isolatedWorld);
+    return domWindow->getAttributeEventListener(eventType);
 }
 
 EventQueue* Document::eventQueue() const
@@ -3690,6 +3747,18 @@ PassRefPtr<Event> Document::createEvent(const String& eventType, ExceptionState&
     return 0;
 }
 
+PassRefPtr<Event> Document::createEvent(ExceptionState& exceptionState)
+{
+    if (!isSVGDocument()) {
+        exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, 0));
+        return 0;
+    }
+
+    UseCounter::count(this, UseCounter::DocumentCreateEventOptionalArgument);
+    // Legacy SVGDocument behavior.
+    return createEvent("undefined", exceptionState);
+}
+
 void Document::addMutationEventListenerTypeIfEnabled(ListenerType listenerType)
 {
     if (ContextFeatures::mutationEventsEnabled(this))
@@ -4038,7 +4107,7 @@ void Document::setEncodingData(const DocumentEncodingData& newData)
     // in the title bar.
     if (m_titleElement
         && encoding() != newData.encoding()
-        && !m_titleElement->firstElementChild()
+        && !ElementTraversal::firstWithin(*m_titleElement)
         && encoding() == Latin1Encoding()
         && m_titleElement->textContent().containsOnlyLatin1()) {
 
@@ -4057,7 +4126,7 @@ void Document::setEncodingData(const DocumentEncodingData& newData)
         // FIXME: How is possible to not have a renderer here?
         if (renderView())
             renderView()->style()->setRTLOrdering(m_visuallyOrdered ? VisualOrder : LogicalOrder);
-        setNeedsStyleRecalc();
+        setNeedsStyleRecalc(SubtreeStyleChange);
     }
 }
 
@@ -4104,6 +4173,22 @@ static Editor::Command command(Document* document, const String& commandName, bo
 
 bool Document::execCommand(const String& commandName, bool userInterface, const String& value)
 {
+    // We don't allow recusrive |execCommand()| to protect against attack code.
+    // Recursive call of |execCommand()| could be happened by moving iframe
+    // with script triggered by insertion, e.g. <iframe src="javascript:...">
+    // <iframe onload="...">. This usage is valid as of the specification
+    // although, it isn't common use case, rather it is used as attack code.
+    static bool inExecCommand = false;
+    if (inExecCommand) {
+        String message = "We don't execute document.execCommand() this time, because it is called recursively.";
+        addConsoleMessage(JSMessageSource, WarningMessageLevel, message);
+        return false;
+    }
+    TemporaryChange<bool> executeScope(inExecCommand, true);
+
+    // Postpone DOM mutation events, which can execute scripts and change
+    // DOM tree against implementation assumption.
+    EventQueueScope eventQueueScope;
     return command(this, commandName, userInterface).execute(value);
 }
 
@@ -4149,7 +4234,7 @@ KURL Document::openSearchDescriptionURL()
         return KURL();
 
     RefPtr<HTMLCollection> children = head()->children();
-    for (unsigned i = 0; Node* child = children->item(i); i++) {
+    for (unsigned i = 0; Element* child = children->item(i); i++) {
         if (!child->hasTagName(linkTag))
             continue;
         HTMLLinkElement* linkElement = toHTMLLinkElement(child);
@@ -4201,7 +4286,7 @@ void Document::setDesignMode(InheritedBool value)
 {
     m_designMode = value;
     for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree().traverseNext(m_frame))
-        frame->document()->setNeedsStyleRecalc();
+        frame->document()->setNeedsStyleRecalc(SubtreeStyleChange);
 }
 
 Document::InheritedBool Document::getDesignMode() const
@@ -4249,21 +4334,11 @@ WeakPtr<Document> Document::contextDocument()
 
 PassRefPtr<Attr> Document::createAttribute(const AtomicString& name, ExceptionState& exceptionState)
 {
-    return createAttributeNS(nullAtom, name, exceptionState, true);
-}
-
-PassRefPtr<Attr> Document::createAttributeNS(const AtomicString& namespaceURI, const AtomicString& qualifiedName, ExceptionState& exceptionState, bool shouldIgnoreNamespaceChecks)
-{
     AtomicString prefix, localName;
-    if (!parseQualifiedName(qualifiedName, prefix, localName, exceptionState))
+    if (!parseQualifiedName(name, prefix, localName, exceptionState))
         return 0;
 
-    QualifiedName qName(prefix, localName, namespaceURI);
-
-    if (!shouldIgnoreNamespaceChecks && !hasValidNamespaceForAttributes(qName)) {
-        exceptionState.throwDOMException(NamespaceError, "The namespace URI provided ('" + namespaceURI + "') is not valid for the qualified name provided ('" + qualifiedName + "').");
-        return 0;
-    }
+    QualifiedName qName(prefix, localName, nullAtom);
 
     return Attr::create(*this, qName, emptyAtom);
 }
@@ -4287,7 +4362,7 @@ bool Document::hasSVGRootNode() const
 
 PassRefPtr<HTMLCollection> Document::ensureCachedCollection(CollectionType type)
 {
-    return ensureRareData().ensureNodeLists().addCacheWithAtomicName<HTMLCollection>(this, type);
+    return ensureRareData().ensureNodeLists().addCache<HTMLCollection>(this, type);
 }
 
 PassRefPtr<HTMLCollection> Document::images()
@@ -4333,17 +4408,17 @@ PassRefPtr<HTMLCollection> Document::allForBinding()
 
 PassRefPtr<HTMLCollection> Document::all()
 {
-    return ensureRareData().ensureNodeLists().addCacheWithAtomicName<HTMLAllCollection>(this, DocAll);
+    return ensureRareData().ensureNodeLists().addCache<HTMLAllCollection>(this, DocAll);
 }
 
 PassRefPtr<HTMLCollection> Document::windowNamedItems(const AtomicString& name)
 {
-    return ensureRareData().ensureNodeLists().addCacheWithAtomicName<HTMLNameCollection>(this, WindowNamedItems, name);
+    return ensureRareData().ensureNodeLists().addCache<HTMLNameCollection>(this, WindowNamedItems, name);
 }
 
 PassRefPtr<HTMLCollection> Document::documentNamedItems(const AtomicString& name)
 {
-    return ensureRareData().ensureNodeLists().addCacheWithAtomicName<HTMLNameCollection>(this, DocumentNamedItems, name);
+    return ensureRareData().ensureNodeLists().addCache<HTMLNameCollection>(this, DocumentNamedItems, name);
 }
 
 void Document::finishedParsing()
@@ -4377,12 +4452,11 @@ void Document::finishedParsing()
         InspectorInstrumentation::domContentLoadedEventFired(f.get());
     }
 
-    // Schedule dropping of the DocumentSharedObjectPool. We keep it alive for a while after parsing finishes
+    // Schedule dropping of the ElementDataCache. We keep it alive for a while after parsing finishes
     // so that dynamically inserted content can also benefit from sharing optimizations.
-    // Note that we don't refresh the timer on pool access since that could lead to huge caches being kept
+    // Note that we don't refresh the timer on cache access since that could lead to huge caches being kept
     // alive indefinitely by something innocuous like JS setting .innerHTML repeatedly on a timer.
-    static const int timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds = 10;
-    m_sharedObjectPoolClearTimer.startOneShot(timeToKeepSharedObjectPoolAliveAfterParsingFinishedInSeconds);
+    m_elementDataCacheClearTimer.startOneShot(10);
 
     // Parser should have picked up all preloads by now
     m_fetcher->clearPreloads();
@@ -4391,9 +4465,9 @@ void Document::finishedParsing()
         m_import->didFinishParsing();
 }
 
-void Document::sharedObjectPoolClearTimerFired(Timer<Document>*)
+void Document::elementDataCacheClearTimerFired(Timer<Document>*)
 {
-    m_sharedObjectPool.clear();
+    m_elementDataCache.clear();
 }
 
 Vector<IconURL> Document::iconURLs(int iconTypesMask)
@@ -4407,7 +4481,7 @@ Vector<IconURL> Document::iconURLs(int iconTypesMask)
     RefPtr<HTMLCollection> children = head() ? head()->children() : 0;
     unsigned length = children ? children->length() : 0;
     for (unsigned i = 0; i < length; i++) {
-        Node* child = children->item(i);
+        Element* child = children->item(i);
         if (!child->hasTagName(linkTag))
             continue;
         HTMLLinkElement* linkElement = toHTMLLinkElement(child);
@@ -4649,7 +4723,7 @@ CanvasRenderingContext* Document::getCSSCanvasContext(const String& type, const
 
 HTMLCanvasElement* Document::getCSSCanvasElement(const String& name)
 {
-    RefPtr<HTMLCanvasElement>& element = m_cssCanvasElements.add(name, 0).iterator->value;
+    RefPtr<HTMLCanvasElement>& element = m_cssCanvasElements.add(name, 0).storedValue->value;
     if (!element) {
         element = HTMLCanvasElement::create(*this);
         element->setAccelerationDisabled(true);
@@ -4749,6 +4823,8 @@ void Document::tasksWereResumed()
         m_parser->resumeScheduledTasks();
     if (m_scriptedAnimationController)
         m_scriptedAnimationController->resume();
+
+    MutationObserver::resumeSuspendedObservers();
 }
 
 // FIXME: suspendScheduledTasks(), resumeScheduledTasks(), tasksNeedSuspension()
@@ -4841,6 +4917,18 @@ void Document::loadEventDelayTimerFired(Timer<Document>*)
         frame()->loader().checkCompleted();
 }
 
+void Document::loadPluginsSoon()
+{
+    // FIXME: Remove this timer once we don't need to compute layout to load plugins.
+    if (!m_pluginLoadingTimer.isActive())
+        m_pluginLoadingTimer.startOneShot(0);
+}
+
+void Document::pluginLoadingTimerFired(Timer<Document>*)
+{
+    updateLayout();
+}
+
 ScriptedAnimationController& Document::ensureScriptedAnimationController()
 {
     if (!m_scriptedAnimationController) {
@@ -4888,55 +4976,75 @@ PassRefPtr<TouchList> Document::createTouchList(Vector<RefPtr<Touch> >& touches)
 
 void Document::didAddTouchEventHandler(Node* handler)
 {
+    // The node should either be in this document, or be the Document node of a child
+    // of this document.
+    ASSERT(&handler->document() == this
+        || (handler->isDocumentNode() && toDocument(handler)->parentDocument() == this));
     if (!m_touchEventTargets.get())
         m_touchEventTargets = adoptPtr(new TouchEventTargetSet);
-    m_touchEventTargets->add(handler);
-    if (Document* parent = parentDocument()) {
-        parent->didAddTouchEventHandler(this);
+    bool isFirstHandler = m_touchEventTargets->isEmpty();
+
+    if (!m_touchEventTargets->add(handler).isNewEntry) {
+        // Just incremented refcount, no real change.
+        // If this is a child document node, then the count should never go above 1.
+        ASSERT(!handler->isDocumentNode() || &handler->document() == this);
         return;
     }
-    if (Page* page = this->page()) {
-        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
-            scrollingCoordinator->touchEventTargetRectsDidChange(this);
-        if (m_touchEventTargets->size() == 1)
-            frameHost()->chrome().client().needTouchEvents(true);
+
+    if (isFirstHandler) {
+        if (Document* parent = parentDocument()) {
+            parent->didAddTouchEventHandler(this);
+        } else {
+            // This is the first touch handler on the whole page.
+            if (FrameHost* frameHost = this->frameHost())
+                frameHost->chrome().client().needTouchEvents(true);
+        }
+    }
+
+    // When we're all done with all frames, ensure touch hit rects are marked as dirty.
+    if (!handler->isDocumentNode() || handler == this) {
+        if (Page* page = this->page()) {
+            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+                scrollingCoordinator->touchEventTargetRectsDidChange();
+        }
     }
 }
 
-void Document::didRemoveTouchEventHandler(Node* handler)
+void Document::didRemoveTouchEventHandler(Node* handler, bool clearAll)
 {
+    // Note that we can't assert that |handler| is in this document because it might be in
+    // the process of moving out of it.
+    ASSERT(clearAll || m_touchEventTargets->contains(handler));
     if (!m_touchEventTargets.get())
         return;
-    ASSERT(m_touchEventTargets->contains(handler));
-    m_touchEventTargets->remove(handler);
-    if (Document* parent = parentDocument()) {
-        parent->didRemoveTouchEventHandler(this);
-        return;
-    }
 
-    Page* page = this->page();
-    if (!page)
-        return;
-    if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
-        scrollingCoordinator->touchEventTargetRectsDidChange(this);
-    if (m_touchEventTargets->size())
-        return;
-    for (const Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
-        if (frame->document() && frame->document()->hasTouchEventHandlers())
+    if (clearAll) {
+        if (!m_touchEventTargets->contains(handler))
+            return;
+        m_touchEventTargets->removeAll(handler);
+    } else {
+        if (!m_touchEventTargets->remove(handler))
+            // Just decremented refcount, no real update.
             return;
     }
-    frameHost()->chrome().client().needTouchEvents(false);
-}
 
-void Document::didRemoveEventTargetNode(Node* handler)
-{
-    if (m_touchEventTargets && !m_touchEventTargets->isEmpty()) {
-        if (handler == this)
-            m_touchEventTargets->clear();
-        else
-            m_touchEventTargets->removeAll(handler);
-        if (m_touchEventTargets->isEmpty() && parentDocument())
-            parentDocument()->didRemoveEventTargetNode(this);
+    if (m_touchEventTargets->isEmpty()) {
+        if (Document* parent = parentDocument()) {
+            // This was the last handler in this document, update the parent document too.
+            parent->didRemoveTouchEventHandler(this, clearAll);
+        } else {
+            // We just removed the last touch handler on the whole page.
+            if (FrameHost* frameHost = this->frameHost())
+                frameHost->chrome().client().needTouchEvents(false);
+        }
+    }
+
+    // When we're all done with all frames, ensure touch hit rects are marked as dirty.
+    if (!handler->isDocumentNode() || handler == this) {
+        if (Page* page = this->page()) {
+            if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+                scrollingCoordinator->touchEventTargetRectsDidChange();
+        }
     }
 }
 
@@ -5198,23 +5306,26 @@ Locale& Document::getCachedLocale(const AtomicString& locale)
         return Locale::defaultLocale();
     LocaleIdentifierToLocaleMap::AddResult result = m_localeCache.add(localeKey, nullptr);
     if (result.isNewEntry)
-        result.iterator->value = Locale::create(localeKey);
-    return *(result.iterator->value);
+        result.storedValue->value = Locale::create(localeKey);
+    return *(result.storedValue->value);
 }
 
 Document& Document::ensureTemplateDocument()
 {
-    if (const Document* document = templateDocument())
-        return *const_cast<Document*>(document);
+    if (isTemplateDocument())
+        return *this;
+
+    if (m_templateDocument)
+        return *m_templateDocument;
 
     if (isHTMLDocument()) {
-        DocumentInit init = DocumentInit::fromContext(contextDocument(), blankURL());
+        DocumentInit init = DocumentInit::fromContext(contextDocument(), blankURL()).withNewRegistrationContext();
         m_templateDocument = HTMLDocument::create(init);
     } else {
         m_templateDocument = Document::create(DocumentInit(blankURL()));
     }
 
-    m_templateDocument->setTemplateDocumentHost(this); // balanced in dtor.
+    m_templateDocument->m_templateDocumentHost = this; // balanced in dtor.
 
     return *m_templateDocument.get();
 }
@@ -5325,4 +5436,15 @@ bool Document::hasFocus() const
     return false;
 }
 
+// FIXME: Remove this code once we have input routing in the browser
+// process. See http://crbug.com/339659.
+void Document::defaultEventHandler(Event* event)
+{
+    if (frame() && frame()->remotePlatformLayer()) {
+        frame()->chromeClient().forwardInputEvent(this, event);
+        return;
+    }
+    Node::defaultEventHandler(event);
+}
+
 } // namespace WebCore