Skip to content

Commit

Permalink
Add function to start OSM signup in WebView
Browse files Browse the repository at this point in the history
Would

fix #1506
  • Loading branch information
simonpoole committed Jan 17, 2024
1 parent cf209c9 commit 0ec40a1
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 44 deletions.
19 changes: 19 additions & 0 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,25 @@
android:configChanges="orientation|screenSize|keyboardHidden|density|screenLayout|uiMode|fontScale"
android:launchMode="singleInstance"
android:theme="@style/Theme.AppCompat" />
<activity
android:name="Signup"
android:configChanges="orientation|screenSize|keyboardHidden|density|screenLayout|uiMode|fontScale"
android:launchMode="singleInstance"
android:theme="@style/Theme.AppCompat"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="master.apis.dev.openstreetmap.org" />
<data android:host="www.openstreetmap.org" />
<data android:pathPattern="/user/.*/confirm.*" />
</intent-filter>
</activity>
<activity
android:name="LicenseViewer"
android:configChanges="orientation|screenSize|keyboardHidden|density|screenLayout|uiMode|fontScale"
Expand Down
48 changes: 9 additions & 39 deletions src/main/java/de/blau/android/Authorize.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
package de.blau.android;

import java.io.ByteArrayInputStream;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import de.blau.android.contract.MimeTypes;
import de.blau.android.contract.Schemes;
import de.blau.android.dialogs.Progress;
import de.blau.android.exception.OsmException;
import de.blau.android.net.OAuth2Helper;
import de.blau.android.net.OAuth1aHelper;
import de.blau.android.net.OAuth2Helper;
import de.blau.android.osm.Server;
import de.blau.android.prefs.API.Auth;
import de.blau.android.prefs.Preferences;
import de.blau.android.util.ActivityResultHandler;
import de.blau.android.util.OsmWebViewClient;
import de.blau.android.util.ScreenMessage;
import de.blau.android.util.UpdatedWebViewClient;
import de.blau.android.util.WebViewActivity;
import oauth.signpost.exception.OAuthException;

Expand Down Expand Up @@ -67,12 +63,7 @@ public static void startForResult(@NonNull FragmentActivity activity, @Nullable
activity.startActivityForResult(intent, REQUEST_CODE);
}

