Bug 1265718 - Decouple AnimationsFront from AnimationsActor;r=jryans
authorEddy Bruel <ejpbruel@mozilla.com>
Thu, 26 May 2016 15:47:52 +0200
changeset 338095 9afab6308cd97d470c6514ccb0e348103e034e4d
parent 338094 a33592050e2465ea62f9d62c42623c9c88b9808f
child 338096 f5ce758ba0fdf72adcc8637be3206d524872040e
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1265718
milestone49.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 1265718 - Decouple AnimationsFront from AnimationsActor;r=jryans
devtools/client/animationinspector/animation-controller.js
devtools/server/actors/animation.js
devtools/server/tests/browser/head.js
devtools/server/tests/mochitest/test_animation_actor-lifetime.html
devtools/shared/fronts/animation.js
devtools/shared/specs/animation.js
--- a/devtools/client/animationinspector/animation-controller.js
+++ b/devtools/client/animationinspector/animation-controller.js
@@ -14,17 +14,17 @@
 
 var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 var { loader, require } = Cu.import("resource://devtools/shared/Loader.jsm");
 var { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "promise");
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
-loader.lazyRequireGetter(this, "AnimationsFront", "devtools/server/actors/animation", true);
+loader.lazyRequireGetter(this, "AnimationsFront", "devtools/shared/fronts/animation", true);
 
 const { LocalizationHelper } = require("devtools/client/shared/l10n");
 
 const STRINGS_URI = "chrome://devtools/locale/animationinspector.properties";
 const L10N = new LocalizationHelper(STRINGS_URI);
 
 // Global toolbox/inspector, set when startup is called.
 var gToolbox, gInspector;
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -26,20 +26,17 @@
  */
 
 const {Cu} = require("chrome");
 const promise = require("promise");
 const {Task} = require("devtools/shared/task");
 const protocol = require("devtools/shared/protocol");
 const {ActorClass, Actor, FrontClass, Front,
        Arg, method, RetVal, types} = protocol;
-// Make sure the nodeActor type is know here.
-const {NodeActor} = require("devtools/server/actors/inspector");
-const {AnimationPlayerFront} = require("devtools/shared/fronts/animation");
-const {animationPlayerSpec} = require("devtools/shared/specs/animation");
+const {animationPlayerSpec, animationsSpec} = require("devtools/shared/specs/animation");
 const events = require("sdk/event/core");
 
 // Types of animations.
 const ANIMATION_TYPES = {
   CSS_ANIMATION: "cssanimation",
   CSS_TRANSITION: "csstransition",
   SCRIPT_ANIMATION: "scriptanimation",
   UNKNOWN: "unknown"
@@ -429,41 +426,21 @@ var AnimationPlayerActor = protocol.Acto
     return this.player.effect.getProperties().map(property => {
       return {name: property.property, values: property.values};
     });
   }
 });
 
 exports.AnimationPlayerActor = AnimationPlayerActor;
 
- /**
- * Sent with the 'mutations' event as part of an array of changes, used to
- * inform fronts of the type of change that occured.
- */
-types.addDictType("animationMutationChange", {
-  // The type of change ("added" or "removed").
-  type: "string",
-  // The changed AnimationPlayerActor.
-  player: "animationplayer"
-});
-
 /**
  * The Animations actor lists animation players for a given node.
  */
