Index: chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeLifetimeController.java |
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeLifetimeController.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeLifetimeController.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7a060c88f41684aa8eadba71b2ac7b96f0e8413f |
--- /dev/null |
+++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/ChromeLifetimeController.java |
@@ -0,0 +1,106 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.chrome.browser; |
+ |
+import android.app.Activity; |
+import android.app.AlarmManager; |
+import android.app.PendingIntent; |
+import android.content.Context; |
+import android.content.Intent; |
+import android.os.Handler; |
+import android.os.Looper; |
+import android.os.Process; |
+import android.util.Log; |
+ |
+import org.chromium.base.ActivityState; |
+import org.chromium.base.ApplicationStatus; |
+ |
+import java.lang.ref.WeakReference; |
+ |
+/** |
+ * Handles killing and potentially restarting Chrome's main Browser process. Note that this class |
+ * relies on main Chrome activities to properly call {@link Activity#finish()} on themselves so that |
+ * it will be notified that all {@link Activity}s under this {@link Application} have been |
+ * destroyed. |
+ */ |
+class ChromeLifetimeController implements ApplicationLifetime.Observer, |
+ ApplicationStatus.ActivityStateListener { |
+ private static final String TAG = "ChromeLifetimeController"; |
+ |
+ private final Context mContext; |
+ private boolean mRestartChromeOnDestroy; |
+ private int mRemainingActivitiesCount = 0; |
+ |
+ /** |
+ * Creates a {@link ChromeLifetimeController} instance. |
+ * @param context A {@link Context} instance. The application context will be saved from this |
+ * one. |
+ */ |
+ public ChromeLifetimeController(Context context) { |
+ mContext = context.getApplicationContext(); |
+ ApplicationLifetime.addObserver(this); |
+ } |
+ |
+ @Override |
+ public void onTerminate(boolean restart) { |
+ mRestartChromeOnDestroy = restart; |
+ |
+ // We've called terminate twice, just wait for the first call to take effect. |
+ if (mRemainingActivitiesCount > 0) { |
+ Log.w(TAG, "onTerminate called twice"); |
+ return; |
+ } |
+ |
+ for (WeakReference<Activity> weakActivity : ApplicationStatus.getRunningActivities()) { |
+ Activity activity = weakActivity.get(); |
+ if (activity != null) { |
+ ApplicationStatus.registerStateListenerForActivity(this, activity); |
+ mRemainingActivitiesCount++; |
+ activity.finish(); |
+ } |
+ } |
+ } |
+ |
+ |
+ @Override |
+ public void onActivityStateChange(Activity activity, int newState) { |
+ assert mRemainingActivitiesCount > 0; |
+ if (newState == ActivityState.DESTROYED) { |
+ mRemainingActivitiesCount--; |
+ if (mRemainingActivitiesCount == 0) { |
+ destroyProcess(); |
+ } |
+ } |
+ |
+ } |
+ |
+ private void destroyProcess() { |
+ Handler handler = new Handler(Looper.getMainLooper()); |
+ handler.post(new Runnable() { |
+ @Override |
+ public void run() { |
+ if (mRestartChromeOnDestroy) scheduleRestart(mContext); |
+ |
+ Log.w(TAG, "Forcefully killing process..."); |
+ Process.killProcess(Process.myPid()); |
+ |
+ mRestartChromeOnDestroy = false; |
+ } |
+ }); |
+ } |
+ |
+ private static void scheduleRestart(Context context) { |
+ Intent intent = new Intent(); |
+ intent.setPackage(context.getPackageName()); |
+ intent.setAction(Intent.ACTION_MAIN); |
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, |
+ PendingIntent.FLAG_ONE_SHOT); |
+ if (pendingIntent != null) { |
+ AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); |
+ am.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pendingIntent); |
+ } |
+ } |
+} |