Bug 508039 - Port |Bug 456439 - add about:rights and a "Know Your Rights" infobar to Firefox| to SeaMonkey, r=Neil, a=KaiRo
authorFrank Wein <mcsmurf@mcsmurf.de>
Tue, 22 Sep 2009 09:07:51 +0200
changeset 4069 e6822b5c172aeeda9fa1a792e1792d8c7267ab53
parent 4068 6d8ae522bfc9d54b637d04d3df0e17f60db0b772
child 4070 176861cdb27129baa893a3fe2a3fb9dbd5a41524
push idunknown
push userunknown
push dateunknown
reviewersNeil, KaiRo
bugs508039, 456439
Bug 508039 - Port |Bug 456439 - add about:rights and a "Know Your Rights" infobar to Firefox| to SeaMonkey, r=Neil, a=KaiRo
suite/branding/content/aboutRights.xhtml
suite/branding/jar.mn
suite/browser/Makefile.in
suite/browser/browser-prefs.js
suite/browser/nsAboutRights.js
suite/common/src/nsSessionStore.js
suite/common/src/nsSuiteGlue.js
suite/installer/unix/packages
suite/installer/windows/packages
suite/locales/jar.mn
new file mode 100644
--- /dev/null
+++ b/suite/branding/content/aboutRights.xhtml
@@ -0,0 +1,100 @@
+<?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 % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+  %brandDTD;
+  <!ENTITY % securityPrefsDTD SYSTEM "chrome://navigator/locale/pref/pref-security.dtd">
+  %securityPrefsDTD;
+  <!ENTITY % aboutRightsDTD SYSTEM "chrome://branding/locale/aboutRights.dtd">
+  %aboutRightsDTD;
+]>
+<!-- ***** BEGIN LICENSE BLOCK *****
+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+   -
+   - The contents of this file are subject to the Mozilla Public License Version
+   - 1.1 (the "License"); you may not use this file except in compliance with
+   - the License. You may obtain a copy of the License at
+   - http://www.mozilla.org/MPL/
+   -
+   - Software distributed under the License is distributed on an "AS IS" basis,
+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+   - for the specific language governing rights and limitations under the
+   - License.
+   -
+   - The Original Code is mozilla.org code.
+   -
+   - The Initial Developer of the Original Code is
+   - Gervase Markham.
+   - Portions created by the Initial Developer are Copyright (C) 2008
+   - the Initial Developer. All Rights Reserved.
+   -
+   - Contributor(s):
+   -   Justin Dolske <dolske@mozilla.com>
+   -
+   - Alternatively, the contents of this file may be used under the terms of
+   - either the GNU General Public License Version 2 or later (the "GPL"), or
+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+   - in which case the provisions of the GPL or the LGPL are applicable instead
+   - of those above. If you wish to allow use of your version of this file only
+   - under the terms of either the GPL or the LGPL, and not to allow others to
+   - use your version of this file under the terms of the MPL, indicate your
+   - decision by deleting the provisions above and replace them with the notice
+   - and other provisions required by the LGPL or the GPL. If you do not delete
+   - the provisions above, a recipient may use your version of this file under
+   - the terms of any one of the MPL, the GPL or the LGPL.
+   -
+   - ***** END LICENSE BLOCK ***** -->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+  <title>&rights.pagetitle;</title>
+  <link rel="stylesheet" href="chrome://global/skin/about.css" type="text/css"/>
+</head>
+
+<body id="your-rights" dir="&rights.locale-direction;" class="aboutPageWideContainer">
+
+<h1>&rights.intro-header;</h1>
+
+<p>&rights.intro;</p>
+
+<ul>
+  <li>&rights.intro-point1a;<a href="http://www.mozilla.org/MPL/">&rights.intro-point1b;</a>&rights.intro-point1c;</li>
+<!-- Point 2 discusses Mozilla trademarks, and isn't needed when the build is unbranded.
+   - Point 3 discusses privacy policy, unbranded builds get a placeholder (for the vendor to replace)
+   - Point 4 discusses web service terms, unbranded builds gets a placeholder (for the vendor to replace) -->
+  <li>&rights.intro-point2a;<a href="http://www.mozilla.org/foundation/trademarks/policy.html">&rights.intro-point2b;</a>&rights.intro-point2c;</li>
+  <li>&rights.intro-point3a;<a href="http://www.seamonkey-project.org/legal/privacy">&rights.intro-point3b;</a>&rights.intro-point3c;</li>
+  <li>&rights.intro-point4a;<a href="about:rights#webservices" onclick="showServices();">&rights.intro-point4b;</a>&rights.intro-point4c;</li>
+</ul>
+
+<div id="webservices-container">
+  <a name="webservices"/>
+  <h3>&rights.webservices-header;</h3>
+
+  <p>&rights.webservices-a;<code>&rights.webservices-b;</code>&rights.webservices-c;<code>&rights.webservices-d;</code>&rights.webservices-e;</p>
+
+  <ol>
+    <li>&rights.webservices-term1;</li>
+    <li>&rights.webservices-term2;</li>
+    <li><strong>&rights.webservices-term3;</strong></li>
+    <li><strong>&rights.webservices-term4;</strong></li>
+    <li>&rights.webservices-term5;</li>
+    <li>&rights.webservices-term6;</li>
+  </ol>
+</div>
+
+<script type="application/x-javascript"><![CDATA[
+  var servicesDiv = document.getElementById("webservices-container");
+  servicesDiv.style.display = "none";
+
+  function showServices() {
+    servicesDiv.style.display = "";
+  }
+]]></script>
+
+</body>
+</html>
+
+
--- a/suite/branding/jar.mn
+++ b/suite/branding/jar.mn
@@ -1,4 +1,5 @@
 comm.jar:
 % content branding %content/branding/
   content/branding/about.png                              (content/about.png)
   content/branding/icon64.png                             (content/icon64.png)