-var AnimationsActor = exports.AnimationsActor = ActorClass({
-  typeName: "animations",
-
-  events: {
-    "mutations": {
-      type: "mutations",
-      changes: Arg(0, "array:animationMutationChange")
-    }
-  },
-
-  initialize: function (conn, tabActor) {
+var AnimationsActor = exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
+  initialize: function(conn, tabActor) {
     Actor.prototype.initialize.call(this, conn);
     this.tabActor = tabActor;
 
     this.onWillNavigate = this.onWillNavigate.bind(this);
     this.onNavigate = this.onNavigate.bind(this);
     this.onAnimationMutation = this.onAnimationMutation.bind(this);
 
     this.allAnimationsPaused = false;
@@ -491,36 +468,31 @@ var AnimationsActor = exports.Animations
   /**
    * Clients can optionally call this with a reference to their WalkerActor.
    * If they do, then AnimationPlayerActor's forms are going to also include
    * NodeActor IDs when the corresponding NodeActors do exist.
    * This, in turns, is helpful for clients to avoid having to go back once more
    * to the server to get a NodeActor for a particular animation.
    * @param {WalkerActor} walker
    */
-  setWalkerActor: method(function (walker) {
+  setWalkerActor: function (walker) {
     this.walker = walker;
-  }, {
-    request: {
-      walker: Arg(0, "domwalker")
-    },
-    response: {}
-  }),
+  },
 
   /**
    * Retrieve the list of AnimationPlayerActor actors for currently running
    * animations on a node and its descendants.
    * Note that calling this method a second time will destroy all previously
    * retrieved AnimationPlayerActors. Indeed, the lifecycle of these actors
    * is managed here on the server and tied to getAnimationPlayersForNode
    * being called.
    * @param {NodeActor} nodeActor The NodeActor as defined in
    * /devtools/server/actors/inspector
    */
-  getAnimationPlayersForNode: method(function (nodeActor) {
+  getAnimationPlayersForNode: function (nodeActor) {
     let animations = nodeActor.rawNode.getAnimations({subtree: true});
 
     // Destroy previously stored actors
     if (this.actors) {
       this.actors.forEach(actor => actor.destroy());
     }
     this.actors = [];
 
@@ -537,24 +509,17 @@ var AnimationsActor = exports.Animations
     let win = nodeActor.rawNode.ownerDocument.defaultView;
     this.observer = new win.MutationObserver(this.onAnimationMutation);
     this.observer.observe(nodeActor.rawNode, {
       animations: true,
       subtree: true
     });
 
     return this.actors;
-  }, {
-    request: {
-      actorID: Arg(0, "domnode")
-    },
-    response: {
-      players: RetVal("array:animationplayer")
-    }
-  }),
+  },
 
   onAnimationMutation: function (mutations) {
     let eventData = [];
     let readyPromises = [];
 
     for (let {addedAnimations, removedAnimations} of mutations) {
       for (let player of removedAnimations) {
         // Note that animations are reported as removed either when they are
@@ -624,24 +589,21 @@ var AnimationsActor = exports.Animations
     }
   },
 
   /**
    * After the client has called getAnimationPlayersForNode for a given DOM
    * node, the actor starts sending animation mutations for this node. If the
    * client doesn't want this to happen anymore, it should call this method.
    */
-  stopAnimationPlayerUpdates: method(function () {
+  stopAnimationPlayerUpdates: function () {
     if (this.observer && !Cu.isDeadWrapper(this.observer)) {
       this.observer.disconnect();
     }
-  }, {
-    request: {},
-    response: {}
-  }),
+  },
 
   /**
    * Iterates through all nodes below a given rootNode (optionally also in
    * nested frames) and finds all existing animation players.
    * @param {DOMNode} rootNode The root node to start iterating at. Animation
    * players will *not* be reported for this node.
    * @param {Boolean} traverseFrames Whether we should iterate through nested
    * frames too.
@@ -669,120 +631,81 @@ var AnimationsActor = exports.Animations
     if (isTopLevel) {
       this.allAnimationsPaused = false;
     }
   },
 
   /**
    * Pause all animations in the current tabActor's frames.
    */
-  pauseAll: method(function () {
+  pauseAll: function () {
     let readyPromises = [];
     // Until the WebAnimations API provides a way to play/pause via the document
     // timeline, we have to iterate through the whole DOM to find all players.
     for (let player of
          this.getAllAnimations(this.tabActor.window.document, true)) {
       player.pause();
       readyPromises.push(player.ready);
     }
     this.allAnimationsPaused = true;
     return promise.all(readyPromises);
-  }, {
-    request: {},
-    response: {}
-  }),
+  },
 
   /**
    * Play all animations in the current tabActor's frames.
    * This method only returns when animations have left their pending states.
    */
-  playAll: method(function () {
+  playAll: function () {
     let readyPromises = [];
     // Until the WebAnimations API provides a way to play/pause via the document
     // timeline, we have to iterate through the whole DOM to find all players.
     for (let player of
          this.getAllAnimations(this.tabActor.window.document, true)) {
       player.play();
       readyPromises.push(player.ready);
     }
     this.allAnimationsPaused = false;
     return promise.all(readyPromises);
-  }, {
-    request: {},
-    response: {}
-  }),
+  },
 
-  toggleAll: method(function () {
+  toggleAll: function () {
     if (this.allAnimationsPaused) {
       return this.playAll();
     }
     return this.pauseAll();
-  }, {
-    request: {},
-    response: {}
-  }),
+  },
 
   /**
    * Toggle (play/pause) several animations at the same time.
    * @param {Array} players A list of AnimationPlayerActor objects.
    * @param {Boolean} shouldPause If set to true, the players will be paused,
    * otherwise they will be played.
    */
-  toggleSeveral: method(function (players, shouldPause) {
+  toggleSeveral: function (players, shouldPause) {
     return promise.all(players.map(player => {
       return shouldPause ? player.pause() : player.play();
     }));
-  }, {
-    request: {
-      players: Arg(0, "array:animationplayer"),
-      shouldPause: Arg(1, "boolean")
-    },
-    response: {}
-  }),
+  },
 
   /**
    * Set the current time of several animations at the same time.
    * @param {Array} players A list of AnimationPlayerActor.
    * @param {Number} time The new currentTime.
    * @param {Boolean} shouldPause Should the players be paused too.
    */
-  setCurrentTimes: method(function (players, time, shouldPause) {
+  setCurrentTimes: function (players, time, shouldPause) {
     return promise.all(players.map(player => {
       let pause = shouldPause ? player.pause() : promise.resolve();
       return pause.then(() => player.setCurrentTime(time));
     }));
-  }, {
-    request: {
-      players: Arg(0, "array:animationplayer"),
-      time: Arg(1, "number"),
-      shouldPause: Arg(2, "boolean")
-    },
-    response: {}
-  }),
+  },
 
   /**
    * Set the playback rate of several animations at the same time.
    * @param {Array} players A list of AnimationPlayerActor.
    * @param {Number} rate The new rate.
    */
-  setPlaybackRates: method(function (players, rate) {
+  setPlaybackRates: function (players, rate) {
     for (let player of players) {
       player.setPlaybackRate(rate);
     }
-  }, {
-    request: {
-      players: Arg(0, "array:animationplayer"),
-      rate: Arg(1, "number")
-    },
-    response: {}
-  })
-});
-
-var AnimationsFront = exports.AnimationsFront = FrontClass(AnimationsActor, {
-  initialize: function (client, {animationsActor}) {
-    Front.prototype.initialize.call(this, client, {actor: animationsActor});
-    this.manage(this);
-  },
-
-  destroy: function () {
-    Front.prototype.destroy.call(this);
   }
 });
--- a/devtools/server/tests/browser/head.js
+++ b/devtools/server/tests/browser/head.js
@@ -44,17 +44,17 @@ var addTab = Task.async(function* (url) 
     let isBlank = url == "about:blank";
     waitForFocus(resolve, content, isBlank);
   });
 
   return tab.linkedBrowser;
 });
 
 function* initAnimationsFrontForUrl(url) {
-  const {AnimationsFront} = require("devtools/server/actors/animation");
+  const {AnimationsFront} = require("devtools/shared/fronts/animation");
   const {InspectorFront} = require("devtools/shared/fronts/inspector");
 
   yield addTab(url);
 
   initDebuggerServer();
   let client = new DebuggerClient(DebuggerServer.connectPipe());
   let form = yield connectDebuggerClient(client);
   let inspector = InspectorFront(client, form);
--- a/devtools/server/tests/mochitest/test_animation_actor-lifetime.html
+++ b/devtools/server/tests/mochitest/test_animation_actor-lifetime.html
@@ -8,17 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug 1247243</title>
 
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
   <script type="application/javascript;version=1.8">
 window.onload = function() {
   const Ci = Components.interfaces;
-  const {AnimationsFront} = require("devtools/server/actors/animation");
+  const {AnimationsFront} = require("devtools/shared/fronts/animation");
   const {InspectorFront} = require("devtools/shared/fronts/inspector");
 
   SimpleTest.waitForExplicitFinish();
 
   let gWalker = null;
   let gClient = null;
   let animationsFront = null;
 
--- a/devtools/shared/fronts/animation.js
+++ b/devtools/shared/fronts/animation.js
@@ -4,17 +4,20 @@
 "use strict";
 
 const {
   Front,
   FrontClassWithSpec,
   custom,
   preEvent
 } = require("devtools/shared/protocol");
-const { animationPlayerSpec } = require("devtools/shared/specs/animation");
+const {
+  animationPlayerSpec,
+  animationsSpec
+} = require("devtools/shared/specs/animation");
 const { Task } = require("devtools/shared/task");
 
 const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, {
   initialize: function (conn, form, detail, ctx) {
     Front.prototype.initialize.call(this, conn, form, detail, ctx);
 
     this.state = {};
   },
@@ -114,8 +117,21 @@ const AnimationPlayerFront = FrontClassW
       }
     }
 
     return {state: data, hasChanged};
   }
 });
 
 exports.AnimationPlayerFront = AnimationPlayerFront;
