Updated Branches: refs/heads/master 478f683a1 -> db43c7668
[CB-3530] PhoneGap app crashes on iOS with error "CDVWebViewDelegate: Navigation started when state=1" (for navigation to an anchor on the same page) commit fe971530ea4bd5e083cc4d8f70f692f55bd3469f Author: Shazron Abdullah <[email protected]> Date: Wed Jun 19 15:13:59 2013 -0700 Remove verbose NSLogs. commit caa93a57b0de81d619effff217fdc20fcc329bc4 Author: Shazron Abdullah <[email protected]> Date: Tue Jun 18 17:50:01 2013 -0700 [CB-3530] PhoneGap app crashes on iOS with error "CDVWebViewDelegate: Navigation started when state=1" (for navigation to an anchor on the same page) Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/db43c766 Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/db43c766 Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/db43c766 Branch: refs/heads/master Commit: db43c7668c93e916eddba978475f22e6e8b9d61f Parents: 478f683 Author: Shazron Abdullah <[email protected]> Authored: Wed Jun 19 15:16:37 2013 -0700 Committer: Shazron Abdullah <[email protected]> Committed: Wed Jun 19 15:16:37 2013 -0700 ---------------------------------------------------------------------- CordovaLib/Classes/CDVWebViewDelegate.h | 1 + CordovaLib/Classes/CDVWebViewDelegate.m | 49 ++++++++++++- CordovaLibTests/CDVWebViewDelegateTests.m | 77 ++++++++++++++++++++ .../CordovaTests.xcodeproj/project.pbxproj | 4 + 4 files changed, 127 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/db43c766/CordovaLib/Classes/CDVWebViewDelegate.h ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVWebViewDelegate.h b/CordovaLib/Classes/CDVWebViewDelegate.h index a4d78bd..dd71807 100644 --- a/CordovaLib/Classes/CDVWebViewDelegate.h +++ b/CordovaLib/Classes/CDVWebViewDelegate.h @@ -34,5 +34,6 @@ } - (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate; +- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest; @end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/db43c766/CordovaLib/Classes/CDVWebViewDelegate.m ---------------------------------------------------------------------- diff --git a/CordovaLib/Classes/CDVWebViewDelegate.m b/CordovaLib/Classes/CDVWebViewDelegate.m index 1ee7aea..7254c2e 100644 --- a/CordovaLib/Classes/CDVWebViewDelegate.m +++ b/CordovaLib/Classes/CDVWebViewDelegate.m @@ -103,6 +103,45 @@ typedef enum { return self; } +- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest +{ + if (originalRequest.URL && newRequest.URL) { + NSString* originalRequestUrl = [originalRequest.URL absoluteString]; + NSString* newRequestUrl = [newRequest.URL absoluteString]; + + // no fragment, easy + if (newRequest.URL.fragment == nil) { + return NO; + } + + // if the urls have fragments and they are equal + if ((originalRequest.URL.fragment && newRequest.URL.fragment) && [originalRequestUrl isEqualToString:newRequestUrl]) { + return YES; + } + + NSString* urlFormat = @"%@://%@:%d/%@#%@"; + // reconstruct the URLs (ignoring basic auth credentials, query string) + NSString* baseOriginalRequestUrl = [NSString stringWithFormat:urlFormat, + [originalRequest.URL scheme], + [originalRequest.URL host], + [[originalRequest.URL port] intValue], + [originalRequest.URL path], + [newRequest.URL fragment] // add the new request's fragment + ]; + NSString* baseNewRequestUrl = [NSString stringWithFormat:urlFormat, + [newRequest.URL scheme], + [newRequest.URL host], + [[newRequest.URL port] intValue], + [newRequest.URL path], + [newRequest.URL fragment] + ]; + + return [baseOriginalRequestUrl isEqualToString:baseNewRequestUrl]; + } + + return NO; +} + - (BOOL)isPageLoaded:(UIWebView*)webView { NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]; @@ -198,10 +237,12 @@ typedef enum { NSLog(@"%@", description); _loadCount = 0; _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]; - [_delegate webView:webView didFailLoadWithError:error]; + if (![self request:request isFragmentIdentifierToRequest:webView.request]) { + if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { + NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description}; + NSError* error = [[NSError alloc] initWithDomain:@"CDVWebViewDelegate" code:1 userInfo:errorDictionary]; + [_delegate webView:webView didFailLoadWithError:error]; + } } } } http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/db43c766/CordovaLibTests/CDVWebViewDelegateTests.m ---------------------------------------------------------------------- diff --git a/CordovaLibTests/CDVWebViewDelegateTests.m b/CordovaLibTests/CDVWebViewDelegateTests.m new file mode 100644 index 0000000..1e536fa --- /dev/null +++ b/CordovaLibTests/CDVWebViewDelegateTests.m @@ -0,0 +1,77 @@ +/* + 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 <SenTestingKit/SenTestingKit.h> + +#import <Cordova/CDVWebViewDelegate.h> + +@interface CDVWebViewDelegateTests : SenTestCase +@end + +@implementation CDVWebViewDelegateTests + +- (void)setUp +{ + [super setUp]; +} + +- (void)tearDown +{ + [super tearDown]; +} + +- (void)testFragmentIdentifiersWithHttpUrl +{ + [self doTestFragmentIdentifiersWithBaseUrl:@"http://cordova.apache.org"]; +} + +- (void)testFragmentIdentifiersWithFileUrl +{ + [self doTestFragmentIdentifiersWithBaseUrl:@"file:///var/mobile/GASGEQGQsdga3313/www/index.html"]; +} + +- (void)doTestFragmentIdentifiersWithBaseUrl:(NSString*)baseUrl +{ + CDVWebViewDelegate* wvd = [[CDVWebViewDelegate alloc] initWithDelegate:nil]; // not really testing delegate handling + + NSString* originalUrlString = baseUrl; + NSURL* originalUrl = [NSURL URLWithString:originalUrlString]; + NSURL* originalUrlWithFragmentOnly = [NSURL URLWithString:[NSString stringWithFormat:@"%@#myfragment", originalUrlString]]; + NSURL* originalUrlWithFragmentOnlyNoIdentifier = [NSURL URLWithString:[NSString stringWithFormat:@"%@#", originalUrlString]]; + NSURL* originalUrlWithQueryParamsAndFragment = [NSURL URLWithString:[NSString stringWithFormat:@"%@?foo=bar#myfragment", originalUrlString]]; + + NSURLRequest* originalRequest = [NSURLRequest requestWithURL:originalUrl]; + NSURLRequest* originalRequestWithFragmentOnly = [NSURLRequest requestWithURL:originalUrlWithFragmentOnly]; + NSURLRequest* originalRequestWithFragmentOnlyNoIdentifier = [NSURLRequest requestWithURL:originalUrlWithFragmentOnlyNoIdentifier]; + NSURLRequest* originalRequestWithQueryParamsAndFragment = [NSURLRequest requestWithURL:originalUrlWithQueryParamsAndFragment]; + NSURLRequest* notOriginalRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://httpd.apache.org"]]; + + STAssertFalse([wvd request:originalRequest isFragmentIdentifierToRequest:originalRequest], @"originalRequest should not be a fragment of originalRequest"); + STAssertTrue([wvd request:originalRequestWithFragmentOnly isFragmentIdentifierToRequest:originalRequest], @"originalRequestWithFragment should be a fragment of originalRequest"); + STAssertTrue([wvd request:originalRequestWithFragmentOnlyNoIdentifier isFragmentIdentifierToRequest:originalRequest], @"originalRequestWithFragmentNoIdentifier should be a fragment of originalRequest"); + STAssertTrue([wvd request:originalRequestWithQueryParamsAndFragment isFragmentIdentifierToRequest:originalRequest], @"originalRequestWithQueryParamsAndFragment should be a fragment of originalRequest"); + STAssertFalse([wvd request:notOriginalRequest isFragmentIdentifierToRequest:originalRequest], @"notOriginalRequest should not be a fragment of originalRequest"); + + // equality tests + STAssertTrue([wvd request:originalRequestWithFragmentOnly isFragmentIdentifierToRequest:originalRequestWithFragmentOnly], @"originalRequestWithFragment should be a fragment of itself"); + STAssertTrue([wvd request:originalRequestWithFragmentOnlyNoIdentifier isFragmentIdentifierToRequest:originalRequestWithFragmentOnlyNoIdentifier], @"originalRequestWithFragmentNoIdentifier should be a fragment of itself"); + STAssertTrue([wvd request:originalRequestWithQueryParamsAndFragment isFragmentIdentifierToRequest:originalRequestWithQueryParamsAndFragment], @"originalRequestWithQueryParamsAndFragment should be a fragment of itself"); +} + +@end http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/db43c766/CordovaLibTests/CordovaTests.xcodeproj/project.pbxproj ---------------------------------------------------------------------- diff --git a/CordovaLibTests/CordovaTests.xcodeproj/project.pbxproj b/CordovaLibTests/CordovaTests.xcodeproj/project.pbxproj index 3ac6c85..88ac047 100644 --- a/CordovaLibTests/CordovaTests.xcodeproj/project.pbxproj +++ b/CordovaLibTests/CordovaTests.xcodeproj/project.pbxproj @@ -43,6 +43,7 @@ 68A32D7E141030EB006B237C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 686357AA141002F100DF4CF2 /* UIKit.framework */; }; 68A32D7F141030F3006B237C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 686357AC141002F100DF4CF2 /* Foundation.framework */; }; 7E13A295175D487B00E522AB /* CDVExifTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E13A294175D487B00E522AB /* CDVExifTests.m */; }; + 7E91406017711D88002C6A3F /* CDVWebViewDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E91405F17711D88002C6A3F /* CDVWebViewDelegateTests.m */; }; 8220B5C216D541BD00EC3921 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8220B5C116D541BD00EC3921 /* AssetsLibrary.framework */; }; 8220B5C616D542F500EC3921 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8220B5C116D541BD00EC3921 /* AssetsLibrary.framework */; }; EB3B34E9161B5532003DBE7D /* libCordova.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EB3B34E6161B5454003DBE7D /* libCordova.a */; }; @@ -110,6 +111,7 @@ 68A32D7414103017006B237C /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; 7E13A293175D487B00E522AB /* CDVExifTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDVExifTests.h; sourceTree = "<group>"; }; 7E13A294175D487B00E522AB /* CDVExifTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVExifTests.m; sourceTree = "<group>"; }; + 7E91405F17711D88002C6A3F /* CDVWebViewDelegateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVWebViewDelegateTests.m; sourceTree = "<group>"; }; 8220B5C116D541BD00EC3921 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; EB37018115D18B2D00BEBC43 /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = ../CordovaLib/CordovaLib.xcodeproj; sourceTree = "<group>"; }; EB89634915FE66EA00E12277 /* CDVInvokedUrlCommandTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDVInvokedUrlCommandTests.m; sourceTree = "<group>"; }; @@ -250,6 +252,7 @@ EB3B34F4161B585D003DBE7D /* CordovaLibTests */ = { isa = PBXGroup; children = ( + 7E91405F17711D88002C6A3F /* CDVWebViewDelegateTests.m */, 7E13A293175D487B00E522AB /* CDVExifTests.h */, 7E13A294175D487B00E522AB /* CDVExifTests.m */, EB96677116ADBCF500D86CDF /* CDVUserAgentTest.m */, @@ -435,6 +438,7 @@ EB89634A15FE66EA00E12277 /* CDVInvokedUrlCommandTests.m in Sources */, EB96677216ADBCF500D86CDF /* CDVUserAgentTest.m in Sources */, 7E13A295175D487B00E522AB /* CDVExifTests.m in Sources */, + 7E91406017711D88002C6A3F /* CDVWebViewDelegateTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };
