Bug 1471025: Part 3c - Also pass the shared preference map handle to Android content processes. r?jld draft
authorKris Maglione <maglione.k@gmail.com>
Mon, 02 Jul 2018 15:17:48 -0700
changeset 815376 7413e7fd2f52bf837910bdb00154ae84d6844368
parent 815375 2e574a3f1c4234758d9dd2f6b222f64c3aeb1971
child 815377 5ccdaed92b8a0e633cacbb7fc3f52579dba9ecfe
push id115503
push usermaglione.k@gmail.com
push dateSat, 07 Jul 2018 19:50:37 +0000
reviewersjld
bugs1471025
milestone63.0a1
Bug 1471025: Part 3c - Also pass the shared preference map handle to Android content processes. r?jld MozReview-Commit-ID: CTjDzVC9gcD
dom/ipc/ContentProcess.cpp
dom/ipc/ContentProcess.h
ipc/glue/GeckoChildProcessHost.cpp
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IChildProcess.aidl
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
mozglue/android/APKOpen.cpp
toolkit/xre/nsEmbedFunctions.cpp
xpcom/build/nsXULAppAPI.h
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -78,22 +78,29 @@ SetUpSandboxEnvironment()
   }
 
   SetTmpEnvironmentVariable(sandboxedContentTemp);
 }
 #endif
 
 #ifdef ANDROID
 static int gPrefsFd = -1;
+static int gPrefMapFd = -1;
 
 void
 SetPrefsFd(int aFd)
 {
   gPrefsFd = aFd;
 }
+
+void
+SetPrefMapFd(int aFd)
+{
+  gPrefMapFd = aFd;
+}
 #endif
 
 bool
 ContentProcess::Init(int aArgc, char* aArgv[])
 {
   Maybe<uint64_t> childID;
   Maybe<bool> isForBrowser;
   Maybe<base::SharedMemoryHandle> prefsHandle;
@@ -223,16 +230,19 @@ ContentProcess::Init(int aArgc, char* aA
 #endif /* XP_MACOSX && MOZ_CONTENT_SANDBOX */
     }
   }
 
 #ifdef ANDROID
   // Android is different; get the FD via gPrefsFd instead of a fixed fd.
   MOZ_RELEASE_ASSERT(gPrefsFd != -1);
   prefsHandle = Some(base::FileDescriptor(gPrefsFd, /* auto_close */ true));
+
+  FileDescriptor::UniquePlatformHandle handle(gPrefMapFd);
+  prefMapHandle.emplace(handle.get());
 #elif XP_UNIX
   prefsHandle = Some(base::FileDescriptor(kPrefsFileDescriptor,
                                           /* auto_close */ true));
 
   // The FileDescriptor constructor will clone this handle when constructed,
   // so store it in a UniquePlatformHandle to make sure the original gets
   // closed.
   FileDescriptor::UniquePlatformHandle handle(kPrefMapFileDescriptor);
--- a/dom/ipc/ContentProcess.h
+++ b/dom/ipc/ContentProcess.h
@@ -45,16 +45,17 @@ private:
   // This object initializes and configures COM.
   mozilla::mscom::MainThreadRuntime mCOMRuntime;
 #endif
 
   DISALLOW_EVIL_CONSTRUCTORS(ContentProcess);
 };
 
 #ifdef ANDROID
-// Android doesn't use -prefsHandle, it gets that FD another way.
+// Android doesn't use -prefsHandle, it gets that FDs another way.
 void SetPrefsFd(int aFd);
+void SetPrefMapFd(int aFd);
 #endif
 
 } // namespace dom
 } // namespace mozilla
 
 #endif  // ifndef dom_tabs_ContentThread_h
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -1253,26 +1253,27 @@ GeckoChildProcessHost::LaunchAndroidServ
   }
 
   // XXX: this processing depends entirely on the internals of
   // ContentParent::LaunchSubprocess()
   // GeckoChildProcessHost::PerformAsyncLaunchInternal(), and the order in
   // which they append to fds_to_remap. There must be a better way to do it.
   // See bug 1440207.
   int32_t prefsFd = fds_to_remap[0].first;
-  int32_t ipcFd = fds_to_remap[1].first;
+  int32_t prefMapFd = fds_to_remap[1].first;
+  int32_t ipcFd = fds_to_remap[2].first;
   int32_t crashFd = -1;
   int32_t crashAnnotationFd = -1;
-  if (fds_to_remap.size() == 3) {
-    crashAnnotationFd = fds_to_remap[2].first;
-  }
   if (fds_to_remap.size() == 4) {
-    crashFd = fds_to_remap[2].first;
     crashAnnotationFd = fds_to_remap[3].first;
   }
