Commit message: None
CVE: CVE-2017-15389
CWE: CWE-20
Vulnerability description: An insufficient watchdog timer in navigation in Google Chrome prior to 62.0.3202.62 allowed a remote attacker to spoof the contents of the Omnibox (URL bar) via a crafted HTML page.

Project: Chrome

void DelegatedFrameHost::AttemptFrameSubscriberCapture(
    const gfx::Rect& damage_rect) {
  if (!frame_subscriber() || !CanCopyFromCompositingSurface())
    return;

  const base::TimeTicks now = tick_clock_->NowTicks();
  base::TimeTicks present_time;
  if (vsync_interval_ <= base::TimeDelta()) {
    present_time = now;
  } else {
    const int64_t intervals_elapsed = (now - vsync_timebase_) / vsync_interval_;
    present_time = vsync_timebase_ + (intervals_elapsed + 1) * vsync_interval_;
  }

  scoped_refptr<media::VideoFrame> frame;
  RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
  if (!frame_subscriber()->ShouldCaptureFrame(damage_rect, present_time, &frame,
                                              &callback))
    return;

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

  std::unique_ptr<viz::CopyOutputRequest> request =
      viz::CopyOutputRequest::CreateRequest(base::BindOnce(
          &DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
          AsWeakPtr(), subscriber_texture, frame,
          base::Bind(callback, present_time)));
  request->set_source(frame_subscriber()->GetSourceIdForCopyRequest());
  if (subscriber_texture.get()) {
    request->SetTextureMailbox(viz::TextureMailbox(
        subscriber_texture->mailbox(), subscriber_texture->sync_token(),
        subscriber_texture->target()));
  }

  if (has_frame_ && request_copy_of_output_callback_for_testing_.is_null()) {
    support_->RequestCopyOfSurface(std::move(request));
  } else {
    RequestCopyOfOutput(std::move(request));
  }
}

Project: Chrome

void DelegatedFrameHost::BeginFrameSubscription(
    std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
  frame_subscriber_ = std::move(subscriber);
}

Project: Chrome

bool DelegatedFrameHost::CanCopyFromCompositingSurface() const {
  return compositor_ &&
         client_->DelegatedFrameHostGetLayer()->has_external_content();
}

Project: Chrome

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

  resize_lock_->UnlockCompositor();
}

Project: Chrome

void DelegatedFrameHost::CopyFromCompositingSurface(
    const gfx::Rect& src_subrect,
    const gfx::Size& output_size,
    const ReadbackRequestCallback& callback,
    const SkColorType preferred_color_type) {
  bool format_support = ((preferred_color_type == kAlpha_8_SkColorType) ||
                         (preferred_color_type == kRGB_565_SkColorType) ||
                         (preferred_color_type == kN32_SkColorType));
  DCHECK(format_support);
  if (!CanCopyFromCompositingSurface()) {
    callback.Run(SkBitmap(), content::READBACK_SURFACE_UNAVAILABLE);
    return;
  }

  std::unique_ptr<viz::CopyOutputRequest> request =
      viz::CopyOutputRequest::CreateRequest(
          base::BindOnce(&CopyFromCompositingSurfaceHasResult, output_size,
                         preferred_color_type, callback));
  if (!src_subrect.IsEmpty())
    request->set_area(src_subrect);
  RequestCopyOfOutput(std::move(request));
}

Project: Chrome

void DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo(
    scoped_refptr<media::VideoFrame> video_frame,
    base::WeakPtr<DelegatedFrameHost> dfh,
    const base::Callback<void(bool)>& callback,
    scoped_refptr<OwnedMailbox> subscriber_texture,
    std::unique_ptr<viz::SingleReleaseCallback> release_callback,
    bool result) {
  callback.Run(result);

  gpu::SyncToken sync_token;
  if (result) {
    viz::GLHelper* gl_helper =
        ImageTransportFactory::GetInstance()->GetGLHelper();
    gl_helper->GenerateSyncToken(&sync_token);
  }
  if (release_callback) {
    DCHECK(!subscriber_texture.get());
    const bool lost_resource = !sync_token.HasData();
    release_callback->Run(sync_token, lost_resource);
  }
  ReturnSubscriberTexture(dfh, subscriber_texture, sync_token);
}

