Bug 1459349 - Use GeckoRuntime to launch Gecko in Fennec r=jchen
MozReview-Commit-ID: AUrvsFWDuhY
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -118,17 +118,16 @@ public abstract class GeckoApp extends G
ViewTreeObserver.OnGlobalLayoutListener {
private static final String LOGTAG = "GeckoApp";
private static final long ONE_DAY_MS = TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS);
public static final String ACTION_ALERT_CALLBACK = "org.mozilla.gecko.ALERT_CALLBACK";
public static final String ACTION_HOMESCREEN_SHORTCUT = "org.mozilla.gecko.BOOKMARK";
public static final String ACTION_WEBAPP = "org.mozilla.gecko.WEBAPP";
- public static final String ACTION_DEBUG = "org.mozilla.gecko.DEBUG";
public static final String ACTION_LAUNCH_SETTINGS = "org.mozilla.gecko.SETTINGS";
public static final String ACTION_LOAD = "org.mozilla.gecko.LOAD";
public static final String ACTION_INIT_PW = "org.mozilla.gecko.INIT_PW";
public static final String ACTION_SWITCH_TAB = "org.mozilla.gecko.SWITCH_TAB";
public static final String ACTION_SHUTDOWN = "org.mozilla.gecko.SHUTDOWN";
public static final String INTENT_REGISTER_STUMBLER_LISTENER = "org.mozilla.gecko.STUMBLER_REGISTER_LOCAL_LISTENER";
@@ -157,18 +156,16 @@ public abstract class GeckoApp extends G
// Delay before running one-time "cleanup" tasks that may be needed
// after a version upgrade.
private static final int CLEANUP_DEFERRAL_SECONDS = 15;
// Length of time in ms during which crashes are classified as startup crashes
// for crash loop detection purposes.
private static final int STARTUP_PHASE_DURATION_MS = 30 * 1000;
- private static boolean sAlreadyLoaded;
-
protected RelativeLayout mRootLayout;
protected RelativeLayout mMainLayout;
protected RelativeLayout mGeckoLayout;
protected MenuPanel mMenuPanel;
protected Menu mMenu;
protected boolean mIsRestoringActivity;
@@ -997,32 +994,29 @@ public abstract class GeckoApp extends G
// restart, and will be propagated to Gecko accordingly, so there's
// no need to touch that here.
if (BrowserLocaleManager.getInstance().systemLocaleDidChange()) {
Log.i(LOGTAG, "System locale changed. Restarting.");
finishAndShutdown(/* restart */ true);
return;
}
- if (sAlreadyLoaded) {
+ if (GeckoApplication.getRuntime() != null) {
// This happens when the GeckoApp activity is destroyed by Android
// without killing the entire application (see Bug 769269).
// In case we have multiple GeckoApp-based activities, this can
// also happen if we're not the first activity to run within a session.
mIsRestoringActivity = true;
Telemetry.addToHistogram("FENNEC_RESTORING_ACTIVITY", 1);
} else {
final String action = intent.getAction();
final String[] args = GeckoApplication.getDefaultGeckoArgs();
- final int flags = ACTION_DEBUG.equals(action) ? GeckoThread.FLAG_DEBUGGING : 0;
-
- sAlreadyLoaded = true;
- GeckoThread.initMainProcess(/* profile */ null, args,
- intent.getExtras(), flags);
+
+ GeckoApplication.createRuntime(this, intent);
// Speculatively pre-fetch the profile in the background.
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
getProfile();
}
});
@@ -1041,18 +1035,16 @@ public abstract class GeckoApp extends G
EventDispatcher.getInstance().registerUiThreadListener(this,
"Gecko:CorruptAPK",
"Update:Check",
"Update:Download",
"Update:Install",
null);
- GeckoThread.launch();
-
Bundle stateBundle = IntentUtils.getBundleExtraSafe(getIntent(), EXTRA_STATE_BUNDLE);
if (stateBundle != null) {
// Use the state bundle if it was given as an intent extra. This is
// only intended to be used internally via Robocop, so a boolean
// is read from a private shared pref to prevent other apps from
// injecting states.
final SharedPreferences prefs = getSharedPreferences();
if (prefs.getBoolean(PREFS_ALLOW_STATE_BUNDLE, false)) {
@@ -1080,17 +1072,17 @@ public abstract class GeckoApp extends G
session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
"chrome://browser/content/browser.xul");
session.setContentDelegate(this);
// If the view already has a session, we need to ensure it is closed.
if (mLayerView.getSession() != null) {
mLayerView.getSession().close();
}
- mLayerView.setSession(session, GeckoRuntime.getDefault(this));
+ mLayerView.setSession(session, GeckoApplication.getRuntime());
mLayerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
getAppEventDispatcher().registerGeckoThreadListener(this,
"Locale:Set",
"PrivateBrowsing:Data",
null);
getAppEventDispatcher().registerUiThreadListener(this,
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -8,20 +8,22 @@ import android.Manifest;
import android.app.Activity;
import android.app.Application;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.os.SystemClock;
import android.provider.MediaStore;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;
@@ -33,31 +35,34 @@ import org.mozilla.gecko.db.LocalBrowser
import org.mozilla.gecko.distribution.Distribution;
import org.mozilla.gecko.home.HomePanelsManager;
import org.mozilla.gecko.icons.IconCallback;
import org.mozilla.gecko.icons.IconResponse;
import org.mozilla.gecko.icons.Icons;
import org.mozilla.gecko.lwt.LightweightTheme;
import org.mozilla.gecko.mdns.MulticastDNSManager;
import org.mozilla.gecko.media.AudioFocusAgent;
+import org.mozilla.gecko.mozglue.SafeIntent;
import org.mozilla.gecko.notifications.NotificationClient;
import org.mozilla.gecko.notifications.NotificationHelper;
import org.mozilla.gecko.permissions.Permissions;
import org.mozilla.gecko.preferences.DistroSharedPrefsImport;
import org.mozilla.gecko.pwa.PwaUtils;
import org.mozilla.gecko.telemetry.TelemetryBackgroundReceiver;
import org.mozilla.gecko.util.ActivityResultHandler;
import org.mozilla.gecko.util.BitmapUtils;
import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.PRNGFixes;
import org.mozilla.gecko.util.ShortcutUtils;
import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.geckoview.GeckoRuntime;
+import org.mozilla.geckoview.GeckoRuntimeSettings;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.UUID;
@@ -205,16 +210,55 @@ public class GeckoApplication extends Ap
GeckoThread.onResume();
mPausedGecko = false;
GeckoNetworkManager.getInstance().start(this);
}
mInBackground = false;
}
+ private static GeckoRuntime sGeckoRuntime;
+ public static synchronized GeckoRuntime getRuntime() {
+ return sGeckoRuntime;
+ }
+
+ public static synchronized GeckoRuntime ensureRuntime(@NonNull Context context) {
+ if (sGeckoRuntime != null) {
+ return sGeckoRuntime;
+ }
+
+ return createRuntime(context, null);
+ }
+
+ public static synchronized GeckoRuntime createRuntime(@NonNull Context context,
+ @Nullable SafeIntent intent) {
+ if (sGeckoRuntime != null) {
+ throw new IllegalStateException("Already have a GeckoRuntime!");
+ }
+
+ if (context == null) {
+ throw new IllegalArgumentException("Context must not be null");
+ }
+
+ GeckoRuntimeSettings.Builder builder = new GeckoRuntimeSettings.Builder()
+ .javaCrashReportingEnabled(true)
+ .nativeCrashReportingEnabled(true)
+ .arguments(getDefaultGeckoArgs());
+
+ if (intent != null) {
+ Bundle extras = intent.getExtras();
+ if (extras != null) {
+ builder.extras(extras);
+ }
+ }
+
+ sGeckoRuntime = GeckoRuntime.create(context, builder.build());
+ return sGeckoRuntime;
+ }
+
@Override
public void onCreate() {
Log.i(LOG_TAG, "zerdatime " + SystemClock.elapsedRealtime() +
" - application start");
final Context oldContext = GeckoAppShell.getApplicationContext();
if (oldContext instanceof GeckoApplication) {
((GeckoApplication) oldContext).onDestroy();
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoService.java
@@ -187,17 +187,17 @@ public class GeckoService extends Servic
Log.d(LOGTAG, "Handling " + intent.getAction());
}
if (!initGecko(intent)) {
stopSelf(startId);
return Service.START_NOT_STICKY;
}
- GeckoThread.launch();
+ GeckoApplication.ensureRuntime(this);
switch (intent.getAction()) {
case INTENT_ACTION_UPDATE_ADDONS:
// Run the add-on update service. Because the service is automatically invoked
// when loading Gecko, we don't have to do anything else here.
case INTENT_ACTION_LOAD_LIBS:
// Load libs only. Don't take any additional actions.
case INTENT_ACTION_START_GECKO:
--- a/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
@@ -127,17 +127,17 @@ class VirtualPresentation extends CastPr
final GeckoSession session = new GeckoSession();
session.getSettings().setString(GeckoSessionSettings.CHROME_URI,
PRESENTATION_VIEW_URI + "#" + deviceId);
session.getSettings().setInt(GeckoSessionSettings.SCREEN_ID, screenId);
// Create new GeckoView
view = new GeckoView(getContext());
- view.setSession(session, GeckoRuntime.getDefault(getContext()));
+ view.setSession(session, GeckoApplication.ensureRuntime(getContext()));
view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
// Create new layout to put the GeckoView
layout = new RelativeLayout(getContext());
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
layout.addView(view);
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -32,16 +32,17 @@ import android.view.View;
import android.widget.ProgressBar;
import org.mozilla.gecko.ActivityHandlerHelper;
import org.mozilla.gecko.BrowserApp;
import org.mozilla.gecko.Clipboard;
import org.mozilla.gecko.DoorHangerPopup;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.FormAssistPopup;
+import org.mozilla.gecko.GeckoApplication;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.preferences.GeckoPreferences;
import org.mozilla.gecko.R;
import org.mozilla.gecko.SnackbarBuilder;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.menu.GeckoMenuInflater;
@@ -126,17 +127,17 @@ public class CustomTabsActivity extends
final GeckoSessionSettings settings = new GeckoSessionSettings();
settings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, false);
mGeckoSession = new GeckoSession(settings);
mGeckoSession.setNavigationDelegate(this);
mGeckoSession.setProgressDelegate(this);
mGeckoSession.setContentDelegate(this);
- mGeckoView.setSession(mGeckoSession, GeckoRuntime.getDefault(this));
+ mGeckoView.setSession(mGeckoSession, GeckoApplication.ensureRuntime(this));
mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
mFormAssistPopup = (FormAssistPopup) findViewById(R.id.form_assist_popup);
mFormAssistPopup.create(mGeckoView);
mTextSelection = TextSelection.Factory.create(mGeckoView, this);
--- a/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
@@ -21,16 +21,17 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import org.mozilla.gecko.ActivityHandlerHelper;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.BrowserApp;
import org.mozilla.gecko.DoorHangerPopup;
import org.mozilla.gecko.FormAssistPopup;
+import org.mozilla.gecko.GeckoApplication;
import org.mozilla.gecko.GeckoScreenOrientation;
import org.mozilla.gecko.GeckoSharedPrefs;
import org.mozilla.gecko.preferences.GeckoPreferences;
import org.mozilla.gecko.R;
import org.mozilla.gecko.customtabs.CustomTabsActivity;
import org.mozilla.gecko.permissions.Permissions;
import org.mozilla.gecko.prompts.PromptService;
import org.mozilla.gecko.text.TextSelection;
@@ -92,17 +93,17 @@ public class WebAppActivity extends AppC
super.onCreate(savedInstanceState);
setContentView(R.layout.webapp_activity);
mGeckoView = (GeckoView) findViewById(R.id.pwa_gecko_view);
final GeckoSessionSettings settings = new GeckoSessionSettings();
settings.setBoolean(GeckoSessionSettings.USE_MULTIPROCESS, false);
mGeckoSession = new GeckoSession(settings);
- mGeckoView.setSession(mGeckoSession, GeckoRuntime.getDefault(this));
+ mGeckoView.setSession(mGeckoSession, GeckoApplication.ensureRuntime(this));
mGeckoSession.setNavigationDelegate(this);
mGeckoSession.setContentDelegate(this);
mGeckoSession.setProgressDelegate(new GeckoSession.ProgressDelegate() {
@Override
public void onPageStart(GeckoSession session, String url) {
}