Commit message: None
CVE: CVE-2013-2921
CWE: CWE-399
Vulnerability description: Double free vulnerability in the ResourceFetcher::didLoadResource function in core/fetch/ResourceFetcher.cpp in the resource loader in Blink, as used in Google Chrome before 30.0.1599.66, allows remote attackers to cause a denial of service or possibly have unspecified other impact by triggering certain callback processing during the reporting of a resource entry.

Project: Chrome

void DelegatedFrameHost::AddOnCommitCallbackAndDisableLocks(
    const base::Closure& callback) {
  ui::Compositor* compositor = client_->GetCompositor();
  DCHECK(compositor);

  if (!compositor->HasObserver(this))
    compositor->AddObserver(this);

  can_lock_compositor_ = NO_PENDING_COMMIT;
  on_compositing_did_commit_callbacks_.push_back(callback);
}

Project: Chrome

void DelegatedFrameHost::AddedToWindow() {
  ui::Compositor* compositor = client_->GetCompositor();
  if (compositor) {
    DCHECK(!vsync_manager_);
    vsync_manager_ = compositor->vsync_manager();
    vsync_manager_->AddObserver(this);
  }
}

Project: Chrome

void DelegatedFrameHost::BeginFrameSubscription(
    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
  frame_subscriber_ = subscriber.Pass();
}

Project: Chrome

bool DelegatedFrameHost::CanCopyToBitmap() const {
  return client_->GetCompositor() &&
         client_->GetLayer()->has_external_content();
}

Project: Chrome

bool DelegatedFrameHost::CanCopyToVideoFrame() const {
  return client_->GetCompositor() &&
         client_->GetLayer()->has_external_content();
}

Project: Chrome

bool DelegatedFrameHost::CanSubscribeFrame() const {
  return true;
}

Project: Chrome

void DelegatedFrameHost::CheckResizeLock() {
  if (!resize_lock_ ||
      resize_lock_->expected_size() != current_frame_size_in_dip_)
    return;

  resize_lock_->UnlockCompositor();
  ui::Compositor* compositor = client_->GetCompositor();
  if (compositor) {
    if (!compositor->HasObserver(this))
      compositor->AddObserver(this);
  }
}

Project: Chrome

void DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo(
    base::WeakPtr<DelegatedFrameHost> dfh,
    const base::Callback<void(bool)>& callback,
    scoped_refptr<OwnedMailbox> subscriber_texture,
    scoped_ptr<cc::SingleReleaseCallback> release_callback,
    bool result) {
  callback.Run(result);

  uint32 sync_point = 0;
  if (result) {
    GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
    sync_point = gl_helper->InsertSyncPoint();
  }
  if (release_callback) {
    DCHECK(!subscriber_texture);
    bool lost_resource = sync_point == 0;
    release_callback->Run(sync_point, lost_resource);
  }
  ReturnSubscriberTexture(dfh, subscriber_texture, sync_point);
}

Project: Chrome

