|  | // 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. | 
|  |  | 
|  | #ifndef COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_ | 
|  | #define COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_ | 
|  |  | 
|  | #include <jni.h> | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  |  | 
|  | #include "base/android/jni_android.h" | 
|  | #include "base/android/jni_array.h" | 
|  | #include "base/android/jni_string.h" | 
|  | #include "base/android/scoped_java_ref.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "net/http/bidirectional_stream.h" | 
|  |  | 
|  | namespace net { | 
|  | struct BidirectionalStreamRequestInfo; | 
|  | class SpdyHeaderBlock; | 
|  | }  // namespace net | 
|  |  | 
|  | namespace cronet { | 
|  |  | 
|  | class CronetURLRequestContextAdapter; | 
|  | class IOBufferWithByteBuffer; | 
|  |  | 
|  | // Convenient wrapper to hold Java references and data to represent the pending | 
|  | // data to be written. | 
|  | struct PendingWriteData { | 
|  | PendingWriteData(JNIEnv* env, | 
|  | jobjectArray jwrite_buffer_list, | 
|  | jintArray jwrite_buffer_pos_list, | 
|  | jintArray jwrite_buffer_limit_list, | 
|  | jboolean jwrite_end_of_stream); | 
|  | ~PendingWriteData(); | 
|  |  | 
|  | // Arguments passed in from Java. Retain a global ref so they won't get GC-ed | 
|  | // until the corresponding onWriteCompleted is invoked. | 
|  | base::android::ScopedJavaGlobalRef<jobjectArray> jwrite_buffer_list; | 
|  | base::android::ScopedJavaGlobalRef<jintArray> jwrite_buffer_pos_list; | 
|  | base::android::ScopedJavaGlobalRef<jintArray> jwrite_buffer_limit_list; | 
|  | // A copy of the end of stream flag passed in from Java. | 
|  | jboolean jwrite_end_of_stream; | 
|  | // Every IOBuffer in |write_buffer_list| points to the memory owned by the | 
|  | // corresponding Java ByteBuffer in |jwrite_buffer_list|. | 
|  | std::vector<scoped_refptr<net::IOBuffer>> write_buffer_list; | 
|  | // A list of the length of each IOBuffer in |write_buffer_list|. | 
|  | std::vector<int> write_buffer_len_list; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(PendingWriteData); | 
|  | }; | 
|  |  | 
|  | // An adapter from Java BidirectionalStream object to net::BidirectionalStream. | 
|  | // Created and configured from a Java thread. Start, ReadData, WritevData and | 
|  | // Destroy can be called on any thread (including network thread), and post | 
|  | // calls to corresponding {Start|ReadData|WritevData|Destroy}OnNetworkThread to | 
|  | // the network thread. The object is always deleted on network thread. All | 
|  | // callbacks into the Java BidirectionalStream are done on the network thread. | 
|  | // Java BidirectionalStream is expected to initiate the next step like ReadData | 
|  | // or Destroy. Public methods can be called on any thread. | 
|  | class CronetBidirectionalStreamAdapter | 
|  | : public net::BidirectionalStream::Delegate { | 
|  | public: | 
|  | static bool RegisterJni(JNIEnv* env); | 
|  |  | 
|  | CronetBidirectionalStreamAdapter( | 
|  | CronetURLRequestContextAdapter* context, | 
|  | JNIEnv* env, | 
|  | const base::android::JavaParamRef<jobject>& jbidi_stream, | 
|  | bool jsend_request_headers_automatically, | 
|  | bool enable_metrics); | 
|  | ~CronetBidirectionalStreamAdapter() override; | 
|  |  | 
|  | // Validates method and headers, initializes and starts the request. If | 
|  | // |jend_of_stream| is true, then stream is half-closed after sending header | 
|  | // frame and no data is expected to be written. | 
|  | // Returns 0 if request is valid and started successfully, | 
|  | // Returns -1 if |jmethod| is not valid HTTP method name. | 
|  | // Returns position of invalid header value in |jheaders| if header name is | 
|  | // not valid. | 
|  | jint Start(JNIEnv* env, | 
|  | const base::android::JavaParamRef<jobject>& jcaller, | 
|  | const base::android::JavaParamRef<jstring>& jurl, | 
|  | jint jpriority, | 
|  | const base::android::JavaParamRef<jstring>& jmethod, | 
|  | const base::android::JavaParamRef<jobjectArray>& jheaders, | 
|  | jboolean jend_of_stream); | 
|  |  | 
|  | // Sends request headers to server. | 
|  | // When |send_request_headers_automatically_| is | 
|  | // false and OnStreamReady() is invoked with request_headers_sent = false, | 
|  | // headers will be combined with next WriteData/WritevData unless this | 
|  | // method is called first, in which case headers will be sent separately | 
|  | // without delay. | 
|  | // (This method cannot be called when |send_request_headers_automatically_| is | 
|  | // true nor when OnStreamReady() is invoked with request_headers_sent = true, | 
|  | // since headers have been sent by the stream when stream is negotiated | 
|  | // successfully.) | 
|  | void SendRequestHeaders(JNIEnv* env, | 
|  | const base::android::JavaParamRef<jobject>& jcaller); | 
|  |  | 
|  | // Reads more data into |jbyte_buffer| starting at |jposition| and not | 
|  | // exceeding |jlimit|. Arguments are preserved to ensure that |jbyte_buffer| | 
|  | // is not modified by the application during read. | 
|  | jboolean ReadData(JNIEnv* env, | 
|  | const base::android::JavaParamRef<jobject>& jcaller, | 
|  | const base::android::JavaParamRef<jobject>& jbyte_buffer, | 
|  | jint jposition, | 
|  | jint jlimit); | 
|  |  | 
|  | // Writes more data from |jbyte_buffers|. For the i_th buffer in | 
|  | // |jbyte_buffers|, bytes to write start from i_th position in |jpositions| | 
|  | // and end at i_th limit in |jlimits|. | 
|  | // Arguments are preserved to ensure that |jbyte_buffer| | 
|  | // is not modified by the application during write. The |jend_of_stream| is | 
|  | // passed to remote to indicate end of stream. | 
|  | jboolean WritevData( | 
|  | JNIEnv* env, | 
|  | const base::android::JavaParamRef<jobject>& jcaller, | 
|  | const base::android::JavaParamRef<jobjectArray>& jbyte_buffers, | 
|  | const base::android::JavaParamRef<jintArray>& jpositions, | 
|  | const base::android::JavaParamRef<jintArray>& jlimits, | 
|  | jboolean jend_of_stream); | 
|  |  | 
|  | // Releases all resources for the request and deletes the object itself. | 
|  | // |jsend_on_canceled| indicates if Java onCanceled callback should be | 
|  | // issued to indicate that no more callbacks will be issued. | 
|  | void Destroy(JNIEnv* env, | 
|  | const base::android::JavaParamRef<jobject>& jcaller, | 
|  | jboolean jsend_on_canceled); | 
|  |  | 
|  | private: | 
|  | // net::BidirectionalStream::Delegate implementations: | 
|  | void OnStreamReady(bool request_headers_sent) override; | 
|  | void OnHeadersReceived(const net::SpdyHeaderBlock& response_headers) override; | 
|  | void OnDataRead(int bytes_read) override; | 
|  | void OnDataSent() override; | 
|  | void OnTrailersReceived(const net::SpdyHeaderBlock& trailers) override; | 
|  | void OnFailed(int error) override; | 
|  |  | 
|  | void StartOnNetworkThread( | 
|  | std::unique_ptr<net::BidirectionalStreamRequestInfo> request_info); | 
|  | void SendRequestHeadersOnNetworkThread(); | 
|  | void ReadDataOnNetworkThread( | 
|  | scoped_refptr<IOBufferWithByteBuffer> read_buffer, | 
|  | int buffer_size); | 
|  | void WritevDataOnNetworkThread( | 
|  | std::unique_ptr<PendingWriteData> pending_write_data); | 
|  | void DestroyOnNetworkThread(bool send_on_canceled); | 
|  | // Gets headers as a Java array. | 
|  | base::android::ScopedJavaLocalRef<jobjectArray> GetHeadersArray( | 
|  | JNIEnv* env, | 
|  | const net::SpdyHeaderBlock& header_block); | 
|  | // Helper method to report metrics to the Java layer. | 
|  | void MaybeReportMetrics(); | 
|  | CronetURLRequestContextAdapter* const context_; | 
|  |  | 
|  | // Java object that owns this CronetBidirectionalStreamAdapter. | 
|  | base::android::ScopedJavaGlobalRef<jobject> owner_; | 
|  | const bool send_request_headers_automatically_; | 
|  | // Whether metrics collection is enabled when |this| is created. | 
|  | const bool enable_metrics_; | 
|  |  | 
|  | scoped_refptr<IOBufferWithByteBuffer> read_buffer_; | 
|  | std::unique_ptr<PendingWriteData> pending_write_data_; | 
|  | std::unique_ptr<net::BidirectionalStream> bidi_stream_; | 
|  |  | 
|  | // Whether BidirectionalStream::Delegate::OnFailed callback is invoked. | 
|  | bool stream_failed_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(CronetBidirectionalStreamAdapter); | 
|  | }; | 
|  |  | 
|  | }  // namespace cronet | 
|  |  | 
|  | #endif  // COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_ |