Skip to content

Commit d1a49f7

Browse files
authored
Protect external activities (#78)
* Protect against external activity failure * change popups to toasts * modify debug code * ignore resolveActivity
1 parent cf250cb commit d1a49f7

File tree

8 files changed

+205
-55
lines changed

8 files changed

+205
-55
lines changed

app/src/main/java/com/samsung/microbit/ui/FetchPopups.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ public void bluetoothOff() {
5959
popupClickActivityCancelled, popupClickActivityCancelled);
6060
}
6161

62+
public void bluetoothEnableRestricted() {
63+
UIUtils.safelyStartActivityToast( mClient.fetchPopupsContext(),
64+
mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth));
65+
mClient.fetchPopupsCancelled();
66+
}
67+
6268
public void bluetoothConnectPermissionError() {
6369
PopUp.show(mClient.fetchPopupsContext().getString(R.string.ble_permission_connect_error),
6470
mClient.fetchPopupsContext().getString(R.string.permissions_needed_title),

app/src/main/java/com/samsung/microbit/ui/UIUtils.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package com.samsung.microbit.ui;
22

33
import android.app.Activity;
4+
import android.content.ComponentName;
5+
import android.content.Context;
6+
import android.content.Intent;
7+
import android.content.pm.PackageManager;
48
import android.graphics.Point;
59
import android.graphics.Rect;
610
import android.graphics.Typeface;
711
import android.graphics.drawable.Drawable;
12+
import android.net.Uri;
13+
import android.os.Bundle;
814
import android.util.Log;
915
import android.util.TypedValue;
1016
import android.view.View;
@@ -13,6 +19,7 @@
1319
import android.widget.Button;
1420
import android.widget.ImageButton;
1521
import android.widget.TextView;
22+
import android.widget.Toast;
1623

1724
import com.samsung.microbit.R;
1825

@@ -271,4 +278,89 @@ public void gifAnimate( @IdRes int id) {
271278
view.animate();
272279
}
273280
}
281+
282+
public static void safelyStartActivityToast( Context context, String message, String title) {
283+
Toast.makeText( context, title + ".\n" + message, Toast.LENGTH_LONG).show();
284+
}
285+
286+
public static void safelyStartActivityToast( Context context, String title) {
287+
safelyStartActivityToast( context, context.getString(R.string.this_device_may_have_restrictions_in_place), title);
288+
}
289+
290+
public static void safelyStartActivityToastGeneric( Context context) {
291+
safelyStartActivityToast( context, context.getString(R.string.unable_to_start_activity));
292+
}
293+
294+
public static void safelyStartActivityToastOpenLink( Context context) {
295+
safelyStartActivityToast( context, context.getString(R.string.unable_to_open_link));
296+
}
297+
298+
// public static boolean safelyStartActivityDebugFail = false;
299+
300+
// Wrap startActivity and startActivityForResult
301+
// Return non-zero error on fail
302+
// When startActivityForResult fails, the caller likely
303+
// needs to add code similar to the cancel case in onActivityResult
304+
public static int safelyStartActivity( Context context, boolean report, Intent intent,
305+
boolean forResult, int requestCode, Bundle options) {
306+
// if ( safelyStartActivityDebugFail) {
307+
// if (report) {
308+
// safelyStartActivityToastGeneric(context);
309+
// }
310+
// return 4;
311+
// }
312+
313+
int error = 0;
314+
315+
try {
316+
if ( forResult) {
317+
if ( !(context instanceof Activity)) {
318+
error = 3;
319+
} else {
320+
((Activity) context).startActivityForResult(intent, requestCode, options);
321+
}
322+
} else {
323+
context.startActivity(intent);
324+
}
325+
} catch (Exception e) {
326+
Log.i(TAG, "startActivity - exception");
327+
e.printStackTrace();
328+
error = 2;
329+
}
330+
331+
if ( report && error != 0) {
332+
safelyStartActivityToastGeneric( context);
333+
}
334+
return error;
335+
}
336+
337+
public static int safelyStartActivity(Context context, boolean report, Intent intent, Bundle options) {
338+
return UIUtils.safelyStartActivity( context, report, intent, false, 0, options);
339+
}
340+
341+
public static int safelyStartActivity(Context context, boolean report, Intent intent) {
342+
return UIUtils.safelyStartActivity( context, report, intent, null);
343+
}
344+
345+
public static int safelyStartActivityForResult(Activity activity, boolean report, Intent intent, int requestCode, Bundle options) {
346+
return UIUtils.safelyStartActivity( activity, report, intent, true, requestCode, options);
347+
}
348+
349+
public static int safelyStartActivityForResult(Activity activity, boolean report, Intent intent, int requestCode) {
350+
return UIUtils.safelyStartActivityForResult( activity, report, intent, requestCode, null);
351+
}
352+
353+
public static int safelyStartActivityViewURI( Context context, boolean report, Uri uri) {
354+
Intent intent = new Intent(Intent.ACTION_VIEW);
355+
intent.setData( uri);
356+
int error = UIUtils.safelyStartActivity( context, false, intent);
357+
if ( report && error != 0) {
358+
safelyStartActivityToastOpenLink( context);
359+
}
360+
return error;
361+
}
362+
363+
public static int safelyStartActivityViewURL( Context context, boolean report, String url) {
364+
return UIUtils.safelyStartActivityViewURI( context, report, Uri.parse( url));
365+
}
274366
}

