Bug 1139425 - Service Worker Client id should return a DOMString uuid. r=baku
authorAlbert Crespell <alberto.crespellperez@telefonica.com>
Fri, 13 Mar 2015 07:15:25 +0100
changeset 233910 dfa2d2fe0a8a12f2c947404d5df5aa306971f430
parent 233909 ea0fbe4ec5d915ca515670de8b99594bcdf4f7ed
child 233911 b60fe2874585204ccc79f5616abf271ce63fc17e
push id28426
push usercbook@mozilla.com
push dateTue, 17 Mar 2015 10:46:54 +0000
treeherdermozilla-central@008b3f65a7e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1139425
milestone39.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 1139425 - Service Worker Client id should return a DOMString uuid. r=baku
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/webidl/Client.webidl
dom/workers/ServiceWorkerClient.cpp
dom/workers/ServiceWorkerClient.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -12839,16 +12839,45 @@ nsIDocument::CreateHTMLElement(nsIAtom* 
   DebugOnly<nsresult> rv = NS_NewHTMLElement(getter_AddRefs(element),
                                              nodeInfo.forget(),
                                              mozilla::dom::NOT_FROM_PARSER);
 
   MOZ_ASSERT(NS_SUCCEEDED(rv), "NS_NewHTMLElement should never fail");
   return element.forget();
 }
 
