Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: ios/net/crn_http_protocol_handler.mm

Issue 1142383006: CrNet: add pauseable NSURLProtocol and switch to using it (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: main.m -> main.mm & format Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ios/net/crn_http_protocol_handler.h ('k') | ios/net/crn_http_protocol_handler_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/mac/bind_objc_block.h" 9 #include "base/mac/bind_objc_block.h"
10 #include "base/mac/scoped_nsobject.h" 10 #include "base/mac/scoped_nsobject.h"
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 _core = core; 859 _core = core;
860 return self; 860 return self;
861 } 861 }
862 862
863 - (void)stream:(NSStream*)theStream handleEvent:(NSStreamEvent)streamEvent { 863 - (void)stream:(NSStream*)theStream handleEvent:(NSStreamEvent)streamEvent {
864 _core->HandleStreamEvent(theStream, streamEvent); 864 _core->HandleStreamEvent(theStream, streamEvent);
865 } 865 }
866 @end 866 @end
867 867
868 #pragma mark - 868 #pragma mark -
869 #pragma mark DeferredCancellation
870
871 // An object of class |DeferredCancellation| represents a deferred cancellation
872 // of a request. In principle this is a block posted to a thread's runloop, but
873 // since there is no performBlock:onThread:, this class wraps the desired
874 // behavior in an object.
875 @interface DeferredCancellation : NSObject
876
877 - (instancetype)initWithCore:(scoped_refptr<net::HttpProtocolHandlerCore>)core;
878 - (void)cancel;
879
880 @end
881
882 @implementation DeferredCancellation {
883 scoped_refptr<net::HttpProtocolHandlerCore> _core;
884 }
885
886 - (instancetype)initWithCore:(scoped_refptr<net::HttpProtocolHandlerCore>)core {
887 if ((self = [super init])) {
888 _core = core;
889 }
890 return self;
891 }
892
893 - (void)cancel {
894 g_protocol_handler_delegate->GetDefaultURLRequestContext()
895 ->GetNetworkTaskRunner()
896 ->PostTask(FROM_HERE,
897 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core));
898 }
899
900 @end
901
902 #pragma mark -
869 #pragma mark HttpProtocolHandler 903 #pragma mark HttpProtocolHandler
870 904
905 @interface CRNHTTPProtocolHandler (Private)
906
907 - (id<CRNHTTPProtocolHandlerProxy>)getProtocolHandlerProxy;
908 - (scoped_refptr<net::HttpProtocolHandlerCore>)getCore;
909 - (NSThread*)getClientThread;
910 - (void)cancelRequest;
911
912 @end
913
871 // The HttpProtocolHandler is called by the iOS system to handle the 914 // The HttpProtocolHandler is called by the iOS system to handle the
872 // NSURLRequest. 915 // NSURLRequest.
873 @implementation CRNHTTPProtocolHandler { 916 @implementation CRNHTTPProtocolHandler {
874 scoped_refptr<net::HttpProtocolHandlerCore> _core; 917 scoped_refptr<net::HttpProtocolHandlerCore> _core;
875 base::scoped_nsprotocol<id<CRNHTTPProtocolHandlerProxy>> _protocolProxy; 918 base::scoped_nsprotocol<id<CRNHTTPProtocolHandlerProxy>> _protocolProxy;
919 NSThread* _clientThread;
920 NSString* _clientRunLoopMode;
876 BOOL _supportedURL; 921 BOOL _supportedURL;
877 } 922 }
878 923
879 #pragma mark NSURLProtocol methods 924 #pragma mark NSURLProtocol methods
880 925
881 + (BOOL)canInitWithRequest:(NSURLRequest*)request { 926 + (BOOL)canInitWithRequest:(NSURLRequest*)request {
882 DVLOG(5) << "canInitWithRequest " << net::FormatUrlRequestForLogging(request); 927 DVLOG(5) << "canInitWithRequest " << net::FormatUrlRequestForLogging(request);
883 return g_protocol_handler_delegate->CanHandleRequest(request); 928 return g_protocol_handler_delegate->CanHandleRequest(request);
884 } 929 }
885 930
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 if (url) 968 if (url)
924 [dictionary setObject:url forKey:NSURLErrorKey]; 969 [dictionary setObject:url forKey:NSURLErrorKey];
925 970
926 NSError* error = [NSError errorWithDomain:NSURLErrorDomain 971 NSError* error = [NSError errorWithDomain:NSURLErrorDomain
927 code:NSURLErrorUnsupportedURL 972 code:NSURLErrorUnsupportedURL
928 userInfo:dictionary]; 973 userInfo:dictionary];
929 [[self client] URLProtocol:self didFailWithError:error]; 974 [[self client] URLProtocol:self didFailWithError:error];
930 return; 975 return;
931 } 976 }
932 977
933 _protocolProxy.reset([[CRNHTTPProtocolHandlerProxyWithClientThread alloc] 978 _clientThread = [NSThread currentThread];
934 initWithProtocol:self 979
935 clientThread:[NSThread currentThread]
936 runLoopMode:[[NSRunLoop currentRunLoop] currentMode]]);
937 g_protocol_handler_delegate->GetDefaultURLRequestContext() 980 g_protocol_handler_delegate->GetDefaultURLRequestContext()
938 ->GetNetworkTaskRunner() 981 ->GetNetworkTaskRunner()
939 ->PostTask(FROM_HERE, base::Bind(&net::HttpProtocolHandlerCore::Start, 982 ->PostTask(FROM_HERE, base::Bind(&net::HttpProtocolHandlerCore::Start,
940 _core, _protocolProxy)); 983 _core, [self getProtocolHandlerProxy]));
941 } 984 }
942 985
943 - (void)stopLoading { 986 - (id<CRNHTTPProtocolHandlerProxy>)getProtocolHandlerProxy {
987 DCHECK_EQ([NSThread currentThread], _clientThread);
988 if (!_protocolProxy.get()) {
989 _protocolProxy.reset([[CRNHTTPProtocolHandlerProxyWithClientThread alloc]
990 initWithProtocol:self
991 clientThread:_clientThread
992 runLoopMode:[[NSRunLoop currentRunLoop] currentMode]]);
993 }
994 return _protocolProxy.get();
995 }
996
997 - (scoped_refptr<net::HttpProtocolHandlerCore>)getCore {
998 return _core;
999 }
1000
1001 - (NSThread*)getClientThread {
1002 return _clientThread;
1003 }
1004
1005 - (void)cancelRequest {
944 g_protocol_handler_delegate->GetDefaultURLRequestContext() 1006 g_protocol_handler_delegate->GetDefaultURLRequestContext()
945 ->GetNetworkTaskRunner() 1007 ->GetNetworkTaskRunner()
946 ->PostTask(FROM_HERE, 1008 ->PostTask(FROM_HERE,
947 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core)); 1009 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core));
948 [_protocolProxy invalidate]; 1010 [_protocolProxy invalidate];
1011 }
1012
1013 - (void)stopLoading {
1014 [self cancelRequest];
949 _protocolProxy.reset(); 1015 _protocolProxy.reset();
950 } 1016 }
951 1017
952 @end 1018 @end
1019
1020 #pragma mark -
1021 #pragma mark PauseableHttpProtocolHandler
1022
1023 // The HttpProtocolHandler is called by the iOS system to handle the
1024 // NSURLRequest. This HttpProtocolHandler conforms to the observed semantics of
1025 // NSURLProtocol when used with NSURLSession on iOS 8 - i.e., |-startLoading|
1026 // means "start or resume request" and |-stopLoading| means "pause request".
1027 // Since there is no way to actually pause a request in the network stack, this
1028 // is implemented using a subclass of CRNHTTPProtocolHandlerProxy that knows how
1029 // to defer callbacks.
1030 //
1031 // Note that this class conforms to somewhat complex threading rules:
1032 // 1) |initWithRequest:cachedResponse:client:| and |dealloc| can be called on
1033 // any thread.
1034 // 2) |startLoading| and |stopLoading| are always called on the client thread.
1035 // 3) |stopLoading| is called before |dealloc| is called.
1036 //
1037 // The main wrinkle is that |dealloc|, which may be called on any thread, needs
1038 // to clean up a running network request. To do this, |dealloc| needs to run
1039 // |cancelRequest|, which needs to be run on the client thread. Since it is
1040 // guaranteed that |startLoading| is called before |dealloc| is called, the
1041 // |startLoading| method stores a pointer to the client thread, then |dealloc|
1042 // asks that client thread to perform the |cancelRequest| selector via
1043 // |scheduleCancelRequest|.
1044 //
1045 // Some of the above logic is implemented in the parent class
1046 // (CRNHTTPProtocolHandler) because it is convenient.
1047 @implementation CRNPauseableHTTPProtocolHandler {
1048 BOOL _started;
1049 dispatch_queue_t _queue;
1050 }
1051
1052 #pragma mark NSURLProtocol methods
1053
1054 - (void)dealloc {
1055 [self scheduleCancelRequest];
1056 [super dealloc];
1057 }
1058
1059 #pragma mark NSURLProtocol overrides.
1060
1061 - (void)startLoading {
1062 if (_started) {
1063 [[self getProtocolHandlerProxy] resume];
1064 return;
1065 }
1066
1067 _started = YES;
1068 [super startLoading];
1069 }
1070
1071 - (void)stopLoading {
1072 [[self getProtocolHandlerProxy] pause];
1073 }
1074
1075 // This method has unusual concurrency properties. It can be called on any
1076 // thread, but it must be called from |-dealloc|, which guarantees that no other
1077 // method of this object is running concurrently (since |-dealloc| is only
1078 // called when the last reference to the object drops).
1079 //
1080 // This method takes a reference to _core to ensure that _core lives long enough
1081 // to have the request cleanly cancelled.
1082 - (void)scheduleCancelRequest {
1083 DeferredCancellation* cancellation =
1084 [[DeferredCancellation alloc] initWithCore:[self getCore]];
1085 NSArray* modes = @[ [[NSRunLoop currentRunLoop] currentMode] ];
1086 [cancellation performSelector:@selector(cancel)
1087 onThread:[self getClientThread]
1088 withObject:nil
1089 waitUntilDone:NO
1090 modes:modes];
1091 }
1092
1093 @end
OLDNEW
« no previous file with comments | « ios/net/crn_http_protocol_handler.h ('k') | ios/net/crn_http_protocol_handler_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698