app/src/main/java/com/samsung/microbit/ui/activity/FetchActivity.java

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,14 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
360360
}
361361
dataToSave = null;
362362
break;
363+
case REQUEST_CODE_CHOOSE_FILE:
364+
if ( resultCode != RESULT_OK) {
365+
mWebFileChooserCallback.onReceiveValue( null);
366+
return;
367+
}
368+
Uri[] uris = WebChromeClient.FileChooserParams.parseResult ( resultCode, data);
369+
mWebFileChooserCallback.onReceiveValue( uris);
370+
break;
363371
}
364372
}
365373

@@ -468,9 +476,7 @@ public void onClick(final View v) {
468476
break;
469477

470478
case R.id.fetchSelectDuringMore:
471-
Intent intent = new Intent(Intent.ACTION_VIEW);
472-
intent.setData(Uri.parse(getString(R.string.fetchDuringFindOutMoreUrl)));
473-
startActivity(intent);
479+
UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.fetchDuringFindOutMoreUrl));
474480
break;
475481
}
476482
}
@@ -675,7 +681,10 @@ private MBAppState.PairState pairState() {
675681
@SuppressLint("MissingPermission")
676682
private void enableBluetooth() {
677683
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
678-
startActivityForResult(enableBtIntent, RequestCodes.REQUEST_ENABLE_BT);
684+
int error = UIUtils.safelyStartActivityForResult( this, false, enableBtIntent, RequestCodes.REQUEST_ENABLE_BT);
685+
if ( error != 0) {
686+
mPopups.bluetoothEnableRestricted();
687+
}
679688
}
680689

681690
private boolean havePermission(String permission) {
@@ -869,9 +878,7 @@ private void displayUpdateDeviceName() {
869878

870879
private void openURL( String url) {
871880
logi( "openURL: " + url);
872-
Intent intent = new Intent(Intent.ACTION_VIEW);
873-
intent.setData(Uri.parse( url));
874-
startActivity(intent);
881+
UIUtils.safelyStartActivityViewURL( this, true, url);
875882
}
876883

877884
/**
@@ -938,16 +945,7 @@ public void onPageFinished(WebView view, String url) {
938945
mWebView.setWebChromeClient(new WebChromeClient() {
939946
@Override
940947
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
941-
mWebFileChooserCallback = filePathCallback;
942-
try {
943-
Intent intent = fileChooserParams.createIntent();
944-
startActivityForResult(intent, REQUEST_CODE_CHOOSE_FILE);
945-
} catch (Exception e) {
946-
e.printStackTrace();
947-
return false;
948-
}
949-
return true;
950-
948+
return showFileChooser( webView, filePathCallback, fileChooserParams);
951949
}
952950
}); //setWebChromeClient
953951

@@ -981,6 +979,21 @@ public void onDownloadBase64( String base64, String mimetype) {
981979
}
982980
}
983981

982+
private boolean showFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
983+
mWebFileChooserCallback = filePathCallback;
984+
try {
985+
Intent intent = fileChooserParams.createIntent();
986+
int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_CHOOSE_FILE);
987+
if ( error != 0) {
988+
mWebFileChooserCallback.onReceiveValue( null);
989+
}
990+
} catch (Exception e) {
991+
e.printStackTrace();
992+
return false;
993+
}
994+
return true;
995+
}
996+
984997
private void onDownloadBlob( String blob) {
985998
String js = "javascript:("
986999
+ "function f() {"
@@ -1032,7 +1045,10 @@ private void saveData( String name, String mimetype, byte[] data) {
10321045
intent.setType( mimetype);
10331046
intent.putExtra(Intent.EXTRA_TITLE, name);
10341047
dataToSave = data;
1035-
startActivityForResult( intent, REQUEST_CODE_SAVEDATA);
1048+
int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_SAVEDATA);
1049+
if ( error != 0) {
1050+
dataToSave = null;
1051+
}
10361052
}
10371053

10381054
private String displayHtmlGetPath() {

app/src/main/java/com/samsung/microbit/ui/activity/HomeActivity.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.samsung.microbit.data.model.ConnectedDevice;
4343
import com.samsung.microbit.service.IPCService;
4444
import com.samsung.microbit.ui.PopUp;
45+
import com.samsung.microbit.ui.UIUtils;
4546
import com.samsung.microbit.utils.FileUtils;
4647
import com.samsung.microbit.utils.ProjectsHelper;
4748
import com.samsung.microbit.utils.Utils;
@@ -393,9 +394,7 @@ public void onClick(final View v) {
393394
startActivity(i);
394395
break;
395396
case R.id.discover_btn:
396-
Intent intent = new Intent(Intent.ACTION_VIEW);
397-
intent.setData(Uri.parse(getString(R.string.discover_url)));
398-
startActivity(intent);
397+
UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.discover_url));
399398
break;
400399

401400
// TODO: HACK - Navigation View items from drawer here instead of [onNavigationItemSelected]
@@ -406,9 +405,7 @@ public void onClick(final View v) {
406405
}
407406
break;
408407
case R.id.btn_about: {
409-
Intent aboutIntent = new Intent(Intent.ACTION_VIEW);
410-
aboutIntent.setData(Uri.parse(getString(R.string.about_url)));
411-
startActivity(aboutIntent);
408+
UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.about_url));
412409
// Close drawer
413410
drawer.closeDrawer(GravityCompat.START);
414411
}
@@ -422,19 +419,13 @@ public void onClick(final View v) {
422419
}
423420
break;
424421
case R.id.btn_privacy_cookies: {
425-
426-
Intent privacyIntent = new Intent(Intent.ACTION_VIEW);
427-
privacyIntent.setData(Uri.parse(getString(R.string.privacy_policy_url)));
428-
startActivity(privacyIntent);
422+
UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.privacy_policy_url));
429423
// Close drawer
430424
drawer.closeDrawer(GravityCompat.START);
431425
}
432426
break;
433427
case R.id.btn_terms_conditions: {
434-
435-
Intent termsIntent = new Intent(Intent.ACTION_VIEW);
436-
termsIntent.setData(Uri.parse(getString(R.string.terms_of_use_url)));
437-
startActivity(termsIntent);
428+
UIUtils.safelyStartActivityViewURL( this, true, getString(R.string.terms_of_use_url));
438429
// Close drawer
439430
drawer.closeDrawer(GravityCompat.START);
440431
}
@@ -449,7 +440,7 @@ public void onClick(final View v) {
449440
String body = prepareEmailBody();
450441
feedbackIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(body));
451442
Intent mailer = Intent.createChooser(feedbackIntent, null);
452-
startActivity(mailer);
443+
UIUtils.safelyStartActivity( this, true, mailer);
453444
// Close drawer
454445
if(drawer != null) {
455446
drawer.closeDrawer(GravityCompat.START);

app/src/main/java/com/samsung/microbit/ui/activity/MakeCodeWebView.java

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.samsung.microbit.BuildConfig;
2323
import com.samsung.microbit.MBApp;
2424
import com.samsung.microbit.R;
25+
import com.samsung.microbit.ui.UIUtils;
2526
import com.samsung.microbit.utils.FileUtils;
2627
import com.samsung.microbit.utils.ProjectsHelper;
2728

@@ -135,15 +136,7 @@ public void onPageFinished (WebView view, String url) {
135136
webView.setWebChromeClient(new WebChromeClient() {
136137
@Override
137138
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
138-
onShowFileChooser_filePathCallback = filePathCallback;
139-
try {
140-
Intent intent = fileChooserParams.createIntent();
141-
startActivityForResult(intent, REQUEST_CODE_CHOOSE_FILE);
142-
} catch (Exception e) {
143-
e.printStackTrace();
144-
return false;
145-
}
146-
return true;
139+
return showFileChooser( webView, filePathCallback, fileChooserParams);
147140

148141
}
149142
}); //setWebChromeClient
@@ -243,7 +236,7 @@ else if ( !hexName.isEmpty()) {
243236
openProjectActivity( hexToWrite);
244237
} else {
245238
Toast.makeText( MakeCodeWebView.this,
246-
"Saved to FLASH page", Toast.LENGTH_LONG).show();
239+
"Saved to My Programs page", Toast.LENGTH_LONG).show();
247240
}
248241
}
249242
} catch ( Exception e) {
@@ -268,6 +261,23 @@ else if ( !hexName.isEmpty()) {
268261
} // onCreate
269262

270263

264+
private boolean showFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
265+
onShowFileChooser_filePathCallback = filePathCallback;
266+
try {
267+
Intent intent = fileChooserParams.createIntent();
268+
int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_CHOOSE_FILE);
269+
if ( error != 0) {
270+
onShowFileChooser_filePathCallback.onReceiveValue( null);
271+
}
272+
} catch (Exception e) {
273+
e.printStackTrace();
274+
return false;
275+
}
276+
return true;
277+
278+
}
279+
280+
271281
private boolean overrideUri( final Uri uri) {
272282
String url = uri.toString().toLowerCase();
273283
Log.v(TAG, "overrideUri: " + url);
@@ -333,9 +343,7 @@ else if ( host.equals( "github.com")) {
333343

334344
void openUri( Uri uri) {
335345
Log.v(TAG, "openUri: " + uri);
336-
Intent intent = new Intent(Intent.ACTION_VIEW);
337-
intent.setData( uri);
338-
startActivity(intent);
346+
UIUtils.safelyStartActivityViewURI( this, true, uri);
339347
}
340348

341349
private void saveData( String name, String mimetype, byte[] data) {
@@ -344,7 +352,10 @@ private void saveData( String name, String mimetype, byte[] data) {
344352
intent.setType( mimetype);
345353
intent.putExtra(Intent.EXTRA_TITLE, name);
346354
dataToSave = data;
347-
startActivityForResult( intent, REQUEST_CODE_SAVEDATA);
355+
int error = UIUtils.safelyStartActivityForResult( this, true, intent, REQUEST_CODE_SAVEDATA);
356+
if ( error != 0) {
357+
dataToSave = null;
358+
}
348359
}
349360

350361
@Override

0 commit comments

Comments
 (0)