Commit message: None
CVE: CVE-2013-0837
CWE: CWE-20
Vulnerability description: Google Chrome before 24.0.1312.52 allows remote attackers to cause a denial of service or possibly have unspecified other impact via vectors related to the handling of extension tabs.

Project: Chrome

LayerWebKitThread::LayerWebKitThread(LayerType type, GraphicsLayerBlackBerry* owner)
    : LayerData(type)
    , m_owner(owner)
    , m_superlayer(0)
    , m_contents(0)
    , m_isDrawable(false)
    , m_isMask(false)
    , m_animationsChanged(false)
    , m_clearOverrideOnCommit(false)
#if ENABLE(CSS_FILTERS)
    , m_filtersChanged(false)
#endif
    , m_didStartAnimations(false)
{
    if (type == Layer)
        m_tiler = LayerTiler::create(this);
    m_layerCompositingThread = LayerCompositingThread::create(type, m_tiler.get());
}

Project: Chrome

void LayerWebKitThread::addOverlay(PassRefPtr<LayerWebKitThread> overlay)
{
    insert(m_overlays, overlay, m_overlays.size());
}

Project: Chrome

void LayerWebKitThread::addSublayer(PassRefPtr<LayerWebKitThread> sublayer)
{
    insert(m_sublayers, sublayer, m_sublayers.size());
}

Project: Chrome

void LayerWebKitThread::commitOnCompositingThread()
{
    FloatPoint oldPosition = m_position;
    m_position += m_absoluteOffset;
    replicate(m_layerCompositingThread.get());
#if ENABLE(CSS_FILTERS)
    if (m_filtersChanged) {
        m_filtersChanged = false;
        m_layerCompositingThread->setFilterOperationsChanged(true);
    }
#endif
    if (m_animationsChanged) {
        m_layerCompositingThread->setRunningAnimations(m_runningAnimations);
        m_layerCompositingThread->setSuspendedAnimations(m_suspendedAnimations);
        m_animationsChanged = false;
    }
    if (m_clearOverrideOnCommit) {
        m_layerCompositingThread->clearOverride();
        m_clearOverrideOnCommit = false;
    }
    m_position = oldPosition;
    updateLayerHierarchy();

    commitPendingTextureUploads();

    size_t listSize = m_sublayers.size();
    for (size_t i = 0; i < listSize; ++i)
        m_sublayers[i]->commitOnCompositingThread();

    listSize = m_overlays.size();
    for (size_t i = 0; i < listSize; ++i)
        m_overlays[i]->commitOnCompositingThread();

    if (maskLayer()) {
        maskLayer()->commitOnCompositingThread();
        layerCompositingThread()->setMaskLayer(maskLayer()->layerCompositingThread());
    } else
        layerCompositingThread()->setMaskLayer(0);

    if (replicaLayer()) {
        replicaLayer()->commitOnCompositingThread();
        layerCompositingThread()->setReplicaLayer(replicaLayer()->layerCompositingThread());
    } else
        layerCompositingThread()->setReplicaLayer(0);
}

Project: Chrome

void LayerWebKitThread::commitPendingTextureUploads()
{
    layerCompositingThread()->commitPendingTextureUploads();
}

Project: Chrome

PassRefPtr<LayerWebKitThread> LayerWebKitThread::create(LayerType type, GraphicsLayerBlackBerry* owner)
{
    return adoptRef(new LayerWebKitThread(type, owner));
}

Project: Chrome

bool LayerWebKitThread::filtersCanBeComposited(const FilterOperations& filters)
{
    if (!filters.size())
        return false;

    for (unsigned i = 0; i < filters.size(); ++i) {
        const FilterOperation* filterOperation = filters.at(i);
        switch (filterOperation->getOperationType()) {
        case FilterOperation::REFERENCE:
#if ENABLE(CSS_SHADERS)
        case FilterOperation::CUSTOM:
#endif
            return false;
        default:
            break;
        }
    }

    return true;
}

Project: Chrome

void LayerWebKitThread::insert(Vector<RefPtr<LayerWebKitThread> >& list, PassRefPtr<LayerWebKitThread> sublayer, size_t index)
{
    sublayer->removeFromSuperlayer();
    index = min(index, list.size());
    sublayer->setSuperlayer(this);
    list.insert(index, sublayer);

    setNeedsCommit();
}

Project: Chrome

IntRect LayerWebKitThread::mapFromTransformed(const IntRect& contentsRect, double scale)
{
    IntRect untransformedContentsRect = contentsRect;

    if (scale != 1.0) {
        TransformationMatrix matrix;
        matrix.scale(1.0 / scale);
        untransformedContentsRect = matrix.mapRect(contentsRect);

        const int atLeastOneDevicePixel = static_cast<int>(ceilf(1.0 / scale));
        untransformedContentsRect.inflate(atLeastOneDevicePixel);
    }

    return untransformedContentsRect;
}

