Skip to content

Commit d7adce9

Browse files
committed
Protect against external activity failure
1 parent cf250cb commit d7adce9

File tree

8 files changed

+219
-54
lines changed

8 files changed

+219
-54
lines changed

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

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

62+
public void bluetoothEnableRestricted() {
63+
PopUp.show( mClient.fetchPopupsContext().getString(R.string.this_device_may_have_restrictions_in_place), //message
64+
mClient.fetchPopupsContext().getString(R.string.unable_to_start_activity_to_enable_bluetooth),
65+
R.drawable.error_face, R.drawable.red_btn,
66+
PopUp.GIFF_ANIMATION_ERROR,
67+
PopUp.TYPE_ALERT,
68+
popupClickActivityCancelled, popupClickActivityCancelled);
69+
}
70+
6271
public void bluetoothConnectPermissionError() {
6372
PopUp.show(mClient.fetchPopupsContext().getString(R.string.ble_permission_connect_error),
6473
mClient.fetchPopupsContext().getString(R.string.permissions_needed_title),

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

Lines changed: 94 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;
@@ -271,4 +277,92 @@ public void gifAnimate( @IdRes int id) {
271277
view.animate();
272278
}
273279
}
280+
281+
public static void safelyStartActivityPopup( String message, String title) {
282+
PopUp.show( message, title,
283+
R.drawable.error_face,
284+
R.drawable.red_btn,
285+
PopUp.GIFF_ANIMATION_ERROR,
286+
PopUp.TYPE_ALERT,
287+
null,
288+
null);
289+
290+
}
291+
public static void safelyStartActivityPopup( Context context, String title) {
292+
safelyStartActivityPopup( context.getString(R.string.this_device_may_have_restrictions_in_place), title);
293+
}
294+
295+
public static void safelyStartActivityPopupGeneric( Context context) {
296+
safelyStartActivityPopup( context, context.getString(R.string.unable_to_start_activity));
297+
}
298+
299+
public static void safelyStartActivityPopupOpenLink( Context context) {
300+
safelyStartActivityPopup( context, context.getString(R.string.unable_to_open_link));
301+
}
302+
303+
// Wrap startActivity and startActivityForResult
304+
// Call resolveActivity and catch exception from startActivity
305+
// Return non-zero error on fail
306+
// When startActivityForResult fails, the caller likely
307+
// needs to add code similar to the cancel case in onActivityResult
308+
public static int safelyStartActivity( Context context, boolean report, Intent intent,
309+
boolean forResult, int requestCode, Bundle options) {
310+
int error = 0;
311+
ComponentName componentName = intent.resolveActivity( context.getPackageManager());
312+
if ( componentName == null) {
313+
Log.i(TAG,"startActivity - no component");
314+
error = 1;
315+
} else {
316+
try {
317+
if ( forResult) {
318+
if ( !(context instanceof Activity)) {
319+
error = 3;
320+
} else {
321+
((Activity) context).startActivityForResult(intent, requestCode, options);
322+
}
323+
} else {
324+
context.startActivity(intent);
325+
}
326+
} catch (Exception e) {
327+
Log.i(TAG, "startActivity - exception");
328+
e.printStackTrace();
329+
error = 2;
330+
}
331+
}
332+
if ( report && error != 0)
333+
{
334+
safelyStartActivityPopupGeneric( context);
335+
}
336+
return error;
337+
}
338+
339+
public static int safelyStartActivity(Context context, boolean report, Intent intent, Bundle options) {
340+
return UIUtils.safelyStartActivity( context, report, intent, false, 0, options);
341+
}
342+
343+
public static int safelyStartActivity(Context context, boolean report, Intent intent) {
344+
return UIUtils.safelyStartActivity( context, report, intent, null);
345+
}
346+
347+
public static int safelyStartActivityForResult(Activity activity, boolean report, Intent intent, int requestCode, Bundle options) {
348+
return UIUtils.safelyStartActivity( activity, report, intent, true, requestCode, options);
349+
}
350+
351+
public static int safelyStartActivityForResult(Activity activity, boolean report, Intent intent, int requestCode) {
352+
return UIUtils.safelyStartActivityForResult( activity, report, intent, requestCode, null);
353+
}
354+
355+
public static int safelyStartActivityViewURI( Context context, boolean report, Uri uri) {
356+
Intent intent = new Intent(Intent.ACTION_VIEW);
357+
intent.setData( uri);
358+
int error = UIUtils.safelyStartActivity( context, false, intent);
359+
if ( report && error != 0) {
360+
safelyStartActivityPopupOpenLink( context);
361+
}
362+
return error;
363+
}
364+
365+
public static int safelyStartActivityViewURL( Context context, boolean report, String url) {
366+
return UIUtils.safelyStartActivityViewURI( context, report, Uri.parse( url));
367+
}
274368
}

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 onShowFileChooser( webView, filePathCallback, fileChooserParams);
951949
}
952950
}); //setWebChromeClient
953951

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

982+
private boolean onShowFileChooser(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: 24 additions & 13 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 onShowFileChooser( webView, filePathCallback, fileChooserParams);
147140

148141
}
149142
}); //setWebChromeClient
@@ -268,6 +261,23 @@ else if ( !hexName.isEmpty()) {
268261
} // onCreate
269262

270263

264+
private boolean onShowFileChooser(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)