AppRTCDemo: builds using ninja on iOS for simulator and device!

Things included in this CL:
- updated READMEs to provide an exact/reproable set of steps for getting the app
  running.
- gyp changes to build the iOS AppRTCDemo sample app using gyp+ninja instead of
  the hand-crafted Xcode project (which has never worked in its checked-in
  form), including a gyp action to sign the sample app for deployment to an iOS
  device (the app can also be used in the simulator)
- deleted the busted hand-crafted Xcode project for the sample app
- updated the sample app to match the PeerConnection API that ended up landing
  (in a surprising twist of fate, the API landed quite a bit later than the
  sample app and this is the first time the CR-time changes in the API are
  reflected in the sample app)
- updated the sample app to reflect apprtc.appspot.com HTML/JS changes (equiv to
  the AppRTCClient.java changes in http://s10/47299162)
- picked up the iossim DEPS to enable launching the sample app in the simulator
  from the command-line.
- renamed some files to match capitalization of the classes they contain (Ice ->
  ICE) per ObjC naming guidelines.
- ran the files involved in this CL through clang-format to deal with xcode
  formatting craxy.

BUG=2106
RISK=P2
TESTED=unittest builds with ninja and passes on OS=mac; sample app builds with ninja and runs on simulator and device, though no audio flows from simulator/device (will fix in a follow-up CL)
R=andrew@webrtc.org, justincohen@google.com, wu@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/1874005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4466 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.h b/talk/examples/ios/AppRTCDemo/APPRTCAppClient.h
index cac2f17..c737bea 100644
--- a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.h
+++ b/talk/examples/ios/AppRTCDemo/APPRTCAppClient.h
@@ -29,10 +29,10 @@
 
 #import "GAEChannelClient.h"
 
-// Called when there are RTCIceServers.
-@protocol IceServerDelegate <NSObject>
+// Called when there are RTCICEServers.
+@protocol ICEServerDelegate<NSObject>
 
-- (void)onIceServers:(NSArray *)servers;
+- (void)onICEServers:(NSArray*)servers;
 
 @end
 
@@ -45,8 +45,8 @@
 // for the registered handler to be called with received messages.
 @interface APPRTCAppClient : NSObject<NSURLConnectionDataDelegate>
 
-@property(nonatomic, assign) id<IceServerDelegate>iceServerDelegate;
-@property(nonatomic, assign) id<GAEMessageHandler>messageHandler;
+@property(nonatomic, assign) id<ICEServerDelegate> ICEServerDelegate;
+@property(nonatomic, assign) id<GAEMessageHandler> messageHandler;
 
 - (void)connectToRoom:(NSURL *)room;
 - (void)sendData:(NSData *)data;
diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m b/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m
index bcc2329..93f0d36 100644
--- a/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m
+++ b/talk/examples/ios/AppRTCDemo/APPRTCAppClient.m
@@ -30,16 +30,16 @@
 #import <dispatch/dispatch.h>
 
 #import "GAEChannelClient.h"
-#import "RTCIceServer.h"
+#import "RTCICEServer.h"
 
 @interface APPRTCAppClient ()
 
-@property(nonatomic, strong) dispatch_queue_t backgroundQueue;
+@property(nonatomic, assign) dispatch_queue_t backgroundQueue;
 @property(nonatomic, copy) NSString *baseURL;
 @property(nonatomic, strong) GAEChannelClient *gaeChannel;
 @property(nonatomic, copy) NSString *postMessageUrl;
 @property(nonatomic, copy) NSString *pcConfig;
-@property(nonatomic, strong) NSMutableString *receivedData;
+@property(nonatomic, strong) NSMutableString *roomHtml;
 @property(atomic, strong) NSMutableArray *sendQueue;
 @property(nonatomic, copy) NSString *token;
 
@@ -52,13 +52,18 @@
 - (id)init {
   if (self = [super init]) {
     _backgroundQueue = dispatch_queue_create("RTCBackgroundQueue", NULL);
+    dispatch_retain(_backgroundQueue);
     _sendQueue = [NSMutableArray array];
     // Uncomment to see Request/Response logging.
-    //_verboseLogging = YES;
+    // _verboseLogging = YES;
   }
   return self;
 }
 
+- (void)dealloc {
+  dispatch_release(_backgroundQueue);
+}
+
 #pragma mark - Public methods
 
 - (void)connectToRoom:(NSURL *)url {
@@ -76,42 +81,41 @@
 
 #pragma mark - Internal methods
 
-- (NSTextCheckingResult *)findMatch:(NSString *)regexpPattern
-                         withString:(NSString *)string
-                       errorMessage:(NSString *)errorMessage {
-  NSError *error;
+- (NSString*)findVar:(NSString*)name
+     strippingQuotes:(BOOL)strippingQuotes {
+  NSError* error;
+  NSString* pattern =
+      [NSString stringWithFormat:@".*\n *var %@ = ([^\n]*);\n.*", name];
   NSRegularExpression *regexp =
-      [NSRegularExpression regularExpressionWithPattern:regexpPattern
+      [NSRegularExpression regularExpressionWithPattern:pattern
                                                 options:0
                                                   error:&error];
-  if (error) {
-    [self maybeLogMessage:
-            [NSString stringWithFormat:@"Failed to create regexp - %@",
-                [error description]]];
+  NSAssert(!error, @"Unexpected error compiling regex: ",
+           error.localizedDescription);
+
+  NSRange fullRange = NSMakeRange(0, [self.roomHtml length]);
+  NSArray *matches =
+      [regexp matchesInString:self.roomHtml options:0 range:fullRange];
+  if ([matches count] != 1) {
+    [self showMessage:[NSString stringWithFormat:@"%d matches for %@ in %@",
+                                [matches count], name, self.roomHtml]];
     return nil;
   }
-  NSRange fullRange = NSMakeRange(0, [string length]);
-  NSArray *matches = [regexp matchesInString:string options:0 range:fullRange];
-  if ([matches count] == 0) {
-    if ([errorMessage length] > 0) {
-      [self maybeLogMessage:string];
-      [self showMessage:
-              [NSString stringWithFormat:@"Missing %@ in HTML.", errorMessage]];
-    }
-    return nil;
-  } else if ([matches count] > 1) {
-    if ([errorMessage length] > 0) {
-      [self maybeLogMessage:string];
-      [self showMessage:[NSString stringWithFormat:@"Too many %@s in HTML.",
-                         errorMessage]];
-    }
-    return nil;
+  NSRange matchRange = [matches[0] rangeAtIndex:1];
+  NSString* value = [self.roomHtml substringWithRange:matchRange];
+  if (strippingQuotes) {
+    NSAssert([value length] > 2,
+             @"Can't strip quotes from short string: [%@]", value);
+    NSAssert(([value characterAtIndex:0] == '\'' &&
+              [value characterAtIndex:[value length] - 1] == '\''),
+             @"Can't strip quotes from unquoted string: [%@]", value);
+    value = [value substringWithRange:NSMakeRange(1, [value length] - 2)];
   }
-  return matches[0];
+  return value;
 }
 
 - (NSURLRequest *)getRequestFromUrl:(NSURL *)url {
-  self.receivedData = [NSMutableString stringWithCapacity:20000];
+  self.roomHtml = [NSMutableString stringWithCapacity:20000];
   NSString *path =
       [NSString stringWithFormat:@"https:%@", [url resourceSpecifier]];
   NSURLRequest *request =
@@ -172,10 +176,10 @@
   [alertView show];
 }
 
-- (void)updateIceServers:(NSMutableArray *)iceServers
+- (void)updateICEServers:(NSMutableArray *)ICEServers
           withTurnServer:(NSString *)turnServerUrl {
   if ([turnServerUrl length] < 1) {
-    [self.iceServerDelegate onIceServers:iceServers];
+    [self.ICEServerDelegate onICEServers:ICEServers];
     return;
   }
   dispatch_async(self.backgroundQueue, ^(void) {
@@ -199,16 +203,16 @@
       NSString *password = json[@"password"];
       NSString *fullUrl =
           [NSString stringWithFormat:@"turn:%@@%@", username, turnServer];
-      RTCIceServer *iceServer =
-          [[RTCIceServer alloc] initWithUri:[NSURL URLWithString:fullUrl]
+      RTCICEServer *ICEServer =
+          [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:fullUrl]
                                    password:password];
-      [iceServers addObject:iceServer];
+      [ICEServers addObject:ICEServer];
     } else {
       NSLog(@"Unable to get TURN server.  Error: %@", error.description);
     }
 
     dispatch_async(dispatch_get_main_queue(), ^(void) {
-      [self.iceServerDelegate onIceServers:iceServers];
+      [self.ICEServerDelegate onICEServers:ICEServers];
     });
   });
 }
@@ -219,7 +223,7 @@
   NSString *roomHtml = [NSString stringWithUTF8String:[data bytes]];
   [self maybeLogMessage:
           [NSString stringWithFormat:@"Received %d chars", [roomHtml length]]];
-  [self.receivedData appendString:roomHtml];
+  [self.roomHtml appendString:roomHtml];
 }
 
 - (void)connection:(NSURLConnection *)connection
@@ -237,64 +241,48 @@
 
 - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
   [self maybeLogMessage:[NSString stringWithFormat:@"finished loading %d chars",
-                         [self.receivedData length]]];
-  NSTextCheckingResult *result =
-      [self findMatch:@".*\n *Sorry, this room is full\\..*"
-            withString:self.receivedData
-          errorMessage:nil];
-  if (result) {
+                         [self.roomHtml length]]];
+  NSRegularExpression* fullRegex =
+    [NSRegularExpression regularExpressionWithPattern:@"room is full"
+                                              options:0
+                                                error:nil];
+  if ([fullRegex numberOfMatchesInString:self.roomHtml
+                                 options:0
+                                   range:NSMakeRange(0, [self.roomHtml length])]) {
     [self showMessage:@"Room full"];
     return;
   }
 
+
   NSString *fullUrl = [[[connection originalRequest] URL] absoluteString];
   NSRange queryRange = [fullUrl rangeOfString:@"?"];
   self.baseURL = [fullUrl substringToIndex:queryRange.location];
-  [self maybeLogMessage:[NSString stringWithFormat:@"URL\n%@", self.baseURL]];
+  [self maybeLogMessage:[NSString stringWithFormat:@"Base URL: %@", self.baseURL]];
 
-  result = [self findMatch:@".*\n *openChannel\\('([^']*)'\\);\n.*"
-                withString:self.receivedData
-              errorMessage:@"channel token"];
-  if (!result) {
+  self.token = [self findVar:@"channelToken" strippingQuotes:YES];
+  if (!self.token)
     return;
-  }
-  self.token = [self.receivedData substringWithRange:[result rangeAtIndex:1]];
-  [self maybeLogMessage:[NSString stringWithFormat:@"Token\n%@", self.token]];
+  [self maybeLogMessage:[NSString stringWithFormat:@"Token: %@", self.token]];
 
-  result =
-      [self findMatch:@".*\n *path = '/(message\\?r=.+)' \\+ '(&u=[0-9]+)';\n.*"
-            withString:self.receivedData
-          errorMessage:@"postMessage URL"];
-  if (!result) {
+  NSString* roomKey = [self findVar:@"roomKey" strippingQuotes:YES];
+  NSString* me = [self findVar:@"me" strippingQuotes:YES];
+  if (!roomKey || !me)
     return;
-  }
   self.postMessageUrl =
-      [NSString stringWithFormat:@"%@%@",
-          [self.receivedData substringWithRange:[result rangeAtIndex:1]],
-          [self.receivedData substringWithRange:[result rangeAtIndex:2]]];
-  [self maybeLogMessage:[NSString stringWithFormat:@"POST message URL\n%@",
-                         self.postMessageUrl]];
+    [NSString stringWithFormat:@"/message?r=%@&u=%@", roomKey, me];
+  [self maybeLogMessage:[NSString stringWithFormat:@"POST message URL: %@",
+                                  self.postMessageUrl]];
 
-  result = [self findMatch:@".*\n *var pc_config = (\\{[^\n]*\\});\n.*"
-                withString:self.receivedData
-              errorMessage:@"pc_config"];
-  if (!result) {
+  NSString* pcConfig = [self findVar:@"pcConfig" strippingQuotes:NO];
+  if (!pcConfig)
     return;
-  }
-  NSString *pcConfig =
-      [self.receivedData substringWithRange:[result rangeAtIndex:1]];
   [self maybeLogMessage:
-          [NSString stringWithFormat:@"PC Config JSON\n%@", pcConfig]];
+          [NSString stringWithFormat:@"PC Config JSON: %@", pcConfig]];
 
-  result = [self findMatch:@".*\n *requestTurn\\('([^\n]*)'\\);\n.*"
-                withString:self.receivedData
-              errorMessage:@"channel token"];
-  NSString *turnServerUrl;
-  if (result) {
-    turnServerUrl =
-        [self.receivedData substringWithRange:[result rangeAtIndex:1]];
+  NSString *turnServerUrl = [self findVar:@"turnUrl" strippingQuotes:YES];
+  if (turnServerUrl) {
     [self maybeLogMessage:
-            [NSString stringWithFormat:@"TURN server request URL\n%@",
+            [NSString stringWithFormat:@"TURN server request URL: %@",
                 turnServerUrl]];
   }
 
@@ -303,8 +291,8 @@
   NSDictionary *json =
       [NSJSONSerialization JSONObjectWithData:pcData options:0 error:&error];
   NSAssert(!error, @"Unable to parse.  %@", error.localizedDescription);
-  NSArray *servers = [json objectForKey:@"iceServers"];
-  NSMutableArray *iceServers = [NSMutableArray array];
+  NSArray *servers = [json objectForKey:@"ICEServers"];
+  NSMutableArray *ICEServers = [NSMutableArray array];
   for (NSDictionary *server in servers) {
     NSString *url = [server objectForKey:@"url"];
     NSString *credential = [server objectForKey:@"credential"];
@@ -315,12 +303,12 @@
             [NSString stringWithFormat:@"url [%@] - credential [%@]",
                 url,
                 credential]];
-    RTCIceServer *iceServer =
-        [[RTCIceServer alloc] initWithUri:[NSURL URLWithString:url]
+    RTCICEServer *ICEServer =
+        [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:url]
                                  password:credential];
-    [iceServers addObject:iceServer];
+    [ICEServers addObject:ICEServer];
   }
-  [self updateIceServers:iceServers withTurnServer:turnServerUrl];
+  [self updateICEServers:ICEServers withTurnServer:turnServerUrl];
 
   [self maybeLogMessage:
           [NSString stringWithFormat:@"About to open GAE with token:  %@",
diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h
index 82b07f0..ad1c512 100644
--- a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h
+++ b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.h
@@ -43,9 +43,11 @@
 // The main application class of the AppRTCDemo iOS app demonstrating
 // interoperability between the Objcective C implementation of PeerConnection
 // and the apprtc.appspot.com demo webapp.
-@interface APPRTCAppDelegate : UIResponder<IceServerDelegate,
-    GAEMessageHandler, APPRTCSendMessage, RTCSessionDescriptonDelegate,
-    UIApplicationDelegate>
+@interface APPRTCAppDelegate : UIResponder<ICEServerDelegate,
+                                           GAEMessageHandler,
+                                           APPRTCSendMessage,
+                                           RTCSessionDescriptonDelegate,
+                                           UIApplicationDelegate>
 
 @property (strong, nonatomic) UIWindow *window;
 @property (strong, nonatomic) APPRTCViewController *viewController;
diff --git a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m
index 0c429a0..710f4ad 100644
--- a/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m
+++ b/talk/examples/ios/AppRTCDemo/APPRTCAppDelegate.m
@@ -28,8 +28,8 @@
 #import "APPRTCAppDelegate.h"
 
 #import "APPRTCViewController.h"
-#import "RTCIceCandidate.h"
-#import "RTCIceServer.h"
+#import "RTCICECandidate.h"
+#import "RTCICEServer.h"
 #import "RTCMediaConstraints.h"
 #import "RTCMediaStream.h"
 #import "RTCPair.h"
@@ -61,12 +61,12 @@
 }
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-    onSignalingStateChange:(RTCSignalingState)stateChanged {
+    signalingStateChanged:(RTCSignalingState)stateChanged {
   NSLog(@"PCO onSignalingStateChange.");
 }
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-           onAddStream:(RTCMediaStream *)stream {
+             addedStream:(RTCMediaStream *)stream {
   NSLog(@"PCO onAddStream.");
   dispatch_async(dispatch_get_main_queue(), ^(void) {
     NSAssert([stream.audioTracks count] >= 1,
@@ -78,7 +78,7 @@
 }
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-        onRemoveStream:(RTCMediaStream *)stream {
+         removedStream:(RTCMediaStream *)stream {
   NSLog(@"PCO onRemoveStream.");
   // TODO(hughv): Remove video track.
 }
@@ -90,8 +90,8 @@
 }
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-        onIceCandidate:(RTCIceCandidate *)candidate {
-  NSLog(@"PCO onIceCandidate.\n  Mid[%@] Index[%d] Sdp[%@]",
+       gotICECandidate:(RTCICECandidate *)candidate {
+  NSLog(@"PCO onICECandidate.\n  Mid[%@] Index[%d] Sdp[%@]",
         candidate.sdpMid,
         candidate.sdpMLineIndex,
         candidate.sdp);
@@ -112,12 +112,12 @@
 }
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-    onIceGatheringChange:(RTCIceGatheringState)newState {
+    iceGatheringChanged:(RTCICEGatheringState)newState {
   NSLog(@"PCO onIceGatheringChange. %d", newState);
 }
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-    onIceConnectionChange:(RTCIceConnectionState)newState {
+    iceConnectionChanged:(RTCICEConnectionState)newState {
   NSLog(@"PCO onIceConnectionChange. %d", newState);
 }
 
@@ -139,9 +139,10 @@
 
 - (BOOL)application:(UIApplication *)application
     didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+  [RTCPeerConnectionFactory initializeSSL];
   self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
   self.viewController =
-      [[APPRTCViewController alloc] initWithNibName:@"RTCViewController"
+      [[APPRTCViewController alloc] initWithNibName:@"APPRTCViewController"
                                              bundle:nil];
   self.window.rootViewController = self.viewController;
   [self.window makeKeyAndVisible];
@@ -174,7 +175,7 @@
     return NO;
   }
   self.client = [[APPRTCAppClient alloc] init];
-  self.client.iceServerDelegate = self;
+  self.client.ICEServerDelegate = self;
   self.client.messageHandler = self;
   [self.client connectToRoom:url];
   return YES;
@@ -191,23 +192,23 @@
   [self.client sendData:data];
 }
 
-#pragma mark - IceServerDelegate method
+#pragma mark - ICEServerDelegate method
 
-- (void)onIceServers:(NSArray *)servers {
+- (void)onICEServers:(NSArray *)servers {
   self.queuedRemoteCandidates = [NSMutableArray array];
   self.peerConnectionFactory = [[RTCPeerConnectionFactory alloc] init];
   RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] init];
   self.pcObserver = [[PCObserver alloc] initWithDelegate:self];
   self.peerConnection =
-      [self.peerConnectionFactory peerConnectionWithIceServers:servers
+      [self.peerConnectionFactory peerConnectionWithICEServers:servers
                                                    constraints:constraints
                                                       delegate:self.pcObserver];
   RTCMediaStream *lms =
       [self.peerConnectionFactory mediaStreamWithLabel:@"ARDAMS"];
   // TODO(hughv): Add video.
-  [lms addAudioTrack:[self.peerConnectionFactory audioTrackWithId:@"ARDAMSa0"]];
-  [self.peerConnection addStream:lms withConstraints:constraints];
-  [self displayLogMessage:@"onIceServers - add local stream."];
+  [lms addAudioTrack:[self.peerConnectionFactory audioTrackWithID:@"ARDAMSa0"]];
+  [self.peerConnection addStream:lms constraints:constraints];
+  [self displayLogMessage:@"onICEServers - add local stream."];
 }
 
 #pragma mark - GAEMessageHandler methods
@@ -245,14 +246,14 @@
     NSString *mid = [objects objectForKey:@"id"];
     NSNumber *sdpLineIndex = [objects objectForKey:@"label"];
     NSString *sdp = [objects objectForKey:@"candidate"];
-    RTCIceCandidate *candidate =
-        [[RTCIceCandidate alloc] initWithMid:mid
+    RTCICECandidate *candidate =
+        [[RTCICECandidate alloc] initWithMid:mid
                                        index:sdpLineIndex.intValue
                                          sdp:sdp];
     if (self.queuedRemoteCandidates) {
       [self.queuedRemoteCandidates addObject:candidate];
     } else {
-      [self.peerConnection addIceCandidate:candidate];
+      [self.peerConnection addICECandidate:candidate];
     }
   } else if (([value compare:@"offer"] == NSOrderedSame) ||
              ([value compare:@"answer"] == NSOrderedSame)) {
@@ -283,8 +284,8 @@
 #pragma mark - RTCSessionDescriptonDelegate methods
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-    createSessionDescriptionCompleted:(RTCSessionDescription *)sdp
-                            withError:(NSError *)error {
+    didCreateSessionDescription:(RTCSessionDescription *)sdp
+                          error:(NSError *)error {
   if (error) {
     [self displayLogMessage:@"SDP onFailure."];
     NSAssert(NO, error.description);
@@ -308,7 +309,7 @@
 }
 
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
-    setSessionDescriptionCompletedWithError:(NSError *)error {
+    didSetSessionDescriptionWithError:(NSError *)error {
   if (error) {
     [self displayLogMessage:@"SDP onFailure."];
     NSAssert(NO, error.description);
@@ -333,14 +334,15 @@
   self.peerConnection = nil;
   self.peerConnectionFactory = nil;
   self.pcObserver = nil;
-  self.client.iceServerDelegate = nil;
+  self.client.ICEServerDelegate = nil;
   self.client.messageHandler = nil;
   self.client = nil;
+  [RTCPeerConnectionFactory deinitializeSSL];
 }
 
 - (void)drainRemoteCandidates {
-  for (RTCIceCandidate *candidate in self.queuedRemoteCandidates) {
-    [self.peerConnection addIceCandidate:candidate];
+  for (RTCICECandidate *candidate in self.queuedRemoteCandidates) {
+    [self.peerConnection addICECandidate:candidate];
   }
   self.queuedRemoteCandidates = nil;
 }
diff --git a/talk/examples/ios/AppRTCDemo/AppRTCDemo-Info.plist b/talk/examples/ios/AppRTCDemo/AppRTCDemo-Info.plist
deleted file mode 100644
index 3ab57ed..0000000
--- a/talk/examples/ios/AppRTCDemo/AppRTCDemo-Info.plist
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>en</string>
-	<key>CFBundleDisplayName</key>
-	<string>${PRODUCT_NAME}</string>
-	<key>CFBundleExecutable</key>
-	<string>${EXECUTABLE_NAME}</string>
-	<key>CFBundleIcons</key>
-	<dict>
-		<key>CFBundlePrimaryIcon</key>
-		<dict>
-			<key>CFBundleIconFiles</key>
-			<array>
-				<string>Icon.png</string>
-			</array>
-		</dict>
-	</dict>
-	<key>CFBundleIdentifier</key>
-	<string>com.Google.${PRODUCT_NAME:rfc1034identifier}</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>${PRODUCT_NAME}</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>1.0</string>
-	<key>CFBundleSignature</key>
-	<string>????</string>
-	<key>CFBundleURLTypes</key>
-	<array>
-		<dict>
-			<key>CFBundleTypeRole</key>
-			<string>Editor</string>
-			<key>CFBundleURLName</key>
-			<string>com.google.apprtcdemo</string>
-			<key>CFBundleURLSchemes</key>
-			<array>
-				<string>apprtc</string>
-			</array>
-		</dict>
-	</array>
-	<key>CFBundleVersion</key>
-	<string>1.0</string>
-	<key>LSRequiresIPhoneOS</key>
-	<true/>
-	<key>UIRequiredDeviceCapabilities</key>
-	<array>
-		<string>armv7</string>
-	</array>
-	<key>UIStatusBarTintParameters</key>
-	<dict>
-		<key>UINavigationBar</key>
-		<dict>
-			<key>Style</key>
-			<string>UIBarStyleDefault</string>
-			<key>Translucent</key>
-			<false/>
-		</dict>
-	</dict>
-	<key>UISupportedInterfaceOrientations</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-	</array>
-</dict>
-</plist>
diff --git a/talk/examples/ios/AppRTCDemo/Info.plist b/talk/examples/ios/AppRTCDemo/Info.plist
new file mode 100644
index 0000000..72504aa
--- /dev/null
+++ b/talk/examples/ios/AppRTCDemo/Info.plist
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>BuildMachineOSBuild</key>
+        <string>12E55</string>
+        <key>CFBundleDevelopmentRegion</key>
+        <string>en</string>
+        <key>CFBundleDisplayName</key>
+        <string>AppRTCDemo</string>
+        <key>CFBundleExecutable</key>
+        <string>AppRTCDemo</string>
+        <key>CFBundleIcons</key>
+        <dict>
+                <key>CFBundlePrimaryIcon</key>
+                <dict>
+                        <key>CFBundleIconFiles</key>
+                        <array>
+                                <string>Icon.png</string>
+                        </array>
+                </dict>
+        </dict>
+        <key>CFBundleIdentifier</key>
+        <string>com.google.AppRTCDemo</string>
+        <key>CFBundleInfoDictionaryVersion</key>
+        <string>6.0</string>
+        <key>CFBundleName</key>
+        <string>AppRTCDemo</string>
+        <key>CFBundlePackageType</key>
+        <string>APPL</string>
+        <key>CFBundleResourceSpecification</key>
+        <string>ResourceRules.plist</string>
+        <key>CFBundleShortVersionString</key>
+        <string>1.0</string>
+        <key>CFBundleSignature</key>
+        <string>????</string>
+        <key>CFBundleSupportedPlatforms</key>
+        <array>
+                <string>iPhoneOS</string>
+        </array>
+        <key>CFBundleURLTypes</key>
+        <array>
+                <dict>
+                        <key>CFBundleTypeRole</key>
+                        <string>Editor</string>
+                        <key>CFBundleURLName</key>
+                        <string>com.google.apprtcdemo</string>
+                        <key>CFBundleURLSchemes</key>
+                        <array>
+                                <string>apprtc</string>
+                        </array>
+                </dict>
+        </array>
+        <key>CFBundleVersion</key>
+        <string>1.0</string>
+        <key>UIRequiredDeviceCapabilities</key>
+        <array>
+                <string>armv7</string>
+        </array>
+        <key>UIStatusBarTintParameters</key>
+        <dict>
+                <key>UINavigationBar</key>
+                <dict>
+                        <key>Style</key>
+                        <string>UIBarStyleDefault</string>
+                        <key>Translucent</key>
+                        <false/>
+                </dict>
+        </dict>
+        <key>UISupportedInterfaceOrientations</key>
+        <array>
+                <string>UIInterfaceOrientationPortrait</string>
+                <string>UIInterfaceOrientationLandscapeLeft</string>
+                <string>UIInterfaceOrientationLandscapeRight</string>
+        </array>
+</dict>
+</plist>
diff --git a/talk/examples/ios/AppRTCDemo/ResourceRules.plist b/talk/examples/ios/AppRTCDemo/ResourceRules.plist
new file mode 100644
index 0000000..e7ec329
--- /dev/null
+++ b/talk/examples/ios/AppRTCDemo/ResourceRules.plist
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>rules</key>
+	<dict>
+		<key>.*</key>
+		<true/>
+		<key>Info.plist</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>10</real>
+		</dict>
+		<key>ResourceRules.plist</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>100</real>
+		</dict>
+	</dict>
+</dict>
+</plist>