Merge from Chromium at DEPS revision 40.0.2214.69

This commit was generated by merge_to_master.py.

Change-Id: Iabb0cdde152fca6c24fec8a72c231fc8e35d7ff9
diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp
index 18f5745..f871570 100644
--- a/Source/core/animation/css/CSSAnimations.cpp
+++ b/Source/core/animation/css/CSSAnimations.cpp
@@ -199,8 +199,11 @@
 const StyleRuleKeyframes* CSSAnimations::matchScopedKeyframesRule(StyleResolver* resolver, const Element* element, const StringImpl* animationName)
 {
     // FIXME: This is all implementation detail of style resolver, CSSAnimations shouldn't be reaching into any of it.
-    if (element->document().styleEngine()->hasOnlyScopedResolverForDocument())
-        return element->document().scopedStyleResolver()->keyframeStylesForAnimation(animationName);
+    if (element->document().styleEngine()->onlyDocumentHasStyles()) {
+        if (ScopedStyleResolver* resolver = element->document().scopedStyleResolver())
+            return resolver->keyframeStylesForAnimation(animationName);
+        return nullptr;
+    }
 
     WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8> stack;
     resolver->styleTreeResolveScopedKeyframesRules(element, stack);
diff --git a/Source/core/css/resolver/StyleResolver.cpp b/Source/core/css/resolver/StyleResolver.cpp
index edcebea..9aeb7a4 100644
--- a/Source/core/css/resolver/StyleResolver.cpp
+++ b/Source/core/css/resolver/StyleResolver.cpp
@@ -181,9 +181,7 @@
     if (!treeScope)
         return;
 
-    ScopedStyleResolver& resolver = treeScope->ensureScopedStyleResolver();
-    document().styleEngine()->addScopedStyleResolver(&resolver);
-    unsigned index = resolver.appendCSSStyleSheet(cssSheet);
+    unsigned index = treeScope->ensureScopedStyleResolver().appendCSSStyleSheet(cssSheet);
 
     addRulesFromSheet(cssSheet, treeScope, index);
 }
@@ -240,10 +238,9 @@
 void StyleResolver::processScopedRules(const RuleSet& authorRules, CSSStyleSheet* parentStyleSheet, unsigned parentIndex, ContainerNode& scope)
 {
     const WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> > keyframesRules = authorRules.keyframesRules();
-    ScopedStyleResolver* resolver = &scope.treeScope().ensureScopedStyleResolver();
-    document().styleEngine()->addScopedStyleResolver(resolver);
+    ScopedStyleResolver& resolver = scope.treeScope().ensureScopedStyleResolver();
     for (unsigned i = 0; i < keyframesRules.size(); ++i)
-        resolver->addKeyframeStyle(keyframesRules[i]);
+        resolver.addKeyframeStyle(keyframesRules[i]);
 
     m_treeBoundaryCrossingRules.addTreeBoundaryCrossingRules(authorRules, parentStyleSheet, parentIndex, scope);
 
@@ -259,19 +256,18 @@
 
 void StyleResolver::resetAuthorStyle(TreeScope& treeScope)
 {
+    m_treeBoundaryCrossingRules.reset(&treeScope.rootNode());
+    resetRuleFeatures();
+
     ScopedStyleResolver* resolver = treeScope.scopedStyleResolver();
     if (!resolver)
         return;
 
-    m_treeBoundaryCrossingRules.reset(&treeScope.rootNode());
-
     resolver->resetAuthorStyle();
-    resetRuleFeatures();
     if (treeScope.rootNode().isDocumentNode())
         return;
 
     // resolver is going to be freed below.
-    document().styleEngine()->removeScopedStyleResolver(resolver);
     treeScope.clearScopedStyleResolver();
 }
 
@@ -402,8 +398,13 @@
     collector.clearMatchedRules();
     collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
 
-    if (document().styleEngine()->hasOnlyScopedResolverForDocument()) {
-        document().scopedStyleResolver()->collectMatchingAuthorRules(collector, includeEmptyRules, ignoreCascadeScope);
+    if (document().styleEngine()->onlyDocumentHasStyles()) {
+        ScopedStyleResolver* resolver = document().scopedStyleResolver();
+        if (!resolver)
+            return;
+        // If we have no resolver for a document, the document has no styles.
+        // We don't need to see any rules (including treeboundary crossing ones).
+        resolver->collectMatchingAuthorRules(collector, includeEmptyRules, ignoreCascadeScope);
         m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
         collector.sortAndTransferMatchedRules();
         return;
@@ -419,15 +420,14 @@
         return;
     }
 
-    if (resolvers.isEmpty())
-        return;
-
-    CascadeScope cascadeScope = 0;
-    CascadeOrder cascadeOrder = resolvers.size();
-    for (unsigned i = 0; i < resolvers.size(); ++i, --cascadeOrder) {
-        ScopedStyleResolver* resolver = resolvers.at(i);
-        // FIXME: Need to clarify how to treat style scoped.
-        resolver->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->treeScope().rootNode().isShadowRoot() ? 0 : cascadeOrder);
+    if (!resolvers.isEmpty()) {
+        CascadeScope cascadeScope = 0;
+        CascadeOrder cascadeOrder = resolvers.size();
+        for (unsigned i = 0; i < resolvers.size(); ++i, --cascadeOrder) {
+            ScopedStyleResolver* resolver = resolvers.at(i);
+            // FIXME: Need to clarify how to treat style scoped.
+            resolver->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->treeScope().rootNode().isShadowRoot() ? 0 : cascadeOrder);
+        }
     }
 
     m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index cb9a033..07c3cab 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -929,12 +929,13 @@
     }
 
     const Attribute& existingAttribute = elementData()->attributes().at(index);
+    AtomicString existingAttributeValue = existingAttribute.value();
     QualifiedName existingAttributeName = existingAttribute.name();
 
     if (!inSynchronizationOfLazyAttribute)
-        willModifyAttribute(existingAttributeName, existingAttribute.value(), newValue);
+        willModifyAttribute(existingAttributeName, existingAttributeValue, newValue);
 
-    if (newValue != existingAttribute.value()) {
+    if (newValue != existingAttributeValue) {
         // If there is an Attr node hooked to this attribute, the Attr::setValue() call below
         // will write into the ElementData.
         // FIXME: Refactor this so it makes some sense.
diff --git a/Source/core/dom/ProcessingInstruction.cpp b/Source/core/dom/ProcessingInstruction.cpp
index d011233..194ea62 100644
--- a/Source/core/dom/ProcessingInstruction.cpp
+++ b/Source/core/dom/ProcessingInstruction.cpp
@@ -273,18 +273,21 @@
     if (!insertionPoint->inDocument())
         return;
 
+    // No need to remove XSLStyleSheet from StyleEngine.
     if (m_isCSS)
         document().styleEngine()->removeStyleSheetCandidateNode(this);
     else if (m_isXSL)
         document().styleEngine()->removeXSLStyleSheet(this);
 
     RefPtrWillBeRawPtr<StyleSheet> removedSheet = m_sheet;
-
     if (m_sheet) {
         ASSERT(m_sheet->ownerNode() == this);
         clearSheet();
     }
 
+    // No need to remove pending sheets.
+    clearResource();
+
     // If we're in document teardown, then we don't need to do any notification of our sheet's removal.
     if (document().isActive())
         document().removedStyleSheet(removedSheet.get());
diff --git a/Source/core/dom/StyleEngine.cpp b/Source/core/dom/StyleEngine.cpp
index 9b72382..9883e46 100644
--- a/Source/core/dom/StyleEngine.cpp
+++ b/Source/core/dom/StyleEngine.cpp
@@ -104,9 +104,7 @@
     m_fontSelector.clear();
     m_resolver.clear();
     m_styleSheetCollectionMap.clear();
-    for (ScopedStyleResolverSet::iterator it = m_scopedStyleResolvers.begin(); it != m_scopedStyleResolvers.end(); ++it)
-        const_cast<TreeScope&>((*it)->treeScope()).clearScopedStyleResolver();
-    m_scopedStyleResolvers.clear();
+    m_activeTreeScopes.clear();
 }
 #endif
 
@@ -320,7 +318,6 @@
     collection->removeStyleSheetCandidateNode(node);
 
     markTreeScopeDirty(treeScope);
-    m_activeTreeScopes.remove(&treeScope);
 }
 
 void StyleEngine::addXSLStyleSheet(ProcessingInstruction* node, bool createdByParser)
@@ -428,8 +425,12 @@
             ShadowTreeStyleSheetCollection* collection = static_cast<ShadowTreeStyleSheetCollection*>(styleSheetCollectionFor(*treeScope));
             ASSERT(collection);
             collection->updateActiveStyleSheets(this, updateMode);
-            if (!collection->hasStyleSheetCandidateNodes())
+            if (!collection->hasStyleSheetCandidateNodes()) {
                 treeScopesRemoved.add(treeScope);
+                // When removing TreeScope from ActiveTreeScopes,
+                // its resolver should be destroyed by invoking resetAuthorStyle.
+                ASSERT(!treeScope->scopedStyleResolver());
+            }
         }
         m_activeTreeScopes.removeAll(treeScopesRemoved);
     }
@@ -465,9 +466,9 @@
 
 void StyleEngine::didRemoveShadowRoot(ShadowRoot* shadowRoot)
 {
-    if (shadowRoot->scopedStyleResolver())
-        removeScopedStyleResolver(shadowRoot->scopedStyleResolver());
     m_styleSheetCollectionMap.remove(shadowRoot);
+    m_activeTreeScopes.remove(shadowRoot);
+    m_dirtyTreeScopes.remove(shadowRoot);
 }
 
 void StyleEngine::appendActiveAuthorStyleSheets()
@@ -494,8 +495,9 @@
     ASSERT(document().frame());
 
     m_resolver = adoptPtrWillBeNoop(new StyleResolver(*m_document));
-    addScopedStyleResolver(&m_document->ensureScopedStyleResolver());
 
+    // A scoped style resolver for document will be created during
+    // appendActiveAuthorStyleSheets if needed.
     appendActiveAuthorStyleSheets();
     combineCSSFeatureFlags(m_resolver->ensureUpdatedRuleFeatureSet());
 }
@@ -505,9 +507,16 @@
     ASSERT(!document().inStyleRecalc());
     ASSERT(isMaster() || !m_resolver);
 
-    for (ScopedStyleResolverSet::iterator it = m_scopedStyleResolvers.begin(); it != m_scopedStyleResolvers.end(); ++it)
-        const_cast<TreeScope&>((*it)->treeScope()).clearScopedStyleResolver();
-    m_scopedStyleResolvers.clear();
+    document().clearScopedStyleResolver();
+    // clearResolver might be invoked while destryoing document. In this case,
+    // treescopes in m_activeTreeScopes might have already been destoryed,
+    // because m_activeTreeScopes are updated in updateActiveStyleSheets, not
+    // in removeStyleSheetCandidateNode. So we should not invoke
+    // treeScope->clearScopedStyleResolver when document is not active.
+    if (document().isActive()) {
+        for (auto& treeScope: m_activeTreeScopes)
+            treeScope->clearScopedStyleResolver();
+    }
 
     if (m_resolver)
         document().updateStyleInvalidationIfNeeded();
@@ -690,8 +699,17 @@
 void StyleEngine::collectScopedStyleFeaturesTo(RuleFeatureSet& features) const
 {
     HashSet<const StyleSheetContents*> visitedSharedStyleSheetContents;
-    for (ScopedStyleResolverSet::iterator it = m_scopedStyleResolvers.begin(); it != m_scopedStyleResolvers.end(); ++it)
-        (*it)->collectFeaturesTo(features, visitedSharedStyleSheetContents);
+    if (document().scopedStyleResolver())
+        document().scopedStyleResolver()->collectFeaturesTo(features, visitedSharedStyleSheetContents);
+    for (auto& treeScope: m_activeTreeScopes) {
+        // When creating StyleResolver, dirty treescopes might not be processed.
+        // So some active treescopes might not have a scoped style resolver.
+        // In this case, we should skip collectFeatures for the treescopes without
+        // scoped style resolvers. When invoking updateActiveStyleSheets,
+        // the treescope's features will be processed.
+        if (ScopedStyleResolver* resolver = treeScope->scopedStyleResolver())
+            resolver->collectFeaturesTo(features, visitedSharedStyleSheetContents);
+    }
 }
 
 void StyleEngine::fontsNeedUpdate(CSSFontSelector*)
