blob: a95e99a8d6c4b1149b70b71fb72685e6a199f15a [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2013, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#import "GAEChannelClient.h"
29
30#import "RTCPeerConnectionFactory.h"
31
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000032#if TARGET_OS_IPHONE
33
34#import <UIKit/UIKit.h>
35
36@interface GAEChannelClient () <UIWebViewDelegate>
37
38@property(nonatomic, strong) UIWebView* webView;
39
40#else
41
42#import <WebKit/WebKit.h>
43
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044@interface GAEChannelClient ()
45
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000046@property(nonatomic, strong) WebView* webView;
47
48#endif
49
henrike@webrtc.org28e20752013-07-10 00:45:36 +000050@end
51
52@implementation GAEChannelClient
53
tkchin@webrtc.org013bdf82014-06-06 22:29:10 +000054- (instancetype)initWithToken:(NSString*)token
55 delegate:(id<GAEMessageHandler>)delegate {
56 NSParameterAssert([token length] > 0);
57 NSParameterAssert(delegate);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058 self = [super init];
59 if (self) {
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000060#if TARGET_OS_IPHONE
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061 _webView = [[UIWebView alloc] init];
62 _webView.delegate = self;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000063#else
64 _webView = [[WebView alloc] init];
65 _webView.policyDelegate = self;
66#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067 _delegate = delegate;
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000068 NSString* htmlPath =
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000069 [[NSBundle mainBundle] pathForResource:@"channel" ofType:@"html"];
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000070 NSURL* htmlUrl = [NSURL fileURLWithPath:htmlPath];
71 NSString* path = [NSString
72 stringWithFormat:@"%@?token=%@", [htmlUrl absoluteString], token];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000073#if TARGET_OS_IPHONE
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074 [_webView
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000075#else
76 [[_webView mainFrame]
77#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078 loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:path]]];
79 }
80 return self;
81}
82
83- (void)dealloc {
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000084#if TARGET_OS_IPHONE
henrike@webrtc.org28e20752013-07-10 00:45:36 +000085 _webView.delegate = nil;
86 [_webView stopLoading];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000087#else
88 _webView.policyDelegate = nil;
89 [[_webView mainFrame] stopLoading];
90#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091}
92
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000093#if TARGET_OS_IPHONE
94#pragma mark - UIWebViewDelegate
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +000095
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +000096- (BOOL)webView:(UIWebView*)webView
97 shouldStartLoadWithRequest:(NSURLRequest*)request
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098 navigationType:(UIWebViewNavigationType)navigationType {
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000099#else
100// WebPolicyDelegate is an informal delegate.
101#pragma mark - WebPolicyDelegate
102
103- (void)webView:(WebView*)webView
104 decidePolicyForNavigationAction:(NSDictionary*)actionInformation
105 request:(NSURLRequest*)request
106 frame:(WebFrame*)frame
107 decisionListener:(id<WebPolicyDecisionListener>)listener {
108#endif
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000109 NSString* scheme = [request.URL scheme];
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +0000110 NSAssert(scheme, @"scheme is nil: %@", request);
111 if (![scheme isEqualToString:@"js-frame"]) {
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000112#if TARGET_OS_IPHONE
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 return YES;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000114#else
115 [listener use];
116 return;
117#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118 }
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000119 dispatch_async(dispatch_get_main_queue(), ^{
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +0000120 NSString* queuedMessage = [webView
121 stringByEvaluatingJavaScriptFromString:@"popQueuedMessage();"];
122 NSAssert([queuedMessage length], @"Empty queued message from JS");
123
124 NSDictionary* queuedMessageDict =
125 [GAEChannelClient jsonStringToDictionary:queuedMessage];
126 NSString* method = queuedMessageDict[@"type"];
127 NSAssert(method, @"Missing method: %@", queuedMessageDict);
128 NSDictionary* payload = queuedMessageDict[@"payload"]; // May be nil.
129
130 if ([method isEqualToString:@"onopen"]) {
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000131 [self.delegate onOpen];
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +0000132 } else if ([method isEqualToString:@"onmessage"]) {
133 NSDictionary* payloadData =
134 [GAEChannelClient jsonStringToDictionary:payload[@"data"]];
135 [self.delegate onMessage:payloadData];
136 } else if ([method isEqualToString:@"onclose"]) {
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000137 [self.delegate onClose];
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +0000138 } else if ([method isEqualToString:@"onerror"]) {
139 NSNumber* codeNumber = payload[@"code"];
140 int code = [codeNumber intValue];
141 NSAssert([codeNumber isEqualToNumber:[NSNumber numberWithInt:code]],
142 @"Unexpected non-integral code: %@", payload);
143 [self.delegate onError:code withDescription:payload[@"description"]];
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000144 } else {
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +0000145 NSAssert(NO, @"Invalid message sent from UIWebView: %@", queuedMessage);
fischman@webrtc.org7fa1fcb2014-03-25 00:11:56 +0000146 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000147 });
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000148#if TARGET_OS_IPHONE
fischman@webrtc.org61e78fc2014-03-31 20:16:49 +0000149 return NO;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000150#else
151 [listener ignore];
152 return;
153#endif
154}
155
156#pragma mark - Private
157
158+ (NSDictionary*)jsonStringToDictionary:(NSString*)str {
159 NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
160 NSError* error;
161 NSDictionary* dict =
162 [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
163 NSAssert(!error, @"Invalid JSON? %@", str);
164 return dict;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000165}
166
167@end