Commit c05fc0f8 authored by Jens Stutte's avatar Jens Stutte
Browse files

Bug 1707963: Let the PermissionManager be initialized lazily but not after...

Bug 1707963: Let the PermissionManager be initialized lazily but not after shutdown started. r=permissions-reviewers,timhuang,janv

Differential Revision: https://phabricator.services.mozilla.com/D132088
parent 0d99e5e9
Loading
Loading
Loading
Loading
+22 −36
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/AbstractThread.h"
#include "mozilla/AppShutdown.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/ContentPrincipal.h"
@@ -612,12 +613,6 @@ PermissionManager::PermissionKey::CreateFromURI(nsIURI* aURI,
  return new PermissionKey(origin);
}

/* static */
void PermissionManager::Startup() {
  nsCOMPtr<nsIPermissionManager> permManager =
      do_GetService("@mozilla.org/permissionmanager;1");
}

////////////////////////////////////////////////////////////////////////////////
// PermissionManager Implementation

@@ -628,7 +623,6 @@ PermissionManager::PermissionManager()
    : mMonitor("PermissionManager::mMonitor"),
      mState(eInitializing),
      mMemoryOnlyDB(false),
      mBlockerAdded(false),
      mLargestID(0) {}

PermissionManager::~PermissionManager() {
@@ -679,6 +673,12 @@ PermissionManager* PermissionManager::GetInstance() {
}

nsresult PermissionManager::Init() {
  // If we are already shutting down, do not permit a creation.
  // This must match the phase in GetAsyncShutdownClient.
  if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
    return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
  }

  // If the 'permissions.memory_only' pref is set to true, then don't write any
  // permission settings to disk, but keep them in a memory-only database.
  mMemoryOnlyDB = Preferences::GetBool("permissions.memory_only", false);
@@ -705,31 +705,22 @@ nsresult PermissionManager::Init() {

  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
  if (observerService) {
    observerService->AddObserver(this, "profile-before-change", true);
    observerService->AddObserver(this, "profile-do-change", true);
    observerService->AddObserver(this, "testonly-reload-permissions-from-disk",
                                 true);
  }

  if (XRE_IsParentProcess()) {
    nsCOMPtr<nsIAsyncShutdownClient> asc = GetShutdownPhase();
    if (asc) {
    nsCOMPtr<nsIAsyncShutdownClient> asc = GetAsyncShutdownClient();
    if (!asc) {
      return NS_ERROR_NOT_AVAILABLE;
    }
    nsAutoString blockerName;
    MOZ_ALWAYS_SUCCEEDS(GetName(blockerName));

      // This method can fail during some xpcshell-tests.
      nsresult rv =
          asc->AddBlocker(this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__),
                          __LINE__, blockerName);
      Unused << NS_WARN_IF(NS_FAILED(rv));
      if (NS_SUCCEEDED(rv)) {
        mBlockerAdded = true;
      }
    }

    if (!mBlockerAdded) {
      ClearOnShutdown(&gPermissionManager);
    }
    nsresult rv = asc->AddBlocker(
        this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, blockerName);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  AddIdleDailyMaintenanceJob();
@@ -2556,15 +2547,7 @@ NS_IMETHODIMP PermissionManager::Observe(nsISupports* aSubject,
                                         const char16_t* someData) {
  ENSURE_NOT_CHILD_PROCESS;

  if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
    if (!mBlockerAdded) {
      // The profile is about to change and the shutdown blocker has not been
      // added yet (we are probably in a xpcshell-test).
      RemoveIdleDailyMaintenanceJob();
      RemoveAllFromMemory();
      CloseDB(eNone);
    }
  } else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
  if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
    // the profile has already changed; init the db from the new location
    InitDB(false);
  } else if (!nsCRT::strcmp(aTopic, "testonly-reload-permissions-from-disk")) {
@@ -3827,7 +3810,7 @@ nsresult PermissionManager::TestPermissionWithoutDefaultsFromPrincipal(
void PermissionManager::MaybeCompleteShutdown() {
  MOZ_ASSERT(NS_IsMainThread());

  nsCOMPtr<nsIAsyncShutdownClient> asc = GetShutdownPhase();
  nsCOMPtr<nsIAsyncShutdownClient> asc = GetAsyncShutdownClient();
  MOZ_ASSERT(asc);

  DebugOnly<nsresult> rv = asc->RemoveBlocker(this);
@@ -3866,7 +3849,8 @@ PermissionManager::GetState(nsIPropertyBag** aBagOut) {
  return NS_OK;
}

nsCOMPtr<nsIAsyncShutdownClient> PermissionManager::GetShutdownPhase() const {
nsCOMPtr<nsIAsyncShutdownClient> PermissionManager::GetAsyncShutdownClient()
    const {
  nsresult rv;
  nsCOMPtr<nsIAsyncShutdownService> svc =
      do_GetService("@mozilla.org/async-shutdown-service;1", &rv);
@@ -3875,7 +3859,9 @@ nsCOMPtr<nsIAsyncShutdownClient> PermissionManager::GetShutdownPhase() const {
  }

  nsCOMPtr<nsIAsyncShutdownClient> client;
  rv = svc->GetProfileBeforeChange(getter_AddRefs(client));
  // This feels very late but there seem to be other services that rely on
  // us later than "profile-before-change".
  rv = svc->GetXpcomWillShutdown(getter_AddRefs(client));
  MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));

  return client;
+1 −12
Original line number Diff line number Diff line
@@ -194,15 +194,6 @@ class PermissionManager final : public nsIPermissionManager,
      nsIURI* aURI, const OriginAttributes* aOriginAttributes,
      const nsACString& aType, uint32_t* aPermission);

  /**
   * Initialize the permission-manager service.
   * The permission manager is always initialized at startup because when it
   * was lazy-initialized on demand, it was possible for it to be created
   * once shutdown had begun, resulting in the manager failing to correctly
   * shutdown because it missed its shutdown observer notification.
   */
  static void Startup();

  nsresult RemovePermissionsWithAttributes(OriginAttributesPattern& aAttrs);

  /**
@@ -529,7 +520,7 @@ class PermissionManager final : public nsIPermissionManager,
                                      uint32_t aExpireType, int64_t aExpireTime,
                                      int64_t aModificationTime, int64_t aId);

  nsCOMPtr<nsIAsyncShutdownClient> GetShutdownPhase() const;
  nsCOMPtr<nsIAsyncShutdownClient> GetAsyncShutdownClient() const;

  void MaybeCompleteShutdown();

@@ -646,8 +637,6 @@ class PermissionManager final : public nsIPermissionManager,

  bool mMemoryOnlyDB;

  bool mBlockerAdded;

  nsTHashtable<PermissionHashKey> mPermissionTable;
  // a unique, monotonically increasing id used to identify each database entry
  int64_t mLargestID;
+5 −0
Original line number Diff line number Diff line
@@ -58,6 +58,11 @@ add_task(function test() {
    Assert.ok(true, "There wasn't a nsINavHistoryService");
  }

  // We need to execute a pm method to be sure that the DB is fully
  // initialized.
  var pm = Services.perms;
  Assert.ok(pm.all.length >= 0, "Permission manager not initialized?");

  let db = Services.storage.openDatabase(GetPermissionsFile(profile));
  db.schemaVersion = 4;
  db.executeSimpleSQL("DROP TABLE moz_perms");
+0 −2
Original line number Diff line number Diff line
@@ -243,8 +243,6 @@ nsresult nsLayoutStatics::Initialize() {

  ProcessPriorityManager::Init();

  PermissionManager::Startup();

  UIDirectionManager::Initialize();

  CacheObserver::Init();
+7 −0
Original line number Diff line number Diff line
@@ -100,6 +100,13 @@ add_task(async function test_hawk_authenticated_request() {
  let timeOffset = -1 * clockSkew;
  let localTime = then + clockSkew;

  // XXX: This test fails if run with socket process enabled. It passes if
  // we force the permission manager to be initialized, but this might just
  // trigger some side effect and seems not a clean solution so we disabled
  // the entire test, see bug 1743079.
  // var pm = Services.perms;
  // Assert.ok(pm.all.length >= 0, "Permission manager not initialized?");

  // Set the accept-languages pref to the Nepalese dialect of Zulu.
  let acceptLanguage = "zu-NP"; // omit trailing ';', which our HTTP libs snip
  Services.prefs.setStringPref("intl.accept_languages", acceptLanguage);
Loading