summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/Home.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/modules/Home.jsm')
-rw-r--r--mobile/android/modules/Home.jsm487
1 files changed, 0 insertions, 487 deletions
diff --git a/mobile/android/modules/Home.jsm b/mobile/android/modules/Home.jsm
deleted file mode 100644
index e77d35dbd..000000000
--- a/mobile/android/modules/Home.jsm
+++ /dev/null
@@ -1,487 +0,0 @@
-// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
-/* 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";
-
-this.EXPORTED_SYMBOLS = ["Home"];
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/SharedPreferences.jsm");
-Cu.import("resource://gre/modules/Messaging.jsm");
-
-// Keep this in sync with the constant defined in PanelAuthCache.java
-const PREFS_PANEL_AUTH_PREFIX = "home_panels_auth_";
-
-// Default weight for a banner message.
-const DEFAULT_WEIGHT = 100;
-
-// See bug 915424
-function resolveGeckoURI(aURI) {
- if (!aURI)
- throw "Can't resolve an empty uri";
-
- if (aURI.startsWith("chrome://")) {
- let registry = Cc['@mozilla.org/chrome/chrome-registry;1'].getService(Ci["nsIChromeRegistry"]);
- return registry.convertChromeURL(Services.io.newURI(aURI, null, null)).spec;
- } else if (aURI.startsWith("resource://")) {
- let handler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
- return handler.resolveURI(Services.io.newURI(aURI, null, null));
- }
- return aURI;
-}
-
-function BannerMessage(options) {
- let uuidgen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
- this.id = uuidgen.generateUUID().toString();
-
- if ("text" in options && options.text != null)
- this.text = options.text;
-
- if ("icon" in options && options.icon != null)
- this.iconURI = resolveGeckoURI(options.icon);
-
- if ("onshown" in options && typeof options.onshown === "function")
- this.onshown = options.onshown;
-
- if ("onclick" in options && typeof options.onclick === "function")
- this.onclick = options.onclick;
-
- if ("ondismiss" in options && typeof options.ondismiss === "function")
- this.ondismiss = options.ondismiss;
-
- let weight = parseInt(options.weight, 10);
- this.weight = weight > 0 ? weight : DEFAULT_WEIGHT;
-}
-
-// We need this object to have access to the HomeBanner
-// private members without leaking it outside Home.jsm.
-var HomeBannerMessageHandlers;
-
-var HomeBanner = (function () {
- // Whether there is a "HomeBanner:Get" request we couldn't fulfill.
- let _pendingRequest = false;
-
- // Functions used to handle messages sent from Java.
- HomeBannerMessageHandlers = {
- "HomeBanner:Get": function handleBannerGet(data) {
- if (Object.keys(_messages).length > 0) {
- _sendBannerData();
- } else {
- _pendingRequest = true;
- }
- }
- };
-
- // Holds the messages that will rotate through the banner.
- let _messages = {};
-
- // Choose a random message from the set of messages, biasing towards those with higher weight.
- // Weight logic copied from desktop snippets:
- // https://github.com/mozilla/snippets-service/blob/7d80edb8b1cddaed075275c2fc7cdf69a10f4003/snippets/base/templates/base/includes/snippet_js.html#L119
- let _sendBannerData = function() {
- let totalWeight = 0;
- for (let key in _messages) {
- let message = _messages[key];
- totalWeight += message.weight;
- message.totalWeight = totalWeight;
- }
-
- let threshold = Math.random() * totalWeight;
- for (let key in _messages) {
- let message = _messages[key];
- if (threshold < message.totalWeight) {
- Messaging.sendRequest({
- type: "HomeBanner:Data",
- id: message.id,
- text: message.text,
- iconURI: message.iconURI
- });
- return;
- }
- }
- };
-
- let _handleShown = function(id) {
- let message = _messages[id];
- if (message.onshown)
- message.onshown();
- };
-
- let _handleClick = function(id) {
- let message = _messages[id];
- if (message.onclick)
- message.onclick();
- };
-
- let _handleDismiss = function(id) {
- let message = _messages[id];
- if (message.ondismiss)
- message.ondismiss();
- };
-
- return Object.freeze({
- observe: function(subject, topic, data) {
- switch(topic) {
- case "HomeBanner:Shown":
- _handleShown(data);
- break;
-
- case "HomeBanner:Click":
- _handleClick(data);
- break;
-
- case "HomeBanner:Dismiss":
- _handleDismiss(data);
- break;
- }
- },
-
- /**
- * 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;
-
- // 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:Shown", false);
- Services.obs.addObserver(this, "HomeBanner:Click", false);
- Services.obs.addObserver(this, "HomeBanner:Dismiss", false);
-
- // Send a message to Java if there's a pending "HomeBanner:Get" request.
- if (_pendingRequest) {
- _pendingRequest = false;
- _sendBannerData();
- }
- }
-
- return message.id;
- },
-
- /**
- * Removes a banner message from the rotation.
- *
- * @param id The id of the message to remove.
- */
- remove: function(id) {
- if (!(id in _messages)) {
- throw "Home.banner: Can't remove message that doesn't exist: id = " + id;
- }
-
- delete _messages[id];
-
- // If there are no more messages, remove the observers.
- if (Object.keys(_messages).length == 0) {
- Services.obs.removeObserver(this, "HomeBanner:Shown");
- Services.obs.removeObserver(this, "HomeBanner:Click");
- Services.obs.removeObserver(this, "HomeBanner:Dismiss");
- }
- }
- });
-})();
-
-// We need this object to have access to the HomePanels
-// private members without leaking it outside Home.jsm.
-var HomePanelsMessageHandlers;
-
-var HomePanels = (function () {
- // Functions used to handle messages sent from Java.
- HomePanelsMessageHandlers = {
-
- "HomePanels:Get": function handlePanelsGet(data) {
- data = JSON.parse(data);
-
- let requestId = data.requestId;
- let ids = data.ids || null;
-
- let panels = [];
- for (let id in _registeredPanels) {
- // Null ids means we want to fetch all available panels
- if (ids == null || ids.indexOf(id) >= 0) {
- try {
- panels.push(_generatePanel(id));
- } catch(e) {
- Cu.reportError("Home.panels: Invalid options, panel.id = " + id + ": " + e);
- }
- }
- }
-
- Messaging.sendRequest({
- type: "HomePanels:Data",
- panels: panels,
- requestId: requestId
- });
- },
-
- "HomePanels:Authenticate": function handlePanelsAuthenticate(id) {
- // Generate panel options to get auth handler.
- let options = _registeredPanels[id]();
- if (!options.auth) {
- throw "Home.panels: Invalid auth for panel.id = " + id;
- }
- if (!options.auth.authenticate || typeof options.auth.authenticate !== "function") {
- throw "Home.panels: Invalid auth authenticate function: panel.id = " + this.id;
- }
- options.auth.authenticate();
- },
-
- "HomePanels:RefreshView": function handlePanelsRefreshView(data) {
- data = JSON.parse(data);
-
- let options = _registeredPanels[data.panelId]();
- let view = options.views[data.viewIndex];
-
- if (!view) {
- throw "Home.panels: Invalid view for panel.id = " + data.panelId
- + ", view.index = " + data.viewIndex;
- }
-
- if (!view.onrefresh || typeof view.onrefresh !== "function") {
- throw "Home.panels: Invalid onrefresh for panel.id = " + data.panelId
- + ", view.index = " + data.viewIndex;
- }
-
- view.onrefresh();
- },
-
- "HomePanels:Installed": function handlePanelsInstalled(id) {
- _assertPanelExists(id);
-
- let options = _registeredPanels[id]();
- if (!options.oninstall) {
- return;
- }
- if (typeof options.oninstall !== "function") {
- throw "Home.panels: Invalid oninstall function: panel.id = " + this.id;
- }
- options.oninstall();
- },
-
- "HomePanels:Uninstalled": function handlePanelsUninstalled(id) {
- _assertPanelExists(id);
-
- let options = _registeredPanels[id]();
- if (!options.onuninstall) {
- return;
- }
- if (typeof options.onuninstall !== "function") {
- throw "Home.panels: Invalid onuninstall function: panel.id = " + this.id;
- }
- options.onuninstall();
- }
- };
-
- // Holds the current set of registered panels that can be
- // 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 = {};
-
- // 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",
- ICON: "icon"
- });
-
- // Valid item handlers for a panel view.
- let ItemHandler = Object.freeze({
- BROWSER: "browser",
- INTENT: "intent"
- });
-
- function Panel(id, options) {
- this.id = id;
- this.title = options.title;
- this.layout = options.layout;
- this.views = options.views;
- this.default = !!options.default;
-
- if (!this.id || !this.title) {
- throw "Home.panels: Can't create a home panel without an id and title!";
- }
-
- if (!this.layout) {
- // Use FRAME layout by default
- this.layout = Layout.FRAME;
- } else if (!_valueExists(Layout, this.layout)) {
- throw "Home.panels: Invalid layout for panel: panel.id = " + this.id + ", panel.layout =" + this.layout;
- }
-
- for (let view of this.views) {
- if (!_valueExists(View, view.type)) {
- throw "Home.panels: Invalid view type: panel.id = " + this.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 = " + this.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 = " + this.id + ", view.itemHandler = " + view.itemHandler;
- }
-
- if (!view.dataset) {
- throw "Home.panels: No dataset provided for view: panel.id = " + this.id + ", view.type = " + view.type;
- }
-
- if (view.onrefresh) {
- view.refreshEnabled = true;
- }
- }
-
- if (options.auth) {
- if (!options.auth.messageText) {
- throw "Home.panels: Invalid auth messageText: panel.id = " + this.id;
- }
- if (!options.auth.buttonText) {
- throw "Home.panels: Invalid auth buttonText: panel.id = " + this.id;
- }
-
- this.authConfig = {
- messageText: options.auth.messageText,
- buttonText: options.auth.buttonText
- };
-
- // Include optional image URL if it is specified.
- if (options.auth.imageUrl) {
- this.authConfig.imageUrl = options.auth.imageUrl;
- }
- }
-
- if (options.position >= 0) {
- this.position = options.position;
- }
- }
-
- let _generatePanel = function(id) {
- let options = _registeredPanels[id]();
- return new Panel(id, options);
- };
-
- // Helper function used to see if a value is in an object.
- let _valueExists = function(obj, value) {
- for (let key in obj) {
- if (obj[key] == value) {
- return true;
- }
- }
- return false;
- };
-
- let _assertPanelExists = function(id) {
- if (!(id in _registeredPanels)) {
- throw "Home.panels: Panel doesn't exist: id = " + id;
- }
- };
-
- return Object.freeze({
- Layout: Layout,
- View: View,
- Item: Item,
- ItemHandler: ItemHandler,
-
- register: function(id, optionsCallback) {
- // Bail if the panel already exists
- if (id in _registeredPanels) {
- throw "Home.panels: Panel already exists: id = " + id;
- }
-
- if (!optionsCallback || typeof optionsCallback !== "function") {
- throw "Home.panels: Panel callback must be a function: id = " + id;
- }
-
- _registeredPanels[id] = optionsCallback;
- },
-
- unregister: function(id) {
- _assertPanelExists(id);
-
- delete _registeredPanels[id];
- },
-
- install: function(id) {
- _assertPanelExists(id);
-
- Messaging.sendRequest({
- type: "HomePanels:Install",
- panel: _generatePanel(id)
- });
- },
-
- uninstall: function(id) {
- _assertPanelExists(id);
-
- Messaging.sendRequest({
- type: "HomePanels:Uninstall",
- id: id
- });
- },
-
- update: function(id) {
- _assertPanelExists(id);
-
- Messaging.sendRequest({
- type: "HomePanels:Update",
- panel: _generatePanel(id)
- });
- },
-
- setAuthenticated: function(id, isAuthenticated) {
- _assertPanelExists(id);
-
- let authKey = PREFS_PANEL_AUTH_PREFIX + id;
- let sharedPrefs = SharedPreferences.forProfile();
- sharedPrefs.setBoolPref(authKey, isAuthenticated);
- }
- });
-})();
-
-// Public API
-this.Home = Object.freeze({
- banner: HomeBanner,
- panels: HomePanels,
-
- // Lazy notification observer registered in browser.js
- observe: function(subject, topic, data) {
- if (topic in HomeBannerMessageHandlers) {
- HomeBannerMessageHandlers[topic](data);
- } else if (topic in HomePanelsMessageHandlers) {
- HomePanelsMessageHandlers[topic](data);
- } else {
- Cu.reportError("Home.observe: message handler not found for topic: " + topic);
- }
- }
-});