@@ -712,7 +730,6 @@
     visitor->trace(m_authorStyleSheets);
     visitor->trace(m_documentStyleSheetCollection);
     visitor->trace(m_styleSheetCollectionMap);
-    visitor->trace(m_scopedStyleResolvers);
     visitor->trace(m_resolver);
     visitor->trace(m_fontSelector);
     visitor->trace(m_textToSheetCache);
diff --git a/Source/core/dom/StyleEngine.h b/Source/core/dom/StyleEngine.h
index 6c6df00..9806bc1 100644
--- a/Source/core/dom/StyleEngine.h
+++ b/Source/core/dom/StyleEngine.h
@@ -170,9 +170,7 @@
     PassRefPtrWillBeRawPtr<CSSStyleSheet> createSheet(Element*, const String& text, TextPosition startPosition, bool createdByParser);
     void removeSheet(StyleSheetContents*);
 
-    void addScopedStyleResolver(const ScopedStyleResolver* resolver) { m_scopedStyleResolvers.add(resolver); }
-    void removeScopedStyleResolver(const ScopedStyleResolver* resolver) { m_scopedStyleResolvers.remove(resolver); }
-    bool hasOnlyScopedResolverForDocument() const { return m_scopedStyleResolvers.size() == 1; }
+    bool onlyDocumentHasStyles() const { return m_activeTreeScopes.isEmpty(); }
     void collectScopedStyleFeaturesTo(RuleFeatureSet&) const;
 
     virtual void trace(Visitor*) override;
@@ -232,8 +230,6 @@
 
     typedef WillBeHeapHashMap<RawPtrWillBeWeakMember<TreeScope>, OwnPtrWillBeMember<ShadowTreeStyleSheetCollection> > StyleSheetCollectionMap;
     StyleSheetCollectionMap m_styleSheetCollectionMap;
-    typedef WillBeHeapHashSet<RawPtrWillBeMember<const ScopedStyleResolver> > ScopedStyleResolverSet;
-    ScopedStyleResolverSet m_scopedStyleResolvers;
 
     bool m_documentScopeDirty;
     TreeScopeSet m_dirtyTreeScopes;
diff --git a/Source/core/dom/shadow/ShadowRoot.cpp b/Source/core/dom/shadow/ShadowRoot.cpp
index d346a20..d598a73 100644
--- a/Source/core/dom/shadow/ShadowRoot.cpp
+++ b/Source/core/dom/shadow/ShadowRoot.cpp
@@ -175,13 +175,16 @@
 
 void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
 {
-    if (insertionPoint->inDocument() && m_registeredWithParentShadowRoot) {
-        ShadowRoot* root = host()->containingShadowRoot();
-        if (!root)
-            root = insertionPoint->containingShadowRoot();
-        if (root)
-            root->removeChildShadowRoot();
-        m_registeredWithParentShadowRoot = false;
+    if (insertionPoint->inDocument()) {
+        clearScopedStyleResolver();
+        if (m_registeredWithParentShadowRoot) {
+            ShadowRoot* root = host()->containingShadowRoot();
+            if (!root)
+                root = insertionPoint->containingShadowRoot();
+            if (root)
+                root->removeChildShadowRoot();
+            m_registeredWithParentShadowRoot = false;
+        }
     }
 
     DocumentFragment::removedFrom(insertionPoint);
diff --git a/Source/core/events/TreeScopeEventContext.cpp b/Source/core/events/TreeScopeEventContext.cpp
index 738193b..bdf4c0f 100644
--- a/Source/core/events/TreeScopeEventContext.cpp
+++ b/Source/core/events/TreeScopeEventContext.cpp
@@ -42,8 +42,8 @@
     WillBeHeapVector<RefPtrWillBeMember<Node>> nodes;
     nodes.reserveInitialCapacity(path.size());
     for (size_t i = 0; i < path.size(); ++i) {
-        TreeScope& treeScope = path[i].treeScopeEventContext().treeScope();
-        if (treeScope.rootNode().isShadowRoot() && toShadowRoot(treeScope).type() == ShadowRoot::AuthorShadowRoot)
+        Node& rootNode = path[i].treeScopeEventContext().rootNode();
+        if (rootNode.isShadowRoot() && toShadowRoot(rootNode).type() == ShadowRoot::AuthorShadowRoot)
             nodes.append(path[i].node());
         else if (path[i].treeScopeEventContext().isInclusiveAncestorOf(*this))
             nodes.append(path[i].node());
@@ -66,6 +66,7 @@
 
 TreeScopeEventContext::TreeScopeEventContext(TreeScope& treeScope)
     : m_treeScope(treeScope)
+    , m_rootNode(treeScope.rootNode())
     , m_preOrder(-1)
     , m_postOrder(-1)
 {
@@ -76,6 +77,7 @@
 void TreeScopeEventContext::trace(Visitor* visitor)
 {
     visitor->trace(m_treeScope);
+    visitor->trace(m_rootNode);
     visitor->trace(m_target);
     visitor->trace(m_relatedTarget);
     visitor->trace(m_eventPath);
diff --git a/Source/core/events/TreeScopeEventContext.h b/Source/core/events/TreeScopeEventContext.h
index 3b040eb..b6d018d 100644
--- a/Source/core/events/TreeScopeEventContext.h
+++ b/Source/core/events/TreeScopeEventContext.h
@@ -51,6 +51,7 @@
     void trace(Visitor*);
 
     TreeScope& treeScope() const { return *m_treeScope; }
+    Node& rootNode() const { return *m_rootNode; }
 
     EventTarget* target() const { return m_target.get(); }
     void setTarget(PassRefPtrWillBeRawPtr<EventTarget>);
@@ -78,6 +79,7 @@
 #endif
 
     RawPtrWillBeMember<TreeScope> m_treeScope;
+    RefPtrWillBeMember<Node> m_rootNode; // Prevents TreeScope from being freed. TreeScope itself isn't RefCounted.
     RefPtrWillBeMember<EventTarget> m_target;
     RefPtrWillBeMember<EventTarget> m_relatedTarget;
     RefPtrWillBeMember<StaticNodeList> m_eventPath;
diff --git a/Source/core/fetch/ResourceFetcher.cpp b/Source/core/fetch/ResourceFetcher.cpp
index 81f56c4..b29a1a2 100644
--- a/Source/core/fetch/ResourceFetcher.cpp
+++ b/Source/core/fetch/ResourceFetcher.cpp
@@ -1161,12 +1161,9 @@
 
 void ResourceFetcher::didLoadResource()
 {
-    RefPtr<DocumentLoader> protectDocumentLoader(m_documentLoader);
-    RefPtrWillBeRawPtr<Document> protectDocument(m_document.get());
-
+    scheduleDocumentResourcesGC();
     if (frame())
         frame()->loader().loadDone();
-    scheduleDocumentResourcesGC();
 }
 
 void ResourceFetcher::scheduleDocumentResourcesGC()
@@ -1303,6 +1300,8 @@
 void ResourceFetcher::didFinishLoading(Resource* resource, double finishTime, int64_t encodedDataLength)
 {
     TRACE_EVENT_ASYNC_END0("net", "Resource", resource);
+    RefPtr<Document> protectDocument(m_document);
+    RefPtr<DocumentLoader> protectDocumentLoader(m_documentLoader);
 
     if (resource && resource->response().isHTTP() && resource->response().httpStatusCode() < 400 && document()) {
         ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource);
diff --git a/Source/core/frame/FrameView.cpp b/Source/core/frame/FrameView.cpp
index cc6f25c..1426827 100644
--- a/Source/core/frame/FrameView.cpp
+++ b/Source/core/frame/FrameView.cpp
@@ -3033,6 +3033,10 @@
 
 void FrameView::setTopControlsViewportAdjustment(float adjustment)
 {
+#if !OS(ANDROID)
+    // The adjustment is done only for top controls which are android only.
+    ASSERT(!adjustment);
+#endif
     m_topControlsViewportAdjustment = adjustment;
 }
 
diff --git a/Source/core/frame/ImageBitmap.cpp b/Source/core/frame/ImageBitmap.cpp
index 60e52ee..d5ffd02 100644
--- a/Source/core/frame/ImageBitmap.cpp
+++ b/Source/core/frame/ImageBitmap.cpp
@@ -82,7 +82,7 @@
 {
     CanvasRenderingContext* sourceContext = canvas->renderingContext();
     if (sourceContext && sourceContext->is3d())
-        sourceContext->paintRenderingResultsToCanvas();
+        sourceContext->paintRenderingResultsToCanvas(CanvasRenderingContext::Back);
 
     IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), canvas->size()));
     m_bitmapRect = IntRect(IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())), srcRect.size());
diff --git a/Source/core/html/HTMLCanvasElement.cpp b/Source/core/html/HTMLCanvasElement.cpp
index bb00e4d..dddb0c2 100644
--- a/Source/core/html/HTMLCanvasElement.cpp
+++ b/Source/core/html/HTMLCanvasElement.cpp
@@ -333,18 +333,12 @@
     if (m_context) {
         if (!paintsIntoCanvasBuffer() && !document().printing())
             return;
-        m_context->paintRenderingResultsToCanvas();
+        m_context->paintRenderingResultsToCanvas(CanvasRenderingContext::Front);
     }
 
     if (hasImageBuffer()) {
-        ImageBuffer* imageBuffer = buffer();
-        if (imageBuffer) {
-            CompositeOperator compositeOperator = !m_context || m_context->hasAlpha() ? CompositeSourceOver : CompositeCopy;
-            if (m_presentedImage)
-                context->drawImage(m_presentedImage.get(), pixelSnappedIntRect(r), compositeOperator, DoNotRespectImageOrientation);
-            else
-                context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), 0, compositeOperator);
-        }
+        CompositeOperator compositeOperator = !m_context || m_context->hasAlpha() ? CompositeSourceOver : CompositeCopy;
+        context->drawImageBuffer(buffer(), pixelSnappedIntRect(r), 0, compositeOperator);
     } else {
         // When alpha is false, we should draw to opaque black.
         if (m_context && !m_context->hasAlpha())
@@ -360,21 +354,6 @@
     return m_context && m_context->is3d();
 }
 
-void HTMLCanvasElement::makePresentationCopy()
-{
-    if (!m_presentedImage) {
-        // The buffer contains the last presented data, so save a copy of it.
-        m_presentedImage = buffer()->copyImage(CopyBackingStore, Unscaled);
-        updateExternallyAllocatedMemory();
-    }
-}
-
-void HTMLCanvasElement::clearPresentationCopy()
-{
-    m_presentedImage.clear();
-    updateExternallyAllocatedMemory();
-}
-
 void HTMLCanvasElement::setSurfaceSize(const IntSize& size)
 {
     m_size = size;
@@ -419,9 +398,7 @@
         return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageData->data()), encodingMimeType, quality);
 
     if (m_context && m_context->is3d()) {
-        toWebGLRenderingContext(m_context.get())->setSavingImage(isSaving);
-        m_context->paintRenderingResultsToCanvas();
-        toWebGLRenderingContext(m_context.get())->setSavingImage(false);
+        m_context->paintRenderingResultsToCanvas(isSaving ? CanvasRenderingContext::Front : CanvasRenderingContext::Back);
     }
 
     return buffer()->toDataURL(encodingMimeType, quality);
@@ -646,8 +623,6 @@
         bufferCount += 2;
     if (m_copiedImage)
         bufferCount++;
