| Index: media/remoting/remoting_renderer_controller.cc
 | 
| diff --git a/media/remoting/remoting_renderer_controller.cc b/media/remoting/remoting_renderer_controller.cc
 | 
| deleted file mode 100644
 | 
| index 515e08298ccd8e502f3be587800605d144722036..0000000000000000000000000000000000000000
 | 
| --- a/media/remoting/remoting_renderer_controller.cc
 | 
| +++ /dev/null
 | 
| @@ -1,481 +0,0 @@
 | 
| -// Copyright 2016 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 "media/remoting/remoting_renderer_controller.h"
 | 
| -
 | 
| -#include "base/bind.h"
 | 
| -#include "base/logging.h"
 | 
| -#include "base/threading/thread_checker.h"
 | 
| -#include "base/time/time.h"
 | 
| -#include "media/remoting/remoting_cdm_context.h"
 | 
| -
 | 
| -namespace media {
 | 
| -
 | 
| -RemotingRendererController::RemotingRendererController(
 | 
| -    scoped_refptr<RemotingSourceImpl> remoting_source)
 | 
| -    : remoting_source_(remoting_source), weak_factory_(this) {
 | 
| -  remoting_source_->AddClient(this);
 | 
| -}
 | 
| -
 | 
| -RemotingRendererController::~RemotingRendererController() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  metrics_recorder_.WillStopSession(remoting::MEDIA_ELEMENT_DESTROYED);
 | 
| -  remoting_source_->RemoveClient(this);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnStarted(bool success) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  if (success) {
 | 
| -    VLOG(1) << "Remoting started successively.";
 | 
| -    if (remote_rendering_started_) {
 | 
| -      metrics_recorder_.DidStartSession();
 | 
| -      DCHECK(!switch_renderer_cb_.is_null());
 | 
| -      switch_renderer_cb_.Run();
 | 
| -    } else {
 | 
| -      remoting_source_->StopRemoting(this);
 | 
| -    }
 | 
| -  } else {
 | 
| -    VLOG(1) << "Failed to start remoting.";
 | 
| -    remote_rendering_started_ = false;
 | 
| -    metrics_recorder_.WillStopSession(remoting::START_RACE);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnSessionStateChanged() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  UpdateFromSessionState(remoting::SINK_AVAILABLE, remoting::ROUTE_TERMINATED);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::UpdateFromSessionState(
 | 
| -    remoting::StartTrigger start_trigger,
 | 
| -    remoting::StopTrigger stop_trigger) {
 | 
| -  VLOG(1) << "UpdateFromSessionState: " << remoting_source_->state();
 | 
| -  if (!sink_available_changed_cb_.is_null())
 | 
| -    sink_available_changed_cb_.Run(IsRemoteSinkAvailable());
 | 
| -
 | 
| -  UpdateInterstitial(base::nullopt);
 | 
| -  UpdateAndMaybeSwitch(start_trigger, stop_trigger);
 | 
| -}
 | 
| -
 | 
| -bool RemotingRendererController::IsRemoteSinkAvailable() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  switch (remoting_source_->state()) {
 | 
| -    case SESSION_CAN_START:
 | 
| -    case SESSION_STARTING:
 | 
| -    case SESSION_STARTED:
 | 
| -      return true;
 | 
| -    case SESSION_UNAVAILABLE:
 | 
| -    case SESSION_STOPPING:
 | 
| -    case SESSION_PERMANENTLY_STOPPED:
 | 
| -      return false;
 | 
| -  }
 | 
| -
 | 
| -  return false;  // To suppress compile warning.
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnEnteredFullscreen() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  is_fullscreen_ = true;
 | 
| -  // See notes in OnBecameDominantVisibleContent() for why this is forced:
 | 
| -  is_dominant_content_ = true;
 | 
| -  UpdateAndMaybeSwitch(remoting::ENTERED_FULLSCREEN,
 | 
| -                       remoting::UNKNOWN_STOP_TRIGGER);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnExitedFullscreen() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  is_fullscreen_ = false;
 | 
| -  // See notes in OnBecameDominantVisibleContent() for why this is forced:
 | 
| -  is_dominant_content_ = false;
 | 
| -  UpdateAndMaybeSwitch(remoting::UNKNOWN_START_TRIGGER,
 | 
| -                       remoting::EXITED_FULLSCREEN);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnBecameDominantVisibleContent(
 | 
| -    bool is_dominant) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  // Two scenarios where "dominance" status mixes with fullscreen transitions:
 | 
| -  //
 | 
| -  //   1. Just before/after entering fullscreen, the element will, of course,
 | 
| -  //      become the dominant on-screen content via automatic page layout.
 | 
| -  //   2. Just before/after exiting fullscreen, the element may or may not
 | 
| -  //      shrink in size enough to become non-dominant. However, exiting
 | 
| -  //      fullscreen was caused by a user action that explicitly indicates a
 | 
| -  //      desire to exit remoting, so even if the element is still dominant,
 | 
| -  //      remoting should be shut down.
 | 
| -  //
 | 
| -  // Thus, to achieve the desired behaviors, |is_dominant_content_| is force-set
 | 
| -  // in OnEnteredFullscreen() and OnExitedFullscreen(), and changes to it here
 | 
| -  // are ignored while in fullscreen.
 | 
| -  if (is_fullscreen_)
 | 
| -    return;
 | 
| -
 | 
| -  is_dominant_content_ = is_dominant;
 | 
| -  UpdateAndMaybeSwitch(remoting::BECAME_DOMINANT_CONTENT,
 | 
| -                       remoting::BECAME_AUXILIARY_CONTENT);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnSetCdm(CdmContext* cdm_context) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  auto* remoting_cdm_context = RemotingCdmContext::From(cdm_context);
 | 
| -  if (!remoting_cdm_context)
 | 
| -    return;
 | 
| -
 | 
| -  remoting_source_->RemoveClient(this);
 | 
| -  remoting_source_ = remoting_cdm_context->GetRemotingSource();
 | 
| -  remoting_source_->AddClient(this);
 | 
| -  UpdateFromSessionState(remoting::CDM_READY, remoting::DECRYPTION_ERROR);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnRemotePlaybackDisabled(bool disabled) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  is_remote_playback_disabled_ = disabled;
 | 
| -  metrics_recorder_.OnRemotePlaybackDisabled(disabled);
 | 
| -  UpdateAndMaybeSwitch(remoting::ENABLED_BY_PAGE, remoting::DISABLED_BY_PAGE);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnSetPoster(const GURL& poster_url) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  if (poster_url != poster_url_) {
 | 
| -    poster_url_ = poster_url;
 | 
| -    if (poster_url_.is_empty())
 | 
| -      UpdateInterstitial(SkBitmap());
 | 
| -    else
 | 
| -      DownloadPosterImage();
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::SetSwitchRendererCallback(
 | 
| -    const base::Closure& cb) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  DCHECK(!cb.is_null());
 | 
| -
 | 
| -  switch_renderer_cb_ = cb;
 | 
| -  // Note: Not calling UpdateAndMaybeSwitch() here since this method should be
 | 
| -  // called during the initialization phase of this RemotingRendererController;
 | 
| -  // and definitely before a whole lot of other things that are needed to
 | 
| -  // trigger a switch.
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::SetRemoteSinkAvailableChangedCallback(
 | 
| -    const base::Callback<void(bool)>& cb) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  sink_available_changed_cb_ = cb;
 | 
| -  if (!sink_available_changed_cb_.is_null())
 | 
| -    sink_available_changed_cb_.Run(IsRemoteSinkAvailable());
 | 
| -}
 | 
| -
 | 
| -base::WeakPtr<remoting::RpcBroker> RemotingRendererController::GetRpcBroker()
 | 
| -    const {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  return remoting_source_->GetRpcBroker()->GetWeakPtr();
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::StartDataPipe(
 | 
| -    std::unique_ptr<mojo::DataPipe> audio_data_pipe,
 | 
| -    std::unique_ptr<mojo::DataPipe> video_data_pipe,
 | 
| -    const RemotingSourceImpl::DataPipeStartCallback& done_callback) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  remoting_source_->StartDataPipe(std::move(audio_data_pipe),
 | 
| -                                  std::move(video_data_pipe), done_callback);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnMetadataChanged(
 | 
| -    const PipelineMetadata& metadata) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  const gfx::Size old_size = pipeline_metadata_.natural_size;
 | 
| -  const bool was_audio_codec_supported = has_audio() && IsAudioCodecSupported();
 | 
| -  const bool was_video_codec_supported = has_video() && IsVideoCodecSupported();
 | 
| -  pipeline_metadata_ = metadata;
 | 
| -  const bool is_audio_codec_supported = has_audio() && IsAudioCodecSupported();
 | 
| -  const bool is_video_codec_supported = has_video() && IsVideoCodecSupported();
 | 
| -  metrics_recorder_.OnPipelineMetadataChanged(metadata);
 | 
| -
 | 
| -  is_encrypted_ = false;
 | 
| -  if (has_video())
 | 
| -    is_encrypted_ |= metadata.video_decoder_config.is_encrypted();
 | 
| -  if (has_audio())
 | 
| -    is_encrypted_ |= metadata.audio_decoder_config.is_encrypted();
 | 
| -
 | 
| -  if (pipeline_metadata_.natural_size != old_size)
 | 
| -    UpdateInterstitial(base::nullopt);
 | 
| -
 | 
| -  remoting::StartTrigger start_trigger = remoting::UNKNOWN_START_TRIGGER;
 | 
| -  if (!was_audio_codec_supported && is_audio_codec_supported)
 | 
| -    start_trigger = remoting::SUPPORTED_AUDIO_CODEC;
 | 
| -  if (!was_video_codec_supported && is_video_codec_supported) {
 | 
| -    start_trigger = start_trigger == remoting::SUPPORTED_AUDIO_CODEC
 | 
| -                        ? remoting::SUPPORTED_AUDIO_AND_VIDEO_CODECS
 | 
| -                        : remoting::SUPPORTED_VIDEO_CODEC;
 | 
| -  }
 | 
| -  remoting::StopTrigger stop_trigger = remoting::UNKNOWN_STOP_TRIGGER;
 | 
| -  if (was_audio_codec_supported && !is_audio_codec_supported)
 | 
| -    stop_trigger = remoting::UNSUPPORTED_AUDIO_CODEC;
 | 
| -  if (was_video_codec_supported && !is_video_codec_supported) {
 | 
| -    stop_trigger = stop_trigger == remoting::UNSUPPORTED_AUDIO_CODEC
 | 
| -                       ? remoting::UNSUPPORTED_AUDIO_AND_VIDEO_CODECS
 | 
| -                       : remoting::UNSUPPORTED_VIDEO_CODEC;
 | 
| -  }
 | 
| -  UpdateAndMaybeSwitch(start_trigger, stop_trigger);
 | 
| -}
 | 
| -
 | 
| -bool RemotingRendererController::IsVideoCodecSupported() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  DCHECK(has_video());
 | 
| -
 | 
| -  switch (pipeline_metadata_.video_decoder_config.codec()) {
 | 
| -    case VideoCodec::kCodecH264:
 | 
| -    case VideoCodec::kCodecVP8:
 | 
| -      return true;
 | 
| -    default:
 | 
| -      VLOG(2) << "Remoting does not support video codec: "
 | 
| -              << pipeline_metadata_.video_decoder_config.codec();
 | 
| -      return false;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -bool RemotingRendererController::IsAudioCodecSupported() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  DCHECK(has_audio());
 | 
| -
 | 
| -  switch (pipeline_metadata_.audio_decoder_config.codec()) {
 | 
| -    case AudioCodec::kCodecAAC:
 | 
| -    case AudioCodec::kCodecMP3:
 | 
| -    case AudioCodec::kCodecPCM:
 | 
| -    case AudioCodec::kCodecVorbis:
 | 
| -    case AudioCodec::kCodecFLAC:
 | 
| -    case AudioCodec::kCodecAMR_NB:
 | 
| -    case AudioCodec::kCodecAMR_WB:
 | 
| -    case AudioCodec::kCodecPCM_MULAW:
 | 
| -    case AudioCodec::kCodecGSM_MS:
 | 
| -    case AudioCodec::kCodecPCM_S16BE:
 | 
| -    case AudioCodec::kCodecPCM_S24BE:
 | 
| -    case AudioCodec::kCodecOpus:
 | 
| -    case AudioCodec::kCodecEAC3:
 | 
| -    case AudioCodec::kCodecPCM_ALAW:
 | 
| -    case AudioCodec::kCodecALAC:
 | 
| -    case AudioCodec::kCodecAC3:
 | 
| -      return true;
 | 
| -    default:
 | 
| -      VLOG(2) << "Remoting does not support audio codec: "
 | 
| -              << pipeline_metadata_.audio_decoder_config.codec();
 | 
| -      return false;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnPlaying() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  is_paused_ = false;
 | 
| -  UpdateAndMaybeSwitch(remoting::PLAY_COMMAND, remoting::UNKNOWN_STOP_TRIGGER);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnPaused() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  is_paused_ = true;
 | 
| -}
 | 
| -
 | 
| -bool RemotingRendererController::ShouldBeRemoting() {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  if (switch_renderer_cb_.is_null()) {
 | 
| -    DCHECK(!remote_rendering_started_);
 | 
| -    return false;  // No way to switch to a RemotingRenderImpl.
 | 
| -  }
 | 
| -
 | 
| -  const RemotingSessionState state = remoting_source_->state();
 | 
| -  if (is_encrypted_) {
 | 
| -    // Due to technical limitations when playing encrypted content, once a
 | 
| -    // remoting session has been started, always return true here to indicate
 | 
| -    // that the RemotingRendererImpl should be used. In the stopped states,
 | 
| -    // RemotingRendererImpl will display an interstitial to notify the user that
 | 
| -    // local rendering cannot be resumed.
 | 
| -    //
 | 
| -    // TODO(miu): Revisit this once more of the encrypted-remoting impl is
 | 
| -    // in-place. For example, this will prevent metrics from recording session
 | 
| -    // stop reasons.
 | 
| -    return state == RemotingSessionState::SESSION_STARTED ||
 | 
| -           state == RemotingSessionState::SESSION_STOPPING ||
 | 
| -           state == RemotingSessionState::SESSION_PERMANENTLY_STOPPED;
 | 
| -  }
 | 
| -
 | 
| -  if (encountered_renderer_fatal_error_)
 | 
| -    return false;
 | 
| -
 | 
| -  switch (state) {
 | 
| -    case SESSION_UNAVAILABLE:
 | 
| -      return false;  // Cannot remote media without a remote sink.
 | 
| -    case SESSION_CAN_START:
 | 
| -    case SESSION_STARTING:
 | 
| -    case SESSION_STARTED:
 | 
| -      break;  // Media remoting is possible, assuming other requirments are met.
 | 
| -    case SESSION_STOPPING:
 | 
| -    case SESSION_PERMANENTLY_STOPPED:
 | 
| -      return false;  // Use local rendering after stopping remoting.
 | 
| -  }
 | 
| -
 | 
| -  switch (remoting_source_->sink_capabilities()) {
 | 
| -    case mojom::RemotingSinkCapabilities::NONE:
 | 
| -      return false;
 | 
| -    case mojom::RemotingSinkCapabilities::RENDERING_ONLY:
 | 
| -    case mojom::RemotingSinkCapabilities::CONTENT_DECRYPTION_AND_RENDERING:
 | 
| -      break;  // The sink is capable of remote rendering.
 | 
| -  }
 | 
| -
 | 
| -  if ((!has_audio() && !has_video()) ||
 | 
| -      (has_video() && !IsVideoCodecSupported()) ||
 | 
| -      (has_audio() && !IsAudioCodecSupported())) {
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  if (is_remote_playback_disabled_)
 | 
| -    return false;
 | 
| -
 | 
| -  // Normally, entering fullscreen or being the dominant visible content is the
 | 
| -  // signal that starts remote rendering. However, current technical limitations
 | 
| -  // require encrypted content be remoted without waiting for a user signal.
 | 
| -  return is_fullscreen_ || is_dominant_content_;
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::UpdateAndMaybeSwitch(
 | 
| -    remoting::StartTrigger start_trigger,
 | 
| -    remoting::StopTrigger stop_trigger) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  bool should_be_remoting = ShouldBeRemoting();
 | 
| -
 | 
| -  if (remote_rendering_started_ == should_be_remoting)
 | 
| -    return;
 | 
| -
 | 
| -  // Only switch to remoting when media is playing. Since the renderer is
 | 
| -  // created when video starts loading/playing, receiver will display a black
 | 
| -  // screen before video starts playing if switching to remoting when paused.
 | 
| -  // Thus, the user experience is improved by not starting remoting until
 | 
| -  // playback resumes.
 | 
| -  if (should_be_remoting && is_paused_)
 | 
| -    return;
 | 
| -
 | 
| -  // Switch between local renderer and remoting renderer.
 | 
| -  remote_rendering_started_ = should_be_remoting;
 | 
| -
 | 
| -  if (remote_rendering_started_) {
 | 
| -    DCHECK(!switch_renderer_cb_.is_null());
 | 
| -    if (remoting_source_->state() ==
 | 
| -        RemotingSessionState::SESSION_PERMANENTLY_STOPPED) {
 | 
| -      switch_renderer_cb_.Run();
 | 
| -      return;
 | 
| -    }
 | 
| -    DCHECK_NE(start_trigger, remoting::UNKNOWN_START_TRIGGER);
 | 
| -    metrics_recorder_.WillStartSession(start_trigger);
 | 
| -    // |switch_renderer_cb_.Run()| will be called after remoting is started
 | 
| -    // successfully.
 | 
| -    remoting_source_->StartRemoting(this);
 | 
| -  } else {
 | 
| -    // For encrypted content, it's only valid to switch to remoting renderer,
 | 
| -    // and never back to the local renderer. The RemotingCdmController will
 | 
| -    // force-stop the session when remoting has ended; so no need to call
 | 
| -    // StopRemoting() from here.
 | 
| -    DCHECK(!is_encrypted_);
 | 
| -    DCHECK_NE(stop_trigger, remoting::UNKNOWN_STOP_TRIGGER);
 | 
| -    metrics_recorder_.WillStopSession(stop_trigger);
 | 
| -    switch_renderer_cb_.Run();
 | 
| -    remoting_source_->StopRemoting(this);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::SetShowInterstitialCallback(
 | 
| -    const ShowInterstitialCallback& cb) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  show_interstitial_cb_ = cb;
 | 
| -  UpdateInterstitial(SkBitmap());
 | 
| -  if (!poster_url_.is_empty())
 | 
| -    DownloadPosterImage();
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::SetDownloadPosterCallback(
 | 
| -    const DownloadPosterCallback& cb) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  DCHECK(download_poster_cb_.is_null());
 | 
| -  download_poster_cb_ = cb;
 | 
| -  if (!poster_url_.is_empty())
 | 
| -    DownloadPosterImage();
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::UpdateInterstitial(
 | 
| -    const base::Optional<SkBitmap>& image) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -  if (show_interstitial_cb_.is_null() ||
 | 
| -      pipeline_metadata_.natural_size.IsEmpty())
 | 
| -    return;
 | 
| -
 | 
| -  RemotingInterstitialType type = RemotingInterstitialType::BETWEEN_SESSIONS;
 | 
| -  switch (remoting_source_->state()) {
 | 
| -    case SESSION_STARTED:
 | 
| -      type = RemotingInterstitialType::IN_SESSION;
 | 
| -      break;
 | 
| -    case SESSION_PERMANENTLY_STOPPED:
 | 
| -      type = RemotingInterstitialType::ENCRYPTED_MEDIA_FATAL_ERROR;
 | 
| -      break;
 | 
| -    case SESSION_UNAVAILABLE:
 | 
| -    case SESSION_CAN_START:
 | 
| -    case SESSION_STARTING:
 | 
| -    case SESSION_STOPPING:
 | 
| -      break;
 | 
| -  }
 | 
| -
 | 
| -  show_interstitial_cb_.Run(image, pipeline_metadata_.natural_size, type);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::DownloadPosterImage() {
 | 
| -  if (download_poster_cb_.is_null() || show_interstitial_cb_.is_null())
 | 
| -    return;
 | 
| -  DCHECK(!poster_url_.is_empty());
 | 
| -
 | 
| -  const base::TimeTicks download_start_time = base::TimeTicks::Now();
 | 
| -  download_poster_cb_.Run(
 | 
| -      poster_url_,
 | 
| -      base::Bind(&RemotingRendererController::OnPosterImageDownloaded,
 | 
| -                 weak_factory_.GetWeakPtr(), poster_url_, download_start_time));
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnPosterImageDownloaded(
 | 
| -    const GURL& download_url,
 | 
| -    base::TimeTicks download_start_time,
 | 
| -    const SkBitmap& image) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  metrics_recorder_.OnPosterImageDownloaded(
 | 
| -      base::TimeTicks::Now() - download_start_time, !image.drawsNothing());
 | 
| -  if (download_url != poster_url_)
 | 
| -    return;  // The poster image URL has changed during the download.
 | 
| -  UpdateInterstitial(image);
 | 
| -}
 | 
| -
 | 
| -void RemotingRendererController::OnRendererFatalError(
 | 
| -    remoting::StopTrigger stop_trigger) {
 | 
| -  DCHECK(thread_checker_.CalledOnValidThread());
 | 
| -
 | 
| -  // Do not act on errors caused by things like Mojo pipes being closed during
 | 
| -  // shutdown.
 | 
| -  if (!remote_rendering_started_)
 | 
| -    return;
 | 
| -
 | 
| -  encountered_renderer_fatal_error_ = true;
 | 
| -  UpdateAndMaybeSwitch(remoting::UNKNOWN_START_TRIGGER, stop_trigger);
 | 
| -}
 | 
| -
 | 
| -}  // namespace media
 | 
| 
 |