diff options
Diffstat (limited to 'dom/system/windows')
-rw-r--r-- | dom/system/windows/WindowsLocationProvider.cpp | 297 | ||||
-rw-r--r-- | dom/system/windows/WindowsLocationProvider.h | 50 | ||||
-rw-r--r-- | dom/system/windows/moz.build | 11 | ||||
-rw-r--r-- | dom/system/windows/nsHapticFeedback.cpp | 15 | ||||
-rw-r--r-- | dom/system/windows/nsHapticFeedback.h | 15 |
5 files changed, 388 insertions, 0 deletions
diff --git a/dom/system/windows/WindowsLocationProvider.cpp b/dom/system/windows/WindowsLocationProvider.cpp new file mode 100644 index 0000000000..3c548cfb21 --- /dev/null +++ b/dom/system/windows/WindowsLocationProvider.cpp @@ -0,0 +1,297 @@ +/* -*- 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 "WindowsLocationProvider.h" +#include "GeolocationPosition.h" +#include "nsComponentManagerUtils.h" +#include "prtime.h" +#include "MLSFallback.h" +#include "mozilla/Attributes.h" +#include "mozilla/Logging.h" +#include "mozilla/FloatingPoint.h" +#include "mozilla/Telemetry.h" +#include "mozilla/dom/GeolocationPositionErrorBinding.h" + +namespace mozilla::dom { + +LazyLogModule gWindowsLocationProviderLog("WindowsLocationProvider"); +#define LOG(...) \ + MOZ_LOG(gWindowsLocationProviderLog, LogLevel::Debug, (__VA_ARGS__)) + +NS_IMPL_ISUPPORTS(WindowsLocationProvider::MLSUpdate, nsIGeolocationUpdate); + +WindowsLocationProvider::MLSUpdate::MLSUpdate(nsIGeolocationUpdate* aCallback) + : mCallback(aCallback) {} + +NS_IMETHODIMP +WindowsLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition* aPosition) { + if (!mCallback) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIDOMGeoPositionCoords> coords; + aPosition->GetCoords(getter_AddRefs(coords)); + if (!coords) { + return NS_ERROR_FAILURE; + } + Telemetry::Accumulate(Telemetry::GEOLOCATION_WIN8_SOURCE_IS_MLS, true); + return mCallback->Update(aPosition); +} +NS_IMETHODIMP +WindowsLocationProvider::MLSUpdate::NotifyError(uint16_t aError) { + if (!mCallback) { + return NS_ERROR_FAILURE; + } + nsCOMPtr<nsIGeolocationUpdate> callback(mCallback); + return callback->NotifyError(aError); +} + +class LocationEvent final : public ILocationEvents { + public: + LocationEvent(nsIGeolocationUpdate* aCallback, + WindowsLocationProvider* aProvider) + : mCallback(aCallback), mProvider(aProvider), mCount(0) {} + + // IUnknown interface + STDMETHODIMP_(ULONG) AddRef() override; + STDMETHODIMP_(ULONG) Release() override; + STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override; + + // ILocationEvents interface + MOZ_CAN_RUN_SCRIPT_BOUNDARY + STDMETHODIMP OnStatusChanged(REFIID aReportType, + LOCATION_REPORT_STATUS aStatus) override; + STDMETHODIMP OnLocationChanged(REFIID aReportType, + ILocationReport* aReport) override; + + private: + nsCOMPtr<nsIGeolocationUpdate> mCallback; + RefPtr<WindowsLocationProvider> mProvider; + ULONG mCount; +}; + +STDMETHODIMP_(ULONG) +LocationEvent::AddRef() { return InterlockedIncrement(&mCount); } + +STDMETHODIMP_(ULONG) +LocationEvent::Release() { + ULONG count = InterlockedDecrement(&mCount); + if (!count) { + delete this; + return 0; + } + return count; +} + +STDMETHODIMP +LocationEvent::QueryInterface(REFIID iid, void** ppv) { + if (iid == IID_IUnknown) { + *ppv = static_cast<IUnknown*>(this); + } else if (iid == IID_ILocationEvents) { + *ppv = static_cast<ILocationEvents*>(this); + } else { + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +STDMETHODIMP +LocationEvent::OnStatusChanged(REFIID aReportType, + LOCATION_REPORT_STATUS aStatus) { + if (aReportType != IID_ILatLongReport) { + return S_OK; + } + + // When registering event, REPORT_INITIALIZING is fired at first. + // Then, when the location is found, REPORT_RUNNING is fired. + if (aStatus == REPORT_RUNNING) { + // location is found by Windows Location provider, we use it. + mProvider->CancelMLSProvider(); + return S_OK; + } + + // Cannot get current location at this time. We use MLS instead until + // Location API returns RUNNING status. + if (NS_SUCCEEDED(mProvider->CreateAndWatchMLSProvider(mCallback))) { + return S_OK; + } + + // Cannot watch location by MLS provider. We must return error by + // Location API. + uint16_t err; + switch (aStatus) { + case REPORT_ACCESS_DENIED: + err = GeolocationPositionError_Binding::PERMISSION_DENIED; + break; + case REPORT_NOT_SUPPORTED: + case REPORT_ERROR: + err = GeolocationPositionError_Binding::POSITION_UNAVAILABLE; + break; + default: + return S_OK; + } + nsCOMPtr<nsIGeolocationUpdate> callback(mCallback); + callback->NotifyError(err); + return S_OK; +} + +STDMETHODIMP +LocationEvent::OnLocationChanged(REFIID aReportType, ILocationReport* aReport) { + if (aReportType != IID_ILatLongReport) { + return S_OK; + } + + RefPtr<ILatLongReport> latLongReport; + if (FAILED(aReport->QueryInterface(IID_ILatLongReport, + getter_AddRefs(latLongReport)))) { + return E_FAIL; + } + + DOUBLE latitude = 0.0; + latLongReport->GetLatitude(&latitude); + + DOUBLE longitude = 0.0; + latLongReport->GetLongitude(&longitude); + + DOUBLE alt = UnspecifiedNaN<double>(); + latLongReport->GetAltitude(&alt); + + DOUBLE herror = 0.0; + latLongReport->GetErrorRadius(&herror); + + DOUBLE verror = UnspecifiedNaN<double>(); + latLongReport->GetAltitudeError(&verror); + + double heading = UnspecifiedNaN<double>(); + double speed = UnspecifiedNaN<double>(); + + // nsGeoPositionCoords will convert NaNs to null for optional properties of + // the JavaScript Coordinates object. + RefPtr<nsGeoPosition> position = + new nsGeoPosition(latitude, longitude, alt, herror, verror, heading, + speed, PR_Now() / PR_USEC_PER_MSEC); + mCallback->Update(position); + + Telemetry::Accumulate(Telemetry::GEOLOCATION_WIN8_SOURCE_IS_MLS, false); + + return S_OK; +} + +NS_IMPL_ISUPPORTS(WindowsLocationProvider, nsIGeolocationProvider) + +WindowsLocationProvider::WindowsLocationProvider() { + LOG("WindowsLocationProvider::WindowsLocationProvider(%p)\n", this); +} + +WindowsLocationProvider::~WindowsLocationProvider() { + LOG("WindowsLocationProvider::~WindowsLocationProvider(%p, %p)\n", this, + mLocation.get()); +} + +NS_IMETHODIMP +WindowsLocationProvider::Startup() { + LOG("WindowsLocationProvider::Startup(%p, %p)\n", this, mLocation.get()); + if (mLocation) { + return NS_OK; + } + + RefPtr<ILocation> location; + if (FAILED(::CoCreateInstance(CLSID_Location, nullptr, CLSCTX_INPROC_SERVER, + IID_ILocation, getter_AddRefs(location)))) { + // We will use MLS provider + return NS_OK; + } + + IID reportTypes[] = {IID_ILatLongReport}; + if (FAILED(location->RequestPermissions(nullptr, reportTypes, 1, FALSE))) { + // We will use MLS provider + return NS_OK; + } + + mLocation = location; + return NS_OK; +} + +NS_IMETHODIMP +WindowsLocationProvider::Watch(nsIGeolocationUpdate* aCallback) { + LOG("WindowsLocationProvider::Watch(%p, %p, %d)\n", this, mLocation.get(), + mWatching); + if (mLocation) { + if (mWatching) { + return NS_OK; + } + RefPtr<LocationEvent> event = new LocationEvent(aCallback, this); + if (SUCCEEDED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) { + mWatching = true; + return NS_OK; + } + } + + // Cannot use Location API. We will use MLS instead. + LOG(" > MLS fallback\n"); + mLocation = nullptr; + + return CreateAndWatchMLSProvider(aCallback); +} + +NS_IMETHODIMP +WindowsLocationProvider::Shutdown() { + LOG("WindowsLocationProvider::Shutdown(%p, %p)\n", this, mLocation.get()); + if (mLocation) { + if (mWatching) { + mLocation->UnregisterForReport(IID_ILatLongReport); + } + mLocation = nullptr; + mWatching = false; + } + + CancelMLSProvider(); + return NS_OK; +} + +NS_IMETHODIMP +WindowsLocationProvider::SetHighAccuracy(bool enable) { + if (!mLocation) { + // MLS provider doesn't support HighAccuracy + return NS_OK; + } + + LOCATION_DESIRED_ACCURACY desiredAccuracy; + if (enable) { + desiredAccuracy = LOCATION_DESIRED_ACCURACY_HIGH; + } else { + desiredAccuracy = LOCATION_DESIRED_ACCURACY_DEFAULT; + } + if (FAILED( + mLocation->SetDesiredAccuracy(IID_ILatLongReport, desiredAccuracy))) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +nsresult WindowsLocationProvider::CreateAndWatchMLSProvider( + nsIGeolocationUpdate* aCallback) { + if (mMLSProvider) { + return NS_OK; + } + + mMLSProvider = new MLSFallback(0); + return mMLSProvider->Startup(new MLSUpdate(aCallback)); +} + +void WindowsLocationProvider::CancelMLSProvider() { + if (!mMLSProvider) { + return; + } + + mMLSProvider->Shutdown(); + mMLSProvider = nullptr; +} + +#undef LOG + +} // namespace mozilla::dom diff --git a/dom/system/windows/WindowsLocationProvider.h b/dom/system/windows/WindowsLocationProvider.h new file mode 100644 index 0000000000..779236d003 --- /dev/null +++ b/dom/system/windows/WindowsLocationProvider.h @@ -0,0 +1,50 @@ +/* -*- 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_WindowsLocationProvider_h__ +#define mozilla_dom_WindowsLocationProvider_h__ + +#include "nsCOMPtr.h" +#include "nsIGeolocationProvider.h" + +#include <locationapi.h> + +class MLSFallback; + +namespace mozilla::dom { + +class WindowsLocationProvider final : public nsIGeolocationProvider { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGEOLOCATIONPROVIDER + + WindowsLocationProvider(); + + nsresult CreateAndWatchMLSProvider(nsIGeolocationUpdate* aCallback); + void CancelMLSProvider(); + + class MLSUpdate : public nsIGeolocationUpdate { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGEOLOCATIONUPDATE + explicit MLSUpdate(nsIGeolocationUpdate* aCallback); + + private: + nsCOMPtr<nsIGeolocationUpdate> mCallback; + virtual ~MLSUpdate() {} + }; + + private: + ~WindowsLocationProvider(); + + RefPtr<ILocation> mLocation; + RefPtr<MLSFallback> mMLSProvider; + bool mWatching = false; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_WindowsLocationProvider_h__ diff --git a/dom/system/windows/moz.build b/dom/system/windows/moz.build new file mode 100644 index 0000000000..45131af39e --- /dev/null +++ b/dom/system/windows/moz.build @@ -0,0 +1,11 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SOURCES += ["nsHapticFeedback.cpp", "WindowsLocationProvider.cpp"] + +LOCAL_INCLUDES += ["/dom/geolocation"] + +FINAL_LIBRARY = "xul" diff --git a/dom/system/windows/nsHapticFeedback.cpp b/dom/system/windows/nsHapticFeedback.cpp new file mode 100644 index 0000000000..f85c5889d9 --- /dev/null +++ b/dom/system/windows/nsHapticFeedback.cpp @@ -0,0 +1,15 @@ +/* -*- 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 "nsHapticFeedback.h" + +NS_IMPL_ISUPPORTS(nsHapticFeedback, nsIHapticFeedback) + +NS_IMETHODIMP +nsHapticFeedback::PerformSimpleAction(int32_t aType) { + // Todo + return NS_OK; +} diff --git a/dom/system/windows/nsHapticFeedback.h b/dom/system/windows/nsHapticFeedback.h new file mode 100644 index 0000000000..b15cb00f31 --- /dev/null +++ b/dom/system/windows/nsHapticFeedback.h @@ -0,0 +1,15 @@ +/* -*- 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 "nsIHapticFeedback.h" + +class nsHapticFeedback final : public nsIHapticFeedback { + ~nsHapticFeedback() {} + + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIHAPTICFEEDBACK +}; |