Bug 1425316 P4 Note that a ClientSource has called register() for a SW scope and use it to match window console reports. r=asuth
authorBen Kelly <ben@wanderview.com>
Tue, 19 Dec 2017 10:04:48 -0500
changeset 396922 c08edd442321e8d3b1c04ca25489e6f1634abbeb
parent 396921 ca80e585ab6d3e85030c583d2139167e8c112ff6
child 396923 8c2c417bbe76fe6f49f2e55503232b5cd54fe16f
push id33117
push userebalazs@mozilla.com
push dateWed, 20 Dec 2017 09:47:43 +0000
treeherdermozilla-central@a235bf4868ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1425316
milestone59.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 1425316 P4 Note that a ClientSource has called register() for a SW scope and use it to match window console reports. r=asuth
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/base/nsPIDOMWindow.h
dom/clients/manager/ClientSource.cpp
dom/clients/manager/ClientSource.h
dom/workers/ServiceWorkerManager.cpp
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -2326,16 +2326,22 @@ nsPIDOMWindowInner::GetClientState() con
 }
 
 Maybe<ServiceWorkerDescriptor>
 nsPIDOMWindowInner::GetController() const
 {
   return Move(nsGlobalWindowInner::Cast(this)->GetController());
 }
 
+void
+nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope(aScope);
+}
+
 bool
 nsGlobalWindowInner::ShouldReportForServiceWorkerScope(const nsAString& aScope)
 {
   bool result = false;
 
   nsPIDOMWindowOuter* topOuter = GetScriptableTop();
   NS_ENSURE_TRUE(topOuter, false);
 
@@ -2370,23 +2376,41 @@ nsGlobalWindowInner::ShouldReportForServ
   // First check to see if this window is controlled.  If so, then we have
   // found a match and are done.
   const Maybe<ServiceWorkerDescriptor> swd = GetController();
   if (swd.isSome() && swd.ref().Scope() == aScope) {
     *aResultOut = true;
     return CallState::Stop;
   }
 
+  // Next, check to see if this window has called navigator.serviceWorker.register()
+  // for this scope.  If so, then treat this as a match so console reports
+  // appear in the devtools console.
+  if (mClientSource && mClientSource->CalledRegisterForServiceWorkerScope(aScope)) {
+    *aResultOut = true;
+    return CallState::Stop;
+  }
+
   // The current window doesn't care about this service worker, but maybe
   // one of our child frames does.
   return CallOnChildren(&nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal,
                         aScope, aResultOut);
 }
 
 void
+nsGlobalWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  if (!mClientSource) {
+    return;
+  }
+
+  mClientSource->NoteCalledRegisterForServiceWorkerScope(aScope);
+}
+
+void
 nsGlobalWindowInner::UpdateTopInnerWindow()
 {
   if (IsTopInnerWindow() || !mTopInnerWindow) {
     return;
   }
 
   mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);
 }
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -346,16 +346,18 @@ public:
   void Thaw();
   virtual bool IsFrozen() const override;
   void SyncStateFromParentWindow();
 
   mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
   mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
   mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
 
+  void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
+
   virtual nsresult FireDelayedDOMEvents() override;
 
   virtual nsresult SetNewDocument(nsIDocument *aDocument,
                                   nsISupports *aState,
                                   bool aForceReuseInnerWindow) override;
 
   virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
                                bool aOriginalOpener) override;
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -326,16 +326,18 @@ public:
   // Return true if there are any open WebSockets that could block
   // timeout-throttling.
   bool HasOpenWebSockets() const;
 
   mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
   mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
   mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
 
+  void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
+
   mozilla::dom::TabGroup* TabGroup();
 
   virtual nsPIDOMWindowOuter* GetPrivateRoot() = 0;
 
   virtual mozilla::dom::CustomElementRegistry* CustomElements() = 0;
 
   // XXX: This is called on inner windows
   virtual nsPIDOMWindowOuter* GetScriptableTop() = 0;
--- a/dom/clients/manager/ClientSource.cpp
+++ b/dom/clients/manager/ClientSource.cpp
@@ -672,10 +672,25 @@ ClientSource::Traverse(nsCycleCollection
                                 aName, aFlags);
   } else if (mOwner.is<nsCOMPtr<nsIDocShell>>()) {
     ImplCycleCollectionTraverse(aCallback,
                                 mOwner.as<nsCOMPtr<nsIDocShell>>(),
                                 aName, aFlags);
   }
 }
 
+void
+ClientSource::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  if (mRegisteringScopeList.Contains(aScope)) {
+    return;
+  }
+  mRegisteringScopeList.AppendElement(aScope);
+}
+
+bool
+ClientSource::CalledRegisterForServiceWorkerScope(const nsACString& aScope)
+{
+  return mRegisteringScopeList.Contains(aScope);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/clients/manager/ClientSource.h
+++ b/dom/clients/manager/ClientSource.h
@@ -58,16 +58,22 @@ class ClientSource final : public Client
   Variant<Nothing,
           RefPtr<nsPIDOMWindowInner>,
           nsCOMPtr<nsIDocShell>,
           mozilla::dom::workers::WorkerPrivate*> mOwner;
 
   ClientInfo mClientInfo;
   Maybe<ServiceWorkerDescriptor> mController;
 
+  // Contained a de-duplicated list of ServiceWorker scope strings
+  // for which this client has called navigator.serviceWorker.register().
+  // Typically there will be either be zero or one scope strings, but
+  // there could be more.  We keep this list until the client is closed.
+  AutoTArray<nsCString, 1> mRegisteringScopeList;
+
   void
   Shutdown();
 
   void
   ExecutionReady(const ClientSourceExecutionReadyArgs& aArgs);
 
   mozilla::dom::workers::WorkerPrivate*
   GetWorkerPrivate() const;
@@ -158,16 +164,22 @@ public:
 
   nsISerialEventTarget*
   EventTarget() const;
 
   void
   Traverse(nsCycleCollectionTraversalCallback& aCallback,
            const char* aName,
            uint32_t aFlags);
+
+  void
+  NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
+
+  bool
+  CalledRegisterForServiceWorkerScope(const nsACString& aScope);
 };
 
 inline void
 ImplCycleCollectionUnlink(UniquePtr<ClientSource>& aField)
 {
   aField.reset();
 }
 
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -833,16 +833,17 @@ ServiceWorkerManager::Register(mozIDOMWi
   }
 
   nsAutoCString scopeKey;
   rv = PrincipalToScopeKey(documentPrincipal, scopeKey);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  window->NoteCalledRegisterForServiceWorkerScope(cleanedScope);
   AddRegisteringDocument(cleanedScope, doc);
 
   RefPtr<ServiceWorkerJobQueue> queue = GetOrCreateJobQueue(scopeKey,
                                                             cleanedScope);
 
   RefPtr<ServiceWorkerResolveWindowPromiseOnRegisterCallback> cb =
     new ServiceWorkerResolveWindowPromiseOnRegisterCallback(window, promise);
 
@@ -3645,51 +3646,16 @@ ServiceWorkerManager::ShouldReportToWind
   nsCOMPtr<nsPIDOMWindowOuter> targetWin = nsPIDOMWindowOuter::From(aWindow);
   if (NS_WARN_IF(!targetWin)) {
     return NS_OK;
   }
 
   targetWin = targetWin->GetScriptableTop();
   uint64_t winId = targetWin->WindowID();
 
-  // Check our weak registering document references first.  This way we clear
-  // out as many dead weak references as possible when this method is called.
-  WeakDocumentList* list = mRegisteringDocuments.Get(aScope);
-  if (list) {
-    for (int32_t i = list->Length() - 1; i >= 0; --i) {
-      nsCOMPtr<nsIDocument> doc = do_QueryReferent(list->ElementAt(i));
-      if (!doc) {
-        list->RemoveElementAt(i);
-        continue;
-      }
-
-      if (!doc->IsCurrentActiveDocument()) {
-        continue;
-      }
-
-      nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
-      if (!win) {
-        continue;
-      }
-
-      win = win->GetScriptableTop();
-
-      // Match.  We should report to this window.
-      if (win && winId == win->WindowID()) {
-        *aResult = true;
-        return NS_OK;
-      }
-    }
-
-    if (list->IsEmpty()) {
-      list = nullptr;
-      mRegisteringDocuments.Remove(aScope);
-    }
-  }
-
   // Examine any windows performing a navigation that we are currently
   // intercepting.
   InterceptionList* intList = mNavigationInterceptions.Get(aScope);
   if (intList) {
     for (uint32_t i = 0; i < intList->Length(); ++i) {
       nsCOMPtr<nsIInterceptedChannel> channel = intList->ElementAt(i);
 
       nsCOMPtr<nsIChannel> inner;