void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
    base::WeakPtr<DelegatedFrameHost> dfh,
    scoped_refptr<OwnedMailbox> subscriber_texture,
    scoped_refptr<media::VideoFrame> video_frame,
    const base::Callback<void(bool)>& callback,
    scoped_ptr<cc::CopyOutputResult> result) {
  base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
  base::ScopedClosureRunner scoped_return_subscriber_texture(
      base::Bind(&ReturnSubscriberTexture, dfh, subscriber_texture, 0));

  if (!dfh)
    return;
  if (result->IsEmpty())
    return;
  if (result->size().IsEmpty())
    return;

  gfx::Rect region_in_frame =
      media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
                                    result->size());
  region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
                              region_in_frame.y() & ~1,
                              region_in_frame.width() & ~1,
                              region_in_frame.height() & ~1);
  if (region_in_frame.IsEmpty())
    return;

  if (!result->HasTexture()) {
    DCHECK(result->HasBitmap());
    scoped_ptr<SkBitmap> bitmap = result->TakeBitmap();
    SkBitmap scaled_bitmap;
    if (result->size().width() != region_in_frame.width() ||
        result->size().height() != region_in_frame.height()) {
      skia::ImageOperations::ResizeMethod method =
          skia::ImageOperations::RESIZE_GOOD;
      scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method,
                                                    region_in_frame.width(),
                                                    region_in_frame.height());
    } else {
      scaled_bitmap = *bitmap.get();
    }

    {
      SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);

      media::CopyRGBToVideoFrame(
          reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
          scaled_bitmap.rowBytes(),
          region_in_frame,
          video_frame.get());
    }
    ignore_result(scoped_callback_runner.Release());
    callback.Run(true);
    return;
  }

  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
  GLHelper* gl_helper = factory->GetGLHelper();
  if (!gl_helper)
    return;
  if (subscriber_texture.get() && !subscriber_texture->texture_id())
    return;

  cc::TextureMailbox texture_mailbox;
  scoped_ptr<cc::SingleReleaseCallback> release_callback;
  result->TakeTexture(&texture_mailbox, &release_callback);
  DCHECK(texture_mailbox.IsTexture());

  gfx::Rect result_rect(result->size());

  content::ReadbackYUVInterface* yuv_readback_pipeline =
      dfh->yuv_readback_pipeline_.get();
  if (yuv_readback_pipeline == NULL ||
      yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
      yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
      yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
    GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
    std::string quality_switch = switches::kTabCaptureDownscaleQuality;
    if (result_rect.size().width() < region_in_frame.size().width() &&
        result_rect.size().height() < region_in_frame.size().height())
      quality_switch = switches::kTabCaptureUpscaleQuality;

    std::string switch_value =
        CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
    if (switch_value == "fast")
      quality = GLHelper::SCALER_QUALITY_FAST;
    else if (switch_value == "good")
      quality = GLHelper::SCALER_QUALITY_GOOD;
    else if (switch_value == "best")
      quality = GLHelper::SCALER_QUALITY_BEST;

    dfh->yuv_readback_pipeline_.reset(
        gl_helper->CreateReadbackPipelineYUV(quality,
                                             result_rect.size(),
                                             result_rect,
                                             video_frame->coded_size(),
                                             region_in_frame,
                                             true,
                                             true));
    yuv_readback_pipeline = dfh->yuv_readback_pipeline_.get();
  }

  ignore_result(scoped_callback_runner.Release());
  ignore_result(scoped_return_subscriber_texture.Release());
  base::Callback<void(bool result)> finished_callback = base::Bind(
      &DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo,
      dfh->AsWeakPtr(),
      callback,
      subscriber_texture,
      base::Passed(&release_callback));
  yuv_readback_pipeline->ReadbackYUV(texture_mailbox.mailbox(),
                                     texture_mailbox.sync_point(),
                                     video_frame.get(),
                                     finished_callback);
}

Project: Chrome

void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame(
      const gfx::Rect& src_subrect,
      const scoped_refptr<media::VideoFrame>& target,
      const base::Callback<void(bool)>& callback) {
  if (!CanCopyToVideoFrame()) {
    callback.Run(false);
    return;
  }

  scoped_refptr<OwnedMailbox> subscriber_texture;
  if (frame_subscriber_) {
    if (!idle_frame_subscriber_textures_.empty()) {
      subscriber_texture = idle_frame_subscriber_textures_.back();
      idle_frame_subscriber_textures_.pop_back();
    } else if (GLHelper* helper =
                   ImageTransportFactory::GetInstance()->GetGLHelper()) {
      subscriber_texture = new OwnedMailbox(helper);
    }
  }

  scoped_ptr<cc::CopyOutputRequest> request =
      cc::CopyOutputRequest::CreateRequest(base::Bind(
          &DelegatedFrameHost::
               CopyFromCompositingSurfaceHasResultForVideo,
          AsWeakPtr(),  // For caching the ReadbackYUVInterface on this class.
          subscriber_texture,
          target,
          callback));
  gfx::Rect src_subrect_in_pixel =
      ConvertRectToPixel(client_->CurrentDeviceScaleFactor(), src_subrect);
  request->set_area(src_subrect_in_pixel);
  if (subscriber_texture.get()) {
    request->SetTextureMailbox(
        cc::TextureMailbox(subscriber_texture->mailbox(),
                           subscriber_texture->target(),
                           subscriber_texture->sync_point()));
  }
  client_->RequestCopyOfOutput(request.Pass());
}

