1 // Copyright 2015 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_ 6 #define COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_ 7 8 #include <jni.h> 9 10 #include <memory> 11 12 #include "base/android/jni_android.h" 13 #include "base/android/jni_array.h" 14 #include "base/android/jni_string.h" 15 #include "base/android/scoped_java_ref.h" 16 #include "base/memory/raw_ptr.h" 17 #include "base/memory/ref_counted.h" 18 #include "net/base/network_handle.h" 19 #include "net/http/bidirectional_stream.h" 20 #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" 21 22 namespace net { 23 struct BidirectionalStreamRequestInfo; 24 } // namespace net 25 26 namespace cronet { 27 28 class CronetContextAdapter; 29 class IOBufferWithByteBuffer; 30 31 // Convenient wrapper to hold Java references and data to represent the pending 32 // data to be written. 33 struct PendingWriteData { 34 PendingWriteData( 35 JNIEnv* env, 36 const base::android::JavaRef<jobjectArray>& jwrite_buffer_list, 37 const base::android::JavaRef<jintArray>& jwrite_buffer_pos_list, 38 const base::android::JavaRef<jintArray>& jwrite_buffer_limit_list, 39 jboolean jwrite_end_of_stream); 40 41 PendingWriteData(const PendingWriteData&) = delete; 42 PendingWriteData& operator=(const PendingWriteData&) = delete; 43 44 ~PendingWriteData(); 45 46 // Arguments passed in from Java. Retain a global ref so they won't get GC-ed 47 // until the corresponding onWriteCompleted is invoked. 48 base::android::ScopedJavaGlobalRef<jobjectArray> jwrite_buffer_list; 49 base::android::ScopedJavaGlobalRef<jintArray> jwrite_buffer_pos_list; 50 base::android::ScopedJavaGlobalRef<jintArray> jwrite_buffer_limit_list; 51 // A copy of the end of stream flag passed in from Java. 52 jboolean jwrite_end_of_stream; 53 // Every IOBuffer in |write_buffer_list| points to the memory owned by the 54 // corresponding Java ByteBuffer in |jwrite_buffer_list|. 55 std::vector<scoped_refptr<net::IOBuffer>> write_buffer_list; 56 // A list of the length of each IOBuffer in |write_buffer_list|. 57 std::vector<int> write_buffer_len_list; 58 }; 59 60 // An adapter from Java BidirectionalStream object to net::BidirectionalStream. 61 // Created and configured from a Java thread. Start, ReadData, WritevData and 62 // Destroy can be called on any thread (including network thread), and post 63 // calls to corresponding {Start|ReadData|WritevData|Destroy}OnNetworkThread to 64 // the network thread. The object is always deleted on network thread. All 65 // callbacks into the Java BidirectionalStream are done on the network thread. 66 // Java BidirectionalStream is expected to initiate the next step like ReadData 67 // or Destroy. Public methods can be called on any thread. 68 class CronetBidirectionalStreamAdapter 69 : public net::BidirectionalStream::Delegate { 70 public: 71 CronetBidirectionalStreamAdapter( 72 CronetContextAdapter* context, 73 JNIEnv* env, 74 const base::android::JavaParamRef<jobject>& jbidi_stream, 75 bool jsend_request_headers_automatically, 76 bool traffic_stats_tag_set, 77 int32_t traffic_stats_tag, 78 bool traffic_stats_uid_set, 79 int32_t traffic_stats_uid, 80 net::handles::NetworkHandle network); 81 82 CronetBidirectionalStreamAdapter(const CronetBidirectionalStreamAdapter&) = 83 delete; 84 CronetBidirectionalStreamAdapter& operator=( 85 const CronetBidirectionalStreamAdapter&) = delete; 86 87 ~CronetBidirectionalStreamAdapter() override; 88 89 // Validates method and headers, initializes and starts the request. If 90 // |jend_of_stream| is true, then stream is half-closed after sending header 91 // frame and no data is expected to be written. 92 // Returns 0 if request is valid and started successfully, 93 // Returns -1 if |jmethod| is not valid HTTP method name. 94 // Returns position of invalid header value in |jheaders| if header name is 95 // not valid. 96 jint Start(JNIEnv* env, 97 const base::android::JavaParamRef<jobject>& jcaller, 98 const base::android::JavaParamRef<jstring>& jurl, 99 jint jpriority, 100 const base::android::JavaParamRef<jstring>& jmethod, 101 const base::android::JavaParamRef<jobjectArray>& jheaders, 102 jboolean jend_of_stream); 103 104 // Sends request headers to server. 105 // When |send_request_headers_automatically_| is 106 // false and OnStreamReady() is invoked with request_headers_sent = false, 107 // headers will be combined with next WriteData/WritevData unless this 108 // method is called first, in which case headers will be sent separately 109 // without delay. 110 // (This method cannot be called when |send_request_headers_automatically_| is 111 // true nor when OnStreamReady() is invoked with request_headers_sent = true, 112 // since headers have been sent by the stream when stream is negotiated 113 // successfully.) 114 void SendRequestHeaders(JNIEnv* env, 115 const base::android::JavaParamRef<jobject>& jcaller); 116 117 // Reads more data into |jbyte_buffer| starting at |jposition| and not 118 // exceeding |jlimit|. Arguments are preserved to ensure that |jbyte_buffer| 119 // is not modified by the application during read. 120 jboolean ReadData(JNIEnv* env, 121 const base::android::JavaParamRef<jobject>& jcaller, 122 const base::android::JavaParamRef<jobject>& jbyte_buffer, 123 jint jposition, 124 jint jlimit); 125 126 // Writes more data from |jbyte_buffers|. For the i_th buffer in 127 // |jbyte_buffers|, bytes to write start from i_th position in |jpositions| 128 // and end at i_th limit in |jlimits|. 129 // Arguments are preserved to ensure that |jbyte_buffer| 130 // is not modified by the application during write. The |jend_of_stream| is 131 // passed to remote to indicate end of stream. 132 jboolean WritevData( 133 JNIEnv* env, 134 const base::android::JavaParamRef<jobject>& jcaller, 135 const base::android::JavaParamRef<jobjectArray>& jbyte_buffers, 136 const base::android::JavaParamRef<jintArray>& jpositions, 137 const base::android::JavaParamRef<jintArray>& jlimits, 138 jboolean jend_of_stream); 139 140 // Releases all resources for the request and deletes the object itself. 141 // |jsend_on_canceled| indicates if Java onCanceled callback should be 142 // issued to indicate that no more callbacks will be issued. 143 void Destroy(JNIEnv* env, 144 const base::android::JavaParamRef<jobject>& jcaller, 145 jboolean jsend_on_canceled); 146 147 private: 148 // net::BidirectionalStream::Delegate implementations: 149 void OnStreamReady(bool request_headers_sent) override; 150 void OnHeadersReceived( 151 const spdy::Http2HeaderBlock& response_headers) override; 152 void OnDataRead(int bytes_read) override; 153 void OnDataSent() override; 154 void OnTrailersReceived(const spdy::Http2HeaderBlock& trailers) override; 155 void OnFailed(int error) override; 156 157 void StartOnNetworkThread( 158 std::unique_ptr<net::BidirectionalStreamRequestInfo> request_info); 159 void SendRequestHeadersOnNetworkThread(); 160 void ReadDataOnNetworkThread( 161 scoped_refptr<IOBufferWithByteBuffer> read_buffer, 162 int buffer_size); 163 void WritevDataOnNetworkThread( 164 std::unique_ptr<PendingWriteData> pending_write_data); 165 void DestroyOnNetworkThread(bool send_on_canceled); 166 // Gets headers as a Java array. 167 base::android::ScopedJavaLocalRef<jobjectArray> GetHeadersArray( 168 JNIEnv* env, 169 const spdy::Http2HeaderBlock& header_block); 170 // Reports metrics to the Java layer if the stream was ever started. Called on 171 // the network thread immediately before the adapter destroys itself. 172 void MaybeReportMetrics(); 173 const raw_ptr<CronetContextAdapter> context_; 174 175 // Java object that owns this CronetBidirectionalStreamAdapter. 176 base::android::ScopedJavaGlobalRef<jobject> owner_; 177 const bool send_request_headers_automatically_; 178 // Whether |traffic_stats_tag_| should be applied. 179 const bool traffic_stats_tag_set_; 180 // TrafficStats tag to apply to URLRequest. 181 const int32_t traffic_stats_tag_; 182 // Whether |traffic_stats_uid_| should be applied. 183 const bool traffic_stats_uid_set_; 184 // UID to be applied to URLRequest. 185 const int32_t traffic_stats_uid_; 186 // If not equal to net::handles::kInvalidNetworkHandle, the network to be used 187 // to send this request. 188 const net::handles::NetworkHandle network_; 189 190 scoped_refptr<IOBufferWithByteBuffer> read_buffer_; 191 std::unique_ptr<PendingWriteData> pending_write_data_; 192 std::unique_ptr<net::BidirectionalStream> bidi_stream_; 193 194 // Whether BidirectionalStream::Delegate::OnFailed callback is invoked. 195 bool stream_failed_; 196 }; 197 198 } // namespace cronet 199 200 #endif // COMPONENTS_CRONET_ANDROID_CRONET_BIDIRECTIONAL_STREAM_ADAPTER_H_ 201