-    if (m_presentedImage)
-        bufferCount++;
 
     Checked<intptr_t, RecordOverflow> checkedExternallyAllocatedMemory = 4 * bufferCount;
     checkedExternallyAllocatedMemory *= width();
@@ -695,9 +670,7 @@
 {
     if (!m_copiedImage && buffer()) {
         if (m_context && m_context->is3d()) {
-            toWebGLRenderingContext(m_context.get())->setSavingImage(true);
-            m_context->paintRenderingResultsToCanvas();
-            toWebGLRenderingContext(m_context.get())->setSavingImage(false);
+            m_context->paintRenderingResultsToCanvas(CanvasRenderingContext::Front);
         }
         m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled);
         updateExternallyAllocatedMemory();
@@ -781,7 +754,7 @@
     }
 
     if (m_context && m_context->is3d()) {
-        m_context->paintRenderingResultsToCanvas();
+        m_context->paintRenderingResultsToCanvas(CanvasRenderingContext::Back);
         *status = ExternalSourceImageStatus;
 
         // can't create SkImage from WebGLImageBufferSurface (contains only SkBitmap)
diff --git a/Source/core/html/HTMLCanvasElement.h b/Source/core/html/HTMLCanvasElement.h
index bd7a75c..9677d01 100644
--- a/Source/core/html/HTMLCanvasElement.h
+++ b/Source/core/html/HTMLCanvasElement.h
@@ -123,8 +123,6 @@
     Image* copiedImage() const;
     void clearCopiedImage();
     PassRefPtrWillBeRawPtr<ImageData> getImageData() const;
-    void makePresentationCopy();
-    void clearPresentationCopy();
 
     SecurityOrigin* securityOrigin() const;
     bool originClean() const { return m_originClean; }
@@ -213,7 +211,6 @@
     OwnPtr<ImageBuffer> m_imageBuffer;
     mutable OwnPtr<GraphicsContextStateSaver> m_contextStateSaver;
 
-    mutable RefPtr<Image> m_presentedImage;
     mutable RefPtr<Image> m_copiedImage; // FIXME: This is temporary for platforms that have to copy the image buffer to render (and for CSSCanvasValue).
 };
 
diff --git a/Source/core/html/HTMLScriptElement.cpp b/Source/core/html/HTMLScriptElement.cpp
index 6bfccd1..bce71bd 100644
--- a/Source/core/html/HTMLScriptElement.cpp
+++ b/Source/core/html/HTMLScriptElement.cpp
@@ -73,8 +73,17 @@
 
 void HTMLScriptElement::didMoveToNewDocument(Document& oldDocument)
 {
-    if (RefPtrWillBeRawPtr<Document> contextDocument = document().contextDocument().get())
-        oldDocument.scriptRunner()->movePendingAsyncScript(contextDocument->scriptRunner(), m_loader.get());
+    RefPtrWillBeRawPtr<Document> contextDocument = document().contextDocument().get();
+    if (!contextDocument) {
+        ASSERT(!document().frame());
+        // A frame-detached document is handled as having no context
+        // document - it would be the document if not detached. The
+        // newly moved script element needs to be the latter here as
+        // the script loader for the pending script must also move to
+        // reside with that document and its script runner.
+        contextDocument = &document();
+    }
+    oldDocument.scriptRunner()->movePendingAsyncScript(contextDocument->scriptRunner(), m_loader.get());
     HTMLElement::didMoveToNewDocument(oldDocument);
 }
 
diff --git a/Source/core/html/canvas/ANGLEInstancedArrays.cpp b/Source/core/html/canvas/ANGLEInstancedArrays.cpp
index 20012cc..15169cc 100644
--- a/Source/core/html/canvas/ANGLEInstancedArrays.cpp
+++ b/Source/core/html/canvas/ANGLEInstancedArrays.cpp
@@ -68,26 +68,29 @@
 
 void ANGLEInstancedArrays::drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
 {
-    if (isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (scoped.isLost())
         return;
 
-    m_context->drawArraysInstancedANGLE(mode, first, count, primcount);
+    scoped.context()->drawArraysInstancedANGLE(mode, first, count, primcount);
 }
 
 void ANGLEInstancedArrays::drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount)
 {
-    if (isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (scoped.isLost())
         return;
 
-    m_context->drawElementsInstancedANGLE(mode, count, type, offset, primcount);
+    scoped.context()->drawElementsInstancedANGLE(mode, count, type, offset, primcount);
 }
 
 void ANGLEInstancedArrays::vertexAttribDivisorANGLE(GLuint index, GLuint divisor)
 {
-    if (isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (scoped.isLost())
         return;
 
-    m_context->vertexAttribDivisorANGLE(index, divisor);
+    scoped.context()->vertexAttribDivisorANGLE(index, divisor);
 }
 
 } // namespace blink
diff --git a/Source/core/html/canvas/CanvasRenderingContext.h b/Source/core/html/canvas/CanvasRenderingContext.h
index 2af7128..b03358e 100644
--- a/Source/core/html/canvas/CanvasRenderingContext.h
+++ b/Source/core/html/canvas/CanvasRenderingContext.h
@@ -58,7 +58,8 @@
     virtual bool hasAlpha() const { return true; }
     virtual void setIsHidden(bool) = 0;
 
-    virtual void paintRenderingResultsToCanvas() {}
+    enum SourceBuffer { Front, Back };
+    virtual void paintRenderingResultsToCanvas(SourceBuffer) { }
 
     virtual blink::WebLayer* platformLayer() const { return nullptr; }
 
diff --git a/Source/core/html/canvas/OESVertexArrayObject.cpp b/Source/core/html/canvas/OESVertexArrayObject.cpp
index 063dc0f..9979902 100644
--- a/Source/core/html/canvas/OESVertexArrayObject.cpp
+++ b/Source/core/html/canvas/OESVertexArrayObject.cpp
@@ -55,54 +55,58 @@
 
 PassRefPtrWillBeRawPtr<WebGLVertexArrayObjectOES> OESVertexArrayObject::createVertexArrayOES()
 {
-    if (isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (scoped.isLost())
         return nullptr;
 
-    RefPtrWillBeRawPtr<WebGLVertexArrayObjectOES> o = WebGLVertexArrayObjectOES::create(m_context, WebGLVertexArrayObjectOES::VaoTypeUser);
-    m_context->addContextObject(o.get());
+    RefPtrWillBeRawPtr<WebGLVertexArrayObjectOES> o = WebGLVertexArrayObjectOES::create(scoped.context(), WebGLVertexArrayObjectOES::VaoTypeUser);
+    scoped.context()->addContextObject(o.get());
     return o.release();
 }
 
 void OESVertexArrayObject::deleteVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject)
 {
-    if (!arrayObject || isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (!arrayObject || scoped.isLost())
         return;
 
-    if (!arrayObject->isDefaultObject() && arrayObject == m_context->m_boundVertexArrayObject)
-        m_context->setBoundVertexArrayObject(nullptr);
+    if (!arrayObject->isDefaultObject() && arrayObject == scoped.context()->m_boundVertexArrayObject)
+        scoped.context()->setBoundVertexArrayObject(nullptr);
 
-    arrayObject->deleteObject(m_context->webContext());
+    arrayObject->deleteObject(scoped.context()->webContext());
 }
 
 GLboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject)
 {
-    if (!arrayObject || isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (!arrayObject || scoped.isLost())
         return 0;
 
     if (!arrayObject->hasEverBeenBound())
         return 0;
 
-    return m_context->webContext()->isVertexArrayOES(arrayObject->object());
+    return scoped.context()->webContext()->isVertexArrayOES(arrayObject->object());
 }
 
 void OESVertexArrayObject::bindVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject)
 {
-    if (isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (scoped.isLost())
         return;
 
-    if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(0, context()))) {
-        m_context->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
+    if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(0, scoped.context()))) {
+        scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
         return;
     }
 
     if (arrayObject && !arrayObject->isDefaultObject() && arrayObject->object()) {
-        m_context->webContext()->bindVertexArrayOES(arrayObject->object());
+        scoped.context()->webContext()->bindVertexArrayOES(arrayObject->object());
 
         arrayObject->setHasEverBeenBound();
-        m_context->setBoundVertexArrayObject(arrayObject);
+        scoped.context()->setBoundVertexArrayObject(arrayObject);
     } else {
-        m_context->webContext()->bindVertexArrayOES(0);
-        m_context->setBoundVertexArrayObject(nullptr);
+        scoped.context()->webContext()->bindVertexArrayOES(0);
+        scoped.context()->setBoundVertexArrayObject(nullptr);
     }
 }
 
diff --git a/Source/core/html/canvas/WebGLDebugShaders.cpp b/Source/core/html/canvas/WebGLDebugShaders.cpp
index 74719bd..229d1b3 100644
--- a/Source/core/html/canvas/WebGLDebugShaders.cpp
+++ b/Source/core/html/canvas/WebGLDebugShaders.cpp
@@ -53,11 +53,12 @@
 
 String WebGLDebugShaders::getTranslatedShaderSource(WebGLShader* shader)
 {
-    if (isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (scoped.isLost())
         return String();
-    if (!m_context->validateWebGLObject("getTranslatedShaderSource", shader))
+    if (!scoped.context()->validateWebGLObject("getTranslatedShaderSource", shader))
         return "";
-    return m_context->ensureNotNull(m_context->webContext()->getTranslatedShaderSourceANGLE(shader->object()));
+    return scoped.context()->ensureNotNull(scoped.context()->webContext()->getTranslatedShaderSourceANGLE(shader->object()));
 }
 
 bool WebGLDebugShaders::supported(WebGLRenderingContextBase* context)
diff --git a/Source/core/html/canvas/WebGLDrawBuffers.cpp b/Source/core/html/canvas/WebGLDrawBuffers.cpp
index e3d14f8..655b188 100644
--- a/Source/core/html/canvas/WebGLDrawBuffers.cpp
+++ b/Source/core/html/canvas/WebGLDrawBuffers.cpp
@@ -63,35 +63,36 @@
 
 void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GLenum>& buffers)
 {
-    if (isLost())
+    WebGLExtensionScopedContext scoped(this);
+    if (scoped.isLost())
         return;
     GLsizei n = buffers.size();
     const GLenum* bufs = buffers.data();
-    if (!m_context->m_framebufferBinding) {
+    if (!scoped.context()->m_framebufferBinding) {
         if (n != 1) {
-            m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than one buffer");
+            scoped.context()->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than one buffer");
             return;
         }
         if (bufs[0] != GL_BACK && bufs[0] != GL_NONE) {
-            m_context->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "BACK or NONE");
+            scoped.context()->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "BACK or NONE");
             return;
         }
         // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0.
         GLenum value = (bufs[0] == GL_BACK) ? GL_COLOR_ATTACHMENT0 : GL_NONE;
-        m_context->webContext()->drawBuffersEXT(1, &value);
-        m_context->setBackDrawBuffer(bufs[0]);
+        scoped.context()->webContext()->drawBuffersEXT(1, &value);
+        scoped.context()->setBackDrawBuffer(bufs[0]);
     } else {
-        if (n > m_context->maxDrawBuffers()) {
-            m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than max draw buffers");
+        if (n > scoped.context()->maxDrawBuffers()) {
+            scoped.context()->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than max draw buffers");
             return;
         }
         for (GLsizei i = 0; i < n; ++i) {
             if (bufs[i] != GL_NONE && bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT + i)) {
-                m_context->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "COLOR_ATTACHMENTi_EXT or NONE");
+                scoped.context()->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "COLOR_ATTACHMENTi_EXT or NONE");
                 return;
             }
         }
-        m_context->m_framebufferBinding->drawBuffers(buffers);
+        scoped.context()->m_framebufferBinding->drawBuffers(buffers);
     }
 }
 
