Bug 968378 - Hide private members in Home.jsm using closures. r=mcomella

This commit is contained in:
Peiyong Lin 2014-02-14 11:52:14 -05:00
parent 38006cdf43
commit 75d3d55226

View File

@ -45,32 +45,21 @@ function BannerMessage(options) {
this.onclick = options.onclick;
}
let HomeBanner = Object.freeze({
let HomeBanner = (function () {
// Holds the messages that will rotate through the banner.
_messages: {},
let _messages = {};
// A queue used to keep track of which message to show next.
_queue: [],
let _queue = [];
observe: function(subject, topic, data) {
switch(topic) {
case "HomeBanner:Get":
this._handleGet();
break;
case "HomeBanner:Click":
this._handleClick(data);
break;
}
},
_handleGet: function() {
let _handleGet = function() {
// Get the message from the front of the queue, then add it back
// to the end of the queue to show it again later.
let id = this._queue.shift();
this._queue.push(id);
let id = _queue.shift();
_queue.push(id);
let message = this._messages[id];
let message = _messages[id];
sendMessageToJava({
type: "HomeBanner:Data",
id: message.id,
@ -80,59 +69,73 @@ let HomeBanner = Object.freeze({
if (message.onshown)
message.onshown();
},
};
_handleClick: function(id) {
let message = this._messages[id];
let _handleClick = function(id) {
let message = _messages[id];
if (message.onclick)
message.onclick();
},
};
/**
* Adds a new banner message to the rotation.
*
* @return id Unique identifer for the message.
*/
add: function(options) {
let message = new BannerMessage(options);
this._messages[message.id] = message;
return Object.freeze({
observe: function(subject, topic, data) {
switch(topic) {
case "HomeBanner:Get":
_handleGet();
break;
// Add the new message to the end of the queue.
this._queue.push(message.id);
case "HomeBanner:Click":
_handleClick(data);
break;
}
},
// If this is the first message we're adding, add
// observers to listen for requests from the Java UI.
if (Object.keys(this._messages).length == 1) {
Services.obs.addObserver(this, "HomeBanner:Get", false);
Services.obs.addObserver(this, "HomeBanner:Click", false);
/**
* Adds a new banner message to the rotation.
*
* @return id Unique identifer for the message.
*/
add: function(options) {
let message = new BannerMessage(options);
_messages[message.id] = message;
// Send a message to Java, in case there's an active HomeBanner
// waiting for a response.
this._handleGet();
// Add the new message to the end of the queue.
_queue.push(message.id);
// If this is the first message we're adding, add
// observers to listen for requests from the Java UI.
if (Object.keys(_messages).length == 1) {
Services.obs.addObserver(this, "HomeBanner:Get", false);
Services.obs.addObserver(this, "HomeBanner:Click", false);
// Send a message to Java, in case there's an active HomeBanner
// waiting for a response.
_handleGet();
}
return message.id;
},
/**
* Removes a banner message from the rotation.
*
* @param id The id of the message to remove.
*/
remove: function(id) {
delete _messages[id];
// Remove the message from the queue.
let index = _queue.indexOf(id);
_queue.splice(index, 1);
// If there are no more messages, remove the observers.
if (Object.keys(_messages).length == 0) {
Services.obs.removeObserver(this, "HomeBanner:Get");
Services.obs.removeObserver(this, "HomeBanner:Click");
}
}
return message.id;
},
/**
* Removes a banner message from the rotation.
*
* @param id The id of the message to remove.
*/
remove: function(id) {
delete this._messages[id];
// Remove the message from the queue.
let index = this._queue.indexOf(id);
this._queue.splice(index, 1);
// If there are no more messages, remove the observers.
if (Object.keys(this._messages).length == 0) {
Services.obs.removeObserver(this, "HomeBanner:Get");
Services.obs.removeObserver(this, "HomeBanner:Click");
}
}
});
});
})();
function Panel(options) {
if ("id" in options)
@ -148,53 +151,30 @@ function Panel(options) {
this.views = options.views;
}
let HomePanels = 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 actions for a panel.
Action: Object.freeze({
INSTALL: "install",
REFRESH: "refresh"
}),
// Valid item handlers for a panel view.
ItemHandler: Object.freeze({
BROWSER: "browser",
INTENT: "intent"
}),
let HomePanels = (function () {
// Holds the currrent set of registered panels.
_panels: {},
let _panels = {};
_panelToJSON : function(panel) {
let _panelToJSON = function(panel) {
return {
id: panel.id,
title: panel.title,
layout: panel.layout,
views: panel.views
};
},
};
_handleGet: function(data) {
let _handleGet = function(data) {
let requestId = data.requestId;
let ids = data.ids || null;
let panels = [];
for (let id in this._panels) {
let panel = this._panels[id];
for (let id in _panels) {
let panel = _panels[id];
// Null ids means we want to fetch all available panels
if (ids == null || ids.indexOf(panel.id) >= 0) {
panels.push(this._panelToJSON(panel));
panels.push(_panelToJSON(panel));
}
}
@ -203,92 +183,117 @@ let HomePanels = Object.freeze({
panels: panels,
requestId: requestId
});
},
add: function(options) {
let panel = new Panel(options);
if (!panel.id || !panel.title) {
throw "Home.panels: Can't create a home panel without an id and title!";
}
let action = options.action;
// Bail if the panel already exists, except when we're refreshing
// an existing panel instance.
if (panel.id in this._panels && action != this.Action.REFRESH) {
throw "Home.panels: Panel already exists: id = " + panel.id;
}
if (!this._valueExists(this.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 (!this._valueExists(this.View, view.type)) {
throw "Home.panels: Invalid view type: panel.id = " + panel.id + ", view.type = " + view.type;
}
if (!view.itemHandler) {
// Use BROWSER item handler by default
view.itemHandler = this.ItemHandler.BROWSER;
} else if (!this._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;
}
}
this._panels[panel.id] = panel;
if (action) {
let messageType;
switch(action) {
case this.Action.INSTALL:
messageType = "HomePanels:Install";
break;
case this.Action.REFRESH:
messageType = "HomePanels:Refresh";
break;
default:
throw "Home.panels: Invalid action for panel: panel.id = " + panel.id + ", action = " + action;
}
sendMessageToJava({
type: messageType,
panel: this._panelToJSON(panel)
});
}
},
remove: function(id) {
if (!(id in this._panels)) {
throw "Home.panels: Panel doesn't exist: id = " + id;
}
let panel = this._panels[id];
delete this._panels[id];
sendMessageToJava({
type: "HomePanels:Remove",
panel: this._panelToJSON(panel)
});
},
};
// Helper function used to see if a value is in an object.
_valueExists: function(obj, value) {
let _valueExists = function(obj, value) {
for (let key in obj) {
if (obj[key] == value) {
return true;
}
}
return false;
}
});
};
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 actions for a panel.
Action: Object.freeze({
INSTALL: "install",
REFRESH: "refresh"
}),
// Valid item handlers for a panel view.
ItemHandler: Object.freeze({
BROWSER: "browser",
INTENT: "intent"
}),
add: function(options) {
let panel = new Panel(options);
if (!panel.id || !panel.title) {
throw "Home.panels: Can't create a home panel without an id and title!";
}
let action = options.action;
// Bail if the panel already exists, except when we're refreshing
// an existing panel instance.
if (panel.id in _panels && action != this.Action.REFRESH) {
throw "Home.panels: Panel already exists: id = " + panel.id;
}
if (!_valueExists(this.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(this.View, view.type)) {
throw "Home.panels: Invalid view type: panel.id = " + panel.id + ", view.type = " + view.type;
}
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;
}
}
_panels[panel.id] = panel;
if (action) {
let messageType;
switch(action) {
case this.Action.INSTALL:
messageType = "HomePanels:Install";
break;
case this.Action.REFRESH:
messageType = "HomePanels:Refresh";
break;
default:
throw "Home.panels: Invalid action for panel: panel.id = " + panel.id + ", action = " + action;
}
sendMessageToJava({
type: messageType,
panel: _panelToJSON(panel)
});
}
},
remove: function(id) {
if (!(id in _panels)) {
throw "Home.panels: Panel doesn't exist: id = " + id;
}
let panel = _panels[id];
delete _panels[id];
sendMessageToJava({
type: "HomePanels:Remove",
panel: _panelToJSON(panel)
});
}
});
})();
// Public API
this.Home = Object.freeze({