summaryrefslogtreecommitdiff
path: root/gfx/src/DriverCrashGuard.h
blob: 9a0c5851a205fb05e680aaf11ab53038a59e1d7a (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef gfx_src_DriverCrashGuard_h__
#define gfx_src_DriverCrashGuard_h__

#include "nsCOMPtr.h"
#include "nsIGfxInfo.h"
#include "nsIFile.h"
#include "nsString.h"
#include "mozilla/Function.h"
#include <string>

namespace mozilla {

namespace dom {
class ContentParent;
} // namespace dom

namespace gfx {

enum class DriverInitStatus
{
  // Drivers have not been initialized yet.
  Unknown,

  // We're attempting to initialize drivers.
  Attempting,

  // Drivers were successfully initialized last run.
  Okay,

  // We crashed during driver initialization, and have restarted.
  Crashed
};

enum class CrashGuardType : uint32_t
{
  D3D11Layers,
  D3D9Video,
  GLContext,
  D3D11Video,
  // Add new entries above this line, update the name array in
  // DriverCrashGuard.cpp, and make sure to add an entry in
  // ContentParent.cpp.

  NUM_TYPES
};

// DriverCrashGuard is used to detect crashes at graphics driver callsites.
// 
// If the graphics environment is unrecognized or has changed since the last
// session, the crash guard will activate and will detect any crashes within
// the scope of the guard object.
//
// If a callsite has a previously encountered crash, and the environment has
// not changed since the last session, then the guard will set a status flag
// indicating that the driver should not be used.
class DriverCrashGuard
{
public:
  DriverCrashGuard(CrashGuardType aType, dom::ContentParent* aContentParent);
  virtual ~DriverCrashGuard();

  bool Crashed();
  void NotifyCrashed();

  // These are the values reported to Telemetry (GRAPHICS_DRIVER_STARTUP_TEST).
  // Values should not change; add new values to the end.
  enum class TelemetryState {
    Okay = 0,
    EnvironmentChanged = 1,
    RecoveredFromCrash = 2,
    FeatureDisabled = 3
  };

  enum class Mode {
    // Normal operation.
    Normal,

    // Acting as a proxy between the parent and child process.
    Proxy
  };

  typedef mozilla::function<void(const char* aName, const char* aPrefName)>
    CrashGuardCallback;
  static void ForEachActiveCrashGuard(const CrashGuardCallback& aCallback);

protected:
  virtual void Initialize();
  virtual bool UpdateEnvironment() = 0;
  virtual void LogCrashRecovery() = 0;
  virtual void LogFeatureDisabled() = 0;

  // Helper functions.
  bool FeatureEnabled(int aFeature, bool aDefault=true);
  bool CheckAndUpdatePref(const char* aPrefName, const nsAString& aCurrentValue);
  bool CheckAndUpdateBoolPref(const char* aPrefName, bool aCurrentValue);
  std::string GetFullPrefName(const char* aPref);

private:
  // Either process.
  void InitializeIfNeeded();
  bool CheckOrRefreshEnvironment();
  bool UpdateBaseEnvironment();
  DriverInitStatus GetStatus() const;

  // Parent process only.
  nsCOMPtr<nsIFile> GetGuardFile();
  bool RecoverFromCrash();
  void ActivateGuard();
  void FlushPreferences();
  void SetStatus(DriverInitStatus aStatus);

private:
  CrashGuardType mType;
  Mode mMode;
  bool mInitialized;
  bool mGuardActivated;
  bool mCrashDetected;
  nsCOMPtr<nsIFile> mGuardFile;

protected:
  nsCString mStatusPref;
  nsCOMPtr<nsIGfxInfo> mGfxInfo;
};

class D3D11LayersCrashGuard final : public DriverCrashGuard
{
 public:
  explicit D3D11LayersCrashGuard(dom::ContentParent* aContentParent = nullptr);

 protected:
  void Initialize() override;
  bool UpdateEnvironment() override;
  void LogCrashRecovery() override;
  void LogFeatureDisabled() override;

 private:
  void RecordTelemetry(TelemetryState aState);
};

class D3D9VideoCrashGuard final : public DriverCrashGuard
{
 public:
  explicit D3D9VideoCrashGuard(dom::ContentParent* aContentParent = nullptr);

 protected:
  bool UpdateEnvironment() override;
  void LogCrashRecovery() override;
  void LogFeatureDisabled() override;
};

class D3D11VideoCrashGuard final : public DriverCrashGuard
{
 public:
  explicit D3D11VideoCrashGuard(dom::ContentParent* aContentParent = nullptr);

 protected:
  bool UpdateEnvironment() override;
  void LogCrashRecovery() override;
  void LogFeatureDisabled() override;
};

class GLContextCrashGuard final : public DriverCrashGuard
{
 public:
  explicit GLContextCrashGuard(dom::ContentParent* aContentParent = nullptr);
  void Initialize() override;

 protected:
  bool UpdateEnvironment() override;
  void LogCrashRecovery() override;
  void LogFeatureDisabled() override;
};

} // namespace gfx
} // namespace mozilla

#endif // gfx_src_DriverCrashGuard_h__