Bug 1466213 part 1. Move PositionError out into a separate file. r=qdot
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 01 Jun 2018 22:35:42 -0400
changeset 475184 886337516a045b3188f3618b05ff720e44dfbae0
parent 475183 ab9cf549cd35888c14fdc97155d50191baf4fca6
child 475185 5aebceb74c3a300842742f0dcc2cbee67da31d97
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1466213
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1466213 part 1. Move PositionError out into a separate file. r=qdot
dom/bindings/Bindings.conf
dom/geolocation/PositionError.cpp
dom/geolocation/PositionError.h
dom/geolocation/moz.build
dom/geolocation/nsGeolocation.cpp
dom/geolocation/nsGeolocation.h
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -678,20 +678,16 @@ DOMInterfaces = {
 'PluginTag': {
     'nativeType': 'nsIPluginTag',
 },
 
 'Position': {
     'headerFile': 'nsGeoPosition.h'
 },
 
-'PositionError': {
-    'headerFile': 'nsGeolocation.h'
-},
-
 'PromiseDebugging': {
     'concrete': False,
 },
 
 'PromiseNativeHandler': {
     'wrapperCache': False,
 },
 
copy from dom/geolocation/nsGeolocation.cpp
copy to dom/geolocation/PositionError.cpp
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/PositionError.cpp
@@ -1,232 +1,20 @@
 /* -*- 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 "mozilla/dom/PositionError.h"
+#include "mozilla/dom/PositionErrorBinding.h"
 #include "nsGeolocation.h"
 
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/PermissionMessageUtils.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Services.h"
-#include "mozilla/Telemetry.h"
-#include "mozilla/UniquePtr.h"
-#include "mozilla/Unused.h"
-#include "mozilla/WeakPtr.h"
-#include "mozilla/EventStateManager.h"
-#include "nsComponentManagerUtils.h"
-#include "nsContentPermissionHelper.h"
-#include "nsContentUtils.h"
-#include "nsGlobalWindow.h"
-#include "nsIDocument.h"
-#include "nsINamed.h"
-#include "nsIObserverService.h"
-#include "nsIScriptError.h"
-#include "nsPIDOMWindow.h"
-#include "nsServiceManagerUtils.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-
-class nsIPrincipal;
-
-#ifdef MOZ_WIDGET_ANDROID
-#include "AndroidLocationProvider.h"
-#endif
-
-#ifdef MOZ_GPSD
-#include "GpsdLocationProvider.h"
-#endif
-
-#ifdef MOZ_WIDGET_COCOA
-#include "CoreLocationLocationProvider.h"
-#endif
-
-#ifdef XP_WIN
-#include "WindowsLocationProvider.h"
-#include "mozilla/WindowsVersion.h"
-#endif
-
-// Some limit to the number of get or watch geolocation requests
-// that a window can make.
-#define MAX_GEO_REQUESTS_PER_WINDOW  1500
-
-// This preference allows to override the "secure context" by
-// default policy.
-#define PREF_GEO_SECURITY_ALLOWINSECURE "geo.security.allowinsecure"
-
-using mozilla::Unused;          // <snicker>
-using namespace mozilla;
-using namespace mozilla::dom;
-
-class nsGeolocationRequest final
- : public nsIContentPermissionRequest
- , public nsIGeolocationUpdate
- , public SupportsWeakPtr<nsGeolocationRequest>
-{
- public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_NSICONTENTPERMISSIONREQUEST
-  NS_DECL_NSIGEOLOCATIONUPDATE
-
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
-
-  nsGeolocationRequest(Geolocation* aLocator,
-                       GeoPositionCallback aCallback,
-                       GeoPositionErrorCallback aErrorCallback,
-                       UniquePtr<PositionOptions>&& aOptions,
-                       uint8_t aProtocolType,
-                       nsIEventTarget* aMainThreadTarget,
-                       bool aWatchPositionRequest = false,
-                       bool aIsHandlingUserInput = false,
-                       int32_t aWatchId = 0);
-
-  MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsGeolocationRequest)
-
-  void Shutdown();
-
-  void SendLocation(nsIDOMGeoPosition* aLocation);
-  bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->mEnableHighAccuracy;}
-  void SetTimeoutTimer();
-  void StopTimeoutTimer();
-  void NotifyErrorAndShutdown(uint16_t);
-  nsIPrincipal* GetPrincipal();
-
-  bool IsWatch() { return mIsWatchPositionRequest; }
-  int32_t WatchId() { return mWatchId; }
- private:
-  virtual ~nsGeolocationRequest();
-
-  class TimerCallbackHolder final : public nsITimerCallback
-                                  , public nsINamed
-  {
-  public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSITIMERCALLBACK
-
-    explicit TimerCallbackHolder(nsGeolocationRequest* aRequest)
-      : mRequest(aRequest)
-    {}
-
-    NS_IMETHOD GetName(nsACString& aName) override
-    {
-      aName.AssignLiteral("nsGeolocationRequest::TimerCallbackHolder");
-      return NS_OK;
-    }
-
-  private:
-    ~TimerCallbackHolder() = default;
-    WeakPtr<nsGeolocationRequest> mRequest;
-  };
-
-  void Notify();
-
-  bool mIsWatchPositionRequest;
-
-  nsCOMPtr<nsITimer> mTimeoutTimer;
-  GeoPositionCallback mCallback;
-  GeoPositionErrorCallback mErrorCallback;
-  UniquePtr<PositionOptions> mOptions;
-  bool mIsHandlingUserInput;
-
-  RefPtr<Geolocation> mLocator;
-
-  int32_t mWatchId;
-  bool mShutdown;
-  nsCOMPtr<nsIContentPermissionRequester> mRequester;
-  uint8_t mProtocolType;
-  nsCOMPtr<nsIEventTarget> mMainThreadTarget;
-};
-
-static UniquePtr<PositionOptions>
-CreatePositionOptionsCopy(const PositionOptions& aOptions)
-{
-  UniquePtr<PositionOptions> geoOptions = MakeUnique<PositionOptions>();
-
-  geoOptions->mEnableHighAccuracy = aOptions.mEnableHighAccuracy;
-  geoOptions->mMaximumAge = aOptions.mMaximumAge;
-  geoOptions->mTimeout = aOptions.mTimeout;
-
-  return geoOptions;
-}
-
-class RequestPromptEvent : public Runnable
-{
-public:
-  RequestPromptEvent(nsGeolocationRequest* aRequest, nsWeakPtr aWindow)
-    : mozilla::Runnable("RequestPromptEvent")
-    , mRequest(aRequest)
-    , mWindow(aWindow)
-  {
-  }
-
-  NS_IMETHOD Run() override
-  {
-    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow);
-    nsContentPermissionUtils::AskPermission(mRequest, window);
-    return NS_OK;
-  }
-
-private:
-  RefPtr<nsGeolocationRequest> mRequest;
-  nsWeakPtr mWindow;
-};
-
-class RequestAllowEvent : public Runnable
-{
-public:
-  RequestAllowEvent(int allow, nsGeolocationRequest* request)
-    : mozilla::Runnable("RequestAllowEvent")
-    , mAllow(allow)
-    , mRequest(request)
-  {
-  }
-
-  NS_IMETHOD Run() override {
-    if (mAllow) {
-      mRequest->Allow(JS::UndefinedHandleValue);
-    } else {
-      mRequest->Cancel();
-    }
-    return NS_OK;
-  }
-
-private:
-  bool mAllow;
-  RefPtr<nsGeolocationRequest> mRequest;
-};
-
-class RequestSendLocationEvent : public Runnable
-{
-public:
-  RequestSendLocationEvent(nsIDOMGeoPosition* aPosition,
-                           nsGeolocationRequest* aRequest)
-    : mozilla::Runnable("RequestSendLocationEvent")
-    , mPosition(aPosition)
-    , mRequest(aRequest)
-  {
-  }
-
-  NS_IMETHOD Run() override {
-    mRequest->SendLocation(mPosition);
-    return NS_OK;
-  }
-
-private:
-  nsCOMPtr<nsIDOMGeoPosition> mPosition;
-  RefPtr<nsGeolocationRequest> mRequest;
-  RefPtr<Geolocation> mLocator;
-};
-
-////////////////////////////////////////////////////
-// PositionError
-////////////////////////////////////////////////////
+namespace mozilla {
+namespace dom {
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PositionError)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionError)
   NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionError)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PositionError, mParent)
@@ -265,17 +53,17 @@ PositionError::GetMessage(nsAString& aMe
       aMessage = NS_LITERAL_STRING("Position acquisition timed out");
       break;
     default:
       break;
   }
   return NS_OK;
 }
 
-Geolocation*
+nsWrapperCache*
 PositionError::GetParentObject() const
 {
   return mParent;
 }
 
 JSObject*
 PositionError::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
@@ -294,1194 +82,12 @@ PositionError::NotifyCallback(const GeoP
     }
   } else {
     nsIDOMGeoPositionErrorCallback* callback = aCallback.GetXPCOMCallback();
     if (callback) {
       callback->HandleEvent(this);
     }
   }
 }
-////////////////////////////////////////////////////
-// nsGeolocationRequest
-////////////////////////////////////////////////////
-
-nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
-                                           GeoPositionCallback aCallback,
-                                           GeoPositionErrorCallback aErrorCallback,
-                                           UniquePtr<PositionOptions>&& aOptions,
-                                           uint8_t aProtocolType,
-                                           nsIEventTarget* aMainThreadTarget,
-                                           bool aWatchPositionRequest,
-                                           bool aIsHandlingUserInput,
-                                           int32_t aWatchId)
-  : mIsWatchPositionRequest(aWatchPositionRequest),
-    mCallback(std::move(aCallback)),
-    mErrorCallback(std::move(aErrorCallback)),
-    mOptions(std::move(aOptions)),
-    mIsHandlingUserInput(aIsHandlingUserInput),
-    mLocator(aLocator),
-    mWatchId(aWatchId),
-    mShutdown(false),
-    mProtocolType(aProtocolType),
-    mMainThreadTarget(aMainThreadTarget)
-{
-  if (nsCOMPtr<nsPIDOMWindowInner> win =
-      do_QueryReferent(mLocator->GetOwner())) {
-    mRequester = new nsContentPermissionRequester(win);
-  }
-}
-
-nsGeolocationRequest::~nsGeolocationRequest()
-{
-  StopTimeoutTimer();
-}
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGeolocationRequest)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
-  NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
-  NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGeolocationRequest)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocationRequest)
-NS_IMPL_CYCLE_COLLECTION(nsGeolocationRequest, mCallback, mErrorCallback, mLocator)
-
-void
-nsGeolocationRequest::Notify()
-{
-  SetTimeoutTimer();
-  NotifyErrorAndShutdown(nsIDOMGeoPositionError::TIMEOUT);
-}
-
-void
-nsGeolocationRequest::NotifyErrorAndShutdown(uint16_t aErrorCode)
-{
-  MOZ_ASSERT(!mShutdown, "timeout after shutdown");
-  if (!mIsWatchPositionRequest) {
-    Shutdown();
-    mLocator->RemoveRequest(this);
-  }
-
-  NotifyError(aErrorCode);
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
-{
-  NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
-
-  nsCOMPtr<nsIPrincipal> principal = mLocator->GetPrincipal();
-  principal.forget(aRequestingPrincipal);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::GetTypes(nsIArray** aTypes)
-{
-  nsTArray<nsString> emptyOptions;
-  return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("geolocation"),
-                                                         NS_LITERAL_CSTRING("unused"),
-                                                         emptyOptions,
-                                                         aTypes);
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::GetWindow(mozIDOMWindow** aRequestingWindow)
-{
-  NS_ENSURE_ARG_POINTER(aRequestingWindow);
-
-  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mLocator->GetOwner());
-  window.forget(aRequestingWindow);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::GetElement(Element** aRequestingElement)
-{
-  NS_ENSURE_ARG_POINTER(aRequestingElement);
-  *aRequestingElement = nullptr;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::GetIsHandlingUserInput(bool* aIsHandlingUserInput)
-{
-  *aIsHandlingUserInput = mIsHandlingUserInput;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::Cancel()
-{
-  if (mRequester) {
-    // Record the number of denied requests for regular web content.
-    // This method is only called when the user explicitly denies the request,
-    // and is not called when the page is simply unloaded, or similar.
-    Telemetry::Accumulate(Telemetry::GEOLOCATION_REQUEST_GRANTED, mProtocolType);
-  }
-
-  if (mLocator->ClearPendingRequest(this)) {
-    return NS_OK;
-  }
-
-  NotifyError(nsIDOMGeoPositionError::PERMISSION_DENIED);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::Allow(JS::HandleValue aChoices)
-{
-  MOZ_ASSERT(aChoices.isUndefined());
-
-  if (mRequester) {
-    // Record the number of granted requests for regular web content.
-    Telemetry::Accumulate(Telemetry::GEOLOCATION_REQUEST_GRANTED, mProtocolType + 10);
-
-    // Record whether a location callback is fulfilled while the owner window
-    // is not visible.
-    bool isVisible = false;
-    nsCOMPtr<nsPIDOMWindowInner> window = mLocator->GetParentObject();
-
-    if (window) {
-      nsCOMPtr<nsIDocument> doc = window->GetDoc();
-      isVisible = doc && !doc->Hidden();
-    }
-
-    if (IsWatch()) {
-      mozilla::Telemetry::Accumulate(mozilla::Telemetry::GEOLOCATION_WATCHPOSITION_VISIBLE, isVisible);
-    } else {
-      mozilla::Telemetry::Accumulate(mozilla::Telemetry::GEOLOCATION_GETCURRENTPOSITION_VISIBLE, isVisible);
-    }
-  }
-
-  if (mLocator->ClearPendingRequest(this)) {
-    return NS_OK;
-  }
-
-  RefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
-
-  bool canUseCache = false;
-  CachedPositionAndAccuracy lastPosition = gs->GetCachedPosition();
-  if (lastPosition.position) {
-    DOMTimeStamp cachedPositionTime_ms;
-    lastPosition.position->GetTimestamp(&cachedPositionTime_ms);
-    // check to see if we can use a cached value
-    // if the user has specified a maximumAge, return a cached value.
-    if (mOptions && mOptions->mMaximumAge > 0) {
-      uint32_t maximumAge_ms = mOptions->mMaximumAge;
-      bool isCachedWithinRequestedAccuracy = WantsHighAccuracy() <= lastPosition.isHighAccuracy;
-      bool isCachedWithinRequestedTime =
-        DOMTimeStamp(PR_Now() / PR_USEC_PER_MSEC - maximumAge_ms) <= cachedPositionTime_ms;
-      canUseCache = isCachedWithinRequestedAccuracy && isCachedWithinRequestedTime;
-    }
-  }
-
-  gs->UpdateAccuracy(WantsHighAccuracy());
-  if (canUseCache) {
-    // okay, we can return a cached position
-    // getCurrentPosition requests serviced by the cache
-    // will now be owned by the RequestSendLocationEvent
-    Update(lastPosition.position);
-
-    // After Update is called, getCurrentPosition finishes it's job.
-    if (!mIsWatchPositionRequest) {
-      return NS_OK;
-    }
-
-  } else {
-    // if it is not a watch request and timeout is 0,
-    // invoke the errorCallback (if present) with TIMEOUT code
-    if (mOptions && mOptions->mTimeout == 0 && !mIsWatchPositionRequest) {
-      NotifyError(nsIDOMGeoPositionError::TIMEOUT);
-      return NS_OK;
-    }
-
-  }
-
-  // Kick off the geo device, if it isn't already running
-  nsresult rv = gs->StartDevice(GetPrincipal());
-
-  if (NS_FAILED(rv)) {
-    // Location provider error
-    NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
-    return NS_OK;
-  }
-
-  if (mIsWatchPositionRequest || !canUseCache) {
-    // let the locator know we're pending
-    // we will now be owned by the locator
-    mLocator->NotifyAllowedRequest(this);
-  }
-
-  SetTimeoutTimer();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
-{
-  NS_ENSURE_ARG_POINTER(aRequester);
-
-  nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
-  requester.forget(aRequester);
-
-  return NS_OK;
-}
-
-void
-nsGeolocationRequest::SetTimeoutTimer()
-{
-  MOZ_ASSERT(!mShutdown, "set timeout after shutdown");
-
-  StopTimeoutTimer();
-
-  if (mOptions && mOptions->mTimeout != 0 && mOptions->mTimeout != 0x7fffffff) {
-    RefPtr<TimerCallbackHolder> holder = new TimerCallbackHolder(this);
-    NS_NewTimerWithCallback(getter_AddRefs(mTimeoutTimer),
-                            holder, mOptions->mTimeout, nsITimer::TYPE_ONE_SHOT);
-  }
-}
-
-void
-nsGeolocationRequest::StopTimeoutTimer()
-{
-  if (mTimeoutTimer) {
-    mTimeoutTimer->Cancel();
-    mTimeoutTimer = nullptr;
-  }
-}
-
-void
-nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
-{
-  if (mShutdown) {
-    // Ignore SendLocationEvents issued before we were cleared.
-    return;
-  }
-
-  if (mOptions && mOptions->mMaximumAge > 0) {
-    DOMTimeStamp positionTime_ms;
-    aPosition->GetTimestamp(&positionTime_ms);
-    const uint32_t maximumAge_ms = mOptions->mMaximumAge;
-    const bool isTooOld =
-        DOMTimeStamp(PR_Now() / PR_USEC_PER_MSEC - maximumAge_ms) > positionTime_ms;
-    if (isTooOld) {
-      return;
-    }
-  }
-
-  RefPtr<mozilla::dom::Position> wrapped;
-
-  if (aPosition) {
-    nsCOMPtr<nsIDOMGeoPositionCoords> coords;
-    aPosition->GetCoords(getter_AddRefs(coords));
-    if (coords) {
-      wrapped = new mozilla::dom::Position(ToSupports(mLocator), aPosition);
-    }
-  }
-
-  if (!wrapped) {
-    NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
-    return;
-  }
-
-  if (!mIsWatchPositionRequest) {
-    // Cancel timer and position updates in case the position
-    // callback spins the event loop
-    Shutdown();
-  }
-
-  nsAutoMicroTask mt;
-  if (mCallback.HasWebIDLCallback()) {
-    PositionCallback* callback = mCallback.GetWebIDLCallback();
-
-    MOZ_ASSERT(callback);
-    callback->Call(*wrapped);
-  } else {
-    nsIDOMGeoPositionCallback* callback = mCallback.GetXPCOMCallback();
-    MOZ_ASSERT(callback);
-    callback->HandleEvent(aPosition);
-  }
-
-  if (mIsWatchPositionRequest && !mShutdown) {
-    SetTimeoutTimer();
-  }
-  MOZ_ASSERT(mShutdown || mIsWatchPositionRequest,
-             "non-shutdown getCurrentPosition request after callback!");
-}
-
-nsIPrincipal*
-nsGeolocationRequest::GetPrincipal()
-{
-  if (!mLocator) {
-    return nullptr;
-  }
-  return mLocator->GetPrincipal();
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition)
-{
-  nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(aPosition, this);
-  mMainThreadTarget->Dispatch(ev.forget());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationRequest::NotifyError(uint16_t aErrorCode)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  RefPtr<PositionError> positionError = new PositionError(mLocator, aErrorCode);
-  positionError->NotifyCallback(mErrorCallback);
-  return NS_OK;
-}
-
-void
-nsGeolocationRequest::Shutdown()
-{
-  MOZ_ASSERT(!mShutdown, "request shutdown twice");
-  mShutdown = true;
-
-  StopTimeoutTimer();
-
-  // If there are no other high accuracy requests, the geolocation service will
-  // notify the provider to switch to the default accuracy.
-  if (mOptions && mOptions->mEnableHighAccuracy) {
-    RefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
-    if (gs) {
-      gs->UpdateAccuracy();
-    }
-  }
-}
-
-
-////////////////////////////////////////////////////
-// nsGeolocationRequest::TimerCallbackHolder
-////////////////////////////////////////////////////
-
-NS_IMPL_ISUPPORTS(nsGeolocationRequest::TimerCallbackHolder,
-                  nsITimerCallback,
-                  nsINamed)
-
-NS_IMETHODIMP
-nsGeolocationRequest::TimerCallbackHolder::Notify(nsITimer*)
-{
-  if (mRequest && mRequest->mLocator) {
-    RefPtr<nsGeolocationRequest> request(mRequest);
-    request->Notify();
-  }
-
-  return NS_OK;
-}
-
-
-////////////////////////////////////////////////////
-// nsGeolocationService
-////////////////////////////////////////////////////
-NS_INTERFACE_MAP_BEGIN(nsGeolocationService)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGeolocationUpdate)
-  NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
-  NS_INTERFACE_MAP_ENTRY(nsIObserver)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_ADDREF(nsGeolocationService)
-NS_IMPL_RELEASE(nsGeolocationService)
-
-
-static bool sGeoEnabled = true;
-static int32_t sProviderTimeout = 6000; // Time, in milliseconds, to wait for the location provider to spin up.
-
-nsresult nsGeolocationService::Init()
-{
-  Preferences::AddIntVarCache(&sProviderTimeout, "geo.timeout", sProviderTimeout);
-  Preferences::AddBoolVarCache(&sGeoEnabled, "geo.enabled", sGeoEnabled);
-
-  if (!sGeoEnabled) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (XRE_IsContentProcess()) {
-    return NS_OK;
-  }
-
-  // geolocation service can be enabled -> now register observer
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return NS_ERROR_FAILURE;
-  }
-
-  obs->AddObserver(this, "xpcom-shutdown", false);
-
-#ifdef MOZ_WIDGET_ANDROID
-  mProvider = new AndroidLocationProvider();
-#endif
-
-#ifdef MOZ_WIDGET_GTK
-#ifdef MOZ_GPSD
-  if (Preferences::GetBool("geo.provider.use_gpsd", false)) {
-    mProvider = new GpsdLocationProvider();
-  }
-#endif
-#endif
-
-#ifdef MOZ_WIDGET_COCOA
-  if (Preferences::GetBool("geo.provider.use_corelocation", true)) {
-    mProvider = new CoreLocationLocationProvider();
-  }
-#endif
-
-#ifdef XP_WIN
-  if (Preferences::GetBool("geo.provider.ms-windows-location", false) &&
-      IsWin8OrLater()) {
-    mProvider = new WindowsLocationProvider();
-  }
-#endif
-
-  if (Preferences::GetBool("geo.provider.use_mls", false)) {
-    mProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1");
-  }
-
-  // Override platform-specific providers with the default (network)
-  // provider while testing. Our tests are currently not meant to exercise
-  // the provider, and some tests rely on the network provider being used.
-  // "geo.provider.testing" is always set for all plain and browser chrome
-  // mochitests, and also for xpcshell tests.
-  if (!mProvider || Preferences::GetBool("geo.provider.testing", false)) {
-    nsCOMPtr<nsIGeolocationProvider> geoTestProvider =
-      do_GetService(NS_GEOLOCATION_PROVIDER_CONTRACTID);
-
-    if (geoTestProvider) {
-      mProvider = geoTestProvider;
-    }
-  }
-
-  return NS_OK;
-}
-
-nsGeolocationService::~nsGeolocationService() = default;
-
-NS_IMETHODIMP
-nsGeolocationService::Observe(nsISupports* aSubject,
-                              const char* aTopic,
-                              const char16_t* aData)
-{
-  if (!strcmp("xpcom-shutdown", aTopic)) {
-    nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-    if (obs) {
-      obs->RemoveObserver(this, "xpcom-shutdown");
-    }
-
-    for (uint32_t i = 0; i< mGeolocators.Length(); i++) {
-      mGeolocators[i]->Shutdown();
-    }
-    StopDevice();
-
-    return NS_OK;
-  }
-
-  if (!strcmp("timer-callback", aTopic)) {
-    // decide if we can close down the service.
-    for (uint32_t i = 0; i< mGeolocators.Length(); i++)
-      if (mGeolocators[i]->HasActiveCallbacks()) {
-        SetDisconnectTimer();
-        return NS_OK;
-      }
-
-    // okay to close up.
-    StopDevice();
-    Update(nullptr);
-    return NS_OK;
-  }
-
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsGeolocationService::Update(nsIDOMGeoPosition *aSomewhere)
-{
-  if (aSomewhere) {
-    SetCachedPosition(aSomewhere);
-  }
-
-  for (uint32_t i = 0; i< mGeolocators.Length(); i++) {
-    mGeolocators[i]->Update(aSomewhere);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGeolocationService::NotifyError(uint16_t aErrorCode)
-{
-  for (uint32_t i = 0; i < mGeolocators.Length(); i++) {
-    mGeolocators[i]->NotifyError(aErrorCode);
-  }
-  return NS_OK;
-}
-
-void
-nsGeolocationService::SetCachedPosition(nsIDOMGeoPosition* aPosition)
-{
-  mLastPosition.position = aPosition;
-  mLastPosition.isHighAccuracy = mHigherAccuracy;
-}
-
-CachedPositionAndAccuracy
-nsGeolocationService::GetCachedPosition()
-{
-  return mLastPosition;
-}
-
-nsresult
-nsGeolocationService::StartDevice(nsIPrincipal *aPrincipal)
-{
-  if (!sGeoEnabled) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // We do not want to keep the geolocation devices online
-  // indefinitely.
-  // Close them down after a reasonable period of inactivivity.
-  SetDisconnectTimer();
-
-  if (XRE_IsContentProcess()) {
-    ContentChild* cpc = ContentChild::GetSingleton();
-    cpc->SendAddGeolocationListener(IPC::Principal(aPrincipal),
-                                    HighAccuracyRequested());
-    return NS_OK;
-  }
-
-  // Start them up!
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (!mProvider) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsresult rv;
-
-  if (NS_FAILED(rv = mProvider->Startup()) ||
-      NS_FAILED(rv = mProvider->Watch(this))) {
-
-    NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
-    return rv;
-  }
-
-  obs->NotifyObservers(mProvider,
-                       "geolocation-device-events",
-                       u"starting");
-
-  return NS_OK;
-}
-
-void
-nsGeolocationService::SetDisconnectTimer()
-{
-  if (!mDisconnectTimer) {
-    mDisconnectTimer = NS_NewTimer();
-  } else {
-    mDisconnectTimer->Cancel();
-  }
-
-  mDisconnectTimer->Init(this,
-                         sProviderTimeout,
-                         nsITimer::TYPE_ONE_SHOT);
-}
 
-bool
-nsGeolocationService::HighAccuracyRequested()
-{
-  for (uint32_t i = 0; i < mGeolocators.Length(); i++) {
-    if (mGeolocators[i]->HighAccuracyRequested()) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-void
-nsGeolocationService::UpdateAccuracy(bool aForceHigh)
-{
-  bool highRequired = aForceHigh || HighAccuracyRequested();
-
-  if (XRE_IsContentProcess()) {
-    ContentChild* cpc = ContentChild::GetSingleton();
-    if (cpc->IsAlive()) {
-      cpc->SendSetGeolocationHigherAccuracy(highRequired);
-    }
-
-    return;
-  }
-
-  mProvider->SetHighAccuracy(!mHigherAccuracy && highRequired);
-  mHigherAccuracy = highRequired;
-}
-
-void
-nsGeolocationService::StopDevice()
-{
-  if (mDisconnectTimer) {
-    mDisconnectTimer->Cancel();
-    mDisconnectTimer = nullptr;
-  }
-
-  if (XRE_IsContentProcess()) {
-    ContentChild* cpc = ContentChild::GetSingleton();
-    cpc->SendRemoveGeolocationListener();
-
-    return; // bail early
-  }
-
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return;
-  }
-
-  if (!mProvider) {
-    return;
-  }
-
-  mHigherAccuracy = false;
-
-  mProvider->Shutdown();
-  obs->NotifyObservers(mProvider,
-                       "geolocation-device-events",
-                       u"shutdown");
-}
-
-StaticRefPtr<nsGeolocationService> nsGeolocationService::sService;
-
-already_AddRefed<nsGeolocationService>
-nsGeolocationService::GetGeolocationService()
-{
-  RefPtr<nsGeolocationService> result;
-  if (nsGeolocationService::sService) {
-    result = nsGeolocationService::sService;
-
-    return result.forget();
-  }
-
-  result = new nsGeolocationService();
-  if (NS_FAILED(result->Init())) {
-    return nullptr;
-  }
-
-  ClearOnShutdown(&nsGeolocationService::sService);
-  nsGeolocationService::sService = result;
-  return result.forget();
-}
-
-void
-nsGeolocationService::AddLocator(Geolocation* aLocator)
-{
-  mGeolocators.AppendElement(aLocator);
-}
-
-void
-nsGeolocationService::RemoveLocator(Geolocation* aLocator)
-{
-  mGeolocators.RemoveElement(aLocator);
-}
-
-////////////////////////////////////////////////////
-// Geolocation
-////////////////////////////////////////////////////
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Geolocation)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoGeolocation)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMGeoGeolocation)
-  NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(Geolocation)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(Geolocation)
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Geolocation,
-                                      mPendingCallbacks,
-                                      mWatchingCallbacks,
-                                      mPendingRequests)
-
-Geolocation::Geolocation()
-: mProtocolType(ProtocolType::OTHER)
-, mLastWatchId(0)
-{
-}
-
-Geolocation::~Geolocation()
-{
-  if (mService) {
-    Shutdown();
-  }
-}
-
-nsresult
-Geolocation::Init(nsPIDOMWindowInner* aContentDom)
-{
-  // Remember the window
-  if (aContentDom) {
-    mOwner = do_GetWeakReference(aContentDom);
-    if (!mOwner) {
-      return NS_ERROR_FAILURE;
-    }
-
-    // Grab the principal of the document
-    nsCOMPtr<nsIDocument> doc = aContentDom->GetDoc();
-    if (!doc) {
-      return NS_ERROR_FAILURE;
-    }
-
-    mPrincipal = doc->NodePrincipal();
-
-    nsCOMPtr<nsIURI> uri;
-    nsresult rv = mPrincipal->GetURI(getter_AddRefs(uri));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (uri) {
-      bool isHttp;
-      rv = uri->SchemeIs("http", &isHttp);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      bool isHttps;
-      rv = uri->SchemeIs("https", &isHttps);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      // Store the protocol to send via telemetry later.
-      if (isHttp) {
-        mProtocolType = ProtocolType::HTTP;
-      } else if (isHttps) {
-        mProtocolType = ProtocolType::HTTPS;
-      }
-    }
-  }
-
-  // If no aContentDom was passed into us, we are being used
-  // by chrome/c++ and have no mOwner, no mPrincipal, and no need
-  // to prompt.
-  mService = nsGeolocationService::GetGeolocationService();
-  if (mService) {
-    mService->AddLocator(this);
-  }
-
-  return NS_OK;
-}
-
-void
-Geolocation::Shutdown()
-{
-  // Release all callbacks
-  mPendingCallbacks.Clear();
-  mWatchingCallbacks.Clear();
-
-  if (mService) {
-    mService->RemoveLocator(this);
-    mService->UpdateAccuracy();
-  }
-
-  mService = nullptr;
-  mPrincipal = nullptr;
-}
-
-nsPIDOMWindowInner*
-Geolocation::GetParentObject() const {
-  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mOwner);
-  return window.get();
-}
-
-bool
-Geolocation::HasActiveCallbacks()
-{
-  return mPendingCallbacks.Length() || mWatchingCallbacks.Length();
-}
-
-bool
-Geolocation::HighAccuracyRequested()
-{
-  for (uint32_t i = 0; i < mWatchingCallbacks.Length(); i++) {
-    if (mWatchingCallbacks[i]->WantsHighAccuracy()) {
-      return true;
-    }
-  }
-
-  for (uint32_t i = 0; i < mPendingCallbacks.Length(); i++) {
-    if (mPendingCallbacks[i]->WantsHighAccuracy()) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-void
-Geolocation::RemoveRequest(nsGeolocationRequest* aRequest)
-{
-  bool requestWasKnown =
-    (mPendingCallbacks.RemoveElement(aRequest) !=
-     mWatchingCallbacks.RemoveElement(aRequest));
-
-  Unused << requestWasKnown;
-}
-
-NS_IMETHODIMP
-Geolocation::Update(nsIDOMGeoPosition *aSomewhere)
-{
-  if (!WindowOwnerStillExists()) {
-    Shutdown();
-    return NS_OK;
-  }
-
-  if (aSomewhere) {
-    nsCOMPtr<nsIDOMGeoPositionCoords> coords;
-    aSomewhere->GetCoords(getter_AddRefs(coords));
-    if (coords) {
-      double accuracy = -1;
-      coords->GetAccuracy(&accuracy);
-      mozilla::Telemetry::Accumulate(mozilla::Telemetry::GEOLOCATION_ACCURACY_EXPONENTIAL, accuracy);
-    }
-  }
-
-  for (uint32_t i = mPendingCallbacks.Length(); i > 0; i--) {
-    mPendingCallbacks[i-1]->Update(aSomewhere);
-    RemoveRequest(mPendingCallbacks[i-1]);
-  }
-
-  // notify everyone that is watching
-  for (uint32_t i = 0; i < mWatchingCallbacks.Length(); i++) {
-    mWatchingCallbacks[i]->Update(aSomewhere);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-Geolocation::NotifyError(uint16_t aErrorCode)
-{
-  if (!WindowOwnerStillExists()) {
-    Shutdown();
-    return NS_OK;
-  }
-
-  mozilla::Telemetry::Accumulate(mozilla::Telemetry::GEOLOCATION_ERROR, true);
-
-  for (uint32_t i = mPendingCallbacks.Length(); i > 0; i--) {
-    mPendingCallbacks[i-1]->NotifyErrorAndShutdown(aErrorCode);
-    //NotifyErrorAndShutdown() removes the request from the array
-  }
-
-  // notify everyone that is watching
-  for (uint32_t i = 0; i < mWatchingCallbacks.Length(); i++) {
-    mWatchingCallbacks[i]->NotifyErrorAndShutdown(aErrorCode);
-  }
-
-  return NS_OK;
-}
+} // namespace mozilla
+} // namespace dom
 
-bool
-Geolocation::IsAlreadyCleared(nsGeolocationRequest* aRequest)
-{
-  for (uint32_t i = 0, length = mClearedWatchIDs.Length(); i < length; ++i) {
-    if (mClearedWatchIDs[i] == aRequest->WatchId()) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool
-Geolocation::ShouldBlockInsecureRequests() const
-{
-  if (Preferences::GetBool(PREF_GEO_SECURITY_ALLOWINSECURE, false)) {
-    return false;
-  }
-
-  nsCOMPtr<nsPIDOMWindowInner> win = do_QueryReferent(mOwner);
-  if (!win) {
-    return false;
-  }
-
-  nsCOMPtr<nsIDocument> doc = win->GetDoc();
-  if (!doc) {
-    return false;
-  }
-
-  if (!nsGlobalWindowInner::Cast(win)->IsSecureContext()) {
-    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,
-                                    NS_LITERAL_CSTRING("DOM"), doc,
-                                    nsContentUtils::eDOM_PROPERTIES,
-                                    "GeolocationInsecureRequestIsForbidden");
-    return true;
-  }
-
-  return false;
-}
-
-bool
-Geolocation::ClearPendingRequest(nsGeolocationRequest* aRequest)
-{
-  if (aRequest->IsWatch() && this->IsAlreadyCleared(aRequest)) {
-    this->NotifyAllowedRequest(aRequest);
-    this->ClearWatch(aRequest->WatchId());
-    return true;
-  }
-
-  return false;
-}
-
-void
-Geolocation::GetCurrentPosition(PositionCallback& aCallback,
-                                PositionErrorCallback* aErrorCallback,
-                                const PositionOptions& aOptions,
-                                CallerType aCallerType,
-                                ErrorResult& aRv)
-{
-  nsresult rv = GetCurrentPosition(GeoPositionCallback(&aCallback),
-                                   GeoPositionErrorCallback(aErrorCallback),
-                                   std::move(CreatePositionOptionsCopy(aOptions)),
-                                   aCallerType);
-
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-  }
-}
-
-static nsIEventTarget* MainThreadTarget(Geolocation* geo)
-{
-  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(geo->GetOwner());
-  if (!window) {
-    return GetMainThreadEventTarget();
-  }
-  return nsGlobalWindowInner::Cast(window)->EventTargetFor(mozilla::TaskCategory::Other);
-}
-
-nsresult
-Geolocation::GetCurrentPosition(GeoPositionCallback callback,
-                                GeoPositionErrorCallback errorCallback,
-                                UniquePtr<PositionOptions>&& options,
-                                CallerType aCallerType)
-{
-  if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // After this we hand over ownership of options to our nsGeolocationRequest.
-
-  // Count the number of requests per protocol/scheme.
-  Telemetry::Accumulate(Telemetry::GEOLOCATION_GETCURRENTPOSITION_SECURE_ORIGIN,
-                        static_cast<uint8_t>(mProtocolType));
-
-  nsIEventTarget* target = MainThreadTarget(this);
-  RefPtr<nsGeolocationRequest> request =
-    new nsGeolocationRequest(this, std::move(callback), std::move(errorCallback),
-                             std::move(options), static_cast<uint8_t>(mProtocolType), target,
-                             false, EventStateManager::IsHandlingUserInput());
-
-  if (!sGeoEnabled || ShouldBlockInsecureRequests() ||
-      nsContentUtils::ResistFingerprinting(aCallerType)) {
-    nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
-    target->Dispatch(ev.forget());
-    return NS_OK;
-  }
-
-  if (!mOwner && aCallerType != CallerType::System) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (mOwner) {
-    if (!RegisterRequestWithPrompt(request)) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    return NS_OK;
-  }
-
-  if (aCallerType != CallerType::System) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(true, request);
-  target->Dispatch(ev.forget());
-
-  return NS_OK;
-}
-
-int32_t
-Geolocation::WatchPosition(PositionCallback& aCallback,
-                           PositionErrorCallback* aErrorCallback,
-                           const PositionOptions& aOptions,
-                           CallerType aCallerType,
-                           ErrorResult& aRv)
-{
-  int32_t ret = 0;
-  nsresult rv = WatchPosition(GeoPositionCallback(&aCallback),
-                              GeoPositionErrorCallback(aErrorCallback),
-                              std::move(CreatePositionOptionsCopy(aOptions)),
-                              aCallerType,
-                              &ret);
-
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-  }
-
-  return ret;
-}
-
-NS_IMETHODIMP
-Geolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
-                           nsIDOMGeoPositionErrorCallback *aErrorCallback,
-                           UniquePtr<PositionOptions>&& aOptions,
-                           int32_t* aRv)
-{
-  NS_ENSURE_ARG_POINTER(aCallback);
-
-  return WatchPosition(GeoPositionCallback(aCallback),
-                       GeoPositionErrorCallback(aErrorCallback),
-                       std::move(aOptions), CallerType::System,
-                       aRv);
-}
-
-nsresult
-Geolocation::WatchPosition(GeoPositionCallback aCallback,
-                           GeoPositionErrorCallback aErrorCallback,
-                           UniquePtr<PositionOptions>&& aOptions,
-                           CallerType aCallerType,
-                           int32_t* aRv)
-{
-  if (mWatchingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // Count the number of requests per protocol/scheme.
-  Telemetry::Accumulate(Telemetry::GEOLOCATION_WATCHPOSITION_SECURE_ORIGIN,
-                        static_cast<uint8_t>(mProtocolType));
-
-  // The watch ID:
-  *aRv = mLastWatchId++;
-
-  nsIEventTarget* target = MainThreadTarget(this);
-  RefPtr<nsGeolocationRequest> request =
-    new nsGeolocationRequest(this, std::move(aCallback), std::move(aErrorCallback),
-                             std::move(aOptions),
-                             static_cast<uint8_t>(mProtocolType), target, true,
-                             EventStateManager::IsHandlingUserInput(), *aRv);
-
-  if (!sGeoEnabled || ShouldBlockInsecureRequests() ||
-      nsContentUtils::ResistFingerprinting(aCallerType)) {
-    nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
-    target->Dispatch(ev.forget());
-    return NS_OK;
-  }
-
-  if (!mOwner && aCallerType != CallerType::System) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (mOwner) {
-    if (!RegisterRequestWithPrompt(request))
-      return NS_ERROR_NOT_AVAILABLE;
-
-    return NS_OK;
-  }
-
-  if (aCallerType != CallerType::System) {
-    return NS_ERROR_FAILURE;
-  }
-
-  request->Allow(JS::UndefinedHandleValue);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-Geolocation::ClearWatch(int32_t aWatchId)
-{
-  if (aWatchId < 0) {
-    return NS_OK;
-  }
-
-  if (!mClearedWatchIDs.Contains(aWatchId)) {
-    mClearedWatchIDs.AppendElement(aWatchId);
-  }
-
-  for (uint32_t i = 0, length = mWatchingCallbacks.Length(); i < length; ++i) {
-    if (mWatchingCallbacks[i]->WatchId() == aWatchId) {
-      mWatchingCallbacks[i]->Shutdown();
-      RemoveRequest(mWatchingCallbacks[i]);
-      mClearedWatchIDs.RemoveElement(aWatchId);
-      break;
-    }
-  }
-
-  // make sure we also search through the pending requests lists for
-  // watches to clear...
-  for (uint32_t i = 0, length = mPendingRequests.Length(); i < length; ++i) {
-    if (mPendingRequests[i]->IsWatch() &&
-        (mPendingRequests[i]->WatchId() == aWatchId)) {
-      mPendingRequests[i]->Shutdown();
-      mPendingRequests.RemoveElementAt(i);
-      break;
-    }
-  }
-
-  return NS_OK;
-}
-
-bool
-Geolocation::WindowOwnerStillExists()
-{
-  // an owner was never set when Geolocation
-  // was created, which means that this object
-  // is being used without a window.
-  if (mOwner == nullptr) {
-    return true;
-  }
-
-  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mOwner);
-
-  if (window) {
-    nsPIDOMWindowOuter* outer = window->GetOuterWindow();
-    if (!outer || outer->GetCurrentInnerWindow() != window ||
-        outer->Closed()) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void
-Geolocation::NotifyAllowedRequest(nsGeolocationRequest* aRequest)
-{
-  if (aRequest->IsWatch()) {
-    mWatchingCallbacks.AppendElement(aRequest);
-  } else {
-    mPendingCallbacks.AppendElement(aRequest);
-  }
-}
-
-bool
-Geolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
-{
-  nsIEventTarget* target = MainThreadTarget(this);
-  if (Preferences::GetBool("geo.prompt.testing", false)) {
-    bool allow = Preferences::GetBool("geo.prompt.testing.allow", false);
-    nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(allow, request);
-    target->Dispatch(ev.forget());
-    return true;
-  }
-
-  nsCOMPtr<nsIRunnable> ev  = new RequestPromptEvent(request, mOwner);
-  target->Dispatch(ev.forget());
-  return true;
-}
-
-JSObject*
-Geolocation::WrapObject(JSContext *aCtx, JS::Handle<JSObject*> aGivenProto)
-{
-  return GeolocationBinding::Wrap(aCtx, this, aGivenProto);
-}
copy from dom/geolocation/nsGeolocation.h
copy to dom/geolocation/PositionError.h
--- a/dom/geolocation/nsGeolocation.h
+++ b/dom/geolocation/PositionError.h
@@ -1,276 +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/. */
 
-#ifndef nsGeoLocation_h
-#define nsGeoLocation_h
-
-// Microsoft's API Name hackery sucks
-#undef CreateEvent
-
-#include "mozilla/StaticPtr.h"
-#include "nsCOMPtr.h"
-#include "nsTArray.h"
-#include "nsITimer.h"
-#include "nsIObserver.h"
-#include "nsWrapperCache.h"
+#ifndef mozilla_dom_PositionError_h
+#define mozilla_dom_PositionError_h
 
-#include "nsWeakPtr.h"
+#include "nsIDOMGeoPositionError.h"
+#include "nsWrapperCache.h"
+#include "nsISupportsImpl.h"
 #include "nsCycleCollectionParticipant.h"
-
-#include "nsGeoPosition.h"
-#include "nsIDOMGeoGeolocation.h"
-#include "nsIDOMGeoPosition.h"
-#include "nsIDOMGeoPositionError.h"
-#include "nsIDOMGeoPositionCallback.h"
-#include "nsIDOMGeoPositionErrorCallback.h"
-#include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/GeolocationBinding.h"
-#include "mozilla/dom/PositionErrorBinding.h"
 #include "mozilla/dom/CallbackObject.h"
 
-#include "nsIGeolocationProvider.h"
-#include "nsIContentPermissionPrompt.h"
-#include "mozilla/Attributes.h"
-
-class nsGeolocationService;
-class nsGeolocationRequest;
-
-namespace mozilla {
-namespace dom {
-class Geolocation;
-typedef CallbackObjectHolder<PositionCallback, nsIDOMGeoPositionCallback> GeoPositionCallback;
-typedef CallbackObjectHolder<PositionErrorCallback, nsIDOMGeoPositionErrorCallback> GeoPositionErrorCallback;
-} // namespace dom
-} // namespace mozilla
-
-struct CachedPositionAndAccuracy {
-  nsCOMPtr<nsIDOMGeoPosition> position;
-  bool isHighAccuracy;
-};
-
-/**
- * Singleton that manages the geolocation provider
- */
-class nsGeolocationService final : public nsIGeolocationUpdate,
-                                   public nsIObserver
-{
-public:
-
-  static already_AddRefed<nsGeolocationService> GetGeolocationService();
-  static mozilla::StaticRefPtr<nsGeolocationService> sService;
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIGEOLOCATIONUPDATE
-  NS_DECL_NSIOBSERVER
-
-  nsGeolocationService() {
-      mHigherAccuracy = false;
-  }
-
-  nsresult Init();
-
-  // Management of the Geolocation objects
-  void AddLocator(mozilla::dom::Geolocation* locator);
-  void RemoveLocator(mozilla::dom::Geolocation* locator);
-
-  void SetCachedPosition(nsIDOMGeoPosition* aPosition);
-  CachedPositionAndAccuracy GetCachedPosition();
-
-  // Find and startup a geolocation device (gps, nmea, etc.)
-  nsresult StartDevice(nsIPrincipal* aPrincipal);
-
-  // Stop the started geolocation device (gps, nmea, etc.)
-  void     StopDevice();
-
-  // create, or reinitalize the callback timer
-  void     SetDisconnectTimer();
-
-  // Update the accuracy and notify the provider if changed
-  void     UpdateAccuracy(bool aForceHigh = false);
-  bool     HighAccuracyRequested();
-
-private:
-
-  ~nsGeolocationService();
-
-  // Disconnect timer.  When this timer expires, it clears all pending callbacks
-  // and closes down the provider, unless we are watching a point, and in that
-  // case, we disable the disconnect timer.
-  nsCOMPtr<nsITimer> mDisconnectTimer;
-
-  // The object providing geo location information to us.
-  nsCOMPtr<nsIGeolocationProvider> mProvider;
-
-  // mGeolocators are not owned here.  Their constructor
-  // adds them to this list, and their destructor removes
-  // them from this list.
-  nsTArray<mozilla::dom::Geolocation*> mGeolocators;
-
-  // This is the last geo position that we have seen.
-  CachedPositionAndAccuracy mLastPosition;
-
-  // Current state of requests for higher accuracy
-  bool mHigherAccuracy;
-};
+class nsIDOMGeoPositionErrorCallback;
 
 namespace mozilla {
 namespace dom {
-
-/**
- * Can return a geolocation info
- */
-class Geolocation final : public nsIDOMGeoGeolocation,
-                          public nsIGeolocationUpdate,
-                          public nsWrapperCache
-{
-public:
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Geolocation, nsIDOMGeoGeolocation)
-
-  NS_DECL_NSIGEOLOCATIONUPDATE
-  NS_DECL_NSIDOMGEOGEOLOCATION
-
-  Geolocation();
-
-  nsresult Init(nsPIDOMWindowInner* aContentDom = nullptr);
-
-  nsPIDOMWindowInner* GetParentObject() const;
-  virtual JSObject* WrapObject(JSContext *aCtx, JS::Handle<JSObject*> aGivenProto) override;
-
-  int32_t WatchPosition(PositionCallback& aCallback,
-                        PositionErrorCallback* aErrorCallback,
-                        const PositionOptions& aOptions,
-                        CallerType aCallerType,
-                        ErrorResult& aRv);
-  void GetCurrentPosition(PositionCallback& aCallback,
-                          PositionErrorCallback* aErrorCallback,
-                          const PositionOptions& aOptions,
-                          CallerType aCallerType,
-                          ErrorResult& aRv);
-
-  // Returns true if any of the callbacks are repeating
-  bool HasActiveCallbacks();
-
-  // Register an allowed request
-  void NotifyAllowedRequest(nsGeolocationRequest* aRequest);
-
-  // Remove request from all callbacks arrays
-  void RemoveRequest(nsGeolocationRequest* request);
-
-  // Check if there is already ClearWatch called for current
-  // request & clear if yes
-  bool ClearPendingRequest(nsGeolocationRequest* aRequest);
-
-  // Shutting down.
-  void Shutdown();
-
-  // Getter for the principal that this Geolocation was loaded from
-  nsIPrincipal* GetPrincipal() { return mPrincipal; }
-
-  // Getter for the window that this Geolocation is owned by
-  nsIWeakReference* GetOwner() { return mOwner; }
-
-  // Check to see if the window still exists
-  bool WindowOwnerStillExists();
-
-  // Check to see if any active request requires high accuracy
-  bool HighAccuracyRequested();
-
-private:
-
-  ~Geolocation();
-
-  nsresult GetCurrentPosition(GeoPositionCallback aCallback,
-                              GeoPositionErrorCallback aErrorCallback,
-                              UniquePtr<PositionOptions>&& aOptions,
-                              CallerType aCallerType);
-  nsresult WatchPosition(GeoPositionCallback aCallback,
-                         GeoPositionErrorCallback aErrorCallback,
-                         UniquePtr<PositionOptions>&& aOptions,
-                         CallerType aCallerType,
-                         int32_t* aRv);
-
-  bool RegisterRequestWithPrompt(nsGeolocationRequest* request);
-
-  // Check if clearWatch is already called
-  bool IsAlreadyCleared(nsGeolocationRequest* aRequest);
-
-  // Returns whether the Geolocation object should block requests
-  // within a context that is not secure.
-  bool ShouldBlockInsecureRequests() const;
-
-  // Two callback arrays.  The first |mPendingCallbacks| holds objects for only
-  // one callback and then they are released/removed from the array.  The second
-  // |mWatchingCallbacks| holds objects until the object is explictly removed or
-  // there is a page change. All requests held by either array are active, that
-  // is, they have been allowed and expect to be fulfilled.
-
-  nsTArray<RefPtr<nsGeolocationRequest> > mPendingCallbacks;
-  nsTArray<RefPtr<nsGeolocationRequest> > mWatchingCallbacks;
-
-  // window that this was created for.  Weak reference.
-  nsWeakPtr mOwner;
-
-  // where the content was loaded from
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-
-  // the protocols we want to measure
-  enum class ProtocolType: uint8_t { OTHER, HTTP, HTTPS };
-
-  // the protocol used to load the content
-  ProtocolType mProtocolType;
-
-  // owning back pointer.
-  RefPtr<nsGeolocationService> mService;
-
-  // Watch ID
-  uint32_t mLastWatchId;
-
-  // Pending requests are used when the service is not ready
-  nsTArray<RefPtr<nsGeolocationRequest> > mPendingRequests;
-
-  // Array containing already cleared watch IDs
-  nsTArray<int32_t> mClearedWatchIDs;
-};
+class PositionErrorCallback;
+class Geolocation;
+typedef CallbackObjectHolder<PositionErrorCallback, nsIDOMGeoPositionErrorCallback> GeoPositionErrorCallback;
 
 class PositionError final : public nsIDOMGeoPositionError,
                             public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PositionError)
 
   NS_DECL_NSIDOMGEOPOSITIONERROR
 
   PositionError(Geolocation* aParent, int16_t aCode);
 
-  Geolocation* GetParentObject() const;
+  nsWrapperCache* GetParentObject() const;
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   int16_t Code() const {
     return mCode;
   }
 
   void NotifyCallback(const GeoPositionErrorCallback& callback);
 private:
   ~PositionError();
   int16_t mCode;
   RefPtr<Geolocation> mParent;
 };
 
 } // namespace dom
