Bug 1321593 part A - Refactor nsXREAppData: 1) make nsXREAppData strongly own its members 2) rename it to mozilla::XREAppData 3) separate out the static compiled data into StaticXREAppData 4) Remove XRE_CreateAppData and XRE_FreeAppData 5) remove the struct size and related size-checking code which was only ever useful for cross-version compatibility, r=glandium
☠☠ backed out by 34405a5f3ec2 ☠ ☠
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 02 Dec 2016 09:07:24 -0500
changeset 370669 eae2252a519f3ac5850f5110a6a1be45891ea5e9
parent 370668 f347515b29ae6f6bdc796261b11f58a3d6f3c8db
child 370670 e531af57cd60ba243721c90fc30fa47d6bdd37e0
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs1321593
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1321593 part A - Refactor nsXREAppData: 1) make nsXREAppData strongly own its members 2) rename it to mozilla::XREAppData 3) separate out the static compiled data into StaticXREAppData 4) Remove XRE_CreateAppData and XRE_FreeAppData 5) remove the struct size and related size-checking code which was only ever useful for cross-version compatibility, r=glandium MozReview-Commit-ID: CQv1UrSaw4D
browser/app/nsBrowserApp.cpp
build/appini_header.py
mozglue/android/APKOpen.cpp
toolkit/xre/CreateAppData.cpp
toolkit/xre/ProfileReset.cpp
toolkit/xre/nsAndroidStartup.cpp
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsAppRunner.h
toolkit/xre/nsNativeAppSupportWin.cpp
xpcom/build/XREAppData.h
xpcom/build/moz.build
xpcom/build/nsXREAppData.h
xpcom/build/nsXULAppAPI.h
xpcom/glue/AppData.cpp
xpcom/glue/AppData.h
xpcom/glue/XREAppData.cpp
xpcom/glue/moz.build
xpcom/glue/objs.mozbuild
xpcom/system/nsIXULAppInfo.idl
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -1,15 +1,15 @@
 /* -*- 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 "nsXULAppAPI.h"
-#include "mozilla/AppData.h"
+#include "mozilla/XREAppData.h"
 #include "application.ini.h"
 #include "nsXPCOMGlue.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/resource.h>
 #include <unistd.h>
@@ -158,36 +158,34 @@ static bool IsArg(const char* arg, const
   if (*arg == '/')
     return !strcasecmp(++arg, s);
 #endif
 
   return false;
 }
 
 XRE_GetFileFromPathType XRE_GetFileFromPath;
-XRE_CreateAppDataType XRE_CreateAppData;
-XRE_FreeAppDataType XRE_FreeAppData;
+XRE_ParseAppDataType XRE_ParseAppData;
 XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
 XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
 XRE_mainType XRE_main;
 XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
 XRE_XPCShellMainType XRE_XPCShellMain;
 XRE_GetProcessTypeType XRE_GetProcessType;
 XRE_SetProcessTypeType XRE_SetProcessType;
 XRE_InitChildProcessType XRE_InitChildProcess;
 XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc;
 #ifdef LIBFUZZER
 XRE_LibFuzzerSetMainType XRE_LibFuzzerSetMain;
 XRE_LibFuzzerGetFuncsType XRE_LibFuzzerGetFuncs;
 #endif
 
 static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
-    { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
-    { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
+    { "XRE_ParseAppData", (NSFuncPtr*) &XRE_ParseAppData },
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
     { "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain },
     { "XRE_GetProcessType", (NSFuncPtr*) &XRE_GetProcessType },
     { "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType },
     { "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess },
@@ -257,55 +255,53 @@ static int do_main(int argc, char* argv[
     shellData.sandboxBrokerServices =
       sandboxing::GetInitializedBrokerServices();
 #endif
 
     return XRE_XPCShellMain(--argc, argv, envp, &shellData);
   }
 
   if (appini) {
-    nsXREAppData *appData;
-    rv = XRE_CreateAppData(appini, &appData);
+    XREAppData appData;
+    rv = XRE_ParseAppData(appini, appData);
     if (NS_FAILED(rv)) {
       Output("Couldn't read application.ini");
       return 255;
     }
 #if defined(HAS_DLL_BLOCKLIST)
     // The dll blocklist operates in the exe vs. xullib. Pass a flag to
     // xullib so automated tests can check the result once the browser
     // is up and running.
     appData->flags |=
       DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
 #endif
-    // xreDirectory already has a refcount from NS_NewLocalFile
-    appData->xreDirectory = xreDirectory;
-    int result = XRE_main(argc, argv, appData, mainFlags);
-    XRE_FreeAppData(appData);
-    return result;
+    appData.xreDirectory = xreDirectory;
+    appini->GetParent(getter_AddRefs(appData.directory));
+    return XRE_main(argc, argv, appData, mainFlags);
   }
 
-  ScopedAppData appData(&sAppData);
+  XREAppData appData;
+  appData = sAppData;
   nsCOMPtr<nsIFile> exeFile;
   rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile));
   if (NS_FAILED(rv)) {
     Output("Couldn't find the application directory.\n");
     return 255;
   }
 
   nsCOMPtr<nsIFile> greDir;
   exeFile->GetParent(getter_AddRefs(greDir));
 #ifdef XP_MACOSX
   greDir->SetNativeLeafName(NS_LITERAL_CSTRING(kOSXResourcesFolder));
 #endif
   nsCOMPtr<nsIFile> appSubdir;
   greDir->Clone(getter_AddRefs(appSubdir));
   appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
 
-  SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get()));
-  // xreDirectory already has a refcount from NS_NewLocalFile
+  appData.directory = appSubdir;
   appData.xreDirectory = xreDirectory;
 
 #if defined(HAS_DLL_BLOCKLIST)
   appData.flags |=
     DllBlocklist_CheckStatus() ? NS_XRE_DLL_BLOCKLIST_ENABLED : 0;
 #endif
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
@@ -320,17 +316,17 @@ static int do_main(int argc, char* argv[
   appData.sandboxBrokerServices = brokerServices;
 #endif
 
 #ifdef LIBFUZZER
   if (getenv("LIBFUZZER"))
     XRE_LibFuzzerSetMain(argc, argv, libfuzzer_main);
 #endif
 
-  return XRE_main(argc, argv, &appData, mainFlags);
+  return XRE_main(argc, argv, appData, mainFlags);
 }
 
 static bool
 FileExists(const char *path)
 {
 #ifdef XP_WIN
   wchar_t wideDir[MAX_PATH];
   MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH);
--- a/build/appini_header.py
+++ b/build/appini_header.py
@@ -1,14 +1,14 @@
 # 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/.
 
 '''Parses a given application.ini file and outputs the corresponding
-   XULAppData structure as a C++ header file'''
+   StaticXREAppData structure as a C++ header file'''
 
 import ConfigParser
 import sys
 
 def main(output, file):
     config = ConfigParser.RawConfigParser()
     config.read(file)
     flags = set()
@@ -29,29 +29,26 @@ def main(output, file):
     if missing:
         print >>sys.stderr, \
             "Missing values in %s: %s" % (file, ', '.join(missing))
         sys.exit(1)
 
     if not 'Crash Reporter:serverurl' in appdata:
         appdata['Crash Reporter:serverurl'] = ''
 
-    output.write('''#include "nsXREAppData.h"
-             static const nsXREAppData sAppData = {
-                 sizeof(nsXREAppData),
-                 NULL, // directory
+    output.write('''#include "mozilla/XREAppData.h"
+             static const mozilla::StaticXREAppData sAppData = {
                  "%(App:vendor)s",
                  "%(App:name)s",
                  "%(App:remotingname)s",
                  "%(App:version)s",
                  "%(App:buildid)s",
                  "%(App:id)s",
                  NULL, // copyright
                  %(flags)s,
-                 NULL, // xreDirectory
                  "%(Gecko:minversion)s",
                  "%(Gecko:maxversion)s",
                  "%(Crash Reporter:serverurl)s",
                  %(App:profile)s
              };''' % appdata)
 
 if __name__ == '__main__':
     if len(sys.argv) != 1:
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -439,17 +439,17 @@ FreeArgv(char** argv, int argc)
 {
   for (int ix=0; ix < argc; ix++) {
     // String was allocated with strndup, so need to use free to deallocate.
     free(argv[ix]);
   }
   delete[](argv);
 }
 
-typedef void (*GeckoStart_t)(JNIEnv*, char**, int, const nsXREAppData*);
+typedef void (*GeckoStart_t)(JNIEnv*, char**, int, const StaticXREAppData&);
 typedef int GeckoProcessType;
 
 extern "C" NS_EXPORT void MOZ_JNICALL
 Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int crashFd, int ipcFd)
 {
   int argc = 0;
   char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
 
@@ -458,17 +458,17 @@ Java_org_mozilla_gecko_mozglue_GeckoLoad
     xul_dlsym("GeckoStart", &GeckoStart);
 
     if (GeckoStart == nullptr) {
       FreeArgv(argv, argc);
       return;
     }
 
     ElfLoader::Singleton.ExpectShutdown(false);
-    GeckoStart(jenv, argv, argc, &sAppData);
+    GeckoStart(jenv, argv, argc, sAppData);
     ElfLoader::Singleton.ExpectShutdown(true);
   } else {
     void (*fXRE_SetAndroidChildFds)(int, int);
     xul_dlsym("XRE_SetAndroidChildFds", &fXRE_SetAndroidChildFds);
 
     void (*fXRE_SetProcessType)(char*);
     xul_dlsym("XRE_SetProcessType", &fXRE_SetProcessType);
 
--- a/toolkit/xre/CreateAppData.cpp
+++ b/toolkit/xre/CreateAppData.cpp
@@ -2,164 +2,76 @@
 /* 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 "nsXULAppAPI.h"
 #include "nsINIParser.h"
 #include "nsIFile.h"
 #include "nsAutoPtr.h"
-#include "mozilla/AppData.h"
+#include "mozilla/XREAppData.h"
 
 using namespace mozilla;
 
-nsresult
-XRE_CreateAppData(nsIFile* aINIFile, nsXREAppData **aAppData)
+static void
+ReadString(nsINIParser &parser, const char* section,
+           const char* key, XREAppData::CharPtr& result)
 {
-  NS_ENSURE_ARG(aINIFile && aAppData);
-
-  nsAutoPtr<ScopedAppData> data(new ScopedAppData());
-  if (!data)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  nsresult rv = XRE_ParseAppData(aINIFile, data);
-  if (NS_FAILED(rv))
-    return rv;
-
-  if (!data->directory) {
-    nsCOMPtr<nsIFile> appDir;
-    rv = aINIFile->GetParent(getter_AddRefs(appDir));
-    if (NS_FAILED(rv))
-      return rv;
-
-    appDir.forget(&data->directory);
-  }
-
-  *aAppData = data.forget();
-  return NS_OK;
-}
-
-struct ReadString {
-  const char *section;
-  const char *key;
-  const char **buffer;
-};
-
-static void
-ReadStrings(nsINIParser &parser, const ReadString *reads)
-{
-  nsresult rv;
   nsCString str;
-
-  while (reads->section) {
-    rv = parser.GetString(reads->section, reads->key, str);
-    if (NS_SUCCEEDED(rv)) {
-      SetAllocatedString(*reads->buffer, str);
-    }
-
-    ++reads;
+  nsresult rv = parser.GetString(section, key, str);
+  if (NS_SUCCEEDED(rv)) {
+    result = str.get();
   }
 }
 
 struct ReadFlag {
   const char *section;
   const char *key;
   uint32_t flag;
 };
 
 static void
-ReadFlags(nsINIParser &parser, const ReadFlag *reads, uint32_t *buffer)
+ReadFlag(nsINIParser &parser, const char* section,
+         const char* key, uint32_t flag, uint32_t& result)
 {
-  nsresult rv;
   char buf[6]; // large enough to hold "false"
-
-  while (reads->section) {
-    rv = parser.GetString(reads->section, reads->key, buf, sizeof(buf));
-    if (NS_SUCCEEDED(rv) || rv == NS_ERROR_LOSS_OF_SIGNIFICANT_DATA) {
-      if (buf[0] == '1' || buf[0] == 't' || buf[0] == 'T') {
-        *buffer |= reads->flag;
-      }
-      if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
-        *buffer &= ~reads->flag;
-      }
+  nsresult rv = parser.GetString(section, key, buf, sizeof(buf));
+  if (NS_SUCCEEDED(rv) || rv == NS_ERROR_LOSS_OF_SIGNIFICANT_DATA) {
+    if (buf[0] == '1' || buf[0] == 't' || buf[0] == 'T') {
+      result |= flag;
     }
-
-    ++reads;
+    if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
+      result &= ~flag;
+    }
   }
 }
 
 nsresult
-XRE_ParseAppData(nsIFile* aINIFile, nsXREAppData *aAppData)
+XRE_ParseAppData(nsIFile* aINIFile, XREAppData& aAppData)
 {
-  NS_ENSURE_ARG(aINIFile && aAppData);
+  NS_ENSURE_ARG(aINIFile);
 
   nsresult rv;
 
   nsINIParser parser;
   rv = parser.Init(aINIFile);
   if (NS_FAILED(rv))
     return rv;
 
-  nsCString str;
-
-  ReadString strings[] = {
-    { "App", "Vendor",        &aAppData->vendor },
-    { "App", "Name",          &aAppData->name },
-    { "App", "RemotingName",  &aAppData->remotingName },
-    { "App", "Version",       &aAppData->version },
-    { "App", "BuildID",       &aAppData->buildID },
-    { "App", "ID",            &aAppData->ID },
-    { "App", "Copyright",     &aAppData->copyright },
-    { "App", "Profile",       &aAppData->profile },
-    { nullptr }
-  };
-  ReadStrings(parser, strings);
-
-  ReadFlag flags[] = {
-    { "XRE", "EnableProfileMigrator", NS_XRE_ENABLE_PROFILE_MIGRATOR },
-    { nullptr }
-  };
-  ReadFlags(parser, flags, &aAppData->flags);
-
-  if (aAppData->size > offsetof(nsXREAppData, xreDirectory)) {
-    ReadString strings2[] = {
-      { "Gecko", "MinVersion", &aAppData->minVersion },
-      { "Gecko", "MaxVersion", &aAppData->maxVersion },
-      { nullptr }
-    };
-    ReadStrings(parser, strings2);
-  }
-
-  if (aAppData->size > offsetof(nsXREAppData, crashReporterURL)) {
-    ReadString strings3[] = {
-      { "Crash Reporter", "ServerURL", &aAppData->crashReporterURL },
-      { nullptr }
-    };
-    ReadStrings(parser, strings3);
-    ReadFlag flags2[] = {
-      { "Crash Reporter", "Enabled", NS_XRE_ENABLE_CRASH_REPORTER },
-      { nullptr }
-    };
-    ReadFlags(parser, flags2, &aAppData->flags);
-  }
-
-  if (aAppData->size > offsetof(nsXREAppData, UAName)) {
-    ReadString strings4[] = {
-      { "App", "UAName",    &aAppData->UAName },
-      { nullptr }
-    };
-    ReadStrings(parser, strings4);
-  }
+  ReadString(parser, "App", "Vendor", aAppData.vendor);
+  ReadString(parser, "App", "Name", aAppData.name),
+  ReadString(parser, "App", "RemotingName", aAppData.remotingName);
+  ReadString(parser, "App", "Version", aAppData.version);
+  ReadString(parser, "App", "BuildID", aAppData.buildID);
+  ReadString(parser, "App", "ID", aAppData.ID);
+  ReadString(parser, "App", "Copyright", aAppData.copyright);
+  ReadString(parser, "App", "Profile", aAppData.profile);
+  ReadString(parser, "Gecko", "MinVersion", aAppData.minVersion);
+  ReadString(parser, "Gecko", "MaxVersion", aAppData.maxVersion);
+  ReadString(parser, "Crash Reporter", "ServerURL", aAppData.crashReporterURL);
+  ReadString(parser, "App", "UAName", aAppData.UAName);
+  ReadFlag(parser, "XRE", "EnableProfileMigrator",
+           NS_XRE_ENABLE_PROFILE_MIGRATOR, aAppData.flags);
+  ReadFlag(parser, "Crash Reporter", "Enabled",
+           NS_XRE_ENABLE_CRASH_REPORTER, aAppData.flags);
 
   return NS_OK;
 }
-
-void
-XRE_FreeAppData(nsXREAppData *aAppData)
-{
-  if (!aAppData) {
-    NS_ERROR("Invalid arg");
-    return;
-  }
-
-  ScopedAppData* sad = static_cast<ScopedAppData*>(aAppData);
-  delete sad;
-}
--- a/toolkit/xre/ProfileReset.cpp
+++ b/toolkit/xre/ProfileReset.cpp
@@ -10,24 +10,27 @@
 #include "nsIWindowWatcher.h"
 
 #include "ProfileReset.h"
 
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
+#include "nsString.h"
 #include "nsToolkitCompsCID.h"
 #include "nsXPCOMCIDInternal.h"
-#include "nsXREAppData.h"
+#include "mozilla/XREAppData.h"
 
 #include "mozilla/Services.h"
 #include "prtime.h"
 
-extern const nsXREAppData* gAppData;
+using namespace mozilla;
+
+extern const XREAppData* gAppData;
 
 static const char kProfileProperties[] =
   "chrome://mozapps/locale/profile/profileSelection.properties";
 
 /**
  * Creates a new profile with a timestamp in the name to use for profile reset.
  */
 nsresult
