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

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

Issue 157013002: Pull HostListDirectoryGrabber out to a separate class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add Host class and address comments Created 6 years, 10 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.chromoting;
6
7 import android.os.Handler;
8 import android.os.HandlerThread;
9 import android.os.Looper;
10 import android.util.Log;
11
12 import org.chromium.chromoting.jni.JniInterface;
13 import org.json.JSONArray;
14 import org.json.JSONException;
15 import org.json.JSONObject;
16
17 import java.io.IOException;
18 import java.net.HttpURLConnection;
19 import java.net.MalformedURLException;
20 import java.net.URL;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.Scanner;
25
26 /** Helper for fetching the host list. */
27 public class HostListLoader {
28 public enum Error {
29 AUTH_FAILED,
30 NETWORK_ERROR,
31 SERVICE_UNAVAILABLE,
32 UNEXPECTED_RESPONSE,
33 UNKNOWN,
34 }
35
36 /** Callback for receiving the host list, or getting notified of an error. * /
37 public interface Callback {
38 void onHostListReceived(Host[] hosts);
39 void onError(Error error);
40 }
41
42 /** Path from which to download a user's host list JSON object. */
43 private static final String HOST_LIST_PATH =
44 "https://www.googleapis.com/chromoting/v1/@me/hosts?key=";
45
46 /** Callback handler to be used for network operations. */
47 private Handler mNetworkThread;
48
49 /** Handler for main thread. */
50 private Handler mMainThread;
51
52 public HostListLoader() {
53 // Thread responsible for downloading the host list.
54 HandlerThread thread = new HandlerThread("network");
55 thread.start();
56 mNetworkThread = new Handler(thread.getLooper());
57
58 mMainThread = new Handler(Looper.getMainLooper());
59 }
60
61 /**
62 * Causes the host list to be fetched on a background thread. This should b e called on the
63 * main thread, and callbacks will also be invoked on the main thread. On s uccess,
64 * callback.onHostListReceived() will be called, otherwise callback.onError () will be called
65 * with an error-code describing the failure.
66 */
67 public void retrieveHostList(String authToken, Callback callback) {
68 final String authTokenFinal = authToken;
69 final Callback callbackFinal = callback;
70 mNetworkThread.post(new Runnable() {
71 @Override
72 public void run() {
73 doRetrieveHostList(authTokenFinal, callbackFinal);
74 }
75 });
76 }
77
78 private void doRetrieveHostList(String authToken, Callback callback) {
79 HttpURLConnection link = null;
80 try {
81 link = (HttpURLConnection)
82 new URL(HOST_LIST_PATH + JniInterface.nativeGetApiKey()).ope nConnection();
83 link.addRequestProperty("client_id", JniInterface.nativeGetClientId( ));
84 link.addRequestProperty("client_secret", JniInterface.nativeGetClien tSecret());
85 link.setRequestProperty("Authorization", "OAuth " + authToken);
86
87 // Listen for the server to respond.
88 int status = link.getResponseCode();
89 switch (status) {
90 case HttpURLConnection.HTTP_OK: // 200
91 break;
92 case HttpURLConnection.HTTP_UNAUTHORIZED: // 401
93 postError(callback, Error.AUTH_FAILED);
94 return;
95 case HttpURLConnection.HTTP_BAD_GATEWAY: // 502
96 case HttpURLConnection.HTTP_UNAVAILABLE: // 503
97 postError(callback, Error.SERVICE_UNAVAILABLE);
98 return;
99 default:
100 postError(callback, Error.UNKNOWN);
101 return;
102 }
103
104 StringBuilder response = new StringBuilder();
105 Scanner incoming = new Scanner(link.getInputStream());
106 Log.i("auth", "Successfully authenticated to directory server");
107 while (incoming.hasNext()) {
108 response.append(incoming.nextLine());
109 }
110 incoming.close();
111
112 // Interpret what the directory server told us.
Sergey Ulanov 2014/02/14 08:55:20 suggest rewording: "Parse directory response"
Lambros 2014/02/15 01:40:21 Done.
113 JSONObject data = new JSONObject(String.valueOf(response)).getJSONOb ject("data");
114 JSONArray hostsJson = data.getJSONArray("items");
115 Log.i("hostlist", "Received host listing from directory server");
116
117 int index = 0;
118 ArrayList<Host> hostList = new ArrayList<Host>();
119 while (!hostsJson.isNull(index)) {
120 JSONObject hostJson = hostsJson.getJSONObject(index);
121 Host host = new Host();
122 host.name = hostJson.getString("hostName");
123 host.id = hostJson.getString("hostId");
124 host.jabberId = hostJson.getString("jabberId");
Sergey Ulanov 2014/02/14 08:55:20 jabberId may not be set when the host was just reg
Lambros 2014/02/15 01:40:21 Done.
125 host.publicKey = hostJson.getString("publicKey");
126 host.isOnline = hostJson.getString("status").equals("ONLINE");
127 hostList.add(host);
128 ++index;
129 }
130
131 sortHosts(hostList);
Sergey Ulanov 2014/02/14 08:55:20 Sorting should be UI feature. Move this to HostLis
Sergey Ulanov 2014/02/14 08:55:20 This and code below it doesn't need to be in try-c
Lambros 2014/02/15 01:40:21 This was already decided in the CL here: https://c
Lambros 2014/02/15 01:40:21 Done.
132
133 final Callback callbackFinal = callback;
134 final Host[] hosts = hostList.toArray(new Host[hostList.size()]);
135 mMainThread.post(new Runnable() {
136 @Override
137 public void run() {
138 callbackFinal.onHostListReceived(hosts);
139 }
140 });
141 } catch (MalformedURLException ex) {
142 // This should never happen.
143 Log.e("hostlist", "Unexpected error while fetching host list: " + ex );
Sergey Ulanov 2014/02/14 08:55:20 Throw RuntimeException?
Lambros 2014/02/15 01:40:21 Done.
144 } catch (JSONException ex) {
Sergey Ulanov 2014/02/14 08:55:20 I suggest having two separate try-catch block. One
Lambros 2014/02/15 01:40:21 Done.
145 postError(callback, Error.UNEXPECTED_RESPONSE);
146 } catch (IOException ex) {
147 postError(callback, Error.NETWORK_ERROR);
148 } finally {
149 if (link != null) {
150 link.disconnect();
151 }
152 }
153 }
154
155 /** Posts error to callback on main thread. */
156 private void postError(Callback callback, Error error) {
157 final Callback callbackFinal = callback;
158 final Error errorFinal = error;
159 mMainThread.post(new Runnable() {
160 @Override
161 public void run() {
162 callbackFinal.onError(errorFinal);
163 }
164 });
165 }
166
167 private static void sortHosts(ArrayList<Host> hosts) {
168 Comparator<Host> compareHosts = new Comparator<Host>() {
Sergey Ulanov 2014/02/14 08:55:20 nit: hostComparator
Lambros 2014/02/15 01:40:21 Done.
169 public int compare(Host a, Host b) {
170 if (a.isOnline != b.isOnline) {
171 return a.isOnline ? -1 : 1;
172 }
173 String aName = a.name.toUpperCase();
174 String bName = b.name.toUpperCase();
175 return aName.compareTo(bName);
176 }
177 };
178 Collections.sort(hosts, compareHosts);
179 }
180 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698