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

Side by Side Diff: remoting/android/java/src/org/chromium/chromoting/Chromoting.java

Issue 102273006: Refactor Chromoting.java to pull out some nested classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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.chromoting; 5 package org.chromium.chromoting;
6 6
7 import android.accounts.Account; 7 import android.accounts.Account;
8 import android.accounts.AccountManager; 8 import android.accounts.AccountManager;
9 import android.accounts.AccountManagerCallback; 9 import android.accounts.AccountManagerCallback;
10 import android.accounts.AccountManagerFuture; 10 import android.accounts.AccountManagerFuture;
11 import android.accounts.AuthenticatorException; 11 import android.accounts.AuthenticatorException;
12 import android.accounts.OperationCanceledException; 12 import android.accounts.OperationCanceledException;
13 import android.app.Activity; 13 import android.app.Activity;
14 import android.content.Context;
15 import android.content.Intent; 14 import android.content.Intent;
16 import android.content.SharedPreferences; 15 import android.content.SharedPreferences;
17 import android.os.Bundle; 16 import android.os.Bundle;
18 import android.os.Handler; 17 import android.os.Handler;
19 import android.os.HandlerThread; 18 import android.os.HandlerThread;
20 import android.text.Html; 19 import android.text.Html;
21 import android.util.Log; 20 import android.util.Log;
22 import android.view.Menu; 21 import android.view.Menu;
23 import android.view.MenuItem; 22 import android.view.MenuItem;
24 import android.view.View; 23 import android.view.View;
(...skipping 22 matching lines...) Expand all
47 private static final String ACCOUNT_TYPE = "com.google"; 46 private static final String ACCOUNT_TYPE = "com.google";
48 47
49 /** Scopes at which the authentication token we request will be valid. */ 48 /** Scopes at which the authentication token we request will be valid. */
50 private static final String TOKEN_SCOPE = "oauth2:https://www.googleapis.com /auth/chromoting " + 49 private static final String TOKEN_SCOPE = "oauth2:https://www.googleapis.com /auth/chromoting " +
51 "https://www.googleapis.com/auth/googletalk"; 50 "https://www.googleapis.com/auth/googletalk";
52 51
53 /** Path from which to download a user's host list JSON object. */ 52 /** Path from which to download a user's host list JSON object. */
54 private static final String HOST_LIST_PATH = 53 private static final String HOST_LIST_PATH =
55 "https://www.googleapis.com/chromoting/v1/@me/hosts?key="; 54 "https://www.googleapis.com/chromoting/v1/@me/hosts?key=";
56 55
57 /** Color to use for hosts that are online. */ 56 /** Lock to protect |mAccount| and |mToken|. */
58 private static final String HOST_COLOR_ONLINE = "green"; 57 // TODO(lambroslambrou): |mHosts| needs to be protected as well.
59 58 private Object mLock = new Object();
60 /** Color to use for hosts that are offline. */
61 private static final String HOST_COLOR_OFFLINE = "red";
62 59
63 /** User's account details. */ 60 /** User's account details. */
64 private Account mAccount; 61 private Account mAccount;
65 62
66 /** Account auth token. */ 63 /** Account auth token. */
67 private String mToken; 64 private String mToken;
68 65
69 /** List of hosts. */ 66 /** List of hosts. */
70 private JSONArray mHosts; 67 private JSONArray mHosts;
71 68
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 } 178 }
182 else { 179 else {
183 // The refresh button simply makes use of the currently-chosen accou nt. 180 // The refresh button simply makes use of the currently-chosen accou nt.
184 AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, t his, 181 AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, t his,
185 new HostListDirectoryGrabber(this), mNetwork); 182 new HostListDirectoryGrabber(this), mNetwork);
186 } 183 }
187 184
188 return true; 185 return true;
189 } 186 }
190 187
188 /** Called when the user taps on a host entry. */
189 public void connectToHost(JSONObject host) {
190 try {
191 synchronized (mLock) {
192 JniInterface.connectToHost(mAccount.name, mToken, host.getString ("jabberId"),
193 host.getString("hostId"), host.getString("publicKey"),
194 new Runnable() {
195 @Override
196 public void run() {
197 startActivity(new Intent(Chromoting.this, De sktop.class));
198 }
199 });
200 }
201 } catch (JSONException ex) {
202 Log.w("host", ex);
203 Toast.makeText(this, getString(R.string.error_reading_host),
204 Toast.LENGTH_LONG).show();
205 // Close the application.
206 finish();
207 }
208 }
209
191 /** 210 /**
192 * Processes the authentication token once the system provides it. Once in p ossession of such a 211 * Processes the authentication token once the system provides it. Once in p ossession of such a
193 * token, attempts to request a host list from the directory server. In case of a bad response, 212 * token, attempts to request a host list from the directory server. In case of a bad response,
194 * this is retried once in case the system's cached auth token had expired. 213 * this is retried once in case the system's cached auth token had expired.
195 */ 214 */
196 private class HostListDirectoryGrabber implements AccountManagerCallback<Bun dle> { 215 private class HostListDirectoryGrabber implements AccountManagerCallback<Bun dle> {
197 /** Whether authentication has already been attempted. */ 216 /** Whether authentication has already been attempted. */
198 private boolean mAlreadyTried; 217 private boolean mAlreadyTried;
199 218
200 /** Communication with the screen. */ 219 /** Communication with the screen. */
(...skipping 13 matching lines...) Expand all
214 public void run(AccountManagerFuture<Bundle> future) { 233 public void run(AccountManagerFuture<Bundle> future) {
215 Log.i("auth", "User finished with auth dialogs"); 234 Log.i("auth", "User finished with auth dialogs");
216 try { 235 try {
217 // Here comes our auth token from the Android system. 236 // Here comes our auth token from the Android system.
218 Bundle result = future.getResult(); 237 Bundle result = future.getResult();
219 String accountName = result.getString(AccountManager.KEY_ACCOUNT _NAME); 238 String accountName = result.getString(AccountManager.KEY_ACCOUNT _NAME);
220 String accountType = result.getString(AccountManager.KEY_ACCOUNT _TYPE); 239 String accountType = result.getString(AccountManager.KEY_ACCOUNT _TYPE);
221 String authToken = result.getString(AccountManager.KEY_AUTHTOKEN ); 240 String authToken = result.getString(AccountManager.KEY_AUTHTOKEN );
222 Log.i("auth", "Received an auth token from system"); 241 Log.i("auth", "Received an auth token from system");
223 242
224 synchronized (mUi) { 243 synchronized (mLock) {
225 mAccount = new Account(accountName, accountType); 244 mAccount = new Account(accountName, accountType);
226 mToken = authToken; 245 mToken = authToken;
227 getPreferences(MODE_PRIVATE).edit().putString("account_name" , accountName). 246 getPreferences(MODE_PRIVATE).edit().putString("account_name" , accountName).
228 putString("account_type", accountType).apply(); 247 putString("account_type", accountType).apply();
229 } 248 }
230 249
231 // Send our HTTP request to the directory server. 250 // Send our HTTP request to the directory server.
232 URLConnection link = 251 URLConnection link =
233 new URL(HOST_LIST_PATH + JniInterface.nativeGetApiKey()) .openConnection(); 252 new URL(HOST_LIST_PATH + JniInterface.nativeGetApiKey()) .openConnection();
234 link.addRequestProperty("client_id", JniInterface.nativeGetClien tId()); 253 link.addRequestProperty("client_id", JniInterface.nativeGetClien tId());
(...skipping 20 matching lines...) Expand all
255 // Assemble error message to display to the user. 274 // Assemble error message to display to the user.
256 String explanation = getString(R.string.error_unknown); 275 String explanation = getString(R.string.error_unknown);
257 if (ex instanceof OperationCanceledException) { 276 if (ex instanceof OperationCanceledException) {
258 explanation = getString(R.string.error_auth_canceled); 277 explanation = getString(R.string.error_auth_canceled);
259 } else if (ex instanceof AuthenticatorException) { 278 } else if (ex instanceof AuthenticatorException) {
260 explanation = getString(R.string.error_no_accounts); 279 explanation = getString(R.string.error_no_accounts);
261 } else if (ex instanceof IOException) { 280 } else if (ex instanceof IOException) {
262 if (!mAlreadyTried) { 281 if (!mAlreadyTried) {
263 // This was our first connection attempt. 282 // This was our first connection attempt.
264 283
265 synchronized (mUi) { 284 synchronized (mLock) {
266 if (mAccount != null) { 285 if (mAccount != null) {
267 // We got an account, but couldn't log into it. We'll retry in case 286 // We got an account, but couldn't log into it. We'll retry in case
268 // the system's cached authentication token had already expired. 287 // the system's cached authentication token had already expired.
269 AccountManager authenticator = AccountManager.ge t(mUi); 288 AccountManager authenticator = AccountManager.ge t(mUi);
270 mAlreadyTried = true; 289 mAlreadyTried = true;
271 290
272 Log.w("auth", "Requesting renewal of rejected au th token"); 291 Log.w("auth", "Requesting renewal of rejected au th token");
273 authenticator.invalidateAuthToken(mAccount.type, mToken); 292 authenticator.invalidateAuthToken(mAccount.type, mToken);
274 mToken = null; 293 mToken = null;
275 authenticator.getAuthToken( 294 authenticator.getAuthToken(
276 mAccount, TOKEN_SCOPE, null, mUi, this, mNetwork); 295 mAccount, TOKEN_SCOPE, null, mUi, this, mNetwork);
277 296
278 // We're not in an error state *yet*. 297 // We're not in an error state *yet*.
279 return; 298 return;
280 } 299 }
281 } 300 }
282 301
283 // We didn't even get an account, so the auth server is likely unreachable. 302 // We didn't even get an account, so the auth server is likely unreachable.
284 explanation = getString(R.string.error_bad_connection); 303 explanation = getString(R.string.error_bad_connection);
285 } else { 304 } else {
286 // Authentication truly failed. 305 // Authentication truly failed.
287 Log.e("auth", "Fresh auth token was also rejected"); 306 Log.e("auth", "Fresh auth token was also rejected");
288 explanation = getString(R.string.error_auth_failed); 307 explanation = getString(R.string.error_auth_failed);
289 } 308 }
290 } else if (ex instanceof JSONException) { 309 } else if (ex instanceof JSONException) {
291 explanation = getString(R.string.error_unexpected_response); 310 explanation = getString(R.string.error_unexpected_response);
292 runOnUiThread(new HostListDisplayer(mUi));
293 } 311 }
294 312
295 mHosts = null; 313 mHosts = null;
296 Log.w("auth", ex); 314 Log.w("auth", ex);
297 Toast.makeText(mUi, explanation, Toast.LENGTH_LONG).show(); 315 Toast.makeText(mUi, explanation, Toast.LENGTH_LONG).show();
298 } 316 }
299 317
300 // Share our findings with the user. 318 // Share our findings with the user.
301 runOnUiThread(new HostListDisplayer(mUi)); 319 runOnUiThread(new Runnable() {
320 @Override
321 public void run() {
322 updateUi();
323 }
324 });
302 } 325 }
303 } 326 }
304 327
305 /** Formats the host list and offers it to the user. */ 328 /**
306 private class HostListDisplayer implements Runnable { 329 * Updates the infotext and host list display.
307 /** Communication with the screen. */ 330 * This method affects the UI and must be run on the main thread.
308 private Activity mUi; 331 */
309 332 private void updateUi() {
310 /** Constructor. */ 333 synchronized (mLock) {
311 public HostListDisplayer(Activity ui) { 334 mRefreshButton.setEnabled(mAccount != null);
312 mUi = ui; 335 if (mAccount != null) {
336 mAccountSwitcher.setTitle(mAccount.name);
337 }
313 } 338 }
314 339
315 /** 340 if (mHosts == null) {
316 * Updates the infotext and host list display. 341 mGreeting.setText(getString(R.string.inst_empty_list));
317 * This method affects the UI and must be run on its same thread. 342 mList.setAdapter(null);
318 */ 343 return;
319 @Override
320 public void run() {
321 synchronized (mUi) {
322 mRefreshButton.setEnabled(mAccount != null);
323 if (mAccount != null) {
324 mAccountSwitcher.setTitle(mAccount.name);
325 }
326 }
327
328 if (mHosts == null) {
329 mGreeting.setText(getString(R.string.inst_empty_list));
330 mList.setAdapter(null);
331 return;
332 }
333
334 mGreeting.setText(getString(R.string.inst_host_list));
335
336 ArrayAdapter<JSONObject> displayer = new HostListAdapter(mUi, R.layo ut.host);
337 Log.i("hostlist", "About to populate host list display");
338 try {
339 int index = 0;
340 while (!mHosts.isNull(index)) {
341 displayer.add(mHosts.getJSONObject(index));
342 ++index;
343 }
344 mList.setAdapter(displayer);
345 }
346 catch(JSONException ex) {
347 Log.w("hostlist", ex);
348 Toast.makeText(
349 mUi, getString(R.string.error_cataloging_hosts), Toast.L ENGTH_LONG).show();
350
351 // Close the application.
352 finish();
353 }
354 }
355 }
356
357 /** Describes the appearance and behavior of each host list entry. */
358 private class HostListAdapter extends ArrayAdapter<JSONObject> {
359 /** Constructor. */
360 public HostListAdapter(Context context, int textViewResourceId) {
361 super(context, textViewResourceId);
362 } 344 }
363 345
364 /** Generates a View corresponding to this particular host. */ 346 mGreeting.setText(getString(R.string.inst_host_list));
365 @Override
366 public View getView(int position, View convertView, ViewGroup parent) {
367 TextView target = (TextView)super.getView(position, convertView, par ent);
368 347
369 try { 348 ArrayAdapter<JSONObject> displayer = new HostListAdapter(this, R.layout. host);
370 final JSONObject host = getItem(position); 349 Log.i("hostlist", "About to populate host list display");
371 target.setText(Html.fromHtml(host.getString("hostName") + " (<fo nt color = \"" + 350 try {
372 (host.getString("status").equals("ONLINE") ? HOST_COLOR_ ONLINE : 351 int index = 0;
373 HOST_COLOR_OFFLINE) + "\">" + host.getString("status") + "</font>)")); 352 while (!mHosts.isNull(index)) {
353 displayer.add(mHosts.getJSONObject(index));
354 ++index;
355 }
356 mList.setAdapter(displayer);
357 } catch (JSONException ex) {
358 Log.w("hostlist", ex);
359 Toast.makeText(this, getString(R.string.error_cataloging_hosts),
360 Toast.LENGTH_LONG).show();
374 361
375 if (host.getString("status").equals("ONLINE")) { // Host is onl ine. 362 // Close the application.
376 target.setOnClickListener(new View.OnClickListener() { 363 finish();
377 @Override
378 public void onClick(View v) {
379 try {
380 synchronized (getContext()) {
381 JniInterface.connectToHost(mAccount.name , mToken,
382 host.getString("jabberId"),
383 host.getString("hostId"),
384 host.getString("publicKey"),
385 new Runnable() {
386 @Override
387 public void run() {
388 startActivity(
389 new Intent(getContext(), Desktop.class));
390 }
391 });
392 }
393 }
394 catch(JSONException ex) {
395 Log.w("host", ex);
396 Toast.makeText(getContext(),
397 getString(R.string.error_reading_hos t),
398 Toast.LENGTH_LONG).show();
399
400 // Close the application.
401 finish();
402 }
403 }
404 });
405 } else { // Host is offline.
406 // Disallow interaction with this entry.
407 target.setEnabled(false);
408 }
409 }
410 catch(JSONException ex) {
411 Log.w("hostlist", ex);
412 Toast.makeText(getContext(),
413 getString(R.string.error_displaying_host),
414 Toast.LENGTH_LONG).show();
415
416 // Close the application.
417 finish();
418 }
419
420 return target;
421 } 364 }
422 } 365 }
423 } 366 }
367
368 /** Describes the appearance and behavior of each host list entry. */
369 class HostListAdapter extends ArrayAdapter<JSONObject> {
Sergey Ulanov 2013/12/21 02:15:28 Does this compile? I think you need to put it to a
Lambros 2013/12/26 19:29:46 It's legal according to: http://docs.oracle.com/ja
Sergey Ulanov 2013/12/26 20:03:48 This isn't really a Pimple (pimple = Private IMPLE
Lambros 2013/12/27 01:56:54 OK, done!
370 /** Color to use for hosts that are online. */
371 private static final String HOST_COLOR_ONLINE = "green";
372
373 /** Color to use for hosts that are offline. */
374 private static final String HOST_COLOR_OFFLINE = "red";
375
376 private Chromoting mChromoting;
377
378 /** Constructor. */
379 public HostListAdapter(Chromoting chromoting, int textViewResourceId) {
380 super(chromoting, textViewResourceId);
381 mChromoting = chromoting;
382 }
383
384 /** Generates a View corresponding to this particular host. */
385 @Override
386 public View getView(int position, View convertView, ViewGroup parent) {
387 TextView target = (TextView)super.getView(position, convertView, parent) ;
388
389 try {
390 final JSONObject host = getItem(position);
391 String status = host.getString("status");
392 boolean online = status.equals("ONLINE");
393 target.setText(Html.fromHtml(host.getString("hostName") + " (<font c olor = \"" +
394 (online ? HOST_COLOR_ONLINE : HOST_COLOR_OFFLINE) + "\">" + status +
395 "</font>)"));
396
397 if (online) {
398 target.setOnClickListener(new View.OnClickListener() {
399 @Override
400 public void onClick(View v) {
401 mChromoting.connectToHost(host);
402 }
403 });
404 } else {
405 // Disallow interaction with this entry.
406 target.setEnabled(false);
407 }
408 } catch (JSONException ex) {
409 Log.w("hostlist", ex);
410 Toast.makeText(mChromoting, mChromoting.getString(R.string.error_dis playing_host),
411 Toast.LENGTH_LONG).show();
412
413 // Close the application.
414 mChromoting.finish();
415 }
416
417 return target;
418 }
419 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698