--- a/toolkit/xre/nsAndroidStartup.cpp
+++ b/toolkit/xre/nsAndroidStartup.cpp
@@ -16,18 +16,20 @@
 #include "nsString.h"
 #include "nsIFile.h"
 #include "nsAppRunner.h"
 #include "APKOpen.h"
 #include "nsExceptionHandler.h"
 
 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, MOZ_APP_NAME, args)
 
+using namespace mozilla;
+
 extern "C" NS_EXPORT void
-GeckoStart(JNIEnv* env, char** argv, int argc, const nsXREAppData* appData)
+GeckoStart(JNIEnv* env, char** argv, int argc, const StaticXREAppData& aAppData)
 {
     mozilla::jni::SetGeckoThreadEnv(env);
 
 #ifdef MOZ_CRASHREPORTER
     const struct mapping_info *info = getLibraryMapping();
     while (info->name) {
       CrashReporter::AddLibraryMapping(info->name, info->base,
                                        info->len, info->offset);
@@ -35,13 +37,16 @@ GeckoStart(JNIEnv* env, char** argv, int
     }
 #endif
 
     if (!argv) {
         LOG("Failed to get arguments for GeckoStart\n");
         return;
     }
 
+    XREAppData appData;
+    appData = aAppData;
+
     int result = XRE_main(argc, argv, appData, 0);
 
     if (result)
         LOG("XRE_main returned %d", result);
 }
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -16,17 +16,17 @@
 #include "mozilla/Poison.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Services.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsAppRunner.h"
-#include "mozilla/AppData.h"
+#include "mozilla/XREAppData.h"
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
 #include "nsUpdateDriver.h"
 #endif
 #include "ProfileReset.h"
 
 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
 #include "EventTracer.h"
 #endif
@@ -1603,33 +1603,33 @@ DumpHelp()
 
 #ifdef MOZ_X11
   printf("X11 options\n"
          "  --display=DISPLAY  X display to use\n"
          "  --sync             Make X calls synchronous\n");
 #endif
 #ifdef XP_UNIX
   printf("  --g-fatal-warnings Make all warnings fatal\n"
-         "\n%s options\n", gAppData->name);
+         "\n%s options\n", (const char*) gAppData->name);
 #endif
 
   printf("  -h or --help       Print this message.\n"
          "  -v or --version    Print %s version.\n"
          "  -P <profile>       Start with <profile>.\n"
          "  --profile <path>   Start with profile at <path>.\n"
          "  --migration        Start with migration wizard.\n"
          "  --ProfileManager   Start with ProfileManager.\n"
          "  --no-remote        Do not accept or send remote commands; implies\n"
          "                     --new-instance.\n"
          "  --new-instance     Open new instance, not a new window in running instance.\n"
          "  --UILocale <locale> Start with <locale> resources as UI Locale.\n"
-         "  --safe-mode        Disables extensions and themes for this session.\n", gAppData->name);
+         "  --safe-mode        Disables extensions and themes for this session.\n", (const char*) gAppData->name);
 
 #if defined(XP_WIN)