Project: Chrome

void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
    base::WeakPtr<DelegatedFrameHost> dfh,
    scoped_refptr<OwnedMailbox> subscriber_texture,
    scoped_refptr<media::VideoFrame> video_frame,
    const base::Callback<void(const gfx::Rect&, bool)>& callback,
    std::unique_ptr<viz::CopyOutputResult> result) {
  base::ScopedClosureRunner scoped_callback_runner(
      base::Bind(callback, gfx::Rect(), false));
  base::ScopedClosureRunner scoped_return_subscriber_texture(base::Bind(
      &ReturnSubscriberTexture, dfh, subscriber_texture, gpu::SyncToken()));

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

  gfx::Rect region_in_frame = media::ComputeLetterboxRegion(
      video_frame->visible_rect(), 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());
    std::unique_ptr<SkBitmap> bitmap = result->TakeBitmap();
    SkBitmap scaled_bitmap;
    if (result->size() != region_in_frame.size()) {
      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();
    }

    media::CopyRGBToVideoFrame(
        reinterpret_cast<uint8_t*>(scaled_bitmap.getPixels()),
        scaled_bitmap.rowBytes(), region_in_frame, video_frame.get());

    ignore_result(scoped_callback_runner.Release());
    callback.Run(region_in_frame, true);
    return;
  }

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

  viz::TextureMailbox texture_mailbox;
  std::unique_ptr<viz::SingleReleaseCallback> release_callback;
  result->TakeTexture(&texture_mailbox, &release_callback);
  DCHECK(texture_mailbox.IsTexture());

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

  viz::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()) {
    viz::GLHelper::ScalerQuality quality =
        ((result_rect.size().width() < region_in_frame.size().width()) &&
         (result_rect.size().height() < region_in_frame.size().height()))
            ? viz::GLHelper::SCALER_QUALITY_BEST
            : viz::GLHelper::SCALER_QUALITY_FAST;

    DVLOG(1) << "Re-creating YUV readback pipeline for source rect "
             << result_rect.ToString() << " and destination size "
             << region_in_frame.size().ToString();

    dfh->yuv_readback_pipeline_.reset(gl_helper->CreateReadbackPipelineYUV(
        quality, result_rect.size(), result_rect, region_in_frame.size(), 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,
      video_frame, dfh->AsWeakPtr(), base::Bind(callback, region_in_frame),
      subscriber_texture, base::Passed(&release_callback));
  yuv_readback_pipeline->ReadbackYUV(
      texture_mailbox.mailbox(), texture_mailbox.sync_token(),
      video_frame->visible_rect(),
      video_frame->stride(media::VideoFrame::kYPlane),
      video_frame->data(media::VideoFrame::kYPlane),
      video_frame->stride(media::VideoFrame::kUPlane),
      video_frame->data(media::VideoFrame::kUPlane),
      video_frame->stride(media::VideoFrame::kVPlane),
      video_frame->data(media::VideoFrame::kVPlane), region_in_frame.origin(),
      finished_callback);
  media::LetterboxYUV(video_frame.get(), region_in_frame);
}

Project: Chrome

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

  std::unique_ptr<viz::CopyOutputRequest> request =
      viz::CopyOutputRequest::CreateRequest(base::BindOnce(
          &DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
          AsWeakPtr(),  // For caching the ReadbackYUVInterface on this class.
          nullptr, std::move(target), callback));
  if (!src_subrect.IsEmpty())
    request->set_area(src_subrect);
  RequestCopyOfOutput(std::move(request));
}

Project: Chrome

