Modified: trunk/Tools/Scripts/webkitdirs.pm (178600 => 178601)
--- trunk/Tools/Scripts/webkitdirs.pm 2015-01-16 21:42:50 UTC (rev 178600)
+++ trunk/Tools/Scripts/webkitdirs.pm 2015-01-16 21:58:28 UTC (rev 178601)
@@ -33,6 +33,7 @@
use version;
use warnings;
use Config;
+use Cwd qw(realpath);
use Digest::MD5 qw(md5_hex);
use FindBin;
use File::Basename;
@@ -63,7 +64,6 @@
¤tSVNRevision
&debugSafari
&findOrCreateSimulatorForIOSDevice
- &installAndLaunchIOSWebKitAppInSimulator
&iosSimulatorDeviceByName
&nmPath
&openIOSSimulator
@@ -86,6 +86,7 @@
use constant USE_OPEN_COMMAND => 1; # Used in runMacWebKitApp().
use constant INCLUDE_OPTIONS_FOR_DEBUGGING => 1;
+use constant SIMULATOR_DEVICE_STATE_BOOTED => "3";
our @EXPORT_OK;
@@ -1178,12 +1179,23 @@
die "Device $name $deviceTypeId $runtimeId wasn't found in " . iOSSimulatorDevicesPath();
}
-sub deleteiOSSimulatorDevice
+sub eraseIOSSimulatorDevice($)
{
my $udid = shift;
- return system("xcrun", "--sdk", "iphonesimulator", "simctl", "delete", $udid);
+ return exitStatus(system("xcrun", "--sdk", "iphonesimulator", "simctl", "erase", $udid)) == 0;
}
+sub bootedIOSSimulatorDevice()
+{
+ my @devices = iOSSimulatorDevices();
+ for my $device (@devices) {
+ if ($device->{state} eq SIMULATOR_DEVICE_STATE_BOOTED) {
+ return $device;
+ }
+ }
+ return undef;
+}
+
sub willUseIOSDeviceSDKWhenBuilding()
{
return xcodeSDKPlatformName() eq "iphoneos";
@@ -2026,9 +2038,14 @@
setUpGuardMallocIfNeeded();
}
+sub iosSimulatorApplicationsPath()
+{
+ return File::Spec->catdir(XcodeSDKPath(), "Applications");
+}
+
sub installedMobileSafariBundle()
{
- return File::Spec->catfile(XcodeSDKPath(), "Applications", "MobileSafari.app");
+ return File::Spec->catfile(iosSimulatorApplicationsPath(), "MobileSafari.app");
}
sub mobileSafariBundle()
@@ -2066,44 +2083,36 @@
return $bundleDisplayName;
}
-sub loadIPhoneSimulatorNotificationIfNeeded()
+sub openIOSSimulator($)
{
- return if $didLoadIPhoneSimulatorNotification;
- push(@INC, productDir() . "/lib/perl5/darwin-thread-multi-2level");
- require IPhoneSimulatorNotification;
- $didLoadIPhoneSimulatorNotification = 1;
-}
-
-sub openIOSSimulator()
-{
+ my ($simulatedDevice) = @_;
chomp(my $developerDirectory = $ENV{DEVELOPER_DIR} || `xcode-select --print-path`);
my $iosSimulatorPath = File::Spec->catfile($developerDirectory, "Applications", "iOS Simulator.app");
- loadIPhoneSimulatorNotificationIfNeeded();
+ system("open", "-a", $iosSimulatorPath, "--args", "-CurrentDeviceUDID", $simulatedDevice->{UDID}) == 0 or die "Failed to open $iosSimulatorPath: $!";
+ my $device;
+ do {
+ $device = iosSimulatorDeviceByName($simulatedDevice->{name});
+ sleep(2);
+ } while ($device->{state} ne SIMULATOR_DEVICE_STATE_BOOTED);
+}
- 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";
+ my $simulatorRuntime = iosSimulatorRuntime();
+ my @devices = iOSSimulatorDevices();
+ for my $device (@devices) {
+ if ($device->{name} eq $simulatorName && $device->{runtime} eq $simulatorRuntime) {
+ return $device;
+ }
}
- return $deviceToUse;
+ return undef;
}
sub iosSimulatorRuntime()
@@ -2130,13 +2139,26 @@
return createiOSSimulatorDevice($simulatorName, $simulatorDeviceType, iosSimulatorRuntime());
}
+sub isIOSSimulatorSystemInstalledApp($)
+{
+ my ($appBundle) = @_;
+ my $simulatorApplicationsPath = iosSimulatorApplicationsPath();
+ return substr(realpath($appBundle), 0, length($simulatorApplicationsPath)) eq $simulatorApplicationsPath;
+}
+
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";
+ my $appDisplayName = appDisplayNameFromBundle($appBundle);;
+ my $simulatedDevice = findOrCreateSimulatorForIOSDevice("For WebKit Development");
+ my $bootedSimulatorDevice = bootedIOSSimulatorDevice();
+ if (!$bootedSimulatorDevice || $bootedSimulatorDevice->{UDID} ne $simulatedDevice->{UDID}) {
+ quitIOSSimulator();
+ openIOSSimulator($simulatedDevice);
+ }
+
$simulatorOptions = {} unless $simulatorOptions;
my %simulatorENV;
@@ -2146,79 +2168,23 @@
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 identifier to use for the iOS Simulator session. Defaults to an identifier
-# 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);
+
+ # Prefix the environment variables with SIMCTL_CHILD_ per `xcrun simctl help launch`.
+ foreach my $key (keys %simulatorENV) {
+ $ENV{"SIMCTL_CHILD_$key"} = $simulatorENV{$key};
}
- # 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_(appIdentifierFromBundle($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();
+ # FIXME: We should also erase the iOS Simulator device when alternating between running a
+ # custom-built MobileSafari and the system-installed MobileSafari.
+ if (!isIOSSimulatorSystemInstalledApp($appBundle)) {
+ eraseIOSSimulatorDevice($simulatedDevice->{UDID}) or die;
}
- $iPhoneSimulatorNotification->stopObservingApplicationLaunchedNotification();
- return $iPhoneSimulatorNotification->applicationLaunchedApplicationPID();
+
+ my $appIdentifier = appIdentifierFromBundle($appBundle);
+ print "Starting $appDisplayName with DYLD_FRAMEWORK_PATH set to point to built WebKit in $productDir.\n";
+ return exitStatus(system("xcrun", "--sdk", "iphonesimulator", "simctl", "launch", $simulatedDevice->{UDID}, $appIdentifier, @$applicationArguments));
}
sub runIOSWebKitApp($)