diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index d175e19880da..b79f321e6b62 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1727,7 +1727,7 @@ Navigator::GetConnection(ErrorResult& aRv) aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } - mConnection = new network::Connection(mWindow); + mConnection = network::Connection::CreateForWindow(mWindow); } return mConnection; diff --git a/dom/bindings/Errors.msg b/dom/bindings/Errors.msg index 0b818da4991d..2d4d2d923d8a 100644 --- a/dom/bindings/Errors.msg +++ b/dom/bindings/Errors.msg @@ -104,3 +104,4 @@ MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache fil MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the supported range for time values.") MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.") MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].") +MSG_DEF(MSG_WORKER_THREAD_SHUTTING_DOWN, 0, JSEXN_TYPEERR, "The Worker thread is shutting down.") diff --git a/dom/network/Connection.cpp b/dom/network/Connection.cpp index 3bf6f40384a6..7b62c6b1134f 100644 --- a/dom/network/Connection.cpp +++ b/dom/network/Connection.cpp @@ -4,12 +4,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include -#include "mozilla/Hal.h" -#include "mozilla/dom/network/Connection.h" +#include "Connection.h" +#include "ConnectionMainThread.h" +#include "ConnectionWorker.h" #include "nsIDOMClassInfo.h" -#include "mozilla/Preferences.h" #include "Constants.h" +#include "WorkerPrivate.h" /** * We have to use macros here because our leak analysis tool things we are @@ -19,6 +19,9 @@ namespace mozilla { namespace dom { + +using namespace workers; + namespace network { NS_IMPL_QUERY_INTERFACE_INHERITED(Connection, DOMEventTargetHelper, @@ -34,63 +37,100 @@ Connection::Connection(nsPIDOMWindowInner* aWindow) , mType(static_cast(kDefaultType)) , mIsWifi(kDefaultIsWifi) , mDHCPGateway(kDefaultDHCPGateway) + , mBeenShutDown(false) { - hal::RegisterNetworkObserver(this); +} - hal::NetworkInformation networkInfo; - hal::GetCurrentNetworkInformation(&networkInfo); - - UpdateFromNetworkInfo(networkInfo); +Connection::~Connection() +{ + NS_ASSERT_OWNINGTHREAD(Connection); + MOZ_ASSERT(mBeenShutDown); } void Connection::Shutdown() { - hal::UnregisterNetworkObserver(this); + NS_ASSERT_OWNINGTHREAD(Connection); + + if (mBeenShutDown) { + return; + } + + mBeenShutDown = true; + ShutdownInternal(); } NS_IMETHODIMP -Connection::GetIsWifi(bool *aIsWifi) +Connection::GetIsWifi(bool* aIsWifi) { + NS_ENSURE_ARG_POINTER(aIsWifi); + NS_ASSERT_OWNINGTHREAD(Connection); + *aIsWifi = mIsWifi; return NS_OK; } NS_IMETHODIMP -Connection::GetDhcpGateway(uint32_t *aGW) +Connection::GetDhcpGateway(uint32_t* aGW) { + NS_ENSURE_ARG_POINTER(aGW); + NS_ASSERT_OWNINGTHREAD(Connection); + *aGW = mDHCPGateway; return NS_OK; } -void -Connection::UpdateFromNetworkInfo(const hal::NetworkInformation& aNetworkInfo) -{ - mType = static_cast(aNetworkInfo.type()); - mIsWifi = aNetworkInfo.isWifi(); - mDHCPGateway = aNetworkInfo.dhcpGateway(); -} - -void -Connection::Notify(const hal::NetworkInformation& aNetworkInfo) -{ - ConnectionType previousType = mType; - - UpdateFromNetworkInfo(aNetworkInfo); - - if (previousType == mType) { - return; - } - - DispatchTrustedEvent(CHANGE_EVENT_NAME); -} - JSObject* Connection::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { return NetworkInformationBinding::Wrap(aCx, this, aGivenProto); } +void +Connection::Update(ConnectionType aType, bool aIsWifi, bool aDHCPGateway, + bool aNotify) +{ + NS_ASSERT_OWNINGTHREAD(Connection); + + ConnectionType previousType = mType; + + mType = aType; + mIsWifi = aIsWifi; + mDHCPGateway = aDHCPGateway; + + if (aNotify && previousType != aType) { + DispatchTrustedEvent(CHANGE_EVENT_NAME); + } +} + +/* static */ bool +Connection::IsEnabled(JSContext* aCx, JSObject* aObj) +{ + if (NS_IsMainThread()) { + return Preferences::GetBool("dom.netinfo.enabled"); + } + + WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); + MOZ_ASSERT(workerPrivate); + return workerPrivate->NetworkInformationEnabled(); +} + +/* static */ Connection* +Connection::CreateForWindow(nsPIDOMWindowInner* aWindow) +{ + MOZ_ASSERT(aWindow); + return new ConnectionMainThread(aWindow); +} + +/* static */ already_AddRefed +Connection::CreateForWorker(workers::WorkerPrivate* aWorkerPrivate, + ErrorResult& aRv) +{ + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); + return ConnectionWorker::Create(aWorkerPrivate, aRv); +} + } // namespace network } // namespace dom } // namespace mozilla diff --git a/dom/network/Connection.h b/dom/network/Connection.h index 907aea144bc0..9e958cf3c227 100644 --- a/dom/network/Connection.h +++ b/dom/network/Connection.h @@ -7,15 +7,17 @@ #ifndef mozilla_dom_network_Connection_h #define mozilla_dom_network_Connection_h -#include "Types.h" #include "mozilla/DOMEventTargetHelper.h" -#include "mozilla/Observer.h" #include "mozilla/dom/NetworkInformationBinding.h" #include "nsCycleCollectionParticipant.h" #include "nsINetworkProperties.h" namespace mozilla { +namespace workers { +class WorkerPrivate; +} // namespace workers + namespace hal { class NetworkInformation; } // namespace hal @@ -23,40 +25,46 @@ class NetworkInformation; namespace dom { namespace network { -class Connection final : public DOMEventTargetHelper - , public NetworkObserver - , public nsINetworkProperties +class Connection : public DOMEventTargetHelper + , public nsINetworkProperties { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSINETWORKPROPERTIES + NS_DECL_OWNINGTHREAD NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper) - explicit Connection(nsPIDOMWindowInner* aWindow); + static bool IsEnabled(JSContext* aCx, JSObject* aObj); + + static Connection* + CreateForWindow(nsPIDOMWindowInner* aWindow); + + static already_AddRefed + CreateForWorker(workers::WorkerPrivate* aWorkerPrivate, + ErrorResult& aRv); void Shutdown(); - // For IObserver - void Notify(const hal::NetworkInformation& aNetworkInfo) override; - // WebIDL - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aGivenProto) override; ConnectionType Type() const { return mType; } IMPL_EVENT_HANDLER(typechange) +protected: + Connection(nsPIDOMWindowInner* aWindow); + virtual ~Connection(); + + void Update(ConnectionType aType, bool aIsWifi, bool aDHCPGateway, + bool aNotify); + + virtual void ShutdownInternal() = 0; + private: - ~Connection() {} - - /** - * Update the connection information stored in the object using a - * NetworkInformation object. - */ - void UpdateFromNetworkInfo(const hal::NetworkInformation& aNetworkInfo); - /** * The type of current connection. */ @@ -71,6 +79,8 @@ private: * DHCP Gateway information for IPV4, in network byte order. 0 if unassigned. */ uint32_t mDHCPGateway; + + bool mBeenShutDown; }; } // namespace network diff --git a/dom/network/ConnectionMainThread.cpp b/dom/network/ConnectionMainThread.cpp new file mode 100644 index 000000000000..5cb5943c0e0c --- /dev/null +++ b/dom/network/ConnectionMainThread.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include "mozilla/Hal.h" +#include "ConnectionMainThread.h" + +namespace mozilla { +namespace dom { +namespace network { + +ConnectionMainThread::ConnectionMainThread(nsPIDOMWindowInner* aWindow) + : Connection(aWindow) +{ + hal::RegisterNetworkObserver(this); + + hal::NetworkInformation networkInfo; + hal::GetCurrentNetworkInformation(&networkInfo); + + UpdateFromNetworkInfo(networkInfo, false); +} + +ConnectionMainThread::~ConnectionMainThread() +{ + Shutdown(); +} + +void +ConnectionMainThread::ShutdownInternal() +{ + hal::UnregisterNetworkObserver(this); +} + +void +ConnectionMainThread::UpdateFromNetworkInfo(const hal::NetworkInformation& aNetworkInfo, + bool aNotify) +{ + Update(static_cast(aNetworkInfo.type()), + aNetworkInfo.isWifi(), aNetworkInfo.dhcpGateway(), aNotify); +} + +void +ConnectionMainThread::Notify(const hal::NetworkInformation& aNetworkInfo) +{ + UpdateFromNetworkInfo(aNetworkInfo, true); +} + +} // namespace network +} // namespace dom +} // namespace mozilla diff --git a/dom/network/ConnectionMainThread.h b/dom/network/ConnectionMainThread.h new file mode 100644 index 000000000000..2cb17a5c7836 --- /dev/null +++ b/dom/network/ConnectionMainThread.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_network_ConnectionMainThread_h +#define mozilla_dom_network_ConnectionMainThread_h + +#include "Connection.h" +#include "mozilla/Observer.h" +#include "Types.h" + +namespace mozilla { +namespace dom { +namespace network { + +class ConnectionMainThread final : public Connection + , public NetworkObserver +{ +public: + explicit ConnectionMainThread(nsPIDOMWindowInner* aWindow); + + // For IObserver + void Notify(const hal::NetworkInformation& aNetworkInfo) override; + +private: + ~ConnectionMainThread(); + + virtual void ShutdownInternal() override; + + /** + * Update the connection information stored in the object using a + * NetworkInformation object. + */ + void UpdateFromNetworkInfo(const hal::NetworkInformation& aNetworkInfo, + bool aNotify); +}; + +} // namespace network +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_network_ConnectionMainThread_h diff --git a/dom/network/ConnectionWorker.cpp b/dom/network/ConnectionWorker.cpp new file mode 100644 index 000000000000..4d11d97214b4 --- /dev/null +++ b/dom/network/ConnectionWorker.cpp @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include "mozilla/Hal.h" +#include "ConnectionWorker.h" +#include "WorkerRunnable.h" + +namespace mozilla { +namespace dom { +namespace network { + +class ConnectionProxy final : public NetworkObserver + , public WorkerHolder +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ConnectionProxy) + + static already_AddRefed + Create(WorkerPrivate* aWorkerPrivate, ConnectionWorker* aConnection) + { + RefPtr proxy = + new ConnectionProxy(aWorkerPrivate, aConnection); + if (!proxy->HoldWorker(aWorkerPrivate, Closing)) { + proxy->mConnection = nullptr; + return nullptr; + } + + return proxy.forget(); + } + + // For IObserver - main-thread only. + void Notify(const hal::NetworkInformation& aNetworkInfo) override; + + // Worker notification + virtual bool Notify(Status aStatus) override + { + Shutdown(); + return true; + } + + void Shutdown(); + + void Update(ConnectionType aType, bool aIsWifi, bool aDHCPGateway) + { + MOZ_ASSERT(mConnection); + mWorkerPrivate->AssertIsOnWorkerThread(); + mConnection->Update(aType, aIsWifi, aDHCPGateway, true); + } + +private: + ConnectionProxy(WorkerPrivate* aWorkerPrivate, ConnectionWorker* aConnection) + : mConnection(aConnection) + , mWorkerPrivate(aWorkerPrivate) + { + MOZ_ASSERT(mWorkerPrivate); + MOZ_ASSERT(mConnection); + mWorkerPrivate->AssertIsOnWorkerThread(); + } + + ~ConnectionProxy() = default; + + // Raw pointer because the ConnectionWorker keeps alive the proxy. + // This is touched only on the worker-thread and it's nullified when the + // shutdown procedure starts. + ConnectionWorker* mConnection; + + WorkerPrivate* mWorkerPrivate; +}; + +namespace { + +// This class initializes the hal observer on the main-thread. +class InitializeRunnable : public WorkerMainThreadRunnable +{ +private: + // raw pointer because this is a sync runnable. + ConnectionProxy* mProxy; + hal::NetworkInformation& mNetworkInfo; + +public: + InitializeRunnable(WorkerPrivate* aWorkerPrivate, + ConnectionProxy* aProxy, + hal::NetworkInformation& aNetworkInfo) + : WorkerMainThreadRunnable(aWorkerPrivate, + NS_LITERAL_CSTRING("ConnectionWorker :: Initialize")) + , mProxy(aProxy) + , mNetworkInfo(aNetworkInfo) + { + MOZ_ASSERT(aProxy); + aWorkerPrivate->AssertIsOnWorkerThread(); + } + + bool + MainThreadRun() + { + MOZ_ASSERT(NS_IsMainThread()); + hal::RegisterNetworkObserver(mProxy); + hal::GetCurrentNetworkInformation(&mNetworkInfo); + return true; + } +}; + +// This class turns down the hal observer on the main-thread. +class ShutdownRunnable : public WorkerMainThreadRunnable +{ +private: + // raw pointer because this is a sync runnable. + ConnectionProxy* mProxy; + +public: + ShutdownRunnable(WorkerPrivate* aWorkerPrivate, ConnectionProxy* aProxy) + : WorkerMainThreadRunnable(aWorkerPrivate, + NS_LITERAL_CSTRING("ConnectionWorker :: Shutdown")) + , mProxy(aProxy) + { + MOZ_ASSERT(aProxy); + aWorkerPrivate->AssertIsOnWorkerThread(); + } + + bool + MainThreadRun() + { + MOZ_ASSERT(NS_IsMainThread()); + hal::UnregisterNetworkObserver(mProxy); + return true; + } +}; + +class NotifyRunnable : public WorkerRunnable +{ +private: + RefPtr mProxy; + + const ConnectionType mConnectionType; + const bool mIsWifi; + const bool mDHCPGateway; + +public: + NotifyRunnable(WorkerPrivate* aWorkerPrivate, + ConnectionProxy* aProxy, ConnectionType aType, + bool aIsWifi, bool aDHCPGateway) + : WorkerRunnable(aWorkerPrivate) + , mProxy(aProxy) + , mConnectionType(aType) + , mIsWifi(aIsWifi) + , mDHCPGateway(aDHCPGateway) + { + MOZ_ASSERT(aProxy); + MOZ_ASSERT(NS_IsMainThread()); + } + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + aWorkerPrivate->AssertIsOnWorkerThread(); + mProxy->Update(mConnectionType, mIsWifi, mDHCPGateway); + return true; + } +}; + +} // anonymous namespace + +/* static */ already_AddRefed +ConnectionWorker::Create(WorkerPrivate* aWorkerPrivate, ErrorResult& aRv) +{ + RefPtr c = new ConnectionWorker(aWorkerPrivate); + c->mProxy = ConnectionProxy::Create(aWorkerPrivate, c); + if (!c->mProxy) { + aRv.ThrowTypeError(); + return nullptr; + } + + hal::NetworkInformation networkInfo; + RefPtr runnable = + new InitializeRunnable(aWorkerPrivate, c->mProxy, networkInfo); + + runnable->Dispatch(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + c->Update(static_cast(networkInfo.type()), + networkInfo.isWifi(), networkInfo.dhcpGateway(), false); + return c.forget(); +} + +ConnectionWorker::ConnectionWorker(WorkerPrivate* aWorkerPrivate) + : Connection(nullptr) + , mWorkerPrivate(aWorkerPrivate) +{ + MOZ_ASSERT(aWorkerPrivate); + aWorkerPrivate->AssertIsOnWorkerThread(); +} + +ConnectionWorker::~ConnectionWorker() +{ + Shutdown(); +} + +void +ConnectionWorker::ShutdownInternal() +{ + mWorkerPrivate->AssertIsOnWorkerThread(); + mProxy->Shutdown(); +} + +void +ConnectionProxy::Notify(const hal::NetworkInformation& aNetworkInfo) +{ + MOZ_ASSERT(NS_IsMainThread()); + + RefPtr runnable = + new NotifyRunnable(mWorkerPrivate, this, + static_cast(aNetworkInfo.type()), + aNetworkInfo.isWifi(), aNetworkInfo.dhcpGateway()); + runnable->Dispatch(); +} + +void +ConnectionProxy::Shutdown() +{ + mWorkerPrivate->AssertIsOnWorkerThread(); + + // Already shut down. + if (!mConnection) { + return; + } + + mConnection = nullptr; + + RefPtr runnable = + new ShutdownRunnable(mWorkerPrivate, this); + + ErrorResult rv; + runnable->Dispatch(rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + } + + ReleaseWorker(); +} + +} // namespace network +} // namespace dom +} // namespace mozilla diff --git a/dom/network/ConnectionWorker.h b/dom/network/ConnectionWorker.h new file mode 100644 index 000000000000..605c3cd20433 --- /dev/null +++ b/dom/network/ConnectionWorker.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_network_ConnectionWorker_h +#define mozilla_dom_network_ConnectionWorker_h + +#include "Connection.h" +#include "mozilla/Observer.h" +#include "Types.h" + +namespace mozilla { +namespace dom { +namespace network { + +class ConnectionProxy; + +class ConnectionWorker final : public Connection +{ + friend class ConnectionProxy; + +public: + static already_AddRefed + Create(workers::WorkerPrivate* aWorkerPrivate, ErrorResult& aRv); + +private: + explicit ConnectionWorker(workers::WorkerPrivate* aWorkerPrivate); + ~ConnectionWorker(); + + virtual void ShutdownInternal() override; + + workers::WorkerPrivate* mWorkerPrivate; + RefPtr mProxy; +}; + +} // namespace network +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_network_ConnectionWorker_h diff --git a/dom/network/moz.build b/dom/network/moz.build index 3c4d3c1c93a4..2170c9b185c6 100644 --- a/dom/network/moz.build +++ b/dom/network/moz.build @@ -29,6 +29,8 @@ EXPORTS.mozilla.dom.network += [ UNIFIED_SOURCES += [ 'Connection.cpp', + 'ConnectionMainThread.cpp', + 'ConnectionWorker.cpp', 'TCPServerSocket.cpp', 'TCPServerSocketChild.cpp', 'TCPServerSocketParent.cpp', @@ -58,6 +60,10 @@ IPDL_SOURCES += [ 'PUDPSocket.ipdl', ] +LOCAL_INCLUDES += [ + '../workers', +] + include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' diff --git a/dom/network/tests/mochitest.ini b/dom/network/tests/mochitest.ini index 76fd55fe4126..af4bac165001 100644 --- a/dom/network/tests/mochitest.ini +++ b/dom/network/tests/mochitest.ini @@ -1,8 +1,11 @@ [DEFAULT] support-files = add_task.js + worker_network_basics.js [test_network_basics.html] skip-if = toolkit == 'android' +[test_network_basics_worker.html] +skip-if = toolkit == 'android' [test_tcpsocket_default_permissions.html] [test_tcpsocket_enabled_no_perm.html] diff --git a/dom/network/tests/test_network_basics_worker.html b/dom/network/tests/test_network_basics_worker.html new file mode 100644 index 000000000000..4e593ef2eaf2 --- /dev/null +++ b/dom/network/tests/test_network_basics_worker.html @@ -0,0 +1,35 @@ + + + + Test for Network in workers API + + + + +

