Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.physicalweb; | 5 package org.chromium.chrome.browser.physicalweb; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
| 9 import android.os.AsyncTask; | 9 import android.os.AsyncTask; |
| 10 import android.os.Build; | 10 import android.os.Build; |
| 11 import android.text.TextUtils; | 11 import android.text.TextUtils; |
| 12 | 12 |
| 13 import org.json.JSONArray; | 13 import org.json.JSONArray; |
| 14 import org.json.JSONException; | 14 import org.json.JSONException; |
| 15 import org.json.JSONObject; | 15 import org.json.JSONObject; |
| 16 | 16 |
| 17 import org.chromium.base.LocaleUtils; | |
| 17 import org.chromium.base.Log; | 18 import org.chromium.base.Log; |
| 18 import org.chromium.base.ThreadUtils; | 19 import org.chromium.base.ThreadUtils; |
| 19 import org.chromium.base.VisibleForTesting; | 20 import org.chromium.base.VisibleForTesting; |
| 20 import org.chromium.chrome.GoogleAPIKeys; | 21 import org.chromium.chrome.GoogleAPIKeys; |
| 21 import org.chromium.chrome.R; | 22 import org.chromium.chrome.R; |
| 22 import org.chromium.chrome.browser.ChromeVersionInfo; | 23 import org.chromium.chrome.browser.ChromeVersionInfo; |
| 23 import org.chromium.chrome.browser.physicalweb.PwsClient.FetchIconCallback; | 24 import org.chromium.chrome.browser.physicalweb.PwsClient.FetchIconCallback; |
| 24 import org.chromium.chrome.browser.physicalweb.PwsClient.ResolveScanCallback; | 25 import org.chromium.chrome.browser.physicalweb.PwsClient.ResolveScanCallback; |
| 25 | 26 |
| 26 import java.net.MalformedURLException; | 27 import java.net.MalformedURLException; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 Log.e(TAG, "Error making request to PWS%s", httpErr); | 137 Log.e(TAG, "Error making request to PWS%s", httpErr); |
| 137 resolveScanCallback.onPwsResults(new ArrayList<PwsResult>()); | 138 resolveScanCallback.onPwsResults(new ArrayList<PwsResult>()); |
| 138 } | 139 } |
| 139 }; | 140 }; |
| 140 | 141 |
| 141 // Create the request. | 142 // Create the request. |
| 142 HttpRequest request = null; | 143 HttpRequest request = null; |
| 143 try { | 144 try { |
| 144 JSONObject payload = createResolveScanPayload(broadcastUrls); | 145 JSONObject payload = createResolveScanPayload(broadcastUrls); |
| 145 String url = ENDPOINT_URL + "?key=" + getApiKey(); | 146 String url = ENDPOINT_URL + "?key=" + getApiKey(); |
| 146 request = new JsonObjectHttpRequest(url, getUserAgent(), getAcceptLa nguage(), payload, | 147 request = new JsonObjectHttpRequest( |
| 147 requestCallback); | 148 url, getUserAgent(), updateAcceptLanguage(), payload, reques tCallback); |
| 148 } catch (MalformedURLException e) { | 149 } catch (MalformedURLException e) { |
| 149 Log.e(TAG, "Error creating PWS HTTP request", e); | 150 Log.e(TAG, "Error creating PWS HTTP request", e); |
| 150 return; | 151 return; |
| 151 } catch (JSONException e) { | 152 } catch (JSONException e) { |
| 152 Log.e(TAG, "Error creating PWS JSON payload", e); | 153 Log.e(TAG, "Error creating PWS JSON payload", e); |
| 153 return; | 154 return; |
| 154 } | 155 } |
| 155 // The callback will be called on the main thread. | 156 // The callback will be called on the main thread. |
| 156 AsyncTask.THREAD_POOL_EXECUTOR.execute(request); | 157 AsyncTask.THREAD_POOL_EXECUTOR.execute(request); |
| 157 } | 158 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 179 if (responseCode > 0) { | 180 if (responseCode > 0) { |
| 180 httpErr = ", HTTP " + responseCode; | 181 httpErr = ", HTTP " + responseCode; |
| 181 } | 182 } |
| 182 Log.e(TAG, "Error requesting icon%s", httpErr); | 183 Log.e(TAG, "Error requesting icon%s", httpErr); |
| 183 } | 184 } |
| 184 }; | 185 }; |
| 185 | 186 |
| 186 // Create the request. | 187 // Create the request. |
| 187 BitmapHttpRequest request = null; | 188 BitmapHttpRequest request = null; |
| 188 try { | 189 try { |
| 189 request = new BitmapHttpRequest(iconUrl, getUserAgent(), getAcceptLa nguage(), | 190 request = new BitmapHttpRequest( |
| 190 requestCallback); | 191 iconUrl, getUserAgent(), updateAcceptLanguage(), requestCall back); |
| 191 } catch (MalformedURLException e) { | 192 } catch (MalformedURLException e) { |
| 192 Log.e(TAG, "Error creating icon request", e); | 193 Log.e(TAG, "Error creating icon request", e); |
| 193 return; | 194 return; |
| 194 } | 195 } |
| 195 // The callback will be called on the main thread. | 196 // The callback will be called on the main thread. |
| 196 AsyncTask.THREAD_POOL_EXECUTOR.execute(request); | 197 AsyncTask.THREAD_POOL_EXECUTOR.execute(request); |
| 197 } | 198 } |
| 198 | 199 |
| 199 /** | 200 /** |
| 200 * Recreate the Chrome for Android User-Agent string as closely as possible without calling any | 201 * Recreate the Chrome for Android User-Agent string as closely as possible without calling any |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 215 | 216 |
| 216 // Build the User-Agent string. | 217 // Build the User-Agent string. |
| 217 // eg: Mozilla/5.0 (Linux; Android 5.1.1; Nexus 4 Build/LMY48T) Appl eWebKit/0.0 (KHTML, | 218 // eg: Mozilla/5.0 (Linux; Android 5.1.1; Nexus 4 Build/LMY48T) Appl eWebKit/0.0 (KHTML, |
| 218 // like Gecko) Chrome/50.0.2661.89 Mobile Safari/0.0 | 219 // like Gecko) Chrome/50.0.2661.89 Mobile Safari/0.0 |
| 219 sUserAgent = String.format(USER_AGENT_FORMAT, osInfo, product); | 220 sUserAgent = String.format(USER_AGENT_FORMAT, osInfo, product); |
| 220 } | 221 } |
| 221 return sUserAgent; | 222 return sUserAgent; |
| 222 } | 223 } |
| 223 | 224 |
| 224 /** | 225 /** |
| 225 * Construct the Accept-Language string based on the current locale. | 226 * Update an Accept-Language string based on the current default locales and make a string of |
| 226 * @return An Accept-Language string. | 227 * an Accept-Language header with q-values. |
| 228 * @return An Accept-Language string made of an Accept-Language header with q-values. | |
| 227 */ | 229 */ |
| 228 @VisibleForTesting | 230 @VisibleForTesting |
| 229 String getAcceptLanguage() { | 231 String updateAcceptLanguage() { |
| 230 String defaultLocale = Locale.getDefault().toString(); | 232 String defaultLocale = LocaleUtils.getDefaultLocale(); |
| 231 if (sDefaultLocale == null || !sDefaultLocale.equals(defaultLocale)) { | 233 if (sDefaultLocale == null || !sDefaultLocale.equals(defaultLocale)) { |
| 232 String acceptLanguages = mContext.getResources().getString(R.string. accept_languages); | 234 String acceptLanguages = mContext.getResources().getString(R.string. accept_languages); |
| 233 acceptLanguages = prependToAcceptLanguagesIfNecessary(defaultLocale, acceptLanguages); | 235 acceptLanguages = prependToAcceptLanguagesIfNecessary(defaultLocale, acceptLanguages); |
| 234 sAcceptLanguage = generateAcceptLanguageHeader(acceptLanguages); | 236 sAcceptLanguage = generateAcceptLanguageHeader(acceptLanguages); |
| 235 sDefaultLocale = defaultLocale; | 237 sDefaultLocale = defaultLocale; |
| 236 } | 238 } |
| 237 return sAcceptLanguage; | 239 return sAcceptLanguage; |
| 238 } | 240 } |
| 239 | 241 |
| 240 /** | 242 /** |
| 241 * Handle the special cases in converting a language code/region code pair i nto an ISO-639-1 | |
| 242 * language tag. | |
| 243 * @param language The 2-character language code | |
| 244 * @param region The 2-character country code | |
| 245 * @return A language tag. | |
| 246 */ | |
| 247 @VisibleForTesting | |
| 248 static String makeLanguageTag(String language, String region) { | |
| 249 // Java mostly follows ISO-639-1 and ICU, except for the following three . | |
| 250 // See documentation on java.util.Locale constructor for more. | |
| 251 String isoLanguage; | |
| 252 if ("iw".equals(language)) { | |
| 253 isoLanguage = "he"; | |
| 254 } else if ("ji".equals(language)) { | |
| 255 isoLanguage = "yi"; | |
| 256 } else if ("in".equals(language)) { | |
| 257 isoLanguage = "id"; | |
| 258 } else { | |
| 259 isoLanguage = language; | |
| 260 } | |
| 261 | |
| 262 return isoLanguage + "-" + region; | |
| 263 } | |
| 264 | |
| 265 /** | |
| 266 * Get the language code for the default locale and prepend it to the Accept -Language string if | 243 * Get the language code for the default locale and prepend it to the Accept -Language string if |
| 267 * it isn't already present. The logic should match PrependToAcceptLanguages IfNecessary in | 244 * it isn't already present. The logic should match PrependToAcceptLanguages IfNecessary in |
| 268 * chrome/browser/android/preferences/pref_service_bridge.cc | 245 * chrome/browser/android/preferences/pref_service_bridge.cc |
| 269 * @param locales A string representing a default locale or a list of defaul t locales. | 246 * @param locales A string representing a default language tag or a list of default language |
| 247 * tags. | |
| 270 * @param acceptLanguages The default language list for the language of the user's locale. | 248 * @param acceptLanguages The default language list for the language of the user's locale. |
| 271 * @return An updated language list. | 249 * @return An updated language list. |
| 272 */ | 250 */ |
| 273 @VisibleForTesting | 251 @VisibleForTesting |
| 274 static String prependToAcceptLanguagesIfNecessary(String locales, String acc eptLanguages) { | 252 static String prependToAcceptLanguagesIfNecessary(String locales, String acc eptLanguages) { |
| 275 String localeString = locales + "," + acceptLanguages; | 253 String localeStrings = locales + "," + acceptLanguages; |
| 276 String[] localeList = localeString.split(","); | 254 String[] localeList = localeStrings.split(","); |
| 277 | 255 |
| 278 HashSet<String> seenLocales = new HashSet<>(); | 256 HashSet<String> seenLanguageTags = new HashSet<>(); |
| 279 ArrayList<String> uniqueList = new ArrayList<>(); | 257 ArrayList<String> uniqueList = new ArrayList<>(); |
| 280 for (String locale : localeList) { | 258 for (String localeString : localeList) { |
| 281 // TODO(yirui): Support BCP47 compliant format including 3-letter co untry code, | 259 Locale locale = LocaleUtils.forLanguageTag(localeString); |
| 282 // '-' separator and missing country case. | 260 String language = locale.getLanguage(); |
| 283 if (locale.length() != 5 || (locale.charAt(2) != '_' && locale.charA t(2) != '-')) { | 261 String country = locale.getCountry(); |
| 284 // Skip checking not well formed locales. | 262 String languageTag = LocaleUtils.toLanguageTag(locale); |
| 263 | |
| 264 if (seenLanguageTags.contains(languageTag)) { | |
| 285 continue; | 265 continue; |
| 286 } | 266 } |
| 287 | 267 if (!country.isEmpty()) { |
| 288 String language = locale.substring(0, 2); | 268 seenLanguageTags.add(languageTag); |
| 289 String country = locale.substring(3); | |
| 290 String languageTag = makeLanguageTag(language, country); | |
| 291 | |
| 292 if (seenLocales.contains(languageTag)) { | |
| 293 continue; | |
| 294 } | 269 } |
| 295 uniqueList.add(languageTag); | 270 uniqueList.add(languageTag); |
|
Seigo Nonaka
2016/10/17 04:12:15
You are creating same locale object twice by calli
Yirui Huang
2016/10/17 10:40:52
Done.
| |
| 296 seenLocales.add(languageTag); | |
| 297 } | 271 } |
| 298 | 272 |
| 299 // If language is not in the accept languages list, also add language co de. | 273 // If language is not in the accept languages list, also add language co de. |
| 300 // A language code should only be inserted after the last languageTag th at | 274 // A language code should only be inserted after the last languageTag th at |
| 301 // contains that language. | 275 // contains that language. |
| 302 // This will work with the IDS_ACCEPT_LANGUAGE localized strings bundled | 276 // This will work with the IDS_ACCEPT_LANGUAGE localized strings bundled |
| 303 // with Chrome but may fail on arbitrary lists of language tags due to | 277 // with Chrome but may fail on arbitrary lists of language tags due to |
| 304 // differences in case and whitespace. | 278 // differences in case and whitespace. |
| 305 HashSet<String> seenLanguages = new HashSet<>(); | 279 HashSet<String> seenLanguages = new HashSet<>(); |
| 306 ArrayList<String> outputList = new ArrayList<>(); | 280 ArrayList<String> outputList = new ArrayList<>(); |
| 307 for (int i = uniqueList.size() - 1; i >= 0; i--) { | 281 for (int i = uniqueList.size() - 1; i >= 0; i--) { |
| 308 String localeAdd = uniqueList.get(i); | 282 String localeStr = uniqueList.get(i); |
| 309 String languageAdd = localeAdd.substring(0, 2); | 283 Locale localeAdd = LocaleUtils.forLanguageTag(localeStr); |
| 284 String languageAdd = localeAdd.getLanguage(); | |
| 285 String countryAdd = localeAdd.getCountry(); | |
| 286 | |
| 310 if (!seenLanguages.contains(languageAdd)) { | 287 if (!seenLanguages.contains(languageAdd)) { |
| 311 seenLanguages.add(languageAdd); | 288 seenLanguages.add(languageAdd); |
| 312 outputList.add(languageAdd); | 289 outputList.add(languageAdd); |
| 313 } | 290 } |
| 314 outputList.add(localeAdd); | 291 if (!countryAdd.isEmpty()) { |
| 292 outputList.add(localeStr); | |
| 293 } | |
| 315 } | 294 } |
| 316 Collections.reverse(outputList); | 295 Collections.reverse(outputList); |
| 317 return TextUtils.join(",", outputList); | 296 return TextUtils.join(",", outputList); |
| 318 } | 297 } |
| 319 | 298 |
| 320 /** | 299 /** |
| 321 * Given a list of comma-delimited language codes in decreasing order of pre ference, insert | 300 * Given a list of comma-delimited language codes in decreasing order of pre ference, insert |
| 322 * q-values to represent the relative quality/precedence of each language. T he logic should | 301 * q-values to represent the relative quality/precedence of each language. T he logic should |
| 323 * match GenerateAcceptLanguageHeader in net/http/http_util.cc. | 302 * match GenerateAcceptLanguageHeader in net/http/http_util.cc. |
| 324 * @param languageList A comma-delimited list of language codes containing n o whitespace. | 303 * @param languageList A comma-delimited list of language codes containing n o whitespace. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 340 langListWithQ.format(",%s;q=0.%d", language, qvalue10); | 319 langListWithQ.format(",%s;q=0.%d", language, qvalue10); |
| 341 } | 320 } |
| 342 // It does not make sense to have 'q=0'. | 321 // It does not make sense to have 'q=0'. |
| 343 if (qvalue10 > kQvalueDecrement10) { | 322 if (qvalue10 > kQvalueDecrement10) { |
| 344 qvalue10 -= kQvalueDecrement10; | 323 qvalue10 -= kQvalueDecrement10; |
| 345 } | 324 } |
| 346 } | 325 } |
| 347 return langListWithQ.toString(); | 326 return langListWithQ.toString(); |
| 348 } | 327 } |
| 349 } | 328 } |
| OLD | NEW |