Verified Commit f98ba63a authored by Pier Angelo Vendrame's avatar Pier Angelo Vendrame 🎃
Browse files

Bug 9173: Change the default Firefox profile directory to be relative.

This commit makes Firefox look for the default profile directory in a
directory relative to the binary path.
The directory can be specified through the --with-relative-data-dir.
This is relative to the same directory as the firefox main binary for
Linux and Windows.

On macOS, we remove Contents/MacOS from it.
Or, in other words, the directory is relative to the application
bundle.

This behavior can be overriden at runtime, by placing a file called
system-install adjacent to the firefox main binary (also on macOS).
parent 9657a56f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -41,3 +41,5 @@ ac_add_options MOZ_TELEMETRY_REPORTING=
if test -z "$WASI_SYSROOT"; then
    ac_add_options --without-wasm-sandboxed-libraries
fi

ac_add_options --with-relative-data-dir=BaseBrowser/Data/Browser
+19 −0
Original line number Diff line number Diff line
@@ -1025,6 +1025,25 @@ set_config("BASE_BROWSER", True, when="--enable-base-browser")
set_define("BASE_BROWSER", True, when="--enable-base-browser")


option(
    "--with-relative-data-dir",
    nargs=1,
    help="Sets the data directories to be relative to the application directory"
)


@depends("--with-relative-data-dir", target)
@imports("json")
def relative_data_dir(value, target):
    if value and target.os == "Android":
        die("--with-relative-data-dir is not supported on Android")
    if value:
        return json.dumps(value[0])


set_define("RELATIVE_DATA_DIR", relative_data_dir)


# Please do not add configure checks from here on.

# Fallthrough to autoconf-based configure
+3 −0
Original line number Diff line number Diff line
@@ -4,3 +4,6 @@ ac_add_options --enable-strip

# See bug #41131
ac_add_options --disable-update-agent

# For base-browser we do not enable portable mode on macOS.
ac_add_options --without-relative-data-dir
+9 −5
Original line number Diff line number Diff line
@@ -2779,6 +2779,8 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) {
#endif    // MOZ_WIDGET_ANDROID
}

// If aUnlocker is NULL, it is also OK for the following arguments to be NULL:
//   aProfileDir, aProfileLocalDir, aResult.
static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir,
                                              nsIFile* aProfileLocalDir,
                                              nsIProfileUnlocker* aUnlocker,
