diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/chrome/renderer/lite_video | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/renderer/lite_video')
9 files changed, 644 insertions, 0 deletions
diff --git a/chromium/chrome/renderer/lite_video/DEPS b/chromium/chrome/renderer/lite_video/DEPS new file mode 100644 index 00000000000..6511c3d7aac --- /dev/null +++ b/chromium/chrome/renderer/lite_video/DEPS @@ -0,0 +1,3 @@ +include_rules = [ +"+services/network/test", +] diff --git a/chromium/chrome/renderer/lite_video/OWNERS b/chromium/chrome/renderer/lite_video/OWNERS new file mode 100644 index 00000000000..d5e2286a680 --- /dev/null +++ b/chromium/chrome/renderer/lite_video/OWNERS @@ -0,0 +1,3 @@ +file://components/data_reduction_proxy/OWNERS + +# COMPONENT: Internal>Network>DataUse diff --git a/chromium/chrome/renderer/lite_video/lite_video_hint_agent.cc b/chromium/chrome/renderer/lite_video/lite_video_hint_agent.cc new file mode 100644 index 00000000000..4f4840c349e --- /dev/null +++ b/chromium/chrome/renderer/lite_video/lite_video_hint_agent.cc @@ -0,0 +1,99 @@ +// Copyright 2020 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 "chrome/renderer/lite_video/lite_video_hint_agent.h" + +#include "base/metrics/histogram_macros.h" +#include "chrome/renderer/lite_video/lite_video_util.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +namespace lite_video { + +LiteVideoHintAgent::LiteVideoHintAgent(content::RenderFrame* render_frame) + : content::RenderFrameObserver(render_frame), + content::RenderFrameObserverTracker<LiteVideoHintAgent>(render_frame) { + DCHECK(render_frame); +} + +LiteVideoHintAgent::~LiteVideoHintAgent() = default; + +void LiteVideoHintAgent::OnDestruct() { + delete this; +} + +void LiteVideoHintAgent::AddThrottle(LiteVideoURLLoaderThrottle* throttle) { + DCHECK(HasLiteVideoHint()); + active_throttles_.insert(throttle); + UMA_HISTOGRAM_COUNTS("LiteVideo.HintAgent.ActiveThrottleSize", + active_throttles_.size()); +} + +void LiteVideoHintAgent::RemoveThrottle(LiteVideoURLLoaderThrottle* throttle) { + active_throttles_.erase(throttle); +} + +base::TimeDelta LiteVideoHintAgent::CalculateLatencyForResourceResponse( + const network::mojom::URLResponseHead& response_head) { + if (!HasLiteVideoHint()) + return base::TimeDelta(); + + int64_t recv_bytes = response_head.content_length; + if (recv_bytes == -1) + recv_bytes = response_head.encoded_body_length; + if (recv_bytes == -1) + return base::TimeDelta(); + + if (kilobytes_buffered_before_throttle_ < + *kilobytes_to_buffer_before_throttle_) { + kilobytes_buffered_before_throttle_ += recv_bytes / 1024; + return base::TimeDelta(); + } + + // The total RTT for this media response should be based on how much time it + // took to transfer the packet in the target bandwidth, and the per RTT + // latency. For example, assuming 100KBPS target bandwidth and target RTT of 1 + // second, an 400KB response should have total delay of 5 seconds + // (400/100 + 1). + auto delay_for_throttled_response = + base::TimeDelta::FromSecondsD( + recv_bytes / (*target_downlink_bandwidth_kbps_ * 1024.0)) + + *target_downlink_rtt_latency_; + auto response_delay = + response_head.response_time - response_head.request_time; + if (delay_for_throttled_response <= response_delay) + return base::TimeDelta(); + + return std::min(delay_for_throttled_response - response_delay, + *max_throttling_delay_); +} + +bool LiteVideoHintAgent::HasLiteVideoHint() const { + return target_downlink_bandwidth_kbps_ && target_downlink_rtt_latency_ && + kilobytes_to_buffer_before_throttle_ && max_throttling_delay_; +} + +void LiteVideoHintAgent::SetLiteVideoHint( + blink::mojom::LiteVideoHintPtr lite_video_hint) { + if (!lite_video_hint) + return; + target_downlink_bandwidth_kbps_ = + lite_video_hint->target_downlink_bandwidth_kbps; + kilobytes_to_buffer_before_throttle_ = + lite_video_hint->kilobytes_to_buffer_before_throttle; + target_downlink_rtt_latency_ = lite_video_hint->target_downlink_rtt_latency; + max_throttling_delay_ = lite_video_hint->max_throttling_delay; + LOCAL_HISTOGRAM_BOOLEAN("LiteVideo.HintAgent.HasHint", true); +} + +void LiteVideoHintAgent::StopThrottling() { + // TODO(rajendrant): Send the stop throttling signal to browser process, after + // some K rebuffer events had occurred. + DCHECK(HasLiteVideoHint()); + for (auto* throttle : active_throttles_) { + throttle->ResumeIfThrottled(); + } + kilobytes_buffered_before_throttle_ = 0; +} + +} // namespace lite_video diff --git a/chromium/chrome/renderer/lite_video/lite_video_hint_agent.h b/chromium/chrome/renderer/lite_video/lite_video_hint_agent.h new file mode 100644 index 00000000000..023150bb979 --- /dev/null +++ b/chromium/chrome/renderer/lite_video/lite_video_hint_agent.h @@ -0,0 +1,94 @@ +// Copyright 2020 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. + +#ifndef CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_HINT_AGENT_H_ +#define CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_HINT_AGENT_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "chrome/renderer/lite_video/lite_video_url_loader_throttle.h" +#include "content/public/renderer/render_frame_observer.h" +#include "content/public/renderer/render_frame_observer_tracker.h" +#include "third_party/blink/public/mojom/loader/previews_resource_loading_hints.mojom.h" +#include "url/gurl.h" + +namespace lite_video { + +// The renderer-side agent for LiteVideos. There is one instance per frame (main +// frame and subframes), to receive LiteVideo throttling parameters from +// browser. +class LiteVideoHintAgent + : public content::RenderFrameObserver, + public content::RenderFrameObserverTracker<LiteVideoHintAgent> { + public: + explicit LiteVideoHintAgent(content::RenderFrame* render_frame); + ~LiteVideoHintAgent() override; + + LiteVideoHintAgent(const LiteVideoHintAgent&) = delete; + LiteVideoHintAgent& operator=(const LiteVideoHintAgent&) = delete; + + // Returns how much time the media response should get throttled. This is the + // difference between the target latency based on target bandwidth, RTT, and + // the latency the response has already spent. Empty duration is returned when + // the response should not be throttled. The first + // |kilobytes_buffered_before_throttle_| for this render frame should not be + // throttled. This function also updates + // |kilobytes_buffered_before_throttle_|. + base::TimeDelta CalculateLatencyForResourceResponse( + const network::mojom::URLResponseHead& response_head); + + // Updates the LiteVideo throttling parameters for calculating + // the latency to add to media requests. + void SetLiteVideoHint(blink::mojom::LiteVideoHintPtr lite_video_hint); + + // Returns whether |this| has been provided a LiteVideoHint and + // has the parameters needed for calculating the throttling latency. + bool HasLiteVideoHint() const; + + void AddThrottle(LiteVideoURLLoaderThrottle* throttle); + void RemoveThrottle(LiteVideoURLLoaderThrottle* throttle); + + const std::set<LiteVideoURLLoaderThrottle*>& GetActiveThrottlesForTesting() + const { + return active_throttles_; + } + + // Stop throttling and resume the current throttled media requests + // immediately. Throttling could start again for new requests + void StopThrottling(); + + private: + friend class LiteVideoHintAgentTest; + + // content::RenderFrameObserver overrides + void OnDestruct() override; + + // The network downlink bandwidth target in kilobytes per second used to + // calculate the throttling delay on media requests + base::Optional<int> target_downlink_bandwidth_kbps_; + + // The network downlink rtt target latency used to calculate the + // throttling delay on media requests + base::Optional<base::TimeDelta> target_downlink_rtt_latency_; + + // The number of kilobytes for media to be observed before starting to + // throttle requests. + base::Optional<int> kilobytes_to_buffer_before_throttle_; + + // The maximum delay a throttle can introduce for a media request in + // milliseconds. + base::Optional<base::TimeDelta> max_throttling_delay_; + + // The number of media KB that have been left unthrottled before starting + // to introduce a throttling delay. + int kilobytes_buffered_before_throttle_ = 0; + + // Set of media requests that are throttled currently. These are maintained + // here to resume them immediately upon StopThrottling() + std::set<LiteVideoURLLoaderThrottle*> active_throttles_; +}; + +} // namespace lite_video + +#endif // CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_HINT_AGENT_H_ diff --git a/chromium/chrome/renderer/lite_video/lite_video_hint_agent_browsertest.cc b/chromium/chrome/renderer/lite_video/lite_video_hint_agent_browsertest.cc new file mode 100644 index 00000000000..b22f60d9b5d --- /dev/null +++ b/chromium/chrome/renderer/lite_video/lite_video_hint_agent_browsertest.cc @@ -0,0 +1,236 @@ +// Copyright 2020 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 "chrome/renderer/lite_video/lite_video_hint_agent.h" + +#include <memory> + +#include "base/macros.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/common/chrome_features.h" +#include "chrome/renderer/lite_video/lite_video_url_loader_throttle.h" +#include "chrome/test/base/chrome_render_view_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_view.h" +#include "services/network/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/web_network_state_notifier.h" + +namespace lite_video { + +namespace { +constexpr char kTestURL[] = "https://litevideo.test.com"; + +} + +// Encapsulates the media URLLoader throttle, its delegate, and maintains the +// current throttling state. +class MediaLoaderThrottleInfo : public blink::URLLoaderThrottle::Delegate { + public: + explicit MediaLoaderThrottleInfo( + std::unique_ptr<LiteVideoURLLoaderThrottle> throttle) + : throttle_(std::move(throttle)) { + throttle_->set_delegate(this); + } + + void SendResponse(network::mojom::URLResponseHead* response_head) { + throttle_->WillProcessResponse(GURL(kTestURL), response_head, + &is_throttled_); + } + + // Implements blink::URLLoaderThrottle::Delegate. + void CancelWithError(int error_code, + base::StringPiece custom_reason) override { + NOTIMPLEMENTED(); + } + void Resume() override { + ASSERT_TRUE(is_throttled_); + is_throttled_ = false; + } + + bool is_throttled() { return is_throttled_; } + + private: + // Current throttling state. + bool is_throttled_ = false; + + std::unique_ptr<LiteVideoURLLoaderThrottle> throttle_; +}; + +class LiteVideoHintAgentTest : public ChromeRenderViewTest { + public: + void DisableLiteVideoFeature() { + scoped_feature_list_.Reset(); + scoped_feature_list_.InitAndDisableFeature(features::kLiteVideo); + } + + std::unique_ptr<LiteVideoURLLoaderThrottle> CreateLiteVideoURLLoaderThrottle( + blink::mojom::RequestContextType request_context_type) { + blink::WebURLRequest request; + request.SetUrl(GURL(kTestURL)); + request.SetRequestContext(request_context_type); + return LiteVideoURLLoaderThrottle::MaybeCreateThrottle( + request, view_->GetMainRenderFrame()->GetRoutingID()); + } + + std::unique_ptr<MediaLoaderThrottleInfo> CreateThrottleAndSendResponse( + net::HttpStatusCode response_code, + const std::string& mime_type, + int content_length) { + auto throttle_info = std::make_unique<MediaLoaderThrottleInfo>( + CreateLiteVideoURLLoaderThrottle( + blink::mojom::RequestContextType::FETCH)); + network::mojom::URLResponseHeadPtr response_head = + network::CreateURLResponseHead(response_code); + response_head->mime_type = mime_type; + response_head->mime_type = mime_type; + response_head->content_length = content_length; + response_head->network_accessed = true; + response_head->was_fetched_via_cache = false; + + throttle_info->SendResponse(response_head.get()); + return throttle_info; + } + + const std::set<LiteVideoURLLoaderThrottle*>& GetActiveThrottledResponses() + const { + return lite_video_hint_agent_->GetActiveThrottlesForTesting(); + } + + const base::HistogramTester& histogram_tester() { return histogram_tester_; } + + void StopThrottling() { lite_video_hint_agent_->StopThrottling(); } + + protected: + void SetUp() override { + ChromeRenderViewTest::SetUp(); + scoped_feature_list_.InitAndEnableFeature(features::kLiteVideo); + blink::WebNetworkStateNotifier::SetSaveDataEnabled(true); + lite_video_hint_agent_ = + new LiteVideoHintAgent(view_->GetMainRenderFrame()); + + // Set some default hints. + blink::mojom::LiteVideoHintPtr hint = blink::mojom::LiteVideoHint::New(); + hint->kilobytes_to_buffer_before_throttle = 10; + hint->target_downlink_bandwidth_kbps = 60; + hint->target_downlink_rtt_latency = base::TimeDelta::FromMilliseconds(500); + hint->max_throttling_delay = base::TimeDelta::FromSeconds(5); + lite_video_hint_agent_->SetLiteVideoHint(std::move(hint)); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + base::HistogramTester histogram_tester_; + + // Owned by the RenderFrame. + LiteVideoHintAgent* lite_video_hint_agent_; +}; + +TEST_F(LiteVideoHintAgentTest, LiteVideoDisabled) { + DisableLiteVideoFeature(); + EXPECT_FALSE(CreateLiteVideoURLLoaderThrottle( + blink::mojom::RequestContextType::FETCH)); +} + +TEST_F(LiteVideoHintAgentTest, SaveDataDisabled) { + blink::WebNetworkStateNotifier::SetSaveDataEnabled(false); + EXPECT_FALSE(CreateLiteVideoURLLoaderThrottle( + blink::mojom::RequestContextType::FETCH)); +} + +TEST_F(LiteVideoHintAgentTest, OnlyFetchAPIResponseThrottled) { + EXPECT_FALSE(CreateLiteVideoURLLoaderThrottle( + blink::mojom::RequestContextType::IMAGE)); +} + +TEST_F(LiteVideoHintAgentTest, OnlyMediaMimeTypeThrottled) { + histogram_tester().ExpectUniqueSample("LiteVideo.HintAgent.HasHint", true, 1); + + auto throttle_info = + CreateThrottleAndSendResponse(net::HTTP_OK, "image/jpeg", 11000); + EXPECT_FALSE(throttle_info->is_throttled()); + + throttle_info = + CreateThrottleAndSendResponse(net::HTTP_OK, "image/jpeg", 11000); + EXPECT_FALSE(throttle_info->is_throttled()); + histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 0); +} + +TEST_F(LiteVideoHintAgentTest, FailedMediaResponseNotThrottled) { + histogram_tester().ExpectUniqueSample("LiteVideo.HintAgent.HasHint", true, 1); + + auto throttle_info = CreateThrottleAndSendResponse( + net::HTTP_INTERNAL_SERVER_ERROR, "video/mp4", 11000); + EXPECT_FALSE(throttle_info->is_throttled()); + + throttle_info = CreateThrottleAndSendResponse(net::HTTP_INTERNAL_SERVER_ERROR, + "video/mp4", 11000); + EXPECT_FALSE(throttle_info->is_throttled()); + histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 0); +} + +TEST_F(LiteVideoHintAgentTest, MediaResponseThrottled) { + histogram_tester().ExpectUniqueSample("LiteVideo.HintAgent.HasHint", true, 1); + + // Initial k media bytes will not be throttled. + auto throttle_info = + CreateThrottleAndSendResponse(net::HTTP_OK, "video/mp4", 11000); + EXPECT_FALSE(throttle_info->is_throttled()); + histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 0); + EXPECT_TRUE(GetActiveThrottledResponses().empty()); + + // Verify if a response gets throttled and eventually resumed. + throttle_info = + CreateThrottleAndSendResponse(net::HTTP_OK, "video/mp4", 440000); + histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 1); + EXPECT_TRUE(throttle_info->is_throttled()); + // This is to wait until the throttle resumes, cannot fast-forward in + // RenderViewTest. + while (throttle_info->is_throttled()) + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(throttle_info->is_throttled()); + + // Verify a response that wasn't yet resumed, gets cleared from hint agent + // when its destroyed. + throttle_info = + CreateThrottleAndSendResponse(net::HTTP_OK, "video/mp4", 440000); + EXPECT_TRUE(throttle_info->is_throttled()); + histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 2); + + EXPECT_FALSE(GetActiveThrottledResponses().empty()); + throttle_info.reset(); + EXPECT_TRUE(GetActiveThrottledResponses().empty()); +} + +TEST_F(LiteVideoHintAgentTest, StopThrottlingResumesResponsesImmediately) { + histogram_tester().ExpectUniqueSample("LiteVideo.HintAgent.HasHint", true, 1); + + // Initial response is not throttled, and the next two are throttled. + auto throttle_info1 = + CreateThrottleAndSendResponse(net::HTTP_OK, "video/mp4", 11000); + auto throttle_info2 = + CreateThrottleAndSendResponse(net::HTTP_OK, "video/mp4", 11000); + auto throttle_info3 = + CreateThrottleAndSendResponse(net::HTTP_OK, "video/mp4", 11000); + EXPECT_FALSE(throttle_info1->is_throttled()); + EXPECT_TRUE(throttle_info2->is_throttled()); + EXPECT_TRUE(throttle_info3->is_throttled()); + histogram_tester().ExpectTotalCount("LiteVideo.URLLoader.ThrottleLatency", 2); + EXPECT_EQ(2U, GetActiveThrottledResponses().size()); + + // Stop throttling will immediately resume. + StopThrottling(); + EXPECT_FALSE(throttle_info2->is_throttled()); + EXPECT_FALSE(throttle_info3->is_throttled()); + + // When the throttle destroys it should get removed from active throttles. + throttle_info2.reset(); + throttle_info3.reset(); + EXPECT_TRUE(GetActiveThrottledResponses().empty()); +} + +} // namespace lite_video diff --git a/chromium/chrome/renderer/lite_video/lite_video_url_loader_throttle.cc b/chromium/chrome/renderer/lite_video/lite_video_url_loader_throttle.cc new file mode 100644 index 00000000000..acde3638f64 --- /dev/null +++ b/chromium/chrome/renderer/lite_video/lite_video_url_loader_throttle.cc @@ -0,0 +1,121 @@ +// Copyright 2020 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 "chrome/renderer/lite_video/lite_video_url_loader_throttle.h" + +#include "base/metrics/histogram_macros.h" +#include "base/test/metrics/histogram_tester.h" +#include "chrome/renderer/lite_video/lite_video_hint_agent.h" +#include "chrome/renderer/lite_video/lite_video_util.h" +#include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_thread.h" +#include "services/network/public/mojom/url_response_head.mojom.h" + +namespace lite_video { + +LiteVideoHintAgent* GetLiteVideoHintAgent(int render_frame_id) { + DCHECK_NE(MSG_ROUTING_NONE, render_frame_id); + if (auto* render_frame = + content::RenderFrame::FromRoutingID(render_frame_id)) { + return LiteVideoHintAgent::Get(render_frame); + } + return nullptr; +} + +// static +std::unique_ptr<LiteVideoURLLoaderThrottle> +LiteVideoURLLoaderThrottle::MaybeCreateThrottle( + const blink::WebURLRequest& request, + int render_frame_id) { + auto request_context = request.GetRequestContext(); + if (request_context != blink::mojom::RequestContextType::FETCH && + request_context != blink::mojom::RequestContextType::XML_HTTP_REQUEST) { + return nullptr; + } + // TODO(rajendrant): Also allow the throttle to be stopped when LiteMode gets + // disabled or ECT worsens. This logic should probably be in the browser + // process. + if (!IsLiteVideoEnabled()) + return nullptr; + + auto* lite_video_hint_agent = GetLiteVideoHintAgent(render_frame_id); + if (lite_video_hint_agent && lite_video_hint_agent->HasLiteVideoHint()) + return std::make_unique<LiteVideoURLLoaderThrottle>(render_frame_id); + + return nullptr; +} + +LiteVideoURLLoaderThrottle::LiteVideoURLLoaderThrottle(int render_frame_id) + : render_frame_id_(render_frame_id) { + DCHECK(IsLiteVideoEnabled()); +} + +LiteVideoURLLoaderThrottle::~LiteVideoURLLoaderThrottle() { + // Existence of |response_delay_timer_| indicates throttling has been + // attempted on this media response. Remove the throttle on this case. + if (response_delay_timer_) { + DCHECK(render_frame_id_); + auto* lite_video_hint_agent = GetLiteVideoHintAgent(render_frame_id_); + if (lite_video_hint_agent) + lite_video_hint_agent->RemoveThrottle(this); + } +} + +void LiteVideoURLLoaderThrottle::WillProcessResponse( + const GURL& response_url, + network::mojom::URLResponseHead* response_head, + bool* defer) { + if (!response_head || !response_head->headers) + return; + // Do not throttle on 4xx, 5xx failures. + if (response_head->headers->response_code() != 200) + return; + if (!response_head->network_accessed || + response_head->was_fetched_via_cache) { + return; + } + if (!base::StartsWith(response_head->mime_type, "video/", + base::CompareCase::SENSITIVE)) { + return; + } + + auto* lite_video_hint_agent = GetLiteVideoHintAgent(render_frame_id_); + if (!lite_video_hint_agent) + return; + + auto latency = lite_video_hint_agent->CalculateLatencyForResourceResponse( + *response_head); + if (latency.is_zero()) + return; + + UMA_HISTOGRAM_TIMES("LiteVideo.URLLoader.ThrottleLatency", latency); + + *defer = true; + // The timer may have already started and running, and the below restart will + // lose that elapsed time. However the elapsed time will be small since this + // case happens if some other url loader throttle is restarting the request. + response_delay_timer_ = std::make_unique<base::OneShotTimer>(); + response_delay_timer_->Start( + FROM_HERE, latency, + base::BindOnce(&LiteVideoURLLoaderThrottle::ResumeThrottledMediaResponse, + base::Unretained(this))); + + lite_video_hint_agent->AddThrottle(this); +} + +void LiteVideoURLLoaderThrottle::ResumeIfThrottled() { + if (response_delay_timer_ && response_delay_timer_->IsRunning()) { + response_delay_timer_->Stop(); + ResumeThrottledMediaResponse(); + } +} + +void LiteVideoURLLoaderThrottle::ResumeThrottledMediaResponse() { + DCHECK(!response_delay_timer_->IsRunning()); + delegate_->Resume(); +} + +void LiteVideoURLLoaderThrottle::DetachFromCurrentSequence() {} + +} // namespace lite_video diff --git a/chromium/chrome/renderer/lite_video/lite_video_url_loader_throttle.h b/chromium/chrome/renderer/lite_video/lite_video_url_loader_throttle.h new file mode 100644 index 00000000000..ec353aa16c4 --- /dev/null +++ b/chromium/chrome/renderer/lite_video/lite_video_url_loader_throttle.h @@ -0,0 +1,56 @@ +// Copyright 2020 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. + +#ifndef CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_URL_LOADER_THROTTLE_H_ +#define CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_URL_LOADER_THROTTLE_H_ + +#include "base/callback.h" +#include "base/timer/timer.h" +#include "third_party/blink/public/common/loader/url_loader_throttle.h" + +namespace blink { +class WebURLRequest; +} // namespace blink + +namespace lite_video { + +// This class throttles media url requests that have audio/video mime-type in +// response headers, to simulate low bandwidth conditions. This allows MSE video +// players to adapt and play the lower resolution videos. +class LiteVideoURLLoaderThrottle : public blink::URLLoaderThrottle { + public: + explicit LiteVideoURLLoaderThrottle(int render_frame_id); + ~LiteVideoURLLoaderThrottle() override; + + // Creates throttle for |request| if LiteVideo is enabled for LiteMode users, + // and LiteVideoHintAgent has received hints for the navigation. Throttle will + // be created only for Fetch/XHR requests. + static std::unique_ptr<LiteVideoURLLoaderThrottle> MaybeCreateThrottle( + const blink::WebURLRequest& request, + int render_frame_id); + + // Resumes the media response if it was currently throttled. Otherwise its a + // no-op. + void ResumeIfThrottled(); + + // blink::URLLoaderThrottle: + void WillProcessResponse(const GURL& response_url, + network::mojom::URLResponseHead* response_head, + bool* defer) override; + void DetachFromCurrentSequence() override; + + private: + // Resumes the media response immediately. + void ResumeThrottledMediaResponse(); + + // Render frame id to get the media throttle observer of the render frame. + const int render_frame_id_; + + // Timer to introduce latency for the response. + std::unique_ptr<base::OneShotTimer> response_delay_timer_; +}; + +} // namespace lite_video + +#endif // CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_URL_LOADER_THROTTLE_H_ diff --git a/chromium/chrome/renderer/lite_video/lite_video_util.cc b/chromium/chrome/renderer/lite_video/lite_video_util.cc new file mode 100644 index 00000000000..69c483cb1a1 --- /dev/null +++ b/chromium/chrome/renderer/lite_video/lite_video_util.cc @@ -0,0 +1,17 @@ +// Copyright 2020 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 "chrome/renderer/lite_video/lite_video_util.h" + +#include "chrome/common/chrome_features.h" +#include "third_party/blink/public/platform/web_network_state_notifier.h" + +namespace lite_video { + +bool IsLiteVideoEnabled() { + return base::FeatureList::IsEnabled(features::kLiteVideo) && + blink::WebNetworkStateNotifier::SaveDataEnabled(); +} + +} // namespace lite_video diff --git a/chromium/chrome/renderer/lite_video/lite_video_util.h b/chromium/chrome/renderer/lite_video/lite_video_util.h new file mode 100644 index 00000000000..35c4603be9d --- /dev/null +++ b/chromium/chrome/renderer/lite_video/lite_video_util.h @@ -0,0 +1,15 @@ +// Copyright 2020 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. + +#ifndef CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_UTIL_H_ +#define CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_UTIL_H_ + +namespace lite_video { + +// Returns whether LiteVideo is enabled. +bool IsLiteVideoEnabled(); + +} // namespace lite_video + +#endif // CHROME_RENDERER_LITE_VIDEO_LITE_VIDEO_UTIL_H_ |