Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSURLProtocol canInitWithRequest: only works for certain requests

I have a WebView that I want to intercept and modify certain requests from various sites. I am doing the exact same modification to each of the intercepted requests regardless of which site it comes from. It works perfectly for every site except one, for seemingly no reason. Here is my code:

In my ResourceLoadDelegate

- (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
{
    //predicates
    const NSPredicate *site1Predicate = [NSPredicate predicateWithFormat:@"SELF like \"/*predicate1*/""];
    const NSPredicate *site2Predicate = [NSPredicate predicateWithFormat:@"SELF like \"/*predicate2*/""];
    const NSPredicate *site3Predicate = [NSPredicate predicateWithFormat:@"SELF like \"/*predicate3*/""];
    const NSPredicate *site4Predicate = [NSPredicate predicateWithFormat:@"SELF like \"/*predicate4*/""];
    const NSPredicate *site5Predicate = [NSPredicate predicateWithFormat:@"SELF like \"/*predicate5*/""];

    //predicate arrays
    const NSArray *songPredicates = [NSArray arrayWithObjects:site1Predicate, site2Predicate, site3Predicate, site4Predicate, site5Predicate, nil];

    //site is an int with its defined in an enum
    if ([[songPredicates objectAtIndex:site-1] evaluateWithObject:request.URL.host])
    {
        NSMutableURLRequest* newRequest = [request mutableCopy];
        [InterceptionProtocol setProperty:self forKey:@"MyApp" inRequest:newRequest];
        dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            /* Do stuff */
        });
        return newRequest;
    }
    return request;
}

In InterceptionProtocol.m

+ (BOOL) canInitWithRequest:(NSURLRequest*)request
{
    id delegate = [NSURLProtocol propertyForKey:@"MyApp" inRequest:request];
    if (delegate) NSLog(@"Can init: %@", request);
    return (delegate != nil);
}

For some reason this works perfectly for everything except site 4. I have stepped through the code and I know that the predicate is matching correctly. I do not know how this could work for the other sites but not this one. Any ideas?

Edit

Full source code can be found here: http://github.com/garrett-davidson/iLikeMusic

like image 928
Garrett Avatar asked Oct 21 '22 18:10

Garrett


2 Answers

Seems the issue is with predicate4 not matching site4. Your note on stepping through code and it matching correctly is confusing - if this were the case, everything would be working, won't it?

Could it be that instead you manually tested the url you expect against the predicate - but instead there is slight difference in what you get during real run (say due to URL encoding - there being spaces or / or ? which are + or % encoded). Put NSLog before evaluateWithObject: to see what exactly comes in request.URL.host?

like image 66
Nas Banov Avatar answered Oct 23 '22 09:10

Nas Banov


Then, we must register this protocol on you App Delegate’s -(

BOOL)application:didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [NSURLProtocol registerClass:[ChromeBrowserURLProtocol class]];
...

source:customizing-uiwebview-requests-with-nsurlprotocol

like image 34
codercat Avatar answered Oct 23 '22 09:10

codercat