Project: Chrome

 void LayerWebKitThread::notifyAnimationsStarted(double time)
{
    if (m_didStartAnimations) {
        m_didStartAnimations = false;
        if (m_owner)
            m_owner->notifyAnimationStarted(time);
    }

    size_t listSize = m_sublayers.size();
    for (size_t i = 0; i < listSize; ++i)
        m_sublayers[i]->notifyAnimationsStarted(time);

    listSize = m_overlays.size();
    for (size_t i = 0; i < listSize; ++i)
        m_overlays[i]->notifyAnimationsStarted(time);
}

Project: Chrome

void LayerWebKitThread::paintContents(BlackBerry::Platform::Graphics::Buffer* buffer, const IntRect& contentsRect, double scale)
{
    if (!drawsContent() && !contents())
        return;

    if (!buffer)
        return;

    IntRect untransformedContentsRect = contentsRect;
    FloatRect clipRect = contentsRect;
    if (scale != 1.0) {
        TransformationMatrix matrix;
        matrix.scale(1.0 / scale);
        untransformedContentsRect = matrix.mapRect(contentsRect);
        clipRect = matrix.mapRect(clipRect);

        const int atLeastOneDevicePixel = static_cast<int>(ceilf(1.0 / scale));
        untransformedContentsRect.inflate(atLeastOneDevicePixel);
    }

    PlatformGraphicsContext* platformContext = lockBufferDrawable(buffer);
    GraphicsContext graphicsContext(platformContext);
    if (contents()) {
        if (!contents()->size().isEmpty())
            graphicsContext.drawImage(contents(), ColorSpaceDeviceRGB, IntPoint(0, 0));
    } else {
        graphicsContext.translate(-contentsRect.x(), -contentsRect.y());
        graphicsContext.scale(FloatSize(scale, scale));
        graphicsContext.clip(clipRect);
        m_owner->paintGraphicsLayerContents(graphicsContext, untransformedContentsRect);
    }

    releaseBufferDrawable(buffer);
}

Project: Chrome

void LayerWebKitThread::releaseLayerResources()
{
    deleteTextures();

    size_t listSize = m_sublayers.size();
    for (size_t i = 0; i < listSize; ++i)
        m_sublayers[i]->releaseLayerResources();

    listSize = m_overlays.size();
    for (size_t i = 0; i < listSize; ++i)
        m_overlays[i]->releaseLayerResources();

    if (maskLayer())
        maskLayer()->releaseLayerResources();

    if (replicaLayer())
        replicaLayer()->releaseLayerResources();
}

Project: Chrome

void LayerWebKitThread::remove(Vector<RefPtr<LayerWebKitThread> >& vector, LayerWebKitThread* sublayer)
{
    int foundIndex = vector.find(sublayer);
    if (foundIndex == notFound)
        return;

    sublayer->setSuperlayer(0);
    vector.remove(foundIndex);

    setNeedsCommit();
}

Project: Chrome

void LayerWebKitThread::removeAll(Vector<RefPtr<LayerWebKitThread> >& vector)
{
    if (!vector.size())
        return;

    while (vector.size()) {
        RefPtr<LayerWebKitThread> layer = vector[0].get();
        ASSERT(layer->superlayer() == this);
        layer->removeFromSuperlayer();
    }

    setNeedsCommit();
}

Project: Chrome

void LayerWebKitThread::removeFromSuperlayer()
{
    if (m_superlayer)
        m_superlayer->removeSublayerOrOverlay(this);
}

Project: Chrome

void LayerWebKitThread::removeSublayerOrOverlay(LayerWebKitThread* sublayer)
{
    remove(m_sublayers, sublayer);
    remove(m_overlays, sublayer);
}

Project: Chrome

void LayerWebKitThread::replaceSublayer(LayerWebKitThread* reference, PassRefPtr<LayerWebKitThread> newLayer)
{
    ASSERT_ARG(reference, reference);
    ASSERT_ARG(reference, reference->superlayer() == this);

    if (reference == newLayer)
        return;

    int referenceIndex = m_sublayers.find(reference);
    if (referenceIndex == notFound) {
        ASSERT_NOT_REACHED();
        return;
    }

    reference->removeFromSuperlayer();

    if (newLayer) {
        newLayer->removeFromSuperlayer();
        insertSublayer(newLayer, referenceIndex);
    }
}

Project: Chrome

const LayerWebKitThread* LayerWebKitThread::rootLayer() const
{
    const LayerWebKitThread* layer = this;
    LayerWebKitThread* superlayer = layer->superlayer();

    while (superlayer) {
        layer = superlayer;
        superlayer = superlayer->superlayer();
    }
    return layer;
}

Project: Chrome

void LayerWebKitThread::setBounds(const IntSize& size)
{
    if (m_bounds == size)
        return;

    bool firstResize = !m_bounds.width() && !m_bounds.height() && size.width() && size.height();

    m_bounds = size;

    boundsChanged();

    if (firstResize)
        setNeedsDisplay();
    else
        setNeedsCommit();
}

