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 |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..44a93d0ae41719a4ba5445f20f56811f4195cf85 |
| --- /dev/null |
| +++ b/util/net/http_transport_mac.mm |
| @@ -0,0 +1,161 @@ |
| +// Copyright 2014 The Crashpad Authors. All rights reserved. |
| +// |
| +// Licensed under the Apache License, Version 2.0 (the "License"); |
| +// you may not use this file except in compliance with the License. |
| +// You may obtain a copy of the License at |
| +// |
| +// http://www.apache.org/licenses/LICENSE-2.0 |
| +// |
| +// Unless required by applicable law or agreed to in writing, software |
| +// distributed under the License is distributed on an "AS IS" BASIS, |
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| +// See the License for the specific language governing permissions and |
| +// limitations under the License. |
| + |
| +#include "util/net/http_transport_mac.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 "util/net/http_body.h" |
| + |
| +@interface CrashpadHTTPBodyStreamTransport : NSInputStream { |
| + @private |
| + NSStreamStatus streamStatus_; |
| + id<NSStreamDelegate> delegate_; |
| + crashpad::HTTPBodyStream* bodyStream_; |
|
Mark Mentovai
2014/10/30 21:13:54
// weak
Robert Sesek
2014/10/31 14:48:14
Done.
|
| +} |
| +- (instancetype)initWithBodyStream:(crashpad::HTTPBodyStream*)bodyStream; |
| +@end |
| + |
| +@implementation CrashpadHTTPBodyStreamTransport |
| + |
| +- (instancetype)initWithBodyStream:(crashpad::HTTPBodyStream*)bodyStream { |
| + if ((self = [super init])) { |
| + streamStatus_ = NSStreamStatusNotOpen; |
| + bodyStream_ = bodyStream; |
| + } |
| + 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." |
| + return YES; |
|
Mark Mentovai
2014/10/30 21:13:54
I guess you could return NO if streamStatus_ is NS
Robert Sesek
2014/10/31 14:48:15
Done.
|
| +} |
| + |
| +- (NSInteger)read:(uint8_t*)buffer maxLength:(NSUInteger)maxLen { |
| + NSInteger rv = bodyStream_->GetBytesBuffer(buffer, maxLen); |
| + if (rv == 0) |
| + streamStatus_ = NSStreamStatusAtEnd; |
| + else if (rv < 0) |
| + streamStatus_ = NSStreamStatusError; |
| + else |
| + streamStatus_ = NSStreamStatusReading; |
|
Mark Mentovai
2014/10/30 21:13:54
The documentation for this status says that it’s s
Robert Sesek
2014/10/31 14:48:15
Done.
|
| + return rv; |
| +} |
| + |
| +- (BOOL)getBuffer:(uint8_t**)buffer length:(NSUInteger*)length { |
| + return NO; |
| +} |
| + |
| +// NSStream: |
| + |
| +- (void)scheduleInRunLoop:(NSRunLoop*)runLoop |
|
Mark Mentovai
2014/10/30 21:13:55
Can you add a comment about why this is unnecessar
Robert Sesek
2014/10/31 14:48:14
I would if I knew why it were necessary ;). I don'
|
| + forMode:(NSString*)mode { |
| +} |
| + |
| +- (void)removeFromRunLoop:(NSRunLoop*)runLoop |
| + forMode:(NSString*)mode { |
| +} |
| + |
| +- (void)open { |
| + streamStatus_ = NSStreamStatusOpen; |
| +} |
| + |
| +- (void)close { |
| + streamStatus_ = NSStreamStatusClosed; |
| +} |
| + |
| +- (NSStreamStatus)streamStatus { |
| + return streamStatus_; |
| +} |
| + |
| +- (id<NSStreamDelegate>)delegate { |
| + return delegate_; |
| +} |
| + |
| +- (void)setDelegate:(id)delegate { |
| + delegate_ = delegate; |
| +} |
| + |
| +@end |
| + |
| +namespace crashpad { |
| + |
| +HTTPTransportMac::HTTPTransportMac() : HTTPTransport() { |
| +} |
| + |
| +HTTPTransportMac::~HTTPTransportMac() { |
| +} |
| + |
| +bool HTTPTransportMac::ExecuteSynchronously() { |
| + DCHECK(body_stream()); |
| + |
| + @autoreleasepool { |
| + NSString* urlNSString = base::SysUTF8ToNSString(url()); |
|
Mark Mentovai
2014/10/30 21:13:54
You’re not in the @implementation anymore here: ur
Robert Sesek
2014/10/31 14:48:14
Done.
|
| + NSURL* url = [NSURL URLWithString:urlNSString]; |
| + NSMutableURLRequest* request = |
| + [NSMutableURLRequest requestWithURL:url |
| + cachePolicy:NSURLRequestUseProtocolCachePolicy |
| + timeoutInterval:15.0]; |
|
Mark Mentovai
2014/10/30 21:13:55
It’d be reasonable for this to be tunable at the H
Robert Sesek
2014/10/31 14:48:14
Done.
|
| + [request setHTTPMethod:base::SysUTF8ToNSString(method())]; |
| + |
| + for (const auto& pair : headers()) { |
| + [request setValue:base::SysUTF8ToNSString(pair.second) |
| + forHTTPHeaderField:base::SysUTF8ToNSString(pair.first)]; |
| + } |
| + |
| + base::scoped_nsobject<CrashpadHTTPBodyStreamTransport> transport( |
| + [[CrashpadHTTPBodyStreamTransport alloc] initWithBodyStream: |
| + body_stream()]); |
| + [request setHTTPBodyStream:transport.get()]; |
| + |
| + NSURLResponse* response = nil; |
| + NSError* error = nil; |
| + [NSURLConnection sendSynchronousRequest:request |
| + returningResponse:&response |
| + error:&error]; |
| + |
| + if (error) { |
| + LOG(ERROR) << [[error localizedDescription] UTF8String] << " (" |
| + << [[error domain] UTF8String] << " " << [error code] << ")"; |
| + return false; |
| + } |
| + if (!response) { |
| + LOG(ERROR) << "no response"; |
| + return false; |
| + } |
| + NSHTTPURLResponse* httpResponse = |
| + base::mac::ObjCCast<NSHTTPURLResponse>(response); |
| + if (!httpResponse) { |
| + LOG(ERROR) << "no httpResponse"; |
| + return false; |
| + } |
| + NSInteger httpStatus = [httpResponse statusCode]; |
| + if (httpStatus != 200) { |
| + LOG(ERROR) << base::StringPrintf("HTTP status %ld", |
| + static_cast<long>(httpStatus)); |
| + return false; |
| + } |
| + |
| + return true; |
| + } |
| +} |
| + |
| +} // namespace crashpad |