/** * Decode and return the bitmap represented by the given index in the Icon Directory, if valid. * * @param index The index into the Icon Directory of the image of interest. * @return The decoded Bitmap object for this image, or null if the entry is invalid or decoding * fails. */ public Bitmap decodeBitmapAtIndex(int index) { final IconDirectoryEntry iconDirEntry = iconDirectory[index]; if (iconDirEntry.payloadIsPNG) { // PNG payload. Simply extract it and decode it. return BitmapUtils.decodeByteArray( decodand, offset + iconDirEntry.payloadOffset, iconDirEntry.payloadSize); } // The payload is a BMP, so we need to do some magic to get the decoder to do what we want. // We construct an ICO containing just the image we want, and let Android do the rest. byte[] decodeTarget = new byte [ICO_HEADER_LENGTH_BYTES + ICO_ICONDIRENTRY_LENGTH_BYTES + iconDirEntry.payloadSize]; // Set the type field in the ICO header. decodeTarget[2] = 1; // Set the num-images field in the header to 1. decodeTarget[4] = 1; // Copy the ICONDIRENTRY we need into the new buffer. System.arraycopy( decodand, offset + iconDirEntry.getOffset(), decodeTarget, ICO_HEADER_LENGTH_BYTES, ICO_ICONDIRENTRY_LENGTH_BYTES); // Copy the payload into the new buffer. final int singlePayloadOffset = ICO_HEADER_LENGTH_BYTES + ICO_ICONDIRENTRY_LENGTH_BYTES; System.arraycopy( decodand, offset + iconDirEntry.payloadOffset, decodeTarget, singlePayloadOffset, iconDirEntry.payloadSize); // Update the offset field of the ICONDIRENTRY to make the new ICO valid. decodeTarget[ICO_HEADER_LENGTH_BYTES + 12] = (byte) singlePayloadOffset; decodeTarget[ICO_HEADER_LENGTH_BYTES + 13] = (byte) (singlePayloadOffset >>> 8); decodeTarget[ICO_HEADER_LENGTH_BYTES + 14] = (byte) (singlePayloadOffset >>> 16); decodeTarget[ICO_HEADER_LENGTH_BYTES + 15] = (byte) (singlePayloadOffset >>> 24); // Decode the newly-constructed singleton-ICO. return BitmapUtils.decodeByteArray(decodeTarget); }
/** Sets search engines to be shown for user-entered queries. */ private void setSearchEngines(JSONObject data) { try { JSONObject suggest = data.getJSONObject("suggest"); String suggestEngine = suggest.isNull("engine") ? null : suggest.getString("engine"); String suggestTemplate = suggest.isNull("template") ? null : suggest.getString("template"); mSuggestionsEnabled = suggest.getBoolean("enabled"); boolean suggestionsPrompted = suggest.getBoolean("prompted"); JSONArray engines = data.getJSONArray("searchEngines"); ArrayList<SearchEngine> searchEngines = new ArrayList<SearchEngine>(); for (int i = 0; i < engines.length(); i++) { JSONObject engineJSON = engines.getJSONObject(i); String name = engineJSON.getString("name"); String iconURI = engineJSON.getString("iconURI"); Bitmap icon = BitmapUtils.getBitmapFromDataURI(iconURI); if (name.equals(suggestEngine) && suggestTemplate != null) { // suggest engine should be at the front of the list searchEngines.add(0, new SearchEngine(name, icon)); // The only time Tabs.getInstance().getSelectedTab() should // be null is when we're restoring after a crash. We should // never restore private tabs when that happens, so it // should be safe to assume that null means non-private. Tab tab = Tabs.getInstance().getSelectedTab(); if (tab == null || !tab.isPrivate()) mSuggestClient = new SuggestClient( GeckoApp.mAppContext, suggestTemplate, SUGGESTION_TIMEOUT, SUGGESTION_MAX); } else { searchEngines.add(new SearchEngine(name, icon)); } } mSearchEngines = searchEngines; mCursorAdapter.notifyDataSetChanged(); // show suggestions opt-in if user hasn't been prompted if (!suggestionsPrompted && mSuggestClient != null) { showSuggestionsOptIn(); } } catch (JSONException e) { Log.e(LOGTAG, "Error getting search engine JSON", e); } filterSuggestions(mSearchTerm); }
@Override public boolean onPrepareActionMode(final ActionModeCompat mode, final Menu menu) { // Android would normally expect us to only update the state of menu items here // To make the js-java interaction a bit simpler, we just wipe out the menu here and recreate // all // the javascript menu items in onPrepare instead. This will be called any time invalidate() // is called on the // action mode. menu.clear(); int length = mItems.length(); 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); BitmapUtils.getDrawable( anchorHandle.getContext(), obj.optString("icon"), new BitmapLoader() { @Override public void onBitmapFound(Drawable d) { if (d != null) { menuitem.setIcon(d); } } }); } catch (Exception ex) { Log.i(LOGTAG, "Exception building menu", ex); } } return true; }
private static void storeFaviconsInMemCache(Cursor c) { if (c == null || !c.moveToFirst()) { return; } final Favicons favicons = Favicons.getInstance(); do { final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL)); final byte[] b = c.getBlob(c.getColumnIndexOrThrow(URLColumns.FAVICON)); if (b == null) { continue; } Bitmap favicon = BitmapUtils.decodeByteArray(b); if (favicon == null) { continue; } favicon = favicons.scaleImage(favicon); favicons.putFaviconInMemCache(url, favicon); } while (c.moveToNext()); }
@Override public void run() { // Load the data from preferences, if it exists. loadFromPrefs(); if (TextUtils.isEmpty(mHeaderURL)) { // mHeaderURL is null is this is the early startup path. Use // the saved values, if we have any. mHeaderURL = mSavedURL; mColor = mSavedColor; if (TextUtils.isEmpty(mHeaderURL)) { // We don't have any saved values, so we probably don't have // any lightweight theme set yet. return; } } else if (TextUtils.equals(mHeaderURL, mSavedURL)) { // If we are already using the given header, just return // without doing any work. return; } else { // mHeaderURL and mColor probably need to be saved if we get here. saveToPrefs(); } String croppedURL = mHeaderURL; int mark = croppedURL.indexOf('?'); if (mark != -1) { croppedURL = croppedURL.substring(0, mark); } if (croppedURL.startsWith(ASSETS_PREFIX)) { onBitmapLoaded(loadFromAssets(croppedURL)); } else { onBitmapLoaded(BitmapUtils.decodeUrl(croppedURL)); } }
private void showNotification(JSONObject message) { NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); // These attributes are required final String id; try { builder.setContentTitle(message.getString(TITLE_ATTR)); builder.setContentText(message.getString(TEXT_ATTR)); id = message.getString(ID_ATTR); } catch (JSONException ex) { Log.i(LOGTAG, "Error parsing", ex); return; } Uri imageUri = Uri.parse(message.optString(SMALLICON_ATTR)); builder.setSmallIcon(BitmapUtils.getResource(imageUri, R.drawable.ic_status_logo)); JSONArray light = message.optJSONArray(LIGHT_ATTR); if (light != null && light.length() == 3) { try { builder.setLights(light.getInt(0), light.getInt(1), light.getInt(2)); } catch (JSONException ex) { Log.i(LOGTAG, "Error parsing", ex); } } boolean ongoing = message.optBoolean(ONGOING_ATTR); builder.setOngoing(ongoing); if (message.has(WHEN_ATTR)) { long when = message.optLong(WHEN_ATTR); builder.setWhen(when); } if (message.has(PRIORITY_ATTR)) { int priority = message.optInt(PRIORITY_ATTR); builder.setPriority(priority); } if (message.has(LARGE_ICON_ATTR)) { Bitmap b = BitmapUtils.getBitmapFromDataURI(message.optString(LARGE_ICON_ATTR)); builder.setLargeIcon(b); } if (message.has(PROGRESS_VALUE_ATTR) && message.has(PROGRESS_MAX_ATTR) && message.has(PROGRESS_INDETERMINATE_ATTR)) { try { final int progress = message.getInt(PROGRESS_VALUE_ATTR); final int progressMax = message.getInt(PROGRESS_MAX_ATTR); final boolean progressIndeterminate = message.getBoolean(PROGRESS_INDETERMINATE_ATTR); builder.setProgress(progressMax, progress, progressIndeterminate); } catch (JSONException ex) { Log.i(LOGTAG, "Error parsing", ex); } } JSONArray actions = message.optJSONArray(ACTIONS_ATTR); if (actions != null) { try { for (int i = 0; i < actions.length(); i++) { JSONObject action = actions.getJSONObject(i); final PendingIntent pending = buildButtonClickPendingIntent(message, action); final String actionTitle = action.getString(ACTION_TITLE_ATTR); final Uri actionImage = Uri.parse(action.optString(ACTION_ICON_ATTR)); builder.addAction( BitmapUtils.getResource(actionImage, R.drawable.ic_status_logo), actionTitle, pending); } } catch (JSONException ex) { Log.i(LOGTAG, "Error parsing", ex); } } PendingIntent pi = buildNotificationPendingIntent(message, CLICK_EVENT); builder.setContentIntent(pi); PendingIntent deletePendingIntent = buildNotificationPendingIntent(message, CLEARED_EVENT); builder.setDeleteIntent(deletePendingIntent); GeckoAppShell.notificationClient.add(id.hashCode(), builder.build()); boolean persistent = message.optBoolean(PERSISTENT_ATTR); // We add only not persistent notifications to the list since we want to purge only // them when geckoapp is destroyed. if (!persistent && !mClearableNotifications.containsKey(id)) { mClearableNotifications.put(id, message.toString()); } }
private void addAddonMenuItem(final MenuItemInfo info) { if (mMenu == null) { if (mAddonMenuItemsCache == null) mAddonMenuItemsCache = new Vector<MenuItemInfo>(); mAddonMenuItemsCache.add(info); return; } Menu menu; if (info.parent == 0) { menu = mMenu; } else { MenuItem parent = mMenu.findItem(info.parent); if (parent == null) return; if (!parent.hasSubMenu()) { mMenu.removeItem(parent.getItemId()); menu = mMenu.addSubMenu(Menu.NONE, parent.getItemId(), Menu.NONE, parent.getTitle()); if (parent.getIcon() != null) ((SubMenu) menu).getItem().setIcon(parent.getIcon()); } else { menu = parent.getSubMenu(); } } final MenuItem item = menu.add(Menu.NONE, info.id, Menu.NONE, info.label); item.setOnMenuItemClickListener( new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { Log.i(LOGTAG, "menu item clicked"); GeckoAppShell.sendEventToGecko( GeckoEvent.createBroadcastEvent( "Menu:Clicked", Integer.toString(info.id - ADDON_MENU_OFFSET))); return true; } }); if (info.icon != null) { if (info.icon.startsWith("data")) { BitmapDrawable drawable = new BitmapDrawable(BitmapUtils.getBitmapFromDataURI(info.icon)); item.setIcon(drawable); } else if (info.icon.startsWith("jar:") || info.icon.startsWith("file://")) { GeckoAppShell.getHandler() .post( new Runnable() { public void run() { try { URL url = new URL(info.icon); InputStream is = (InputStream) url.getContent(); try { Drawable drawable = Drawable.createFromStream(is, "src"); item.setIcon(drawable); } finally { is.close(); } } catch (Exception e) { Log.w(LOGTAG, "Unable to set icon", e); } } }); } } item.setCheckable(info.checkable); item.setChecked(info.checked); item.setEnabled(info.enabled); item.setVisible(info.visible); }