progress train wreck draft swms-oracle
authorAndrew Sutherland <asutherland@asutherland.org>
Tue, 30 May 2017 03:23:47 -0400
changeset 400048 b38646e04061084e720465ece8379e63efa6da75
parent 400047 4ba9f1addfff934c38056b8b324fbcd5a48b2c1e
push id4
push userbugmail@asutherland.org
push dateMon, 26 Jun 2017 06:55:04 +0000
milestone55.0a1
progress train wreck
dom/interfaces/base/nsIServiceWorkerManager.idl
dom/workers/ServiceWorkerManager.cpp
dom/workers/ServiceWorkerManagerService.cpp
dom/workers/ServiceWorkerManagerService.h
xpcom/threads/AbstractThread.h
--- a/dom/interfaces/base/nsIServiceWorkerManager.idl
+++ b/dom/interfaces/base/nsIServiceWorkerManager.idl
@@ -130,16 +130,25 @@ interface nsIServiceWorkerManager : nsIS
   nsISupports getReadyPromise(in mozIDOMWindow aWindow);
 
   // Remove ready pending Promise
   void removeReadyPromise(in mozIDOMWindow aWindow);
 
   nsIServiceWorkerRegistrationInfo getRegistrationByPrincipal(in nsIPrincipal aPrincipal,
                                                               in DOMString aScope);
 
