1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsUpdateSyncManager.h"
9 #include "mozilla/Unused.h"
10 #include "mozilla/Services.h"
11 #include "nsComponentManagerUtils.h"
14 #include "nsIObserverService.h"
15 #include "nsIProperties.h"
17 #include "nsXULAppAPI.h"
19 // The lock code generates a path that already includes the vendor name,
20 // so this only needs to name the specific lock.
21 #define UPDATE_LOCK_NAME_TOKEN "UpdateLock"
23 nsUpdateSyncManager
* gUpdateSyncManager
= nullptr;
25 NS_IMPL_ISUPPORTS(nsUpdateSyncManager
, nsIUpdateSyncManager
, nsIObserver
)
27 nsUpdateSyncManager::nsUpdateSyncManager(nsIFile
* anAppFile
/* = nullptr */) {
28 gUpdateSyncManager
= this;
32 nsUpdateSyncManager::~nsUpdateSyncManager() {
34 gUpdateSyncManager
= nullptr;
37 already_AddRefed
<nsUpdateSyncManager
> nsUpdateSyncManager::GetSingleton() {
38 if (!gUpdateSyncManager
) {
39 new nsUpdateSyncManager(); // This sets gUpdateSyncManager.
41 return do_AddRef(gUpdateSyncManager
);
44 NS_IMETHODIMP
nsUpdateSyncManager::Observe(nsISupports
* aSubject
,
46 const char16_t
* aData
) {
47 mozilla::Unused
<< aSubject
;
48 mozilla::Unused
<< aData
;
50 // We want to hold the lock for as much of the lifetime of the app as we can,
51 // so we observe xpcom-startup so we get constructed as early as possible,
52 // which triggers constructing the singleton.
53 if (!nsCRT::strcmp(aTopic
, NS_XPCOM_STARTUP_OBSERVER_ID
)) {
54 nsCOMPtr
<nsIObserverService
> observerService
=
55 mozilla::services::GetObserverService();
56 if (observerService
) {
57 return observerService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
,
60 return NS_ERROR_SERVICE_NOT_AVAILABLE
;
62 if (!nsCRT::strcmp(aTopic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
)) {
69 nsresult
nsUpdateSyncManager::OpenLock(nsIFile
* anAppFile
) {
71 if (mLock
!= MULTI_INSTANCE_LOCK_HANDLE_ERROR
) {
72 // Lock is already open.
76 // Our component registration should already have made sure of this.
77 if (NS_WARN_IF(XRE_GetProcessType() != GeckoProcessType_Default
)) {
81 nsCOMPtr
<nsIFile
> appFile
= mozilla::GetNormalizedAppFile(anAppFile
);
83 return NS_ERROR_NOT_AVAILABLE
;
86 nsCOMPtr
<nsIFile
> appDirFile
;
87 rv
= appFile
->GetParent(getter_AddRefs(appDirFile
));
88 NS_ENSURE_SUCCESS(rv
, rv
);
90 nsAutoString appDirPath
;
91 rv
= appDirFile
->GetPath(appDirPath
);
92 NS_ENSURE_SUCCESS(rv
, rv
);
95 mozilla::OpenMultiInstanceLock(UPDATE_LOCK_NAME_TOKEN
, appDirPath
.get());
96 NS_ENSURE_TRUE(mLock
, NS_ERROR_FAILURE
);
101 void nsUpdateSyncManager::ReleaseLock() {
102 if (mLock
== MULTI_INSTANCE_LOCK_HANDLE_ERROR
) {
103 // Lock is already released.
107 mozilla::ReleaseMultiInstanceLock(mLock
);
108 mLock
= MULTI_INSTANCE_LOCK_HANDLE_ERROR
;
111 NS_IMETHODIMP
nsUpdateSyncManager::IsOtherInstanceRunning(bool* aResult
) {
112 if (NS_WARN_IF(XRE_GetProcessType() != GeckoProcessType_Default
)) {
113 return NS_ERROR_SERVICE_NOT_AVAILABLE
;
116 if (mLock
== MULTI_INSTANCE_LOCK_HANDLE_ERROR
) {
117 return NS_ERROR_NOT_INITIALIZED
;
120 bool rv
= mozilla::IsOtherInstanceRunning(mLock
, aResult
);
121 NS_ENSURE_TRUE(rv
, NS_ERROR_FAILURE
);
126 NS_IMETHODIMP
nsUpdateSyncManager::ResetLock(nsIFile
* anAppFile
= nullptr) {
128 return OpenLock(anAppFile
);