• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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