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

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

Powered by Google App Engine
This is Rietveld 408576698