diff options
| author | Jules Laplace <jules@okfoc.us> | 2016-11-08 11:46:59 -0500 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2016-11-08 11:46:59 -0500 |
| commit | 5fa81da81260d65113f57a293b6256d334fe8e2d (patch) | |
| tree | 01d3dd7ab7a1febccd20de1756d0801a64ae64e9 /StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m | |
| parent | e5652e9cd560ccda249819857c207643820b075f (diff) | |
| parent | 7773d1d0686de69504e9b820efdb3e94d72eff04 (diff) | |
le build
Diffstat (limited to 'StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m')
| -rwxr-xr-x | StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m | 1065 |
1 files changed, 0 insertions, 1065 deletions
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m deleted file mode 100755 index 6bfabe42..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.m +++ /dev/null @@ -1,1065 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -#import <objc/message.h> -#import "CDV.h" -#import "CDVCommandDelegateImpl.h" -#import "CDVConfigParser.h" -#import "CDVUserAgentUtil.h" -#import "CDVWebViewDelegate.h" -#import <AVFoundation/AVFoundation.h> -#import "CDVHandleOpenURL.h" - -#define degreesToRadian(x) (M_PI * (x) / 180.0) - -@interface CDVViewController () { - NSInteger _userAgentLockToken; - CDVWebViewDelegate* _webViewDelegate; -} - -@property (nonatomic, readwrite, strong) NSXMLParser* configParser; -@property (nonatomic, readwrite, strong) NSMutableDictionary* settings; -@property (nonatomic, readwrite, strong) CDVWhitelist* whitelist; -@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginObjects; -@property (nonatomic, readwrite, strong) NSArray* startupPluginNames; -@property (nonatomic, readwrite, strong) NSDictionary* pluginsMap; -@property (nonatomic, readwrite, strong) NSArray* supportedOrientations; -@property (nonatomic, readwrite, assign) BOOL loadFromString; - -@property (readwrite, assign) BOOL initialized; - -@property (atomic, strong) NSURL* openURL; - -@end - -@implementation CDVViewController - -@synthesize webView, supportedOrientations; -@synthesize pluginObjects, pluginsMap, whitelist, startupPluginNames; -@synthesize configParser, settings, loadFromString; -@synthesize wwwFolderName, startPage, initialized, openURL, baseUserAgent; -@synthesize commandDelegate = _commandDelegate; -@synthesize commandQueue = _commandQueue; - -- (void)__init -{ - if ((self != nil) && !self.initialized) { - _commandQueue = [[CDVCommandQueue alloc] initWithViewController:self]; - _commandDelegate = [[CDVCommandDelegateImpl alloc] initWithViewController:self]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillTerminate:) - name:UIApplicationWillTerminateNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillResignActive:) - name:UIApplicationWillResignActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppWillEnterForeground:) - name:UIApplicationWillEnterForegroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidEnterBackground:) - name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPageDidLoad:) - name:CDVPageDidLoadNotification object:nil]; - - // read from UISupportedInterfaceOrientations (or UISupportedInterfaceOrientations~iPad, if its iPad) from -Info.plist - self.supportedOrientations = [self parseInterfaceOrientations: - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"]]; - - [self printVersion]; - [self printMultitaskingInfo]; - [self printPlatformVersionWarning]; - self.initialized = YES; - - // load config.xml settings - [self loadSettings]; - } -} - -- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil -{ - self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; - [self __init]; - return self; -} - -- (id)initWithCoder:(NSCoder*)aDecoder -{ - self = [super initWithCoder:aDecoder]; - [self __init]; - return self; -} - -- (id)init -{ - self = [super init]; - [self __init]; - return self; -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; -} - -- (void)viewWillDisappear:(BOOL)animated -{ - [super viewWillDisappear:animated]; -} - -- (void)printVersion -{ - NSLog(@"Apache Cordova native platform version %@ is starting.", CDV_VERSION); -} - -- (void)printPlatformVersionWarning -{ - if (!IsAtLeastiOSVersion(@"6.0")) { - NSLog(@"CRITICAL: For Cordova 3.5.0 and above, you will need to upgrade to at least iOS 6.0 or greater. Your current version of iOS is %@.", - [[UIDevice currentDevice] systemVersion] - ); - } -} - -- (void)printMultitaskingInfo -{ - UIDevice* device = [UIDevice currentDevice]; - BOOL backgroundSupported = NO; - - if ([device respondsToSelector:@selector(isMultitaskingSupported)]) { - backgroundSupported = device.multitaskingSupported; - } - - NSNumber* exitsOnSuspend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationExitsOnSuspend"]; - if (exitsOnSuspend == nil) { // if it's missing, it should be NO (i.e. multi-tasking on by default) - exitsOnSuspend = [NSNumber numberWithBool:NO]; - } - - NSLog(@"Multi-tasking -> Device: %@, App: %@", (backgroundSupported ? @"YES" : @"NO"), (![exitsOnSuspend intValue]) ? @"YES" : @"NO"); -} - -- (BOOL)URLisAllowed:(NSURL*)url -{ - if (self.whitelist == nil) { - return YES; - } - - return [self.whitelist URLIsAllowed:url]; -} - -- (void)loadSettings -{ - CDVConfigParser* delegate = [[CDVConfigParser alloc] init]; - - // read from config.xml in the app bundle - NSString* path = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"xml"]; - - if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { - NSAssert(NO, @"ERROR: config.xml does not exist. Please run cordova-ios/bin/cordova_plist_to_config_xml path/to/project."); - return; - } - - NSURL* url = [NSURL fileURLWithPath:path]; - - configParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; - if (configParser == nil) { - NSLog(@"Failed to initialize XML parser."); - return; - } - [configParser setDelegate:((id < NSXMLParserDelegate >)delegate)]; - [configParser parse]; - - // Get the plugin dictionary, whitelist and settings from the delegate. - self.pluginsMap = delegate.pluginsDict; - self.startupPluginNames = delegate.startupPluginNames; - self.whitelist = [[CDVWhitelist alloc] initWithArray:delegate.whitelistHosts]; - self.settings = delegate.settings; - - // And the start folder/page. - self.wwwFolderName = @"www"; - self.startPage = delegate.startPage; - if (self.startPage == nil) { - self.startPage = @"index.html"; - } - - // Initialize the plugin objects dict. - self.pluginObjects = [[NSMutableDictionary alloc] initWithCapacity:20]; -} - -- (NSURL*)appUrl -{ - NSURL* appURL = nil; - - if ([self.startPage rangeOfString:@"://"].location != NSNotFound) { - appURL = [NSURL URLWithString:self.startPage]; - } else if ([self.wwwFolderName rangeOfString:@"://"].location != NSNotFound) { - appURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", self.wwwFolderName, self.startPage]]; - } else { - // CB-3005 strip parameters from start page to check if page exists in resources - NSURL* startURL = [NSURL URLWithString:self.startPage]; - NSString* startFilePath = [self.commandDelegate pathForResource:[startURL path]]; - - if (startFilePath == nil) { - self.loadFromString = YES; - appURL = nil; - } else { - appURL = [NSURL fileURLWithPath:startFilePath]; - // CB-3005 Add on the query params or fragment. - NSString* startPageNoParentDirs = self.startPage; - NSRange r = [startPageNoParentDirs rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"?#"] options:0]; - if (r.location != NSNotFound) { - NSString* queryAndOrFragment = [self.startPage substringFromIndex:r.location]; - appURL = [NSURL URLWithString:queryAndOrFragment relativeToURL:appURL]; - } - } - } - - return appURL; -} - -- (NSURL*)errorUrl -{ - NSURL* errorURL = nil; - - id setting = [self settingForKey:@"ErrorUrl"]; - - if (setting) { - NSString* errorUrlString = (NSString*)setting; - if ([errorUrlString rangeOfString:@"://"].location != NSNotFound) { - errorURL = [NSURL URLWithString:errorUrlString]; - } else { - NSURL* url = [NSURL URLWithString:(NSString*)setting]; - NSString* errorFilePath = [self.commandDelegate pathForResource:[url path]]; - if (errorFilePath) { - errorURL = [NSURL fileURLWithPath:errorFilePath]; - } - } - } - - return errorURL; -} - -// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. -- (void)viewDidLoad -{ - [super viewDidLoad]; - - // // Fix the iOS 5.1 SECURITY_ERR bug (CB-347), this must be before the webView is instantiated //// - - NSString* backupWebStorageType = @"cloud"; // default value - - id backupWebStorage = [self settingForKey:@"BackupWebStorage"]; - if ([backupWebStorage isKindOfClass:[NSString class]]) { - backupWebStorageType = backupWebStorage; - } - [self setSetting:backupWebStorageType forKey:@"BackupWebStorage"]; - - if (IsAtLeastiOSVersion(@"5.1")) { - [CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType]; - } - - // // Instantiate the WebView /////////////// - - if (!self.webView) { - [self createGapView]; - } - - // Configure WebView - _webViewDelegate = [[CDVWebViewDelegate alloc] initWithDelegate:self]; - self.webView.delegate = _webViewDelegate; - - // register this viewcontroller with the NSURLProtocol, only after the User-Agent is set - [CDVURLProtocol registerViewController:self]; - - // ///////////////// - - NSString* enableViewportScale = [self settingForKey:@"EnableViewportScale"]; - NSNumber* allowInlineMediaPlayback = [self settingForKey:@"AllowInlineMediaPlayback"]; - BOOL mediaPlaybackRequiresUserAction = YES; // default value - if ([self settingForKey:@"MediaPlaybackRequiresUserAction"]) { - mediaPlaybackRequiresUserAction = [(NSNumber*)[self settingForKey:@"MediaPlaybackRequiresUserAction"] boolValue]; - } - - self.webView.scalesPageToFit = [enableViewportScale boolValue]; - - /* - * Fire up CDVLocalStorage to work-around WebKit storage limitations: on all iOS 5.1+ versions for local-only backups, but only needed on iOS 5.1 for cloud backup. - */ - if (IsAtLeastiOSVersion(@"5.1") && (([backupWebStorageType isEqualToString:@"local"]) || - ([backupWebStorageType isEqualToString:@"cloud"] && !IsAtLeastiOSVersion(@"6.0")))) { - [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVLocalStorage class])]; - } - - /* - * This is for iOS 4.x, where you can allow inline <video> and <audio>, and also autoplay them - */ - if ([allowInlineMediaPlayback boolValue] && [self.webView respondsToSelector:@selector(allowsInlineMediaPlayback)]) { - self.webView.allowsInlineMediaPlayback = YES; - } - if ((mediaPlaybackRequiresUserAction == NO) && [self.webView respondsToSelector:@selector(mediaPlaybackRequiresUserAction)]) { - self.webView.mediaPlaybackRequiresUserAction = NO; - } - - // By default, overscroll bouncing is allowed. - // UIWebViewBounce has been renamed to DisallowOverscroll, but both are checked. - BOOL bounceAllowed = YES; - NSNumber* disallowOverscroll = [self settingForKey:@"DisallowOverscroll"]; - if (disallowOverscroll == nil) { - NSNumber* bouncePreference = [self settingForKey:@"UIWebViewBounce"]; - bounceAllowed = (bouncePreference == nil || [bouncePreference boolValue]); - } else { - bounceAllowed = ![disallowOverscroll boolValue]; - } - - // prevent webView from bouncing - // based on the DisallowOverscroll/UIWebViewBounce key in config.xml - if (!bounceAllowed) { - if ([self.webView respondsToSelector:@selector(scrollView)]) { - ((UIScrollView*)[self.webView scrollView]).bounces = NO; - } else { - for (id subview in self.webView.subviews) { - if ([[subview class] isSubclassOfClass:[UIScrollView class]]) { - ((UIScrollView*)subview).bounces = NO; - } - } - } - } - - NSString* decelerationSetting = [self settingForKey:@"UIWebViewDecelerationSpeed"]; - if (![@"fast" isEqualToString:decelerationSetting]) { - [self.webView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal]; - } - - /* - * iOS 6.0 UIWebView properties - */ - if (IsAtLeastiOSVersion(@"6.0")) { - BOOL keyboardDisplayRequiresUserAction = YES; // KeyboardDisplayRequiresUserAction - defaults to YES - if ([self settingForKey:@"KeyboardDisplayRequiresUserAction"] != nil) { - if ([self settingForKey:@"KeyboardDisplayRequiresUserAction"]) { - keyboardDisplayRequiresUserAction = [(NSNumber*)[self settingForKey:@"KeyboardDisplayRequiresUserAction"] boolValue]; - } - } - - // property check for compiling under iOS < 6 - if ([self.webView respondsToSelector:@selector(setKeyboardDisplayRequiresUserAction:)]) { - [self.webView setValue:[NSNumber numberWithBool:keyboardDisplayRequiresUserAction] forKey:@"keyboardDisplayRequiresUserAction"]; - } - - BOOL suppressesIncrementalRendering = NO; // SuppressesIncrementalRendering - defaults to NO - if ([self settingForKey:@"SuppressesIncrementalRendering"] != nil) { - if ([self settingForKey:@"SuppressesIncrementalRendering"]) { - suppressesIncrementalRendering = [(NSNumber*)[self settingForKey:@"SuppressesIncrementalRendering"] boolValue]; - } - } - - // property check for compiling under iOS < 6 - if ([self.webView respondsToSelector:@selector(setSuppressesIncrementalRendering:)]) { - [self.webView setValue:[NSNumber numberWithBool:suppressesIncrementalRendering] forKey:@"suppressesIncrementalRendering"]; - } - } - - /* - * iOS 7.0 UIWebView properties - */ - if (IsAtLeastiOSVersion(@"7.0")) { - SEL ios7sel = nil; - id prefObj = nil; - - CGFloat gapBetweenPages = 0.0; // default - prefObj = [self settingForKey:@"GapBetweenPages"]; - if (prefObj != nil) { - gapBetweenPages = [prefObj floatValue]; - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setGapBetweenPages:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithFloat:gapBetweenPages] forKey:@"gapBetweenPages"]; - } - - CGFloat pageLength = 0.0; // default - prefObj = [self settingForKey:@"PageLength"]; - if (prefObj != nil) { - pageLength = [[self settingForKey:@"PageLength"] floatValue]; - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setPageLength:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithBool:pageLength] forKey:@"pageLength"]; - } - - NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage - prefObj = [self settingForKey:@"PaginationBreakingMode"]; - if (prefObj != nil) { - NSArray* validValues = @[@"page", @"column"]; - NSString* prefValue = [validValues objectAtIndex:0]; - - if ([prefObj isKindOfClass:[NSString class]]) { - prefValue = prefObj; - } - - paginationBreakingMode = [validValues indexOfObject:[prefValue lowercaseString]]; - if (paginationBreakingMode == NSNotFound) { - paginationBreakingMode = 0; - } - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setPaginationBreakingMode:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithInteger:paginationBreakingMode] forKey:@"paginationBreakingMode"]; - } - - NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated - prefObj = [self settingForKey:@"PaginationMode"]; - if (prefObj != nil) { - NSArray* validValues = @[@"unpaginated", @"lefttoright", @"toptobottom", @"bottomtotop", @"righttoleft"]; - NSString* prefValue = [validValues objectAtIndex:0]; - - if ([prefObj isKindOfClass:[NSString class]]) { - prefValue = prefObj; - } - - paginationMode = [validValues indexOfObject:[prefValue lowercaseString]]; - if (paginationMode == NSNotFound) { - paginationMode = 0; - } - } - - // property check for compiling under iOS < 7 - ios7sel = NSSelectorFromString(@"setPaginationMode:"); - if ([self.webView respondsToSelector:ios7sel]) { - [self.webView setValue:[NSNumber numberWithInteger:paginationMode] forKey:@"paginationMode"]; - } - } - - if ([self.startupPluginNames count] > 0) { - [CDVTimer start:@"TotalPluginStartup"]; - - for (NSString* pluginName in self.startupPluginNames) { - [CDVTimer start:pluginName]; - [self getCommandInstance:pluginName]; - [CDVTimer stop:pluginName]; - } - - [CDVTimer stop:@"TotalPluginStartup"]; - } - - [self registerPlugin:[[CDVHandleOpenURL alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVHandleOpenURL class])]; - - // ///////////////// - NSURL* appURL = [self appUrl]; - - [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) { - _userAgentLockToken = lockToken; - [CDVUserAgentUtil setUserAgent:self.userAgent lockToken:lockToken]; - if (appURL) { - NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0]; - [self.webView loadRequest:appReq]; - } else { - NSString* loadErr = [NSString stringWithFormat:@"ERROR: Start Page at '%@/%@' was not found.", self.wwwFolderName, self.startPage]; - NSLog(@"%@", loadErr); - - NSURL* errorUrl = [self errorUrl]; - if (errorUrl) { - errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [loadErr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl]; - NSLog(@"%@", [errorUrl absoluteString]); - [self.webView loadRequest:[NSURLRequest requestWithURL:errorUrl]]; - } else { - NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr]; - [self.webView loadHTMLString:html baseURL:nil]; - } - } - }]; -} - -- (id)settingForKey:(NSString*)key -{ - return [[self settings] objectForKey:[key lowercaseString]]; -} - -- (void)setSetting:(id)setting forKey:(NSString*)key -{ - [[self settings] setObject:setting forKey:[key lowercaseString]]; -} - -- (NSArray*)parseInterfaceOrientations:(NSArray*)orientations -{ - NSMutableArray* result = [[NSMutableArray alloc] init]; - - if (orientations != nil) { - NSEnumerator* enumerator = [orientations objectEnumerator]; - NSString* orientationString; - - while (orientationString = [enumerator nextObject]) { - if ([orientationString isEqualToString:@"UIInterfaceOrientationPortrait"]) { - [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]]; - } else if ([orientationString isEqualToString:@"UIInterfaceOrientationPortraitUpsideDown"]) { - [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown]]; - } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeLeft"]) { - [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]]; - } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeRight"]) { - [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]]; - } - } - } - - // default - if ([result count] == 0) { - [result addObject:[NSNumber numberWithInt:UIInterfaceOrientationPortrait]]; - } - - return result; -} - -- (NSInteger)mapIosOrientationToJsOrientation:(UIInterfaceOrientation)orientation -{ - switch (orientation) { - case UIInterfaceOrientationPortraitUpsideDown: - return 180; - - case UIInterfaceOrientationLandscapeLeft: - return -90; - - case UIInterfaceOrientationLandscapeRight: - return 90; - - case UIInterfaceOrientationPortrait: - return 0; - - default: - return 0; - } -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - // First, ask the webview via JS if it supports the new orientation - NSString* jsCall = [NSString stringWithFormat: - @"window.shouldRotateToOrientation && window.shouldRotateToOrientation(%ld);" - , (long)[self mapIosOrientationToJsOrientation:interfaceOrientation]]; - NSString* res = [webView stringByEvaluatingJavaScriptFromString:jsCall]; - - if ([res length] > 0) { - return [res boolValue]; - } - - // if js did not handle the new orientation (no return value), use values from the plist (via supportedOrientations) - return [self supportsOrientation:interfaceOrientation]; -} - -- (BOOL)shouldAutorotate -{ - return YES; -} - -- (NSUInteger)supportedInterfaceOrientations -{ - NSUInteger ret = 0; - - if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) { - ret = ret | (1 << UIInterfaceOrientationPortrait); - } - if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortraitUpsideDown]) { - ret = ret | (1 << UIInterfaceOrientationPortraitUpsideDown); - } - if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight]) { - ret = ret | (1 << UIInterfaceOrientationLandscapeRight); - } - if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft]) { - ret = ret | (1 << UIInterfaceOrientationLandscapeLeft); - } - - return ret; -} - -- (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation -{ - return [self.supportedOrientations containsObject:[NSNumber numberWithInt:orientation]]; -} - -- (UIWebView*)newCordovaViewWithFrame:(CGRect)bounds -{ - return [[UIWebView alloc] initWithFrame:bounds]; -} - -- (NSString*)userAgent -{ - if (_userAgent != nil) { - return _userAgent; - } - - NSString* localBaseUserAgent; - if (self.baseUserAgent != nil) { - localBaseUserAgent = self.baseUserAgent; - } else if ([self settingForKey:@"OverrideUserAgent"] != nil) { - localBaseUserAgent = [self settingForKey:@"OverrideUserAgent"]; - } else { - localBaseUserAgent = [CDVUserAgentUtil originalUserAgent]; - } - NSString* appendUserAgent = [self settingForKey:@"AppendUserAgent"]; - if (appendUserAgent) { - _userAgent = [NSString stringWithFormat:@"%@ %@", localBaseUserAgent, appendUserAgent]; - } else { - // Use our address as a unique number to append to the User-Agent. - _userAgent = [NSString stringWithFormat:@"%@ (%lld)", localBaseUserAgent, (long long)self]; - } - return _userAgent; -} - -- (void)createGapView -{ - CGRect webViewBounds = self.view.bounds; - - webViewBounds.origin = self.view.bounds.origin; - - self.webView = [self newCordovaViewWithFrame:webViewBounds]; - self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); - - [self.view addSubview:self.webView]; - [self.view sendSubviewToBack:self.webView]; -} - -- (void)didReceiveMemoryWarning -{ - // iterate through all the plugin objects, and call hasPendingOperation - // if at least one has a pending operation, we don't call [super didReceiveMemoryWarning] - - NSEnumerator* enumerator = [self.pluginObjects objectEnumerator]; - CDVPlugin* plugin; - - BOOL doPurge = YES; - - while ((plugin = [enumerator nextObject])) { - if (plugin.hasPendingOperation) { - NSLog(@"Plugin '%@' has a pending operation, memory purge is delayed for didReceiveMemoryWarning.", NSStringFromClass([plugin class])); - doPurge = NO; - } - } - - if (doPurge) { - // Releases the view if it doesn't have a superview. - [super didReceiveMemoryWarning]; - } - - // Release any cached data, images, etc. that aren't in use. -} - -- (void)viewDidUnload -{ - // Release any retained subviews of the main view. - // e.g. self.myOutlet = nil; - - self.webView.delegate = nil; - self.webView = nil; - [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; - - [super viewDidUnload]; -} - -#pragma mark UIWebViewDelegate - -/** - When web application loads Add stuff to the DOM, mainly the user-defined settings from the Settings.plist file, and - the device's data such as device ID, platform version, etc. - */ -- (void)webViewDidStartLoad:(UIWebView*)theWebView -{ - NSLog(@"Resetting plugins due to page load."); - [_commandQueue resetRequestId]; - [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:self.webView]]; -} - -/** - Called when the webview finishes loading. This stops the activity view. - */ -- (void)webViewDidFinishLoad:(UIWebView*)theWebView -{ - NSLog(@"Finished load of: %@", theWebView.request.URL); - // It's safe to release the lock even if this is just a sub-frame that's finished loading. - [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; - - /* - * Hide the Top Activity THROBBER in the Battery Bar - */ - [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; - - [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:self.webView]]; -} - -- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error -{ - [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; - - NSString* message = [NSString stringWithFormat:@"Failed to load webpage with error: %@", [error localizedDescription]]; - NSLog(@"%@", message); - - NSURL* errorUrl = [self errorUrl]; - if (errorUrl) { - errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [message stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl]; - NSLog(@"%@", [errorUrl absoluteString]); - [theWebView loadRequest:[NSURLRequest requestWithURL:errorUrl]]; - } -} - -- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType -{ - NSURL* url = [request URL]; - - /* - * Execute any commands queued with cordova.exec() on the JS side. - * The part of the URL after gap:// is irrelevant. - */ - if ([[url scheme] isEqualToString:@"gap"]) { - [_commandQueue fetchCommandsFromJs]; - // The delegate is called asynchronously in this case, so we don't have to use - // flushCommandQueueWithDelayedJs (setTimeout(0)) as we do with hash changes. - [_commandQueue executePending]; - return NO; - } - - if ([[url fragment] hasPrefix:@"%01"] || [[url fragment] hasPrefix:@"%02"]) { - // Delegate is called *immediately* for hash changes. This means that any - // calls to stringByEvaluatingJavascriptFromString will occur in the middle - // of an existing (paused) call stack. This doesn't cause errors, but may - // be unexpected to callers (exec callbacks will be called before exec() even - // returns). To avoid this, we do not do any synchronous JS evals by using - // flushCommandQueueWithDelayedJs. - NSString* inlineCommands = [[url fragment] substringFromIndex:3]; - if ([inlineCommands length] == 0) { - // Reach in right away since the WebCore / Main thread are already synchronized. - [_commandQueue fetchCommandsFromJs]; - } else { - inlineCommands = [inlineCommands stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - [_commandQueue enqueueCommandBatch:inlineCommands]; - } - // Switch these for minor performance improvements, and to really live on the wild side. - // Callbacks will occur in the middle of the location.hash = ... statement! - [(CDVCommandDelegateImpl*)_commandDelegate flushCommandQueueWithDelayedJs]; - // [_commandQueue executePending]; - - // Although we return NO, the hash change does end up taking effect. - return NO; - } - - /* - * Give plugins the chance to handle the url - */ - for (NSString* pluginName in pluginObjects) { - CDVPlugin* plugin = [pluginObjects objectForKey:pluginName]; - SEL selector = NSSelectorFromString(@"shouldOverrideLoadWithRequest:navigationType:"); - if ([plugin respondsToSelector:selector]) { - if (((BOOL (*)(id, SEL, id, int))objc_msgSend)(plugin, selector, request, navigationType) == YES) { - return NO; - } - } - } - - /* - * If a URL is being loaded that's a file/http/https URL, just load it internally - */ - if ([url isFileURL]) { - return YES; - } - - /* - * If we loaded the HTML from a string, we let the app handle it - */ - else if (self.loadFromString == YES) { - self.loadFromString = NO; - return YES; - } - - /* - * all tel: scheme urls we let the UIWebview handle it using the default behavior - */ - else if ([[url scheme] isEqualToString:@"tel"]) { - return YES; - } - - /* - * all about: scheme urls are not handled - */ - else if ([[url scheme] isEqualToString:@"about"]) { - return NO; - } - - /* - * all data: scheme urls are handled - */ - else if ([[url scheme] isEqualToString:@"data"]) { - return YES; - } - - /* - * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview. - */ - else { - if ([self.whitelist schemeIsAllowed:[url scheme]]) { - return [self.whitelist URLIsAllowed:url]; - } else { - if ([[UIApplication sharedApplication] canOpenURL:url]) { - [[UIApplication sharedApplication] openURL:url]; - } else { // handle any custom schemes to plugins - [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]]; - } - } - - return NO; - } - - return YES; -} - -#pragma mark GapHelpers - -- (void)javascriptAlert:(NSString*)text -{ - NSString* jsString = [NSString stringWithFormat:@"alert('%@');", text]; - - [self.commandDelegate evalJs:jsString]; -} - -+ (NSString*)applicationDocumentsDirectory -{ - NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString* basePath = (([paths count] > 0) ? ([paths objectAtIndex : 0]) : nil); - - return basePath; -} - -#pragma mark CordovaCommands - -- (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className -{ - if ([plugin respondsToSelector:@selector(setViewController:)]) { - [plugin setViewController:self]; - } - - if ([plugin respondsToSelector:@selector(setCommandDelegate:)]) { - [plugin setCommandDelegate:_commandDelegate]; - } - - [self.pluginObjects setObject:plugin forKey:className]; - [plugin pluginInitialize]; -} - -- (void)registerPlugin:(CDVPlugin*)plugin withPluginName:(NSString*)pluginName -{ - if ([plugin respondsToSelector:@selector(setViewController:)]) { - [plugin setViewController:self]; - } - - if ([plugin respondsToSelector:@selector(setCommandDelegate:)]) { - [plugin setCommandDelegate:_commandDelegate]; - } - - NSString* className = NSStringFromClass([plugin class]); - [self.pluginObjects setObject:plugin forKey:className]; - [self.pluginsMap setValue:className forKey:[pluginName lowercaseString]]; - [plugin pluginInitialize]; -} - -/** - Returns an instance of a CordovaCommand object, based on its name. If one exists already, it is returned. - */ -- (id)getCommandInstance:(NSString*)pluginName -{ - // first, we try to find the pluginName in the pluginsMap - // (acts as a whitelist as well) if it does not exist, we return nil - // NOTE: plugin names are matched as lowercase to avoid problems - however, a - // possible issue is there can be duplicates possible if you had: - // "org.apache.cordova.Foo" and "org.apache.cordova.foo" - only the lower-cased entry will match - NSString* className = [self.pluginsMap objectForKey:[pluginName lowercaseString]]; - - if (className == nil) { - return nil; - } - - id obj = [self.pluginObjects objectForKey:className]; - if (!obj) { - obj = [[NSClassFromString(className)alloc] initWithWebView:webView]; - - if (obj != nil) { - [self registerPlugin:obj withClassName:className]; - } else { - NSLog(@"CDVPlugin class %@ (pluginName: %@) does not exist.", className, pluginName); - } - } - return obj; -} - -#pragma mark - - -- (NSString*)appURLScheme -{ - NSString* URLScheme = nil; - - NSArray* URLTypes = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleURLTypes"]; - - if (URLTypes != nil) { - NSDictionary* dict = [URLTypes objectAtIndex:0]; - if (dict != nil) { - NSArray* URLSchemes = [dict objectForKey:@"CFBundleURLSchemes"]; - if (URLSchemes != nil) { - URLScheme = [URLSchemes objectAtIndex:0]; - } - } - } - - return URLScheme; -} - -/** - Returns the contents of the named plist bundle, loaded as a dictionary object - */ -+ (NSDictionary*)getBundlePlist:(NSString*)plistName -{ - NSString* errorDesc = nil; - NSPropertyListFormat format; - NSString* plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:@"plist"]; - NSData* plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath]; - NSDictionary* temp = (NSDictionary*)[NSPropertyListSerialization - propertyListFromData:plistXML - mutabilityOption:NSPropertyListMutableContainersAndLeaves - format:&format errorDescription:&errorDesc]; - - return temp; -} - -#pragma mark - -#pragma mark UIApplicationDelegate impl - -/* - This method lets your application know that it is about to be terminated and purged from memory entirely - */ -- (void)onAppWillTerminate:(NSNotification*)notification -{ - // empty the tmp directory - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - NSError* __autoreleasing err = nil; - - // clear contents of NSTemporaryDirectory - NSString* tempDirectoryPath = NSTemporaryDirectory(); - NSDirectoryEnumerator* directoryEnumerator = [fileMgr enumeratorAtPath:tempDirectoryPath]; - NSString* fileName = nil; - BOOL result; - - while ((fileName = [directoryEnumerator nextObject])) { - NSString* filePath = [tempDirectoryPath stringByAppendingPathComponent:fileName]; - result = [fileMgr removeItemAtPath:filePath error:&err]; - if (!result && err) { - NSLog(@"Failed to delete: %@ (error: %@)", filePath, err); - } - } -} - -/* - This method is called to let your application know that it is about to move from the active to inactive state. - You should use this method to pause ongoing tasks, disable timer, ... - */ -- (void)onAppWillResignActive:(NSNotification*)notification -{ - // NSLog(@"%@",@"applicationWillResignActive"); - [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('resign');" scheduledOnRunLoop:NO]; -} - -/* - In iOS 4.0 and later, this method is called as part of the transition from the background to the inactive state. - You can use this method to undo many of the changes you made to your application upon entering the background. - invariably followed by applicationDidBecomeActive - */ -- (void)onAppWillEnterForeground:(NSNotification*)notification -{ - // NSLog(@"%@",@"applicationWillEnterForeground"); - [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('resume');"]; - - /** Clipboard fix **/ - UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; - NSString *string = pasteboard.string; - if (string) { - [pasteboard setValue:string forPasteboardType:@"public.text"]; - } -} - -// This method is called to let your application know that it moved from the inactive to active state. -- (void)onAppDidBecomeActive:(NSNotification*)notification -{ - // NSLog(@"%@",@"applicationDidBecomeActive"); - [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('active');"]; -} - -/* - In iOS 4.0 and later, this method is called instead of the applicationWillTerminate: method - when the user quits an application that supports background execution. - */ -- (void)onAppDidEnterBackground:(NSNotification*)notification -{ - // NSLog(@"%@",@"applicationDidEnterBackground"); - [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('pause', null, true);" scheduledOnRunLoop:NO]; -} - -// /////////////////////// - -- (void)onPageDidLoad:(NSNotification*)notification -{ - if (self.openURL) { - [self processOpenUrl:self.openURL pageLoaded:YES]; - self.openURL = nil; - } -} - -- (void)processOpenUrl:(NSURL*)url pageLoaded:(BOOL)pageLoaded -{ - if (!pageLoaded) { - // query the webview for readystate - NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; - pageLoaded = [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"]; - } - - if (pageLoaded) { - // calls into javascript global function 'handleOpenURL' - NSString* jsString = [NSString stringWithFormat:@"if (typeof handleOpenURL === 'function') { handleOpenURL(\"%@\");}", url]; - [self.webView stringByEvaluatingJavaScriptFromString:jsString]; - } else { - // save for when page has loaded - self.openURL = url; - } -} - -- (void)processOpenUrl:(NSURL*)url -{ - [self processOpenUrl:url pageLoaded:NO]; -} - -// /////////////////////// - -- (void)dealloc -{ - [CDVURLProtocol unregisterViewController:self]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - self.webView.delegate = nil; - self.webView = nil; - [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; - [_commandQueue dispose]; - [[self.pluginObjects allValues] makeObjectsPerformSelector:@selector(dispose)]; -} - -@end |
