/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.imagepipeline.producers;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import android.net.Uri;
import android.util.Base64;
import com.facebook.common.executors.CallerThreadExecutor;
import com.facebook.common.internal.Preconditions;
import com.facebook.common.internal.VisibleForTesting;
import com.facebook.imagepipeline.image.EncodedImage;
import com.facebook.imagepipeline.memory.PooledByteBufferFactory;
import com.facebook.imagepipeline.request.ImageRequest;
/**
* Producer for data URIs.
*
* <p>Data URIs embed the data in the URI itself. They don't point to a file location;
* the URI is the data. Data can be encoded in either base-64 or escaped ASCII.
* See the <a href="http://tools.ietf.org/html/rfc2397">spec</a> for full details.
*
* <p>Data URIs are intended for small pieces of data only, since the URI lives on the Java
* heap. For large data, use a another URI type.
*
* <p>Charsets specified in the URI are ignored. Only UTF-8 encoding is currently supported.
*/
public class DataFetchProducer extends LocalFetchProducer {
private static final String PRODUCER_NAME = "DataFetchProducer";
public DataFetchProducer(
PooledByteBufferFactory pooledByteBufferFactory,
boolean fileDescriptorEnabled) {
super(CallerThreadExecutor.getInstance(), pooledByteBufferFactory, fileDescriptorEnabled);
}
@Override
protected EncodedImage getEncodedImage(ImageRequest imageRequest) throws IOException {
byte[] data = getData(imageRequest.getSourceUri().toString());
return getByteBufferBackedEncodedImage(new ByteArrayInputStream(data), data.length);
}
@Override
protected String getProducerName() {
return PRODUCER_NAME;
}
@VisibleForTesting
static byte[] getData(String uri) {
/*
* Format of a data URL:
* data:mime/type;param=value;param=value;base64,actual_data
* everything is optional except the actual data, which is either
* base-64 or escaped ASCII encoded.
*/
Preconditions.checkArgument(uri.substring(0, 5).equals("data:"));
int commaPos = uri.indexOf(',');
String dataStr = uri.substring(commaPos + 1, uri.length());
if (isBase64(uri.substring(0, commaPos))) {
return Base64.decode(dataStr, Base64.DEFAULT);
} else {
String str = Uri.decode(dataStr);
byte[] b = str.getBytes();
return b;
}
}
@VisibleForTesting
static boolean isBase64(String prefix) {
if (!prefix.contains(";")) {
return false;
}
String[] parameters = prefix.split(";");
return parameters[parameters.length - 1].equals("base64");
}
}