-
-inline nsISupports*
-ToSupports(dom::Geolocation* aGeolocation)
-{
-  return ToSupports(static_cast<nsIDOMGeoGeolocation*>(aGeolocation));
-}
-
 } // namespace mozilla
 
-#endif /* nsGeoLocation_h */
+#endif /* mozilla_dom_PositionError_h */
--- a/dom/geolocation/moz.build
+++ b/dom/geolocation/moz.build
@@ -7,18 +7,23 @@
 with Files("**"):
     BUG_COMPONENT = ("Core", "Geolocation")
 
 EXPORTS += [
     'nsGeoPosition.h',
     'nsGeoPositionIPCSerialiser.h',
 ]
 
+EXPORTS.mozilla.dom += [
+    'PositionError.h',
+]
+
 SOURCES += [
     'nsGeolocation.cpp',
+    'PositionError.cpp',
 ]
 
 UNIFIED_SOURCES += [
     'MLSFallback.cpp',
     'nsGeoPosition.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -4,28 +4,30 @@
  * 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 "nsGeolocation.h"
 
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
+#include "mozilla/dom/PositionError.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 #include "mozilla/WeakPtr.h"
 #include "mozilla/EventStateManager.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentPermissionHelper.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
+#include "nsIDOMGeoPositionError.h"
 #include "nsINamed.h"
 #include "nsIObserverService.h"
 #include "nsIScriptError.h"
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
@@ -215,96 +217,16 @@ public:
 
 private:
   nsCOMPtr<nsIDOMGeoPosition> mPosition;
   RefPtr<nsGeolocationRequest> mRequest;
   RefPtr<Geolocation> mLocator;
 };
 
 ////////////////////////////////////////////////////