+
+const AnimationsFront = FrontClassWithSpec(animationsSpec, {
+  initialize: function (client, {animationsActor}) {
+    Front.prototype.initialize.call(this, client, {actor: animationsActor});
+    this.manage(this);
+  },
+
+  destroy: function () {
+    Front.prototype.destroy.call(this);
+  }
+});
+
+exports.AnimationsFront = AnimationsFront;
--- a/devtools/shared/specs/animation.js
+++ b/devtools/shared/specs/animation.js
@@ -1,14 +1,31 @@
 /* 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/. */
 "use strict";
 
-const { Arg, RetVal, generateActorSpec } = require("devtools/shared/protocol");
+const {
+  Arg,
+  RetVal,
+  generateActorSpec,
+  types
+} = require("devtools/shared/protocol");
+require("devtools/shared/specs/inspector");
+
+/**
+ * Sent with the 'mutations' event as part of an array of changes, used to
+ * inform fronts of the type of change that occured.
+ */
+types.addDictType("animationMutationChange", {
+  // The type of change ("added" or "removed").
+  type: "string",
+  // The changed AnimationPlayerActor.
+  player: "animationplayer"
+});
 
 const animationPlayerSpec = generateActorSpec({
   typeName: "animationplayer",
 
   events: {
     "changed": {
       type: "changed",
       state: Arg(0, "json")
@@ -58,8 +75,77 @@ const animationPlayerSpec = generateActo
       response: {
         properties: RetVal("array:json")
       }
     }
   }
 });
 
 exports.animationPlayerSpec = animationPlayerSpec;