void DelegatedFrameHost::CreateCompositorFrameSinkSupport() {
  DCHECK(!support_);
  constexpr bool is_root = false;
  constexpr bool needs_sync_points = true;
  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
  support_ = factory->GetContextFactoryPrivate()
                 ->GetHostFrameSinkManager()
                 ->CreateCompositorFrameSinkSupport(this, frame_sink_id_,
                                                    is_root, needs_sync_points);
  if (compositor_)
    compositor_->AddFrameSink(frame_sink_id_);
  if (needs_begin_frame_)
    support_->SetNeedsBeginFrame(true);
}

Project: Chrome

DelegatedFrameHost::DelegatedFrameHost(const viz::FrameSinkId& frame_sink_id,
                                       DelegatedFrameHostClient* client)
    : frame_sink_id_(frame_sink_id),
      client_(client),
      compositor_(nullptr),
      tick_clock_(new base::DefaultTickClock()),
      skipped_frames_(false),
      background_color_(SK_ColorRED),
      current_scale_factor_(1.f),
      frame_evictor_(new viz::FrameEvictor(this)) {
  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
  factory->GetContextFactory()->AddObserver(this);
  viz::HostFrameSinkManager* host_frame_sink_manager =
      factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
  host_frame_sink_manager->RegisterFrameSinkId(frame_sink_id_, this);
  CreateCompositorFrameSinkSupport();
}

Project: Chrome

void DelegatedFrameHost::EvictDelegatedFrame() {
  if (!has_frame_)
    return;
  client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent();
  support_->EvictCurrentSurface();
  has_frame_ = false;
  resize_lock_.reset();
  frame_evictor_->DiscardedFrame();
  UpdateGutters();
}

Project: Chrome

viz::FrameSinkId DelegatedFrameHost::GetFrameSinkId() {
  return frame_sink_id_;
}

Project: Chrome

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

Project: Chrome

bool DelegatedFrameHost::HasSavedFrame() {
  return frame_evictor_->HasFrame();
}

Project: Chrome

void DelegatedFrameHost::LockResources() {
  DCHECK(local_surface_id_.is_valid());
  frame_evictor_->LockFrame();
}

Project: Chrome

void DelegatedFrameHost::MaybeCreateResizeLock() {
  DCHECK(!resize_lock_);

  if (!compositor_)
    return;

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableResizeLock))
    return;

  if (!has_frame_)
    return;

  if (!client_->DelegatedFrameCanCreateResizeLock())
    return;

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

  resize_lock_ = client_->DelegatedFrameHostCreateResizeLock();
  bool locked = resize_lock_->Lock();
  DCHECK(locked);
}

Project: Chrome

void DelegatedFrameHost::OnBeginFrame(const viz::BeginFrameArgs& args) {
  if (renderer_compositor_frame_sink_)
    renderer_compositor_frame_sink_->OnBeginFrame(args);
  client_->OnBeginFrame();
}

Project: Chrome

void DelegatedFrameHost::OnCompositingLockStateChanged(
    ui::Compositor* compositor) {
  if (resize_lock_ && resize_lock_->timed_out()) {
    resize_lock_.reset();
    create_resize_lock_after_commit_ = true;
    allow_one_renderer_frame_during_resize_lock_ = true;
  }
}

Project: Chrome

void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) {
  DCHECK_EQ(compositor, compositor_);
  ResetCompositor();
  DCHECK(!compositor_);
}

Project: Chrome

void DelegatedFrameHost::OnFirstSurfaceActivation(
    const viz::SurfaceInfo& surface_info) {
}

Project: Chrome

void DelegatedFrameHost::OnLostResources() {
  EvictDelegatedFrame();
  idle_frame_subscriber_textures_.clear();
  yuv_readback_pipeline_.reset();
}

Project: Chrome

void DelegatedFrameHost::OnUpdateVSyncParameters(base::TimeTicks timebase,
                                                 base::TimeDelta interval) {
  vsync_timebase_ = timebase;
  vsync_interval_ = interval;
}

Project: Chrome

void DelegatedFrameHost::ReclaimResources(
    const std::vector<viz::ReturnedResource>& resources) {
  renderer_compositor_frame_sink_->ReclaimResources(resources);
}

Project: Chrome