+  if (fds_to_remap.size() == 5) {
+    crashFd = fds_to_remap[3].first;
+    crashAnnotationFd = fds_to_remap[4].first;
+  }
 
-  int32_t handle = java::GeckoProcessManager::Start(type, jargs, prefsFd, ipcFd, crashFd, crashAnnotationFd);
+  int32_t handle = java::GeckoProcessManager::Start(type, jargs, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd);
 
   if (process_handle) {
     *process_handle = handle;
   }
 }
 #endif
--- a/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IChildProcess.aidl
+++ b/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IChildProcess.aidl
@@ -7,14 +7,15 @@ package org.mozilla.gecko.process;
 import org.mozilla.gecko.process.IProcessManager;
 
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 
 interface IChildProcess {
     int getPid();
     boolean start(in IProcessManager procMan, in String[] args, in Bundle extras, int flags,
-                  in ParcelFileDescriptor prefsPfd, in ParcelFileDescriptor ipcPfd,
+                  in ParcelFileDescriptor prefsPfd, in ParcelFileDescriptor prefMapPfd,
+                  in ParcelFileDescriptor ipcPfd,
                   in ParcelFileDescriptor crashReporterPfd,
                   in ParcelFileDescriptor crashAnnotationPfd);
 
     void crash();
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
@@ -127,16 +127,17 @@ public class GeckoThread extends Thread 
     // Main process parameters
     public static final int FLAG_DEBUGGING = 1 << 0; // Debugging mode.
     public static final int FLAG_PRELOAD_CHILD = 1 << 1; // Preload child during main thread start.
     public static final int FLAG_ENABLE_NATIVE_CRASHREPORTER = 1 << 2; // Enable native crash reporting
     public static final int FLAG_ENABLE_JAVA_CRASHREPORTER = 1 << 3; // Enable java crash reporting
 
     /* package */ static final String EXTRA_ARGS = "args";
     private static final String EXTRA_PREFS_FD = "prefsFd";
+    private static final String EXTRA_PREF_MAP_FD = "prefMapFd";
     private static final String EXTRA_IPC_FD = "ipcFd";
     private static final String EXTRA_CRASH_FD = "crashFd";
     private static final String EXTRA_CRASH_ANNOTATION_FD = "crashAnnotationFd";
 
     private boolean mInitialized;
     private GeckoProfile mProfile;
     private String[] mArgs;
     private Bundle mExtras;
@@ -148,56 +149,60 @@ public class GeckoThread extends Thread 
 
     @WrapForJNI
     private static boolean isChildProcess() {
         return INSTANCE.mExtras.getInt(EXTRA_IPC_FD, -1) != -1;
     }
 
     private synchronized boolean init(final GeckoProfile profile, final String[] args,
                                       final Bundle extras, final int flags,
-                                      final int prefsFd, final int ipcFd,
+                                      final int prefsFd, final int prefMapFd,
+                                      final int ipcFd,
                                       final int crashFd,
                                       final int crashAnnotationFd) {
         ThreadUtils.assertOnUiThread();
         uiThreadId = android.os.Process.myTid();
 
         if (mInitialized) {
             return false;
         }
 
         mProfile = profile;
         mArgs = args;
         mFlags = flags;
 
         mExtras = (extras != null) ? new Bundle(extras) : new Bundle(3);
         mExtras.putInt(EXTRA_PREFS_FD, prefsFd);
+        mExtras.putInt(EXTRA_PREF_MAP_FD, prefMapFd);
         mExtras.putInt(EXTRA_IPC_FD, ipcFd);
         mExtras.putInt(EXTRA_CRASH_FD, crashFd);
         mExtras.putInt(EXTRA_CRASH_ANNOTATION_FD, crashAnnotationFd);
 
         mInitialized = true;
         notifyAll();
         return true;
     }
 
     public static boolean initMainProcess(final GeckoProfile profile, final String[] args,
                                           final Bundle extras, final int flags) {
         return INSTANCE.init(profile, args, extras, flags, /* fd */ -1,
-                             /* fd */ -1, /* fd */ -1, /* fd */ -1);
+                             /* fd */ -1, /* fd */ -1, /* fd */ -1,
+                             /* fd */ -1);
     }
 
     public static boolean initChildProcess(final String[] args,
                                            final Bundle extras,
                                            final int flags,
                                            final int prefsFd,
+                                           final int prefMapFd,
                                            final int ipcFd,
                                            final int crashFd,
                                            final int crashAnnotationFd) {
         return INSTANCE.init(/* profile */ null, args, extras, flags,
-                             prefsFd, ipcFd, crashFd, crashAnnotationFd);
+                             prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd);
     }
 
     private static boolean canUseProfile(final Context context, final GeckoProfile profile,
                                          final String profileName, final File profileDir) {
         if (profileDir != null && !profileDir.isDirectory()) {
             return false;
         }
 
@@ -492,16 +497,17 @@ public class GeckoThread extends Thread 
             GeckoAppShell.ensureCrashHandling();
         }
 
         GeckoLoader.setupGeckoEnvironment(context, context.getFilesDir().getPath(), env);
 
         // And go.
         GeckoLoader.nativeRun(args,
                               mExtras.getInt(EXTRA_PREFS_FD, -1),
+                              mExtras.getInt(EXTRA_PREF_MAP_FD, -1),
                               mExtras.getInt(EXTRA_IPC_FD, -1),
                               mExtras.getInt(EXTRA_CRASH_FD, -1),
                               mExtras.getInt(EXTRA_CRASH_ANNOTATION_FD, -1));
 
         // And... we're done.
         final boolean restarting = isState(State.RESTARTING);
         setState(State.EXITED);
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
@@ -451,15 +451,15 @@ public final class GeckoLoader {
         }
     }
 
     // These methods are implemented in mozglue/android/nsGeckoUtils.cpp
     private static native void putenv(String map);
     public static native boolean verifyCRCs(String apkName);
 
     // These methods are implemented in mozglue/android/APKOpen.cpp
