Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java

Issue 2948583002: Photo Picker dialog: Convert to AIDL for easier security review. (Closed)
Patch Set: Add comment Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.photo_picker; 5 package org.chromium.chrome.browser.photo_picker;
6 6
7 import android.app.Service; 7 import android.app.Service;
8 import android.content.Intent; 8 import android.content.Intent;
9 import android.graphics.Bitmap; 9 import android.graphics.Bitmap;
10 import android.os.Bundle; 10 import android.os.Bundle;
11 import android.os.Handler;
12 import android.os.IBinder; 11 import android.os.IBinder;
13 import android.os.Message;
14 import android.os.Messenger;
15 import android.os.ParcelFileDescriptor; 12 import android.os.ParcelFileDescriptor;
16 import android.os.RemoteException; 13 import android.os.RemoteException;
17 import android.os.SystemClock; 14 import android.os.SystemClock;
18 15
19 import org.chromium.base.Log; 16 import org.chromium.base.Log;
20 17
21 import java.io.FileDescriptor; 18 import java.io.FileDescriptor;
22 import java.io.IOException; 19 import java.io.IOException;
23 20
24 /** 21 /**
25 * A service to accept requests to take image file contents and decode them. 22 * A service to accept requests to take image file contents and decode them.
26 */ 23 */
27 public class DecoderService extends Service { 24 public class DecoderService extends Service {
28 // Message ids for communicating with the client.
29
30 // A message sent by the client to decode an image.
31 static final int MSG_DECODE_IMAGE = 1;
32 // A message sent by the server to notify the client of the results of the d ecoding.
33 static final int MSG_IMAGE_DECODED_REPLY = 2;
34
35 // The keys for the bundle when passing data to and from this service. 25 // The keys for the bundle when passing data to and from this service.
36 static final String KEY_FILE_DESCRIPTOR = "file_descriptor"; 26 static final String KEY_FILE_DESCRIPTOR = "file_descriptor";
37 static final String KEY_FILE_PATH = "file_path"; 27 static final String KEY_FILE_PATH = "file_path";
38 static final String KEY_IMAGE_BITMAP = "image_bitmap"; 28 static final String KEY_IMAGE_BITMAP = "image_bitmap";
39 static final String KEY_IMAGE_BYTE_COUNT = "image_byte_count";
40 static final String KEY_IMAGE_DESCRIPTOR = "image_descriptor";
41 static final String KEY_SIZE = "size"; 29 static final String KEY_SIZE = "size";
42 static final String KEY_SUCCESS = "success"; 30 static final String KEY_SUCCESS = "success";
43 static final String KEY_DECODE_TIME = "decode_time"; 31 static final String KEY_DECODE_TIME = "decode_time";
44 32
45 // A tag for logging error messages. 33 // A tag for logging error messages.
46 private static final String TAG = "ImageDecoder"; 34 private static final String TAG = "ImageDecoder";
47 35
48 /** 36 @Override
49 * Handler for incoming messages from clients. 37 public void onCreate() {
50 */ 38 super.onCreate();
51 static class IncomingHandler extends Handler { 39 }
52 @Override
53 public void handleMessage(Message msg) {
54 switch (msg.what) {
55 case MSG_DECODE_IMAGE:
56 Bundle bundle = null;
57 Messenger client = null;
58 String filePath = "";
59 int size = 0;
60 try {
61 Bundle payload = msg.getData();
62 client = msg.replyTo;
63 40
64 filePath = payload.getString(KEY_FILE_PATH); 41 @Override
65 ParcelFileDescriptor pfd = payload.getParcelable(KEY_FIL E_DESCRIPTOR); 42 public IBinder onBind(Intent intent) {
66 size = payload.getInt(KEY_SIZE); 43 return mBinder;
44 }
67 45
68 // Setup a minimum viable response to parent process. Wi ll be fleshed out 46 private final IDecoderService.Stub mBinder = new IDecoderService.Stub() {
69 // further below. 47 public void decodeImage(Bundle payload, IDecoderServiceCallback callback ) {
70 bundle = new Bundle(); 48 Bundle bundle = null;
71 bundle.putString(KEY_FILE_PATH, filePath); 49 String filePath = "";
72 bundle.putBoolean(KEY_SUCCESS, false); 50 int size = 0;
51 try {
52 filePath = payload.getString(KEY_FILE_PATH);
53 ParcelFileDescriptor pfd = payload.getParcelable(KEY_FILE_DESCRI PTOR);
54 size = payload.getInt(KEY_SIZE);
73 55
74 FileDescriptor fd = pfd.getFileDescriptor(); 56 // Setup a minimum viable response to parent process. Will be fl eshed out
57 // further below.
58 bundle = new Bundle();
59 bundle.putString(KEY_FILE_PATH, filePath);
60 bundle.putBoolean(KEY_SUCCESS, false);
75 61
76 long begin = SystemClock.elapsedRealtime(); 62 FileDescriptor fd = pfd.getFileDescriptor();
77 Bitmap bitmap = BitmapUtils.decodeBitmapFromFileDescript or(fd, size);
78 long decodeTime = SystemClock.elapsedRealtime() - begin;
79 63
80 try { 64 long begin = SystemClock.elapsedRealtime();
81 pfd.close(); 65 Bitmap bitmap = BitmapUtils.decodeBitmapFromFileDescriptor(fd, s ize);
82 } catch (IOException e) { 66 long decodeTime = SystemClock.elapsedRealtime() - begin;
83 Log.e(TAG, "Closing failed " + filePath + " (size: " + size + ") " + e);
84 }
85 67
86 if (bitmap == null) { 68 try {
87 Log.e(TAG, "Decode failed " + filePath + " (size: " + size + ")"); 69 pfd.close();
88 sendReply(client, bundle); // Sends SUCCESS == false ; 70 } catch (IOException e) {
89 return; 71 Log.e(TAG, "Closing failed " + filePath + " (size: " + size + ") " + e);
90 } 72 }
91 73
92 // The most widely supported, easiest, and reasonably ef ficient method is to 74 if (bitmap == null) {
93 // decode to an immutable bitmap and just return the bit map over binder. It 75 Log.e(TAG, "Decode failed " + filePath + " (size: " + size + ")");
94 // will internally memcpy itself to ashmem and then just send over the file 76 sendReply(callback, bundle); // Sends SUCCESS == false;
95 // descriptor. In the receiving process it will just lea ve the bitmap on 77 return;
96 // ashmem since it's immutable and carry on. 78 }
97 bundle.putParcelable(KEY_IMAGE_BITMAP, bitmap);
98 bundle.putBoolean(KEY_SUCCESS, true);
99 bundle.putLong(KEY_DECODE_TIME, decodeTime);
100 sendReply(client, bundle);
101 bitmap.recycle();
102 } catch (Exception e) {
103 // This service has no UI and maintains no state so if i t crashes on
104 // decoding a photo, it is better UX to eat the exceptio n instead of showing
105 // a crash dialog and discarding other requests that hav e already been sent.
106 Log.e(TAG,
107 "Unexpected error during decoding " + filePath + " (size: " + size
108 + ") " + e);
109 79
110 if (bundle != null && client != null) sendReply(client, bundle); 80 // The most widely supported, easiest, and reasonably efficient method is to
111 } 81 // decode to an immutable bitmap and just return the bitmap over binder. It
112 break; 82 // will internally memcpy itself to ashmem and then just send ov er the file
113 default: 83 // descriptor. In the receiving process it will just leave the b itmap on
114 super.handleMessage(msg); 84 // ashmem since it's immutable and carry on.
85 bundle.putParcelable(KEY_IMAGE_BITMAP, bitmap);
86 bundle.putBoolean(KEY_SUCCESS, true);
87 bundle.putLong(KEY_DECODE_TIME, decodeTime);
88 sendReply(callback, bundle);
89 bitmap.recycle();
90 } catch (Exception e) {
91 // This service has no UI and maintains no state so if it crashe s on
92 // decoding a photo, it is better UX to eat the exception instea d of showing
93 // a crash dialog and discarding other requests that have alread y been sent.
94 Log.e(TAG,
95 "Unexpected error during decoding " + filePath + " (size : " + size + ") "
96 + e);
97
98 if (bundle != null) sendReply(callback, bundle);
115 } 99 }
116 } 100 }
117 101
118 private void sendReply(Messenger client, Bundle bundle) { 102 private void sendReply(IDecoderServiceCallback callback, Bundle bundle) {
119 Message reply = Message.obtain(null, MSG_IMAGE_DECODED_REPLY);
120 reply.setData(bundle);
121 try { 103 try {
122 client.send(reply); 104 callback.onDecodeImageDone(bundle);
123 } catch (RemoteException remoteException) { 105 } catch (RemoteException remoteException) {
124 Log.e(TAG, "Remote error while replying: " + remoteException); 106 Log.e(TAG, "Remote error while replying: " + remoteException);
125 } 107 }
126 } 108 }
127 } 109 };
128
129 /**
130 * The target we publish for clients to send messages to IncomingHandler.
131 */
132 final Messenger mMessenger = new Messenger(new IncomingHandler());
133
134 /**
135 * When binding to the service, we return an interface to our messenger
136 * for sending messages to the service.
137 */
138 @Override
139 public IBinder onBind(Intent intent) {
140 return mMessenger.getBinder();
141 }
142 } 110 }
OLDNEW
« no previous file with comments | « chrome/android/BUILD.gn ('k') | chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698