Bug 1433336 - Add nsIDocument::CollectDescendantDocument(). r?smaug draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 26 Jan 2018 20:11:09 +0900
changeset 747566 433d0fe8f0333cfa29b7f1013ee309824601569f
parent 747565 56fe0d8fa4b014110ae5a26779a3912022e166aa
child 747567 62b17453cb7edba8b1335785f0e042d33abbf996
push id96936
push userhikezoe@mozilla.com
push dateFri, 26 Jan 2018 11:11:56 +0000
reviewerssmaug
bugs1433336
milestone60.0a1
Bug 1433336 - Add nsIDocument::CollectDescendantDocument(). r?smaug In contrast to nsIDocument::EnumerateSubDocuments(), this new function is supposed to work with the callback function which does not mutate any state in the document, and also this function checks all descendant documents even if there is a descendant that the callback function returns false. MozReview-Commit-ID: 4f6zD29qQD2
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsIDocument.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -8599,16 +8599,37 @@ nsDocument::EnumerateSubDocuments(nsSubD
   }
   for (auto subdoc : subdocs) {
     if (!aCallback(subdoc, aData)) {
       break;
     }
   }
 }
 
+void
+nsDocument::CollectDescendantDocuments(
+  nsTArray<nsCOMPtr<nsIDocument>>& aDescendants,
+  nsDocTestFunc aCallback) const
+{
+  if (!mSubDocuments) {
+    return;
+  }
+
+  for (auto iter = mSubDocuments->Iter(); !iter.Done(); iter.Next()) {
+    auto entry = static_cast<SubDocMapEntry*>(iter.Get());
+    const nsIDocument* subdoc = entry->mSubDocument;
+    if (subdoc) {
+      if (aCallback(subdoc)) {
+        aDescendants.AppendElement(entry->mSubDocument);
+      }
+      subdoc->CollectDescendantDocuments(aDescendants, aCallback);
+    }
+  }
+}
+
 #ifdef DEBUG_bryner
 #define DEBUG_PAGE_CACHE
 #endif
 
 bool
 nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
 {
   if (EventHandlingSuppressed()) {
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -673,16 +673,19 @@ public:
                                                nsAtom* aPrefix,
                                                int32_t aNamespaceID,
                                                const nsAString* aIs = nullptr) override;
 
   virtual void Sanitize() override;
 
   virtual void EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
                                                  void *aData) override;
+  virtual void CollectDescendantDocuments(
+    nsTArray<nsCOMPtr<nsIDocument>>& aDescendants,
+    nsDocTestFunc aCallback) const override;
 
   virtual bool CanSavePresentation(nsIRequest *aNewRequest) override;
   virtual void Destroy() override;
   virtual void RemovedFromDocShell() override;
   virtual already_AddRefed<nsILayoutHistoryState> GetLayoutHistoryState() const override;
 
   virtual void BlockOnload() override;
   virtual void UnblockOnload(bool aFireSync) override;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -1912,16 +1912,25 @@ public:
    * The enumerator callback should return true to continue enumerating, or
    * false to stop.  This will never get passed a null aDocument.
    */
   typedef bool (*nsSubDocEnumFunc)(nsIDocument *aDocument, void *aData);
   virtual void EnumerateSubDocuments(nsSubDocEnumFunc aCallback,
                                      void *aData) = 0;
 
   /**
+   * Collect all the descendant documents for which |aCalback| returns true.
+   * The callback function must not mutate any state for the given document.
+   */
+  typedef bool (*nsDocTestFunc)(const nsIDocument* aDocument);
+  virtual void CollectDescendantDocuments(
+    nsTArray<nsCOMPtr<nsIDocument>>& aDescendants,
+    nsDocTestFunc aCallback) const = 0;
+
+  /**
    * Check whether it is safe to cache the presentation of this document
    * and all of its subdocuments. This method checks the following conditions
    * recursively:
    *  - Some document types, such as plugin documents, cannot be safely cached.
    *  - If there are any pending requests, we don't allow the presentation
    *    to be cached.  Ideally these requests would be suspended and resumed,
    *    but that is difficult in some cases, such as XMLHttpRequest.
    *  - If there are any beforeunload or unload listeners, we must fire them