From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Frazee <pfrazee@gmail.com>
Date: Sat, 6 Jun 2020 10:30:45 -0500
Subject: feat: add streaming-protocol registry to multibuffer_data_source

blink::WebMediaPlayerImpl - which provides the <video> and <audio> behaviors - needs to know
whether a data source will stream or fully buffer the response. It determines this behavior
with MultibufferDataSource::AssumeFullyBuffered() which has http/s hardwired. An incorrect
determination will cause the video/audio to fail playing.

This patch adds a list of "streaming protocols" to the MultibufferDataSource in order to allow
other protocols to register their streaming behavior. MultibufferDataSource::AssumeFullyBuffered()
then refers to the list so that it can correctly determine the data source's settings.

This patch also reverts https://chromium-review.googlesource.com/c/chromium/src/+/6431846,
which removed range-requests-supported on non-http protocols. See https://issues.chromium.org/issues/41161335
for more information.

diff --git a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
index 14eeb24b27ae9c3798fac7cfbb2ef53b85250dbe..dfcb69a1bf75af5e315e02702109b958fa8edfcf 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
+++ b/third_party/blink/renderer/platform/media/multi_buffer_data_source.cc
@@ -11,8 +11,10 @@
 #include "base/containers/adapters.h"
 #include "base/location.h"
 #include "base/memory/raw_ptr.h"
+#include "base/no_destructor.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/strings/string_util.h"
 #include "media/base/media_log.h"
 #include "net/base/net_errors.h"
 #include "third_party/blink/renderer/platform/media/buffered_data_source_host_impl.h"
@@ -69,6 +71,10 @@ constexpr base::TimeDelta kSeekDelay = base::Milliseconds(20);
 
 }  // namespace
 
+void AddStreamingScheme(const char* new_scheme) {
+  MultiBufferDataSource::GetStreamingSchemes()->push_back(new_scheme);
+}
+
 class MultiBufferDataSource::ReadOperation {
  public:
   ReadOperation() = delete;
@@ -143,13 +149,29 @@ MultiBufferDataSource::~MultiBufferDataSource() {
   DCHECK(render_task_runner_->BelongsToCurrentThread());
 }
 
+// static
+std::vector<std::string>* MultiBufferDataSource::GetStreamingSchemes() {
+  static base::NoDestructor<std::vector<std::string>> streaming_schemes({
+    url::kHttpsScheme,
+    url::kHttpScheme
+  });
+  return streaming_schemes.get();
+}
+
 bool MultiBufferDataSource::media_has_played() const {
   return media_has_played_;
 }
 
 bool MultiBufferDataSource::AssumeFullyBuffered() const {
   DCHECK(url_data_);
-  return !url_data_->url().ProtocolIsInHTTPFamily();
+
+  const std::string scheme = url_data_->url().Protocol().Ascii();
+  for (const std::string& streaming_scheme : *GetStreamingSchemes()) {
+    if (base::EqualsCaseInsensitiveASCII(scheme, streaming_scheme)) {
+      return false;
+    }
+  }
+  return true;
 }
 
 void MultiBufferDataSource::SetReader(
diff --git a/third_party/blink/renderer/platform/media/multi_buffer_data_source.h b/third_party/blink/renderer/platform/media/multi_buffer_data_source.h
index 8c92f1c0c5028069cdad967b5be2bccf8005ed43..8b49dc182296f7f277981aed29b58947fb0980cb 100644
--- a/third_party/blink/renderer/platform/media/multi_buffer_data_source.h
+++ b/third_party/blink/renderer/platform/media/multi_buffer_data_source.h
@@ -17,6 +17,7 @@
 #include "media/base/data_source.h"
 #include "media/base/ranges.h"
 #include "media/base/tuneable.h"
+#include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/renderer/platform/media/url_index.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -34,6 +35,8 @@ namespace blink {
 class BufferedDataSourceHost;
 class MultiBufferReader;
 
+void BLINK_PLATFORM_EXPORT AddStreamingScheme(const char* new_scheme);
+
 // A data source capable of loading URLs and buffering the data using an
 // in-memory sliding window.
 //
@@ -63,6 +66,8 @@ class PLATFORM_EXPORT MultiBufferDataSource
     return url_data_->mime_type();
   }
 
+  static std::vector<std::string>* GetStreamingSchemes();
+
   // Method called on the render thread.
   using InitializeCB = base::OnceCallback<void(bool)>;
   void Initialize(InitializeCB init_cb) override;
diff --git a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
index 1fdc54c1de28ef0c32fc9a386097d95b48aedcaa..5822251daaa9fa5a49ace1bdad684e0076c225dc 100644
--- a/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
+++ b/third_party/blink/renderer/platform/media/resource_multi_buffer_data_provider.cc
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <utility>
+#include <algorithm>
 
 #include "base/containers/contains.h"
 #include "base/location.h"
@@ -30,6 +31,7 @@
 #include "third_party/blink/public/platform/web_url_response.h"
 #include "third_party/blink/public/web/web_associated_url_loader.h"
 #include "third_party/blink/renderer/platform/media/cache_util.h"
+#include "third_party/blink/renderer/platform/media/multi_buffer_data_source.h"
 #include "third_party/blink/renderer/platform/media/resource_fetch_context.h"
 #include "third_party/blink/renderer/platform/media/url_index.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -313,6 +315,16 @@ void ResourceMultiBufferDataProvider::DidReceiveResponse(
       do_fail = true;
     }
   } else {
+    // For non-HTTP protocols, only set range_supported for registered streaming schemes
+    const std::string scheme = destination_url_data->url().Protocol().Ascii();
+
+    if (std::ranges::any_of(*MultiBufferDataSource::GetStreamingSchemes(),
+                         [&scheme](const std::string& streaming_scheme) {
+                           return base::EqualsCaseInsensitiveASCII(scheme, streaming_scheme);
+                         })) {
+      destination_url_data->set_range_supported();
+    }
+
     if (content_length != kPositionNotSpecified) {
       destination_url_data->set_length(content_length + byte_pos());
     }
