代码之家  ›  专栏  ›  技术社区  ›  J. Perkins

拦截来自WebView Flash插件的Web请求

  •  2
  • J. Perkins  · 技术社区  · 16 年前

    我有一个桌面浏览器应用程序,它使用一个WebView来托管一个Flash插件。Flash插件定期向外部网站请求新数据,然后将其绘制成精美的图形。

    我想拦截这些Web请求并获取数据(这样我可以通过咆哮来显示它,而不是保留桌面窗口)。但我能说的是,Flash的请求不会被普通的WebView代理接受。

    还有别的地方可以挂钩吗?我尝试通过[nsurlcache setshareduralcache]安装自定义nsurlcache,但从未被调用。我还尝试了使用其他一些类(如nscachedurlResponse)的方法,但找不到方法。有什么想法吗?多谢!

    1 回复  |  直到 15 年前
        1
  •  3
  •   J. Perkins    15 年前

    令人惊讶的是,没有人回答这个问题,其实很容易。创建nsurlprotocol的子类,然后调用registerClass开始拦截。

    [NSURLProtocol registerClass:[MyCustomURLProtocol class]];
    

    下面是子类的重要部分:

    #define REQUEST_HEADER_TAG  @"x-mycustomurl-intercept"
    
    + (BOOL)canInitWithRequest:(NSURLRequest*)theRequest
    {
        // Check for the custom header on the request to break the 
        // infinite loop created by the [startLoading] below.
        if ([theRequest valueForHTTPHeaderField:REQUEST_HEADER_TAG]) {
            return NO;
        }
    
        if ([theRequest.URL.scheme caseInsensitiveCompare:@"http"] == NSOrderedSame) {
            return YES;
        }
        return NO;
    }
    
    + (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)theRequest
    {
        return theRequest;
    }
    
    - (id)initWithRequest:(NSURLRequest*)theRequest
           cachedResponse:(NSCachedURLResponse*)cachedResponse
                   client:(id<NSURLProtocolClient>)client
    {
        // Add a custom header on the request to break the 
        // infinite loop created by the [startLoading] below.
        NSMutableURLRequest* newRequest = [theRequest mutableCopy];
        [newRequest setValue:@"" forHTTPHeaderField:REQUEST_HEADER_TAG];
    
        // Now continue the process with this "tagged" request
        self = [super initWithRequest:theRequest 
                       cachedResponse:cachedResponse 
                               client:client];
        if (self) {
           // capture the data received 
           [self setRequest:newRequest];
           receivedData = [[NSMutableData data] retain];
        }
    
        [newRequest release];
        return self;
    }
    
    - (void)dealloc
    {
        [connection release];
        [request release];
        [receivedData release];
        [super dealloc];
    }
    
    
    - (void)startLoading
    {
        // Load the data off the web as usual, but set myself up as the delegate 
        // so I can intercept the response data as it comes in.
        [self setConnection:[NSURLConnection connectionWithRequest:request delegate:self]];
    }
    
    
    - (void)stopLoading 
    {
        [connection cancel];
    }
    
    #pragma mark NSURLConnection delegate implementation
    
    - (void)connection:(NSURLConnection*)conn 
                       didReceiveResponse:(NSURLResponse*)response 
    {
        [[self client] URLProtocol:self 
                didReceiveResponse:response 
                cacheStoragePolicy:[request cachePolicy]];
        [receivedData setLength:0];
    }
    
    
    - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
    {
        [[self client] URLProtocol:self didLoadData:data];
        [receivedData appendData:data];
    }
    
    
    - (void)connectionDidFinishLoading:(NSURLConnection*)conn
    {
        [[self client] URLProtocolDidFinishLoading:self];
        [self setConnection:nil];
        if (requestTag != 0) {
            if (requestDelegate && 
                [requestDelegate respondsToSelector:
                   @selector(finishedLoadingData:forURL:taggedWith:)]) {
                [requestDelegate finishedLoadingData:receivedData 
                                              forURL:[request URL] 
                                          taggedWith:requestTag];
            }
        }
    }
    
    
    - (void)connection:(NSURLConnection*)conn didFailWithError:(NSError*)error 
    {
        [[self client] URLProtocol:self didFailWithError:error];
        [self setConnection:nil];
    }