Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.net.impl; | 5 package org.chromium.net.impl; |
| 6 | 6 |
| 7 import android.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
| 8 import android.annotation.TargetApi; | 8 import android.annotation.TargetApi; |
| 9 import android.net.TrafficStats; | 9 import android.net.TrafficStats; |
| 10 import android.os.Build; | 10 import android.os.Build; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 import java.io.IOException; | 21 import java.io.IOException; |
| 22 import java.io.OutputStream; | 22 import java.io.OutputStream; |
| 23 import java.net.HttpURLConnection; | 23 import java.net.HttpURLConnection; |
| 24 import java.net.URI; | 24 import java.net.URI; |
| 25 import java.net.URL; | 25 import java.net.URL; |
| 26 import java.nio.ByteBuffer; | 26 import java.nio.ByteBuffer; |
| 27 import java.nio.channels.Channels; | 27 import java.nio.channels.Channels; |
| 28 import java.nio.channels.ReadableByteChannel; | 28 import java.nio.channels.ReadableByteChannel; |
| 29 import java.nio.channels.WritableByteChannel; | 29 import java.nio.channels.WritableByteChannel; |
| 30 import java.util.AbstractMap.SimpleEntry; | 30 import java.util.AbstractMap.SimpleEntry; |
| 31 import java.util.ArrayDeque; | |
| 31 import java.util.ArrayList; | 32 import java.util.ArrayList; |
| 32 import java.util.Collections; | 33 import java.util.Collections; |
| 33 import java.util.List; | 34 import java.util.List; |
| 34 import java.util.Map; | 35 import java.util.Map; |
| 35 import java.util.TreeMap; | 36 import java.util.TreeMap; |
| 36 import java.util.concurrent.Executor; | 37 import java.util.concurrent.Executor; |
| 37 import java.util.concurrent.RejectedExecutionException; | 38 import java.util.concurrent.RejectedExecutionException; |
| 38 import java.util.concurrent.atomic.AtomicBoolean; | 39 import java.util.concurrent.atomic.AtomicBoolean; |
| 39 import java.util.concurrent.atomic.AtomicReference; | 40 import java.util.concurrent.atomic.AtomicReference; |
| 40 | 41 |
| 42 import javax.annotation.concurrent.GuardedBy; | |
| 43 | |
| 41 /** | 44 /** |
| 42 * Pure java UrlRequest, backed by {@link HttpURLConnection}. | 45 * Pure java UrlRequest, backed by {@link HttpURLConnection}. |
| 43 */ | 46 */ |
| 44 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) // TrafficStats only availabl e on ICS | 47 @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) // TrafficStats only availabl e on ICS |
| 45 final class JavaUrlRequest extends UrlRequestBase { | 48 final class JavaUrlRequest extends UrlRequestBase { |
| 46 private static final String X_ANDROID = "X-Android"; | 49 private static final String X_ANDROID = "X-Android"; |
| 47 private static final String X_ANDROID_SELECTED_TRANSPORT = "X-Android-Select ed-Transport"; | 50 private static final String X_ANDROID_SELECTED_TRANSPORT = "X-Android-Select ed-Transport"; |
| 48 private static final String TAG = "JavaUrlConnection"; | 51 private static final String TAG = "JavaUrlConnection"; |
| 49 private static final int DEFAULT_UPLOAD_BUFFER_SIZE = 8192; | 52 private static final int DEFAULT_UPLOAD_BUFFER_SIZE = 8192; |
| 50 private static final int DEFAULT_CHUNK_LENGTH = DEFAULT_UPLOAD_BUFFER_SIZE; | 53 private static final int DEFAULT_CHUNK_LENGTH = DEFAULT_UPLOAD_BUFFER_SIZE; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 119 STARTED, | 122 STARTED, |
| 120 REDIRECT_RECEIVED, | 123 REDIRECT_RECEIVED, |
| 121 AWAITING_FOLLOW_REDIRECT, | 124 AWAITING_FOLLOW_REDIRECT, |
| 122 AWAITING_READ, | 125 AWAITING_READ, |
| 123 READING, | 126 READING, |
| 124 ERROR, | 127 ERROR, |
| 125 COMPLETE, | 128 COMPLETE, |
| 126 CANCELLED, | 129 CANCELLED, |
| 127 } | 130 } |
| 128 | 131 |
| 132 // Executor that runs one task at a time on an underlying Executor. | |
| 133 private class SeriaizingExecutor implements Executor { | |
|
Charles
2017/01/11 16:50:05
private final class
pauljensen
2017/01/11 16:53:50
Done.
| |
| 134 private final Executor mUnderlyingExecutor; | |
| 135 // Queue of tasks to run. First element is the task currently executing . | |
| 136 // Task processing loop is running if queue is not empty. Synchronized on itself. | |
| 137 @GuardedBy("mTaskQueue") | |
| 138 private final ArrayDeque<Runnable> mTaskQueue = new ArrayDeque<>(); | |
| 139 | |
| 140 public SeriaizingExecutor(Executor underlyingExecutor) { | |
|
Charles
2017/01/11 16:50:05
No need for public
pauljensen
2017/01/11 16:53:50
Done.
| |
| 141 mUnderlyingExecutor = underlyingExecutor; | |
| 142 } | |
| 143 | |
| 144 private void runTask(final Runnable task) { | |
| 145 mUnderlyingExecutor.execute(new Runnable() { | |
| 146 @Override | |
| 147 public void run() { | |
| 148 try { | |
| 149 task.run(); | |
| 150 } finally { | |
| 151 Runnable nextTask; | |
| 152 synchronized (mTaskQueue) { | |
| 153 mTaskQueue.removeFirst(); | |
| 154 nextTask = mTaskQueue.peekFirst(); | |
| 155 } | |
| 156 if (nextTask != null) { | |
| 157 runTask(nextTask); | |
| 158 } | |
| 159 } | |
| 160 } | |
| 161 }); | |
| 162 } | |
| 163 | |
| 164 @Override | |
| 165 public void execute(Runnable command) { | |
| 166 synchronized (mTaskQueue) { | |
| 167 mTaskQueue.addLast(command); | |
| 168 // Task processing loop is already running if there are other it ems in mTaskQueue. | |
| 169 if (mTaskQueue.size() > 1) { | |
| 170 return; | |
| 171 } | |
| 172 } | |
| 173 runTask(command); | |
| 174 }; | |
| 175 } | |
| 176 | |
| 129 /** | 177 /** |
| 130 * @param executor The executor used for reading and writing from sockets | 178 * @param executor The executor used for reading and writing from sockets |
| 131 * @param userExecutor The executor used to dispatch to {@code callback} | 179 * @param userExecutor The executor used to dispatch to {@code callback} |
| 132 */ | 180 */ |
| 133 JavaUrlRequest(Callback callback, final Executor executor, Executor userExec utor, String url, | 181 JavaUrlRequest(Callback callback, final Executor executor, Executor userExec utor, String url, |
| 134 String userAgent, boolean allowDirectExecutor) { | 182 String userAgent, boolean allowDirectExecutor) { |
| 135 if (url == null) { | 183 if (url == null) { |
| 136 throw new NullPointerException("URL is required"); | 184 throw new NullPointerException("URL is required"); |
| 137 } | 185 } |
| 138 if (callback == null) { | 186 if (callback == null) { |
| 139 throw new NullPointerException("Listener is required"); | 187 throw new NullPointerException("Listener is required"); |
| 140 } | 188 } |
| 141 if (executor == null) { | 189 if (executor == null) { |
| 142 throw new NullPointerException("Executor is required"); | 190 throw new NullPointerException("Executor is required"); |
| 143 } | 191 } |
| 144 if (userExecutor == null) { | 192 if (userExecutor == null) { |
| 145 throw new NullPointerException("userExecutor is required"); | 193 throw new NullPointerException("userExecutor is required"); |
| 146 } | 194 } |
| 147 | 195 |
| 148 this.mAllowDirectExecutor = allowDirectExecutor; | 196 this.mAllowDirectExecutor = allowDirectExecutor; |
| 149 this.mCallbackAsync = new AsyncUrlRequestCallback(callback, userExecutor ); | 197 this.mCallbackAsync = new AsyncUrlRequestCallback(callback, userExecutor ); |
| 150 this.mTrafficStatsTag = TrafficStats.getThreadStatsTag(); | 198 this.mTrafficStatsTag = TrafficStats.getThreadStatsTag(); |
| 151 this.mExecutor = new Executor() { | 199 this.mExecutor = new SeriaizingExecutor(new Executor() { |
| 152 @Override | 200 @Override |
| 153 public void execute(final Runnable command) { | 201 public void execute(final Runnable command) { |
| 154 executor.execute(new Runnable() { | 202 executor.execute(new Runnable() { |
| 155 @Override | 203 @Override |
| 156 public void run() { | 204 public void run() { |
| 157 int oldTag = TrafficStats.getThreadStatsTag(); | 205 int oldTag = TrafficStats.getThreadStatsTag(); |
| 158 TrafficStats.setThreadStatsTag(mTrafficStatsTag); | 206 TrafficStats.setThreadStatsTag(mTrafficStatsTag); |
| 159 try { | 207 try { |
| 160 command.run(); | 208 command.run(); |
| 161 } finally { | 209 } finally { |
| 162 TrafficStats.setThreadStatsTag(oldTag); | 210 TrafficStats.setThreadStatsTag(oldTag); |
| 163 } | 211 } |
| 164 } | 212 } |
| 165 }); | 213 }); |
| 166 } | 214 } |
| 167 }; | 215 }); |
| 168 this.mCurrentUrl = url; | 216 this.mCurrentUrl = url; |
| 169 this.mUserAgent = userAgent; | 217 this.mUserAgent = userAgent; |
| 170 } | 218 } |
| 171 | 219 |
| 172 @Override | 220 @Override |
| 173 public void setHttpMethod(String method) { | 221 public void setHttpMethod(String method) { |
| 174 checkNotStarted(); | 222 checkNotStarted(); |
| 175 if (method == null) { | 223 if (method == null) { |
| 176 throw new NullPointerException("Method is required."); | 224 throw new NullPointerException("Method is required."); |
| 177 } | 225 } |
| (...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 972 // Can't throw directly from here, since the delegate execut or could catch this | 1020 // Can't throw directly from here, since the delegate execut or could catch this |
| 973 // exception. | 1021 // exception. |
| 974 mExecutedInline = new InlineExecutionProhibitedException(); | 1022 mExecutedInline = new InlineExecutionProhibitedException(); |
| 975 return; | 1023 return; |
| 976 } | 1024 } |
| 977 mCommand.run(); | 1025 mCommand.run(); |
| 978 } | 1026 } |
| 979 } | 1027 } |
| 980 } | 1028 } |
| 981 } | 1029 } |
| OLD | NEW |