 61e78fca6c
			
		
	
	61e78fca6c
	
	
	
		
			
			Previously GAE Channel callbacks would be handled by JS string-encoding the payload into a URL. Unfortunately this is limited to the (undocumented, silently problematic) maximum URL length UIWebView supports. Replaced this scheme by a notification from JS to ObjC and a getter from ObjC to JS (which happens out-of-line to avoid worrying about UIWebView's re-entrancy, or lack thereof). Part of this change also moved from a combination of: JSON, URL-escaping, and ad-hoc :-separated values to simply JSON. Also incidentally: - Removed outdated TODO about onRenegotiationNeeded, which is unneeded - Move handling of PeerConnection callbacks to the main queue to avoid having to think about concurrency too hard. - Replaced a bunch of NSOrderedSame with isEqualToString for clearer code and not having to worry about the fact that [nil compare:@"foo"]==NSOrderedSame is always true (yay ObjC!). - Auto-scroll messages view. BUG=3117 R=noahric@google.com Review URL: https://webrtc-codereview.appspot.com/10899006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5814 4adac7df-926f-26a2-2b94-8c16560cd09d
		
			
				
	
	
		
			95 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <html>
 | |
|   <head>
 | |
|     <script src="http://apprtc.appspot.com/_ah/channel/jsapi"></script>
 | |
|   </head>
 | |
|   <!--
 | |
|   Helper HTML that redirects Google AppEngine's Channel API to Objective C.
 | |
|   This is done by hosting this page in an iOS application.  The hosting
 | |
|   class creates a UIWebView control and implements the UIWebViewDelegate
 | |
|   protocol.  Then when there is a channel message it is queued in JS,
 | |
|   and an IFRAME is added to the DOM, triggering a navigation event
 | |
|   |shouldStartLoadWithRequest| in Objective C which can then fetch the
 | |
|   message using |popQueuedMessage|.  This queuing is necessary to avoid URL
 | |
|   length limits in UIWebView (which are undocumented).
 | |
|   -->
 | |
|   <body onbeforeunload="closeSocket()" onload="openSocket()">
 | |
|     <script type="text/javascript">
 | |
|       // QueryString is copy/pasta from
 | |
|       // chromium's chrome/test/data/media/html/utils.js.
 | |
|       var QueryString = function () {
 | |
|         // Allows access to query parameters on the URL; e.g., given a URL like:
 | |
|         //    http://<url>/my.html?test=123&bob=123
 | |
|         // parameters can now be accessed via QueryString.test or
 | |
|         // QueryString.bob.
 | |
|         var params = {};
 | |
| 
 | |
|         // RegEx to split out values by &.
 | |
|         var r = /([^&=]+)=?([^&]*)/g;
 | |
| 
 | |
|         // Lambda function for decoding extracted match values. Replaces '+'
 | |
|         // with space so decodeURIComponent functions properly.
 | |
|         function d(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }
 | |
| 
 | |
|         var match;
 | |
|         while (match = r.exec(window.location.search.substring(1)))
 | |
|           params[d(match[1])] = d(match[2]);
 | |
| 
 | |
|         return params;
 | |
|       } ();
 | |
| 
 | |
|       var channel = null;
 | |
|       var socket = null;
 | |
|       // In-order queue of messages to be delivered to ObjectiveC.
 | |
|       // Each is a JSON.stringify()'d dictionary containing a 'type'
 | |
|       // field and optionally a 'payload'.
 | |
|       var messageQueue = [];
 | |
| 
 | |
|       function openSocket() {
 | |
|         if (!QueryString.token || !QueryString.token.match(/^[A-z0-9_-]+$/)) {
 | |
|           // Send error back to ObjC.  This will assert in GAEChannelClient.m.
 | |
|           sendMessageToObjC("JSError:Missing/malformed token parameter " +
 | |
|                             QueryString.token);
 | |
|           throw "Missing/malformed token parameter: " + QueryString.token;
 | |
|         }
 | |
|         channel = new goog.appengine.Channel(QueryString.token);
 | |
|         socket = channel.open({
 | |
|           'onopen': function() {
 | |
|             sendMessageToObjC("onopen");
 | |
|           },
 | |
|           'onmessage': function(msg) {
 | |
|             sendMessageToObjC("onmessage", msg);
 | |
|           },
 | |
|           'onclose': function() {
 | |
|             sendMessageToObjC("onclose");
 | |
|           },
 | |
|           'onerror': function(err) {
 | |
|             sendMessageToObjC("onerror", err);
 | |
|           }
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       function closeSocket() {
 | |
|         socket.close();
 | |
|       }
 | |
| 
 | |
|       // Add an IFRAME to the DOM to trigger a navigation event.  Then remove
 | |
|       // it as it is no longer needed.  Only one event is generated.
 | |
|       function sendMessageToObjC(type, payload) {
 | |
|         messageQueue.push(JSON.stringify({'type': type, 'payload': payload}));
 | |
|         var iframe = document.createElement("IFRAME");
 | |
|         iframe.setAttribute("src", "js-frame:");
 | |
|         // For some reason we need to set a non-empty size for the iOS6
 | |
|         // simulator...
 | |
|         iframe.setAttribute("height", "1px");
 | |
|         iframe.setAttribute("width", "1px");
 | |
|         document.documentElement.appendChild(iframe);
 | |
|         iframe.parentNode.removeChild(iframe);
 | |
|       }
 | |
| 
 | |
|       function popQueuedMessage() {
 | |
|         return messageQueue.shift();
 | |
|       }
 | |
|     </script>
 | |
|   </body>
 | |
| </html>
 |