blob: 9e98e76a8cdd4f3588489b7273a8bde44bfd3ccf [file] [log] [blame]
John Reck847b5322011-04-14 17:02:18 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
19import android.app.AlertDialog;
20import android.content.Context;
21import android.content.DialogInterface;
22import android.content.DialogInterface.OnClickListener;
23import android.content.Intent;
24import android.os.Bundle;
25import android.os.Debug;
26import android.os.Parcel;
27import android.util.Log;
28
29import java.io.ByteArrayOutputStream;
30import java.io.FileInputStream;
31import java.io.FileNotFoundException;
32import java.io.FileOutputStream;
33
34public class CrashRecoveryHandler {
35
36 private static final String LOGTAG = "BrowserCrashRecovery";
37 private static final String STATE_FILE = "browser_state.parcel";
38 private static final int BUFFER_SIZE = 4096;
39
40 private Controller mController;
41
42 public CrashRecoveryHandler(Controller controller) {
43 mController = controller;
44 }
45
46 public void backupState() {
47 final Bundle state = new Bundle();
48 mController.onSaveInstanceState(state);
49 final Context context = mController.getActivity();
50 new Thread() {
51 @Override
52 public void run() {
53 Parcel p = Parcel.obtain();
54 try {
55 state.writeToParcel(p, 0);
56 FileOutputStream fout = context.openFileOutput(STATE_FILE,
57 Context.MODE_PRIVATE);
58 fout.write(p.marshall());
59 fout.close();
60 } catch (Exception e) {
61 Log.i(LOGTAG, "Failed to save persistent state", e);
62 } finally {
63 p.recycle();
64 }
65 }
66 }.start();
67 }
68
69 public void clearState() {
70 Context context = mController.getActivity();
71 context.deleteFile(STATE_FILE);
72 }
73
74 public void promptToRecover(final Bundle state, final Intent intent) {
75 new AlertDialog.Builder(mController.getActivity())
76 .setTitle(R.string.recover_title)
77 .setMessage(R.string.recover_prompt)
78 .setPositiveButton(R.string.recover_yes, new OnClickListener() {
79 @Override
80 public void onClick(DialogInterface dialog, int which) {
81 mController.doStart(state, intent);
82 }
83 })
84 .setNegativeButton(R.string.recover_no, new OnClickListener() {
85 @Override
86 public void onClick(DialogInterface dialog, int which) {
87 clearState();
88 mController.doStart(null, intent);
89 }
90 })
91 .show();
92 }
93
94 public void startRecovery(Intent intent) {
95 Parcel parcel = Parcel.obtain();
96 try {
97 Context context = mController.getActivity();
98 FileInputStream fin = context.openFileInput(STATE_FILE);
99 ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
100 byte[] buffer = new byte[BUFFER_SIZE];
101 int read;
102 while ((read = fin.read(buffer)) > 0) {
103 dataStream.write(buffer, 0, read);
104 }
105 byte[] data = dataStream.toByteArray();
106 parcel.unmarshall(data, 0, data.length);
107 parcel.setDataPosition(0);
108 Bundle state = parcel.readBundle();
109 promptToRecover(state, intent);
110 } catch (FileNotFoundException e) {
111 // No state to recover
112 mController.doStart(null, intent);
113 } catch (Exception e) {
114 Log.w(LOGTAG, "Failed to recover state!", e);
115 mController.doStart(null, intent);
116 } finally {
117 parcel.recycle();
118 }
119 }
120}