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