void DelegatedFrameHost::RequestCopyOfOutput(
    std::unique_ptr<viz::CopyOutputRequest> request) {
  if (!request->has_area())
    request->set_area(gfx::Rect(current_frame_size_in_dip_));

  if (request_copy_of_output_callback_for_testing_.is_null()) {
    client_->DelegatedFrameHostGetLayer()->RequestCopyOfOutput(
        std::move(request));
  } else {
    request_copy_of_output_callback_for_testing_.Run(std::move(request));
  }
}

Project: Chrome

void DelegatedFrameHost::ResetCompositorFrameSinkSupport() {
  if (!support_)
    return;
  if (compositor_)
    compositor_->RemoveFrameSink(frame_sink_id_);
  support_.reset();
}

Project: Chrome

void DelegatedFrameHost::ReturnSubscriberTexture(
    base::WeakPtr<DelegatedFrameHost> dfh,
    scoped_refptr<OwnedMailbox> subscriber_texture,
    const gpu::SyncToken& sync_token) {
  if (!subscriber_texture.get())
    return;
  if (!dfh)
    return;

  subscriber_texture->UpdateSyncToken(sync_token);

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

Project: Chrome

void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) {
  DCHECK(!compositor_);
  if (!compositor)
    return;
  compositor_ = compositor;
  compositor_->AddObserver(this);
  DCHECK(!vsync_manager_.get());
  vsync_manager_ = compositor_->vsync_manager();
  vsync_manager_->AddObserver(this);

  compositor_->AddFrameSink(frame_sink_id_);
}

Project: Chrome

void DelegatedFrameHost::SetNeedsBeginFrames(bool needs_begin_frames) {
  needs_begin_frame_ = needs_begin_frames;
  support_->SetNeedsBeginFrame(needs_begin_frames);
}

Project: Chrome

void DelegatedFrameHost::SubmitCompositorFrame(
    const viz::LocalSurfaceId& local_surface_id,
    cc::CompositorFrame frame) {
#if defined(OS_CHROMEOS)
  DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled());
#endif
  float frame_device_scale_factor = frame.metadata.device_scale_factor;
  viz::BeginFrameAck ack(frame.metadata.begin_frame_ack);

  DCHECK(!frame.render_pass_list.empty());

  cc::RenderPass* root_pass = frame.render_pass_list.back().get();

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

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

  if (ShouldSkipFrame(frame_size_in_dip)) {
    std::vector<viz::ReturnedResource> resources =
        viz::TransferableResource::ReturnResources(frame.resource_list);

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

    renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(resources);

    skipped_frames_ = true;
    ack.has_damage = false;
    DidNotProduceFrame(ack);
    return;
  }

  allow_one_renderer_frame_during_resize_lock_ = false;

  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.render_pass_list.back().get();
    root_pass->damage_rect = damage_rect;
  }

  background_color_ = frame.metadata.root_background_color;

  if (frame_size.IsEmpty()) {
    DCHECK(frame.resource_list.empty());
    EvictDelegatedFrame();
  } else {
    ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
    viz::FrameSinkManagerImpl* manager =
        factory->GetContextFactoryPrivate()->GetFrameSinkManager();

    frame.metadata.latency_info.insert(frame.metadata.latency_info.end(),
                                       skipped_latency_info_list_.begin(),
                                       skipped_latency_info_list_.end());
    skipped_latency_info_list_.clear();

    bool result =
        support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
    DCHECK(result);

    if (local_surface_id != local_surface_id_ || !has_frame_) {
      viz::SurfaceId surface_id(frame_sink_id_, local_surface_id);
      viz::SurfaceInfo surface_info(surface_id, frame_device_scale_factor,
                                    frame_size);
      client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface(
          surface_info, manager->surface_manager()->reference_factory());
      client_->DelegatedFrameHostGetLayer()->SetFallbackSurface(surface_info);
      current_surface_size_ = frame_size;
      current_scale_factor_ = frame_device_scale_factor;
    }

    has_frame_ = true;
  }
  local_surface_id_ = local_surface_id;

  released_front_lock_ = NULL;
  current_frame_size_in_dip_ = frame_size_in_dip;
  CheckResizeLock();

  UpdateGutters();

  if (!damage_rect_in_dip.IsEmpty()) {
    client_->DelegatedFrameHostGetLayer()->OnDelegatedFrameDamage(
        damage_rect_in_dip);
  }

  if (has_frame_) {
    frame_evictor_->SwappedFrame(client_->DelegatedFrameHostIsVisible());
  }
 }

