Commit message: None
CVE: None
Vulnerability description: None

Project: Chrome

void HTMLMediaElement::ActivateViewportIntersectionMonitoring(bool activate) {
  if (activate && !viewport_intersection_observer_) {
    viewport_intersection_observer_ = IntersectionObserver::Create(
        {}, {kMostlyFillViewportThreshold}, &(GetDocument()),
        WTF::BindRepeating(&HTMLMediaElement::OnViewportIntersectionChanged,
                           WrapWeakPersistent(this)),
        IntersectionObserver::kFractionOfRoot);
    viewport_intersection_observer_->observe(this);
  } else if (!activate && viewport_intersection_observer_) {
    viewport_intersection_observer_->disconnect();
    viewport_intersection_observer_ = nullptr;
    mostly_filling_viewport_ = false;
  }
}

Project: Chrome

void HTMLMediaElement::AddPlayedRange(double start, double end) {
  BLINK_MEDIA_LOG << "addPlayedRange(" << (void*)this << ", " << start << ", "
                  << end << ")";
  if (!played_time_ranges_)
    played_time_ranges_ = TimeRanges::Create();
  played_time_ranges_->Add(start, end);
}

Project: Chrome

void HTMLMediaElement::AssertShadowRootChildren(ShadowRoot& shadow_root) {
#if DCHECK_IS_ON()
  unsigned number_of_children = shadow_root.CountChildren();
  DCHECK_LE(number_of_children, 3u);
  Node* first_child = shadow_root.firstChild();
  Node* last_child = shadow_root.lastChild();
  if (number_of_children == 1) {
    DCHECK(first_child->IsTextTrackContainer() ||
           first_child->IsMediaControls() ||
           first_child->IsMediaRemotingInterstitial() ||
           first_child->IsPictureInPictureInterstitial());
  } else if (number_of_children == 2) {
    DCHECK(first_child->IsTextTrackContainer() ||
           first_child->IsMediaRemotingInterstitial() ||
           first_child->IsPictureInPictureInterstitial());
    DCHECK(last_child->IsTextTrackContainer() || last_child->IsMediaControls());
    if (first_child->IsTextTrackContainer())
      DCHECK(last_child->IsMediaControls());
  } else if (number_of_children == 3) {
    Node* second_child = first_child->nextSibling();
    DCHECK(first_child->IsMediaRemotingInterstitial() ||
           first_child->IsPictureInPictureInterstitial());
    DCHECK(second_child->IsTextTrackContainer());
    DCHECK(last_child->IsMediaControls());
  }
#endif
}

Project: Chrome

void HTMLMediaElement::DidNotifySubtreeInsertionsToDocument() {
  UpdateControlsVisibility();
}

Project: Chrome

void HTMLMediaElement::ExecuteDeferredLoad() {
  DCHECK_GE(deferred_load_state_, kWaitingForTrigger);


  CancelDeferredLoad();
  SetShouldDelayLoadEvent(true);
  SetNetworkState(kNetworkLoading);

  StartProgressEventTimer();

  StartPlayerLoad();
}

Project: Chrome

bool HTMLMediaElement::HasNativeControls() {
  return ShouldShowControls(RecordMetricsBehavior::kDoRecord);
}

Project: Chrome

void HTMLMediaElement::MediaControlsDidBecomeVisible() {
  BLINK_MEDIA_LOG << "mediaControlsDidBecomeVisible(" << (void*)this << ")";

  if (IsHTMLVideoElement() && TextTracksVisible()) {
    EnsureTextTrackContainer().UpdateDisplay(
        *this, TextTrackContainer::kDidStartExposingControls);
  }
}

Project: Chrome

bool HTMLMediaElement::PotentiallyPlaying() const {
  bool paused_to_buffer =
      ready_state_maximum_ >= kHaveFutureData && ready_state_ < kHaveFutureData;
  return (paused_to_buffer || ready_state_ >= kHaveFutureData) &&
         CouldPlayIfEnoughData();
}

Project: Chrome

void HTMLMediaElement::RejectScheduledPlayPromises() {
  DCHECK(play_promise_error_code_ == DOMExceptionCode::kAbortError ||
         play_promise_error_code_ == DOMExceptionCode::kNotSupportedError);
  if (play_promise_error_code_ == DOMExceptionCode::kAbortError) {
    RecordPlayPromiseRejected(PlayPromiseRejectReason::kInterruptedByPause);
    RejectPlayPromisesInternal(DOMExceptionCode::kAbortError,
                               "The play() request was interrupted by a call "
                               "to pause(). https://goo.gl/LdLk22");
  } else {
    RecordPlayPromiseRejected(PlayPromiseRejectReason::kNoSupportedSources);
    RejectPlayPromisesInternal(
        DOMExceptionCode::kNotSupportedError,
        "Failed to load because no supported source was found.");
  }
}

Project: Chrome

void HTMLMediaElement::RemotePlaybackStarted() {
  if (RemotePlaybackClient())
    RemotePlaybackClient()->StateChanged(WebRemotePlaybackState::kConnected);
}

