| 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..9688d18cbabb2bf83ee32359ae4b8f6d1eacdb4c 100644
|
| --- a/util/net/http_transport_mac.mm
|
| +++ b/util/net/http_transport_mac.mm
|
| @@ -14,102 +14,128 @@
|
|
|
| #include "util/net/http_transport.h"
|
|
|
| +#include <CoreFoundation/CoreFoundation.h>
|
| #import <Foundation/Foundation.h>
|
|
|
| #include "base/mac/foundation_util.h"
|
| #import "base/mac/scoped_nsobject.h"
|
| #include "base/strings/stringprintf.h"
|
| #include "base/strings/sys_string_conversions.h"
|
| +#include "third_party/apple_cf/CFStreamAbstract.h"
|
| #include "util/net/http_body.h"
|
|
|
| -@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 = {
|
| + .version = 0,
|
| + .info = this,
|
| + .retain = nullptr,
|
| + .release = nullptr,
|
| + .copyDescription = nullptr
|
| + };
|
| + const 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(nullptr,
|
| + 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) {
|
| + if (buffer_length == 0)
|
| + return 0;
|
| +
|
| + ssize_t bytes_read = GetStream(info)->GetBytesBuffer(buffer, buffer_length);
|
| + 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 +171,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;
|
|
|