aboutsummaryrefslogtreecommitdiffstats
path: root/iPhone/CordovaLib/Classes/CDVWebViewDelegate.m
diff options
context:
space:
mode:
authorDave Arter <davea@mysociety.org>2015-07-17 15:51:54 +0100
committerDave Arter <davea@mysociety.org>2015-08-28 14:27:15 +0100
commitaf7c5ce2233eb14a5ba57cc581948ffa9658ecc2 (patch)
treeb22ed93c540aaa58a3aa91f71d5e3329a5641be6 /iPhone/CordovaLib/Classes/CDVWebViewDelegate.m
parente1fc2b466ae83d221864232851b1f55ff012f38c (diff)
Upgrade iOS version of the app to latest Cordova; remove old phonegap 2 bits
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVWebViewDelegate.m')
-rwxr-xr-xiPhone/CordovaLib/Classes/CDVWebViewDelegate.m380
1 files changed, 0 insertions, 380 deletions
diff --git a/iPhone/CordovaLib/Classes/CDVWebViewDelegate.m b/iPhone/CordovaLib/Classes/CDVWebViewDelegate.m
deleted file mode 100755
index 7254c2e..0000000
--- a/iPhone/CordovaLib/Classes/CDVWebViewDelegate.m
+++ /dev/null
@@ -1,380 +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.
- */
-
-//
-// Testing shows:
-//
-// In all cases, webView.request.URL is the previous page's URL (or empty) during the didStartLoad callback.
-// When loading a page with a redirect:
-// 1. shouldStartLoading (requestURL is target page)
-// 2. didStartLoading
-// 3. shouldStartLoading (requestURL is redirect target)
-// 4. didFinishLoad (request.URL is redirect target)
-//
-// Note the lack of a second didStartLoading **
-//
-// When loading a page with iframes:
-// 1. shouldStartLoading (requestURL is main page)
-// 2. didStartLoading
-// 3. shouldStartLoading (requestURL is one of the iframes)
-// 4. didStartLoading
-// 5. didFinishLoad
-// 6. didFinishLoad
-//
-// Note there is no way to distinguish which didFinishLoad maps to which didStartLoad **
-//
-// Loading a page by calling window.history.go(-1):
-// 1. didStartLoading
-// 2. didFinishLoad
-//
-// Note the lack of a shouldStartLoading call **
-// Actually - this is fixed on iOS6. iOS6 has a shouldStart. **
-//
-// Loading a page by calling location.reload()
-// 1. shouldStartLoading
-// 2. didStartLoading
-// 3. didFinishLoad
-//
-// Loading a page with an iframe that fails to load:
-// 1. shouldStart (main page)
-// 2. didStart
-// 3. shouldStart (iframe)
-// 4. didStart
-// 5. didFailWithError
-// 6. didFinish
-//
-// Loading a page with an iframe that fails to load due to an invalid URL:
-// 1. shouldStart (main page)
-// 2. didStart
-// 3. shouldStart (iframe)
-// 5. didFailWithError
-// 6. didFinish
-//
-// This case breaks our logic since there is a missing didStart. To prevent this,
-// we check URLs in shouldStart and return NO if they are invalid.
-//
-// Loading a page with an invalid URL
-// 1. shouldStart (main page)
-// 2. didFailWithError
-//
-// TODO: Record order when page is re-navigated before the first navigation finishes.
-//
-
-#import "CDVWebViewDelegate.h"
-#import "CDVAvailability.h"
-
-// #define VerboseLog NSLog
-#define VerboseLog(...) do {} while (0)
-
-typedef enum {
- STATE_IDLE,
- STATE_WAITING_FOR_LOAD_START,
- STATE_WAITING_FOR_LOAD_FINISH,
- STATE_IOS5_POLLING_FOR_LOAD_START,
- STATE_IOS5_POLLING_FOR_LOAD_FINISH
-} State;
-
-@implementation CDVWebViewDelegate
-
-- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate
-{
- self = [super init];
- if (self != nil) {
- _delegate = delegate;
- _loadCount = -1;
- _state = STATE_IDLE;
- }
- 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"];
-
- return [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
-}
-
-- (BOOL)isJsLoadTokenSet:(UIWebView*)webView
-{
- NSString* loadToken = [webView stringByEvaluatingJavaScriptFromString:@"window.__cordovaLoadToken"];
-
- return [[NSString stringWithFormat:@"%d", _curLoadToken] isEqualToString:loadToken];
-}
-
-- (void)setLoadToken:(UIWebView*)webView
-{
- _curLoadToken += 1;
- [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.__cordovaLoadToken=%d", _curLoadToken]];
-}
-
-- (void)pollForPageLoadStart:(UIWebView*)webView
-{
- if (_state != STATE_IOS5_POLLING_FOR_LOAD_START) {
- return;
- }
- if (![self isJsLoadTokenSet:webView]) {
- VerboseLog(@"Polled for page load start. result = YES!");
- _state = STATE_IOS5_POLLING_FOR_LOAD_FINISH;
- [self setLoadToken:webView];
- if ([_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
- [_delegate webViewDidStartLoad:webView];
- }
- [self pollForPageLoadFinish:webView];
- } else {
- VerboseLog(@"Polled for page load start. result = NO");
- // Poll only for 1 second, and then fall back on checking only when delegate methods are called.
- ++_loadStartPollCount;
- if (_loadStartPollCount < (1000 * .05)) {
- [self performSelector:@selector(pollForPageLoadStart:) withObject:webView afterDelay:.05];
- }
- }
-}
-
-- (void)pollForPageLoadFinish:(UIWebView*)webView
-{
- if (_state != STATE_IOS5_POLLING_FOR_LOAD_FINISH) {
- return;
- }
- if ([self isPageLoaded:webView]) {
- VerboseLog(@"Polled for page load finish. result = YES!");
- _state = STATE_IDLE;
- if ([_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
- [_delegate webViewDidFinishLoad:webView];
- }
- } else {
- VerboseLog(@"Polled for page load finish. result = NO");
- [self performSelector:@selector(pollForPageLoadFinish:) withObject:webView afterDelay:.05];
- }
-}
-
-- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
-{
- BOOL shouldLoad = YES;
-
- if ([_delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
- shouldLoad = [_delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
- }
-
- VerboseLog(@"webView shouldLoad=%d (before) state=%d loadCount=%d URL=%@", shouldLoad, _state, _loadCount, request.URL);
-
- if (shouldLoad) {
- BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
- if (isTopLevelNavigation) {
- switch (_state) {
- case STATE_WAITING_FOR_LOAD_FINISH:
- // Redirect case.
- // We expect loadCount == 1.
- if (_loadCount != 1) {
- NSLog(@"CDVWebViewDelegate: Detected redirect when loadCount=%d", _loadCount);
- }
- break;
-
- case STATE_IDLE:
- case STATE_IOS5_POLLING_FOR_LOAD_START:
- // Page navigation start.
- _loadCount = 0;
- _state = STATE_WAITING_FOR_LOAD_START;
- break;
-
- default:
- {
- NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%d", _state];
- NSLog(@"%@", description);
- _loadCount = 0;
- _state = STATE_WAITING_FOR_LOAD_START;
- 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];
- }
- }
- }
- }
- } else {
- // Deny invalid URLs so that we don't get the case where we go straight from
- // webViewShouldLoad -> webViewDidFailLoad (messes up _loadCount).
- shouldLoad = shouldLoad && [NSURLConnection canHandleRequest:request];
- }
- VerboseLog(@"webView shouldLoad=%d (after) isTopLevelNavigation=%d state=%d loadCount=%d", shouldLoad, isTopLevelNavigation, _state, _loadCount);
- }
- return shouldLoad;
-}
-
-- (void)webViewDidStartLoad:(UIWebView*)webView
-{
- VerboseLog(@"webView didStartLoad (before). state=%d loadCount=%d", _state, _loadCount);
- 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 naviagtion).
- _state = STATE_IOS5_POLLING_FOR_LOAD_START;
- _loadStartPollCount = 0;
- [self setLoadToken:webView];
- [self pollForPageLoadStart:webView];
- break;
-
- case STATE_WAITING_FOR_LOAD_START:
- if (_loadCount != 0) {
- NSLog(@"CDVWebViewDelegate: Unexpected loadCount in didStart. count=%d", _loadCount);
- }
- fireCallback = YES;
- _state = STATE_WAITING_FOR_LOAD_FINISH;
- _loadCount = 1;
- break;
-
- case STATE_WAITING_FOR_LOAD_FINISH:
- _loadCount += 1;
- break;
-
- case STATE_IOS5_POLLING_FOR_LOAD_START:
- [self pollForPageLoadStart:webView];
- break;
-
- case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
- [self pollForPageLoadFinish:webView];
- break;
-
- default:
- NSLog(@"CDVWebViewDelegate: Unexpected didStart with state=%d loadCount=%d", _state, _loadCount);
- }
- VerboseLog(@"webView didStartLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
- if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
- [_delegate webViewDidStartLoad:webView];
- }
-}
-
-- (void)webViewDidFinishLoad:(UIWebView*)webView
-{
- VerboseLog(@"webView didFinishLoad (before). state=%d loadCount=%d", _state, _loadCount);
- BOOL fireCallback = NO;
- switch (_state) {
- case STATE_IDLE:
- break;
-
- case STATE_WAITING_FOR_LOAD_START:
- NSLog(@"CDVWebViewDelegate: Unexpected didFinish while waiting for load start.");
- break;
-
- case STATE_WAITING_FOR_LOAD_FINISH:
- if (_loadCount == 1) {
- fireCallback = YES;
- _state = STATE_IDLE;
- }
- _loadCount -= 1;
- break;
-
- case STATE_IOS5_POLLING_FOR_LOAD_START:
- [self pollForPageLoadStart:webView];
- break;
-
- case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
- [self pollForPageLoadFinish:webView];
- break;
- }
- VerboseLog(@"webView didFinishLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
- if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
- [_delegate webViewDidFinishLoad:webView];
- }
-}
-
-- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
-{
- VerboseLog(@"webView didFailLoad (before). state=%d loadCount=%d", _state, _loadCount);
- BOOL fireCallback = NO;
-
- switch (_state) {
- case STATE_IDLE:
- break;
-
- case STATE_WAITING_FOR_LOAD_START:
- _state = STATE_IDLE;
- fireCallback = YES;
- break;
-
- case STATE_WAITING_FOR_LOAD_FINISH:
- if (_loadCount == 1) {
- _state = STATE_IDLE;
- fireCallback = YES;
- }
- _loadCount = -1;
- break;
-
- case STATE_IOS5_POLLING_FOR_LOAD_START:
- [self pollForPageLoadStart:webView];
- break;
-
- case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
- [self pollForPageLoadFinish:webView];
- break;
- }
- VerboseLog(@"webView didFailLoad (after). state=%d loadCount=%d, fireCallback=%d", _state, _loadCount, fireCallback);
- if (fireCallback && [_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
- [_delegate webView:webView didFailLoadWithError:error];
- }
-}
-
-@end