Add navigator.networkType to allow apps to detect the connection type.
The online event is fired when the networkType changes.

Bug: 2368650
diff --git a/WebCore/Android.derived.jscbindings.mk b/WebCore/Android.derived.jscbindings.mk
index d7ca0a4..cc7ba28 100644
--- a/WebCore/Android.derived.jscbindings.mk
+++ b/WebCore/Android.derived.jscbindings.mk
@@ -289,6 +289,7 @@
 # page
 GEN := \
     $(intermediates)/page/JSBarInfo.h \
+    $(intermediates)/page/JSConnection.h \
     $(intermediates)/page/JSConsole.h \
     $(intermediates)/page/JSCoordinates.h \
     $(intermediates)/page/JSDOMSelection.h \
diff --git a/WebCore/Android.derived.v8bindings.mk b/WebCore/Android.derived.v8bindings.mk
index a9f403a..e3bd4ca 100644
--- a/WebCore/Android.derived.v8bindings.mk
+++ b/WebCore/Android.derived.v8bindings.mk
@@ -281,6 +281,7 @@
 # page
 GEN := \
     $(intermediates)/bindings/V8BarInfo.h \
+    $(intermediates)/bindings/V8Connection.h \
     $(intermediates)/bindings/V8Console.h \
     $(intermediates)/bindings/V8Coordinates.h \
     $(intermediates)/bindings/V8DOMSelection.h \
diff --git a/WebCore/Android.mk b/WebCore/Android.mk
index d5bc740..19e3fd2 100644
--- a/WebCore/Android.mk
+++ b/WebCore/Android.mk
@@ -326,6 +326,7 @@
 	\
 	page/BarInfo.cpp \
 	page/Chrome.cpp \
+	page/Connection.cpp \
 	page/Console.cpp \
 	page/ContextMenuController.cpp \
 	page/DOMSelection.cpp \
diff --git a/WebCore/bindings/v8/DOMObjectsInclude.h b/WebCore/bindings/v8/DOMObjectsInclude.h
index 6ed14be..bded7f2 100644
--- a/WebCore/bindings/v8/DOMObjectsInclude.h
+++ b/WebCore/bindings/v8/DOMObjectsInclude.h
@@ -229,6 +229,7 @@
 #endif // SVG
 
 #if PLATFORM(ANDROID)
+#include "Connection.h"
 // TODO: Upstream TOUCH_EVENTS guard.
 #if ENABLE(TOUCH_EVENTS)
 #include "Touch.h"
diff --git a/WebCore/bindings/v8/V8Index.cpp b/WebCore/bindings/v8/V8Index.cpp
index 9686dc6..ea13d2f 100644
--- a/WebCore/bindings/v8/V8Index.cpp
+++ b/WebCore/bindings/v8/V8Index.cpp
@@ -447,6 +447,7 @@
 #include "V8PositionError.h"
 
 #if PLATFORM(ANDROID)
+#include "V8Connection.h"
 // TODO: Upstream these guards to webkit.org
 #if ENABLE(TOUCH_EVENTS)
 #include "V8Touch.h"
diff --git a/WebCore/bindings/v8/V8Index.h b/WebCore/bindings/v8/V8Index.h
index d786aab..a3aebdf 100644
--- a/WebCore/bindings/v8/V8Index.h
+++ b/WebCore/bindings/v8/V8Index.h
@@ -512,6 +512,8 @@
 #else
 #define DOM_OBJECT_TOUCH_EVENT_TYPES(V)
 #endif
+#define DOM_OBJECT_CONNECTION_TYPES(V)                                  \
+    V(CONNECTION, Connection)
 #endif
 
 #if PLATFORM(ANDROID)
@@ -535,6 +537,7 @@
     DOM_OBJECT_INSPECTOR_TYPES(V)                                       \
     DOM_OBJECT_GEOLOCATION_TYPES(V)                                     \
     DOM_OBJECT_TOUCH_EVENT_TYPES(V)                                     \
+    DOM_OBJECT_CONNECTION_TYPES(V)                                      \
     DOM_OBJECT_VOIDCALLBACK_TYPES(V)
 #endif
 
