mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-11-03 19:43:52 +00:00 
			
		
		
		
	fix: potential risk of being unable to launch URLs without HTTP(S) scheme (#4867)
This commit is contained in:
		
							parent
							
								
									4b5195d891
								
							
						
					
					
						commit
						fb887bec10
					
				@ -1,10 +1,10 @@
 | 
				
			|||||||
import 'package:flutter/services.dart';
 | 
					 | 
				
			||||||
import 'package:flutter/widgets.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import 'package:appflowy/generated/locale_keys.g.dart';
 | 
					import 'package:appflowy/generated/locale_keys.g.dart';
 | 
				
			||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
 | 
					import 'package:appflowy/workspace/presentation/home/toast.dart';
 | 
				
			||||||
import 'package:appflowy_backend/log.dart';
 | 
					import 'package:appflowy_backend/log.dart';
 | 
				
			||||||
import 'package:easy_localization/easy_localization.dart';
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/widgets.dart';
 | 
				
			||||||
 | 
					import 'package:string_validator/string_validator.dart';
 | 
				
			||||||
import 'package:url_launcher/url_launcher.dart' as launcher;
 | 
					import 'package:url_launcher/url_launcher.dart' as launcher;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef OnFailureCallback = void Function(Uri uri);
 | 
					typedef OnFailureCallback = void Function(Uri uri);
 | 
				
			||||||
@ -16,35 +16,60 @@ Future<bool> afLaunchUrl(
 | 
				
			|||||||
  launcher.LaunchMode mode = launcher.LaunchMode.platformDefault,
 | 
					  launcher.LaunchMode mode = launcher.LaunchMode.platformDefault,
 | 
				
			||||||
  String? webOnlyWindowName,
 | 
					  String? webOnlyWindowName,
 | 
				
			||||||
}) async {
 | 
					}) async {
 | 
				
			||||||
 | 
					  // try to launch the uri directly
 | 
				
			||||||
 | 
					  bool result;
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    return await launcher.launchUrl(
 | 
					    result = await launcher.launchUrl(uri);
 | 
				
			||||||
      uri,
 | 
					 | 
				
			||||||
      mode: mode,
 | 
					 | 
				
			||||||
      webOnlyWindowName: webOnlyWindowName,
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  } on PlatformException catch (e) {
 | 
					  } on PlatformException catch (e) {
 | 
				
			||||||
    Log.error("Failed to open uri: $e");
 | 
					    Log.error('Failed to open uri: $e');
 | 
				
			||||||
    if (onFailure != null) {
 | 
					  } finally {
 | 
				
			||||||
      onFailure(uri);
 | 
					    result = false;
 | 
				
			||||||
    } else {
 | 
					  }
 | 
				
			||||||
      showMessageToast(
 | 
					
 | 
				
			||||||
        LocaleKeys.failedToOpenUrl.tr(args: [e.message ?? "PlatformException"]),
 | 
					  // if the uri is not a valid url, try to launch it with https scheme
 | 
				
			||||||
        context: context,
 | 
					  final url = uri.toString();
 | 
				
			||||||
      );
 | 
					  if (!result && !isURL(url, {'require_protocol': true})) {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      final uriWithScheme = Uri.parse('https://$url');
 | 
				
			||||||
 | 
					      result = await launcher.launchUrl(uriWithScheme);
 | 
				
			||||||
 | 
					    } on PlatformException catch (e) {
 | 
				
			||||||
 | 
					      Log.error('Failed to open uri: $e');
 | 
				
			||||||
 | 
					      if (context != null && context.mounted) {
 | 
				
			||||||
 | 
					        _errorHandler(uri, context: context, onFailure: onFailure, e: e);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return false;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Future<void> afLaunchUrlString(String url) async {
 | 
					Future<bool> afLaunchUrlString(String url) async {
 | 
				
			||||||
 | 
					  final Uri uri;
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    final uri = Uri.parse(url);
 | 
					    uri = Uri.parse(url);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    await launcher.launchUrl(uri);
 | 
					 | 
				
			||||||
  } on PlatformException catch (e) {
 | 
					 | 
				
			||||||
    Log.error("Failed to open uri: $e");
 | 
					 | 
				
			||||||
  } on FormatException catch (e) {
 | 
					  } on FormatException catch (e) {
 | 
				
			||||||
    Log.error("Failed to parse url: $e");
 | 
					    Log.error('Failed to parse url: $e');
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // try to launch the uri directly
 | 
				
			||||||
 | 
					  return afLaunchUrl(uri);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _errorHandler(
 | 
				
			||||||
 | 
					  Uri uri, {
 | 
				
			||||||
 | 
					  BuildContext? context,
 | 
				
			||||||
 | 
					  OnFailureCallback? onFailure,
 | 
				
			||||||
 | 
					  PlatformException? e,
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  Log.error('Failed to open uri: $e');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (onFailure != null) {
 | 
				
			||||||
 | 
					    onFailure(uri);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    showMessageToast(
 | 
				
			||||||
 | 
					      LocaleKeys.failedToOpenUrl.tr(args: [e?.message ?? "PlatformException"]),
 | 
				
			||||||
 | 
					      context: context,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user