diff options
author | John Reck <jreck@google.com> | 2011-04-14 17:02:18 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2011-04-14 17:18:33 -0700 |
commit | 847b532045e3cb117a847ebb956c9919401f332d (patch) | |
tree | d77224bee94f8e86f3571044fe4bf1900f643fed /src/com/android/browser | |
parent | 94dbea662ef66fb22b7184cee2322f2a18ba496a (diff) | |
download | packages_apps_Browser-847b532045e3cb117a847ebb956c9919401f332d.zip packages_apps_Browser-847b532045e3cb117a847ebb956c9919401f332d.tar.gz packages_apps_Browser-847b532045e3cb117a847ebb956c9919401f332d.tar.bz2 |
Recover tabs in the event of a crash
Change-Id: Ia47a5bc1e659e46e7f29a8cec52b6fd2ed675be4
Diffstat (limited to 'src/com/android/browser')
-rw-r--r-- | src/com/android/browser/BaseUi.java | 2 | ||||
-rw-r--r-- | src/com/android/browser/Controller.java | 23 | ||||
-rw-r--r-- | src/com/android/browser/CrashRecoveryHandler.java | 120 | ||||
-rw-r--r-- | src/com/android/browser/Tab.java | 3 | ||||
-rw-r--r-- | src/com/android/browser/XLargeUi.java | 5 |
5 files changed, 144 insertions, 9 deletions
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java index 548292a..b7964dc 100644 --- a/src/com/android/browser/BaseUi.java +++ b/src/com/android/browser/BaseUi.java @@ -226,7 +226,7 @@ public abstract class BaseUi implements UI, WebViewFactory { @Override public boolean needsRestoreAllTabs() { - return false; + return true; } @Override diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java index e8e13d1..2f47cad 100644 --- a/src/com/android/browser/Controller.java +++ b/src/com/android/browser/Controller.java @@ -47,6 +47,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; +import android.os.Parcel; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.preference.PreferenceActivity; @@ -83,6 +84,7 @@ import android.widget.Toast; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.net.URLEncoder; import java.util.Calendar; import java.util.HashMap; @@ -198,6 +200,7 @@ public class Controller // Tabs' notion of whether they represent bookmarked sites. private ContentObserver mBookmarksObserver; private DataController mDataController; + private CrashRecoveryHandler mCrashRecoveryHandler; private static class ClearThumbnails extends AsyncTask<File, Void, Void> { @Override @@ -219,6 +222,7 @@ public class Controller mDataController = DataController.getInstance(mActivity); mTabControl = new TabControl(this); mSettings.setController(this); + mCrashRecoveryHandler = new CrashRecoveryHandler(this); mUrlHandler = new UrlHandler(this); mIntentHandler = new IntentHandler(mActivity, this); @@ -252,6 +256,15 @@ public class Controller } void start(final Bundle icicle, final Intent intent) { + if (icicle != null) { + mCrashRecoveryHandler.clearState(); + doStart(icicle, intent); + } else { + mCrashRecoveryHandler.startRecovery(intent); + } + } + + void doStart(final Bundle icicle, final Intent intent) { // Unless the last browser usage was within 24 hours, destroy any // remaining incognito tabs. @@ -279,12 +292,12 @@ public class Controller GoogleAccountLogin.startLoginIfNeeded(mActivity, new Runnable() { @Override public void run() { - start(icicle, intent, currentTab, restoreIncognitoTabs); + onPreloginFinished(icicle, intent, currentTab, restoreIncognitoTabs); } }); } - private void start(Bundle icicle, Intent intent, int currentTab, + private void onPreloginFinished(Bundle icicle, Intent intent, int currentTab, boolean restoreIncognitoTabs) { if (currentTab == -1) { final Bundle extra = intent.getExtras(); @@ -610,6 +623,7 @@ public class Controller mNetworkHandler.onPause(); WebView.disablePlatformNotifications(); + mCrashRecoveryHandler.clearState(); } void onSaveInstanceState(Bundle outState) { @@ -911,6 +925,11 @@ public class Controller } mDataController.updateVisitedHistory(url); WebIconDatabase.getInstance().retainIconForPageUrl(url); + if (!mActivityPaused) { + // Since we clear the state in onPause, don't backup the current + // state if we are already paused + mCrashRecoveryHandler.backupState(); + } } @Override diff --git a/src/com/android/browser/CrashRecoveryHandler.java b/src/com/android/browser/CrashRecoveryHandler.java new file mode 100644 index 0000000..9e98e76 --- /dev/null +++ b/src/com/android/browser/CrashRecoveryHandler.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.browser; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.os.Bundle; +import android.os.Debug; +import android.os.Parcel; +import android.util.Log; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; + +public class CrashRecoveryHandler { + + private static final String LOGTAG = "BrowserCrashRecovery"; + private static final String STATE_FILE = "browser_state.parcel"; + private static final int BUFFER_SIZE = 4096; + + private Controller mController; + + public CrashRecoveryHandler(Controller controller) { + mController = controller; + } + + public void backupState() { + final Bundle state = new Bundle(); + mController.onSaveInstanceState(state); + final Context context = mController.getActivity(); + new Thread() { + @Override + public void run() { + Parcel p = Parcel.obtain(); + try { + state.writeToParcel(p, 0); + FileOutputStream fout = context.openFileOutput(STATE_FILE, + Context.MODE_PRIVATE); + fout.write(p.marshall()); + fout.close(); + } catch (Exception e) { + Log.i(LOGTAG, "Failed to save persistent state", e); + } finally { + p.recycle(); + } + } + }.start(); + } + + public void clearState() { + Context context = mController.getActivity(); + context.deleteFile(STATE_FILE); + } + + public void promptToRecover(final Bundle state, final Intent intent) { + new AlertDialog.Builder(mController.getActivity()) + .setTitle(R.string.recover_title) + .setMessage(R.string.recover_prompt) + .setPositiveButton(R.string.recover_yes, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + mController.doStart(state, intent); + } + }) + .setNegativeButton(R.string.recover_no, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + clearState(); + mController.doStart(null, intent); + } + }) + .show(); + } + + public void startRecovery(Intent intent) { + Parcel parcel = Parcel.obtain(); + try { + Context context = mController.getActivity(); + FileInputStream fin = context.openFileInput(STATE_FILE); + ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[BUFFER_SIZE]; + int read; + while ((read = fin.read(buffer)) > 0) { + dataStream.write(buffer, 0, read); + } + byte[] data = dataStream.toByteArray(); + parcel.unmarshall(data, 0, data.length); + parcel.setDataPosition(0); + Bundle state = parcel.readBundle(); + promptToRecover(state, intent); + } catch (FileNotFoundException e) { + // No state to recover + mController.doStart(null, intent); + } catch (Exception e) { + Log.w(LOGTAG, "Failed to recover state!", e); + mController.doStart(null, intent); + } finally { + parcel.recycle(); + } + } +} diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java index 87aca57..8368c33 100644 --- a/src/com/android/browser/Tab.java +++ b/src/com/android/browser/Tab.java @@ -1299,7 +1299,8 @@ class Tab { mCloseOnExit = closeOnExit; mAppId = appId; mDataController = DataController.getInstance(mActivity); - mCurrentState = new PageState(mActivity, w.isPrivateBrowsingEnabled()); + mCurrentState = new PageState(mActivity, w != null + ? w.isPrivateBrowsingEnabled() : false); mInPageLoad = false; mInForeground = false; diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java index 4b06d28..39981b0 100644 --- a/src/com/android/browser/XLargeUi.java +++ b/src/com/android/browser/XLargeUi.java @@ -176,11 +176,6 @@ public class XLargeUi extends BaseUi implements ScrollListener { } @Override - public boolean needsRestoreAllTabs() { - return true; - } - - @Override public void addTab(Tab tab) { mTabBar.onNewTab(tab); } |