diff --git a/Source/core/html/canvas/WebGLExtension.cpp b/Source/core/html/canvas/WebGLExtension.cpp
index 8070663..a65b65c 100644
--- a/Source/core/html/canvas/WebGLExtension.cpp
+++ b/Source/core/html/canvas/WebGLExtension.cpp
@@ -29,6 +29,21 @@
 
 namespace blink {
 
+WebGLExtensionScopedContext::WebGLExtensionScopedContext(WebGLExtension* extension)
+    : m_context(extension->m_context)
+{
+}
+
+WebGLExtensionScopedContext::~WebGLExtensionScopedContext()
+{
+}
+
+void WebGLExtensionScopedContext::trace(Visitor* visitor)
+{
+    visitor->trace(m_context);
+}
+
+
 WebGLExtension::WebGLExtension(WebGLRenderingContextBase* context)
     : m_context(context)
 {
diff --git a/Source/core/html/canvas/WebGLExtension.h b/Source/core/html/canvas/WebGLExtension.h
index 474f500..09ae66a 100644
--- a/Source/core/html/canvas/WebGLExtension.h
+++ b/Source/core/html/canvas/WebGLExtension.h
@@ -26,6 +26,7 @@
 #ifndef WebGLExtension_h
 #define WebGLExtension_h
 
+#include "core/html/HTMLCanvasElement.h"
 #include "core/html/canvas/WebGLExtensionName.h"
 #include "core/html/canvas/WebGLRenderingContextBase.h"
 #include "platform/heap/Handle.h"
@@ -33,11 +34,25 @@
 
 namespace blink {
 
+class WebGLExtensionScopedContext : public NoBaseWillBeGarbageCollectedFinalized<WebGLExtensionScopedContext> {
+    WTF_MAKE_NONCOPYABLE(WebGLExtensionScopedContext);
+    WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
+public:
+    WebGLExtensionScopedContext(WebGLExtension*);
+    virtual ~WebGLExtensionScopedContext();
+
+    bool isLost() { return !m_context; }
+    WebGLRenderingContextBase* context() const { return m_context.get(); }
+
+    virtual void trace(Visitor*);
+
+private:
+    RefPtrWillBeMember<WebGLRenderingContextBase> m_context;
+};
+
 class WebGLExtension : public RefCountedWillBeGarbageCollectedFinalized<WebGLExtension> {
     WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
 public:
-    WebGLRenderingContextBase* context() { return m_context; }
-
     virtual ~WebGLExtension();
     virtual WebGLExtensionName name() const = 0;
 
@@ -49,16 +64,16 @@
         m_context = nullptr;
     }
 
-    bool isLost()
-    {
-        return !m_context;
-    }
+    bool isLost() { return !m_context; }
 
     virtual void trace(Visitor*);
 
 protected:
     explicit WebGLExtension(WebGLRenderingContextBase*);
 
+private:
+    friend WebGLExtensionScopedContext;
+
     RawPtrWillBeWeakMember<WebGLRenderingContextBase> m_context;
 };
 
diff --git a/Source/core/html/canvas/WebGLLoseContext.cpp b/Source/core/html/canvas/WebGLLoseContext.cpp
index 7fe3222..51e9677 100644
--- a/Source/core/html/canvas/WebGLLoseContext.cpp
+++ b/Source/core/html/canvas/WebGLLoseContext.cpp
@@ -58,14 +58,16 @@
 
 void WebGLLoseContext::loseContext()
 {
-    if (!isLost())
-        m_context->forceLostContext(WebGLRenderingContextBase::WebGLLoseContextLostContext, WebGLRenderingContextBase::Manual);
+    WebGLExtensionScopedContext scoped(this);
+    if (!scoped.isLost())
+        scoped.context()->forceLostContext(WebGLRenderingContextBase::WebGLLoseContextLostContext, WebGLRenderingContextBase::Manual);
 }
 
 void WebGLLoseContext::restoreContext()
 {
-    if (!isLost())
-        m_context->forceRestoreContext();
+    WebGLExtensionScopedContext scoped(this);
+    if (!scoped.isLost())
+        scoped.context()->forceRestoreContext();
 }
 
 bool WebGLLoseContext::supported(WebGLRenderingContextBase*)
diff --git a/Source/core/html/canvas/WebGLRenderingContextBase.cpp b/Source/core/html/canvas/WebGLRenderingContextBase.cpp
index 4305ba8..31844c8 100644
--- a/Source/core/html/canvas/WebGLRenderingContextBase.cpp
+++ b/Source/core/html/canvas/WebGLRenderingContextBase.cpp
@@ -565,7 +565,6 @@
     , m_multisamplingAllowed(false)
     , m_multisamplingObserverRegistered(false)
     , m_onePlusMaxNonDefaultTextureUnit(0)
-    , m_savingImage(false)
 {
     ASSERT(context);
 
@@ -888,24 +887,10 @@
         drawingBuffer()->setIsHidden(hidden);
 }
 
-void WebGLRenderingContextBase::paintRenderingResultsToCanvas()
+void WebGLRenderingContextBase::paintRenderingResultsToCanvas(SourceBuffer source)
 {
-    if (isContextLost()) {
-        canvas()->clearPresentationCopy();
+    if (isContextLost())
         return;
-    }
-
-    if (canvas()->document().printing())
-        canvas()->clearPresentationCopy();
-
-    // Until the canvas is written to by the application, the clear that
-    // happened after it was composited should be ignored by the compositor.
-    if (drawingBuffer()->layerComposited() && !m_requestedAttributes->preserveDrawingBuffer()) {
-        drawingBuffer()->paintCompositedResultsToCanvas(canvas()->buffer());
-
-        canvas()->makePresentationCopy();
-    } else
-        canvas()->clearPresentationCopy();
 
     clearIfComposited();
 
@@ -918,7 +903,7 @@
     ScopedTexture2DRestorer restorer(this);
 
     drawingBuffer()->commit();
-    if (!canvas()->buffer()->copyRenderingResultsFromDrawingBuffer(drawingBuffer(), m_savingImage)) {
+    if (!canvas()->buffer()->copyRenderingResultsFromDrawingBuffer(drawingBuffer(), source == Front)) {
         canvas()->ensureUnacceleratedImageBuffer();
         if (canvas()->hasImageBuffer())
             drawingBuffer()->paintRenderingResultsToCanvas(canvas()->buffer());
@@ -3565,7 +3550,7 @@
             WebGLRenderingContextBase* gl = toWebGLRenderingContextBase(canvas->renderingContext());
             ScopedTexture2DRestorer restorer(gl);
             if (gl && gl->drawingBuffer()->copyToPlatformTexture(webContext(), texture->object(), internalformat, type,
-                level, m_unpackPremultiplyAlpha, !m_unpackFlipY)) {
+                level, m_unpackPremultiplyAlpha, !m_unpackFlipY, DrawingBuffer::Back)) {
                 texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
                 return;
             }
diff --git a/Source/core/html/canvas/WebGLRenderingContextBase.h b/Source/core/html/canvas/WebGLRenderingContextBase.h
index 16a8a5e..aacb79c 100644
--- a/Source/core/html/canvas/WebGLRenderingContextBase.h
+++ b/Source/core/html/canvas/WebGLRenderingContextBase.h
@@ -359,8 +359,6 @@
     virtual bool hasPendingActivity() const override;
     virtual void stop() override;
 
-    void setSavingImage(bool isSaving) { m_savingImage = isSaving; }
-
     virtual void trace(Visitor*) override;
 
     class TextureUnitState {
@@ -400,7 +398,7 @@
     virtual bool is3d() const override { return true; }
     virtual bool isAccelerated() const override { return true; }
     virtual void setIsHidden(bool) override;
-    virtual void paintRenderingResultsToCanvas() override;
+    virtual void paintRenderingResultsToCanvas(SourceBuffer) override;
     virtual blink::WebLayer* platformLayer() const override;
 
     void addSharedObject(WebGLSharedObject*);
@@ -571,8 +569,6 @@
 
     OwnPtr<Extensions3DUtil> m_extensionsUtil;
 
-    bool m_savingImage;
-
     enum ExtensionFlags {
         ApprovedExtension               = 0x00,
         // Extension that is behind the draft extensions runtime flag:
diff --git a/Source/core/html/shadow/MediaControls.cpp b/Source/core/html/shadow/MediaControls.cpp
index c3d51df..4c693c5 100644
--- a/Source/core/html/shadow/MediaControls.cpp
+++ b/Source/core/html/shadow/MediaControls.cpp
@@ -370,6 +370,24 @@
     refreshClosedCaptionsButtonVisibility();
 }
 
+static Element* elementFromCenter(Element& element)
+{
+    RefPtrWillBeRawPtr<ClientRect> clientRect = element.getBoundingClientRect();
+    int centerX = static_cast<int>((clientRect->left() + clientRect->right()) / 2);
+    int centerY = static_cast<int>((clientRect->top() + clientRect->bottom()) / 2);
+
+    return element.document().elementFromPoint(centerX , centerY);
+}
+
+void MediaControls::tryShowOverlayCastButton()
+{
+    // The element needs to be shown to have its dimensions and position.
+    m_overlayCastButton->show();
+
+    if (elementFromCenter(*m_overlayCastButton) != &mediaElement())
+        m_overlayCastButton->hide();
+}
+
 void MediaControls::refreshCastButtonVisibility()
 {
     if (mediaElement().hasRemoteRoutes()) {
@@ -386,7 +404,7 @@
             // Check that the cast button actually fits on the bar.
             if (m_fullScreenButton->getBoundingClientRect()->right() > m_panel->getBoundingClientRect()->right()) {
                 m_castButton->hide();
-                m_overlayCastButton->show();
+                tryShowOverlayCastButton();
             }
         }
     } else {
@@ -397,7 +415,7 @@
 
 void MediaControls::showOverlayCastButton()
 {
-    m_overlayCastButton->show();
+    tryShowOverlayCastButton();
     resetHideMediaControlsTimer();
 }
 
diff --git a/Source/core/html/shadow/MediaControls.h b/Source/core/html/shadow/MediaControls.h
index 8da8ff7..a04a9f5 100644
--- a/Source/core/html/shadow/MediaControls.h
+++ b/Source/core/html/shadow/MediaControls.h
@@ -96,6 +96,10 @@
     void stopHideMediaControlsTimer();
     void resetHideMediaControlsTimer();
 
+    // Attempts to show the overlay cast button. If it is covered by another
+    // element in the page, it will be hidden.
+    void tryShowOverlayCastButton();
+
     void createTextTrackDisplay();
     void showTextTrackDisplay();
     void hideTextTrackDisplay();
diff --git a/Source/core/inspector/InspectorStyleSheet.cpp b/Source/core/inspector/InspectorStyleSheet.cpp
index d341945..0adbafe 100644
--- a/Source/core/inspector/InspectorStyleSheet.cpp
+++ b/Source/core/inspector/InspectorStyleSheet.cpp
@@ -1068,13 +1068,15 @@
         return false;
     }
 
-    rule->setSelectorText(selector);
-    RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = ruleSourceDataAt(id.ordinal());
-    if (!sourceData) {
-        exceptionState.throwDOMException(NotFoundError, "The selector '" + selector + "' could not be set.");
+    if (!verifySelectorText(selector)) {
+        exceptionState.throwDOMException(SyntaxError, "Selector text is not valid.");
         return false;
     }
 
+    rule->setSelectorText(selector);
+    RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = ruleSourceDataAt(id.ordinal());
+    ASSERT(sourceData);
+
     String sheetText = m_parsedStyleSheet->text();
     sheetText.replace(sourceData->ruleHeaderRange.start, sourceData->ruleHeaderRange.length(), selector);
     updateText(sheetText);
@@ -1183,6 +1185,33 @@
     return true;
 }
 
+bool InspectorStyleSheet::verifySelectorText(const String& selectorText)
+{
+    DEFINE_STATIC_LOCAL(String, bogusPropertyName, ("-webkit-boguz-propertee"));
+    RuleSourceDataList sourceData;
+    RefPtrWillBeRawPtr<StyleSheetContents> styleSheetContents = StyleSheetContents::create(strictCSSParserContext());
+    String text = selectorText + " div { " + bogusPropertyName + ": none; }";
+    StyleSheetHandler handler(text, ownerDocument(), styleSheetContents.get(), &sourceData);
+    CSSParser::parseSheet(parserContextForDocument(ownerDocument()), styleSheetContents.get(), text, TextPosition::minimumPosition(), &handler);
+
+    // Exactly one rule should be parsed.
+    unsigned ruleCount = sourceData.size();
+    if (ruleCount != 1 || sourceData.at(0)->type != CSSRuleSourceData::STYLE_RULE)
+        return false;
+
+    // Exactly one property should be in style rule.
+    WillBeHeapVector<CSSPropertySourceData>& propertyData = sourceData.at(0)->styleSourceData->propertyData;
+    unsigned propertyCount = propertyData.size();
+    if (propertyCount != 1)
+        return false;
+
+    // Check for the property name.
+    if (propertyData.at(0).name != bogusPropertyName)
+        return false;
+
+    return true;
+}
+
 CSSStyleRule* InspectorStyleSheet::addRule(const String& ruleText, const SourceRange& location, ExceptionState& exceptionState)
 {
     if (!ensureParsedDataReady()) {
diff --git a/Source/core/inspector/InspectorStyleSheet.h b/Source/core/inspector/InspectorStyleSheet.h
index 03f24a9..53badeb 100644
--- a/Source/core/inspector/InspectorStyleSheet.h
+++ b/Source/core/inspector/InspectorStyleSheet.h
@@ -237,6 +237,7 @@
     CSSStyleRule* insertCSSOMRuleInMediaRule(CSSMediaRule*, const SourceRange&, const String& ruleText, ExceptionState&);
     CSSStyleRule* insertCSSOMRuleBySourceRange(const SourceRange&, const String& ruleText, ExceptionState&);
     bool verifyRuleText(const String& ruleText);
+    bool verifySelectorText(const String& selectorText);
     unsigned ruleIndexByStyle(CSSStyleDeclaration*) const;
     String sourceMapURL() const;
     String sourceURL() const;
diff --git a/Source/core/page/EventSource.cpp b/Source/core/page/EventSource.cpp
index a6902c8..5b5dda3 100644
--- a/Source/core/page/EventSource.cpp
+++ b/Source/core/page/EventSource.cpp
@@ -86,12 +86,7 @@
     }
 
     // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
-    bool shouldBypassMainWorldCSP = false;
-    if (context->isDocument()) {
-        Document* document = toDocument(context);
-        shouldBypassMainWorldCSP = document->frame()->script().shouldBypassMainWorldCSP();
-    }
-    if (!shouldBypassMainWorldCSP && !context->contentSecurityPolicy()->allowConnectToSource(fullURL)) {
+    if (!ContentSecurityPolicy::shouldBypassMainWorld(context) && !context->contentSecurityPolicy()->allowConnectToSource(fullURL)) {
         // We can safely expose the URL to JavaScript, as this exception is generate synchronously before any redirects take place.
         exceptionState.throwSecurityError("Refused to connect to '" + fullURL.elidedString() + "' because it violates the document's Content Security Policy.");
         return nullptr;
diff --git a/Source/core/rendering/InlineBox.cpp b/Source/core/rendering/InlineBox.cpp
index 362384c..830a7e5 100644
--- a/Source/core/rendering/InlineBox.cpp
+++ b/Source/core/rendering/InlineBox.cpp
@@ -107,7 +107,7 @@
 
 void InlineBox::showBox(int printedCharacters) const
 {
-    printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this);
+    printedCharacters += fprintf(stderr, "%s %p", boxName(), this);
     for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
         fputc(' ', stderr);
     fprintf(stderr, "\t%s %p {pos=%g,%g size=%g,%g} baseline=%i/%i\n",
diff --git a/Source/core/rendering/InlineTextBox.cpp b/Source/core/rendering/InlineTextBox.cpp
index 91d7ad6..e3c5bc7 100644
--- a/Source/core/rendering/InlineTextBox.cpp
+++ b/Source/core/rendering/InlineTextBox.cpp
@@ -552,11 +552,11 @@
     value = value.substring(start(), len());
     value.replaceWithLiteral('\\', "\\\\");
     value.replaceWithLiteral('\n', "\\n");
-    printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this);
+    printedCharacters += fprintf(stderr, "%s %p", boxName(), this);
     for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
         fputc(' ', stderr);
     printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj);
-    const int rendererCharacterOffset = 24;
+    const int rendererCharacterOffset = 75;
     for (; printedCharacters < rendererCharacterOffset; printedCharacters++)
         fputc(' ', stderr);
     fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().data());
diff --git a/Source/core/rendering/RenderBlock.cpp b/Source/core/rendering/RenderBlock.cpp
index 53b3e20..8fbdcc8 100644
--- a/Source/core/rendering/RenderBlock.cpp
+++ b/Source/core/rendering/RenderBlock.cpp
@@ -613,11 +613,6 @@
     if (!beforeChild && isAfterContent(lastChild()))
         beforeChild = lastChild();
 
-    // If we are moving inline children from |this| to cloneBlock, then we need
-    // to clear our line box tree.
-    if (beforeChild && childrenInline())
-        deleteLineBoxTree();
-
     // Now take all of the children from beforeChild to the end and remove
     // them from |this| and place them in the clone.
     moveChildrenTo(cloneBlock, beforeChild, 0, true);
@@ -788,7 +783,8 @@
     // This function currently supports (1) and (2).
     RenderBlockFlow* columnsBlockAncestor = 0;
     if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent()
-        && !newChild->isFloatingOrOutOfFlowPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
+        && !newChild->isFloatingOrOutOfFlowPositioned() && !newChild->isInline() && !newChild->isTablePart()
+        && !isAnonymousColumnSpanBlock()) {
         columnsBlockAncestor = containingColumnsBlock(false);
         if (columnsBlockAncestor) {
             // Make sure that none of the parent ancestors have a continuation.
diff --git a/Source/core/rendering/RenderBlockFlow.cpp b/Source/core/rendering/RenderBlockFlow.cpp
index 79571ad..13bfdc8 100644
--- a/Source/core/rendering/RenderBlockFlow.cpp
+++ b/Source/core/rendering/RenderBlockFlow.cpp
@@ -2717,6 +2717,13 @@
     return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
 }
 
+void RenderBlockFlow::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
+{
+    if (childrenInline())
+        deleteLineBoxTree();
+    RenderBoxModelObject::moveChildrenTo(toBoxModelObject, startChild, endChild, beforeChild, fullRemoveInsert);
+}
+
 LayoutUnit RenderBlockFlow::logicalLeftSelectionOffset(const RenderBlock* rootBlock, LayoutUnit position) const
 {
     LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
diff --git a/Source/core/rendering/RenderBlockFlow.h b/Source/core/rendering/RenderBlockFlow.h
index a6aaabb..adbf636 100644
--- a/Source/core/rendering/RenderBlockFlow.h
+++ b/Source/core/rendering/RenderBlockFlow.h
@@ -186,6 +186,9 @@
 
     virtual bool avoidsFloats() const override;
 
+    using RenderBoxModelObject::moveChildrenTo;
+    virtual void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false) override;
+
     LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
     {
         if (isHorizontalWritingMode())
diff --git a/Source/core/rendering/RenderBoxModelObject.h b/Source/core/rendering/RenderBoxModelObject.h
index 98ce0dc..40adffa 100644
--- a/Source/core/rendering/RenderBoxModelObject.h
+++ b/Source/core/rendering/RenderBoxModelObject.h
@@ -208,7 +208,7 @@
     {
         moveChildrenTo(toBoxModelObject, startChild, endChild, 0, fullRemoveInsert);
     }
-    void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
+    virtual void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
 
     enum ScaleByEffectiveZoomOrNot { ScaleByEffectiveZoom, DoNotScaleByEffectiveZoom };
     IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const;
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp
index 4fc9077..b96470b 100644
--- a/Source/core/rendering/RenderLayer.cpp
+++ b/Source/core/rendering/RenderLayer.cpp
@@ -551,6 +551,11 @@
 {
     RenderLayer* paintInvalidationLayer = paintInvalidationContainer->layer();
     if (!paintInvalidationLayer->groupedMapping()) {
+        // FIXME: this is defensive code to avoid crashes such as those described in crbug.com/440887, most likely due to
+        // the new multi-column code special-casing when choosing paint invalidation containers. Remove once that is cleaned up.
+        if (!paintInvalidationLayer->compositedLayerMapping())
+            return;
+
         point.move(paintInvalidationLayer->compositedLayerMapping()->contentOffsetInCompositingLayer());
         return;
     }
diff --git a/Source/core/rendering/RenderTable.cpp b/Source/core/rendering/RenderTable.cpp
index cf2d2f3..a10fc6a 100644
--- a/Source/core/rendering/RenderTable.cpp
+++ b/Source/core/rendering/RenderTable.cpp
@@ -389,6 +389,11 @@
 
 void RenderTable::simplifiedNormalFlowLayout()
 {
+    // FIXME: We should walk through the items in the tree in tree order to do the layout here
+    // instead of walking through individual parts of the tree. crbug.com/442737
+    for (auto& caption : m_captions)
+        caption->layoutIfNeeded();
+
     for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
         section->layoutIfNeeded();
         section->computeOverflowFromCells();
diff --git a/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/Source/core/xmlhttprequest/XMLHttpRequest.cpp
index 3494b56..96ea78b 100644
--- a/Source/core/xmlhttprequest/XMLHttpRequest.cpp
+++ b/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -208,6 +208,7 @@
     , m_uploadComplete(false)
     , m_sameOriginRequest(true)
     , m_downloadingToFile(false)
+    , m_responseTextOverflow(false)
 {
 #ifndef NDEBUG
     xmlHttpRequestCounter.increment();
@@ -1361,8 +1362,13 @@
         return;
     }
 
-    if (m_decoder)
-        m_responseText = m_responseText.concatenateWith(m_decoder->flush());
+    if (m_decoder) {
+        auto text = m_decoder->flush();
+        if (!text.isEmpty() && !m_responseTextOverflow) {
+            m_responseText = m_responseText.concatenateWith(text);
+            m_responseTextOverflow = m_responseText.isEmpty();
+        }
+    }
 
     if (m_responseLegacyStream)
         m_responseLegacyStream->finalize();
@@ -1538,7 +1544,11 @@
         if (!m_decoder)
             m_decoder = createDecoder();
 
-        m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len));
+        auto text = m_decoder->decode(data, len);
+        if (!text.isEmpty() && !m_responseTextOverflow) {
+            m_responseText = m_responseText.concatenateWith(text);
+            m_responseTextOverflow = m_responseText.isEmpty();
+        }
     } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) {
         // Buffer binary data.
         if (!m_binaryResponseBuilder)
diff --git a/Source/core/xmlhttprequest/XMLHttpRequest.h b/Source/core/xmlhttprequest/XMLHttpRequest.h
index d7151be..e7f726d 100644
--- a/Source/core/xmlhttprequest/XMLHttpRequest.h
+++ b/Source/core/xmlhttprequest/XMLHttpRequest.h
@@ -306,6 +306,7 @@
     // True iff the ongoing resource loading is using the downloadToFile
     // option.
     bool m_downloadingToFile;
+    bool m_responseTextOverflow;
 };
 
 } // namespace blink
diff --git a/Source/modules/indexeddb/IDBCursor.cpp b/Source/modules/indexeddb/IDBCursor.cpp
index 9414b92..9aa7c34 100644
--- a/Source/modules/indexeddb/IDBCursor.cpp
+++ b/Source/modules/indexeddb/IDBCursor.cpp
@@ -38,7 +38,6 @@
 #include "modules/indexeddb/IDBTracing.h"
 #include "modules/indexeddb/IDBTransaction.h"
 #include "modules/indexeddb/WebIDBCallbacksImpl.h"
-#include "public/platform/WebBlobInfo.h"
 #include "public/platform/WebIDBDatabase.h"
 #include "public/platform/WebIDBKeyRange.h"
 #include <limits>
@@ -72,12 +71,6 @@
 
 IDBCursor::~IDBCursor()
 {
-    ASSERT(!m_blobInfo || m_blobInfo->size() == 0);
-}
-
-void IDBCursor::dispose()
-{
-    handleBlobAcks();
 }
 
 void IDBCursor::trace(Visitor* visitor)
@@ -274,7 +267,7 @@
 
 void IDBCursor::close()
 {
-    handleBlobAcks();
+    m_blobs.clear();
     m_request.clear();
     m_backend.clear();
 }
@@ -299,17 +292,16 @@
     const IDBObjectStoreMetadata& metadata = objectStore->metadata();
     IDBAny* value;
     if (metadata.autoIncrement && !metadata.keyPath.isNull()) {
-        value = IDBAny::create(m_value, m_blobInfo.get(), m_primaryKey, metadata.keyPath);
+        value = IDBAny::create(m_value, m_blobs->getInfo(), m_primaryKey, metadata.keyPath);
 #if ENABLE(ASSERT)
-        assertPrimaryKeyValidOrInjectable(scriptState, m_value, m_blobInfo.get(), m_primaryKey, metadata.keyPath);
+        assertPrimaryKeyValidOrInjectable(scriptState, m_value, m_blobs->getInfo(), m_primaryKey, metadata.keyPath);
 #endif
     } else {
-        value = IDBAny::create(m_value, m_blobInfo.get());
+        value = IDBAny::create(m_value, m_blobs->getInfo());
     }
 
     m_valueDirty = false;
     ScriptValue scriptValue = idbAnyToScriptValue(scriptState, value);
-    handleBlobAcks();
     return scriptValue;
 }
 
@@ -318,7 +310,7 @@
     return idbAnyToScriptValue(scriptState, m_source);
 }
 
-void IDBCursor::setValueReady(IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<WebBlobInfo> > blobInfo)
+void IDBCursor::setValueReady(IDBKey* key, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<IDBRequest::IDBBlobHolder> blobs)
 {
     m_key = key;
     m_keyDirty = true;
@@ -328,11 +320,8 @@
 
     if (isCursorWithValue()) {
         m_value = value;
-        handleBlobAcks();
-        m_blobInfo = blobInfo;
+        m_blobs = blobs;
         m_valueDirty = true;
-        if (m_blobInfo && m_blobInfo->size() > 0)
-            ThreadState::current()->registerPreFinalizer(*this);
     }
 
     m_gotValue = true;
@@ -352,17 +341,6 @@
     return m_source->idbIndex()->isDeleted();
 }
 
-void IDBCursor::handleBlobAcks()
-{
-    ASSERT(m_request || !m_blobInfo || !m_blobInfo->size());
-    if (m_blobInfo.get() && m_blobInfo->size()) {
-        ASSERT(m_request);
-        m_transaction->db()->ackReceivedBlobs(m_blobInfo.get());
-        m_blobInfo.clear();
-        ThreadState::current()->unregisterPreFinalizer(*this);
-    }
-}
-
 WebIDBCursorDirection IDBCursor::stringToDirection(const String& directionString, ExceptionState& exceptionState)
 {
     if (directionString == IndexedDBNames::next)
diff --git a/Source/modules/indexeddb/IDBCursor.h b/Source/modules/indexeddb/IDBCursor.h
index b44a442..ac7ad65 100644
--- a/Source/modules/indexeddb/IDBCursor.h
+++ b/Source/modules/indexeddb/IDBCursor.h
@@ -43,11 +43,9 @@
 class IDBTransaction;
 class ScriptState;
 class SharedBuffer;
-class WebBlobInfo;
 
 class IDBCursor : public GarbageCollectedFinalized<IDBCursor>, public ScriptWrappable {
     DEFINE_WRAPPERTYPEINFO();
-    USING_PRE_FINALIZER(IDBCursor, dispose);
 public:
     static WebIDBCursorDirection stringToDirection(const String& modeString, ExceptionState&);
 
@@ -77,7 +75,7 @@
     void postSuccessHandlerCallback();
     bool isDeleted() const;
     void close();
-    void setValueReady(IDBKey*, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<WebBlobInfo> >);
+    void setValueReady(IDBKey*, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<IDBRequest::IDBBlobHolder>);
     IDBKey* idbPrimaryKey() const { return m_primaryKey; }
     IDBRequest* request() const { return m_request.get(); }
     virtual bool isKeyCursor() const { return true; }
@@ -87,9 +85,7 @@
     IDBCursor(PassOwnPtr<WebIDBCursor>, WebIDBCursorDirection, IDBRequest*, IDBAny* source, IDBTransaction*);
 
 private:
-    void dispose();
     IDBObjectStore* effectiveObjectStore() const;
-    void handleBlobAcks();
 
     OwnPtr<WebIDBCursor> m_backend;
     Member<IDBRequest> m_request;
@@ -103,7 +99,7 @@
     Member<IDBKey> m_key;
     Member<IDBKey> m_primaryKey;
     RefPtr<SharedBuffer> m_value;
-    OwnPtr<Vector<WebBlobInfo> > m_blobInfo;
+    OwnPtr<IDBRequest::IDBBlobHolder> m_blobs;
 };
 
 } // namespace blink
diff --git a/Source/modules/indexeddb/IDBDatabase.cpp b/Source/modules/indexeddb/IDBDatabase.cpp
index a02f9c5..4e39cb4 100644
--- a/Source/modules/indexeddb/IDBDatabase.cpp
+++ b/Source/modules/indexeddb/IDBDatabase.cpp
@@ -110,16 +110,10 @@
     return atomicIncrement(&currentTransactionId);
 }
 
-void IDBDatabase::ackReceivedBlobs(const Vector<WebBlobInfo>* blobInfo)
+void IDBDatabase::ackReceivedBlobs(const Vector<String>& uuids)
 {
-    ASSERT(blobInfo);
-    if (!blobInfo->size() || !m_backend)
+    if (!m_backend)
         return;
-    Vector<WebBlobInfo>::const_iterator iter;
-    Vector<String> uuids;
-    uuids.reserveCapacity(blobInfo->size());
-    for (iter = blobInfo->begin(); iter != blobInfo->end(); ++iter)
-        uuids.append(iter->uuid());
     m_backend->ackReceivedBlobs(uuids);
 }
 
diff --git a/Source/modules/indexeddb/IDBDatabase.h b/Source/modules/indexeddb/IDBDatabase.h
index fdce7a2..185a101 100644
--- a/Source/modules/indexeddb/IDBDatabase.h
+++ b/Source/modules/indexeddb/IDBDatabase.h
@@ -118,7 +118,8 @@
 
     static int64_t nextTransactionId();
 
-    void ackReceivedBlobs(const Vector<WebBlobInfo>*);
+    // Acknowledge receipt of the blobs (referenced by their UUID's).
+    void ackReceivedBlobs(const Vector<String>& uuids);
 
     static const char indexDeletedErrorMessage[];
     static const char isKeyCursorErrorMessage[];
diff --git a/Source/modules/indexeddb/IDBRequest.cpp b/Source/modules/indexeddb/IDBRequest.cpp
index 36f55b0..742c8f0 100644
--- a/Source/modules/indexeddb/IDBRequest.cpp
+++ b/Source/modules/indexeddb/IDBRequest.cpp
@@ -77,12 +77,6 @@
 IDBRequest::~IDBRequest()
 {
     ASSERT(m_readyState == DONE || m_readyState == EarlyDeath || !executionContext());
-    ASSERT(!m_blobInfo || m_blobInfo->size() == 0);
-}
-
-void IDBRequest::dispose()
-{
-    handleBlobAcks();
 }
 
 void IDBRequest::trace(Visitor* visitor)
@@ -110,7 +104,6 @@
         return ScriptValue();
     m_resultDirty = false;
     ScriptValue value = idbAnyToScriptValue(m_scriptState.get(), m_result);
-    handleBlobAcks();
     return value;
 }
 