Project: Chrome

void HTMLMediaElement::SizeChanged() {
  BLINK_MEDIA_LOG << "sizeChanged(" << (void*)this << ")";

  DCHECK(HasVideo());  // "resize" makes no sense in absence of video.
  if (ready_state_ > kHaveNothing && IsHTMLVideoElement())
    ScheduleEvent(event_type_names::kResize);

  if (GetLayoutObject())
    GetLayoutObject()->UpdateFromElement();
}

Project: Chrome

bool HTMLMediaElement::SupportsSave() const {
  if (GetDocument().GetSettings() &&
      GetDocument().GetSettings()->GetHideDownloadUI()) {
    return false;
  }

  if (current_src_.IsNull() || current_src_.IsEmpty())
    return false;

  if (network_state_ == kNetworkEmpty || network_state_ == kNetworkNoSource)
    return false;

  if (current_src_.IsLocalFile())
    return false;

  if (GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream)
    return false;

  if (HasMediaSource())
    return false;

  if (IsHLSURL(current_src_))
    return false;

  if (duration() == std::numeric_limits<double>::infinity())
    return false;

  return true;
}

Project: Chrome

void HTMLMediaElement::AudioSourceProviderImpl::Trace(blink::Visitor* visitor) {
  visitor->Trace(client_);
}

Project: Chrome

void HTMLMediaElement::VideoWillBeDrawnToCanvas() const {
  DCHECK(IsHTMLVideoElement());
  UseCounter::Count(GetDocument(), WebFeature::kVideoInCanvas);
  autoplay_policy_->VideoWillBeDrawnToCanvas();
}

Project: Chrome

void HTMLMediaElement::AudioSourceProviderImpl::Wrap(
    WebAudioSourceProvider* provider) {
  MutexLocker locker(provide_input_lock);

  if (web_audio_source_provider_ && provider != web_audio_source_provider_)
    web_audio_source_provider_->SetClient(nullptr);

  web_audio_source_provider_ = provider;
  if (web_audio_source_provider_)
    web_audio_source_provider_->SetClient(client_.Get());
}

Project: Chrome

void HTMLMediaElement::setPlaybackRate(double rate,
                                       ExceptionState& exception_state) {
  BLINK_MEDIA_LOG << "setPlaybackRate(" << (void*)this << ", " << rate << ")";
  if (GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream)
    return;

  if (rate != 0.0 && (rate < kMinRate || rate > kMaxRate)) {
    UseCounter::Count(GetDocument(),
                      WebFeature::kHTMLMediaElementMediaPlaybackRateOutOfRange);

    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotSupportedError,
        "The provided playback rate (" + String::Number(rate) +
            ") is not in the " + "supported playback range.");

    return;
  }

  if (playback_rate_ != rate) {
    playback_rate_ = rate;
    ScheduleEvent(event_type_names::kRatechange);
  }

  UpdatePlaybackRate();
}

Project: Chrome

  ~AudioSourceProviderClientLockScope() {
    if (client_)
      client_->unlock();
  }

Project: Chrome

  void SetCurrentSrc(const AtomicString& src) {
    KURL url(src);
    Media()->current_src_ = url;
  }

Project: Chrome

Document* BaseAudioContext::GetDocument() const {
  return To<Document>(GetExecutionContext());
}

Project: Chrome

const SecurityOrigin* BaseAudioContext::GetSecurityOrigin() const {
  if (GetExecutionContext())
    return GetExecutionContext()->GetSecurityOrigin();

  return nullptr;
}

Project: Chrome

void BaseAudioContext::HandleDecodeAudioData(
    AudioBuffer* audio_buffer,
    ScriptPromiseResolver* resolver,
    V8PersistentCallbackFunction<V8DecodeSuccessCallback>* success_callback,
    V8PersistentCallbackFunction<V8DecodeErrorCallback>* error_callback) {
  DCHECK(IsMainThread());

  if (audio_buffer) {
    resolver->Resolve(audio_buffer);
    if (success_callback)
      success_callback->InvokeAndReportException(this, audio_buffer);
  } else {
    DOMException* error = DOMException::Create(DOMExceptionCode::kEncodingError,
                                               "Unable to decode audio data");
    resolver->Reject(error);
    if (error_callback)
      error_callback->InvokeAndReportException(this, error);
  }

  DCHECK(decode_audio_resolvers_.Contains(resolver));
  decode_audio_resolvers_.erase(resolver);
}

Project: Chrome

bool BaseAudioContext::HasPendingActivity() const {
  if (audioWorklet() && audioWorklet()->HasPendingTasks()) {
    return true;
  }

  return !is_cleared_;
}

Project: Chrome

void BaseAudioContext::NotifyWorkletIsReady() {
  DCHECK(IsMainThread());
  DCHECK(audioWorklet()->IsReady());

  {
    GraphAutoLocker locker(this);

    audio_worklet_thread_ =
        audioWorklet()->GetMessagingProxy()->GetBackingWorkerThread();
  }

  if (ContextState() != kClosed) {
    destination()->GetAudioDestinationHandler().RestartRendering();
  }
}

