platform-packages-apps-Settings / src / com / android / settings / webview / WebViewAppPicker.java
WebViewAppPicker.java
Raw
/*
 * Copyright (C) 2017 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 com.android.settings.webview;

import static android.provider.Settings.ACTION_WEBVIEW_SETTINGS;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.webkit.UserPackage;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
import com.android.settingslib.applications.DefaultAppInfo;
import com.android.settingslib.wrapper.PackageManagerWrapper;

import java.util.ArrayList;
import java.util.List;

public class WebViewAppPicker extends DefaultAppPickerFragment {
    private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;

    private WebViewUpdateServiceWrapper getWebViewUpdateServiceWrapper() {
        if (mWebViewUpdateServiceWrapper == null) {
            setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper());
        }
        return mWebViewUpdateServiceWrapper;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        if (!mUserManager.isAdminUser()) {
            getActivity().finish();
        }
    }

    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.webview_app_settings;
    }

    @Override
    protected List<DefaultAppInfo> getCandidates() {
        final List<DefaultAppInfo> packageInfoList = new ArrayList<DefaultAppInfo>();
        final Context context = getContext();
        final WebViewUpdateServiceWrapper webViewUpdateService = getWebViewUpdateServiceWrapper();
        final List<ApplicationInfo> pkgs =
                webViewUpdateService.getValidWebViewApplicationInfos(context);
        for (ApplicationInfo ai : pkgs) {
            packageInfoList.add(createDefaultAppInfo(context, mPm, ai,
                    getDisabledReason(webViewUpdateService, context, ai.packageName)));
        }
        return packageInfoList;
    }

    @Override
    protected String getDefaultKey() {
        PackageInfo currentPackage = getWebViewUpdateServiceWrapper().getCurrentWebViewPackage();
        return currentPackage == null ? null : currentPackage.packageName;
    }

    protected boolean setDefaultKey(String key) {
        boolean success = getWebViewUpdateServiceWrapper().setWebViewProvider(key);
        return success;
    }

    @Override
    protected void onSelectionPerformed(boolean success) {
        if (success) {
            Activity activity = getActivity();
            Intent intent = activity == null ? null : activity.getIntent();
            if (intent != null && ACTION_WEBVIEW_SETTINGS.equals(intent.getAction())) {
                // If this was started through ACTION_WEBVIEW_SETTINGS then return once we have
                // chosen a new package.
                getActivity().finish();
            }
        } else {
            getWebViewUpdateServiceWrapper().showInvalidChoiceToast(getActivity());
            updateCandidates();
        }
    }

    private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() {
        return new WebViewUpdateServiceWrapper();
    }

    @VisibleForTesting
    void setWebViewUpdateServiceWrapper(WebViewUpdateServiceWrapper wvusWrapper) {
        mWebViewUpdateServiceWrapper = wvusWrapper;
    }

    @Override
    public int getMetricsCategory() {
        return MetricsEvent.WEBVIEW_IMPLEMENTATION;
    }

    private static class WebViewAppInfo extends DefaultAppInfo {
        public WebViewAppInfo(Context context, PackageManagerWrapper pm,
                PackageItemInfo packageItemInfo, String summary, boolean enabled) {
            super(context, pm, packageItemInfo, summary, enabled);
        }

        @Override
        public CharSequence loadLabel() {
            String versionName = "";
            try {
                versionName = mPm.getPackageManager().
                        getPackageInfo(packageItemInfo.packageName, 0).versionName;
            } catch (PackageManager.NameNotFoundException e) {
            }
            return String.format("%s %s", super.loadLabel(), versionName);
        }
    }


    @VisibleForTesting
    DefaultAppInfo createDefaultAppInfo(Context context, PackageManagerWrapper pm,
            PackageItemInfo packageItemInfo, String disabledReason) {
        return new WebViewAppInfo(context, pm, packageItemInfo, disabledReason,
                TextUtils.isEmpty(disabledReason) /* enabled */);
    }

    /**
     * Returns the reason why a package cannot be used as WebView implementation.
     * This is either because of it being disabled, uninstalled, or hidden for any user.
     */
    @VisibleForTesting
    String getDisabledReason(WebViewUpdateServiceWrapper webviewUpdateServiceWrapper,
            Context context, String packageName) {
        List<UserPackage> userPackages =
                webviewUpdateServiceWrapper.getPackageInfosAllUsers(context, packageName);
        for (UserPackage userPackage : userPackages) {
            if (!userPackage.isInstalledPackage()) {
                // Package uninstalled/hidden
                return context.getString(
                        R.string.webview_uninstalled_for_user, userPackage.getUserInfo().name);
            } else if (!userPackage.isEnabledPackage()) {
                // Package disabled
                return context.getString(
                        R.string.webview_disabled_for_user, userPackage.getUserInfo().name);
            }
        }
        return null;
    }
}