Пример #1
0
  /**
   * 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);
  }
Пример #2
0
  /** 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);
  }
Пример #3
0
    @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());
  }
Пример #5
0
    @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));
      }
    }
Пример #6
0
  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());
    }
  }
Пример #7
0
  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);
  }