ContentReadbackHandler.java revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.content.browser;
6
7import android.graphics.Bitmap;
8import android.graphics.Rect;
9import android.util.SparseArray;
10
11import org.chromium.base.CalledByNative;
12import org.chromium.base.JNINamespace;
13import org.chromium.base.ThreadUtils;
14import org.chromium.ui.base.WindowAndroid;
15
16/**
17 * A class for reading back content.
18 */
19@JNINamespace("content")
20public abstract class ContentReadbackHandler {
21    /**
22     * A callback interface for content readback into a bitmap.
23     */
24    public static interface GetBitmapCallback {
25        /**
26         * Called when the content readback finishes.
27         * @param success    Indicates whether the readback succeeded or not.
28         * @param bitmap     The {@link Bitmap} of the content.
29         */
30        public void onFinishGetBitmap(boolean success, Bitmap bitmap);
31    }
32
33    private int mNextReadbackId = 1;
34    private SparseArray<GetBitmapCallback> mGetBitmapRequests;
35
36    private long mNativeContentReadbackHandler;
37
38    /**
39     * Creates a {@link ContentReadbackHandler}.
40     */
41    public ContentReadbackHandler() {
42        mGetBitmapRequests = new SparseArray<GetBitmapCallback>();
43    }
44
45    /**
46     * Initialize the native object.
47     */
48    public void initNativeContentReadbackHandler() {
49        mNativeContentReadbackHandler = nativeInit();
50    }
51
52    /**
53     * Should be called when the ContentReadackHandler is not needed anymore.
54     */
55    public void destroy() {
56        if (mNativeContentReadbackHandler != 0) nativeDestroy(mNativeContentReadbackHandler);
57        mNativeContentReadbackHandler = 0;
58    }
59
60
61    @CalledByNative
62    private void notifyGetBitmapFinished(int readbackId, boolean success, Bitmap bitmap) {
63        GetBitmapCallback callback = mGetBitmapRequests.get(readbackId);
64        if (callback != null) {
65            mGetBitmapRequests.delete(readbackId);
66            callback.onFinishGetBitmap(success, bitmap);
67        } else {
68            // readback Id is unregistered.
69            assert false : "Readback finished for unregistered Id: " + readbackId;
70        }
71    }
72
73    /**
74     * Asynchronously, generate and grab a bitmap representing what is currently on the screen
75     * for {@code view}.
76     *
77     * @param scale The scale that should be applied to the content.
78     * @param srcRect  A subrect of the original content to capture. If this is empty, it will grab
79     *                 the whole surface.
80     * @param view  The {@link ContentViewCore} to grab the bitmap from.
81     * @param callback The callback to be executed after readback completes.
82     */
83    public void getContentBitmapAsync(float scale, Rect srcRect, ContentViewCore view,
84            GetBitmapCallback callback) {
85        if (!readyForReadback()) {
86            callback.onFinishGetBitmap(false, null);
87            return;
88        }
89        ThreadUtils.assertOnUiThread();
90
91        int readbackId = mNextReadbackId++;
92        mGetBitmapRequests.put(readbackId, callback);
93        nativeGetContentBitmap(mNativeContentReadbackHandler, readbackId, scale,
94                Bitmap.Config.ARGB_8888, srcRect.top, srcRect.left, srcRect.width(),
95                srcRect.height(), view);
96    }
97
98    /**
99     * Asynchronously, grab a bitmap of the current browser compositor root layer.
100     *
101     * @param windowAndroid The window that hosts the compositor.
102     * @param callback      The callback to be executed after readback completes.
103     */
104    public void getCompositorBitmapAsync(WindowAndroid windowAndroid, GetBitmapCallback callback) {
105        if (!readyForReadback()) {
106            callback.onFinishGetBitmap(false, null);
107            return;
108        }
109        ThreadUtils.assertOnUiThread();
110
111        int readbackId = mNextReadbackId++;
112        mGetBitmapRequests.put(readbackId, callback);
113        nativeGetCompositorBitmap(mNativeContentReadbackHandler, readbackId,
114                windowAndroid.getNativePointer());
115    }
116
117    /**
118     * Implemented by the owner of this class to signal whether readback is possible or not.
119     * @return Whether readback is possible or not.
120     */
121    protected abstract boolean readyForReadback();
122
123    private native long nativeInit();
124    private native void nativeDestroy(long nativeContentReadbackHandler);
125    private native void nativeGetContentBitmap(long nativeContentReadbackHandler, int readback_id,
126            float scale, Bitmap.Config config, float x, float y, float width, float height,
127            Object contentViewCore);
128    private native void nativeGetCompositorBitmap(long nativeContentReadbackHandler,
129            int readback_id, long nativeWindowAndroid);
130}
131