+nsresult
+nsIDocument::GetId(nsAString& aId)
+{
+  if (mId.IsEmpty()) {
+    nsresult rv;
+    nsCOMPtr<nsIUUIDGenerator> uuidgen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    nsID id;
+    rv = uuidgen->GenerateUUIDInPlace(&id);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    // Build a string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format
+    char buffer[NSID_LENGTH];
+    id.ToProvidedString(buffer);
+    NS_ConvertASCIItoUTF16 uuid(buffer);
+
+    // Remove {} and the null terminator
+    mId.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
+  }
+
+  aId = mId;
+  return NS_OK;
+}
+
 bool
 MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
 {
   nsCOMArray<nsIDocument>* documents =
     static_cast<nsCOMArray<nsIDocument>*>(aData);
   if (aDoc) {
     aDoc->SetIsInSyncOperation(true);
     documents->AppendObject(aDoc);
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -11,16 +11,18 @@
 #include "nsCRT.h"                       // for NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 #include "nsCompatibility.h"             // for member
 #include "nsCOMPtr.h"                    // for member
 #include "nsGkAtoms.h"                   // for static class members
 #include "nsIDocumentObserver.h"         // for typedef (nsUpdateType)
 #include "nsILoadGroup.h"                // for member (in nsCOMPtr)
 #include "nsINode.h"                     // for base class
 #include "nsIScriptGlobalObject.h"       // for member (in nsCOMPtr)
+#include "nsIServiceManager.h"
+#include "nsIUUIDGenerator.h"
 #include "nsPIDOMWindow.h"               // for use in inline functions
 #include "nsPropertyTable.h"             // for member
 #include "nsTHashtable.h"                // for member
 #include "mozilla/net/ReferrerPolicy.h"  // for member
 #include "nsWeakReference.h"
 #include "mozilla/dom/DocumentBinding.h"
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
@@ -742,16 +744,18 @@ public:
   InsertAnonymousContent(mozilla::dom::Element& aElement,
                          mozilla::ErrorResult& aError);
   void RemoveAnonymousContent(mozilla::dom::AnonymousContent& aContent,
                               mozilla::ErrorResult& aError);
   nsTArray<nsRefPtr<mozilla::dom::AnonymousContent>>& GetAnonymousContents() {
     return mAnonymousContents;
   }
 
+  nsresult GetId(nsAString& aId);
+
 protected:
   virtual Element *GetRootElementInternal() const = 0;
 
 private:
   class SelectorCacheKey
   {
     public:
       explicit SelectorCacheKey(const nsAString& aString) : mKey(aString)
@@ -2793,16 +2797,17 @@ protected:
   uint32_t mSandboxFlags;
 
   nsCString mContentLanguage;
 
   // The channel that got passed to nsDocument::StartDocumentLoad(), if any.
   nsCOMPtr<nsIChannel> mChannel;
 private:
   nsCString mContentType;
+  nsString mId;
 protected:
 
   // The document's security info
   nsCOMPtr<nsISupports> mSecurityInfo;
 
   // The channel that failed to load and resulted in an error page.
   // This only applies to error pages. Might be null.
   nsCOMPtr<nsIChannel> mFailedChannel;
--- a/dom/webidl/Client.webidl
+++ b/dom/webidl/Client.webidl
@@ -5,16 +5,17 @@
  *
  * The origin of this IDL file is
  * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html
  *
  */
 
 [Exposed=ServiceWorker]
 interface Client {
+  readonly attribute DOMString id;
   readonly attribute USVString url;
 
   [Throws]
   void postMessage(any message, optional sequence<Transferable> transfer);
 };
 
 [Exposed=ServiceWorker]
 interface WindowClient : Client {
--- a/dom/workers/ServiceWorkerClient.cpp
+++ b/dom/workers/ServiceWorkerClient.cpp
@@ -26,18 +26,23 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
 {
   MOZ_ASSERT(aDoc);
   MOZ_ASSERT(aDoc->GetWindow());
 
+  nsresult rv = aDoc->GetId(mClientId);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to get the UUID of the document.");
+  }
+
   nsRefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aDoc->GetWindow());
-  mClientId = outerWindow->WindowID();
+  mWindowId = outerWindow->WindowID();
   aDoc->GetURL(mUrl);
   mVisibilityState = aDoc->VisibilityState();
 
   ErrorResult result;
   mFocused = aDoc->HasFocus(result);
   if (result.Failed()) {
     NS_WARNING("Failed to get focus information.");
   }
@@ -56,35 +61,35 @@ ServiceWorkerClient::WrapObject(JSContex
 {
   return ClientBinding::Wrap(aCx, this);
 }
 
 namespace {
 
 class ServiceWorkerClientPostMessageRunnable MOZ_FINAL : public nsRunnable
 {
-  uint64_t mId;
+  uint64_t mWindowId;
   JSAutoStructuredCloneBuffer mBuffer;
   nsTArray<nsCOMPtr<nsISupports>> mClonedObjects;
 
 public:
-  ServiceWorkerClientPostMessageRunnable(uint64_t aId,
+  ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId,
                                          JSAutoStructuredCloneBuffer&& aData,
                                          nsTArray<nsCOMPtr<nsISupports>>& aClonedObjects)
-    : mId(aId),
+    : mWindowId(aWindowId),
       mBuffer(Move(aData))
   {
     mClonedObjects.SwapElements(aClonedObjects);
   }
 
   NS_IMETHOD
   Run()
   {
     AssertIsOnMainThread();
-    nsGlobalWindow* window = nsGlobalWindow::GetOuterWindowWithId(mId);
+    nsGlobalWindow* window = nsGlobalWindow::GetOuterWindowWithId(mWindowId);
     if (!window) {
       return NS_ERROR_FAILURE;
     }
 
     ErrorResult result;
     dom::Navigator* navigator = window->GetNavigator(result);
     if (NS_WARN_IF(result.Failed())) {
       return result.ErrorCode();
@@ -177,15 +182,15 @@ ServiceWorkerClient::PostMessage(JSConte
 
   JSAutoStructuredCloneBuffer buffer;
   if (!buffer.write(aCx, aMessage, transferable, callbacks, &clonedObjects)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
   nsRefPtr<ServiceWorkerClientPostMessageRunnable> runnable =
-    new ServiceWorkerClientPostMessageRunnable(mId, Move(buffer), clonedObjects);
+    new ServiceWorkerClientPostMessageRunnable(mWindowId, Move(buffer), clonedObjects);
   nsresult rv = NS_DispatchToMainThread(runnable);
   if (NS_FAILED(rv)) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 }
 
--- a/dom/workers/ServiceWorkerClient.h
+++ b/dom/workers/ServiceWorkerClient.h
@@ -26,17 +26,18 @@ class ServiceWorkerClientInfo MOZ_FINAL
 {
   friend class ServiceWorkerClient;
   friend class ServiceWorkerWindowClient;
 
 public:
   explicit ServiceWorkerClientInfo(nsIDocument* aDoc);
 
 private:
-  uint64_t mClientId;
+  nsString mClientId;
+  uint64_t mWindowId;
   nsString mUrl;
 
   // Window Clients
   VisibilityState mVisibilityState;
   bool mFocused;
   FrameType mFrameType;
 };
 
@@ -46,27 +47,33 @@ class ServiceWorkerClient : public nsISu
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ServiceWorkerClient)
 
   ServiceWorkerClient(nsISupports* aOwner,
                       const ServiceWorkerClientInfo& aClientInfo)
     : mOwner(aOwner),
       mId(aClientInfo.mClientId),
+      mWindowId(aClientInfo.mWindowId),
       mUrl(aClientInfo.mUrl)
   {
     MOZ_ASSERT(aOwner);
   }
 
   nsISupports*
   GetParentObject() const
   {
     return mOwner;
   }
 
+  void GetId(nsString& aRetval) const
+  {
+    aRetval = mId;
+  }
+
   void
   GetUrl(nsAString& aUrl) const
   {
     aUrl.Assign(mUrl);
   }
 
   void
   PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
@@ -76,17 +83,18 @@ public:
   JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
 protected:
   virtual ~ServiceWorkerClient()
   { }
 
 private:
   nsCOMPtr<nsISupports> mOwner;
-  uint64_t mId;
+  nsString mId;
+  uint64_t mWindowId;
   nsString mUrl;
 };
 
 } // namespace workers
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_workers_serviceworkerclient_h