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

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: Documentation and refactors 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
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 @interface DeferredCancellation : NSObject {}
droger 2015/06/11 15:45:56 Remove {}
droger 2015/06/11 15:45:56 Add comments.
Elly Fong-Jones 2015/06/12 15:02:59 Done.
Elly Fong-Jones 2015/06/12 15:02:59 Done.
872
873 - (instancetype)initWithCore:(scoped_refptr<net::HttpProtocolHandlerCore>)core;
874 - (void)cancel;
875
876 @end
877
878 @implementation DeferredCancellation {
879 scoped_refptr<net::HttpProtocolHandlerCore> _core;
880 }
881
882 - (instancetype)initWithCore:(scoped_refptr<net::HttpProtocolHandlerCore>)core {
883 if ((self = [super init])) {
884 _core = core;
885 }
886 return self;
887 }
888
889 - (void)cancel {
890 g_protocol_handler_delegate->GetDefaultURLRequestContext()
891 ->GetNetworkTaskRunner()
892 ->PostTask(FROM_HERE,
893 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core));
894 }
895
896 @end
897
898 #pragma mark -
869 #pragma mark HttpProtocolHandler 899 #pragma mark HttpProtocolHandler
870 900
901 @interface CRNHTTPProtocolHandler (Private) {}
902
903 - (id<CRNHTTPProtocolHandlerProxy>)getProtocolHandlerProxy;
904 - (scoped_refptr<net::HttpProtocolHandlerCore>)getCore;
905 - (NSThread*)getClientThread;
906 - (void)cancelRequest;
907
908 @end
909
871 // The HttpProtocolHandler is called by the iOS system to handle the 910 // The HttpProtocolHandler is called by the iOS system to handle the
872 // NSURLRequest. 911 // NSURLRequest.
873 @implementation CRNHTTPProtocolHandler { 912 @implementation CRNHTTPProtocolHandler {
874 scoped_refptr<net::HttpProtocolHandlerCore> _core; 913 scoped_refptr<net::HttpProtocolHandlerCore> _core;
875 base::scoped_nsprotocol<id<CRNHTTPProtocolHandlerProxy>> _protocolProxy; 914 base::scoped_nsprotocol<id<CRNHTTPProtocolHandlerProxy>> _protocolProxy;
915 NSThread* _clientThread;
916 NSString* _clientRunLoopMode;
876 BOOL _supportedURL; 917 BOOL _supportedURL;
877 } 918 }
878 919
879 #pragma mark NSURLProtocol methods 920 #pragma mark NSURLProtocol methods
880 921
881 + (BOOL)canInitWithRequest:(NSURLRequest*)request { 922 + (BOOL)canInitWithRequest:(NSURLRequest*)request {
882 DVLOG(5) << "canInitWithRequest " << net::FormatUrlRequestForLogging(request); 923 DVLOG(5) << "canInitWithRequest " << net::FormatUrlRequestForLogging(request);
883 return g_protocol_handler_delegate->CanHandleRequest(request); 924 return g_protocol_handler_delegate->CanHandleRequest(request);
884 } 925 }
885 926
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 if (url) 964 if (url)
924 [dictionary setObject:url forKey:NSURLErrorKey]; 965 [dictionary setObject:url forKey:NSURLErrorKey];
925 966
926 NSError* error = [NSError errorWithDomain:NSURLErrorDomain 967 NSError* error = [NSError errorWithDomain:NSURLErrorDomain
927 code:NSURLErrorUnsupportedURL 968 code:NSURLErrorUnsupportedURL
928 userInfo:dictionary]; 969 userInfo:dictionary];
929 [[self client] URLProtocol:self didFailWithError:error]; 970 [[self client] URLProtocol:self didFailWithError:error];
930 return; 971 return;
931 } 972 }
932 973
933 _protocolProxy.reset([[CRNHTTPProtocolHandlerProxyWithClientThread alloc] 974 _clientThread = [NSThread currentThread];
934 initWithProtocol:self 975
935 clientThread:[NSThread currentThread]
936 runLoopMode:[[NSRunLoop currentRunLoop] currentMode]]);
937 g_protocol_handler_delegate->GetDefaultURLRequestContext() 976 g_protocol_handler_delegate->GetDefaultURLRequestContext()
938 ->GetNetworkTaskRunner() 977 ->GetNetworkTaskRunner()
939 ->PostTask(FROM_HERE, base::Bind(&net::HttpProtocolHandlerCore::Start, 978 ->PostTask(FROM_HERE, base::Bind(&net::HttpProtocolHandlerCore::Start,
940 _core, _protocolProxy)); 979 _core, [self getProtocolHandlerProxy]));
941 } 980 }
942 981
943 - (void)stopLoading { 982 - (id<CRNHTTPProtocolHandlerProxy>)getProtocolHandlerProxy {
983 DCHECK_EQ([NSThread currentThread], _clientThread);
984 if (!_protocolProxy.get()) {
985 _protocolProxy.reset([[CRNHTTPProtocolHandlerProxyWithClientThread alloc]
986 initWithProtocol:self
987 clientThread:_clientThread
988 runLoopMode:[[NSRunLoop currentRunLoop] currentMode]]);
989 }
990 return _protocolProxy.get();
991 }
992
993 - (scoped_refptr<net::HttpProtocolHandlerCore>)getCore {
994 return _core;
995 }
996
997 - (NSThread*)getClientThread {
998 return _clientThread;
999 }
1000
1001 - (void)cancelRequest {
944 g_protocol_handler_delegate->GetDefaultURLRequestContext() 1002 g_protocol_handler_delegate->GetDefaultURLRequestContext()
945 ->GetNetworkTaskRunner() 1003 ->GetNetworkTaskRunner()
946 ->PostTask(FROM_HERE, 1004 ->PostTask(FROM_HERE,
947 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core)); 1005 base::Bind(&net::HttpProtocolHandlerCore::Cancel, _core));
948 [_protocolProxy invalidate]; 1006 [_protocolProxy invalidate];
1007 }
1008
1009 - (void)stopLoading {
1010 [self cancelRequest];
949 _protocolProxy.reset(); 1011 _protocolProxy.reset();
950 } 1012 }
951 1013
952 @end 1014 @end
1015
1016 #pragma mark -
1017 #pragma mark PauseableHttpProtocolHandler
1018
1019 // The HttpProtocolHandler is called by the iOS system to handle the
1020 // NSURLRequest. This HttpProtocolHandler conforms to the observed semantics of
1021 // NSURLProtocol when used with NSURLSession on iOS 8 - i.e., |-startLoading|
1022 // means "start or resume request" and |-stopLoading| means "pause request".
1023 // Since there is no way to actually pause a request in the network stack, this
1024 // is implemented using a subclass of CRNHTTPProtocolHandlerProxy that knows how
1025 // to defer callbacks.
1026 //
1027 // Note that this class conforms to somewhat complex threading rules:
1028 // 1) |initWithRequest:cachedResponse:client:| and |dealloc| can be called on
1029 // any thread.
1030 // 2) |startLoading| and |stopLoading| are always called on the client thread.
1031 // 3) |stopLoading| is called before |dealloc| is called.
1032 //
1033 // The main wrinkle is that |dealloc|, which may be called on any thread, needs
1034 // to clean up a running network request. To do this, |dealloc| needs to run
1035 // |cancelRequest|, which needs to be run on the client thread. Since it is
1036 // guaranteed that |startLoading| is called before |dealloc| is called, the
1037 // |startLoading| method stores a pointer to the client thread, then |dealloc|
1038 // asks that client thread to perform the |cancelRequest| selector via
1039 // |scheduleCancelRequest|.
1040 //
1041 // Some of the above logic is implemented in the parent class
1042 // (CRNHTTPProtocolHandler) because it is convenient.
1043 @implementation CRNPauseableHTTPProtocolHandler {
1044 BOOL _started;
1045 dispatch_queue_t _queue;
1046 }
1047
1048 #pragma mark NSURLProtocol methods
1049
1050 - (void)dealloc {
1051 [self scheduleCancelRequest];
1052 [super dealloc];
1053 }
1054
1055 #pragma mark NSURLProtocol overrides.
1056
1057 - (void)startLoading {
1058 if (_started) {
1059 [[self getProtocolHandlerProxy] resume];
1060 return;
1061 }
1062
1063 _started = YES;
1064 [super startLoading];
1065 }
1066
1067 - (void)stopLoading {
1068 [[self getProtocolHandlerProxy] pause];
1069 }
1070
1071 // This method has unusual concurrency properties. It can be called on any
1072 // thread, but it must be called from |-dealloc|, which guarantees that no other
1073 // method of this object is running concurrently (since |-dealloc| is only
1074 // called when the last reference to the object drops).
1075 //
1076 // This method takes a reference to _core to ensure that _core lives long enough
1077 // to have the request cleanly cancelled.
1078 - (void)scheduleCancelRequest {
1079 DeferredCancellation* cancellation =
droger 2015/06/11 15:45:57 <rant> It seems overkill to create a class for tha
Elly Fong-Jones 2015/06/12 15:02:59 Yep.
1080 [[DeferredCancellation alloc] initWithCore:[self getCore]];
1081 NSArray* modes = @[ [[NSRunLoop currentRunLoop] currentMode] ];
1082 [cancellation performSelector:@selector(cancel)
1083 onThread:[self getClientThread]
1084 withObject:nil
1085 waitUntilDone:NO
1086 modes:modes];
1087 }
1088
1089 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698