Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 926cf566 authored by John Reck's avatar John Reck
Browse files

Show WebView layers in hierarchyviewer

Change-Id: I373e084d236baafe17982cfc367d167b81ca3e20
parent eb859df3
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -255,6 +255,35 @@ public class ViewDebug {
        boolean retrieveReturn() default false;
    }

    /**
     * Allows a View to inject custom children into HierarchyViewer. For example,
     * WebView uses this to add its internal layer tree as a child to itself
     * @hide
     */
    public interface HierarchyHandler {
        /**
         * Dumps custom children to hierarchy viewer.
         * See {@link ViewDebug#dumpViewWithProperties(Context, View, BufferedWriter, int)}
         * for the format
         *
         * An empty implementation should simply do nothing
         *
         * @param out The output writer
         * @param level The indentation level
         */
        public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);

        /**
         * Returns a View to enable grabbing screenshots from custom children
         * returned in dumpViewHierarchyWithProperties.
         *
         * @param className The className of the view to find
         * @param hashCode The hashCode of the view to find
         * @return the View to capture from, or null if not found
         */
        public View findHierarchyView(String className, int hashCode);
    }

    private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
    private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;

@@ -759,6 +788,13 @@ public class ViewDebug {
            } else if (isRequestedView(view, className, hashCode)) {
                return view;
            }
            if (view instanceof HierarchyHandler) {
                final View found = ((HierarchyHandler)view)
                        .findHierarchyView(className, hashCode);
                if (found != null) {
                    return found;
                }
            }
        }

        return null;
