Bug 1596665 - P2. Add ability to copy all property bag contents to another. r=mattwoodrow
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 26 Nov 2019 01:49:28 +0000
changeset 503774 452793927396fbe72b7f78f676bbeef8cb0aeae4
parent 503773 d328964a7526625eea38a3e177321fe0f7ce9c70
child 503775 4bd5a9363b0d05871982e5d8c4a66ea4b971724c
push id36847
push userncsoregi@mozilla.com
push dateTue, 26 Nov 2019 09:34:48 +0000
treeherdermozilla-central@7bc0df30a8a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1596665
milestone72.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 1596665 - P2. Add ability to copy all property bag contents to another. r=mattwoodrow Add static CopyFrom method which is to be used in a follow-up patch. The static method takes a nsIWritablePropertyBag so that we don't need to cast to the concrete class. Differential Revision: https://phabricator.services.mozilla.com/D53923
netwerk/base/nsBaseChannel.cpp
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
xpcom/ds/nsHashPropertyBag.cpp
xpcom/ds/nsHashPropertyBag.h
--- a/netwerk/base/nsBaseChannel.cpp
+++ b/netwerk/base/nsBaseChannel.cpp
@@ -132,21 +132,18 @@ nsresult nsBaseChannel::Redirect(nsIChan
   if (mPrivateBrowsingOverriden) {
     nsCOMPtr<nsIPrivateBrowsingChannel> newPBChannel =
         do_QueryInterface(newChannel);
     if (newPBChannel) {
       newPBChannel->SetPrivate(mPrivateBrowsing);
     }
   }
 
-  nsCOMPtr<nsIWritablePropertyBag> bag = ::do_QueryInterface(newChannel);
-  if (bag) {
-    for (auto iter = mPropertyHash.Iter(); !iter.Done(); iter.Next()) {
-      bag->SetProperty(iter.Key(), iter.UserData());
-    }
+  if (nsCOMPtr<nsIWritablePropertyBag> bag = ::do_QueryInterface(newChannel)) {
+    nsHashPropertyBag::CopyFrom(bag, static_cast<nsIPropertyBag2*>(this));
   }
 
   // Notify consumer, giving chance to cancel redirect.
 
   auto redirectCallbackHelper = MakeRefPtr<net::nsAsyncRedirectVerifyHelper>();
 
   bool checkRedirectSynchronously = !openNewChannel;
   nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
--- a/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
@@ -39,45 +39,18 @@ nsDNSServiceInfo::nsDNSServiceInfo(nsIDN
     Unused << NS_WARN_IF(NS_FAILED(SetServiceType(str)));
   }
   if (NS_SUCCEEDED(aServiceInfo->GetDomainName(str))) {
     Unused << NS_WARN_IF(NS_FAILED(SetDomainName(str)));
   }
 
   nsCOMPtr<nsIPropertyBag2> attributes;  // deep copy
   if (NS_SUCCEEDED(aServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
-    nsCOMPtr<nsISimpleEnumerator> enumerator;
-    if (NS_WARN_IF(
-            NS_FAILED(attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
-      return;
-    }
-
-    nsCOMPtr<nsIWritablePropertyBag2> newAttributes = new nsHashPropertyBag();
-
-    bool hasMoreElements;
-    while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
-           hasMoreElements) {
-      nsCOMPtr<nsISupports> element;
-      Unused << NS_WARN_IF(
-          NS_FAILED(enumerator->GetNext(getter_AddRefs(element))));
-      nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
-      MOZ_ASSERT(property);
-
-      nsAutoString name;
-      nsCOMPtr<nsIVariant> value;
-      Unused << NS_WARN_IF(NS_FAILED(property->GetName(name)));
-      Unused << NS_WARN_IF(
-          NS_FAILED(property->GetValue(getter_AddRefs(value))));
-      nsAutoCString valueStr;
-      Unused << NS_WARN_IF(NS_FAILED(value->GetAsACString(valueStr)));
-
-      Unused << NS_WARN_IF(
-          NS_FAILED(newAttributes->SetPropertyAsACString(name, valueStr)));
-    }
-
+    RefPtr<nsHashPropertyBag> newAttributes = new nsHashPropertyBag();
+    newAttributes->CopyFrom(attributes);
     Unused << NS_WARN_IF(NS_FAILED(SetAttributes(newAttributes)));
   }
 }
 
 NS_IMETHODIMP
 nsDNSServiceInfo::GetHost(nsACString& aHost) {
   if (!mIsHostSet) {
     return NS_ERROR_NOT_INITIALIZED;
--- a/xpcom/ds/nsHashPropertyBag.cpp
+++ b/xpcom/ds/nsHashPropertyBag.cpp
@@ -1,23 +1,25 @@
 /* -*- 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 "nsHashPropertyBag.h"
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Move.h"
+#include "mozilla/SimpleEnumerator.h"
 #include "nsArray.h"
 #include "nsArrayEnumerator.h"
+#include "nsIProperty.h"
 #include "nsIVariant.h"
-#include "nsIProperty.h"
 #include "nsThreadUtils.h"
 #include "nsVariant.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/Move.h"
 
 extern "C" {
 
 // This function uses C linkage because it's exposed to Rust to support the
 // `HashPropertyBag` wrapper in the `storage_variant` crate.
 void NS_NewHashPropertyBag(nsIWritablePropertyBag** aBag) {
   MakeRefPtr<nsHashPropertyBag>().forget(aBag);
 }
@@ -223,16 +225,47 @@ nsHashPropertyBagBase::SetPropertyAsAUTF
 NS_IMETHODIMP
 nsHashPropertyBagBase::SetPropertyAsInterface(const nsAString& aProp,
                                               nsISupports* aValue) {
   nsCOMPtr<nsIWritableVariant> var = new nsVariant();
   var->SetAsISupports(aValue);
   return SetProperty(aProp, var);
 }
 
+void nsHashPropertyBagBase::CopyFrom(const nsHashPropertyBagBase* aOther) {
+  for (auto iter = aOther->mPropertyHash.ConstIter(); !iter.Done();
+       iter.Next()) {
+    SetProperty(iter.Key(), iter.UserData());
+  }
+}
+
+void nsHashPropertyBagBase::CopyFrom(nsIPropertyBag* aOther) {
+  CopyFrom(this, aOther);
+}
+
+/* static */ void nsHashPropertyBagBase::CopyFrom(nsIWritablePropertyBag* aTo,
+                                                  nsIPropertyBag* aFrom) {
+  if (aTo && aFrom) {
+    nsCOMPtr<nsISimpleEnumerator> enumerator;
+    if (NS_SUCCEEDED(aFrom->GetEnumerator(getter_AddRefs(enumerator)))) {
+      for (auto& property : SimpleEnumerator<nsIProperty>(enumerator)) {
+        nsString name;
+        nsCOMPtr<nsIVariant> value;
+        Unused << NS_WARN_IF(NS_FAILED(property->GetName(name)));
+        Unused << NS_WARN_IF(
+            NS_FAILED(property->GetValue(getter_AddRefs(value))));
+        Unused << NS_WARN_IF(
+            NS_FAILED(aTo->SetProperty(std::move(name), value)));
+      }
+    } else {
+      NS_WARNING("Unable to copy nsIPropertyBag");
+    }
+  }
+}
+
 /*
  * nsHashPropertyBag implementation.
  */
 
 NS_IMPL_ADDREF(nsHashPropertyBag)
 NS_IMPL_RELEASE(nsHashPropertyBag)
 
 NS_INTERFACE_MAP_BEGIN(nsHashPropertyBag)
--- a/xpcom/ds/nsHashPropertyBag.h
+++ b/xpcom/ds/nsHashPropertyBag.h
@@ -12,17 +12,21 @@
 #include "nsIWritablePropertyBag2.h"
 
 #include "nsCycleCollectionParticipant.h"
 #include "nsInterfaceHashtable.h"
 
 class nsHashPropertyBagBase : public nsIWritablePropertyBag,
                               public nsIWritablePropertyBag2 {
  public:
-  nsHashPropertyBagBase() {}
+  nsHashPropertyBagBase() = default;
+
+  void CopyFrom(const nsHashPropertyBagBase* aOther);
+  void CopyFrom(nsIPropertyBag* aOther);
+  static void CopyFrom(nsIWritablePropertyBag* aTo, nsIPropertyBag* aFrom);
 
   NS_DECL_NSIPROPERTYBAG
   NS_DECL_NSIPROPERTYBAG2
 
   NS_DECL_NSIWRITABLEPROPERTYBAG
   NS_DECL_NSIWRITABLEPROPERTYBAG2
 
  protected:
@@ -42,21 +46,21 @@ class nsHashPropertyBag : public nsHashP
 
  protected:
   virtual ~nsHashPropertyBag();
 };
 
 /* A cycle collected nsHashPropertyBag for main-thread-only use. */
 class nsHashPropertyBagCC final : public nsHashPropertyBagBase {
  public:
-  nsHashPropertyBagCC() {}
+  nsHashPropertyBagCC() = default;
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHashPropertyBagCC,
                                            nsIWritablePropertyBag)
  protected:
-  virtual ~nsHashPropertyBagCC() {}
+  virtual ~nsHashPropertyBagCC() = default;
 };
 
 inline nsISupports* ToSupports(nsHashPropertyBagBase* aPropertyBag) {
   return static_cast<nsIWritablePropertyBag*>(aPropertyBag);
 }
 
 #endif /* nsHashPropertyBag_h___ */