blob: 1517f41c762309af19b3c679290f317255cb17ad [file] [log] [blame]
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.webkit;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Holds user-agent metadata information and uses to generate user-agent client
* hints.
* <p>
* This class is functionally equivalent to
* <a href="https://wicg.github.io/ua-client-hints/#interface">UADataValues</a>.
*/
public final class UserAgentMetadata {
/**
* Use this value for bitness to use the platform's default bitness value, which is an empty
* string for Android WebView.
*/
public static final int BITNESS_DEFAULT = 0;
private final List<BrandVersion> mBrandVersionList;
private final String mFullVersion;
private final String mPlatform;
private final String mPlatformVersion;
private final String mArchitecture;
private final String mModel;
private boolean mMobile = true;
private int mBitness = BITNESS_DEFAULT;
private boolean mWow64 = false;
@RestrictTo(RestrictTo.Scope.LIBRARY)
private UserAgentMetadata(@NonNull List<BrandVersion> brandVersionList,
@Nullable String fullVersion, @Nullable String platform,
@Nullable String platformVersion, @Nullable String architecture,
@Nullable String model,
boolean mobile,
int bitness, boolean wow64) {
mBrandVersionList = brandVersionList;
mFullVersion = fullVersion;
mPlatform = platform;
mPlatformVersion = platformVersion;
mArchitecture = architecture;
mModel = model;
mMobile = mobile;
mBitness = bitness;
mWow64 = wow64;
}
/**
* Returns the current list of user-agent brand versions which are used to populate
* user-agent client hints {@code sec-ch-ua} and {@code sec-ch-ua-full-version-list}. Each
* {@link BrandVersion} object holds the brand name, brand major version and brand
* full version.
* <p>
* @see Builder#setBrandVersionList
*
*/
@NonNull
public List<BrandVersion> getBrandVersionList() {
return mBrandVersionList;
}
/**
* Returns the value for the {@code sec-ch-ua-full-version} client hint.
* <p>
* @see Builder#setFullVersion
*
*/
@Nullable
public String getFullVersion() {
return mFullVersion;
}
/**
* Returns the value for the {@code sec-ch-ua-platform} client hint.
* <p>
* @see Builder#setPlatform
*
*/
@Nullable
public String getPlatform() {
return mPlatform;
}
/**
* Returns the value for the {@code sec-ch-ua-platform-version} client hint.
* <p>
* @see Builder#setPlatformVersion
*
* @return Platform version string.
*/
@Nullable
public String getPlatformVersion() {
return mPlatformVersion;
}
/**
* Returns the value for the {@code sec-ch-ua-arch} client hint.
* <p>
* @see Builder#setArchitecture
*
*/
@Nullable
public String getArchitecture() {
return mArchitecture;
}
/**
* Returns the value for the {@code sec-ch-ua-model} client hint.
* <p>
* @see Builder#setModel
*
*/
@Nullable
public String getModel() {
return mModel;
}
/**
* Returns the value for the {@code sec-ch-ua-mobile} client hint.
* <p>
* @see Builder#setMobile
*
* @return A boolean indicates user-agent's device mobileness.
*/
public boolean isMobile() {
return mMobile;
}
/**
* Returns the value for the {@code sec-ch-ua-bitness} client hint.
* <p>
* @see Builder#setBitness
*
* @return An integer indicates the CPU bitness, the integer value will convert to string
* when generating the user-agent client hint, and {@link UserAgentMetadata#BITNESS_DEFAULT}
* means an empty string.
*/
public int getBitness() {
return mBitness;
}
/**
* Returns the value for the {@code sec-ch-ua-wow64} client hint.
* <p>
* @see Builder#setWow64
*
* @return A boolean to indicate whether user-agent's binary is running in 32-bit mode on
* 64-bit Windows.
*/
public boolean isWow64() {
return mWow64;
}
/**
* Two UserAgentMetadata objects are equal only if all the metadata values are equal.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof UserAgentMetadata)) return false;
UserAgentMetadata that = (UserAgentMetadata) o;
return mMobile == that.mMobile && mBitness == that.mBitness && mWow64 == that.mWow64
&& Objects.equals(mBrandVersionList, that.mBrandVersionList)
&& Objects.equals(mFullVersion, that.mFullVersion)
&& Objects.equals(mPlatform, that.mPlatform) && Objects.equals(
mPlatformVersion, that.mPlatformVersion) && Objects.equals(mArchitecture,
that.mArchitecture) && Objects.equals(mModel, that.mModel);
}
@Override
public int hashCode() {
return Objects.hash(mBrandVersionList, mFullVersion, mPlatform, mPlatformVersion,
mArchitecture, mModel, mMobile, mBitness, mWow64);
}
/**
* Class that holds brand name, major version and full version. Brand name and major version
* used to generated user-agent client hint {@code sec-cu-ua}. Brand name and full version
* used to generated user-agent client hint {@code sec-ch-ua-full-version-list}.
* <p>
* This class is functionally equivalent to
* <a href="https://wicg.github.io/ua-client-hints/#interface">NavigatorUABrandVersion</a>.
*
*/
public static final class BrandVersion {
private final String mBrand;
private final String mMajorVersion;
private final String mFullVersion;
@RestrictTo(RestrictTo.Scope.LIBRARY)
private BrandVersion(@NonNull String brand, @NonNull String majorVersion,
@NonNull String fullVersion) {
mBrand = brand;
mMajorVersion = majorVersion;
mFullVersion = fullVersion;
}
/**
* Returns the brand of user-agent brand version tuple.
*
*/
@NonNull
public String getBrand() {
return mBrand;
}
/**
* Returns the major version of user-agent brand version tuple.
*
*/
@NonNull
public String getMajorVersion() {
return mMajorVersion;
}
/**
* Returns the full version of user-agent brand version tuple.
*
*/
@NonNull
public String getFullVersion() {
return mFullVersion;
}
@NonNull
@Override
public String toString() {
return mBrand + "," + mMajorVersion + "," + mFullVersion;
}
/**
* Two BrandVersion objects are equal only if brand name, major version and full version
* are equal.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BrandVersion)) return false;
BrandVersion that = (BrandVersion) o;
return Objects.equals(mBrand, that.mBrand) && Objects.equals(mMajorVersion,
that.mMajorVersion) && Objects.equals(mFullVersion, that.mFullVersion);
}
@Override
public int hashCode() {
return Objects.hash(mBrand, mMajorVersion, mFullVersion);
}
/**
* Builder used to create {@link BrandVersion} objects.
* <p>
* Examples:
* <pre class="prettyprint">
* // Create a setting with a brand version contains brand name: myBrand,
* // major version: 100, full version: 100.1.1.1.
* new BrandVersion.Builder().setBrand("myBrand")
* .setMajorVersion("100")
* .setFullVersion("100.1.1.1")
* .build();
* </pre>
*/
public static final class Builder {
private String mBrand;
private String mMajorVersion;
private String mFullVersion;
/**
* Create an empty BrandVersion Builder.
*/
public Builder() {
}
/**
* Create a BrandVersion Builder from an existing BrandVersion object.
*/
public Builder(@NonNull BrandVersion brandVersion) {
mBrand = brandVersion.getBrand();
mMajorVersion = brandVersion.getMajorVersion();
mFullVersion = brandVersion.getFullVersion();
}
/**
* Builds the current brand, majorVersion and fullVersion into a BrandVersion object.
*
* @return The BrandVersion object represented by this Builder.
* @throws IllegalStateException If any of the value in brand, majorVersion and
* fullVersion is null or blank.
*/
@NonNull
public BrandVersion build() {
if (mBrand == null || mBrand.trim().isEmpty()
|| mMajorVersion == null || mMajorVersion.trim().isEmpty()
|| mFullVersion == null || mFullVersion.trim().isEmpty()) {
throw new IllegalStateException("Brand name, major version and full version "
+ "should not be null or blank.");
}
return new BrandVersion(mBrand, mMajorVersion, mFullVersion);
}
/**
* Sets the BrandVersion's brand. The brand should not be blank.
*
* @param brand The brand is used to generate user-agent client hint
* {@code sec-ch-ua} and {@code sec-ch-ua-full-version-list}.
*
*/
@NonNull
public BrandVersion.Builder setBrand(@NonNull String brand) {
if (brand.trim().isEmpty()) {
throw new IllegalArgumentException("Brand should not be blank.");
}
mBrand = brand;
return this;
}
/**
* Sets the BrandVersion's majorVersion. The majorVersion should not be blank.
*
* @param majorVersion The majorVersion is used to generate user-agent client hint
* {@code sec-ch-ua}.
*
*/
@NonNull
public BrandVersion.Builder setMajorVersion(@NonNull String majorVersion) {
if (majorVersion.trim().isEmpty()) {
throw new IllegalArgumentException("MajorVersion should not be blank.");
}
mMajorVersion = majorVersion;
return this;
}
/**
* Sets the BrandVersion's fullVersion. The fullVersion should not be blank.
*
* @param fullVersion The brand is used to generate user-agent client hint
* {@code sec-ch-ua-full-version-list}.
*
*/
@NonNull
public BrandVersion.Builder setFullVersion(@NonNull String fullVersion) {
if (fullVersion.trim().isEmpty()) {
throw new IllegalArgumentException("FullVersion should not be blank.");
}
mFullVersion = fullVersion;
return this;
}
}
}
/**
* Builder used to create {@link UserAgentMetadata} objects.
* <p>
* Examples:
* <pre class="prettyprint">
* // Create a setting with default options.
* new UserAgentMetadata.Builder().build();
*
* // Create a setting with a brand version contains brand name: myBrand, major version: 100,
* // full version: 100.1.1.1.
* BrandVersion brandVersion = new BrandVersion.Builder().setBrand("myBrand")
* .setMajorVersion("100")
* .setFullVersion("100.1.1.1")
* .build();
* new UserAgentMetadata.Builder().setBrandVersionList(Collections.singletonList(brandVersion))
* .build();
*
* // Create a setting brand version, platform, platform version and bitness.
* new UserAgentMetadata.Builder().setBrandVersionList(Collections.singletonList(brandVersion))
* .setPlatform("myPlatform")
* .setPlatform("1.1.1.1")
* .setBitness(BITNESS_64)
* .build();
* </pre>
*/
public static final class Builder {
private List<BrandVersion> mBrandVersionList = new ArrayList<>();
private String mFullVersion;
private String mPlatform;
private String mPlatformVersion;
private String mArchitecture;
private String mModel;
private boolean mMobile = true;
private int mBitness = BITNESS_DEFAULT;
private boolean mWow64 = false;
/**
* Create an empty UserAgentMetadata Builder.
*/
public Builder() {
}
/**
* Create a UserAgentMetadata Builder from an existing UserAgentMetadata object.
*/
public Builder(@NonNull UserAgentMetadata uaMetadata) {
mBrandVersionList = uaMetadata.getBrandVersionList();
mFullVersion = uaMetadata.getFullVersion();
mPlatform = uaMetadata.getPlatform();
mPlatformVersion = uaMetadata.getPlatformVersion();
mArchitecture = uaMetadata.getArchitecture();
mModel = uaMetadata.getModel();
mMobile = uaMetadata.isMobile();
mBitness = uaMetadata.getBitness();
mWow64 = uaMetadata.isWow64();
}
/**
* Builds the current settings into a UserAgentMetadata object.
*
* @return The UserAgentMetadata object represented by this Builder
*/
@NonNull
public UserAgentMetadata build() {
return new UserAgentMetadata(mBrandVersionList, mFullVersion, mPlatform,
mPlatformVersion, mArchitecture, mModel, mMobile, mBitness, mWow64);
}
/**
* Sets user-agent metadata brands and their versions. The brand name, major version and
* full version should not be blank. The default value is an empty list which means the
* system default user-agent metadata brands and versions will be used to generate the
* user-agent client hints.
*
* @param brandVersions a list of {@link BrandVersion} used to generated user-agent client
* hints {@code sec-cu-ua} and {@code sec-ch-ua-full-version-list}.
*
*/
@NonNull
public Builder setBrandVersionList(@NonNull List<BrandVersion> brandVersions) {
mBrandVersionList = brandVersions;
return this;
}
/**
* Sets the user-agent metadata full version. The full version should not be blank, even
* though the <a href="https://wicg.github.io/ua-client-hints">spec<a/> about brand full
* version could be empty. A blank full version could cause inconsistent brands when
* generating brand version related user-agent client hints. It also provides a bad
* experience for developers when processing the brand full version. If null is provided,
* the system default value will be used to generate the client hint.
*
* @param fullVersion The full version is used to generate user-agent client hint
* {@code sec-ch-ua-full-version}.
*
*/
@NonNull
public Builder setFullVersion(@Nullable String fullVersion) {
if (fullVersion == null) {
mFullVersion = null;
return this;
}
if (fullVersion.trim().isEmpty()) {
throw new IllegalArgumentException("Full version should not be blank.");
}
mFullVersion = fullVersion;
return this;
}
/**
* Sets the user-agent metadata platform. The platform should not be blank. If null is
* provided, the system default value will be used to generate the client hint.
*
* @param platform The platform is used to generate user-agent client hint
* {@code sec-ch-ua-platform}.
*
*/
@NonNull
public Builder setPlatform(@Nullable String platform) {
if (platform == null) {
mPlatform = null;
return this;
}
if (platform.trim().isEmpty()) {
throw new IllegalArgumentException("Platform should not be blank.");
}
mPlatform = platform;
return this;
}
/**
* Sets the user-agent metadata platform version. If null is provided, the system default
* value will be used to generate the client hint.
*
* @param platformVersion The platform version is used to generate user-agent client
* hint {@code sec-ch-ua-platform-version}.
*
*/
@NonNull
public Builder setPlatformVersion(@Nullable String platformVersion) {
mPlatformVersion = platformVersion;
return this;
}
/**
* Sets the user-agent metadata architecture. If null is provided, the system default
* value will be used to generate the client hint.
*
* @param architecture The architecture is used to generate user-agent client hint
* {@code sec-ch-ua-arch}.
*
*/
@NonNull
public Builder setArchitecture(@Nullable String architecture) {
mArchitecture = architecture;
return this;
}
/**
* Sets the user-agent metadata model. If null is provided, the system default value will
* be used to generate the client hint.
*
* @param model The model is used to generate user-agent client hint
* {@code sec-ch-ua-model}.
*
*/
@NonNull
public Builder setModel(@Nullable String model) {
mModel = model;
return this;
}
/**
* Sets the user-agent metadata mobile, the default value is true.
*
* @param mobile The mobile is used to generate user-agent client hint
* {@code sec-ch-ua-mobile}.
*
*/
@NonNull
public Builder setMobile(boolean mobile) {
mMobile = mobile;
return this;
}
/**
* Sets the user-agent metadata bitness, the default value is
* {@link UserAgentMetadata#BITNESS_DEFAULT}, which indicates an empty string for
* {@code sec-ch-ua-bitness}.
*
* @param bitness The bitness is used to generate user-agent client hint
* {@code sec-ch-ua-bitness}.
*
*/
@NonNull
public Builder setBitness(int bitness) {
mBitness = bitness;
return this;
}
/**
* Sets the user-agent metadata wow64, the default is false.
*
* @param wow64 The wow64 is used to generate user-agent client hint
* {@code sec-ch-ua-wow64}.
*
*/
@NonNull
public Builder setWow64(boolean wow64) {
mWow64 = wow64;
return this;
}
}
}