1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
media / base / android / media_service_throttler.h [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_ANDROID_MEDIA_SERVICE_THROTTLER_H_
#define MEDIA_BASE_ANDROID_MEDIA_SERVICE_THROTTLER_H_
#include <memory>
#include "base/cancelable_callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "media/base/media_export.h"
namespace media {
class MediaServerCrashListener;
// The MediaServiceThrottler's purpose is to prevent a compromised process from
// attempting to crash the MediaServer, by repeatedly requesting resources or
// issuing malformed requests. It is used to delay the creation of Android
// MediaServer clients (currently only the MediaPlayerBridge) by some amount
// that makes it impractical to DOS the MediaServer (by requesting the
// playback of hundreds of malformed URLs per second, for example).
//
// GetDelayForClientCreation() linearly spaces out client creations and
// guarantees that the clients will never be scheduled faster than some
// threshold (see the .cc file for the latest values).
// The MediaServiceThrottler also uses a MediaServerCrashListener to monitor for
// MediaServer crashes. The delay between client creations is exponentially
// increased (up to a cap) based on the number of recent MediaServer crashes.
//
// NOTE: The MediaServiceThrottler has small moving window that allows a certain
// number of clients to be immediately scheduled, while still respecting the
// max scheduling rates. This allows clients to be 'burst created' to account
// for a burst of requests from a new page load.
//
// For an example of usage, look at MediaPlayerRenderer::Initialize().
class MEDIA_EXPORT MediaServiceThrottler {
public:
// Called to get the singleton MediaServiceThrottler instance.
// The first thread on which GetInstance() is called is the thread on which
// calls to OnMediaServerCrash() will be signaled.
static MediaServiceThrottler* GetInstance();
MediaServiceThrottler(const MediaServiceThrottler&) = delete;
MediaServiceThrottler& operator=(const MediaServiceThrottler&) = delete;
// Returns the delay to wait until a new client is allowed to be created.
base::TimeDelta GetDelayForClientCreation();
// Test only methods.
void SetTickClockForTesting(const base::TickClock* clock);
void ResetInternalStateForTesting();
base::TimeDelta GetBaseThrottlingRateForTesting();
bool IsCrashListenerAliveForTesting();
void SetCrashListenerTaskRunnerForTesting(
scoped_refptr<base::SingleThreadTaskRunner> crash_listener_task_runner);
private:
friend class MediaServiceThrottlerTest;
MediaServiceThrottler();
virtual ~MediaServiceThrottler();
// Called by the |crash_listener_| whenever a crash is detected.
void OnMediaServerCrash(bool watchdog_needs_release);
// Updates |current_crashes_| according to a linear decay function.
void UpdateServerCrashes();
// Ensures that the MediaServerCrashListener was properly started (can lead
// to OnMediaServerCrash() being called in the case it hasn't).
void EnsureCrashListenerStarted();
// Frees up the resources used by |crash_listener_|;
void ReleaseCrashListener();
// Gets the delay for ScheduleClientCreation(), which grows exponentially
// based on |current_crashes_|.
base::TimeDelta GetThrottlingDelayFromServerCrashes();
raw_ptr<const base::TickClock> clock_;
// Effective number of media server crashes.
// NOTE: This is of type double because we decay the number of crashes at a
// rate of one per minute (e.g. 30s after a single crash, |current_crashes_|
// should be equal to 0.5).
double current_crashes_;
// Next time at which a client creation can be scheduled.
base::TimeTicks next_schedulable_slot_;
// Last media server crash time.
base::TimeTicks last_server_crash_;
// Last time UpdateServerCrashes() was called.
base::TimeTicks last_current_crash_update_time_;
// Last time ScheduleClientCreation() was called.
base::TimeTicks last_schedule_call_;
// Callbacks used to release |crash_listener_| after 60s of inactivity.
base::RepeatingClosure release_crash_listener_cb_;
base::CancelableRepeatingClosure cancelable_release_crash_listener_cb_;
// Listens for MediaServer crashes using a watchdog MediaPlayer.
std::unique_ptr<MediaServerCrashListener> crash_listener_;
scoped_refptr<base::SingleThreadTaskRunner> crash_listener_task_runner_;
};
} // namespace media
#endif // MEDIA_BASE_ANDROID_MEDIA_SERVICE_THROTTLER_H_