Merge fx-team to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 26 Sep 2013 21:36:35 -0400
changeset 148919 e4cd2242cc7d85e240c585f68730753348fd1a9e
parent 148897 af156cfb281f109e0cd76d2ed543556f4de8b7c5 (current diff)
parent 148918 7571fd150b38a8029efe7fed1ddd6b779fe84e1d (diff)
child 148920 fdc6054e33e4f9b045196401947c13df186fb37a
child 148965 c21219ddfd725d773e31b449291ac881c58d92f3
child 149089 9433c19bf735b27e4dbcdea5aed5d08982915033
child 149740 b5014120f28b3cfc51a65cef2c181d3ee5403628
child 155859 649ce586dae312d228aa65ca4e74bba426fa020d
push id34380
push userryanvm@gmail.com
push dateFri, 27 Sep 2013 01:41:00 +0000
treeherdermozilla-inbound@fdc6054e33e4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge fx-team to m-c.
mobile/android/base/resources/drawable-hdpi/icon_most_visited_empty.png
mobile/android/base/resources/drawable-mdpi/icon_most_visited_empty.png
mobile/android/base/resources/drawable-xhdpi/icon_most_visited_empty.png
--- a/accessible/tests/crashtests/471493.xul
+++ b/accessible/tests/crashtests/471493.xul
@@ -4,20 +4,18 @@
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         title="bug 471493 'crash [@ nsPropertyTable::GetPropertyInternal]'"
         onload="doTest();">
 
   <script type="application/javascript">
   <![CDATA[
     function doTest()
     {
-      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-
-      var accRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
-        getService(Components.interfaces.nsIAccessibleRetrieval);
+      var accRetrieval = SpecialPowers.Cc["@mozilla.org/accessibleRetrieval;1"].
+        getService(SpecialPowers.Ci.nsIAccessibleRetrieval);
 
       var treecol = document.getElementById("col");
       var x = treecol.boxObject.screenX;
       var y = treecol.boxObject.screenY;
 
       var tree = document.getElementById("tree");
       var treeAcc = accRetrieval.getAccessibleFor(tree);
       treeAcc.getChildAtPoint(x + 1, y + 1);
--- a/accessible/tests/crashtests/crashtests.list
+++ b/accessible/tests/crashtests/crashtests.list
@@ -1,1 +1,2 @@
-load 471493.xul
\ No newline at end of file
+# Disabled because it causes assertions/crashes in later crashtests, see bug 918246
+skip load 471493.xul
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -869,28 +869,37 @@ SocialToolbar = {
     let socialEnabled = SocialUI.enabled;
     for (let className of ["social-statusarea-separator", "social-statusarea-user"]) {
       for (let element of document.getElementsByClassName(className))
         element.hidden = !socialEnabled;
     }
     let toggleNotificationsCommand = document.getElementById("Social:ToggleNotifications");
     toggleNotificationsCommand.setAttribute("hidden", !socialEnabled);
 
-    let parent = document.getElementById("social-notification-panel");
-    while (parent.hasChildNodes()) {
-      let frame = parent.firstChild;
-      SharedFrame.forgetGroup(frame.id);
-      parent.removeChild(frame);
-    }
-
+    // we need to remove buttons and frames if !socialEnabled or the provider
+    // has changed (frame origin does not match current provider). We only
+    // remove frames that are "attached" to buttons in this toolbar button since
+    // other buttons may also be using grouped frames.
     let tbi = document.getElementById("social-provider-button");
     if (tbi) {
       // buttons after social-provider-button are ambient icons
-      while (tbi.nextSibling) {
-        tbi.parentNode.removeChild(tbi.nextSibling);
+      let next = tbi.nextSibling;
+      let currentOrigin = Social.provider ? Social.provider.origin : null;
+
+      while (next) {
+        let button = next;
+        next = next.nextSibling;
+        // get the frame for this button
+        let frameId = button.getAttribute("notificationFrameId");
+        let frame = document.getElementById(frameId);
+        if (!socialEnabled || frame.getAttribute("origin") != currentOrigin) {
+          SharedFrame.forgetGroup(frame.id);
+          frame.parentNode.removeChild(frame);
+          button.parentNode.removeChild(button);
+        }
       }
     }
   },
 
   updateProfile: function SocialToolbar_updateProfile() {
     // Profile may not have been initialized yet, since it depends on a worker
     // response. In that case we'll be called again when it's available, via
     // social:profile-changed
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -254,17 +254,17 @@ panel[noactions] > richlistbox > richlis
 }
 
 #urlbar:not([actiontype]) > #urlbar-display-box {
   display: none;
 }
 
 #wrapper-urlbar-container > #urlbar-container > #urlbar {
   -moz-user-input: disabled;
-  cursor: -moz-grab;
+  cursor: grab;
 }
 
 #PopupAutoComplete {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#browser-autocomplete-result-popup");
 }
 
 #PopupAutoCompleteRichResult {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#urlbar-rich-result-popup");
--- a/browser/base/content/sanitizeDialog.css
+++ b/browser/base/content/sanitizeDialog.css
@@ -6,17 +6,17 @@
 
 #placesTreechildren {
   -moz-user-focus: normal;
 }
 
 #placesTreechildren::-moz-tree-cell(grippyRow),
 #placesTreechildren::-moz-tree-cell-text(grippyRow),
 #placesTreechildren::-moz-tree-image(grippyRow) {
-  cursor: -moz-grab;
+  cursor: grab;
 }
 
 
 /* Sanitize everything warnings */
 
 #sanitizeEverythingWarning,
 #sanitizeEverythingUndoWarning {
   white-space: pre-wrap;
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1494,17 +1494,17 @@
           document.getAnonymousElementByAttribute(this, "anonid",
                     "center-item-menulist").value = val;
         </setter>
       </property>
     </implementation>
   </binding>
 
   <binding id="click-to-play-plugins-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
-    <content align="start" class="click-to-play-plugins-notification-content">
+    <content align="start" style="width: &pluginNotification.width;;">
       <xul:vbox flex="1" align="stretch" class="popup-notification-main-box"
                 xbl:inherits="popupid">
         <xul:hbox class="click-to-play-plugins-notification-description-box" flex="1" align="start">
           <xul:description class="click-to-play-plugins-outer-description" flex="1">
             <html:span anonid="click-to-play-plugins-notification-description" />
             <xul:label class="text-link click-to-play-plugins-notification-link" anonid="click-to-play-plugins-notification-link" />
           </xul:description>
           <xul:toolbarbutton anonid="closebutton"
--- a/browser/devtools/app-manager/app-projects.js
+++ b/browser/devtools/app-manager/app-projects.js
@@ -63,16 +63,33 @@ const IDB = {
     };
     request.onsuccess = function() {
       deferred.resolve();
     };
 
     return deferred.promise;
   },
 