+
+const animationsSpec = generateActorSpec({
+  typeName: "animations",
+
+  events: {
+    "mutations": {
+      type: "mutations",
+      changes: Arg(0, "array:animationMutationChange")
+    }
+  },
+
+  methods: {
+    setWalkerActor: {
+      request: {
+        walker: Arg(0, "domwalker")
+      },
+      response: {}
+    },
+    getAnimationPlayersForNode: {
+      request: {
+        actorID: Arg(0, "domnode")
+      },
+      response: {
+        players: RetVal("array:animationplayer")
+      }
+    },
+    stopAnimationPlayerUpdates: {
+      request: {},
+      response: {}
+    },
+    pauseAll: {
+      request: {},
+      response: {}
+    },
+    playAll: {
+      request: {},
+      response: {}
+    },
+    toggleAll: {
+      request: {},
+      response: {}
+    },
+    toggleSeveral: {
+      request: {
+        players: Arg(0, "array:animationplayer"),
+        shouldPause: Arg(1, "boolean")
+      },
+      response: {}
+    },
+    setCurrentTimes: {
+      request: {
+        players: Arg(0, "array:animationplayer"),
+        time: Arg(1, "number"),
+        shouldPause: Arg(2, "boolean")
+      },
+      response: {}
+    },
+    setPlaybackRates: {
+      request: {
+        players: Arg(0, "array:animationplayer"),
+        rate: Arg(1, "number")
+      },
+      response: {}
+    }
+  }
+});
+
+exports.animationsSpec = animationsSpec;
+