提交 48571735 编写于 作者: C Chinmay Garde

Basic network service implementation for iOS

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/1165283002.
上级 1f0c506d
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("ns_net") {
sources = [
"network_service_impl.h",
"network_service_impl.mm",
"url_loader_impl.h",
"url_loader_impl.mm",
]
deps = [
"//base:base",
"//mojo/common",
"//mojo/public/cpp/application",
"//mojo/services/network/public/interfaces",
]
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/services/network/public/interfaces/network_service.mojom.h"
namespace mojo {
class NetworkServiceImpl : public NetworkService {
public:
explicit NetworkServiceImpl(InterfaceRequest<NetworkService> request)
: binding_(this, request.Pass()) {}
void CreateURLLoader(InterfaceRequest<URLLoader> loader) override;
void GetCookieStore(InterfaceRequest<CookieStore> cookie_store) override;
void CreateWebSocket(InterfaceRequest<WebSocket> socket) override;
void CreateTCPBoundSocket(
NetAddressPtr local_address,
InterfaceRequest<TCPBoundSocket> bound_socket,
const CreateTCPBoundSocketCallback& callback) override;
void CreateTCPConnectedSocket(
NetAddressPtr remote_address,
ScopedDataPipeConsumerHandle send_stream,
ScopedDataPipeProducerHandle receive_stream,
InterfaceRequest<TCPConnectedSocket> client_socket,
const CreateTCPConnectedSocketCallback& callback) override;
void CreateUDPSocket(InterfaceRequest<UDPSocket> socket) override;
void CreateHttpServer(NetAddressPtr local_address,
HttpServerDelegatePtr delegate,
const CreateHttpServerCallback& callback) override;
void RegisterURLLoaderInterceptor(
URLLoaderInterceptorFactoryPtr factory) override;
private:
StrongBinding<NetworkService> binding_;
};
class NetworkServiceFactory : public InterfaceFactory<NetworkService> {
public:
void Create(ApplicationConnection* connection,
InterfaceRequest<NetworkService> request) override;
};
} // namespace mojo
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "network_service_impl.h"
#include "url_loader_impl.h"
#include "base/logging.h"
#include <Foundation/Foundation.h>
namespace mojo {
void NetworkServiceImpl::CreateURLLoader(
InterfaceRequest<URLLoader> loader) {
new URLLoaderImpl(loader.Pass());
}
void NetworkServiceImpl::GetCookieStore(
InterfaceRequest<CookieStore> cookie_store) {
DCHECK(false);
}
void NetworkServiceImpl::CreateWebSocket(
InterfaceRequest<WebSocket> socket) {
DCHECK(false);
}
void NetworkServiceImpl::CreateTCPBoundSocket(
NetAddressPtr local_address,
InterfaceRequest<TCPBoundSocket> bound_socket,
const CreateTCPBoundSocketCallback& callback) {
DCHECK(false);
}
void NetworkServiceImpl::CreateTCPConnectedSocket(
NetAddressPtr remote_address,
ScopedDataPipeConsumerHandle send_stream,
ScopedDataPipeProducerHandle receive_stream,
InterfaceRequest<TCPConnectedSocket> client_socket,
const CreateTCPConnectedSocketCallback& callback) {
DCHECK(false);
}
void NetworkServiceImpl::CreateUDPSocket(
InterfaceRequest<UDPSocket> socket) {
DCHECK(false);
}
void NetworkServiceImpl::CreateHttpServer(
NetAddressPtr local_address,
HttpServerDelegatePtr delegate,
const CreateHttpServerCallback& callback) {
DCHECK(false);
}
void NetworkServiceImpl::RegisterURLLoaderInterceptor(
URLLoaderInterceptorFactoryPtr factory) {
DCHECK(false);
}
void NetworkServiceFactory::Create(ApplicationConnection* connection,
InterfaceRequest<NetworkService> request) {
new NetworkServiceImpl(request.Pass());
}
} // namespace mojo
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/services/network/public/interfaces/url_loader.mojom.h"
namespace mojo {
class URLLoaderImpl : public URLLoader {
public:
explicit URLLoaderImpl(InterfaceRequest<URLLoader> request);
~URLLoaderImpl();
void Start(URLRequestPtr request, const StartCallback& callback) override;
void FollowRedirect(const FollowRedirectCallback& callback) override;
void QueryStatus(const QueryStatusCallback& callback) override;
private:
StrongBinding<URLLoader> binding_;
void* connection_delegate_;
void* pending_connection_;
};
} // namespace mojo
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "url_loader_impl.h"
#include "base/logging.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#import <Foundation/Foundation.h>
@interface URLLoaderConnectionDelegate : NSObject<NSURLConnectionDataDelegate>
@property(nonatomic) mojo::URLLoaderImpl::StartCallback startCallback;
@end
@implementation URLLoaderConnectionDelegate {
mojo::URLResponsePtr _response;
mojo::ScopedDataPipeProducerHandle _producer;
}
@synthesize startCallback = _startCallback;
- (void)connection:(NSURLConnection*)connection
didReceiveResponse:(NSHTTPURLResponse*)response {
_response = mojo::URLResponse::New();
_response->status_code = response.statusCode;
_response->url =
mojo::String(connection.originalRequest.URL.absoluteString.UTF8String);
mojo::DataPipe pipe;
_response->body = pipe.consumer_handle.Pass();
_producer = pipe.producer_handle.Pass();
[self.class updateDelegate:self asPending:YES];
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data {
if (!_startCallback.is_null()) {
DCHECK(_response);
_startCallback.Run(_response.Pass());
_startCallback.reset();
_response.reset();
}
uint32_t length = data.length;
MojoResult result = WriteDataRaw(_producer.get(), data.bytes, &length,
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
// FIXME(csg): Handle buffers in case of failures
DCHECK(result == MOJO_RESULT_OK);
DCHECK(length == data.length);
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection {
DCHECK(_response.is_null());
DCHECK(_startCallback.is_null());
_producer.reset();
[self.class updateDelegate:self asPending:NO];
}
- (void)connection:(NSURLConnection*)connection
didFailWithError:(NSError*)error {
if (!_startCallback.is_null()) {
if (_response.is_null()) {
_response = mojo::URLResponse::New();
_response->url = mojo::String(
connection.originalRequest.URL.absoluteString.UTF8String);
}
_response->error = mojo::NetworkError::New();
_response->error->description =
mojo::String(error.localizedDescription.UTF8String);
_startCallback.Run(_response.Pass());
_startCallback.reset();
}
_response.reset();
_producer.reset();
[self.class updateDelegate:self asPending:NO];
}
// Since the only reference to the producer end of a data pipe is held by the
// delegate, which itself has no strong reference, we put the in-flight requests
// in a collection that references these delegates while they are active.
+ (void)updateDelegate:(URLLoaderConnectionDelegate*)delegate
asPending:(BOOL)pending {
static NSMutableSet* pendingConnections = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
pendingConnections = [[NSMutableSet alloc] init];
});
if (pending) {
[pendingConnections addObject:delegate];
} else {
[pendingConnections removeObject:delegate];
}
}
- (void)dealloc {
DCHECK(_response.is_null());
DCHECK(_startCallback.is_null());
_producer.reset();
[super dealloc];
}
@end
namespace mojo {
URLLoaderImpl::URLLoaderImpl(InterfaceRequest<URLLoader> request)
: binding_(this, request.Pass()),
connection_delegate_(nullptr),
pending_connection_(nullptr) {
connection_delegate_ = [[URLLoaderConnectionDelegate alloc] init];
}
URLLoaderImpl::~URLLoaderImpl() {
[(id)connection_delegate_ release];
[(id)pending_connection_ cancel];
[(id)pending_connection_ release];
}
void URLLoaderImpl::Start(URLRequestPtr request,
const StartCallback& callback) {
base::mac::ScopedNSAutoreleasePool pool;
NSURL* url = [NSURL URLWithString:@(request->url.data())];
NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:url];
req.HTTPMethod = @(request->method.data());
if (request->bypass_cache) {
req.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
}
URLLoaderConnectionDelegate* delegate =
(URLLoaderConnectionDelegate*)connection_delegate_;
NSURLConnection* connection =
[NSURLConnection connectionWithRequest:req delegate:delegate];
delegate.startCallback = callback;
[connection start];
pending_connection_ = [connection retain];
}
void URLLoaderImpl::FollowRedirect(const FollowRedirectCallback& callback) {
base::mac::ScopedNSAutoreleasePool pool;
DCHECK(false);
}
void URLLoaderImpl::QueryStatus(const QueryStatusCallback& callback) {
base::mac::ScopedNSAutoreleasePool pool;
DCHECK(false);
}
} // namespace mojo
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册