diff --git a/WebCore/page/Connection.cpp b/WebCore/page/Connection.cpp
new file mode 100644
index 0000000..ffbb838
--- /dev/null
+++ b/WebCore/page/Connection.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "Connection.h"
+
+#include "NetworkStateNotifier.h"
+
+namespace WebCore {
+
+Connection::ConnectionType Connection::type() const
+{
+    return networkStateNotifier().type();
+}
+
+};
\ No newline at end of file
diff --git a/WebCore/page/Connection.h b/WebCore/page/Connection.h
new file mode 100644
index 0000000..837a36f
--- /dev/null
+++ b/WebCore/page/Connection.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Connection_h
+#define Connection_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Connection : public RefCounted<Connection> {
+public:
+    enum ConnectionType {
+        Unknown = 0,
+        Ethernet = 1,
+        WiFi = 2,
+        Cell_2G = 3,
+        Cell_3G = 4,
+    };
+
+    static PassRefPtr<Connection> create() { return adoptRef(new Connection()); }
+
+    ConnectionType type() const;
+
+private:
+    Connection() { }
+};
+
+} // namespace WebCore
+
+#endif // Connection_h
diff --git a/WebCore/page/Connection.idl b/WebCore/page/Connection.idl
new file mode 100644
index 0000000..b4cfbd1
--- /dev/null
+++ b/WebCore/page/Connection.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ module core {
+
+    interface Connection {
+        readonly attribute unsigned short type;
+
+        const unsigned short UNKNOWN = 0;
+        const unsigned short ETHERNET = 1;
+        const unsigned short WIFI = 2;
+        const unsigned short CELL_2G = 3;
+        const unsigned short CELL_3G = 4;
+    };
+
+}
diff --git a/WebCore/page/Navigator.cpp b/WebCore/page/Navigator.cpp
index a4193fc..8563a0e 100644
--- a/WebCore/page/Navigator.cpp
+++ b/WebCore/page/Navigator.cpp
@@ -24,6 +24,9 @@
 #include "Navigator.h"
 
 #include "CookieJar.h"
+#if PLATFORM(ANDROID)
+#include "Connection.h"
+#endif
 #include "ExceptionCode.h"
 #include "Frame.h"
 #include "FrameLoader.h"
@@ -155,6 +158,15 @@
     return m_geolocation.get();
 }
 
+#if PLATFORM(ANDROID)
+Connection* Navigator::connection() const
+{
+    if (!m_connection)
+        m_connection = Connection::create();
+    return m_connection.get();
+}
+#endif
+
 #if ENABLE(DOM_STORAGE)
 void Navigator::getStorageUpdates()
 {
diff --git a/WebCore/page/Navigator.h b/WebCore/page/Navigator.h
index 107082b..9967fba 100644
--- a/WebCore/page/Navigator.h
+++ b/WebCore/page/Navigator.h
@@ -27,6 +27,9 @@
 
 namespace WebCore {
 
+#if PLATFORM(ANDROID)
+    class Connection;
+#endif
     class Frame;
     class Geolocation;
     class MimeTypeArray;
@@ -57,6 +60,10 @@
         // This is used for GC marking.
         Geolocation* optionalGeolocation() const { return m_geolocation.get(); }
 
+#if PLATFORM(ANDROID)
+        Connection* connection() const;
+#endif
+
 #if ENABLE(DOM_STORAGE)
         // Relinquishes the storage lock, if one exists.
         void getStorageUpdates();
@@ -71,6 +78,9 @@
         mutable RefPtr<PluginArray> m_plugins;
         mutable RefPtr<MimeTypeArray> m_mimeTypes;
         mutable RefPtr<Geolocation> m_geolocation;
+#if PLATFORM(ANDROID)
+        mutable RefPtr<Connection> m_connection;
+#endif
     };
 
 }
diff --git a/WebCore/page/Navigator.idl b/WebCore/page/Navigator.idl
index 99b22af..f3079de 100644
--- a/WebCore/page/Navigator.idl
+++ b/WebCore/page/Navigator.idl
@@ -39,6 +39,9 @@
         
         readonly attribute boolean onLine;
 
+        // ANDROID-only for now, upstreaming in progress.
+        readonly attribute Connection connection;
+
 #if defined(ENABLE_GEOLOCATION) && ENABLE_GEOLOCATION
         readonly attribute Geolocation geolocation;
 #endif
diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h
index 570ced0..d0463d4 100644
--- a/WebCore/platform/network/NetworkStateNotifier.h
+++ b/WebCore/platform/network/NetworkStateNotifier.h
@@ -27,6 +27,9 @@
 #define NetworkStateNotifier_h
 
 #include <wtf/Noncopyable.h>
+#if PLATFORM(ANDROID)
+#include "Connection.h"
+#endif
 
 #if PLATFORM(MAC)
 
@@ -54,9 +57,15 @@
     void setNetworkStateChangedFunction(void (*)());
     
     bool onLine() const { return m_isOnLine; }
