From f9ace6e25a73057ee476cdc1fccd42b9e2f2382e Mon Sep 17 00:00:00 2001 From: simonpoole Date: Sun, 10 Nov 2024 15:06:50 +0100 Subject: [PATCH] Avoid network access in onPostExecute Reading the OkHttps Response object in onPostExecute can potentially lead to network access on the main thread (probably depending on how much data is transferred). This fix moves any potential IO to doInBackground. --- .../de/blau/android/net/OAuth2Helper.java | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/main/java/de/blau/android/net/OAuth2Helper.java b/src/main/java/de/blau/android/net/OAuth2Helper.java index 779d74ca89..16f34dee22 100644 --- a/src/main/java/de/blau/android/net/OAuth2Helper.java +++ b/src/main/java/de/blau/android/net/OAuth2Helper.java @@ -26,6 +26,7 @@ import androidx.annotation.NonNull; import de.blau.android.App; import de.blau.android.AsyncResult; +import de.blau.android.ErrorCodes; import de.blau.android.PostAsyncActionHandler; import de.blau.android.exception.OsmException; import de.blau.android.osm.OsmXml; @@ -168,9 +169,9 @@ public String getAuthorisationUrl(Context context) throws OsmException { String description = data.getQueryParameter(ERROR_DESCRIPTION_PARAM); throw new IllegalArgumentException(description == null ? error : description); } - return new ExecutorTask() { + return new ExecutorTask() { @Override - protected Response doInBackground(Void param) throws IOException { + protected AsyncResult doInBackground(Void param) throws IOException { Log.d(DEBUG_TAG, "oAuthHandshake doInBackground"); try (AdvancedPrefDatabase prefDb = new AdvancedPrefDatabase(context)) { API api = prefDb.getCurrentAPI(); @@ -183,37 +184,52 @@ protected Response doInBackground(Void param) throws IOException { Request request = new Request.Builder().url(accessTokenUrl).post(requestBody).build(); OkHttpClient.Builder builder = App.getHttpClient().newBuilder().connectTimeout(TIMEOUT, TimeUnit.SECONDS).readTimeout(TIMEOUT, TimeUnit.SECONDS); - return builder.build().newCall(request).execute(); + Response result = builder.build().newCall(request).execute(); + if (result.isSuccessful()) { + return readAccessToken(context, result); + } + Log.e(DEBUG_TAG, "Handshake fail " + result.code() + " " + result.message()); + return new AsyncResult(result.code(), result.message()); + } + } + + /** + * Read/parse access token and save it + * + * @param context an Android Context + * @param result the Response from the API + * @return an AsyncResult object indicating if things worked or failed + */ + private AsyncResult readAccessToken(@NonNull Context context, @NonNull Response result) { + try (BufferedReader rd = new BufferedReader(new InputStreamReader(result.body().byteStream(), Charset.forName(OsmXml.UTF_8)))) { + JsonElement root = JsonParser.parseReader(rd); + if (root.isJsonObject()) { + JsonElement accessToken = ((JsonObject) root).get(ACCESS_TOKEN_FIELD); + if (accessToken instanceof JsonElement) { + setAccessToken(context, accessToken.getAsString(), null); + } + } + } catch (IOException | JsonSyntaxException e) { + Log.e(DEBUG_TAG, "Error reading response " + e.getMessage()); + return new AsyncResult(ErrorCodes.UNKNOWN_ERROR, e.getMessage()); } + return new AsyncResult(ErrorCodes.OK); } @Override protected void onBackgroundError(Exception e) { Log.d(DEBUG_TAG, "oAuthHandshake onBackgroundError " + e.getMessage()); - handler.onError(new AsyncResult(0, e.getMessage())); + handler.onError(new AsyncResult(ErrorCodes.UNKNOWN_ERROR, e.getMessage())); } @Override - protected void onPostExecute(Response result) { + protected void onPostExecute(AsyncResult result) { Log.d(DEBUG_TAG, "oAuthHandshake onPostExecute"); - if (result.isSuccessful()) { - try (BufferedReader rd = new BufferedReader(new InputStreamReader(result.body().byteStream(), Charset.forName(OsmXml.UTF_8)))) { - JsonElement root = JsonParser.parseReader(rd); - if (root.isJsonObject()) { - JsonElement accessToken = ((JsonObject) root).get(ACCESS_TOKEN_FIELD); - if (accessToken instanceof JsonElement) { - setAccessToken(context, accessToken.getAsString(), null); - } - } - handler.onSuccess(); - } catch (IOException | JsonSyntaxException e) { - Log.e(DEBUG_TAG, "Error reading response " + e.getMessage()); - handler.onError(new AsyncResult(0, e.getMessage())); - } + if (ErrorCodes.OK == result.getCode()) { + handler.onSuccess(); return; } - Log.e(DEBUG_TAG, "Handshake fail " + result.code() + " " + result.message()); - handler.onError(new AsyncResult(result.code(), result.message())); + handler.onError(result); } }; }