gecko-dev/dom/workers/ServiceWorkerRegistrar.h
Kris Maglione 8b884c80c8 Bug 1399646: Part 2 - Use the async shutdown service for ServiceWorkerRegistrar. r=baku
The current shutdown handling code is susceptible to deadlocks, since it spins
the event loop while it holds mMonitor, and other main thread methods which
try to acquire mMonitor can be called from code that runs while the event loop
is spinning.

My initial solution was just to release mMonitor before spinning the event
loop, but at this point I think it makes more sense to switch to the
standardized AsyncShutdown routines, which provide better diagnostics and
allow us to avoid one more nested event loop during shutdown.

MozReview-Commit-ID: 1RtFN585IR7

--HG--
extra : rebase_source : 978f3bf7cef73e56b3e1c1c838c2bc6efcefb0c0
extra : amend_source : 2b7c9422004b58ad1d38d7dd705ad446bc47cb23
extra : histedit_source : 7a4e80de7d5aa48e074ea03821bb78e5e287842e%2C92c1119a131adaa33f5691c0e534bb243115817b
2017-09-14 11:30:50 -07:00

106 lines
2.7 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 mozilla_dom_workers_ServiceWorkerRegistrar_h
#define mozilla_dom_workers_ServiceWorkerRegistrar_h
#include "mozilla/Monitor.h"
#include "mozilla/Telemetry.h"
#include "nsClassHashtable.h"
#include "nsIAsyncShutdown.h"
#include "nsIObserver.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"
#define SERVICEWORKERREGISTRAR_FILE "serviceworker.txt"
#define SERVICEWORKERREGISTRAR_VERSION "8"
#define SERVICEWORKERREGISTRAR_TERMINATOR "#"
#define SERVICEWORKERREGISTRAR_TRUE "true"
#define SERVICEWORKERREGISTRAR_FALSE "false"
class nsIFile;
namespace mozilla {
namespace ipc {
class PrincipalInfo;
} // namespace ipc
namespace dom {
class ServiceWorkerRegistrationData;
class ServiceWorkerRegistrar : public nsIObserver
, public nsIAsyncShutdownBlocker
{
friend class ServiceWorkerRegistrarSaveDataRunnable;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIASYNCSHUTDOWNBLOCKER
static void Initialize();
void Shutdown();
void DataSaved();
static already_AddRefed<ServiceWorkerRegistrar> Get();
void GetRegistrations(nsTArray<ServiceWorkerRegistrationData>& aValues);
void RegisterServiceWorker(const ServiceWorkerRegistrationData& aData);
void UnregisterServiceWorker(const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
const nsACString& aScope);
void RemoveAll();
protected:
// These methods are protected because we test this class using gTest
// subclassing it.
void LoadData();
void SaveData();
nsresult ReadData();
nsresult WriteData();
void DeleteData();
void RegisterServiceWorkerInternal(const ServiceWorkerRegistrationData& aData);
ServiceWorkerRegistrar();
virtual ~ServiceWorkerRegistrar();
private:
void ProfileStarted();
void ProfileStopped();
void ScheduleSaveData();
void ShutdownCompleted();
void MaybeScheduleShutdownCompleted();
nsCOMPtr<nsIAsyncShutdownClient> GetShutdownPhase() const;
bool IsSupportedVersion(const nsACString& aVersion) const;
mozilla::Monitor mMonitor;
protected:
// protected by mMonitor.
nsCOMPtr<nsIFile> mProfileDir;
nsTArray<ServiceWorkerRegistrationData> mData;
bool mDataLoaded;
// PBackground thread only
bool mShuttingDown;
uint32_t mRunnableCounter;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_workers_ServiceWorkerRegistrar_h