// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.webapps;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import org.chromium.blink_public.platform.WebDisplayMode;
import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.chrome.browser.ShortcutSource;
import org.chromium.chrome.browser.util.IntentUtils;
import org.chromium.content_public.common.ScreenOrientationValues;
import org.chromium.webapk.lib.common.WebApkConstants;
/**
* Stores info about a web app.
*/
public class WebappInfo {
private boolean mIsInitialized;
private String mId;
private String mEncodedIcon;
private Bitmap mDecodedIcon;
private Uri mUri;
private Uri mScopeUri;
private String mName;
private String mShortName;
private int mDisplayMode;
private int mOrientation;
private int mSource;
private long mThemeColor;
private long mBackgroundColor;
private boolean mIsIconGenerated;
private String mWebApkPackageName;
public static WebappInfo createEmpty() {
return new WebappInfo();
}
private static String titleFromIntent(Intent intent) {
// The reference to title has been kept for reasons of backward compatibility. For intents
// and shortcuts which were created before we utilized the concept of name and shortName,
// we set the name and shortName to be the title.
String title = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_TITLE);
return title == null ? "" : title;
}
public static String nameFromIntent(Intent intent) {
String name = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_NAME);
return name == null ? titleFromIntent(intent) : name;
}
public static String shortNameFromIntent(Intent intent) {
String shortName = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SHORT_NAME);
return shortName == null ? titleFromIntent(intent) : shortName;
}
public static int displayModeFromIntent(Intent intent) {
String displayMode =
IntentUtils.safeGetStringExtra(intent, WebApkConstants.EXTRA_WEBAPK_DISPLAY_MODE);
if (displayMode == null) {
return IntentUtils.safeGetIntExtra(
intent, ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.Standalone);
}
// {@link displayMode} should be one of
// https://w3c.github.io/manifest/#dfn-display-modes-values
if (displayMode.equals("fullscreen")) {
return WebDisplayMode.Fullscreen;
} else if (displayMode.equals("minimal-ui")) {
return WebDisplayMode.MinimalUi;
} else if (displayMode.equals("browser")) {
return WebDisplayMode.Browser;
} else {
return WebDisplayMode.Standalone;
}
}
public static int orientationFromIntent(Intent intent) {
String orientation =
IntentUtils.safeGetStringExtra(intent, WebApkConstants.EXTRA_WEBAPK_ORIENTATION);
if (orientation == null) {
return IntentUtils.safeGetIntExtra(
intent, ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.DEFAULT);
}
// {@link orientation} should be one of
// w3c.github.io/screen-orientation/#orientationlocktype-enum
if (orientation.equals("any")) {
return ScreenOrientationValues.ANY;
} else if (orientation.equals("natural")) {
return ScreenOrientationValues.NATURAL;
} else if (orientation.equals("landscape")) {
return ScreenOrientationValues.LANDSCAPE;
} else if (orientation.equals("landscape-primary")) {
return ScreenOrientationValues.LANDSCAPE_PRIMARY;
} else if (orientation.equals("landscape-secondary")) {
return ScreenOrientationValues.LANDSCAPE_SECONDARY;
} else if (orientation.equals("portrait")) {
return ScreenOrientationValues.PORTRAIT;
} else if (orientation.equals("portrait-primary")) {
return ScreenOrientationValues.PORTRAIT_PRIMARY;
} else if (orientation.equals("portrait-secondary")) {
return ScreenOrientationValues.PORTRAIT_SECONDARY;
} else {
return ScreenOrientationValues.DEFAULT;
}
}
/**
* Construct a WebappInfo.
* @param intent Intent containing info about the app.
*/
public static WebappInfo create(Intent intent) {
String id = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ID);
String icon = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ICON);
String url = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_URL);
String scope = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SCOPE);
int displayMode = displayModeFromIntent(intent);
int orientation = orientationFromIntent(intent);
int source = IntentUtils.safeGetIntExtra(intent,
ShortcutHelper.EXTRA_SOURCE, ShortcutSource.UNKNOWN);
long themeColor = IntentUtils.safeGetLongExtra(intent,
ShortcutHelper.EXTRA_THEME_COLOR,
ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
long backgroundColor = IntentUtils.safeGetLongExtra(intent,
ShortcutHelper.EXTRA_BACKGROUND_COLOR,
ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING);
boolean isIconGenerated = IntentUtils.safeGetBooleanExtra(intent,
ShortcutHelper.EXTRA_IS_ICON_GENERATED, false);
String name = nameFromIntent(intent);
String shortName = shortNameFromIntent(intent);
String webApkPackageName = IntentUtils.safeGetStringExtra(intent,
ShortcutHelper.EXTRA_WEBAPK_PACKAGE_NAME);
return create(id, url, scope, icon, name, shortName, displayMode, orientation, source,
themeColor, backgroundColor, isIconGenerated, webApkPackageName);
}
/**
* Construct a WebappInfo.
* @param id ID for the webapp.
* @param url URL for the webapp.
* @param scope Scope for the webapp.
* @param icon Icon to show for the webapp.
* @param name Name of the webapp.
* @param shortName The short name of the webapp.
* @param displayMode Display mode of the webapp.
* @param orientation Orientation of the webapp.
* @param source Source where the webapp was added from.
* @param themeColor The theme color of the webapp.
* @param isIconGenerated Whether the |icon| was generated by Chromium.
* @param webApkPackageName The package of the WebAPK associated with the webapp. Null if
* no WebAPK is associated with the webapp.
*/
public static WebappInfo create(String id, String url, String scope, String icon, String name,
String shortName, int displayMode, int orientation, int source, long themeColor,
long backgroundColor, boolean isIconGenerated, String webApkPackageName) {
if (id == null || url == null) {
Log.e("WebappInfo", "Data passed in was incomplete: " + id + ", " + url);
return null;
}
Uri uri = Uri.parse(url);
if (scope == null || scope.isEmpty()) {
scope = ShortcutHelper.getScopeFromUrl(url);
}
Uri scopeUri = Uri.parse(scope);
Uri webManifestUri = null;
return new WebappInfo(id, uri, scopeUri, icon, name, shortName, displayMode, orientation,
source, themeColor, backgroundColor, isIconGenerated, webApkPackageName);
}
private WebappInfo(String id, Uri uri, Uri scopeUri, String encodedIcon, String name,
String shortName, int displayMode, int orientation, int source, long themeColor,
long backgroundColor, boolean isIconGenerated, String webApkPackageName) {
mEncodedIcon = encodedIcon;
mId = id;
mName = name;
mShortName = shortName;
mUri = uri;
mScopeUri = scopeUri;
mDisplayMode = displayMode;
mOrientation = orientation;
mSource = source;
mThemeColor = themeColor;
mBackgroundColor = backgroundColor;
mIsIconGenerated = isIconGenerated;
mIsInitialized = mUri != null;
mWebApkPackageName = webApkPackageName;
}
private WebappInfo() {
}
public boolean isInitialized() {
return mIsInitialized;
}
public String id() {
return mId;
}
public Uri uri() {
return mUri;
}
public Uri scopeUri() {
return mScopeUri;
}
public String name() {
return mName;
}
public String shortName() {
return mShortName;
}
public int displayMode() {
return mDisplayMode;
}
public String webApkPackageName() {
return mWebApkPackageName;
}
public int orientation() {
return mOrientation;
}
public int source() {
return mSource;
}
/**
* Theme color is actually a 32 bit unsigned integer which encodes a color
* in ARGB format. mThemeColor is a long because we also need to encode the
* error state of ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING.
*/
public long themeColor() {
return mThemeColor;
}
/**
* Returns whether the theme color specified in the Intent is valid.
* A theme color isn't valid if its value is ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
*/
public boolean hasValidThemeColor() {
return mThemeColor != ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
}
/**
* Background color is actually a 32 bit unsigned integer which encodes a color
* in ARGB format. mBackgroundColor is a long because we also need to encode the
* error state of ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING.
*/
public long backgroundColor() {
return mBackgroundColor;
}
/**
* Returns whether the background color specified in the Intent is valid.
* A background color isn't valid if its value is
* ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING.
*/
public boolean hasValidBackgroundColor() {
return mBackgroundColor != ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING;
}
/**
* Returns the background color specified by {@link #backgroundColor()} if
* the value is valid. Returns the specified fallback color otherwise.
*/
public int backgroundColor(int fallback) {
return hasValidBackgroundColor() ? (int) mBackgroundColor : fallback;
}
// This is needed for clients that want to send the icon trough an intent.
public String encodedIcon() {
return mEncodedIcon;
}
/**
* Returns the icon in Bitmap form. Caches the result for future retrievals.
*/
public Bitmap icon() {
if (mDecodedIcon != null) return mDecodedIcon;
mDecodedIcon = ShortcutHelper.decodeBitmapFromString(mEncodedIcon);
return mDecodedIcon;
}
/**
* Returns whether the icon was generated by Chromium.
*/
public boolean isIconGenerated() {
return mIsIconGenerated;
}
/**
* Sets extras on an Intent that will launch a WebappActivity.
* @param intent Intent that will be used to launch a WebappActivity.
*/
public void setWebappIntentExtras(Intent intent) {
intent.putExtra(ShortcutHelper.EXTRA_ID, id());
intent.putExtra(ShortcutHelper.EXTRA_URL, uri().toString());
intent.putExtra(ShortcutHelper.EXTRA_SCOPE, scopeUri().toString());
intent.putExtra(ShortcutHelper.EXTRA_ICON, encodedIcon());
intent.putExtra(ShortcutHelper.EXTRA_VERSION, ShortcutHelper.WEBAPP_SHORTCUT_VERSION);
intent.putExtra(ShortcutHelper.EXTRA_NAME, name());
intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName());
intent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, displayMode());
intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, orientation());
intent.putExtra(ShortcutHelper.EXTRA_SOURCE, source());
intent.putExtra(ShortcutHelper.EXTRA_THEME_COLOR, themeColor());
intent.putExtra(ShortcutHelper.EXTRA_BACKGROUND_COLOR, backgroundColor());
intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_GENERATED, isIconGenerated());
if (webApkPackageName() != null) {
intent.putExtra(ShortcutHelper.EXTRA_WEBAPK_PACKAGE_NAME, webApkPackageName());
}
}
/**
* Returns true if the WebappInfo was created for an Intent fired from a launcher shortcut (as
* opposed to an intent from a push notification or other internal source).
*/
public boolean isLaunchedFromHomescreen() {
return source() != ShortcutSource.NOTIFICATION;
}
}