-  printf("  --console          Start %s with a debugging console.\n", gAppData->name);
+  printf("  --console          Start %s with a debugging console.\n", (const char*) gAppData->name);
 #endif
 
   // this works, but only after the components have registered.  so if you drop in a new command line handler, --help
   // won't not until the second run.
   // out of the bug, because we ship a component.reg file, it works correctly.
   DumpArbitraryHelp();
 }
 
@@ -1674,20 +1674,20 @@ static int MSCRTReportHook( int aReportT
 }
 
 #endif
 
 static inline void
 DumpVersion()
 {
   if (gAppData->vendor)
-    printf("%s ", gAppData->vendor);
-  printf("%s %s", gAppData->name, gAppData->version);
+    printf("%s ", (const char*) gAppData->vendor);
+  printf("%s %s", (const char*) gAppData->name, (const char*) gAppData->version);
   if (gAppData->copyright)
-      printf(", %s", gAppData->copyright);
+      printf(", %s", (const char*) gAppData->copyright);
   printf("\n");
 }
 
 #ifdef MOZ_ENABLE_XREMOTE
 static RemoteResult
 ParseRemoteCommandLine(nsCString& program,
                        const char** profile,
                        const char** username)
@@ -2798,17 +2798,17 @@ static void MakeOrSetMinidumpPath(nsIFil
 
     nsAutoString pathStr;
     if (NS_SUCCEEDED(dumpD->GetPath(pathStr)))
       CrashReporter::SetMinidumpPath(pathStr);
   }
 }
 #endif
 