+  content/branding/aboutRights.xhtml                      (content/aboutRights.xhtml)
--- a/suite/browser/Makefile.in
+++ b/suite/browser/Makefile.in
@@ -45,22 +45,27 @@ include $(DEPTH)/config/autoconf.mk
 PARALLEL_DIRS = public src
 
 ifdef ENABLE_TESTS
 PARALLEL_DIRS += test
 endif
 
 EXTRA_COMPONENTS = \
 	nsAboutAbout.js \
+	nsAboutRights.js \
 	nsBrowserContentHandler.js \
 	nsTypeAheadFind.js \
 	$(NULL)
 
 PREF_JS_EXPORTS = $(srcdir)/browser-prefs.js \
 		  $(srcdir)/channel-prefs.js \
 		  $(NULL)
 
 DEFINES += -DMOZ_APP_NAME="$(MOZ_APP_NAME)" \
            -DMOZ_APP_DISPLAYNAME="$(MOZ_APP_DISPLAYNAME)" \
            -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)" \
            $(NULL)
 
+ifneq (,$(BUILD_OFFICIAL)$(MOZILLA_OFFICIAL))
+DEFINES += -DOFFICIAL_BUILD=1
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/suite/browser/browser-prefs.js
+++ b/suite/browser/browser-prefs.js
@@ -600,8 +600,19 @@ pref("layout.word_select.stop_at_punctua
 // The breakpad report server to link to in about:crashes
 pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
 
 // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
 pref("security.alternate_certificate_error_page", "certerror");
 
 // FAQ URLs
 pref("browser.geolocation.warning.infoURL", "http://www.seamonkey-project.org/doc/2.0/geolocation");
+
+pref("browser.rights.version", 1);
+pref("browser.rights.1.shown", false);
+
+#ifdef DEBUG
+// Don't show the about:rights notification in debug builds.
+pref("browser.rights.override", true);
+#elifndef OFFICIAL_BUILD
+// Don't show the about:rights notification in non-official builds.
+pref("browser.rights.override", true);
+#endif
new file mode 100644
--- /dev/null
+++ b/suite/browser/nsAboutRights.js
@@ -0,0 +1,71 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is about:robots.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ryan Flint <rflint@mozilla.com>
+ *   Justin Dolske <dolske@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function AboutRights() {}
+AboutRights.prototype = {
+  classDescription: "about:rights",
+  contractID: "@mozilla.org/network/protocol/about;1?what=rights",
+  classID: Components.ID("{89e9da80-4c03-46a0-a357-cf77bbef98b9}"),
+  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIAboutModule]),
+  getURIFlags: function(aURI) {
+    return (Components.interfaces.nsIAboutModule.ALLOW_SCRIPT |
+            Components.interfaces.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT);
+  },
+
+  newChannel: function(aURI) {
+    var ios = Components.classes["@mozilla.org/network/io-service;1"]
+                        .getService(Components.interfaces.nsIIOService);
+
+    var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+                           .getService(Components.interfaces.nsIScriptSecurityManager);
+
+    var channel = ios.newChannel("chrome://branding/content/aboutRights.xhtml",
+                                 null, null);
+    var principal = secMan.getCodebasePrincipal(aURI);
+
+    channel.originalURI = aURI;
+    channel.owner = principal;
+
+    return channel;
+  }
+};
+
+function NSGetModule(compMgr, fileSpec)
+  XPCOMUtils.generateModule([AboutRights]);
+
--- a/suite/common/src/nsSessionStore.js
+++ b/suite/common/src/nsSessionStore.js
@@ -465,17 +465,17 @@ SessionStoreService.prototype = {
         // _loadState changed from "stopped" to "running"
         // force a save operation so that crashes happening during startup are correctly counted
         this.saveState(true);
       }
       else {
         // Nothing to restore, notify observers things are complete.
         var observerService = Components.classes["@mozilla.org/observer-service;1"]
                                         .getService(Components.interfaces.nsIObserverService);
-        observerService.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
+        observerService.notifyObservers(aWindow, NOTIFY_WINDOWS_RESTORED, "");
 
         // the next delayed save request should execute immediately
         this._lastSaveTime -= this._interval;
       }
     }
     // this window was opened by _openWindowWithState
     else if (!this._isWindowLoaded(aWindow)) {
       let followUp = this._statesToRestore[aWindow.__SS_restoreID].windows.length == 1;
@@ -2551,17 +2551,18 @@ SessionStoreService.prototype = {
 
   _notifyIfAllWindowsRestored: function sss_notifyIfAllWindowsRestored() {
     if (this._restoreCount) {
       this._restoreCount--;
       if (this._restoreCount == 0) {
         // This was the last window restored at startup, notify observers.
         var observerService = Components.classes["@mozilla.org/observer-service;1"]
                                         .getService(Components.interfaces.nsIObserverService);
-        observerService.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
+        observerService.notifyObservers(this.windowToFocus,
+                                        NOTIFY_WINDOWS_RESTORED, "");
       }
     }
   },
 
   /**
    * @param aWindow
    *        Window reference
    * @returns whether this window's data is still cached in _statesToRestore
--- a/suite/common/src/nsSuiteGlue.js
+++ b/suite/common/src/nsSuiteGlue.js
@@ -68,16 +68,19 @@ SuiteGlue.prototype = {
       case "xpcom-shutdown":
         this._dispose();
         break;
       case "final-ui-startup":
         this._onProfileStartup();
         this._promptForMasterPassword();
         this._checkForNewAddons();
         break;
+      case "sessionstore-windows-restored":
+        this._onBrowserStartup(subject);
+        break;
       case "browser:purge-session-history":
         // reset the console service's error buffer
         const cs = Components.classes["@mozilla.org/consoleservice;1"]
                              .getService(Components.interfaces.nsIConsoleService);
         cs.logStringMessage(null); // clear the console (in case it's open)
         cs.reset();
         break;
       case "quit-application-requested":
@@ -112,16 +115,17 @@ SuiteGlue.prototype = {
   // initialization (called on application startup)
   _init: function()
   {
     // observer registration
     const osvr = Components.classes["@mozilla.org/observer-service;1"]
                            .getService(Components.interfaces.nsIObserverService);
     osvr.addObserver(this, "xpcom-shutdown", false);
     osvr.addObserver(this, "final-ui-startup", false);
+    osvr.addObserver(this, "sessionstore-windows-restored", false);
     osvr.addObserver(this, "browser:purge-session-history", false);
     osvr.addObserver(this, "quit-application-requested", false);
     osvr.addObserver(this, "quit-application-granted", false);
     osvr.addObserver(this, "browser-lastwindow-close-requested", false);
     osvr.addObserver(this, "browser-lastwindow-close-granted", false);
     osvr.addObserver(this, "session-save", false);
     osvr.addObserver(this, "dl-done", false);
     try {
@@ -135,16 +139,17 @@ SuiteGlue.prototype = {
   // cleanup (called on application shutdown)
   _dispose: function()
   {
     // observer removal
     const osvr = Components.classes["@mozilla.org/observer-service;1"]
                            .getService(Components.interfaces.nsIObserverService);
     osvr.removeObserver(this, "xpcom-shutdown");
     osvr.removeObserver(this, "final-ui-startup");
+    osvr.removeObserver(this, "sessionstore-windows-restored");
     osvr.removeObserver(this, "browser:purge-session-history");
     osvr.removeObserver(this, "quit-application-requested");
     osvr.removeObserver(this, "quit-application-granted");
     osvr.removeObserver(this, "browser-lastwindow-close-requested");
     osvr.removeObserver(this, "browser-lastwindow-close-granted");
     osvr.removeObserver(this, "session-save");
     osvr.removeObserver(this, "dl-done");
   },
@@ -163,16 +168,24 @@ SuiteGlue.prototype = {
       // We need to persist this preference change, since we want to
       // check it at next app start even if the browser exits abruptly
       prefSvc.savePrefFile(null);
     }
 
     // once we support a safe mode popup, it should be called here
   },
 
+  // Browser startup complete. All initial windows have opened.
+  _onBrowserStartup: function(aWindow)
+  {
+    // Show about:rights notification, if needed.
+    if (this._shouldShowRights())
+      this._showRightsNotification(aWindow);
+  },
+
   // profile shutdown handler (contains profile cleanup routines)
   _onProfileShutdown: function()
   {
     Sanitizer.checkAndSanitize();
   },
 
   _promptForMasterPassword: function()
   {
@@ -358,16 +371,87 @@ SuiteGlue.prototype = {
                               .getService(Components.interfaces.nsIIOService);
         this._sound.play(ioSvc.newURI(url.data, null, null));
       } catch (e) {
         this._sound.beep();
       }
     }
   },
 
+  /*
+   * _shouldShowRights - Determines if the user should be shown the
+   * about:rights notification. The notification should *not* be shown if
+   * we've already shown the current version, or if the override pref says to
+   * never show it. The notification *should* be shown if it's never been seen
+   * before, if a newer version is available, or if the override pref says to
+   * always show it.
+   */
+  _shouldShowRights: function () {
+    // Look for an unconditional override pref. If set, do what it says.
+    // (true --> never show, false --> always show)
+    var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
+                               .getService(Components.interfaces.nsIPrefBranch);
+    try {
+      return !prefBranch.getBoolPref("browser.rights.override");
+    } catch (e) { }
+    // Ditto, for the legacy EULA pref (tinderbox testing profile sets this).
+    try {
+      return !prefBranch.getBoolPref("browser.EULA.override");
+    } catch (e) { }
+
+    // Look to see if the user has seen the current version or not.
+    var currentVersion = prefBranch.getIntPref("browser.rights.version");
+    try {
+      return !prefBranch.getBoolPref("browser.rights." + currentVersion + ".shown");
+    } catch (e) { }
+
+    // We haven't shown the notification before, so do so now.
+    return true;
+  },
+
+  _showRightsNotification: function(aSubject) {
+    // Stick the notification onto the selected tab of the active browser window.
+    var browser = aSubject.getBrowser(); // for closure in notification bar callback
+    var notifyBox = browser.getNotificationBox();
+
+    const nsIStringBundleService = Components.interfaces.nsIStringBundleService;
+    var bundleService = Components.classes["@mozilla.org/intl/stringbundle;1"]
+                                  .getService(nsIStringBundleService);
+    var brandBundle  = bundleService.createBundle("chrome://branding/locale/brand.properties");
+    var rightsBundle = bundleService.createBundle("chrome://branding/locale/aboutRights.properties");
+
+    var buttonLabel      = rightsBundle.GetStringFromName("buttonLabel");
+    var buttonAccessKey  = rightsBundle.GetStringFromName("buttonAccessKey");
+    var productName      = brandBundle.GetStringFromName("brandFullName");
+    var notifyRightsText = rightsBundle.formatStringFromName("notifyRightsText",
+                                                             [productName], 1);
+
+    var buttons = [
+                    {
+                      label:     buttonLabel,
+                      accessKey: buttonAccessKey,
+                      popup:     null,
+                      callback: function(aNotificationBar, aButton) {
+                        browser.selectedTab = browser.addTab("about:rights");
+                      }
+                    }
+                  ];
+
+    // Set pref to indicate we've shown the notficiation.
+    var prefBranch = Components.classes["@mozilla.org/preferences-service;1"]
+                               .getService(Components.interfaces.nsIPrefBranch);
+    var currentVersion = prefBranch.getIntPref("browser.rights.version");
+    prefBranch.setBoolPref("browser.rights." + currentVersion + ".shown", true);
+
+    var box = notifyBox.appendNotification(notifyRightsText, "about-rights",
+                                           null, notifyBox.PRIORITY_INFO_LOW,
+                                           buttons);
+    box.persistence = 3; // arbitrary number, just so bar sticks around for a bit
+  },
+
   _updatePrefs: function()
   {
     // Get the preferences service
     var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                           .getService(Components.interfaces.nsIPrefService)
                           .getBranch(null);
     const PREF_INVALID = Components.interfaces.nsIPrefBranch.PREF_INVALID;
     if (prefs.getPrefType("browser.download.dir") == PREF_INVALID ||
--- a/suite/installer/unix/packages
+++ b/suite/installer/unix/packages
@@ -265,16 +265,17 @@ bin/components/zipwriter.xpt
 bin/components/FeedConverter.js
 bin/components/FeedProcessor.js
 bin/components/FeedWriter.js
 #ifndef MOZILLA_1_9_1_BRANCH
 bin/components/GPSDGeolocationProvider.js
 #endif
 bin/components/jsconsole-clhandler.js
 bin/components/NetworkGeolocationProvider.js
+bin/components/aboutRights.js
 bin/components/nsAboutAbout.js
 bin/components/nsAboutCertError.js
 bin/components/nsAboutFeeds.js
 bin/components/nsAboutSessionRestore.js
 bin/components/nsAddonRepository.js
 bin/components/nsBadCertHandler.js
 bin/components/nsBlocklistService.js
 bin/components/nsBrowserContentHandler.js
--- a/suite/installer/windows/packages
+++ b/suite/installer/windows/packages
@@ -289,16 +289,17 @@ bin\components\zipwriter.xpt
 bin\components\FeedConverter.js
 bin\components\FeedProcessor.js
 bin\components\FeedWriter.js
 #ifndef MOZILLA_1_9_1_BRANCH
 bin\components\GPSDGeolocationProvider.js
 #endif
 bin\components\jsconsole-clhandler.js
 bin\components\NetworkGeolocationProvider.js
+bin\components\aboutRights.js
 bin\components\nsAboutAbout.js
 bin\components\nsAboutCertError.js
 bin\components\nsAboutFeeds.js
 bin\components\nsAboutSessionRestore.js
 bin\components\nsAddonRepository.js
 bin\components\nsAxSecurityPolicy.js
 bin\components\nsBadCertHandler.js
 bin\components\nsBlocklistService.js
--- a/suite/locales/jar.mn
+++ b/suite/locales/jar.mn
@@ -13,16 +13,18 @@
 #endif
 % locale messenger-newsblog @AB_CD@ %locale/@AB_CD@/messenger-newsblog/
 % locale mozldap @AB_CD@ %locale/@AB_CD@/mozldap/
 % locale navigator @AB_CD@ %locale/@AB_CD@/navigator/
 % locale navigator-platform @AB_CD@ %locale/@AB_CD@/navigator-platform/
 % locale navigator-region @AB_CD@ %locale/@AB_CD@/navigator-region/
   locale/@AB_CD@/branding/brand.dtd                                         (%chrome/branding/brand.dtd)
   locale/@AB_CD@/branding/brand.properties                                  (%chrome/branding/brand.properties)
+  locale/@AB_CD@/branding/aboutRights.dtd                                   (%chrome/branding/aboutRights.dtd)
+  locale/@AB_CD@/branding/aboutRights.properties                            (%chrome/branding/aboutRights.properties)
   locale/@AB_CD@/communicator/askViewZoom.dtd                               (%chrome/common/askViewZoom.dtd)
   locale/@AB_CD@/communicator/certError.dtd                                 (%chrome/common/certError.dtd)
   locale/@AB_CD@/communicator/consoleOverlay.dtd                            (%chrome/common/consoleOverlay.dtd)
   locale/@AB_CD@/communicator/contentAreaCommands.dtd                       (%chrome/common/contentAreaCommands.dtd)
   locale/@AB_CD@/communicator/contentAreaCommands.properties                (%chrome/common/contentAreaCommands.properties)
   locale/@AB_CD@/communicator/defaultClientDialog.dtd                       (%chrome/common/defaultClientDialog.dtd)
   locale/@AB_CD@/communicator/feeds/subscribe.dtd                           (%chrome/common/feeds/subscribe.dtd)
   locale/@AB_CD@/communicator/feeds/subscribe.properties                    (%chrome/common/feeds/subscribe.properties)