protected void update(String title, String url, long bookmarkId, boolean hasReaderCacheItem) {
    if (mShowIcons) {
      // The bookmark id will be 0 (null in database) when the url
      // is not a bookmark and negative for 'fake' bookmarks.
      final boolean isBookmark = bookmarkId > 0;

      updateStatusIcon(isBookmark, hasReaderCacheItem);
    } else {
      updateStatusIcon(false, false);
    }

    // Use the URL instead of an empty title for consistency with the normal URL
    // bar view - this is the equivalent of getDisplayTitle() in Tab.java
    setTitle(TextUtils.isEmpty(title) ? url : title);

    // No point updating the below things if URL has not changed. Prevents evil Favicon flicker.
    if (url.equals(mPageUrl)) {
      return;
    }

    // Blank the Favicon, so we don't show the wrong Favicon if we scroll and miss DB.
    mFavicon.clearImage();

    if (mOngoingIconLoad != null) {
      mOngoingIconLoad.cancel(true);
    }

    // Displayed RecentTabsPanel URLs may refer to pages opened in reader mode, so we
    // remove the about:reader prefix to ensure the Favicon loads properly.
    final String pageURL = ReaderModeUtils.stripAboutReaderUrl(url);

    if (bookmarkId < BrowserContract.Bookmarks.FAKE_PARTNER_BOOKMARKS_START) {
      mOngoingIconLoad =
          Icons.with(getContext())
              .pageUrl(pageURL)
              .skipNetwork()
              .privileged(true)
              .icon(
                  IconDescriptor.createGenericIcon(
                      PartnerBookmarksProviderProxy.getUriForIcon(getContext(), bookmarkId)
                          .toString()))
              .build()
              .execute(mFavicon.createIconCallback());
    } else {
      mOngoingIconLoad =
          Icons.with(getContext())
              .pageUrl(pageURL)
              .skipNetwork()
              .build()
              .execute(mFavicon.createIconCallback());
    }

    updateDisplayedUrl(url, hasReaderCacheItem);
  }
  /**
   * Configure this Preference object from the Gecko search engine object.
   *
   * @param geckoEngine The Gecko-formatted object representing the search engine.
   */
  public void setSearchEngineFromBundle(GeckoBundle geckoEngine) {
    mIdentifier = geckoEngine.getString("identifier");

    // A null JS value gets converted into a string.
    if (mIdentifier == null || mIdentifier.equals("null")) {
      mIdentifier = "other";
    }

    final String engineName = geckoEngine.getString("name");
    final SpannableString titleSpannable = new SpannableString(engineName);

    setTitle(titleSpannable);

    final String iconURI = geckoEngine.getString("iconURI");
    // Keep a reference to the bitmap - we'll need it later in onBindView.
    try {
      Icons.with(getContext())
          .pageUrl(mIdentifier)
          .icon(IconDescriptor.createGenericIcon(iconURI))
          .privileged(true)
          .build()
          .execute(
              new IconCallback() {
                @Override
                public void onIconResponse(IconResponse response) {
                  mIconBitmap = response.getBitmap();

                  if (mFaviconView != null) {
                    mFaviconView.updateAndScaleImage(response);
                  }
                }
              });
    } catch (IllegalArgumentException e) {
      Log.e(
          LOGTAG, "IllegalArgumentException creating Bitmap. Most likely a zero-length bitmap.", e);
    } catch (NullPointerException e) {
      Log.e(LOGTAG, "NullPointerException creating Bitmap. Most likely a zero-length bitmap.", e);
    }
  }