diff options
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVViewController.m')
-rwxr-xr-x | iPhone/CordovaLib/Classes/CDVViewController.m | 341 |
1 files changed, 95 insertions, 246 deletions
diff --git a/iPhone/CordovaLib/Classes/CDVViewController.m b/iPhone/CordovaLib/Classes/CDVViewController.m index f1b36df..bec716d 100755 --- a/iPhone/CordovaLib/Classes/CDVViewController.m +++ b/iPhone/CordovaLib/Classes/CDVViewController.m @@ -22,36 +22,38 @@ #import "CDVCommandQueue.h" #import "CDVCommandDelegateImpl.h" #import "CDVConfigParser.h" +#import "CDVUserAgentUtil.h" +#import "CDVWebViewDelegate.h" #define degreesToRadian(x) (M_PI * (x) / 180.0) -#define CDV_USER_AGENT_KEY @"Cordova-User-Agent" -#define CDV_USER_AGENT_VERSION_KEY @"Cordova-User-Agent-Version" -static NSString* gOriginalUserAgent = nil; - -@interface CDVViewController () +@interface CDVViewController () { + NSInteger _userAgentLockToken; + CDVWebViewDelegate* _webViewDelegate; +} @property (nonatomic, readwrite, strong) NSXMLParser* configParser; -@property (nonatomic, readwrite, strong) NSDictionary* settings; +@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 (nonatomic, readwrite, strong) IBOutlet UIActivityIndicatorView* activityView; -@property (nonatomic, readwrite, strong) UIImageView* imageView; @property (readwrite, assign) BOOL initialized; +@property (atomic, strong) NSURL* openURL; + @end @implementation CDVViewController @synthesize webView, supportedOrientations; -@synthesize pluginObjects, pluginsMap, whitelist; +@synthesize pluginObjects, pluginsMap, whitelist, startupPluginNames; @synthesize configParser, settings, loadFromString; -@synthesize imageView, activityView, useSplashScreen; -@synthesize wwwFolderName, startPage, invokeString, initialized; +@synthesize useSplashScreen; +@synthesize wwwFolderName, startPage, initialized, openURL; @synthesize commandDelegate = _commandDelegate; @synthesize commandQueue = _commandQueue; @@ -60,38 +62,30 @@ static NSString* gOriginalUserAgent = nil; if ((self != nil) && !self.initialized) { _commandQueue = [[CDVCommandQueue alloc] initWithViewController:self]; _commandDelegate = [[CDVCommandDelegateImpl alloc] initWithViewController:self]; - [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedOrientationChange) - name:UIDeviceOrientationDidChangeNotification object:nil]; [[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(onAppLocaleDidChange:) - name:NSCurrentLocaleDidChangeNotification object:nil]; - - if (IsAtLeastiOSVersion(@"4.0")) { - [[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(onAppWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURL:) name:CDVPluginHandleOpenURLNotification object:nil]; // read from UISupportedInterfaceOrientations (or UISupportedInterfaceOrientations~iPad, if its iPad) from -Info.plist self.supportedOrientations = [self parseInterfaceOrientations: [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"]]; - self.wwwFolderName = @"www"; - self.startPage = @"index.html"; - [self printMultitaskingInfo]; [self printDeprecationNotice]; self.initialized = YES; // load config.xml settings [self loadSettings]; + useSplashScreen = YES; } } @@ -167,12 +161,20 @@ static NSString* gOriginalUserAgent = nil; [configParser parse]; // Get the plugin dictionary, whitelist and settings from the delegate. - self.pluginsMap = [delegate.pluginsDict dictionaryWithLowercaseKeys]; + 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:4]; + self.pluginObjects = [[NSMutableDictionary alloc] initWithCapacity:20]; } // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. @@ -203,13 +205,14 @@ static NSString* gOriginalUserAgent = nil; NSString* backupWebStorageType = @"cloud"; // default value - id backupWebStorage = [self.settings objectForKey:@"BackupWebStorage"]; + id backupWebStorage = self.settings[@"BackupWebStorage"]; if ([backupWebStorage isKindOfClass:[NSString class]]) { backupWebStorageType = backupWebStorage; } else if ([backupWebStorage isKindOfClass:[NSNumber class]]) { NSLog(@"Deprecated: BackupWebStorage boolean property is a string property now (none, local, cloud). A boolean value of 'true' will be mapped to 'cloud'. Consult the docs: http://docs.cordova.io/en/edge/guide_project-settings_ios_index.md.html#Project%%20Settings%%20for%%20iOS"); backupWebStorageType = [(NSNumber*) backupWebStorage boolValue] ? @"cloud" : @"none"; } + self.settings[@"BackupWebStorage"] = backupWebStorageType; if (IsAtLeastiOSVersion(@"5.1")) { [CDVLocalStorage __fixupDatabaseLocationsWithBackupType:backupWebStorageType]; @@ -244,8 +247,7 @@ static NSString* gOriginalUserAgent = nil; */ if (IsAtLeastiOSVersion(@"5.1") && (([backupWebStorageType isEqualToString:@"local"]) || ([backupWebStorageType isEqualToString:@"cloud"] && !IsAtLeastiOSVersion(@"6.0")))) { - [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView settings:[NSDictionary dictionaryWithObjectsAndKeys: - @"backupType", backupWebStorageType, nil]] withClassName:NSStringFromClass([CDVLocalStorage class])]; + [self registerPlugin:[[CDVLocalStorage alloc] initWithWebView:self.webView] withClassName:NSStringFromClass([CDVLocalStorage class])]; } /* @@ -305,15 +307,27 @@ static NSString* gOriginalUserAgent = nil; } } - // ///////////////// + for (NSString* pluginName in self.startupPluginNames) { + [self getCommandInstance:pluginName]; + } - if (!loadErr) { - NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0]; - [self.webView loadRequest:appReq]; - } else { - NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr]; - [self.webView loadHTMLString:html baseURL:nil]; + // TODO: Remove this explicit instantiation once we move to cordova-CLI. + if (useSplashScreen) { + [self getCommandInstance:@"splashscreen"]; } + + // ///////////////// + [CDVUserAgentUtil acquireLock:^(NSInteger lockToken) { + _userAgentLockToken = lockToken; + [CDVUserAgentUtil setUserAgent:self.userAgent lockToken:lockToken]; + if (!loadErr) { + NSURLRequest* appReq = [NSURLRequest requestWithURL:appURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0]; + [self.webView loadRequest:appReq]; + } else { + NSString* html = [NSString stringWithFormat:@"<html><body> %@ </body></html>", loadErr]; + [self.webView loadHTMLString:html baseURL:nil]; + } + }]; } - (NSArray*)parseInterfaceOrientations:(NSArray*)orientations @@ -411,55 +425,15 @@ static NSString* gOriginalUserAgent = nil; return [self.supportedOrientations containsObject:[NSNumber numberWithInt:orientation]]; } -/** - Called by UIKit when the device starts to rotate to a new orientation. This fires the \c setOrientation - method on the Orientation object in JavaScript. Look at the JavaScript documentation for more information. - */ -- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation -{ - if (!IsAtLeastiOSVersion(@"5.0")) { - NSString* jsCallback = [NSString stringWithFormat: - @"window.__defineGetter__('orientation',function(){ return %d; }); \ - cordova.fireWindowEvent('orientationchange');" - , [self mapIosOrientationToJsOrientation:fromInterfaceOrientation]]; - [self.commandDelegate evalJs:jsCallback]; - } -} - -- (CDVCordovaView*)newCordovaViewWithFrame:(CGRect)bounds -{ - return [[CDVCordovaView alloc] initWithFrame:bounds]; -} - -+ (NSString*)originalUserAgent +- (UIWebView*)newCordovaViewWithFrame:(CGRect)bounds { - if (gOriginalUserAgent == nil) { - NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; - NSString* systemVersion = [[UIDevice currentDevice] systemVersion]; - NSString* localeStr = [[NSLocale currentLocale] localeIdentifier]; - NSString* systemAndLocale = [NSString stringWithFormat:@"%@ %@", systemVersion, localeStr]; - - NSString* cordovaUserAgentVersion = [userDefaults stringForKey:CDV_USER_AGENT_VERSION_KEY]; - gOriginalUserAgent = [userDefaults stringForKey:CDV_USER_AGENT_KEY]; - BOOL cachedValueIsOld = ![systemAndLocale isEqualToString:cordovaUserAgentVersion]; - - if ((gOriginalUserAgent == nil) || cachedValueIsOld) { - UIWebView* sampleWebView = [[UIWebView alloc] initWithFrame:CGRectZero]; - gOriginalUserAgent = [sampleWebView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; - - [userDefaults setObject:gOriginalUserAgent forKey:CDV_USER_AGENT_KEY]; - [userDefaults setObject:systemAndLocale forKey:CDV_USER_AGENT_VERSION_KEY]; - - [userDefaults synchronize]; - } - } - return gOriginalUserAgent; + return [[UIWebView alloc] initWithFrame:bounds]; } - (NSString*)userAgent { if (_userAgent == nil) { - NSString* originalUserAgent = [[self class] originalUserAgent]; + NSString* originalUserAgent = [CDVUserAgentUtil originalUserAgent]; // Use our address as a unique number to append to the User-Agent. _userAgent = [NSString stringWithFormat:@"%@ (%lld)", originalUserAgent, (long long)self]; } @@ -473,18 +447,14 @@ static NSString* gOriginalUserAgent = nil; webViewBounds.origin = self.view.bounds.origin; if (!self.webView) { - // setting the UserAgent must occur before the UIWebView is instantiated. - // This is read per instantiation, so it does not affect the main Cordova UIWebView - NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys:self.userAgent, @"UserAgent", nil]; - [[NSUserDefaults standardUserDefaults] registerDefaults:dict]; - self.webView = [self newCordovaViewWithFrame:webViewBounds]; self.webView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); [self.view addSubview:self.webView]; [self.view sendSubviewToBack:self.webView]; - self.webView.delegate = self; + _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]; @@ -523,6 +493,7 @@ static NSString* gOriginalUserAgent = nil; self.webView.delegate = nil; self.webView = nil; + [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; } #pragma mark UIWebViewDelegate @@ -533,43 +504,41 @@ static NSString* gOriginalUserAgent = nil; */ - (void)webViewDidStartLoad:(UIWebView*)theWebView { + NSLog(@"Resetting plugins due to page load."); [_commandQueue resetRequestId]; - [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:nil]]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginResetNotification object:self.webView]]; } /** - Called when the webview finishes loading. This stops the activity view and closes the imageview + 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]; + + // The .onNativeReady().fire() will work when cordova.js is already loaded. + // The _nativeReady = true; is used when this is run before cordova.js is loaded. + NSString* nativeReady = @"try{cordova.require('cordova/channel').onNativeReady.fire();}catch(e){window._nativeReady = true;}"; + // Don't use [commandDelegate evalJs] here since it relies on cordova.js being loaded already. + [self.webView stringByEvaluatingJavaScriptFromString:nativeReady]; + /* * Hide the Top Activity THROBBER in the Battery Bar */ [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; - id autoHideSplashScreenValue = [self.settings objectForKey:@"AutoHideSplashScreen"]; - // if value is missing, default to yes - if ((autoHideSplashScreenValue == nil) || [autoHideSplashScreenValue boolValue]) { - self.imageView.hidden = YES; - self.activityView.hidden = YES; - [self.view.superview bringSubviewToFront:self.webView]; - } - [self didRotateFromInterfaceOrientation:(UIInterfaceOrientation)[[UIDevice currentDevice] orientation]]; + [self processOpenUrl]; - // The .onNativeReady().fire() will work when cordova.js is already loaded. - // The _nativeReady = true; is used when this is run before cordova.js is loaded. - NSString* nativeReady = @"try{cordova.require('cordova/channel').onNativeReady.fire();}catch(e){window._nativeReady = true;}"; - [self.commandDelegate evalJs:nativeReady]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:nil]]; } -- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error +- (void)webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error { - NSLog(@"Failed to load webpage with error: %@", [error localizedDescription]); + [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; - /* - if ([error code] != NSURLErrorCancelled) - alert([error localizedDescription]); - */ + NSLog(@"Failed to load webpage with error: %@", [error localizedDescription]); } - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType @@ -625,8 +594,6 @@ static NSString* gOriginalUserAgent = nil; * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview. */ else { - // BOOL isIFrame = ([theWebView.request.mainDocumentURL absoluteString] == nil); - if ([self.whitelist schemeIsAllowed:[url scheme]]) { return [self.whitelist URLIsAllowed:url]; } else { @@ -677,131 +644,6 @@ static NSString* gOriginalUserAgent = nil; return basePath; } -- (void)showSplashScreen -{ - CGRect screenBounds = [[UIScreen mainScreen] bounds]; - NSString* launchImageFile = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; - - if (launchImageFile == nil) { // fallback if no launch image was specified - if (CDV_IsIPhone5()) { - // iPhone 5 or iPod Touch 6th-gen - launchImageFile = @"Default-568h"; - } else { - launchImageFile = @"Default"; - } - } - - NSString* orientedLaunchImageFile = nil; - CGAffineTransform startupImageTransform = CGAffineTransformIdentity; - UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; - CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; - UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation; - UIImage* launchImage = nil; - - // default to center of screen as in the original implementation. This will produce the 20px jump - CGPoint center = CGPointMake((screenBounds.size.width / 2), (screenBounds.size.height / 2)); - - if (CDV_IsIPad()) { - if (!UIDeviceOrientationIsValidInterfaceOrientation(deviceOrientation)) { - deviceOrientation = (UIDeviceOrientation)statusBarOrientation; - } - - switch (deviceOrientation) { - case UIDeviceOrientationLandscapeLeft: // this is where the home button is on the right (yeah, I know, confusing) - { - orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Landscape", launchImageFile]; - startupImageTransform = CGAffineTransformMakeRotation(degreesToRadian(90)); - center.x -= MIN(statusBarFrame.size.width, statusBarFrame.size.height) / 2; - } - break; - - case UIDeviceOrientationLandscapeRight: // this is where the home button is on the left (yeah, I know, confusing) - { - orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Landscape", launchImageFile]; - startupImageTransform = CGAffineTransformMakeRotation(degreesToRadian(-90)); - center.x += MIN(statusBarFrame.size.width, statusBarFrame.size.height) / 2; - } - break; - - case UIDeviceOrientationPortraitUpsideDown: - { - orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Portrait", launchImageFile]; - startupImageTransform = CGAffineTransformMakeRotation(degreesToRadian(180)); - center.y -= MIN(statusBarFrame.size.width, statusBarFrame.size.height) / 2; - } - break; - - case UIDeviceOrientationPortrait: - default: - { - orientedLaunchImageFile = [NSString stringWithFormat:@"%@-Portrait", launchImageFile]; - startupImageTransform = CGAffineTransformIdentity; - center.y += MIN(statusBarFrame.size.width, statusBarFrame.size.height) / 2; - } - break; - } - } else { // not iPad - orientedLaunchImageFile = launchImageFile; - } - - launchImage = [UIImage imageNamed:[[self class] resolveImageResource:orientedLaunchImageFile]]; - if (launchImage == nil) { - NSLog(@"WARNING: Splash-screen image '%@' was not found. Orientation: %d, iPad: %d", orientedLaunchImageFile, deviceOrientation, CDV_IsIPad()); - } - - self.imageView = [[UIImageView alloc] initWithImage:launchImage]; - self.imageView.tag = 1; - self.imageView.center = center; - - self.imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin); - [self.imageView setTransform:startupImageTransform]; - [self.view.superview addSubview:self.imageView]; - - /* - * The Activity View is the top spinning throbber in the status/battery bar. We init it with the default Grey Style. - * - * whiteLarge = UIActivityIndicatorViewStyleWhiteLarge - * white = UIActivityIndicatorViewStyleWhite - * gray = UIActivityIndicatorViewStyleGray - * - */ - NSString* topActivityIndicator = [self.settings objectForKey:@"TopActivityIndicator"]; - UIActivityIndicatorViewStyle topActivityIndicatorStyle = UIActivityIndicatorViewStyleGray; - - if ([topActivityIndicator isEqualToString:@"whiteLarge"]) { - topActivityIndicatorStyle = UIActivityIndicatorViewStyleWhiteLarge; - } else if ([topActivityIndicator isEqualToString:@"white"]) { - topActivityIndicatorStyle = UIActivityIndicatorViewStyleWhite; - } else if ([topActivityIndicator isEqualToString:@"gray"]) { - topActivityIndicatorStyle = UIActivityIndicatorViewStyleGray; - } - - self.activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:topActivityIndicatorStyle]; - self.activityView.tag = 2; - - id showSplashScreenSpinnerValue = [self.settings objectForKey:@"ShowSplashScreenSpinner"]; - // backwards compatibility - if key is missing, default to true - if ((showSplashScreenSpinnerValue == nil) || [showSplashScreenSpinnerValue boolValue]) { - [self.view.superview addSubview:self.activityView]; - } - - self.activityView.center = self.view.center; - [self.activityView startAnimating]; - - [self.view.superview layoutSubviews]; -} - -BOOL gSplashScreenShown = NO; -- (void)receivedOrientationChange -{ - if (self.imageView == nil) { - gSplashScreenShown = YES; - if (self.useSplashScreen) { - [self showSplashScreen]; - } - } -} - #pragma mark CordovaCommands - (void)registerPlugin:(CDVPlugin*)plugin withClassName:(NSString*)className @@ -815,6 +657,7 @@ BOOL gSplashScreenShown = NO; } [self.pluginObjects setObject:plugin forKey:className]; + [plugin pluginInitialize]; } /** @@ -835,16 +678,9 @@ BOOL gSplashScreenShown = NO; id obj = [self.pluginObjects objectForKey:className]; if (!obj) { - // attempt to load the settings for this command class - NSDictionary* classSettings = [self.settings objectForKey:className]; - - if (classSettings) { - obj = [[NSClassFromString (className)alloc] initWithWebView:webView settings:classSettings]; - } else { - obj = [[NSClassFromString (className)alloc] initWithWebView:webView]; - } + obj = [[NSClassFromString (className)alloc] initWithWebView:webView]; - if ((obj != nil) && [obj isKindOfClass:[CDVPlugin class]]) { + if (obj != nil) { [self registerPlugin:obj withClassName:className]; } else { NSLog(@"CDVPlugin class %@ (pluginName: %@) does not exist.", className, pluginName); @@ -956,9 +792,21 @@ BOOL gSplashScreenShown = NO; [self.commandDelegate evalJs:@"cordova.fireDocumentEvent('pause', null, true);" scheduledOnRunLoop:NO]; } -- (void)onAppLocaleDidChange:(NSNotification*)notification +// /////////////////////// + +- (void)handleOpenURL:(NSNotification*)notification +{ + self.openURL = notification.object; +} + +- (void)processOpenUrl { - gOriginalUserAgent = nil; + if (self.openURL) { + // calls into javascript global function 'handleOpenURL' + NSString* jsString = [NSString stringWithFormat:@"handleOpenURL(\"%@\");", [self.openURL description]]; + [self.webView stringByEvaluatingJavaScriptFromString:jsString]; + self.openURL = nil; + } } // /////////////////////// @@ -972,9 +820,10 @@ BOOL gSplashScreenShown = NO; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSCurrentLocaleDidChangeNotification object:nil]; - + [[NSNotificationCenter defaultCenter] removeObserver:self name:CDVPluginHandleOpenURLNotification object:nil]; self.webView.delegate = nil; self.webView = nil; + [CDVUserAgentUtil releaseLock:&_userAgentLockToken]; [_commandQueue dispose]; [[self.pluginObjects allValues] makeObjectsPerformSelector:@selector(dispose)]; } |