10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2013, Google Inc. 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer. 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * and/or other materials provided with the distribution. 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * derived from this software without specific prior written permission. 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#import "GAEChannelClient.h" 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#import "RTCPeerConnectionFactory.h" 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3252348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#if TARGET_OS_IPHONE 3352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 3452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#import <UIKit/UIKit.h> 3552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 3652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org@interface GAEChannelClient () <UIWebViewDelegate> 3752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 3852348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org@property(nonatomic, strong) UIWebView* webView; 3952348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 4052348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#else 4152348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 4252348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#import <WebKit/WebKit.h> 4352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org@interface GAEChannelClient () 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org@property(nonatomic, strong) WebView* webView; 4752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 4852348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#endif 4952348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org@end 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org@implementation GAEChannelClient 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 54596929a99d1d5191866a038aab5dd451e76213adtkchin@webrtc.org- (instancetype)initWithToken:(NSString*)token 55596929a99d1d5191866a038aab5dd451e76213adtkchin@webrtc.org delegate:(id<GAEMessageHandler>)delegate { 56596929a99d1d5191866a038aab5dd451e76213adtkchin@webrtc.org NSParameterAssert([token length] > 0); 57596929a99d1d5191866a038aab5dd451e76213adtkchin@webrtc.org NSParameterAssert(delegate); 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org self = [super init]; 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (self) { 6052348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#if TARGET_OS_IPHONE 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org _webView = [[UIWebView alloc] init]; 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org _webView.delegate = self; 6352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#else 6452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org _webView = [[WebView alloc] init]; 6552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org _webView.policyDelegate = self; 6652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#endif 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org _delegate = delegate; 68bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org NSString* htmlPath = 6952348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org [[NSBundle mainBundle] pathForResource:@"channel" ofType:@"html"]; 70bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org NSURL* htmlUrl = [NSURL fileURLWithPath:htmlPath]; 71bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org NSString* path = [NSString 72bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org stringWithFormat:@"%@?token=%@", [htmlUrl absoluteString], token]; 7352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#if TARGET_OS_IPHONE 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org [_webView 7552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#else 7652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org [[_webView mainFrame] 7752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#endif 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:path]]]; 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return self; 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org- (void)dealloc { 8452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#if TARGET_OS_IPHONE 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org _webView.delegate = nil; 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org [_webView stopLoading]; 8752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#else 8852348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org _webView.policyDelegate = nil; 8952348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org [[_webView mainFrame] stopLoading]; 9052348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#endif 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 9352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#if TARGET_OS_IPHONE 9452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#pragma mark - UIWebViewDelegate 95d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org 96bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org- (BOOL)webView:(UIWebView*)webView 97bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org shouldStartLoadWithRequest:(NSURLRequest*)request 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org navigationType:(UIWebViewNavigationType)navigationType { 9952348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#else 10052348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org// WebPolicyDelegate is an informal delegate. 10152348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#pragma mark - WebPolicyDelegate 10252348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 10352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org- (void)webView:(WebView*)webView 10452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org decidePolicyForNavigationAction:(NSDictionary*)actionInformation 10552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org request:(NSURLRequest*)request 10652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org frame:(WebFrame*)frame 10752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org decisionListener:(id<WebPolicyDecisionListener>)listener { 10852348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#endif 109bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org NSString* scheme = [request.URL scheme]; 110d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSAssert(scheme, @"scheme is nil: %@", request); 111d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org if (![scheme isEqualToString:@"js-frame"]) { 11252348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#if TARGET_OS_IPHONE 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return YES; 11452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#else 11552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org [listener use]; 11652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org return; 11752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#endif 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 11952348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org dispatch_async(dispatch_get_main_queue(), ^{ 120d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSString* queuedMessage = [webView 121d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org stringByEvaluatingJavaScriptFromString:@"popQueuedMessage();"]; 122d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSAssert([queuedMessage length], @"Empty queued message from JS"); 123d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org 124d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSDictionary* queuedMessageDict = 125d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org [GAEChannelClient jsonStringToDictionary:queuedMessage]; 126d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSString* method = queuedMessageDict[@"type"]; 127d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSAssert(method, @"Missing method: %@", queuedMessageDict); 128d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSDictionary* payload = queuedMessageDict[@"payload"]; // May be nil. 129d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org 130d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org if ([method isEqualToString:@"onopen"]) { 131bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org [self.delegate onOpen]; 132d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org } else if ([method isEqualToString:@"onmessage"]) { 133d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSDictionary* payloadData = 134d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org [GAEChannelClient jsonStringToDictionary:payload[@"data"]]; 135d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org [self.delegate onMessage:payloadData]; 136d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org } else if ([method isEqualToString:@"onclose"]) { 137bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org [self.delegate onClose]; 138d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org } else if ([method isEqualToString:@"onerror"]) { 139d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSNumber* codeNumber = payload[@"code"]; 140d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org int code = [codeNumber intValue]; 141d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSAssert([codeNumber isEqualToNumber:[NSNumber numberWithInt:code]], 142d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org @"Unexpected non-integral code: %@", payload); 143d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org [self.delegate onError:code withDescription:payload[@"description"]]; 144bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org } else { 145d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org NSAssert(NO, @"Invalid message sent from UIWebView: %@", queuedMessage); 146bb288156332dd2e684f0dde156bd984c73da210bfischman@webrtc.org } 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org }); 14852348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#if TARGET_OS_IPHONE 149d1dae16fa01bc5aebc29decaea6901e8b1b75f54fischman@webrtc.org return NO; 15052348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#else 15152348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org [listener ignore]; 15252348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org return; 15352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#endif 15452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org} 15552348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 15652348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org#pragma mark - Private 15752348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org 15852348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org+ (NSDictionary*)jsonStringToDictionary:(NSString*)str { 15952348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding]; 16052348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org NSError* error; 16152348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org NSDictionary* dict = 16252348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; 16352348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org NSAssert(!error, @"Invalid JSON? %@", str); 16452348f6729702ec8888955b7aa5d6b47a4727e6atkchin@webrtc.org return dict; 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org@end 168