add account settings ui for file link providers, r=squib
authorMike Conley <mconley@mozilla.com>
Mon, 12 Mar 2012 16:13:44 -0700
changeset 11070 c995fdc3e91a5d53cd1d6f7b84c2dd9731bce25f
parent 11069 05d971f9c1d6603800393bc17087678dfedc867f
child 11071 0d9014f1f95325841c3cd01d7183b845c8043be5
push id463
push userbugzilla@standard8.plus.com
push dateTue, 24 Apr 2012 17:34:51 +0000
treeherdercomm-beta@e53588e8f7b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssquib
add account settings ui for file link providers, r=squib
mail/components/cloudfile/Makefile.in
mail/components/cloudfile/content/Dropbox/management.js
mail/components/cloudfile/content/Dropbox/management.xhtml
mail/components/cloudfile/content/Dropbox/settings.xhtml
mail/components/cloudfile/content/YouSendIt/management.xhtml
mail/components/cloudfile/content/YouSendIt/settings.js
mail/components/cloudfile/content/YouSendIt/settings.xhtml
mail/components/cloudfile/content/addAccountDialog.js
mail/components/cloudfile/content/addAccountDialog.xul
mail/components/cloudfile/jar.mn
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/Makefile.in
@@ -0,0 +1,27 @@
+# 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/.
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE    = cloudfile
+
+EXTRA_COMPONENTS = \
+  nsYouSendIt.js \
+  nsDropbox.js \
+  cloudFileComponents.manifest \
+  $(NULL)
+
+EXTRA_JS_MODULES = \
+  cloudFileAccounts.js \
+  $(NULL)
+
+XPIDLSRCS = nsIMsgCloudFileProvider.idl \
+            $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/Dropbox/management.js
@@ -0,0 +1,40 @@
+function onLoadProvider(provider) {
+  let messenger = Components.classes["@mozilla.org/messenger;1"]
+                            .createInstance(Components.interfaces.nsIMessenger);
+
+  let fileSpaceUsed = document.getElementById("file-space-used");
+  fileSpaceUsed.textContent = messenger.formatFileSize(provider.fileSpaceUsed);
+  let fileSpaceUsedSwatch = document.getElementById("file-space-used-swatch");
+  fileSpaceUsedSwatch.style.backgroundColor = pv.Colors.category20.values[0];
+
+  let remainingFileSpace = document.getElementById("remaining-file-space");
+  remainingFileSpace.textContent = messenger.formatFileSize(
+    provider.remainingFileSpace);
+  let remainingFileSpaceSwatch = document.getElementById("remaining-file-space-swatch");
+  remainingFileSpaceSwatch.style.backgroundColor = pv.Colors.category20.values[1];
+
+  let totalSpace = provider.fileSpaceUsed + provider.remainingFileSpace;
+  let pieScale = 2 * Math.PI / totalSpace;
+
+  let spaceDiv = document.getElementById("provider-space-visuals");
+  let vis = new pv.Panel().canvas(spaceDiv)
+    .width(150)
+    .height(150);
+  vis.add(pv.Wedge)
+    .data([provider.fileSpaceUsed, provider.remainingFileSpace])
+    .left(75)
+    .top(75)
+    .innerRadius(30)
+    .outerRadius(65)
+    .angle(function(d) d * pieScale);
+
+  vis.add(pv.Label)
+    .left(75)
+    .top(75)
+    .font("14px Sans-Serif")
+    .textAlign("center")
+    .textBaseline("middle")
+    .text(messenger.formatFileSize(totalSpace));
+
+  vis.render();
+}
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/Dropbox/management.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html [
+  <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> %htmlDTD;
+  <!ENTITY % managementDTD SYSTEM "chrome://messenger/locale/cloudfile/management.dtd"> %managementDTD;
+  <!ENTITY % dropboxDTD SYSTEM "chrome://messenger/locale/cloudfile/Dropbox/management.dtd"> %dropboxDTD;
+]>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <script type="application/javascript;version=1.8"
+            src="chrome://messenger/content/protovis-r2.6-modded.js"/>
+    <script type="text/javascript;version=1.8"
+            src="chrome://messenger/content/cloudfile/Dropbox/management.js"/>
+    <link rel="stylesheet"
+        type="text/css"
+        href="chrome://messenger/skin/preferences/preferences.css" />
+  </head>
+  <body id="provider-management">
+    <div id="provider-header">
+      <div id="provider-terms">
+      <a href="https://www.dropbox.com/terms#privacy">&cloudfileMgmt.privacyPolicy;</a>
+      <a href="https://www.dropbox.com/terms#terms">&cloudfileMgmt.termsOfService;</a>
+      </div>
+      <div id="provider-name">
+      <h1>Dropbox</h1>
+      </div>
+    </div>
+    <div id="provider-spacebox">
+      <div id="provider-space-visuals"></div>
+      <div id="provider-space">
+        <div>&cloudfileMgmt.usedSpace;<span id="file-space-used"/><span id="file-space-used-swatch" class="space-swatch"/></div>
+        <div>&cloudfileMgmt.unusedSpace;<span id="remaining-file-space"/><span id="remaining-file-space-swatch" class="space-swatch"/></div>
+        <div id="upgrade"><a href="https://www.dropbox.com/plans">&cloudfileMgmt.upgradeOffer;</a></div>
+      </div>
+   </div>
+   <div id="provider-account-settings"><a href="https://www.dropbox.com/account#settings">&dropboxMgmt.viewSettings;</a></div> 
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/Dropbox/settings.xhtml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <link rel="stylesheet"
+        type="text/css"
+        href="chrome://messenger/skin/preferences/preferences.css" />
+  </head>
+  <body id="provider-settings">
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/YouSendIt/management.xhtml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html [
+  <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> %htmlDTD;
+  <!ENTITY % managementDTD SYSTEM "chrome://messenger/locale/cloudfile/management.dtd"> %managementDTD;
+  <!ENTITY % ysiDTD SYSTEM "chrome://messenger/locale/cloudfile/YouSendIt/management.dtd"> %ysiDTD;
+]>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <script type="application/javascript;version=1.8"
+            src="chrome://messenger/content/protovis-r2.6-modded.js"/>
+    <link rel="stylesheet"
+        type="text/css"
+        href="chrome://messenger/skin/preferences/preferences.css" />
+  </head>
+  <body id="provider-management">
+    <div id="provider-header">
+      <div id="provider-terms">
+      <a href="http://www.yousendit.com/aboutus/legal/privacy">&cloudfileMgmt.privacyPolicy;</a>
+      <a href="http://www.yousendit.com/aboutus/legal/terms-of-service">&cloudfileMgmt.termsOfService;</a>
+      </div>
+      <div id="provider-name">
+      <h1>YouSendIt</h1>
+      </div>
+    </div>
+
+    <div id="provider-spacebox">
+      <div id="provider-space-visuals"></div>
+      <div id="provider-space">
+        <div>&cloudfileMgmt.usedSpace;<span id="file-space-used"/><span id="file-space-used-swatch" class="space-swatch"/></div>
+        <div>&cloudfileMgmt.unusedSpace;<span id="remaining-file-space"/><span id="remaining-file-space-swatch" class="space-swatch"/></div>
+        <div id="upgrade"><a href="https://www.yousendit.com/compareaccounts">&cloudfileMgmt.upgradeOffer;</a></div>
+      </div>
+      </div>
+    <div id="provider-account-settings"><a href="https://www.yousendit.com/myaccount">&youSendItMgmt.viewSettings;</a></div>
+  </body>
+
+
+  <script type="text/javascript;version=1.8">
+
+    function onLoadProvider(provider) {
+    }
+
+  </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/YouSendIt/settings.js
@@ -0,0 +1,10 @@
+/* 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/. */
+
+function extraArgs() {
+  var usernameValue = document.getElementById("username").value;
+  return {
+    "username": {type: "char", value: usernameValue},
+  };
+}
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/YouSendIt/settings.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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/.  -->
+
+<!DOCTYPE html [
+  <!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> %htmlDTD;
+  <!ENTITY % ysiDTD SYSTEM "chrome://messenger/locale/cloudfile/YouSendIt/settings.dtd"> %ysiDTD;
+]>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+  <head>
+    <script type="application/javascript"
+            src="chrome://messenger/content/cloudfile/YouSendIt/settings.js"/>
+    <link rel="stylesheet"
+        type="text/css"
+        href="chrome://messenger/skin/preferences/preferences.css" />
+  </head>
+  <body id="provider-settings">
+    <form id="providerForm" onsubmit="return false;">
+      <label for="username">&youSendItSettings.username;</label><input id="username" type="text" required="true"/>
+      <div class="indented">
+        <a href="http://www.yousendit.com/compare-plans">&youSendItSettings.needAnAccount;</a>
+      </div>
+    </form>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/addAccountDialog.js
@@ -0,0 +1,187 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const Cr = Components.results;
+
+const kFormId = "providerForm";
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource:///modules/cloudFileAccounts.js");
+
+function createAccountObserver() {};
+
+createAccountObserver.prototype = {
+  onStartRequest: function(aRequest, aContext) {},
+  onStopRequest: function(aRequest, aContext, aStatusCode) {
+    if (aStatusCode == Cr.NS_OK
+        && aContext instanceof Ci.nsIMsgCloudFileProvider) {
+      let accountKey = aContext.accountKey;
+
+      // For now, we'll just set the display name to be the name of the service
+      cloudFileAccounts.setDisplayName(accountKey, aContext.displayName);
+
+      window.arguments[0].accountKey = aContext.accountKey;
+      window.close();
+    }
+    else {
+      if (aContext instanceof Ci.nsIMsgCloudFileProvider) {
+        cloudFileAccounts.removeAccount(aContext.accountKey);
+      }
+      else {
+        // Something went seriously wrong here...
+        Components.utils.reportError("Cloud account creation failed, and " +
+                                     "provider instance missing!");
+      }
+
+      addAccountDialog._accept.disabled = false;
+      addAccountDialog._messages.selectedPanel = addAccountDialog._error;
+    }
+  },
+}
+
+let addAccountDialog = {
+  _settings: null,
+  _settingsWrap: null,
+  _accountType: null,
+  _accountName: null,
+  _accept: null,
+  _strings: Services.strings
+                    .createBundle("chrome://messenger/locale/cloudfile/addAccountDialog.properties"),
+
+  onInit: function AAD_onInit() {
+    this._settings = document.getElementById("accountSettings");
+    this._accountType = document.getElementById("accountType");
+    this._noAccountText = document.getElementById("noAccountText");
+    this._accept = document.documentElement.getButton("accept");
+    this._messages = document.getElementById("messages");
+    this._authSpinner = document.getElementById("authorizing");
+    this._error = document.getElementById("error");
+    this._createAccountText = document.getElementById("createAccountText");
+
+    this.removeTitleMenuItem();
+    this.addAccountTypes();
+
+    // Hook up our onInput event handler
+    this._settings.addEventListener("DOMContentLoaded", function(e) {
+      let doc = this.contentDocument;
+
+      let links = doc.getElementsByTagName("a");
+
+      for (let [, link] in Iterator(links))
+        link.addEventListener("click", addAccountDialog.onClickLink);
+
+      let form = doc.getElementById(kFormId);
+
+      if (form)
+        form.addEventListener("input", addAccountDialog.onInput);
+
+      addAccountDialog.onInput();
+    }, false);
+  },
+
+  removeTitleMenuItem: function AAD_removeTitleMenuItem() {
+    let menuitem = this._accountType.querySelector('menuitem[value=""]');
+    if (menuitem) {
+      let index = this._accountType.getIndexOfItem(menuitem);
+      this._accountType.removeItemAt(index);
+    }
+  },
+
+  addAccountTypes: function AAD_addAccountTypes() {
+    for (let [key, provider] in cloudFileAccounts.enumerateProviders()) {
+      // If we already have an account for this type, don't add it to the list.
+      // This limitation will hopefully be removed in the future.
+      if (cloudFileAccounts.getAccountsForType(key).length > 0)
+        continue;
+
+      let menuitem = document.createElement("menuitem");
+      menuitem.setAttribute("label", provider.displayName);
+      menuitem.setAttribute("value", key);
+
+      if (provider.iconClass) {
+        menuitem.setAttribute("class", "menuitem-iconic");
+        menuitem.setAttribute("image", provider.iconClass);
+      }
+
+      this._accountType.menupopup.appendChild(menuitem);
+    }
+
+    if (this._accountType.itemCount == 0) {
+      this._createAccountText.hidden = true;
+      this._accountType.hidden = true;
+      this._noAccountText.hidden = false;
+    }
+  },
+
+  onOK: function AAD_onOK() {
+    let accountType = this._accountType.value;
+    let obs = new createAccountObserver();
+
+    let extras = this.getExtraArgs();
+
+    let provider = cloudFileAccounts.createAccount(accountType, obs, extras);
+    this._accept.disabled = true;
+    this._messages.selectedPanel = this._authSpinner;
+
+    return false;
+  },
+
+  getExtraArgs: function AAD_getExtraArgs() {
+    if (!this._settings)
+      return {};
+
+    let func = this._settings.contentWindow
+                   .wrappedJSObject
+                   .extraArgs;
+    if (!func)
+      return {};
+
+    return func();
+  },
+
+  accountTypeSelected: function AAD_accountTypeSelected() {
+    let providerKey = this._accountType.selectedItem.value;
+    if (!providerKey)
+      return;
+
+    let provider = cloudFileAccounts.getProviderForType(providerKey);
+    if (!provider)
+      return;
+
+    // Load up the correct XHTML page for this provider.
+    this._settings.contentDocument.location.href = provider.settingsURL;
+    this._settings.hidden = false;
+  },
+
+  onClickLink: function AAD_onClickLink(e) {
+    e.preventDefault();
+    let href = e.target.getAttribute("href");
+    gProtocolService.loadUrl(Services.io.newURI(href, "UTF-8", null));
+  },
+
+  onInput: function AAD_onInput() {
+    // Let's see if we have everything we need to make OK enabled...
+    addAccountDialog._accept.disabled = !addAccountDialog.checkValidity();
+  },
+
+  checkValidity: function AAD_checkValidity() {
+    // If there's a form in the iframe, ensure that
+    // it's checkValidity function passes.
+    let form = this._settings
+                   .contentWindow
+                   .wrappedJSObject
+                   .document
+                   .getElementById(kFormId);
+
+    if (form)
+      return form.checkValidity();
+
+    return true;
+  },
+
+}
+
+XPCOMUtils.defineLazyServiceGetter(this, "gProtocolService",
+                                   "@mozilla.org/uriloader/external-protocol-service;1",
+                                   "nsIExternalProtocolService");
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/content/addAccountDialog.xul
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!DOCTYPE overlay [
+<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
+%brandDTD;
+<!ENTITY % addAccountDialogDTD SYSTEM "chrome://messenger/locale/cloudfile/addAccountDialog.dtd" >
+%addAccountDialogDTD;
+]>
+
+<!-- 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/.  -->
+<?xml-stylesheet href="chrome://global/skin/"?>
+<?xml-stylesheet href="chrome://messenger/skin/preferences/preferences.css" type="text/css"?>
+
+<dialog id="addCloudFileAccount"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        buttons="accept,cancel"
+        buttonlabelaccept="&addAccountDialog.acceptButton.label;"
+        buttondisabledaccept="true"
+        onload="return addAccountDialog.onInit();"
+        ondialogaccept="return addAccountDialog.onOK();"
+        title="&addAccountDialog.title;"
+        style="&addAccountDialog.style;"
+        persist="screenX screenY">
+
+  <script type="text/javascript;version=1.8"
+          src="chrome://messenger/content/cloudfile/addAccountDialog.js"/>
+
+#ifdef XP_MACOSX
+  <description id="createAccountTitle">&addAccountDialog.title;</description>
+#endif
+  <description id="createAccountText">&addAccountDialog.createAccountText;</description>
+  <description id="noAccountText" hidden="true">&addAccountDialog.noAccountText;</description>
+
+  <menulist id="accountType" onselect="return addAccountDialog.accountTypeSelected();">
+    <menupopup>
+      <menuitem label="&addAccountDialog.menuTitle;" value=""/>
+    </menupopup>
+  </menulist>
+
+  <iframe id="accountSettings" flex="1" hidden="true"/>
+  <deck id="messages" selectedIndex="-1">
+    <hbox id="authorizing">
+      <image src="chrome://global/skin/icons/loading_16.png"/>
+      <label>&addAccountDialog.authorizing;</label>
+    </hbox>
+    <hbox id="error">
+      <image src="chrome://global/skin/icons/warning-16.png"/>
+      <label>&addAccountDialog.error;</label>
+    </hbox>
+  </deck>
+</dialog>
new file mode 100644
--- /dev/null
+++ b/mail/components/cloudfile/jar.mn
@@ -0,0 +1,10 @@
+messenger.jar:
+*   content/messenger/cloudfile/addAccountDialog.xul (content/addAccountDialog.xul)
+    content/messenger/cloudfile/addAccountDialog.js  (content/addAccountDialog.js)
+    content/messenger/cloudfile/attachment-24.png (content/attachment-24.png)
+    content/messenger/cloudfile/Dropbox/management.xhtml (content/Dropbox/management.xhtml)
+    content/messenger/cloudfile/Dropbox/management.js    (content/Dropbox/management.js)
+    content/messenger/cloudfile/Dropbox/settings.xhtml (content/Dropbox/settings.xhtml)
+    content/messenger/cloudfile/YouSendIt/management.xhtml (content/YouSendIt/management.xhtml)
+    content/messenger/cloudfile/YouSendIt/settings.js (content/YouSendIt/settings.js)
+    content/messenger/cloudfile/YouSendIt/settings.xhtml (content/YouSendIt/settings.xhtml)