Commit b5a9774a authored by David Maunder's avatar David Maunder Committed by Commit Bot

Update integration acquiring page annotations with new endpoint

There is a new endpoint for serving page annotation data. This CL
updates to the new endpoint.

Bug: 1149236
Change-Id: I65f4f30473654bccf8392144e1f585177af32fb8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2541578
Commit-Queue: David Maunder <davidjm@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Reviewed-by: default avatarWei-Yin Chen (陳威尹) <wychen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#830049}
parent be518858
...@@ -75,7 +75,8 @@ public class TabSuggestionsServerFetcher implements TabSuggestionsFetcher { ...@@ -75,7 +75,8 @@ public class TabSuggestionsServerFetcher implements TabSuggestionsFetcher {
-> { fetchCallback(res, callback, tabContext); }, -> { fetchCallback(res, callback, tabContext); },
mProfileForTesting == null ? Profile.getLastUsedRegularProfile() mProfileForTesting == null ? Profile.getLastUsedRegularProfile()
: mProfileForTesting, : mProfileForTesting,
ENDPOINT, METHOD, CONTENT_TYPE, getTabContextJson(tabContext), TIMEOUT_MS); ENDPOINT, METHOD, CONTENT_TYPE, getTabContextJson(tabContext), TIMEOUT_MS,
new String[] {});
} catch (JSONException e) { } catch (JSONException e) {
// Soft failure for now so we don't crash the app and fall back on client side // Soft failure for now so we don't crash the app and fall back on client side
// providers. // providers.
......
...@@ -114,21 +114,21 @@ public class TabSuggestionsServerFetcherUnitTest { ...@@ -114,21 +114,21 @@ public class TabSuggestionsServerFetcherUnitTest {
doAnswer(new Answer<Void>() { doAnswer(new Answer<Void>() {
@Override @Override
public Void answer(InvocationOnMock invocation) { public Void answer(InvocationOnMock invocation) {
Callback callback = (Callback) invocation.getArguments()[6]; Callback callback = (Callback) invocation.getArguments()[7];
callback.onResult(new EndpointResponse(response)); callback.onResult(new EndpointResponse(response));
return null; return null;
} }
}) })
.when(mEndpointFetcherJniMock) .when(mEndpointFetcherJniMock)
.nativeFetchChromeAPIKey(any(Profile.class), anyString(), anyString(), anyString(), .nativeFetchChromeAPIKey(any(Profile.class), anyString(), anyString(), anyString(),
anyString(), anyLong(), any(Callback.class)); anyString(), anyLong(), any(String[].class), any(Callback.class));
} }
private void verifyEndpointArguments() { private void verifyEndpointArguments() {
verify(mEndpointFetcherJniMock) verify(mEndpointFetcherJniMock)
.nativeFetchChromeAPIKey(eq(mProfile), eq(EXPECTED_ENDPOINT_URL), .nativeFetchChromeAPIKey(eq(mProfile), eq(EXPECTED_ENDPOINT_URL),
eq(EXPECTED_METHOD), eq(EXPECTED_CONTENT_TYPE), any(String.class), eq(EXPECTED_METHOD), eq(EXPECTED_CONTENT_TYPE), any(String.class),
eq(EXPECTED_TIMEOUT), any(Callback.class)); eq(EXPECTED_TIMEOUT), any(String[].class), any(Callback.class));
} }
@Test @Test
......
...@@ -36,7 +36,6 @@ import org.chromium.chrome.browser.tab.Tab; ...@@ -36,7 +36,6 @@ import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.ChromeBrowserTestRule;
import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.Locale;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
...@@ -70,13 +69,18 @@ public class ShoppingPersistedTabDataTest { ...@@ -70,13 +69,18 @@ public class ShoppingPersistedTabDataTest {
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 =
"{\"representations\" : [{\"type\" : \"SHOPPING\", \"productTitle\" : \"Book of Pie\"," "{\"annotations\":[{\"type\":\"DOCUMENT_INTENT\",\"documentIntent\":"
+ String.format(Locale.US, "\"price\" : %d, \"currency\" : \"USD\"}]}", PRICE_MICROS); + "{\"intent\":\"UNKNOWN\"}},{\"type\":\"BUYABLE_PRODUCT\",\"buyableProduct\":"
+ "{\"title\":\"foo title\",\"imageUrl\":\"https://images.com?q=1234\","
+ "\"currentPrice\":{\"currencyCode\":\"USD\",\"amountMicros\":\"123456789012345\"},"
+ "\"referenceType\":\"MAIN_PRODUCT\"}}]}";
private static final String ENDPOINT_RESPONSE_UPDATE = private static final String ENDPOINT_RESPONSE_UPDATE =
"{\"representations\" : [{\"type\" : \"SHOPPING\", \"productTitle\" : \"Book of Pie\"," "{\"annotations\":[{\"type\":\"DOCUMENT_INTENT\",\"documentIntent\":"
+ String.format( + "{\"intent\":\"UNKNOWN\"}},{\"type\":\"BUYABLE_PRODUCT\",\"buyableProduct\":"
Locale.US, "\"price\" : %d, \"currency\" : \"USD\"}]}", UPDATED_PRICE_MICROS); + "{\"title\":\"foo title\",\"imageUrl\":\"https://images.com?q=1234\","
+ "\"currentPrice\":{\"currencyCode\":\"USD\",\"amountMicros\":\"287000000\"},"
+ "\"referenceType\":\"MAIN_PRODUCT\"}}]}";
@Before @Before
public void setUp() { public void setUp() {
...@@ -454,9 +458,8 @@ public class ShoppingPersistedTabDataTest { ...@@ -454,9 +458,8 @@ public class ShoppingPersistedTabDataTest {
private void verifyEndpointFetcherCalled(int numTimes) { private void verifyEndpointFetcherCalled(int numTimes) {
verify(mEndpointFetcherJniMock, times(numTimes)) verify(mEndpointFetcherJniMock, times(numTimes))
.nativeFetchOAuth(any(Profile.class), anyString(), anyString(), anyString(), .nativeFetchChromeAPIKey(any(Profile.class), anyString(), anyString(), anyString(),
anyString(), any(String[].class), anyString(), anyLong(), anyString(), anyLong(), any(String[].class), any(Callback.class));
any(Callback.class));
} }
private static Tab createTabOnUiThread(int tabId, boolean isIncognito) { private static Tab createTabOnUiThread(int tabId, boolean isIncognito) {
...@@ -479,7 +482,7 @@ public class ShoppingPersistedTabDataTest { ...@@ -479,7 +482,7 @@ public class ShoppingPersistedTabDataTest {
doAnswer(new Answer<Void>() { doAnswer(new Answer<Void>() {
@Override @Override
public Void answer(InvocationOnMock invocation) { public Void answer(InvocationOnMock invocation) {
Callback callback = (Callback) invocation.getArguments()[8]; Callback callback = (Callback) invocation.getArguments()[7];
String res = mCalledOnce ? ENDPOINT_RESPONSE_UPDATE : ENDPOINT_RESPONSE_INITIAL; String res = mCalledOnce ? ENDPOINT_RESPONSE_UPDATE : ENDPOINT_RESPONSE_INITIAL;
mCalledOnce = true; mCalledOnce = true;
callback.onResult(new EndpointResponse(res)); callback.onResult(new EndpointResponse(res));
...@@ -487,9 +490,8 @@ public class ShoppingPersistedTabDataTest { ...@@ -487,9 +490,8 @@ public class ShoppingPersistedTabDataTest {
} }
}) })
.when(mEndpointFetcherJniMock) .when(mEndpointFetcherJniMock)
.nativeFetchOAuth(any(Profile.class), anyString(), anyString(), anyString(), .nativeFetchChromeAPIKey(any(Profile.class), anyString(), anyString(), anyString(),
anyString(), any(String[].class), anyString(), anyLong(), anyString(), anyLong(), any(String[].class), any(Callback.class));
any(Callback.class));
} }
private static void acquireSemaphore(Semaphore semaphore) { private static void acquireSemaphore(Semaphore semaphore) {
......
...@@ -64,6 +64,7 @@ EndpointFetcher::EndpointFetcher( ...@@ -64,6 +64,7 @@ EndpointFetcher::EndpointFetcher(
const std::string& content_type, const std::string& content_type,
int64_t timeout_ms, int64_t timeout_ms,
const std::string& post_data, const std::string& post_data,
const std::vector<std::string>& headers,
const net::NetworkTrafficAnnotationTag& annotation_tag) const net::NetworkTrafficAnnotationTag& annotation_tag)
: auth_type_(CHROME_API_KEY), : auth_type_(CHROME_API_KEY),
url_(url), url_(url),
...@@ -71,6 +72,7 @@ EndpointFetcher::EndpointFetcher( ...@@ -71,6 +72,7 @@ EndpointFetcher::EndpointFetcher(
content_type_(content_type), content_type_(content_type),
timeout_ms_(timeout_ms), timeout_ms_(timeout_ms),
post_data_(post_data), post_data_(post_data),
headers_(headers),
annotation_tag_(annotation_tag), annotation_tag_(annotation_tag),
url_loader_factory_( url_loader_factory_(
content::BrowserContext::GetDefaultStoragePartition(profile) content::BrowserContext::GetDefaultStoragePartition(profile)
...@@ -165,6 +167,10 @@ void EndpointFetcher::PerformRequest( ...@@ -165,6 +167,10 @@ void EndpointFetcher::PerformRequest(
if (base::EqualsCaseInsensitiveASCII(http_method_, "POST")) { if (base::EqualsCaseInsensitiveASCII(http_method_, "POST")) {
resource_request->headers.SetHeader(kContentTypeKey, content_type_); resource_request->headers.SetHeader(kContentTypeKey, content_type_);
} }
DCHECK(headers_.size() % 2 == 0);
for (size_t i = 0; i + 1 < headers_.size(); i += 2) {
resource_request->headers.SetHeader(headers_[i], headers_[i + 1]);
}
switch (auth_type_) { switch (auth_type_) {
case OAUTH: case OAUTH:
resource_request->headers.SetHeader( resource_request->headers.SetHeader(
...@@ -304,13 +310,16 @@ static void JNI_EndpointFetcher_NativeFetchChromeAPIKey( ...@@ -304,13 +310,16 @@ static void JNI_EndpointFetcher_NativeFetchChromeAPIKey(
const base::android::JavaParamRef<jstring>& jcontent_type, const base::android::JavaParamRef<jstring>& jcontent_type,
const base::android::JavaParamRef<jstring>& jpost_data, const base::android::JavaParamRef<jstring>& jpost_data,
jlong jtimeout, jlong jtimeout,
const base::android::JavaParamRef<jobjectArray>& jheaders,
const base::android::JavaParamRef<jobject>& jcallback) { const base::android::JavaParamRef<jobject>& jcallback) {
std::vector<std::string> headers;
base::android::AppendJavaStringArrayToStringVector(env, jheaders, &headers);
auto endpoint_fetcher = std::make_unique<EndpointFetcher>( auto endpoint_fetcher = std::make_unique<EndpointFetcher>(
ProfileAndroid::FromProfileAndroid(jprofile), ProfileAndroid::FromProfileAndroid(jprofile),
GURL(base::android::ConvertJavaStringToUTF8(env, jurl)), GURL(base::android::ConvertJavaStringToUTF8(env, jurl)),
base::android::ConvertJavaStringToUTF8(env, jhttps_method), base::android::ConvertJavaStringToUTF8(env, jhttps_method),
base::android::ConvertJavaStringToUTF8(env, jcontent_type), jtimeout, base::android::ConvertJavaStringToUTF8(env, jcontent_type), jtimeout,
base::android::ConvertJavaStringToUTF8(env, jpost_data), base::android::ConvertJavaStringToUTF8(env, jpost_data), headers,
NO_TRAFFIC_ANNOTATION_YET); NO_TRAFFIC_ANNOTATION_YET);
endpoint_fetcher->PerformRequest( endpoint_fetcher->PerformRequest(
base::BindOnce(&OnEndpointFetcherComplete, base::BindOnce(&OnEndpointFetcherComplete,
......
...@@ -69,6 +69,7 @@ class EndpointFetcher { ...@@ -69,6 +69,7 @@ class EndpointFetcher {
const std::string& content_type, const std::string& content_type,
int64_t timeout_ms, int64_t timeout_ms,
const std::string& post_data, const std::string& post_data,
const std::vector<std::string>& headers,
const net::NetworkTrafficAnnotationTag& annotation_tag); const net::NetworkTrafficAnnotationTag& annotation_tag);
// Constructor if no authentication is needed. // Constructor if no authentication is needed.
...@@ -121,6 +122,7 @@ class EndpointFetcher { ...@@ -121,6 +122,7 @@ class EndpointFetcher {
const std::string content_type_; const std::string content_type_;
int64_t timeout_ms_; int64_t timeout_ms_;
const std::string post_data_; const std::string post_data_;
const std::vector<std::string> headers_;
const net::NetworkTrafficAnnotationTag annotation_tag_; const net::NetworkTrafficAnnotationTag annotation_tag_;
signin::ScopeSet oauth_scopes_; signin::ScopeSet oauth_scopes_;
......
...@@ -56,14 +56,16 @@ public final class EndpointFetcher { ...@@ -56,14 +56,16 @@ public final class EndpointFetcher {
* @param postData data for a "POST" request * @param postData data for a "POST" request
* @param timeout time after which the request will terminate in the event a response hasn't * @param timeout time after which the request will terminate in the event a response hasn't
* been received * been received
* @param headers headers for the request. Key/value pairs are stored sequentially in the array.
*/ */
@MainThread @MainThread
public static void fetchUsingChromeAPIKey(Callback<EndpointResponse> callback, Profile profile, public static void fetchUsingChromeAPIKey(Callback<EndpointResponse> callback, Profile profile,
String url, String httpsMethod, String contentType, String postData, long timeout) { String url, String httpsMethod, String contentType, String postData, long timeout,
String[] headers) {
// EndpointFetcher currently does not support incognito mode // EndpointFetcher currently does not support incognito mode
// assert !profile.isOffTheRecord(); // assert !profile.isOffTheRecord();
EndpointFetcherJni.get().nativeFetchChromeAPIKey( EndpointFetcherJni.get().nativeFetchChromeAPIKey(
profile, url, httpsMethod, contentType, postData, timeout, callback); profile, url, httpsMethod, contentType, postData, timeout, headers, callback);
} }
@NativeMethods @NativeMethods
...@@ -72,7 +74,7 @@ public final class EndpointFetcher { ...@@ -72,7 +74,7 @@ public final class EndpointFetcher {
String httpsMethod, String contentType, String[] scopes, String postData, String httpsMethod, String contentType, String[] scopes, String postData,
long timeout, Callback<EndpointResponse> callback); long timeout, Callback<EndpointResponse> callback);
void nativeFetchChromeAPIKey(Profile profile, String url, String httpsMethod, void nativeFetchChromeAPIKey(Profile profile, String url, String httpsMethod,
String contentType, String postData, long timeout, String contentType, String postData, long timeout, String[] headers,
Callback<EndpointResponse> callback); Callback<EndpointResponse> callback);
void nativeFetchWithNoAuth( void nativeFetchWithNoAuth(
Profile profile, String url, Callback<EndpointResponse> callback); Profile profile, String url, Callback<EndpointResponse> callback);
......
...@@ -29,21 +29,23 @@ import java.util.concurrent.TimeUnit; ...@@ -29,21 +29,23 @@ import java.util.concurrent.TimeUnit;
*/ */
public class ShoppingPersistedTabData extends PersistedTabData { public class ShoppingPersistedTabData extends PersistedTabData {
private static final String TAG = "SPTD"; private static final String TAG = "SPTD";
private static final String ENDPOINT = private static final String ENDPOINT = "https://memex-pa.googleapis.com/v1/annotations?url=%s";
"https://task-management-chrome.sandbox.google.com/tabs/representations?url=%s&locale=en:US";
private static final String[] SCOPES =
new String[] {"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile"};
private static final long TIMEOUT_MS = 1000L; private static final long TIMEOUT_MS = 1000L;
private static final String HTTPS_METHOD = "GET"; private static final String HTTPS_METHOD = "GET";
private static final String CONTENT_TYPE = "application/json; charset=UTF-8"; private static final String CONTENT_TYPE = "application/json; charset=UTF-8";
private static final String OAUTH_NAME = "SPTD"; private static final String OAUTH_NAME = "SPTD";
private static final String EMPTY_POST_DATA = ""; private static final String EMPTY_POST_DATA = "";
private static final String REPRESENTATIONS_KEY = "representations"; private static final String ANNOTATIONS_KEY = "annotations";
private static final String PRICE_KEY = "price"; private static final String PRICE_KEY = "price";
private static final String TYPE_KEY = "type"; private static final String TYPE_KEY = "type";
private static final String SHOPPING_ID = "SHOPPING"; private static final String BUYABLE_PRODUCT_ANNOTATION_KEY = "BUYABLE_PRODUCT";
private static final String BUYABLE_PRODUCT_KEY = "buyableProduct";
private static final String CURRENT_PRICE_KEY = "currentPrice";
private static final String AMOUNT_MICROS_KEY = "amountMicros";
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 Class<ShoppingPersistedTabData> USER_DATA_KEY = private static final Class<ShoppingPersistedTabData> USER_DATA_KEY =
ShoppingPersistedTabData.class; ShoppingPersistedTabData.class;
...@@ -112,16 +114,17 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -112,16 +114,17 @@ public class ShoppingPersistedTabData extends PersistedTabData {
-> { -> {
ShoppingPersistedTabData previousShoppingPersistedTabData = ShoppingPersistedTabData previousShoppingPersistedTabData =
PersistedTabData.from(tab, USER_DATA_KEY); PersistedTabData.from(tab, USER_DATA_KEY);
EndpointFetcher.fetchUsingOAuth( EndpointFetcher.fetchUsingChromeAPIKey(
(endpointResponse) (endpointResponse)
-> { -> {
supplierCallback.onResult( supplierCallback.onResult(
build(tab, endpointResponse.getResponseString(), build(tab, endpointResponse.getResponseString(),
previousShoppingPersistedTabData)); previousShoppingPersistedTabData));
}, },
Profile.getLastUsedRegularProfile(), OAUTH_NAME, Profile.getLastUsedRegularProfile(),
String.format(Locale.US, ENDPOINT, tab.getUrlString()), HTTPS_METHOD, String.format(ENDPOINT, tab.getUrlString()), HTTPS_METHOD, CONTENT_TYPE,
CONTENT_TYPE, SCOPES, EMPTY_POST_DATA, TIMEOUT_MS); EMPTY_POST_DATA, TIMEOUT_MS,
new String[] {ACCEPT_LANGUAGE_KEY, ACCEPT_LANGUAGE_VALUE});
}, },
ShoppingPersistedTabData.class, callback); ShoppingPersistedTabData.class, callback);
} }
...@@ -131,12 +134,14 @@ public class ShoppingPersistedTabData extends PersistedTabData { ...@@ -131,12 +134,14 @@ public class ShoppingPersistedTabData extends PersistedTabData {
ShoppingPersistedTabData res = new ShoppingPersistedTabData(tab); ShoppingPersistedTabData res = new ShoppingPersistedTabData(tab);
try { try {
JSONObject jsonObject = new JSONObject(responseString); JSONObject jsonObject = new JSONObject(responseString);
JSONArray representations = jsonObject.getJSONArray(REPRESENTATIONS_KEY); JSONArray annotations = jsonObject.getJSONArray(ANNOTATIONS_KEY);
for (int i = 0; i < representations.length(); i++) { for (int i = 0; i < annotations.length(); i++) {
JSONObject representation = representations.getJSONObject(i); JSONObject annotation = annotations.getJSONObject(i);
if (SHOPPING_ID.equals(representation.getString(TYPE_KEY))) { if (BUYABLE_PRODUCT_ANNOTATION_KEY.equals(annotation.getString(TYPE_KEY))) {
res.setPriceMicros( JSONObject metadata = annotation.getJSONObject(BUYABLE_PRODUCT_KEY);
representation.getLong(PRICE_KEY), previousShoppingPersistedTabData); JSONObject priceMetadata = metadata.getJSONObject(CURRENT_PRICE_KEY);
res.setPriceMicros(Long.parseLong(priceMetadata.getString(AMOUNT_MICROS_KEY)),
previousShoppingPersistedTabData);
break; break;
} }
} }
......
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