-    public static native void nativeRun(String[] args, int prefsFd, int ipcFd, int crashFd, int crashAnnotationFd);
+    public static native void nativeRun(String[] args, int prefsFd, int prefMapFd, int ipcFd, int crashFd, int crashAnnotationFd);
     private static native void loadGeckoLibsNative(String apkName);
     private static native void loadSQLiteLibsNative(String apkName);
     private static native void loadNSSLibsNative(String apkName);
     public static native boolean neonCompatible();
     public static native void suppressCrashDialog();
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
@@ -177,67 +177,71 @@ public final class GeckoProcessManager e
         try {
             mConnections.get("tab").bind().crash();
         } catch (RemoteException e) {
         }
     }
 
     @WrapForJNI
     private static int start(final String type, final String[] args,
-                             final int prefsFd, final int ipcFd,
+                             final int prefsFd, final int prefMapFd,
+                             final int ipcFd,
                              final int crashFd, final int crashAnnotationFd) {
-        return INSTANCE.start(type, args, prefsFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
+        return INSTANCE.start(type, args, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
     }
 
     private int filterFlagsForChild(int flags) {
         return flags & (GeckoThread.FLAG_ENABLE_JAVA_CRASHREPORTER |
                 GeckoThread.FLAG_ENABLE_NATIVE_CRASHREPORTER);
     }
 
-    private int start(final String type, final String[] args, final int prefsFd,
+    private int start(final String type, final String[] args,
+                      final int prefsFd, final int prefMapFd,
                       final int ipcFd, final int crashFd,
                       final int crashAnnotationFd, final boolean retry) {
         final ChildConnection connection = getConnection(type);
         final IChildProcess child = connection.bind();
         if (child == null) {
             return 0;
         }
 
         final Bundle extras = GeckoThread.getActiveExtras();
         final ParcelFileDescriptor prefsPfd;
+        final ParcelFileDescriptor prefMapPfd;
         final ParcelFileDescriptor ipcPfd;
         final ParcelFileDescriptor crashPfd;
         final ParcelFileDescriptor crashAnnotationPfd;
         try {
             prefsPfd = ParcelFileDescriptor.fromFd(prefsFd);
+            prefMapPfd = ParcelFileDescriptor.fromFd(prefMapFd);
             ipcPfd = ParcelFileDescriptor.fromFd(ipcFd);
             crashPfd = (crashFd >= 0) ? ParcelFileDescriptor.fromFd(crashFd) : null;
             crashAnnotationPfd = (crashAnnotationFd >= 0) ? ParcelFileDescriptor.fromFd(crashAnnotationFd) : null;
         } catch (final IOException e) {
             Log.e(LOGTAG, "Cannot create fd for " + type, e);
             return 0;
         }
 
         final int flags = filterFlagsForChild(GeckoThread.getActiveFlags());
 
         boolean started = false;
         try {
-            started = child.start(this, args, extras, flags, prefsPfd, ipcPfd, crashPfd,
-                                  crashAnnotationPfd);
+            started = child.start(this, args, extras, flags, prefsPfd, prefMapPfd,
+                                  ipcPfd, crashPfd, crashAnnotationPfd);
         } catch (final RemoteException e) {
         }
 
         if (!started) {
             if (retry) {
                 Log.e(LOGTAG, "Cannot restart child " + type);
                 return 0;
             }
             Log.w(LOGTAG, "Attempting to kill running child " + type);
             connection.unbind();
-            return start(type, args, prefsFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ true);
+            return start(type, args, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ true);
         }
 
         try {
             if (crashAnnotationPfd != null) {
                 crashAnnotationPfd.close();
             }
             if (crashPfd != null) {
                 crashPfd.close();
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
@@ -57,39 +57,41 @@ public class GeckoServiceChildProcess ex
         }
 
         @Override
         public boolean start(final IProcessManager procMan,
                              final String[] args,
                              final Bundle extras,
                              final int flags,
                              final ParcelFileDescriptor prefsPfd,
+                             final ParcelFileDescriptor prefMapPfd,
                              final ParcelFileDescriptor ipcPfd,
                              final ParcelFileDescriptor crashReporterPfd,
                              final ParcelFileDescriptor crashAnnotationPfd) {
             synchronized (GeckoServiceChildProcess.class) {
                 if (sProcessManager != null) {
                     Log.e(LOGTAG, "Child process already started");
                     return false;
                 }
                 sProcessManager = procMan;
             }
 
             final int prefsFd = prefsPfd.detachFd();
+            final int prefMapFd = prefMapPfd.detachFd();
             final int ipcFd = ipcPfd.detachFd();
             final int crashReporterFd = crashReporterPfd != null ?
                                         crashReporterPfd.detachFd() : -1;
             final int crashAnnotationFd = crashAnnotationPfd != null ?
                                           crashAnnotationPfd.detachFd() : -1;
 
             ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
-                    if (GeckoThread.initChildProcess(args, extras, flags, prefsFd, ipcFd, crashReporterFd,
-                                                     crashAnnotationFd)) {
+                    if (GeckoThread.initChildProcess(args, extras, flags, prefsFd, prefMapFd, ipcFd,
+                                                     crashReporterFd, crashAnnotationFd)) {
                         GeckoThread.launch();
                     }
                 }
             });
             return true;
         }
 
         @Override
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -388,32 +388,32 @@ 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);
 }
 
 extern "C" APKOPEN_EXPORT void MOZ_JNICALL
-Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int prefsFd, int ipcFd, int crashFd, int crashAnnotationFd)
+Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int prefsFd, int prefMapFd, int ipcFd, int crashFd, int crashAnnotationFd)
 {
   int argc = 0;
   char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
 
   if (ipcFd < 0) {
     if (gBootstrap == nullptr) {
       FreeArgv(argv, argc);
       return;
     }
 
     ElfLoader::Singleton.ExpectShutdown(false);
     gBootstrap->GeckoStart(jenv, argv, argc, sAppData);
     ElfLoader::Singleton.ExpectShutdown(true);
   } else {
-    gBootstrap->XRE_SetAndroidChildFds(jenv, { prefsFd, ipcFd, crashFd, crashAnnotationFd });
+    gBootstrap->XRE_SetAndroidChildFds(jenv, { prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd });
     gBootstrap->XRE_SetProcessType(argv[argc - 1]);
 
     XREChildData childData;
     gBootstrap->XRE_InitChildProcess(argc - 1, argv, &childData);
   }
 
   gBootstrap.reset();
   FreeArgv(argv, argc);
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -243,16 +243,17 @@ GeckoProcessType sChildProcessType = Gec
 } // namespace mozilla
 
 #if defined(MOZ_WIDGET_ANDROID)
 void
 XRE_SetAndroidChildFds (JNIEnv* env, const XRE_AndroidChildFds& fds)
 {
   mozilla::jni::SetGeckoThreadEnv(env);
   mozilla::dom::SetPrefsFd(fds.mPrefsFd);
+  mozilla::dom::SetPrefMapFd(fds.mPrefMapFd);
   IPC::Channel::SetClientChannelFd(fds.mIpcFd);
   CrashReporter::SetNotificationPipeForChild(fds.mCrashFd);
   CrashReporter::SetCrashAnnotationPipeForChild(fds.mCrashAnnotationFd);
 }
 #endif // defined(MOZ_WIDGET_ANDROID)
 
 void
 XRE_SetProcessType(const char* aProcessTypeString)
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -395,16 +395,17 @@ static_assert(MOZ_ARRAY_LENGTH(kGeckoPro
 
 XRE_API(const char*,
         XRE_ChildProcessTypeToString, (GeckoProcessType aProcessType))
 
 #if defined(MOZ_WIDGET_ANDROID)
 struct XRE_AndroidChildFds
 {
   int mPrefsFd;
+  int mPrefMapFd;
   int mIpcFd;
   int mCrashFd;
   int mCrashAnnotationFd;
 };
 
 XRE_API(void,
         XRE_SetAndroidChildFds, (JNIEnv* env, const XRE_AndroidChildFds& fds))
 #endif // defined(MOZ_WIDGET_ANDROID)