Bug 1314442 - Limit editor's editability to the right subtree. r=masayuki
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 29 Nov 2016 17:07:27 -0500
changeset 324708 f2631b49bb7d178dde8e5f2f4b740803453fbbb4
parent 324707 e10cae7946b2581b3737771d456f4474734c63f7
child 324709 667c1a30679730fbf513e310b2768bc8eea5cc51
push id31014
push usercbook@mozilla.com
push dateWed, 30 Nov 2016 14:46:01 +0000
treeherdermozilla-central@3b3a1f1c4b9b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1314442
milestone53.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 1314442 - Limit editor's editability to the right subtree. r=masayuki
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -3230,24 +3230,45 @@ HTMLEditor::ContentInserted(nsIDocument*
                             nsIContent* aContainer,
                             nsIContent* aChild,
                             int32_t aIndexInContainer)
 {
   DoContentInserted(aDocument, aContainer, aChild, aIndexInContainer,
                     eInserted);
 }
 
+bool
+HTMLEditor::IsInObservedSubtree(nsIDocument* aDocument,
+                                nsIContent* aContainer,
+                                nsIContent* aChild)
+{
+  if (!aChild) {
+    return false;
+  }
+
+  Element* root = GetRoot();
+  // To be super safe here, check both ChromeOnlyAccess and GetBindingParent.
+  // That catches (also unbound) native anonymous content, XBL and ShadowDOM.
+  if (root &&
+      (root->ChromeOnlyAccess() != aChild->ChromeOnlyAccess() ||
+       root->GetBindingParent() != aChild->GetBindingParent())) {
+    return false;
+  }
+
+  return !aChild->ChromeOnlyAccess() && !aChild->GetBindingParent();
+}
+
 void
 HTMLEditor::DoContentInserted(nsIDocument* aDocument,
                               nsIContent* aContainer,
                               nsIContent* aChild,
                               int32_t aIndexInContainer,
                               InsertedOrAppended aInsertedOrAppended)
 {
-  if (!aChild) {
+  if (!IsInObservedSubtree(aDocument, aContainer, aChild)) {
     return;
   }
 
   nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
 
   if (ShouldReplaceRootElement()) {
     nsContentUtils::AddScriptRunner(NewRunnableMethod(
       this, &HTMLEditor::ResetRootElementAndEventTarget));
@@ -3285,16 +3306,20 @@ HTMLEditor::DoContentInserted(nsIDocumen
 
 void
 HTMLEditor::ContentRemoved(nsIDocument* aDocument,
                            nsIContent* aContainer,
                            nsIContent* aChild,
                            int32_t aIndexInContainer,
                            nsIContent* aPreviousSibling)
 {
+  if (!IsInObservedSubtree(aDocument, aContainer, aChild)) {
+    return;
+  }
+
   nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
 
   if (SameCOMIdentity(aChild, mRootElement)) {
     nsContentUtils::AddScriptRunner(NewRunnableMethod(
       this, &HTMLEditor::ResetRootElementAndEventTarget));
   }
   // We don't need to handle our own modifications
   else if (!mAction && (aContainer ? aContainer->IsEditable() : aDocument->IsEditable())) {
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -935,16 +935,20 @@ protected:
   nsresult GetPositionAndDimensions(nsIDOMElement* aElement,
                                     int32_t& aX, int32_t& aY,
                                     int32_t& aW, int32_t& aH,
                                     int32_t& aBorderLeft,
                                     int32_t& aBorderTop,
                                     int32_t& aMarginLeft,
                                     int32_t& aMarginTop);
 
+  bool IsInObservedSubtree(nsIDocument* aDocument,
+                           nsIContent* aContainer,
+                           nsIContent* aChild);
+
   // resizing
   bool mIsObjectResizingEnabled;
   bool mIsResizing;
   bool mPreserveRatio;
   bool mResizedObjectIsAnImage;
 
   // absolute positioning
   bool mIsAbsolutelyPositioningEnabled;