diff options
Diffstat (limited to 'StoneIsland/platforms/ios/CordovaLib/Classes')
62 files changed, 2009 insertions, 2255 deletions
diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailabilityDeprecated.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailabilityDeprecated.h deleted file mode 100755 index 216b4c1d..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailabilityDeprecated.h +++ /dev/null @@ -1,38 +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 <UIKit/UIKit.h> - -#ifdef __clang__ -#define CDV_DEPRECATED(version, msg) __attribute__((deprecated("Deprecated in Cordova " #version ". " msg))) -#else -#define CDV_DEPRECATED(version, msg) __attribute__((deprecated())) -#endif - -static inline BOOL CDV_IsIPad(void) CDV_DEPRECATED(3.7.0, "This will be removed in 4.0.0"); -static inline BOOL CDV_IsIPhone5(void) CDV_DEPRECATED(3.7.0, "This will be removed in 4.0.0"); - -static inline BOOL CDV_IsIPad(void) { - return [[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad; -} - -static inline BOOL CDV_IsIPhone5(void) { - return ([[UIScreen mainScreen] bounds].size.width == 568 && [[UIScreen mainScreen] bounds].size.height == 320) || ([[UIScreen mainScreen] bounds].size.height == 568 && [[UIScreen mainScreen] bounds].size.width == 320); -}
\ No newline at end of file diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.h b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.h deleted file mode 100755 index ede708f9..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.h +++ /dev/null @@ -1,37 +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 "CDVAvailabilityDeprecated.h" - -@interface NSArray (CDVJSONSerializing) -- (NSString*)JSONString CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead."); - -@end - -@interface NSDictionary (CDVJSONSerializing) -- (NSString*)JSONString CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead."); - -@end - -@interface NSString (CDVJSONSerializing) -- (id)JSONObject CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead."); - -- (id)JSONFragment CDV_DEPRECATED(3.8 .0, "Use NSJSONSerialization instead."); - -@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.m b/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.m deleted file mode 100755 index fce5783a..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.m +++ /dev/null @@ -1,213 +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 <AssetsLibrary/ALAsset.h> -#import <AssetsLibrary/ALAssetRepresentation.h> -#import <AssetsLibrary/ALAssetsLibrary.h> -#import <MobileCoreServices/MobileCoreServices.h> -#import "CDVURLProtocol.h" -#import "CDVCommandQueue.h" -#import "CDVWhitelist.h" -#import "CDVViewController.h" - -static CDVWhitelist* gWhitelist = nil; -// Contains a set of NSNumbers of addresses of controllers. It doesn't store -// the actual pointer to avoid retaining. -static NSMutableSet* gRegisteredControllers = nil; - -NSString* const kCDVAssetsLibraryPrefixes = @"assets-library://"; - -// Returns the registered view controller that sent the given request. -// If the user-agent is not from a UIWebView, or if it's from an unregistered one, -// then nil is returned. -static CDVViewController *viewControllerForRequest(NSURLRequest* request) -{ - // The exec bridge explicitly sets the VC address in a header. - // This works around the User-Agent not being set for file: URLs. - NSString* addrString = [request valueForHTTPHeaderField:@"vc"]; - - if (addrString == nil) { - NSString* userAgent = [request valueForHTTPHeaderField:@"User-Agent"]; - if (userAgent == nil) { - return nil; - } - NSUInteger bracketLocation = [userAgent rangeOfString:@"(" options:NSBackwardsSearch].location; - if (bracketLocation == NSNotFound) { - return nil; - } - addrString = [userAgent substringFromIndex:bracketLocation + 1]; - } - - long long viewControllerAddress = [addrString longLongValue]; - @synchronized(gRegisteredControllers) { - if (![gRegisteredControllers containsObject:[NSNumber numberWithLongLong:viewControllerAddress]]) { - return nil; - } - } - - return (__bridge CDVViewController*)(void*)viewControllerAddress; -} - -@implementation CDVURLProtocol - -+ (void)registerPGHttpURLProtocol {} - -+ (void)registerURLProtocol {} - -// Called to register the URLProtocol, and to make it away of an instance of -// a ViewController. -+ (void)registerViewController:(CDVViewController*)viewController -{ - if (gRegisteredControllers == nil) { - [NSURLProtocol registerClass:[CDVURLProtocol class]]; - gRegisteredControllers = [[NSMutableSet alloc] initWithCapacity:8]; - // The whitelist doesn't change, so grab the first one and store it. - gWhitelist = viewController.whitelist; - - // Note that we grab the whitelist from the first viewcontroller for now - but this will change - // when we allow a registered viewcontroller to have its own whitelist (e.g InAppBrowser) - // Differentiating the requests will be through the 'vc' http header below as used for the js->objc bridge. - // The 'vc' value is generated by casting the viewcontroller object to a (long long) value (see CDVViewController::webViewDidFinishLoad) - if (gWhitelist == nil) { - NSLog(@"WARNING: NO whitelist has been set in CDVURLProtocol."); - } - } - - @synchronized(gRegisteredControllers) { - [gRegisteredControllers addObject:[NSNumber numberWithLongLong:(long long)viewController]]; - } -} - -+ (void)unregisterViewController:(CDVViewController*)viewController -{ - @synchronized(gRegisteredControllers) { - [gRegisteredControllers removeObject:[NSNumber numberWithLongLong:(long long)viewController]]; - } -} - -+ (BOOL)canInitWithRequest:(NSURLRequest*)theRequest -{ - NSURL* theUrl = [theRequest URL]; - CDVViewController* viewController = viewControllerForRequest(theRequest); - - if ([[theUrl absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) { - return YES; - } else if (viewController != nil) { - if ([[theUrl path] isEqualToString:@"/!gap_exec"]) { - NSString* queuedCommandsJSON = [theRequest valueForHTTPHeaderField:@"cmds"]; - NSString* requestId = [theRequest valueForHTTPHeaderField:@"rc"]; - if (requestId == nil) { - NSLog(@"!cordova request missing rc header"); - return NO; - } - BOOL hasCmds = [queuedCommandsJSON length] > 0; - if (hasCmds) { - SEL sel = @selector(enqueueCommandBatch:); - [viewController.commandQueue performSelectorOnMainThread:sel withObject:queuedCommandsJSON waitUntilDone:NO]; - [viewController.commandQueue performSelectorOnMainThread:@selector(executePending) withObject:nil waitUntilDone:NO]; - } else { - SEL sel = @selector(processXhrExecBridgePoke:); - [viewController.commandQueue performSelectorOnMainThread:sel withObject:[NSNumber numberWithInteger:[requestId integerValue]] waitUntilDone:NO]; - } - // Returning NO here would be 20% faster, but it spams WebInspector's console with failure messages. - // If JS->Native bridge speed is really important for an app, they should use the iframe bridge. - // Returning YES here causes the request to come through canInitWithRequest two more times. - // For this reason, we return NO when cmds exist. - return !hasCmds; - } - // we only care about http and https connections. - // CORS takes care of http: trying to access file: URLs. - if ([gWhitelist schemeIsAllowed:[theUrl scheme]]) { - // if it FAILS the whitelist, we return TRUE, so we can fail the connection later - return ![gWhitelist URLIsAllowed:theUrl]; - } - } - - return NO; -} - -+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request -{ - // NSLog(@"%@ received %@", self, NSStringFromSelector(_cmd)); - return request; -} - -- (void)startLoading -{ - // NSLog(@"%@ received %@ - start", self, NSStringFromSelector(_cmd)); - NSURL* url = [[self request] URL]; - - if ([[url path] isEqualToString:@"/!gap_exec"]) { - [self sendResponseWithResponseCode:200 data:nil mimeType:nil]; - return; - } else if ([[url absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) { - ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) { - if (asset) { - // We have the asset! Get the data and send it along. - ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation]; - NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType); - Byte* buffer = (Byte*)malloc((unsigned long)[assetRepresentation size]); - NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:(NSUInteger)[assetRepresentation size] error:nil]; - NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES]; - [self sendResponseWithResponseCode:200 data:data mimeType:MIMEType]; - } else { - // Retrieving the asset failed for some reason. Send an error. - [self sendResponseWithResponseCode:404 data:nil mimeType:nil]; - } - }; - ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) { - // Retrieving the asset failed for some reason. Send an error. - [self sendResponseWithResponseCode:401 data:nil mimeType:nil]; - }; - - ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init]; - [assetsLibrary assetForURL:url resultBlock:resultBlock failureBlock:failureBlock]; - return; - } - - NSString* body = [gWhitelist errorStringForURL:url]; - [self sendResponseWithResponseCode:401 data:[body dataUsingEncoding:NSASCIIStringEncoding] mimeType:nil]; -} - -- (void)stopLoading -{ - // do any cleanup here -} - -+ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB -{ - return NO; -} - -- (void)sendResponseWithResponseCode:(NSInteger)statusCode data:(NSData*)data mimeType:(NSString*)mimeType -{ - if (mimeType == nil) { - mimeType = @"text/plain"; - } - - NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL] statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:@{@"Content-Type" : mimeType}]; - - [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; - if (data != nil) { - [[self client] URLProtocol:self didLoadData:data]; - } - [[self client] URLProtocolDidFinishLoading:self]; -} - -@end 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 diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.h b/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.h deleted file mode 100755 index 1633a72b..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// NSData+Base64.h -// base64 -// -// Created by Matt Gallagher on 2009/06/03. -// Copyright 2009 Matt Gallagher. All rights reserved. -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. Permission is granted to anyone to -// use this software for any purpose, including commercial applications, and to -// alter it and redistribute it freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source -// distribution. -// - -#import <Foundation/Foundation.h> -#import "CDVAvailabilityDeprecated.h" - -void *CDVNewBase64Decode( - const char* inputBuffer, - size_t length, - size_t * outputLength); - -char *CDVNewBase64Encode( - const void* inputBuffer, - size_t length, - bool separateLines, - size_t * outputLength); - -@interface NSData (CDVBase64) - -+ (NSData*)dataFromBase64String:(NSString*)aString CDV_DEPRECATED(3.8 .0, "Use cdv_dataFromBase64String"); - -- (NSString*)base64EncodedString CDV_DEPRECATED(3.8 .0, "Use [NSData cdv_base64EncodedString]"); - -+ (NSData*)cdv_dataFromBase64String:(NSString*)aString CDV_DEPRECATED(3.9.2, "Use NSData initWithBase64EncodedString instead. This will be removed in 4.0.0"); -- (NSString*)cdv_base64EncodedString CDV_DEPRECATED(3.9.2, "Use NSData base64EncodedStringWithOptions instead. This will be removed in 4.0.0"); - -@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.m b/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.m deleted file mode 100755 index 634dff67..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSData+Base64.m +++ /dev/null @@ -1,308 +0,0 @@ -// -// NSData+Base64.m -// base64 -// -// Created by Matt Gallagher on 2009/06/03. -// Copyright 2009 Matt Gallagher. All rights reserved. -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. Permission is granted to anyone to -// use this software for any purpose, including commercial applications, and to -// alter it and redistribute it freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source -// distribution. -// - -#import "NSData+Base64.h" - -// -// Mapping from 6 bit pattern to ASCII character. -// -static unsigned char base64EncodeLookup[65] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -// -// Definition for "masked-out" areas of the base64DecodeLookup mapping -// -#define xx 65 - -// -// Mapping from ASCII character to 6 bit pattern. -// -static unsigned char base64DecodeLookup[256] = -{ - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, - xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx, - xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, - xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, -}; - -// -// Fundamental sizes of the binary and base64 encode/decode units in bytes -// -#define BINARY_UNIT_SIZE 3 -#define BASE64_UNIT_SIZE 4 - -// -// NewBase64Decode -// -// Decodes the base64 ASCII string in the inputBuffer to a newly malloced -// output buffer. -// -// inputBuffer - the source ASCII string for the decode -// length - the length of the string or -1 (to specify strlen should be used) -// outputLength - if not-NULL, on output will contain the decoded length -// -// returns the decoded buffer. Must be free'd by caller. Length is given by -// outputLength. -// -void *CDVNewBase64Decode( - const char* inputBuffer, - size_t length, - size_t * outputLength) -{ - if (length == -1) { - length = strlen(inputBuffer); - } - - size_t outputBufferSize = - ((length + BASE64_UNIT_SIZE - 1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE; - unsigned char* outputBuffer = (unsigned char*)malloc(outputBufferSize); - - size_t i = 0; - size_t j = 0; - - while (i < length) { - // - // Accumulate 4 valid characters (ignore everything else) - // - unsigned char accumulated[BASE64_UNIT_SIZE]; - size_t accumulateIndex = 0; - - while (i < length) { - unsigned char decode = base64DecodeLookup[inputBuffer[i++]]; - if (decode != xx) { - accumulated[accumulateIndex] = decode; - accumulateIndex++; - - if (accumulateIndex == BASE64_UNIT_SIZE) { - break; - } - } - } - - // - // Store the 6 bits from each of the 4 characters as 3 bytes - // - // (Uses improved bounds checking suggested by Alexandre Colucci) - // - if (accumulateIndex >= 2) { - outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4); - } - if (accumulateIndex >= 3) { - outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2); - } - if (accumulateIndex >= 4) { - outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3]; - } - j += accumulateIndex - 1; - } - - if (outputLength) { - *outputLength = j; - } - return outputBuffer; -} - -// -// NewBase64Encode -// -// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced -// output buffer. -// -// inputBuffer - the source data for the encode -// length - the length of the input in bytes -// separateLines - if zero, no CR/LF characters will be added. Otherwise -// a CR/LF pair will be added every 64 encoded chars. -// outputLength - if not-NULL, on output will contain the encoded length -// (not including terminating 0 char) -// -// returns the encoded buffer. Must be free'd by caller. Length is given by -// outputLength. -// -char *CDVNewBase64Encode( - const void* buffer, - size_t length, - bool separateLines, - size_t * outputLength) -{ - const unsigned char* inputBuffer = (const unsigned char*)buffer; - -#define MAX_NUM_PADDING_CHARS 2 -#define OUTPUT_LINE_LENGTH 64 -#define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE) -#define CR_LF_SIZE 2 - - // - // Byte accurate calculation of final buffer size - // - size_t outputBufferSize = - ((length / BINARY_UNIT_SIZE) - + ((length % BINARY_UNIT_SIZE) ? 1 : 0)) - * BASE64_UNIT_SIZE; - if (separateLines) { - outputBufferSize += - (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE; - } - - // - // Include space for a terminating zero - // - outputBufferSize += 1; - - // - // Allocate the output buffer - // - char* outputBuffer = (char*)malloc(outputBufferSize); - if (!outputBuffer) { - return NULL; - } - - size_t i = 0; - size_t j = 0; - const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length; - size_t lineEnd = lineLength; - - while (true) { - if (lineEnd > length) { - lineEnd = length; - } - - for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE) { - // - // Inner loop: turn 48 bytes into 64 base64 characters - // - outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; - outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) - | ((inputBuffer[i + 1] & 0xF0) >> 4)]; - outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2) - | ((inputBuffer[i + 2] & 0xC0) >> 6)]; - outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F]; - } - - if (lineEnd == length) { - break; - } - - // - // Add the newline - // - // outputBuffer[j++] = '\r'; - // outputBuffer[j++] = '\n'; - lineEnd += lineLength; - } - - if (i + 1 < length) { - // - // Handle the single '=' case - // - outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; - outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) - | ((inputBuffer[i + 1] & 0xF0) >> 4)]; - outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2]; - outputBuffer[j++] = '='; - } else if (i < length) { - // - // Handle the double '=' case - // - outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; - outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4]; - outputBuffer[j++] = '='; - outputBuffer[j++] = '='; - } - outputBuffer[j] = 0; - - // - // Set the output length and return the buffer - // - if (outputLength) { - *outputLength = j; - } - return outputBuffer; -} - -@implementation NSData (CDVBase64) - -// -// dataFromBase64String: -// -// Creates an NSData object containing the base64 decoded representation of -// the base64 string 'aString' -// -// Parameters: -// aString - the base64 string to decode -// -// returns the autoreleased NSData representation of the base64 string -// -+ (NSData*)cdv_dataFromBase64String:(NSString*)aString -{ - size_t outputLength = 0; - void* outputBuffer = CDVNewBase64Decode([aString UTF8String], [aString length], &outputLength); - - return [NSData dataWithBytesNoCopy:outputBuffer length:outputLength freeWhenDone:YES]; -} - -// -// base64EncodedString -// -// Creates an NSString object that contains the base 64 encoding of the -// receiver's data. Lines are broken at 64 characters long. -// -// returns an autoreleased NSString being the base 64 representation of the -// receiver. -// -- (NSString*)cdv_base64EncodedString -{ - size_t outputLength = 0; - char* outputBuffer = - CDVNewBase64Encode([self bytes], [self length], true, &outputLength); - - NSString* result = [[NSString alloc] initWithBytesNoCopy:outputBuffer - length:outputLength - encoding:NSASCIIStringEncoding - freeWhenDone:YES]; - - return result; -} - -+ (NSData*)dataFromBase64String:(NSString*)aString -{ - return [self cdv_dataFromBase64String:aString]; -} - -- (NSString*)base64EncodedString -{ - return [self cdv_base64EncodedString]; -} - -@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.h b/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.h deleted file mode 100755 index 4020864e..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.h +++ /dev/null @@ -1,43 +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 <Foundation/Foundation.h> -#import "CDVAvailabilityDeprecated.h" - -@interface NSDictionary (org_apache_cordova_NSDictionary_Extension) - -- (bool)existsValue:(NSString*)expectedValue forKey:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue withRange:(NSRange)range CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (BOOL)typeValueForKey:(NSString*)key isArray:(BOOL*)bArray isNull:(BOOL*)bNull isNumber:(BOOL*)bNumber isString:(BOOL*)bString CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (BOOL)valueForKeyIsArray:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (BOOL)valueForKeyIsNull:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (BOOL)valueForKeyIsString:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (BOOL)valueForKeyIsNumber:(NSString*)key CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -- (NSDictionary*)dictionaryWithLowercaseKeys CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); - -@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.m b/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.m deleted file mode 100755 index 0361ff95..00000000 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSDictionary+Extensions.m +++ /dev/null @@ -1,159 +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 "NSDictionary+Extensions.h" -#import <math.h> - -@implementation NSDictionary (org_apache_cordova_NSDictionary_Extension) - -- (bool)existsValue:(NSString*)expectedValue forKey:(NSString*)key -{ - id val = [self valueForKey:key]; - bool exists = false; - - if (val != nil) { - exists = [(NSString*)val compare : expectedValue options : NSCaseInsensitiveSearch] == 0; - } - - return exists; -} - -- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue withRange:(NSRange)range -{ - NSInteger value = defaultValue; - - NSNumber* val = [self valueForKey:key]; // value is an NSNumber - - if (val != nil) { - value = [val integerValue]; - } - - // min, max checks - value = MAX(range.location, value); - value = MIN(range.length, value); - - return value; -} - -- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue -{ - NSInteger value = defaultValue; - - NSNumber* val = [self valueForKey:key]; // value is an NSNumber - - if (val != nil) { - value = [val integerValue]; - } - return value; -} - -/* - * Determine the type of object stored in a dictionary - * IN: - * (BOOL*) bString - if exists will be set to YES if object is an NSString, NO if not - * (BOOL*) bNull - if exists will be set to YES if object is an NSNull, NO if not - * (BOOL*) bArray - if exists will be set to YES if object is an NSArray, NO if not - * (BOOL*) bNumber - if exists will be set to YES if object is an NSNumber, NO if not - * - * OUT: - * YES if key exists - * NO if key does not exist. Input parameters remain untouched - * - */ - -- (BOOL)typeValueForKey:(NSString*)key isArray:(BOOL*)bArray isNull:(BOOL*)bNull isNumber:(BOOL*)bNumber isString:(BOOL*)bString -{ - BOOL bExists = YES; - NSObject* value = [self objectForKey:key]; - - if (value) { - bExists = YES; - if (bString) { - *bString = [value isKindOfClass:[NSString class]]; - } - if (bNull) { - *bNull = [value isKindOfClass:[NSNull class]]; - } - if (bArray) { - *bArray = [value isKindOfClass:[NSArray class]]; - } - if (bNumber) { - *bNumber = [value isKindOfClass:[NSNumber class]]; - } - } - return bExists; -} - -- (BOOL)valueForKeyIsArray:(NSString*)key -{ - BOOL bArray = NO; - NSObject* value = [self objectForKey:key]; - - if (value) { - bArray = [value isKindOfClass:[NSArray class]]; - } - return bArray; -} - -- (BOOL)valueForKeyIsNull:(NSString*)key -{ - BOOL bNull = NO; - NSObject* value = [self objectForKey:key]; - - if (value) { - bNull = [value isKindOfClass:[NSNull class]]; - } - return bNull; -} - -- (BOOL)valueForKeyIsString:(NSString*)key -{ - BOOL bString = NO; - NSObject* value = [self objectForKey:key]; - - if (value) { - bString = [value isKindOfClass:[NSString class]]; - } - return bString; -} - -- (BOOL)valueForKeyIsNumber:(NSString*)key -{ - BOOL bNumber = NO; - NSObject* value = [self objectForKey:key]; - - if (value) { - bNumber = [value isKindOfClass:[NSNumber class]]; - } - return bNumber; -} - -- (NSDictionary*)dictionaryWithLowercaseKeys -{ - NSMutableDictionary* result = [NSMutableDictionary dictionaryWithCapacity:self.count]; - NSString* key; - - for (key in self) { - [result setObject:[self objectForKey:key] forKey:[key lowercaseString]]; - } - - return result; -} - -@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVDebug.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVDebug.h index 4a0d9f92..4a0d9f92 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVDebug.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVDebug.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.h index afb5cc66..afb5cc66 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.m index 53856806..53856806 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON_private.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVJSON_private.m diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVShared.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVPlugin+Private.h index 68acc5c2..f88638c2 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVShared.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/CDVPlugin+Private.h @@ -17,6 +17,8 @@ under the License. */ -// This file was emptied out in 3.6.0 release (July 2014). -// It will be deleted in a future release. -#import <CoreLocation/CoreLocation.h> +@interface CDVPlugin (Private) + +- (instancetype)initWithWebViewEngine:(id <CDVWebViewEngineProtocol>)theWebViewEngine; + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.h new file mode 100644 index 00000000..510b6ebf --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.h @@ -0,0 +1,26 @@ +/* + 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 "CDVPlugin.h" + +@interface CDVGestureHandler : CDVPlugin + +@property (nonatomic, strong) UILongPressGestureRecognizer* lpgr; + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.m new file mode 100644 index 00000000..242ac55b --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVGestureHandler/CDVGestureHandler.m @@ -0,0 +1,74 @@ +/* + 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 "CDVGestureHandler.h" + +@implementation CDVGestureHandler + +- (void)pluginInitialize +{ + [self applyLongPressFix]; +} + +- (void)applyLongPressFix +{ + // You can't suppress 3D Touch and still have regular longpress, + // so if this is false, let's not consider the 3D Touch setting at all. + if (![self.commandDelegate.settings objectForKey:@"suppresseslongpressgesture"] || + ![[self.commandDelegate.settings objectForKey:@"suppresseslongpressgesture"] boolValue]) { + return; + } + + self.lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGestures:)]; + self.lpgr.minimumPressDuration = 0.45f; + self.lpgr.allowableMovement = 100.0f; + + // 0.45 is ok for 'regular longpress', 0.05-0.08 is required for '3D Touch longpress', + // but since this will also kill onclick handlers (not ontouchend) it's optional. + if ([self.commandDelegate.settings objectForKey:@"suppresses3dtouchgesture"] && + [[self.commandDelegate.settings objectForKey:@"suppresses3dtouchgesture"] boolValue]) { + self.lpgr.minimumPressDuration = 0.05f; + } + + NSArray *views = self.webView.subviews; + if (views.count == 0) { + NSLog(@"No webview subviews found, not applying the longpress fix."); + return; + } + for (int i=0; i<views.count; i++) { + UIView *webViewScrollView = views[i]; + if ([webViewScrollView isKindOfClass:[UIScrollView class]]) { + NSArray *webViewScrollViewSubViews = webViewScrollView.subviews; + UIView *browser = webViewScrollViewSubViews[0]; + [browser addGestureRecognizer:self.lpgr]; + break; + } + } +} + +- (void)handleLongPressGestures:(UILongPressGestureRecognizer*)sender +{ + if ([sender isEqual:self.lpgr]) { + if (sender.state == UIGestureRecognizerStateBegan) { + NSLog(@"Ignoring a longpress in order to suppress the magnifying glass."); + } + } +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.h index 24f461f3..f9b0bffa 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.h @@ -25,4 +25,3 @@ @property (nonatomic, assign) BOOL pageLoaded; @end - diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.m index e5dcdd5a..72199b9c 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVHandleOpenURL.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVHandleOpenURL/CDVHandleOpenURL.m @@ -30,9 +30,10 @@ - (void)applicationLaunchedWithUrl:(NSNotification*)notification { - NSURL *url = [notification object]; + NSURL* url = [notification object]; + self.url = url; - + // warm-start handler if (self.pageLoaded) { [self processOpenUrl:self.url pageLoaded:YES]; @@ -43,7 +44,7 @@ - (void)applicationPageDidLoad:(NSNotification*)notification { // cold-start handler - + self.pageLoaded = YES; if (self.url) { @@ -54,21 +55,32 @@ - (void)processOpenUrl:(NSURL*)url pageLoaded:(BOOL)pageLoaded { - if (!pageLoaded) { - // query the webview for readystate - NSString* readyState = [self.webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; - pageLoaded = [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"]; - } - - if (pageLoaded) { + __weak __typeof(self) weakSelf = self; + + dispatch_block_t handleOpenUrl = ^(void) { // calls into javascript global function 'handleOpenURL' - NSString* jsString = [NSString stringWithFormat:@"document.addEventListener('deviceready',function(){if (typeof handleOpenURL === 'function') { handleOpenURL(\"%@\");}});", url]; - [self.webView stringByEvaluatingJavaScriptFromString:jsString]; + NSString* jsString = [NSString stringWithFormat:@"document.addEventListener('deviceready',function(){if (typeof handleOpenURL === 'function') { handleOpenURL(\"%@\");}});", url.absoluteString]; + + [weakSelf.webViewEngine evaluateJavaScript:jsString completionHandler:nil]; + }; + + if (!pageLoaded) { + NSString* jsString = @"document.readystate"; + [self.webViewEngine evaluateJavaScript:jsString + completionHandler:^(id object, NSError* error) { + if ((error == nil) && [object isKindOfClass:[NSString class]]) { + NSString* readyState = (NSString*)object; + BOOL ready = [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"]; + if (ready) { + handleOpenUrl(); + } else { + self.url = url; + } + } + }]; } else { - // save for when page has loaded - self.url = url; + handleOpenUrl(); } } - @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h new file mode 100644 index 00000000..ee89e1a8 --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.h @@ -0,0 +1,34 @@ +/* + 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 "CDVPlugin.h" +#import "CDVWhitelist.h" + +typedef NS_ENUM(NSInteger, CDVIntentAndNavigationFilterValue) { + CDVIntentAndNavigationFilterValueIntentAllowed, + CDVIntentAndNavigationFilterValueNavigationAllowed, + CDVIntentAndNavigationFilterValueNoneAllowed +}; + +@interface CDVIntentAndNavigationFilter : CDVPlugin <NSXMLParserDelegate> + ++ (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url intentsWhitelist:(CDVWhitelist*)intentsWhitelist navigationsWhitelist:(CDVWhitelist*)navigationsWhitelist; ++ (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType filterValue:(CDVIntentAndNavigationFilterValue)filterValue; ++ (BOOL)shouldOpenURLRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType; +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m new file mode 100644 index 00000000..bc8f7200 --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVIntentAndNavigationFilter/CDVIntentAndNavigationFilter.m @@ -0,0 +1,142 @@ +/* + 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 "CDVIntentAndNavigationFilter.h" +#import <Cordova/CDV.h> + +@interface CDVIntentAndNavigationFilter () + +@property (nonatomic, readwrite) NSMutableArray* allowIntents; +@property (nonatomic, readwrite) NSMutableArray* allowNavigations; +@property (nonatomic, readwrite) CDVWhitelist* allowIntentsWhitelist; +@property (nonatomic, readwrite) CDVWhitelist* allowNavigationsWhitelist; + +@end + +@implementation CDVIntentAndNavigationFilter + +#pragma mark NSXMLParserDelegate + +- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName attributes:(NSDictionary*)attributeDict +{ + if ([elementName isEqualToString:@"allow-navigation"]) { + [self.allowNavigations addObject:attributeDict[@"href"]]; + } + if ([elementName isEqualToString:@"allow-intent"]) { + [self.allowIntents addObject:attributeDict[@"href"]]; + } +} + +- (void)parserDidStartDocument:(NSXMLParser*)parser +{ + // file: url <allow-navigations> are added by default + self.allowNavigations = [[NSMutableArray alloc] initWithArray:@[ @"file://" ]]; + // no intents are added by default + self.allowIntents = [[NSMutableArray alloc] init]; +} + +- (void)parserDidEndDocument:(NSXMLParser*)parser +{ + self.allowIntentsWhitelist = [[CDVWhitelist alloc] initWithArray:self.allowIntents]; + self.allowNavigationsWhitelist = [[CDVWhitelist alloc] initWithArray:self.allowNavigations]; +} + +- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError +{ + NSAssert(NO, @"config.xml parse error line %ld col %ld", (long)[parser lineNumber], (long)[parser columnNumber]); +} + +#pragma mark CDVPlugin + +- (void)pluginInitialize +{ + if ([self.viewController isKindOfClass:[CDVViewController class]]) { + [(CDVViewController*)self.viewController parseSettingsWithParser:self]; + } +} + ++ (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url intentsWhitelist:(CDVWhitelist*)intentsWhitelist navigationsWhitelist:(CDVWhitelist*)navigationsWhitelist +{ + // a URL can only allow-intent OR allow-navigation, if both are specified, + // only allow-navigation is allowed + + BOOL allowNavigationsPass = [navigationsWhitelist URLIsAllowed:url logFailure:NO]; + BOOL allowIntentPass = [intentsWhitelist URLIsAllowed:url logFailure:NO]; + + if (allowNavigationsPass && allowIntentPass) { + return CDVIntentAndNavigationFilterValueNavigationAllowed; + } else if (allowNavigationsPass) { + return CDVIntentAndNavigationFilterValueNavigationAllowed; + } else if (allowIntentPass) { + return CDVIntentAndNavigationFilterValueIntentAllowed; + } + + return CDVIntentAndNavigationFilterValueNoneAllowed; +} + +- (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url +{ + return [[self class] filterUrl:url intentsWhitelist:self.allowIntentsWhitelist navigationsWhitelist:self.allowNavigationsWhitelist]; +} + ++ (BOOL)shouldOpenURLRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType +{ + return (UIWebViewNavigationTypeLinkClicked == navigationType || + (UIWebViewNavigationTypeOther == navigationType && + [[request.mainDocumentURL absoluteString] isEqualToString:[request.URL absoluteString]] + ) + ); +} + ++ (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType filterValue:(CDVIntentAndNavigationFilterValue)filterValue +{ + NSString* allowIntents_whitelistRejectionFormatString = @"ERROR External navigation rejected - <allow-intent> not set for url='%@'"; + NSString* allowNavigations_whitelistRejectionFormatString = @"ERROR Internal navigation rejected - <allow-navigation> not set for url='%@'"; + + NSURL* url = [request URL]; + + switch (filterValue) { + case CDVIntentAndNavigationFilterValueNavigationAllowed: + return YES; + case CDVIntentAndNavigationFilterValueIntentAllowed: + // only allow-intent if it's a UIWebViewNavigationTypeLinkClicked (anchor tag) OR + // it's a UIWebViewNavigationTypeOther, and it's an internal link + if ([[self class] shouldOpenURLRequest:request navigationType:navigationType]){ + [[UIApplication sharedApplication] openURL:url]; + } + + // consume the request (i.e. no error) if it wasn't handled above + return NO; + case CDVIntentAndNavigationFilterValueNoneAllowed: + // allow-navigation attempt failed for sure + NSLog(@"%@", [NSString stringWithFormat:allowNavigations_whitelistRejectionFormatString, [url absoluteString]]); + // anchor tag link means it was an allow-intent attempt that failed as well + if (UIWebViewNavigationTypeLinkClicked == navigationType) { + NSLog(@"%@", [NSString stringWithFormat:allowIntents_whitelistRejectionFormatString, [url absoluteString]]); + } + return NO; + } +} + +- (BOOL)shouldOverrideLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType +{ + return [[self class] shouldOverrideLoadWithRequest:request navigationType:navigationType filterValue:[self filterUrl:request.URL]]; +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.h index dec6ab3b..dec6ab3b 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.m index 8aec403b..252dfaf1 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVLocalStorage.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVLocalStorage/CDVLocalStorage.m @@ -121,10 +121,9 @@ + (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL*)URL skip:(BOOL)skip { - NSAssert(IsAtLeastiOSVersion(@"5.1"), @"Cannot mark files for NSURLIsExcludedFromBackupKey on iOS less than 5.1"); - NSError* error = nil; BOOL success = [URL setResourceValue:[NSNumber numberWithBool:skip] forKey:NSURLIsExcludedFromBackupKey error:&error]; + if (!success) { NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error); } @@ -330,10 +329,6 @@ + (void)__restoreLegacyDatabaseLocationsWithBackupType:(NSString*)backupType { // on iOS 6, if you toggle between cloud/local backup, you must move database locations. Default upgrade from iOS5.1 to iOS6 is like a toggle from local to cloud. - if (!IsAtLeastiOSVersion(@"6.0")) { - return; - } - NSString* appLibraryFolder = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString* appDocumentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.h index f6c419f7..d77f1913 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.h @@ -26,7 +26,7 @@ * and didFinishLoad is called only for top-level navigations. * Relevant bug: CB-2389 */ -@interface CDVWebViewDelegate : NSObject <UIWebViewDelegate>{ +@interface CDVUIWebViewDelegate : NSObject <UIWebViewDelegate>{ __weak NSObject <UIWebViewDelegate>* _delegate; NSInteger _loadCount; NSInteger _state; diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m index a7e29086..0af97dfb 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWebViewDelegate.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m @@ -76,11 +76,11 @@ // TODO: Record order when page is re-navigated before the first navigation finishes. // -#import "CDVWebViewDelegate.h" -#import "CDVAvailability.h" +#import "CDVUIWebViewDelegate.h" // #define VerboseLog NSLog -#define VerboseLog(...) do {} while (0) +#define VerboseLog(...) do { \ +} while (0) typedef enum { STATE_IDLE = 0, @@ -101,7 +101,7 @@ static NSString *stripFragment(NSString* url) return [url substringToIndex:r.location]; } -@implementation CDVWebViewDelegate +@implementation CDVUIWebViewDelegate - (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate { @@ -196,12 +196,13 @@ static NSString *stripFragment(NSString* url) - (BOOL)shouldLoadRequest:(NSURLRequest*)request { NSString* scheme = [[request URL] scheme]; - - if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"] || [scheme isEqualToString:@"sms"] || [scheme isEqualToString:@"blob"]) { + NSArray* allowedSchemes = [NSArray arrayWithObjects:@"mailto",@"tel",@"blob",@"sms",@"data", nil]; + if([allowedSchemes containsObject:scheme]) { return YES; } - - return [NSURLConnection canHandleRequest:request]; + else { + return [NSURLConnection canHandleRequest:request]; + } } - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType @@ -257,7 +258,7 @@ static NSString *stripFragment(NSString* url) _state = STATE_WAITING_FOR_LOAD_START; if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description}; - NSError* error = [[NSError alloc] initWithDomain:@"CDVWebViewDelegate" code:1 userInfo:errorDictionary]; + NSError* error = [[NSError alloc] initWithDomain:@"CDVUIWebViewDelegate" code:1 userInfo:errorDictionary]; [_delegate webView:webView didFailLoadWithError:error]; } } @@ -278,19 +279,6 @@ static NSString *stripFragment(NSString* url) BOOL fireCallback = NO; switch (_state) { case STATE_IDLE: - if (IsAtLeastiOSVersion(@"6.0")) { - break; - } - // If history.go(-1) is used pre-iOS6, the shouldStartLoadWithRequest function is not called. - // Without shouldLoad, we can't distinguish an iframe from a top-level navigation. - // We could try to distinguish using [UIWebView canGoForward], but that's too much complexity, - // and would work only on the first time it was used. - - // Our work-around is to set a JS variable and poll until it disappears (from a navigation). - _state = STATE_IOS5_POLLING_FOR_LOAD_START; - _loadStartPollCount = 0; - [self setLoadToken:webView]; - [self pollForPageLoadStart:webView]; break; case STATE_CANCELLED: diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.h new file mode 100644 index 00000000..6a9ee77e --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.h @@ -0,0 +1,27 @@ +/* + 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 "CDVPlugin.h" +#import "CDVWebViewEngineProtocol.h" + +@interface CDVUIWebViewEngine : CDVPlugin <CDVWebViewEngineProtocol> + +@property (nonatomic, strong, readonly) id <UIWebViewDelegate> uiWebViewDelegate; + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.m new file mode 100644 index 00000000..f571d80a --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewEngine.m @@ -0,0 +1,202 @@ +/* + 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 "CDVUIWebViewEngine.h" +#import "CDVUIWebViewDelegate.h" +#import "CDVUIWebViewNavigationDelegate.h" +#import "NSDictionary+CordovaPreferences.h" + +#import <objc/message.h> + +@interface CDVUIWebViewEngine () + +@property (nonatomic, strong, readwrite) UIView* engineWebView; +@property (nonatomic, strong, readwrite) id <UIWebViewDelegate> uiWebViewDelegate; +@property (nonatomic, strong, readwrite) CDVUIWebViewNavigationDelegate* navWebViewDelegate; + +@end + +@implementation CDVUIWebViewEngine + +@synthesize engineWebView = _engineWebView; + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super init]; + if (self) { + self.engineWebView = [[UIWebView alloc] initWithFrame:frame]; + NSLog(@"Using UIWebView"); + } + + return self; +} + +- (void)pluginInitialize +{ + // viewController would be available now. we attempt to set all possible delegates to it, by default + + UIWebView* uiWebView = (UIWebView*)_engineWebView; + + if ([self.viewController conformsToProtocol:@protocol(UIWebViewDelegate)]) { + self.uiWebViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:(id <UIWebViewDelegate>)self.viewController]; + uiWebView.delegate = self.uiWebViewDelegate; + } else { + self.navWebViewDelegate = [[CDVUIWebViewNavigationDelegate alloc] initWithEnginePlugin:self]; + self.uiWebViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:self.navWebViewDelegate]; + uiWebView.delegate = self.uiWebViewDelegate; + } + + [self updateSettings:self.commandDelegate.settings]; +} + +- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler +{ + NSString* ret = [(UIWebView*)_engineWebView stringByEvaluatingJavaScriptFromString:javaScriptString]; + + if (completionHandler) { + completionHandler(ret, nil); + } +} + +- (id)loadRequest:(NSURLRequest*)request +{ + [(UIWebView*)_engineWebView loadRequest:request]; + return nil; +} + +- (id)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL +{ + [(UIWebView*)_engineWebView loadHTMLString:string baseURL:baseURL]; + return nil; +} + +- (NSURL*)URL +{ + return [[(UIWebView*)_engineWebView request] URL]; +} + +- (BOOL) canLoadRequest:(NSURLRequest*)request +{ + return (request != nil); +} + +- (void)updateSettings:(NSDictionary*)settings +{ + UIWebView* uiWebView = (UIWebView*)_engineWebView; + + uiWebView.scalesPageToFit = [settings cordovaBoolSettingForKey:@"EnableViewportScale" defaultValue:NO]; + uiWebView.allowsInlineMediaPlayback = [settings cordovaBoolSettingForKey:@"AllowInlineMediaPlayback" defaultValue:NO]; + uiWebView.mediaPlaybackRequiresUserAction = [settings cordovaBoolSettingForKey:@"MediaPlaybackRequiresUserAction" defaultValue:YES]; + uiWebView.mediaPlaybackAllowsAirPlay = [settings cordovaBoolSettingForKey:@"MediaPlaybackAllowsAirPlay" defaultValue:YES]; + uiWebView.keyboardDisplayRequiresUserAction = [settings cordovaBoolSettingForKey:@"KeyboardDisplayRequiresUserAction" defaultValue:YES]; + uiWebView.suppressesIncrementalRendering = [settings cordovaBoolSettingForKey:@"SuppressesIncrementalRendering" defaultValue:NO]; + uiWebView.gapBetweenPages = [settings cordovaFloatSettingForKey:@"GapBetweenPages" defaultValue:0.0]; + uiWebView.pageLength = [settings cordovaFloatSettingForKey:@"PageLength" defaultValue:0.0]; + + id prefObj = nil; + + // By default, DisallowOverscroll is false (thus bounce is allowed) + BOOL bounceAllowed = !([settings cordovaBoolSettingForKey:@"DisallowOverscroll" defaultValue:NO]); + + // prevent webView from bouncing + if (!bounceAllowed) { + if ([uiWebView respondsToSelector:@selector(scrollView)]) { + ((UIScrollView*)[uiWebView scrollView]).bounces = NO; + } else { + for (id subview in self.webView.subviews) { + if ([[subview class] isSubclassOfClass:[UIScrollView class]]) { + ((UIScrollView*)subview).bounces = NO; + } + } + } + } + + NSString* decelerationSetting = [settings cordovaSettingForKey:@"UIWebViewDecelerationSpeed"]; + if (![@"fast" isEqualToString:decelerationSetting]) { + [uiWebView.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal]; + } + + NSInteger paginationBreakingMode = 0; // default - UIWebPaginationBreakingModePage + prefObj = [settings cordovaSettingForKey:@"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; + } + } + uiWebView.paginationBreakingMode = paginationBreakingMode; + + NSInteger paginationMode = 0; // default - UIWebPaginationModeUnpaginated + prefObj = [settings cordovaSettingForKey:@"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; + } + } + uiWebView.paginationMode = paginationMode; +} + +- (void)updateWithInfo:(NSDictionary*)info +{ + UIWebView* uiWebView = (UIWebView*)_engineWebView; + + id <UIWebViewDelegate> uiWebViewDelegate = [info objectForKey:kCDVWebViewEngineUIWebViewDelegate]; + NSDictionary* settings = [info objectForKey:kCDVWebViewEngineWebViewPreferences]; + + if (uiWebViewDelegate && + [uiWebViewDelegate conformsToProtocol:@protocol(UIWebViewDelegate)]) { + self.uiWebViewDelegate = [[CDVUIWebViewDelegate alloc] initWithDelegate:(id <UIWebViewDelegate>)self.viewController]; + uiWebView.delegate = self.uiWebViewDelegate; + } + + if (settings && [settings isKindOfClass:[NSDictionary class]]) { + [self updateSettings:settings]; + } +} + +// This forwards the methods that are in the header that are not implemented here. +// Both WKWebView and UIWebView implement the below: +// loadHTMLString:baseURL: +// loadRequest: +- (id)forwardingTargetForSelector:(SEL)aSelector +{ + return _engineWebView; +} + +- (UIView*)webView +{ + return self.engineWebView; +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.h index 85db545a..9138deba 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVJSON.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.h @@ -17,36 +17,13 @@ under the License. */ -#import "CDVJSON_private.h" +#import <UIKit/UIKit.h> +#import "CDVUIWebViewEngine.h" -@implementation NSArray (CDVJSONSerializing) +@interface CDVUIWebViewNavigationDelegate : NSObject <UIWebViewDelegate> -- (NSString*)JSONString -{ - return [self cdv_JSONString]; -} +@property (nonatomic, weak) CDVPlugin* enginePlugin; -@end - -@implementation NSDictionary (CDVJSONSerializing) - -- (NSString*)JSONString -{ - return [self cdv_JSONString]; -} - -@end - -@implementation NSString (CDVJSONSerializing) - -- (id)JSONObject -{ - return [self cdv_JSONObject]; -} - -- (id)JSONFragment -{ - return [self cdv_JSONFragment]; -} +- (instancetype)initWithEnginePlugin:(CDVPlugin*)enginePlugin; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m new file mode 100644 index 00000000..6e316595 --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewNavigationDelegate.m @@ -0,0 +1,151 @@ +/* + 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 "CDVUIWebViewNavigationDelegate.h" +#import <Cordova/CDVViewController.h> +#import <Cordova/CDVCommandDelegateImpl.h> +#import <Cordova/CDVUserAgentUtil.h> +#import <objc/message.h> + +@implementation CDVUIWebViewNavigationDelegate + +- (instancetype)initWithEnginePlugin:(CDVPlugin*)theEnginePlugin +{ + self = [super init]; + if (self) { + self.enginePlugin = theEnginePlugin; + } + + return self; +} + +/** + 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."); + CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController; + + [vc.commandQueue resetRequestId]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:self.enginePlugin.webView]]; +} + +/** + Called when the webview finishes loading. This stops the activity view. + */ +- (void)webViewDidFinishLoad:(UIWebView*)theWebView +{ + NSLog(@"Finished load of: %@", theWebView.request.URL); + CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController; + + // It's safe to release the lock even if this is just a sub-frame that's finished loading. + [CDVUserAgentUtil releaseLock:vc.userAgentLockToken]; + + /* + * Hide the Top Activity THROBBER in the Battery Bar + */ + [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; + + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:self.enginePlugin.webView]]; +} + +- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error +{ + CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController; + + [CDVUserAgentUtil releaseLock:vc.userAgentLockToken]; + + NSString* message = [NSString stringWithFormat:@"Failed to load webpage with error: %@", [error localizedDescription]]; + NSLog(@"%@", message); + + NSURL* errorUrl = vc.errorURL; + if (errorUrl) { + errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [message stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl]; + NSLog(@"%@", [errorUrl absoluteString]); + [theWebView loadRequest:[NSURLRequest requestWithURL:errorUrl]]; + } +} + +- (BOOL)defaultResourcePolicyForURL:(NSURL*)url +{ + /* + * If a URL is being loaded that's a file url, just load it internally + */ + if ([url isFileURL]) { + return YES; + } + + return NO; +} + +- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType +{ + NSURL* url = [request URL]; + CDVViewController* vc = (CDVViewController*)self.enginePlugin.viewController; + + /* + * 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"]) { + [vc.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. + [vc.commandQueue executePending]; + return NO; + } + + /* + * Give plugins the chance to handle the url + */ + BOOL anyPluginsResponded = NO; + BOOL shouldAllowRequest = NO; + + for (NSString* pluginName in vc.pluginObjects) { + CDVPlugin* plugin = [vc.pluginObjects objectForKey:pluginName]; + SEL selector = NSSelectorFromString(@"shouldOverrideLoadWithRequest:navigationType:"); + if ([plugin respondsToSelector:selector]) { + anyPluginsResponded = YES; + shouldAllowRequest = (((BOOL (*)(id, SEL, id, int))objc_msgSend)(plugin, selector, request, navigationType)); + if (!shouldAllowRequest) { + break; + } + } + } + + if (anyPluginsResponded) { + return shouldAllowRequest; + } + + /* + * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview. + */ + BOOL shouldAllowNavigation = [self defaultResourcePolicyForURL:url]; + if (shouldAllowNavigation) { + return YES; + } else { + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]]; + } + + return NO; +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDV.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDV.h index 6cf592a0..96d6efc8 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDV.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDV.h @@ -18,24 +18,15 @@ */ #import "CDVAvailability.h" - +#import "CDVAvailabilityDeprecated.h" +#import "CDVAppDelegate.h" #import "CDVPlugin.h" +#import "CDVPluginResult.h" #import "CDVViewController.h" #import "CDVCommandDelegate.h" #import "CDVURLProtocol.h" #import "CDVInvokedUrlCommand.h" - -#import "CDVDebug.h" -#import "CDVPluginResult.h" #import "CDVWhitelist.h" -#import "CDVLocalStorage.h" #import "CDVScreenOrientationDelegate.h" #import "CDVTimer.h" - -#import "NSArray+Comparisons.h" -#import "NSData+Base64.h" -#import "NSDictionary+Extensions.h" -#import "NSMutableArray+QueueAdditions.h" -#import "UIDevice+Extensions.h" - -#import "CDVJSON.h" +#import "CDVUserAgentUtil.h" diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.h index 7dd68290..de5b518f 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.h @@ -18,10 +18,11 @@ */ #import <Foundation/Foundation.h> -#import "CDVAvailabilityDeprecated.h" +#import "CDVViewController.h" -@interface NSArray (Comparisons) +@interface CDVAppDelegate : NSObject <UIApplicationDelegate>{} -- (id)objectAtIndex:(NSUInteger)index withDefault:(id)aDefault CDV_DEPRECATED(3.8 .0, "Use [command argumentAtIndex] instead."); +@property (nonatomic, strong) IBOutlet UIWindow* window; +@property (nonatomic, strong) IBOutlet CDVViewController* viewController; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.m new file mode 100644 index 00000000..13c2e7bd --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAppDelegate.m @@ -0,0 +1,105 @@ +/* + 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 "CDVAppDelegate.h" + +@implementation CDVAppDelegate + +@synthesize window, viewController; + +- (id)init +{ + /** If you need to do any extra app-specific initialization, you can do it here + * -jm + **/ + NSHTTPCookieStorage* cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + + [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; + + int cacheSizeMemory = 8 * 1024 * 1024; // 8MB + int cacheSizeDisk = 32 * 1024 * 1024; // 32MB + NSURLCache* sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"]; + [NSURLCache setSharedURLCache:sharedCache]; + + self = [super init]; + return self; +} + +#pragma mark UIApplicationDelegate implementation + +/** + * This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up) + */ +- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions +{ + CGRect screenBounds = [[UIScreen mainScreen] bounds]; + + self.window = [[UIWindow alloc] initWithFrame:screenBounds]; + self.window.autoresizesSubviews = YES; + + // only set if not already set in subclass + if (self.viewController == nil) { + self.viewController = [[CDVViewController alloc] init]; + } + + // Set your app's start page by setting the <content src='foo.html' /> tag in config.xml. + // If necessary, uncomment the line below to override it. + // self.viewController.startPage = @"index.html"; + + // NOTE: To customize the view's frame size (which defaults to full screen), override + // [self.viewController viewWillAppear:] in your view controller. + + self.window.rootViewController = self.viewController; + [self.window makeKeyAndVisible]; + + return YES; +} + +// this happens while we are running ( in the background, or from within our own app ) +// only valid if 40x-Info.plist specifies a protocol to handle +- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation +{ + if (!url) { + return NO; + } + + // all plugins will get the notification, and their handlers will be called + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]]; + + return YES; +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000 +- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window +#else +- (UIInterfaceOrientationMask)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window +#endif +{ + // iPhone doesn't support upside down by default, while the iPad does. Override to allow all orientations always, and let the root view controller decide what's allowed (the supported orientations mask gets intersected). + NSUInteger supportedInterfaceOrientations = (1 << UIInterfaceOrientationPortrait) | (1 << UIInterfaceOrientationLandscapeLeft) | (1 << UIInterfaceOrientationLandscapeRight) | (1 << UIInterfaceOrientationPortraitUpsideDown); + + return supportedInterfaceOrientations; +} + +- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application +{ + [[NSURLCache sharedURLCache] removeAllCachedResponses]; +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailability.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAvailability.h index 059152ea..c9244327 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVAvailability.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAvailability.h @@ -58,17 +58,26 @@ #define __CORDOVA_3_9_0 30900 #define __CORDOVA_3_9_1 30901 #define __CORDOVA_3_9_2 30902 +#define __CORDOVA_4_0_0 40000 +#define __CORDOVA_4_0_1 40001 +#define __CORDOVA_4_1_0 40100 +#define __CORDOVA_4_1_1 40101 +#define __CORDOVA_4_2_0 40200 +#define __CORDOVA_4_2_1 40201 +#define __CORDOVA_4_3_0 40300 +/* coho:next-version,insert-before */ #define __CORDOVA_NA 99999 /* not available */ /* - #if CORDOVA_VERSION_MIN_REQUIRED >= __CORDOVA_1_7_0 - // do something when its at least 1.7.0 + #if CORDOVA_VERSION_MIN_REQUIRED >= __CORDOVA_4_0_0 + // do something when its at least 4.0.0 #else - // do something else (non 1.7.0) + // do something else (non 4.0.0) #endif */ #ifndef CORDOVA_VERSION_MIN_REQUIRED - #define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_3_9_2 + /* coho:next-version-min-required,replace-after */ + #define CORDOVA_VERSION_MIN_REQUIRED __CORDOVA_4_3_0 #endif /* @@ -91,5 +100,6 @@ #if CDV_ENABLE_EXEC_LOGGING #define CDV_EXEC_LOG NSLog #else - #define CDV_EXEC_LOG(...) do {} while (NO) + #define CDV_EXEC_LOG(...) do { \ +} while (NO) #endif diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAvailabilityDeprecated.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAvailabilityDeprecated.h new file mode 100644 index 00000000..abf7a16a --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVAvailabilityDeprecated.h @@ -0,0 +1,26 @@ +/* + 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 <UIKit/UIKit.h> + +#ifdef __clang__ + #define CDV_DEPRECATED(version, msg) __attribute__((deprecated("Deprecated in Cordova " #version ". " msg))) +#else + #define CDV_DEPRECATED(version, msg) __attribute__((deprecated())) +#endif diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegate.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegate.h index 04df6bc7..3d9d90c9 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegate.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegate.h @@ -24,9 +24,12 @@ @class CDVPluginResult; @class CDVWhitelist; +typedef NSURL* (^ UrlTransformerBlock)(NSURL*); + @protocol CDVCommandDelegate <NSObject> @property (nonatomic, readonly) NSDictionary* settings; +@property (nonatomic, copy) UrlTransformerBlock urlTransformer; - (NSString*)pathForResource:(NSString*)resourcepath; - (id)getCommandInstance:(NSString*)pluginName; @@ -44,7 +47,5 @@ - (void)runInBackground:(void (^)())block; // Returns the User-Agent of the associated UIWebView. - (NSString*)userAgent; -// Returns whether the given URL passes the white-list. -- (BOOL)URLIsWhitelisted:(NSURL*)url; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.h index 05311343..05311343 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.m index be7eb63a..fd8b3e8d 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandDelegateImpl.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandDelegateImpl.m @@ -25,6 +25,8 @@ @implementation CDVCommandDelegateImpl +@synthesize urlTransformer; + - (id)initWithViewController:(CDVViewController*)viewController { self = [super init]; @@ -71,13 +73,18 @@ - (void)evalJsHelper2:(NSString*)js { CDV_EXEC_LOG(@"Exec: evalling: %@", [js substringToIndex:MIN([js length], 160)]); - NSString* commandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString:js]; - if ([commandsJSON length] > 0) { - CDV_EXEC_LOG(@"Exec: Retrieved new exec messages by chaining."); - } + [_viewController.webViewEngine evaluateJavaScript:js completionHandler:^(id obj, NSError* error) { + // TODO: obj can be something other than string + if ([obj isKindOfClass:[NSString class]]) { + NSString* commandsJSON = (NSString*)obj; + if ([commandsJSON length] > 0) { + CDV_EXEC_LOG(@"Exec: Retrieved new exec messages by chaining."); + } - [_commandQueue enqueueCommandBatch:commandsJSON]; - [_commandQueue executePending]; + [_commandQueue enqueueCommandBatch:commandsJSON]; + [_commandQueue executePending]; + } + }]; } - (void)evalJsHelper:(NSString*)js @@ -119,7 +126,7 @@ { CDV_EXEC_LOG(@"Exec(%@): Sending result. Status=%@", callbackId, result.status); // This occurs when there is are no win/fail callbacks for the call. - if ([@"INVALID" isEqualToString : callbackId]) { + if ([@"INVALID" isEqualToString:callbackId]) { return; } // This occurs when the callback id is malformed. @@ -130,8 +137,13 @@ int status = [result.status intValue]; BOOL keepCallback = [result.keepCallback boolValue]; NSString* argumentsAsJSON = [result argumentsAsJSON]; + BOOL debug = NO; + +#ifdef DEBUG + debug = YES; +#endif - NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d)", callbackId, status, argumentsAsJSON, keepCallback]; + NSString* js = [NSString stringWithFormat:@"cordova.require('cordova/exec').nativeCallback('%@',%d,%@,%d, %d)", callbackId, status, argumentsAsJSON, keepCallback, debug]; [self evalJsHelper:js]; } @@ -143,7 +155,7 @@ - (void)evalJs:(NSString*)js scheduledOnRunLoop:(BOOL)scheduledOnRunLoop { - js = [NSString stringWithFormat:@"try{cordova.require('cordova/exec').nativeEvalAndFetch(function(){%@})}catch(e){console.log('exeption nativeEvalAndFetch : '+e);};", js]; + js = [NSString stringWithFormat:@"try{cordova.require('cordova/exec').nativeEvalAndFetch(function(){%@})}catch(e){console.log('exception nativeEvalAndFetch : '+e);};", js]; if (scheduledOnRunLoop) { [self evalJsHelper:js]; } else { @@ -166,12 +178,6 @@ return [_viewController userAgent]; } -- (BOOL)URLIsWhitelisted:(NSURL*)url -{ - return ![_viewController.whitelist schemeIsAllowed:[url scheme]] || - [_viewController.whitelist URLIsAllowed:url logFailure:NO]; -} - - (NSDictionary*)settings { return _viewController.settings; diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.h index 3329078a..cb7bd6e4 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.h @@ -32,7 +32,6 @@ - (void)resetRequestId; - (void)enqueueCommandBatch:(NSString*)batchJSON; -- (void)processXhrExecBridgePoke:(NSNumber*)requestId; - (void)fetchCommandsFromJs; - (void)executePending; - (BOOL)execute:(CDVInvokedUrlCommand*)command; diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.m index 48264b2a..b78ed833 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVCommandQueue.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVCommandQueue.m @@ -18,11 +18,11 @@ */ #include <objc/message.h> -#import "CDV.h" #import "CDVCommandQueue.h" #import "CDVViewController.h" #import "CDVCommandDelegateImpl.h" #import "CDVJSON_private.h" +#import "CDVDebug.h" // Parse JS on the main thread if it's shorter than this. static const NSInteger JSON_SIZE_FOR_MAIN_THREAD = 4 * 1024; // Chosen arbitrarily. @@ -74,48 +74,31 @@ static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame. [commandBatchHolder addObject:[batchJSON cdv_JSONObject]]; } else { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^() { - NSMutableArray* result = [batchJSON cdv_JSONObject]; - @synchronized(commandBatchHolder) { - [commandBatchHolder addObject:result]; - } - [self performSelectorOnMainThread:@selector(executePending) withObject:nil waitUntilDone:NO]; - }); + NSMutableArray* result = [batchJSON cdv_JSONObject]; + @synchronized(commandBatchHolder) { + [commandBatchHolder addObject:result]; + } + [self performSelectorOnMainThread:@selector(executePending) withObject:nil waitUntilDone:NO]; + }); } } } -- (void)processXhrExecBridgePoke:(NSNumber*)requestId -{ - NSInteger rid = [requestId integerValue]; - - // An ID of 1 is a special case because that signifies the first request of - // the page. Since resetRequestId is called from webViewDidStartLoad, and the - // JS context at the time of webViewDidStartLoad is still that of the previous - // page, it's possible for requests from the previous page to come in after this - // point. We ignore these by enforcing that ID=1 be the first ID. - if ((_lastCommandQueueFlushRequestId == 0) && (rid != 1)) { - CDV_EXEC_LOG(@"Exec: Ignoring exec request from previous page."); - return; - } - - // Use the request ID to determine if we've already flushed for this request. - // This is required only because the NSURLProtocol enqueues the same request - // multiple times. - if (rid > _lastCommandQueueFlushRequestId) { - _lastCommandQueueFlushRequestId = [requestId integerValue]; - [self fetchCommandsFromJs]; - [self executePending]; - } -} - - (void)fetchCommandsFromJs { - // Grab all the queued commands from the JS side. - NSString* queuedCommandsJSON = [_viewController.webView stringByEvaluatingJavaScriptFromString: - @"cordova.require('cordova/exec').nativeFetchMessages()"]; + __weak CDVCommandQueue* weakSelf = self; + NSString* js = @"cordova.require('cordova/exec').nativeFetchMessages()"; - CDV_EXEC_LOG(@"Exec: Flushed JS->native queue (hadCommands=%d).", [queuedCommandsJSON length] > 0); - [self enqueueCommandBatch:queuedCommandsJSON]; + [_viewController.webViewEngine evaluateJavaScript:js + completionHandler:^(id obj, NSError* error) { + if ((error == nil) && [obj isKindOfClass:[NSString class]]) { + NSString* queuedCommandsJSON = (NSString*)obj; + CDV_EXEC_LOG(@"Exec: Flushed JS->native queue (hadCommands=%d).", [queuedCommandsJSON length] > 0); + [weakSelf enqueueCommandBatch:queuedCommandsJSON]; + // this has to be called here now, because fetchCommandsFromJs is now async (previously: synchronous) + [self executePending]; + } + }]; } - (void)executePending @@ -141,7 +124,7 @@ static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame. while ([commandBatch count] > 0) { @autoreleasepool { // Execute the commands one-at-a-time. - NSArray* jsonEntry = [commandBatch dequeue]; + NSArray* jsonEntry = [commandBatch cdv_dequeue]; if ([commandBatch count] == 0) { [_queue removeObjectAtIndex:0]; } @@ -153,7 +136,7 @@ static const double MAX_EXECUTION_TIME = .008; // Half of a 60fps frame. NSString* commandJson = [jsonEntry cdv_JSONString]; static NSUInteger maxLogLength = 1024; NSString* commandString = ([commandJson length] > maxLogLength) ? - [NSString stringWithFormat:@"%@[...]", [commandJson substringToIndex:maxLogLength]] : + [NSString stringWithFormat : @"%@[...]", [commandJson substringToIndex:maxLogLength]] : commandJson; DLog(@"FAILED pluginJSON = %@", commandString); diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.h index 2e06c88f..bae3d0f8 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.h @@ -24,7 +24,6 @@ @property (nonatomic, readonly, strong) NSMutableDictionary* pluginsDict; @property (nonatomic, readonly, strong) NSMutableDictionary* settings; -@property (nonatomic, readonly, strong) NSMutableArray* whitelistHosts; @property (nonatomic, readonly, strong) NSMutableArray* startupPluginNames; @property (nonatomic, readonly, strong) NSString* startPage; diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.m index 4b73b60a..ab32b4a7 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVConfigParser.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVConfigParser.m @@ -23,7 +23,6 @@ @property (nonatomic, readwrite, strong) NSMutableDictionary* pluginsDict; @property (nonatomic, readwrite, strong) NSMutableDictionary* settings; -@property (nonatomic, readwrite, strong) NSMutableArray* whitelistHosts; @property (nonatomic, readwrite, strong) NSMutableArray* startupPluginNames; @property (nonatomic, readwrite, strong) NSString* startPage; @@ -31,7 +30,7 @@ @implementation CDVConfigParser -@synthesize pluginsDict, settings, whitelistHosts, startPage, startupPluginNames; +@synthesize pluginsDict, settings, startPage, startupPluginNames; - (id)init { @@ -39,10 +38,6 @@ if (self != nil) { self.pluginsDict = [[NSMutableDictionary alloc] initWithCapacity:30]; self.settings = [[NSMutableDictionary alloc] initWithCapacity:30]; - self.whitelistHosts = [[NSMutableArray alloc] initWithCapacity:30]; - [self.whitelistHosts addObject:@"file:///*"]; - [self.whitelistHosts addObject:@"content:///*"]; - [self.whitelistHosts addObject:@"data:///*"]; self.startupPluginNames = [[NSMutableArray alloc] initWithCapacity:8]; featureName = nil; } @@ -66,8 +61,6 @@ if (paramIsOnload || attribIsOnload) { [self.startupPluginNames addObject:featureName]; } - } else if ([elementName isEqualToString:@"access"]) { - [whitelistHosts addObject:attributeDict[@"origin"]]; } else if ([elementName isEqualToString:@"content"]) { self.startPage = attributeDict[@"src"]; } diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h index 993e0a28..993e0a28 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.m index 3a5e8e75..5b4281df 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVInvokedUrlCommand.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVInvokedUrlCommand.m @@ -19,7 +19,6 @@ #import "CDVInvokedUrlCommand.h" #import "CDVJSON_private.h" -#import "NSData+Base64.h" @implementation CDVInvokedUrlCommand @@ -85,7 +84,7 @@ newArgs = [NSMutableArray arrayWithArray:_arguments]; _arguments = newArgs; } - [newArgs replaceObjectAtIndex:i withObject:[NSData cdv_dataFromBase64String:data]]; + [newArgs replaceObjectAtIndex:i withObject:[[NSData alloc] initWithBase64EncodedString:data options:0]]; } } diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.h index c0c91af2..cc43b16b 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.h @@ -18,30 +18,22 @@ */ #import <UIKit/UIKit.h> -#import "UIDevice+Extensions.h" +#import "CDVPlugin.h" -@implementation UIDevice (org_apache_cordova_UIDevice_Extension) +@interface CDVPlugin (CDVPluginResources) -- (NSString*)uniqueAppInstanceIdentifier -{ - NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; - static NSString* UUID_KEY = @"CDVUUID"; - - NSString* app_uuid = [userDefaults stringForKey:UUID_KEY]; - - if (app_uuid == nil) { - CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault); - CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidRef); - - app_uuid = [NSString stringWithString:(__bridge NSString*)uuidString]; - [userDefaults setObject:app_uuid forKey:UUID_KEY]; - [userDefaults synchronize]; - - CFRelease(uuidString); - CFRelease(uuidRef); - } +/* + This will return the localized string for a key in a .bundle that is named the same as your class + For example, if your plugin class was called Foo, and you have a Spanish localized strings file, it will + try to load the desired key from Foo.bundle/es.lproj/Localizable.strings + */ +- (NSString*)pluginLocalizedString:(NSString*)key; - return app_uuid; -} +/* + This will return the image for a name in a .bundle that is named the same as your class + For example, if your plugin class was called Foo, and you have an image called "bar", + it will try to load the image from Foo.bundle/bar.png (and appropriately named retina versions) + */ +- (UIImage*)pluginImageResource:(NSString*)name; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.m index e29c03da..56907385 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSArray+Comparisons.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin+Resources.m @@ -17,27 +17,22 @@ under the License. */ -#import "NSArray+Comparisons.h" +#import "CDVPlugin+Resources.h" -@implementation NSArray (Comparisons) +@implementation CDVPlugin (CDVPluginResources) -- (id)objectAtIndex:(NSUInteger)index withDefault:(id)aDefault +- (NSString*)pluginLocalizedString:(NSString*)key { - id obj = nil; - - @try { - if (index < [self count]) { - obj = [self objectAtIndex:index]; - } - if ((obj == [NSNull null]) || (obj == nil)) { - return aDefault; - } - } - @catch(NSException* exception) { - NSLog(@"Exception - Name: %@ Reason: %@", [exception name], [exception reason]); - } - - return obj; + NSBundle* bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:NSStringFromClass([self class]) ofType:@"bundle"]]; + + return [bundle localizedStringForKey:(key) value:nil table:nil]; +} + +- (UIImage*)pluginImageResource:(NSString*)name +{ + NSString* resourceIdentifier = [NSString stringWithFormat:@"%@.bundle/%@", NSStringFromClass([self class]), name]; + + return [UIImage imageNamed:resourceIdentifier]; } @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.h index c9991e57..d59507ae 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.h @@ -22,23 +22,46 @@ #import "CDVPluginResult.h" #import "NSMutableArray+QueueAdditions.h" #import "CDVCommandDelegate.h" +#import "CDVWebViewEngineProtocol.h" + +@interface UIView (org_apache_cordova_UIView_Extension) + +@property (nonatomic, weak) UIScrollView* scrollView; + +@end extern NSString* const CDVPageDidLoadNotification; extern NSString* const CDVPluginHandleOpenURLNotification; extern NSString* const CDVPluginResetNotification; -extern NSString* const CDVLocalNotification; -extern NSString* const CDVRemoteNotification; -extern NSString* const CDVRemoteNotificationError; +extern NSString* const CDVViewWillAppearNotification; +extern NSString* const CDVViewDidAppearNotification; +extern NSString* const CDVViewWillDisappearNotification; +extern NSString* const CDVViewDidDisappearNotification; +extern NSString* const CDVViewWillLayoutSubviewsNotification; +extern NSString* const CDVViewDidLayoutSubviewsNotification; +extern NSString* const CDVViewWillTransitionToSizeNotification; + +/* + * The local and remote push notification functionality has been removed from the core in cordova-ios 4.x, + * but these constants have unfortunately have not been removed, but will be removed in 5.x. + * + * To have the same functionality as 3.x, use a third-party plugin or the experimental + * https://github.com/apache/cordova-plugins/tree/master/notification-rebroadcast + */ +extern NSString* const CDVLocalNotification CDV_DEPRECATED(4.0, "Functionality removed in 4.0, constant will be removed in 5.0"); +extern NSString* const CDVRemoteNotification CDV_DEPRECATED(4.0, "Functionality removed in 4.0, constant will be removed in 5.0"); +extern NSString* const CDVRemoteNotificationError CDV_DEPRECATED(4.0, "Functionality removed in 4.0, constant will be removed in 5.0"); @interface CDVPlugin : NSObject {} -@property (nonatomic, weak) UIWebView* webView; +@property (nonatomic, readonly, weak) UIView* webView; +@property (nonatomic, readonly, weak) id <CDVWebViewEngineProtocol> webViewEngine; + @property (nonatomic, weak) UIViewController* viewController; @property (nonatomic, weak) id <CDVCommandDelegate> commandDelegate; @property (readonly, assign) BOOL hasPendingOperation; -- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView CDV_DEPRECATED(3.9.2, "Use pluginInitialize method instead. This will be removed in 4.0.0"); - (void)pluginInitialize; - (void)handleOpenURL:(NSNotification*)notification; @@ -53,15 +76,8 @@ extern NSString* const CDVRemoteNotificationError; - (void) onResume {} - (void) onOrientationWillChange {} - (void) onOrientationDidChange {} - - (void)didReceiveLocalNotification:(NSNotification *)notification; */ - (id)appDelegate; -- (NSString*)writeJavascript:(NSString*)javascript CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of evalJs:. This will be removed in 4.0.0"); - -- (NSString*)success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of sendPluginResult:callbackId. This will be removed in 4.0.0"); - -- (NSString*)error:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate equivalent of sendPluginResult:callbackId. This will be removed in 4.0.0"); - @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.m index ea81ddd1..f16f7fbe 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPlugin.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPlugin.m @@ -18,6 +18,27 @@ */ #import "CDVPlugin.h" +#import "CDVPlugin+Private.h" +#import "CDVPlugin+Resources.h" +#import "CDVViewController.h" +#include <objc/message.h> + +@implementation UIView (org_apache_cordova_UIView_Extension) + +@dynamic scrollView; + +- (UIScrollView*)scrollView +{ + SEL scrollViewSelector = NSSelectorFromString(@"scrollView"); + + if ([self respondsToSelector:scrollViewSelector]) { + return ((id (*)(id, SEL))objc_msgSend)(self, scrollViewSelector); + } + + return nil; +} + +@end NSString* const CDVPageDidLoadNotification = @"CDVPageDidLoadNotification"; NSString* const CDVPluginHandleOpenURLNotification = @"CDVPluginHandleOpenURLNotification"; @@ -25,32 +46,36 @@ NSString* const CDVPluginResetNotification = @"CDVPluginResetNotification"; NSString* const CDVLocalNotification = @"CDVLocalNotification"; NSString* const CDVRemoteNotification = @"CDVRemoteNotification"; NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError"; +NSString* const CDVViewWillAppearNotification = @"CDVViewWillAppearNotification"; +NSString* const CDVViewDidAppearNotification = @"CDVViewDidAppearNotification"; +NSString* const CDVViewWillDisappearNotification = @"CDVViewWillDisappearNotification"; +NSString* const CDVViewDidDisappearNotification = @"CDVViewDidDisappearNotification"; +NSString* const CDVViewWillLayoutSubviewsNotification = @"CDVViewWillLayoutSubviewsNotification"; +NSString* const CDVViewDidLayoutSubviewsNotification = @"CDVViewDidLayoutSubviewsNotification"; +NSString* const CDVViewWillTransitionToSizeNotification = @"CDVViewWillTransitionToSizeNotification"; @interface CDVPlugin () @property (readwrite, assign) BOOL hasPendingOperation; +@property (nonatomic, readwrite, weak) id <CDVWebViewEngineProtocol> webViewEngine; @end @implementation CDVPlugin -@synthesize webView, viewController, commandDelegate, hasPendingOperation; +@synthesize webViewEngine, viewController, commandDelegate, hasPendingOperation; +@dynamic webView; // Do not override these methods. Use pluginInitialize instead. -- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView settings:(NSDictionary*)classSettings -{ - return [self initWithWebView:theWebView]; -} - -- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView +- (instancetype)initWithWebViewEngine:(id <CDVWebViewEngineProtocol>)theWebViewEngine { self = [super init]; if (self) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppTerminate) name:UIApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURL:) name:CDVPluginHandleOpenURLNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReset) name:CDVPluginResetNotification object:theWebView]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReset) name:CDVPluginResetNotification object:theWebViewEngine.engineWebView]; - self.webView = theWebView; + self.webViewEngine = theWebViewEngine; } return self; } @@ -67,18 +92,31 @@ NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError"; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationWillChange) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationDidChange) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; - // Added in 2.3.0 - // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveLocalNotification:) name:CDVLocalNotification object:nil]; - // Added in 2.5.0 // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageDidLoad:) name:CDVPageDidLoadNotification object:self.webView]; + //Added in 4.3.0 + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillAppear:) name:CDVViewWillAppearNotification object:nil]; + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidAppear:) name:CDVViewDidAppearNotification object:nil]; + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillDisappear:) name:CDVViewWillDisappearNotification object:nil]; + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidDisappear:) name:CDVViewDidDisappearNotification object:nil]; + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillLayoutSubviews:) name:CDVViewWillLayoutSubviewsNotification object:nil]; + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidLayoutSubviews:) name:CDVViewDidLayoutSubviewsNotification object:nil]; + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillTransitionToSize:) name:CDVViewWillTransitionToSizeNotification object:nil]; } - (void)dispose { viewController = nil; commandDelegate = nil; - webView = nil; +} + +- (UIView*)webView +{ + if (self.webViewEngine != nil) { + return self.webViewEngine.engineWebView; + } + + return nil; } /* @@ -120,7 +158,7 @@ NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError"; - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; // this will remove all notification unless added using addObserverForName:object:queue:usingBlock: + [[NSNotificationCenter defaultCenter] removeObserver:self]; // this will remove all notifications unless added using addObserverForName:object:queue:usingBlock: } - (id)appDelegate @@ -128,27 +166,4 @@ NSString* const CDVRemoteNotificationError = @"CDVRemoteNotificationError"; return [[UIApplication sharedApplication] delegate]; } -- (NSString*)writeJavascript:(NSString*)javascript -{ - return [self.webView stringByEvaluatingJavaScriptFromString:javascript]; -} - -- (NSString*)success:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId -{ - [self.commandDelegate evalJs:[pluginResult toSuccessCallbackString:callbackId]]; - return @""; -} - -- (NSString*)error:(CDVPluginResult*)pluginResult callbackId:(NSString*)callbackId -{ - [self.commandDelegate evalJs:[pluginResult toErrorCallbackString:callbackId]]; - return @""; -} - -// default implementation does nothing, ideally, we are not registered for notification if we aren't going to do anything. -// - (void)didReceiveLocalNotification:(NSNotification *)notification -// { -// // UILocalNotification* localNotification = [notification object]; // get the payload as a LocalNotification -// } - @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.h index e624d4de..56b8c232 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.h @@ -47,6 +47,8 @@ typedef enum { + (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsString:(NSString*)theMessage; + (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsArray:(NSArray*)theMessage; + (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsInt:(int)theMessage; ++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSInteger:(NSInteger)theMessage; ++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSUInteger:(NSUInteger)theMessage; + (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDouble:(double)theMessage; + (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsBool:(BOOL)theMessage; + (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDictionary:(NSDictionary*)theMessage; @@ -61,11 +63,4 @@ typedef enum { - (NSString*)argumentsAsJSON; -// These methods are used by the legacy plugin return result method -- (NSString*)toJSONString CDV_DEPRECATED(3.6, "Only used by toSuccessCallbackString and toErrorCallbackString which are deprecated. This will be removed in 4.0.0"); - -- (NSString*)toSuccessCallbackString:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate method sendPluginResult:callbackId instead. This will be removed in 4.0.0"); - -- (NSString*)toErrorCallbackString:(NSString*)callbackId CDV_DEPRECATED(3.6, "Use the CDVCommandDelegate method sendPluginResult:callbackId instead. This will be removed in 4.0.0"); - @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.m index 13839efd..3521e6d7 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVPluginResult.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVPluginResult.m @@ -20,7 +20,6 @@ #import "CDVPluginResult.h" #import "CDVJSON_private.h" #import "CDVDebug.h" -#import "NSData+Base64.h" @interface CDVPluginResult () @@ -37,7 +36,7 @@ id messageFromArrayBuffer(NSData* data) { return @{ @"CDVType" : @"ArrayBuffer", - @"data" :[data cdv_base64EncodedString] + @"data" :[data base64EncodedStringWithOptions:0] }; } @@ -114,6 +113,16 @@ id messageFromMultipart(NSArray* theMessages) return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithInt:theMessage]]; } ++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSInteger:(NSInteger)theMessage +{ + return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithInteger:theMessage]]; +} + ++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsNSUInteger:(NSUInteger)theMessage +{ + return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithUnsignedInteger:theMessage]]; +} + + (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAsDouble:(double)theMessage { return [[self alloc] initWithStatus:statusOrdinal message:[NSNumber numberWithDouble:theMessage]]; @@ -163,53 +172,6 @@ id messageFromMultipart(NSArray* theMessages) return argumentsJSON; } -// These methods are used by the legacy plugin return result method -- (NSString*)toJSONString -{ - NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: - self.status, @"status", - self.message ? self. message:[NSNull null], @"message", - self.keepCallback, @"keepCallback", - nil]; - - NSError* error = nil; - NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dict - options:NSJSONWritingPrettyPrinted - error:&error]; - NSString* resultString = nil; - - if (error != nil) { - NSLog(@"toJSONString error: %@", [error localizedDescription]); - } else { - resultString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - } - - if ([[self class] isVerbose]) { - NSLog(@"PluginResult:toJSONString - %@", resultString); - } - return resultString; -} - -- (NSString*)toSuccessCallbackString:(NSString*)callbackId -{ - NSString* successCB = [NSString stringWithFormat:@"cordova.callbackSuccess('%@',%@);", callbackId, [self toJSONString]]; - - if ([[self class] isVerbose]) { - NSLog(@"PluginResult toSuccessCallbackString: %@", successCB); - } - return successCB; -} - -- (NSString*)toErrorCallbackString:(NSString*)callbackId -{ - NSString* errorCB = [NSString stringWithFormat:@"cordova.callbackError('%@',%@);", callbackId, [self toJSONString]]; - - if ([[self class] isVerbose]) { - NSLog(@"PluginResult toErrorCallbackString: %@", errorCB); - } - return errorCB; -} - static BOOL gIsVerbose = NO; + (void)setVerbose:(BOOL)verbose { diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVScreenOrientationDelegate.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVScreenOrientationDelegate.h index 7226205a..7226205a 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVScreenOrientationDelegate.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVScreenOrientationDelegate.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVTimer.h index 6d31593f..6d31593f 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVTimer.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVTimer.m index 784e94d3..784e94d3 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVTimer.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVTimer.m diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.h index 5444f6d1..0561e04d 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVURLProtocol.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.h @@ -24,6 +24,4 @@ @interface CDVURLProtocol : NSURLProtocol {} -+ (void)registerViewController:(CDVViewController*)viewController; -+ (void)unregisterViewController:(CDVViewController*)viewController; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.m new file mode 100644 index 00000000..7b2c5ce5 --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVURLProtocol.m @@ -0,0 +1,113 @@ +/* + 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 <AssetsLibrary/ALAsset.h> +#import <AssetsLibrary/ALAssetRepresentation.h> +#import <AssetsLibrary/ALAssetsLibrary.h> +#import <MobileCoreServices/MobileCoreServices.h> +#import "CDVURLProtocol.h" +#import "CDVCommandQueue.h" +#import "CDVViewController.h" + +// Contains a set of NSNumbers of addresses of controllers. It doesn't store +// the actual pointer to avoid retaining. +static NSMutableSet* gRegisteredControllers = nil; + +NSString* const kCDVAssetsLibraryPrefixes = @"assets-library://"; + +@implementation CDVURLProtocol + + ++ (BOOL)canInitWithRequest:(NSURLRequest*)theRequest +{ + NSURL* theUrl = [theRequest URL]; + + if ([[theUrl absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) { + return YES; + } + + return NO; +} + ++ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request +{ + // NSLog(@"%@ received %@", self, NSStringFromSelector(_cmd)); + return request; +} + +- (void)startLoading +{ + // NSLog(@"%@ received %@ - start", self, NSStringFromSelector(_cmd)); + NSURL* url = [[self request] URL]; + + if ([[url absoluteString] hasPrefix:kCDVAssetsLibraryPrefixes]) { + ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) { + if (asset) { + // We have the asset! Get the data and send it along. + ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation]; + NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType); + Byte* buffer = (Byte*)malloc((unsigned long)[assetRepresentation size]); + NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:(NSUInteger)[assetRepresentation size] error:nil]; + NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES]; + [self sendResponseWithResponseCode:200 data:data mimeType:MIMEType]; + } else { + // Retrieving the asset failed for some reason. Send an error. + [self sendResponseWithResponseCode:404 data:nil mimeType:nil]; + } + }; + ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) { + // Retrieving the asset failed for some reason. Send an error. + [self sendResponseWithResponseCode:401 data:nil mimeType:nil]; + }; + + ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init]; + [assetsLibrary assetForURL:url resultBlock:resultBlock failureBlock:failureBlock]; + return; + } + + NSString* body = [NSString stringWithFormat:@"Access not allowed to URL: %@", url]; + [self sendResponseWithResponseCode:401 data:[body dataUsingEncoding:NSASCIIStringEncoding] mimeType:nil]; +} + +- (void)stopLoading +{ + // do any cleanup here +} + ++ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB +{ + return NO; +} + +- (void)sendResponseWithResponseCode:(NSInteger)statusCode data:(NSData*)data mimeType:(NSString*)mimeType +{ + if (mimeType == nil) { + mimeType = @"text/plain"; + } + + NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL] statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:@{@"Content-Type" : mimeType}]; + + [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + if (data != nil) { + [[self client] URLProtocol:self didLoadData:data]; + } + [[self client] URLProtocolDidFinishLoading:self]; +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.h index 4de382f0..4de382f0 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.m index c3402d08..b589e1f3 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVUserAgentUtil.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVUserAgentUtil.m @@ -45,7 +45,9 @@ static NSMutableArray* gPendingSetUserAgentBlocks = nil; NSString* localeStr = [[NSLocale currentLocale] localeIdentifier]; // Record the model since simulator can change it without re-install (CB-5420). NSString* model = [UIDevice currentDevice].model; - NSString* systemAndLocale = [NSString stringWithFormat:@"%@ %@ %@", model, systemVersion, localeStr]; + // Record the version of the app so that we can bust the cache when it changes (CB-10078) + NSString* appVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"]; + NSString* systemAndLocale = [NSString stringWithFormat:@"%@ %@ %@ %@", appVersion, model, systemVersion, localeStr]; NSString* cordovaUserAgentVersion = [userDefaults stringForKey:kCdvUserAgentVersionKey]; gOriginalUserAgent = [userDefaults stringForKey:kCdvUserAgentKey]; diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVViewController.h index ed114049..90d33d22 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVViewController.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVViewController.h @@ -23,11 +23,13 @@ #import "CDVInvokedUrlCommand.h" #import "CDVCommandDelegate.h" #import "CDVCommandQueue.h" -#import "CDVWhitelist.h" #import "CDVScreenOrientationDelegate.h" #import "CDVPlugin.h" +#import "CDVWebViewEngineProtocol.h" -@interface CDVViewController : UIViewController <UIWebViewDelegate, CDVScreenOrientationDelegate>{ +@interface CDVViewController : UIViewController <CDVScreenOrientationDelegate>{ + @protected + id <CDVWebViewEngineProtocol> _webViewEngine; @protected id <CDVCommandDelegate> _commandDelegate; @protected @@ -35,18 +37,18 @@ NSString* _userAgent; } -@property (nonatomic, strong) IBOutlet UIWebView* webView; +@property (nonatomic, readonly, weak) IBOutlet UIView* webView; @property (nonatomic, readonly, strong) NSMutableDictionary* pluginObjects; @property (nonatomic, readonly, strong) NSDictionary* pluginsMap; @property (nonatomic, readonly, strong) NSMutableDictionary* settings; @property (nonatomic, readonly, strong) NSXMLParser* configParser; -@property (nonatomic, readonly, strong) CDVWhitelist* whitelist CDV_DEPRECATED(3.9.2, "Use URLisAllowed to check specific URL. This will be removed in 4.0.0"); // readonly for public -@property (nonatomic, readonly, assign) BOOL loadFromString CDV_DEPRECATED(3.9.2, "This will be removed in 4.0.0"); +@property (nonatomic, readwrite, copy) NSString* configFile; @property (nonatomic, readwrite, copy) NSString* wwwFolderName; @property (nonatomic, readwrite, copy) NSString* startPage; @property (nonatomic, readonly, strong) CDVCommandQueue* commandQueue; +@property (nonatomic, readonly, strong) id <CDVWebViewEngineProtocol> webViewEngine; @property (nonatomic, readonly, strong) id <CDVCommandDelegate> commandDelegate; /** @@ -61,15 +63,21 @@ */ @property (nonatomic, readwrite, copy) NSString* baseUserAgent; -+ (NSDictionary*)getBundlePlist:(NSString*)plistName CDV_DEPRECATED(3.9.2, "This will be removed in 4.0.0"); -+ (NSString*)applicationDocumentsDirectory CDV_DEPRECATED(3.9.2, "This will be removed in 4.0.0"); +/** + Takes/Gives an array of UIInterfaceOrientation (int) objects + ex. UIInterfaceOrientationPortrait +*/ +@property (nonatomic, readwrite, strong) NSArray* supportedOrientations; + +/** + The address of the lock token used for controlling access to setting the user-agent + */ +@property (nonatomic, readonly) NSInteger* userAgentLockToken; -- (void)printMultitaskingInfo CDV_DEPRECATED(3.9.2, "This will be removed in 4.0.0"); -- (void)createGapView CDV_DEPRECATED(3.9.2, "This will be removed in 4.0.0"); -- (UIWebView*)newCordovaViewWithFrame:(CGRect)bounds; +- (UIView*)newCordovaViewWithFrame:(CGRect)bounds; -- (void)javascriptAlert:(NSString*)text CDV_DEPRECATED(3.9.2, "Use the CDVCommandDelegate evalJs: directly. This will be removed in 4.0.0"); - (NSString*)appURLScheme; +- (NSURL*)errorURL; - (NSArray*)parseInterfaceOrientations:(NSArray*)orientations; - (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation; @@ -78,7 +86,6 @@ - (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className; - (void)registerPlugin:(CDVPlugin*)plugin withPluginName:(NSString*)pluginName; -- (BOOL)URLisAllowed:(NSURL*)url; -- (void)processOpenUrl:(NSURL*)url; +- (void)parseSettingsWithParser:(NSObject <NSXMLParserDelegate>*)delegate; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVViewController.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVViewController.m new file mode 100644 index 00000000..4019c204 --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVViewController.m @@ -0,0 +1,719 @@ +/* + 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 "CDVPlugin+Private.h" +#import "CDVUIWebViewDelegate.h" +#import "CDVConfigParser.h" +#import "CDVUserAgentUtil.h" +#import <AVFoundation/AVFoundation.h> +#import "NSDictionary+CordovaPreferences.h" +#import "CDVLocalStorage.h" +#import "CDVCommandDelegateImpl.h" + +@interface CDVViewController () { + NSInteger _userAgentLockToken; +} + +@property (nonatomic, readwrite, strong) NSXMLParser* configParser; +@property (nonatomic, readwrite, strong) NSMutableDictionary* settings; +@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginObjects; +@property (nonatomic, readwrite, strong) NSMutableArray* startupPluginNames; +@property (nonatomic, readwrite, strong) NSDictionary* pluginsMap; +@property (nonatomic, readwrite, strong) id <CDVWebViewEngineProtocol> webViewEngine; + +@property (readwrite, assign) BOOL initialized; + +@property (atomic, strong) NSURL* openURL; + +@end + +@implementation CDVViewController + +@synthesize supportedOrientations; +@synthesize pluginObjects, pluginsMap, startupPluginNames; +@synthesize configParser, settings; +@synthesize wwwFolderName, startPage, initialized, openURL, baseUserAgent; +@synthesize commandDelegate = _commandDelegate; +@synthesize commandQueue = _commandQueue; +@synthesize webViewEngine = _webViewEngine; +@dynamic webView; + +- (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]; + + // 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; + } +} + +- (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)printVersion +{ + NSLog(@"Apache Cordova native platform version %@ is starting.", CDV_VERSION); +} + +- (void)printPlatformVersionWarning +{ + if (!IsAtLeastiOSVersion(@"8.0")) { + NSLog(@"CRITICAL: For Cordova 4.0.0 and above, you will need to upgrade to at least iOS 8.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"); +} + +-(NSString*)configFilePath{ + NSString* path = self.configFile ?: @"config.xml"; + + // if path is relative, resolve it against the main bundle + if(![path isAbsolutePath]){ + NSString* absolutePath = [[NSBundle mainBundle] pathForResource:path ofType:nil]; + if(!absolutePath){ + NSAssert(NO, @"ERROR: %@ not found in the main bundle!", path); + } + path = absolutePath; + } + + // Assert file exists + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + NSAssert(NO, @"ERROR: %@ does not exist. Please run cordova-ios/bin/cordova_plist_to_config_xml path/to/project.", path); + return nil; + } + + return path; +} + +- (void)parseSettingsWithParser:(NSObject <NSXMLParserDelegate>*)delegate +{ + // read from config.xml in the app bundle + NSString* path = [self configFilePath]; + + NSURL* url = [NSURL fileURLWithPath:path]; + + self.configParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; + if (self.configParser == nil) { + NSLog(@"Failed to initialize XML parser."); + return; + } + [self.configParser setDelegate:((id < NSXMLParserDelegate >)delegate)]; + [self.configParser parse]; +} + +- (void)loadSettings +{ + CDVConfigParser* delegate = [[CDVConfigParser alloc] init]; + + [self parseSettingsWithParser:delegate]; + + // Get the plugin dictionary, whitelist and settings from the delegate. + self.pluginsMap = delegate.pluginsDict; + self.startupPluginNames = delegate.startupPluginNames; + self.settings = delegate.settings; + + // And the start folder/page. + if(self.wwwFolderName == nil){ + self.wwwFolderName = @"www"; + } + if(delegate.startPage && self.startPage == nil){ + 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 if([self.wwwFolderName hasSuffix:@".bundle"]){ + // www folder is actually a bundle + NSBundle* bundle = [NSBundle bundleWithPath:self.wwwFolderName]; + appURL = [bundle URLForResource:self.startPage withExtension:nil]; + } else if([self.wwwFolderName hasSuffix:@".framework"]){ + // www folder is actually a framework + NSBundle* bundle = [NSBundle bundleWithPath:self.wwwFolderName]; + appURL = [bundle URLForResource:self.startPage withExtension:nil]; + } 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) { + 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.settings cordovaSettingForKey:@"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; +} + +- (UIView*)webView +{ + if (self.webViewEngine != nil) { + return self.webViewEngine.engineWebView; + } + + return nil; +} + +// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Load settings + [self loadSettings]; + + NSString* backupWebStorageType = @"cloud"; // default value + + id backupWebStorage = [self.settings cordovaSettingForKey:@"BackupWebStorage"]; + if ([backupWebStorage isKindOfClass:[NSString class]]) { + backupWebStorageType = backupWebStorage; + } + [self.settings setCordovaSetting:backupWebStorageType forKey:@"BackupWebStorage"]; + + [CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType]; + + // // Instantiate the WebView /////////////// + + if (!self.webView) { + [self createGapView]; + } + + // ///////////////// + + /* + * 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. + With minimum iOS 7/8 supported, only first clause applies. + */ + if ([backupWebStorageType isEqualToString:@"local"]) { + NSString* localStorageFeatureName = @"localstorage"; + if ([self.pluginsMap objectForKey:localStorageFeatureName]) { // plugin specified in config + [self.startupPluginNames addObject:localStorageFeatureName]; + } + } + + 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"]; + } + + // ///////////////// + 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.webViewEngine 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.webViewEngine loadRequest:[NSURLRequest requestWithURL:errorUrl]]; + } else { + NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr]; + [self.webViewEngine loadHTMLString:html baseURL:nil]; + } + } + }]; +} + +-(void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillAppearNotification object:nil]]; +} + +-(void)viewDidAppear:(BOOL)animated +{ + [super viewDidAppear:animated]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewDidAppearNotification object:nil]]; +} + +-(void)viewWillDisappear:(BOOL)animated +{ + [super viewWillDisappear:animated]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillDisappearNotification object:nil]]; +} + +-(void)viewDidDisappear:(BOOL)animated +{ + [super viewDidDisappear:animated]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewDidDisappearNotification object:nil]]; +} + +-(void)viewWillLayoutSubviews +{ + [super viewWillLayoutSubviews]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillLayoutSubviewsNotification object:nil]]; +} + +-(void)viewDidLayoutSubviews +{ + [super viewDidLayoutSubviews]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewDidLayoutSubviewsNotification object:nil]]; +} + +-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator +{ + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVViewWillTransitionToSizeNotification object:[NSValue valueWithCGSize:size]]]; +} + +- (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; +} + +- (BOOL)shouldAutorotate +{ + return YES; +} + +- (NSUInteger)supportedInterfaceOrientations +{ + NSUInteger ret = 0; + + if ([self supportsOrientation:UIInterfaceOrientationPortrait]) { + ret = ret | (1 << UIInterfaceOrientationPortrait); + } + if ([self supportsOrientation:UIInterfaceOrientationPortraitUpsideDown]) { + ret = ret | (1 << UIInterfaceOrientationPortraitUpsideDown); + } + if ([self supportsOrientation:UIInterfaceOrientationLandscapeRight]) { + ret = ret | (1 << UIInterfaceOrientationLandscapeRight); + } + if ([self supportsOrientation:UIInterfaceOrientationLandscapeLeft]) { + ret = ret | (1 << UIInterfaceOrientationLandscapeLeft); + } + + return ret; +} + +- (BOOL)supportsOrientation:(UIInterfaceOrientation)orientation +{ + return [self.supportedOrientations containsObject:[NSNumber numberWithInt:orientation]]; +} + +- (UIView*)newCordovaViewWithFrame:(CGRect)bounds +{ + NSString* defaultWebViewEngineClass = [self.settings cordovaSettingForKey:@"CordovaDefaultWebViewEngine"]; + NSString* webViewEngineClass = [self.settings cordovaSettingForKey:@"CordovaWebViewEngine"]; + + if (!defaultWebViewEngineClass) { + defaultWebViewEngineClass = @"CDVUIWebViewEngine"; + } + if (!webViewEngineClass) { + webViewEngineClass = defaultWebViewEngineClass; + } + + // Find webViewEngine + if (NSClassFromString(webViewEngineClass)) { + self.webViewEngine = [[NSClassFromString(webViewEngineClass) alloc] initWithFrame:bounds]; + // if a webView engine returns nil (not supported by the current iOS version) or doesn't conform to the protocol, or can't load the request, we use UIWebView + if (!self.webViewEngine || ![self.webViewEngine conformsToProtocol:@protocol(CDVWebViewEngineProtocol)] || ![self.webViewEngine canLoadRequest:[NSURLRequest requestWithURL:self.appUrl]]) { + self.webViewEngine = [[NSClassFromString(defaultWebViewEngineClass) alloc] initWithFrame:bounds]; + } + } else { + self.webViewEngine = [[NSClassFromString(defaultWebViewEngineClass) alloc] initWithFrame:bounds]; + } + + if ([self.webViewEngine isKindOfClass:[CDVPlugin class]]) { + [self registerPlugin:(CDVPlugin*)self.webViewEngine withClassName:webViewEngineClass]; + } + + return self.webViewEngine.engineWebView; +} + +- (NSString*)userAgent +{ + if (_userAgent != nil) { + return _userAgent; + } + + NSString* localBaseUserAgent; + if (self.baseUserAgent != nil) { + localBaseUserAgent = self.baseUserAgent; + } else if ([self.settings cordovaSettingForKey:@"OverrideUserAgent"] != nil) { + localBaseUserAgent = [self.settings cordovaSettingForKey:@"OverrideUserAgent"]; + } else { + localBaseUserAgent = [CDVUserAgentUtil originalUserAgent]; + } + NSString* appendUserAgent = [self.settings cordovaSettingForKey:@"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; + + UIView* view = [self newCordovaViewWithFrame:webViewBounds]; + + view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); + [self.view addSubview:view]; + [self.view sendSubviewToBack:view]; +} + +- (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; + + [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; + + [super viewDidUnload]; +} + +#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] initWithWebViewEngine:_webViewEngine]; + + 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; +} + +#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)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; + [_commandQueue dispose]; + [[self.pluginObjects allValues] makeObjectsPerformSelector:@selector(dispose)]; +} + +- (NSInteger*)userAgentLockToken +{ + return &_userAgentLockToken; +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h new file mode 100644 index 00000000..34d07f3d --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVWebViewEngineProtocol.h @@ -0,0 +1,42 @@ +/* + 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 <UIKit/UIKit.h> + +#define kCDVWebViewEngineScriptMessageHandlers @"kCDVWebViewEngineScriptMessageHandlers" +#define kCDVWebViewEngineUIWebViewDelegate @"kCDVWebViewEngineUIWebViewDelegate" +#define kCDVWebViewEngineWKNavigationDelegate @"kCDVWebViewEngineWKNavigationDelegate" +#define kCDVWebViewEngineWKUIDelegate @"kCDVWebViewEngineWKUIDelegate" +#define kCDVWebViewEngineWebViewPreferences @"kCDVWebViewEngineWebViewPreferences" + +@protocol CDVWebViewEngineProtocol <NSObject> + +@property (nonatomic, strong, readonly) UIView* engineWebView; + +- (id)loadRequest:(NSURLRequest*)request; +- (id)loadHTMLString:(NSString*)string baseURL:(NSURL*)baseURL; +- (void)evaluateJavaScript:(NSString*)javaScriptString completionHandler:(void (^)(id, NSError*))completionHandler; + +- (NSURL*)URL; +- (BOOL)canLoadRequest:(NSURLRequest*)request; + +- (instancetype)initWithFrame:(CGRect)frame; +- (void)updateWithInfo:(NSDictionary*)info; + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.h index 91650970..91650970 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.h diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.m index 8e3be752..552ea957 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/CDVWhitelist.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/CDVWhitelist.m @@ -64,7 +64,7 @@ NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme"; } else { _scheme = [NSRegularExpression regularExpressionWithPattern:[CDVWhitelistPattern regexFromPattern:scheme allowWildcards:NO] options:NSRegularExpressionCaseInsensitive error:nil]; } - if ([host isEqualToString:@"*"]) { + if ([host isEqualToString:@"*"] || host == nil) { _host = nil; } else if ([host hasPrefix:@"*."]) { _host = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"([a-z0-9.-]*\\.)?%@", [CDVWhitelistPattern regexFromPattern:[host substringFromIndex:2] allowWildcards:false]] options:NSRegularExpressionCaseInsensitive error:nil]; @@ -88,7 +88,7 @@ NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme"; - (bool)matches:(NSURL*)url { return (_scheme == nil || [_scheme numberOfMatchesInString:[url scheme] options:NSMatchingAnchored range:NSMakeRange(0, [[url scheme] length])]) && - (_host == nil || [_host numberOfMatchesInString:[url host] options:NSMatchingAnchored range:NSMakeRange(0, [[url host] length])]) && + (_host == nil || ([url host] != nil && [_host numberOfMatchesInString:[url host] options:NSMatchingAnchored range:NSMakeRange(0, [[url host] length])])) && (_port == nil || [[url port] isEqualToNumber:_port]) && (_path == nil || [_path numberOfMatchesInString:[url path] options:NSMatchingAnchored range:NSMakeRange(0, [[url path] length])]) ; @@ -169,7 +169,7 @@ NSString* const kCDVDefaultSchemeName = @"cdv-default-scheme"; self.whitelist = nil; self.permittedSchemes = nil; } else { // specific access - NSRegularExpression* parts = [NSRegularExpression regularExpressionWithPattern:@"^((\\*|[A-Za-z-]+)://)?(((\\*\\.)?[^*/:]+)|\\*)?(:(\\d+))?(/.*)?" options:0 error:nil]; + NSRegularExpression* parts = [NSRegularExpression regularExpressionWithPattern:@"^((\\*|[A-Za-z-]+):/?/?)?(((\\*\\.)?[^*/:]+)|\\*)?(:(\\d+))?(/.*)?" options:0 error:nil]; NSTextCheckingResult* m = [parts firstMatchInString:origin options:NSMatchingAnchored range:NSMakeRange(0, [origin length])]; if (m != nil) { NSRange r; diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.h index 1b2c0739..9be2be2d 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/UIDevice+Extensions.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.h @@ -18,15 +18,18 @@ */ #import <Foundation/Foundation.h> -#import "CDVAvailabilityDeprecated.h" +#import <UIKit/UIKit.h> -@interface UIDevice (org_apache_cordova_UIDevice_Extension) +@interface NSDictionary (CordovaPreferences) -/* - Get the unique identifier from the app bundle's folder, which is already a GUID - Upgrading and/or deleting the app and re-installing will get you a new GUID, so - this is only unique per install per device. - */ -- (NSString*)uniqueAppInstanceIdentifier CDV_DEPRECATED(3.8 .0, "API is slated for removal in 4.0.0"); +- (id)cordovaSettingForKey:(NSString*)key; +- (BOOL)cordovaBoolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue; +- (CGFloat)cordovaFloatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue; + +@end + +@interface NSMutableDictionary (CordovaPreferences) + +- (void)setCordovaSetting:(id)value forKey:(NSString*)key; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.m new file mode 100644 index 00000000..dcac40f1 --- /dev/null +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSDictionary+CordovaPreferences.m @@ -0,0 +1,63 @@ +/* + 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 "NSDictionary+CordovaPreferences.h" +#import <Foundation/Foundation.h> + +@implementation NSDictionary (CordovaPreferences) + +- (id)cordovaSettingForKey:(NSString*)key +{ + return [self objectForKey:[key lowercaseString]]; +} + +- (BOOL)cordovaBoolSettingForKey:(NSString*)key defaultValue:(BOOL)defaultValue +{ + BOOL value = defaultValue; + id prefObj = [self cordovaSettingForKey:key]; + + if (prefObj != nil) { + value = [(NSNumber*)prefObj boolValue]; + } + + return value; +} + +- (CGFloat)cordovaFloatSettingForKey:(NSString*)key defaultValue:(CGFloat)defaultValue +{ + CGFloat value = defaultValue; + id prefObj = [self cordovaSettingForKey:key]; + + if (prefObj != nil) { + value = [prefObj floatValue]; + } + + return value; +} + +@end + +@implementation NSMutableDictionary (CordovaPreferences) + +- (void)setCordovaSetting:(id)value forKey:(NSString*)key +{ + [self setObject:value forKey:[key lowercaseString]]; +} + +@end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.h b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.h index 31940949..79e65164 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.h +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.h @@ -21,9 +21,9 @@ @interface NSMutableArray (QueueAdditions) -- (id)pop; -- (id)queueHead; -- (id)dequeue; -- (void)enqueue:(id)obj; +- (id)cdv_pop; +- (id)cdv_queueHead; +- (id)cdv_dequeue; +- (void)cdv_enqueue:(id)obj; @end diff --git a/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.m b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.m index 9e67edeb..2b3acdc0 100755..100644 --- a/StoneIsland/platforms/ios/CordovaLib/Classes/NSMutableArray+QueueAdditions.m +++ b/StoneIsland/platforms/ios/CordovaLib/Classes/Public/NSMutableArray+QueueAdditions.m @@ -21,7 +21,7 @@ @implementation NSMutableArray (QueueAdditions) -- (id)queueHead +- (id)cdv_queueHead { if ([self count] == 0) { return nil; @@ -30,7 +30,7 @@ return [self objectAtIndex:0]; } -- (__autoreleasing id)dequeue +- (__autoreleasing id)cdv_dequeue { if ([self count] == 0) { return nil; @@ -45,12 +45,12 @@ return head; } -- (id)pop +- (id)cdv_pop { - return [self dequeue]; + return [self cdv_dequeue]; } -- (void)enqueue:(id)object +- (void)cdv_enqueue:(id)object { [self addObject:object]; } |
