Home | History | Annotate | Download | only in AppRTCDemo
      1 <html>
      2   <head>
      3     <script src="http://apprtc.appspot.com/_ah/channel/jsapi"></script>
      4   </head>
      5   <!--
      6   Helper HTML that redirects Google AppEngine's Channel API to Objective C.
      7   This is done by hosting this page in an iOS application.  The hosting
      8   class creates a UIWebView control and implements the UIWebViewDelegate
      9   protocol.  Then when there is a channel message, it is encoded in an IFRAME.
     10   That IFRAME is added to the DOM which triggers a navigation event
     11   |shouldStartLoadWithRequest| in Objective C which can then be routed in the
     12   application as desired.
     13   -->
     14   <body onbeforeunload="closeSocket()" onload="openSocket()">
     15     <script type="text/javascript">
     16       // QueryString is copy/pasta from
     17       // chromium's chrome/test/data/media/html/utils.js.
     18       var QueryString = function () {
     19         // Allows access to query parameters on the URL; e.g., given a URL like:
     20         //    http://<url>/my.html?test=123&bob=123
     21         // parameters can now be accessed via QueryString.test or
     22         // QueryString.bob.
     23         var params = {};
     24 
     25         // RegEx to split out values by &.
     26         var r = /([^&=]+)=?([^&]*)/g;
     27 
     28         // Lambda function for decoding extracted match values. Replaces '+'
     29         // with space so decodeURIComponent functions properly.
     30         function d(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }
     31 
     32         var match;
     33         while (match = r.exec(window.location.search.substring(1)))
     34           params[d(match[1])] = d(match[2]);
     35 
     36         return params;
     37       } ();
     38 
     39       var channel = null;
     40       var socket = null;
     41 
     42       function openSocket() {
     43         if (!QueryString.token || !QueryString.token.match(/^[A-z0-9_-]+$/)) {
     44           // Send error back to ObjC.  This will assert in GAEChannelClient.m.
     45           sendMessageToObjC("JSError:Missing/malformed token parameter " +
     46                             QueryString.token);
     47           throw "Missing/malformed token parameter: " + QueryString.token;
     48         }
     49         channel = new goog.appengine.Channel(QueryString.token);
     50         socket = channel.open({
     51           'onopen': function() {
     52             sendMessageToObjC("onopen");
     53           },
     54           'onmessage': function(msg) {
     55             sendMessageToObjC("onmessage:" +
     56                               encodeURIComponent(JSON.stringify(msg.data)));
     57           },
     58           'onclose': function() {
     59             sendMessageToObjC("onclose");
     60           },
     61           'onerror': function(err) {
     62             sendMessageToObjC("onerror:" +
     63                               encodeURIComponent(JSON.stringify(err.code)) +
     64                               ":message:" +
     65                               encodeURIComponent(JSON.stringify(err.description)));
     66           }
     67         });
     68       }
     69 
     70       function closeSocket() {
     71         socket.close();
     72       }
     73 
     74       // Add an IFRAME to the DOM to trigger a navigation event.  Then remove
     75       // it as it is no longer needed.  Only one event is generated.
     76       function sendMessageToObjC(message) {
     77         var iframe = document.createElement("IFRAME");
     78         iframe.setAttribute("src", "js-frame:" + message);
     79         // For some reason we need to set a non-empty size for the iOS6
     80         // simulator...
     81         iframe.setAttribute("height", "1px");
     82         iframe.setAttribute("width", "1px");
     83         document.documentElement.appendChild(iframe);
     84         iframe.parentNode.removeChild(iframe);
     85       }
     86     </script>
     87   </body>
     88 </html>
     89