diff options
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java')
-rw-r--r-- | mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java | 1694 |
1 files changed, 0 insertions, 1694 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java b/mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java deleted file mode 100644 index 08e79be3a..000000000 --- a/mobile/android/base/java/org/mozilla/gecko/home/HomeConfig.java +++ /dev/null @@ -1,1694 +0,0 @@ -/* -*- 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.home; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.annotation.RobocopTarget; -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.R; -import org.mozilla.gecko.util.ThreadUtils; - -import android.content.Context; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.Pair; - -public final class HomeConfig { - public static final String PREF_KEY_BOOKMARKS_PANEL_ENABLED = "bookmarksPanelEnabled"; - public static final String PREF_KEY_HISTORY_PANEL_ENABLED = "combinedHistoryPanelEnabled"; - - /** - * Used to determine what type of HomeFragment subclass to use when creating - * a given panel. With the exception of DYNAMIC, all of these types correspond - * to a default set of built-in panels. The DYNAMIC panel type is used by - * third-party services to create panels with varying types of content. - */ - @RobocopTarget - public static enum PanelType implements Parcelable { - TOP_SITES("top_sites", TopSitesPanel.class), - BOOKMARKS("bookmarks", BookmarksPanel.class), - COMBINED_HISTORY("combined_history", CombinedHistoryPanel.class), - DYNAMIC("dynamic", DynamicPanel.class), - // Deprecated panels that should no longer exist but are kept around for - // migration code. Class references have been replaced with new version of the panel. - DEPRECATED_REMOTE_TABS("remote_tabs", CombinedHistoryPanel.class), - DEPRECATED_HISTORY("history", CombinedHistoryPanel.class), - DEPRECATED_READING_LIST("reading_list", BookmarksPanel.class), - DEPRECATED_RECENT_TABS("recent_tabs", CombinedHistoryPanel.class); - - private final String mId; - private final Class<?> mPanelClass; - - PanelType(String id, Class<?> panelClass) { - mId = id; - mPanelClass = panelClass; - } - - public static PanelType fromId(String id) { - if (id == null) { - throw new IllegalArgumentException("Could not convert null String to PanelType"); - } - - for (PanelType panelType : PanelType.values()) { - if (TextUtils.equals(panelType.mId, id.toLowerCase())) { - return panelType; - } - } - - throw new IllegalArgumentException("Could not convert String id to PanelType"); - } - - @Override - public String toString() { - return mId; - } - - public Class<?> getPanelClass() { - return mPanelClass; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(ordinal()); - } - - public static final Creator<PanelType> CREATOR = new Creator<PanelType>() { - @Override - public PanelType createFromParcel(final Parcel source) { - return PanelType.values()[source.readInt()]; - } - - @Override - public PanelType[] newArray(final int size) { - return new PanelType[size]; - } - }; - } - - public static class PanelConfig implements Parcelable { - private final PanelType mType; - private final String mTitle; - private final String mId; - private final LayoutType mLayoutType; - private final List<ViewConfig> mViews; - private final AuthConfig mAuthConfig; - private final EnumSet<Flags> mFlags; - private final int mPosition; - - static final String JSON_KEY_TYPE = "type"; - static final String JSON_KEY_TITLE = "title"; - static final String JSON_KEY_ID = "id"; - static final String JSON_KEY_LAYOUT = "layout"; - static final String JSON_KEY_VIEWS = "views"; - static final String JSON_KEY_AUTH_CONFIG = "authConfig"; - static final String JSON_KEY_DEFAULT = "default"; - static final String JSON_KEY_DISABLED = "disabled"; - static final String JSON_KEY_POSITION = "position"; - - public enum Flags { - DEFAULT_PANEL, - DISABLED_PANEL - } - - public PanelConfig(JSONObject json) throws JSONException, IllegalArgumentException { - final String panelType = json.optString(JSON_KEY_TYPE, null); - if (TextUtils.isEmpty(panelType)) { - mType = PanelType.DYNAMIC; - } else { - mType = PanelType.fromId(panelType); - } - - mTitle = json.getString(JSON_KEY_TITLE); - mId = json.getString(JSON_KEY_ID); - - final String layoutTypeId = json.optString(JSON_KEY_LAYOUT, null); - if (layoutTypeId != null) { - mLayoutType = LayoutType.fromId(layoutTypeId); - } else { - mLayoutType = null; - } - - final JSONArray jsonViews = json.optJSONArray(JSON_KEY_VIEWS); - if (jsonViews != null) { - mViews = new ArrayList<ViewConfig>(); - - final int viewCount = jsonViews.length(); - for (int i = 0; i < viewCount; i++) { - final JSONObject jsonViewConfig = (JSONObject) jsonViews.get(i); - final ViewConfig viewConfig = new ViewConfig(i, jsonViewConfig); - mViews.add(viewConfig); - } - } else { - mViews = null; - } - - final JSONObject jsonAuthConfig = json.optJSONObject(JSON_KEY_AUTH_CONFIG); - if (jsonAuthConfig != null) { - mAuthConfig = new AuthConfig(jsonAuthConfig); - } else { - mAuthConfig = null; - } - - mFlags = EnumSet.noneOf(Flags.class); - - if (json.optBoolean(JSON_KEY_DEFAULT, false)) { - mFlags.add(Flags.DEFAULT_PANEL); - } - - if (json.optBoolean(JSON_KEY_DISABLED, false)) { - mFlags.add(Flags.DISABLED_PANEL); - } - - mPosition = json.optInt(JSON_KEY_POSITION, -1); - - validate(); - } - - @SuppressWarnings("unchecked") - public PanelConfig(Parcel in) { - mType = (PanelType) in.readParcelable(getClass().getClassLoader()); - mTitle = in.readString(); - mId = in.readString(); - mLayoutType = (LayoutType) in.readParcelable(getClass().getClassLoader()); - - mViews = new ArrayList<ViewConfig>(); - in.readTypedList(mViews, ViewConfig.CREATOR); - - mAuthConfig = (AuthConfig) in.readParcelable(getClass().getClassLoader()); - - mFlags = (EnumSet<Flags>) in.readSerializable(); - mPosition = in.readInt(); - - validate(); - } - - public PanelConfig(PanelConfig panelConfig) { - mType = panelConfig.mType; - mTitle = panelConfig.mTitle; - mId = panelConfig.mId; - mLayoutType = panelConfig.mLayoutType; - - mViews = new ArrayList<ViewConfig>(); - List<ViewConfig> viewConfigs = panelConfig.mViews; - if (viewConfigs != null) { - for (ViewConfig viewConfig : viewConfigs) { - mViews.add(new ViewConfig(viewConfig)); - } - } - - mAuthConfig = panelConfig.mAuthConfig; - mFlags = panelConfig.mFlags.clone(); - mPosition = panelConfig.mPosition; - - validate(); - } - - public PanelConfig(PanelType type, String title, String id) { - this(type, title, id, EnumSet.noneOf(Flags.class)); - } - - public PanelConfig(PanelType type, String title, String id, EnumSet<Flags> flags) { - this(type, title, id, null, null, null, flags, -1); - } - - public PanelConfig(PanelType type, String title, String id, LayoutType layoutType, - List<ViewConfig> views, AuthConfig authConfig, EnumSet<Flags> flags, int position) { - mType = type; - mTitle = title; - mId = id; - mLayoutType = layoutType; - mViews = views; - mAuthConfig = authConfig; - mFlags = flags; - mPosition = position; - - validate(); - } - - private void validate() { - if (mType == null) { - throw new IllegalArgumentException("Can't create PanelConfig with null type"); - } - - if (TextUtils.isEmpty(mTitle)) { - throw new IllegalArgumentException("Can't create PanelConfig with empty title"); - } - - if (TextUtils.isEmpty(mId)) { - throw new IllegalArgumentException("Can't create PanelConfig with empty id"); - } - - if (mLayoutType == null && mType == PanelType.DYNAMIC) { - throw new IllegalArgumentException("Can't create a dynamic PanelConfig with null layout type"); - } - - if ((mViews == null || mViews.size() == 0) && mType == PanelType.DYNAMIC) { - throw new IllegalArgumentException("Can't create a dynamic PanelConfig with no views"); - } - - if (mFlags == null) { - throw new IllegalArgumentException("Can't create PanelConfig with null flags"); - } - } - - public PanelType getType() { - return mType; - } - - public String getTitle() { - return mTitle; - } - - public String getId() { - return mId; - } - - public LayoutType getLayoutType() { - return mLayoutType; - } - - public int getViewCount() { - return (mViews != null ? mViews.size() : 0); - } - - public ViewConfig getViewAt(int index) { - return (mViews != null ? mViews.get(index) : null); - } - - public EnumSet<Flags> getFlags() { - return mFlags.clone(); - } - - public boolean isDynamic() { - return (mType == PanelType.DYNAMIC); - } - - public boolean isDefault() { - return mFlags.contains(Flags.DEFAULT_PANEL); - } - - private void setIsDefault(boolean isDefault) { - if (isDefault) { - mFlags.add(Flags.DEFAULT_PANEL); - } else { - mFlags.remove(Flags.DEFAULT_PANEL); - } - } - - public boolean isDisabled() { - return mFlags.contains(Flags.DISABLED_PANEL); - } - - private void setIsDisabled(boolean isDisabled) { - if (isDisabled) { - mFlags.add(Flags.DISABLED_PANEL); - } else { - mFlags.remove(Flags.DISABLED_PANEL); - } - } - - public AuthConfig getAuthConfig() { - return mAuthConfig; - } - - public int getPosition() { - return mPosition; - } - - public JSONObject toJSON() throws JSONException { - final JSONObject json = new JSONObject(); - - json.put(JSON_KEY_TYPE, mType.toString()); - json.put(JSON_KEY_TITLE, mTitle); - json.put(JSON_KEY_ID, mId); - - if (mLayoutType != null) { - json.put(JSON_KEY_LAYOUT, mLayoutType.toString()); - } - - if (mViews != null) { - final JSONArray jsonViews = new JSONArray(); - - final int viewCount = mViews.size(); - for (int i = 0; i < viewCount; i++) { - final ViewConfig viewConfig = mViews.get(i); - final JSONObject jsonViewConfig = viewConfig.toJSON(); - jsonViews.put(jsonViewConfig); - } - - json.put(JSON_KEY_VIEWS, jsonViews); - } - - if (mAuthConfig != null) { - json.put(JSON_KEY_AUTH_CONFIG, mAuthConfig.toJSON()); - } - - if (mFlags.contains(Flags.DEFAULT_PANEL)) { - json.put(JSON_KEY_DEFAULT, true); - } - - if (mFlags.contains(Flags.DISABLED_PANEL)) { - json.put(JSON_KEY_DISABLED, true); - } - - json.put(JSON_KEY_POSITION, mPosition); - - return json; - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - - if (this == o) { - return true; - } - - if (!(o instanceof PanelConfig)) { - return false; - } - - final PanelConfig other = (PanelConfig) o; - return mId.equals(other.mId); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(mType, 0); - dest.writeString(mTitle); - dest.writeString(mId); - dest.writeParcelable(mLayoutType, 0); - dest.writeTypedList(mViews); - dest.writeParcelable(mAuthConfig, 0); - dest.writeSerializable(mFlags); - dest.writeInt(mPosition); - } - - public static final Creator<PanelConfig> CREATOR = new Creator<PanelConfig>() { - @Override - public PanelConfig createFromParcel(final Parcel in) { - return new PanelConfig(in); - } - - @Override - public PanelConfig[] newArray(final int size) { - return new PanelConfig[size]; - } - }; - } - - public static enum LayoutType implements Parcelable { - FRAME("frame"); - - private final String mId; - - LayoutType(String id) { - mId = id; - } - - public static LayoutType fromId(String id) { - if (id == null) { - throw new IllegalArgumentException("Could not convert null String to LayoutType"); - } - - for (LayoutType layoutType : LayoutType.values()) { - if (TextUtils.equals(layoutType.mId, id.toLowerCase())) { - return layoutType; - } - } - - throw new IllegalArgumentException("Could not convert String id to LayoutType"); - } - - @Override - public String toString() { - return mId; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(ordinal()); - } - - public static final Creator<LayoutType> CREATOR = new Creator<LayoutType>() { - @Override - public LayoutType createFromParcel(final Parcel source) { - return LayoutType.values()[source.readInt()]; - } - - @Override - public LayoutType[] newArray(final int size) { - return new LayoutType[size]; - } - }; - } - - public static enum ViewType implements Parcelable { - LIST("list"), - GRID("grid"); - - private final String mId; - - ViewType(String id) { - mId = id; - } - - public static ViewType fromId(String id) { - if (id == null) { - throw new IllegalArgumentException("Could not convert null String to ViewType"); - } - - for (ViewType viewType : ViewType.values()) { - if (TextUtils.equals(viewType.mId, id.toLowerCase())) { - return viewType; - } - } - - throw new IllegalArgumentException("Could not convert String id to ViewType"); - } - - @Override - public String toString() { - return mId; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(ordinal()); - } - - public static final Creator<ViewType> CREATOR = new Creator<ViewType>() { - @Override - public ViewType createFromParcel(final Parcel source) { - return ViewType.values()[source.readInt()]; - } - - @Override - public ViewType[] newArray(final int size) { - return new ViewType[size]; - } - }; - } - - public static enum ItemType implements Parcelable { - ARTICLE("article"), - IMAGE("image"), - ICON("icon"); - - private final String mId; - - ItemType(String id) { - mId = id; - } - - public static ItemType fromId(String id) { - if (id == null) { - throw new IllegalArgumentException("Could not convert null String to ItemType"); - } - - for (ItemType itemType : ItemType.values()) { - if (TextUtils.equals(itemType.mId, id.toLowerCase())) { - return itemType; - } - } - - throw new IllegalArgumentException("Could not convert String id to ItemType"); - } - - @Override - public String toString() { - return mId; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(ordinal()); - } - - public static final Creator<ItemType> CREATOR = new Creator<ItemType>() { - @Override - public ItemType createFromParcel(final Parcel source) { - return ItemType.values()[source.readInt()]; - } - - @Override - public ItemType[] newArray(final int size) { - return new ItemType[size]; - } - }; - } - - public static enum ItemHandler implements Parcelable { - BROWSER("browser"), - INTENT("intent"); - - private final String mId; - - ItemHandler(String id) { - mId = id; - } - - public static ItemHandler fromId(String id) { - if (id == null) { - throw new IllegalArgumentException("Could not convert null String to ItemHandler"); - } - - for (ItemHandler itemHandler : ItemHandler.values()) { - if (TextUtils.equals(itemHandler.mId, id.toLowerCase())) { - return itemHandler; - } - } - - throw new IllegalArgumentException("Could not convert String id to ItemHandler"); - } - - @Override - public String toString() { - return mId; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(ordinal()); - } - - public static final Creator<ItemHandler> CREATOR = new Creator<ItemHandler>() { - @Override - public ItemHandler createFromParcel(final Parcel source) { - return ItemHandler.values()[source.readInt()]; - } - - @Override - public ItemHandler[] newArray(final int size) { - return new ItemHandler[size]; - } - }; - } - - public static class ViewConfig implements Parcelable { - private final int mIndex; - private final ViewType mType; - private final String mDatasetId; - private final ItemType mItemType; - private final ItemHandler mItemHandler; - private final String mBackImageUrl; - private final String mFilter; - private final EmptyViewConfig mEmptyViewConfig; - private final HeaderConfig mHeaderConfig; - private final EnumSet<Flags> mFlags; - - static final String JSON_KEY_TYPE = "type"; - static final String JSON_KEY_DATASET = "dataset"; - static final String JSON_KEY_ITEM_TYPE = "itemType"; - static final String JSON_KEY_ITEM_HANDLER = "itemHandler"; - static final String JSON_KEY_BACK_IMAGE_URL = "backImageUrl"; - static final String JSON_KEY_FILTER = "filter"; - static final String JSON_KEY_EMPTY = "empty"; - static final String JSON_KEY_HEADER = "header"; - static final String JSON_KEY_REFRESH_ENABLED = "refreshEnabled"; - - public enum Flags { - REFRESH_ENABLED - } - - public ViewConfig(int index, JSONObject json) throws JSONException, IllegalArgumentException { - mIndex = index; - mType = ViewType.fromId(json.getString(JSON_KEY_TYPE)); - mDatasetId = json.getString(JSON_KEY_DATASET); - mItemType = ItemType.fromId(json.getString(JSON_KEY_ITEM_TYPE)); - mItemHandler = ItemHandler.fromId(json.getString(JSON_KEY_ITEM_HANDLER)); - mBackImageUrl = json.optString(JSON_KEY_BACK_IMAGE_URL, null); - mFilter = json.optString(JSON_KEY_FILTER, null); - - final JSONObject jsonEmptyViewConfig = json.optJSONObject(JSON_KEY_EMPTY); - if (jsonEmptyViewConfig != null) { - mEmptyViewConfig = new EmptyViewConfig(jsonEmptyViewConfig); - } else { - mEmptyViewConfig = null; - } - - final JSONObject jsonHeaderConfig = json.optJSONObject(JSON_KEY_HEADER); - mHeaderConfig = jsonHeaderConfig != null ? new HeaderConfig(jsonHeaderConfig) : null; - - mFlags = EnumSet.noneOf(Flags.class); - if (json.optBoolean(JSON_KEY_REFRESH_ENABLED, false)) { - mFlags.add(Flags.REFRESH_ENABLED); - } - - validate(); - } - - @SuppressWarnings("unchecked") - public ViewConfig(Parcel in) { - mIndex = in.readInt(); - mType = (ViewType) in.readParcelable(getClass().getClassLoader()); - mDatasetId = in.readString(); - mItemType = (ItemType) in.readParcelable(getClass().getClassLoader()); - mItemHandler = (ItemHandler) in.readParcelable(getClass().getClassLoader()); - mBackImageUrl = in.readString(); - mFilter = in.readString(); - mEmptyViewConfig = (EmptyViewConfig) in.readParcelable(getClass().getClassLoader()); - mHeaderConfig = (HeaderConfig) in.readParcelable(getClass().getClassLoader()); - mFlags = (EnumSet<Flags>) in.readSerializable(); - - validate(); - } - - public ViewConfig(ViewConfig viewConfig) { - mIndex = viewConfig.mIndex; - mType = viewConfig.mType; - mDatasetId = viewConfig.mDatasetId; - mItemType = viewConfig.mItemType; - mItemHandler = viewConfig.mItemHandler; - mBackImageUrl = viewConfig.mBackImageUrl; - mFilter = viewConfig.mFilter; - mEmptyViewConfig = viewConfig.mEmptyViewConfig; - mHeaderConfig = viewConfig.mHeaderConfig; - mFlags = viewConfig.mFlags.clone(); - - validate(); - } - - private void validate() { - if (mType == null) { - throw new IllegalArgumentException("Can't create ViewConfig with null type"); - } - - if (TextUtils.isEmpty(mDatasetId)) { - throw new IllegalArgumentException("Can't create ViewConfig with empty dataset ID"); - } - - if (mItemType == null) { - throw new IllegalArgumentException("Can't create ViewConfig with null item type"); - } - - if (mItemHandler == null) { - throw new IllegalArgumentException("Can't create ViewConfig with null item handler"); - } - - if (mFlags == null) { - throw new IllegalArgumentException("Can't create ViewConfig with null flags"); - } - } - - public int getIndex() { - return mIndex; - } - - public ViewType getType() { - return mType; - } - - public String getDatasetId() { - return mDatasetId; - } - - public ItemType getItemType() { - return mItemType; - } - - public ItemHandler getItemHandler() { - return mItemHandler; - } - - public String getBackImageUrl() { - return mBackImageUrl; - } - - public String getFilter() { - return mFilter; - } - - public EmptyViewConfig getEmptyViewConfig() { - return mEmptyViewConfig; - } - - public HeaderConfig getHeaderConfig() { - return mHeaderConfig; - } - - public boolean hasHeaderConfig() { - return mHeaderConfig != null; - } - - public boolean isRefreshEnabled() { - return mFlags.contains(Flags.REFRESH_ENABLED); - } - - public JSONObject toJSON() throws JSONException { - final JSONObject json = new JSONObject(); - - json.put(JSON_KEY_TYPE, mType.toString()); - json.put(JSON_KEY_DATASET, mDatasetId); - json.put(JSON_KEY_ITEM_TYPE, mItemType.toString()); - json.put(JSON_KEY_ITEM_HANDLER, mItemHandler.toString()); - - if (!TextUtils.isEmpty(mBackImageUrl)) { - json.put(JSON_KEY_BACK_IMAGE_URL, mBackImageUrl); - } - - if (!TextUtils.isEmpty(mFilter)) { - json.put(JSON_KEY_FILTER, mFilter); - } - - if (mEmptyViewConfig != null) { - json.put(JSON_KEY_EMPTY, mEmptyViewConfig.toJSON()); - } - - if (mHeaderConfig != null) { - json.put(JSON_KEY_HEADER, mHeaderConfig.toJSON()); - } - - if (mFlags.contains(Flags.REFRESH_ENABLED)) { - json.put(JSON_KEY_REFRESH_ENABLED, true); - } - - return json; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mIndex); - dest.writeParcelable(mType, 0); - dest.writeString(mDatasetId); - dest.writeParcelable(mItemType, 0); - dest.writeParcelable(mItemHandler, 0); - dest.writeString(mBackImageUrl); - dest.writeString(mFilter); - dest.writeParcelable(mEmptyViewConfig, 0); - dest.writeParcelable(mHeaderConfig, 0); - dest.writeSerializable(mFlags); - } - - public static final Creator<ViewConfig> CREATOR = new Creator<ViewConfig>() { - @Override - public ViewConfig createFromParcel(final Parcel in) { - return new ViewConfig(in); - } - - @Override - public ViewConfig[] newArray(final int size) { - return new ViewConfig[size]; - } - }; - } - - public static class EmptyViewConfig implements Parcelable { - private final String mText; - private final String mImageUrl; - - static final String JSON_KEY_TEXT = "text"; - static final String JSON_KEY_IMAGE_URL = "imageUrl"; - - public EmptyViewConfig(JSONObject json) throws JSONException, IllegalArgumentException { - mText = json.optString(JSON_KEY_TEXT, null); - mImageUrl = json.optString(JSON_KEY_IMAGE_URL, null); - } - - public EmptyViewConfig(Parcel in) { - mText = in.readString(); - mImageUrl = in.readString(); - } - - public EmptyViewConfig(EmptyViewConfig emptyViewConfig) { - mText = emptyViewConfig.mText; - mImageUrl = emptyViewConfig.mImageUrl; - } - - public EmptyViewConfig(String text, String imageUrl) { - mText = text; - mImageUrl = imageUrl; - } - - public String getText() { - return mText; - } - - public String getImageUrl() { - return mImageUrl; - } - - public JSONObject toJSON() throws JSONException { - final JSONObject json = new JSONObject(); - - json.put(JSON_KEY_TEXT, mText); - json.put(JSON_KEY_IMAGE_URL, mImageUrl); - - return json; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mText); - dest.writeString(mImageUrl); - } - - public static final Creator<EmptyViewConfig> CREATOR = new Creator<EmptyViewConfig>() { - @Override - public EmptyViewConfig createFromParcel(final Parcel in) { - return new EmptyViewConfig(in); - } - - @Override - public EmptyViewConfig[] newArray(final int size) { - return new EmptyViewConfig[size]; - } - }; - } - - public static class HeaderConfig implements Parcelable { - static final String JSON_KEY_IMAGE_URL = "image_url"; - static final String JSON_KEY_URL = "url"; - - private final String mImageUrl; - private final String mUrl; - - public HeaderConfig(JSONObject json) { - mImageUrl = json.optString(JSON_KEY_IMAGE_URL); - mUrl = json.optString(JSON_KEY_URL); - } - - public HeaderConfig(Parcel in) { - mImageUrl = in.readString(); - mUrl = in.readString(); - } - - public String getImageUrl() { - return mImageUrl; - } - - public String getUrl() { - return mUrl; - } - - public JSONObject toJSON() throws JSONException { - JSONObject json = new JSONObject(); - - json.put(JSON_KEY_IMAGE_URL, mImageUrl); - json.put(JSON_KEY_URL, mUrl); - - return json; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mImageUrl); - dest.writeString(mUrl); - } - - public static final Creator<HeaderConfig> CREATOR = new Creator<HeaderConfig>() { - @Override - public HeaderConfig createFromParcel(Parcel source) { - return new HeaderConfig(source); - } - - @Override - public HeaderConfig[] newArray(int size) { - return new HeaderConfig[size]; - } - }; - } - - public static class AuthConfig implements Parcelable { - private final String mMessageText; - private final String mButtonText; - private final String mImageUrl; - - static final String JSON_KEY_MESSAGE_TEXT = "messageText"; - static final String JSON_KEY_BUTTON_TEXT = "buttonText"; - static final String JSON_KEY_IMAGE_URL = "imageUrl"; - - public AuthConfig(JSONObject json) throws JSONException, IllegalArgumentException { - mMessageText = json.optString(JSON_KEY_MESSAGE_TEXT); - mButtonText = json.optString(JSON_KEY_BUTTON_TEXT); - mImageUrl = json.optString(JSON_KEY_IMAGE_URL, null); - } - - public AuthConfig(Parcel in) { - mMessageText = in.readString(); - mButtonText = in.readString(); - mImageUrl = in.readString(); - - validate(); - } - - public AuthConfig(AuthConfig authConfig) { - mMessageText = authConfig.mMessageText; - mButtonText = authConfig.mButtonText; - mImageUrl = authConfig.mImageUrl; - - validate(); - } - - public AuthConfig(String messageText, String buttonText, String imageUrl) { - mMessageText = messageText; - mButtonText = buttonText; - mImageUrl = imageUrl; - - validate(); - } - - private void validate() { - if (mMessageText == null) { - throw new IllegalArgumentException("Can't create AuthConfig with null message text"); - } - - if (mButtonText == null) { - throw new IllegalArgumentException("Can't create AuthConfig with null button text"); - } - } - - public String getMessageText() { - return mMessageText; - } - - public String getButtonText() { - return mButtonText; - } - - public String getImageUrl() { - return mImageUrl; - } - - public JSONObject toJSON() throws JSONException { - final JSONObject json = new JSONObject(); - - json.put(JSON_KEY_MESSAGE_TEXT, mMessageText); - json.put(JSON_KEY_BUTTON_TEXT, mButtonText); - json.put(JSON_KEY_IMAGE_URL, mImageUrl); - - return json; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mMessageText); - dest.writeString(mButtonText); - dest.writeString(mImageUrl); - } - - public static final Creator<AuthConfig> CREATOR = new Creator<AuthConfig>() { - @Override - public AuthConfig createFromParcel(final Parcel in) { - return new AuthConfig(in); - } - - @Override - public AuthConfig[] newArray(final int size) { - return new AuthConfig[size]; - } - }; - } - /** - * Immutable representation of the current state of {@code HomeConfig}. - * This is what HomeConfig returns from a load() call and takes as - * input to save a new state. - * - * Users of {@code State} should use an {@code Iterator} to iterate - * through the contained {@code PanelConfig} instances. - * - * {@code State} is immutable i.e. you can't add, remove, or update - * contained elements directly. You have to use an {@code Editor} to - * change the state, which can be created through the {@code edit()} - * method. - */ - public static class State implements Iterable<PanelConfig> { - private HomeConfig mHomeConfig; - private final List<PanelConfig> mPanelConfigs; - private final boolean mIsDefault; - - State(List<PanelConfig> panelConfigs, boolean isDefault) { - this(null, panelConfigs, isDefault); - } - - private State(HomeConfig homeConfig, List<PanelConfig> panelConfigs, boolean isDefault) { - mHomeConfig = homeConfig; - mPanelConfigs = Collections.unmodifiableList(panelConfigs); - mIsDefault = isDefault; - } - - private void setHomeConfig(HomeConfig homeConfig) { - if (mHomeConfig != null) { - throw new IllegalStateException("Can't set HomeConfig more than once"); - } - - mHomeConfig = homeConfig; - } - - @Override - public Iterator<PanelConfig> iterator() { - return mPanelConfigs.iterator(); - } - - /** - * Returns whether this {@code State} instance represents the default - * {@code HomeConfig} configuration or not. - */ - public boolean isDefault() { - return mIsDefault; - } - - /** - * Creates an {@code Editor} for this state. - */ - public Editor edit() { - return new Editor(mHomeConfig, this); - } - } - - /** - * {@code Editor} allows you to make changes to a {@code State}. You - * can create {@code Editor} by calling {@code edit()} on the target - * {@code State} instance. - * - * {@code Editor} works on a copy of the {@code State} that originated - * it. This means that adding, removing, or updating panels in an - * {@code Editor} will never change the {@code State} which you - * created the {@code Editor} from. Calling {@code commit()} or - * {@code apply()} will cause the new {@code State} instance to be - * created and saved using the {@code HomeConfig} instance that - * created the source {@code State}. - * - * {@code Editor} is *not* thread-safe. You can only make calls on it - * from the thread where it was originally created. It will throw an - * exception if you don't follow this invariant. - */ - public static class Editor implements Iterable<PanelConfig> { - private final HomeConfig mHomeConfig; - private final Map<String, PanelConfig> mConfigMap; - private final List<String> mConfigOrder; - private final Thread mOriginalThread; - - // Each Pair represents parameters to a GeckoAppShell.notifyObservers call; - // the first String is the observer topic and the second string is the notification data. - private List<Pair<String, String>> mNotificationQueue; - private PanelConfig mDefaultPanel; - private int mEnabledCount; - - private boolean mHasChanged; - private final boolean mIsFromDefault; - - private Editor(HomeConfig homeConfig, State configState) { - mHomeConfig = homeConfig; - mOriginalThread = Thread.currentThread(); - mConfigMap = new HashMap<String, PanelConfig>(); - mConfigOrder = new LinkedList<String>(); - mNotificationQueue = new ArrayList<>(); - - mIsFromDefault = configState.isDefault(); - - initFromState(configState); - } - - /** - * Initialize the initial state of the editor from the given - * {@sode State}. A HashMap is used to represent the list of - * panels as it provides fast access, and a LinkedList is used to - * keep track of order. We keep a reference to the default panel - * and the number of enabled panels to avoid iterating through the - * map every time we need those. - * - * @param configState The source State to load the editor from. - */ - private void initFromState(State configState) { - for (PanelConfig panelConfig : configState) { - final PanelConfig panelCopy = new PanelConfig(panelConfig); - - if (!panelCopy.isDisabled()) { - mEnabledCount++; - } - - if (panelCopy.isDefault()) { - if (mDefaultPanel == null) { - mDefaultPanel = panelCopy; - } else { - throw new IllegalStateException("Multiple default panels in HomeConfig state"); - } - } - - final String panelId = panelConfig.getId(); - mConfigOrder.add(panelId); - mConfigMap.put(panelId, panelCopy); - } - - // We should always have a defined default panel if there's - // at least one enabled panel around. - if (mEnabledCount > 0 && mDefaultPanel == null) { - throw new IllegalStateException("Default panel in HomeConfig state is undefined"); - } - } - - private PanelConfig getPanelOrThrow(String panelId) { - final PanelConfig panelConfig = mConfigMap.get(panelId); - if (panelConfig == null) { - throw new IllegalStateException("Tried to access non-existing panel: " + panelId); - } - - return panelConfig; - } - - private boolean isCurrentDefaultPanel(PanelConfig panelConfig) { - if (mDefaultPanel == null) { - return false; - } - - return mDefaultPanel.equals(panelConfig); - } - - private void findNewDefault() { - // Pick the first panel that is neither disabled nor currently - // set as default. - for (PanelConfig panelConfig : makeOrderedCopy(false)) { - if (!panelConfig.isDefault() && !panelConfig.isDisabled()) { - setDefault(panelConfig.getId()); - return; - } - } - - mDefaultPanel = null; - } - - /** - * Makes an ordered list of PanelConfigs that can be references - * or deep copied objects. - * - * @param deepCopy true to make deep-copied objects - * @return ordered List of PanelConfigs - */ - private List<PanelConfig> makeOrderedCopy(boolean deepCopy) { - final List<PanelConfig> copiedList = new ArrayList<PanelConfig>(mConfigOrder.size()); - for (String panelId : mConfigOrder) { - PanelConfig panelConfig = mConfigMap.get(panelId); - if (deepCopy) { - panelConfig = new PanelConfig(panelConfig); - } - copiedList.add(panelConfig); - } - - return copiedList; - } - - private void setPanelIsDisabled(PanelConfig panelConfig, boolean disabled) { - if (panelConfig.isDisabled() == disabled) { - return; - } - - panelConfig.setIsDisabled(disabled); - mEnabledCount += (disabled ? -1 : 1); - } - - /** - * Gets the ID of the current default panel. - */ - public String getDefaultPanelId() { - ThreadUtils.assertOnThread(mOriginalThread); - - if (mDefaultPanel == null) { - return null; - } - - return mDefaultPanel.getId(); - } - - /** - * Set a new default panel. - * - * @param panelId the ID of the new default panel. - */ - public void setDefault(String panelId) { - ThreadUtils.assertOnThread(mOriginalThread); - - final PanelConfig panelConfig = getPanelOrThrow(panelId); - if (isCurrentDefaultPanel(panelConfig)) { - return; - } - - if (mDefaultPanel != null) { - mDefaultPanel.setIsDefault(false); - } - - panelConfig.setIsDefault(true); - setPanelIsDisabled(panelConfig, false); - - mDefaultPanel = panelConfig; - mHasChanged = true; - } - - /** - * Toggles disabled state for a panel. - * - * @param panelId the ID of the target panel. - * @param disabled true to disable the panel. - */ - public void setDisabled(String panelId, boolean disabled) { - ThreadUtils.assertOnThread(mOriginalThread); - - final PanelConfig panelConfig = getPanelOrThrow(panelId); - if (panelConfig.isDisabled() == disabled) { - return; - } - - setPanelIsDisabled(panelConfig, disabled); - - if (disabled) { - if (isCurrentDefaultPanel(panelConfig)) { - panelConfig.setIsDefault(false); - findNewDefault(); - } - } else if (mEnabledCount == 1) { - setDefault(panelId); - } - - mHasChanged = true; - } - - /** - * Adds a new {@code PanelConfig}. It will do nothing if the - * {@code Editor} already contains a panel with the same ID. - * - * @param panelConfig the {@code PanelConfig} instance to be added. - * @return true if the item has been added. - */ - public boolean install(PanelConfig panelConfig) { - ThreadUtils.assertOnThread(mOriginalThread); - - if (panelConfig == null) { - throw new IllegalStateException("Can't install a null panel"); - } - - if (!panelConfig.isDynamic()) { - throw new IllegalStateException("Can't install a built-in panel: " + panelConfig.getId()); - } - - if (panelConfig.isDisabled()) { - throw new IllegalStateException("Can't install a disabled panel: " + panelConfig.getId()); - } - - boolean installed = false; - - final String id = panelConfig.getId(); - if (!mConfigMap.containsKey(id)) { - mConfigMap.put(id, panelConfig); - - final int position = panelConfig.getPosition(); - if (position < 0 || position >= mConfigOrder.size()) { - mConfigOrder.add(id); - } else { - mConfigOrder.add(position, id); - } - - mEnabledCount++; - if (mEnabledCount == 1 || panelConfig.isDefault()) { - setDefault(panelConfig.getId()); - } - - installed = true; - - // Add an event to the queue if a new panel is successfully installed. - mNotificationQueue.add(new Pair<String, String>( - "HomePanels:Installed", panelConfig.getId())); - } - - mHasChanged = true; - return installed; - } - - /** - * Removes an existing panel. - * - * @return true if the item has been removed. - */ - public boolean uninstall(String panelId) { - ThreadUtils.assertOnThread(mOriginalThread); - - final PanelConfig panelConfig = mConfigMap.get(panelId); - if (panelConfig == null) { - return false; - } - - if (!panelConfig.isDynamic()) { - throw new IllegalStateException("Can't uninstall a built-in panel: " + panelConfig.getId()); - } - - mConfigMap.remove(panelId); - mConfigOrder.remove(panelId); - - if (!panelConfig.isDisabled()) { - mEnabledCount--; - } - - if (isCurrentDefaultPanel(panelConfig)) { - findNewDefault(); - } - - // Add an event to the queue if a panel is successfully uninstalled. - mNotificationQueue.add(new Pair<String, String>("HomePanels:Uninstalled", panelId)); - - mHasChanged = true; - return true; - } - - /** - * Moves panel associated with panelId to the specified position. - * - * @param panelId Id of panel - * @param destIndex Destination position - * @return true if move succeeded - */ - public boolean moveTo(String panelId, int destIndex) { - ThreadUtils.assertOnThread(mOriginalThread); - - if (!mConfigOrder.contains(panelId)) { - return false; - } - - mConfigOrder.remove(panelId); - mConfigOrder.add(destIndex, panelId); - mHasChanged = true; - - return true; - } - - /** - * Replaces an existing panel with a new {@code PanelConfig} instance. - * - * @return true if the item has been updated. - */ - public boolean update(PanelConfig panelConfig) { - ThreadUtils.assertOnThread(mOriginalThread); - - if (panelConfig == null) { - throw new IllegalStateException("Can't update a null panel"); - } - - boolean updated = false; - - final String id = panelConfig.getId(); - if (mConfigMap.containsKey(id)) { - final PanelConfig oldPanelConfig = mConfigMap.put(id, panelConfig); - - // The disabled and default states can't never be - // changed by an update operation. - panelConfig.setIsDefault(oldPanelConfig.isDefault()); - panelConfig.setIsDisabled(oldPanelConfig.isDisabled()); - - updated = true; - } - - mHasChanged = true; - return updated; - } - - /** - * Saves the current {@code Editor} state asynchronously in the - * background thread. - * - * @return the resulting {@code State} instance. - */ - public State apply() { - ThreadUtils.assertOnThread(mOriginalThread); - - // We're about to save the current state in the background thread - // so we should use a deep copy of the PanelConfig instances to - // avoid saving corrupted state. - final State newConfigState = - new State(mHomeConfig, makeOrderedCopy(true), isDefault()); - - // Copy the event queue to a new list, so that we only modify mNotificationQueue on - // the original thread where it was created. - final List<Pair<String, String>> copiedQueue = mNotificationQueue; - mNotificationQueue = new ArrayList<>(); - - ThreadUtils.getBackgroundHandler().post(new Runnable() { - @Override - public void run() { - mHomeConfig.save(newConfigState); - - // Send pending events after the new config is saved. - sendNotificationsToGecko(copiedQueue); - } - }); - - return newConfigState; - } - - /** - * Saves the current {@code Editor} state synchronously in the - * current thread. - * - * @return the resulting {@code State} instance. - */ - public State commit() { - ThreadUtils.assertOnThread(mOriginalThread); - - final State newConfigState = - new State(mHomeConfig, makeOrderedCopy(false), isDefault()); - - // This is a synchronous blocking operation, hence no - // need to deep copy the current PanelConfig instances. - mHomeConfig.save(newConfigState); - - // Send pending events after the new config is saved. - sendNotificationsToGecko(mNotificationQueue); - mNotificationQueue.clear(); - - return newConfigState; - } - - /** - * Returns whether the {@code Editor} represents the default - * {@code HomeConfig} configuration without any unsaved changes. - */ - public boolean isDefault() { - ThreadUtils.assertOnThread(mOriginalThread); - - return (!mHasChanged && mIsFromDefault); - } - - public boolean isEmpty() { - return mConfigMap.isEmpty(); - } - - private void sendNotificationsToGecko(List<Pair<String, String>> notifications) { - for (Pair<String, String> p : notifications) { - GeckoAppShell.notifyObservers(p.first, p.second); - } - } - - private class EditorIterator implements Iterator<PanelConfig> { - private final Iterator<String> mOrderIterator; - - public EditorIterator() { - mOrderIterator = mConfigOrder.iterator(); - } - - @Override - public boolean hasNext() { - return mOrderIterator.hasNext(); - } - - @Override - public PanelConfig next() { - final String panelId = mOrderIterator.next(); - return mConfigMap.get(panelId); - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Can't 'remove' from on Editor iterator."); - } - } - - @Override - public Iterator<PanelConfig> iterator() { - ThreadUtils.assertOnThread(mOriginalThread); - - return new EditorIterator(); - } - } - - public interface OnReloadListener { - public void onReload(); - } - - public interface HomeConfigBackend { - public State load(); - public void save(State configState); - public String getLocale(); - public void setOnReloadListener(OnReloadListener listener); - } - - // UUIDs used to create PanelConfigs for default built-in panels. These are - // public because they can be used in "about:home?panel=UUID" query strings - // to open specific panels without querying the active Home Panel - // configuration. Because they don't consider the active configuration, it - // is only sensible to do this for built-in panels (and not for dynamic - // panels). - private static final String TOP_SITES_PANEL_ID = "4becc86b-41eb-429a-a042-88fe8b5a094e"; - private static final String BOOKMARKS_PANEL_ID = "7f6d419a-cd6c-4e34-b26f-f68b1b551907"; - private static final String HISTORY_PANEL_ID = "f134bf20-11f7-4867-ab8b-e8e705d7fbe8"; - private static final String COMBINED_HISTORY_PANEL_ID = "4d716ce2-e063-486d-9e7c-b190d7b04dc6"; - private static final String RECENT_TABS_PANEL_ID = "5c2601a5-eedc-4477-b297-ce4cef52adf8"; - private static final String REMOTE_TABS_PANEL_ID = "72429afd-8d8b-43d8-9189-14b779c563d0"; - private static final String DEPRECATED_READING_LIST_PANEL_ID = "20f4549a-64ad-4c32-93e4-1dcef792733b"; - - private final HomeConfigBackend mBackend; - - public HomeConfig(HomeConfigBackend backend) { - mBackend = backend; - } - - public State load() { - final State configState = mBackend.load(); - configState.setHomeConfig(this); - - return configState; - } - - public String getLocale() { - return mBackend.getLocale(); - } - - public void save(State configState) { - mBackend.save(configState); - } - - public void setOnReloadListener(OnReloadListener listener) { - mBackend.setOnReloadListener(listener); - } - - public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType) { - return createBuiltinPanelConfig(context, panelType, EnumSet.noneOf(PanelConfig.Flags.class)); - } - - public static int getTitleResourceIdForBuiltinPanelType(PanelType panelType) { - switch (panelType) { - case TOP_SITES: - return R.string.home_top_sites_title; - - case BOOKMARKS: - case DEPRECATED_READING_LIST: - return R.string.bookmarks_title; - - case DEPRECATED_HISTORY: - case DEPRECATED_REMOTE_TABS: - case DEPRECATED_RECENT_TABS: - case COMBINED_HISTORY: - return R.string.home_history_title; - - default: - throw new IllegalArgumentException("Only for built-in panel types: " + panelType); - } - } - - public static String getIdForBuiltinPanelType(PanelType panelType) { - switch (panelType) { - case TOP_SITES: - return TOP_SITES_PANEL_ID; - - case BOOKMARKS: - return BOOKMARKS_PANEL_ID; - - case DEPRECATED_HISTORY: - return HISTORY_PANEL_ID; - - case COMBINED_HISTORY: - return COMBINED_HISTORY_PANEL_ID; - - case DEPRECATED_REMOTE_TABS: - return REMOTE_TABS_PANEL_ID; - - case DEPRECATED_READING_LIST: - return DEPRECATED_READING_LIST_PANEL_ID; - - case DEPRECATED_RECENT_TABS: - return RECENT_TABS_PANEL_ID; - - default: - throw new IllegalArgumentException("Only for built-in panel types: " + panelType); - } - } - - public static PanelConfig createBuiltinPanelConfig(Context context, PanelType panelType, EnumSet<PanelConfig.Flags> flags) { - final int titleId = getTitleResourceIdForBuiltinPanelType(panelType); - final String id = getIdForBuiltinPanelType(panelType); - - return new PanelConfig(panelType, context.getString(titleId), id, flags); - } - - public static HomeConfig getDefault(Context context) { - return new HomeConfig(new HomeConfigPrefsBackend(context)); - } -} |