@@ -783,6 +819,9 @@ public class ViewDebug {
                dumpViewWithProperties(context, view, out, level + 1);
            }
        }
        if (group instanceof HierarchyHandler) {
            ((HierarchyHandler)group).dumpViewHierarchyWithProperties(out, level + 1);
        }
    }

    private static boolean dumpViewWithProperties(Context context, View view,
+9 −1
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
package android.webkit;

import android.graphics.Point;
import android.graphics.Region;
import android.webkit.WebViewCore.DrawData;

import java.io.DataInputStream;
@@ -68,6 +67,15 @@ class ViewStateSerializer {
        return draw;
    }

    public static void dumpLayerHierarchy(int baseLayer, OutputStream out, int level) {
        nativeDumpLayerHierarchy(baseLayer, level, out,
                new byte[WORKING_STREAM_STORAGE]);
    }


    private static native void nativeDumpLayerHierarchy(int baseLayer, int level,
            OutputStream out, byte[] storage);

    private static native boolean nativeSerializeViewState(int baseLayer,
            OutputStream stream, byte[] storage);

+27 −2
Original line number Diff line number Diff line
@@ -35,8 +35,8 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -44,6 +44,7 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.AbsoluteLayout;

import java.io.BufferedWriter;
import java.io.File;
import java.util.Map;

@@ -263,7 +264,7 @@ import java.util.Map;
@Widget
public class WebView extends AbsoluteLayout
        implements ViewTreeObserver.OnGlobalFocusChangeListener,
        ViewGroup.OnHierarchyChangeListener {
        ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler {

    private static final String LOGTAG = "webview_proxy";

@@ -1004,6 +1005,7 @@ public class WebView extends AbsoluteLayout
     *
     * @return the current scale
     */
    @ViewDebug.ExportedProperty(category = "webview")
    public float getScale() {
        checkThread();
        return mProvider.getScale();
@@ -1094,6 +1096,7 @@ public class WebView extends AbsoluteLayout
     *
     * @return the URL for the current page
     */
    @ViewDebug.ExportedProperty(category = "webview")
    public String getUrl() {
        checkThread();
        return mProvider.getUrl();
@@ -1108,6 +1111,7 @@ public class WebView extends AbsoluteLayout
     *
     * @return the URL that was originally requested for the current page
     */
    @ViewDebug.ExportedProperty(category = "webview")
    public String getOriginalUrl() {
        checkThread();
        return mProvider.getOriginalUrl();
@@ -1119,6 +1123,7 @@ public class WebView extends AbsoluteLayout
     *
     * @return the title for the current page
     */
    @ViewDebug.ExportedProperty(category = "webview")
    public String getTitle() {
        checkThread();
        return mProvider.getTitle();
@@ -1161,6 +1166,7 @@ public class WebView extends AbsoluteLayout
     *
     * @return the height of the HTML content
     */
    @ViewDebug.ExportedProperty(category = "webview")
    public int getContentHeight() {
        checkThread();
        return mProvider.getContentHeight();
@@ -1172,6 +1178,7 @@ public class WebView extends AbsoluteLayout
     * @return the width of the HTML content
     * @hide
     */
    @ViewDebug.ExportedProperty(category = "webview")
    public int getContentWidth() {
        return mProvider.getContentWidth();
    }
@@ -1652,6 +1659,24 @@ public class WebView extends AbsoluteLayout
        mProvider.debugDump();
    }

    /**
     * See {@link ViewDebug.HierarchyHandler#dumpViewHierarchyWithProperties(String, int)}
     * @hide
     */
    @Override
    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
        mProvider.dumpViewHierarchyWithProperties(out, level);
    }

    /**
     * See {@link ViewDebug.HierarchyHandler#findHierarchyView(String, int)}
     * @hide
     */
    @Override
    public View findHierarchyView(String className, int hashCode) {
        return mProvider.findHierarchyView(className, hashCode);
    }

    //-------------------------------------------------------------------------
    // Interface for WebView providers
    //-------------------------------------------------------------------------
+53 −0
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ import android.widget.Toast;

import junit.framework.Assert;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -132,6 +134,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@@ -8594,6 +8597,54 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
        WebViewCore.setShouldMonitorWebCoreThread();
    }

    @Override
    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level) {
        int layer = getBaseLayer();
        if (layer != 0) {
            try {
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                ViewStateSerializer.dumpLayerHierarchy(layer, stream, level);
                stream.close();
                byte[] buf = stream.toByteArray();
                out.write(new String(buf, "ascii"));
            } catch (IOException e) {}
        }
    }

    @Override
    public View findHierarchyView(String className, int hashCode) {
        if (mNativeClass == 0) return null;
        Picture pic = new Picture();
        if (!nativeDumpLayerContentToPicture(mNativeClass, className, hashCode, pic)) {
            return null;
        }
        return new PictureWrapperView(getContext(), pic, mWebView);
    }

    private static class PictureWrapperView extends View {
        Picture mPicture;
        WebView mWebView;

        public PictureWrapperView(Context context, Picture picture, WebView parent) {
            super(context);
            mPicture = picture;
            mWebView = parent;
            setWillNotDraw(false);
            setRight(mPicture.getWidth());
            setBottom(mPicture.getHeight());
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawPicture(mPicture);
        }

        @Override
        public boolean post(Runnable action) {
            return mWebView.post(action);
        }
    }

    private native void     nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
    private native void     nativeDebugDump();
    private static native void nativeDestroy(int ptr);
@@ -8614,6 +8665,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
            int scrollingLayer);
    private native int      nativeGetBaseLayer(int nativeInstance);
    private native void     nativeCopyBaseContentToPicture(Picture pict);
    private native boolean     nativeDumpLayerContentToPicture(int nativeInstance,
            String className, int layerId, Picture pict);
    private native boolean  nativeHasContent();
    private native void     nativeStopGL(int ptr);
    private native void     nativeDiscardAllTextures();
+5 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.view.inputmethod.InputConnection;
import android.webkit.WebView.HitTestResult;
import android.webkit.WebView.PictureListener;

import java.io.BufferedWriter;
import java.io.File;
import java.util.Map;

@@ -238,6 +239,10 @@ public interface WebViewProvider {

    public void debugDump();

    public void dumpViewHierarchyWithProperties(BufferedWriter out, int level);

    public View findHierarchyView(String className, int hashCode);

    //-------------------------------------------------------------------------
    // Provider glue methods
    //-------------------------------------------------------------------------