-const nsXREAppData* gAppData = nullptr;
+const XREAppData* gAppData = nullptr;
 
 #ifdef MOZ_WIDGET_GTK
 static void MOZ_gdk_display_close(GdkDisplay *display)
 {
 #if CLEANUP_MEMORY
   // XXX wallpaper for bug 417163: don't close the Display if we're using the
   // Qt theme because we crash (in Qt code) when using jemalloc.
   bool skip_display_close = false;
@@ -3015,34 +3015,34 @@ public:
 #endif
   {};
 
   ~XREMain() {
     mScopedXPCOM = nullptr;
     mAppData = nullptr;
   }
 
-  int XRE_main(int argc, char* argv[], const nsXREAppData* aAppData);
+  int XRE_main(int argc, char* argv[], const XREAppData& aAppData);
   int XRE_mainInit(bool* aExitFlag);
   int XRE_mainStartup(bool* aExitFlag);
   nsresult XRE_mainRun();
 
   nsCOMPtr<nsINativeAppSupport> mNativeApp;
   nsCOMPtr<nsIToolkitProfileService> mProfileSvc;
   nsCOMPtr<nsIFile> mProfD;
   nsCOMPtr<nsIFile> mProfLD;
   nsCOMPtr<nsIProfileLock> mProfileLock;
 #ifdef MOZ_ENABLE_XREMOTE
   nsCOMPtr<nsIRemoteService> mRemoteService;
   nsProfileLock mRemoteLock;
   nsCOMPtr<nsIFile> mRemoteLockDir;
 #endif
 
   UniquePtr<ScopedXPCOMStartup> mScopedXPCOM;
-  nsAutoPtr<mozilla::ScopedAppData> mAppData;
+  UniquePtr<XREAppData> mAppData;
 
   nsXREDirProvider mDirProvider;
   nsAutoCString mProfileName;
   nsAutoCString mDesktopStartupID;
 
   bool mStartOffline;
   bool mShuttingDown;
 #ifdef MOZ_ENABLE_XREMOTE
@@ -3154,17 +3154,17 @@ XREMain::XRE_mainInit(bool* aExitFlag)
   else if (ar == ARG_FOUND) {
     nsCOMPtr<nsIFile> overrideLF;
     rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
     if (NS_FAILED(rv)) {
       Output(true, "Error: unrecognized override.ini path.\n");
       return 1;
     }
 
-    rv = XRE_ParseAppData(overrideLF, mAppData.get());
+    rv = XRE_ParseAppData(overrideLF, *mAppData);
     if (NS_FAILED(rv)) {
       Output(true, "Couldn't read override.ini");
       return 1;
     }
   }
 
   // Check sanity and correctness of app data.
 
@@ -3193,43 +3193,41 @@ XREMain::XRE_mainInit(bool* aExitFlag)
 
 #ifdef XP_MACOSX
     nsCOMPtr<nsIFile> parent;
     greDir->GetParent(getter_AddRefs(parent));
     greDir = parent.forget();
     greDir->AppendNative(NS_LITERAL_CSTRING("Resources"));
 #endif
 
-    greDir.forget(&mAppData->xreDirectory);
+    mAppData->xreDirectory = greDir;
   }
 
   if (!mAppData->directory) {
-    NS_IF_ADDREF(mAppData->directory = mAppData->xreDirectory);
+    mAppData->directory = mAppData->xreDirectory;
+  }
+
+  if (!mAppData->minVersion) {
+    Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
+    return 1;
   }
 
-  if (mAppData->size > offsetof(nsXREAppData, minVersion)) {
-    if (!mAppData->minVersion) {
-      Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
-      return 1;
-    }
-
-    if (!mAppData->maxVersion) {
-      // If no maxVersion is specified, we assume the app is only compatible
-      // with the initial preview release. Do not increment this number ever!
-      SetAllocatedString(mAppData->maxVersion, "1.*");
-    }
-
-    if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
-        mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
-      Output(true, "Error: Platform version '%s' is not compatible with\n"
-             "minVersion >= %s\nmaxVersion <= %s\n",
-             gToolkitVersion,
-             mAppData->minVersion, mAppData->maxVersion);
-      return 1;
-    }
+  if (!mAppData->maxVersion) {
+    // If no maxVersion is specified, we assume the app is only compatible
+    // with the initial preview release. Do not increment this number ever!
+    mAppData->maxVersion = "1.*";
+  }
+
+  if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
+      mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
+    Output(true, "Error: Platform version '%s' is not compatible with\n"
+           "minVersion >= %s\nmaxVersion <= %s\n",
+           (const char*) gToolkitVersion, (const char*) mAppData->minVersion,
+           (const char*) mAppData->maxVersion);
+    return 1;
   }
 
   rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
   if (NS_FAILED(rv))
     return 1;
 
 #ifdef MOZ_CRASHREPORTER
   if (EnvHasValue("MOZ_CRASHREPORTER")) {
@@ -4527,17 +4525,17 @@ XRE_CreateStatsObject()
 }
 
 /*
  * XRE_main - A class based main entry point used by most platforms.
  *            Note that on OSX, aAppData->xreDirectory will point to
  *            .app/Contents/Resources.
  */
 int
-XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
+XREMain::XRE_main(int argc, char* argv[], const XREAppData& aAppData)
 {
   ScopedLogging log;
 
   // NB: this must happen after the creation of |ScopedLogging log| since
   // ScopedLogging::ScopedLogging calls NS_LogInit, and
   // XRE_CreateStatsObject calls Telemetry::CreateStatisticsRecorder,
   // and NS_LogInit must be called before Telemetry::CreateStatisticsRecorder.
   // NS_LogInit must be called before Telemetry::CreateStatisticsRecorder
@@ -4556,26 +4554,22 @@ XREMain::XRE_main(int argc, char* argv[]
   PROFILER_LABEL("Startup", "XRE_Main",
     js::ProfileEntry::Category::OTHER);
 
   nsresult rv = NS_OK;
 
   gArgc = argc;
   gArgv = argv;
 
-  NS_ENSURE_TRUE(aAppData, 2);
-
-  mAppData = new ScopedAppData(aAppData);
-  if (!mAppData)
-    return 1;
+  mAppData = MakeUnique<XREAppData>(aAppData);
   if (!mAppData->remotingName) {
-    SetAllocatedString(mAppData->remotingName, mAppData->name);
+    mAppData->remotingName = mAppData->name;
   }
   // used throughout this file
-  gAppData = mAppData;
+  gAppData = mAppData.get();
 
   nsCOMPtr<nsIFile> binFile;
   rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(binFile));
   NS_ENSURE_SUCCESS(rv, 1);
 
   rv = binFile->GetPath(gAbsoluteArgv0Path);
   NS_ENSURE_SUCCESS(rv, 1);
 
@@ -4697,17 +4691,17 @@ XREMain::XRE_main(int argc, char* argv[]
 }
 
 void
 XRE_StopLateWriteChecks(void) {
   mozilla::StopLateWriteChecks();
 }
 
 int
-XRE_main(int argc, char* argv[], const nsXREAppData* aAppData, uint32_t aFlags)
+XRE_main(int argc, char* argv[], const XREAppData& aAppData, uint32_t aFlags)
 {
   XREMain main;
 
   int result = main.XRE_main(argc, argv, aAppData);
   mozilla::RecordShutdownEndTimeStamp();
   return result;
 }
 
--- a/toolkit/xre/nsAppRunner.h
+++ b/toolkit/xre/nsAppRunner.h
@@ -37,20 +37,18 @@ class nsIToolkitProfileService;
 class nsIFile;
 class nsIProfileLock;
 class nsIProfileUnlocker;
 class nsIFactory;
 class nsString;
 
 extern nsXREDirProvider* gDirServiceProvider;
 
-// NOTE: gAppData will be null in embedded contexts. The "size" parameter
-// will be the size of the original structure passed to XRE_main, but the
-// structure will have all of the members available.
-extern const nsXREAppData* gAppData;
+// NOTE: gAppData will be null in embedded contexts.
+extern const mozilla::XREAppData* gAppData;
 extern bool gSafeMode;
 
 extern int    gArgc;
 extern char **gArgv;
 extern int    gRestartArgc;
 extern char **gRestartArgv;
 extern bool gLogConsoleErrors;
 extern nsString gAbsoluteArgv0Path;
--- a/toolkit/xre/nsNativeAppSupportWin.cpp
+++ b/toolkit/xre/nsNativeAppSupportWin.cpp
@@ -680,17 +680,17 @@ nsNativeAppSupportWin::StartDDE() {
     // Initialize DDE.
     NS_ENSURE_TRUE( DMLERR_NO_ERROR == DdeInitialize( &mInstance,
                                                       nsNativeAppSupportWin::HandleDDENotification,
                                                       APPCLASS_STANDARD,
                                                       0 ),
                     NS_ERROR_FAILURE );
 
     // Allocate DDE strings.
-    NS_ENSURE_TRUE( ( mApplication = DdeCreateStringHandleA( mInstance, (char*) gAppData->name, CP_WINANSI ) ) && InitTopicStrings(),
+    NS_ENSURE_TRUE( ( mApplication = DdeCreateStringHandleA( mInstance, (char*)(const char*) gAppData->name, CP_WINANSI ) ) && InitTopicStrings(),
                     NS_ERROR_FAILURE );
 
     // Next step is to register a DDE service.
     NS_ENSURE_TRUE( DdeNameService( mInstance, mApplication, 0, DNS_REGISTER ), NS_ERROR_FAILURE );
 
 #if MOZ_DEBUG_DDE
     printf( "DDE server started\n" );
 #endif
rename from xpcom/build/nsXREAppData.h
rename to xpcom/build/XREAppData.h
--- a/xpcom/build/nsXREAppData.h
+++ b/xpcom/build/XREAppData.h
@@ -4,147 +4,196 @@
  * 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 nsXREAppData_h
 #define nsXREAppData_h
 
 #include <stdint.h>
 #include "mozilla/Attributes.h"
-
-class nsIFile;
+#include "nsCOMPtr.h"
+#include "nsCRTGlue.h"
+#include "nsIFile.h"
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
 namespace sandbox {
 class BrokerServices;
 }
 #endif
 
+namespace mozilla {
+
+struct StaticXREAppData;
+
 /**
  * Application-specific data needed to start the apprunner.
- *
- * @note When this structure is allocated and manipulated by XRE_CreateAppData,
- *       string fields will be allocated with moz_xmalloc, and interface pointers
- *       are strong references.
  */
-struct nsXREAppData
+class XREAppData
 {
-  /**
-   * This should be set to sizeof(nsXREAppData). This structure may be
-   * extended in future releases, and this ensures that binary compatibility
-   * is maintained.
-   */
-  uint32_t size;
+public:
+  XREAppData() { }
+  ~XREAppData() { }
+  XREAppData(const XREAppData& aOther)
+  {
+    *this = aOther;
+  }
+
+  XREAppData& operator=(const StaticXREAppData& aOther);
+  XREAppData& operator=(const XREAppData& aOther);
+  XREAppData& operator=(XREAppData&& aOther) = default;
+
+  struct NSFreePolicy
+  {
+    void operator()(const void* ptr) {
+      NS_Free(const_cast<void*>(ptr));
+    }
+  };
+
+  // Lots of code reads these fields directly like a struct, so rather
+  // than using UniquePtr directly, use an auto-converting wrapper.
+  class CharPtr
+  {
+  public:
+    explicit CharPtr() = default;
+    explicit CharPtr(const char* v)
+    {
+      *this = v;
+    }
+    CharPtr(CharPtr&&) = default;
+    ~CharPtr() = default;
+
+    CharPtr& operator=(const char* v)
+    {
+      if (v) {
+        mValue.reset(NS_strdup(v));
+      } else {
+        mValue = nullptr;
+      }
+      return *this;
+    }
+    CharPtr& operator=(const CharPtr& v)
+    {
+      *this = (const char*) v;
+      return *this;
+    }
+
+    operator const char*() const {
+      return mValue.get();
+    }
+
+  private:
+    UniquePtr<const char, NSFreePolicy> mValue;
+  };
 
   /**
    * The directory of the application to be run. May be null if the
    * xulrunner and the app are installed into the same directory.
    */
-  nsIFile* MOZ_NON_OWNING_REF directory;
+  nsCOMPtr<nsIFile> directory;
 
   /**
    * The name of the application vendor. This must be ASCII, and is normally
    * mixed-case, e.g. "Mozilla". Optional (may be null), but highly
    * recommended. Must not be the empty string.
    */
-  const char* vendor;
+  CharPtr vendor;
 
   /**
    * The name of the application. This must be ASCII, and is normally
    * mixed-case, e.g. "Firefox". Required (must not be null or an empty
    * string).
    */
-  const char* name;
+  CharPtr name;
 
   /**
    * The internal name of the application for remoting purposes. When left
    * unspecified, "name" is used instead. This must be ASCII, and is normally
    * lowercase, e.g. "firefox". Optional (may be null but not an empty string).
    */
-  const char* remotingName;
+  CharPtr remotingName;
 
   /**
    * The major version, e.g. "0.8.0+". Optional (may be null), but
    * required for advanced application features such as the extension
    * manager and update service. Must not be the empty string.
    */
-  const char* version;
+  CharPtr version;
 
   /**
    * The application's build identifier, e.g. "2004051604"
    */
-  const char* buildID;
+  CharPtr buildID;
 
   /**
    * The application's UUID. Used by the extension manager to determine
    * compatible extensions. Optional, but required for advanced application
    * features such as the extension manager and update service.
    *
    * This has traditionally been in the form
    * "{AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE}" but for new applications
    * a more readable form is encouraged: "appname@vendor.tld". Only
    * the following characters are allowed: a-z A-Z 0-9 - . @ _ { } *
    */
-  const char* ID;
+  CharPtr ID;
 
   /**
    * The copyright information to print for the -h commandline flag,
    * e.g. "Copyright (c) 2003 mozilla.org".
    */
-  const char* copyright;
+  CharPtr copyright;
 
   /**
    * Combination of NS_XRE_ prefixed flags (defined below).
    */
-  uint32_t flags;
+  uint32_t flags = 0;
 
   /**
    * The location of the XRE. XRE_main may not be able to figure this out
    * programatically.
    */
-  nsIFile* MOZ_NON_OWNING_REF xreDirectory;
+  nsCOMPtr<nsIFile> xreDirectory;
 
   /**
    * The minimum/maximum compatible XRE version.
    */
-  const char* minVersion;
-  const char* maxVersion;
+  CharPtr minVersion;
+  CharPtr maxVersion;
 
   /**
    * The server URL to send crash reports to.
    */
-  const char* crashReporterURL;
+  CharPtr crashReporterURL;
 
   /**
    * The profile directory that will be used. Optional (may be null). Must not
    * be the empty string, must be ASCII. The path is split into components
    * along the path separator characters '/' and '\'.
    *
    * The application data directory ("UAppData", see below) is normally
    * composed as follows, where $HOME is platform-specific:
    *
    *   UAppData = $HOME[/$vendor]/$name
    *
    * If present, the 'profile' string will be used instead of the combination of
    * vendor and name as follows:
    *
    *   UAppData = $HOME/$profile
    */
-  const char* profile;
+  CharPtr profile;
 
   /**
    * The application name to use in the User Agent string.
    */
-  const char* UAName;
+  CharPtr UAName;
 
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
   /**
    * Chromium sandbox BrokerServices.
    */
-  sandbox::BrokerServices* sandboxBrokerServices;
+  sandbox::BrokerServices* sandboxBrokerServices = nullptr;
 #endif
 };
 
 /**
  * Indicates whether or not the profile migrator service may be
  * invoked at startup when creating a profile.
  */
 #define NS_XRE_ENABLE_PROFILE_MIGRATOR (1 << 1)
@@ -156,9 +205,34 @@ struct nsXREAppData
  */
 #define NS_XRE_DLL_BLOCKLIST_ENABLED (1 << 2)
 
 /**
  * Indicates whether or not to use Breakpad crash reporting.
  */
 #define NS_XRE_ENABLE_CRASH_REPORTER (1 << 3)
 
-#endif // nsXREAppData_h
+/**
+ * A static version of the XRE app data is compiled into the application
+ * so that it is not necessary to read application.ini at startup.
+ *
+ * This structure is initialized into and matches nsXREAppData
+ */
+struct StaticXREAppData
+{
+  const char* vendor;
+  const char* name;
+  const char* remotingName;
+  const char* version;
+  const char* buildID;
+  const char* ID;
+  const char* copyright;
+  uint32_t flags;
+  const char* minVersion;
+  const char* maxVersion;
+  const char* crashReporterURL;
+  const char* profile;
+  const char* UAName;
+};
+
+} // namespace mozilla
+
+#endif // XREAppData_h
--- a/xpcom/build/moz.build
+++ b/xpcom/build/moz.build
@@ -3,32 +3,32 @@
 # 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/.
 
 EXPORTS += [
     'nsXPCOM.h',
     'nsXPCOMCID.h',
     'nsXPCOMCIDInternal.h',
-    'nsXREAppData.h',
     'nsXULAppAPI.h',
     'XREChildData.h',
     'xrecore.h',
     'XREShellData.h',
 ]
 
 EXPORTS.mozilla += [
     'FileLocation.h',
     'IOInterposer.h',
     'LateWriteChecks.h',
     'Omnijar.h',
     'PoisonIOInterposer.h',
     'ServiceList.h',
     'Services.h',
     'XPCOM.h',
+    'XREAppData.h',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     EXPORTS += ['nsWindowsDllInterceptor.h']
     EXPORTS.mozilla += ['perfprobe.h']
     SOURCES += [
         'perfprobe.cpp',
         'PoisonIOInterposerBase.cpp',
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -7,17 +7,17 @@
 #ifndef _nsXULAppAPI_h__
 #define _nsXULAppAPI_h__
 
 #include "nsID.h"
 #include "xrecore.h"
 #include "nsXPCOM.h"
 #include "nsISupports.h"
 #include "mozilla/Logging.h"
-#include "nsXREAppData.h"
+#include "mozilla/XREAppData.h"
 #include "js/TypeDecls.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Vector.h"
 #include "mozilla/TimeStamp.h"
 #include "XREChildData.h"
 #include "XREShellData.h"
@@ -199,17 +199,17 @@
  * @param aFlags    Platform specific flags.
  *
  * @return         A native result code suitable for returning from main().
  *
  * @note           If the binary is linked against the standalone XPCOM glue,
  *                 XPCOMGlueStartup() should be called before this method.
  */
 XRE_API(int,
-        XRE_main, (int argc, char* argv[], const nsXREAppData* aAppData,
+        XRE_main, (int argc, char* argv[], const mozilla::XREAppData& aAppData,
                    uint32_t aFlags))
 
 /**
  * Given a path relative to the current working directory (or an absolute
  * path), return an appropriate nsIFile object.
  *
  * @note Pass UTF8 strings on Windows... native charset on other platforms.
  */
@@ -357,43 +357,25 @@ XRE_API(void,
 
 /**
  * Terminate embedding started with XRE_InitEmbedding or XRE_InitEmbedding2
  */
 XRE_API(void,
         XRE_TermEmbedding, ())
 
 /**
- * Create a new nsXREAppData structure from an application.ini file.
- *
- * @param aINIFile The application.ini file to parse.
- * @param aAppData A newly-allocated nsXREAppData structure. The caller is
- *                 responsible for freeing this structure using
- *                 XRE_FreeAppData.
- */
-XRE_API(nsresult,
-        XRE_CreateAppData, (nsIFile* aINIFile,
-                            nsXREAppData** aAppData))
-
-/**
  * Parse an INI file (application.ini or override.ini) into an existing
  * nsXREAppData structure.
  *
  * @param aINIFile The INI file to parse
  * @param aAppData The nsXREAppData structure to fill.
  */
 XRE_API(nsresult,
         XRE_ParseAppData, (nsIFile* aINIFile,
-                           nsXREAppData* aAppData))
-
-/**
- * Free a nsXREAppData structure that was allocated with XRE_CreateAppData.
- */
-XRE_API(void,
-        XRE_FreeAppData, (nsXREAppData* aAppData))
+                           mozilla::XREAppData& aAppData))
 
 enum GeckoProcessType
 {
   GeckoProcessType_Default = 0,
 
   GeckoProcessType_Plugin,
   GeckoProcessType_Content,
 
deleted file mode 100644
--- a/xpcom/glue/AppData.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- 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_AppData_h
-#define mozilla_AppData_h
-
-#include "nsXREAppData.h"
-#include "nscore.h"
-#include "nsStringGlue.h"
-#include "nsISupportsUtils.h"
-
-namespace mozilla {
-
-// Like nsXREAppData, but releases all strong refs/allocated memory
-// in the destructor.
-class ScopedAppData : public nsXREAppData
-{
-public:
-  ScopedAppData()
-  {
-    Zero();
-    this->size = sizeof(*this);
-  }
-
-  explicit ScopedAppData(const nsXREAppData* aAppData);
-
-  void Zero() { memset(this, 0, sizeof(*this)); }
-
-  ~ScopedAppData();
-};
-
-/**
- * Given |aStr| is holding a string allocated with NS_Alloc, or null:
- * replace the value in |aStr| with a new value.
- *
- * @param aNewValue Null is permitted. The string is cloned with NS_strdup.
- */
-void SetAllocatedString(const char*& aStr, const char* aNewValue);
-
-/**
- * Given "str" is holding a string allocated with NS_Alloc, or null:
- * replace the value in "str" with a new value.
- *
- * @param aNewValue If |aNewValue| is the empty string, |aStr| will be set
- *                  to null.
- */
-void SetAllocatedString(const char*& aStr, const nsACString& aNewValue);
-
-template<class T>
-void
-SetStrongPtr(T*& aPtr, T* aNewValue)
-{
-  NS_IF_RELEASE(aPtr);
-  aPtr = aNewValue;
-  NS_IF_ADDREF(aPtr);
-}
-
-} // namespace mozilla
-
-#endif
rename from xpcom/glue/AppData.cpp
rename to xpcom/glue/XREAppData.cpp
--- a/xpcom/glue/AppData.cpp
+++ b/xpcom/glue/XREAppData.cpp
@@ -1,95 +1,56 @@
 /* -*- 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/. */
 
-#include "mozilla/AppData.h"
-#include "nsXULAppAPI.h"
-#include "nsINIParser.h"
-#include "nsIFile.h"
+#include "mozilla/XREAppData.h"
 #include "nsCRTGlue.h"
-#include "nsAutoPtr.h"
 
 namespace mozilla {
 
-void
-SetAllocatedString(const char*& aStr, const char* aNewValue)
+XREAppData&
+XREAppData::operator=(const StaticXREAppData& aOther)
 {
-  NS_Free(const_cast<char*>(aStr));
-  if (aNewValue) {
-    aStr = NS_strdup(aNewValue);
-  } else {
-    aStr = nullptr;
-  }
-}
+  vendor = aOther.vendor;
+  name = aOther.name;
+  remotingName = aOther.remotingName;
+  version = aOther.version;
+  buildID = aOther.buildID;
+  ID = aOther.ID;
+  copyright = aOther.copyright;
+  flags = aOther.flags;
+  minVersion = aOther.minVersion;
+  maxVersion = aOther.maxVersion;
+  crashReporterURL = aOther.crashReporterURL;
+  profile = aOther.profile;
+  UAName = aOther.UAName;
 
-void
-SetAllocatedString(const char*& aStr, const nsACString& aNewValue)
-{
-  NS_Free(const_cast<char*>(aStr));
-  if (aNewValue.IsEmpty()) {
-    aStr = nullptr;
-  } else {
-    aStr = ToNewCString(aNewValue);
-  }
+  return *this;
 }
 
-ScopedAppData::ScopedAppData(const nsXREAppData* aAppData)
+XREAppData&
+XREAppData::operator=(const XREAppData& aOther)
 {
-  Zero();
-
-  this->size = aAppData->size;
-
-  SetAllocatedString(this->vendor, aAppData->vendor);
-  SetAllocatedString(this->name, aAppData->name);
-  SetAllocatedString(this->remotingName, aAppData->remotingName);
-  SetAllocatedString(this->version, aAppData->version);
-  SetAllocatedString(this->buildID, aAppData->buildID);
-  SetAllocatedString(this->ID, aAppData->ID);
-  SetAllocatedString(this->copyright, aAppData->copyright);
-  SetAllocatedString(this->profile, aAppData->profile);
-  SetStrongPtr(this->directory, aAppData->directory);
-  this->flags = aAppData->flags;
-
-  if (aAppData->size > offsetof(nsXREAppData, xreDirectory)) {
-    SetStrongPtr(this->xreDirectory, aAppData->xreDirectory);
-    SetAllocatedString(this->minVersion, aAppData->minVersion);
-    SetAllocatedString(this->maxVersion, aAppData->maxVersion);
-  }
-
-  if (aAppData->size > offsetof(nsXREAppData, crashReporterURL)) {
-    SetAllocatedString(this->crashReporterURL, aAppData->crashReporterURL);
-  }
-
-  if (aAppData->size > offsetof(nsXREAppData, UAName)) {
-    SetAllocatedString(this->UAName, aAppData->UAName);
-  }
-
+  directory = aOther.directory;
+  vendor = aOther.vendor;
+  name = aOther.name;
+  remotingName = aOther.remotingName;
+  version = aOther.version;
+  buildID = aOther.buildID;
+  ID = aOther.ID;
+  copyright = aOther.copyright;
+  flags = aOther.flags;
+  xreDirectory = aOther.xreDirectory;
+  minVersion = aOther.minVersion;
+  maxVersion = aOther.maxVersion;
+  crashReporterURL = aOther.crashReporterURL;
+  profile = aOther.profile;
+  UAName = aOther.UAName;
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
-  sandboxBrokerServices = aAppData->sandboxBrokerServices;
+  sandboxBrokerServices = aOther.sandboxBrokerServices;
 #endif
-}
-
-ScopedAppData::~ScopedAppData()
-{
-  SetAllocatedString(this->vendor, nullptr);
-  SetAllocatedString(this->name, nullptr);
-  SetAllocatedString(this->remotingName, nullptr);
-  SetAllocatedString(this->version, nullptr);
-  SetAllocatedString(this->buildID, nullptr);
-  SetAllocatedString(this->ID, nullptr);
-  SetAllocatedString(this->copyright, nullptr);
-  SetAllocatedString(this->profile, nullptr);
-
-  NS_IF_RELEASE(this->directory);
-
-  SetStrongPtr(this->xreDirectory, (nsIFile*)nullptr);
-  SetAllocatedString(this->minVersion, nullptr);
-  SetAllocatedString(this->maxVersion, nullptr);
-
-  SetAllocatedString(this->crashReporterURL, nullptr);
-  SetAllocatedString(this->UAName, nullptr);
+  return *this;
 }
 
 } // namespace mozilla
--- a/xpcom/glue/moz.build
+++ b/xpcom/glue/moz.build
@@ -62,17 +62,16 @@ EXPORTS += [
     'nsTWeakRef.h',
     'nsVersionComparator.h',
     'nsWeakReference.h',
     'nsXPTCUtils.h',
     'PLDHashTable.h',
 ]
 
 EXPORTS.mozilla += [
-    'AppData.h',
     'AutoRestore.h',
     'BlockingResourceBase.h',
     'CondVar.h',
     'DeadlockDetector.h',
     'EnumeratedArrayCycleCollection.h',
     'FileUtils.h',
     'GenericFactory.h',
     'IntentionalCrash.h',
--- a/xpcom/glue/objs.mozbuild
+++ b/xpcom/glue/objs.mozbuild
@@ -1,16 +1,15 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 xpcom_glue_src_lcppsrcs = [
-    'AppData.cpp',
     'FileUtils.cpp',
     'nsArrayEnumerator.cpp',
     'nsArrayUtils.cpp',
     'nsCategoryCache.cpp',
     'nsClassInfoImpl.cpp',
     'nsCOMArray.cpp',
     'nsComponentManagerUtils.cpp',
     'nsCOMPtr.cpp',
@@ -25,16 +24,17 @@ xpcom_glue_src_lcppsrcs = [
     'nsMemory.cpp',
     'nsQuickSort.cpp',
     'nsTArray.cpp',
     'nsThreadUtils.cpp',
     'nsTObserverArray.cpp',
     'nsVersionComparator.cpp',
     'nsWeakReference.cpp',
     'PLDHashTable.cpp',
+    'XREAppData.cpp',
 ]
 
 xpcom_glue_src_cppsrcs = [
     '/xpcom/glue/%s' % s for s in xpcom_glue_src_lcppsrcs
 ]
 
 xpcom_gluens_src_lcppsrcs = [
     'BlockingResourceBase.cpp',
--- a/xpcom/system/nsIXULAppInfo.idl
+++ b/xpcom/system/nsIXULAppInfo.idl
@@ -8,46 +8,46 @@
  * A scriptable interface to the nsXULAppAPI structure. See nsXULAppAPI.h for
  * a detailed description of each attribute.
  */
 
 [scriptable, uuid(ddea4f31-3c5e-4769-ac68-21ab4b3d7845)]
 interface nsIXULAppInfo : nsIPlatformInfo
 {
   /**
-   * @see nsXREAppData.vendor
-   * @returns an empty string if nsXREAppData.vendor is not set.
+   * @see XREAppData.vendor
+   * @returns an empty string if XREAppData.vendor is not set.
    */
   readonly attribute ACString vendor;
 
   /**
-   * @see nsXREAppData.name
+   * @see XREAppData.name
    */
   readonly attribute ACString name;
 
   /**
-   * @see nsXREAppData.ID
-   * @returns an empty string if nsXREAppData.ID is not set.
+   * @see XREAppData.ID
+   * @returns an empty string if XREAppData.ID is not set.
    */
   readonly attribute ACString ID;
 
   /**
    * The version of the XUL application. It is different than the
    * version of the XULRunner platform. Be careful about which one you want.
    *
-   * @see nsXREAppData.version
-   * @returns an empty string if nsXREAppData.version is not set.
+   * @see XREAppData.version
+   * @returns an empty string if XREAppData.version is not set.
    */
   readonly attribute ACString version;
 
   /**
    * The build ID/date of the application. For xulrunner applications,
    * this will be different than the build ID of the platform. Be careful
    * about which one you want.
    */
   readonly attribute ACString appBuildID;
 
   /**
-   * @see nsXREAppData.UAName
-   * @returns an empty string if nsXREAppData.UAName is not set.
+   * @see XREAppData.UAName
+   * @returns an empty string if XREAppData.UAName is not set.
    */
   readonly attribute ACString UAName;
 };