+  update: function(project) {
+    let deferred = promise.defer();
+
+    var transaction = IDB._db.transaction(["projects"], "readwrite");
+    var objectStore = transaction.objectStore("projects");
+    var request = objectStore.put(project);
+    request.onerror = function(event) {
+      deferred.reject("Unable to update project to the AppProjects indexedDB: " +
+                      this.error.name + " - " + this.error.message );
+    };
+    request.onsuccess = function() {
+      deferred.resolve();
+    };
+
+    return deferred.promise;
+  },
+
   remove: function(location) {
     let deferred = promise.defer();
 
     let request = IDB._db.transaction(["projects"], "readwrite")
                     .objectStore("projects")
                     .delete(location);
     request.onsuccess = function(event) {
       deferred.resolve();
@@ -105,16 +122,18 @@ const AppProjects = {
     let project = {
       type: "packaged",
       location: folder.path,
       // We need a unique id, that is the app origin,
       // in order to identify the app when being installed on the device.
       // The packaged app local path is a valid id, but only on the client.
       // This origin will be used to generate the true id of an app:
       // its manifest URL.
+      // If the app ends up specifying an explicit origin in its manifest,
+      // we will override this random UUID on app install.
       packagedAppOrigin: generateUUID().toString().slice(1, -1)
     };
     return IDB.add(project).then(function () {
       store.object.projects.push(project);
       // return the added objects (proxified)
       return store.object.projects[store.object.projects.length - 1];
     });
   },
@@ -126,16 +145,24 @@ const AppProjects = {
     };
     return IDB.add(project).then(function () {
       store.object.projects.push(project);
       // return the added objects (proxified)
       return store.object.projects[store.object.projects.length - 1];
     });
   },
 
+  update: function (project) {
+    return IDB.update({
+      type: project.type,
+      location: project.location,
+      packagedAppOrigin: project.packagedAppOrigin
+    }).then(() => project);
+  },
+
   remove: function(location) {
     return IDB.remove(location).then(function () {
       let projects = store.object.projects;
       for (let i = 0; i < projects.length; i++) {
         if (projects[i].location == location) {
           projects.splice(i, 1);
           return;
         }
--- a/browser/devtools/app-manager/content/projects.js
+++ b/browser/devtools/app-manager/content/projects.js
@@ -203,30 +203,35 @@ let UI = {
     if (project.type == "packaged") {
       return "app://" + project.packagedAppOrigin + "/manifest.webapp";
     } else if (project.type == "hosted") {
       return project.location;
     }
   },
 
   install: function(project) {
-    let install;
     if (project.type == "packaged") {
-      install = installPackaged(this.connection.client, this.listTabsResponse.webappsActor, project.location, project.packagedAppOrigin);
+      return installPackaged(this.connection.client, this.listTabsResponse.webappsActor, project.location, project.packagedAppOrigin)
+        .then(({ appId }) => {
+          // If the packaged app specified a custom origin override,
+          // we need to update the local project origin
+          project.packagedAppOrigin = appId;
+          // And ensure the indexed db on disk is also updated
+          AppProjects.update(project);
+        });
     } else {
       let manifestURLObject = Services.io.newURI(project.location, null, null);
       let origin = Services.io.newURI(manifestURLObject.prePath, null, null);
       let appId = origin.host;
       let metadata = {
         origin: origin.spec,
         manifestURL: project.location
       };
-      install = installHosted(this.connection.client, this.listTabsResponse.webappsActor, appId, metadata, project.manifest);
+      return installHosted(this.connection.client, this.listTabsResponse.webappsActor, appId, metadata, project.manifest);
     }
-    return install;
   },
 
   start: function(project) {
     let deferred = promise.defer();
     let request = {
       to: this.listTabsResponse.webappsActor,
       type: "launch",
       manifestURL: this._getProjectManifestURL(project)
--- a/browser/devtools/webconsole/webconsole.js
+++ b/browser/devtools/webconsole/webconsole.js
@@ -4517,16 +4517,17 @@ var Utils = {
       case "CSS Loader":
         return CATEGORY_CSS;
 
       case "Mixed Content Blocker":
       case "Mixed Content Message":
       case "CSP":
       case "Invalid HSTS Headers":
       case "Insecure Password Field":
+      case "SSL":
         return CATEGORY_SECURITY;
 
       default:
         return CATEGORY_JS;
     }
   },
 
   /**
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -667,16 +667,23 @@ just addresses the organization to follo
 <!ENTITY pluginNotification.showAll.label "Show All">
 <!ENTITY pluginNotification.showAll.accesskey "S">
 
 <!-- LOCALIZATION NOTE (pluginActivateNow.label, pluginActivateAlways.label, pluginBlockNow.label): These should be the same as the matching strings in browser.properties -->
 <!ENTITY pluginActivateNow.label "Allow Now">
 <!ENTITY pluginActivateAlways.label "Allow and Remember">
 <!ENTITY pluginBlockNow.label "Block Plugin">
 
+<!-- LOCALIZATION NOTE: (pluginNotification.width): This is used to determine the
+     width of the plugin popup notification that can appear if a plugin has been
+     blocked on a page. Should be wide enough to fit the pluginActivateNow.label
+     and pluginActivateAlways.label strings above on a single line. This must be
+     a CSS length value. -->
+<!ENTITY pluginNotification.width "28em">
+
 <!ENTITY tabCrashed.header "Tab crashed">
 <!ENTITY tabCrashed.message "Well, this is embarrassing. We tried to display this Web page, but it's not responding.">
 <!ENTITY tabCrashed.checkSendReport "Tell &vendorShortName; about this crash so they can fix it.">
 <!ENTITY tabCrashed.tryAgain "Try Again">
 
 <!-- LOCALIZATION NOTE: the following strings are unused in Australis, they're
      kept here to avoid warnings from l10n tools like compare-locales on
      l10n-central. They will be definitely removed when Australis is ready
--- a/browser/themes/shared/plugin-doorhanger.inc.css
+++ b/browser/themes/shared/plugin-doorhanger.inc.css
@@ -1,16 +1,12 @@
 #notification-popup[popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0px;
 }
 
-.click-to-play-plugins-notification-content {
-  width: 28em;
-}
-
 .click-to-play-plugins-notification-center-box {
   border: 1px solid ThreeDShadow;
   margin: 10px;
 }
 
 .plugin-popupnotification-centeritem:nth-child(odd) {
   background-color: rgba(0,0,0,0.1);
 }
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -733,16 +733,24 @@ public:
    * Return the nsIXPConnect service.
    */
   static nsIXPConnect *XPConnect()
   {
     return sXPConnect;
   }
 
   /**
+   * Report simple error message to the browser console
+   *   @param aErrorText the error message
+   *   @param classification Name of the module reporting error
+   */
+  static void LogSimpleConsoleError(const nsAString& aErrorText,
+                                    const char * classification);
+
+  /**
    * Report a non-localized error message to the error console.
    *   @param aErrorText the error message
    *   @param aErrorFlags See nsIScriptError.
    *   @param aCategory Name of module reporting error.
    *   @param aDocument Reference to the document which triggered the message.
    *   @param [aURI=nullptr] (Optional) URI of resource containing error.
    *   @param [aSourceLine=EmptyString()] (Optional) The text of the line that
               contains the error (may be empty).
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3009,16 +3009,34 @@ nsresult nsContentUtils::FormatLocalized
   NS_ENSURE_SUCCESS(rv, rv);
   nsIStringBundle *bundle = sStringBundles[aFile];
 
   return bundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
                                       aParams, aParamsLength,
                                       getter_Copies(aResult));
 }
 
+/* static */ void
+nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
+                                      const char * classification)
+{
+  nsCOMPtr<nsIScriptError> scriptError =
+    do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
+  if (scriptError) {
+    nsCOMPtr<nsIConsoleService> console =
+      do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+    if (console && NS_SUCCEEDED(scriptError->Init(aErrorText, EmptyString(),
+                                                  EmptyString(), 0, 0,
+                                                  nsIScriptError::errorFlag,
+                                                  classification))) {
+      console->LogMessage(scriptError);
+    }
+  }
+}
+
 /* static */ nsresult
 nsContentUtils::ReportToConsole(uint32_t aErrorFlags,
                                 const nsACString& aCategory,
                                 nsIDocument* aDocument,
                                 PropertiesFile aFile,
                                 const char *aMessageName,
                                 const PRUnichar **aParams,
                                 uint32_t aParamsLength,
--- a/layout/mathml/crashtests/400157.xhtml
+++ b/layout/mathml/crashtests/400157.xhtml
@@ -1,31 +1,34 @@
-<html xmlns="http://www.w3.org/1999/xhtml" xmlns:mathml="http://www.w3.org/1998/Math/MathML">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:mathml="http://www.w3.org/1998/Math/MathML" class="reftest-wait">
 <mathml:mfenced/>
 
 
 <script><![CDATA[
 var docviewer;
 function do_onload() {
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-var navigator1 = parent.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation);
-var docShell = navigator1.QueryInterface(Components.interfaces.nsIDocShell);
-docviewer = docShell.contentViewer.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
+  var navigator1 = SpecialPowers.wrap(parent).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(SpecialPowers.Ci.nsIWebNavigation);
+  var docShell = navigator1.QueryInterface(SpecialPowers.Ci.nsIDocShell);
+  docviewer = docShell.contentViewer.QueryInterface(SpecialPowers.Ci.nsIMarkupDocumentViewer);
 
-setTimeout(function() {window.location.reload()}, 500);
-setTimeout(doe,50, 0.2);
+  setTimeout(function() {
+    clearTimeout(timer);
+    docviewer.textZoom = 1;
+    document.documentElement.removeAttribute("class");
+  }, 500);
+  setTimeout(doe,50, 0.2);
 }
 do_onload();
 
+var timer;
 function doe(i) {
-netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
- docviewer.textZoom += i;
+  docviewer.textZoom += i;
 
-if (docviewer.textZoom >=4)
-  i = -0.2;
+  if (docviewer.textZoom >=4)
+    i = -0.2;
 
-if (docviewer.textZoom <=0)
-  i = 0.2;
-window.status = docviewer.textZoom;
-setTimeout(doe, 50, i);
+  if (docviewer.textZoom <=0)
+    i = 0.2;
+  window.status = docviewer.textZoom;
+  timer = setTimeout(doe, 50, i);
 }
 ]]></script>
 </html>
\ No newline at end of file
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -196,16 +196,17 @@
         <receiver android:name="org.mozilla.gecko.ReferrerReceiver" android:exported="true">
             <intent-filter>
                 <action android:name="com.android.vending.INSTALL_REFERRER" />
             </intent-filter>
         </receiver>
 
         <activity android:name="org.mozilla.gecko.Restarter"
                   android:process="@ANDROID_PACKAGE_NAME@Restarter"
+                  android:noHistory="true"
                   android:theme="@style/Gecko">
           <intent-filter>
             <action android:name="org.mozilla.gecko.restart"/>
             <action android:name="org.mozilla.gecko.restart_update"/>
           </intent-filter>
         </activity>
 
 #include ../services/manifests/AnnouncementsAndroidManifest_activities.xml.in
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -2263,18 +2263,22 @@ abstract public class BrowserApp extends
                     GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Feedback:LastUrl", url));
             }
         }).execute();
     }
 
     // HomePager.OnNewTabsListener
     @Override
     public void onNewTabs(String[] urls) {
+        final EnumSet<OnUrlOpenListener.Flags> flags = EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB);
+ 
         for (String url : urls) {
-            openUrl(url, true);
+            if (!maybeSwitchToTab(url, flags)) {
+                openUrl(url, true);
+            }
         }
     }
 
     // HomePager.OnUrlOpenListener
     @Override
     public void onUrlOpen(String url, EnumSet<OnUrlOpenListener.Flags> flags) {
         if (!maybeSwitchToTab(url, flags)) {
             openUrl(url);
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -2127,18 +2127,16 @@ abstract public class GeckoApp
     }
 
     public void doRestart(String action, String args) {
         Log.d(LOGTAG, "doRestart(\"" + action + "\")");
         try {
             Intent intent = new Intent(action);
             intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, RESTARTER_CLASS);
             /* TODO: addEnvToIntent(intent); */
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                            Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
             if (args != null)
                 intent.putExtra("args", args);
             intent.putExtra("didRestart", true);
             Log.d(LOGTAG, "Restart intent: " + intent.toString());
             GeckoAppShell.killAnyZombies();
             startActivity(intent);
         } catch (Exception e) {
             Log.e(LOGTAG, "Error effecting restart.", e);
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -661,17 +661,16 @@ RES_DRAWABLE_MDPI = \
   res/drawable-mdpi/ic_url_bar_search.png \
   res/drawable-mdpi/ic_url_bar_star.png \
   res/drawable-mdpi/ic_url_bar_tab.png \
   res/drawable-mdpi/icon_last_tabs.png \
   res/drawable-mdpi/icon_last_tabs_empty.png \
   res/drawable-mdpi/icon_most_recent.png \
   res/drawable-mdpi/icon_most_recent_empty.png \
   res/drawable-mdpi/icon_most_visited.png \
-  res/drawable-mdpi/icon_most_visited_empty.png \
   res/drawable-mdpi/icon_openinapp.png \
   res/drawable-mdpi/icon_pageaction.png \
   res/drawable-mdpi/icon_reading_list_empty.png \
   res/drawable-mdpi/progress_spinner.png \
   res/drawable-mdpi/play.png \
   res/drawable-mdpi/pause.png \
   res/drawable-mdpi/tab_indicator_divider.9.png \
   res/drawable-mdpi/tab_indicator_selected.9.png \
@@ -777,17 +776,16 @@ RES_DRAWABLE_HDPI = \
   res/drawable-hdpi/ic_url_bar_search.png \
   res/drawable-hdpi/ic_url_bar_star.png \
   res/drawable-hdpi/ic_url_bar_tab.png \
   res/drawable-hdpi/icon_last_tabs.png \
   res/drawable-hdpi/icon_last_tabs_empty.png \
   res/drawable-hdpi/icon_most_recent.png \
   res/drawable-hdpi/icon_most_recent_empty.png \
   res/drawable-hdpi/icon_most_visited.png \
-  res/drawable-hdpi/icon_most_visited_empty.png \
   res/drawable-hdpi/icon_openinapp.png \
   res/drawable-hdpi/icon_pageaction.png \
   res/drawable-hdpi/icon_reading_list_empty.png \
   res/drawable-hdpi/tab_indicator_divider.9.png \
   res/drawable-hdpi/tab_indicator_selected.9.png \
   res/drawable-hdpi/tab_indicator_selected_focused.9.png \
   res/drawable-hdpi/spinner_default.9.png \
   res/drawable-hdpi/spinner_focused.9.png \
@@ -879,17 +877,16 @@ RES_DRAWABLE_XHDPI = \
   res/drawable-xhdpi/ic_url_bar_search.png \
   res/drawable-xhdpi/ic_url_bar_star.png \
   res/drawable-xhdpi/ic_url_bar_tab.png \
   res/drawable-xhdpi/icon_last_tabs.png \
   res/drawable-xhdpi/icon_last_tabs_empty.png \
   res/drawable-xhdpi/icon_most_recent.png \
   res/drawable-xhdpi/icon_most_recent_empty.png \
   res/drawable-xhdpi/icon_most_visited.png \
-  res/drawable-xhdpi/icon_most_visited_empty.png \
   res/drawable-xhdpi/icon_openinapp.png \
   res/drawable-xhdpi/icon_pageaction.png \
   res/drawable-xhdpi/icon_reading_list_empty.png \
   res/drawable-xhdpi/spinner_default.9.png \
   res/drawable-xhdpi/spinner_focused.9.png \
   res/drawable-xhdpi/spinner_pressed.9.png \
   res/drawable-xhdpi/tab_new.png \
   res/drawable-xhdpi/tab_new_pb.png \
--- a/mobile/android/base/Restarter.java
+++ b/mobile/android/base/Restarter.java
@@ -10,16 +10,18 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
 
 public class Restarter extends Activity {
     private static final String LOGTAG = "GeckoRestarter";
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
         Log.i(LOGTAG, "Trying to restart " + AppConstants.MOZ_APP_NAME);
         try {
             int countdown = 40;
             while (GeckoAppShell.checkForGeckoProcs() &&  --countdown > 0) {
                 // Wait for the old process to die before we continue
                 try {
                     Thread.sleep(100);
                 } catch (InterruptedException ie) {}
@@ -41,20 +43,15 @@ public class Restarter extends Activity 
         }
         try {
             Intent intent = new Intent(Intent.ACTION_MAIN);
             intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
                                 AppConstants.BROWSER_INTENT_CLASS);
             Bundle b = getIntent().getExtras();
             if (b != null)
                 intent.putExtras(b);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
             Log.i(LOGTAG, intent.toString());
             startActivity(intent);
         } catch (Exception e) {
             Log.i(LOGTAG, e.toString());
         }
-        // Give the new process time to start before we die
-        GeckoAppShell.waitForAnotherGeckoProc();
-        System.exit(0);
     }
 }
--- a/mobile/android/base/home/TopSitesPage.java
+++ b/mobile/android/base/home/TopSitesPage.java
@@ -42,21 +42,18 @@ import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.LayoutInflater;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
-import android.view.ViewStub;
 import android.widget.AdapterView;
-import android.widget.ImageView;
 import android.widget.ListView;
-import android.widget.TextView;
 import android.widget.Toast;
 
 import java.util.EnumSet;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -82,19 +79,16 @@ public class TopSitesPage extends HomeFr
     private TopSitesGridAdapter mGridAdapter;
 
     // List of top sites
     private ListView mList;
 
     // Grid of top sites
     private TopSitesGridView mGrid;
 
-    // Reference to the View to display when there are no results.
-    private View mEmptyView;
-
     // Banner to show snippets.
     private HomeBanner mBanner;
 
     // Raw Y value of the last event that happened on the list view.
     private float mListTouchY = -1;
 
     // Scrolling direction of the banner.
     private boolean mSnapBannerToTop;
@@ -219,17 +213,16 @@ public class TopSitesPage extends HomeFr
         });
     }
 
     @Override
     public void onDestroyView() {
         super.onDestroyView();
         mList = null;
         mGrid = null;
-        mEmptyView = null;
         mListAdapter = null;
         mGridAdapter = null;
     }
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
@@ -461,30 +454,16 @@ public class TopSitesPage extends HomeFr
     }
 
     private void updateUiFromCursor(Cursor c) {
         mList.setHeaderDividersEnabled(c != null && c.getCount() > mMaxGridEntries);
 
         if (c != null && c.getCount() > 0) {
             return;
         }
-
-        if (mEmptyView == null) {
-            // Set empty page view. We delay this so that the empty view won't flash.
-            ViewStub emptyViewStub = (ViewStub) getView().findViewById(R.id.home_empty_view_stub);
-            mEmptyView = emptyViewStub.inflate();
-
-            final ImageView emptyIcon = (ImageView) mEmptyView.findViewById(R.id.home_empty_image);
-            emptyIcon.setImageResource(R.drawable.icon_most_visited_empty);
-
-            final TextView emptyText = (TextView) mEmptyView.findViewById(R.id.home_empty_text);
-            emptyText.setText(R.string.home_most_visited_empty);
-
-            mList.setEmptyView(mEmptyView);
-        }
     }
 
     private static class TopSitesLoader extends SimpleCursorLoader {
         // Max number of search results
         private static final int SEARCH_LIMIT = 30;
         private int mMaxGridEntries;
 
         public TopSitesLoader(Context context) {
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -275,28 +275,26 @@ size. -->
 <!ENTITY home_top_sites_add "Add a site">
 
 <!ENTITY home_history_title "History">
 <!ENTITY home_last_tabs_title "Tabs from last time">
 <!ENTITY home_last_tabs_open "Open all tabs from last time">
 <!ENTITY home_last_tabs_empty "Your recent tabs show up here.">
 <!ENTITY home_most_recent_title "Most recent">
 <!ENTITY home_most_recent_empty "Websites you visited most recently show up here.">
-<!ENTITY home_most_visited_title "Most visited">
 <!ENTITY home_reading_list_empty "Articles you save for later show up here.">
 <!-- Localization note (home_reading_list_hint): The "TIP" string is synonymous to "hint", "clue", etc. This string is displayed
      as an advisory message on how to add content to the reading list when the reading list empty.
      The "&#37;I" in the string will be replaced by a small image of the icon described, and can be moved to wherever
      it is applicable. Please keep the spacing around the "&#37;I" string. -->
 <!ENTITY home_reading_list_hint "TIP: Save articles to your reading list by long pressing the &#37;I icon when it appears in the title bar.">
 <!-- Localization note (home_reading_list_hint_accessible): This string is used
      as alternate text for accessibility. It is not visible in the UI. -->
 <!ENTITY home_reading_list_hint_accessible "TIP: Save articles to your reading list by long pressing the reader mode button when it appears in the title bar.">
 
-<!ENTITY home_most_visited_empty "Websites you visit most frequently show up here.">
 <!ENTITY pin_site_dialog_hint "Enter a search keyword">
 
 <!ENTITY filepicker_title "Choose File">
 <!ENTITY filepicker_audio_title "Choose or record a sound">
 <!ENTITY filepicker_image_title "Choose or take a picture">
 <!ENTITY filepicker_video_title "Choose or record a video">
 
 <!-- Site identity popup -->
deleted file mode 100644
index 93f5bf2d0ddb74d232252088c59837e6dc682216..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index bb2881758447ac8832eae19d1a7dd3b739f1d020..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 4182b7e4c36a5b6b66880d180ec11ff825601484..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/mobile/android/base/resources/layout/home_suggestion_prompt.xml
+++ b/mobile/android/base/resources/layout/home_suggestion_prompt.xml
@@ -1,53 +1,52 @@
 <?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/. -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
-             android:background="@drawable/url_bar_bg">
+             android:background="@color/background_light">
 
     <LinearLayout android:id="@+id/prompt"
                   android:focusable="true"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:orientation="horizontal"
                   android:minHeight="@dimen/search_row_height"
                   android:gravity="center_vertical"
                   android:padding="10dip">
 
         <TextView android:id="@+id/suggestions_prompt_title"
                   android:layout_height="wrap_content"
                   android:layout_width="0dp"
-                  android:textColor="@color/url_bar_title"
                   android:layout_marginLeft="6dip"
-                  android:textSize="14sp"
-                  android:layout_weight="1" />
+                  android:layout_weight="1"
+                  android:textAppearance="@style/TextAppearance.Widget.SuggestionsPrompt"/>
 
         <TextView android:id="@+id/suggestions_prompt_yes"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="14sp"
                   android:layout_marginLeft="15dip"
+                  android:textAppearance="@style/TextAppearance.Widget.SuggestionsPrompt"
                   android:background="@drawable/suggestion_selector"
                   android:paddingLeft="15dp"
                   android:paddingRight="15dp"
                   android:paddingTop="7dp"
                   android:paddingBottom="7dp"
                   android:focusable="true"
                   android:text="@string/button_yes" />
 
         <TextView android:id="@+id/suggestions_prompt_no"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="14sp"
                   android:layout_marginLeft="6dip"
+                  android:textAppearance="@style/TextAppearance.Widget.SuggestionsPrompt"
                   android:background="@drawable/suggestion_selector"
                   android:nextFocusRight="@+id/suggestions_prompt_no"
                   android:paddingLeft="15dp"
                   android:paddingRight="15dp"
                   android:paddingTop="7dp"
                   android:paddingBottom="7dp"
                   android:focusable="true"
                   android:text="@string/button_no" />
--- a/mobile/android/base/resources/layout/home_top_sites_page.xml
+++ b/mobile/android/base/resources/layout/home_top_sites_page.xml
@@ -3,21 +3,16 @@
    - 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/. -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               android:orientation="vertical">
 
-    <ViewStub android:id="@+id/home_empty_view_stub"
-              android:layout="@layout/home_empty_page"
-              android:layout_width="fill_parent"
-              android:layout_height="fill_parent"/>
-
     <org.mozilla.gecko.home.HomeListView
             android:id="@+id/list"
             style="@style/Widget.TopSitesListView"
             android:layout_width="fill_parent"
             android:layout_height="0dp"
             android:layout_weight="1"/>
 
     <org.mozilla.gecko.home.HomeBanner android:id="@+id/home_banner"
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -307,16 +307,20 @@
     <style name="TextAppearance.Widget.TwoLinePageRow" />
 
     <style name="TextAppearance.Widget.TwoLinePageRow.Title" parent="TextAppearance.Medium"/>
 
     <style name="TextAppearance.Widget.TwoLinePageRow.Url" parent="TextAppearance.Micro">
         <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
 
+    <style name="TextAppearance.Widget.SuggestionsPrompt" parent="TextAppearance.Small">
+        <item name="android:textColor">@color/url_bar_title</item>
+    </style>
+
     <style name="TextAppearance.Widget.Home" />
 
     <style name="TextAppearance.Widget.Home.Header" parent="TextAppearance.Small">
         <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.Widget.Home.PageTitle" parent="TextAppearance.Medium" />
 
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -254,18 +254,16 @@
   <string name="home_top_sites_title">&home_top_sites_title;</string>
   <string name="home_top_sites_add">&home_top_sites_add;</string>
   <string name="home_history_title">&home_history_title;</string>
   <string name="home_last_tabs_title">&home_last_tabs_title;</string>
   <string name="home_last_tabs_open">&home_last_tabs_open;</string>
   <string name="home_last_tabs_empty">&home_last_tabs_empty;</string>
   <string name="home_most_recent_title">&home_most_recent_title;</string>
   <string name="home_most_recent_empty">&home_most_recent_empty;</string>
-  <string name="home_most_visited_title">&home_most_visited_title;</string>
-  <string name="home_most_visited_empty">&home_most_visited_empty;</string>
   <string name="home_reading_list_empty">&home_reading_list_empty;</string>
   <string name="home_reading_list_hint">&home_reading_list_hint;</string>
   <string name="home_reading_list_hint_accessible">&home_reading_list_hint_accessible;</string>
   <string name="pin_site_dialog_hint">&pin_site_dialog_hint;</string>
 
   <string name="filepicker_title">&filepicker_title;</string>
   <string name="filepicker_audio_title">&filepicker_audio_title;</string>
   <string name="filepicker_image_title">&filepicker_image_title;</string>
--- a/mobile/android/chrome/content/aboutHome.xhtml
+++ b/mobile/android/chrome/content/aboutHome.xhtml
@@ -1,16 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
-  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<!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 % abouthomeDTD SYSTEM "chrome://browser/locale/aboutHome.dtd">
+  %abouthomeDTD;
+]>
 
 <!-- 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/. -->
 
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
+  <title>&abouthome.title;</title>
   <link rel="icon" type="image/png" sizes="64x64" href="chrome://branding/content/favicon64.png" />
 </head>
 <body>
 </body>
 </html>
--- a/mobile/android/chrome/content/aboutPrivateBrowsing.xhtml
+++ b/mobile/android/chrome/content/aboutPrivateBrowsing.xhtml
@@ -12,16 +12,17 @@
   <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
   %globalDTD;
   <!ENTITY % privatebrowsingpageDTD SYSTEM "chrome://browser/locale/aboutPrivateBrowsing.dtd">
   %privatebrowsingpageDTD;
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
+    <title>&privatebrowsingpage.title;</title>
     <meta name="viewport" content="width=device-width, initial-scale=1; user-scalable=no"/>
     <link rel="stylesheet" href="chrome://browser/skin/aboutPrivateBrowsing.css" type="text/css" media="all"/>
     <link rel="icon" type="image/png" href="chrome://branding/content/favicon32.png" />
     <script type="application/javascript;version=1.7"><![CDATA[
       const Ci = Components.interfaces;
       const Cu = Components.utils;
 
       Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
new file mode 100644
--- /dev/null
+++ b/mobile/android/locales/en-US/chrome/aboutHome.dtd
@@ -0,0 +1,5 @@
+<!-- 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/. -->
+
+<!ENTITY abouthome.title                  "&brandShortName; Home">
--- a/mobile/android/locales/jar.mn
+++ b/mobile/android/locales/jar.mn
@@ -9,16 +9,17 @@
   locale/@AB_CD@/browser/about.dtd                (%chrome/about.dtd)
   locale/@AB_CD@/browser/aboutAddons.dtd          (%chrome/aboutAddons.dtd)
   locale/@AB_CD@/browser/aboutAddons.properties   (%chrome/aboutAddons.properties)
   locale/@AB_CD@/browser/aboutApps.dtd            (%chrome/aboutApps.dtd)
   locale/@AB_CD@/browser/aboutCertError.dtd       (%chrome/aboutCertError.dtd)
   locale/@AB_CD@/browser/aboutDownloads.dtd       (%chrome/aboutDownloads.dtd)
   locale/@AB_CD@/browser/aboutDownloads.properties (%chrome/aboutDownloads.properties)
   locale/@AB_CD@/browser/aboutFeedback.dtd        (%chrome/aboutFeedback.dtd)
+  locale/@AB_CD@/browser/aboutHome.dtd            (%chrome/aboutHome.dtd)
   locale/@AB_CD@/browser/aboutPrivateBrowsing.dtd (%chrome/aboutPrivateBrowsing.dtd)
   locale/@AB_CD@/browser/aboutReader.properties   (%chrome/aboutReader.properties)
 #ifdef MOZ_SERVICES_HEALTHREPORT
   locale/@AB_CD@/browser/aboutHealthReport.dtd    (%chrome/aboutHealthReport.dtd)
 #endif
   locale/@AB_CD@/browser/browser.properties       (%chrome/browser.properties)
   locale/@AB_CD@/browser/config.dtd               (%chrome/config.dtd)
   locale/@AB_CD@/browser/config.properties        (%chrome/config.properties)
--- a/security/manager/ssl/src/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/src/SSLServerCertVerification.cpp
@@ -108,19 +108,19 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Telemetry.h"
 #include "nsIThreadPool.h"
 #include "nsNetUtil.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
-#include "nsIConsoleService.h"
 #include "PSMRunnable.h"
 #include "SharedSSLState.h"
+#include "nsContentUtils.h"
 
 #include "ssl.h"
 #include "secerr.h"
 #include "secport.h"
 #include "sslerr.h"
 #include "ocsp.h"
 
 #ifdef PR_LOGGING
@@ -208,21 +208,17 @@ LogInvalidCertError(TransportSecurityInf
                     PRErrorCode errorCode,
                     ::mozilla::psm::SSLErrorMessageType errorMessageType,
                     nsIX509Cert* ix509)
 {
   nsString message;
   socketInfo->GetErrorLogMessage(errorCode, errorMessageType, message);
   
   if (!message.IsEmpty()) {
-    nsCOMPtr<nsIConsoleService> console;
-    console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-    if (console) {
-      console->LogStringMessage(message.get());
-    }
+    nsContentUtils::LogSimpleConsoleError(message, "SSL");
   }
 }
 
 // Dispatched to the STS thread to notify the infoObject of the verification
 // result.
 //
 // This will cause the PR_Poll in the STS thread to return, so things work
 // correctly even if the STS thread is blocked polling (only) on the file
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -13,17 +13,17 @@
 #include "nsIWebProgressListener.h"
 #include "nsProtectedAuthThread.h"
 #include "nsITokenDialogs.h"
 #include "nsIUploadChannel.h"
 #include "nsIPrompt.h"
 #include "nsProxyRelease.h"
 #include "PSMRunnable.h"
 #include "ScopedNSSTypes.h"
-#include "nsIConsoleService.h"
+#include "nsContentUtils.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsNetUtil.h"
 #include "SharedSSLState.h"
 #include "ssl.h"
 #include "sslproto.h"
 
 using namespace mozilla;
 using namespace mozilla::psm;
@@ -1037,26 +1037,24 @@ void HandshakeCallback(PRFileDesc* fd, v
 
   // XXX Bug 883674: We shouldn't be formatting messages here in PSM; instead,
   // we should set a flag on the channel that higher (UI) level code can check
   // to log the warning. In particular, these warnings should go to the web
   // console instead of to the error console. Also, the warning is not
   // localized.
   if (!siteSupportsSafeRenego &&
       ioLayerHelpers.getWarnLevelMissingRFC5746() > 0) {
-    nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-    if (console) {
-      nsXPIDLCString hostName;
-      infoObject->GetHostName(getter_Copies(hostName));
+    nsXPIDLCString hostName;
+    infoObject->GetHostName(getter_Copies(hostName));
 
-      nsAutoString msg;
-      msg.Append(NS_ConvertASCIItoUTF16(hostName));
-      msg.Append(NS_LITERAL_STRING(" : server does not support RFC 5746, see CVE-2009-3555"));
-      console->LogStringMessage(msg.get());
-    }
+    nsAutoString msg;
+    msg.Append(NS_ConvertASCIItoUTF16(hostName));
+    msg.Append(NS_LITERAL_STRING(" : server does not support RFC 5746, see CVE-2009-3555"));
+
+    nsContentUtils::LogSimpleConsoleError(msg, "SSL");
   }
 
   ScopedCERTCertificate serverCert(SSL_PeerCertificate(fd));
 
   /* Set the SSL Status information */
   RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
   if (!status) {
     status = new nsSSLStatus();
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -32,16 +32,17 @@
 #endif
 
 #include "nsCharSeparatedTokenizer.h"
 #include "nsIConsoleService.h"
 #include "PSMRunnable.h"
 #include "ScopedNSSTypes.h"
 #include "SharedSSLState.h"
 #include "mozilla/Preferences.h"
+#include "nsContentUtils.h"
 
 #include "ssl.h"
 #include "secerr.h"
 #include "sslerr.h"
 #include "secder.h"
 #include "keyhi.h"
 
 using namespace mozilla;
@@ -663,21 +664,17 @@ nsHandleSSLError(nsNSSSocketInfo *socket
   }
   
   // We must cancel first, which sets the error code.
   socketInfo->SetCanceled(err, PlainErrorMessage);
   nsXPIDLString errorString;
   socketInfo->GetErrorLogMessage(err, errtype, errorString);
   
   if (!errorString.IsEmpty()) {
-    nsCOMPtr<nsIConsoleService> console;
-    console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-    if (console) {
-      console->LogStringMessage(errorString.get());
-    }
+    nsContentUtils::LogSimpleConsoleError(errorString, "SSL");
   }
 }
 
 namespace {
 
 enum Operation { reading, writing, not_reading_or_writing };
 
 int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
--- a/testing/crashtest/crashtests.list
+++ b/testing/crashtest/crashtests.list
@@ -1,13 +1,15 @@
 # Add your lines including crashtest manifests below here.
 # DO NOT ADD CRASHTESTS INDIVIDUALLY HERE!
 
 include ../../testing/crashtest/sanity/crashtests.list
 
+include ../../accessible/tests/crashtests/crashtests.list
+
 include ../../content/base/crashtests/crashtests.list
 include ../../content/canvas/crashtests/crashtests.list
 include ../../content/events/crashtests/crashtests.list
 include ../../content/html/document/crashtests/crashtests.list
 include ../../content/html/content/crashtests/crashtests.list
 include ../../content/smil/crashtests/crashtests.list
 include ../../content/svg/content/src/crashtests/crashtests.list
 include ../../content/xml/content/crashtest/crashtests.list
--- a/toolkit/components/jsdownloads/src/DownloadCore.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadCore.jsm
@@ -333,18 +333,18 @@ Download.prototype = {
     // caller to wait for the current attempt to finish.
     if (this._currentAttempt) {
       return this._currentAttempt;
     }
 
     // While shutting down or disposing of this object, we prevent the download
     // from returning to be in progress.
     if (this._finalized) {
-      return Promise.reject(new DownloadError(Cr.NS_ERROR_FAILURE,
-                                "Cannot start after finalization."));
+      return Promise.reject(new DownloadError({
+                                message: "Cannot start after finalization."}));
     }
 
     // Initialize all the status properties for a new or restarted download.
     this.stopped = false;
     this.canceled = false;
     this.error = null;
     this.hasProgress = false;
     this.progress = 0;
@@ -403,39 +403,45 @@ Download.prototype = {
         try {
           yield this._promiseRemovePartialData;
         } catch (ex) {
           // Ignore any errors, which are already reported by the original
           // caller of the removePartialData method.
         }
       }
 
-      // Disallow download if parental controls service restricts it.
-      if (yield DownloadIntegration.shouldBlockForParentalControls(this)) {
-        let error = new DownloadError(Cr.NS_ERROR_FAILURE, "Download blocked.");
-        error.becauseBlocked = true;
-        error.becauseBlockedByParentalControls = true;
-        throw error;
-      }
+      try {
+        // Disallow download if parental controls service restricts it.
+        if (yield DownloadIntegration.shouldBlockForParentalControls(this)) {
+          throw new DownloadError({ becauseBlockedByParentalControls: true });
+        }
 
-      try {
         // Execute the actual download through the saver object.
         yield this.saver.execute(DS_setProgressBytes.bind(this),
                                  DS_setProperties.bind(this));
 
         // Update the status properties for a successful download.
         this.progress = 100;
         this.succeeded = true;
         this.hasPartialData = false;
       } catch (ex) {
         // Fail with a generic status code on cancellation, so that the caller
         // is forced to actually check the status properties to see if the
         // download was canceled or failed because of other reasons.
         if (this._promiseCanceled) {
-          throw new DownloadError(Cr.NS_ERROR_FAILURE, "Download canceled.");
+          throw new DownloadError({ message: "Download canceled." });
+        }
+
+        // An HTTP 450 error code is used by Windows to indicate that a uri is
+        // blocked by parental controls. This will prevent the download from
+        // occuring, so an error needs to be raised. This is not performed
+        // during the parental controls check above as it requires the request
+        // to start.
+        if (this._blockedByParentalControls) {
+          ex = new DownloadError({ becauseBlockedByParentalControls: true });
         }
 
         // Update the download error, unless a new attempt already started. The
         // change in the status property is notified in the finally block.
         if (this._currentAttempt == currentAttempt || !this._currentAttempt) {
           this.error = ex;
         }
         throw ex;
@@ -470,17 +476,17 @@ Download.prototype = {
             }
           }
         }
       }
     }.bind(this)));
 
     // Notify the new download state before returning.
     this._notifyChange();
-    return this._currentAttempt;
+    return currentAttempt;
   },
 
   /*
    * Launches the file after download has completed. This can open
    * the file with the default application for the target MIME type
    * or file extension, or with a custom application if launcherPath
    * is set.
    *
@@ -1147,47 +1153,72 @@ DownloadTarget.fromSerializable = functi
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadError
 
 /**
  * Provides detailed information about a download failure.
  *
- * @param aResult
- *        The result code associated with the error.
- * @param aMessage
- *        The message to be displayed, or null to use the message associated
- *        with the result code.
- * @param aInferCause
- *        If true, attempts to determine if the cause of the download is a
- *        network failure or a local file failure, based on a set of known
- *        values of the result code.  This is useful when the error is received
- *        by a component that handles both aspects of the download.
+ * @param aProperties
+ *        Object which may contain any of the following properties:
+ *          {
+ *            result: Result error code, defaulting to Cr.NS_ERROR_FAILURE
+ *            message: String error message to be displayed, or null to use the
+ *                     message associated with the result code.
+ *            inferCause: If true, attempts to determine if the cause of the
+ *                        download is a network failure or a local file failure,
+ *                        based on a set of known values of the result code.
+ *                        This is useful when the error is received by a
+ *                        component that handles both aspects of the download.
+ *          }
+ *        The properties object may also contain any of the DownloadError's
+ *        because properties, which will be set accordingly in the error object.
  */
-function DownloadError(aResult, aMessage, aInferCause)
+function DownloadError(aProperties)
 {
   const NS_ERROR_MODULE_BASE_OFFSET = 0x45;
   const NS_ERROR_MODULE_NETWORK = 6;
   const NS_ERROR_MODULE_FILES = 13;
 
   // Set the error name used by the Error object prototype first.
   this.name = "DownloadError";
-  this.result = aResult || Cr.NS_ERROR_FAILURE;
-  if (aMessage) {
-    this.message = aMessage;
+  this.result = aProperties.result || Cr.NS_ERROR_FAILURE;
+  if (aProperties.message) {
+    this.message = aProperties.message;
+  } else if (aProperties.becauseBlocked ||
+             aProperties.becauseBlockedByParentalControls) {
+    this.message = "Download blocked.";
   } else {
     let exception = new Components.Exception("", this.result);
     this.message = exception.toString();
   }
-  if (aInferCause) {
-    let module = ((aResult & 0x7FFF0000) >> 16) - NS_ERROR_MODULE_BASE_OFFSET;
+  if (aProperties.inferCause) {
+    let module = ((this.result & 0x7FFF0000) >> 16) -
+                 NS_ERROR_MODULE_BASE_OFFSET;
     this.becauseSourceFailed = (module == NS_ERROR_MODULE_NETWORK);
     this.becauseTargetFailed = (module == NS_ERROR_MODULE_FILES);
   }
+  else {
+    if (aProperties.becauseSourceFailed) {
+      this.becauseSourceFailed = true;
+    }
+    if (aProperties.becauseTargetFailed) {
+      this.becauseTargetFailed = true;
+    }
+  }
+
+  if (aProperties.becauseBlockedByParentalControls) {
+    this.becauseBlocked = true;
+    this.becauseBlockedByParentalControls = true;
+  }
+  else if (aProperties.becauseBlocked) {
+    this.becauseBlocked = true;
+  }
+
   this.stack = new Error().stack;
 }
 
 DownloadError.prototype = {
   __proto__: Error.prototype,
 
   /**
    * The result code associated with this error.
@@ -1305,16 +1336,41 @@ DownloadSaver.prototype = {
     // The start time is always available when we reach this point.
     let startPRTime = this.download.startTime.getTime() * 1000;
 
     gDownloadHistory.addDownload(sourceUri, referrerUri, startPRTime,
                                  targetUri);
   },
 
   /**
+   * Return true if the request's response has been blocked by Windows parental
+   * controls with an HTTP 450 error code.
+   *
+   * @param aRequest
+   *        nsIRequest object
+   * @return True if the response is blocked.
+   */
+  isResponseParentalBlocked: function(aRequest)
+  {
+    // If the HTTP status is 450, then Windows Parental Controls have
+    // blocked this download.
+    if (aRequest instanceof Ci.nsIHttpChannel &&
+        aRequest.responseStatus == 450) {
+      // Cancel the request, but set a flag on the download that can be
+      // retrieved later when handling the cancellation so that the proper
+      // blocked by parental controls error can be thrown.
+      this.download._blockedByParentalControls = true;
+      aRequest.cancel(Cr.NS_BINDING_ABORTED);
+      return true;
+    }
+
+    return false;
+  },
+
+  /**
    * Returns a static representation of the current object state.
    *
    * @return A JavaScript object that can be serialized to JSON.
    */
   toSerializable: function ()
   {
     throw new Error("Not implemented.");
   },
@@ -1415,28 +1471,28 @@ DownloadCopySaver.prototype = {
       try {
         // If the file already exists, don't delete its contents yet.
         let file = yield OS.File.open(targetPath, { write: true });
         yield file.close();
       } catch (ex if ex instanceof OS.File.Error) {
         // Throw a DownloadError indicating that the operation failed because of
         // the target file.  We cannot translate this into a specific result
         // code, but we preserve the original message using the toString method.
-        let error = new DownloadError(Cr.NS_ERROR_FAILURE, ex.toString());
+        let error = new DownloadError({ message: ex.toString() });
         error.becauseTargetFailed = true;
         throw error;
       }
 
       try {
         let deferSaveComplete = Promise.defer();
 
         if (this._canceled) {
           // Don't create the BackgroundFileSaver object if we have been
           // canceled meanwhile.
-          throw new DownloadError(Cr.NS_ERROR_FAILURE, "Saver canceled.");
+          throw new DownloadError({ message: "Saver canceled." });
         }
 
         // Create the object that will save the file in a background thread.
         let backgroundFileSaver = new BackgroundFileSaverStreamListener();
         try {
           // When the operation completes, reflect the status in the promise
           // returned by this download execution function.
           backgroundFileSaver.observer = {
@@ -1448,18 +1504,18 @@ DownloadCopySaver.prototype = {
               this._backgroundFileSaver = null;
 
               // Send notifications now that we can restart if needed.
               if (Components.isSuccessCode(aStatus)) {
                 deferSaveComplete.resolve();
               } else {
                 // Infer the origin of the error from the failure code, because
                 // BackgroundFileSaver does not provide more specific data.
-                deferSaveComplete.reject(new DownloadError(aStatus, null,
-                                                           true));
+                let properties = { result: aStatus, inferCause: true };
+                deferSaveComplete.reject(new DownloadError(properties));
               }
             },
           };
 
           // Create a channel from the source, and listen to progress
           // notifications.
           let channel = NetUtil.newChannel(NetUtil.newURI(download.source.url));
           if (channel instanceof Ci.nsIPrivateBrowsingChannel) {
@@ -1501,16 +1557,20 @@ DownloadCopySaver.prototype = {
           };
 
           // Open the channel, directing output to the background file saver.
           backgroundFileSaver.QueryInterface(Ci.nsIStreamListener);
           channel.asyncOpen({
             onStartRequest: function (aRequest, aContext) {
               backgroundFileSaver.onStartRequest(aRequest, aContext);
 
+              if (this.isResponseParentalBlocked(aRequest)) {
+                return;
+              }
+
               aSetPropertiesFn({ contentType: channel.contentType });
 
               // Ensure we report the value of "Content-Length", if available,
               // even if the download doesn't generate any progress events
               // later.
               if (channel.contentLength >= 0) {
                 aSetProgressBytesFn(0, channel.contentLength);
               }
@@ -1772,16 +1832,20 @@ DownloadLegacySaver.prototype = {
         aRequest instanceof Ci.nsIResumableChannel) {
       try {
         // If reading the ID succeeds, the source is resumable.
         this.entityID = aRequest.entityID;
       } catch (ex if ex instanceof Components.Exception &&
                      ex.result == Cr.NS_ERROR_NOT_RESUMABLE) { }
     }
 
+    if (this.isResponseParentalBlocked(aRequest)) {
+      return;
+    }
+
     // For legacy downloads, we must update the referrer at this time.
     if (aRequest instanceof Ci.nsIHttpChannel && aRequest.referrer) {
       this.download.source.referrer = aRequest.referrer.spec;
     }
 
     if (!aAlreadyAddedToHistory) {
       this.addToHistory();
     }
@@ -1800,17 +1864,18 @@ DownloadLegacySaver.prototype = {
     // Store a reference to the request, used when handling completion.
     this.request = aRequest;
 
     if (Components.isSuccessCode(aStatus)) {
       this.deferExecuted.resolve();
     } else {
       // Infer the origin of the error from the failure code, because more
       // specific data is not available through the nsITransfer implementation.
-      this.deferExecuted.reject(new DownloadError(aStatus, null, true));
+      let properties = { result: aStatus, inferCause: true };
+      this.deferExecuted.reject(new DownloadError(properties));
     }
   },
 
   /**
    * When the first execution of the download finished, it can be restarted by
    * using a DownloadCopySaver object instead of the original legacy component
    * that executed the download.
    */
--- a/toolkit/components/jsdownloads/test/unit/common_test_Download.js
+++ b/toolkit/components/jsdownloads/test/unit/common_test_Download.js
@@ -1350,25 +1350,52 @@ add_task(function test_blocked_parental_
       // the "error" property checked by promiseDownloadStopped.  This happens
       // because we don't have control over when the download is started.
       download = yield promiseStartLegacyDownload();
       yield promiseDownloadStopped(download);
     }
     do_throw("The download should have blocked.");
   } catch (ex if ex instanceof Downloads.Error && ex.becauseBlocked) {
     do_check_true(ex.becauseBlockedByParentalControls);
+    do_check_true(download.error.becauseBlockedByParentalControls);
   }
 
   // Now that the download stopped, the target file should not exist.
   do_check_false(yield OS.File.exists(download.target.path));
 
   cleanup();
 });
 
 /**
+ * Test a download that will be blocked by Windows parental controls by
+ * resulting in an HTTP status code of 450.
+ */
+add_task(function test_blocked_parental_controls_httpstatus450()
+{
+  let download;
+  try {
+    if (!gUseLegacySaver) {
+      download = yield promiseNewDownload(httpUrl("parentalblocked.zip"));
+      yield download.start();
+    }
+    else {
+      download = yield promiseStartLegacyDownload(httpUrl("parentalblocked.zip"));
+      yield promiseDownloadStopped(download);
+    }
+    do_throw("The download should have blocked.");
+  } catch (ex if ex instanceof Downloads.Error && ex.becauseBlocked) {
+    do_check_true(ex.becauseBlockedByParentalControls);
+    do_check_true(download.error.becauseBlockedByParentalControls);
+    do_check_true(download.stopped);
+  }
+
+  do_check_false(yield OS.File.exists(download.target.path));
+});
+
+/**
  * download.showContainingDirectory() action
  */
 add_task(function test_showContainingDirectory() {
   DownloadIntegration._deferTestShowDir = Promise.defer();
 
   let targetPath = getTempFile(TEST_TARGET_FILE_NAME).path;
 
   let download = yield Downloads.createDownload({
--- a/toolkit/components/jsdownloads/test/unit/head.js
+++ b/toolkit/components/jsdownloads/test/unit/head.js
@@ -768,16 +768,23 @@ add_task(function test_common_initialize
       bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED_FIRST,
                          TEST_DATA_SHORT_GZIP_ENCODED_FIRST.length);
     }, function secondPart(aRequest, aResponse) {
       let bos =  new BinaryOutputStream(aResponse.bodyOutputStream);
       bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED_SECOND,
                          TEST_DATA_SHORT_GZIP_ENCODED_SECOND.length);
     });
 
+  // This URL will emulate being blocked by Windows Parental controls
+  gHttpServer.registerPathHandler("/parentalblocked.zip",
+    function (aRequest, aResponse) {
+      aResponse.setStatusLine(aRequest.httpVersion, 450,
+                              "Blocked by Windows Parental Controls");
+    });
+
   // Disable integration with the host application requiring profile access.
   DownloadIntegration.dontLoadList = true;
   DownloadIntegration.dontLoadObservers = true;
   // Disable the parental controls checking.
   DownloadIntegration.dontCheckParentalControls = true;
   // Disable the calls to the OS to launch files and open containing folders
   DownloadIntegration.dontOpenFileAndFolder = true;
   DownloadIntegration._deferTestOpenFile = Promise.defer();
--- a/toolkit/components/jsdownloads/test/unit/test_DownloadCore.js
+++ b/toolkit/components/jsdownloads/test/unit/test_DownloadCore.js
@@ -4,21 +4,92 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests the main download interfaces using DownloadCopySaver.
  */
 
 "use strict";
 
+XPCOMUtils.defineLazyModuleGetter(this, "DownloadError",
+                                  "resource://gre/modules/DownloadCore.jsm");
+
 ////////////////////////////////////////////////////////////////////////////////
 //// Execution of common tests
 
 let gUseLegacySaver = false;
 
 let scriptFile = do_get_file("common_test_Download.js");
 Services.scriptloader.loadSubScript(NetUtil.newURI(scriptFile).spec);
 
 ////////////////////////////////////////////////////////////////////////////////
+//// Tests
+
+/**
+ * Tests the DownloadError object.
+ */
+add_task(function test_DownloadError()
+{
+  let error = new DownloadError({ result: Cr.NS_ERROR_NOT_RESUMABLE,
+                                  message: "Not resumable."});
+  do_check_eq(error.result, Cr.NS_ERROR_NOT_RESUMABLE);
+  do_check_eq(error.message, "Not resumable.");
+  do_check_false(error.becauseSourceFailed);
+  do_check_false(error.becauseTargetFailed);
+  do_check_false(error.becauseBlocked);
+  do_check_false(error.becauseBlockedByParentalControls);
+
+  error = new DownloadError({ message: "Unknown error."});
+  do_check_eq(error.result, Cr.NS_ERROR_FAILURE);
+  do_check_eq(error.message, "Unknown error.");
+
+  error = new DownloadError({ result: Cr.NS_ERROR_NOT_RESUMABLE });
+  do_check_eq(error.result, Cr.NS_ERROR_NOT_RESUMABLE);
+  do_check_true(error.message.indexOf("Exception") > 0);
+
+  // becauseSourceFailed will be set, but not the unknown property.
+  error = new DownloadError({ message: "Unknown error.",
+                              becauseSourceFailed: true,
+                              becauseUnknown: true });
+  do_check_true(error.becauseSourceFailed);
+  do_check_false("becauseUnknown" in error);
+
+  error = new DownloadError({ result: Cr.NS_ERROR_MALFORMED_URI,
+                              inferCause: true });
+  do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI);
+  do_check_true(error.becauseSourceFailed);
+  do_check_false(error.becauseTargetFailed);
+  do_check_false(error.becauseBlocked);
+  do_check_false(error.becauseBlockedByParentalControls);
+
+  // This test does not set inferCause, so becauseSourceFailed will not be set.
+  error = new DownloadError({ result: Cr.NS_ERROR_MALFORMED_URI });
+  do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI);
+  do_check_false(error.becauseSourceFailed);
+
+  error = new DownloadError({ result: Cr.NS_ERROR_FILE_INVALID_PATH,
+                              inferCause: true });
+  do_check_eq(error.result, Cr.NS_ERROR_FILE_INVALID_PATH);
+  do_check_false(error.becauseSourceFailed);
+  do_check_true(error.becauseTargetFailed);
+  do_check_false(error.becauseBlocked);
+  do_check_false(error.becauseBlockedByParentalControls);
+
+  error = new DownloadError({ becauseBlocked: true });
+  do_check_eq(error.message, "Download blocked.");
+  do_check_false(error.becauseSourceFailed);
+  do_check_false(error.becauseTargetFailed);
+  do_check_true(error.becauseBlocked);
+  do_check_false(error.becauseBlockedByParentalControls);
+
+  error = new DownloadError({ becauseBlockedByParentalControls: true });
+  do_check_eq(error.message, "Download blocked.");
+  do_check_false(error.becauseSourceFailed);
+  do_check_false(error.becauseTargetFailed);
+  do_check_true(error.becauseBlocked);
+  do_check_true(error.becauseBlockedByParentalControls);
+});
+
+////////////////////////////////////////////////////////////////////////////////
 //// Termination
 
 let tailFile = do_get_file("tail.js");
 Services.scriptloader.loadSubScript(NetUtil.newURI(tailFile).spec);
--- a/toolkit/devtools/server/actors/inspector.js
+++ b/toolkit/devtools/server/actors/inspector.js
@@ -929,17 +929,16 @@ var WalkerActor = protocol.ActorClass({
 
     if (!node ||
         !node.rawNode ||
          node.rawNode.nodeType !== Ci.nsIDOMNode.ELEMENT_NODE) {
       return;
     }
 
     this._installHelperSheet(node);
-    this.layoutHelpers.scrollIntoViewIfNeeded(node.rawNode);
     DOMUtils.addPseudoClassLock(node.rawNode, HIGHLIGHTED_PSEUDO_CLASS);
     this._highlightTimeout = setTimeout(this._unhighlight.bind(this), HIGHLIGHTED_TIMEOUT);
 
   }, { request: { node: Arg(0, "nullable:domnode") }}),
 
   /**
    * Watch the given document node for mutations using the DOM observer
    * API.
--- a/toolkit/themes/linux/global/toolbar.css
+++ b/toolkit/themes/linux/global/toolbar.css
@@ -51,17 +51,17 @@ toolbarseparator {
 
 toolbarspacer {
   width: 15px;
 }
 
 /* ::::: toolbarpaletteitem ::::: */
 
 toolbarpaletteitem {
-  cursor: -moz-grab;
+  cursor: grab;
 }
 
 .toolbarpaletteitem-box[type="spacer"],
 .toolbarpaletteitem-box[type="spring"] {
   border: 1px solid #808080;
   background-color: #FFF !important;
 }
 
--- a/toolkit/themes/os2/global/toolbar.css
+++ b/toolkit/themes/os2/global/toolbar.css
@@ -69,17 +69,17 @@ toolbarseparator {
 
 toolbarspacer {
   width: 15px;
 }
 
 /* ::::: toolbarpaletteitem ::::: */
 
 toolbarpaletteitem {
-  cursor: -moz-grab;
+  cursor: grab;
 }
 
 .toolbarpaletteitem-box[type="spacer"],
 .toolbarpaletteitem-box[type="spring"] {
   border: 1px solid #808080;
   background-color: #FFF !important;
 }
 
--- a/toolkit/themes/osx/global/toolbar.css
+++ b/toolkit/themes/osx/global/toolbar.css
@@ -36,17 +36,17 @@ toolbarseparator {
   background: url("chrome://global/skin/toolbar/toolbar-separator.png") transparent repeat-y;
   padding: 0;
   width: 1px !important;
 }
 
 /* ::::: toolbarpaletteitem ::::: */
 
 toolbarpaletteitem {
-  cursor: -moz-grab;
+  cursor: grab;
 }
 
 toolbar[iconsize="small"] toolbarpaletteitem[type="spacer"] {
   min-width: 24px !important;
 }
 
 toolbarpaletteitem[type="spacer"] {
   min-width: 32px !important;
--- a/toolkit/themes/windows/global/toolbar.css
+++ b/toolkit/themes/windows/global/toolbar.css
@@ -60,17 +60,17 @@ toolbarseparator {
 
 toolbarspacer {
   width: 15px;
 }
 
 /* ::::: toolbarpaletteitem ::::: */
 
 toolbarpaletteitem {
-  cursor: -moz-grab;
+  cursor: grab;
 }
 
 .toolbarpaletteitem-box[type="spacer"],
 .toolbarpaletteitem-box[type="spring"] {
   border: 1px solid #808080;
   background-color: #FFF !important;
 }