Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1406)

Unified Diff: chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java

Issue 2880663004: Adding visible networks to the Geolocation Header. (Closed)
Patch Set: Adding visible networks to the Geolocation Header. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/android/java_sources.gni ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b448d9d3e4ab45199ca7512e99a8d480a848f572
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderTest.java
@@ -0,0 +1,393 @@
+// Copyright 2017 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.omnibox.geo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.location.Location;
+import android.os.Build;
+import android.os.SystemClock;
+import android.util.Base64;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import org.chromium.base.library_loader.ProcessInitException;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderTest.ShadowRecordHistogram;
+import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderTest.ShadowUrlUtilities;
+import org.chromium.chrome.browser.omnibox.geo.GeolocationHeaderTest.ShadowWebsitePreferenceBridge;
+import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleCell;
+import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleWifi;
+import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlUtilities;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Locale;
+
+/**
+ * Robolectric tests for {@link GeolocationHeader}.
+ */
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE,
+ shadows = {ShadowUrlUtilities.class, ShadowRecordHistogram.class,
+ ShadowWebsitePreferenceBridge.class})
+public class GeolocationHeaderTest {
+ private static final String SEARCH_URL = "https://www.google.com/search?q=potatoes";
+
+ private static final double LOCATION_LAT = 20.3;
+ private static final double LOCATION_LONG = 155.8;
+ private static final float LOCATION_ACCURACY = 20f;
+ private static final long LOCATION_TIME = 400;
+ // Encoded location for LOCATION_LAT, LOCATION_LONG, LOCATION_ACCURACY and LOCATION_TIME.
+ private static final String ENCODED_PROTO_LOCATION = "CAEQDBiAtRgqCg3AiBkMFYAx3Vw9AECcRg==";
+ private static final String ENCODED_ASCII_LOCATION = "cm9sZToxIHByb2R1Y2VyOjEyIHRpbWVzdGFtcDo0M"
+ + "DAwMDAgbGF0bG5ne2xhdGl0dWRlX2U3OjIwMzAwMDAwMCBsb25naXR1ZGVfZTc6MTU1ODAwMDAwMH0gcmFka"
+ + "XVzOjIwMDAw";
+
+ private static final VisibleWifi VISIBLE_WIFI1 =
+ VisibleWifi.create("ssid1", "11:11:11:11:11:11", -1, 10L);
+ private static final VisibleWifi VISIBLE_WIFI_NO_LEVEL =
+ VisibleWifi.create("ssid1", "11:11:11:11:11:11", null, 10L);
+ private static final VisibleWifi VISIBLE_WIFI2 =
+ VisibleWifi.create("ssid2", "11:11:11:11:11:12", -10, 20L);
+ private static final VisibleWifi VISIBLE_WIFI3 =
+ VisibleWifi.create("ssid3", "11:11:11:11:11:13", -30, 30L);
+ private static final VisibleWifi VISIBLE_WIFI_NOMAP =
+ VisibleWifi.create("ssid1_nomap", "11:11:11:11:11:11", -1, 10L);
+ private static final VisibleWifi VISIBLE_WIFI_OPTOUT =
+ VisibleWifi.create("ssid1_optout", "11:11:11:11:11:11", -1, 10L);
+ private static final VisibleCell VISIBLE_CELL1 =
+ VisibleCell.builder(VisibleCell.CDMA_RADIO_TYPE)
+ .setCellId(10)
+ .setLocationAreaCode(11)
+ .setMobileCountryCode(12)
+ .setMobileNetworkCode(13)
+ .setTimestamp(10L)
+ .build();
+ private static final VisibleCell VISIBLE_CELL2 = VisibleCell.builder(VisibleCell.GSM_RADIO_TYPE)
+ .setCellId(20)
+ .setLocationAreaCode(21)
+ .setMobileCountryCode(22)
+ .setMobileNetworkCode(23)
+ .setTimestamp(20L)
+ .build();
+ // Encoded proto location for VISIBLE_WIFI1 connected, VISIBLE_WIFI3 not connected,
+ // VISIBLE_CELL1 connected, VISIBLE_CELL2 not connected.
+ private static final String ENCODED_PROTO_VISIBLE_NETWORKS =
+ "CAEQDLoBJAoeChExMToxMToxMToxMToxMToxMRD___________8BGAEgCroBJAoeChExMToxMToxMToxMTox"
+ + "MToxMxDi__________8BGAAgHroBEBIKCAMQChgLIAwoDRgBIAq6ARASCggBEBQYFSAWKBcYACAU";
+
+ private static int sRefreshVisibleNetworksRequests = 0;
+ private static int sRefreshLastKnownLocation = 0;
+
+ @Rule
+ public Features.Processor mFeatureProcessor = new Features.Processor();
+
+ @Mock
+ private Tab mTab;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ GeolocationTracker.setLocationAgeForTesting(null);
+ GeolocationHeader.setLocationSourceForTesting(
+ GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
+ GeolocationHeader.setAppPermissionGrantedForTesting(true);
+ when(mTab.isIncognito()).thenReturn(false);
+ sRefreshVisibleNetworksRequests = 0;
+ sRefreshLastKnownLocation = 0;
+ }
+
+ @Test
+ public void testEncodeAsciiLocation() throws ProcessInitException {
+ Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
+ String encodedAsciiLocation = GeolocationHeader.encodeAsciiLocation(location);
+ assertEquals(ENCODED_ASCII_LOCATION, encodedAsciiLocation);
+ }
+
+ @Test
+ public void testEncodeProtoLocation() throws ProcessInitException {
+ Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
+ String encodedProtoLocation = GeolocationHeader.encodeProtoLocation(location);
+ assertEquals(ENCODED_PROTO_LOCATION, encodedProtoLocation);
+ }
+
+ @Test
+ public void voidtestTrimVisibleNetworks() throws ProcessInitException {
+ VisibleNetworks visibleNetworks =
+ VisibleNetworks.create(VISIBLE_WIFI_NO_LEVEL, VISIBLE_CELL1,
+ new HashSet(Arrays.asList(VISIBLE_WIFI1, VISIBLE_WIFI2, VISIBLE_WIFI3)),
+ new HashSet(Arrays.asList(VISIBLE_CELL1, VISIBLE_CELL2)));
+
+ // We expect trimming to replace connected Wifi (since it will have level), and select only
+ // the visible wifi different from the connected one, with strongest level.
+ VisibleNetworks expectedTrimmed = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+ new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+ new HashSet(Arrays.asList(VISIBLE_CELL2)));
+
+ VisibleNetworks trimmed = GeolocationHeader.trimVisibleNetworks(visibleNetworks);
+ assertEquals(expectedTrimmed, trimmed);
+ }
+
+ @Test
+ public void testTrimVisibleNetworksEmptyOrNull() throws ProcessInitException {
+ VisibleNetworks visibleNetworks = VisibleNetworks.create(
+ VisibleWifi.create("whatever", null, null, null),
+ null, new HashSet(), new HashSet());
+ assertNull(GeolocationHeader.trimVisibleNetworks(visibleNetworks));
+ assertNull(GeolocationHeader.trimVisibleNetworks(null));
+ }
+
+ @Test
+ public void testEncodeProtoVisibleNetworks() throws ProcessInitException {
+ VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+ new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+ new HashSet(Arrays.asList(VISIBLE_CELL2)));
+ String encodedProtoLocation = GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks);
+ assertEquals(ENCODED_PROTO_VISIBLE_NETWORKS, encodedProtoLocation);
+ }
+
+ @Test
+ public void testEncodeProtoVisibleNetworksEmptyOrNull() throws ProcessInitException {
+ VisibleNetworks visibleNetworks =
+ VisibleNetworks.create(null, null, new HashSet(), new HashSet());
+ assertNull(GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks));
+ assertNull(GeolocationHeader.encodeProtoVisibleNetworks(null));
+ }
+
+ @Test
+ public void testEncodeProtoVisibleNetworksExcludeNoMapOrOptout() throws ProcessInitException {
+ VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI_NOMAP, null,
+ new HashSet(Arrays.asList(VISIBLE_WIFI_OPTOUT)), new HashSet());
+ String encodedProtoLocation = GeolocationHeader.encodeProtoVisibleNetworks(visibleNetworks);
+ assertNull(encodedProtoLocation);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION),
+ @Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS)})
+ public void testGetGeoHeaderFreshLocation() throws ProcessInitException {
+ VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+ new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+ new HashSet(Arrays.asList(VISIBLE_CELL2)));
+ VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
+ Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
+ GeolocationTracker.setLocationForTesting(location, null);
+ // 1 minute should be good enough and not require visible networks.
+ GeolocationTracker.setLocationAgeForTesting(1 * 60 * 1000L);
+ String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
+ assertEquals("X-Geo: w " + ENCODED_PROTO_LOCATION, header);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION),
+ @Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS)})
+ public void testGetGeoHeaderLocationMissing() throws ProcessInitException {
+ VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+ new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+ new HashSet(Arrays.asList(VISIBLE_CELL2)));
+ VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
+ GeolocationTracker.setLocationForTesting(null, null);
+ String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
+ assertEquals("X-Geo: w " + ENCODED_PROTO_VISIBLE_NETWORKS, header);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION),
+ @Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS)})
+ public void testGetGeoHeaderOldLocationHighAccuracy() throws ProcessInitException {
+ GeolocationHeader.setLocationSourceForTesting(
+ GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
+ // Visible networks should be included
+ checkOldLocation(
+ "X-Geo: w " + ENCODED_PROTO_LOCATION + " w " + ENCODED_PROTO_VISIBLE_NETWORKS);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION),
+ @Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS)})
+ public void testGetGeoHeaderOldLocationBatterySaving() throws ProcessInitException {
+ GeolocationHeader.setLocationSourceForTesting(
+ GeolocationHeader.LOCATION_SOURCE_BATTERY_SAVING);
+ checkOldLocation(
+ "X-Geo: w " + ENCODED_PROTO_LOCATION + " w " + ENCODED_PROTO_VISIBLE_NETWORKS);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION),
+ @Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS)})
+ public void testGetGeoHeaderOldLocationGpsOnly() throws ProcessInitException {
+ GeolocationHeader.setLocationSourceForTesting(GeolocationHeader.LOCATION_SOURCE_GPS_ONLY);
+ // In GPS only mode, networks should never be included.
+ checkOldLocation("X-Geo: w " + ENCODED_PROTO_LOCATION);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS),
+ @Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION)})
+ public void testGetGeoHeaderOldLocationLocationOff() throws ProcessInitException {
+ GeolocationHeader.setLocationSourceForTesting(GeolocationHeader.LOCATION_SOURCE_MASTER_OFF);
+ // If the master switch is off, networks should never be included (old location might).
+ checkOldLocation("X-Geo: w " + ENCODED_PROTO_LOCATION);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION),
+ @Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS)})
+ public void testGetGeoHeaderOldLocationAppPermissionDenied() throws ProcessInitException {
+ GeolocationHeader.setLocationSourceForTesting(
+ GeolocationHeader.LOCATION_SOURCE_HIGH_ACCURACY);
+ GeolocationHeader.setAppPermissionGrantedForTesting(false);
+ // Nothing should be included when app permission is missing.
+ checkOldLocation(null);
+ }
+
+ @Test
+ @Features({@Features.Register(ChromeFeatureList.CONSISTENT_OMNIBOX_GEOLOCATION),
+ @Features.Register(value = ChromeFeatureList.XGEO_VISIBLE_NETWORKS, enabled = false)})
+ public void testGetGeoHeaderOldLocationFeatureOff() throws ProcessInitException {
+ long timestamp = LOCATION_TIME * 1000;
+ int latitudeE7 = (int) (LOCATION_LAT * 10000000);
+ int longitudeE7 = (int) (LOCATION_LONG * 10000000);
+ int radius = (int) (LOCATION_ACCURACY * 1000);
+ String locationAscii = String.format(Locale.US,
+ "role:1 producer:12 timestamp:%d latlng{latitude_e7:%d longitude_e7:%d} "
+ + "radius:%d",
+ timestamp, latitudeE7, longitudeE7, radius);
+ String expectedHeader =
+ "X-Geo: a " + new String(Base64.encode(locationAscii.getBytes(), Base64.NO_WRAP));
+ checkOldLocation(expectedHeader);
+ }
+
+ @Test
+ @Config(shadows = {ShadowVisibleNetworksTracker.class, ShadowGeolocationTracker.class})
+ @Features(@Features.Register(value = ChromeFeatureList.XGEO_VISIBLE_NETWORKS, enabled = false))
+ public void testPrimeLocationForGeoHeaderFeatureOff() throws ProcessInitException {
+ GeolocationHeader.primeLocationForGeoHeader();
+ assertEquals(1, sRefreshLastKnownLocation);
+ assertEquals(0, sRefreshVisibleNetworksRequests);
+ }
+
+ @Test
+ @Config(shadows = {ShadowVisibleNetworksTracker.class, ShadowGeolocationTracker.class})
+ @Features(@Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS))
+ public void testPrimeLocationForGeoHeaderFeatureOn() throws ProcessInitException {
+ GeolocationHeader.primeLocationForGeoHeader();
+ assertEquals(1, sRefreshLastKnownLocation);
+ assertEquals(1, sRefreshVisibleNetworksRequests);
+ }
+
+ @Test
+ @Config(shadows = {ShadowVisibleNetworksTracker.class, ShadowGeolocationTracker.class})
+ @Features(@Features.Register(ChromeFeatureList.XGEO_VISIBLE_NETWORKS))
+ public void testPrimeLocationForGeoHeaderPermissionOff() throws ProcessInitException {
+ GeolocationHeader.setAppPermissionGrantedForTesting(false);
+ GeolocationHeader.primeLocationForGeoHeader();
+ assertEquals(0, sRefreshLastKnownLocation);
+ assertEquals(0, sRefreshVisibleNetworksRequests);
+ }
+
+ private void checkOldLocation(String expectedHeader) throws ProcessInitException {
+ VisibleNetworks visibleNetworks = VisibleNetworks.create(VISIBLE_WIFI1, VISIBLE_CELL1,
+ new HashSet(Arrays.asList(VISIBLE_WIFI3)),
+ new HashSet(Arrays.asList(VISIBLE_CELL2)));
+ VisibleNetworksTracker.setVisibleNetworksForTesting(visibleNetworks);
+ Location location = generateMockLocation("should_not_matter", LOCATION_TIME);
+ GeolocationTracker.setLocationForTesting(location, null);
+ // 6 minutes should hit the age limit, but the feature is off.
+ GeolocationTracker.setLocationAgeForTesting(6 * 60 * 1000L);
+ String header = GeolocationHeader.getGeoHeader(SEARCH_URL, mTab);
+ assertEquals(expectedHeader, header);
+ }
+
+ private Location generateMockLocation(String provider, long time) {
+ Location location = new Location(provider);
+ location.setLatitude(LOCATION_LAT);
+ location.setLongitude(LOCATION_LONG);
+ location.setAccuracy(LOCATION_ACCURACY);
+ location.setTime(time);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()
+ + 1000000 * (time - System.currentTimeMillis()));
+ }
+ return location;
+ }
+
+ /**
+ * Shadow for UrlUtilities
+ */
+ @Implements(UrlUtilities.class)
+ public static class ShadowUrlUtilities {
+ @Implementation
+ public static boolean nativeIsGoogleSearchUrl(String url) {
+ return true;
+ }
+ }
+
+ /**
+ * Shadow for RecordHistogram
+ */
+ @Implements(RecordHistogram.class)
+ public static class ShadowRecordHistogram {
+ @Implementation
+ public static void recordEnumeratedHistogram(String name, int sample, int boundary) {
+ // Noop.
+ }
+ }
+
+ /**
+ * Shadow for WebsitePreferenceBridge
+ */
+ @Implements(WebsitePreferenceBridge.class)
+ public static class ShadowWebsitePreferenceBridge {
+ @Implementation
+ public static boolean shouldUseDSEGeolocationSetting(String origin, boolean isIncognito) {
+ return true;
+ }
+
+ @Implementation
+ public static boolean getDSEGeolocationSetting() {
+ return true;
+ }
+ }
+
+ /**
+ * Shadow for VisibleNetworksTracker
+ */
+ @Implements(VisibleNetworksTracker.class)
+ public static class ShadowVisibleNetworksTracker {
+ @Implementation
+ public static void refreshVisibleNetworks(final Context context) {
+ sRefreshVisibleNetworksRequests++;
+ }
+ }
+
+ /**
+ * Shadow for GeolocationTracker
+ */
+ @Implements(GeolocationTracker.class)
+ public static class ShadowGeolocationTracker {
+ @Implementation
+ public static void refreshLastKnownLocation(Context context, long maxAge) {
+ sRefreshLastKnownLocation++;
+ }
+ }
+}
« no previous file with comments | « chrome/android/java_sources.gni ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698