Project: Chrome

DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client)
    : client_(client),
      use_surfaces_(base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kUseSurfaces)),
      last_output_surface_id_(0),
      pending_delegated_ack_count_(0),
      skipped_frames_(false),
      can_lock_compositor_(YES_CAN_LOCK),
      delegated_frame_evictor_(new DelegatedFrameEvictor(this)) {
  ImageTransportFactory::GetInstance()->AddObserver(this);
}

Project: Chrome

void DelegatedFrameHost::DidReceiveFrameFromRenderer() {
  if (frame_subscriber() && CanCopyToVideoFrame()) {
    const base::TimeTicks present_time = base::TimeTicks::Now();
    scoped_refptr<media::VideoFrame> frame;
    RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
    if (frame_subscriber()->ShouldCaptureFrame(present_time,
                                               &frame, &callback)) {
      CopyFromCompositingSurfaceToVideoFrame(
          gfx::Rect(current_frame_size_in_dip_),
          frame,
          base::Bind(callback, present_time));
    }
  }
}

Project: Chrome

void DelegatedFrameHost::EndFrameSubscription() {
  idle_frame_subscriber_textures_.clear();
  frame_subscriber_.reset();
}

Project: Chrome

void DelegatedFrameHost::EvictDelegatedFrame() {
  client_->GetLayer()->SetShowPaintedContent();
  frame_provider_ = NULL;
  if (!surface_id_.is_null()) {
    surface_factory_->Destroy(surface_id_);
    surface_id_ = cc::SurfaceId();
  }
  delegated_frame_evictor_->DiscardedFrame();
}

Project: Chrome

gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const {
  if (resize_lock_)
    return resize_lock_->expected_size();
  else
    return client_->DesiredFrameSize();
}

Project: Chrome

void DelegatedFrameHost::LockResources() {
  DCHECK(frame_provider_ || !surface_id_.is_null());
  delegated_frame_evictor_->LockFrame();
}

Project: Chrome

void DelegatedFrameHost::MaybeCreateResizeLock() {
  if (!client_->ShouldCreateResizeLock())
    return;
  DCHECK(client_->GetCompositor());

  ui::Compositor* compositor = client_->GetCompositor();
  if (!compositor->HasObserver(this))
    compositor->AddObserver(this);

  bool defer_compositor_lock =
      can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
      can_lock_compositor_ == NO_PENDING_COMMIT;

  if (can_lock_compositor_ == YES_CAN_LOCK)
    can_lock_compositor_ = YES_DID_LOCK;

  resize_lock_ = client_->CreateResizeLock(defer_compositor_lock);
}

Project: Chrome

void DelegatedFrameHost::OnCompositingAborted(ui::Compositor* compositor) {
}

Project: Chrome

void DelegatedFrameHost::OnCompositingDidCommit(
    ui::Compositor* compositor) {
  RenderWidgetHostImpl* host = client_->GetHost();
  if (can_lock_compositor_ == NO_PENDING_COMMIT) {
    can_lock_compositor_ = YES_CAN_LOCK;
    if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
      can_lock_compositor_ = YES_DID_LOCK;
  }
  RunOnCommitCallbacks();
  if (resize_lock_ &&
      resize_lock_->expected_size() == current_frame_size_in_dip_) {
    resize_lock_.reset();
    host->WasResized();
    MaybeCreateResizeLock();
  }
}

Project: Chrome

void DelegatedFrameHost::OnCompositingEnded(
    ui::Compositor* compositor) {
}

Project: Chrome

void DelegatedFrameHost::OnCompositingLockStateChanged(
    ui::Compositor* compositor) {
  if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
    can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
  }
}

Project: Chrome

void DelegatedFrameHost::OnCompositingStarted(
    ui::Compositor* compositor, base::TimeTicks start_time) {
  last_draw_ended_ = start_time;
}

Project: Chrome

