Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / android / java / src / org / chromium / net / NetworkChangeNotifier.java
1 // Copyright 2012 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.net;
6
7 import android.content.Context;
8
9 import org.chromium.base.CalledByNative;
10 import org.chromium.base.JNINamespace;
11 import org.chromium.base.NativeClassQualifiedName;
12 import org.chromium.base.ObserverList;
13
14 import java.util.ArrayList;
15
16 /**
17  * Triggers updates to the underlying network state in Chrome.
18  *
19  * By default, connectivity is assumed and changes must pushed from the embedder via the
20  * forceConnectivityState function.
21  * Embedders may choose to have this class auto-detect changes in network connectivity by invoking
22  * the setAutoDetectConnectivityState function.
23  *
24  * WARNING: This class is not thread-safe.
25  */
26 @JNINamespace("net")
27 public class NetworkChangeNotifier {
28     /**
29      * Alerted when the connection type of the network changes.
30      * The alert is fired on the UI thread.
31      */
32     public interface ConnectionTypeObserver {
33         public void onConnectionTypeChanged(int connectionType);
34     }
35
36     // These constants must always match the ones in network_change_notifier.h.
37     public static final int CONNECTION_UNKNOWN = 0;
38     public static final int CONNECTION_ETHERNET = 1;
39     public static final int CONNECTION_WIFI = 2;
40     public static final int CONNECTION_2G = 3;
41     public static final int CONNECTION_3G = 4;
42     public static final int CONNECTION_4G = 5;
43     public static final int CONNECTION_NONE = 6;
44     public static final int CONNECTION_BLUETOOTH = 7;
45
46     private final Context mContext;
47     private final ArrayList<Long> mNativeChangeNotifiers;
48     private final ObserverList<ConnectionTypeObserver> mConnectionTypeObservers;
49     private NetworkChangeNotifierAutoDetect mAutoDetector;
50     private int mCurrentConnectionType = CONNECTION_UNKNOWN;
51
52     private static NetworkChangeNotifier sInstance;
53
54     private NetworkChangeNotifier(Context context) {
55         mContext = context.getApplicationContext();
56         mNativeChangeNotifiers = new ArrayList<Long>();
57         mConnectionTypeObservers = new ObserverList<ConnectionTypeObserver>();
58     }
59
60     /**
61      * Initializes the singleton once.
62      */
63     @CalledByNative
64     public static NetworkChangeNotifier init(Context context) {
65         if (sInstance == null) {
66             sInstance = new NetworkChangeNotifier(context);
67         }
68         return sInstance;
69     }
70
71     public static boolean isInitialized() {
72         return sInstance != null;
73     }
74
75     static void resetInstanceForTests(Context context) {
76         sInstance = new NetworkChangeNotifier(context);
77     }
78
79     @CalledByNative
80     public int getCurrentConnectionType() {
81         return mCurrentConnectionType;
82     }
83
84     /**
85      * Adds a native-side observer.
86      */
87     @CalledByNative
88     public void addNativeObserver(long nativeChangeNotifier) {
89         mNativeChangeNotifiers.add(nativeChangeNotifier);
90     }
91
92     /**
93      * Removes a native-side observer.
94      */
95     @CalledByNative
96     public void removeNativeObserver(long nativeChangeNotifier) {
97         mNativeChangeNotifiers.remove(nativeChangeNotifier);
98     }
99
100     /**
101      * Returns the singleton instance.
102      */
103     public static NetworkChangeNotifier getInstance() {
104         assert sInstance != null;
105         return sInstance;
106     }
107
108     /**
109      * Enables auto detection of the current network state based on notifications from the system.
110      * Note that passing true here requires the embedding app have the platform ACCESS_NETWORK_STATE
111      * permission.
112      *
113      * @param shouldAutoDetect true if the NetworkChangeNotifier should listen for system changes in
114      *    network connectivity.
115      */
116     public static void setAutoDetectConnectivityState(boolean shouldAutoDetect) {
117         getInstance().setAutoDetectConnectivityStateInternal(shouldAutoDetect, false);
118     }
119
120     private void destroyAutoDetector() {
121         if (mAutoDetector != null) {
122             mAutoDetector.destroy();
123             mAutoDetector = null;
124         }
125     }
126
127     /**
128      * Registers to always receive network change notifications no matter if
129      * the app is in the background or foreground.
130      * Note that in normal circumstances, chrome embedders should use
131      * {@code setAutoDetectConnectivityState} to listen to network changes only
132      * when the app is in the foreground, because network change observers
133      * might perform expensive work depending on the network connectivity.
134      */
135     public static void registerToReceiveNotificationsAlways() {
136         getInstance().setAutoDetectConnectivityStateInternal(true, true);
137     }
138
139     private void setAutoDetectConnectivityStateInternal(
140             boolean shouldAutoDetect, boolean alwaysWatchForChanges) {
141         if (shouldAutoDetect) {
142             if (mAutoDetector == null) {
143                 mAutoDetector = new NetworkChangeNotifierAutoDetect(
144                     new NetworkChangeNotifierAutoDetect.Observer() {
145                         @Override
146                         public void onConnectionTypeChanged(int newConnectionType) {
147                             updateCurrentConnectionType(newConnectionType);
148                         }
149                     },
150                     mContext,
151                     alwaysWatchForChanges);
152                 updateCurrentConnectionType(mAutoDetector.getCurrentConnectionType());
153             }
154         } else {
155             destroyAutoDetector();
156         }
157     }
158
159     /**
160      * Updates the perceived network state when not auto-detecting changes to connectivity.
161      *
162      * @param networkAvailable True if the NetworkChangeNotifier should perceive a "connected"
163      *    state, false implies "disconnected".
164      */
165     @CalledByNative
166     public static void forceConnectivityState(boolean networkAvailable) {
167         setAutoDetectConnectivityState(false);
168         getInstance().forceConnectivityStateInternal(networkAvailable);
169     }
170
171     private void forceConnectivityStateInternal(boolean forceOnline) {
172         boolean connectionCurrentlyExists = mCurrentConnectionType != CONNECTION_NONE;
173         if (connectionCurrentlyExists != forceOnline) {
174             updateCurrentConnectionType(forceOnline ? CONNECTION_UNKNOWN : CONNECTION_NONE);
175         }
176     }
177
178     private void updateCurrentConnectionType(int newConnectionType) {
179         mCurrentConnectionType = newConnectionType;
180         notifyObserversOfConnectionTypeChange(newConnectionType);
181     }
182
183     /**
184      * Alerts all observers of a connection change.
185      */
186     void notifyObserversOfConnectionTypeChange(int newConnectionType) {
187         for (Long nativeChangeNotifier : mNativeChangeNotifiers) {
188             nativeNotifyConnectionTypeChanged(nativeChangeNotifier, newConnectionType);
189         }
190         for (ConnectionTypeObserver observer : mConnectionTypeObservers) {
191             observer.onConnectionTypeChanged(newConnectionType);
192         }
193     }
194
195     /**
196      * Adds an observer for any connection type changes.
197      */
198     public static void addConnectionTypeObserver(ConnectionTypeObserver observer) {
199         getInstance().addConnectionTypeObserverInternal(observer);
200     }
201
202     private void addConnectionTypeObserverInternal(ConnectionTypeObserver observer) {
203         mConnectionTypeObservers.addObserver(observer);
204     }
205
206     /**
207      * Removes an observer for any connection type changes.
208      */
209     public static void removeConnectionTypeObserver(ConnectionTypeObserver observer) {
210         getInstance().removeConnectionTypeObserverInternal(observer);
211     }
212
213     private void removeConnectionTypeObserverInternal(ConnectionTypeObserver observer) {
214         mConnectionTypeObservers.removeObserver(observer);
215     }
216
217     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
218     private native void nativeNotifyConnectionTypeChanged(long nativePtr, int newConnectionType);
219
220     // For testing only.
221     public static NetworkChangeNotifierAutoDetect getAutoDetectorForTest() {
222         return getInstance().mAutoDetector;
223     }
224
225     /**
226      * Checks if there currently is connectivity.
227      */
228     public static boolean isOnline() {
229         int connectionType = getInstance().getCurrentConnectionType();
230         return connectionType != CONNECTION_UNKNOWN && connectionType != CONNECTION_NONE;
231     }
232 }