@@ -211,19 +204,7 @@
 
 void IDBRequest::setBlobInfo(PassOwnPtr<Vector<WebBlobInfo>> blobInfo)
 {
-    ASSERT(!m_blobInfo);
-    m_blobInfo = blobInfo;
-    if (m_blobInfo && m_blobInfo->size() > 0)
-        ThreadState::current()->registerPreFinalizer(*this);
-}
-
-void IDBRequest::handleBlobAcks()
-{
-    if (m_blobInfo.get() && m_blobInfo->size()) {
-        m_transaction->db()->ackReceivedBlobs(m_blobInfo.get());
-        m_blobInfo.clear();
-        ThreadState::current()->unregisterPreFinalizer(*this);
-    }
+    m_blobs = adoptPtr(new IDBBlobHolder(blobInfo));
 }
 
 bool IDBRequest::shouldEnqueueEvent() const
@@ -310,7 +291,7 @@
     }
 
     setBlobInfo(blobInfo);
-    onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get()));
+    onSuccessInternal(IDBAny::create(valueBuffer, m_blobs->getInfo()));
 }
 
 #if ENABLE(ASSERT)
@@ -339,10 +320,10 @@
     setBlobInfo(blobInfo);
 
 #if ENABLE(ASSERT)
-    assertPrimaryKeyValidOrInjectable(m_scriptState.get(), valueBuffer, m_blobInfo.get(), primaryKey, keyPath);
+    assertPrimaryKeyValidOrInjectable(m_scriptState.get(), valueBuffer, m_blobs->getInfo(), primaryKey, keyPath);
 #endif
 
