diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 55b601c7a2c..db72eb78e6f 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -175,7 +175,10 @@ Navigator::Invalidate() } #endif - mConnection = nsnull; + if (mConnection) { + mConnection->Shutdown(); + mConnection = nsnull; + } } nsPIDOMWindow * @@ -1074,8 +1077,20 @@ Navigator::GetMozTelephony(nsIDOMTelephony** aTelephony) NS_IMETHODIMP Navigator::GetMozConnection(nsIDOMMozConnection** aConnection) { + *aConnection = nsnull; + if (!mConnection) { + nsCOMPtr window = do_QueryReferent(mWindow); + NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK); + + nsCOMPtr sgo = do_QueryInterface(window); + NS_ENSURE_TRUE(sgo, NS_OK); + + nsIScriptContext* scx = sgo->GetContext(); + NS_ENSURE_TRUE(scx, NS_OK); + mConnection = new network::Connection(); + mConnection->Init(window, scx); } NS_ADDREF(*aConnection = mConnection); diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index 1bac07f31d5..209f0b11b34 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -80,6 +80,10 @@ namespace sms { class SmsManager; } // namespace sms +namespace network { +class Connection; +} // namespace Connection; + class Navigator : public nsIDOMNavigator , public nsIDOMClientInformation , public nsIDOMNavigatorGeolocation @@ -136,7 +140,7 @@ private: #ifdef MOZ_B2G_RIL nsCOMPtr mTelephony; #endif - nsCOMPtr mConnection; + nsRefPtr mConnection; nsWeakPtr mWindow; }; diff --git a/dom/network/interfaces/nsIDOMConnection.idl b/dom/network/interfaces/nsIDOMConnection.idl index a49b05d8a50..4552c9cc477 100644 --- a/dom/network/interfaces/nsIDOMConnection.idl +++ b/dom/network/interfaces/nsIDOMConnection.idl @@ -36,8 +36,13 @@ #include "nsISupports.idl" -[scriptable, uuid(0bd0bcc8-ca92-43fa-97bd-aec8d79edb24)] +interface nsIDOMEventListener; + +[scriptable, uuid(8c6b574d-1135-4387-a6e3-6d8ba38d79a1)] interface nsIDOMMozConnection : nsISupports { + readonly attribute double bandwidth; readonly attribute boolean metered; + + attribute nsIDOMEventListener onchange; }; diff --git a/dom/network/src/Connection.cpp b/dom/network/src/Connection.cpp index b552d1cb167..d023b795e8e 100644 --- a/dom/network/src/Connection.cpp +++ b/dom/network/src/Connection.cpp @@ -35,9 +35,19 @@ * * ***** END LICENSE BLOCK ***** */ +#include +#include "mozilla/Hal.h" #include "Connection.h" #include "nsIDOMClassInfo.h" #include "mozilla/Preferences.h" +#include "nsDOMEvent.h" +#include "Constants.h" + +/** + * We have to use macros here because our leak analysis tool things we are + * leaking strings when we have |static const nsString|. Sad :( + */ +#define CHANGE_EVENT_NAME NS_LITERAL_STRING("change") DOMCI_DATA(MozConnection, mozilla::dom::network::Connection) @@ -48,23 +58,121 @@ namespace network { const char* Connection::sMeteredPrefName = "dom.network.metered"; const bool Connection::sMeteredDefaultValue = false; -NS_INTERFACE_MAP_BEGIN(Connection) - NS_INTERFACE_MAP_ENTRY(nsIDOMMozConnection) - NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozConnection) -NS_INTERFACE_MAP_END +NS_IMPL_CYCLE_COLLECTION_CLASS(Connection) -NS_IMPL_ADDREF(Connection) -NS_IMPL_RELEASE(Connection) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Connection, + nsDOMEventTargetWrapperCache) + NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(change) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Connection, + nsDOMEventTargetWrapperCache) + NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(change) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Connection) + NS_INTERFACE_MAP_ENTRY(nsIDOMMozConnection) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozConnection) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozConnection) +NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache) + +NS_IMPL_ADDREF_INHERITED(Connection, nsDOMEventTargetWrapperCache) +NS_IMPL_RELEASE_INHERITED(Connection, nsDOMEventTargetWrapperCache) + +Connection::Connection() + : mCanBeMetered(kDefaultCanBeMetered) + , mBandwidth(kDefaultBandwidth) +{ +} + +void +Connection::Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext) +{ + // Those vars come from nsDOMEventTargetHelper. + mOwner = aWindow; + mScriptContext = aScriptContext; + + hal::RegisterNetworkObserver(this); + + hal::NetworkInformation networkInfo; + hal::GetCurrentNetworkInformation(&networkInfo); + + UpdateFromNetworkInfo(networkInfo); +} + +void +Connection::Shutdown() +{ + hal::UnregisterNetworkObserver(this); +} + +NS_IMETHODIMP +Connection::GetBandwidth(double* aBandwidth) +{ + if (mBandwidth == kDefaultBandwidth) { + *aBandwidth = std::numeric_limits::infinity(); + return NS_OK; + } + + *aBandwidth = mBandwidth; + return NS_OK; +} NS_IMETHODIMP Connection::GetMetered(bool* aMetered) { + if (!mCanBeMetered) { + *aMetered = false; + return NS_OK; + } + *aMetered = Preferences::GetBool(sMeteredPrefName, sMeteredDefaultValue); return NS_OK; } +NS_IMPL_EVENT_HANDLER(Connection, change) + +nsresult +Connection::DispatchTrustedEventToSelf(const nsAString& aEventName) +{ + nsRefPtr event = new nsDOMEvent(nsnull, nsnull); + nsresult rv = event->InitEvent(aEventName, false, false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = event->SetTrusted(PR_TRUE); + NS_ENSURE_SUCCESS(rv, rv); + + bool dummy; + rv = DispatchEvent(event, &dummy); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +void +Connection::UpdateFromNetworkInfo(const hal::NetworkInformation& aNetworkInfo) +{ + mBandwidth = aNetworkInfo.bandwidth(); + mCanBeMetered = aNetworkInfo.canBeMetered(); +} + +void +Connection::Notify(const hal::NetworkInformation& aNetworkInfo) +{ + double previousBandwidth = mBandwidth; + bool previousCanBeMetered = mCanBeMetered; + + UpdateFromNetworkInfo(aNetworkInfo); + + if (previousBandwidth == mBandwidth && + previousCanBeMetered == mCanBeMetered) { + return; + } + + DispatchTrustedEventToSelf(CHANGE_EVENT_NAME); +} + } // namespace network } // namespace dom } // namespace mozilla diff --git a/dom/network/src/Connection.h b/dom/network/src/Connection.h index 31c16e27379..7e69f0b7e87 100644 --- a/dom/network/src/Connection.h +++ b/dom/network/src/Connection.h @@ -39,18 +39,65 @@ #define mozilla_dom_network_Connection_h #include "nsIDOMConnection.h" +#include "nsDOMEventTargetWrapperCache.h" +#include "nsCycleCollectionParticipant.h" +#include "mozilla/Observer.h" +#include "Types.h" namespace mozilla { + +namespace hal { +class NetworkInformation; +} // namespace hal + namespace dom { namespace network { -class Connection : public nsIDOMMozConnection +class Connection : public nsDOMEventTargetWrapperCache + , public nsIDOMMozConnection + , public NetworkObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIDOMMOZCONNECTION + NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetWrapperCache::) + + Connection(); + + void Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext); + void Shutdown(); + + // For IObserver + void Notify(const hal::NetworkInformation& aNetworkInfo); + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Connection, + nsDOMEventTargetWrapperCache) + private: + /** + * Dispatch a trusted non-cancellable and non-bubbling event to itself. + */ + nsresult DispatchTrustedEventToSelf(const nsAString& aEventName); + + /** + * Update the connection information stored in the object using a + * NetworkInformation object. + */ + void UpdateFromNetworkInfo(const hal::NetworkInformation& aNetworkInfo); + + /** + * If the connection is of a type that can be metered. + */ + bool mCanBeMetered; + + /** + * The connection bandwidth. + */ + double mBandwidth; + + NS_DECL_EVENT_HANDLER(change) + static const char* sMeteredPrefName; static const bool sMeteredDefaultValue; }; diff --git a/dom/network/src/Makefile.in b/dom/network/src/Makefile.in index 59c8a537c2f..601304da94c 100644 --- a/dom/network/src/Makefile.in +++ b/dom/network/src/Makefile.in @@ -61,6 +61,9 @@ CPPSRCS = \ $(NULL) LOCAL_INCLUDES = \ + -I$(topsrcdir)/content/events/src \ $(NULL) +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk diff --git a/dom/network/tests/test_network_basics.html b/dom/network/tests/test_network_basics.html index 094b9233d9e..017d236e2b8 100644 --- a/dom/network/tests/test_network_basics.html +++ b/dom/network/tests/test_network_basics.html @@ -28,6 +28,16 @@ ok(navigator.mozConnection instanceof MozConnection, checkInterface("Connection"); +ok('bandwidth' in navigator.mozConnection, + "bandwidth should be a Connection attribute"); +is(navigator.mozConnection.bandwidth, Infinity, + "By default connection.bandwidth is equals to Infinity"); + +ok('metered' in navigator.mozConnection, + "metered should be a Connection attribute"); +is(navigator.mozConnection.metered, false, + "By default the connection is not metered"); +