// 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.physicalweb; import android.content.SharedPreferences; import android.os.Build; import org.chromium.base.ContextUtils; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager; import org.chromium.components.location.LocationUtils; /** * This class provides the basic interface to the Physical Web feature. */ public class PhysicalWeb { public static final int OPTIN_NOTIFY_MAX_TRIES = 1; private static final String PREF_PHYSICAL_WEB_NOTIFY_COUNT = "physical_web_notify_count"; private static final String PREF_IGNORE_OTHER_CLIENTS = "physical_web_ignore_other_clients"; private static final String FEATURE_NAME = "PhysicalWeb"; private static final String IGNORE_OTHER_CLIENTS_FEATURE_NAME = "PhysicalWebIgnoreOtherClients"; private static final int MIN_ANDROID_VERSION = 18; /** * Evaluate whether the environment is one in which the Physical Web should * be enabled. * @return true if the PhysicalWeb should be enabled */ public static boolean featureIsEnabled() { return ChromeFeatureList.isEnabled(FEATURE_NAME) && Build.VERSION.SDK_INT >= MIN_ANDROID_VERSION; } /** * Checks whether the Physical Web preference is switched to On. * * @return boolean {@code true} if the preference is On. */ public static boolean isPhysicalWebPreferenceEnabled() { return PrivacyPreferencesManager.getInstance().isPhysicalWebEnabled(); } /** * Checks whether the Physical Web onboard flow is active and the user has * not yet elected to either enable or decline the feature. * * @return boolean {@code true} if onboarding is complete. */ public static boolean isOnboarding() { return PrivacyPreferencesManager.getInstance().isPhysicalWebOnboarding(); } /** * Start the Physical Web feature. * At the moment, this only enables URL discovery over BLE. */ public static void startPhysicalWeb() { // Only subscribe to Nearby if we have the location permission. LocationUtils locationUtils = LocationUtils.getInstance(); if (locationUtils.hasAndroidLocationPermission() && locationUtils.isSystemLocationSettingEnabled()) { new NearbyBackgroundSubscription(NearbySubscription.SUBSCRIBE, new Runnable() { @Override public void run() { // We need to clear the list of nearby URLs so that they can be repopulated by // the new subscription, but we don't know whether we are already subscribed, so // we need to pass a callback so that we can clear as soon as we are // resubscribed. UrlManager.getInstance().clearNearbyUrls(); } }).run(); } } /** * Stop the Physical Web feature. */ public static void stopPhysicalWeb() { new NearbyBackgroundSubscription(NearbySubscription.UNSUBSCRIBE, new Runnable() { @Override public void run() { // This isn't absolutely necessary, but it's nice to clean up all our shared prefs. UrlManager.getInstance().clearAllUrls(); } }).run(); } /** * Returns true if we should fire notifications regardless of the existence of other Physical * Web clients. * This method is for use when the native library is not available. */ public static boolean shouldIgnoreOtherClients() { return ContextUtils.getAppSharedPreferences().getBoolean(PREF_IGNORE_OTHER_CLIENTS, false); } /** * Increments a value tracking how many times we've shown the Physical Web * opt-in notification. */ public static void recordOptInNotification() { SharedPreferences sharedPreferences = ContextUtils.getAppSharedPreferences(); int value = sharedPreferences.getInt(PREF_PHYSICAL_WEB_NOTIFY_COUNT, 0); sharedPreferences.edit().putInt(PREF_PHYSICAL_WEB_NOTIFY_COUNT, value + 1).apply(); } /** * Gets the current count of how many times a high-priority opt-in notification * has been shown. * @return an integer representing the high-priority notifification display count. */ public static int getOptInNotifyCount() { SharedPreferences sharedPreferences = ContextUtils.getAppSharedPreferences(); return sharedPreferences.getInt(PREF_PHYSICAL_WEB_NOTIFY_COUNT, 0); } /** * Perform various Physical Web operations that should happen on startup. */ public static void onChromeStart() { // The PhysicalWebUma calls in this method should be called only when the native library is // loaded. This is always the case on chrome startup. if (featureIsEnabled() && (isPhysicalWebPreferenceEnabled() || isOnboarding())) { boolean ignoreOtherClients = ChromeFeatureList.isEnabled(IGNORE_OTHER_CLIENTS_FEATURE_NAME); ContextUtils.getAppSharedPreferences().edit() .putBoolean(PREF_IGNORE_OTHER_CLIENTS, ignoreOtherClients) .apply(); startPhysicalWeb(); PhysicalWebUma.uploadDeferredMetrics(); } else { stopPhysicalWeb(); } } }