OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import <Foundation/Foundation.h> | 5 #import <Foundation/Foundation.h> |
6 #include <asl.h> | 6 #include <asl.h> |
7 #include <libgen.h> | 7 #include <libgen.h> |
8 #include <stdarg.h> | 8 #include <stdarg.h> |
9 #include <stdio.h> | 9 #include <stdio.h> |
10 | 10 |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 // Creates the necessary directory structure under the given user home directory | 444 // Creates the necessary directory structure under the given user home directory |
445 // path. | 445 // path. |
446 // Returns YES if successful, NO if unable to create the directories. | 446 // Returns YES if successful, NO if unable to create the directories. |
447 BOOL CreateHomeDirSubDirs(NSString* userHomePath) { | 447 BOOL CreateHomeDirSubDirs(NSString* userHomePath) { |
448 NSFileManager* fileManager = [NSFileManager defaultManager]; | 448 NSFileManager* fileManager = [NSFileManager defaultManager]; |
449 | 449 |
450 // Create user home and subdirectories. | 450 // Create user home and subdirectories. |
451 NSArray* subDirsToCreate = [NSArray arrayWithObjects: | 451 NSArray* subDirsToCreate = [NSArray arrayWithObjects: |
452 @"Documents", | 452 @"Documents", |
453 @"Library/Caches", | 453 @"Library/Caches", |
| 454 @"Library/Preferences", |
454 nil]; | 455 nil]; |
455 for (NSString* subDir in subDirsToCreate) { | 456 for (NSString* subDir in subDirsToCreate) { |
456 NSString* path = [userHomePath stringByAppendingPathComponent:subDir]; | 457 NSString* path = [userHomePath stringByAppendingPathComponent:subDir]; |
457 NSError* error; | 458 NSError* error; |
458 if (![fileManager createDirectoryAtPath:path | 459 if (![fileManager createDirectoryAtPath:path |
459 withIntermediateDirectories:YES | 460 withIntermediateDirectories:YES |
460 attributes:nil | 461 attributes:nil |
461 error:&error]) { | 462 error:&error]) { |
462 LogError(@"Unable to create directory: %@. Error: %@", | 463 LogError(@"Unable to create directory: %@. Error: %@", |
463 path, [error localizedDescription]); | 464 path, [error localizedDescription]); |
464 return NO; | 465 return NO; |
465 } | 466 } |
466 } | 467 } |
467 | 468 |
468 return YES; | 469 return YES; |
469 } | 470 } |
470 | 471 |
471 // Creates the necessary directory structure under the given user home directory | 472 // Creates the necessary directory structure under the given user home directory |
472 // path, then sets the path in the appropriate environment variable. | 473 // path, then sets the path in the appropriate environment variable. |
473 // Returns YES if successful, NO if unable to create or initialize the given | 474 // Returns YES if successful, NO if unable to create or initialize the given |
474 // directory. | 475 // directory. |
475 BOOL InitializeSimulatorUserHome(NSString* userHomePath) { | 476 BOOL InitializeSimulatorUserHome(NSString* userHomePath, NSString* deviceName) { |
476 if (!CreateHomeDirSubDirs(userHomePath)) | 477 if (!CreateHomeDirSubDirs(userHomePath)) |
477 return NO; | 478 return NO; |
478 | 479 |
| 480 // Set the device to simulate. Note that the iOS Simulator must not be running |
| 481 // for this setting to take effect. |
| 482 NSMutableDictionary* plistDict = |
| 483 [NSMutableDictionary dictionaryWithObject:deviceName |
| 484 forKey:@"SimulateDevice"]; |
| 485 NSString* plistPath = @"Library/Preferences/com.apple.iphonesimulator.plist"; |
| 486 [plistDict writeToFile:[userHomePath stringByAppendingPathComponent:plistPath] |
| 487 atomically:YES]; |
| 488 |
479 // Update the environment to use the specified directory as the user home | 489 // Update the environment to use the specified directory as the user home |
480 // directory. | 490 // directory. |
481 // Note: the third param of setenv specifies whether or not to overwrite the | 491 // Note: the third param of setenv specifies whether or not to overwrite the |
482 // variable's value if it has already been set. | 492 // variable's value if it has already been set. |
483 if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) || | 493 if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) || |
484 (setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) { | 494 (setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) { |
485 LogError(@"Unable to set environment variables for home directory."); | 495 LogError(@"Unable to set environment variables for home directory."); |
486 return NO; | 496 return NO; |
487 } | 497 } |
488 | 498 |
489 return YES; | 499 return YES; |
490 } | 500 } |
491 | 501 |
| 502 // Performs a case-insensitive search to see if |stringToSearch| begins with |
| 503 // |prefixToFind|. Returns true if a match is found. |
| 504 BOOL CaseInsensitivePrefixSearch(NSString* stringToSearch, |
| 505 NSString* prefixToFind) { |
| 506 NSStringCompareOptions options = (NSAnchoredSearch | NSCaseInsensitiveSearch); |
| 507 NSRange range = [stringToSearch rangeOfString:prefixToFind |
| 508 options:options]; |
| 509 return range.location != 0; |
| 510 } |
| 511 |
492 // Prints the usage information to stderr. | 512 // Prints the usage information to stderr. |
493 void PrintUsage() { | 513 void PrintUsage() { |
494 fprintf(stderr, "Usage: iossim [-d device] [-s sdkVersion] [-u homeDir] " | 514 fprintf(stderr, "Usage: iossim [-d device] [-s sdkVersion] [-u homeDir] " |
495 "[-e envKey=value]* [-t startupTimeout] <appPath> [<appArgs>]\n" | 515 "[-e envKey=value]* [-t startupTimeout] <appPath> [<appArgs>]\n" |
496 " where <appPath> is the path to the .app directory and appArgs are any" | 516 " where <appPath> is the path to the .app directory and appArgs are any" |
497 " arguments to send the simulated app.\n" | 517 " arguments to send the simulated app.\n" |
498 "\n" | 518 "\n" |
499 "Options:\n" | 519 "Options:\n" |
500 " -d Specifies the device (either 'iPhone' or 'iPad')." | 520 " -d Specifies the device (must be one of the values from the iOS" |
501 " Defaults to 'iPhone'.\n" | 521 " Simulator's Hardware -> Device menu. Defaults to 'iPhone'.\n" |
502 " -s Specifies the SDK version to use (e.g '4.3')." | 522 " -s Specifies the SDK version to use (e.g '4.3')." |
503 " Will use system default if not specified.\n" | 523 " Will use system default if not specified.\n" |
504 " -u Specifies a user home directory for the simulator." | 524 " -u Specifies a user home directory for the simulator." |
505 " Will create a new directory if not specified.\n" | 525 " Will create a new directory if not specified.\n" |
506 " -e Specifies an environment key=value pair that will be" | 526 " -e Specifies an environment key=value pair that will be" |
507 " set in the simulated application's environment.\n" | 527 " set in the simulated application's environment.\n" |
508 " -t Specifies the session startup timeout (in seconds)." | 528 " -t Specifies the session startup timeout (in seconds)." |
509 " Defaults to %d.\n", | 529 " Defaults to %d.\n", |
510 static_cast<int>(kDefaultSessionStartTimeoutSeconds)); | 530 static_cast<int>(kDefaultSessionStartTimeoutSeconds)); |
511 } | 531 } |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 if (!systemRoot) { | 643 if (!systemRoot) { |
624 LogError(@"Invalid SDK version: %@", sdkVersion); | 644 LogError(@"Invalid SDK version: %@", sdkVersion); |
625 exit(EXIT_FAILURE); | 645 exit(EXIT_FAILURE); |
626 } | 646 } |
627 | 647 |
628 // Get the paths for stdout and stderr so the simulated app's output will show | 648 // Get the paths for stdout and stderr so the simulated app's output will show |
629 // up in the caller's stdout/stderr. | 649 // up in the caller's stdout/stderr. |
630 NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX"); | 650 NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX"); |
631 NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"]; | 651 NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"]; |
632 | 652 |
633 // Make sure the device name is legit. | 653 // Determine the deviceFamily based on the deviceName |
634 NSNumber* deviceFamily = nil; | 654 NSNumber* deviceFamily = nil; |
635 if (!deviceName || | 655 if (!deviceName || CaseInsensitivePrefixSearch(deviceName, @"iPhone")) { |
636 [@"iPhone" caseInsensitiveCompare:deviceName] == NSOrderedSame) { | |
637 deviceFamily = [NSNumber numberWithInt:kIPhoneFamily]; | 656 deviceFamily = [NSNumber numberWithInt:kIPhoneFamily]; |
638 } else if ([@"iPad" caseInsensitiveCompare:deviceName] == NSOrderedSame) { | 657 } else if (CaseInsensitivePrefixSearch(deviceName, @"iPad")) { |
639 deviceFamily = [NSNumber numberWithInt:kIPadFamily]; | 658 deviceFamily = [NSNumber numberWithInt:kIPadFamily]; |
640 } else { | 659 } else { |
641 LogError(@"Invalid device name: %@", deviceName); | 660 LogError(@"Invalid device name: %@. Must begin with 'iPhone' or 'iPad'", |
| 661 deviceName); |
642 exit(EXIT_FAILURE); | 662 exit(EXIT_FAILURE); |
643 } | 663 } |
644 | 664 |
645 // Set up the user home directory for the simulator | 665 // Set up the user home directory for the simulator |
646 if (!simHomePath) { | 666 if (!simHomePath) { |
647 NSString* dirNameTemplate = | 667 NSString* dirNameTemplate = |
648 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName]; | 668 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName]; |
649 simHomePath = CreateTempDirectory(dirNameTemplate); | 669 simHomePath = CreateTempDirectory(dirNameTemplate); |
650 if (!simHomePath) { | 670 if (!simHomePath) { |
651 LogError(@"Unable to create unique directory for template %@", | 671 LogError(@"Unable to create unique directory for template %@", |
652 dirNameTemplate); | 672 dirNameTemplate); |
653 exit(EXIT_FAILURE); | 673 exit(EXIT_FAILURE); |
654 } | 674 } |
655 } | 675 } |
656 if (!InitializeSimulatorUserHome(simHomePath)) { | 676 if (!InitializeSimulatorUserHome(simHomePath, deviceName)) { |
657 LogError(@"Unable to initialize home directory for simulator: %@", | 677 LogError(@"Unable to initialize home directory for simulator: %@", |
658 simHomePath); | 678 simHomePath); |
659 exit(EXIT_FAILURE); | 679 exit(EXIT_FAILURE); |
660 } | 680 } |
661 | 681 |
662 // Create the config and simulator session. | 682 // Create the config and simulator session. |
663 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec, | 683 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec, |
664 systemRoot, | 684 systemRoot, |
665 stdioPath, | 685 stdioPath, |
666 stdioPath, | 686 stdioPath, |
(...skipping 20 matching lines...) Expand all Loading... |
687 [error localizedDescription], | 707 [error localizedDescription], |
688 [error domain], static_cast<long int>([error code])); | 708 [error domain], static_cast<long int>([error code])); |
689 } | 709 } |
690 | 710 |
691 // Note that this code is only executed if the simulator fails to start | 711 // Note that this code is only executed if the simulator fails to start |
692 // because once the main run loop is started, only the delegate calling | 712 // because once the main run loop is started, only the delegate calling |
693 // exit() will end the program. | 713 // exit() will end the program. |
694 [pool drain]; | 714 [pool drain]; |
695 return EXIT_FAILURE; | 715 return EXIT_FAILURE; |
696 } | 716 } |
OLD | NEW |