iOS url launcher to use SafariServices instead of changing to Safari app (#243)

* Use safari services instead of using application openURL

* Update version info

* Formatting

* review
diff --git a/packages/url_launcher/CHANGELOG.md b/packages/url_launcher/CHANGELOG.md
index d082103..b0cdfc9 100644
--- a/packages/url_launcher/CHANGELOG.md
+++ b/packages/url_launcher/CHANGELOG.md
@@ -1,14 +1,18 @@
+## 1.0.0
+
+* iOS plugin presents a Safari view controller instead of switching to the Safari app.
+
 ## 0.4.2+5
 
 * Aligned author name with rest of repo.
 
 ## [0.4.2+2], [0.4.2+3], [0.4.2+4] - 2017-08-16
 
-* Updated README
+* Updated README.
 
 ## [0.4.2+1] - 2017-05-16
 
-* Updated README
+* Updated README.
 
 ## [0.4.2] - 2017-05-15
 
@@ -36,7 +40,7 @@
 
 ## [0.3.3] - 2017-05-05
 
-* Change to buildToolsVersion
+* Change to buildToolsVersion.
 
 ## [0.3.2] - 2017-05-04
 
@@ -56,7 +60,7 @@
 
 ## [0.1.1] - 2017-04-21
 
-* Change to README.md
+* Change to README.md.
 
 ## [0.1.0] - 2017-04-20
 
diff --git a/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m b/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m
index a4ebf94..146db29 100644
--- a/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m
+++ b/packages/url_launcher/ios/Classes/UrlLauncherPlugin.m
@@ -2,56 +2,94 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#import <SafariServices/SafariServices.h>
+
 #import "UrlLauncherPlugin.h"
 
-@implementation UrlLauncherPlugin
-+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
-  FlutterMethodChannel* channel =
-      [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/url_launcher"
-                                  binaryMessenger:registrar.messenger];
-  [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
-    NSString* url = call.arguments;
-    if ([@"canLaunch" isEqualToString:call.method]) {
-      result(@([self canLaunchURL:url]));
-    } else if ([@"launch" isEqualToString:call.method]) {
-      [self launchURL:url result:result];
-    } else {
-      result(FlutterMethodNotImplemented);
-    }
-  }];
+@interface UrlLaunchSession : NSObject<SFSafariViewControllerDelegate>
+@end
+
+@implementation UrlLaunchSession {
+  NSURL *_url;
+  FlutterResult _flutterResult;
 }
 
-+ (BOOL)canLaunchURL:(NSString*)urlString {
-  NSURL* url = [NSURL URLWithString:urlString];
-  UIApplication* application = [UIApplication sharedApplication];
+- (instancetype)initWithUrl:url withFlutterResult:result {
+  self = [super init];
+  if (self) {
+    _url = url;
+    _flutterResult = result;
+  }
+  return self;
+}
+
+- (void)safariViewController:(SFSafariViewController *)controller
+      didCompleteInitialLoad:(BOOL)didLoadSuccessfully {
+  if (didLoadSuccessfully) {
+    _flutterResult(nil);
+  } else {
+    _flutterResult([FlutterError
+        errorWithCode:@"Error"
+              message:[NSString stringWithFormat:@"Error while launching %@", _url]
+              details:nil]);
+  }
+}
+
+- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller {
+  [controller dismissViewControllerAnimated:YES completion:nil];
+  _url = nil;
+  _flutterResult = nil;
+}
+
+@end
+
+@implementation UrlLauncherPlugin {
+  UIViewController *_viewController;
+  UrlLaunchSession *_currentSession;
+}
+
++ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
+  FlutterMethodChannel *channel =
+      [FlutterMethodChannel methodChannelWithName:@"plugins.flutter.io/url_launcher"
+                                  binaryMessenger:registrar.messenger];
+  UIViewController *viewController =
+      [UIApplication sharedApplication].delegate.window.rootViewController;
+  UrlLauncherPlugin *plugin = [[UrlLauncherPlugin alloc] initWithViewController:viewController];
+  [registrar addMethodCallDelegate:plugin channel:channel];
+}
+
+- (instancetype)initWithViewController:(UIViewController *)viewController {
+  self = [super init];
+  if (self) {
+    _viewController = viewController;
+  }
+  return self;
+}
+
+- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
+  NSString *url = call.arguments;
+  if ([@"canLaunch" isEqualToString:call.method]) {
+    result(@([self canLaunchURL:url]));
+  } else if ([@"launch" isEqualToString:call.method]) {
+    [self launchURL:url result:result];
+  } else {
+    result(FlutterMethodNotImplemented);
+  }
+}
+
+- (BOOL)canLaunchURL:(NSString *)urlString {
+  NSURL *url = [NSURL URLWithString:urlString];
+  UIApplication *application = [UIApplication sharedApplication];
   return [application canOpenURL:url];
 }
 
-+ (void)launchURL:(NSString*)urlString result:(FlutterResult)result {
-  NSURL* url = [NSURL URLWithString:urlString];
-  UIApplication* application = [UIApplication sharedApplication];
+- (void)launchURL:(NSString *)urlString result:(FlutterResult)result {
+  NSURL *url = [NSURL URLWithString:urlString];
 
-// Using ifdef as workaround to support running with Xcode 7.0 and sdk version 9
-// where the dynamic check fails.
-#if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_9_0
-  [application openURL:url
-      options:@{}
-      completionHandler:^(BOOL success) {
-        [self sendResult:success result:result url:url];
-      }];
-#else
-  [self sendResult:[application openURL:url] result:result url:url];
-#endif
-}
-
-+ (void)sendResult:(BOOL)success result:(FlutterResult)result url:(NSURL*)url {
-  if (success) {
-    result(nil);
-  } else {
-    result([FlutterError errorWithCode:@"Error"
-                               message:[NSString stringWithFormat:@"Error while launching %@", url]
-                               details:nil]);
-  }
+  SFSafariViewController *safari = [[SFSafariViewController alloc] initWithURL:url];
+  _currentSession = [[UrlLaunchSession alloc] initWithUrl:url withFlutterResult:result];
+  safari.delegate = _currentSession;
+  [_viewController presentViewController:safari animated:YES completion:nil];
 }
 
 @end
diff --git a/packages/url_launcher/pubspec.yaml b/packages/url_launcher/pubspec.yaml
index a6a405e..d67169e 100644
--- a/packages/url_launcher/pubspec.yaml
+++ b/packages/url_launcher/pubspec.yaml
@@ -1,6 +1,6 @@
 name: url_launcher
 
-version: 0.4.2+5
+version: 1.0.0
 description: A Flutter plugin for launching a URL.
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/url_launcher