Bug 1312114 - Pre: Move getDrawable() from (geckoview) BitmapUtils into (fennec) MenuBitmapUtils to allow support library access r=nalexander
In order to use VectorDrawable's in this code we need to use AppCompatDrawableManager, which
is in the v7 appcompat support library. GeckoView cannot access that library, hence
we should move getDrawable() into the main Fennec jar in order to let us use
VectorDrawable's.
Similarly we need to move DrawableUtil for the same reasons.
(This commit only takes care of moving the code, the following code adds VectorDrawable support.)
MozReview-Commit-ID: CE2yTMLgBlJ
--- a/mobile/android/base/java/org/mozilla/gecko/ActionBarTextSelection.java
+++ b/mobile/android/base/java/org/mozilla/gecko/ActionBarTextSelection.java
@@ -1,18 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
-import org.mozilla.gecko.gfx.BitmapUtils;
-import org.mozilla.gecko.gfx.BitmapUtils.BitmapLoader;
import org.mozilla.gecko.menu.GeckoMenu;
import org.mozilla.gecko.menu.GeckoMenuItem;
+import org.mozilla.gecko.util.ResourceDrawableUtils;
import org.mozilla.gecko.text.TextSelection;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.ActionModeCompat.Callback;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import android.content.Context;
@@ -203,17 +202,17 @@ class ActionBarTextSelection implements
for (int i = 0; i < length; i++) {
try {
final JSONObject obj = mItems.getJSONObject(i);
final GeckoMenuItem menuitem = (GeckoMenuItem) menu.add(0, i, 0, obj.optString("label"));
final int actionEnum = obj.optBoolean("showAsAction") ? GeckoMenuItem.SHOW_AS_ACTION_ALWAYS : GeckoMenuItem.SHOW_AS_ACTION_NEVER;
menuitem.setShowAsAction(actionEnum, R.attr.menuItemActionModeStyle);
final String iconString = obj.optString("icon");
- BitmapUtils.getDrawable(context, iconString, new BitmapLoader() {
+ ResourceDrawableUtils.getDrawable(context, iconString, new ResourceDrawableUtils.BitmapLoader() {
@Override
public void onBitmapFound(Drawable d) {
if (d != null) {
menuitem.setIcon(d);
}
}
});
} catch (Exception ex) {
--- a/mobile/android/base/java/org/mozilla/gecko/ThumbnailHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/ThumbnailHelper.java
@@ -2,16 +2,17 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.gfx.BitmapUtils;
+import org.mozilla.gecko.util.ResourceDrawableUtils;
import org.mozilla.gecko.mozglue.DirectBufferAllocator;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.util.Log;
import android.util.TypedValue;
import java.nio.ByteBuffer;
@@ -73,34 +74,34 @@ public final class ThumbnailHelper {
try {
mPendingWidth = (int) res.getDimension(R.dimen.tab_thumbnail_width);
} catch (Resources.NotFoundException nfe) {
}
mWidth = -1;
mHeight = -1;
}
- public void getAndProcessThumbnailFor(final int tabId, final BitmapUtils.BitmapLoader loader) {
+ public void getAndProcessThumbnailFor(final int tabId, final ResourceDrawableUtils.BitmapLoader loader) {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab != null) {
getAndProcessThumbnailFor(tab, loader);
}
}
- public void getAndProcessThumbnailFor(final Tab tab, final BitmapUtils.BitmapLoader loader) {
- BitmapUtils.runOnBitmapFoundOnUiThread(loader, tab.getThumbnail());
+ public void getAndProcessThumbnailFor(final Tab tab, final ResourceDrawableUtils.BitmapLoader loader) {
+ ResourceDrawableUtils.runOnBitmapFoundOnUiThread(loader, tab.getThumbnail());
Tabs.registerOnTabsChangedListener(new Tabs.OnTabsChangedListener() {
@Override
public void onTabChanged(final Tab t, final Tabs.TabEvents msg, final String data) {
if (tab != t || msg != Tabs.TabEvents.THUMBNAIL) {
return;
}
Tabs.unregisterOnTabsChangedListener(this);
- BitmapUtils.runOnBitmapFoundOnUiThread(loader, t.getThumbnail());
+ ResourceDrawableUtils.runOnBitmapFoundOnUiThread(loader, t.getThumbnail());
}
});
getAndProcessThumbnailFor(tab);
}
public void getAndProcessThumbnailFor(Tab tab) {
if (AboutPages.isAboutHome(tab.getURL()) || AboutPages.isAboutPrivateBrowsing(tab.getURL())) {
tab.updateThumbnail(null, CachePolicy.NO_STORE);
--- a/mobile/android/base/java/org/mozilla/gecko/home/HomeBanner.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/HomeBanner.java
@@ -9,17 +9,17 @@ import org.json.JSONObject;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.R;
import org.mozilla.gecko.animation.PropertyAnimator;
import org.mozilla.gecko.animation.PropertyAnimator.Property;
import org.mozilla.gecko.animation.ViewHelper;
-import org.mozilla.gecko.gfx.BitmapUtils;
+import org.mozilla.gecko.util.ResourceDrawableUtils;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.widget.EllipsisTextView;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.text.TextUtils;
@@ -166,17 +166,17 @@ public class HomeBanner extends LinearLa
// Update the banner message on the UI thread.
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
// Store the current message id to pass back to JS in the view's OnClickListener.
setTag(id);
mTextView.setOriginalText(Html.fromHtml(text));
- BitmapUtils.getDrawable(getContext(), iconURI, new BitmapUtils.BitmapLoader() {
+ ResourceDrawableUtils.getDrawable(getContext(), iconURI, new ResourceDrawableUtils.BitmapLoader() {
@Override
public void onBitmapFound(final Drawable d) {
// Hide the image view if we don't have an icon to show.
if (d == null) {
mIconView.setVisibility(View.GONE);
} else {
mIconView.setImageDrawable(d);
mIconView.setVisibility(View.VISIBLE);
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/IconGridInput.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/IconGridInput.java
@@ -8,17 +8,17 @@ package org.mozilla.gecko.prompts;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.R;
-import org.mozilla.gecko.gfx.BitmapUtils;
+import org.mozilla.gecko.util.ResourceDrawableUtils;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -153,17 +153,17 @@ public class IconGridInput extends Promp
Drawable icon;
public IconGridItem(final Context context, final JSONObject obj) {
label = obj.optString("name");
final String iconUrl = obj.optString("iconUri");
description = obj.optString("description");
selected = obj.optBoolean("selected");
- BitmapUtils.getDrawable(context, iconUrl, new BitmapUtils.BitmapLoader() {
+ ResourceDrawableUtils.getDrawable(context, iconUrl, new ResourceDrawableUtils.BitmapLoader() {
@Override
public void onBitmapFound(Drawable d) {
icon = d;
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
});
--- a/mobile/android/base/java/org/mozilla/gecko/prompts/PromptListItem.java
+++ b/mobile/android/base/java/org/mozilla/gecko/prompts/PromptListItem.java
@@ -1,14 +1,14 @@
package org.mozilla.gecko.prompts;
import org.mozilla.gecko.IntentHelper;
-import org.mozilla.gecko.gfx.BitmapUtils;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.ThumbnailHelper;
+import org.mozilla.gecko.util.ResourceDrawableUtils;
import org.mozilla.gecko.widget.GeckoActionProvider;
import org.json.JSONArray;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -53,28 +53,28 @@ public class PromptListItem {
mIntent = null;
showAsActions = false;
// Support both "isParent" (backwards compat for older consumers), and "menu" for the new Tabbed prompt ui.
isParent = aObject.optBoolean("isParent") || aObject.optBoolean("menu");
}
final String iconStr = aObject.optString("icon");
if (iconStr != null) {
- final BitmapUtils.BitmapLoader loader = new BitmapUtils.BitmapLoader() {
+ final ResourceDrawableUtils.BitmapLoader loader = new ResourceDrawableUtils.BitmapLoader() {
@Override
public void onBitmapFound(Drawable d) {
mIcon = d;
}
};
if (iconStr.startsWith("thumbnail:")) {
final int id = Integer.parseInt(iconStr.substring(10), 10);
ThumbnailHelper.getInstance().getAndProcessThumbnailFor(id, loader);
} else {
- BitmapUtils.getDrawable(context, iconStr, loader);
+ ResourceDrawableUtils.getDrawable(context, iconStr, loader);
}
}
}
public void setIntent(Intent i) {
mIntent = i;
}
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
@@ -4,17 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.toolbar;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.R;
-import org.mozilla.gecko.gfx.BitmapUtils;
+import org.mozilla.gecko.util.ResourceDrawableUtils;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.widget.GeckoPopupMenu;
import android.content.Context;
import android.content.res.Resources;
@@ -136,17 +136,17 @@ public class PageActionLayout extends Li
final PageAction pageAction = new PageAction(id, title, null, onPageActionClickListeners, important);
int insertAt = mPageActionList.size();
while (insertAt > 0 && mPageActionList.get(insertAt - 1).isImportant()) {
insertAt--;
}
mPageActionList.add(insertAt, pageAction);
- BitmapUtils.getDrawable(mContext, imageData, new BitmapUtils.BitmapLoader() {
+ ResourceDrawableUtils.getDrawable(mContext, imageData, new ResourceDrawableUtils.BitmapLoader() {
@Override
public void onBitmapFound(final Drawable d) {
if (mPageActionList.contains(pageAction)) {
pageAction.setDrawable(d);
refreshPageActionIcons();
}
}
});
rename from mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/DrawableUtil.java
rename to mobile/android/base/java/org/mozilla/gecko/util/DrawableUtil.java
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/util/ResourceDrawableUtils.java
@@ -0,0 +1,127 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.gecko.util;
+
+import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.support.v7.widget.AppCompatDrawableManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.mozilla.gecko.util.GeckoJarReader;
+import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.gecko.util.UIAsyncTask;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import static org.mozilla.gecko.gfx.BitmapUtils.getBitmapFromDataURI;
+import static org.mozilla.gecko.gfx.BitmapUtils.getResource;
+
+public class ResourceDrawableUtils {
+ private static final String LOGTAG = "ResourceDrawableUtils";
+
+ public interface BitmapLoader {
+ public void onBitmapFound(Drawable d);
+ }
+
+ public static void runOnBitmapFoundOnUiThread(final BitmapLoader loader, final Drawable d) {
+ if (ThreadUtils.isOnUiThread()) {
+ loader.onBitmapFound(d);
+ return;
+ }
+
+ ThreadUtils.postToUiThread(new Runnable() {
+ @Override
+ public void run() {
+ loader.onBitmapFound(d);
+ }
+ });
+ }
+
+ /**
+ * Attempts to find a drawable associated with a given string, using its URI scheme to determine
+ * how to load the drawable. The BitmapLoader's `onBitmapFound` method is always called, and
+ * will be called with `null` if no drawable is found.
+ *
+ * The BitmapLoader `onBitmapFound` method always runs on the UI thread.
+ */
+ public static void getDrawable(final Context context, final String data, final BitmapLoader loader) {
+ if (TextUtils.isEmpty(data)) {
+ runOnBitmapFoundOnUiThread(loader, null);
+ return;
+ }
+
+ if (data.startsWith("data")) {
+ final BitmapDrawable d = new BitmapDrawable(context.getResources(), getBitmapFromDataURI(data));
+ runOnBitmapFoundOnUiThread(loader, d);
+ return;
+ }
+
+ if (data.startsWith("jar:") || data.startsWith("file://")) {
+ (new UIAsyncTask.WithoutParams<Drawable>(ThreadUtils.getBackgroundHandler()) {
+ @Override
+ public Drawable doInBackground() {
+ try {
+ if (data.startsWith("jar:jar")) {
+ return GeckoJarReader.getBitmapDrawable(
+ context, context.getResources(), data);
+ }
+
+ // Don't attempt to validate the JAR signature when loading an add-on icon
+ if (data.startsWith("jar:file")) {
+ return GeckoJarReader.getBitmapDrawable(
+ context, context.getResources(), Uri.decode(data));
+ }
+
+ final URL url = new URL(data);
+ final InputStream is = (InputStream) url.getContent();
+ try {
+ return Drawable.createFromStream(is, "src");
+ } finally {
+ is.close();
+ }
+ } catch (Exception e) {
+ Log.w(LOGTAG, "Unable to set icon", e);
+ }
+ return null;
+ }
+
+ @Override
+ public void onPostExecute(Drawable drawable) {
+ loader.onBitmapFound(drawable);
+ }
+ }).execute();
+ return;
+ }
+
+ if (data.startsWith("-moz-icon://")) {
+ final Uri imageUri = Uri.parse(data);
+ final String ssp = imageUri.getSchemeSpecificPart();
+ final String resource = ssp.substring(ssp.lastIndexOf('/') + 1);
+
+ try {
+ final Drawable d = context.getPackageManager().getApplicationIcon(resource);
+ runOnBitmapFoundOnUiThread(loader, d);
+ } catch (Exception ex) { }
+
+ return;
+ }
+
+ if (data.startsWith("drawable://")) {
+ final Uri imageUri = Uri.parse(data);
+ final int id = getResource(context, imageUri);
+ final Drawable d = context.getResources().getDrawable(id);
+
+ runOnBitmapFoundOnUiThread(loader, d);
+ return;
+ }
+
+ runOnBitmapFoundOnUiThread(loader, null);
+ }
+
+}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -119,17 +119,16 @@ gujar = add_java_jar('gecko-util')
gujar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x for x in [
'util/ActivityResultHandler.java',
'util/ActivityResultHandlerMap.java',
'util/ActivityUtils.java',
'util/BundleEventListener.java',
'util/Clipboard.java',
'util/ContextUtils.java',
'util/DateUtil.java',
- 'util/DrawableUtil.java',
'util/EventCallback.java',
'util/FileUtils.java',
'util/FloatUtils.java',
'util/GamepadUtils.java',
'util/GeckoBackgroundThread.java',
'util/GeckoEventListener.java',
'util/GeckoJarReader.java',
'util/GeckoRequest.java',
@@ -723,16 +722,18 @@ gbjar.sources += ['java/org/mozilla/geck
'toolbar/ToolbarEditLayout.java',
'toolbar/ToolbarEditText.java',
'toolbar/ToolbarPrefs.java',
'toolbar/ToolbarProgressView.java',
'trackingprotection/TrackingProtectionPrompt.java',
'updater/PostUpdateHandler.java',
'updater/UpdateService.java',
'updater/UpdateServiceHelper.java',
+ 'util/DrawableUtil.java',
+ 'util/ResourceDrawableUtils.java',
'util/TouchTargetUtil.java',
'widget/ActivityChooserModel.java',
'widget/AllCapsTextView.java',
'widget/AnchoredPopup.java',
'widget/AnimatedHeightLayout.java',
'widget/BasicColorPicker.java',
'widget/CheckableLinearLayout.java',
'widget/ClickableWhenDisabledEditText.java',
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/BitmapUtils.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/BitmapUtils.java
@@ -2,144 +2,36 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.gfx;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
-import org.mozilla.gecko.util.GeckoJarReader;
-import org.mozilla.gecko.util.ThreadUtils;
-import org.mozilla.gecko.util.UIAsyncTask;
-
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
public final class BitmapUtils {
private static final String LOGTAG = "GeckoBitmapUtils";
private BitmapUtils() {}
- public interface BitmapLoader {
- public void onBitmapFound(Drawable d);
- }
-
- public static void runOnBitmapFoundOnUiThread(final BitmapLoader loader, final Drawable d) {
- if (ThreadUtils.isOnUiThread()) {
- loader.onBitmapFound(d);
- return;
- }
-
- ThreadUtils.postToUiThread(new Runnable() {
- @Override
- public void run() {
- loader.onBitmapFound(d);
- }
- });
- }
-
- /**
- * Attempts to find a drawable associated with a given string, using its URI scheme to determine
- * how to load the drawable. The BitmapLoader's `onBitmapFound` method is always called, and
- * will be called with `null` if no drawable is found.
- *
- * The BitmapLoader `onBitmapFound` method always runs on the UI thread.
- */
- public static void getDrawable(final Context context, final String data, final BitmapLoader loader) {
- if (TextUtils.isEmpty(data)) {
- runOnBitmapFoundOnUiThread(loader, null);
- return;
- }
-
- if (data.startsWith("data")) {
- final BitmapDrawable d = new BitmapDrawable(context.getResources(), getBitmapFromDataURI(data));
- runOnBitmapFoundOnUiThread(loader, d);
- return;
- }
-
- if (data.startsWith("jar:") || data.startsWith("file://")) {
- (new UIAsyncTask.WithoutParams<Drawable>(ThreadUtils.getBackgroundHandler()) {
- @Override
- public Drawable doInBackground() {
- try {
- if (data.startsWith("jar:jar")) {
- return GeckoJarReader.getBitmapDrawable(
- context, context.getResources(), data);
- }
-
- // Don't attempt to validate the JAR signature when loading an add-on icon
- if (data.startsWith("jar:file")) {
- return GeckoJarReader.getBitmapDrawable(
- context, context.getResources(), Uri.decode(data));
- }
-
- final URL url = new URL(data);
- final InputStream is = (InputStream) url.getContent();
- try {
- return Drawable.createFromStream(is, "src");
- } finally {
- is.close();
- }
- } catch (Exception e) {
- Log.w(LOGTAG, "Unable to set icon", e);
- }
- return null;
- }
-
- @Override
- public void onPostExecute(Drawable drawable) {
- loader.onBitmapFound(drawable);
- }
- }).execute();
- return;
- }
-
- if (data.startsWith("-moz-icon://")) {
- final Uri imageUri = Uri.parse(data);
- final String ssp = imageUri.getSchemeSpecificPart();
- final String resource = ssp.substring(ssp.lastIndexOf('/') + 1);
-
- try {
- final Drawable d = context.getPackageManager().getApplicationIcon(resource);
- runOnBitmapFoundOnUiThread(loader, d);
- } catch (Exception ex) { }
-
- return;
- }
-
- if (data.startsWith("drawable://")) {
- final Uri imageUri = Uri.parse(data);
- final int id = getResource(context, imageUri);
- final Drawable d = context.getResources().getDrawable(id);
-
- runOnBitmapFoundOnUiThread(loader, d);
- return;
- }
-
- runOnBitmapFoundOnUiThread(loader, null);
- }
-
public static Bitmap decodeByteArray(byte[] bytes) {
return decodeByteArray(bytes, null);
}
public static Bitmap decodeByteArray(byte[] bytes, BitmapFactory.Options options) {
return decodeByteArray(bytes, 0, bytes.length, options);
}