@@ -2786,18 +2788,20 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir,
                                              nsIProfileLock** aResult) {
  nsresult rv;

  if (aProfileDir) {
    bool exists;
    aProfileDir->Exists(&exists);
    if (!exists) {
      return ProfileMissingDialog(aNative);
    }
  }

  ScopedXPCOMStartup xpcom;
  rv = xpcom.Initialize();
  NS_ENSURE_SUCCESS(rv, rv);

#if defined(MOZ_TELEMETRY_REPORTING)
  mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
  if (aProfileDir) mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
#endif

  rv = xpcom.SetWindowCreator(aNative);
+115 −0
Original line number Diff line number Diff line
@@ -111,6 +111,10 @@ nsIFile* gDataDirHome = nullptr;
nsCOMPtr<nsIFile> gDataDirProfileLocal = nullptr;
nsCOMPtr<nsIFile> gDataDirProfile = nullptr;

#if defined(RELATIVE_DATA_DIR)
mozilla::Maybe<nsCOMPtr<nsIFile>> gDataDirPortable;
#endif

// These are required to allow nsXREDirProvider to be usable in xpcshell tests.
// where gAppData is null.
#if defined(XP_MACOSX) || defined(XP_UNIX)
@@ -1324,10 +1328,96 @@ nsresult nsXREDirProvider::SetUserDataProfileDirectory(nsCOMPtr<nsIFile>& aFile,
  return NS_OK;
}

#if defined(RELATIVE_DATA_DIR)
nsresult nsXREDirProvider::GetPortableDataDir(nsIFile** aFile,
                                              bool& aIsPortable) {
  if (gDataDirPortable) {
    if (*gDataDirPortable) {
      nsresult rv = (*gDataDirPortable)->Clone(aFile);
      NS_ENSURE_SUCCESS(rv, rv);
      aIsPortable = true;
    } else {
      aIsPortable = false;
    }
    return NS_OK;
  }

  nsCOMPtr<nsIFile> exeFile, exeDir;
  bool persistent = false;
  nsresult rv =
      GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(exeFile));
  NS_ENSURE_SUCCESS(rv, rv);
  rv = exeFile->Normalize();
  NS_ENSURE_SUCCESS(rv, rv);
  rv = exeFile->GetParent(getter_AddRefs(exeDir));
  NS_ENSURE_SUCCESS(rv, rv);

#  if defined(XP_MACOSX)
  nsAutoString exeDirPath;
  rv = exeDir->GetPath(exeDirPath);
  NS_ENSURE_SUCCESS(rv, rv);
  // When the browser is installed in /Applications, we never run in portable
  // mode.
  if (exeDirPath.Find("/Applications/", true /* ignore case */) == 0) {
    aIsPortable = false;
    return NS_OK;
  }
#  endif

  nsCOMPtr<nsIFile> systemInstallFile;
  rv = exeDir->Clone(getter_AddRefs(systemInstallFile));
  NS_ENSURE_SUCCESS(rv, rv);
  rv = systemInstallFile->AppendNative("system-install"_ns);
  NS_ENSURE_SUCCESS(rv, rv);

  bool exists = false;
  rv = systemInstallFile->Exists(&exists);
  NS_ENSURE_SUCCESS(rv, rv);
  if (exists) {
    aIsPortable = false;
    gDataDirPortable.emplace(nullptr);
    return NS_OK;
  }

  nsCOMPtr<nsIFile> localDir = exeDir;
#  if defined(XP_MACOSX)
  rv = exeDir->GetParent(getter_AddRefs(localDir));
  NS_ENSURE_SUCCESS(rv, rv);
  exeDir = localDir;
  rv = exeDir->GetParent(getter_AddRefs(localDir));
  NS_ENSURE_SUCCESS(rv, rv);
#  endif
  rv = localDir->SetRelativePath(localDir.get(),
                                 nsLiteralCString(RELATIVE_DATA_DIR));
  NS_ENSURE_SUCCESS(rv, rv);

#  if defined(XP_MACOSX)
  // On macOS we try to create the directory immediately to switch to
  // system-install mode if needed (e.g., when running from the DMG).
  rv = localDir->Exists(&exists);
  NS_ENSURE_SUCCESS(rv, rv);
  if (!exists) {
    rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
    if (NS_FAILED(rv)) {
      aIsPortable = false;
      return NS_OK;
    }
  }
#  endif

  gDataDirPortable.emplace(localDir);
  rv = (*gDataDirPortable)->Clone(aFile);
  NS_ENSURE_SUCCESS(rv, rv);
  aIsPortable = true;
  return rv;
}
#endif

nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
                                                    bool aLocal) {
  // Copied from nsAppFileLocationProvider (more or less)
  nsresult rv;
  NS_ENSURE_ARG_POINTER(aFile);
  nsCOMPtr<nsIFile> localDir;

  if (aLocal && gDataDirHomeLocal) {
@@ -1337,6 +1427,24 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
    return gDataDirHome->Clone(aFile);
  }

#if defined(RELATIVE_DATA_DIR)
  RefPtr<nsXREDirProvider> singleton = GetSingleton();
  if (!singleton) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  bool isPortable = false;
  rv = singleton->GetPortableDataDir(getter_AddRefs(localDir), isPortable);
  NS_ENSURE_SUCCESS(rv, rv);
  if (isPortable) {
    if (aLocal) {
      rv = localDir->AppendNative("Caches"_ns);
      NS_ENSURE_SUCCESS(rv, rv);
    }
    NS_IF_ADDREF(*aFile = localDir);
    return rv;
  }
#endif

#if defined(XP_MACOSX)
  FSRef fsRef;
  OSType folderType;
@@ -1530,6 +1638,13 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) {
    return NS_OK;
  }

#if defined(RELATIVE_DATA_DIR)
  if (gDataDirPortable && *gDataDirPortable) {
    // Do nothing in portable mode
    return NS_OK;
  }
#endif

  nsAutoCString profile;
  nsAutoCString appName;
  nsAutoCString vendor;
Loading