+#if PLATFORM(ANDROID)
+    Connection::ConnectionType type() const { return m_type; }
+#endif
     
 private:    
     bool m_isOnLine;
+#if PLATFORM(ANDROID)
+    Connection::ConnectionType m_type;
+#endif
     void (*m_networkStateChangedFunction)();
 
     void updateState();
@@ -84,6 +93,7 @@
 #elif PLATFORM(ANDROID)
 public:
     void networkStateChange(bool online);
+    void networkTypeChange(Connection::ConnectionType type);
 #endif
 };
 
@@ -91,6 +101,9 @@
 
 inline NetworkStateNotifier::NetworkStateNotifier()
     : m_isOnLine(true)
+#if PLATFORM(ANDROID)
+    , m_type(Connection::Unknown)
+#endif
     , m_networkStateChangedFunction(0)
 {    
 }
diff --git a/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp b/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp
index 3aa5578..134e206 100644
--- a/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp
+++ b/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp
@@ -39,4 +39,15 @@
         m_networkStateChangedFunction();
 }
 
+void NetworkStateNotifier::networkTypeChange(Connection::ConnectionType type)
+{
+    if (m_type == type)
+        return;
+
+    m_type = type;
+
+    if (m_networkStateChangedFunction)
+        m_networkStateChangedFunction();
+}
+
 }
diff --git a/WebKit/android/jni/JavaBridge.cpp b/WebKit/android/jni/JavaBridge.cpp
index 049a7da..9e83d6a 100644
--- a/WebKit/android/jni/JavaBridge.cpp
+++ b/WebKit/android/jni/JavaBridge.cpp
@@ -27,8 +27,11 @@
 
 #include <config.h>
 #include <wtf/Platform.h>
+#include <wtf/StdLibExtras.h>
 
+#include "AtomicString.h"
 #include "Cache.h"
+#include "Connection.h"
 #include "CookieClient.h"
 #include "JavaSharedClient.h"
 #include "KeyGeneratorClient.h"
@@ -96,6 +99,7 @@
     static void SharedTimerFired(JNIEnv* env, jobject);
     static void SetCacheSize(JNIEnv* env, jobject obj, jint bytes);
     static void SetNetworkOnLine(JNIEnv* env, jobject obj, jboolean online);
+    static void SetNetworkType(JNIEnv* env, jobject obj, jstring type, jstring subtype);
     static void SetDeferringTimers(JNIEnv* env, jobject obj, jboolean defer);
     static void ServiceFuncPtrQueue(JNIEnv*);
     static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload);
@@ -344,6 +348,29 @@
 	WebCore::networkStateNotifier().networkStateChange(online);
 }
 
+void JavaBridge::SetNetworkType(JNIEnv* env, jobject obj, jstring javatype, jstring javasubtype)
+{
+    DEFINE_STATIC_LOCAL(AtomicString, wifi, ("wifi"));
+    DEFINE_STATIC_LOCAL(AtomicString, mobile, ("mobile"));
+    DEFINE_STATIC_LOCAL(AtomicString, mobileSupl, ("mobile_supl"));
+    DEFINE_STATIC_LOCAL(AtomicString, gprs, ("gprs"));
+    DEFINE_STATIC_LOCAL(AtomicString, edge, ("edge"));
+    DEFINE_STATIC_LOCAL(AtomicString, umts, ("umts"));
+
+    String type = to_string(env, javatype);
+    String subtype = to_string(env, javasubtype);
+    Connection::ConnectionType connectionType = Connection::Unknown;
+    if (type == wifi)
+        connectionType = Connection::WiFi;
+    else if (type == mobile || type == mobileSupl) {
+        if (subtype == edge || subtype == gprs)
+            connectionType = Connection::Cell_2G;
+        else if (subtype == umts)
+            connectionType = Connection::Cell_3G;
+    }
+    WebCore::networkStateNotifier().networkTypeChange(connectionType);
+}
+
 void JavaBridge::ServiceFuncPtrQueue(JNIEnv*)
 {
     JavaSharedClient::ServiceFunctionPtrQueue();
@@ -383,6 +410,8 @@
         (void*) JavaBridge::SetCacheSize },
     { "setNetworkOnLine", "(Z)V",
         (void*) JavaBridge::SetNetworkOnLine },
+    { "setNetworkType", "(Ljava/lang/String;Ljava/lang/String;)V",
+        (void*) JavaBridge::SetNetworkType },
     { "nativeServiceFuncPtrQueue", "()V",
         (void*) JavaBridge::ServiceFuncPtrQueue },
     { "nativeUpdatePluginDirectories", "([Ljava/lang/String;Z)V",