Commit 67d941ce authored by David Maunder's avatar David Maunder Committed by Commit Bot

Internationalize price drop formatted currency

The price formatting was originally hard coded for USD. It is now
internationalized. UX/PM requirements are not yet available for exact
formatting (e.g. commas, decimal places) so this change does not
finalize our price formatting but rather gives us the ability to
do some initial experimentation in other locales.

TBR=yusufo@chromium.org

Bug: 1130068
Change-Id: I075b035a560ad651ad166bc47a94031fc44859e1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2556454
Commit-Queue: David Maunder <davidjm@chromium.org>
Reviewed-by: default avatarSahel Sharify <sahel@chromium.org>
Reviewed-by: default avatarWei-Yin Chen (陳威尹) <wychen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#831129}
parent 18de5889
...@@ -67,6 +67,9 @@ public class ShoppingPersistedTabDataTest { ...@@ -67,6 +67,9 @@ public class ShoppingPersistedTabDataTest {
private static final long LOW_PRICE_MICROS = 100000000L; private static final long LOW_PRICE_MICROS = 100000000L;
private static final String HIGH_PRICE_FORMATTED = "$141"; private static final String HIGH_PRICE_FORMATTED = "$141";
private static final String LOW_PRICE_FORMATTED = "$100"; private static final String LOW_PRICE_FORMATTED = "$100";
private static final String UNITED_STATES_CURRENCY_CODE = "USD";
private static final String GREAT_BRITAIN_CURRENCY_CODE = "GBP";
private static final String JAPAN_CURRENCY_CODE = "JPY";
private static final String EMPTY_PRICE = ""; private static final String EMPTY_PRICE = "";
private static final String ENDPOINT_RESPONSE_INITIAL = private static final String ENDPOINT_RESPONSE_INITIAL =
...@@ -136,6 +139,8 @@ public class ShoppingPersistedTabDataTest { ...@@ -136,6 +139,8 @@ public class ShoppingPersistedTabDataTest {
PRICE_MICROS, shoppingPersistedTabData.getPreviousPriceMicros()); PRICE_MICROS, shoppingPersistedTabData.getPreviousPriceMicros());
Assert.assertEquals(mLastPriceChangeTimeMs, Assert.assertEquals(mLastPriceChangeTimeMs,
shoppingPersistedTabData.getLastPriceChangeTimeMs()); shoppingPersistedTabData.getLastPriceChangeTimeMs());
Assert.assertEquals(
UNITED_STATES_CURRENCY_CODE, shoppingPersistedTabData.getCurrencyCode());
semaphore.release(); semaphore.release();
}); });
}); });
...@@ -150,6 +155,8 @@ public class ShoppingPersistedTabDataTest { ...@@ -150,6 +155,8 @@ public class ShoppingPersistedTabDataTest {
ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> { ShoppingPersistedTabData.from(tab, (shoppingPersistedTabData) -> {
verifyEndpointFetcherCalled(1); verifyEndpointFetcherCalled(1);
Assert.assertEquals(PRICE_MICROS, shoppingPersistedTabData.getPriceMicros()); Assert.assertEquals(PRICE_MICROS, shoppingPersistedTabData.getPriceMicros());
Assert.assertEquals(
UNITED_STATES_CURRENCY_CODE, shoppingPersistedTabData.getCurrencyCode());
Assert.assertEquals(ShoppingPersistedTabData.NO_PRICE_KNOWN, Assert.assertEquals(ShoppingPersistedTabData.NO_PRICE_KNOWN,
shoppingPersistedTabData.getPreviousPriceMicros()); shoppingPersistedTabData.getPreviousPriceMicros());
Assert.assertEquals(ShoppingPersistedTabData.NO_TRANSITIONS_OCCURRED, Assert.assertEquals(ShoppingPersistedTabData.NO_TRANSITIONS_OCCURRED,
...@@ -190,6 +197,8 @@ public class ShoppingPersistedTabDataTest { ...@@ -190,6 +197,8 @@ public class ShoppingPersistedTabDataTest {
Assert.assertEquals(PRICE_MICROS, shoppingPersistedTabData.getPriceMicros()); Assert.assertEquals(PRICE_MICROS, shoppingPersistedTabData.getPriceMicros());
Assert.assertEquals(ShoppingPersistedTabData.NO_PRICE_KNOWN, Assert.assertEquals(ShoppingPersistedTabData.NO_PRICE_KNOWN,
shoppingPersistedTabData.getPreviousPriceMicros()); shoppingPersistedTabData.getPreviousPriceMicros());
Assert.assertEquals(
UNITED_STATES_CURRENCY_CODE, shoppingPersistedTabData.getCurrencyCode());
// By setting time to live to be a negative number, an update // By setting time to live to be a negative number, an update
// will be forced in the subsequent call // will be forced in the subsequent call
initialSemaphore.release(); initialSemaphore.release();
...@@ -218,8 +227,8 @@ public class ShoppingPersistedTabDataTest { ...@@ -218,8 +227,8 @@ public class ShoppingPersistedTabDataTest {
@SmallTest @SmallTest
@Test @Test
public void testPriceDrop() { public void testPriceDrop() {
Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO); ShoppingPersistedTabData shoppingPersistedTabData =
ShoppingPersistedTabData shoppingPersistedTabData = new ShoppingPersistedTabData(tab); createShoppingPersistedTabDataWithDefaults();
// Prices unknown is not a price drop // Prices unknown is not a price drop
Assert.assertNull(shoppingPersistedTabData.getPriceDrop()); Assert.assertNull(shoppingPersistedTabData.getPriceDrop());
...@@ -246,7 +255,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -246,7 +255,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterSamePrice() { public void testPriceDropFilterSamePrice() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $10 -> $10 is not a price drop (same price) // $10 -> $10 is not a price drop (same price)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10_000_000L);
...@@ -259,7 +268,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -259,7 +268,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterNoFormattedPriceDifference() { public void testPriceDropFilterNoFormattedPriceDifference() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $10.40 -> $10 (which would be displayed $10 -> $10 is not a price drop) // $10.40 -> $10 (which would be displayed $10 -> $10 is not a price drop)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10_400_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10_400_000L);
...@@ -272,7 +281,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -272,7 +281,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAbsoluteDifferenceTooSmall() { public void testPriceDropFilterAbsoluteDifferenceTooSmall() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $2 -> $1 ($1 price drop - less than $2. Not big enough) // $2 -> $1 ($1 price drop - less than $2. Not big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(1_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(1_000_000L);
...@@ -285,7 +294,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -285,7 +294,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterPriceIncrease() { public void testPriceDropFilterPriceIncrease() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $9.33 -> $9.66 price increase is not a price drop // $9.33 -> $9.66 price increase is not a price drop
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(9_330_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(9_330_000L);
...@@ -298,7 +307,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -298,7 +307,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterPercentageDropNotEnough() { public void testPriceDropFilterPercentageDropNotEnough() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $50 -> $46 (8% price drop (less than 10%) not big enough) // $50 -> $46 (8% price drop (less than 10%) not big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(50_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(50_000_000L);
...@@ -306,12 +315,27 @@ public class ShoppingPersistedTabDataTest { ...@@ -306,12 +315,27 @@ public class ShoppingPersistedTabDataTest {
Assert.assertNull(shoppingPersistedTabData.getPriceDrop()); Assert.assertNull(shoppingPersistedTabData.getPriceDrop());
} }
private ShoppingPersistedTabData createShoppingPersistedTabDataWithDefaults() {
ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO));
shoppingPersistedTabData.setCurrencyCode(UNITED_STATES_CURRENCY_CODE);
return shoppingPersistedTabData;
}
private ShoppingPersistedTabData createShoppingPersistedTabDataWithCurrencyCode(
int tabId, boolean isIncognito, String currencyCode) {
ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(tabId, isIncognito));
shoppingPersistedTabData.setCurrencyCode(currencyCode);
return shoppingPersistedTabData;
}
@UiThreadTest @UiThreadTest
@SmallTest @SmallTest
@Test @Test
public void testPriceDropFilterAllowedPriceDrop1() { public void testPriceDropFilterAllowedPriceDrop1() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $10 -> $7 (30% and $3 price drop is big enough) // $10 -> $7 (30% and $3 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10_000_000L);
...@@ -326,7 +350,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -326,7 +350,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop2() { public void testPriceDropFilterAllowedPriceDrop2() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $15.72 -> $4.80 (70% and $10.92 price drop is big enough) // $15.72 -> $4.80 (70% and $10.92 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(15_720_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(15_720_000L);
...@@ -341,7 +365,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -341,7 +365,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop3() { public void testPriceDropFilterAllowedPriceDrop3() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $20 -> $10 (50% and $10 price drop is big enough) // $20 -> $10 (50% and $10 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(20_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(20_000_000L);
...@@ -356,7 +380,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -356,7 +380,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop4() { public void testPriceDropFilterAllowedPriceDrop4() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $30 -> $27 (10% and $3 price drop is big enough) // $30 -> $27 (10% and $3 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(30_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(30_000_000L);
...@@ -371,7 +395,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -371,7 +395,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop5() { public void testPriceDropFilterAllowedPriceDrop5() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $30.65 -> $25.50 (17% and $5.15 price drop is big enough) // $30.65 -> $25.50 (17% and $5.15 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(30_650_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(30_650_000L);
...@@ -386,7 +410,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -386,7 +410,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop6() { public void testPriceDropFilterAllowedPriceDrop6() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $9.65 -> $3.80 (40% and $5.85 price drop is big enough) // $9.65 -> $3.80 (40% and $5.85 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(9_650_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(9_650_000L);
...@@ -401,7 +425,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -401,7 +425,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop7() { public void testPriceDropFilterAllowedPriceDrop7() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $9.33 -> $0.90 (96% price drop and $8.43 price drop is big enough) // $9.33 -> $0.90 (96% price drop and $8.43 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(9_330_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(9_330_000L);
...@@ -416,7 +440,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -416,7 +440,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop8() { public void testPriceDropFilterAllowedPriceDrop8() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $20 -> $18 (10% price drop and $2 price drop is big enough) // $20 -> $18 (10% price drop and $2 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(20_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(20_000_000L);
...@@ -431,7 +455,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -431,7 +455,7 @@ public class ShoppingPersistedTabDataTest {
@Test @Test
public void testPriceDropFilterAllowedPriceDrop9() { public void testPriceDropFilterAllowedPriceDrop9() {
ShoppingPersistedTabData shoppingPersistedTabData = ShoppingPersistedTabData shoppingPersistedTabData =
new ShoppingPersistedTabData(createTabOnUiThread(TAB_ID, IS_INCOGNITO)); createShoppingPersistedTabDataWithDefaults();
// $2 -> $0 ($2 price drop is big enough) // $2 -> $0 ($2 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(2_000_000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(2_000_000L);
...@@ -444,9 +468,40 @@ public class ShoppingPersistedTabDataTest { ...@@ -444,9 +468,40 @@ public class ShoppingPersistedTabDataTest {
@UiThreadTest @UiThreadTest
@SmallTest @SmallTest
@Test @Test
public void testStalePriceDrop() { public void testPriceDropGBP() {
Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO); ShoppingPersistedTabData shoppingPersistedTabData =
ShoppingPersistedTabData shoppingPersistedTabData = new ShoppingPersistedTabData(tab); createShoppingPersistedTabDataWithCurrencyCode(
TAB_ID, IS_INCOGNITO, GREAT_BRITAIN_CURRENCY_CODE);
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(15_000_000L);
shoppingPersistedTabData.setPriceMicrosForTesting(9_560_000L);
Assert.assertNotNull(shoppingPersistedTabData.getPriceDrop());
Assert.assertEquals("£15", shoppingPersistedTabData.getPriceDrop().previousPrice);
Assert.assertEquals("£9.56", shoppingPersistedTabData.getPriceDrop().price);
}
@UiThreadTest
@SmallTest
@Test
public void testPriceDropJPY() {
ShoppingPersistedTabData shoppingPersistedTabData =
createShoppingPersistedTabDataWithCurrencyCode(
TAB_ID, IS_INCOGNITO, JAPAN_CURRENCY_CODE);
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(3_140_000_000_000L);
shoppingPersistedTabData.setPriceMicrosForTesting(287_000_000_000L);
Assert.assertNotNull(shoppingPersistedTabData.getPriceDrop());
Assert.assertEquals("¥3,140,000", shoppingPersistedTabData.getPriceDrop().previousPrice);
Assert.assertEquals("¥287,000", shoppingPersistedTabData.getPriceDrop().price);
}
@UiThreadTest
@SmallTest
@Test
public void testStalePriceDropUSD() {
ShoppingPersistedTabData shoppingPersistedTabData =
createShoppingPersistedTabDataWithCurrencyCode(
TAB_ID, IS_INCOGNITO, UNITED_STATES_CURRENCY_CODE);
// $10 -> $5 (50% and $5 price drop is big enough) // $10 -> $5 (50% and $5 price drop is big enough)
shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10000000L); shoppingPersistedTabData.setPreviousPriceMicrosForTesting(10000000L);
shoppingPersistedTabData.setPriceMicrosForTesting(5000000L); shoppingPersistedTabData.setPriceMicrosForTesting(5000000L);
......
...@@ -60,6 +60,7 @@ android_library("java") { ...@@ -60,6 +60,7 @@ android_library("java") {
"//components/external_intents/android:java", "//components/external_intents/android:java",
"//components/find_in_page/android:java", "//components/find_in_page/android:java",
"//components/navigation_interception/android:navigation_interception_java", "//components/navigation_interception/android:navigation_interception_java",
"//components/payments/content/android:java",
"//content/public/android:content_java", "//content/public/android:content_java",
"//net/android:net_java", "//net/android:net_java",
"//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_annotation_annotation_java",
......
include_rules = [ include_rules = [
"+chrome/browser/tabpersistence", "+chrome/browser/tabpersistence",
"+components/payments/content/android",
] ]
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
package org.chromium.chrome.browser.tab.state; package org.chromium.chrome.browser.tab.state;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
...@@ -15,11 +14,13 @@ import org.json.JSONException; ...@@ -15,11 +14,13 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.base.LocaleUtils;
import org.chromium.base.Log; import org.chromium.base.Log;
import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher; import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.proto.ShoppingPersistedTabData.ShoppingPersistedTabDataProto; import org.chromium.chrome.browser.tab.proto.ShoppingPersistedTabData.ShoppingPersistedTabDataProto;
import org.chromium.components.payments.CurrencyFormatter;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -42,10 +43,12 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -42,10 +43,12 @@ public class ShoppingPersistedTabData extends PersistedTabData {
private static final String BUYABLE_PRODUCT_ANNOTATION_KEY = "BUYABLE_PRODUCT"; private static final String BUYABLE_PRODUCT_ANNOTATION_KEY = "BUYABLE_PRODUCT";
private static final String BUYABLE_PRODUCT_KEY = "buyableProduct"; private static final String BUYABLE_PRODUCT_KEY = "buyableProduct";
private static final String CURRENT_PRICE_KEY = "currentPrice"; private static final String CURRENT_PRICE_KEY = "currentPrice";
private static final String CURRENCY_CODE_KEY = "currencyCode";
private static final String AMOUNT_MICROS_KEY = "amountMicros"; private static final String AMOUNT_MICROS_KEY = "amountMicros";
private static final String ACCEPT_LANGUAGE_KEY = "Accept-Language"; private static final String ACCEPT_LANGUAGE_KEY = "Accept-Language";
// TODO(crbug.com/1130068) support all locales
private static final String ACCEPT_LANGUAGE_VALUE = "en-US"; private static final int FRACTIONAL_DIGITS_LESS_THAN_TEN_UNITS = 2;
private static final int FRACTIONAL_DIGITS_GREATER_THAN_TEN_UNITS = 0;
private static final Class<ShoppingPersistedTabData> USER_DATA_KEY = private static final Class<ShoppingPersistedTabData> USER_DATA_KEY =
ShoppingPersistedTabData.class; ShoppingPersistedTabData.class;
...@@ -69,6 +72,8 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -69,6 +72,8 @@ public class ShoppingPersistedTabData extends PersistedTabData {
private long mPriceMicros = NO_PRICE_KNOWN; private long mPriceMicros = NO_PRICE_KNOWN;
private long mPreviousPriceMicros = NO_PRICE_KNOWN; private long mPreviousPriceMicros = NO_PRICE_KNOWN;
private String mCurrencyCode;
/** /**
* A price drop for the offer {@link ShoppingPersistedTabData} * A price drop for the offer {@link ShoppingPersistedTabData}
* refers to * refers to
...@@ -124,7 +129,8 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -124,7 +129,8 @@ public class ShoppingPersistedTabData extends PersistedTabData {
Profile.getLastUsedRegularProfile(), Profile.getLastUsedRegularProfile(),
String.format(ENDPOINT, tab.getUrlString()), HTTPS_METHOD, CONTENT_TYPE, String.format(ENDPOINT, tab.getUrlString()), HTTPS_METHOD, CONTENT_TYPE,
EMPTY_POST_DATA, TIMEOUT_MS, EMPTY_POST_DATA, TIMEOUT_MS,
new String[] {ACCEPT_LANGUAGE_KEY, ACCEPT_LANGUAGE_VALUE}); new String[] {
ACCEPT_LANGUAGE_KEY, LocaleUtils.getDefaultLocaleListString()});
}, },
ShoppingPersistedTabData.class, callback); ShoppingPersistedTabData.class, callback);
} }
...@@ -142,6 +148,7 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -142,6 +148,7 @@ public class ShoppingPersistedTabData extends PersistedTabData {
JSONObject priceMetadata = metadata.getJSONObject(CURRENT_PRICE_KEY); JSONObject priceMetadata = metadata.getJSONObject(CURRENT_PRICE_KEY);
res.setPriceMicros(Long.parseLong(priceMetadata.getString(AMOUNT_MICROS_KEY)), res.setPriceMicros(Long.parseLong(priceMetadata.getString(AMOUNT_MICROS_KEY)),
previousShoppingPersistedTabData); previousShoppingPersistedTabData);
res.setCurrencyCode(priceMetadata.getString(CURRENCY_CODE_KEY));
break; break;
} }
} }
...@@ -178,6 +185,15 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -178,6 +185,15 @@ public class ShoppingPersistedTabData extends PersistedTabData {
save(); save();
} }
protected void setCurrencyCode(String currencyCode) {
mCurrencyCode = currencyCode;
}
@VisibleForTesting
protected String getCurrencyCode() {
return mCurrencyCode;
}
@VisibleForTesting @VisibleForTesting
protected void setPreviousPriceMicros(long previousPriceMicros) { protected void setPreviousPriceMicros(long previousPriceMicros) {
mPreviousPriceMicros = previousPriceMicros; mPreviousPriceMicros = previousPriceMicros;
...@@ -249,12 +265,21 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -249,12 +265,21 @@ public class ShoppingPersistedTabData extends PersistedTabData {
} }
// TODO(crbug.com/1130068) support all currencies // TODO(crbug.com/1130068) support all currencies
private static String formatPrice(long priceMicros) { private String formatPrice(long priceMicros) {
CurrencyFormatter currencyFormatter =
new CurrencyFormatter(mCurrencyCode, Locale.getDefault());
String formattedPrice;
if (priceMicros < TEN_UNITS) { if (priceMicros < TEN_UNITS) {
return String.format(Locale.US, "$%.2f", (100 * priceMicros / MICROS_TO_UNITS) / 100.0); currencyFormatter.setMaximumFractionalDigits(FRACTIONAL_DIGITS_LESS_THAN_TEN_UNITS);
} formattedPrice = String.format(
return String.format(Locale.US, "$%d", Locale.getDefault(), "%.2f", (100 * priceMicros / MICROS_TO_UNITS) / 100.0);
(int) Math.floor((double) (priceMicros + MICROS_TO_UNITS / 2) / MICROS_TO_UNITS)); } else {
currencyFormatter.setMaximumFractionalDigits(FRACTIONAL_DIGITS_GREATER_THAN_TEN_UNITS);
formattedPrice = String.format(Locale.getDefault(), "%d",
(long) Math.floor(
(double) (priceMicros + MICROS_TO_UNITS / 2) / MICROS_TO_UNITS));
}
return currencyFormatter.format(formattedPrice);
} }
@Override @Override
......
...@@ -34,6 +34,12 @@ void CurrencyFormatterAndroid::Destroy(JNIEnv* env, ...@@ -34,6 +34,12 @@ void CurrencyFormatterAndroid::Destroy(JNIEnv* env,
delete this; delete this;
} }
void CurrencyFormatterAndroid::SetMaxFractionalDigits(
JNIEnv* env,
jint jmax_fractional_digits) {
currency_formatter_->SetMaxFractionalDigits(jmax_fractional_digits);
}
base::android::ScopedJavaLocalRef<jstring> CurrencyFormatterAndroid::Format( base::android::ScopedJavaLocalRef<jstring> CurrencyFormatterAndroid::Format(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jobject>& jcaller, const JavaParamRef<jobject>& jcaller,
......
...@@ -29,6 +29,9 @@ class CurrencyFormatterAndroid { ...@@ -29,6 +29,9 @@ class CurrencyFormatterAndroid {
void Destroy(JNIEnv* env, void Destroy(JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller); const base::android::JavaParamRef<jobject>& jcaller);
// Set the maximum number of fractional digits.
void SetMaxFractionalDigits(JNIEnv* env, jint jnum_fractional_digits);
// Refer to CurrencyFormatter::Format documentation. // Refer to CurrencyFormatter::Format documentation.
base::android::ScopedJavaLocalRef<jstring> Format( base::android::ScopedJavaLocalRef<jstring> Format(
JNIEnv* env, JNIEnv* env,
......
...@@ -46,6 +46,15 @@ public class CurrencyFormatter { ...@@ -46,6 +46,15 @@ public class CurrencyFormatter {
} }
} }
/**
* Set the maximum number of fractional digits in the formatted price.
* @param maxFractionalDigits maximum number of fractional digits
*/
public void setMaximumFractionalDigits(int maxFractionalDigits) {
CurrencyFormatterJni.get().setMaxFractionalDigits(
mCurrencyFormatterAndroid, maxFractionalDigits);
}
/** @return The currency code formatted for display. */ /** @return The currency code formatted for display. */
public String getFormattedCurrencyCode() { public String getFormattedCurrencyCode() {
return CurrencyFormatterJni.get().getFormattedCurrencyCode( return CurrencyFormatterJni.get().getFormattedCurrencyCode(
...@@ -76,6 +85,7 @@ public class CurrencyFormatter { ...@@ -76,6 +85,7 @@ public class CurrencyFormatter {
void destroy(long nativeCurrencyFormatterAndroid, CurrencyFormatter caller); void destroy(long nativeCurrencyFormatterAndroid, CurrencyFormatter caller);
String format( String format(
long nativeCurrencyFormatterAndroid, CurrencyFormatter caller, String amountValue); long nativeCurrencyFormatterAndroid, CurrencyFormatter caller, String amountValue);
void setMaxFractionalDigits(long nativeCurrencyFormatterAndroid, int maxFractionalDigits);
String getFormattedCurrencyCode( String getFormattedCurrencyCode(
long nativeCurrencyFormatterAndroid, CurrencyFormatter caller); long nativeCurrencyFormatterAndroid, CurrencyFormatter caller);
} }
......
...@@ -85,6 +85,10 @@ CurrencyFormatter::CurrencyFormatter(const std::string& currency_code, ...@@ -85,6 +85,10 @@ CurrencyFormatter::CurrencyFormatter(const std::string& currency_code,
CurrencyFormatter::~CurrencyFormatter() {} CurrencyFormatter::~CurrencyFormatter() {}
void CurrencyFormatter::SetMaxFractionalDigits(const int maxFractionalDigits) {
icu_formatter_->setMaximumFractionDigits(maxFractionalDigits);
}
base::string16 CurrencyFormatter::Format(const std::string& amount) { base::string16 CurrencyFormatter::Format(const std::string& amount) {
// It's possible that the ICU formatter didn't initialize properly. // It's possible that the ICU formatter didn't initialize properly.
if (!icu_formatter_ || !icu_formatter_->getCurrency()) if (!icu_formatter_ || !icu_formatter_->getCurrency())
......
...@@ -27,6 +27,10 @@ class CurrencyFormatter { ...@@ -27,6 +27,10 @@ class CurrencyFormatter {
const std::string& locale_name); const std::string& locale_name);
~CurrencyFormatter(); ~CurrencyFormatter();
// Set the maximum number of fractional digits. (kMaximumNumFractionalDigits
// is the default if unset)
void SetMaxFractionalDigits(const int maxFractionalDigits);
// Formats the |amount| according to the currency code that was set. The // Formats the |amount| according to the currency code that was set. The
// result will NOT contain the currency code, nor a subset of it. Rather, the // result will NOT contain the currency code, nor a subset of it. Rather, the
// caller of this function should display the currency code separately. The // caller of this function should display the currency code separately. The
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment