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(¤tTransactionId);
}
-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.