Project: Chrome

void LayerWebKitThread::setFrame(const FloatRect& rect)
{
    if (rect == m_frame)
      return;

    m_frame = rect;
    setNeedsDisplay();
}

Project: Chrome

void LayerWebKitThread::setIsMask(bool isMask)
{
    m_isMask = isMask;
    if (isMask && m_tiler)
        m_tiler->setNeedsBacking(true);
}

Project: Chrome

void LayerWebKitThread::setNeedsDisplay()
{
    if (m_tiler)
        m_tiler->setNeedsDisplay();
    setNeedsCommit(); // FIXME: Replace this with a more targeted message for dirty rect handling with plugin content?
}

Project: Chrome

void LayerWebKitThread::setNeedsDisplayInRect(const FloatRect& dirtyRect)
{
    if (m_tiler)
        m_tiler->setNeedsDisplay(dirtyRect);
    setNeedsCommit(); // FIXME: Replace this with a more targeted message for dirty rect handling with plugin content?
}

Project: Chrome

void LayerWebKitThread::setRunningAnimations(const Vector<RefPtr<LayerAnimation> >& animations)
{
    m_runningAnimations = animations;
    m_animationsChanged = true;
    setNeedsCommit();
}

Project: Chrome

void LayerWebKitThread::setSublayers(const Vector<RefPtr<LayerWebKitThread> >& sublayers)
{
    if (sublayers == m_sublayers)
        return;

    removeAllSublayers();
    size_t listSize = sublayers.size();
    for (size_t i = 0; i < listSize; ++i)
        addSublayer(sublayers[i]);
}

Project: Chrome

void LayerWebKitThread::setSuspendedAnimations(const Vector<RefPtr<LayerAnimation> >& animations)
{
    m_suspendedAnimations = animations;
    m_animationsChanged = true;
    setNeedsCommit();
}

Project: Chrome

bool LayerWebKitThread::startAnimations(double time)
{
    bool didStartAnimations = false;
    for (size_t i = 0; i < m_runningAnimations.size(); ++i) {
        if (!m_runningAnimations[i]->startTime()) {
            m_runningAnimations[i]->setStartTime(time);
            m_didStartAnimations = didStartAnimations = true;
        }
    }

    size_t listSize = m_sublayers.size();
    for (size_t i = 0; i < listSize; ++i)
        didStartAnimations |= m_sublayers[i]->startAnimations(time);

    listSize = m_overlays.size();
    for (size_t i = 0; i < listSize; ++i)
        didStartAnimations |= m_overlays[i]->startAnimations(time);

    return didStartAnimations;
}

Project: Chrome

void LayerWebKitThread::updateLayerHierarchy()
{
    m_layerCompositingThread->setSuperlayer(superlayer() ? superlayer()->m_layerCompositingThread.get() : 0);

    Vector<RefPtr<LayerCompositingThread> > sublayers;
    size_t listSize = m_overlays.size();
    for (size_t i = 0; i < listSize; ++i)
        sublayers.append(m_overlays[i]->m_layerCompositingThread.get());
    listSize = m_sublayers.size();
    for (size_t i = 0; i < listSize; ++i)
        sublayers.append(m_sublayers[i]->m_layerCompositingThread.get());
    m_layerCompositingThread->setSublayers(sublayers);
}

Project: Chrome

void LayerWebKitThread::updateTextureContents(double scale)
{
    if (m_contentsScale != scale) {
        m_contentsScale = scale;

        if (drawsContent())
            setNeedsDisplay();
    }

    updateTextureContentsIfNeeded();

    if (includeVisibility()) {
        RenderLayer* renderLayer(static_cast<RenderLayerBacking*>(m_owner->client())->owningLayer());
        bool isVisible(renderLayer->hasVisibleContent() || renderLayer->hasVisibleDescendant());
        if (m_isVisible != isVisible) {
            m_isVisible = isVisible;
            setNeedsCommit();
        }
    }

    size_t listSize = m_sublayers.size();
    for (size_t i = 0; i < listSize; ++i)
        m_sublayers[i]->updateTextureContents(scale);

    listSize = m_overlays.size();
    for (size_t i = 0; i < listSize; ++i)
        m_overlays[i]->updateTextureContents(scale);

    if (maskLayer())
        maskLayer()->updateTextureContents(scale);

    if (replicaLayer())
        replicaLayer()->updateTextureContents(scale);
}

Project: Chrome

void LayerWebKitThread::updateTextureContentsIfNeeded()
{
    if (m_tiler)
        m_tiler->updateTextureContentsIfNeeded(m_isMask ? 1.0 : contentsScale());
}

Project: Chrome

LayerWebKitThread::~LayerWebKitThread()
{
    if (m_tiler)
        m_tiler->layerWebKitThreadDestroyed();

    ASSERT(!superlayer());

    removeAll(m_sublayers);
    removeAll(m_overlays);
}