Chromium Code Reviews| Index: util/net/http_transport_mac.mm |
| diff --git a/util/net/http_transport_mac.mm b/util/net/http_transport_mac.mm |
| index 135fd280d2eb111cc03fece50b2e2f1619c344d9..c8bf9831235ed4215b20004587ae40b7f767cb22 100644 |
| --- a/util/net/http_transport_mac.mm |
| +++ b/util/net/http_transport_mac.mm |
| @@ -14,6 +14,7 @@ |
| #include "util/net/http_transport.h" |
| +#include <CoreFoundation/CoreFoundation.h> |
| #import <Foundation/Foundation.h> |
| #include "base/mac/foundation_util.h" |
| @@ -21,95 +22,117 @@ |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "util/net/http_body.h" |
| +#include "third_party/apple_cf/CFStreamAbstract.h" |
|
Mark Mentovai
2015/03/11 20:47:42
third_party < util
Robert Sesek
2015/03/11 20:53:57
Done.
|
| -@interface CrashpadHTTPBodyStreamTransport : NSInputStream { |
| - @private |
| - NSStreamStatus streamStatus_; |
| - id<NSStreamDelegate> delegate_; |
| - crashpad::HTTPBodyStream* bodyStream_; // weak |
| -} |
| -- (instancetype)initWithBodyStream:(crashpad::HTTPBodyStream*)bodyStream; |
| -@end |
| +namespace crashpad { |
| -@implementation CrashpadHTTPBodyStreamTransport |
| +namespace { |
| -- (instancetype)initWithBodyStream:(crashpad::HTTPBodyStream*)bodyStream { |
| - if ((self = [super init])) { |
| - streamStatus_ = NSStreamStatusNotOpen; |
| - bodyStream_ = bodyStream; |
| +// An implementation of CFReadStream. This implements the V0 callback |
| +// scheme. |
| +class HTTPBodyStreamCFReadStream { |
| + public: |
| + explicit HTTPBodyStreamCFReadStream(HTTPBodyStream* body_stream) |
| + : body_stream_(body_stream) { |
| } |
| - return self; |
| -} |
| -// NSInputStream: |
| - |
| -- (BOOL)hasBytesAvailable { |
| - // Per Apple's documentation: "May also return YES if a read must be attempted |
| - // in order to determine the availability of bytes." |
| - switch (streamStatus_) { |
| - case NSStreamStatusAtEnd: |
| - case NSStreamStatusClosed: |
| - case NSStreamStatusError: |
| - return NO; |
| - default: |
| - return YES; |
| + // Creates a new NSInputStream, which the caller owns. |
| + NSInputStream* CreateInputStream() { |
| + CFStreamClientContext context = { |
|
Mark Mentovai
2015/03/11 20:47:42
Can these both be const?
Robert Sesek
2015/03/11 20:53:56
No, only the callbacks.
|
| + .version = 0, |
| + .info = this, |
| + .retain = nullptr, |
| + .release = nullptr, |
| + .copyDescription = nullptr |
| + }; |
| + CFReadStreamCallBacksV0 callbacks = { |
| + .version = 0, |
| + .open = &Open, |
| + .openCompleted = &OpenCompleted, |
| + .read = &Read, |
| + .getBuffer = &GetBuffer, |
| + .canRead = &CanRead, |
| + .close = &Close, |
| + .copyProperty = &CopyProperty, |
| + .schedule = &Schedule, |
| + .unschedule = &Unschedule |
| + }; |
| + CFReadStreamRef read_stream = CFReadStreamCreate(NULL, |
|
Mark Mentovai
2015/03/11 20:47:42
nullptr
Robert Sesek
2015/03/11 20:53:57
Done. Force of habit with CF.
|
| + reinterpret_cast<const CFReadStreamCallBacks*>(&callbacks), &context); |
| + return base::mac::CFToNSCast(read_stream); |
| } |
| -} |
| - |
| -- (NSInteger)read:(uint8_t*)buffer maxLength:(NSUInteger)maxLen { |
| - streamStatus_ = NSStreamStatusReading; |
| - |
| - NSInteger rv = bodyStream_->GetBytesBuffer(buffer, maxLen); |
| - if (rv == 0) |
| - streamStatus_ = NSStreamStatusAtEnd; |
| - else if (rv < 0) |
| - streamStatus_ = NSStreamStatusError; |
| - else |
| - streamStatus_ = NSStreamStatusOpen; |
| - |
| - return rv; |
| -} |
| + private: |
| + static HTTPBodyStream* GetStream(void* info) { |
| + return static_cast<HTTPBodyStreamCFReadStream*>(info)->body_stream_; |
| + } |
| -- (BOOL)getBuffer:(uint8_t**)buffer length:(NSUInteger*)length { |
| - return NO; |
| -} |
| + static Boolean Open(CFReadStreamRef stream, |
| + CFStreamError* error, |
| + Boolean* open_complete, |
| + void* info) { |
| + *open_complete = TRUE; |
| + return TRUE; |
| + } |
| -// NSStream: |
| + static Boolean OpenCompleted(CFReadStreamRef stream, |
| + CFStreamError* error, |
| + void* info) { |
| + return TRUE; |
| + } |
| -- (void)scheduleInRunLoop:(NSRunLoop*)runLoop |
| - forMode:(NSString*)mode { |
| -} |
| + static CFIndex Read(CFReadStreamRef stream, |
| + UInt8* buffer, |
| + CFIndex buffer_length, |
| + CFStreamError* error, |
| + Boolean* at_eof, |
| + void* info) { |
| + ssize_t bytes_read = GetStream(info)->GetBytesBuffer(buffer, buffer_length); |
|
Mark Mentovai
2015/03/11 20:47:42
Paranoia: if buffer_length == 0, just return 0.
Robert Sesek
2015/03/11 20:53:57
Done.
|
| + if (bytes_read == 0) { |
| + *at_eof = TRUE; |
| + } else if (bytes_read < 0) { |
| + error->error = -1; |
| + error->domain = kCFStreamErrorDomainCustom; |
| + } |
| -- (void)removeFromRunLoop:(NSRunLoop*)runLoop |
| - forMode:(NSString*)mode { |
| -} |
| + return bytes_read; |
| + } |
| -- (void)open { |
| - streamStatus_ = NSStreamStatusOpen; |
| -} |
| + static const UInt8* GetBuffer(CFReadStreamRef stream, |
| + CFIndex max_bytes_to_read, |
| + CFIndex* num_bytes_read, |
| + CFStreamError* error, |
| + Boolean* at_eof, |
| + void* info) { |
| + return nullptr; |
| + } |
| -- (void)close { |
| - streamStatus_ = NSStreamStatusClosed; |
| -} |
| + static Boolean CanRead(CFReadStreamRef stream, void* info) { |
| + return TRUE; |
| + } |
| -- (NSStreamStatus)streamStatus { |
| - return streamStatus_; |
| -} |
| + static void Close(CFReadStreamRef stream, void* info) {} |
| -- (id<NSStreamDelegate>)delegate { |
| - return delegate_; |
| -} |
| + static CFTypeRef CopyProperty(CFReadStreamRef stream, |
| + CFStringRef property_name, |
| + void* info) { |
| + return nullptr; |
| + } |
| -- (void)setDelegate:(id)delegate { |
| - delegate_ = delegate; |
| -} |
| + static void Schedule(CFReadStreamRef stream, |
| + CFRunLoopRef run_loop, |
| + CFStringRef run_loop_mode, |
| + void* info) {} |
| -@end |
| + static void Unschedule(CFReadStreamRef stream, |
| + CFRunLoopRef run_loop, |
| + CFStringRef run_loop_mode, |
| + void* info) {} |
| -namespace crashpad { |
| + HTTPBodyStream* body_stream_; // weak |
| -namespace { |
| + DISALLOW_COPY_AND_ASSIGN(HTTPBodyStreamCFReadStream); |
| +}; |
| class HTTPTransportMac final : public HTTPTransport { |
| public: |
| @@ -145,10 +168,10 @@ bool HTTPTransportMac::ExecuteSynchronously(std::string* response_body) { |
| forHTTPHeaderField:base::SysUTF8ToNSString(pair.first)]; |
| } |
| - base::scoped_nsobject<CrashpadHTTPBodyStreamTransport> transport( |
| - [[CrashpadHTTPBodyStreamTransport alloc] initWithBodyStream: |
| - body_stream()]); |
| - [request setHTTPBodyStream:transport.get()]; |
| + HTTPBodyStreamCFReadStream body_stream_cf(body_stream()); |
| + base::scoped_nsobject<NSInputStream> input_stream( |
| + body_stream_cf.CreateInputStream()); |
| + [request setHTTPBodyStream:input_stream.get()]; |
| NSURLResponse* response = nil; |
| NSError* error = nil; |