void DelegatedFrameHost::OnLayerRecreated(ui::Layer* old_layer,
                                                ui::Layer* new_layer) {
  if (frame_provider_.get()) {
    new_layer->SetShowDelegatedContent(frame_provider_.get(),
                                       current_frame_size_in_dip_);
  }
  if (!surface_id_.is_null()) {
    new_layer->SetShowSurface(surface_id_, current_frame_size_in_dip_);
  }
}

Project: Chrome

void DelegatedFrameHost::OnLostResources() {
  RenderWidgetHostImpl* host = client_->GetHost();
  if (frame_provider_.get() || !surface_id_.is_null())
    EvictDelegatedFrame();
  idle_frame_subscriber_textures_.clear();
  yuv_readback_pipeline_.reset();

  host->ScheduleComposite();
}

Project: Chrome

void DelegatedFrameHost::OnUpdateVSyncParameters(
    base::TimeTicks timebase,
    base::TimeDelta interval) {
  RenderWidgetHostImpl* host = client_->GetHost();
  if (client_->IsVisible())
    host->UpdateVSyncParameters(timebase, interval);
}

Project: Chrome

void DelegatedFrameHost::PrepareBitmapCopyOutputResult(
    const gfx::Size& dst_size_in_pixel,
    const SkColorType color_type,
    const base::Callback<void(bool, const SkBitmap&)>& callback,
    scoped_ptr<cc::CopyOutputResult> result) {
  if (color_type != kN32_SkColorType) {
    NOTIMPLEMENTED();
    callback.Run(false, SkBitmap());
    return;
  }
  DCHECK(result->HasBitmap());
  scoped_ptr<SkBitmap> source = result->TakeBitmap();
  DCHECK(source);
  SkBitmap bitmap = skia::ImageOperations::Resize(
      *source,
      skia::ImageOperations::RESIZE_BEST,
      dst_size_in_pixel.width(),
      dst_size_in_pixel.height());
  callback.Run(true, bitmap);
}

Project: Chrome

void DelegatedFrameHost::RemovingFromWindow() {
  RunOnCommitCallbacks();
  resize_lock_.reset();
  client_->GetHost()->WasResized();
  ui::Compositor* compositor = client_->GetCompositor();
  if (compositor && compositor->HasObserver(this))
    compositor->RemoveObserver(this);

  if (vsync_manager_) {
    vsync_manager_->RemoveObserver(this);
    vsync_manager_ = NULL;
  }
}

Project: Chrome

void DelegatedFrameHostClient::RequestCopyOfOutput(
    scoped_ptr<cc::CopyOutputRequest> request) {
  GetDelegatedFrameHost()->RequestCopyOfOutput(request.Pass());
}

Project: Chrome

void DelegatedFrameHost::RequestCopyOfOutput(
    scoped_ptr<cc::CopyOutputRequest> request) {
  client_->GetLayer()->RequestCopyOfOutput(request.Pass());
}

Project: Chrome

void DelegatedFrameHost::ReturnResources(
    const cc::ReturnedResourceArray& resources) {
  if (resources.empty())
    return;
  std::copy(resources.begin(),
            resources.end(),
            std::back_inserter(surface_returned_resources_));
  if (!pending_delegated_ack_count_)
    SendReturnedDelegatedResources(last_output_surface_id_);
}

Project: Chrome

void DelegatedFrameHost::ReturnSubscriberTexture(
    base::WeakPtr<DelegatedFrameHost> dfh,
    scoped_refptr<OwnedMailbox> subscriber_texture,
    uint32 sync_point) {
  if (!subscriber_texture.get())
    return;
  if (!dfh)
    return;

  subscriber_texture->UpdateSyncPoint(sync_point);

  if (dfh->frame_subscriber_ && subscriber_texture->texture_id())
    dfh->idle_frame_subscriber_textures_.push_back(subscriber_texture);
}

Project: Chrome

void DelegatedFrameHost::RunOnCommitCallbacks() {
  for (std::vector<base::Closure>::const_iterator
      it = on_compositing_did_commit_callbacks_.begin();
      it != on_compositing_did_commit_callbacks_.end(); ++it) {
    it->Run();
  }
  on_compositing_did_commit_callbacks_.clear();
}

Project: Chrome

