1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.cronet_sample_apk; 6 7 import android.app.Activity; 8 import android.app.AlertDialog; 9 import android.content.DialogInterface; 10 import android.content.Intent; 11 import android.os.Bundle; 12 import android.os.Environment; 13 import android.util.Log; 14 import android.widget.EditText; 15 import android.widget.Toast; 16 17 import org.chromium.net.HttpUrlRequest; 18 import org.chromium.net.HttpUrlRequestFactory; 19 import org.chromium.net.HttpUrlRequestFactoryConfig; 20 import org.chromium.net.HttpUrlRequestListener; 21 import org.chromium.net.LibraryLoader; 22 import org.chromium.net.UrlRequest; 23 import org.chromium.net.UrlRequestContext; 24 import org.chromium.net.UrlRequestPriority; 25 26 import java.io.ByteArrayInputStream; 27 import java.io.InputStream; 28 29 import java.nio.channels.Channels; 30 import java.nio.channels.ReadableByteChannel; 31 import java.nio.channels.WritableByteChannel; 32 import java.util.HashMap; 33 import java.util.Map; 34 35 /** 36 * Activity for managing the Cronet Sample. 37 */ 38 public class CronetSampleActivity extends Activity { 39 private static final String TAG = "CronetSampleActivity"; 40 41 public static final String COMMAND_LINE_ARGS_KEY = "commandLineArgs"; 42 43 public static final String POST_DATA_KEY = "postData"; 44 public static final String CONFIG_KEY = "config"; 45 46 UrlRequestContext mRequestContext; 47 48 HttpUrlRequestFactory mRequestFactory; 49 50 String mUrl; 51 52 boolean mLoading = false; 53 54 int mHttpStatusCode = 0; 55 56 class SampleRequestContext extends UrlRequestContext { 57 public SampleRequestContext() { 58 super(getApplicationContext(), "Cronet Sample", 59 new HttpUrlRequestFactoryConfig().toString()); 60 } 61 } 62 63 class SampleRequest extends UrlRequest { 64 public SampleRequest(UrlRequestContext requestContext, String url, 65 int priority, Map<String, String> headers, 66 WritableByteChannel sink) { 67 super(requestContext, url, priority, headers, sink); 68 } 69 70 @Override 71 protected void onRequestComplete() { 72 mHttpStatusCode = super.getHttpStatusCode(); 73 Log.i(TAG, "****** Request Complete, status code is " 74 + mHttpStatusCode); 75 Intent intent = new Intent(getApplicationContext(), 76 CronetSampleActivity.class); 77 startActivity(intent); 78 final String url = super.getUrl(); 79 final CharSequence text = "Completed " + url + " (" 80 + mHttpStatusCode + ")"; 81 CronetSampleActivity.this.runOnUiThread(new Runnable() { 82 public void run() { 83 mLoading = false; 84 Toast toast = Toast.makeText(getApplicationContext(), text, 85 Toast.LENGTH_SHORT); 86 toast.show(); 87 promptForURL(url); 88 } 89 }); 90 } 91 } 92 93 class SampleHttpUrlRequestListener implements HttpUrlRequestListener { 94 public SampleHttpUrlRequestListener() { 95 } 96 97 @Override 98 public void onResponseStarted(HttpUrlRequest request) { 99 Log.i(TAG, "****** Response Started, content length is " 100 + request.getContentLength()); 101 } 102 103 @Override 104 public void onRequestComplete(HttpUrlRequest request) { 105 Log.i(TAG, "****** Request Complete, status code is " 106 + getHttpStatusCode()); 107 Intent intent = new Intent(getApplicationContext(), 108 CronetSampleActivity.class); 109 startActivity(intent); 110 final String url = request.getUrl(); 111 final CharSequence text = "Completed " + request.getUrl() + " (" 112 + request.getHttpStatusCode() + ")"; 113 mHttpStatusCode = request.getHttpStatusCode(); 114 CronetSampleActivity.this.runOnUiThread(new Runnable() { 115 public void run() { 116 mLoading = false; 117 Toast toast = Toast.makeText(getApplicationContext(), text, 118 Toast.LENGTH_SHORT); 119 toast.show(); 120 promptForURL(url); 121 } 122 }); 123 } 124 } 125 126 @Override 127 protected void onCreate(final Bundle savedInstanceState) { 128 super.onCreate(savedInstanceState); 129 130 try { 131 LibraryLoader.ensureInitialized(); 132 } catch (UnsatisfiedLinkError e) { 133 Log.e(TAG, "libcronet_sample initialization failed.", e); 134 finish(); 135 return; 136 } 137 138 mRequestContext = new SampleRequestContext(); 139 HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig(); 140 config.enableHttpCache(HttpUrlRequestFactoryConfig.HttpCache.IN_MEMORY, 141 100 * 1024) 142 .enableSPDY(true) 143 .enableQUIC(true); 144 145 // Override config if it is passed from the launcher. 146 String configString = getCommandLineArg(CONFIG_KEY); 147 if (configString != null) { 148 try { 149 Log.i(TAG, "Using Config: " + configString); 150 config = new HttpUrlRequestFactoryConfig(configString); 151 } catch (org.json.JSONException e) { 152 Log.e(TAG, "Invalid Config.", e); 153 finish(); 154 return; 155 } 156 } 157 158 mRequestFactory = HttpUrlRequestFactory.createFactory( 159 getApplicationContext(), config); 160 161 String appUrl = getUrlFromIntent(getIntent()); 162 if (appUrl == null) { 163 promptForURL("https://"); 164 } else { 165 startWithURL(appUrl); 166 } 167 } 168 169 private void promptForURL(String url) { 170 Log.i(TAG, "No URL provided via intent, prompting user..."); 171 AlertDialog.Builder alert = new AlertDialog.Builder(this); 172 alert.setTitle("Enter a URL"); 173 alert.setMessage("Enter a URL"); 174 final EditText input = new EditText(this); 175 input.setText(url); 176 alert.setView(input); 177 alert.setPositiveButton("Load", new DialogInterface.OnClickListener() { 178 public void onClick(DialogInterface dialog, int button) { 179 String url = input.getText().toString(); 180 startWithURL(url); 181 } 182 }); 183 alert.show(); 184 } 185 186 private static String getUrlFromIntent(Intent intent) { 187 return intent != null ? intent.getDataString() : null; 188 } 189 190 private String getCommandLineArg(String key) { 191 Intent intent = getIntent(); 192 Bundle extras = intent.getExtras(); 193 Log.i(TAG, "Cronet extras: " + extras); 194 if (extras != null) { 195 String[] commandLine = extras.getStringArray(COMMAND_LINE_ARGS_KEY); 196 if (commandLine != null) { 197 for (int i = 0; i < commandLine.length; ++i) { 198 Log.i(TAG, 199 "Cronet commandLine[" + i + "]=" + commandLine[i]); 200 if (commandLine[i].equals(key)) { 201 return commandLine[++i]; 202 } 203 } 204 } 205 } 206 return null; 207 } 208 209 private void applyCommandLineToRequest(UrlRequest request) { 210 String postData = getCommandLineArg(POST_DATA_KEY); 211 if (postData != null) { 212 InputStream dataStream = new ByteArrayInputStream( 213 postData.getBytes()); 214 ReadableByteChannel dataChannel = Channels.newChannel(dataStream); 215 request.setUploadChannel("text/plain", dataChannel); 216 } 217 } 218 219 private void startWithURL(String url) { 220 Log.i(TAG, "Cronet started: " + url); 221 mUrl = url; 222 mLoading = true; 223 224 HashMap<String, String> headers = new HashMap<String, String>(); 225 HttpUrlRequestListener listener = new SampleHttpUrlRequestListener(); 226 227 HttpUrlRequest request = mRequestFactory.createRequest( 228 url, UrlRequestPriority.MEDIUM, headers, listener); 229 request.start(); 230 } 231 232 public void startWithURL_UrlRequest(String url) { 233 Log.i(TAG, "Cronet started: " + url); 234 mUrl = url; 235 mLoading = true; 236 237 HashMap<String, String> headers = new HashMap<String, String>(); 238 WritableByteChannel sink = Channels.newChannel(System.out); 239 UrlRequest request = new SampleRequest(mRequestContext, url, 240 UrlRequestPriority.MEDIUM, headers, sink); 241 applyCommandLineToRequest(request); 242 request.start(); 243 } 244 245 public String getUrl() { 246 return mUrl; 247 } 248 249 public boolean isLoading() { 250 return mLoading; 251 } 252 253 public int getHttpStatusCode() { 254 return mHttpStatusCode; 255 } 256 257 public void startNetLog() { 258 mRequestContext.startNetLogToFile( 259 Environment.getExternalStorageDirectory().getPath() + "/cronet_sample_netlog.json"); 260 } 261 262 public void stopNetLog() { 263 mRequestContext.stopNetLog(); 264 } 265 } 266