Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/places/Shutdown.h
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#ifndef mozilla_places_Shutdown_h_
6
#define mozilla_places_Shutdown_h_
7
8
#include "nsIAsyncShutdown.h"
9
#include "Database.h"
10
#include "nsProxyRelease.h"
11
12
namespace mozilla {
13
namespace places {
14
15
class Database;
16
17
/**
18
 * This is most of the code responsible for Places shutdown.
19
 *
20
 * PHASE 1 (Legacy clients shutdown)
21
 * The shutdown procedure begins when the Database singleton receives
22
 * profile-change-teardown (note that tests will instead notify nsNavHistory,
23
 * that forwards the notification to the Database instance).
24
 * Database::Observe first of all checks if initialization was completed
25
 * properly, to avoid race conditions, then it notifies "places-shutdown" to
26
 * legacy clients. Legacy clients are supposed to start and complete any
27
 * shutdown critical work in the same tick, since we won't wait for them.
28
29
 * PHASE 2 (Modern clients shutdown)
30
 * Modern clients should instead register as a blocker by passing a promise to
31
 * nsINavHistoryService::shutdownClient (for example see Sanitizer.jsm), so they
32
 * block Places shutdown until the promise is resolved.
33
 * When profile-change-teardown is observed by async shutdown, it calls
34
 * ClientsShutdownBlocker::BlockShutdown. This class is registered as a teardown
35
 * phase blocker in Database::Init (see Database::mClientsShutdown).
36
 * ClientsShutdownBlocker::BlockShudown waits for all the clients registered
37
 * through nsINavHistoryService::shutdownClient. When all the clients are done,
38
 * its `Done` method is invoked, and it stops blocking the shutdown phase, so
39
 * that it can continue.
40
 *
41
 * PHASE 3 (Connection shutdown)
42
 * ConnectionBlocker is registered as a profile-before-change blocker in
43
 * Database::Init (see Database::mConnectionShutdown).
44
 * When profile-before-change is observer by async shutdown, it calls
45
 * ConnectionShutdownBlocker::BlockShutdown.
46
 * Then the control is passed to Database::Shutdown, that executes some sanity
47
 * checks, clears cached statements and proceeds with asyncClose.
48
 * Once the connection is definitely closed, Database will call back
49
 * ConnectionBlocker::Complete. At this point a final
50
 * places-connection-closed notification is sent, for testing purposes.
51
 */
52
53
/**
54
 * A base AsyncShutdown blocker in charge of shutting down Places.
55
 */
56
class PlacesShutdownBlocker : public nsIAsyncShutdownBlocker
57
                            , public nsIAsyncShutdownCompletionCallback
58
{
59
public:
60
  NS_DECL_THREADSAFE_ISUPPORTS
61
  NS_DECL_NSIASYNCSHUTDOWNBLOCKER
62
  NS_DECL_NSIASYNCSHUTDOWNCOMPLETIONCALLBACK
63
64
  explicit PlacesShutdownBlocker(const nsString& aName);
65
66
  already_AddRefed<nsIAsyncShutdownClient> GetClient();
67
68
  /**
69
   * `true` if we have not started shutdown, i.e.  if
70
   * `BlockShutdown()` hasn't been called yet, false otherwise.
71
   */
72
  static bool IsStarted() {
73
    return sIsStarted;
74
  }
75
76
  // The current state, used internally and for forensics/debugging purposes.
77
  // Not all the states make sense for all the derived classes.
78
  enum States {
79
    NOT_STARTED,
80
    // Execution of `BlockShutdown` in progress.
81
    RECEIVED_BLOCK_SHUTDOWN,
82
83
    // Values specific to ClientsShutdownBlocker
84
    // a. Set while we are waiting for clients to do their job and unblock us.
85
    CALLED_WAIT_CLIENTS,
86
    // b. Set when all the clients are done.
87
    RECEIVED_DONE,
88
89
    // Values specific to ConnectionShutdownBlocker
90
    // a. Set after we notified observers that Places is closing the connection.
91
    NOTIFIED_OBSERVERS_PLACES_WILL_CLOSE_CONNECTION,
92
    // b. Set after we pass control to Database::Shutdown, and wait for it to
93
    // close the connection and call our `Complete` method when done.
94
    CALLED_STORAGESHUTDOWN,
95
    // c. Set when Database has closed the connection and passed control to
96
    // us through `Complete`.
97
    RECEIVED_STORAGESHUTDOWN_COMPLETE,
98
    // d. We have notified observers that Places has closed the connection.
99
    NOTIFIED_OBSERVERS_PLACES_CONNECTION_CLOSED,
100
  };
101
  States State() {
102
    return mState;
103
  }
104
105
protected:
106
  // The blocker name, also used as barrier name.
107
  nsString mName;
108
  // The current state, see States.
109
  States mState;
110
  // The barrier optionally used to wait for clients.
111
  nsMainThreadPtrHandle<nsIAsyncShutdownBarrier> mBarrier;
112
  // The parent object who registered this as a blocker.
113
  nsMainThreadPtrHandle<nsIAsyncShutdownClient> mParentClient;
114
115
  // As tests may resurrect a dead `Database`, we use a counter to
116
  // give the instances of `PlacesShutdownBlocker` unique names.
117
  uint16_t mCounter;
118
  static uint16_t sCounter;
119
120
  static Atomic<bool> sIsStarted;
121
122
  virtual ~PlacesShutdownBlocker() {}
123
};
124
125
/**
126
 * Blocker also used to wait for clients, through an owned barrier.
127
 */
128
class ClientsShutdownBlocker final : public PlacesShutdownBlocker
129
{
130
public:
131
  NS_INLINE_DECL_REFCOUNTING_INHERITED(ClientsShutdownBlocker,
132
               PlacesShutdownBlocker)
133
134
  explicit ClientsShutdownBlocker();
135
136
  NS_IMETHOD Done() override;
137
private:
138
0
  ~ClientsShutdownBlocker() {}
139
};
140
141
/**
142
 * Blocker used to wait when closing the database connection.
143
 */
144
class ConnectionShutdownBlocker final : public PlacesShutdownBlocker
145
                                      , public mozIStorageCompletionCallback
146
{
147
public:
148
  NS_DECL_ISUPPORTS_INHERITED
149
  NS_DECL_MOZISTORAGECOMPLETIONCALLBACK
150
151
  explicit ConnectionShutdownBlocker(mozilla::places::Database* aDatabase);
152
153
  NS_IMETHOD Done() override;
154
155
private:
156
  ~ConnectionShutdownBlocker() {}
157
158
  // The owning database.
159
  // The cycle is broken in method Complete(), once the connection
160
  // has been closed by mozStorage.
161
  RefPtr<mozilla::places::Database> mDatabase;
162
};
163
164
} // namespace places
165
} // namespace mozilla
166
167
#endif // mozilla_places_Shutdown_h_