Bug 1204557 - Stop using base64 for native app icons in the application registry r=jchen

This commit is contained in:
Fabrice Desré 2015-09-24 11:53:05 -07:00
parent 588d4a59e0
commit ac27fb0f29
4 changed files with 73 additions and 13 deletions

View File

@ -57,7 +57,8 @@ this.AndroidUtils = {
// We put the version with the normal case as part of the manifest url.
let [origin, manifestURL] =
this.getOriginAndManifestURL(aApp.packagename);
// TODO: Bug 1204557 to improve the icons support.
// We choose 96 as an arbitrary size since we can only get one icon
// from Android.
let manifest = {
name: aApp.name,
icons: { "96": aApp.icon }

View File

@ -76,17 +76,7 @@ class Apps extends BroadcastReceiver
(appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0;
obj.put("removable", removable);
// For now, create a data: url for the icon, since we need additional
// android:// protocol support for icons. Once it's there we'll do
// something like: obj.put("icon", "android:icon/" + info.packageName);
Drawable d = pm.getApplicationIcon(info.packageName);
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
obj.put("icon", "data:image/png;base64," + encoded);
obj.put("icon", "android://icon/" + appInfo.packageName);
} catch(Exception ex) {
Log.wtf(LOGTAG, "Error building ActivityInfo JSON", ex);
}

View File

@ -13,6 +13,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
@ -2592,6 +2595,55 @@ public class GeckoAppShell
return connection.getInputStream();
}
private static class BitmapConnection extends URLConnection {
private Bitmap bitmap;
BitmapConnection(Bitmap b) throws MalformedURLException, IOException {
super(null);
bitmap = b;
}
@Override
public void connect() {}
@Override
public InputStream getInputStream() throws IOException {
return new BitmapInputStream();
}
@Override
public String getContentType() {
return "image/png";
}
private final class BitmapInputStream extends PipedInputStream {
private boolean mHaveConnected = false;
@Override
public synchronized int read(byte[] buffer, int byteOffset, int byteCount)
throws IOException {
if (mHaveConnected) {
return super.read(buffer, byteOffset, byteCount);
}
final PipedOutputStream output = new PipedOutputStream();
connect(output);
ThreadUtils.postToBackgroundThread(
new Runnable() {
@Override
public void run() {
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
output.close();
} catch (IOException ioe) {}
}
});
mHaveConnected = true;
return super.read(buffer, byteOffset, byteCount);
}
}
}
@WrapForJNI(allowMultithread = true, narrowChars = true)
static URLConnection getConnection(String url) {
try {
@ -2602,6 +2654,23 @@ public class GeckoAppShell
spec = url.substring(8);
}
// Check if we are loading a package icon.
try {
if (spec.startsWith("icon/")) {
String[] splits = spec.split("/");
if (splits.length != 2) {
return null;
}
final String pkg = splits[1];
final PackageManager pm = getContext().getPackageManager();
final Drawable d = pm.getApplicationIcon(pkg);
final Bitmap bitmap = BitmapUtils.getBitmapFromDrawable(d);
return new BitmapConnection(bitmap);
}
} catch(Exception ex) {
Log.e(LOGTAG, "error", ex);
}
// if the colon got stripped, put it back
int colon = spec.indexOf(':');
if (colon == -1 || colon > spec.indexOf('/')) {

View File

@ -2087,7 +2087,7 @@ AndroidBridge::SetPresentationSurface(EGLSurface aPresentationSurface)
Object::LocalRef AndroidBridge::ChannelCreate(Object::Param stream) {
JNIEnv* const env = GetEnvForThread();
auto rv = Object::LocalRef::Adopt(env, env->CallStaticObjectMethod(
sBridge->jReadableByteChannel, sBridge->jChannelCreate, stream.Get()));
sBridge->jChannels, sBridge->jChannelCreate, stream.Get()));
HandleUncaughtException(env);
return rv;
}