Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Unified Diff: components/cronet/android/java/src/org/chromium/net/CronetBidirectionalStream.java

Issue 1849753002: [Cronet] Separate Cronet implementation and API by package name. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: sync Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/cronet/android/java/src/org/chromium/net/CronetBidirectionalStream.java
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetBidirectionalStream.java b/components/cronet/android/java/src/org/chromium/net/CronetBidirectionalStream.java
deleted file mode 100644
index 86bde7ec8a3750e9af407afc19b58a71aa6a5fb1..0000000000000000000000000000000000000000
--- a/components/cronet/android/java/src/org/chromium/net/CronetBidirectionalStream.java
+++ /dev/null
@@ -1,767 +0,0 @@
-// 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.
-
-package org.chromium.net;
-
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeClassQualifiedName;
-
-import java.nio.ByteBuffer;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
-
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * {@link BidirectionalStream} implementation using Chromium network stack.
- * All @CalledByNative methods are called on the native network thread
- * and post tasks with callback calls onto Executor. Upon returning from callback, the native
- * stream is called on Executor thread and posts native tasks to the native network thread.
- */
-@JNINamespace("cronet")
-class CronetBidirectionalStream extends BidirectionalStream {
- /**
- * States of BidirectionalStream are tracked in mReadState and mWriteState.
- * The write state is separated out as it changes independently of the read state.
- * There is one initial state: State.NOT_STARTED. There is one normal final state:
- * State.SUCCESS, reached after State.READING_DONE and State.WRITING_DONE. There are two
- * exceptional final states: State.CANCELED and State.ERROR, which can be reached from
- * any other non-final state.
- */
- private enum State {
- /* Initial state, stream not started. */
- NOT_STARTED,
- /*
- * Stream started, request headers are being sent if mDelayRequestHeadersUntilNextFlush
- * is not set to true.
- */
- STARTED,
- /* Waiting for {@code read()} to be called. */
- WAITING_FOR_READ,
- /* Reading from the remote, {@code onReadCompleted()} callback will be called when done. */
- READING,
- /* There is no more data to read and stream is half-closed by the remote side. */
- READING_DONE,
- /* Stream is canceled. */
- CANCELED,
- /* Error has occured, stream is closed. */
- ERROR,
- /* Reading and writing are done, and the stream is closed successfully. */
- SUCCESS,
- /* Waiting for {@code nativeSendRequestHeaders()} or {@code nativeWritevData()} to be
- called. */
- WAITING_FOR_FLUSH,
- /* Writing to the remote, {@code onWritevCompleted()} callback will be called when done. */
- WRITING,
- /* There is no more data to write and stream is half-closed by the local side. */
- WRITING_DONE,
- }
-
- private final CronetUrlRequestContext mRequestContext;
- private final Executor mExecutor;
- private final Callback mCallback;
- private final String mInitialUrl;
- private final int mInitialPriority;
- private final String mInitialMethod;
- private final String mRequestHeaders[];
- private final boolean mDisableAutoFlush;
- private final boolean mDelayRequestHeadersUntilFirstFlush;
-
- /*
- * Synchronizes access to mNativeStream, mReadState and mWriteState.
- */
- private final Object mNativeStreamLock = new Object();
-
- @GuardedBy("mNativeStreamLock")
- // Pending write data.
- private LinkedList<ByteBuffer> mPendingData;
-
- @GuardedBy("mNativeStreamLock")
- // Flush data queue that should be pushed to the native stack when the previous
- // nativeWritevData completes.
- private LinkedList<ByteBuffer> mFlushData;
-
- @GuardedBy("mNativeStreamLock")
- // Whether an end-of-stream flag is passed in through write().
- private boolean mEndOfStreamWritten;
-
- @GuardedBy("mNativeStreamLock")
- // Whether request headers have been sent.
- private boolean mRequestHeadersSent;
-
- /* Native BidirectionalStream object, owned by CronetBidirectionalStream. */
- @GuardedBy("mNativeStreamLock")
- private long mNativeStream;
-
- /**
- * Read state is tracking reading flow.
- * / <--- READING <--- \
- * | |
- * \ /
- * NOT_STARTED -> STARTED --> WAITING_FOR_READ -> READING_DONE -> SUCCESS
- */
- @GuardedBy("mNativeStreamLock")
- private State mReadState = State.NOT_STARTED;
-
- /**
- * Write state is tracking writing flow.
- * / <--- WRITING <--- \
- * | |
- * \ /
- * NOT_STARTED -> STARTED --> WAITING_FOR_FLUSH -> WRITING_DONE -> SUCCESS
- */
- @GuardedBy("mNativeStreamLock")
- private State mWriteState = State.NOT_STARTED;
-
- // Only modified on the network thread.
- private UrlResponseInfo mResponseInfo;
-
- /*
- * OnReadCompleted callback is repeatedly invoked when each read is completed, so it
- * is cached as a member variable.
- */
- // Only modified on the network thread.
- private OnReadCompletedRunnable mOnReadCompletedTask;
-
- private Runnable mOnDestroyedCallbackForTesting;
-
- private final class OnReadCompletedRunnable implements Runnable {
- // Buffer passed back from current invocation of onReadCompleted.
- ByteBuffer mByteBuffer;
- // End of stream flag from current invocation of onReadCompleted.
- boolean mEndOfStream;
-
- @Override
- public void run() {
- try {
- // Null out mByteBuffer, to pass buffer ownership to callback or release if done.
- ByteBuffer buffer = mByteBuffer;
- mByteBuffer = null;
- boolean maybeOnSucceeded = false;
- synchronized (mNativeStreamLock) {
- if (isDoneLocked()) {
- return;
- }
- if (mEndOfStream) {
- mReadState = State.READING_DONE;
- maybeOnSucceeded = (mWriteState == State.WRITING_DONE);
- } else {
- mReadState = State.WAITING_FOR_READ;
- }
- }
- mCallback.onReadCompleted(
- CronetBidirectionalStream.this, mResponseInfo, buffer, mEndOfStream);
- if (maybeOnSucceeded) {
- maybeOnSucceededOnExecutor();
- }
- } catch (Exception e) {
- onCallbackException(e);
- }
- }
- }
-
- private final class OnWriteCompletedRunnable implements Runnable {
- // Buffer passed back from current invocation of onWriteCompleted.
- private ByteBuffer mByteBuffer;
- // End of stream flag from current call to write.
- private final boolean mEndOfStream;
-
- OnWriteCompletedRunnable(ByteBuffer buffer, boolean endOfStream) {
- mByteBuffer = buffer;
- mEndOfStream = endOfStream;
- }
-
- @Override
- public void run() {
- try {
- // Null out mByteBuffer, to pass buffer ownership to callback or release if done.
- ByteBuffer buffer = mByteBuffer;
- mByteBuffer = null;
- boolean maybeOnSucceeded = false;
- synchronized (mNativeStreamLock) {
- if (isDoneLocked()) {
- return;
- }
- if (mEndOfStream) {
- mWriteState = State.WRITING_DONE;
- maybeOnSucceeded = (mReadState == State.READING_DONE);
- }
- }
- mCallback.onWriteCompleted(
- CronetBidirectionalStream.this, mResponseInfo, buffer, mEndOfStream);
- if (maybeOnSucceeded) {
- maybeOnSucceededOnExecutor();
- }
- } catch (Exception e) {
- onCallbackException(e);
- }
- }
- }
-
- CronetBidirectionalStream(CronetUrlRequestContext requestContext, String url,
- @BidirectionalStream.Builder.StreamPriority int priority, Callback callback,
- Executor executor, String httpMethod, List<Map.Entry<String, String>> requestHeaders,
- boolean disableAutoFlush, boolean delayRequestHeadersUntilNextFlush) {
- mRequestContext = requestContext;
- mInitialUrl = url;
- mInitialPriority = convertStreamPriority(priority);
- mCallback = callback;
- mExecutor = executor;
- mInitialMethod = httpMethod;
- mRequestHeaders = stringsFromHeaderList(requestHeaders);
- mDisableAutoFlush = disableAutoFlush;
- mDelayRequestHeadersUntilFirstFlush = delayRequestHeadersUntilNextFlush;
- mPendingData = new LinkedList<>();
- mFlushData = new LinkedList<>();
- }
-
- @Override
- public void start() {
- synchronized (mNativeStreamLock) {
- if (mReadState != State.NOT_STARTED) {
- throw new IllegalStateException("Stream is already started.");
- }
- try {
- mNativeStream = nativeCreateBidirectionalStream(
- mRequestContext.getUrlRequestContextAdapter(),
- !mDelayRequestHeadersUntilFirstFlush);
- mRequestContext.onRequestStarted();
- // Non-zero startResult means an argument error.
- int startResult = nativeStart(mNativeStream, mInitialUrl, mInitialPriority,
- mInitialMethod, mRequestHeaders, !doesMethodAllowWriteData(mInitialMethod));
- if (startResult == -1) {
- throw new IllegalArgumentException("Invalid http method " + mInitialMethod);
- }
- if (startResult > 0) {
- int headerPos = startResult - 1;
- throw new IllegalArgumentException("Invalid header "
- + mRequestHeaders[headerPos] + "=" + mRequestHeaders[headerPos + 1]);
- }
- mReadState = mWriteState = State.STARTED;
- } catch (RuntimeException e) {
- // If there's an exception, clean up and then throw the
- // exception to the caller.
- destroyNativeStreamLocked(false);
- throw e;
- }
- }
- }
-
- @Override
- public void read(ByteBuffer buffer) {
- synchronized (mNativeStreamLock) {
- Preconditions.checkHasRemaining(buffer);
- Preconditions.checkDirect(buffer);
- if (mReadState != State.WAITING_FOR_READ) {
- throw new IllegalStateException("Unexpected read attempt.");
- }
- if (isDoneLocked()) {
- return;
- }
- if (mOnReadCompletedTask == null) {
- mOnReadCompletedTask = new OnReadCompletedRunnable();
- }
- mReadState = State.READING;
- if (!nativeReadData(mNativeStream, buffer, buffer.position(), buffer.limit())) {
- // Still waiting on read. This is just to have consistent
- // behavior with the other error cases.
- mReadState = State.WAITING_FOR_READ;
- throw new IllegalArgumentException("Unable to call native read");
- }
- }
- }
-
- @Override
- public void write(ByteBuffer buffer, boolean endOfStream) {
- synchronized (mNativeStreamLock) {
- Preconditions.checkDirect(buffer);
- if (!buffer.hasRemaining() && !endOfStream) {
- throw new IllegalArgumentException("Empty buffer before end of stream.");
- }
- if (mEndOfStreamWritten) {
- throw new IllegalArgumentException("Write after writing end of stream.");
- }
- if (isDoneLocked()) {
- return;
- }
- mPendingData.add(buffer);
- if (endOfStream) {
- mEndOfStreamWritten = true;
- }
- if (!mDisableAutoFlush) {
- flushLocked();
- }
- }
- }
-
- @Override
- public void flush() {
- synchronized (mNativeStreamLock) {
- flushLocked();
- }
- }
-
- @SuppressWarnings("GuardedByChecker")
- private void flushLocked() {
- if (isDoneLocked()
- || (mWriteState != State.WAITING_FOR_FLUSH && mWriteState != State.WRITING)) {
- return;
- }
- if (mPendingData.isEmpty() && mFlushData.isEmpty()) {
- // If there is no pending write when flush() is called, see if
- // request headers need to be flushed.
- if (!mRequestHeadersSent) {
- mRequestHeadersSent = true;
- nativeSendRequestHeaders(mNativeStream);
- if (!doesMethodAllowWriteData(mInitialMethod)) {
- mWriteState = State.WRITING_DONE;
- }
- }
- return;
- }
-
- assert !mPendingData.isEmpty() || !mFlushData.isEmpty();
-
- // Move buffers from mPendingData to the flushing queue.
- if (!mPendingData.isEmpty()) {
- mFlushData.addAll(mPendingData);
- mPendingData.clear();
- }
-
- if (mWriteState == State.WRITING) {
- // If there is a write already pending, wait until onWritevCompleted is
- // called before pushing data to the native stack.
- return;
- }
- sendFlushDataLocked();
- }
-
- // Helper method to send buffers in mFlushData. Caller needs to acquire
- // mNativeStreamLock and make sure mWriteState is WAITING_FOR_FLUSH and
- // mFlushData queue isn't empty.
- @SuppressWarnings("GuardedByChecker")
- private void sendFlushDataLocked() {
- assert mWriteState == State.WAITING_FOR_FLUSH;
- int size = mFlushData.size();
- ByteBuffer[] buffers = new ByteBuffer[size];
- int[] positions = new int[size];
- int[] limits = new int[size];
- for (int i = 0; i < size; i++) {
- ByteBuffer buffer = mFlushData.poll();
- buffers[i] = buffer;
- positions[i] = buffer.position();
- limits[i] = buffer.limit();
- }
- assert mFlushData.isEmpty();
- assert buffers.length >= 1;
- mWriteState = State.WRITING;
- if (!nativeWritevData(mNativeStream, buffers, positions, limits,
- mEndOfStreamWritten && mPendingData.isEmpty())) {
- // Still waiting on flush. This is just to have consistent
- // behavior with the other error cases.
- mWriteState = State.WAITING_FOR_FLUSH;
- throw new IllegalArgumentException("Unable to call native writev.");
- }
- }
-
- /**
- * Returns a read-only copy of {@code mPendingData} for testing.
- */
- @VisibleForTesting
- public List<ByteBuffer> getPendingDataForTesting() {
- synchronized (mNativeStreamLock) {
- List<ByteBuffer> pendingData = new LinkedList<ByteBuffer>();
- for (ByteBuffer buffer : mPendingData) {
- pendingData.add(buffer.asReadOnlyBuffer());
- }
- return pendingData;
- }
- }
-
- /**
- * Returns a read-only copy of {@code mFlushData} for testing.
- */
- @VisibleForTesting
- public List<ByteBuffer> getFlushDataForTesting() {
- synchronized (mNativeStreamLock) {
- List<ByteBuffer> flushData = new LinkedList<ByteBuffer>();
- for (ByteBuffer buffer : mFlushData) {
- flushData.add(buffer.asReadOnlyBuffer());
- }
- return flushData;
- }
- }
-
- @Override
- public void cancel() {
- synchronized (mNativeStreamLock) {
- if (isDoneLocked() || mReadState == State.NOT_STARTED) {
- return;
- }
- mReadState = mWriteState = State.CANCELED;
- destroyNativeStreamLocked(true);
- }
- }
-
- @Override
- public boolean isDone() {
- synchronized (mNativeStreamLock) {
- return isDoneLocked();
- }
- }
-
- @GuardedBy("mNativeStreamLock")
- private boolean isDoneLocked() {
- return mReadState != State.NOT_STARTED && mNativeStream == 0;
- }
-
- /*
- * Runs an onSucceeded callback if both Read and Write sides are closed.
- */
- private void maybeOnSucceededOnExecutor() {
- synchronized (mNativeStreamLock) {
- if (isDoneLocked()) {
- return;
- }
- if (!(mWriteState == State.WRITING_DONE && mReadState == State.READING_DONE)) {
- return;
- }
- mReadState = mWriteState = State.SUCCESS;
- // Destroy native stream first, so UrlRequestContext could be shut
- // down from the listener.
- destroyNativeStreamLocked(false);
- }
- try {
- mCallback.onSucceeded(CronetBidirectionalStream.this, mResponseInfo);
- } catch (Exception e) {
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onSucceeded method", e);
- }
- }
-
- @SuppressWarnings("unused")
- @CalledByNative
- private void onStreamReady(final boolean requestHeadersSent) {
- postTaskToExecutor(new Runnable() {
- public void run() {
- synchronized (mNativeStreamLock) {
- if (isDoneLocked()) {
- return;
- }
- mRequestHeadersSent = requestHeadersSent;
- mReadState = State.WAITING_FOR_READ;
- if (!doesMethodAllowWriteData(mInitialMethod) && mRequestHeadersSent) {
- mWriteState = State.WRITING_DONE;
- } else {
- mWriteState = State.WAITING_FOR_FLUSH;
- }
- }
-
- try {
- mCallback.onStreamReady(CronetBidirectionalStream.this);
- } catch (Exception e) {
- onCallbackException(e);
- }
- }
- });
- }
-
- /**
- * Called when the final set of headers, after all redirects,
- * is received. Can only be called once for each stream.
- */
- @SuppressWarnings("unused")
- @CalledByNative
- private void onResponseHeadersReceived(int httpStatusCode, String negotiatedProtocol,
- String[] headers, long receivedBytesCount) {
- try {
- mResponseInfo = prepareResponseInfoOnNetworkThread(
- httpStatusCode, negotiatedProtocol, headers, receivedBytesCount);
- } catch (Exception e) {
- failWithException(new CronetException("Cannot prepare ResponseInfo", null));
- return;
- }
- postTaskToExecutor(new Runnable() {
- public void run() {
- synchronized (mNativeStreamLock) {
- if (isDoneLocked()) {
- return;
- }
- mReadState = State.WAITING_FOR_READ;
- }
-
- try {
- mCallback.onResponseHeadersReceived(
- CronetBidirectionalStream.this, mResponseInfo);
- } catch (Exception e) {
- onCallbackException(e);
- }
- }
- });
- }
-
- @SuppressWarnings("unused")
- @CalledByNative
- private void onReadCompleted(final ByteBuffer byteBuffer, int bytesRead, int initialPosition,
- int initialLimit, long receivedBytesCount) {
- mResponseInfo.setReceivedBytesCount(receivedBytesCount);
- if (byteBuffer.position() != initialPosition || byteBuffer.limit() != initialLimit) {
- failWithException(
- new CronetException("ByteBuffer modified externally during read", null));
- return;
- }
- if (bytesRead < 0 || initialPosition + bytesRead > initialLimit) {
- failWithException(new CronetException("Invalid number of bytes read", null));
- return;
- }
- byteBuffer.position(initialPosition + bytesRead);
- assert mOnReadCompletedTask.mByteBuffer == null;
- mOnReadCompletedTask.mByteBuffer = byteBuffer;
- mOnReadCompletedTask.mEndOfStream = (bytesRead == 0);
- postTaskToExecutor(mOnReadCompletedTask);
- }
-
- @SuppressWarnings("unused")
- @CalledByNative
- private void onWritevCompleted(final ByteBuffer[] byteBuffers, int[] initialPositions,
- int[] initialLimits, boolean endOfStream) {
- assert byteBuffers.length == initialPositions.length;
- assert byteBuffers.length == initialLimits.length;
- synchronized (mNativeStreamLock) {
- mWriteState = State.WAITING_FOR_FLUSH;
- // Flush if there is anything in the flush queue mFlushData.
- if (!mFlushData.isEmpty()) {
- sendFlushDataLocked();
- }
- }
- for (int i = 0; i < byteBuffers.length; i++) {
- ByteBuffer buffer = byteBuffers[i];
- if (buffer.position() != initialPositions[i] || buffer.limit() != initialLimits[i]) {
- failWithException(
- new CronetException("ByteBuffer modified externally during write", null));
- return;
- }
- // Current implementation always writes the complete buffer.
- buffer.position(buffer.limit());
- postTaskToExecutor(new OnWriteCompletedRunnable(buffer,
- // Only set endOfStream flag if this buffer is the last in byteBuffers.
- endOfStream && i == byteBuffers.length - 1));
- }
- }
-
- @SuppressWarnings("unused")
- @CalledByNative
- private void onResponseTrailersReceived(String[] trailers) {
- final UrlResponseInfo.HeaderBlock trailersBlock =
- new UrlResponseInfo.HeaderBlock(headersListFromStrings(trailers));
- postTaskToExecutor(new Runnable() {
- public void run() {
- synchronized (mNativeStreamLock) {
- if (isDoneLocked()) {
- return;
- }
- }
- try {
- mCallback.onResponseTrailersReceived(
- CronetBidirectionalStream.this, mResponseInfo, trailersBlock);
- } catch (Exception e) {
- onCallbackException(e);
- }
- }
- });
- }
-
- @SuppressWarnings("unused")
- @CalledByNative
- private void onError(int errorCode, int nativeError, int nativeQuicError, String errorString,
- long receivedBytesCount) {
- if (mResponseInfo != null) {
- mResponseInfo.setReceivedBytesCount(receivedBytesCount);
- }
- if (errorCode == UrlRequestException.ERROR_QUIC_PROTOCOL_FAILED) {
- failWithException(new QuicException("Exception in BidirectionalStream: " + errorString,
- nativeError, nativeQuicError));
- } else {
- failWithException(new CronetException(
- "Exception in BidirectionalStream: " + errorString, errorCode, nativeError));
- }
- }
-
- /**
- * Called when request is canceled, no callbacks will be called afterwards.
- */
- @SuppressWarnings("unused")
- @CalledByNative
- private void onCanceled() {
- postTaskToExecutor(new Runnable() {
- public void run() {
- try {
- mCallback.onCanceled(CronetBidirectionalStream.this, mResponseInfo);
- } catch (Exception e) {
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCanceled method", e);
- }
- }
- });
- }
-
- @VisibleForTesting
- public void setOnDestroyedCallbackForTesting(Runnable onDestroyedCallbackForTesting) {
- mOnDestroyedCallbackForTesting = onDestroyedCallbackForTesting;
- }
-
- private static boolean doesMethodAllowWriteData(String methodName) {
- return !methodName.equals("GET") && !methodName.equals("HEAD");
- }
-
- private static ArrayList<Map.Entry<String, String>> headersListFromStrings(String[] headers) {
- ArrayList<Map.Entry<String, String>> headersList = new ArrayList<>(headers.length / 2);
- for (int i = 0; i < headers.length; i += 2) {
- headersList.add(new AbstractMap.SimpleImmutableEntry<>(headers[i], headers[i + 1]));
- }
- return headersList;
- }
-
- private static String[] stringsFromHeaderList(List<Map.Entry<String, String>> headersList) {
- String headersArray[] = new String[headersList.size() * 2];
- int i = 0;
- for (Map.Entry<String, String> requestHeader : headersList) {
- headersArray[i++] = requestHeader.getKey();
- headersArray[i++] = requestHeader.getValue();
- }
- return headersArray;
- }
-
- private static int convertStreamPriority(
- @BidirectionalStream.Builder.StreamPriority int priority) {
- switch (priority) {
- case Builder.STREAM_PRIORITY_IDLE:
- return RequestPriority.IDLE;
- case Builder.STREAM_PRIORITY_LOWEST:
- return RequestPriority.LOWEST;
- case Builder.STREAM_PRIORITY_LOW:
- return RequestPriority.LOW;
- case Builder.STREAM_PRIORITY_MEDIUM:
- return RequestPriority.MEDIUM;
- case Builder.STREAM_PRIORITY_HIGHEST:
- return RequestPriority.HIGHEST;
- default:
- throw new IllegalArgumentException("Invalid stream priority.");
- }
- }
-
- /**
- * Posts task to application Executor. Used for callbacks
- * and other tasks that should not be executed on network thread.
- */
- private void postTaskToExecutor(Runnable task) {
- try {
- mExecutor.execute(task);
- } catch (RejectedExecutionException failException) {
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to executor",
- failException);
- // If posting a task throws an exception, then there is no choice
- // but to destroy the stream without invoking the callback.
- synchronized (mNativeStreamLock) {
- mReadState = mWriteState = State.ERROR;
- destroyNativeStreamLocked(false);
- }
- }
- }
-
- private UrlResponseInfo prepareResponseInfoOnNetworkThread(int httpStatusCode,
- String negotiatedProtocol, String[] headers, long receivedBytesCount) {
- UrlResponseInfo responseInfo =
- new UrlResponseInfo(Arrays.asList(mInitialUrl), httpStatusCode, "",
- headersListFromStrings(headers), false, negotiatedProtocol, null);
- responseInfo.setReceivedBytesCount(receivedBytesCount);
- return responseInfo;
- }
-
- @GuardedBy("mNativeStreamLock")
- private void destroyNativeStreamLocked(boolean sendOnCanceled) {
- Log.i(CronetUrlRequestContext.LOG_TAG, "destroyNativeStreamLocked " + this.toString());
- if (mNativeStream == 0) {
- return;
- }
- nativeDestroy(mNativeStream, sendOnCanceled);
- mNativeStream = 0;
- mRequestContext.onRequestDestroyed();
- if (mOnDestroyedCallbackForTesting != null) {
- mOnDestroyedCallbackForTesting.run();
- }
- }
-
- /**
- * Fails the stream with an exception. Only called on the Executor.
- */
- private void failWithExceptionOnExecutor(CronetException e) {
- // Do not call into mCallback if request is complete.
- synchronized (mNativeStreamLock) {
- if (isDoneLocked()) {
- return;
- }
- mReadState = mWriteState = State.ERROR;
- destroyNativeStreamLocked(false);
- }
- try {
- mCallback.onFailed(this, mResponseInfo, e);
- } catch (Exception failException) {
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception notifying of failed request",
- failException);
- }
- }
-
- /**
- * If callback method throws an exception, stream gets canceled
- * and exception is reported via onFailed callback.
- * Only called on the Executor.
- */
- private void onCallbackException(Exception e) {
- CronetException streamError =
- new CronetException("CalledByNative method has thrown an exception", e);
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in CalledByNative method", e);
- failWithExceptionOnExecutor(streamError);
- }
-
- /**
- * Fails the stream with an exception. Can be called on any thread.
- */
- private void failWithException(final CronetException exception) {
- postTaskToExecutor(new Runnable() {
- public void run() {
- failWithExceptionOnExecutor(exception);
- }
- });
- }
-
- // Native methods are implemented in cronet_bidirectional_stream_adapter.cc.
- private native long nativeCreateBidirectionalStream(
- long urlRequestContextAdapter, boolean sendRequestHeadersAutomatically);
-
- @NativeClassQualifiedName("CronetBidirectionalStreamAdapter")
- private native int nativeStart(long nativePtr, String url, int priority, String method,
- String[] headers, boolean endOfStream);
-
- @NativeClassQualifiedName("CronetBidirectionalStreamAdapter")
- private native void nativeSendRequestHeaders(long nativePtr);
-
- @NativeClassQualifiedName("CronetBidirectionalStreamAdapter")
- private native boolean nativeReadData(
- long nativePtr, ByteBuffer byteBuffer, int position, int limit);
-
- @NativeClassQualifiedName("CronetBidirectionalStreamAdapter")
- private native boolean nativeWritevData(long nativePtr, ByteBuffer[] buffers, int[] positions,
- int[] limits, boolean endOfStream);
-
- @NativeClassQualifiedName("CronetBidirectionalStreamAdapter")
- private native void nativeDestroy(long nativePtr, boolean sendOnCanceled);
-}

Powered by Google App Engine
This is Rietveld 408576698