-    onSuccessInternal(IDBAny::create(valueBuffer, m_blobInfo.get(), primaryKey, keyPath));
+    onSuccessInternal(IDBAny::create(valueBuffer, m_blobs->getInfo(), primaryKey, keyPath));
 }
 
 void IDBRequest::onSuccess(int64_t value)
@@ -458,11 +439,8 @@
     IDBCursor* cursorToNotify = 0;
     if (event->type() == EventTypeNames::success) {
         cursorToNotify = getResultCursor();
-        if (cursorToNotify) {
-            if (m_blobInfo && m_blobInfo->size() > 0)
-                ThreadState::current()->unregisterPreFinalizer(*this);
-            cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release(), m_blobInfo.release());
-        }
+        if (cursorToNotify)
+            cursorToNotify->setValueReady(m_cursorKey.release(), m_cursorPrimaryKey.release(), m_cursorValue.release(), m_blobs.release());
     }
 
     if (event->type() == EventTypeNames::upgradeneeded) {
@@ -556,4 +534,23 @@
     }
 }
 
+IDBRequest::IDBBlobHolder::IDBBlobHolder(PassOwnPtr<Vector<WebBlobInfo>> blobInfo)
+    : m_blobInfo(blobInfo)
+{
+    if (!m_blobInfo->isEmpty()) {
+        m_blobData = adoptPtr(new Vector<RefPtr<BlobDataHandle>>());
+        for (const auto& info : *m_blobInfo.get())
+            m_blobData->append(BlobDataHandle::create(info.uuid(), info.type(), info.size()));
+    }
+}
+
+Vector<String> IDBRequest::IDBBlobHolder::getUUIDs() const
+{
+    Vector<String> uuids;
+    uuids.reserveCapacity(m_blobInfo->size());
+    for (const auto& info : *m_blobInfo)
+        uuids.append(info.uuid());
+    return uuids;
+}
+
 } // namespace blink
diff --git a/Source/modules/indexeddb/IDBRequest.h b/Source/modules/indexeddb/IDBRequest.h
index 81afa0d..a59c61d 100644
--- a/Source/modules/indexeddb/IDBRequest.h
+++ b/Source/modules/indexeddb/IDBRequest.h
@@ -40,6 +40,7 @@
 #include "modules/indexeddb/IDBAny.h"
 #include "modules/indexeddb/IDBTransaction.h"
 #include "modules/indexeddb/IndexedDB.h"
