summaryrefslogtreecommitdiffstats
path: root/mailnews/base/util/Services.cpp
blob: a10d44aa3469fd661215a8c5524e16b141870a25 (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
/* -*- 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/. */

#include "mozilla/mailnews/Services.h"

#include "nsIObserverService.h"
#include "nsIObserver.h"
#include "nsServiceManagerUtils.h"

// All of the includes for the services we initiate here
#include "mozINewMailNotificationService.h"
#include "nsIAbManager.h"
#include "nsIImapService.h"
#include "nsIImportService.h"
#include "nsIMimeConverter.h"
#include "nsIMsgAccountManager.h"
#include "nsIMsgComposeService.h"
#include "nsIMsgCopyService.h"
#include "nsIMsgDatabase.h"
#include "nsIMsgFilterService.h"
#include "nsIMsgFolderNotificationService.h"
#include "nsIMsgHeaderParser.h"
#include "nsIMsgMailSession.h"
#include "nsIMsgTagService.h"
#include "nsINntpService.h"
#include "nsIPop3Service.h"
#include "nsISmtpService.h"

namespace mozilla {
namespace services {

namespace {
class ShutdownObserver final : public nsIObserver
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIOBSERVER

  static void EnsureInitialized();
private:
  ~ShutdownObserver() {}

  void ShutdownServices();
  static ShutdownObserver *sShutdownObserver;
  static bool sShuttingDown;
};

bool ShutdownObserver::sShuttingDown = false;
ShutdownObserver *ShutdownObserver::sShutdownObserver = nullptr;
}

#define MOZ_SERVICE(NAME, TYPE, CONTRACT_ID) \
  static TYPE *g##NAME = nullptr; \
  already_AddRefed<TYPE> Get##NAME() \
  { \
    ShutdownObserver::EnsureInitialized(); \
    if (!g##NAME) \
    { \
      nsCOMPtr<TYPE> os = do_GetService(CONTRACT_ID); \
      os.forget(&g##NAME); \
      MOZ_ASSERT(g##NAME, "This service is unexpectedly missing."); \
    } \
    nsCOMPtr<TYPE> ret = g##NAME; \
    return ret.forget(); \
  }
#include "mozilla/mailnews/ServiceList.h"
#undef MOZ_SERVICE

NS_IMPL_ISUPPORTS(ShutdownObserver, nsIObserver)

NS_IMETHODIMP ShutdownObserver::Observe(nsISupports *aSubject,
    const char *aTopic, const char16_t *aData)
{
  if (!strcmp(aTopic, "xpcom-shutdown-threads"))
    ShutdownServices();
  return NS_OK;
}

void ShutdownObserver::EnsureInitialized()
{
  MOZ_ASSERT(!sShuttingDown, "It is illegal to use this code after shutdown!");
  if (!sShutdownObserver)
  {
    sShutdownObserver = new ShutdownObserver;
    sShutdownObserver->AddRef();
    nsCOMPtr<nsIObserverService> obs(mozilla::services::GetObserverService());
    MOZ_ASSERT(obs, "This should never be null");
    obs->AddObserver(sShutdownObserver, "xpcom-shutdown-threads", false);
  }
}

void ShutdownObserver::ShutdownServices()
{
  sShuttingDown = true;
  MOZ_ASSERT(sShutdownObserver, "Shutting down twice?");
  sShutdownObserver->Release();
  sShutdownObserver = nullptr;
#define MOZ_SERVICE(NAME, TYPE, CONTRACT_ID) NS_IF_RELEASE(g##NAME);
#include "mozilla/mailnews/ServiceList.h"
#undef MOZ_SERVICE
}

} // namespace services
} // namespace mozilla