Bug 1246290 - Add a disableapz HTML attribute that allows disabling APZ on specific scrollframes in chrome documents. r?botond,ehsan draft
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 18 Feb 2016 17:47:14 -0500
changeset 331966 3b19fdd5cb2efe45c6847bc6488fb8097517118f
parent 331965 b6192de79ed01f317e73787f063c04db79b04267
child 514511 e47eed6d7353a52282fdacf1a286500201358cdd
push id11128
push userkgupta@mozilla.com
push dateThu, 18 Feb 2016 22:47:37 +0000
reviewersbotond, ehsan
bugs1246290
milestone47.0a1
Bug 1246290 - Add a disableapz HTML attribute that allows disabling APZ on specific scrollframes in chrome documents. r?botond,ehsan MozReview-Commit-ID: TQ6efi14z4
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/webidl/HTMLElement.webidl
layout/base/nsLayoutUtils.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -6363,16 +6363,23 @@ nsContentUtils::IsUserFocusIgnored(nsINo
 
 bool
 nsContentUtils::HasScrollgrab(nsIContent* aContent)
 {
   nsGenericHTMLElement* element = nsGenericHTMLElement::FromContentOrNull(aContent);
   return element && element->Scrollgrab();
 }
 
+bool
+nsContentUtils::HasDisableApz(nsIContent* aContent)
+{
+  nsGenericHTMLElement* element = nsGenericHTMLElement::FromContentOrNull(aContent);
+  return element && element->Disableapz();
+}
+
 void
 nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow)
 {
   if (!aWindow) {
     return;
   }
 
   // Note that because FlushPendingNotifications flushes parents, this
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -2106,16 +2106,22 @@ public:
 
   /**
    * Returns if aContent has the 'scrollgrab' property.
    * aContent may be null (in this case false is returned).
    */
   static bool HasScrollgrab(nsIContent* aContent);
 
   /**
+   * Returns true if aContent is a non-null HTML element and has the
+   * 'disableapz' property. Returns false otherwise.
+   */
+  static bool HasDisableApz(nsIContent* aContent);
+
+  /**
    * Flushes the layout tree (recursively)
    *
    * @param aWindow the window the flush should start at
    *
    */
   static void FlushLayoutForTree(nsPIDOMWindowOuter* aWindow);
 
   /**
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1763,16 +1763,23 @@ nsGenericHTMLElement::GetURIAttr(nsIAtom
 nsGenericHTMLElement::IsScrollGrabAllowed(JSContext*, JSObject*)
 {
   // Only allow scroll grabbing in chrome and certified apps.
   nsIPrincipal* prin = nsContentUtils::SubjectPrincipal();
   return nsContentUtils::IsSystemPrincipal(prin) ||
     prin->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED;
 }
 
+/* static */ bool
+nsGenericHTMLElement::IsDisablingApzAllowed(JSContext*, JSObject*)
+{
+  // Only allow this in chrome code.
+  return nsContentUtils::IsSystemPrincipal(nsContentUtils::SubjectPrincipal());
+}
+
 nsresult
 nsGenericHTMLElement::GetURIListAttr(nsIAtom* aAttr, nsAString& aResult)
 {
   aResult.Truncate();
 
   nsAutoString value;
   if (!GetAttr(kNameSpaceID_None, aAttr, value))
     return NS_OK;
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -48,18 +48,19 @@ typedef nsMappedAttributeElement nsGener
 /**
  * A common superclass for HTML elements
  */
 class nsGenericHTMLElement : public nsGenericHTMLElementBase,
                              public nsIDOMHTMLElement
 {
 public:
   explicit nsGenericHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
-    : nsGenericHTMLElementBase(aNodeInfo),
-      mScrollgrab(false)
+    : nsGenericHTMLElementBase(aNodeInfo)
+    , mScrollgrab(false)
+    , mDisableApz(false)
   {
     NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
                  "Unexpected namespace");
     AddStatesSilently(NS_EVENT_STATE_LTR);
     SetFlags(NODE_HAS_DIRECTION_LTR);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
@@ -235,16 +236,24 @@ public:
   bool Scrollgrab() const
   {
     return mScrollgrab;
   }
   void SetScrollgrab(bool aValue)
   {
     mScrollgrab = aValue;
   }
+  bool Disableapz() const
+  {
+    return mDisableApz;
+  }
+  void SetDisableapz(bool aValue)
+  {
+    mDisableApz = aValue;
+  }
 
   void GetInnerText(mozilla::dom::DOMString& aValue, mozilla::ErrorResult& aError);
   void SetInnerText(const nsAString& aValue);
 
   /**
    * Determine whether an attribute is an event (onclick, etc.)
    * @param aName the attribute
    * @return whether the name is an event handler name
@@ -970,16 +979,19 @@ public:
     // name (which doesn't have to match the id or anything).
     // HasName() is true precisely when name is nonempty.
     return aElement->IsHTMLElement(nsGkAtoms::img) && aElement->HasName();
   }
 
   static bool
   IsScrollGrabAllowed(JSContext*, JSObject*);
 
+  static bool
+  IsDisablingApzAllowed(JSContext*, JSObject*);
+
 protected:
   /**
    * Add/remove this element to the documents name cache
    */
   void AddToNameTable(nsIAtom* aName) {
     NS_ASSERTION(HasName(), "Node doesn't have name?");
     nsIDocument* doc = GetCurrentDoc();
     if (doc && !IsInAnonymousSubtree()) {
@@ -1240,16 +1252,17 @@ protected:
   bool IsEditableRoot() const;
 
   nsresult SetUndoScopeInternal(bool aUndoScope);
 
 private:
   void ChangeEditableState(int32_t aChange);
 
   bool mScrollgrab;
+  bool mDisableApz;
 };
 
 namespace mozilla {
 namespace dom {
 class HTMLFieldSetElement;
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/webidl/HTMLElement.webidl
+++ b/dom/webidl/HTMLElement.webidl
@@ -96,16 +96,24 @@ partial interface HTMLElement {
 
 // Extension for scroll-grabbing, used in the B2G dynamic toolbar.
 // This is likely to be revised.
 partial interface HTMLElement {
   [Func="nsGenericHTMLElement::IsScrollGrabAllowed"]
            attribute boolean scrollgrab;
 };
 
+// Extension for disabling APZ-scrolling in chrome code. This is
+// a temporary hack, mostly for the DevTools team until they can make
+// their CodeMirror-based tooling APZ-friendly.
+partial interface HTMLElement {
+  [Func="nsGenericHTMLElement::IsDisablingApzAllowed"]
+           attribute boolean disableapz;
+};
+
 [NoInterfaceObject]
 interface TouchEventHandlers {
   [Func="nsGenericHTMLElement::TouchEventsEnabled"]
            attribute EventHandler ontouchstart;
   [Func="nsGenericHTMLElement::TouchEventsEnabled"]
            attribute EventHandler ontouchend;
   [Func="nsGenericHTMLElement::TouchEventsEnabled"]
            attribute EventHandler ontouchmove;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1031,16 +1031,19 @@ GetDisplayPortFromMarginsData(nsIContent
   result = result.MoveInsideAndClamp(expandedScrollableRect - scrollPos);
 
   return result;
 }
 
 static bool
 DisableApzForElement(nsIContent* aContent)
 {
+  if (nsContentUtils::HasDisableApz(aContent)) {
+    return true;
+  }
   if (gfxPrefs::APZDisableForSLEPages() && aContent) {
     nsIDocument* doc = aContent->GetComposedDoc();
     return (doc && doc->HasScrollLinkedEffect());
   }
   return false;
 }
 
 static bool