void DelegatedFrameHost::SendDelegatedFrameAck(uint32 output_surface_id) {
  RenderWidgetHostImpl* host = client_->GetHost();
  cc::CompositorFrameAck ack;
  if (!surface_returned_resources_.empty())
    ack.resources.swap(surface_returned_resources_);
  if (resource_collection_)
    resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
  RenderWidgetHostImpl::SendSwapCompositorFrameAck(host->GetRoutingID(),
                                                   output_surface_id,
                                                   host->GetProcess()->GetID(),
                                                   ack);
  DCHECK_GT(pending_delegated_ack_count_, 0);
  pending_delegated_ack_count_--;
}

Project: Chrome

void DelegatedFrameHost::SendReturnedDelegatedResources(
    uint32 output_surface_id) {
  RenderWidgetHostImpl* host = client_->GetHost();

  cc::CompositorFrameAck ack;
  if (!surface_returned_resources_.empty()) {
    ack.resources.swap(surface_returned_resources_);
  } else {
    DCHECK(resource_collection_);
    resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
  }
  DCHECK(!ack.resources.empty());

  RenderWidgetHostImpl::SendReclaimCompositorResources(
      host->GetRoutingID(),
      output_surface_id,
      host->GetProcess()->GetID(),
      ack);
}

Project: Chrome

bool DelegatedFrameHost::ShouldCreateResizeLock() {
  RenderWidgetHostImpl* host = client_->GetHost();

  if (resize_lock_)
    return false;

  if (host->should_auto_resize())
    return false;

  gfx::Size desired_size = client_->DesiredFrameSize();
  if (desired_size == current_frame_size_in_dip_ || desired_size.IsEmpty())
    return false;

  ui::Compositor* compositor = client_->GetCompositor();
  if (!compositor)
    return false;

  return true;
}

Project: Chrome

bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const {
  if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
      can_lock_compositor_ == NO_PENDING_COMMIT ||
      !resize_lock_.get())
    return false;

  return size_in_dip != resize_lock_->expected_size();
}

Project: Chrome

