Teach run-{safari, webkit-app} about iOS Simulator
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jun 2014 17:20:48 +0000 (17:20 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Jun 2014 17:20:48 +0000 (17:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=133986

Reviewed by David Kilzer.

Extract the logic from old-run-webkit-tests to install and launch {DumpRenderTree, WebKitTestRunnerApp}.app
into general-purpose routines in webkitdirs.pm so that they can be used both by script old-run-webkit-tests
and run-safari.

* Scripts/old-run-webkit-tests:
(installAndLaunchDumpToolAppUsingNotification): Extracted logic to install and launch {DumpRenderTree,
WebKitTestRunnerApp}.app into webkitdirs::installAndLaunchIOSWebKitAppInSimulator() and modified code
to call it.
(openIPhoneSimulator): Deleted; moved logic to webkitdirs::openIOSSimulator().
(quitIPhoneSimulator): Deleted; moved logic to webkitdirs::quitIOSSimulator().
* Scripts/run-webkit-app: Modified to call runIOSWebKitApp() when the iOS simulator SDK is used
(say, by specifying the optional command-line argument --simulator). For now, die() with an error
when the iOS device SDK is used as we don't support launching an app on the device at this time.
* Scripts/webkitdirs.pm:
(xcodeSDKVersion): Added.
(setupIOSWebKitEnvironment): Added.
(installedMobileSafariBundle): Added.
(mobileSafariBundle): Added.
(plistPathFromBundle): Added.
(appIdentiferFromBundle): Added.
(appDisplayNameFromBundle): Added.
(loadIPhoneSimulatorNotificationIfNeeded): Added.
(openIOSSimulator): Added.
(quitIOSSimulator): Added.
(iosSimulatorDeviceByName): Added.
(iosSimulatorRuntime): Added.
(findOrCreateSimulatorForIOSDevice): Added.
(runIOSWebKitAppInSimulator): Added.
(installAndLaunchIOSWebKitAppInSimulator): Added.
(runIOSWebKitApp): Added.
(runSafari): Modified to call runIOSWebKitAppInSimulator() the iOS simulator SDK is used. For now,
die() with an error when the iOS device SDK is used as we don't support launching Safari on the
device at this time.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@170189 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/old-run-webkit-tests
Tools/Scripts/run-webkit-app
Tools/Scripts/webkitdirs.pm

index 40e9361..38295de 100644 (file)
@@ -1,3 +1,44 @@
+2014-06-20  Daniel Bates  <dabates@apple.com>
+
+        Teach run-{safari, webkit-app} about iOS Simulator
+        https://bugs.webkit.org/show_bug.cgi?id=133986
+
+        Reviewed by David Kilzer.
+
+        Extract the logic from old-run-webkit-tests to install and launch {DumpRenderTree, WebKitTestRunnerApp}.app
+        into general-purpose routines in webkitdirs.pm so that they can be used both by script old-run-webkit-tests
+        and run-safari.
+
+        * Scripts/old-run-webkit-tests:
+        (installAndLaunchDumpToolAppUsingNotification): Extracted logic to install and launch {DumpRenderTree,
+        WebKitTestRunnerApp}.app into webkitdirs::installAndLaunchIOSWebKitAppInSimulator() and modified code
+        to call it.
+        (openIPhoneSimulator): Deleted; moved logic to webkitdirs::openIOSSimulator().
+        (quitIPhoneSimulator): Deleted; moved logic to webkitdirs::quitIOSSimulator().
+        * Scripts/run-webkit-app: Modified to call runIOSWebKitApp() when the iOS simulator SDK is used
+        (say, by specifying the optional command-line argument --simulator). For now, die() with an error
+        when the iOS device SDK is used as we don't support launching an app on the device at this time.
+        * Scripts/webkitdirs.pm:
+        (xcodeSDKVersion): Added.
+        (setupIOSWebKitEnvironment): Added.
+        (installedMobileSafariBundle): Added.
+        (mobileSafariBundle): Added.
+        (plistPathFromBundle): Added.
+        (appIdentiferFromBundle): Added.
+        (appDisplayNameFromBundle): Added.
+        (loadIPhoneSimulatorNotificationIfNeeded): Added.
+        (openIOSSimulator): Added.
+        (quitIOSSimulator): Added.
+        (iosSimulatorDeviceByName): Added.
+        (iosSimulatorRuntime): Added.
+        (findOrCreateSimulatorForIOSDevice): Added.
+        (runIOSWebKitAppInSimulator): Added.
+        (installAndLaunchIOSWebKitAppInSimulator): Added.
+        (runIOSWebKitApp): Added.
+        (runSafari): Modified to call runIOSWebKitAppInSimulator() the iOS simulator SDK is used. For now,
+        die() with an error when the iOS device SDK is used as we don't support launching Safari on the
+        device at this time.
+
 2014-06-19  Anders Carlsson  <andersca@apple.com>
 
         Add WTF::Optional class
index b071467..8be1b10 100755 (executable)
@@ -128,9 +128,7 @@ sub toWindowsPath($);
 sub validateSkippedArg($$;$);
 sub writeToFile($$);
 sub installAndLaunchDumpToolAppUsingNotification($$);
-sub openIPhoneSimulator();
 sub quitDumpToolUsingNotification();
-sub quitIPhoneSimulator();
 sub simulatorSessionUUID();
 
 # Argument handling
@@ -460,7 +458,7 @@ setConfigurationProductDir(Cwd::abs_path($root)) if (defined($root));
 my $productDir = productDir();
 $productDir .= "/Programs" if isGtk();
 
-quitIPhoneSimulator() if isIOSWebKit();
+quitIOSSimulator() if isIOSWebKit();
 
 # Save the current directory before chaging it via chdirWebKit
 my $currentDir = cwd();
@@ -503,7 +501,7 @@ if (isAppleMacWebKit()) {
     eval 'use DumpRenderTreeSupport;';
 }
 
-openIPhoneSimulator() if isIOSWebKit();
+openIOSSimulator() if isIOSWebKit();
 
 if (isAppleMacWebKit()) {
     push @INC, $productDir;
@@ -1164,7 +1162,7 @@ printf "\n%0.2fs total testing time\n", $totalTestingTime . "";
 
 !$isDumpToolOpen || die "Failed to close $dumpToolName.\n";
 
-quitIPhoneSimulator() if isIOSWebKit();
+quitIOSSimulator() if isIOSWebKit();
 
 $isHttpdOpen = !closeHTTPD();
 closeWebSocketServer();
@@ -1362,103 +1360,17 @@ sub writeToFile($$)
 sub installAndLaunchDumpToolAppUsingNotification($$)
 {
     my ($args, $cleanEnv) = @_;
-
-    my $iPhoneSimulatorNotification = new IPhoneSimulatorNotification;
-    $iPhoneSimulatorNotification->startObservingApplicationLaunchedNotification();
-
-    my $makeNSDictionaryFromHash = sub {
-        my ($dict) = @_;
-        my $result = NSMutableDictionary->alloc()->initWithCapacity_(scalar(keys %{$dict}));
-        for my $key (keys %{$dict}) {
-            $result->setObject_forKey_(NSString->stringWithCString_($dict->{$key}), NSString->stringWithCString_($key));
-        }
-        return $result->autorelease();
-    };
-
-    my $makeNSArrayFromArray = sub {
-        my ($array) = @_;
-        my $result = NSMutableArray->alloc()->initWithCapacity_(scalar(@{$array}));
-        for my $item (@{$array}) {
-            $result->addObject_(NSString->stringWithCString_($item));
-        }
-        return $result->autorelease();
-    };
-
-    my $deviceName = "iPhone 5 WebKit Tester";
-    my $deviceType = "com.apple.CoreSimulator.SimDeviceType.iPhone-5";
-
-    if (architecture() eq 'x86_64') {
-        $deviceName = "iPhone 5s WebKit Tester";
-        $deviceType = "com.apple.CoreSimulator.SimDeviceType.iPhone-5s";
-    }
-
-    chomp(my $sdkVersion = `xcrun --sdk iphonesimulator --show-sdk-version`);
-    $sdkVersion =~ s/\./-/;
-
-    my $runtime = "com.apple.CoreSimulator.SimRuntime.iOS-$sdkVersion";
-
-    my @devices = iOSSimulatorDevices();
-    my $device = (grep {
-        $_->{name} eq $deviceName and $_->{runtime} eq $runtime and $_->{deviceType} eq $deviceType;
-    } @devices)[0];
-
-    if (not $device) {
-        print "Creating simulator device: $deviceName\n";
-        $device = createiOSSimulatorDevice($deviceName, $deviceType, $runtime);
-    } else {
-        print "Found simulator device with properties: " . Dumper($device);
-    }
-
-    my $identifier = iOSDumpToolAppIdentifier();
-    my $applicationPath;
-
+    my $productDir = productDir();
+    my $appBundle;
     if ($useWebKitTestRunner) {
-        $applicationPath = "$productDir/WebKitTestRunnerApp.app";
+        $appBundle = "$productDir/WebKitTestRunnerApp.app";
     } else {
-        $applicationPath = "$productDir/DumpRenderTree.app";
+        $appBundle = "$productDir/DumpRenderTree.app";
     }
-
-    my $dict = {
-        applicationArguments => &$makeNSArrayFromArray($args),
-        applicationEnvironment => &$makeNSDictionaryFromHash($cleanEnv),
-        applicationIdentifier => NSString->stringWithCString_($identifier),
-        applicationPath => NSString->stringWithCString_($applicationPath),
-        deviceUDID => NSString->stringWithCString_($device->{UDID}),
-        sessionUUID => NSString->stringWithCString_(simulatorSessionUUID()),
-    };
-    $iPhoneSimulatorNotification->postStartSessionNotification($dict);
-
-    while (!$iPhoneSimulatorNotification->hasReceivedApplicationLaunchedNotification()) {
-        my $date = NSDate->alloc()->initWithTimeIntervalSinceNow_(0.1);
-        NSRunLoop->currentRunLoop->runUntilDate_($date);
-        $date->release();
-    }
-
-    print "$identifier has launched.\n";
-
-    $iPhoneSimulatorNotification->stopObservingApplicationLaunchedNotification();
-
-    return $iPhoneSimulatorNotification->applicationLaunchedApplicationPID();
-}
-
-sub openIPhoneSimulator()
-{
-    my $iPhoneSimulatorNotification = new IPhoneSimulatorNotification;
-    $iPhoneSimulatorNotification->startObservingReadyNotification();
-
-    my $deviceName = architecture() eq 'i386' ? "iPhone 5" : "iPhone 5s";
-
-    system "open", "-a", $simulatorApp, "--args", "-SessionOnLaunch", "NO", "-SimulateDevice", $deviceName;
-
-    die $! if exitStatus($?);
-
-    while (!$iPhoneSimulatorNotification->hasReceivedReadyNotification()) {
-        my $date = NSDate->alloc()->initWithTimeIntervalSinceNow_(0.1);
-        NSRunLoop->currentRunLoop->runUntilDate_($date);
-        $date->release();
-    }
-
-    $iPhoneSimulatorNotification->stopObservingReadyNotification();
+    my $simulatorOptions = {applicationArguments => $args, applicationEnvironment => $cleanEnv, sessionUUID => simulatorSessionUUID()};
+    my $pid = installAndLaunchIOSWebKitAppInSimulator($appBundle, findOrCreateSimulatorForIOSDevice("WebKit Tester"), $simulatorOptions);
+    print appDisplayNameFromBundle($appBundle) . " has launched.\n";
+    return $pid;
 }
 
 sub quitDumpToolUsingNotification()
@@ -1488,11 +1400,6 @@ sub quitDumpToolUsingNotification()
     $iPhoneSimulatorNotification->stopObservingApplicationQuitNotification();
 }
 
-sub quitIPhoneSimulator()
-{
-    system "osascript", "-e", "tell application \"iOS Simulator\" to quit";
-}
-
 sub simulatorSessionUUID()
 {
     return "theAwesomeUniqueSessionIdentifierForDumpRenderTree";
index ef98f6a..f275b9b 100755 (executable)
@@ -43,4 +43,7 @@ die "Did not specify an application to open (e.g. run-webkit-app AppName).\n" un
 checkFrameworks();
 
 my $appPath = shift(@ARGV);
+if (isIOSWebKit()) {
+    exit exitStatus(runIOSWebKitApp($appPath));
+}
 exit exitStatus(runMacWebKitApp($appPath, USE_OPEN_COMMAND));
index 3e5bc6e..a323707 100755 (executable)
@@ -52,6 +52,7 @@ BEGIN {
        &XcodeOptionString
        &XcodeOptionStringNoConfig
        &XcodeOptions
+       &appDisplayNameFromBundle
        &baseProductDir
        &chdirWebKit
        &checkFrameworks
@@ -59,10 +60,16 @@ BEGIN {
        &cmakeBasedPortName
        &currentSVNRevision
        &debugSafari
+       &findOrCreateSimulatorForIOSDevice
+       &installAndLaunchIOSWebKitAppInSimulator
+       &iosSimulatorDeviceByName
        &nmPath
+       &openIOSSimulator
        &passedConfiguration
        &printHelpAndExitForRunAndDebugWebKitAppIfNeeded
        &productDir
+       &quitIOSSimulator
+       &runIOSWebKitApp
        &runMacWebKitApp
        &safariPath
        &setConfiguration
@@ -93,6 +100,7 @@ my $sourceDir;
 my $currentSVNRevision;
 my $debugger;
 my $iPhoneSimulatorVersion;
+my $didLoadIPhoneSimulatorNotification;
 my $nmPath;
 my $osXVersion;
 my $generateDsym;
@@ -437,6 +445,17 @@ sub XcodeSDKPath
     return $sdkPath;
 }
 
+sub xcodeSDKVersion
+{
+    determineXcodeSDK();
+
+    die "Can't find the SDK version because no Xcode SDK was specified" if !$xcodeSDK;
+
+    chomp(my $sdkVersion = `xcrun --sdk $xcodeSDK --show-sdk-version`);
+    die "Failed to get SDK version from xcrun" if exitStatus($?);
+
+    return $sdkVersion;
+}
 
 sub programFilesPath
 {
@@ -2116,6 +2135,229 @@ sub setupMacWebKitEnvironment($)
     setUpGuardMallocIfNeeded();
 }
 
+sub setupIOSWebKitEnvironment($)
+{
+    my ($dyldFrameworkPath) = @_;
+    $dyldFrameworkPath = File::Spec->rel2abs($dyldFrameworkPath);
+
+    $ENV{DYLD_FRAMEWORK_PATH} = $dyldFrameworkPath;
+    $ENV{DYLD_LIBRARY_PATH} = $dyldFrameworkPath;
+
+    setUpGuardMallocIfNeeded();
+}
+
+sub installedMobileSafariBundle()
+{
+    return File::Spec->catfile(XcodeSDKPath(), "Applications", "MobileSafari.app");
+}
+
+sub mobileSafariBundle()
+{
+    determineConfigurationProductDir();
+
+    # Use MobileSafari.app in product directory if present.
+    if (isAppleMacWebKit() && -d "$configurationProductDir/MobileSafari.app") {
+        return "$configurationProductDir/MobileSafari.app";
+    }
+    return installedMobileSafariBundle();
+}
+
+sub plistPathFromBundle($)
+{
+    my ($appBundle) = @_;
+    return "$appBundle/Info.plist" if -f "$appBundle/Info.plist"; # iOS app bundle
+    return "$appBundle/Contents/Info.plist" if "$appBundle/Contents/Info.plist"; # Mac app bundle
+    return "";
+}
+
+sub appIdentiferFromBundle($)
+{
+    my ($appBundle) = @_;
+    my $plistPath = plistPathFromBundle($appBundle);
+    chomp(my $bundleIdentifer = `defaults read '$plistPath' CFBundleIdentifier 2> /dev/null`);
+    return $bundleIdentifer;
+}
+
+sub appDisplayNameFromBundle($)
+{
+    my ($appBundle) = @_;
+    my $plistPath = plistPathFromBundle($appBundle);
+    chomp(my $bundleDisplayName = `defaults read '$plistPath' CFBundleDisplayName 2> /dev/null`);
+    return $bundleDisplayName;
+}
+
+sub loadIPhoneSimulatorNotificationIfNeeded()
+{
+    return if $didLoadIPhoneSimulatorNotification;
+    push(@INC, productDir() . "/lib/perl5/darwin-thread-multi-2level");
+    require IPhoneSimulatorNotification;
+    $didLoadIPhoneSimulatorNotification = 1;
+}
+
+sub openIOSSimulator()
+{
+    chomp(my $developerDirectory = $ENV{DEVELOPER_DIR} || `xcode-select --print-path`);
+    my $iosSimulatorPath = File::Spec->catfile($developerDirectory, "Applications", "iOS Simulator.app");
+
+    loadIPhoneSimulatorNotificationIfNeeded();
+
+    my $iPhoneSimulatorNotification = new IPhoneSimulatorNotification;
+    $iPhoneSimulatorNotification->startObservingReadyNotification();
+    system("open", "-a", $iosSimulatorPath, "--args", "-SessionOnLaunch", "NO") == 0 or die "Failed to open $iosSimulatorPath: $!";
+    while (!$iPhoneSimulatorNotification->hasReceivedReadyNotification()) {
+        my $date = NSDate->alloc()->initWithTimeIntervalSinceNow_(0.1);
+        NSRunLoop->currentRunLoop->runUntilDate_($date);
+        $date->release();
+    }
+    $iPhoneSimulatorNotification->stopObservingReadyNotification();
+}
+
+sub quitIOSSimulator()
+{
+    return system {"osascript"} "osascript", "-e", 'tell application "iOS Simulator" to quit';
+}
+
+sub iosSimulatorDeviceByName($)
+{
+    my ($simulatorName) = @_;
+    my @devices = grep {$_->{name} eq $simulatorName} iOSSimulatorDevices();
+    my $deviceToUse = $devices[0];
+    if (@devices > 1) {
+        print "Warning: Found more than one simulator device named '$simulatorName'.\n";
+        print "         Using simulator device with UDID: $deviceToUse->{UDID}.\n";
+        print "         To see the list of simulator devices, run:\n";
+        print "         xcrun --sdk iphonesimulator simctl list\n";
+    }
+    return $deviceToUse;
+}
+
+sub iosSimulatorRuntime()
+{
+    my $xcodeSDKVersion = xcodeSDKVersion();
+    $xcodeSDKVersion =~ s/\./-/;
+    return "com.apple.CoreSimulator.SimRuntime.iOS-$xcodeSDKVersion";
+}
+
+sub findOrCreateSimulatorForIOSDevice($)
+{
+    my ($simulatorNameSuffix) = @_;
+    my $simulatorName;
+    my $simulatorDeviceType;
+    if (architecture() eq "x86_64") {
+        $simulatorName = "iPhone 5s " . $simulatorNameSuffix;
+        $simulatorDeviceType = "com.apple.CoreSimulator.SimDeviceType.iPhone-5s";
+    } else {
+        $simulatorName = "iPhone 5 " . $simulatorNameSuffix;
+        $simulatorDeviceType = "com.apple.CoreSimulator.SimDeviceType.iPhone-5";
+    }
+    my $simulatedDevice = iosSimulatorDeviceByName($simulatorName);
+    return $simulatedDevice if $simulatedDevice;
+    return createiOSSimulatorDevice($simulatorName, $simulatorDeviceType, iosSimulatorRuntime());
+}
+
+sub runIOSWebKitAppInSimulator($;$)
+{
+    my ($appBundle, $simulatorOptions) = @_;
+    my $productDir = productDir();
+    my $appDisplayName = appDisplayNameFromBundle($appBundle);
+    print "Starting $appDisplayName with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
+
+    $simulatorOptions = {} unless $simulatorOptions;
+
+    my %simulatorENV;
+    %simulatorENV = %{$simulatorOptions->{applicationEnvironment}} if $simulatorOptions->{applicationEnvironment};
+    {
+        local %ENV; # Shadow global-scope %ENV so that changes to it will not be seen outside of this scope.
+        setupIOSWebKitEnvironment($productDir);
+        %simulatorENV = %ENV;
+    }
+    $simulatorOptions->{applicationEnvironment} = \%simulatorENV;
+    return installAndLaunchIOSWebKitAppInSimulator($appBundle, findOrCreateSimulatorForIOSDevice("For WebKit Development"), $simulatorOptions) <= 0;
+}
+
+# Launches the iOS WebKit-based application in the specified simulator device and dynamically
+# linked against the built WebKit. The application will be installed if applicable.
+#
+# Args:
+#   $appBundle: the path to the app bundle to launch.
+#   $simulatedDevice: the simulator device to use to run the app.
+#   $simulatorOptions: a hash reference representing optional simulator options.
+#     sessionUUID: a unique identifer to use for the iOS Simulator session. Defaults to an identifer
+#                  of the form "theAwesomeUniqueSessionIdentifierForX" where X is the display name of
+#                  the specified app.
+#     applicationArguments: an array reference representing the arguments to pass to the app (defaults to \@ARGV).
+#     applicationEnvironment: a hash reference representing the environment variables to use when launching the app (defaults to {}).
+#
+# Returns the process identifier of the launched app.
+sub installAndLaunchIOSWebKitAppInSimulator($$;$)
+{
+    my ($appBundle, $simulatedDevice, $simulatorOptions) = @_;
+
+    loadIPhoneSimulatorNotificationIfNeeded();
+
+    my $makeNSDictionaryFromHash = sub {
+        my ($dict) = @_;
+        my $result = NSMutableDictionary->alloc()->initWithCapacity_(scalar(keys %{$dict}));
+        for my $key (keys %{$dict}) {
+            $result->setObject_forKey_(NSString->stringWithCString_($dict->{$key}), NSString->stringWithCString_($key));
+        }
+        return $result->autorelease();
+    };
+    my $makeNSArrayFromArray = sub {
+        my ($array) = @_;
+        my $result = NSMutableArray->alloc()->initWithCapacity_(scalar(@{$array}));
+        for my $item (@{$array}) {
+            $result->addObject_(NSString->stringWithCString_($item));
+        }
+        return $result->autorelease();
+    };
+
+    my $simulatorENVHashRef = {};
+    $simulatorENVHashRef = $simulatorOptions->{applicationEnvironment} if $simulatorOptions && $simulatorOptions->{applicationEnvironment};
+    my $applicationArguments = \@ARGV;
+    $applicationArguments = $simulatorOptions->{applicationArguments} if $simulatorOptions && $simulatorOptions->{applicationArguments};
+    my $sessionUUID;
+    if ($simulatorOptions && $simulatorOptions->{sessionUUID}) {
+        $sessionUUID = $simulatorOptions->{sessionUUID};
+    } else {
+        $sessionUUID = "theAwesomeUniqueSessionIdentifierFor" . appDisplayNameFromBundle($appBundle);
+    }
+    # FIXME: We should have the iOS application adopt the files descriptors for our standard output and error streams.
+    my $sessionInfo = {
+        applicationArguments => &$makeNSArrayFromArray($applicationArguments),
+        applicationEnvironment => &$makeNSDictionaryFromHash($simulatorENVHashRef),
+        applicationIdentifier => NSString->stringWithCString_(appIdentiferFromBundle($appBundle)),
+        applicationPath => NSString->stringWithCString_($appBundle),
+        deviceUDID => NSString->stringWithCString_($simulatedDevice->{UDID}),
+        sessionUUID => NSString->stringWithCString_($sessionUUID),
+    };
+
+    openIOSSimulator();
+
+    my $iPhoneSimulatorNotification = new IPhoneSimulatorNotification;
+    $iPhoneSimulatorNotification->startObservingApplicationLaunchedNotification();
+    $iPhoneSimulatorNotification->postStartSessionNotification($sessionInfo);
+    while (!$iPhoneSimulatorNotification->hasReceivedApplicationLaunchedNotification()) {
+        my $date = NSDate->alloc()->initWithTimeIntervalSinceNow_(0.1);
+        NSRunLoop->currentRunLoop->runUntilDate_($date);
+        $date->release();
+    }
+    $iPhoneSimulatorNotification->stopObservingApplicationLaunchedNotification();
+    return $iPhoneSimulatorNotification->applicationLaunchedApplicationPID();
+}
+
+sub runIOSWebKitApp($)
+{
+    my ($appBundle) = @_;
+    if (willUseIOSDeviceSDKWhenBuilding()) {
+        die "Only running Safari in iOS Simulator is supported now.";
+    }
+    if (willUseIOSSimulatorSDKWhenBuilding()) {
+        return runIOSWebKitAppInSimulator($appBundle);
+    }
+    die "Not using an iOS SDK."
+}
+
 sub runMacWebKitApp($;$)
 {
     my ($appPath, $useOpenCommand) = @_;
@@ -2189,6 +2431,9 @@ sub debugSafari
 
 sub runSafari
 {
+    if (isIOSWebKit()) {
+        return runIOSWebKitApp(mobileSafariBundle());
+    }
 
     if (isAppleMacWebKit()) {
         return runMacWebKitApp(safariPath());