iosobjective-cnsurlprotocol

NSURLProtocol - startLoading not invoked


Since upgrading to iOS 9.1 my custom NSURLProtocol, won't invoke -(void)startLoading anymore. Has anyone else experienced this ?

Everything worked fine on iOS 8 ...

Code:

@implementation RZCustomProtocol
@dynamic request;

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    if ([request.URL.scheme isEqualToString:@"imsweb"]) {
        NSLog(@"%@", @"YES");
        return YES;
    }
    return NO;
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    return request;
}

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
    return [super requestIsCacheEquivalent:a toRequest:b];
}

- (void)startLoading {
    NSLog(@"STARTLOADING: %@", [self.request.URL absoluteString]);
    NSString *filename = [[self.request.URL lastPathComponent] stringByDeletingPathExtension];
    NSLog(@"%@", filename);
    NSString *videoUrl = [[NSBundle mainBundle] pathForResource:filename ofType:@"mp4"];
    NSData *video = [NSData dataWithContentsOfFile:videoUrl];
    NSLog(@"%lu", (unsigned long)video.length);
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL
                                                              statusCode:200 HTTPVersion:nil headerFields:@{
                                                                                                            @"Content-Length": [NSString stringWithFormat:@"%lu", (unsigned long)video.length],
                                                                                                            @"Content-Type": @"video/mp4",
                                                                                                            }];

    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    [self.client URLProtocol:self didLoadData:video];
    [self.client URLProtocolDidFinishLoading:self];
}

- (void)stopLoading {
    NSLog(@"STOPLOADING: %@", [self.request.URL absoluteString]);
}

Solution

  • I had the same issue. In my case, I was adding an iframe to the page dynamically using JavaScript and loading my custom protocol content in that. In iOS 9.1 the WebView refuses to load the iframe content when the main document is accessed over https, but it works fine over http. This looks like a new security control, to avoid loading insecure resources over a secure session.

    The fix I went with was to change my scheme to use https. For example, use https://imsweb/... instead of imsweb://. It's a bit of a hack but the best solution I could find.

    Something like:

    + (BOOL)canInitWithRequest:(NSURLRequest *)request
    {
        if ([request.URL.scheme isEqualToString:@"https"] &&
                [request.URL.host isEqualToString:@"imsweb"]) {
            NSLog(@"%@", @"YES");
            return YES;
        }
        return NO;
    }
    

    and of course you need to reconstruct the correct URL in startLoading.