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

Side by Side Diff: ios/net/crn_http_protocol_handler_proxy_with_client_thread.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: Fold PauseableProxy into Proxy 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_proxy_with_client_thread.h" 5 #import "ios/net/crn_http_protocol_handler_proxy_with_client_thread.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #import "base/mac/scoped_nsobject.h" 8 #import "base/mac/scoped_nsobject.h"
9 #include "base/time/time.h" 9 #include "base/time/time.h"
10 #import "ios/net/protocol_handler_util.h" 10 #import "ios/net/protocol_handler_util.h"
(...skipping 18 matching lines...) Expand all
29 __weak NSThread* _clientThread; 29 __weak NSThread* _clientThread;
30 // The run loop modes to use when posting tasks to |clientThread_|. 30 // The run loop modes to use when posting tasks to |clientThread_|.
31 base::scoped_nsobject<NSArray> _runLoopModes; 31 base::scoped_nsobject<NSArray> _runLoopModes;
32 // The request URL. 32 // The request URL.
33 base::scoped_nsobject<NSString> _url; 33 base::scoped_nsobject<NSString> _url;
34 // The creation time of the request. 34 // The creation time of the request.
35 base::Time _creationTime; 35 base::Time _creationTime;
36 // |requestComplete_| is used in debug to check that the client is not called 36 // |requestComplete_| is used in debug to check that the client is not called
37 // after completion. 37 // after completion.
38 BOOL _requestComplete; 38 BOOL _requestComplete;
39 BOOL _paused;
40
41 base::scoped_nsobject<NSMutableArray> _queuedInvocations;
39 } 42 }
40 43
41 // Performs the selector on |clientThread_| using |runLoopModes_|. 44 // Performs the selector on |clientThread_| using |runLoopModes_|.
45 - (void)runInvocationQueueOnClientThread;
46 - (void)enqueueInvocationOnClientThread:(NSInvocation*)invocation;
42 - (void)performSelectorOnClientThread:(SEL)aSelector withObject:(id)arg; 47 - (void)performSelectorOnClientThread:(SEL)aSelector withObject:(id)arg;
43 // These functions are just wrappers around the corresponding 48 // These functions are just wrappers around the corresponding
44 // NSURLProtocolClient methods, used for task posting. 49 // NSURLProtocolClient methods, used for task posting.
45 - (void)didFailWithErrorOnClientThread:(NSError*)error; 50 - (void)didFailWithErrorOnClientThread:(NSError*)error;
46 - (void)didLoadDataOnClientThread:(NSData*)data; 51 - (void)didLoadDataOnClientThread:(NSData*)data;
47 - (void)didReceiveResponseOnClientThread:(NSURLResponse*)response; 52 - (void)didReceiveResponseOnClientThread:(NSURLResponse*)response;
48 - (void)wasRedirectedToRequestOnClientThread:(NSArray*)params; 53 - (void)wasRedirectedToRequestOnClientThread:(NSArray*)params;
49 - (void)didFinishLoadingOnClientThread; 54 - (void)didFinishLoadingOnClientThread;
50 @end 55 @end
51 56
52 @implementation CRNHTTPProtocolHandlerProxyWithClientThread 57 @implementation CRNHTTPProtocolHandlerProxyWithClientThread
53 58
54 - (instancetype)initWithProtocol:(NSURLProtocol*)protocol 59 - (instancetype)initWithProtocol:(NSURLProtocol*)protocol
55 clientThread:(NSThread*)clientThread 60 clientThread:(NSThread*)clientThread
56 runLoopMode:(NSString*)mode { 61 runLoopMode:(NSString*)mode {
57 DCHECK(protocol); 62 DCHECK(protocol);
58 DCHECK(clientThread); 63 DCHECK(clientThread);
59 if ((self = [super init])) { 64 if ((self = [super init])) {
60 _protocol = protocol; 65 _protocol = protocol;
61 _url.reset([[[[protocol request] URL] absoluteString] copy]); 66 _url.reset([[[[protocol request] URL] absoluteString] copy]);
62 _creationTime = base::Time::Now(); 67 _creationTime = base::Time::Now();
63 _clientThread = clientThread; 68 _clientThread = clientThread;
64 // Use the common run loop mode in addition to the client thread mode, in 69 // Use the common run loop mode in addition to the client thread mode, in
65 // hope that our tasks are executed even if the client thread changes mode 70 // hope that our tasks are executed even if the client thread changes mode
66 // later on. 71 // later on.
67 if ([mode isEqualToString:NSRunLoopCommonModes]) 72 if ([mode isEqualToString:NSRunLoopCommonModes])
68 _runLoopModes.reset([@[ NSRunLoopCommonModes ] retain]); 73 _runLoopModes.reset([@[ NSRunLoopCommonModes ] retain]);
69 else 74 else
70 _runLoopModes.reset([@[ mode, NSRunLoopCommonModes ] retain]); 75 _runLoopModes.reset([@[ mode, NSRunLoopCommonModes ] retain]);
76 _paused = NO;
droger 2015/05/27 17:09:00 Nit: in objective-C, instance variables are auto-z
Elly Fong-Jones 2015/06/10 17:06:35 Done.
77 _queuedInvocations.reset([[NSMutableArray alloc] init]);
71 } 78 }
72 return self; 79 return self;
73 } 80 }
74 81
75 - (void)invalidate { 82 - (void)invalidate {
76 DCHECK([NSThread currentThread] == _clientThread); 83 DCHECK([NSThread currentThread] == _clientThread);
77 _protocol = nil; 84 _protocol = nil;
78 _requestComplete = YES; 85 _requestComplete = YES;
86 // TODO(ellyjones): This DCHECK fails sometimes. What this implies is that a
87 // callback is coming from the chrome network stack, being enqueued, and then
88 // this proxy is being invalidated before that callback has ever been
89 // delivered. Disturbingly, in practice these seem to be didLoadData and
90 // similar...
91 // DCHECK(_queuedInvocations.get().count == 0);
droger 2015/05/27 17:09:01 This might be caused by the problem with |_paused|
Elly Fong-Jones 2015/06/10 17:06:35 Done.
92 }
93
94 - (void)enqueueInvocationOnClientThread:(NSInvocation*)inv {
95 DCHECK([NSThread currentThread] == _clientThread);
96 DCHECK(!_requestComplete || !_protocol);
97 [_queuedInvocations addObject:inv];
98 // This function receives these two references from
99 // |performSelectorOnClientThread:| below.
100 [inv release];
101 [self release];
102 }
103
104 - (void)runInvocationQueueOnClientThread {
105 DCHECK([NSThread currentThread] == _clientThread);
106 DCHECK(!_requestComplete || !_protocol);
107 while (!_paused && _queuedInvocations.get().count > 0) {
108 NSInvocation* inv = [_queuedInvocations objectAtIndex:0];
109 // Since |_queuedInvocations| owns the only reference to each queued
110 // invocation, this function has to retain another reference before removing
111 // the queued invocation from the array.
112 [inv retain];
113 [_queuedInvocations removeObjectAtIndex:0];
114 [inv invoke];
115 [inv release];
116 }
79 } 117 }
80 118
81 - (void)performSelectorOnClientThread:(SEL)aSelector withObject:(id)arg { 119 - (void)performSelectorOnClientThread:(SEL)aSelector withObject:(id)arg {
82 [self performSelector:aSelector 120 if (!_paused) {
droger 2015/05/27 17:09:00 I don't think it is safe to access _paused here.
Elly Fong-Jones 2015/06/10 17:06:35 Done.
83 onThread:_clientThread 121 [self performSelector:aSelector
84 withObject:arg 122 onThread:_clientThread
85 waitUntilDone:NO 123 withObject:arg
86 modes:_runLoopModes]; 124 waitUntilDone:NO
125 modes:_runLoopModes];
126 } else {
127 // The memory management for this case is tricky. The |inv| NSInvocation
128 // object created here is autoreleased, so it would be destroyed by the
129 // autorelease pool if this function did not retain another reference to it.
130 // That reference is given to |enqueueInvocationOnClientThread:| via
131 // |performSelector:|, and |enqueueInvocationOnClientThread:| is responsible
132 // for releasing it.
133 //
134 // This function also needs an extra reference to |self|. Otherwise, this
135 // object can be destroyed by the time the |enqueueInvocationOnClientThread|
136 // function runs, with disastrous results. |enqueueInvocationOnClientThread|
137 // is responsible for releasing this extra reference as well; it receives
138 // ownership of it through |performSelector|.
139 NSMethodSignature* sig = [self methodSignatureForSelector:aSelector];
140 DCHECK(sig != nil);
141 NSInvocation* inv = [NSInvocation invocationWithMethodSignature:sig];
142 [inv setTarget:self];
143 if (sig.numberOfArguments > 2) {
144 [inv setArgument:&arg atIndex:2];
145 }
146 [inv setSelector:aSelector];
147 [inv retainArguments];
148 [inv retain];
149
150 [self retain];
151 [self performSelector:@selector(enqueueInvocationOnClientThread:)
152 onThread:_clientThread
153 withObject:inv
154 waitUntilDone:NO
155 modes:_runLoopModes];
156 }
87 } 157 }
88 158
89 #pragma mark Proxy methods called from any thread. 159 #pragma mark Proxy methods called from any thread.
90 160
91 - (void)didFailWithNSErrorCode:(NSInteger)nsErrorCode 161 - (void)didFailWithNSErrorCode:(NSInteger)nsErrorCode
92 netErrorCode:(int)netErrorCode { 162 netErrorCode:(int)netErrorCode {
93 DCHECK(_clientThread); 163 DCHECK(_clientThread);
94 if (!_protocol) 164 if (!_protocol)
95 return; 165 return;
96 NSError* error = 166 NSError* error =
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 redirectResponse:params[1]]; 261 redirectResponse:params[1]];
192 } 262 }
193 263
194 - (void)didFinishLoadingOnClientThread { 264 - (void)didFinishLoadingOnClientThread {
195 DCHECK([NSThread currentThread] == _clientThread); 265 DCHECK([NSThread currentThread] == _clientThread);
196 DCHECK(!_requestComplete || !_protocol); 266 DCHECK(!_requestComplete || !_protocol);
197 _requestComplete = YES; 267 _requestComplete = YES;
198 [[_protocol client] URLProtocolDidFinishLoading:_protocol]; 268 [[_protocol client] URLProtocolDidFinishLoading:_protocol];
199 } 269 }
200 270
271 - (void)pause {
272 _paused = YES;
droger 2015/05/27 17:09:01 We probably need thread checks here DCHECK([NSThre
Elly Fong-Jones 2015/06/10 17:06:35 Done.
273 }
274
275 - (void)resume {
276 _paused = NO;
droger 2015/05/27 17:09:01 Thread checks.
Elly Fong-Jones 2015/06/10 17:06:35 Done.
277 [self runInvocationQueueOnClientThread];
278 }
279
201 @end 280 @end
OLDNEW
« ios/net/crn_http_protocol_handler.mm ('K') | « ios/net/crn_http_protocol_handler_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698