summaryrefslogtreecommitdiff
path: root/chromium/media/base/android/media_service_throttler.h
blob: 1bae14a7c47f46b23f1a7c2b1e2df0a2dcb2fbba (plain)
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
// 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/callback_forward.h"
#include "base/cancelable_callback.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_