• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 package org.chromium.content.browser;
6 
7 import android.graphics.Bitmap;
8 import android.graphics.Rect;
9 import android.util.SparseArray;
10 
11 import org.chromium.base.CalledByNative;
12 import org.chromium.base.JNINamespace;
13 import org.chromium.base.ThreadUtils;
14 import org.chromium.ui.base.WindowAndroid;
15 
16 /**
17  * A class for reading back content.
18  */
19 @JNINamespace("content")
20 public 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 bitmap     The {@link Bitmap} of the content.  Null will be passed for readback
28          *                   failure.
29          */
onFinishGetBitmap(Bitmap bitmap)30         public void onFinishGetBitmap(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      */
ContentReadbackHandler()41     public ContentReadbackHandler() {
42         mGetBitmapRequests = new SparseArray<GetBitmapCallback>();
43     }
44 
45     /**
46      * Initialize the native object.
47      */
initNativeContentReadbackHandler()48     public void initNativeContentReadbackHandler() {
49         mNativeContentReadbackHandler = nativeInit();
50     }
51 
52     /**
53      * Should be called when the ContentReadackHandler is not needed anymore.
54      */
destroy()55     public void destroy() {
56         if (mNativeContentReadbackHandler != 0) nativeDestroy(mNativeContentReadbackHandler);
57         mNativeContentReadbackHandler = 0;
58     }
59 
60 
61     @CalledByNative
notifyGetBitmapFinished(int readbackId, Bitmap bitmap)62     private void notifyGetBitmapFinished(int readbackId, Bitmap bitmap) {
63         GetBitmapCallback callback = mGetBitmapRequests.get(readbackId);
64         if (callback != null) {
65             mGetBitmapRequests.delete(readbackId);
66             callback.onFinishGetBitmap(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      */
getContentBitmapAsync(float scale, Rect srcRect, ContentViewCore view, GetBitmapCallback callback)83     public void getContentBitmapAsync(float scale, Rect srcRect, ContentViewCore view,
84             GetBitmapCallback callback) {
85         if (!readyForReadback()) {
86             callback.onFinishGetBitmap(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      */
getCompositorBitmapAsync(WindowAndroid windowAndroid, GetBitmapCallback callback)104     public void getCompositorBitmapAsync(WindowAndroid windowAndroid, GetBitmapCallback callback) {
105         if (!readyForReadback()) {
106             callback.onFinishGetBitmap(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      */
readyForReadback()121     protected abstract boolean readyForReadback();
122 
nativeInit()123     private native long nativeInit();
nativeDestroy(long nativeContentReadbackHandler)124     private native void nativeDestroy(long nativeContentReadbackHandler);
nativeGetContentBitmap(long nativeContentReadbackHandler, int readbackId, float scale, Bitmap.Config config, float x, float y, float width, float height, Object contentViewCore)125     private native void nativeGetContentBitmap(long nativeContentReadbackHandler, int readbackId,
126             float scale, Bitmap.Config config, float x, float y, float width, float height,
127             Object contentViewCore);
nativeGetCompositorBitmap(long nativeContentReadbackHandler, int readbackId, long nativeWindowAndroid)128     private native void nativeGetCompositorBitmap(long nativeContentReadbackHandler,
129             int readbackId, long nativeWindowAndroid);
130 }
131