void DelegatedFrameHost::SwapDelegatedFrame(
    uint32 output_surface_id,
    scoped_ptr<cc::DelegatedFrameData> frame_data,
    float frame_device_scale_factor,
    const std::vector<ui::LatencyInfo>& latency_info) {
  RenderWidgetHostImpl* host = client_->GetHost();
  DCHECK(!frame_data->render_pass_list.empty());

  cc::RenderPass* root_pass = frame_data->render_pass_list.back();

  gfx::Size frame_size = root_pass->output_rect.size();
  gfx::Size frame_size_in_dip =
      ConvertSizeToDIP(frame_device_scale_factor, frame_size);

  gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
  damage_rect.Intersect(gfx::Rect(frame_size));
  gfx::Rect damage_rect_in_dip =
      ConvertRectToDIP(frame_device_scale_factor, damage_rect);

  if (ShouldSkipFrame(frame_size_in_dip)) {
    cc::CompositorFrameAck ack;
    cc::TransferableResource::ReturnResources(frame_data->resource_list,
                                              &ack.resources);

    skipped_latency_info_list_.insert(skipped_latency_info_list_.end(),
        latency_info.begin(), latency_info.end());

    RenderWidgetHostImpl::SendSwapCompositorFrameAck(
        host->GetRoutingID(), output_surface_id,
        host->GetProcess()->GetID(), ack);
    skipped_frames_ = true;
    return;
  }

  if (skipped_frames_) {
    skipped_frames_ = false;
    damage_rect = gfx::Rect(frame_size);
    damage_rect_in_dip = gfx::Rect(frame_size_in_dip);

    cc::RenderPass* root_pass = frame_data->render_pass_list.back();
    root_pass->damage_rect = damage_rect;
  }

  if (output_surface_id != last_output_surface_id_) {
    EvictDelegatedFrame();

    if (resource_collection_.get()) {
      resource_collection_->SetClient(NULL);

      if (resource_collection_->LoseAllResources())
        SendReturnedDelegatedResources(last_output_surface_id_);

      resource_collection_ = NULL;
    }
    last_output_surface_id_ = output_surface_id;
  }
  if (frame_size.IsEmpty()) {
    DCHECK(frame_data->resource_list.empty());
    EvictDelegatedFrame();
  } else {
    if (use_surfaces_) {
      if (!surface_factory_) {
        ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
        cc::SurfaceManager* manager = factory->GetSurfaceManager();
        id_allocator_ = factory->CreateSurfaceIdAllocator();
        surface_factory_ =
            make_scoped_ptr(new cc::SurfaceFactory(manager, this));
      }
      if (surface_id_.is_null() || frame_size != current_surface_size_ ||
          frame_size_in_dip != current_frame_size_in_dip_) {
        if (!surface_id_.is_null())
          surface_factory_->Destroy(surface_id_);
        surface_id_ = id_allocator_->GenerateId();
        surface_factory_->Create(surface_id_, frame_size);
        client_->GetLayer()->SetShowSurface(surface_id_, frame_size_in_dip);
        current_surface_size_ = frame_size;
      }
      scoped_ptr<cc::CompositorFrame> compositor_frame =
          make_scoped_ptr(new cc::CompositorFrame());
      compositor_frame->delegated_frame_data = frame_data.Pass();
      surface_factory_->SubmitFrame(surface_id_, compositor_frame.Pass());
    } else {
      if (!resource_collection_) {
        resource_collection_ = new cc::DelegatedFrameResourceCollection;
        resource_collection_->SetClient(this);
      }
      if (!frame_provider_.get() ||
          frame_size != frame_provider_->frame_size() ||
          frame_size_in_dip != current_frame_size_in_dip_) {
        frame_provider_ = new cc::DelegatedFrameProvider(
            resource_collection_.get(), frame_data.Pass());
        client_->GetLayer()->SetShowDelegatedContent(frame_provider_.get(),
                                                     frame_size_in_dip);
      } else {
        frame_provider_->SetFrameData(frame_data.Pass());
      }
    }
  }
  released_front_lock_ = NULL;
  current_frame_size_in_dip_ = frame_size_in_dip;
  CheckResizeLock();

  client_->SchedulePaintInRect(damage_rect_in_dip);

  pending_delegated_ack_count_++;

  ui::Compositor* compositor = client_->GetCompositor();
  if (!compositor) {
    SendDelegatedFrameAck(output_surface_id);
  } else {
    std::vector<ui::LatencyInfo>::const_iterator it;
    for (it = latency_info.begin(); it != latency_info.end(); ++it)
      compositor->SetLatencyInfo(*it);
    for (it = skipped_latency_info_list_.begin();
        it != skipped_latency_info_list_.end();
        ++it)
      compositor->SetLatencyInfo(*it);
    skipped_latency_info_list_.clear();
    AddOnCommitCallbackAndDisableLocks(
        base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
                   AsWeakPtr(),
                   output_surface_id));
  }
  DidReceiveFrameFromRenderer();
  if (frame_provider_.get() || !surface_id_.is_null())
    delegated_frame_evictor_->SwappedFrame(!host->is_hidden());
}

Project: Chrome

void DelegatedFrameHost::UnlockResources() {
  DCHECK(frame_provider_ || !surface_id_.is_null());
  delegated_frame_evictor_->UnlockFrame();
}

Project: Chrome

void DelegatedFrameHost::UnusedResourcesAreAvailable() {
  if (pending_delegated_ack_count_)
    return;

  SendReturnedDelegatedResources(last_output_surface_id_);
}

Project: Chrome

void DelegatedFrameHost::WasResized() {
  MaybeCreateResizeLock();
}

Project: Chrome

void DelegatedFrameHost::WasShown() {
  delegated_frame_evictor_->SetVisible(true);

  if (!released_front_lock_.get()) {
    ui::Compositor* compositor = client_->GetCompositor();
    if (compositor)
      released_front_lock_ = compositor->GetCompositorLock();
  }
}

Project: Chrome

DelegatedFrameHost::~DelegatedFrameHost() {
  ImageTransportFactory::GetInstance()->RemoveObserver(this);

  if (!surface_id_.is_null())
    surface_factory_->Destroy(surface_id_);
  if (resource_collection_.get())
    resource_collection_->SetClient(NULL);

  DCHECK(!vsync_manager_);
}