-// PositionError
-////////////////////////////////////////////////////
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PositionError)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionError)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionError)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PositionError, mParent)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(PositionError)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(PositionError)
-
-PositionError::PositionError(Geolocation* aParent, int16_t aCode)
-  : mCode(aCode)
-  , mParent(aParent)
-{
-}
-
-PositionError::~PositionError() = default;
-
-
-NS_IMETHODIMP
-PositionError::GetCode(int16_t *aCode)
-{
-  NS_ENSURE_ARG_POINTER(aCode);
-  *aCode = Code();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-PositionError::GetMessage(nsAString& aMessage)
-{
-  switch (mCode)
-  {
-    case nsIDOMGeoPositionError::PERMISSION_DENIED:
-      aMessage = NS_LITERAL_STRING("User denied geolocation prompt");
-      break;
-    case nsIDOMGeoPositionError::POSITION_UNAVAILABLE:
-      aMessage = NS_LITERAL_STRING("Unknown error acquiring position");
-      break;
-    case nsIDOMGeoPositionError::TIMEOUT:
-      aMessage = NS_LITERAL_STRING("Position acquisition timed out");
-      break;
-    default:
-      break;
-  }
-  return NS_OK;
-}
-
-Geolocation*
-PositionError::GetParentObject() const
-{
-  return mParent;
-}
-
-JSObject*
-PositionError::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return PositionErrorBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-PositionError::NotifyCallback(const GeoPositionErrorCallback& aCallback)
-{
-  nsAutoMicroTask mt;
-  if (aCallback.HasWebIDLCallback()) {
-    PositionErrorCallback* callback = aCallback.GetWebIDLCallback();
-
-    if (callback) {
-      callback->Call(*this);
-    }
-  } else {
-    nsIDOMGeoPositionErrorCallback* callback = aCallback.GetXPCOMCallback();
-    if (callback) {
-      callback->HandleEvent(this);
-    }
-  }
-}
-////////////////////////////////////////////////////
 // nsGeolocationRequest
 ////////////////////////////////////////////////////
 
 nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
                                            GeoPositionCallback aCallback,
                                            GeoPositionErrorCallback aErrorCallback,
                                            UniquePtr<PositionOptions>&& aOptions,
                                            uint8_t aProtocolType,
--- a/dom/geolocation/nsGeolocation.h
+++ b/dom/geolocation/nsGeolocation.h
@@ -18,22 +18,20 @@
 #include "nsWrapperCache.h"
 
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsGeoPosition.h"
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
-#include "nsIDOMGeoPositionError.h"
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIDOMGeoPositionErrorCallback.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/GeolocationBinding.h"
-#include "mozilla/dom/PositionErrorBinding.h"
 #include "mozilla/dom/CallbackObject.h"
 
 #include "nsIGeolocationProvider.h"
 #include "nsIContentPermissionPrompt.h"
 #include "mozilla/Attributes.h"
 
 class nsGeolocationService;
 class nsGeolocationRequest;
@@ -232,42 +230,16 @@ private:
 
   // Pending requests are used when the service is not ready
   nsTArray<RefPtr<nsGeolocationRequest> > mPendingRequests;
 
   // Array containing already cleared watch IDs
   nsTArray<int32_t> mClearedWatchIDs;
 };
 
-class PositionError final : public nsIDOMGeoPositionError,
-                            public nsWrapperCache
-{
-public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PositionError)
-
-  NS_DECL_NSIDOMGEOPOSITIONERROR
-
-  PositionError(Geolocation* aParent, int16_t aCode);
-
-  Geolocation* GetParentObject() const;
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-  int16_t Code() const {
-    return mCode;
-  }
-
-  void NotifyCallback(const GeoPositionErrorCallback& callback);
-private:
-  ~PositionError();
-  int16_t mCode;
-  RefPtr<Geolocation> mParent;
-};
-
 } // namespace dom
 
 inline nsISupports*
 ToSupports(dom::Geolocation* aGeolocation)
 {
   return ToSupports(static_cast<nsIDOMGeoGeolocation*>(aGeolocation));
 }