+#include "platform/blob/BlobData.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/WebBlobInfo.h"
 #include "public/platform/WebIDBCursor.h"
@@ -58,7 +59,7 @@
     , public ActiveDOMObject {
     DEFINE_EVENT_TARGET_REFCOUNTING_WILL_BE_REMOVED(RefCountedGarbageCollected<IDBRequest>);
     DEFINE_WRAPPERTYPEINFO();
-    USING_PRE_FINALIZER(IDBRequest, dispose);
+    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(IDBRequest);
     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(IDBRequest);
 public:
     static IDBRequest* create(ScriptState*, IDBAny* source, IDBTransaction*);
@@ -85,6 +86,20 @@
         EarlyDeath = 3
     };
 
+    class IDBBlobHolder {
+        WTF_MAKE_NONCOPYABLE(IDBBlobHolder);
+    public:
+        explicit IDBBlobHolder(PassOwnPtr<Vector<WebBlobInfo>>);
+        virtual ~IDBBlobHolder() { }
+
+        const Vector<WebBlobInfo>* getInfo() const { return m_blobInfo.get(); }
+        Vector<String> getUUIDs() const;
+
+    private:
+        OwnPtr<Vector<WebBlobInfo>> m_blobInfo;
+        OwnPtr<Vector<RefPtr<BlobDataHandle>>> m_blobData;
+    };
+
     const String& readyState() const;
 
     DEFINE_ATTRIBUTE_EVENT_LISTENER(success);
@@ -142,10 +157,8 @@
     bool m_requestAborted; // May be aborted by transaction then receive async onsuccess; ignore vs. assert.
 
 private:
-    void dispose();
     void setResultCursor(IDBCursor*, IDBKey*, IDBKey* primaryKey, PassRefPtr<SharedBuffer> value, PassOwnPtr<Vector<WebBlobInfo> >);
     void setBlobInfo(PassOwnPtr<Vector<WebBlobInfo>>);
-    void handleBlobAcks();
 
     RefPtr<ScriptState> m_scriptState;
     Member<IDBAny> m_source;
@@ -164,7 +177,7 @@
     Member<IDBKey> m_cursorKey;
     Member<IDBKey> m_cursorPrimaryKey;
     RefPtr<SharedBuffer> m_cursorValue;
-    OwnPtr<Vector<WebBlobInfo> > m_blobInfo;
+    OwnPtr<IDBBlobHolder> m_blobs;
 
     bool m_didFireUpgradeNeededEvent;
     bool m_preventPropagation;
diff --git a/Source/modules/mediastream/MediaStream.cpp b/Source/modules/mediastream/MediaStream.cpp
index 0d1a4f1..046c118 100644
--- a/Source/modules/mediastream/MediaStream.cpp
+++ b/Source/modules/mediastream/MediaStream.cpp
@@ -260,9 +260,9 @@
     if (ended())
         return;
 
-    MediaStreamCenter::instance().didStopLocalMediaStream(descriptor());
-
     streamEnded();
+
+    MediaStreamCenter::instance().didStopLocalMediaStream(descriptor());
 }
 
 void MediaStream::trackEnded()
diff --git a/Source/modules/serviceworkers/ServiceWorkerClient.h b/Source/modules/serviceworkers/ServiceWorkerClient.h
index f8eaa71..938fa4c 100644
--- a/Source/modules/serviceworkers/ServiceWorkerClient.h
+++ b/Source/modules/serviceworkers/ServiceWorkerClient.h
@@ -18,7 +18,6 @@
     static ServiceWorkerClient* create(unsigned id);
 
     // ServiceWorkerClient.idl
-    unsigned id() const { return m_id; }
     void postMessage(ExecutionContext*, PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionState&);
 
     void trace(Visitor*) { }
diff --git a/Source/modules/serviceworkers/ServiceWorkerClient.idl b/Source/modules/serviceworkers/ServiceWorkerClient.idl
index db7d411..fe6a0e7 100644
--- a/Source/modules/serviceworkers/ServiceWorkerClient.idl
+++ b/Source/modules/serviceworkers/ServiceWorkerClient.idl
@@ -9,7 +9,5 @@
     GarbageCollected,
     TypeChecking=Interface,
 ] interface ServiceWorkerClient {
-    readonly attribute unsigned long id;
-
     [Custom, RaisesException, CallWith=ExecutionContext] void postMessage(SerializedScriptValue message, optional sequence<Transferable> transfer);
 };
diff --git a/Source/modules/serviceworkers/ServiceWorkerContainer.cpp b/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
index 4ced420..83b6909 100644
--- a/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
+++ b/Source/modules/serviceworkers/ServiceWorkerContainer.cpp
@@ -141,11 +141,6 @@
         return promise;
     }
 
-    if (!patternURL.string().startsWith(scriptURL.baseAsString())) {
-        resolver->reject(DOMException::create(SecurityError, "The scope must be under the directory of the script URL."));
-        return promise;
-    }
-
     m_provider->registerServiceWorker(patternURL, scriptURL, new CallbackPromiseAdapter<ServiceWorkerRegistration, ServiceWorkerError>(resolver));
 
     return promise;
diff --git a/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp b/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp
index bf4ac0e..90e63eb 100644
--- a/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp
+++ b/Source/modules/serviceworkers/ServiceWorkerContainerTest.cpp
@@ -228,15 +228,6 @@
         ExpectDOMException("SecurityError", "The scope must match the current origin."));
 }
 
-TEST_F(ServiceWorkerContainerTest, Register_DifferentDirectoryThanScript)
-{
-    setPageURL("https://www.example.com/");
-    testRegisterRejected(
-        "https://www.example.com/js/worker.js",
-        "https://www.example.com/",
-        ExpectDOMException("SecurityError", "The scope must be under the directory of the script URL."));
-}
-
 TEST_F(ServiceWorkerContainerTest, GetRegistration_NonSecureOriginIsRejected)
 {
     setPageURL("http://www.example.com/");
diff --git a/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp b/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
index b0de045..a65ff09 100644
--- a/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
+++ b/Source/modules/serviceworkers/ServiceWorkerGlobalScope.cpp
@@ -89,6 +89,8 @@
 
 String ServiceWorkerGlobalScope::scope(ExecutionContext* context)
 {
+    // FIXME: Remove scope from ServiceWorkerGlobalScope.
+    context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "ServiceWorkerGlobalScope.scope is deprecated. It will be replaced by ServiceWorkerGlobalScope.registration.scope. https://crbug.com/443881"));
     return ServiceWorkerGlobalScopeClient::from(context)->scope().string();
 }
 
diff --git a/Source/modules/websockets/DOMWebSocket.cpp b/Source/modules/websockets/DOMWebSocket.cpp
index 4ac9187..fa21826 100644
--- a/Source/modules/websockets/DOMWebSocket.cpp
+++ b/Source/modules/websockets/DOMWebSocket.cpp
@@ -304,12 +304,7 @@
     }
 
     // FIXME: Convert this to check the isolated world's Content Security Policy once webkit.org/b/104520 is solved.
-    bool shouldBypassMainWorldCSP = false;
-    if (executionContext()->isDocument()) {
-        Document* document = toDocument(executionContext());
-        shouldBypassMainWorldCSP = document->frame()->script().shouldBypassMainWorldCSP();
-    }
-    if (!shouldBypassMainWorldCSP && !executionContext()->contentSecurityPolicy()->allowConnectToSource(m_url)) {
+    if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !executionContext()->contentSecurityPolicy()->allowConnectToSource(m_url)) {
         m_state = CLOSED;
         // The URL is safe to expose to JavaScript, as this check happens synchronously before redirection.
         exceptionState.throwSecurityError("Refused to connect to '" + m_url.elidedString() + "' because it violates the document's Content Security Policy.");
diff --git a/Source/platform/blink_platform.gypi b/Source/platform/blink_platform.gypi
index afefacb..b3b9016 100644
--- a/Source/platform/blink_platform.gypi
+++ b/Source/platform/blink_platform.gypi
@@ -918,6 +918,7 @@
       'network/HTTPParsersTest.cpp',
       'network/ResourceRequestTest.cpp',
       'scheduler/SchedulerTest.cpp',
+      'scroll/ScrollableAreaTest.cpp',
       'testing/ArenaTestHelpers.h',
       'testing/TreeTestHelpers.cpp',
       'testing/TreeTestHelpers.h',
diff --git a/Source/platform/graphics/ImageBuffer.cpp b/Source/platform/graphics/ImageBuffer.cpp
index 2c733d6..c7ac9b2 100644
--- a/Source/platform/graphics/ImageBuffer.cpp
+++ b/Source/platform/graphics/ImageBuffer.cpp
@@ -249,7 +249,7 @@
 
     m_surface->invalidateCachedBitmap();
     bool result = drawingBuffer->copyToPlatformTexture(context3D, tex, GL_RGBA,
-        GL_UNSIGNED_BYTE, 0, true, false, fromFrontBuffer);
+        GL_UNSIGNED_BYTE, 0, true, false, fromFrontBuffer ? DrawingBuffer::Front : DrawingBuffer::Back);
 
     if (result) {
         m_surface->didModifyBackingTexture();
diff --git a/Source/platform/graphics/gpu/DrawingBuffer.cpp b/Source/platform/graphics/gpu/DrawingBuffer.cpp
index 3f15b36..60a9d98 100644
--- a/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -458,7 +458,8 @@
     return true;
 }
 
-bool DrawingBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, bool fromFrontBuffer)
+bool DrawingBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat,
+    GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, SourceBuffer source)
 {
     if (m_contentsChanged) {
         if (m_multisampleMode != None) {
@@ -477,7 +478,7 @@
     // Contexts may be in a different share group. We must transfer the texture through a mailbox first
     WebExternalTextureMailbox mailbox;
     GLint textureId = 0;
-    if (fromFrontBuffer && m_frontColorBuffer.texInfo.textureId) {
+    if (source == Front && m_frontColorBuffer.texInfo.textureId) {
         textureId = m_frontColorBuffer.texInfo.textureId;
         mailbox = m_frontColorBuffer.mailbox;
     } else {
@@ -533,45 +534,6 @@
     return m_layer->layer();
 }
 
-void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer)
-{
-    if (m_context->getGraphicsResetStatusARB() != GL_NO_ERROR)
-        return;
-
-    if (!imageBuffer || !m_frontColorBuffer.texInfo.textureId)
-        return;
-    Platform3DObject tex = imageBuffer->getBackingTexture();
-    if (tex) {
-        OwnPtr<WebGraphicsContext3DProvider> provider =
-            adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
-        if (!provider)
-            return;
-        WebGraphicsContext3D* context = provider->context3d();
-        if (!context)
-            return;
-
-        context->waitSyncPoint(m_frontColorBuffer.mailbox.syncPoint);
-        Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, m_frontColorBuffer.mailbox.name);
-        context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture,
-            tex, 0, GL_RGBA, GL_UNSIGNED_BYTE);
-        context->deleteTexture(sourceTexture);
-        context->flush();
-        m_context->waitSyncPoint(context->insertSyncPoint());
-        imageBuffer->didModifyBackingTexture();
-        return;
-    }
-
-    Platform3DObject framebuffer = m_context->createFramebuffer();
-    m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
-    // We don't need to bind a copy of m_frontColorBuffer since the texture parameters are untouched.
-    m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_frontColorBuffer.texInfo.textureId, 0);
-
-    paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_actualAttributes.premultipliedAlpha, imageBuffer);
-    m_context->deleteFramebuffer(framebuffer);
-    // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding).
-    restoreFramebufferBinding();
-}
-
 void DrawingBuffer::clearPlatformLayer()
 {
     if (m_layer)
diff --git a/Source/platform/graphics/gpu/DrawingBuffer.h b/Source/platform/graphics/gpu/DrawingBuffer.h
index 698b4a3..c28f68f 100644
--- a/Source/platform/graphics/gpu/DrawingBuffer.h
+++ b/Source/platform/graphics/gpu/DrawingBuffer.h
@@ -144,7 +144,6 @@
     void setIsHidden(bool);
 
     WebLayer* platformLayer();
-    void paintCompositedResultsToCanvas(ImageBuffer*);
 
     WebGraphicsContext3D* context();
 
@@ -156,9 +155,10 @@
     virtual bool prepareMailbox(WebExternalTextureMailbox*, WebExternalBitmap*) override;
     virtual void mailboxReleased(const WebExternalTextureMailbox&, bool lostResource = false) override;
 
+    enum SourceBuffer { Front, Back };
     // Destroys the TEXTURE_2D binding for the owned context
     bool copyToPlatformTexture(WebGraphicsContext3D*, Platform3DObject texture, GLenum internalFormat,
-        GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, bool fromFrontBuffer = false);
+        GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, SourceBuffer);
 
     void setPackAlignment(GLint param);
 
diff --git a/Source/platform/mac/ScrollAnimatorMac.mm b/Source/platform/mac/ScrollAnimatorMac.mm
index 1856fe7..96ef816 100644
--- a/Source/platform/mac/ScrollAnimatorMac.mm
+++ b/Source/platform/mac/ScrollAnimatorMac.mm
@@ -326,7 +326,6 @@
     void stop()
     {
         m_timer.stop();
-        [m_animation setCurrentProgress:1];
     }
 
     void setDuration(CFTimeInterval duration)
@@ -340,12 +339,12 @@
         double currentTime = WTF::currentTime();
         double delta = currentTime - m_startTime;
 
-        if (delta >= m_duration) {
-            stop();
-            return;
-        }
+        if (delta >= m_duration)
+            m_timer.stop();
 
         double fraction = delta / m_duration;
+        fraction = std::min(1.0, fraction);
+        fraction = std::max(0.0, fraction);
         double progress = m_timingFunction->evaluate(fraction, 0.001);
         [m_animation setCurrentProgress:progress];
     }
diff --git a/Source/platform/scroll/ScrollableArea.cpp b/Source/platform/scroll/ScrollableArea.cpp
index f170495..9992fd0 100644
--- a/Source/platform/scroll/ScrollableArea.cpp
+++ b/Source/platform/scroll/ScrollableArea.cpp
@@ -183,7 +183,7 @@
 void ScrollableArea::notifyScrollPositionChanged(const IntPoint& position)
 {
     scrollPositionChanged(DoublePoint(position));
-    scrollAnimator()->setCurrentPosition(position);
+    scrollAnimator()->setCurrentPosition(scrollPosition());
 }
 
 void ScrollableArea::scrollPositionChanged(const DoublePoint& position)
diff --git a/Source/platform/scroll/ScrollableAreaTest.cpp b/Source/platform/scroll/ScrollableAreaTest.cpp
new file mode 100644
index 0000000..1ba5f45
--- /dev/null
+++ b/Source/platform/scroll/ScrollableAreaTest.cpp
@@ -0,0 +1,60 @@
+// Copyright 2015 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 "platform/scroll/ScrollableArea.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace blink;
+
+namespace {
+
+class MockScrollableArea : public ScrollableArea {
+public:
+    MockScrollableArea(const IntPoint& maximumScrollPosition)
+        : m_maximumScrollPosition(maximumScrollPosition) { }
+
+    MOCK_CONST_METHOD0(isActive, bool());
+    MOCK_CONST_METHOD1(scrollSize, int(ScrollbarOrientation));
+    MOCK_METHOD2(invalidateScrollbar, void(Scrollbar*, const IntRect&));
+    MOCK_CONST_METHOD0(isScrollCornerVisible, bool());
+    MOCK_CONST_METHOD0(scrollCornerRect, IntRect());
+    MOCK_METHOD2(invalidateScrollbarRect, void(Scrollbar*, const IntRect&));
+    MOCK_METHOD1(invalidateScrollCornerRect, void(const IntRect&));
+    MOCK_CONST_METHOD0(enclosingScrollableArea, ScrollableArea*());
+    MOCK_CONST_METHOD0(minimumScrollPosition, IntPoint());
+    MOCK_CONST_METHOD1(visibleContentRect, IntRect(IncludeScrollbarsInRect));
+    MOCK_CONST_METHOD0(contentsSize, IntSize());
+    MOCK_CONST_METHOD0(overhangAmount, IntSize());
+    MOCK_CONST_METHOD0(scrollbarsCanBeActive, bool());
+    MOCK_CONST_METHOD0(scrollableAreaBoundingBox, IntRect());
+
+    virtual bool userInputScrollable(ScrollbarOrientation) const override { return true; }
+    virtual bool shouldPlaceVerticalScrollbarOnLeft() const override { return false; }
+    virtual void setScrollOffset(const IntPoint& offset) override { m_scrollPosition = offset.shrunkTo(m_maximumScrollPosition); }
+    virtual IntPoint scrollPosition() const override { return m_scrollPosition; }
+    virtual IntPoint maximumScrollPosition() const override { return m_maximumScrollPosition; }
+    virtual int visibleHeight() const override { return 768; }
+    virtual int visibleWidth() const override { return 1024; }
+    virtual bool scrollAnimatorEnabled() const override { return false; }
+    virtual int pageStep(ScrollbarOrientation) const override { return 0; }
+
+private:
+    IntPoint m_scrollPosition;
+    IntPoint m_maximumScrollPosition;
+};
+
+TEST(ScrollableAreaTest, ScrollAnimatorCurrentPositionShouldBeSync)
+{
+    MockScrollableArea scrollableArea(IntPoint(0, 100));
+    scrollableArea.notifyScrollPositionChanged(IntPoint(0, 10000));
+    EXPECT_EQ(100.0, scrollableArea.scrollAnimator()->currentPosition().y());
+}
+
+} // unnamed namespace
+
+
diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp
index a105f63..b9e8617 100644
--- a/Source/web/WebViewImpl.cpp
+++ b/Source/web/WebViewImpl.cpp
@@ -1733,11 +1733,15 @@
 
         pinchViewport.setTopControlsAdjustment(topControlsViewportAdjustment);
 
+// On ChromeOS the pinch viewport can change size independent of the layout viewport due to the
+// on screen keyboard so we should only set the FrameView adjustment on Android.
+#if OS(ANDROID)
         // Shrink the FrameView by the amount that will maintain the aspect-ratio with the PinchViewport.
         float aspectRatio = pinchViewport.visibleRect().width() / pinchViewport.visibleRect().height();
         float newHeight = view->unscaledVisibleContentSize(ExcludeScrollbars).width() / aspectRatio;
         float adjustment = newHeight - view->unscaledVisibleContentSize(ExcludeScrollbars).height();
         view->setTopControlsViewportAdjustment(adjustment);
+#endif
     }
 }
 
@@ -1782,6 +1786,9 @@
     m_fullscreenController->updateSize();
 
     if (settings()->viewportEnabled()) {
+        PinchViewport& pinchViewport = page()->frameHost().pinchViewport();
+        FloatPoint viewportOffsetBeforeResize = pinchViewport.visibleRectInDocument().location();
+
         // Relayout immediately to recalculate the minimum scale limit.
         if (view->needsLayout())
             view->layout();
@@ -1798,6 +1805,9 @@
             viewportAnchor.computeOrigins(*view, pinchViewportSize,
                 mainFrameOrigin, pinchViewportOrigin);
             scrollAndRescaleViewports(newPageScaleFactor, mainFrameOrigin, pinchViewportOrigin);
+        } else {
+            FloatSize deltaFromResize = viewportOffsetBeforeResize - pinchViewport.visibleRectInDocument().location();
+            pinchViewport.move(FloatPoint(deltaFromResize));
         }
     }
 
diff --git a/Source/web/tests/PinchViewportTest.cpp b/Source/web/tests/PinchViewportTest.cpp
index 7807423..0b96421 100644
--- a/Source/web/tests/PinchViewportTest.cpp
+++ b/Source/web/tests/PinchViewportTest.cpp
@@ -1009,6 +1009,36 @@
     EXPECT_FLOAT_POINT_EQ(FloatPoint(0, 10), pinchViewport.visibleRect().location());
 }
 
+#if OS(ANDROID)
+
+// Top controls can make an unscrollable page temporarily scrollable, causing
+// a scroll clamp when the page is resized. Make sure this bug is fixed.
+// crbug.com/437620
+TEST_F(PinchViewportTest, TestResizeDoesntChangeScrollOffset)
+{
+    initializeWithAndroidSettings();
+    webViewImpl()->resize(IntSize(100, 150));
+
+    navigateTo("about:blank");
+
+    PinchViewport& pinchViewport = frame()->page()->frameHost().pinchViewport();
+    FrameView& frameView = *webViewImpl()->mainFrameImpl()->frameView();
+
+    pinchViewport.setScale(2);
+    pinchViewport.move(FloatPoint(0, 40));
+
+    // Simulate bringing down the top controls by 20px but counterscrolling the outer viewport.
+    webViewImpl()->applyViewportDeltas(WebSize(), WebSize(0, 20), 1, 20);
+
+    EXPECT_EQ(20, frameView.scrollPosition().y());
+
+    webViewImpl()->setTopControlsLayoutHeight(20);
+    webViewImpl()->resize(WebSize(100, 130));
+
+    EXPECT_EQ(0, frameView.scrollPosition().y());
+    EXPECT_EQ(60, pinchViewport.location().y());
+}
+
 static IntPoint expectedMaxFrameViewScrollOffset(PinchViewport& pinchViewport, FrameView& frameView)
 {
     float aspectRatio = pinchViewport.visibleRect().width() / pinchViewport.visibleRect().height();
@@ -1165,25 +1195,6 @@
     EXPECT_POINT_EQ(pinchViewportExpected, pinchViewport.location());
 }
 
-// Tests that the layout viewport's scroll layer bounds are updated in a compositing
-// change update. crbug.com/423188.
-TEST_F(PinchViewportTest, TestChangingContentSizeAffectsScrollBounds)
-{
-    initializeWithAndroidSettings();
-    webViewImpl()->resize(IntSize(100, 150));
-
-    registerMockedHttpURLLoad("content-width-1000.html");
-    navigateTo(m_baseURL + "content-width-1000.html");
-
-    FrameView& frameView = *webViewImpl()->mainFrameImpl()->frameView();
-    WebLayer* scrollLayer = frameView.layerForScrolling()->platformLayer();
-
-    frameView.setContentsSize(IntSize(1500, 2400));
-    frameView.updateLayoutAndStyleForPainting();
-
-    EXPECT_SIZE_EQ(IntSize(1500, 2400), IntSize(scrollLayer->bounds()));
-}
-
 // Tests that a resize due to top controls hiding doesn't incorrectly clamp the
 // main frame's scroll offset. crbug.com/428193.
 TEST_F(PinchViewportTest, TestTopControlHidingResizeDoesntClampMainFrame)
@@ -1209,6 +1220,26 @@
     webViewImpl()->resize(IntSize(1000, 1500));
     EXPECT_EQ(500, frameView.scrollPositionDouble().y());
 }
+#endif
+
+// Tests that the layout viewport's scroll layer bounds are updated in a compositing
+// change update. crbug.com/423188.
+TEST_F(PinchViewportTest, TestChangingContentSizeAffectsScrollBounds)
+{
+    initializeWithAndroidSettings();
+    webViewImpl()->resize(IntSize(100, 150));
+
+    registerMockedHttpURLLoad("content-width-1000.html");
+    navigateTo(m_baseURL + "content-width-1000.html");
+
+    FrameView& frameView = *webViewImpl()->mainFrameImpl()->frameView();
+    WebLayer* scrollLayer = frameView.layerForScrolling()->platformLayer();
+
+    frameView.setContentsSize(IntSize(1500, 2400));
+    frameView.updateLayoutAndStyleForPainting();
+
+    EXPECT_SIZE_EQ(IntSize(1500, 2400), IntSize(scrollLayer->bounds()));
+}
 
 // Tests that resizing the pinch viepwort keeps its bounds within the outer
 // viewport.