Bug 1663089 [wpt PR 25399] - idle-detection: Implement requestPermission() method...
[gecko.git] / dom / network / ConnectionWorker.cpp
blob50849291c83c9daf865f42bd16a540a49115673f
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include <limits>
8 #include "mozilla/Hal.h"
9 #include "ConnectionWorker.h"
10 #include "mozilla/dom/WorkerRef.h"
11 #include "mozilla/dom/WorkerRunnable.h"
13 namespace mozilla {
14 namespace dom {
15 namespace network {
17 class ConnectionProxy final : public hal::NetworkObserver {
18 public:
19 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ConnectionProxy)
21 static already_AddRefed<ConnectionProxy> Create(
22 WorkerPrivate* aWorkerPrivate, ConnectionWorker* aConnection) {
23 RefPtr<ConnectionProxy> proxy = new ConnectionProxy(aConnection);
25 RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(
26 aWorkerPrivate, "ConnectionProxy", [proxy]() { proxy->Shutdown(); });
27 if (NS_WARN_IF(!workerRef)) {
28 return nullptr;
31 proxy->mWorkerRef = new ThreadSafeWorkerRef(workerRef);
32 return proxy.forget();
35 ThreadSafeWorkerRef* WorkerRef() const { return mWorkerRef; }
37 // For IObserver - main-thread only.
38 void Notify(const hal::NetworkInformation& aNetworkInfo) override;
40 void Shutdown();
42 void Update(ConnectionType aType, bool aIsWifi, uint32_t aDHCPGateway) {
43 MOZ_ASSERT(mConnection);
44 MOZ_ASSERT(IsCurrentThreadRunningWorker());
45 mConnection->Update(aType, aIsWifi, aDHCPGateway, true);
48 private:
49 explicit ConnectionProxy(ConnectionWorker* aConnection)
50 : mConnection(aConnection) {}
52 ~ConnectionProxy() = default;
54 // Raw pointer because the ConnectionWorker keeps alive the proxy.
55 // This is touched only on the worker-thread and it's nullified when the
56 // shutdown procedure starts.
57 ConnectionWorker* mConnection;
59 RefPtr<ThreadSafeWorkerRef> mWorkerRef;
62 namespace {
64 // This class initializes the hal observer on the main-thread.
65 class InitializeRunnable : public WorkerMainThreadRunnable {
66 private:
67 // raw pointer because this is a sync runnable.
68 ConnectionProxy* mProxy;
69 hal::NetworkInformation& mNetworkInfo;
71 public:
72 InitializeRunnable(WorkerPrivate* aWorkerPrivate, ConnectionProxy* aProxy,
73 hal::NetworkInformation& aNetworkInfo)
74 : WorkerMainThreadRunnable(aWorkerPrivate,
75 "ConnectionWorker :: Initialize"_ns),
76 mProxy(aProxy),
77 mNetworkInfo(aNetworkInfo) {
78 MOZ_ASSERT(aProxy);
79 aWorkerPrivate->AssertIsOnWorkerThread();
82 bool MainThreadRun() override {
83 MOZ_ASSERT(NS_IsMainThread());
84 hal::RegisterNetworkObserver(mProxy);
85 hal::GetCurrentNetworkInformation(&mNetworkInfo);
86 return true;
90 // This class turns down the hal observer on the main-thread.
91 class ShutdownRunnable : public WorkerMainThreadRunnable {
92 private:
93 // raw pointer because this is a sync runnable.
94 ConnectionProxy* mProxy;
96 public:
97 ShutdownRunnable(WorkerPrivate* aWorkerPrivate, ConnectionProxy* aProxy)
98 : WorkerMainThreadRunnable(aWorkerPrivate,
99 "ConnectionWorker :: Shutdown"_ns),
100 mProxy(aProxy) {
101 MOZ_ASSERT(aProxy);
102 aWorkerPrivate->AssertIsOnWorkerThread();
105 bool MainThreadRun() override {
106 MOZ_ASSERT(NS_IsMainThread());
107 hal::UnregisterNetworkObserver(mProxy);
108 return true;
112 class NotifyRunnable : public WorkerRunnable {
113 private:
114 RefPtr<ConnectionProxy> mProxy;
116 const ConnectionType mConnectionType;
117 const bool mIsWifi;
118 const uint32_t mDHCPGateway;
120 public:
121 NotifyRunnable(WorkerPrivate* aWorkerPrivate, ConnectionProxy* aProxy,
122 ConnectionType aType, bool aIsWifi, uint32_t aDHCPGateway)
123 : WorkerRunnable(aWorkerPrivate),
124 mProxy(aProxy),
125 mConnectionType(aType),
126 mIsWifi(aIsWifi),
127 mDHCPGateway(aDHCPGateway) {
128 MOZ_ASSERT(aProxy);
129 MOZ_ASSERT(NS_IsMainThread());
132 bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
133 aWorkerPrivate->AssertIsOnWorkerThread();
134 mProxy->Update(mConnectionType, mIsWifi, mDHCPGateway);
135 return true;
139 } // anonymous namespace
141 /* static */
142 already_AddRefed<ConnectionWorker> ConnectionWorker::Create(
143 WorkerPrivate* aWorkerPrivate, ErrorResult& aRv) {
144 RefPtr<ConnectionWorker> c = new ConnectionWorker();
145 c->mProxy = ConnectionProxy::Create(aWorkerPrivate, c);
146 if (!c->mProxy) {
147 aRv.ThrowTypeError("The Worker thread is shutting down.");
148 return nullptr;
151 hal::NetworkInformation networkInfo;
152 RefPtr<InitializeRunnable> runnable =
153 new InitializeRunnable(aWorkerPrivate, c->mProxy, networkInfo);
155 runnable->Dispatch(Canceling, aRv);
156 if (NS_WARN_IF(aRv.Failed())) {
157 return nullptr;
160 c->Update(static_cast<ConnectionType>(networkInfo.type()),
161 networkInfo.isWifi(), networkInfo.dhcpGateway(), false);
162 return c.forget();
165 ConnectionWorker::ConnectionWorker() : Connection(nullptr) {
166 MOZ_ASSERT(IsCurrentThreadRunningWorker());
169 ConnectionWorker::~ConnectionWorker() { Shutdown(); }
171 void ConnectionWorker::ShutdownInternal() {
172 MOZ_ASSERT(IsCurrentThreadRunningWorker());
173 mProxy->Shutdown();
176 void ConnectionProxy::Notify(const hal::NetworkInformation& aNetworkInfo) {
177 MOZ_ASSERT(NS_IsMainThread());
179 RefPtr<NotifyRunnable> runnable =
180 new NotifyRunnable(mWorkerRef->Private(), this,
181 static_cast<ConnectionType>(aNetworkInfo.type()),
182 aNetworkInfo.isWifi(), aNetworkInfo.dhcpGateway());
183 runnable->Dispatch();
186 void ConnectionProxy::Shutdown() {
187 MOZ_ASSERT(IsCurrentThreadRunningWorker());
189 // Already shut down.
190 if (!mConnection) {
191 return;
194 mConnection = nullptr;
196 RefPtr<ShutdownRunnable> runnable =
197 new ShutdownRunnable(mWorkerRef->Private(), this);
199 ErrorResult rv;
200 // This runnable _must_ be executed.
201 runnable->Dispatch(Killing, rv);
202 if (NS_WARN_IF(rv.Failed())) {
203 rv.SuppressException();
206 mWorkerRef = nullptr;
209 } // namespace network
210 } // namespace dom
211 } // namespace mozilla