blob: 86846dd68701c597801a0cbfe8a60be85cd1662e [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001<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
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +00009 protocol. Then when there is a channel message it is queued in JS,
10 and an IFRAME is added to the DOM, triggering a navigation event
11 |shouldStartLoadWithRequest| in Objective C which can then fetch the
12 message using |popQueuedMessage|. This queuing is necessary to avoid URL
13 length limits in UIWebView (which are undocumented).
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014 -->
15 <body onbeforeunload="closeSocket()" onload="openSocket()">
16 <script type="text/javascript">
17 // QueryString is copy/pasta from
18 // chromium's chrome/test/data/media/html/utils.js.
19 var QueryString = function () {
20 // Allows access to query parameters on the URL; e.g., given a URL like:
21 // http://<url>/my.html?test=123&bob=123
22 // parameters can now be accessed via QueryString.test or
23 // QueryString.bob.
24 var params = {};
25
26 // RegEx to split out values by &.
27 var r = /([^&=]+)=?([^&]*)/g;
28
29 // Lambda function for decoding extracted match values. Replaces '+'
30 // with space so decodeURIComponent functions properly.
31 function d(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }
32
33 var match;
34 while (match = r.exec(window.location.search.substring(1)))
35 params[d(match[1])] = d(match[2]);
36
37 return params;
38 } ();
39
40 var channel = null;
41 var socket = null;
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +000042 // In-order queue of messages to be delivered to ObjectiveC.
43 // Each is a JSON.stringify()'d dictionary containing a 'type'
44 // field and optionally a 'payload'.
45 var messageQueue = [];
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046
47 function openSocket() {
48 if (!QueryString.token || !QueryString.token.match(/^[A-z0-9_-]+$/)) {
49 // Send error back to ObjC. This will assert in GAEChannelClient.m.
50 sendMessageToObjC("JSError:Missing/malformed token parameter " +
51 QueryString.token);
52 throw "Missing/malformed token parameter: " + QueryString.token;
53 }
54 channel = new goog.appengine.Channel(QueryString.token);
55 socket = channel.open({
56 'onopen': function() {
57 sendMessageToObjC("onopen");
58 },
59 'onmessage': function(msg) {
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +000060 sendMessageToObjC("onmessage", msg);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061 },
62 'onclose': function() {
63 sendMessageToObjC("onclose");
64 },
65 'onerror': function(err) {
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +000066 sendMessageToObjC("onerror", err);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 }
68 });
69 }
70
71 function closeSocket() {
72 socket.close();
73 }
74
75 // Add an IFRAME to the DOM to trigger a navigation event. Then remove
76 // it as it is no longer needed. Only one event is generated.
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +000077 function sendMessageToObjC(type, payload) {
78 messageQueue.push(JSON.stringify({'type': type, 'payload': payload}));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079 var iframe = document.createElement("IFRAME");
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +000080 iframe.setAttribute("src", "js-frame:");
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081 // For some reason we need to set a non-empty size for the iOS6
82 // simulator...
83 iframe.setAttribute("height", "1px");
84 iframe.setAttribute("width", "1px");
85 document.documentElement.appendChild(iframe);
86 iframe.parentNode.removeChild(iframe);
87 }
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +000088
89 function popQueuedMessage() {
90 return messageQueue.shift();
91 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092 </script>
93 </body>
94</html>