Bug 974139 - Redefine registration logic to return panel options dynamically (r=margaret)
authorLucas Rocha <lucasr@mozilla.com>
Tue, 25 Feb 2014 17:29:49 +0000
changeset 170889 6fa0c7a9f778bacc2bfd722b7b5f86381e1d1ce5
parent 170888 9e154b6934627348e724f58ae7b7c6eb9b7ae9b4
child 170890 95ff5102419c0e9f741a0792c9b0d0205e93b8f8
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersmargaret
bugs974139
milestone30.0a1
Bug 974139 - Redefine registration logic to return panel options dynamically (r=margaret)
mobile/android/modules/Home.jsm
--- a/mobile/android/modules/Home.jsm
+++ b/mobile/android/modules/Home.jsm
@@ -151,61 +151,119 @@ let HomeBanner = (function () {
         Services.obs.removeObserver(this, "HomeBanner:Get");
         Services.obs.removeObserver(this, "HomeBanner:Click");
         Services.obs.removeObserver(this, "HomeBanner:Dismiss");
       }
     }
   });
 })();
 
-function Panel(options) {
-  if ("id" in options)
-    this.id = options.id;
-
-  if ("title" in options)
-    this.title = options.title;
+function Panel(id, options) {
+  this.id = id;
+  this.title = options.title;
 
   if ("layout" in options)
     this.layout = options.layout;
 
   if ("views" in options)
     this.views = options.views;
 }
 
 // We need this function to have access to the HomePanels
 // private members without leaking it outside Home.jsm.
 let handlePanelsGet;
 
 let HomePanels = (function () {
   // Holds the current set of registered panels that can be
-  // installed, updated, uninstalled, or unregistered. This
-  // is also used to retrieve the list of available panels
-  // in the system (see HomePanels:Get handler).
+  // installed, updated, uninstalled, or unregistered. It maps
+  // panel ids with the functions that dynamically generate
+  // their respective panel options. This is used to retrieve
+  // the current list of available panels in the system.
+  // See HomePanels:Get handler.
   let _registeredPanels = {};
 
-  let _panelToJSON = function(panel) {
-    return {
-      id: panel.id,
-      title: panel.title,
-      layout: panel.layout,
-      views: panel.views
-    };
+  // Valid layouts for a panel.
+  let Layout = Object.freeze({
+    FRAME: "frame"
+  });
+
+  // Valid types of views for a dataset.
+  let View = Object.freeze({
+    LIST: "list",
+    GRID: "grid"
+  });
+
+  // Valid item types for a panel view.
+  let Item = Object.freeze({
+    ARTICLE: "article",
+    IMAGE: "image"
+  });
+
+  // Valid item handlers for a panel view.
+  let ItemHandler = Object.freeze({
+    BROWSER: "browser",
+    INTENT: "intent"
+  });
+
+  let _generatePanel = function(id) {
+    let panel = new Panel(id, _registeredPanels[id]());
+
+    if (!panel.id || !panel.title) {
+      throw "Home.panels: Can't create a home panel without an id and title!";
+    }
+
+    if (!_valueExists(Layout, panel.layout)) {
+      throw "Home.panels: Invalid layout for panel: panel.id = " + panel.id + ", panel.layout =" + panel.layout;
+    }
+
+    for (let view of panel.views) {
+      if (!_valueExists(View, view.type)) {
+        throw "Home.panels: Invalid view type: panel.id = " + panel.id + ", view.type = " + view.type;
+      }
+
+      if (!view.itemType) {
+        if (view.type == View.LIST) {
+          // Use ARTICLE item type by default in LIST views
+          view.itemType = Item.ARTICLE;
+        } else if (view.type == View.GRID) {
+          // Use IMAGE item type by default in GRID views
+          view.itemType = Item.IMAGE;
+        }
+      } else if (!_valueExists(Item, view.itemType)) {
+        throw "Home.panels: Invalid item type: panel.id = " + panel.id + ", view.itemType = " + view.itemType;
+      }
+
+      if (!view.itemHandler) {
+        // Use BROWSER item handler by default
+        view.itemHandler = ItemHandler.BROWSER;
+      } else if (!_valueExists(ItemHandler, view.itemHandler)) {
+        throw "Home.panels: Invalid item handler: panel.id = " + panel.id + ", view.itemHandler = " + view.itemHandler;
+      }
+
+      if (!view.dataset) {
+        throw "Home.panels: No dataset provided for view: panel.id = " + panel.id + ", view.type = " + view.type;
+      }
+    }
+
+    return panel;
   };
 
   handlePanelsGet = function(data) {
     let requestId = data.requestId;
     let ids = data.ids || null;
 
     let panels = [];
     for (let id in _registeredPanels) {
-      let panel = _registeredPanels[id];
-
       // Null ids means we want to fetch all available panels
-      if (ids == null || ids.indexOf(panel.id) >= 0) {
-        panels.push(_panelToJSON(panel));
+      if (ids == null || ids.indexOf(id) >= 0) {
+        try {
+          panels.push(_generatePanel(id));
+        } catch(e) {
+          Cu.reportError("Home.panels: Invalid options, panel.id = " + id + ": " + e);
+        }
       }
     }
 
     sendMessageToJava({
       type: "HomePanels:Data",
       panels: panels,
       requestId: requestId
     });
@@ -223,99 +281,46 @@ let HomePanels = (function () {
 
   let _assertPanelExists = function(id) {
     if (!(id in _registeredPanels)) {
       throw "Home.panels: Panel doesn't exist: id = " + id;
     }
   };
 
   return Object.freeze({
-    // Valid layouts for a panel.
-    Layout: Object.freeze({
-      FRAME: "frame"
-    }),
-
-    // Valid types of views for a dataset.
-    View: Object.freeze({
-      LIST: "list",
-      GRID: "grid"
-    }),
-
-    // Valid item types for a panel view.
-    Item: Object.freeze({
-      ARTICLE: "article",
-      IMAGE: "image"
-    }),
+    Layout: Layout,
+    View: View,
+    Item: Item,
+    ItemHandler: ItemHandler,
 
-    // Valid item handlers for a panel view.
-    ItemHandler: Object.freeze({
-      BROWSER: "browser",
-      INTENT: "intent"
-    }),
-
-    register: function(options) {
-      let panel = new Panel(options);
-
+    register: function(id, optionsCallback) {
       // Bail if the panel already exists
-      if (panel.id in _registeredPanels) {
-        throw "Home.panels: Panel already exists: id = " + panel.id;
-      }
-
-      if (!panel.id || !panel.title) {
-        throw "Home.panels: Can't create a home panel without an id and title!";
+      if (id in _registeredPanels) {
+        throw "Home.panels: Panel already exists: id = " + id;
       }
 
-      if (!_valueExists(this.Layout, panel.layout)) {
-        throw "Home.panels: Invalid layout for panel: panel.id = " + panel.id + ", panel.layout =" + panel.layout;
+      if (!optionsCallback || typeof optionsCallback !== "function") {
+        throw "Home.panels: Panel callback must be a function: id = " + id;
       }
 
-      for (let view of panel.views) {
-        if (!_valueExists(this.View, view.type)) {
-          throw "Home.panels: Invalid view type: panel.id = " + panel.id + ", view.type = " + view.type;
-        }
-
-        if (!view.itemType) {
-          if (view.type == this.View.LIST) {
-            // Use ARTICLE item type by default in LIST views
-            view.itemType = this.Item.ARTICLE;
-          } else if (view.type == this.View.GRID) {
-            // Use IMAGE item type by default in GRID views
-            view.itemType = this.Item.IMAGE;
-          }
-        } else if (!_valueExists(this.Item, view.itemType)) {
-          throw "Home.panels: Invalid item type: panel.id = " + panel.id + ", view.itemType = " + view.itemType;
-        }
-
-        if (!view.itemHandler) {
-          // Use BROWSER item handler by default
-          view.itemHandler = this.ItemHandler.BROWSER;
-        } else if (!_valueExists(this.ItemHandler, view.itemHandler)) {
-          throw "Home.panels: Invalid item handler: panel.id = " + panel.id + ", view.itemHandler = " + view.itemHandler;
-        }
-
-        if (!view.dataset) {
-          throw "Home.panels: No dataset provided for view: panel.id = " + panel.id + ", view.type = " + view.type;
-        }
-      }
-
-      _registeredPanels[panel.id] = panel;
+      _registeredPanels[id] = optionsCallback;
     },
 
     unregister: function(id) {
       _assertPanelExists(id);
 
       delete _registeredPanels[id];
     },
 
     install: function(id) {
       _assertPanelExists(id);
 
       sendMessageToJava({
         type: "HomePanels:Install",
-        panel: _panelToJSON(_registeredPanels[id])
+        panel: _generatePanel(id)
       });
     },
 
     uninstall: function(id) {
       _assertPanelExists(id);
 
       sendMessageToJava({
         type: "HomePanels:Uninstall",
@@ -323,17 +328,17 @@ let HomePanels = (function () {
       });
     },
 
     update: function(id) {
       _assertPanelExists(id);
 
       sendMessageToJava({
         type: "HomePanels:Update",
-        panel: _panelToJSON(_registeredPanels[id])
+        panel: _generatePanel(id)
       });
     }
   });
 })();
 
 // Public API
 this.Home = Object.freeze({
   banner: HomeBanner,