private class OAuthWebViewClient extends UpdatedWebViewClient {
private static final String MATOMO = "matomo";

Object progressLock = new Object();
boolean progressShown = false;
Runnable dismiss = () -> Progress.dismissDialog(Authorize.this, Progress.PROGRESS_OAUTH);
private class OAuthWebViewClient extends OsmWebViewClient {

@Override
public boolean handleLoading(WebView view, Uri uri) {
Expand All @@ -87,40 +78,19 @@ public boolean handleLoading(WebView view, Uri uri) {
}

@Override
public WebResourceResponse handleIntercept(WebView view, Uri uri) {
final String path = uri.getPath();
if (path != null && path.toLowerCase().contains(MATOMO)) {
return new WebResourceResponse(MimeTypes.TEXTPLAIN, "utf-8", new ByteArrayInputStream("".getBytes()));
}
return super.handleIntercept(view, uri);
public void exit() {
Authorize.this.exit();
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
synchronized (progressLock) {
if (!progressShown) {
progressShown = true;
Progress.showDialog(Authorize.this, Progress.PROGRESS_OAUTH);
}
}
}
protected void showProgressDialog() {
Progress.showDialog(Authorize.this, Progress.PROGRESS_OAUTH);

@Override
public void onPageFinished(WebView view, String url) {
synchronized (progressLock) {
synchronized (webViewLock) {
if (progressShown && webView != null) {
webView.removeCallbacks(dismiss);
webView.postDelayed(dismiss, 500);
}
}
}
}

@Override
public void receivedError(WebView view, int errorCode, String description, String failingUrl) {
exit();
ScreenMessage.toastTopError(view.getContext(), description);
protected void dismissProgressDialog() {
Progress.dismissDialog(Authorize.this, Progress.PROGRESS_OAUTH);
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/main/java/de/blau/android/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,9 @@ public boolean read(FragmentActivity currentActivity, Uri fileUri) {
case R.id.tag_menu_reset_address_prediction:
Address.resetLastAddresses(this);
return true;
case R.id.menu_tools_signup:
Signup.startForResult(this, null);
break;
case R.id.menu_tools_oauth_reset: // reset the current OAuth tokens
if (server.getOAuth()) {
try (AdvancedPrefDatabase prefdb = new AdvancedPrefDatabase(this)) {
Expand Down
122 changes: 122 additions & 0 deletions src/main/java/de/blau/android/Signup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package de.blau.android;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import de.blau.android.dialogs.Progress;
import de.blau.android.prefs.Preferences;
import de.blau.android.util.ActivityResultHandler;
import de.blau.android.util.OsmWebViewClient;
import de.blau.android.util.WebViewActivity;

/**
* Create a new OSM account
*
* Depends on the path of the page with the sign up form
*
* https://master.apis.dev.openstreetmap.org/user/new
*
* the format of confirmation url received in the received e-mail (see the app manifest)
*
* https://master.apis.dev.openstreetmap.org/user/SimonDev1234/confirm?confirm_string=7x4FHpz7zvd1O8Z8hd70NIxVQDvIXpFH
*
* and the query parameter added when the "Start mapping" button in clicked
*
* @author Simon
*
*/
public class Signup extends WebViewActivity {

private static final String DEBUG_TAG = Signup.class.getSimpleName();

public static final int REQUEST_CODE = Signup.class.hashCode() & 0x0000FFFF;

private static final String EDIT_HELP_VALUE = "1";
private static final String EDIT_HELP_PARAM = "edit_help";
private static final String USER_NEW_PATH = "/user/new";

/**
* Start a Signup activity
*
* @param activity calling activity
* @param listener an ActivityResult.Listener to process the result or null
*/
public static void startForResult(@NonNull FragmentActivity activity, @Nullable ActivityResultHandler.Listener listener) {
Log.d(DEBUG_TAG, "startForResult");
if (!hasWebView(activity)) {
return;
}
Log.d(DEBUG_TAG, "request code " + REQUEST_CODE);
if (listener != null) {
if (activity instanceof ActivityResultHandler) {
((ActivityResultHandler) activity).setResultListener(REQUEST_CODE, listener);
} else {
throw new ClassCastException("activity must implement ActivityResultHandler");
}
}

Intent intent = new Intent(activity, Signup.class);
activity.startActivityForResult(intent, REQUEST_CODE);
}

private class SignupViewClient extends OsmWebViewClient {

@Override
public boolean handleLoading(WebView view, Uri uri) {
final String editHelp = uri.getQueryParameter(EDIT_HELP_PARAM);
if (editHelp != null && editHelp.equals(EDIT_HELP_VALUE)) {
exit();
return true;
}
return false;
}

@Override
public void exit() {
Signup.this.exit();
}

@Override
protected void showProgressDialog() {
Progress.showDialog(Signup.this, Progress.PROGRESS_WEBSITE);
}

@Override
protected void dismissProgressDialog() {
Progress.dismissDialog(Signup.this, Progress.PROGRESS_WEBSITE);
}
}

@Override
protected void onCreate(final Bundle savedInstanceState) {
final Preferences prefs = App.getPreferences(this);
if (prefs.lightThemeEnabled()) {
setTheme(R.style.Theme_customMain_Light);
}
super.onCreate(savedInstanceState);

String dataUrl = getIntent().getDataString();
String signupUrl = dataUrl == null ? prefs.getServer().getWebsiteBaseUrl() + USER_NEW_PATH : dataUrl;

Log.d(DEBUG_TAG, "signup for " + signupUrl);
synchronized (webViewLock) {
webView = new WebView(this);
setContentView(webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new SignupViewClient());
loadUrlOrRestore(savedInstanceState, signupUrl);
}
}

@Override
protected void onNewIntent(Intent intent) {
Log.d(DEBUG_TAG, "onNewIntent");
super.onNewIntent(intent);
loadUrlOrRestore(null, intent.getDataString());
}
}
4 changes: 4 additions & 0 deletions src/main/java/de/blau/android/dialogs/Progress.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class Progress extends ImmersiveDialogFragment {
public static final int PROGRESS_LOADING_PRESET = 14;
public static final int PROGRESS_IMPORTING_FILE = 15;
public static final int PROGRESS_DOWNLOAD_TASKS = 16;
public static final int PROGRESS_WEBSITE = 17;

private int dialogType;

Expand Down Expand Up @@ -116,6 +117,7 @@ public static void dismissAll(@NonNull FragmentActivity activity) {
dismissDialog(activity, PROGRESS_LOADING_PRESET);
dismissDialog(activity, PROGRESS_IMPORTING_FILE);
dismissDialog(activity, PROGRESS_DOWNLOAD_TASKS);
dismissDialog(activity, PROGRESS_WEBSITE);
}

/**
Expand Down Expand Up @@ -159,6 +161,8 @@ private static String getTag(int dialogType) {
return "dialog_progress_importing_file";
case PROGRESS_DOWNLOAD_TASKS:
return "dialog_progress_download_tasks";
case PROGRESS_WEBSITE:
return "dialog_progress_website";
default:
Log.w(DEBUG_TAG, "Unknown dialog type " + dialogType);
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/de/blau/android/dialogs/ProgressDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public static AlertDialog get(@NonNull Context ctx, int dialogType) {
titleId = R.string.progress_title;
messageId = R.string.progress_download_tasks_message;
break;
case Progress.PROGRESS_WEBSITE:
titleId = R.string.progress_general_title;
messageId = R.string.progress_website;
break;
default:
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/blau/android/util/DownloadActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public boolean handleLoading(@NonNull WebView view, @NonNull Uri uri) {
@Override
protected WebResourceResponse handleIntercept(WebView view, Uri uri) {
if (FAVICON.equals(uri.getLastPathSegment())) {
return new WebResourceResponse(MimeTypes.PNG, "utf-8", new ByteArrayInputStream("".getBytes()));
return emptyResponse();
}
return super.handleIntercept(view, uri);
}
Expand Down
94 changes: 94 additions & 0 deletions src/main/java/de/blau/android/util/OsmWebViewClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package de.blau.android.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import androidx.annotation.Nullable;

/**
* WebViewClient for some OSM website specifics
*
* @author Simon
*
*/
public abstract class OsmWebViewClient extends UpdatedWebViewClient {

private static final String DEBUG_TAG = OsmWebViewClient.class.getSimpleName();

private static final String MATOMO = "matomo";

private Runnable dismiss = () -> dismissProgressDialog();

private Object progressLock = new Object();
private boolean progressShown = false;

/**
* Manipulate the response to a query
*
* @param view the WebView
* @param uri the request Uri
* @return a WebResourceResponse or null if normal processing should continue
*/
@Nullable
protected WebResourceResponse handleIntercept(WebView view, Uri uri) { // NOSONAR
// remove known trackers
final String path = uri.getPath();
if (path != null && path.toLowerCase().contains(MATOMO)) {
return emptyResponse();
}
return null;
}

@Override
public void receivedError(WebView view, int errorCode, String description, String failingUrl) {
exit();
ScreenMessage.toastTopError(view.getContext(), description);
}

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
synchronized (progressLock) {
if (!progressShown) {
progressShown = true;
showProgressDialog();
}
}
}

@Override
public void onPageFinished(WebView view, String url) {
synchronized (progressLock) {
if (view != null) { // shouldn't happen but historically has
Context context = view.getContext();
if (context instanceof WebViewActivity) {
synchronized (((WebViewActivity) context).webViewLock) {
if (progressShown) {
view.removeCallbacks(dismiss);
view.postDelayed(dismiss, 500);
}
}
return;
}
}
Log.e(DEBUG_TAG, "onPageFinish context not a WebViewActivity");
}
}

/**
* Exit the activity holding the WebView
*/
protected abstract void exit();

/**
* Show the progress dialog
*/
protected abstract void showProgressDialog();

/**
* Dismiss the progress dialog
*/
protected abstract void dismissProgressDialog();
}
Loading

0 comments on commit 0ec40a1

Please sign in to comment.