diff --git a/.gitignore b/.gitignore index 287c93cf8..9f0094d1e 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,6 @@ tools/webgfx-tests-fxr/ # Room schemas app/schemas/ + +# Token files +.mls_token diff --git a/.taskcluster.yml b/.taskcluster.yml index 7fe7e771a..881e93cf0 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -73,6 +73,7 @@ tasks: - "secrets:get:project/firefoxreality/fr/github-deploy-key" - "secrets:get:project/firefoxreality/fr/staging-signing-token" - "secrets:get:project/firefoxreality/fr/symbols-token" + - "secrets:get:project/firefoxreality/fr/mls-key" routes: - notify.email.fxr-releng@mozilla.com.on-any payload: @@ -91,6 +92,7 @@ tasks: && rm -rf gvr-android-sdk && git clone https://github.com/MozillaReality/FirefoxReality-gvr-android-sdk.git gvr-android-sdk && git submodule update && . tools/taskcluster/get_third_party.sh + && python tools/taskcluster/fetch_secret.py -s project/firefoxreality/fr/mls-key -o .mls_token -n key && cp tools/gradle/taskcluster.properties ./user.properties && ./gradlew --no-daemon --console=plain clean `python tools/taskcluster/build_targets.py =all` && python tools/taskcluster/fetch_secret.py -s project/firefoxreality/fr/staging-signing-token -o token -n token @@ -123,6 +125,7 @@ tasks: - "secrets:get:project/firefoxreality/fr/github-deploy-key" - "secrets:get:project/firefoxreality/fr/release-signing-token" - "secrets:get:project/firefoxreality/fr/symbols-token" + - "secrets:get:project/firefoxreality/fr/mls-key" routes: - notify.email.fxr-releng@mozilla.com.on-any payload: @@ -141,6 +144,7 @@ tasks: && rm -rf gvr-android-sdk && git clone https://github.com/MozillaReality/FirefoxReality-gvr-android-sdk.git gvr-android-sdk && git submodule update && . tools/taskcluster/get_third_party.sh + && python tools/taskcluster/fetch_secret.py -s project/firefoxreality/fr/mls-key -o .mls_token -n key && cp tools/gradle/taskcluster.properties ./user.properties && ./gradlew --no-daemon --console=plain clean `python tools/taskcluster/build_targets.py ${event.release.tag_name}` && python tools/taskcluster/fetch_secret.py -s project/firefoxreality/fr/release-signing-token -o token -n token diff --git a/app/build.gradle b/app/build.gradle index 61fef3d94..5bcfa0cdc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -477,6 +477,7 @@ dependencies { implementation deps.android_components.browser_storage implementation deps.android_components.browser_domains implementation deps.android_components.service_accounts + implementation deps.android_components.mozilla_service_location implementation deps.android_components.ui_autocomplete implementation deps.android_components.concept_fetch implementation deps.android_components.lib_fetch @@ -558,6 +559,24 @@ if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcd apply from: "${topsrcdir}/substitute-local-geckoview.gradle" } +// ------------------------------------------------------------------------------------------------- +// MLS: Read token from local file if it exists +// ------------------------------------------------------------------------------------------------- + +android.applicationVariants.all { variant -> + print("MLS token: ") + + try { + def token = new File("${rootDir}/.mls_token").text.trim() + buildConfigField 'String', 'MLS_TOKEN', '"' + token + '"' + println "(Added from .mls_token file)" + } catch (FileNotFoundException ignored) { + buildConfigField 'String', 'MLS_TOKEN', '""' + println("X_X") + } + +} + // ------------------------------------------------------------------------------------------------- // Dynamically set versionCode (See tools/build/versionCode.gradle // ------------------------------------------------------------------------------------------------- diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 606416538..e9e06e4f9 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -292,7 +292,7 @@ protected void onCreate(Bundle savedInstanceState) { mSearchEngineWrapper = SearchEngineWrapper.get(this); mSearchEngineWrapper.registerForUpdates(); - GeolocationWrapper.update(this); + GeolocationWrapper.INSTANCE.update(this); mConnectivityReceiver = new ConnectivityReceiver(); mPoorPerformanceWhiteList = new HashSet<>(); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt index 2e013c8c1..42c6824e6 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/EngineProvider.kt @@ -16,6 +16,7 @@ object EngineProvider { private var runtime: GeckoRuntime? = null private var executor: GeckoWebExecutor? = null + private var client: GeckoViewFetchClient? = null @Synchronized fun getOrCreateRuntime(context: Context): GeckoRuntime { @@ -74,4 +75,12 @@ object EngineProvider { return GeckoViewFetchClient(context) } + fun getDefaultClient(context: Context): GeckoViewFetchClient { + if (client == null) { + client = createClient(context) + } + + return client!! + } + } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java index 58959f163..4f39130a9 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java @@ -1430,7 +1430,9 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin if (mContext != null) { if (key.equals(mContext.getString(R.string.settings_key_geolocation_data))) { GeolocationData data = GeolocationData.parse(sharedPreferences.getString(key, null)); - setRegion(data.getCountryCode()); + if (data != null) { + setRegion(data.getCountryCode()); + } } } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationClient.java b/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationClient.java deleted file mode 100644 index 4e5eb9927..000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationClient.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.mozilla.vrbrowser.geolocation; - -import android.os.Handler; -import android.os.Looper; - -import androidx.annotation.NonNull; - -import org.json.JSONObject; -import org.mozilla.geckoview.GeckoWebExecutor; -import org.mozilla.geckoview.WebRequest; - -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; -import java.util.function.Function; - -class GeolocationClient { - - static void getGeolocation(@NonNull GeckoWebExecutor executor, String aQuery, Function success, Function error) { - new Handler(Looper.getMainLooper()).post(() -> { - WebRequest request = new WebRequest.Builder(aQuery) - .method("GET") - .build(); - - executor.fetch(request).then(webResponse -> { - String body; - if (webResponse != null) { - if (webResponse.body != null) { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - int nRead; - byte[] data = new byte[1024]; - while ((nRead = webResponse.body.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - body = new String(buffer.toByteArray(), StandardCharsets.UTF_8); - - if (webResponse.statusCode == 200) { - JSONObject reader = new JSONObject(body); - success.apply(GeolocationData.parse(reader.toString())); - - } else { - // called when response HTTP status is not "200" - error.apply(String.format("Network Error: %s", webResponse.statusCode)); - } - - } else { - // WebResponse body is null - error.apply("Response body is null"); - } - - } else { - // WebResponse is null - error.apply("Response is null"); - } - return null; - - }).exceptionally(throwable -> { - // Exception happened - error.apply(String.format("Unknown network Error: %s", String.format("An exception happened during the request: %s", throwable.getMessage()))); - return null; - }); - }); - } -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationData.java b/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationData.java index aa1e96b81..0767114df 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationData.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationData.java @@ -7,6 +7,7 @@ import org.mozilla.vrbrowser.utils.SystemUtils; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** * Class representing a Geolocation success response (HTTP 200) @@ -15,6 +16,9 @@ public class GeolocationData { private static final String LOGTAG = SystemUtils.createLogtag(GeolocationData.class); + private static final String COUNTRY_CODE = "country_code"; + private static final String COUNTRY_NAME = "country_name"; + private JSONObject mData; private GeolocationData(JSONObject data) { @@ -27,6 +31,19 @@ public static GeolocationData create(JSONObject data) { } @NonNull + public static GeolocationData create(String countryCode, String countryName) { + JSONObject json = new JSONObject(); + try { + json.put(COUNTRY_CODE, countryCode); + json.put(COUNTRY_NAME, countryName); + + } catch (JSONException e) { + e.printStackTrace(); + } + return GeolocationData.create(json); + } + + @Nullable public static GeolocationData parse(String aGeolocationJson) { try { return GeolocationData.create(new JSONObject(aGeolocationJson)); @@ -38,11 +55,11 @@ public static GeolocationData parse(String aGeolocationJson) { } public String getCountryCode() { - return mData.optString("country_code", ""); + return mData.optString(COUNTRY_CODE, ""); } public String getCountryName() { - return mData.optString("country_name", ""); + return mData.optString(COUNTRY_NAME, ""); } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationWrapper.java b/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationWrapper.java deleted file mode 100644 index 18dee0f16..000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationWrapper.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.mozilla.vrbrowser.geolocation; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import org.mozilla.gecko.util.ThreadUtils; -import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.browser.SettingsStore; -import org.mozilla.vrbrowser.browser.engine.EngineProvider; - -public class GeolocationWrapper { - - private static final int MAX_RETRIES = 2; - private static final int RETRY_SLEEP = 5 * 1000; - - public static void update(final @NonNull Context aContext) { - String endpoint = aContext.getString(R.string.geolocation_api_url); - update(aContext, endpoint, 0, MAX_RETRIES); - } - - private static void update(final @NonNull Context aContext, - final @NonNull String endPoint, - final int retryCount, - final int maxRetries) { - if (retryCount <= maxRetries - 1) { - GeolocationClient.getGeolocation( - EngineProvider.INSTANCE.getDefaultGeckoWebExecutor(aContext), - endPoint, - (data) -> { - if (data == null) { - if (retryCount <= maxRetries) { - ThreadUtils.postDelayedToUiThread(() -> - update(aContext, endPoint, retryCount + 1, maxRetries), - RETRY_SLEEP); - } - - } else { - SettingsStore.getInstance(aContext).setGeolocationData(data.toString()); - } - return null; - }, - (error) -> { - if (retryCount <= maxRetries) { - ThreadUtils.postDelayedToUiThread(() -> - update(aContext, endPoint, retryCount + 1, maxRetries), - RETRY_SLEEP); - } - return null; - }); - } - } - -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationWrapper.kt b/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationWrapper.kt new file mode 100644 index 000000000..fadcfead6 --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/geolocation/GeolocationWrapper.kt @@ -0,0 +1,40 @@ +package org.mozilla.vrbrowser.geolocation + +import android.content.Context +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.future.future +import kotlinx.coroutines.launch +import mozilla.components.service.location.MozillaLocationService +import org.mozilla.vrbrowser.browser.engine.EngineProvider +import org.mozilla.vrbrowser.browser.SettingsStore +import java.util.concurrent.CompletableFuture + +object GeolocationWrapper { + + fun update(context: Context) { + val locationService = MozillaLocationService( + context, + EngineProvider.getDefaultClient(context), + org.mozilla.vrbrowser.BuildConfig.MLS_TOKEN + ) + CoroutineScope(Dispatchers.IO).launch { + locationService.fetchRegion(true)?.run { + val data: GeolocationData = GeolocationData.create(countryCode, countryName) + SettingsStore.getInstance(context).setGeolocationData(data.toString()) + } + } + } + + fun get(context: Context): CompletableFuture = + GlobalScope.future { + val locationService = MozillaLocationService( + context, + EngineProvider.getDefaultClient(context), + org.mozilla.vrbrowser.BuildConfig.MLS_TOKEN + ) + locationService.fetchRegion(false) + } + +} \ No newline at end of file diff --git a/app/src/common/shared/org/mozilla/vrbrowser/search/GeolocationLocalizationProvider.java b/app/src/common/shared/org/mozilla/vrbrowser/search/GeolocationLocalizationProvider.java index 75d6cac1e..2177dfe43 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/search/GeolocationLocalizationProvider.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/search/GeolocationLocalizationProvider.java @@ -23,6 +23,12 @@ public class GeolocationLocalizationProvider implements SearchLocalizationProvid mRegion = data.getCountryCode(); } + GeolocationLocalizationProvider(@NonNull String countryCode, @NonNull String region) { + mCountry = countryCode; + mLanguage = Locale.getDefault().getLanguage(); + mRegion = region; + } + @Nullable @Override public SearchLocalization determineRegion(@NonNull Continuation continuation) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/search/SearchEngineWrapper.java b/app/src/common/shared/org/mozilla/vrbrowser/search/SearchEngineWrapper.java index 9d08a1369..45b14ddb4 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/search/SearchEngineWrapper.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/search/SearchEngineWrapper.java @@ -7,6 +7,7 @@ import android.content.SharedPreferences; import android.net.Uri; import android.preference.PreferenceManager; +import android.util.Log; import androidx.annotation.NonNull; @@ -140,7 +141,7 @@ public String getIdentifier() { private BroadcastReceiver mLocaleChangedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction() == Intent.ACTION_LOCALE_CHANGED) { + if (intent.getAction().equals(Intent.ACTION_LOCALE_CHANGED)) { setupSearchEngine(context, EMPTY); } } @@ -157,10 +158,12 @@ private void setupSearchEngine(@NonNull Context aContext, String userPref) { GeolocationData data = GeolocationData.parse(SettingsStore.getInstance(aContext).getGeolocationData()); if (data == null) { + Log.d(LOGTAG, "Using Locale based search localization provider"); // If we don't have geolocation data we default to the Locale search localization provider mLocalizationProvider = new LocaleSearchLocalizationProvider(); } else { + Log.d(LOGTAG, "Using Geolocation based search localization provider: " + data.toString()); // If we have geolocation data we initialize the provider with the received data // and setup a filter to filter the engines that we need to override for FxR. mLocalizationProvider = new GeolocationLocalizationProvider(data); @@ -199,7 +202,7 @@ private String getEngine(String aCountryCode) { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (mContext != null) { - if (key == mContext.getString(R.string.settings_key_geolocation_data)) { + if (key.equals(mContext.getString(R.string.settings_key_geolocation_data))) { setupSearchEngine(mContext, EMPTY); } } diff --git a/app/src/main/res/values/non_L10n.xml b/app/src/main/res/values/non_L10n.xml index 38f1bd84f..e780320f7 100644 --- a/app/src/main/res/values/non_L10n.xml +++ b/app/src/main/res/values/non_L10n.xml @@ -181,8 +181,6 @@ ìíiïîįī - - https://location.services.mozilla.com/v1/country?key=fff72d56-b040-4205-9a11-82feda9d83a3 q=%1$s&client=firefox-b-o q=%1$s&client=firefox-b-1-o diff --git a/versions.gradle b/versions.gradle index d42b6c5fe..4c729b9bf 100644 --- a/versions.gradle +++ b/versions.gradle @@ -71,6 +71,7 @@ android_components.browser_search = "org.mozilla.components:browser-search:$vers android_components.browser_storage = "org.mozilla.components:browser-storage-sync:$versions.android_components" android_components.browser_domains = "org.mozilla.components:browser-domains:$versions.android_components" android_components.service_accounts = "org.mozilla.components:service-firefox-accounts:$versions.android_components" +android_components.mozilla_service_location = "org.mozilla.components:service-location:${versions.android_components}" android_components.ui_autocomplete = "org.mozilla.components:ui-autocomplete:$versions.android_components" android_components.concept_fetch = "org.mozilla.components:concept-fetch:$versions.android_components" android_components.lib_fetch = "org.mozilla.components:lib-fetch-httpurlconnection:$versions.android_components"