+  // Testing support for ServiceWorkerManagerService::PickParentForScope.  Don't
+  // use this.  Returns a promise that resolves with the nsITabParent of the
+  // ContentParent that either is home to the currently running Active SW for
+  // the given scope or would be a swell place to spin one up.  You should still
+  // not use this even though you know what it does now.
+  [implicit_jscontext]
+  jsval testOnlyPickParentForScope(in nsIPrincipal aPrincipal,
+                                   in DOMString aScope);
+
   /**
    * Call this to request that document `aDoc` be controlled by a ServiceWorker
    * if a registration exists for it's scope.
    *
    * This MUST only be called once per document!
    */
   [notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc, in DOMString aDocumentId);
 
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -3512,16 +3512,40 @@ ServiceWorkerManager::GetRegistrationByP
   if (!info) {
     return NS_ERROR_FAILURE;
   }
   info.forget(aInfo);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+ServiceWorkerManager::TestOnlyPickParentForScope(nsIPrincipal* aPrincipal,
+                                                 const nsAString& aScope,
+                                                 JSContext* aCx,
+                                                 JS::MutableHandleValue aRval)
+{
+  nsCOMPtr<nsIGlobalObject> global =
+    xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
+  NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
+
+  ErrorResult errv;
+  RefPtr<dom::Promise> promise = dom::Promise::Create(global, errv);
+  if (errv.Failed()) {
+    return errv.StealNSResult();
+  }
+
+  InvokeAsync()
+
+  if (!ToJSValue(aCx, promise, aRval)) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
 already_AddRefed<ServiceWorkerRegistrationInfo>
 ServiceWorkerManager::GetRegistration(const nsACString& aScopeKey,
                                       const nsACString& aScope) const
 {
   RefPtr<ServiceWorkerRegistrationInfo> reg;
 
   RegistrationDataPerPrincipal* data;
   if (!mRegistrationInfos.Get(aScopeKey, &data)) {
--- a/dom/workers/ServiceWorkerManagerService.cpp
+++ b/dom/workers/ServiceWorkerManagerService.cpp
@@ -8,32 +8,34 @@
 #include "ServiceWorkerManagerParent.h"
 #include "ServiceWorkerRegistrar.h"
 #include "ServiceWorkerUpdaterParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/RefCounted.h"
 #include "mozilla/Unused.h"
 #include "nsAutoPtr.h"
+#include "nsIThread.h"
 #include "nsIXULRuntime.h"
 
 namespace mozilla {
 
 using namespace ipc;
 
 namespace dom {
 namespace workers {
 
 namespace {
 
 ServiceWorkerManagerService* sInstance = nullptr;
 
 } // namespace
 
 ServiceWorkerManagerService::ServiceWorkerManagerService()
+  : mBackgroundAbstractThread()
 {
   AssertIsOnBackgroundThread();
 
   // sInstance is a raw ServiceWorkerManagerService*.
   MOZ_ASSERT(!sInstance);
   sInstance = this;
 }
 
@@ -62,16 +64,31 @@ ServiceWorkerManagerService::GetOrCreate
 
   RefPtr<ServiceWorkerManagerService> instance = sInstance;
   if (!instance) {
     instance = new ServiceWorkerManagerService();
   }
   return instance.forget();
 }
 
+/* static */ RefPtr<ServiceWorkerManagerService::PickContentParentPromise>
+ServiceWorkerManagerService::MainThreadPickParentForScope(
+  nsIPrincipal* aPrincipal, const nsCString& aScope)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!sInstance) {
+    return PickContentParentPromise::CreateAndReject(
+      NS_ERROR_NOT_AVAILABLE, __func__);
+  }
+
+
+}
+
+
 namespace {
 
 /**
  * PickParentForScope helper that tracks the number of outstanding promises and
  * processes their results as they come in so it can resolve its own promise
  * when it sees any process with the desired SW running.  Otherwise, logic makes
  * an arbitrary decision when all the results are in.
  *
--- a/dom/workers/ServiceWorkerManagerService.h
+++ b/dom/workers/ServiceWorkerManagerService.h
@@ -7,16 +7,18 @@
 #ifndef mozilla_dom_ServiceWorkerManagerService_h
 #define mozilla_dom_ServiceWorkerManagerService_h
 
 #include "mozilla/MozPromise.h"
 #include "nsISupportsImpl.h"
 #include "nsHashKeys.h"
 #include "nsTHashtable.h"
 
+class nsIPrincipal;
+
 namespace mozilla {
 
 class OriginAttributes;
 
 namespace ipc {
 class PrincipalInfo;
 } // namespace ipc
 
@@ -32,16 +34,28 @@ class ServiceWorkerUpdaterParent;
 class ServiceWorkerManagerService final
 {
 public:
   NS_INLINE_DECL_REFCOUNTING(ServiceWorkerManagerService)
 
   static already_AddRefed<ServiceWorkerManagerService> Get();
   static already_AddRefed<ServiceWorkerManagerService> GetOrCreate();
 
+  typedef MozPromise<RefPtr<ContentParent>, nsresult, false>
+    PickContentParentPromise;
+
+  /**
+   * Testing helper variant of PickParentForScope for use by the parent-process
+   * ServiceWorkerManager only.  Rejects if the SWMS has not yet been
+   * initialized on the PBackground thread.  In general, a big hack.
+   */
+  static RefPtr<PickContentParentPromise>
+  MainThreadPickParentForScope(nsIPrincipal* aPrincipal,
+                               const nsCString& aScope);
+
   typedef MozPromise<RefPtr<ServiceWorkerManagerParent>, nsresult, false>
     PickParentPromise;
 
   /**
    * Asynchronously pick a ServiceWorkerManagerParent instance appropriate for
    * the given scope, possibly causing a content process to be spun up.
    *
    * This is a temporary e10s hack to make the BackgroundSync API happy.  We
@@ -102,16 +116,18 @@ public:
                            uint64_t aParentID);
 
   void UpdaterActorDestroyed(ServiceWorkerUpdaterParent* aActor);
 
 private:
   ServiceWorkerManagerService();
   ~ServiceWorkerManagerService();
 
+  nsCOMPtr<nsIThread> mBackgroundThread;
+
   nsTHashtable<nsPtrHashKey<ServiceWorkerManagerParent>> mAgents;
   // List of promises to be resolved with the next agent that registers itself
   // with us.  Used by PickParentForScope.
   nsTArray<MozPromiseHolder<PickParentPromise>> mPicksWaitingForNewProcess;
 
   struct PendingUpdaterActor
   {
     nsCString mScope;
--- a/xpcom/threads/AbstractThread.h
+++ b/xpcom/threads/AbstractThread.h
@@ -26,17 +26,17 @@ class TaskDispatcher;
  * nsIThread and TaskQueue. Note that nsIThreadPool (which implements
  * nsIEventTarget) does not have this property, so we do not want to use
  * nsIEventTarget for this purpose. This class encapsulates the specifics of
  * the structures we might use here and provides a consistent interface.
  *
  * At present, the supported AbstractThread implementations are TaskQueue,
  * AbstractThread::MainThread() and DocGroup::AbstractThreadFor().
  * If you add support for another thread that is not the MainThread, you'll need
- * to figure out how to make it unique such that comparing AbstractThread
+ * to figure out how to make i tunique such that comparing AbstractThread
  * pointers is equivalent to comparing nsIThread pointers.
  */
 class AbstractThread
 {
 public:
   // Returns the AbstractThread that the caller is currently running in, or null
   // if the caller is not running in an AbstractThread.
   static AbstractThread* GetCurrent() { return sCurrentThreadTLS.get(); }