Merge "Save and load snapshots async"
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index e672b62..35168cf 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -34,21 +34,21 @@
 
     static final int VERSION = 1;
 
-    static boolean serializeViewState(OutputStream stream, WebViewClassic web)
+    static boolean serializeViewState(OutputStream stream, DrawData draw)
             throws IOException {
-        int baseLayer = web.getBaseLayer();
+        int baseLayer = draw.mBaseLayer;
         if (baseLayer == 0) {
             return false;
         }
         DataOutputStream dos = new DataOutputStream(stream);
         dos.writeInt(VERSION);
-        dos.writeInt(web.getContentWidth());
-        dos.writeInt(web.getContentHeight());
+        dos.writeInt(draw.mContentSize.x);
+        dos.writeInt(draw.mContentSize.y);
         return nativeSerializeViewState(baseLayer, dos,
                 new byte[WORKING_STREAM_STORAGE]);
     }
 
-    static DrawData deserializeViewState(InputStream stream, WebViewClassic web)
+    static DrawData deserializeViewState(InputStream stream)
             throws IOException {
         DataInputStream dis = new DataInputStream(stream);
         int version = dis.readInt();
@@ -62,13 +62,10 @@
 
         final WebViewCore.DrawData draw = new WebViewCore.DrawData();
         draw.mViewState = new WebViewCore.ViewState();
-        int viewWidth = web.getViewWidth();
-        int viewHeight = web.getViewHeightWithTitle() - web.getTitleHeight();
-        draw.mViewSize = new Point(viewWidth, viewHeight);
         draw.mContentSize = new Point(contentWidth, contentHeight);
-        draw.mViewState.mDefaultScale = web.getDefaultZoomScale();
         draw.mBaseLayer = baseLayer;
         draw.mInvalRegion = new Region(0, 0, contentWidth, contentHeight);
+        stream.close();
         return draw;
     }
 
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index c8cfb0a..f429e09 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -2437,34 +2437,51 @@
      * version specific, and may not be able to be loaded by newer versions
      * of WebView.
      * @param stream The {@link OutputStream} to save to
-     * @return True if saved successfully
+     * @param callback The {@link ValueCallback} to call with the result
      */
-    public boolean saveViewState(OutputStream stream) {
-        try {
-            return ViewStateSerializer.serializeViewState(stream, this);
-        } catch (IOException e) {
-            Log.w(LOGTAG, "Failed to saveViewState", e);
+    public void saveViewState(OutputStream stream, ValueCallback<Boolean> callback) {
+        if (mWebViewCore == null) {
+            callback.onReceiveValue(false);
+            return;
         }
-        return false;
+        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SAVE_VIEW_STATE,
+                new WebViewCore.SaveViewStateRequest(stream, callback));
     }
 
     /**
      * Loads the view data from the input stream. See
      * {@link #saveViewState(OutputStream)} for more information.
      * @param stream The {@link InputStream} to load from
-     * @return True if loaded successfully
      */
-    public boolean loadViewState(InputStream stream) {
-        try {
-            mLoadedPicture = ViewStateSerializer.deserializeViewState(stream, this);
-            mBlockWebkitViewMessages = true;
-            setNewPicture(mLoadedPicture, true);
-            mLoadedPicture.mViewState = null;
-            return true;
-        } catch (IOException e) {
-            Log.w(LOGTAG, "Failed to loadViewState", e);
-        }
-        return false;
+    public void loadViewState(InputStream stream) {
+        mBlockWebkitViewMessages = true;
+        new AsyncTask<InputStream, Void, DrawData>() {
+
+            @Override
+            protected DrawData doInBackground(InputStream... params) {
+                try {
+                    return ViewStateSerializer.deserializeViewState(params[0]);
+                } catch (IOException e) {
+                    return null;
+                }
+            }
+
+            @Override
+            protected void onPostExecute(DrawData draw) {
+                if (draw == null) {
+                    Log.e(LOGTAG, "Failed to load view state!");
+                    return;
+                }
+                int viewWidth = getViewWidth();
+                int viewHeight = getViewHeightWithTitle() - getTitleHeight();
+                draw.mViewSize = new Point(viewWidth, viewHeight);
+                draw.mViewState.mDefaultScale = getDefaultZoomScale();
+                mLoadedPicture = draw;
+                setNewPicture(mLoadedPicture, true);
+                mLoadedPicture.mViewState = null;
+            }
+
+        }.execute(stream);
     }
 
     /**
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index f86262e..0565ed7 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -44,6 +44,7 @@
 
 import junit.framework.Assert;
 
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -1048,6 +1049,15 @@
         public int mMatchIndex;
     }
 
+    static class SaveViewStateRequest {
+        SaveViewStateRequest(OutputStream s, ValueCallback<Boolean> cb) {
+            mStream = s;
+            mCallback = cb;
+        }
+        public OutputStream mStream;
+        public ValueCallback<Boolean> mCallback;
+    }
+
     /**
      * @hide
      */
@@ -1180,6 +1190,8 @@
         static final int KEY_PRESS = 223;
         static final int SET_INITIAL_FOCUS = 224;
 
+        static final int SAVE_VIEW_STATE = 225;
+
         // Private handler for WebCore messages.
         private Handler mHandler;
         // Message queue for containing messages before the WebCore thread is
@@ -1754,8 +1766,13 @@
                         case SET_INITIAL_FOCUS:
                             nativeSetInitialFocus(mNativeClass, msg.arg1);
                             break;
+                        case SAVE_VIEW_STATE:
+                            SaveViewStateRequest request = (SaveViewStateRequest) msg.obj;
+                            saveViewState(request.mStream, request.mCallback);
+                            break;
                     }
                 }
+
             };
             // Take all queued messages and resend them to the new handler.
             synchronized (this) {
@@ -2254,6 +2271,31 @@
         }
     }
 
+    private void saveViewState(OutputStream stream,
+            ValueCallback<Boolean> callback) {
+        // TODO: Create a native method to do this better without overloading
+        // the draw path (and fix saving <canvas>)
+        DrawData draw = new DrawData();
+        if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "saveViewState start");
+        draw.mBaseLayer = nativeRecordContent(mNativeClass, draw.mInvalRegion,
+                draw.mContentSize);
+        boolean result = false;
+        try {
+            result = ViewStateSerializer.serializeViewState(stream, draw);
+        } catch (Throwable t) {
+            Log.w(LOGTAG, "Failed to save view state", t);
+        }
+        callback.onReceiveValue(result);
+        if (draw.mBaseLayer != 0) {
+            if (mDrawIsScheduled) {
+                mDrawIsScheduled = false;
+                mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
+            }
+            mLastDrawData = draw;
+            webkitDraw(draw);
+        }
+    }
+
     static void reducePriority() {
         // remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
         sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);