summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tobias Sargeant <tobiasjs@google.com> 2015-03-03 18:07:40 +0000
committer Tobias Sargeant <tobiasjs@google.com> 2015-03-17 15:19:07 +0000
commita8352f40316fb265c74d42e908eb30284259b47d (patch)
treef50649c45831244354ff905e10e480c3da85acfb
parentbb41a5f6def031b99f5569b192425b9edbdce7cc (diff)
Add visual state callbacks to the WebView.
Registering a visual state callback allows the caller to be notified after the commit, activation and swap of the current (or future) state of the DOM tree has occurred. At the point at which the callback is called, the caller can be sure that any DOM updates made prior to the registration are ready to be drawn in the next WebView#onDraw. We also provide a convenience callback related to the visual state: * WebViewClient.onPageCommitVisible; called at the earliest point at which the next draw will not render contents from the previously loaded page. Bug: 6375170 Change-Id: I17e706b6e6ba4a8c28c835552687c9f7a4623024
-rw-r--r--api/current.txt7
-rw-r--r--api/system-current.txt8
-rw-r--r--core/java/android/webkit/WebView.java68
-rw-r--r--core/java/android/webkit/WebViewClient.java26
-rw-r--r--core/java/android/webkit/WebViewProvider.java4
5 files changed, 113 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt
index 7bac613a5c56..c0466fc9adbb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37444,6 +37444,7 @@ package android.webkit {
method public void goBack();
method public void goBackOrForward(int);
method public void goForward();
+ method public void insertVisualStateCallback(long, android.webkit.WebView.VisualStateCallback);
method public void invokeZoomPicker();
method public boolean isPrivateBrowsingEnabled();
method public void loadData(java.lang.String, java.lang.String, java.lang.String);
@@ -37518,6 +37519,11 @@ package android.webkit {
method public abstract deprecated void onNewPicture(android.webkit.WebView, android.graphics.Picture);
}
+ public static abstract class WebView.VisualStateCallback {
+ ctor public WebView.VisualStateCallback();
+ method public abstract void onComplete(long);
+ }
+
public class WebView.WebViewTransport {
ctor public WebView.WebViewTransport();
method public synchronized android.webkit.WebView getWebView();
@@ -37529,6 +37535,7 @@ package android.webkit {
method public void doUpdateVisitedHistory(android.webkit.WebView, java.lang.String, boolean);
method public void onFormResubmission(android.webkit.WebView, android.os.Message, android.os.Message);
method public void onLoadResource(android.webkit.WebView, java.lang.String);
+ method public void onPageCommitVisible(android.webkit.WebView, java.lang.String);
method public void onPageFinished(android.webkit.WebView, java.lang.String);
method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
method public void onReceivedClientCertRequest(android.webkit.WebView, android.webkit.ClientCertRequest);
diff --git a/api/system-current.txt b/api/system-current.txt
index 89c0460e9883..d16386dcdbea 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -39876,6 +39876,7 @@ package android.webkit {
method public void goBack();
method public void goBackOrForward(int);
method public void goForward();
+ method public void insertVisualStateCallback(long, android.webkit.WebView.VisualStateCallback);
method public void invokeZoomPicker();
method public boolean isPrivateBrowsingEnabled();
method public void loadData(java.lang.String, java.lang.String, java.lang.String);
@@ -39980,6 +39981,11 @@ package android.webkit {
method public void super_setLayoutParams(android.view.ViewGroup.LayoutParams);
}
+ public static abstract class WebView.VisualStateCallback {
+ ctor public WebView.VisualStateCallback();
+ method public abstract void onComplete(long);
+ }
+
public class WebView.WebViewTransport {
ctor public WebView.WebViewTransport();
method public synchronized android.webkit.WebView getWebView();
@@ -39991,6 +39997,7 @@ package android.webkit {
method public void doUpdateVisitedHistory(android.webkit.WebView, java.lang.String, boolean);
method public void onFormResubmission(android.webkit.WebView, android.os.Message, android.os.Message);
method public void onLoadResource(android.webkit.WebView, java.lang.String);
+ method public void onPageCommitVisible(android.webkit.WebView, java.lang.String);
method public void onPageFinished(android.webkit.WebView, java.lang.String);
method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
method public void onReceivedClientCertRequest(android.webkit.WebView, android.webkit.ClientCertRequest);
@@ -40137,6 +40144,7 @@ package android.webkit {
method public abstract void goBackOrForward(int);
method public abstract void goForward();
method public abstract void init(java.util.Map<java.lang.String, java.lang.Object>, boolean);
+ method public abstract void insertVisualStateCallback(long, android.webkit.WebView.VisualStateCallback);
method public abstract void invokeZoomPicker();
method public abstract boolean isPaused();
method public abstract boolean isPrivateBrowsingEnabled();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 67ad642cf02d..6711a6b05ff1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -364,6 +364,20 @@ public class WebView extends AbsoluteLayout
}
/**
+ * Callback interface supplied to {@link #insertVisualStateCallback} for receiving
+ * notifications about the visual state.
+ */
+ public static abstract class VisualStateCallback {
+ /**
+ * Invoked when the visual state is ready to be drawn in the next {@link #onDraw}.
+ *
+ * @param requestId the id supplied to the corresponding {@link #insertVisualStateCallback}
+ * request
+ */
+ public abstract void onComplete(long requestId);
+ }
+
+ /**
* Interface to listen for new pictures as they change.
*
* @deprecated This interface is now obsolete.
@@ -1144,6 +1158,60 @@ public class WebView extends AbsoluteLayout
}
/**
+ * Inserts a {@link VisualStateCallback}.
+ *
+ * <p>Updates to the the DOM are reflected asynchronously such that when the DOM is updated the
+ * subsequent {@link WebView#onDraw} invocation might not reflect those updates. The
+ * {@link VisualStateCallback} provides a mechanism to notify the caller when the contents of
+ * the DOM at the current time are ready to be drawn the next time the {@link WebView} draws.
+ * By current time we mean the time at which this API was called. The next draw after the
+ * callback completes is guaranteed to reflect all the updates to the DOM applied before the
+ * current time, but it may also contain updates applied after the current time.</p>
+ *
+ * <p>The state of the DOM covered by this API includes the following:
+ * <ul>
+ * <li>primitive HTML elements (div, img, span, etc..)</li>
+ * <li>images</li>
+ * <li>CSS animations</li>
+ * <li>WebGL</li>
+ * <li>canvas</li>
+ * </ul>
+ * It does not include the state of:
+ * <ul>
+ * <li>the video tag</li>
+ * </ul></p>
+ *
+ * <p>To guarantee that the {@link WebView} will successfully render the first frame
+ * after the {@link VisualStateCallback#onComplete} method has been called a set of conditions
+ * must be met:
+ * <ul>
+ * <li>If the {@link WebView}'s visibility is set to {@link View#VISIBLE VISIBLE} then
+ * the {@link WebView} must be attached to the view hierarchy.</li>
+ * <li>If the {@link WebView}'s visibility is set to {@link View#INVISIBLE INVISIBLE}
+ * then the {@link WebView} must be attached to the view hierarchy and must be made
+ * {@link View#VISIBLE VISIBLE} from the {@link VisualStateCallback#onComplete} method.</li>
+ * <li>If the {@link WebView}'s visibility is set to {@link View#GONE GONE} then the
+ * {@link WebView} must be attached to the view hierarchy and its
+ * {@link AbsoluteLayout.LayoutParams LayoutParams}'s width and height need to be set to fixed
+ * values and must be made {@link View#VISIBLE VISIBLE} from the
+ * {@link VisualStateCallback#onComplete} method.</li>
+ * </ul></p>
+ *
+ * <p>When using this API it is also recommended to enable pre-rasterization if the
+ * {@link WebView} is offscreen to avoid flickering. See WebSettings#setOffscreenPreRaster for
+ * more details and do consider its caveats.</p>
+ *
+ * @param requestId an id that will be returned in the callback to allow callers to match
+ * requests with callbacks.
+ * @param callback the callback to be invoked.
+ */
+ public void insertVisualStateCallback(long requestId, VisualStateCallback callback) {
+ checkThread();
+ if (TRACE) Log.d(LOGTAG, "insertVisualStateCallback");
+ mProvider.insertVisualStateCallback(requestId, callback);
+ }
+
+ /**
* Clears this WebView so that onDraw() will draw nothing but white background,
* and onMeasure() will return 0 if MeasureSpec is not MeasureSpec.EXACTLY.
* @deprecated Use WebView.loadUrl("about:blank") to reliably reset the view state
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 34b8cf6348b3..53c7e04d4ca4 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -83,6 +83,32 @@ public class WebViewClient {
}
/**
+ * Notify the host application that the page commit is visible.
+ *
+ * <p>This is the earliest point at which we can guarantee that the contents of the previously
+ * loaded page will not longer be drawn in the next {@link WebView#onDraw}. The next draw will
+ * render the {@link WebView#setBackgroundColor background color} of the WebView or some of the
+ * contents from the committed page already. This callback may be useful when reusing
+ * {@link WebView}s to ensure that no stale content is shown. This method is only called for
+ * the main frame.</p>
+ *
+ * <p>This method is called when the state of the DOM at the point at which the
+ * body of the HTTP response (commonly the string of html) had started loading will be visible.
+ * If you set a background color for the page in the HTTP response body this will most likely
+ * be visible and perhaps some other elements. At that point no other resources had usually
+ * been loaded, so you can expect images for example to not be visible. If you want
+ * a finer level of granularity consider calling {@link WebView#insertVisualStateCallback}
+ * directly.</p>
+ *
+ * <p>Please note that all the conditions and recommendations presented in
+ * {@link WebView#insertVisualStateCallback} also apply to this API.<p>
+ *
+ * @param url the url of the committed page
+ */
+ public void onPageCommitVisible(WebView view, String url) {
+ }
+
+ /**
* Notify the host application of a resource request and allow the
* application to return the data. If the return value is null, the WebView
* will continue to load the resource as usual. Otherwise, the return
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 0cdb8755ef1d..fa2ce1b22c6a 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -40,6 +40,8 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.webkit.WebView.HitTestResult;
import android.webkit.WebView.PictureListener;
+import android.webkit.WebView.VisualStateCallback;
+
import java.io.BufferedWriter;
import java.io.File;
@@ -146,6 +148,8 @@ public interface WebViewProvider {
public boolean pageDown(boolean bottom);
+ public void insertVisualStateCallback(long requestId, VisualStateCallback callback);
+
public void clearView();
public Picture capturePicture();