| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ios/net/crn_http_protocol_handler.h" | 5 #import "ios/net/crn_http_protocol_handler.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core)); | 958 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core)); |
| 959 [_protocolProxy invalidate]; | 959 [_protocolProxy invalidate]; |
| 960 } | 960 } |
| 961 | 961 |
| 962 - (void)stopLoading { | 962 - (void)stopLoading { |
| 963 [self cancelRequest]; | 963 [self cancelRequest]; |
| 964 _protocolProxy.reset(); | 964 _protocolProxy.reset(); |
| 965 } | 965 } |
| 966 | 966 |
| 967 @end | 967 @end |
| 968 | |
| 969 #pragma mark - | |
| 970 #pragma mark PauseableHttpProtocolHandler | |
| 971 | |
| 972 // The HttpProtocolHandler is called by the iOS system to handle the | |
| 973 // NSURLRequest. This HttpProtocolHandler conforms to the observed semantics of | |
| 974 // NSURLProtocol when used with NSURLSession on iOS 8 - i.e., |-startLoading| | |
| 975 // means "start or resume request" and |-stopLoading| means "pause request". | |
| 976 // Since there is no way to actually pause a request in the network stack, this | |
| 977 // is implemented using a subclass of CRNHTTPProtocolHandlerProxy that knows how | |
| 978 // to defer callbacks. | |
| 979 // | |
| 980 // Note that this class conforms to somewhat complex threading rules: | |
| 981 // 1) |initWithRequest:cachedResponse:client:| and |dealloc| can be called on | |
| 982 // any thread. | |
| 983 // 2) |startLoading| and |stopLoading| are always called on the client thread. | |
| 984 // 3) |stopLoading| is called before |dealloc| is called. | |
| 985 // | |
| 986 // The main wrinkle is that |dealloc|, which may be called on any thread, needs | |
| 987 // to clean up a running network request. To do this, |dealloc| needs to run | |
| 988 // |cancelRequest|, which needs to be run on the client thread. Since it is | |
| 989 // guaranteed that |startLoading| is called before |dealloc| is called, the | |
| 990 // |startLoading| method stores a pointer to the client thread, then |dealloc| | |
| 991 // asks that client thread to perform the |cancelRequest| selector via | |
| 992 // |scheduleCancelRequest|. | |
| 993 // | |
| 994 // Some of the above logic is implemented in the parent class | |
| 995 // (CRNHTTPProtocolHandler) because it is convenient. | |
| 996 @implementation CRNPauseableHTTPProtocolHandler { | |
| 997 BOOL _started; | |
| 998 dispatch_queue_t _queue; | |
| 999 } | |
| 1000 | |
| 1001 #pragma mark NSURLProtocol methods | |
| 1002 | |
| 1003 - (void)dealloc { | |
| 1004 [self scheduleCancelRequest]; | |
| 1005 } | |
| 1006 | |
| 1007 #pragma mark NSURLProtocol overrides. | |
| 1008 | |
| 1009 - (void)startLoading { | |
| 1010 if (_started) { | |
| 1011 [[self getProtocolHandlerProxy] resume]; | |
| 1012 return; | |
| 1013 } | |
| 1014 | |
| 1015 _started = YES; | |
| 1016 [super startLoading]; | |
| 1017 } | |
| 1018 | |
| 1019 - (void)stopLoading { | |
| 1020 [[self getProtocolHandlerProxy] pause]; | |
| 1021 } | |
| 1022 | |
| 1023 // This method has unusual concurrency properties. It can be called on any | |
| 1024 // thread, but it must be called from |-dealloc|, which guarantees that no other | |
| 1025 // method of this object is running concurrently (since |-dealloc| is only | |
| 1026 // called when the last reference to the object drops). | |
| 1027 // | |
| 1028 // This method takes a reference to _core to ensure that _core lives long enough | |
| 1029 // to have the request cleanly cancelled. | |
| 1030 - (void)scheduleCancelRequest { | |
| 1031 DeferredCancellation* cancellation = | |
| 1032 [[DeferredCancellation alloc] initWithCore:[self getCore]]; | |
| 1033 NSArray* modes = @[ [[NSRunLoop currentRunLoop] currentMode] ]; | |
| 1034 [cancellation performSelector:@selector(cancel) | |
| 1035 onThread:[self getClientThread] | |
| 1036 withObject:nil | |
| 1037 waitUntilDone:NO | |
| 1038 modes:modes]; | |
| 1039 } | |
| 1040 | |
| 1041 @end | |
| OLD | NEW |