+ +
+
+
+ + diff --git a/dom/network/tests/worker_network_basics.js b/dom/network/tests/worker_network_basics.js new file mode 100644 index 000000000000..e4c9b1859b75 --- /dev/null +++ b/dom/network/tests/worker_network_basics.js @@ -0,0 +1,24 @@ +function ok(a, msg) { + postMessage({type: 'status', status: !!a, msg: msg}); +} + +function is(a, b, msg) { + ok(a === b, msg); +} + +function finish() { + postMessage({type: 'finish'}); +} + +ok('connection' in navigator, "navigator.connection should exist"); + +ok(navigator.connection, "navigator.connection returns an object"); + +ok(navigator.connection instanceof EventTarget, + "navigator.connection is a EventTarget object"); + +ok('type' in navigator.connection, + "type should be a Connection attribute"); +is(navigator.connection.type, "none", + "By default connection.type equals to none"); +finish(); diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 3b3a8d6f915c..2932e6d8ed01 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -13,6 +13,7 @@ * https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension * http://www.w3.org/TR/beacon/#sec-beacon-method * https://html.spec.whatwg.org/#navigatorconcurrenthardware + * http://wicg.github.io/netinfo/#extensions-to-the-navigator-interface * * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and * Opera Software ASA. You are granted a license to use, reproduce diff --git a/dom/webidl/NetworkInformation.webidl b/dom/webidl/NetworkInformation.webidl index 3ad203af6b99..79d85971f45c 100644 --- a/dom/webidl/NetworkInformation.webidl +++ b/dom/webidl/NetworkInformation.webidl @@ -18,7 +18,8 @@ enum ConnectionType { "unknown" }; -[Pref="dom.netinfo.enabled"] +[Func="mozilla::dom::network::Connection::IsEnabled", + Exposed=(Window,Worker)] interface NetworkInformation : EventTarget { readonly attribute ConnectionType type; attribute EventHandler ontypechange; diff --git a/dom/webidl/WorkerNavigator.webidl b/dom/webidl/WorkerNavigator.webidl index 44d1e29f688a..8622546eed94 100644 --- a/dom/webidl/WorkerNavigator.webidl +++ b/dom/webidl/WorkerNavigator.webidl @@ -12,3 +12,10 @@ WorkerNavigator implements NavigatorLanguage; WorkerNavigator implements NavigatorOnLine; WorkerNavigator implements NavigatorConcurrentHardware; WorkerNavigator implements NavigatorStorage; + +// http://wicg.github.io/netinfo/#extensions-to-the-navigator-interface +[Exposed=(Worker)] +partial interface WorkerNavigator { + [Func="mozilla::dom::network::Connection::IsEnabled", Throws] + readonly attribute NetworkInformation connection; +}; diff --git a/dom/workers/WorkerNavigator.cpp b/dom/workers/WorkerNavigator.cpp index 2d3493eee210..dea9287386e7 100644 --- a/dom/workers/WorkerNavigator.cpp +++ b/dom/workers/WorkerNavigator.cpp @@ -10,6 +10,7 @@ #include "mozilla/dom/StorageManager.h" #include "mozilla/dom/WorkerNavigator.h" #include "mozilla/dom/WorkerNavigatorBinding.h" +#include "mozilla/dom/network/Connection.h" #include "nsProxyRelease.h" #include "RuntimeService.h" @@ -27,10 +28,23 @@ namespace dom { using namespace mozilla::dom::workers; -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WorkerNavigator, mStorageManager); +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WorkerNavigator, mStorageManager, + mConnection); + NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WorkerNavigator, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WorkerNavigator, Release) +WorkerNavigator::WorkerNavigator(const NavigatorProperties& aProperties, + bool aOnline) + : mProperties(aProperties) + , mOnline(aOnline) +{ +} + +WorkerNavigator::~WorkerNavigator() +{ +} + /* static */ already_AddRefed WorkerNavigator::Create(bool aOnLine) { @@ -183,5 +197,19 @@ WorkerNavigator::Storage() return mStorageManager; } +network::Connection* +WorkerNavigator::GetConnection(ErrorResult& aRv) +{ + if (!mConnection) { + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + + mConnection = network::Connection::CreateForWorker(workerPrivate, aRv); + } + + return mConnection; +} + + } // namespace dom } // namespace mozilla diff --git a/dom/workers/WorkerNavigator.h b/dom/workers/WorkerNavigator.h index ed8cf7441109..f8b41227ac41 100644 --- a/dom/workers/WorkerNavigator.h +++ b/dom/workers/WorkerNavigator.h @@ -19,26 +19,21 @@ namespace dom { class Promise; class StorageManager; +namespace network { +class Connection; +} // namespace network + class WorkerNavigator final : public nsWrapperCache { typedef struct workers::RuntimeService::NavigatorProperties NavigatorProperties; NavigatorProperties mProperties; RefPtr mStorageManager; + RefPtr mConnection; bool mOnline; - WorkerNavigator(const NavigatorProperties& aProperties, - bool aOnline) - : mProperties(aProperties) - , mOnline(aOnline) - { - MOZ_COUNT_CTOR(WorkerNavigator); - } - - ~WorkerNavigator() - { - MOZ_COUNT_DTOR(WorkerNavigator); - } + WorkerNavigator(const NavigatorProperties& aProperties, bool aOnline); + ~WorkerNavigator(); public: @@ -110,6 +105,8 @@ public: uint64_t HardwareConcurrency() const; StorageManager* Storage(); + + network::Connection* GetConnection(ErrorResult& aRv); }; } // namespace dom diff --git a/dom/workers/WorkerPrefs.h b/dom/workers/WorkerPrefs.h index c9b605a841d8..d63b9ab8a920 100644 --- a/dom/workers/WorkerPrefs.h +++ b/dom/workers/WorkerPrefs.h @@ -39,6 +39,7 @@ WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED) WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED) WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED) WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK) +WORKER_SIMPLE_PREF("dom.netinfo.enabled", NetworkInformationEnabled, NETWORKINFORMATION_ENABLED) WORKER_PREF("dom.workers.latestJSVersion", JSVersionChanged) WORKER_PREF("intl.accept_languages", PrefLanguagesChanged) WORKER_PREF("general.appname.override", AppNameOverrideChanged) diff --git a/dom/workers/test/navigator_worker.js b/dom/workers/test/navigator_worker.js index 63853aef12ab..bb962f45ebc7 100644 --- a/dom/workers/test/navigator_worker.js +++ b/dom/workers/test/navigator_worker.js @@ -16,6 +16,7 @@ var supportedProps = [ "languages", "hardwareConcurrency", { name: "storage", nightly: true }, + { name: "connection", nightly: true }, ]; self.onmessage = function(event) { diff --git a/dom/workers/test/test_worker_interfaces.js b/dom/workers/test/test_worker_interfaces.js index a4764471b8ea..9206975c1b61 100644 --- a/dom/workers/test/test_worker_interfaces.js +++ b/dom/workers/test/test_worker_interfaces.js @@ -150,6 +150,8 @@ var interfaceNamesInGlobalScope = "MessageEvent", // IMPORTANT: Do not change this list without review from a DOM peer! "MessagePort", +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "NetworkInformation", nightly: true}, // IMPORTANT: Do not change this list without review from a DOM peer! "Notification", // IMPORTANT: Do not change this list without review from a DOM peer!