diff -r 000000000000 -r 6474c204b198 dom/system/gonk/SystemWorkerManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/system/gonk/SystemWorkerManager.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,263 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Copyright 2012 Mozilla Foundation and Mozilla contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SystemWorkerManager.h" + +#include "nsINetworkService.h" +#include "nsIWifi.h" +#include "nsIWorkerHolder.h" +#include "nsIXPConnect.h" + +#include "jsfriendapi.h" +#include "mozilla/dom/workers/Workers.h" +#include "AutoMounter.h" +#include "TimeZoneSettingObserver.h" +#include "AudioManager.h" +#ifdef MOZ_B2G_RIL +#include "mozilla/ipc/Ril.h" +#endif +#ifdef MOZ_NFC +#include "mozilla/ipc/Nfc.h" +#endif +#include "mozilla/ipc/KeyStore.h" +#include "nsIObserverService.h" +#include "nsCxPusher.h" +#include "nsServiceManagerUtils.h" +#include "nsThreadUtils.h" +#include "nsRadioInterfaceLayer.h" +#include "WifiWorker.h" +#include "mozilla/Services.h" + +USING_WORKERS_NAMESPACE + +using namespace mozilla::dom::gonk; +using namespace mozilla::ipc; +using namespace mozilla::system; + +namespace { + +NS_DEFINE_CID(kWifiWorkerCID, NS_WIFIWORKER_CID); + +// Doesn't carry a reference, we're owned by services. +SystemWorkerManager *gInstance = nullptr; + +} // anonymous namespace + +SystemWorkerManager::SystemWorkerManager() + : mShutdown(false) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!gInstance, "There should only be one instance!"); +} + +SystemWorkerManager::~SystemWorkerManager() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!gInstance || gInstance == this, + "There should only be one instance!"); + gInstance = nullptr; +} + +nsresult +SystemWorkerManager::Init() +{ + if (XRE_GetProcessType() != GeckoProcessType_Default) { + return NS_ERROR_NOT_AVAILABLE; + } + + NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread"); + NS_ASSERTION(!mShutdown, "Already shutdown!"); + + mozilla::AutoSafeJSContext cx; + + nsresult rv = InitWifi(cx); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to initialize WiFi Networking!"); + return rv; + } + + InitKeyStore(cx); + + InitAutoMounter(); + InitializeTimeZoneSettingObserver(); + nsCOMPtr audioManager = + do_GetService(NS_AUDIOMANAGER_CONTRACTID); + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (!obs) { + NS_WARNING("Failed to get observer service!"); + return NS_ERROR_FAILURE; + } + + rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to initialize worker shutdown event!"); + return rv; + } + + return NS_OK; +} + +void +SystemWorkerManager::Shutdown() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + mShutdown = true; + + ShutdownAutoMounter(); + +#ifdef MOZ_B2G_RIL + RilConsumer::Shutdown(); +#endif + +#ifdef MOZ_NFC + NfcConsumer::Shutdown(); +#endif + + nsCOMPtr wifi(do_QueryInterface(mWifiWorker)); + if (wifi) { + wifi->Shutdown(); + wifi = nullptr; + } + mWifiWorker = nullptr; + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, WORKERS_SHUTDOWN_TOPIC); + } +} + +// static +already_AddRefed +SystemWorkerManager::FactoryCreate() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + nsRefPtr instance(gInstance); + + if (!instance) { + instance = new SystemWorkerManager(); + if (NS_FAILED(instance->Init())) { + instance->Shutdown(); + return nullptr; + } + + gInstance = instance; + } + + return instance.forget(); +} + +// static +nsIInterfaceRequestor* +SystemWorkerManager::GetInterfaceRequestor() +{ + return gInstance; +} + +NS_IMETHODIMP +SystemWorkerManager::GetInterface(const nsIID &aIID, void **aResult) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + if (aIID.Equals(NS_GET_IID(nsIWifi))) { + return CallQueryInterface(mWifiWorker, + reinterpret_cast(aResult)); + } + + NS_WARNING("Got nothing for the requested IID!"); + return NS_ERROR_NO_INTERFACE; +} + +nsresult +SystemWorkerManager::RegisterRilWorker(unsigned int aClientId, + JS::Handle aWorker, + JSContext *aCx) +{ +#ifndef MOZ_B2G_RIL + return NS_ERROR_NOT_IMPLEMENTED; +#else + NS_ENSURE_TRUE(aWorker.isObject(), NS_ERROR_UNEXPECTED); + + JSAutoCompartment ac(aCx, &aWorker.toObject()); + + WorkerCrossThreadDispatcher *wctd = + GetWorkerCrossThreadDispatcher(aCx, aWorker); + if (!wctd) { + NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for ril"); + return NS_ERROR_FAILURE; + } + + return RilConsumer::Register(aClientId, wctd); +#endif // MOZ_B2G_RIL +} + +nsresult +SystemWorkerManager::RegisterNfcWorker(JS::Handle aWorker, + JSContext* aCx) +{ +#ifndef MOZ_NFC + return NS_ERROR_NOT_IMPLEMENTED; +#else + NS_ENSURE_TRUE(aWorker.isObject(), NS_ERROR_UNEXPECTED); + + JSAutoCompartment ac(aCx, &aWorker.toObject()); + + WorkerCrossThreadDispatcher* wctd = + GetWorkerCrossThreadDispatcher(aCx, aWorker); + if (!wctd) { + NS_WARNING("Failed to GetWorkerCrossThreadDispatcher for nfc"); + return NS_ERROR_FAILURE; + } + + return NfcConsumer::Register(wctd); +#endif // MOZ_NFC +} + +nsresult +SystemWorkerManager::InitWifi(JSContext *cx) +{ + nsCOMPtr worker = do_CreateInstance(kWifiWorkerCID); + NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE); + + mWifiWorker = worker; + return NS_OK; +} + +nsresult +SystemWorkerManager::InitKeyStore(JSContext *cx) +{ + mKeyStore = new KeyStore(); + return NS_OK; +} + +NS_IMPL_ISUPPORTS(SystemWorkerManager, + nsIObserver, + nsIInterfaceRequestor, + nsISystemWorkerManager) + +NS_IMETHODIMP +SystemWorkerManager::Observe(nsISupports *aSubject, const char *aTopic, + const char16_t *aData) +{ + if (!strcmp(aTopic, WORKERS_SHUTDOWN_TOPIC)) { + Shutdown(); + } + + return NS_OK; +}