Project: Chrome

void BaseAudioContext::PerformCleanupOnMainThread() {
  DCHECK(IsMainThread());
  GraphAutoLocker locker(this);

  if (is_resolving_resume_promises_) {
    for (auto& resolver : resume_resolvers_) {
      if (context_state_ == kClosed) {
        resolver->Reject(DOMException::Create(
            DOMExceptionCode::kInvalidStateError,
            "Cannot resume a context that has been closed"));
      } else {
        SetContextState(kRunning);
        resolver->Resolve();
      }
    }
    resume_resolvers_.clear();
    is_resolving_resume_promises_ = false;
  }

  if (active_source_nodes_.size()) {
    for (AudioNode* node : active_source_nodes_) {
      if (node->Handler().GetNodeType() ==
          AudioHandler::kNodeTypeAudioBufferSource) {
        AudioBufferSourceNode* source_node =
            static_cast<AudioBufferSourceNode*>(node);
        source_node->GetAudioBufferSourceHandler().HandleStoppableSourceNode();
      }
    }

    Vector<AudioHandler*> finished_handlers;
    {
      MutexLocker lock(finished_source_handlers_mutex_);
      finished_source_handlers_.swap(finished_handlers);
    }
    wtf_size_t remove_count = 0;
    Vector<bool> removables;
    removables.resize(active_source_nodes_.size());
    for (AudioHandler* handler : finished_handlers) {
      for (wtf_size_t i = 0; i < active_source_nodes_.size(); ++i) {
        if (handler == &active_source_nodes_[i]->Handler()) {
          handler->BreakConnectionWithLock();
          removables[i] = true;
          remove_count++;
          break;
        }
      }
    }

    if (remove_count > 0) {
      HeapVector<Member<AudioNode>> actives;
      DCHECK_GE(active_source_nodes_.size(), remove_count);
      wtf_size_t initial_capacity =
          std::min(active_source_nodes_.size() - remove_count,
                   active_source_nodes_.size());
      actives.ReserveInitialCapacity(initial_capacity);
      for (wtf_size_t i = 0; i < removables.size(); ++i) {
        if (!removables[i])
          actives.push_back(active_source_nodes_[i]);
      }
      active_source_nodes_.swap(actives);
    }
  }

  has_posted_cleanup_task_ = false;
}

Project: Chrome

AnalyserNode* BaseAudioContext::createAnalyser(
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  return AnalyserNode::Create(*this, exception_state);
}

Project: Chrome

AudioBuffer* BaseAudioContext::createBuffer(uint32_t number_of_channels,
                                            uint32_t number_of_frames,
                                            float sample_rate,
                                            ExceptionState& exception_state) {

  AudioBuffer* buffer = AudioBuffer::Create(
      number_of_channels, number_of_frames, sample_rate, exception_state);

  if (buffer) {
    DEFINE_STATIC_LOCAL(SparseHistogram, audio_buffer_channels_histogram,
                        ("WebAudio.AudioBuffer.NumberOfChannels"));

    DEFINE_STATIC_LOCAL(CustomCountHistogram, audio_buffer_length_histogram,
                        ("WebAudio.AudioBuffer.Length", 1, 1000000, 50));
    DEFINE_STATIC_LOCAL(
        CustomCountHistogram, audio_buffer_sample_rate_histogram,
        ("WebAudio.AudioBuffer.SampleRate384kHz", 3000, 384000, 60));

    audio_buffer_channels_histogram.Sample(number_of_channels);
    audio_buffer_length_histogram.Count(number_of_frames);
    audio_buffer_sample_rate_histogram.Count(sample_rate);

    if (!IsContextClosed()) {
      DEFINE_STATIC_LOCAL(
          CustomCountHistogram, audio_buffer_sample_rate_ratio_histogram,
          ("WebAudio.AudioBuffer.SampleRateRatio384kHz", 1, 12800, 50));
      float ratio = 100 * sample_rate / this->sampleRate();
      audio_buffer_sample_rate_ratio_histogram.Count(
          static_cast<int>(0.5 + ratio));
    }
  }

  return buffer;
}

Project: Chrome

AudioBufferSourceNode* BaseAudioContext::createBufferSource(
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  AudioBufferSourceNode* node =
      AudioBufferSourceNode::Create(*this, exception_state);


  return node;
}

Project: Chrome

ChannelSplitterNode* BaseAudioContext::createChannelSplitter(
    uint32_t number_of_outputs,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  return ChannelSplitterNode::Create(*this, number_of_outputs, exception_state);
}

Project: Chrome

DelayNode* BaseAudioContext::createDelay(ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  return DelayNode::Create(*this, exception_state);
}

Project: Chrome

StereoPannerNode* BaseAudioContext::createStereoPanner(
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  return StereoPannerNode::Create(*this, exception_state);
}

Project: Chrome

void OfflineAudioDestinationHandler::Dispose() {
  Uninitialize();
  AudioDestinationHandler::Dispose();
}