Project: Chrome

viz::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint(
    viz::SurfaceHittestDelegate* delegate,
    const gfx::Point& point,
    gfx::Point* transformed_point) {
  viz::SurfaceId surface_id(frame_sink_id_, local_surface_id_);
  if (!surface_id.is_valid())
    return surface_id;
  viz::SurfaceHittest hittest(delegate,
                              GetFrameSinkManager()->surface_manager());
  gfx::Transform target_transform;
  viz::SurfaceId target_local_surface_id =
      hittest.GetTargetSurfaceAtPoint(surface_id, point, &target_transform);
  *transformed_point = point;
  if (target_local_surface_id.is_valid())
    target_transform.TransformPoint(transformed_point);
  return target_local_surface_id;
}

Project: Chrome

bool DelegatedFrameHost::TransformPointToCoordSpaceForView(
    const gfx::Point& point,
    RenderWidgetHostViewBase* target_view,
    gfx::Point* transformed_point) {
  if (!has_frame_)
    return false;

  return target_view->TransformPointToLocalCoordSpace(
      point, viz::SurfaceId(frame_sink_id_, local_surface_id_),
      transformed_point);
}

Project: Chrome

bool DelegatedFrameHost::TransformPointToLocalCoordSpace(
    const gfx::Point& point,
    const viz::SurfaceId& original_surface,
    gfx::Point* transformed_point) {
  viz::SurfaceId surface_id(frame_sink_id_, local_surface_id_);
  if (!surface_id.is_valid())
    return false;
  *transformed_point = point;
  if (original_surface == surface_id)
    return true;

  viz::SurfaceHittest hittest(nullptr,
                              GetFrameSinkManager()->surface_manager());
  return hittest.TransformPointToTargetSurface(original_surface, surface_id,
                                               transformed_point);
}

Project: Chrome

void DelegatedFrameHost::UnlockResources() {
  DCHECK(local_surface_id_.is_valid());
  frame_evictor_->UnlockFrame();
}

Project: Chrome

void DelegatedFrameHost::WasHidden() {
  frame_evictor_->SetVisible(false);
  released_front_lock_ = NULL;
}

Project: Chrome

void DelegatedFrameHost::WasResized() {
  if (client_->DelegatedFrameHostDesiredSizeInDIP() !=
          current_frame_size_in_dip_ &&
      !client_->DelegatedFrameHostIsVisible())
    EvictDelegatedFrame();
  if (!resize_lock_ && !create_resize_lock_after_commit_)
    MaybeCreateResizeLock();
  UpdateGutters();
}

Project: Chrome

void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) {
  frame_evictor_->SetVisible(true);

  if (!has_frame_ && !released_front_lock_.get()) {
    if (compositor_)
      released_front_lock_ = compositor_->GetCompositorLock(nullptr);
  }

  if (compositor_) {
    compositor_->SetLatencyInfo(latency_info);
  }
}

Project: Chrome

void DelegatedFrameHost::WillDrawSurface(const viz::LocalSurfaceId& id,
                                         const gfx::Rect& damage_rect) {
  if (id != local_surface_id_)
    return;
  AttemptFrameSubscriberCapture(damage_rect);
}

Project: Chrome

DelegatedFrameHost::~DelegatedFrameHost() {
  DCHECK(!compositor_);
  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
  factory->GetContextFactory()->RemoveObserver(this);

  ResetCompositorFrameSinkSupport();

  viz::HostFrameSinkManager* host_frame_sink_manager =
      factory->GetContextFactoryPrivate()->GetHostFrameSinkManager();
  host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_);

  DCHECK(!vsync_manager_.get());
}