Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 02 Oct 2012 21:20:48 -0400
changeset 108985 635fcc11d2b16265114d6bbc02768d007f73d66b
parent 108984 e679d2e1d02ddfbca75aa1296bac9316b8ed1e19 (current diff)
parent 108949 fb1751609d90b58c881c080f0d3ffe4141f19a75 (diff)
child 108986 4d5e812682389945e07e5a4bc40a1d695cba6d61
push id15793
push userryanvm@gmail.com
push dateWed, 03 Oct 2012 02:09:02 +0000
treeherdermozilla-inbound@24b61485c945 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone18.0a1
first release with
nightly linux32
635fcc11d2b1 / 18.0a1 / 20121003030545 / files
nightly linux64
635fcc11d2b1 / 18.0a1 / 20121003030545 / files
nightly mac
635fcc11d2b1 / 18.0a1 / 20121003030545 / files
nightly win32
635fcc11d2b1 / 18.0a1 / 20121003030545 / files
nightly win64
635fcc11d2b1 / 18.0a1 / 20121003030545 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge the last PGO-green inbound changeset to m-c.
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -47,30 +47,31 @@ ifdef MOZ_XUL
 CPPSRCS += \
   XULListboxAccessibleWrap.cpp \
   XULMenuAccessibleWrap.cpp \
   XULTreeGridAccessibleWrap.cpp \
   $(NULL)
 endif
 
 EXPORTS = \
-  				CAccessibleValue.h \
-  				ia2AccessibleAction.h \
-  				ia2AccessibleComponent.h \
-  				ia2AccessibleEditableText.h \
-  				ia2AccessibleHyperlink.h \
-  				ia2AccessibleHypertext.h \
-  				ia2AccessibleText.h \
+  CAccessibleValue.h \
+  ia2AccessibleAction.h \
+  ia2AccessibleComponent.h \
+  ia2AccessibleEditableText.h \
+  ia2AccessibleHyperlink.h \
+  ia2AccessibleHypertext.h \
+  ia2AccessibleText.h \
   nsAccessNodeWrap.h \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/a11y \
 
 EXPORTS_mozilla/a11y = \
   AccessibleWrap.h \
+  Compatibility.h \
   HyperTextAccessibleWrap.h \
   $(null)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -445,18 +445,18 @@ pref("marionette.defaultPrefs.port", 282
 #endif
 
 #ifdef MOZ_UPDATER
 // When we're applying updates, we can't let anything hang us on
 // quit+restart.  The user has no recourse.
 pref("shutdown.watchdog.timeoutSecs", 5);
 // Timeout before the update prompt automatically installs the update
 pref("b2g.update.apply-prompt-timeout", 60000); // milliseconds
-// Optional timeout the user can wait before getting another update prompt
-pref("b2g.update.apply-wait-timeout", 1800000); // milliseconds
+// Amount of time to wait after the user is idle before prompting to apply an update
+pref("b2g.update.apply-idle-timeout", 600000); // milliseconds
 // Amount of time the updater waits for the process to exit cleanly before
 // forcefully exiting the process
 pref("b2g.update.self-destruct-timeout", 5000); // milliseconds
 
 pref("app.update.enabled", true);
 pref("app.update.auto", false);
 pref("app.update.silent", false);
 pref("app.update.mode", 0);
@@ -538,19 +538,19 @@ pref("hal.processPriorityManager.gonk.fo
 pref("hal.processPriorityManager.gonk.backgroundOomScoreAdjust", 400);
 pref("hal.processPriorityManager.gonk.masterNice", -1);
 pref("hal.processPriorityManager.gonk.foregroundNice", 0);
 pref("hal.processPriorityManager.gonk.backgroundNice", 10);
 
 #ifndef DEBUG
 // Enable pre-launching content processes for improved startup time
 // (hiding latency).
-pref("dom.ipc.processPrelauch.enabled", true);
+pref("dom.ipc.processPrelaunch.enabled", true);
 // Wait this long before pre-launching a new subprocess.
-pref("dom.ipc.processPrelauch.delayMs", 1000);
+pref("dom.ipc.processPrelaunch.delayMs", 1000);
 #endif
 
 // Ignore the "dialog=1" feature in window.open.
 pref("dom.disable_window_open_dialog_feature", true);
 
 // Screen reader support
 pref("accessibility.accessfu.activate", 2);
 
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -15,36 +15,43 @@ Cu.import("resource://gre/modules/Servic
 const VERBOSE = 1;
 let log =
   VERBOSE ?
   function log_dump(msg) { dump("UpdatePrompt: "+ msg +"\n"); } :
   function log_noop(msg) { };
 
 const APPLY_PROMPT_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.apply-prompt-timeout");
-const APPLY_WAIT_TIMEOUT =
-      Services.prefs.getIntPref("b2g.update.apply-wait-timeout");
+const APPLY_IDLE_TIMEOUT =
+      Services.prefs.getIntPref("b2g.update.apply-idle-timeout");
 const SELF_DESTRUCT_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.self-destruct-timeout");
 
+const APPLY_IDLE_TIMEOUT_SECONDS = APPLY_IDLE_TIMEOUT / 1000;
+
+
 XPCOMUtils.defineLazyServiceGetter(Services, "aus",
                                    "@mozilla.org/updates/update-service;1",
                                    "nsIApplicationUpdateService");
 
+XPCOMUtils.defineLazyServiceGetter(Services, "idle",
+                                   "@mozilla.org/widget/idleservice;1",
+                                   "nsIIdleService");
 function UpdatePrompt() { }
 
 UpdatePrompt.prototype = {
   classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
                                          Ci.nsIRequestObserver,
-                                         Ci.nsIProgressEventSink]),
+                                         Ci.nsIProgressEventSink,
+                                         Ci.nsIObserver]),
 
   _update: null,
   _applyPromptTimer: null,
-  _applyWaitTimer: null,
+  _waitingForIdle: false,
 
   // nsIUpdatePrompt
 
   // FIXME/bug 737601: we should have users opt-in to downloading
   // updates when on a billed pipe.  Initially, opt-in for 3g, but
   // that doesn't cover all cases.
   checkForUpdates: function UP_checkForUpdates() { },
 
@@ -53,37 +60,70 @@ UpdatePrompt.prototype = {
                              this.handleAvailableResult)) {
 
       log("Unable to prompt for available update, forcing download");
       this.downloadUpdate(aUpdate);
     }
   },
 
   showUpdateDownloaded: function UP_showUpdateDownloaded(aUpdate, aBackground) {
-    if (!this.sendUpdateEvent("update-downloaded", aUpdate,
-                             this.handleDownloadedResult)) {
-      log("Unable to prompt, forcing restart");
-      this.restartProcess();
+    // The update has been downloaded and staged. We send the update-downloaded
+    // event right away. After the user has been idle for a while, we send the
+    // update-prompt-restart event, increasing the chances that we can apply the
+    // update quietly without user intervention.
+    this.sendUpdateEvent("update-downloaded", aUpdate);
+
+    if (Services.idle.idleTime >= APPLY_IDLE_TIMEOUT) {
+      this.showApplyPrompt(aUpdate);
       return;
     }
 
-    // Schedule a fallback timeout in case the UI is unable to respond or show
-    // a prompt for some reason
-    this._applyPromptTimer = this.createTimer(APPLY_PROMPT_TIMEOUT);
+    // We haven't been idle long enough, so register an observer
+    log("Update is ready to apply, registering idle timeout of " +
+        APPLY_IDLE_TIMEOUT_SECONDS + " seconds before prompting.");
+
+    this._update = aUpdate;
+    this.waitForIdle();
   },
 
   showUpdateError: function UP_showUpdateError(aUpdate) {
     if (aUpdate.state == "failed") {
       log("Failed to download update, errorCode: " + aUpdate.errorCode);
     }
   },
 
   showUpdateHistory: function UP_showUpdateHistory(aParent) { },
   showUpdateInstalled: function UP_showUpdateInstalled() { },
 
+  // Custom functions
+
+  waitForIdle: function UP_waitForIdle() {
+    if (this._waitingForIdle) {
+      return;
+    }
+
+    this._waitingForIdle = true;
+    Services.idle.addIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
+    Services.obs.addObserver(this, "quit-application", false);
+  },
+
+
+  showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
+    if (!this.sendUpdateEvent("update-prompt-apply", aUpdate,
+                             this.handleApplyPromptResult)) {
+      log("Unable to prompt, forcing restart");
+      this.restartProcess();
+      return;
+    }
+
+    // Schedule a fallback timeout in case the UI is unable to respond or show
+    // a prompt for some reason.
+    this._applyPromptTimer = this.createTimer(APPLY_PROMPT_TIMEOUT);
+  },
+
   sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate, aCallback) {
     let detail = {
       displayVersion: aUpdate.displayVersion,
       detailsURL: aUpdate.detailsURL
     };
 
     let patch = aUpdate.selectedPatch;
     if (!patch) {
@@ -150,27 +190,26 @@ UpdatePrompt.prototype = {
     // showUpdateAvailable again after a certain period of time
     switch (aDetail.result) {
       case "download":
         this.downloadUpdate(this._update);
         break;
     }
   },
 
-  handleDownloadedResult: function UP_handleDownloadedResult(aDetail) {
+  handleApplyPromptResult: function UP_handleApplyPromptResult(aDetail) {
     if (this._applyPromptTimer) {
       this._applyPromptTimer.cancel();
       this._applyPromptTimer = null;
     }
 
     switch (aDetail.result) {
       case "wait":
-        // Wait for a fixed period of time, allowing the user to temporarily
-        // postpone applying an update
-        this._applyWaitTimer = this.createTimer(APPLY_WAIT_TIMEOUT);
+        // Wait until the user is idle before prompting to apply the update
+        this.waitForIdle();
         break;
       case "restart":
         this.finishUpdate();
         break;
     }
   },
 
   downloadUpdate: function UP_downloadUpdate(aUpdate) {
@@ -231,24 +270,36 @@ UpdatePrompt.prototype = {
     try {
       recoveryService.installFotaUpdate(aOsUpdatePath);
     } catch(e) {
       log("Error: Couldn't reboot into recovery to apply FOTA update " +
           aOsUpdatePath);
     }
   },
 
+  // nsIObserver
+
+  observe: function UP_observe(aSubject, aTopic, aData) {
+    switch (aTopic) {
+      case "idle":
+        this._waitingForIdle = false;
+        this.showApplyPrompt(this._update);
+        // Fall through
+      case "quit-application":
+        Services.idle.removeIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
+        Services.obs.removeObserver(this, "quit-application");
+        break;
+    }
+  },
+
   notify: function UP_notify(aTimer) {
     if (aTimer == this._applyPromptTimer) {
       log("Timed out waiting for result, restarting");
       this._applyPromptTimer = null;
       this.finishUpdate();
-    } else if (aTimer == this._applyWaitTimer) {
-      this._applyWaitTimer = null;
-      this.showUpdatePrompt();
     }
   },
 
   createTimer: function UP_createTimer(aTimeoutMs) {
     let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     timer.initWithCallback(this, aTimeoutMs, timer.TYPE_ONE_SHOT);
     return timer;
   },
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -2,16 +2,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 function getPluginInfo(pluginElement)
 {
   var tagMimetype;
   var pluginsPage;
+  var pluginName = gNavigatorBundle.getString("pluginInfo.unknownPlugin");
   if (pluginElement instanceof HTMLAppletElement) {
     tagMimetype = "application/x-java-vm";
   } else {
     if (pluginElement instanceof HTMLObjectElement) {
       pluginsPage = pluginElement.getAttribute("codebase");
     } else {
       pluginsPage = pluginElement.getAttribute("pluginspage");
     }
@@ -30,37 +31,50 @@ function getPluginInfo(pluginElement)
     tagMimetype = pluginElement.QueryInterface(Components.interfaces.nsIObjectLoadingContent)
                                .actualType;
 
     if (tagMimetype == "") {
       tagMimetype = pluginElement.type;
     }
   }
 
-  return {mimetype: tagMimetype, pluginsPage: pluginsPage};
+  if (tagMimetype) {
+    let navMimeType = navigator.mimeTypes[tagMimetype];
+    if (navMimeType && navMimeType.enabledPlugin) {
+      pluginName = navMimeType.enabledPlugin.name;
+      pluginName = gPluginHandler.makeNicePluginName(pluginName);
+    }
+  }
+
+  return { mimetype: tagMimetype,
+           pluginsPage: pluginsPage,
+           pluginName: pluginName };
 }
 
 var gPluginHandler = {
 
 #ifdef MOZ_CRASHREPORTER
   get CrashSubmit() {
     delete this.CrashSubmit;
     Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
     return this.CrashSubmit;
   },
 #endif
 
   // Map the plugin's name to a filtered version more suitable for user UI.
-  makeNicePluginName : function (aName, aFilename) {
+  makeNicePluginName : function (aName) {
     if (aName == "Shockwave Flash")
       return "Adobe Flash";
 
     // Clean up the plugin name by stripping off any trailing version numbers
     // or "plugin". EG, "Foo Bar Plugin 1.23_02" --> "Foo Bar"
-    let newName = aName.replace(/\bplug-?in\b/i, "").replace(/[\s\d\.\-\_\(\)]+$/, "");
+    // Do this by first stripping the numbers, etc. off the end, and then
+    // removing "Plugin" (and then trimming to get rid of any whitespace).
+    // (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled)
+    let newName = aName.replace(/[\s\d\.\-\_\(\)]+$/, "").replace(/\bplug-?in\b/i, "").trim();
     return newName;
   },
 
   isTooSmall : function (plugin, overlay) {
     // Is the <object>'s size too small to hold what we want to show?
     let pluginRect = plugin.getBoundingClientRect();
     // XXX bug 446693. The text-shadow on the submitted-report text at
     //     the bottom causes scrollHeight to be larger than it should be.
@@ -143,16 +157,27 @@ var gPluginHandler = {
       case "PluginVulnerableUpdatable":
         let updateLink = doc.getAnonymousElementByAttribute(plugin, "class", "checkForUpdatesLink");
         self.addLinkClickCallback(updateLink, "openPluginUpdatePage");
         /* FALLTHRU */
 
       case "PluginVulnerableNoUpdate":
       case "PluginClickToPlay":
         self._handleClickToPlayEvent(plugin);
+        let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
+        let pluginName = getPluginInfo(plugin).pluginName;
+        let messageString = gNavigatorBundle.getFormattedString("PluginClickToPlay", [pluginName]);
+        let overlayText = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgClickToPlay");
+        overlayText.textContent = messageString;
+        if (event.type == "PluginVulnerableUpdatable" ||
+            event.type == "PluginVulnerableNoUpdate") {
+          let vulnerabilityString = gNavigatorBundle.getString(event.type);
+          let vulnerabilityText = doc.getAnonymousElementByAttribute(plugin, "anonid", "vulnerabilityStatus");
+          vulnerabilityText.textContent = vulnerabilityString;
+        }
         break;
 
       case "PluginPlayPreview":
         self._handlePlayPreviewEvent(plugin);
         break;
 
       case "PluginDisabled":
         let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink");
@@ -192,26 +217,26 @@ var gPluginHandler = {
 
   activateSinglePlugin: function PH_activateSinglePlugin(aContentWindow, aPlugin) {
     let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
     if (gPluginHandler.canActivatePlugin(objLoadingContent))
       objLoadingContent.playPlugin();
 
     let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindowUtils);
-    let haveUnplayedPlugins = cwu.plugins.some(function(plugin) {
-      let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-      return (plugin != aPlugin && gPluginHandler.canActivatePlugin(objLoadingContent));
-    });
+    let pluginNeedsActivation = gPluginHandler._pluginNeedsActivationExceptThese([aPlugin]);
     let browser = gBrowser.getBrowserForDocument(aContentWindow.document);
     let notification = PopupNotifications.getNotification("click-to-play-plugins", browser);
-    if (notification && !haveUnplayedPlugins) {
+    if (notification) {
       browser._clickToPlayDoorhangerShown = false;
       notification.remove();
     }
+    if (pluginNeedsActivation) {
+      gPluginHandler._showClickToPlayNotification(browser);
+    }
   },
 
   stopPlayPreview: function PH_stopPlayPreview(aPlugin, aPlayPlugin) {
     let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
     if (objLoadingContent.activated)
       return;
 
     if (aPlayPlugin)
@@ -355,37 +380,131 @@ var gPluginHandler = {
       return;
 
     let browser = gBrowser.selectedBrowser;
 
     let pluginsPermission = Services.perms.testPermission(browser.currentURI, "plugins");
     if (pluginsPermission == Ci.nsIPermissionManager.DENY_ACTION)
       return;
 
-    let contentWindow = browser.contentWindow;
+    if (gPluginHandler._pluginNeedsActivationExceptThese([]))
+      gPluginHandler._showClickToPlayNotification(browser);
+  },
+
+  // returns true if there is a plugin on this page that needs activation
+  // and isn't in the "except these" list
+  _pluginNeedsActivationExceptThese: function PH_pluginNeedsActivationExceptThese(aExceptThese) {
+    let contentWindow = gBrowser.selectedBrowser.contentWindow;
     let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindowUtils);
     let pluginNeedsActivation = cwu.plugins.some(function(plugin) {
       let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-      return gPluginHandler.canActivatePlugin(objLoadingContent);
+      return (gPluginHandler.canActivatePlugin(objLoadingContent) &&
+              aExceptThese.indexOf(plugin) < 0);
     });
-    if (pluginNeedsActivation)
-      gPluginHandler._showClickToPlayNotification(browser);
+
+    return pluginNeedsActivation;
+  },
+
+  /* Gets all plugins currently in the page of the given name */
+  _getPluginsByName: function PH_getPluginsByName(aDOMWindowUtils, aName) {
+    let plugins = [];
+    for (let plugin of aDOMWindowUtils.plugins) {
+      let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+      if (gPluginHandler.canActivatePlugin(objLoadingContent)) {
+        let pluginName = getPluginInfo(plugin).pluginName;
+        if (aName == pluginName) {
+          plugins.push(objLoadingContent);
+        }
+      }
+    }
+    return plugins;
   },
 
+  _makeCenterActions: function PH_makeCenterActions(aBrowser) {
+    let contentWindow = aBrowser.contentWindow;
+    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                           .getInterface(Ci.nsIDOMWindowUtils);
+    let pluginsDictionary = {};
+    for (let plugin of cwu.plugins) {
+      let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+      if (gPluginHandler.canActivatePlugin(objLoadingContent)) {
+        let pluginName = getPluginInfo(plugin).pluginName;
+        if (!pluginsDictionary[pluginName]) pluginsDictionary[pluginName] = [];
+        pluginsDictionary[pluginName].push(objLoadingContent);
+      }
+    }
+
+    let centerActions = [];
+    for (let pluginName in pluginsDictionary) {
+      let plugin = pluginsDictionary[pluginName][0];
+      let warn = false;
+      let warningText = "";
+      let updateLink = Services.urlFormatter.formatURLPref("plugins.update.url");
+      if (plugin.pluginFallbackType) {
+        if (plugin.pluginFallbackType ==
+              Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE) {
+          warn = true;
+          warningText = gNavigatorBundle.getString("vulnerableUpdatablePluginWarning");
+        }
+        else if (plugin.pluginFallbackType ==
+                   Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE) {
+          warn = true;
+          warningText = gNavigatorBundle.getString("vulnerableNoUpdatePluginWarning");
+          updateLink = "";
+        }
+      }
+
+      let action = {
+        message: pluginName,
+        warn: warn,
+        warningText: warningText,
+        updateLink: updateLink,
+        label: gNavigatorBundle.getString("activateSinglePlugin"),
+        callback: function() {
+          let plugins = gPluginHandler._getPluginsByName(cwu, this.message);
+          for (let objLoadingContent of plugins) {
+            objLoadingContent.playPlugin();
+          }
+
+          let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
+          if (notification &&
+              !gPluginHandler._pluginNeedsActivationExceptThese(plugins)) {
+            notification.remove();
+          }
+        }
+      };
+      centerActions.push(action);
+    }
+
+    return centerActions;
+   },
+
   _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser) {
     aBrowser._clickToPlayDoorhangerShown = true;
     let contentWindow = aBrowser.contentWindow;
 
     let messageString = gNavigatorBundle.getString("activatePluginsMessage.message");
     let mainAction = {
       label: gNavigatorBundle.getString("activatePluginsMessage.label"),
       accessKey: gNavigatorBundle.getString("activatePluginsMessage.accesskey"),
       callback: function() { gPluginHandler.activatePlugins(contentWindow); }
     };
+    let centerActions = gPluginHandler._makeCenterActions(aBrowser);
+    let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                           .getInterface(Ci.nsIDOMWindowUtils);
+    let haveVulnerablePlugin = cwu.plugins.some(function(plugin) {
+      let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+      return (gPluginHandler.canActivatePlugin(objLoadingContent) &&
+              (objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE ||
+               objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE));
+    });
+    if (haveVulnerablePlugin) {
+      messageString = gNavigatorBundle.getString("vulnerablePluginsMessage");
+    }
     let secondaryActions = [{
       label: gNavigatorBundle.getString("activatePluginsMessage.always"),
       accessKey: gNavigatorBundle.getString("activatePluginsMessage.always.accesskey"),
       callback: function () {
         Services.perms.add(aBrowser.currentURI, "plugins", Ci.nsIPermissionManager.ALLOW_ACTION);
         gPluginHandler.activatePlugins(contentWindow);
       }
     },{
@@ -394,17 +513,17 @@ var gPluginHandler = {
       callback: function () {
         Services.perms.add(aBrowser.currentURI, "plugins", Ci.nsIPermissionManager.DENY_ACTION);
         let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
         if (notification)
           notification.remove();
         gPluginHandler._removeClickToPlayOverlays(contentWindow);
       }
     }];
-    let options = { dismissed: true };
+    let options = { dismissed: true, centerActions: centerActions };
     PopupNotifications.show(aBrowser, "click-to-play-plugins",
                             messageString, "plugins-notification-icon",
                             mainAction, secondaryActions, options);
   },
 
   _removeClickToPlayOverlays: function PH_removeClickToPlayOverlays(aContentWindow) {
     let doc = aContentWindow.document;
     let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -615,22 +734,21 @@ var gPluginHandler = {
     // Ensure the plugin and event are of the right type.
     if (!(aEvent instanceof Ci.nsIDOMDataContainerEvent))
       return;
 
     let submittedReport = aEvent.getData("submittedCrashReport");
     let doPrompt        = true; // XXX followup for .getData("doPrompt");
     let submitReports   = true; // XXX followup for .getData("submitReports");
     let pluginName      = aEvent.getData("pluginName");
-    let pluginFilename  = aEvent.getData("pluginFilename");
     let pluginDumpID    = aEvent.getData("pluginDumpID");
     let browserDumpID   = aEvent.getData("browserDumpID");
 
     // Remap the plugin name to a more user-presentable form.
-    pluginName = this.makeNicePluginName(pluginName, pluginFilename);
+    pluginName = this.makeNicePluginName(pluginName);
 
     let messageString = gNavigatorBundle.getFormattedString("crashedpluginsMessage.title", [pluginName]);
 
     //
     // Configure the crashed-plugin placeholder.
     //
     let doc = plugin.ownerDocument;
     let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -485,16 +485,24 @@ window[chromehidden~="toolbar"] toolbar:
 #addon-progress-notification {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#addon-progress-notification");
 }
 
 #identity-request-notification {
   -moz-binding: url("chrome://browser/content/urlbarBindings.xml#identity-request-notification");
 }
 
+#click-to-play-plugins-notification {
+  -moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
+}
+
+popupnotification-centeritem {
+  -moz-binding: url("chrome://browser/content/urlbarBindings.xml#center-item");
+}
+
 /* override hidden="true" for the status bar compatibility shim
    in case it was persisted for the real status bar */
 #status-bar {
   display: -moz-box;
 }
 
 /* Remove the resizer from the statusbar compatibility shim */
 #status-bar[hideresizer] > .statusbar-resizerpanel {
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -231,16 +231,17 @@ endif
                  plugin_alternate_content.html \
                  plugin_both.html \
                  plugin_both2.html \
                  plugin_bug743421.html \
                  plugin_clickToPlayAllow.html \
                  plugin_clickToPlayDeny.html \
                  plugin_bug749455.html \
                  plugin_hidden_to_visible.html \
+                 plugin_two_types.html \
                  alltabslistener.html \
                  zoom_test.html \
                  dummy_page.html \
                  browser_tabMatchesInAwesomebar.js \
                  file_bug550565_popup.html \
                  file_bug550565_favicon.ico \
                  browser_aboutHome.js \
                  app_bug575561.html \
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -218,17 +218,19 @@ function test8() {
 }
 
 // Tests that activating one click-to-play plugin will activate only that plugin (part 1/3)
 function test9a() {
   var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
   ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 9a, Should not have displayed the missing plugin notification");
   ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 9a, Should not have displayed the blocked plugin notification");
   ok(!gTestBrowser.missingPlugins, "Test 9a, Should not be a missing plugin list");
-  ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 9a, Should have a click-to-play notification");
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(notification, "Test 9a, Should have a click-to-play notification");
+  ok(notification.options.centerActions.length == 1, "Test 9a, Should have only one type of plugin in the notification");
 
   var doc = gTestBrowser.contentDocument;
   var plugin1 = doc.getElementById("test1");
   var rect = doc.getAnonymousElementByAttribute(plugin1, "class", "mainBox").getBoundingClientRect();
   ok(rect.width == 200, "Test 9a, Plugin with id=" + plugin1.id + " overlay rect should have 200px width before being clicked");
   ok(rect.height == 200, "Test 9a, Plugin with id=" + plugin1.id + " overlay rect should have 200px height before being clicked");
   var objLoadingContent = plugin1.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test 9a, Plugin with id=" + plugin1.id + " should not be activated");
@@ -247,17 +249,19 @@ function test9a() {
 }
 
 // Tests that activating one click-to-play plugin will activate only that plugin (part 2/3)
 function test9b() {
   var notificationBox = gBrowser.getNotificationBox(gTestBrowser);
   ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 9b, Should not have displayed the missing plugin notification");
   ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 9b, Should not have displayed the blocked plugin notification");
   ok(!gTestBrowser.missingPlugins, "Test 9b, Should not be a missing plugin list");
-  ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 9b, Click to play notification should not be removed now");
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(notification, "Test 9b, Click to play notification should not be removed now");
+  ok(notification.options.centerActions.length == 1, "Test 9b, Should have only one type of plugin in the notification");
 
   var doc = gTestBrowser.contentDocument;
   var plugin1 = doc.getElementById("test1");
   var pluginRect1 = doc.getAnonymousElementByAttribute(plugin1, "class", "mainBox").getBoundingClientRect();
   ok(pluginRect1.width == 0, "Test 9b, Plugin with id=" + plugin1.id + " should have click-to-play overlay with zero width");
   ok(pluginRect1.height == 0, "Test 9b, Plugin with id=" + plugin1.id + " should have click-to-play overlay with zero height");
   var objLoadingContent = plugin1.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 9b, Plugin with id=" + plugin1.id + " should be activated");
@@ -769,10 +773,143 @@ function test20c() {
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("plugin");
   var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
   ok(pluginRect.width == 0, "Test 20c, plugin should have click-to-play overlay with zero width");
   ok(pluginRect.height == 0, "Test 20c, plugin should have click-to-play overlay with zero height");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 20c, plugin should be activated");
 
+  prepareTest(test21a, gTestRoot + "plugin_two_types.html");
+}
+
+// Test having multiple different types of plugin on one page
+function test21a() {
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(notification, "Test 21a, Should have a click-to-play notification");
+  ok(notification.options.centerActions.length == 2, "Test 21a, Should have two types of plugin in the notification");
+
+  var doc = gTestBrowser.contentDocument;
+  var ids = ["test", "secondtestA", "secondtestB"];
+  for (var id of ids) {
+    var plugin = doc.getElementById(id);
+    var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
+    ok(rect.width == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
+    ok(rect.height == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
+    var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(!objLoadingContent.activated, "Test 21a, Plugin with id=" + plugin.id + " should not be activated");
+  }
+
+  // we have to actually show the panel to get the bindings to instantiate
+  notification.options.dismissed = false;
+  notification.options.eventCallback = test21b;
+  PopupNotifications._showPanel([notification], notification.anchorElement);
+}
+
+function test21b() {
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  notification.options.eventCallback = null;
+  var centerAction = null;
+  for (var action of notification.options.centerActions) {
+    if (action.message == "Test") {
+      centerAction = action;
+      break;
+    }
+  }
+  ok(centerAction, "Test 21b, found center action for the Test plugin");
+
+  var centerItem = null;
+  for (var item of centerAction.popupnotification.childNodes) {
+    if (item.action == centerAction) {
+      centerItem = item;
+      break;
+    }
+  }
+  ok(centerItem, "Test 21b, found center item for the Test plugin");
+
+  // "click" the button to activate the Test plugin
+  centerItem.runCallback.apply(centerItem);
+
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  var condition = function() objLoadingContent.activated;
+  waitForCondition(condition, test21c, "Test 21b, Waited too long for plugin to activate");
+}
+
+function test21c() {
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(notification, "Test 21c, Should have a click-to-play notification");
+  ok(notification.options.centerActions.length == 1, "Test 21c, Should have one type of plugin in the notification");
+
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("test");
+  var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
+  ok(rect.width == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
+  ok(rect.height == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  ok(objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should be activated");
+
+  var ids = ["secondtestA", "secondtestB"];
+  for (var id of ids) {
+    var plugin = doc.getElementById(id);
+    var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
+    ok(rect.width == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
+    ok(rect.height == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
+    var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(!objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should not be activated");
+  }
+
+  // we have to actually show the panel to get the bindings to instantiate
+  notification.options.dismissed = false;
+  notification.options.eventCallback = test21d;
+  PopupNotifications._showPanel([notification], notification.anchorElement);
+}
+
+function test21d() {
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  notification.options.eventCallback = null;
+
+  var centerAction = null;
+  for (var action of notification.options.centerActions) {
+    if (action.message == "Second Test") {
+      centerAction = action;
+      break;
+    }
+  }
+  ok(centerAction, "Test 21d, found center action for the Second Test plugin");
+
+  var centerItem = null;
+  for (var item of centerAction.popupnotification.childNodes) {
+    if (item.action == centerAction) {
+      centerItem = item;
+      break;
+    }
+  }
+  ok(centerItem, "Test 21d, found center item for the Second Test plugin");
+
+  // "click" the button to activate the Second Test plugins
+  centerItem.runCallback.apply(centerItem);
+
+  var doc = gTestBrowser.contentDocument;
+  var plugin = doc.getElementById("secondtestA");
+  var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+  var condition = function() objLoadingContent.activated;
+  waitForCondition(condition, test21e, "Test 21d, Waited too long for plugin to activate");
+}
+
+function test21e() {
+  var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
+  ok(!notification, "Test 21e, Should not have a click-to-play notification");
+
+  var doc = gTestBrowser.contentDocument;
+  var ids = ["test", "secondtestA", "secondtestB"];
+  for (var id of ids) {
+    var plugin = doc.getElementById(id);
+    var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect();
+    ok(rect.width == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
+    ok(rect.height == 0, "Test 21e, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
+    var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    ok(objLoadingContent.activated, "Test 21e, Plugin with id=" + plugin.id + " should be activated");
+  }
+
   finishTest();
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/plugin_two_types.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head><meta charset="utf-8"/></head>
+<body>
+<embed id="test" style="width: 200px; height: 200px" type="application/x-test"/>
+<embed id="secondtestA" style="width: 200px; height: 200px" type="application/x-second-test"/>
+<embed id="secondtestB" style="width: 200px; height: 200px" type="application/x-second-test"/>
+</body>
+</html>
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1413,16 +1413,133 @@
           this.identity.selected = chosenId;
           this.onIdentitySelected();
         ]]></body>
       </method>
 
     </implementation>
   </binding>
 
+  <binding id="center-item">
+    <content align="center">
+      <xul:vbox flex="1" class="center-item-box"
+                xbl:inherits="warn,showseparator,padbottom">
+        <xul:hbox flex="1" align="center">
+          <xul:image class="center-item-icon"
+                     xbl:inherits="src=itemicon"/>
+          <xul:description class="center-item-label"
+                           xbl:inherits="xbl:text=itemtext"/>
+          <xul:spacer flex="1"/>
+          <xul:button class="popup-notification-menubutton center-item-button"
+                      oncommand="document.getBindingParent(this).runCallback();"
+                      xbl:inherits="label=buttonlabel"/>
+        </xul:hbox>
+        <xul:hbox flex="1" align="center" class="center-item-warning">
+          <xul:image class="center-item-warning-icon"/>
+          <xul:label class="center-item-warning-description" xbl:inherits="xbl:text=warningText"/>
+          <xul:label xbl:inherits="href=updateLink" value="&checkForUpdates;" class="text-link"/>
+          <xul:spacer flex="1"/>
+        </xul:hbox>
+      </xul:vbox>
+    </content>
+    <resources>
+      <stylesheet src="chrome://global/skin/notification.css"/>
+    </resources>
+    <implementation>
+      <field name="action"></field>
+      <method name="runCallback">
+        <body><![CDATA[
+          let action = this.action;
+          action.callback();
+          let cas = action.popupnotification.notification.options.centerActions;
+          cas.splice(cas.indexOf(action), 1);
+          PopupNotifications._dismiss();
+        ]]></body>
+      </method>
+    </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">
+      <xul:hbox flex="1">
+        <xul:vbox class="click-to-play-plugins-notification-icon-box" flex="1">
+          <xul:image class="popup-notification-icon"
+                     xbl:inherits="popupid,src=icon"/>
+          <xul:spacer flex="1"/>
+        </xul:vbox>
+        <xul:spacer class="click-to-play-plugins-notification-separator"/>
+        <xul:vbox flex="1" class="popup-notification-main-box"
+                  xbl:inherits="popupid">
+          <xul:box class="click-to-play-plugins-notification-description-box" flex="1">
+            <xul:description xbl:inherits="xbl:text=label"/>
+          </xul:box>
+          <xul:spacer class="click-to-play-plugins-notification-separator"/>
+          <xul:vbox class="click-to-play-plugins-notification-center-box">
+            <children includes="popupnotification-centeritem"/>
+          </xul:vbox>
+          <xul:spacer class="click-to-play-plugins-notification-separator"/>
+          <xul:hbox class="click-to-play-plugins-notification-button-container"
+                    pack="end" align="center">
+            <xul:button anonid="button"
+                        class="popup-notification-menubutton"
+                        type="menu-button"
+                        xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
+              <xul:menupopup anonid="menupopup"
+                             xbl:inherits="oncommand=menucommand">
+                <children/>
+                <xul:menuitem class="menuitem-iconic popup-notification-closeitem"
+                              label="&closeNotificationItem.label;"
+                              xbl:inherits="oncommand=closeitemcommand"/>
+              </xul:menupopup>
+            </xul:button>
+          </xul:hbox>
+        </xul:vbox>
+      </xul:hbox>
+    </content>
+    <resources>
+      <stylesheet src="chrome://global/skin/notification.css"/>
+    </resources>
+    <implementation>
+      <field name="button" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "button");
+      </field>
+      <field name="menupopup" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "menupopup");
+      </field>
+      <constructor><![CDATA[
+        const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+        let popupnotification = this;
+        let item = null;
+        let prev = null;
+        this.notification.options.centerActions.forEach(function(action) {
+          action.popupnotification = popupnotification;
+          item = document.createElementNS(XUL_NS, "popupnotification-centeritem");
+          item.action = action;
+          item.setAttribute("itemtext", action.message);
+          item.setAttribute("buttonlabel", action.label);
+          item.setAttribute("warn", action.warn);
+          item.setAttribute("warningText", action.warningText);
+          item.setAttribute("updateLink", action.updateLink);
+          if (prev &&
+              (prev.getAttribute("warn") == "true" ||
+               item.getAttribute("warn") == "true")) {
+            item.setAttribute("showseparator", true);
+            if (prev.getAttribute("warn") != "true") {
+              prev.setAttribute("padbottom", true);
+            }
+          }
+          popupnotification.appendChild(item);
+          prev = item;
+        });
+        if (item != null) {
+          item.setAttribute("padbottom", "true");
+        }
+      ]]></constructor>
+    </implementation>
+  </binding>
 
   <binding id="splitmenu">
     <content>
       <xul:hbox anonid="menuitem" flex="1"
                 class="splitmenu-menuitem"
                 xbl:inherits="iconic,label,disabled,onclick=oncommand,_moz-menuactive=active"/>
       <xul:menu anonid="menu" class="splitmenu-menu"
                 xbl:inherits="disabled,_moz-menuactive=active"
--- a/browser/devtools/styleeditor/StyleEditor.jsm
+++ b/browser/devtools/styleeditor/StyleEditor.jsm
@@ -904,16 +904,23 @@ StyleEditor.prototype = {
         if (!Components.isSuccessCode(aStatusCode)) {
           return this._signalError(LOAD_ERROR);
         }
 
         this._onSourceLoad(chunks.join(""), channelCharset);
       }.bind(this)
     };
 
+    if (channel instanceof Ci.nsIPrivateBrowsingChannel) {
+      let contentWin = this.contentDocument.defaultView;
+      let loadContext = contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
+                          .getInterface(Ci.nsIWebNavigation)
+                          .QueryInterface(Ci.nsILoadContext);
+      channel.setPrivate(loadContext.usePrivateBrowsing);
+    }
     channel.loadFlags = channel.LOAD_FROM_CACHE;
     channel.asyncOpen(streamListener, null);
   },
 
   /**
    * Called when source has been loaded.
    *
    * @param string aSourceText
--- a/browser/devtools/styleeditor/test/Makefile.in
+++ b/browser/devtools/styleeditor/test/Makefile.in
@@ -17,16 +17,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_styleeditor_cmd_edit.js \
                  browser_styleeditor_cmd_edit.html \
                  browser_styleeditor_import.js \
                  browser_styleeditor_init.js \
                  browser_styleeditor_loading.js \
                  browser_styleeditor_new.js \
                  browser_styleeditor_passedinsheet.js \
                  browser_styleeditor_pretty.js \
+                 browser_styleeditor_private.js \
                  browser_styleeditor_readonly.js \
                  browser_styleeditor_reopen.js \
                  browser_styleeditor_sv_keynav.js \
                  browser_styleeditor_sv_resize.js \
                  four.html \
                  head.js \
                  helpers.js \
                  media.html \
@@ -35,12 +36,14 @@ include $(topsrcdir)/config/rules.mk
                  resources_inpage.jsi \
                  resources_inpage1.css \
                  resources_inpage2.css \
                  simple.css \
                  simple.css.gz \
                  simple.css.gz^headers^ \
                  simple.gz.html \
                  simple.html \
+                 test_private.html \
+                 test_private.css \
                  $(NULL)
 
 libs::	$(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_private.js
@@ -0,0 +1,63 @@
+/* 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/. */
+
+// This test makes sure that the style editor does not store any
+// content CSS files in the permanent cache when opened from PB mode.
+
+function checkDiskCacheFor(host) {
+  let visitor = {
+    visitDevice: function(deviceID, deviceInfo) {
+      if (deviceID == "disk")
+        info("disk device contains " + deviceInfo.entryCount + " entries");
+      return deviceID == "disk";
+    },
+    
+    visitEntry: function(deviceID, entryInfo) {
+      info(entryInfo.key);
+      is(entryInfo.key.contains(host), false, "web content present in disk cache");
+    }
+  };
+  cache.visitEntries(visitor);
+}
+
+const TEST_HOST = 'mochi.test:8888';
+
+var cache = Cc["@mozilla.org/network/cache-service;1"]
+              .getService(Ci.nsICacheService);
+
+function test() {
+  waitForExplicitFinish();
+  
+  gPrefService.setBoolPref("browser.privatebrowsing.keep_current_session", true);
+  let pb = Cc["@mozilla.org/privatebrowsing;1"].
+           getService(Ci.nsIPrivateBrowsingService);
+  pb.privateBrowsingEnabled = true;
+  
+  function checkCache() {
+    checkDiskCacheFor(TEST_HOST);
+    pb.privateBrowsingEnabled = false;
+    gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
+    finish();
+  }
+
+  gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+    gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+    cache.evictEntries(Ci.nsICache.STORE_ANYWHERE);
+    launchStyleEditorChrome(function(aChrome) {
+      aChrome.addChromeListener({
+        onEditorAdded: function(aChrome, aEditor) {
+          if (aEditor.isLoaded) {
+            checkCache();            
+          } else {
+            aEditor.addActionListener({
+              onLoad: checkCache
+            });
+          }
+        }
+      });
+    });
+  }, true);
+
+  content.location = 'http://' + TEST_HOST + '/browser/browser/devtools/styleeditor/test/test_private.html';
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleeditor/test/test_private.css
@@ -0,0 +1,3 @@
+body {
+    background-color: red;
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleeditor/test/test_private.html
@@ -0,0 +1,7 @@
+<html>
+<head>
+<link rel="stylesheet" href="test_private.css"></link>
+</head>
+<body>
+</body>
+</html>
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -115,22 +115,32 @@ crashedpluginsMessage.reloadButton.label
 crashedpluginsMessage.reloadButton.accesskey=R
 crashedpluginsMessage.submitButton.label=Submit a crash report
 crashedpluginsMessage.submitButton.accesskey=S
 crashedpluginsMessage.learnMore=Learn More…
 carbonFailurePluginsMessage.message=This page asks to use a plugin that can only run in 32-bit mode
 carbonFailurePluginsMessage.restartButton.label=Restart in 32-bit mode
 carbonFailurePluginsMessage.restartButton.accesskey=R
 activatePluginsMessage.message=Would you like to activate the plugins on this page?
-activatePluginsMessage.label=Activate plugins
+activatePluginsMessage.label=Activate All Plugins
 activatePluginsMessage.accesskey=A
 activatePluginsMessage.always=Always activate plugins for this site
 activatePluginsMessage.always.accesskey=c
 activatePluginsMessage.never=Never activate plugins for this site
 activatePluginsMessage.never.accesskey=N
+activateSinglePlugin=Activate
+PluginClickToPlay=Click here to activate the %S plugin.
+# LOCALIZATION NOTE - "vulnerable" indicates there is a security bug in the
+# plugin that is being exploited by attackers.
+PluginVulnerableUpdatable=This plugin is vulnerable and should be updated.
+PluginVulnerableNoUpdate=This plugin has security vulnerabilities.
+vulnerableUpdatablePluginWarning=Outdated Version!
+vulnerableNoUpdatePluginWarning=Vulnerable Plugin!
+vulnerablePluginsMessage=Some plugins have been deactivated for your safety.
+pluginInfo.unknownPlugin=Unknown
 
 # Sanitize
 # LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to
 # clear" is set to "Everything", the Clear Recent History dialog's title is
 # changed to this.  See UI mockup and comment 11 at bug 480169 -->
 sanitizeDialog2.everything.title=Clear All History
 sanitizeButtonOK=Clear Now
 # LOCALIZATION NOTE (sanitizeEverythingWarning2): Warning that appears when
--- a/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/responsiveUI.properties
@@ -1,8 +1,12 @@
+# 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/.
+
 # LOCALIZATION NOTE These strings are used inside the Responsive Mode
 # which is available from the Web Developer sub-menu -> 'Responsive Mode'.
 #
 # The correct localization of this file might be to keep it in
 # English, or another language commonly spoken among web developers.
 # You want to make that choice consistent across the developer tools.
 # A good criteria is the language in which you'd find the best
 # documentation on web development on the web.
@@ -28,9 +32,9 @@ responsiveUI.customResolution=%S (custom
 responsiveUI.namedResolution=%S (%S)
 
 # LOCALIZATION NOTE  (responsiveUI.customNamePromptTitle): prompt title when asking
 # the user to specify a name for a new custom preset.
 responsiveUI.customNamePromptTitle=Responsive Design View
 
 # LOCALIZATION NOTE  (responsiveUI.customNamePromptMsg): prompt message when asking
 # the user to specify a name for a new custom preset.
-responsiveUI.customNamePromptMsg=Give a name to the %Sx%S preset
\ No newline at end of file
+responsiveUI.customNamePromptMsg=Give a name to the %Sx%S preset
--- a/browser/locales/en-US/defines.inc
+++ b/browser/locales/en-US/defines.inc
@@ -1,8 +1,11 @@
+# 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/.
 #filter emptyLines
 
 #define MOZ_LANGPACK_CREATOR mozilla.org
 
 # If non-English locales wish to credit multiple contributors, uncomment this
 # variable definition and use the format specified.
 # #define MOZ_LANGPACK_CONTRIBUTORS <em:contributor>Joe Solon</em:contributor> <em:contributor>Suzy Solon</em:contributor>
 
--- a/browser/locales/en-US/pdfviewer/chrome.properties
+++ b/browser/locales/en-US/pdfviewer/chrome.properties
@@ -1,4 +1,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/.
+
 # Chrome notification bar messages and buttons
 unsupported_feature=This PDF document might not be displayed correctly.
 open_with_different_viewer=Open With Different Viewer
 open_with_different_viewer.accessKey=o
--- a/browser/locales/en-US/pdfviewer/viewer.properties
+++ b/browser/locales/en-US/pdfviewer/viewer.properties
@@ -1,8 +1,12 @@
+# 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/.
+
 # Main toolbar buttons (tooltips and alt text for images)
 previous.title=Previous Page
 previous_label=Previous
 next.title=Next Page
 next_label=Next
 
 # LOCALIZATION NOTE (page_label, page_of):
 # These strings are concatenated to form the "Page: X of Y" string.
--- a/browser/locales/en-US/profile/bookmarks.inc
+++ b/browser/locales/en-US/profile/bookmarks.inc
@@ -1,8 +1,11 @@
+# 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/.
 #filter emptyLines
 
 # LOCALIZATION NOTE: The 'en-US' strings in the URLs will be replaced with
 # your locale code, and link to your translated pages as soon as they're 
 # live.
 
 #define bookmarks_title Bookmarks
 #define bookmarks_heading Bookmarks
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1154,19 +1154,17 @@ toolbar[iconsize="small"] #feed-button {
 .popup-notification-icon[popupid="addon-install-failed"],
 .popup-notification-icon[popupid="addon-install-complete"] {
   list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
   width: 32px;
   height: 32px;
 }
 
 .popup-notification-icon[popupid="click-to-play-plugins"] {
-  list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
-  width: 32px;
-  height: 32px;
+  list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
 }
 
 .popup-progress-label,
@@ -2822,8 +2820,114 @@ chatbox {
   border: 1px solid gray;
   border-bottom: none;
 }
 
 chatbox[minimized="true"] {
   width: 160px;
   height: 20px;
 }
+
+panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="top"],
+panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="bottom"] {
+  list-style-image: url("chrome://global/skin/icons/panelarrow-light-vertical.svg");
+}
+
+.click-to-play-plugins-notification-content {
+  margin: -10px;
+}
+
+.click-to-play-plugins-notification-icon-box {
+  background: hsla(0,0%,100%,.4);
+  -moz-border-end: 1px solid hsla(0,0%,100%,.2);
+  padding-top: 16px;
+  -moz-padding-start: 16px;
+  -moz-padding-end: 6px;
+}
+
+.click-to-play-plugins-notification-separator {
+  -moz-border-start: 1px solid hsla(211,79%,6%,.1);
+  border-top: 1px solid hsla(211,79%,6%,.1);
+}
+
+.click-to-play-plugins-notification-description-box {
+  border-bottom: 1px solid hsla(0,0%,100%,.2);
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  padding: 14px 10px 9px 10px;
+}
+
+.click-to-play-plugins-notification-center-box {
+  border-top: 1px solid hsla(0,0%,100%,.2);
+  border-bottom: 1px solid hsla(0,0%,100%,.2);
+  background-color: hsla(211,79%,6%,.05);
+}
+
+.click-to-play-plugins-notification-button-container {
+  border-top: 1px solid hsla(0,0%,100%,.2);
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  margin: 0px;
+  padding: 15px 11px 14px 11px;
+}
+
+.center-item-box {
+  padding-top: 11px;
+  -moz-padding-start: 16px;
+  -moz-padding-end: 11px;
+  margin-bottom: -2px;
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+}
+
+.center-item-box[padbottom="true"] {
+  padding-bottom: 12px;
+}
+
+.center-item-icon {
+  background-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
+  background-repeat: no-repeat;
+  height: 16px;
+  width: 16px;
+  margin-bottom: 4px;
+}
+
+.center-item-box[warn="true"] {
+  background-image: url("chrome://mozapps/skin/extensions/stripes-info-negative-small.png");
+  background-repeat: repeat-x;
+  padding-top: 7px;
+  -moz-padding-end: 11px;
+  padding-bottom: 9px;
+  -moz-padding-start: 16px;
+}
+
+.center-item-box[padbottom="true"][warn="true"] {
+  padding-bottom: 7px;
+}
+
+.center-item-box[showseparator="true"] {
+  border-top: 1px solid hsla(211,79%,6%,.1);
+}
+
+.center-item-box[warn="false"] > .center-item-warning {
+  display: none;
+}
+
+.center-item-warning > .text-link {
+  color: #3d8cd7;
+}
+
+.center-item-warning > .text-link[href=""] {
+  display: none;
+}
+
+.center-item-warning-icon {
+  background-image: url("chrome://mozapps/skin/extensions/alerticon-info-negative.png");
+  background-repeat: no-repeat;
+  width: 16px;
+  height: 15px;
+  margin-bottom: 4px;
+}
+
+.center-item-warning-description {
+  color: #828282;
+}
+
+.center-item-button {
+  min-width: 0;
+}
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -3050,19 +3050,17 @@ toolbarbutton.chevron > .toolbarbutton-m
 .popup-notification-icon[popupid="addon-install-failed"],
 .popup-notification-icon[popupid="addon-install-complete"] {
   list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
   width: 32px;
   height: 32px;
 }
 
 .popup-notification-icon[popupid="click-to-play-plugins"] {
-  list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
-  width: 32px;
-  height: 32px;
+  list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
 }
 
 .popup-progress-label,
@@ -4246,8 +4244,127 @@ chatbox {
   border: 1px solid #404040;
   border-bottom: none;
 }
 
 chatbox[minimized="true"] {
   width: 160px;
   height: 20px;
 }
+
+panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="top"],
+panel[type="arrow"][popupid="click-to-play-plugins"] > .panel-arrowcontainer > .panel-arrowbox > .panel-arrow[side="bottom"] {
+  list-style-image: url("chrome://global/skin/arrow/panelarrow-light-vertical.png");
+}
+
+.click-to-play-plugins-notification-content {
+  margin: -16px;
+  border-radius: 5px;
+}
+
+.click-to-play-plugins-notification-icon-box {
+  background: hsla(0,0%,100%,.4);
+  -moz-border-end: 1px solid hsla(0,0%,100%,.2);
+  padding-top: 16px;
+  -moz-padding-end: 12px;
+  -moz-padding-start: 20px;
+}
+
+.click-to-play-plugins-notification-icon-box:-moz-locale-dir(ltr) {
+  border-bottom-left-radius: 5px;
+  border-top-left-radius: 5px;
+}
+
+.click-to-play-plugins-notification-icon-box:-moz-locale-dir(rtl) {
+  border-bottom-right-radius: 5px;
+  border-top-right-radius: 5px;
+}
+
+.click-to-play-plugins-notification-separator {
+  -moz-border-start: 1px solid hsla(211,79%,6%,.1);
+  border-top: 1px solid hsla(211,79%,6%,.1);
+}
+
+.click-to-play-plugins-notification-description-box {
+  border-bottom: 1px solid hsla(0,0%,100%,.2);
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  max-width: 28em;
+  padding: 14px 16px 9px 16px;
+}
+
+.click-to-play-plugins-notification-center-box {
+  border-top: 1px solid hsla(0,0%,100%,.2);
+  border-bottom: 1px solid hsla(0,0%,100%,.2);
+  background-color: hsla(211,79%,6%,.05);
+}
+
+.click-to-play-plugins-notification-button-container {
+  border-top: 1px solid hsla(0,0%,100%,.2);
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  margin: 0px;
+  padding: 16px 16px 17px 16px;
+}
+
+.center-item-box {
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  padding-top: 7px;
+  -moz-padding-end: 11px;
+  -moz-padding-start: 16px;
+  margin-bottom: -3px;
+}
+
+.center-item-box[padbottom="true"] {
+  padding-bottom: 12px;
+}
+
+.center-item-icon {
+  background-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
+  background-repeat: no-repeat;
+  height: 16px;
+  width: 16px;
+  margin-bottom: 4px;
+  -moz-margin-end: 6px;
+}
+
+.center-item-box[warn="true"] {
+  background-image: url("chrome://mozapps/skin/extensions/stripes-info-negative-small.png");
+  background-repeat: repeat-x;
+  padding-top: 3px;
+  -moz-padding-end: 11px;
+  padding-bottom: 9px;
+  -moz-padding-start: 16px;
+}
+
+.center-item-box[padbottom="true"][warn="true"] {
+  padding-bottom: 7px;
+}
+
+.center-item-box[showseparator="true"] {
+  border-top: 1px solid hsla(211,79%,6%,.1);
+}
+
+.center-item-box[warn="false"] > .center-item-warning {
+  display: none;
+}
+
+.center-item-warning > .text-link {
+  color: #3d8cd7;
+}
+
+.center-item-warning > .text-link[href=""] {
+  display: none;
+}
+
+.center-item-warning-icon {
+  background-image: url("chrome://mozapps/skin/extensions/alerticon-info-negative.png");
+  background-repeat: no-repeat;
+  width: 16px;
+  height: 15px;
+  margin-bottom: 4px;
+}
+
+.center-item-warning-description {
+  color: #828282;
+}
+
+.center-item-button {
+  min-width: 0;
+}
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -2277,19 +2277,17 @@ toolbarbutton.bookmark-item[dragover="tr
 .popup-notification-icon[popupid="addon-install-failed"],
 .popup-notification-icon[popupid="addon-install-complete"] {
   list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
   width: 32px;
   height: 32px;
 }
 
 .popup-notification-icon[popupid="click-to-play-plugins"] {
-  list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
-  width: 32px;
-  height: 32px;
+  list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked-64.png);
 }
 
 .addon-progress-description {
   width: 350px;
   max-width: 350px;
 }
 
 .popup-progress-label,
@@ -3513,8 +3511,117 @@ chatbox {
   border: 1px solid gray;
   border-bottom: none;
 }
 
 chatbox[minimized="true"] {
   width: 160px;
   height: 20px;
 }
+
+.click-to-play-plugins-notification-content {
+  margin: -10px;
+  border-radius: 4px;
+}
+
+.click-to-play-plugins-notification-icon-box {
+  background: hsla(0,0%,100%,.4);
+  -moz-border-end: 1px solid hsla(0,0%,100%,.2);
+  padding-top: 16px;
+  -moz-padding-end: 16px;
+  -moz-padding-start: 24px;
+}
+
+.click-to-play-plugins-notification-icon-box:-moz-locale-dir(ltr) {
+  border-bottom-left-radius: 4px;
+  border-top-left-radius: 4px;
+}
+
+.click-to-play-plugins-notification-icon-box:-moz-locale-dir(rtl) {
+  border-bottom-right-radius: 4px;
+  border-top-right-radius: 4px;
+}
+
+.click-to-play-plugins-notification-separator {
+  -moz-border-start: 1px solid hsla(211,79%,6%,.1);
+  border-top: 1px solid hsla(211,79%,6%,.1);
+}
+
+.click-to-play-plugins-notification-description-box {
+  border-bottom: 1px solid hsla(0,0%,100%,.2);
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  padding-top: 12px;
+  -moz-padding-end: 11px;
+  padding-bottom: 9px;
+  -moz-padding-start: 10px;
+}
+
+.click-to-play-plugins-notification-center-box {
+  border-top: 1px solid hsla(0,0%,100%,.2);
+  border-bottom: 1px solid hsla(0,0%,100%,.2);
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  background-color: hsla(211,79%,6%,.05);
+}
+
+.click-to-play-plugins-notification-button-container {
+  border-top: 1px solid hsla(0,0%,100%,.2);
+  -moz-border-start: 1px solid hsla(0,0%,100%,.2);
+  margin: 0px;
+  padding: 16px;
+}
+
+.center-item-box {
+  padding: 12px 16px 0px 16px;
+}
+
+.center-item-box[padbottom="true"] {
+  padding-bottom: 12px;
+}
+
+.center-item-icon {
+  background-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
+  background-repeat: no-repeat;
+  height: 16px;
+  width: 16px;
+  margin-bottom: 4px;
+}
+
+.center-item-box[warn="true"] {
+  background-image: url("chrome://mozapps/skin/extensions/stripes-info-negative-small.png");
+  background-repeat: repeat-x;
+  padding: 8px 16px 6px 16px;
+}
+
+.center-item-box[padbottom="true"][warn="true"] {
+  padding-bottom: 4px;
+}
+
+.center-item-box[showseparator="true"] {
+  border-top: 1px solid hsla(211,79%,6%,.1);
+}
+
+.center-item-box[warn="false"] > .center-item-warning {
+  display: none;
+}
+
+.center-item-warning > .text-link {
+  color: #3d8cd7;
+}
+
+.center-item-warning > .text-link[href=""] {
+  display: none;
+}
+
+.center-item-warning-icon {
+  background-image: url("chrome://mozapps/skin/extensions/alerticon-info-negative.png");
+  background-repeat: no-repeat;
+  width: 16px;
+  height: 15px;
+  margin-bottom: 4px;
+}
+
+.center-item-warning-description {
+  color: #828282;
+}
+
+.center-item-button {
+  min-width: 0;
+}
--- a/build/pymake/make.py
+++ b/build/pymake/make.py
@@ -7,13 +7,16 @@ A drop-in or mostly drop-in replacement 
 """
 
 import sys, os
 import pymake.command, pymake.process
 
 import gc
 
 if __name__ == '__main__':
+  sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+  sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)
+
   gc.disable()
 
   pymake.command.main(sys.argv[1:], os.environ, os.getcwd(), cb=sys.exit)
   pymake.process.ParallelContext.spin()
   assert False, "Not reached"
--- a/build/pymake/pymake/data.py
+++ b/build/pymake/pymake/data.py
@@ -442,17 +442,17 @@ class Variables(object):
     SOURCE_IMPLICIT = 5
 
     def __init__(self, parent=None):
         self._map = {} # vname -> flavor, source, valuestr, valueexp
         self.parent = parent
 
     def readfromenvironment(self, env):
         for k, v in env.iteritems():
-            self.set(k, self.FLAVOR_SIMPLE, self.SOURCE_ENVIRONMENT, v)
+            self.set(k, self.FLAVOR_RECURSIVE, self.SOURCE_ENVIRONMENT, v)
 
     def get(self, name, expand=True):
         """
         Get the value of a named variable. Returns a tuple (flavor, source, value)
 
         If the variable is not present, returns (None, None, None)
 
         @param expand If true, the value will be returned as an expansion. If false,
new file mode 100644
--- /dev/null
+++ b/build/pymake/tests/env-var-append.mk
@@ -0,0 +1,7 @@
+#T environment: {'FOO': 'TEST'}
+
+FOO += $(BAR)
+BAR := PASS
+
+all:
+	@echo $(subst $(NULL) ,-,$(FOO))
new file mode 100644
--- /dev/null
+++ b/build/pymake/tests/env-var-append2.mk
@@ -0,0 +1,8 @@
+#T environment: {'FOO': '$(BAZ)'}
+
+FOO += $(BAR)
+BAR := PASS
+BAZ := TEST
+
+all:
+	@echo $(subst $(NULL) ,-,$(FOO))
--- a/configure.in
+++ b/configure.in
@@ -49,17 +49,17 @@ dnl ====================================
 _SUBDIR_HOST_CFLAGS="$HOST_CFLAGS"
 _SUBDIR_HOST_CXXFLAGS="$HOST_CXXFLAGS"
 _SUBDIR_HOST_LDFLAGS="$HOST_LDFLAGS"
 _SUBDIR_CONFIG_ARGS="$ac_configure_args"
 
 dnl Set the version number of the libs included with mozilla
 dnl ========================================================
 MOZJPEG=62
-MOZPNG=10511
+MOZPNG=10513
 NSPR_VERSION=4
 NSS_VERSION=3
 
 dnl Set the minimum version of toolkit libs used by mozilla
 dnl ========================================================
 GLIB_VERSION=1.2.0
 PERL_VERSION=5.006
 PYTHON_VERSION_MAJOR=2
@@ -1481,21 +1481,23 @@ if test "$GNU_CXX"; then
     # Turn on GNU-specific warnings:
     # -Wall - turn on a lot of warnings
     # -pedantic - this is turned on below
     # -Wpointer-arith - enabled with -pedantic, but good to have even if not
     # -Woverloaded-virtual - ???
     # -Werror=return-type - catches missing returns, zero false positives
     # -Wtype-limits - catches overflow bugs, few false positives
     # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
+    # -Werror=conversion-null - catches conversions between NULL and non-pointer types
     #
     _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual"
     MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
     MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
     MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
+    MOZ_CXX_SUPPORTS_WARNING(-W, error=conversion-null, ac_cxx_has_werror_conversion_null)
 
     # Turn off the following warnings that -Wall/-pedantic turn on:
     # -Wno-ctor-dtor-privacy - ???
     # -Wno-overlength-strings - we exceed the minimum maximum length frequently 
     # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently
     # -Wno-variadic-macros - ???
     #
     _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-ctor-dtor-privacy"
@@ -2192,17 +2194,23 @@ ia64*-hpux*)
         MKSHLIB_FORCE_ALL=
         MKSHLIB_UNFORCE_ALL=
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS
         _USE_CPP_INCLUDE_FLAG=1
         _DEFINES_CFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
         _DEFINES_CXXFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
         CXXFLAGS="$CXXFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
-        CXXFLAGS="$CXXFLAGS -wd4800" # disable warning "forcing value to bool"
+        # MSVC warning C4345 warns of newly conformant behavior as of VS2003.
+        # MSVC warning C4351 warns of newly conformant behavior as of VS2005.
+        # MSVC warning C4800 warns when a value is implicitly cast to bool,
+        # because this also forces narrowing to a single byte, which can be a
+        # perf hit.  But this matters so little in practice (and often we want
+        # that behavior) that it's better to turn it off.
+        CXXFLAGS="$CXXFLAGS -wd4345 -wd4351 -wd4800"
         # make 'foo == bar;' error out
         CFLAGS="$CFLAGS -we4553"
         CXXFLAGS="$CXXFLAGS -we4553"
         LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib"
         MOZ_DEBUG_FLAGS='-Zi'
         MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
         WARNINGS_AS_ERRORS='-WX'
         MOZ_OPTIMIZE_FLAGS='-O1'
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -402,16 +402,17 @@ CSPRep.fromString = function(aStr, self,
 
       // suspend the parent document request while we fetch the policy-uri
       try {
         docRequest.suspend();
         var chan = gIoService.newChannel(uri.asciiSpec, null, null);
         // make request anonymous (no cookies, etc.) so the request for the
         // policy-uri can't be abused for CSRF
         chan.loadFlags |= Ci.nsIChannel.LOAD_ANONYMOUS;
+        chan.loadGroup = docRequest.loadGroup;
         chan.asyncOpen(new CSPPolicyURIListener(uri, docRequest, csp), null);
       }
       catch (e) {
         // resume the document request and apply most restrictive policy
         docRequest.resume();
         cspError(aCSPR, CSPLocalizer.getFormatStr("errorFetchingPolicy",
                                                   [e.toString()]));
         return CSPRep.fromString("default-src 'none'");
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -410,21 +410,18 @@ public:
                          ErrorResult& aRv)
   {
     nsCString result;
     GetResponseHeader(NS_ConvertUTF16toUTF8(aHeader), result, aRv);
     if (result.IsVoid()) {
       aResult.SetIsVoid(true);
     }
     else {
-      // We use UTF8ToNewUnicode here because it truncates after invalid UTF-8
-      // characters, CopyUTF8toUTF16 just doesn't copy in that case.
-      uint32_t length;
-      PRUnichar* chars = UTF8ToNewUnicode(result, &length);
-      aResult.Adopt(chars, length);
+      // The result value should be inflated:
+      CopyASCIItoUTF16(result, aResult);
     }
   }
   void GetAllResponseHeaders(nsString& aResponseHeaders);
   void OverrideMimeType(const nsAString& aMimeType)
   {
     // XXX Should we do some validation here?
     mOverrideMimeType = aMimeType;
   }
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -183,16 +183,18 @@ MOCHITEST_FILES_A = \
 		file_XHR_pass2.txt \
 		file_XHR_pass3.txt \
 		file_XHR_pass3.txt^headers^ \
 		file_XHR_fail1.txt \
 		file_XHR_fail1.txt^headers^ \
 		file_XHR_binary1.bin \
 		file_XHR_binary1.bin^headers^ \
 		file_XHR_binary2.bin \
+		file_XHR_header.sjs \
+		test_XHR_header.html \
 		test_bug428847.html \
 		file_bug428847-1.xhtml \
 		file_bug428847-2.xhtml \
 		test_bug431701.html \
 		test_bug431833.html \
 		test_bug435425.html \
 		bug435425.sjs \
 		bug435425_redirect.sjs \
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_XHR_header.sjs
@@ -0,0 +1,6 @@
+// SJS file for getAllResponseRequests vs getResponseRequest
+function handleRequest(request, response)
+{
+  response.setHeader("X-Custom-Header-Bytes", "…", false);
+  response.write("42");
+}
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_XHR_header.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for XMLHttpRequest.GetResponseHeader(foo) byte-inflates the output</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <meta charset="utf-8">
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+"use strict";
+SimpleTest.waitForExplicitFinish();
+
+let xhr = new XMLHttpRequest();
+xhr.open('GET', 'file_XHR_header.sjs', true);
+xhr.onreadystatechange = function() {
+  if (xhr.readyState == 4) {
+    ok(xhr.getResponseHeader('X-Custom-Header-Bytes') == "\xE2\x80\xA6", 'getResponseHeader byte-inflates the output');
+    SimpleTest.finish();
+  }
+}
+xhr.send(null);
+</script>
+</pre>
+</body>
+</html>
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -597,17 +597,17 @@ nsresult ChannelMediaResource::OpenChann
 
     nsCOMPtr<nsIStreamListener> listener = mListener.get();
 
     // Ensure that if we're loading cross domain, that the server is sending
     // an authorizing Access-Control header.
     nsHTMLMediaElement* element = mDecoder->GetMediaElement();
     NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
     if (element->ShouldCheckAllowOrigin()) {
-      nsCORSListenerProxy* crossSiteListener =
+      nsRefPtr<nsCORSListenerProxy> crossSiteListener =
         new nsCORSListenerProxy(mListener,
                                 element->NodePrincipal(),
                                 false);
       nsresult rv = crossSiteListener->Init(mChannel);
       listener = crossSiteListener;
       NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
       NS_ENSURE_SUCCESS(rv, rv);
     } else {
--- a/dom/apps/src/Webapps.js
+++ b/dom/apps/src/Webapps.js
@@ -60,18 +60,18 @@ WebappsRegistry.prototype = {
       case "Webapps:GetSelf:Return:OK":
         if (msg.apps.length) {
           app = msg.apps[0];
           Services.DOMRequest.fireSuccess(req, createApplicationObject(this._window, app));
         } else {
           Services.DOMRequest.fireSuccess(req, null);
         }
         break;
-      case "Webapps:IsInstalled:Return:OK":
-        Services.DOMRequest.fireSuccess(req, msg.installed);
+      case "Webapps:CheckInstalled:Return:OK":
+        Services.DOMRequest.fireSuccess(req, msg.app);
         break;
       case "Webapps:GetInstalled:Return:OK":
         Services.DOMRequest.fireSuccess(req, convertAppsArray(msg.apps, this._window));
         break;
     }
     this.removeRequest(msg.requestID);
   },
 
@@ -154,25 +154,25 @@ WebappsRegistry.prototype = {
     let request = this.createRequest();
     cpmm.sendAsyncMessage("Webapps:GetSelf", { origin: this._getOrigin(this._window.location.href),
                                                appId: this._window.document.nodePrincipal.appId,
                                                oid: this._id,
                                                requestID: this.getRequestId(request) });
     return request;
   },
 
-  isInstalled: function(aManifestURL) {
+  checkInstalled: function(aManifestURL) {
     let manifestURL = Services.io.newURI(aManifestURL, null, this._window.document.baseURIObject);
     this._window.document.nodePrincipal.checkMayLoad(manifestURL, true, false);
 
     let request = this.createRequest();
-    cpmm.sendAsyncMessage("Webapps:IsInstalled", { origin: this._getOrigin(this._window.location.href),
-                                                   manifestURL: manifestURL.spec,
-                                                   oid: this._id,
-                                                   requestID: this.getRequestId(request) });
+    cpmm.sendAsyncMessage("Webapps:CheckInstalled", { origin: this._getOrigin(this._window.location.href),
+                                                      manifestURL: manifestURL.spec,
+                                                      oid: this._id,
+                                                      requestID: this.getRequestId(request) });
     return request;
   },
 
   getInstalled: function() {
     let request = this.createRequest();
     cpmm.sendAsyncMessage("Webapps:GetInstalled", { origin: this._getOrigin(this._window.location.href),
                                                     oid: this._id,
                                                     requestID: this.getRequestId(request) });
@@ -254,17 +254,17 @@ WebappsRegistry.prototype = {
     return request;
   },
 
   // nsIDOMGlobalPropertyInitializer implementation
   init: function(aWindow) {
     this.initHelper(aWindow, ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
                               "Webapps:GetInstalled:Return:OK",
                               "Webapps:GetSelf:Return:OK",
-                              "Webapps:IsInstalled:Return:OK" ]);
+                              "Webapps:CheckInstalled:Return:OK" ]);
 
     let util = this._window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     this._id = util.outerWindowID;
     cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
                           ["Webapps:Install:Return:OK"]);
   },
 
   classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -149,17 +149,17 @@ let DOMApplicationRegistry = {
   appsFile: null,
   webapps: { },
   children: [ ],
   allAppsLaunchable: false,
   downloads: { },
 
   init: function() {
     this.messages = ["Webapps:Install", "Webapps:Uninstall",
-                     "Webapps:GetSelf", "Webapps:IsInstalled",
+                     "Webapps:GetSelf", "Webapps:CheckInstalled",
                      "Webapps:GetInstalled", "Webapps:GetNotInstalled",
                      "Webapps:Launch", "Webapps:GetAll",
                      "Webapps:InstallPackage", "Webapps:GetBasePath",
                      "Webapps:GetList", "Webapps:RegisterForMessages",
                      "Webapps:CancelDownload", "Webapps:CheckForUpdate",
                      "Webapps::Download", "Webapps::ApplyDownload",
                      "child-process-shutdown"];
 
@@ -556,18 +556,18 @@ let DOMApplicationRegistry = {
         break;
       case "Webapps:Uninstall":
         this.uninstall(msg, mm);
         debug("Webapps:Uninstall");
         break;
       case "Webapps:Launch":
         this.launchApp(msg, mm);
         break;
-      case "Webapps:IsInstalled":
-        this.isInstalled(msg, mm);
+      case "Webapps:CheckInstalled":
+        this.checkInstalled(msg, mm);
         break;
       case "Webapps:GetInstalled":
         this.getInstalled(msg, mm);
         break;
       case "Webapps:GetNotInstalled":
         this.getNotInstalled(msg, mm);
         break;
       case "Webapps:GetAll":
@@ -1449,27 +1449,35 @@ let DOMApplicationRegistry = {
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       aMm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
     }).bind(this));
   },
 
-  isInstalled: function(aData, aMm) {
-    aData.installed = false;
+  checkInstalled: function(aData, aMm) {
+    aData.app = null;
+    let tmp = [];
 
     for (let appId in this.webapps) {
       if (this.webapps[appId].manifestURL == aData.manifestURL) {
-        aData.installed = true;
+        aData.app = AppsUtils.cloneAppObject(this.webapps[appId]);
+        tmp.push({ id: appId });
         break;
       }
     }
 
-    aMm.sendAsyncMessage("Webapps:IsInstalled:Return:OK", aData);
+    this._readManifests(tmp, (function(aResult) {
+      for (let i = 0; i < aResult.length; i++) {
+        aData.app.manifest = aResult[i].manifest;
+        break;
+      }
+      aMm.sendAsyncMessage("Webapps:CheckInstalled:Return:OK", aData);
+    }).bind(this));
   },
 
   getInstalled: function(aData, aMm) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       if (this.webapps[id].installOrigin == aData.origin &&
--- a/dom/interfaces/apps/nsIDOMApplicationRegistry.idl
+++ b/dom/interfaces/apps/nsIDOMApplicationRegistry.idl
@@ -117,17 +117,17 @@ interface mozIDOMApplicationMgmt : nsISu
   /**
    * Applies a downloaded update.
    * This function is a no-op if it's passed an app object which doesn't have
    * |readyToApplyDownload| set to true.
    */
   void applyDownload(in mozIDOMApplication app);
 };
 
-[scriptable, uuid(7ca34d3e-d855-4d0a-a3b3-58c0acad9ec3)]
+[scriptable, uuid(abfc6c15-8b92-4b9a-b892-52e6ae76f379)]
 interface mozIDOMApplicationRegistry : nsISupports
 {
   /**
    * Install a web app.
    *
    * @param manifestUrl : the URL of the webapps manifest.
    * @param parameters  : A structure with optional information.
    *                      {
@@ -139,19 +139,19 @@ interface mozIDOMApplicationRegistry : n
   nsIDOMDOMRequest install(in DOMString manifestUrl, [optional] in jsval parameters);
 
   /**
    * the request will return the application currently installed, or null.
    */
   nsIDOMDOMRequest getSelf();
 
   /**
-   * the request will return true if the app from that origin is installed
+   * the request will return the application if the app from that origin is installed
    */
-  nsIDOMDOMRequest isInstalled(in DOMString manifestUrl);
+  nsIDOMDOMRequest checkInstalled(in DOMString manifestUrl);
 
   /**
    * the request will return the applications installed from this origin, or null.
    */
   nsIDOMDOMRequest getInstalled();
 
   readonly attribute mozIDOMApplicationMgmt mgmt;
 };
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -234,22 +234,22 @@ ContentParent::MaybeTakePreallocatedAppP
 /*static*/ void
 ContentParent::StartUp()
 {
     if (XRE_GetProcessType() != GeckoProcessType_Default) {
         return;
     }
 
     sKeepAppProcessPreallocated =
-        Preferences::GetBool("dom.ipc.processPrelauch.enabled", false);
+        Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false);
     if (sKeepAppProcessPreallocated) {
         ClearOnShutdown(&sPreallocatedAppProcess);
 
         sPreallocateDelayMs = Preferences::GetUint(
-            "dom.ipc.processPrelauch.delayMs", 1000);
+            "dom.ipc.processPrelaunch.delayMs", 1000);
 
         MOZ_ASSERT(!sPreallocateAppProcessTask);
         ScheduleDelayedPreallocateAppProcess();
     }
 }
 
 /*static*/ void
 ContentParent::ShutDown()
--- a/dom/plugins/base/nsIPluginInstanceOwner.idl
+++ b/dom/plugins/base/nsIPluginInstanceOwner.idl
@@ -14,17 +14,17 @@ interface nsIDocument;
 #include "nsNPAPIPluginInstance.h"
 class nsPluginEvent;
 %}
 
 [ptr] native nsNPAPIPluginInstancePtr(nsNPAPIPluginInstance);
 
 // Do not make this interface scriptable, because the virtual functions in C++
 // blocks will make script call the wrong functions.
-[uuid(23bd0a76-a5dc-4a1d-be76-13d7a0dfd9ff)]
+[uuid(CE1EE148-B201-4DC7-8A65-311143EA01BF)]
 interface nsIPluginInstanceOwner : nsISupports
 {
   /**
    * Let the owner know what its instance is
    */
   void setInstance(in nsNPAPIPluginInstancePtr aInstance);
 
   /**
@@ -114,9 +114,15 @@ interface nsIPluginInstanceOwner : nsISu
 %{C++
   virtual void SendIdleEvent() = 0;
 %}
 
   /**
    * Call NPP_SetWindow on the plugin.
    */
   void callSetWindow();
+
+  /**
+   * Get the contents scale factor for the screen the plugin is
+   * drawn on.
+   */
+  double getContentsScaleFactor();
 };
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -89,16 +89,19 @@ using mozilla::plugins::PluginModulePare
 
 #ifdef MOZ_X11
 #include "mozilla/X11Util.h"
 #endif
 
 #ifdef XP_WIN
 #include <windows.h>
 #include "nsWindowsHelpers.h"
+#ifdef ACCESSIBILITY
+#include "mozilla/a11y/Compatibility.h"
+#endif
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include <android/log.h>
 #include "android_npapi.h"
 #include "ANPBase.h"
 #include "AndroidBridge.h"
 #undef LOG
@@ -249,21 +252,34 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
   if (PR_GetEnv("MOZ_DISABLE_OOP_PLUGINS")) {
     return false;
   }
 
   if (!aPluginTag) {
     return false;
   }
 
+#ifdef ACCESSIBILITY
+  // Certain assistive technologies don't want oop Flash, thus we have a special
+  // pref for them to disable oop Flash (refer to bug 785047 for details).
+  bool useA11yPref = false;
+#endif
+
 #ifdef XP_WIN
+  useA11yPref =  a11y::Compatibility::IsJAWS();
+
   // On Windows Vista+, we force Flash to run in OOPP mode because Adobe
   // doesn't test Flash in-process and there are known stability bugs.
   if (aPluginTag->mIsFlashPlugin && IsVistaOrLater()) {
+#ifdef ACCESSIBILITY
+    if (!useA11yPref)
+      return true;
+#else
     return true;
+#endif
   }
 #endif
 
   nsIPrefBranch* prefs = Preferences::GetRootBranch();
   if (!prefs) {
     return false;
   }
 
@@ -286,16 +302,21 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
   nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.x86_64.");
 #elif defined(__ppc__)
   nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.ppc.");
 #endif
 #else
   nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.");
 #endif
 
+#ifdef ACCESSIBILITY
+  if (useA11yPref)
+    prefGroupKey.AssignLiteral("dom.ipc.plugins.enabled.a11y.");
+#endif
+
   // Java plugins include a number of different file names,
   // so use the mime type (mIsJavaPlugin) and a special pref.
   if (aPluginTag->mIsJavaPlugin &&
       !Preferences::GetBool("dom.ipc.plugins.java.enabled", true)) {
     return false;
   }
 
   uint32_t prefCount;
@@ -340,16 +361,19 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
 #if defined(__i386__)
     Preferences::GetBool("dom.ipc.plugins.enabled.i386", false);
 #elif defined(__x86_64__)
     Preferences::GetBool("dom.ipc.plugins.enabled.x86_64", false);
 #elif defined(__ppc__)
     Preferences::GetBool("dom.ipc.plugins.enabled.ppc", false);
 #endif
 #else
+#ifdef ACCESSIBILITY
+    useA11yPref ? Preferences::GetBool("dom.ipc.plugins.enabled.a11y", false) :
+#endif
     Preferences::GetBool("dom.ipc.plugins.enabled", false);
 #endif
   }
 
   return oopPluginsEnabled;
 }
 
 inline PluginLibrary*
@@ -2114,16 +2138,24 @@ NPError NP_CALLBACK
 
     return NPERR_NO_ERROR;
   }
 
   case NPNVsupportsUpdatedCocoaTextInputBool: {
     *(NPBool*)result = true;
     return NPERR_NO_ERROR;
   }
+
+  case NPNVcontentsScaleFactor: {
+    nsNPAPIPluginInstance *inst =
+      (nsNPAPIPluginInstance *) (npp ? npp->ndata : nullptr);
+    double scaleFactor = inst ? inst->GetContentsScaleFactor() : 1.0;
+    *(double*)result = scaleFactor;
+    return NPERR_NO_ERROR;
+  }
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
     case kLogInterfaceV0_ANPGetValue: {
       LOG("get log interface");
       ANPLogInterfaceV0 *i = (ANPLogInterfaceV0 *) result;
       InitLogInterface(i);
       return NPERR_NO_ERROR;
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -1711,8 +1711,18 @@ nsNPAPIPluginInstance::CarbonNPAPIFailur
   }
 
   nsCOMPtr<nsIRunnable> e = new CarbonEventModelFailureEvent(content);
   nsresult rv = NS_DispatchToCurrentThread(e);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to dispatch CarbonEventModelFailureEvent.");
   }
 }
+
+double
+nsNPAPIPluginInstance::GetContentsScaleFactor()
+{
+  double scaleFactor = 1.0;
+  if (mOwner) {
+    mOwner->GetContentsScaleFactor(&scaleFactor);
+  }
+  return scaleFactor;
+}
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -261,16 +261,19 @@ public:
                            void *initData, NPAsyncSurface *surface);
   NPError FinalizeAsyncSurface(NPAsyncSurface *surface);
   void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed);
 
   // Called when the instance fails to instantiate beceause the Carbon
   // event model is not supported.
   void CarbonNPAPIFailure();
 
+  // Returns the contents scale factor of the screen the plugin is drawn on.
+  double GetContentsScaleFactor();
+
 protected:
 
   nsresult GetTagType(nsPluginTagType *result);
   nsresult GetAttributes(uint16_t& n, const char*const*& names,
                          const char*const*& values);
   nsresult GetParameters(uint16_t& n, const char*const*& names,
                          const char*const*& values);
   nsresult GetMode(int32_t *result);
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -659,16 +659,22 @@ NS_IMETHODIMP nsPluginInstanceOwner::Inv
                                   invalidRect->bottom - invalidRect->top));
     return NS_OK;
   }
 #endif
   nsIntRect rect(invalidRect->left,
                  invalidRect->top,
                  invalidRect->right - invalidRect->left,
                  invalidRect->bottom - invalidRect->top);
+  // invalidRect is in "display pixels".  In non-HiDPI modes "display pixels"
+  // are device pixels.  But in HiDPI modes each display pixel corresponds
+  // to more than one device pixel.
+  double scaleFactor = 1.0;
+  GetContentsScaleFactor(&scaleFactor);
+  rect.ScaleRoundOut(scaleFactor);
   mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN, &rect);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
@@ -1492,26 +1498,34 @@ void nsPluginInstanceOwner::RenderCoreAn
 {
   if (aWidth == 0 || aHeight == 0)
     return;
 
   if (!mCARenderer) {
     mCARenderer = new nsCARenderer();
   }
 
+  // aWidth and aHeight are in "display pixels".  In non-HiDPI modes
+  // "display pixels" are device pixels.  But in HiDPI modes each
+  // display pixel corresponds to more than one device pixel.
+  double scaleFactor = 1.0;
+  GetContentsScaleFactor(&scaleFactor);
+
   if (!mIOSurface ||
       (mIOSurface->GetWidth() != (size_t)aWidth ||
-       mIOSurface->GetHeight() != (size_t)aHeight)) {
+       mIOSurface->GetHeight() != (size_t)aHeight ||
+       mIOSurface->GetContentsScaleFactor() != scaleFactor)) {
     mIOSurface = nullptr;
 
     // If the renderer is backed by an IOSurface, resize it as required.
-    mIOSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight);
+    mIOSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight, scaleFactor);
     if (mIOSurface) {
       RefPtr<MacIOSurface> attachSurface = MacIOSurface::LookupSurface(
-                                              mIOSurface->GetIOSurfaceID());
+                                              mIOSurface->GetIOSurfaceID(),
+                                              scaleFactor);
       if (attachSurface) {
         mCARenderer->AttachIOSurface(attachSurface);
       } else {
         NS_ERROR("IOSurface attachment failed");
         mIOSurface = nullptr;
       }
     }
   }
@@ -1524,34 +1538,35 @@ void nsPluginInstanceOwner::RenderCoreAn
     void *caLayer = NULL;
     nsresult rv = mInstance->GetValueFromPlugin(NPPVpluginCoreAnimationLayer, &caLayer);
     if (NS_FAILED(rv) || !caLayer) {
       return;
     }
 
     // We don't run Flash in-process so we can unconditionally disallow
     // the offliner renderer.
-    mCARenderer->SetupRenderer(caLayer, aWidth, aHeight, DISALLOW_OFFLINE_RENDERER);
+    mCARenderer->SetupRenderer(caLayer, aWidth, aHeight, scaleFactor,
+                               DISALLOW_OFFLINE_RENDERER);
 
     // Setting up the CALayer requires resetting the painting otherwise we
     // get garbage for the first few frames.
     FixUpPluginWindow(ePluginPaintDisable);
     FixUpPluginWindow(ePluginPaintEnable);
   }
 
   CGImageRef caImage = NULL;
-  nsresult rt = mCARenderer->Render(aWidth, aHeight, &caImage);
+  nsresult rt = mCARenderer->Render(aWidth, aHeight, scaleFactor, &caImage);
   if (rt == NS_OK && mIOSurface && mColorProfile) {
     nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, mColorProfile,
                                          0, 0, aWidth, aHeight);
   } else if (rt == NS_OK && caImage != NULL) {
     // Significant speed up by resetting the scaling
     ::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone );
-    ::CGContextTranslateCTM(aCGContext, 0, aHeight);
-    ::CGContextScaleCTM(aCGContext, 1.0, -1.0);
+    ::CGContextTranslateCTM(aCGContext, 0, (double) aHeight * scaleFactor);
+    ::CGContextScaleCTM(aCGContext, scaleFactor, -scaleFactor);
 
     ::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage);
   } else {
     NS_NOTREACHED("nsCARenderer::Render failure");
   }
 }
 
 void* nsPluginInstanceOwner::GetPluginPortCopy()
@@ -2146,22 +2161,27 @@ nsEventStatus nsPluginInstanceOwner::Pro
   EventRecord synthCarbonEvent;
 #endif
   NPCocoaEvent synthCocoaEvent;
   void* event = anEvent.pluginEvent;
   nsPoint pt =
   nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) -
   mObjectFrame->GetContentRectRelativeToSelf().TopLeft();
   nsPresContext* presContext = mObjectFrame->PresContext();
-  nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
-                  presContext->AppUnitsToDevPixels(pt.y));
+  // Plugin event coordinates need to be translated from device pixels
+  // into "display pixels" in HiDPI modes.
+  double scaleFactor = 1.0;
+  GetContentsScaleFactor(&scaleFactor);
+  size_t intScaleFactor = ceil(scaleFactor);
+  nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor,
+                  presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor);
 #ifndef NP_NO_CARBON
   nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
-  ::Point carbonPt = { static_cast<short>(ptPx.y + geckoScreenCoords.y),
-                       static_cast<short>(ptPx.x + geckoScreenCoords.x) };
+  ::Point carbonPt = { static_cast<short>(ptPx.y + geckoScreenCoords.y / intScaleFactor),
+                       static_cast<short>(ptPx.x + geckoScreenCoords.x / intScaleFactor) };
   if (eventModel == NPEventModelCarbon) {
     if (event && anEvent.eventStructType == NS_MOUSE_EVENT) {
       static_cast<EventRecord*>(event)->where = carbonPt;
     }
   }
 #endif
   if (!event) {
 #ifndef NP_NO_CARBON
@@ -2802,32 +2822,42 @@ nsPluginInstanceOwner::Destroy()
 
 // Paints are handled differently, so we just simulate an update event.
 
 #ifdef XP_MACOSX
 void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgContext)
 {
   if (!mInstance || !mObjectFrame)
     return;
- 
+
+  gfxRect dirtyRectCopy = aDirtyRect; 
+  double scaleFactor = 1.0;
+  GetContentsScaleFactor(&scaleFactor);
+  if (scaleFactor != 1.0) {
+    ::CGContextScaleCTM(cgContext, scaleFactor, scaleFactor);
+    // Convert aDirtyRect from device pixels to "display pixels"
+    // for HiDPI modes
+    dirtyRectCopy.ScaleRoundOut(1.0 / scaleFactor);
+  }
+
   nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
   if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
 #ifndef NP_NO_CARBON
     void* window = FixUpPluginWindow(ePluginPaintEnable);
     if (GetEventModel() == NPEventModelCarbon && window) {
       EventRecord updateEvent;
       InitializeEventRecord(&updateEvent, nullptr);
       updateEvent.what = updateEvt;
       updateEvent.message = UInt32(window);
 
       mInstance->HandleEvent(&updateEvent, nullptr);
     } else if (GetEventModel() == NPEventModelCocoa)
 #endif
     {
-      DoCocoaEventDrawRect(aDirtyRect, cgContext);
+      DoCocoaEventDrawRect(dirtyRectCopy, cgContext);
     }
     pluginWidget->EndDrawPlugin();
   }
 }
 
 void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext)
 {
   if (!mInstance || !mObjectFrame)
@@ -3465,18 +3495,24 @@ void* nsPluginInstanceOwner::FixUpPlugin
   if (eventModel == NPEventModelCarbon) {
     NS_NPAPI_CarbonWindowFrame(static_cast<WindowRef>(static_cast<NP_CGContext*>(pluginPort)->window), windowRect);
   } else
 #endif
   {
     NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect);
   }
 
-  mPluginWindow->x = geckoScreenCoords.x - windowRect.x;
-  mPluginWindow->y = geckoScreenCoords.y - windowRect.y;
+  double scaleFactor = 1.0;
+  GetContentsScaleFactor(&scaleFactor);
+  int intScaleFactor = ceil(scaleFactor);
+
+  // Convert geckoScreenCoords from device pixels to "display pixels"
+  // for HiDPI modes.
+  mPluginWindow->x = geckoScreenCoords.x/intScaleFactor - windowRect.x;
+  mPluginWindow->y = geckoScreenCoords.y/intScaleFactor - windowRect.y;
 
   NPRect oldClipRect = mPluginWindow->clipRect;
   
   // fix up the clipping region
   mPluginWindow->clipRect.top    = widgetClip.y;
   mPluginWindow->clipRect.left   = widgetClip.x;
 
   if (!mWidgetVisible || inPaintState == ePluginPaintDisable) {
@@ -3684,16 +3720,44 @@ void nsPluginInstanceOwner::RemoveScroll
         sf->RemoveScrollPositionListener(this);
       }
     }
     mRegisteredScrollPositionListener = false;
   }
 }
 #endif
 
+NS_IMETHODIMP
+nsPluginInstanceOwner::GetContentsScaleFactor(double *result)
+{
+  NS_ENSURE_ARG_POINTER(result);
+  double scaleFactor = 1.0;
+  if (mWidget) {
+    scaleFactor = mWidget->GetDefaultScale();
+  } else {
+    nsCOMPtr<nsIScreenManager> screenMgr =
+      do_GetService("@mozilla.org/gfx/screenmanager;1");
+    if (screenMgr) {
+      nsCOMPtr<nsIScreen> screen;
+      nsIntRect screenRect = mObjectFrame->GetScreenRect();
+      screenMgr->ScreenForRect(screenRect.x, screenRect.y,
+                               screenRect.width, screenRect.height,
+                               getter_AddRefs(screen));
+      if (screen) {
+        nsresult rv = screen->GetContentsScaleFactor(&scaleFactor);
+        if (NS_FAILED(rv)) {
+          scaleFactor = 1.0;
+        }
+      }
+    }
+  }
+  *result = scaleFactor;
+  return NS_OK;
+}
+
 void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
 {
   // Don't do anything if the frame situation hasn't changed.
   if (mObjectFrame == aFrame) {
     return;
   }
 
   // If we already have a frame that is changing or going away...
--- a/dom/plugins/ipc/NPEventOSX.h
+++ b/dom/plugins/ipc/NPEventOSX.h
@@ -11,16 +11,17 @@
 #include "npapi.h"
 
 namespace mozilla {
 
 namespace plugins {
 
 struct NPRemoteEvent {
     NPCocoaEvent event;
+    double contentsScaleFactor;
 };
 
 } // namespace plugins
 
 } // namespace mozilla
 
 namespace IPC {
 
@@ -73,16 +74,17 @@ struct ParamTraits<mozilla::plugins::NPR
                 break;
             case NPCocoaEventTextInput:
                 WriteParam(aMsg, aParam.event.data.text.text);
                 break;
             default:
                 NS_NOTREACHED("Attempted to serialize unknown event type.");
                 return;
         }
+        aMsg->WriteDouble(aParam.contentsScaleFactor);
     }
 
     static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
     {
         int type = 0;
         if (!aMsg->ReadInt(aIter, &type)) {
             return false;
         }
@@ -169,16 +171,19 @@ struct ParamTraits<mozilla::plugins::NPR
                 if (!ReadParam(aMsg, aIter, &aResult->event.data.text.text)) {
                     return false;
                 }
                 break;
             default:
                 NS_NOTREACHED("Attempted to de-serialize unknown event type.");
                 return false;
         }
+        if (!aMsg->ReadDouble(aIter, &aResult->contentsScaleFactor)) {
+            return false;
+        }
 
         return true;
     }
 
     static void Log(const paramType& aParam, std::wstring* aLog)
     {
         aLog->append(L"(NPCocoaEvent)");
     }
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -34,16 +34,17 @@ using nsIntRect;
 using nsTextEvent;
 using nsKeyEvent;
 
 namespace mozilla {
 namespace plugins {
 
 struct IOSurfaceDescriptor {
   uint32_t surfaceId;
+  double contentsScaleFactor;
 };
 
 union SurfaceDescriptor {
   Shmem;
   SurfaceDescriptorX11;
   PPluginSurface; // used on Windows
   IOSurfaceDescriptor; // used on OSX 10.5+
   // Descriptor can be null here in case
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -98,16 +98,19 @@ template<>
 struct RunnableMethodTraits<PluginInstanceChild>
 {
     static void RetainCallee(PluginInstanceChild* obj) { }
     static void ReleaseCallee(PluginInstanceChild* obj) { }
 };
 
 PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
     : mPluginIface(aPluginIface)
+#if defined(XP_MACOSX)
+    , mContentsScaleFactor(1.0)
+#endif
     , mDrawingModel(kDefaultDrawingModel)
     , mCurrentAsyncSurface(0)
     , mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex")
     , mAsyncInvalidateTask(0)
     , mCachedWindowActor(nullptr)
     , mCachedElementActor(nullptr)
 #if defined(MOZ_WIDGET_GTK)
     , mXEmbed(false)
@@ -428,16 +431,21 @@ PluginInstanceChild::NPN_GetValue(NPNVar
       return NPERR_NO_ERROR;
     }
 
 #ifndef NP_NO_QUICKDRAW
     case NPNVsupportsQuickDrawBool: {
         *((NPBool*)aValue) = false;
         return NPERR_NO_ERROR;
     }
+
+    case NPNVcontentsScaleFactor: {
+        *static_cast<double*>(aValue) = mContentsScaleFactor;
+        return NPERR_NO_ERROR;
+    }
 #endif /* NP_NO_QUICKDRAW */
 #endif /* XP_MACOSX */
 
 #ifdef DEBUG
     case NPNVjavascriptEnabledBool:
     case NPNVasdEnabledBool:
     case NPNVisOfflineBool:
     case NPNVSupportsXEmbedBool:
@@ -728,16 +736,22 @@ PluginInstanceChild::AnswerNPP_HandleEve
     if (GraphicsExpose == event.event.type)
         PLUGIN_LOG_DEBUG(("  received drawable 0x%lx\n",
                           event.event.xgraphicsexpose.drawable));
 #endif
 
 #ifdef XP_MACOSX
     // Mac OS X does not define an NPEvent structure. It defines more specific types.
     NPCocoaEvent evcopy = event.event;
+    // event.contentsScaleFactor <= 0 is a signal we shouldn't use it,
+    // for example when AnswerNPP_HandleEvent() is called from elsewhere
+    // in the child process (not via rpc code from the parent process).
+    if (event.contentsScaleFactor > 0) {
+      mContentsScaleFactor = event.contentsScaleFactor;
+    }
 
     // Make sure we reset mCurrentEvent in case of an exception
     AutoRestore<const NPCocoaEvent*> savePreviousEvent(mCurrentEvent);
 
     // Track the current event for NPN_PopUpContextMenu.
     mCurrentEvent = &event.event;
 #else
     // Make a copy since we may modify values.
@@ -813,32 +827,35 @@ PluginInstanceChild::AnswerNPP_HandleEve
                                                  Shmem* rtnmem)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
 
     PaintTracker pt;
 
     NPCocoaEvent evcopy = event.event;
+    mContentsScaleFactor = event.contentsScaleFactor;
 
     if (evcopy.type == NPCocoaEventDrawRect) {
+        int scaleFactor = ceil(mContentsScaleFactor);
         if (!mShColorSpace) {
             mShColorSpace = CreateSystemColorSpace();
             if (!mShColorSpace) {
                 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
                 *handled = false;
                 *rtnmem = mem;
                 return true;
             } 
         }
         if (!mShContext) {
             void* cgContextByte = mem.get<char>();
             mShContext = ::CGBitmapContextCreate(cgContextByte, 
-                              mWindow.width, mWindow.height, 8, 
-                              mWindow.width * 4, mShColorSpace, 
+                              mWindow.width * scaleFactor,
+                              mWindow.height * scaleFactor, 8, 
+                              mWindow.width * 4 * scaleFactor, mShColorSpace, 
                               kCGImageAlphaPremultipliedFirst |
                               kCGBitmapByteOrder32Host);
     
             if (!mShContext) {
                 PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
                 *handled = false;
                 *rtnmem = mem;
                 return true;
@@ -895,16 +912,18 @@ PluginInstanceChild::CGDraw(CGContextRef
   drawEvent.version = 0;
   drawEvent.data.draw.x = aUpdateRect.x;
   drawEvent.data.draw.y = aUpdateRect.y;
   drawEvent.data.draw.width = aUpdateRect.width;
   drawEvent.data.draw.height = aUpdateRect.height;
   drawEvent.data.draw.context = ref;
 
   NPRemoteEvent remoteDrawEvent = {drawEvent};
+  // Signal to AnswerNPP_HandleEvent() not to use this value
+  remoteDrawEvent.contentsScaleFactor = -1.0;
 
   int16_t handled;
   AnswerNPP_HandleEvent(remoteDrawEvent, &handled);
   return handled == true;
 }
 
 bool
 PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
@@ -912,17 +931,19 @@ PluginInstanceChild::AnswerNPP_HandleEve
                                                      int16_t* handled)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
 
     PaintTracker pt;
 
     NPCocoaEvent evcopy = event.event;
-    RefPtr<MacIOSurface> surf = MacIOSurface::LookupSurface(surfaceid);
+    mContentsScaleFactor = event.contentsScaleFactor;
+    RefPtr<MacIOSurface> surf = MacIOSurface::LookupSurface(surfaceid,
+                                                            mContentsScaleFactor);
     if (!surf) {
         NS_ERROR("Invalid IOSurface.");
         *handled = false;
         return false;
     }
 
     if (!mCARenderer) {
       mCARenderer = new nsCARenderer();
@@ -939,31 +960,33 @@ PluginInstanceChild::AnswerNPP_HandleEve
             if (result != NPERR_NO_ERROR || !caLayer) {
                 PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
                                   "provide CALayer."));
                 *handled = false;
                 return false;
             }
 
             mCARenderer->SetupRenderer(caLayer, mWindow.width, mWindow.height,
+                            mContentsScaleFactor,
                             GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ?
                             ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
 
             // Flash needs to have the window set again after this step
             if (mPluginIface->setwindow)
                 (void) mPluginIface->setwindow(&mData, &mWindow);
         }
     } else {
         PLUGIN_LOG_DEBUG(("Invalid event type for "
                           "AnswerNNP_HandleEvent_IOSurface."));
         *handled = false;
         return false;
     } 
 
-    mCARenderer->Render(mWindow.width, mWindow.height, nullptr);
+    mCARenderer->Render(mWindow.width, mWindow.height,
+                        mContentsScaleFactor, nullptr);
 
     return true;
 
 }
 
 #else
 bool
 PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
@@ -1179,16 +1202,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
 #elif defined(XP_MACOSX)
 
     mWindow.x = aWindow.x;
     mWindow.y = aWindow.y;
     mWindow.width = aWindow.width;
     mWindow.height = aWindow.height;
     mWindow.clipRect = aWindow.clipRect;
     mWindow.type = aWindow.type;
+    mContentsScaleFactor = aWindow.contentsScaleFactor;
 
     if (mShContext) {
         // Release the shared context so that it is reallocated
         // with the new size. 
         ::CGContextRelease(mShContext);
         mShContext = nullptr;
     }
 
@@ -2763,16 +2787,19 @@ PluginInstanceChild::DoAsyncSetWindow(co
         mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height);
 
     mWindow.x = aWindow.x;
     mWindow.y = aWindow.y;
     mWindow.width = aWindow.width;
     mWindow.height = aWindow.height;
     mWindow.clipRect = aWindow.clipRect;
     mWindow.type = aWindow.type;
+#ifdef XP_MACOSX
+    mContentsScaleFactor = aWindow.contentsScaleFactor;
+#endif
 
     if (GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT)
         mIsTransparent = true;
 
     mLayersRendering = true;
     mSurfaceType = aSurfaceType;
     UpdateWindowAttributes(true);
 
@@ -3019,23 +3046,24 @@ PluginInstanceChild::EnsureCurrentBuffer
                 return false;
             }
         }
         mDoubleBufferCARenderer.SetCALayer(caLayer);
     }
 
     if (mDoubleBufferCARenderer.HasFrontSurface() &&
         (mDoubleBufferCARenderer.GetFrontSurfaceWidth() != mWindow.width ||
-         mDoubleBufferCARenderer.GetFrontSurfaceHeight() != mWindow.height) ) {
+         mDoubleBufferCARenderer.GetFrontSurfaceHeight() != mWindow.height ||
+         mDoubleBufferCARenderer.GetContentsScaleFactor() != mContentsScaleFactor)) {
         mDoubleBufferCARenderer.ClearFrontSurface();
     }
 
     if (!mDoubleBufferCARenderer.HasFrontSurface()) {
         bool allocSurface = mDoubleBufferCARenderer.InitFrontSurface(
-                                mWindow.width, mWindow.height,
+                                mWindow.width, mWindow.height, mContentsScaleFactor,
                                 GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ?
                                 ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER);
         if (!allocSurface) {
             PLUGIN_LOG_DEBUG(("Fail to allocate front IOSurface"));
             return false;
         }
 
         if (mPluginIface->setwindow)
@@ -3475,17 +3503,18 @@ PluginInstanceChild::ShowPluginFrame()
             mozilla::plugins::PluginUtilsOSX::Repaint(mCGLayer, rect);
         }
 
         mDoubleBufferCARenderer.Render();
 
         NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
                      (uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
         SurfaceDescriptor currSurf;
-        currSurf = IOSurfaceDescriptor(mDoubleBufferCARenderer.GetFrontSurfaceID());
+        currSurf = IOSurfaceDescriptor(mDoubleBufferCARenderer.GetFrontSurfaceID(),
+                                       mDoubleBufferCARenderer.GetContentsScaleFactor());
 
         mHasPainted = true;
 
         SurfaceDescriptor returnSurf;
 
         if (!SendShow(r, currSurf, &returnSurf)) {
             return false;
         }
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -352,16 +352,19 @@ private:
         LPARAM               mLParam;
         bool                 mWindowed;
     };
 
 #endif
     const NPPluginFuncs* mPluginIface;
     NPP_t mData;
     NPWindow mWindow;
+#if defined(XP_MACOSX)
+    double mContentsScaleFactor;
+#endif
     int16_t               mDrawingModel;
     NPAsyncSurface* mCurrentAsyncSurface;
     struct AsyncBitmapData {
       void *mRemotePtr;
       Shmem mShmem;
     };
 
     static PLDHashOperator DeleteSurface(NPAsyncSurface* surf, nsAutoPtr<AsyncBitmapData> &data, void* userArg);
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -563,26 +563,29 @@ PluginInstanceParent::RecvShow(const NPR
             NS_WARNING("back surface not readable");
             return false;
         }
         surface = gfxSharedImageSurface::Open(newSurface.get_Shmem());
     }
 #ifdef XP_MACOSX
     else if (newSurface.type() == SurfaceDescriptor::TIOSurfaceDescriptor) {
         IOSurfaceDescriptor iodesc = newSurface.get_IOSurfaceDescriptor();
-    
-        RefPtr<MacIOSurface> newIOSurface = MacIOSurface::LookupSurface(iodesc.surfaceId());
+
+        RefPtr<MacIOSurface> newIOSurface =
+          MacIOSurface::LookupSurface(iodesc.surfaceId(),
+                                      iodesc.contentsScaleFactor());
 
         if (!newIOSurface) {
             NS_WARNING("Got bad IOSurfaceDescriptor in RecvShow");
             return false;
         }
       
         if (mFrontIOSurface)
-            *prevSurface = IOSurfaceDescriptor(mFrontIOSurface->GetIOSurfaceID());
+            *prevSurface = IOSurfaceDescriptor(mFrontIOSurface->GetIOSurfaceID(),
+                                               mFrontIOSurface->GetContentsScaleFactor());
         else
             *prevSurface = null_t();
 
         mFrontIOSurface = newIOSurface;
 
         RecvNPN_InvalidateRect(updatedRect);
 
         PLUGIN_LOG_DEBUG(("   (RecvShow invalidated for surface %p)",
@@ -652,16 +655,21 @@ PluginInstanceParent::AsyncSetWindow(NPW
     mWindowType = aWindow->type;
     window.window = reinterpret_cast<uint64_t>(aWindow->window);
     window.x = aWindow->x;
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
     window.clipRect = aWindow->clipRect;
     window.type = aWindow->type;
+#ifdef XP_MACOSX
+    double scaleFactor = 1.0;
+    mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor);
+    window.contentsScaleFactor = scaleFactor;
+#endif
     if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
                             window))
         return NS_ERROR_FAILURE;
 
     return NS_OK;
 }
 
 #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
@@ -995,37 +1003,44 @@ PluginInstanceParent::NPP_SetWindow(cons
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
     window.clipRect = aWindow->clipRect; // MacOS specific
     window.type = aWindow->type;
 #endif
 
 #if defined(XP_MACOSX)
-    if (mShWidth != window.width || mShHeight != window.height) {
+    double floatScaleFactor = 1.0;
+    mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &floatScaleFactor);
+    int scaleFactor = ceil(floatScaleFactor);
+    window.contentsScaleFactor = floatScaleFactor;
+
+    if (mShWidth != window.width * scaleFactor || mShHeight != window.height * scaleFactor) {
         if (mDrawingModel == NPDrawingModelCoreAnimation || 
             mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) {
-            mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height);
-        } else if (uint32_t(mShWidth * mShHeight) != window.width * window.height) {
+            mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height,
+                                                       floatScaleFactor);
+        } else if (uint32_t(mShWidth * mShHeight) !=
+                   window.width * scaleFactor * window.height * scaleFactor) {
             if (mShWidth != 0 && mShHeight != 0) {
                 DeallocShmem(mShSurface);
                 mShWidth = 0;
                 mShHeight = 0;
             }
 
             if (window.width != 0 && window.height != 0) {
-                if (!AllocShmem(window.width * window.height*4, 
+                if (!AllocShmem(window.width * scaleFactor * window.height*4 * scaleFactor,
                                 SharedMemory::TYPE_BASIC, &mShSurface)) {
                     PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
                     return NPERR_GENERIC_ERROR;
                 } 
             }
         }
-        mShWidth = window.width;
-        mShHeight = window.height;
+        mShWidth = window.width * scaleFactor;
+        mShHeight = window.height * scaleFactor;
     }
 #endif
 
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     const NPSetWindowCallbackStruct* ws_info =
       static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info);
     window.visualID = ws_info->visual ? ws_info->visual->visualid : None;
     window.colormap = ws_info->colormap;
@@ -1171,16 +1186,21 @@ PluginInstanceParent::NPP_HandleEvent(vo
 
 #if defined(XP_MACOSX)
     NPCocoaEvent* npevent = reinterpret_cast<NPCocoaEvent*>(event);
 #else
     NPEvent* npevent = reinterpret_cast<NPEvent*>(event);
 #endif
     NPRemoteEvent npremoteevent;
     npremoteevent.event = *npevent;
+#if defined(XP_MACOSX)
+    double scaleFactor = 1.0;
+    mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor);
+    npremoteevent.contentsScaleFactor = scaleFactor;
+#endif
     int16_t handled = 0;
 
 #if defined(OS_WIN)
     if (mWindowType == NPWindowTypeDrawable) {
         if (IsAsyncDrawing()) {
             if (npevent->event == WM_PAINT || npevent->event == DoublePassRenderingEvent()) {
                 // This plugin maintains its own async drawing.
                 return handled;
--- a/dom/plugins/ipc/PluginMessageUtils.cpp
+++ b/dom/plugins/ipc/PluginMessageUtils.cpp
@@ -52,16 +52,19 @@ NPRemoteWindow::NPRemoteWindow() :
   window(0), x(0), y(0), width(0), height(0), type(NPWindowTypeDrawable)
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
   , visualID(0)
   , colormap(0)
 #endif /* XP_UNIX */
 #if defined(XP_WIN)
   ,surfaceHandle(0)
 #endif
+#if defined(XP_MACOSX)
+  ,contentsScaleFactor(1.0)
+#endif
 {
   clipRect.top = 0;
   clipRect.left = 0;
   clipRect.bottom = 0;
   clipRect.right = 0;
 }
 
 RPCChannel::RacyRPCPolicy
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -102,16 +102,19 @@ struct NPRemoteWindow
   NPWindowType type;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
   VisualID visualID;
   Colormap colormap;
 #endif /* XP_UNIX */
 #if defined(XP_WIN)
   base::SharedMemoryHandle surfaceHandle;
 #endif
+#if defined(XP_MACOSX)
+  double contentsScaleFactor;
+#endif
 };
 
 #ifdef XP_WIN
 typedef HWND NativeWindowHandle;
 #elif defined(MOZ_X11)
 typedef XID NativeWindowHandle;
 #elif defined(XP_MACOSX) || defined(ANDROID) || defined(MOZ_WIDGET_QT)
 typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
@@ -377,16 +380,19 @@ struct ParamTraits<mozilla::plugins::NPR
     WriteParam(aMsg, aParam.type);
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     aMsg->WriteULong(aParam.visualID);
     aMsg->WriteULong(aParam.colormap);
 #endif
 #if defined(XP_WIN)
     WriteParam(aMsg, aParam.surfaceHandle);
 #endif
+#if defined(XP_MACOSX)
+    aMsg->WriteDouble(aParam.contentsScaleFactor);
+#endif
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     uint64_t window;
     int32_t x, y;
     uint32_t width, height;
     NPRect clipRect;
@@ -409,30 +415,39 @@ struct ParamTraits<mozilla::plugins::NPR
 #endif
 
 #if defined(XP_WIN)
     base::SharedMemoryHandle surfaceHandle;
     if (!ReadParam(aMsg, aIter, &surfaceHandle))
       return false;
 #endif
 
+#if defined(XP_MACOSX)
+    double contentsScaleFactor;
+    if (!aMsg->ReadDouble(aIter, &contentsScaleFactor))
+      return false;
+#endif
+
     aResult->window = window;
     aResult->x = x;
     aResult->y = y;
     aResult->width = width;
     aResult->height = height;
     aResult->clipRect = clipRect;
     aResult->type = type;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     aResult->visualID = visualID;
     aResult->colormap = colormap;
 #endif
 #if defined(XP_WIN)
     aResult->surfaceHandle = surfaceHandle;
 #endif
+#if defined(XP_MACOSX)
+    aResult->contentsScaleFactor = contentsScaleFactor;
+#endif
     return true;
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
     aLog->append(StringPrintf(L"[%u, %d, %d, %u, %u, %d",
                               (unsigned long)aParam.window,
                               aParam.x, aParam.y, aParam.width,
--- a/dom/plugins/ipc/PluginUtilsOSX.h
+++ b/dom/plugins/ipc/PluginUtilsOSX.h
@@ -36,38 +36,55 @@ bool SetProcessName(const char* aProcess
  * without having to unbind nsCARenderer on every surface swaps.
  *
  * The double buffer renderer begins with no initialize surfaces.
  * The buffers can be initialized and cleared individually.
  * Swapping still occurs regardless if the buffers are initialized.
  */
 class THEBES_API nsDoubleBufferCARenderer {
 public:
-  nsDoubleBufferCARenderer() : mCALayer(nullptr) {}
+  nsDoubleBufferCARenderer() : mCALayer(nullptr), mContentsScaleFactor(1.0) {}
+  // Returns width in "display pixels".  A "display pixel" is the smallest
+  // fully addressable part of a display.  But in HiDPI modes each "display
+  // pixel" corresponds to more than one device pixel.  Multiply display pixels
+  // by mContentsScaleFactor to get device pixels.
   size_t GetFrontSurfaceWidth();
+  // Returns height in "display pixels".  Multiply by
+  // mContentsScaleFactor to get device pixels.
   size_t GetFrontSurfaceHeight();
+  // Returns width in "display pixels".  Multiply by
+  // mContentsScaleFactor to get device pixels.
   size_t GetBackSurfaceWidth();
+  // Returns height in "display pixels".  Multiply by
+  // mContentsScaleFactor to get device pixels.
   size_t GetBackSurfaceHeight();
   IOSurfaceID GetFrontSurfaceID();
 
   bool HasBackSurface();
   bool HasFrontSurface();
   bool HasCALayer();
 
   void SetCALayer(void *aCALayer);
-  bool InitFrontSurface(size_t aWidth, size_t aHeight, AllowOfflineRendererEnum aAllowOfflineRenderer);
+  // aWidth and aHeight are in "display pixels".  Multiply by
+  // aContentsScaleFactor to get device pixels.
+  bool InitFrontSurface(size_t aWidth, size_t aHeight,
+                        double aContentsScaleFactor,
+                        AllowOfflineRendererEnum aAllowOfflineRenderer);
   void Render();
   void SwapSurfaces();
   void ClearFrontSurface();
   void ClearBackSurface();
 
+  double GetContentsScaleFactor() { return mContentsScaleFactor; }
+
 private:
   void *mCALayer;
   RefPtr<nsCARenderer> mCARenderer;
   RefPtr<MacIOSurface> mFrontSurface;
   RefPtr<MacIOSurface> mBackSurface;
+  double mContentsScaleFactor;
 };
 
 } // namespace PluginUtilsOSX
 } // namespace plugins
 } // namespace mozilla
 
 #endif //dom_plugins_PluginUtilsOSX_h
--- a/dom/plugins/ipc/PluginUtilsOSX.mm
+++ b/dom/plugins/ipc/PluginUtilsOSX.mm
@@ -9,16 +9,21 @@
 #include "PluginUtilsOSX.h"
 
 // Remove definitions for try/catch interfering with ObjCException macros.
 #include "nsObjCExceptions.h"
 #include "nsCocoaUtils.h"
 
 #include "nsDebug.h"
 
+@interface CALayer (ContentsScale)
+- (double)contentsScale;
+- (void)setContentsScale:(double)scale;
+@end
+
 using namespace mozilla::plugins::PluginUtilsOSX;
 
 @interface CGBridgeLayer : CALayer {
   DrawPluginFunc mDrawFunc;
   void* mPluginInstance;
   nsIntRect mUpdateRect;
 }
 - (void) setDrawFunc: (DrawPluginFunc)aFunc pluginInstance:(void*) aPluginInstance;
@@ -300,22 +305,24 @@ bool nsDoubleBufferCARenderer::HasCALaye
   return !!mCALayer;
 }
 
 void nsDoubleBufferCARenderer::SetCALayer(void *aCALayer) {
   mCALayer = aCALayer;
 }
 
 bool nsDoubleBufferCARenderer::InitFrontSurface(size_t aWidth, size_t aHeight,
+                                                double aContentsScaleFactor,
                                                 AllowOfflineRendererEnum aAllowOfflineRenderer) {
   if (!mCALayer) {
     return false;
   }
 
-  mFrontSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight);
+  mContentsScaleFactor = aContentsScaleFactor;
+  mFrontSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight, mContentsScaleFactor);
   if (!mFrontSurface) {
     mCARenderer = nullptr;
     return false;
   }
 
   if (!mCARenderer) {
     mCARenderer = new nsCARenderer();
     if (!mCARenderer) {
@@ -323,16 +330,17 @@ bool nsDoubleBufferCARenderer::InitFront
       return false;
     }
 
     mCARenderer->AttachIOSurface(mFrontSurface);
 
     nsresult result = mCARenderer->SetupRenderer(mCALayer,
                         mFrontSurface->GetWidth(),
                         mFrontSurface->GetHeight(),
+                        mContentsScaleFactor,
                         aAllowOfflineRenderer);
 
     if (result != NS_OK) {
       mCARenderer = nullptr;
       mFrontSurface = nullptr;
       return false;
     }
   } else {
@@ -342,17 +350,18 @@ bool nsDoubleBufferCARenderer::InitFront
   return true;
 }
 
 void nsDoubleBufferCARenderer::Render() {
   if (!HasFrontSurface() || !mCARenderer) {
     return;
   }
 
-  mCARenderer->Render(GetFrontSurfaceWidth(), GetFrontSurfaceHeight(), nullptr);
+  mCARenderer->Render(GetFrontSurfaceWidth(), GetFrontSurfaceHeight(),
+                      mContentsScaleFactor, nullptr);
 }
 
 void nsDoubleBufferCARenderer::SwapSurfaces() {
   RefPtr<MacIOSurface> prevFrontSurface = mFrontSurface;
   mFrontSurface = mBackSurface;
   mBackSurface = prevFrontSurface;
 
   if (mFrontSurface) {
--- a/dom/plugins/test/mochitest/cocoa_focus.html
+++ b/dom/plugins/test/mochitest/cocoa_focus.html
@@ -20,20 +20,20 @@
                                         getInterface(Components.interfaces.nsIDOMWindowUtils);
 
       var plugin1 = document.getElementById("plugin1"); // What we're testing.
       var plugin2 = document.getElementById("plugin2"); // Dummy.
 
       var plugin1Bounds = plugin1.getBoundingClientRect();
       var plugin2Bounds = plugin2.getBoundingClientRect();
 
-      var plugin1X = (window.mozInnerScreenX + plugin1Bounds.left + 10) * utils.screenPixelsPerCSSPixel;
-      var plugin1Y = (window.mozInnerScreenY + plugin1Bounds.top + 10) * utils.screenPixelsPerCSSPixel;
-      var plugin2X = (window.mozInnerScreenX + plugin2Bounds.left + 10) * utils.screenPixelsPerCSSPixel;
-      var plugin2Y = (window.mozInnerScreenY + plugin2Bounds.top + 10) * utils.screenPixelsPerCSSPixel;
+      var plugin1X = (window.mozInnerScreenX + plugin1Bounds.left + 10);
+      var plugin1Y = (window.mozInnerScreenY + plugin1Bounds.top + 10);
+      var plugin2X = (window.mozInnerScreenX + plugin2Bounds.left + 10);
+      var plugin2Y = (window.mozInnerScreenY + plugin2Bounds.top + 10);
 
       const NSLeftMouseDown          = 1,
             NSLeftMouseUp            = 2;
 
       if (plugin1.getEventModel() != 1) {
         window.opener.todo(false, "Skipping this test when not testing the Cocoa event model");
         window.opener.testsFinished();
         return;
--- a/dom/tests/mochitest/webapps/file_bug_779982.html
+++ b/dom/tests/mochitest/webapps/file_bug_779982.html
@@ -18,29 +18,29 @@
           if (data[1] == 'true') {
             finish(this.result == null);
           } else {
             finish(this.result != null);
           }
         }
         break;
 
-      case "isInstalled":
-        navigator.mozApps.isInstalled('http://example.org/manifest.webapp').onsuccess = function onIsInstalled() {
+      case "checkInstalled":
+        navigator.mozApps.checkInstalled('http://example.org/manifest.webapp').onsuccess = function onCheckInstalled() {
           if (data[1] == 'true') {
-            finish(this.result == false);
+            finish(!this.result);
           } else {
-            finish(this.result == true);
+            finish(!!this.result);
           }
         }
         break;
 
-      case "isInstalledWrong":
+      case "checkInstalledWrong":
         try {
-          navigator.mozApps.isInstalled('http://something.org/manifest.webapp');
+          navigator.mozApps.checkInstalled('http://something.org/manifest.webapp');
           finish(false);
         } catch (e) {
           finish(true);
         }
         break;
 
       default:
         finish(false);
--- a/dom/tests/mochitest/webapps/file_bug_779982.js
+++ b/dom/tests/mochitest/webapps/file_bug_779982.js
@@ -41,49 +41,49 @@ var gData = [
     app: 'http://example.org/manifest.webapp',
     action: 'getSelf',
     isnull: false,
     src: fileTestOnCurrentOrigin,
     message: 'getSelf() for app should return something'
   },
   {
     app: 'http://example.org/manifest.webapp',
-    action: 'isInstalled',
+    action: 'checkInstalled',
     isnull: false,
     src: fileTestOnCurrentOrigin,
-    message: 'isInstalled() for app should return true'
+    message: 'checkInstalled() for app should return true'
   },
   {
     app: 'http://example.org/manifest.webapp',
-    action: 'isInstalledWrong',
+    action: 'checkInstalledWrong',
     isnull: true,
     src: fileTestOnCurrentOrigin,
-    message: 'isInstalled() for browser should return true'
+    message: 'checkInstalled() for browser should return true'
   },
   // Browser
   {
     browser: true,
     action: 'getSelf',
     isnull: true,
     src: fileTestOnCurrentOrigin,
     message: 'getSelf() for browser should return null'
   },
   {
     browser: true,
-    action: 'isInstalled',
+    action: 'checkInstalled',
     isnull: false,
     src: fileTestOnCurrentOrigin,
-    message: 'isInstalled() for browser should return true'
+    message: 'checkInstalled() for browser should return true'
   },
   {
     browser: true,
-    action: 'isInstalledWrong',
+    action: 'checkInstalledWrong',
     isnull: true,
     src: fileTestOnCurrentOrigin,
-    message: 'isInstalled() for browser should return true'
+    message: 'checkInstalled() for browser should return true'
   },
 ];
 
 function runTest() {
   for (var i in gData) {
     var iframe = document.createElement('iframe');
     var data = gData[i];
 
--- a/dom/tests/mochitest/webapps/test_bug_779982.html
+++ b/dom/tests/mochitest/webapps/test_bug_779982.html
@@ -1,15 +1,15 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=779982
 -->
 <head>
-  <title>Test for getSelf()/isInstalled() in browser and in apps</title>
+  <title>Test for getSelf()/checkInstalled() in browser and in apps</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=779982">Mozilla Bug 779982</a>
 <div id="content" style="display: none">
 
 </div>
--- a/dom/tests/mochitest/webapps/test_list_api.xul
+++ b/dom/tests/mochitest/webapps/test_list_api.xul
@@ -15,17 +15,17 @@
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741549"
      target="_blank">Mozilla Bug 741549</a>
   </body>
 
 <script>
 
 var props = {
   QueryInterface: "function",
-  isInstalled: "function",
+  checkInstalled: "function",
   getInstalled: "function",
   getSelf: "function",
   install: "function",
   mgmt: "object",
 };
 
 isDeeply([p for (p in navigator.mozApps)].sort(), Object.keys(props).sort(),
          "navigator.mozApps has only the expected properties");
--- a/gfx/2d/MacIOSurface.h
+++ b/gfx/2d/MacIOSurface.h
@@ -19,40 +19,51 @@ typedef _CGLContextObject* CGLContextObj
 typedef struct CGContext* CGContextRef;
 typedef struct CGImage* CGImageRef;
 typedef uint32_t IOSurfaceID;
 
 class MacIOSurface : public mozilla::RefCounted<MacIOSurface> {
 public:
   typedef mozilla::gfx::SourceSurface SourceSurface;
 
-  static mozilla::TemporaryRef<MacIOSurface> CreateIOSurface(int aWidth, int aHeight);
+  static mozilla::TemporaryRef<MacIOSurface> CreateIOSurface(int aWidth, int aHeight,
+                                                             double aContentsScaleFactor = 1.0);
   static void ReleaseIOSurface(MacIOSurface *aIOSurface);
-  static mozilla::TemporaryRef<MacIOSurface> LookupSurface(IOSurfaceID aSurfaceID);
+  static mozilla::TemporaryRef<MacIOSurface> LookupSurface(IOSurfaceID aSurfaceID,
+                                                           double aContentsScaleFactor = 1.0);
 
-  MacIOSurface(const void *aIOSurfacePtr) : mIOSurfacePtr(aIOSurfacePtr) {}
+  MacIOSurface(const void *aIOSurfacePtr, double aContentsScaleFactor = 1.0)
+    : mIOSurfacePtr(aIOSurfacePtr), mContentsScaleFactor(aContentsScaleFactor) {}
   ~MacIOSurface();
   IOSurfaceID GetIOSurfaceID();
   void *GetBaseAddress();
+  // GetWidth() and GetHeight() return values in "display pixels".  A
+  // "display pixel" is the smallest fully addressable part of a display.
+  // But in HiDPI modes each "display pixel" corresponds to more than one
+  // device pixel.  Multiply display pixels by mContentsScaleFactor to
+  // get device pixels.
   size_t GetWidth();
   size_t GetHeight();
+  double GetContentsScaleFactor() { return mContentsScaleFactor; }
   size_t GetBytesPerRow();
   void Lock();
   void Unlock();
   // We would like to forward declare NSOpenGLContext, but it is an @interface
   // and this file is also used from c++, so we use a void *.
   CGLError CGLTexImageIOSurface2D(void *ctxt,
                                   GLenum internalFormat, GLenum format,
                                   GLenum type, GLuint plane);
   mozilla::TemporaryRef<SourceSurface> GetAsSurface();
   CGContextRef CreateIOSurfaceContext();
 
   // FIXME This doesn't really belong here
   static CGImageRef CreateImageFromIOSurfaceContext(CGContextRef aContext);
-  static mozilla::TemporaryRef<MacIOSurface> IOSurfaceContextGetSurface(CGContextRef aContext);
+  static mozilla::TemporaryRef<MacIOSurface> IOSurfaceContextGetSurface(CGContextRef aContext,
+                                                                        double aContentsScaleFactor = 1.0);
 
 private:
   friend class nsCARenderer;
   const void* mIOSurfacePtr;
+  double mContentsScaleFactor;
 };
 
 #endif
 #endif
--- a/gfx/2d/QuartzSupport.h
+++ b/gfx/2d/QuartzSupport.h
@@ -24,58 +24,75 @@ struct _CGLContextObject;
 enum AllowOfflineRendererEnum { ALLOW_OFFLINE_RENDERER, DISALLOW_OFFLINE_RENDERER };
 
 class nsCARenderer : public mozilla::RefCounted<nsCARenderer> {
 public:
   nsCARenderer() : mCARenderer(nullptr), mFBOTexture(0), mOpenGLContext(nullptr),
                    mCGImage(nullptr), mCGData(nullptr), mIOSurface(nullptr), mFBO(0),
                    mIOTexture(0),
                    mUnsupportedWidth(UINT32_MAX), mUnsupportedHeight(UINT32_MAX),
-                   mAllowOfflineRenderer(DISALLOW_OFFLINE_RENDERER) {}
+                   mAllowOfflineRenderer(DISALLOW_OFFLINE_RENDERER),
+                   mContentsScaleFactor(1.0) {}
   ~nsCARenderer();
+  // aWidth and aHeight are in "display pixels".  A "display pixel" is the
+  // smallest fully addressable part of a display.  But in HiDPI modes each
+  // "display pixel" corresponds to more than one device pixel.  Multiply
+  // display pixels by aContentsScaleFactor to get device pixels.
   nsresult SetupRenderer(void* aCALayer, int aWidth, int aHeight,
+                         double aContentsScaleFactor,
                          AllowOfflineRendererEnum aAllowOfflineRenderer);
-  nsresult Render(int aWidth, int aHeight, CGImageRef *aOutCAImage);
+  // aWidth and aHeight are in "display pixels".  Multiply by
+  // aContentsScaleFactor to get device pixels.
+  nsresult Render(int aWidth, int aHeight,
+                  double aContentsScaleFactor,
+                  CGImageRef *aOutCAImage);
   bool isInit() { return mCARenderer != nullptr; }
   /*
    * Render the CALayer to an IOSurface. If no IOSurface
    * is attached then an internal pixel buffer will be
    * used.
    */
   void AttachIOSurface(mozilla::RefPtr<MacIOSurface> aSurface);
   IOSurfaceID GetIOSurfaceID();
+  // aX, aY, aWidth and aHeight are in "display pixels".  Multiply by
+  // surf->GetContentsScaleFactor() to get device pixels.
   static nsresult DrawSurfaceToCGContext(CGContextRef aContext,
                                          MacIOSurface *surf,
                                          CGColorSpaceRef aColorSpace,
                                          int aX, int aY,
                                          size_t aWidth, size_t aHeight);
 
   // Remove & Add the layer without destroying
   // the renderer for fast back buffer swapping.
   void DettachCALayer();
   void AttachCALayer(void *aCALayer);
 #ifdef DEBUG
   static void SaveToDisk(MacIOSurface *surf);
 #endif
 private:
+  // aWidth and aHeight are in "display pixels".  Multiply by
+  // mContentsScaleFactor to get device pixels.
   void SetBounds(int aWidth, int aHeight);
+  // aWidth and aHeight are in "display pixels".  Multiply by
+  // mContentsScaleFactor to get device pixels.
   void SetViewport(int aWidth, int aHeight);
   void Destroy();
 
   void *mCARenderer;
   GLuint                    mFBOTexture;
   _CGLContextObject        *mOpenGLContext;
   CGImageRef                mCGImage;
   void                     *mCGData;
   mozilla::RefPtr<MacIOSurface> mIOSurface;
   uint32_t                  mFBO;
   uint32_t                  mIOTexture;
   uint32_t                  mUnsupportedWidth;
   uint32_t                  mUnsupportedHeight;
   AllowOfflineRendererEnum  mAllowOfflineRenderer;
+  double                    mContentsScaleFactor;
 };
 
 enum CGContextType {
   CG_CONTEXT_TYPE_UNKNOWN = 0,
   // These are found by inspection, it's possible they could be changed
   CG_CONTEXT_TYPE_BITMAP = 4,
   CG_CONTEXT_TYPE_IOSURFACE = 8
 };
--- a/gfx/2d/QuartzSupport.mm
+++ b/gfx/2d/QuartzSupport.mm
@@ -13,16 +13,21 @@
 
 #define IOSURFACE_FRAMEWORK_PATH \
   "/System/Library/Frameworks/IOSurface.framework/IOSurface"
 #define OPENGL_FRAMEWORK_PATH \
   "/System/Library/Frameworks/OpenGL.framework/OpenGL"
 #define COREGRAPHICS_FRAMEWORK_PATH \
   "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/CoreGraphics"
 
+@interface CALayer (ContentsScale)
+- (double)contentsScale;
+- (void)setContentsScale:(double)scale;
+@end
+
 using mozilla::RefPtr;
 using mozilla::TemporaryRef;
 
 // IOSurface signatures
 typedef CFTypeRef IOSurfacePtr;
 typedef IOSurfacePtr (*IOSurfaceCreateFunc) (CFDictionaryRef properties);
 typedef IOSurfacePtr (*IOSurfaceLookupFunc) (uint32_t io_surface_id);
 typedef IOSurfaceID (*IOSurfaceGetIDFunc) (CFTypeRef io_surface);
@@ -297,28 +302,32 @@ void MacIOSurfaceLib::CloseLibrary() {
   sIOSurfaceFramework = nullptr;
   sOpenGLFramework = nullptr;
 }
 
 MacIOSurface::~MacIOSurface() {
   CFRelease(mIOSurfacePtr);
 }
 
-TemporaryRef<MacIOSurface> MacIOSurface::CreateIOSurface(int aWidth, int aHeight) {
-  if (!MacIOSurfaceLib::isInit())
+TemporaryRef<MacIOSurface> MacIOSurface::CreateIOSurface(int aWidth, int aHeight,
+                                                         double aContentsScaleFactor) {
+  if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
     return nullptr;
 
   CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
                       kCFAllocatorDefault, 4,
                       &kCFTypeDictionaryKeyCallBacks,
                       &kCFTypeDictionaryValueCallBacks);
   if (!props)
     return nullptr;
 
   int32_t bytesPerElem = 4;
+  size_t intScaleFactor = ceil(aContentsScaleFactor);
+  aWidth *= intScaleFactor;
+  aHeight *= intScaleFactor;
   CFNumberRef cfWidth = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aWidth);
   CFNumberRef cfHeight = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aHeight);
   CFNumberRef cfBytesPerElem = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &bytesPerElem);
   ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropWidth,
                                 cfWidth);
   ::CFRelease(cfWidth);
   ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropHeight,
                                 cfHeight);
@@ -330,55 +339,58 @@ TemporaryRef<MacIOSurface> MacIOSurface:
                                 kCFBooleanTrue);
 
   IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceCreate(props);
   ::CFRelease(props);
 
   if (!surfaceRef)
     return nullptr;
 
-  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef);
+  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor);
   if (!ioSurface) {
     ::CFRelease(surfaceRef);
     return nullptr;
   }
 
   return ioSurface.forget();
 }
 
-TemporaryRef<MacIOSurface> MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID) { 
-  if (!MacIOSurfaceLib::isInit())
+TemporaryRef<MacIOSurface> MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID,
+                                                       double aContentsScaleFactor) { 
+  if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
     return nullptr;
 
   IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID);
   if (!surfaceRef)
     return nullptr;
 
-  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef);
+  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor);
   if (!ioSurface) {
     ::CFRelease(surfaceRef);
     return nullptr;
   }
   return ioSurface.forget();
 }
 
 IOSurfaceID MacIOSurface::GetIOSurfaceID() { 
   return MacIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr);
 }
 
 void* MacIOSurface::GetBaseAddress() { 
   return MacIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr);
 }
 
-size_t MacIOSurface::GetWidth() { 
-  return MacIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr);
+size_t MacIOSurface::GetWidth() {
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
+  return MacIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr) / intScaleFactor;
 }
 
-size_t MacIOSurface::GetHeight() { 
-  return MacIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr);
+size_t MacIOSurface::GetHeight() {
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
+  return MacIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr) / intScaleFactor;
 }
 
 size_t MacIOSurface::GetBytesPerRow() { 
   return MacIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr);
 }
 
 #define READ_ONLY 0x1
 void MacIOSurface::Lock() {
@@ -393,18 +405,19 @@ void MacIOSurface::Unlock() {
 using mozilla::gfx::SourceSurface;
 using mozilla::gfx::SourceSurfaceRawData;
 using mozilla::gfx::IntSize;
 
 TemporaryRef<SourceSurface>
 MacIOSurface::GetAsSurface() {
   Lock();
   size_t bytesPerRow = GetBytesPerRow();
-  size_t ioWidth = GetWidth();
-  size_t ioHeight = GetHeight();
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
+  size_t ioWidth = GetWidth() * intScaleFactor;
+  size_t ioHeight = GetHeight() * intScaleFactor;
 
   unsigned char* ioData = (unsigned char*)GetBaseAddress();
   unsigned char* dataCpy = (unsigned char*)malloc(bytesPerRow*ioHeight);
   for (size_t i = 0; i < ioHeight; i++) {
     memcpy(dataCpy + i * bytesPerRow,
            ioData + i * bytesPerRow, ioWidth * 4);
   }
 
@@ -417,20 +430,22 @@ MacIOSurface::GetAsSurface() {
 }
 
 CGLError 
 MacIOSurface::CGLTexImageIOSurface2D(void *c,
                                     GLenum internalFormat, GLenum format, 
                                     GLenum type, GLuint plane)
 {
   NSOpenGLContext *ctxt = static_cast<NSOpenGLContext*>(c);
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
   return MacIOSurfaceLib::CGLTexImageIOSurface2D((CGLContextObj)[ctxt CGLContextObj],
                                                 GL_TEXTURE_RECTANGLE_ARB,
                                                 internalFormat,
-                                                GetWidth(), GetHeight(),
+                                                GetWidth() * intScaleFactor,
+                                                GetHeight() * intScaleFactor,
                                                 format, type,
                                                 mIOSurfacePtr, plane);
 }
 
 CGColorSpaceRef CreateSystemColorSpace() {
     CMProfileRef system_profile = nullptr;
     CGColorSpaceRef cspace = nullptr;
 
@@ -442,17 +457,20 @@ CGColorSpaceRef CreateSystemColorSpace()
       // Default to generic
       cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
     }
 
     return cspace;
 }
 
 CGContextRef MacIOSurface::CreateIOSurfaceContext() {
-  CGContextRef ref = MacIOSurfaceLib::IOSurfaceContextCreate(mIOSurfacePtr, GetWidth(), GetHeight(),
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
+  CGContextRef ref = MacIOSurfaceLib::IOSurfaceContextCreate(mIOSurfacePtr,
+                                                GetWidth() * intScaleFactor,
+                                                GetHeight() * intScaleFactor,
                                                 8, 32, CreateSystemColorSpace(), 0x2002);
   return ref;
 }
 
 nsCARenderer::~nsCARenderer() {
   Destroy();
 }
 
@@ -503,20 +521,21 @@ void nsCARenderer::Destroy() {
   mOpenGLContext = nullptr;
   mCGImage = nullptr;
   mIOSurface = nullptr;
   mFBO = 0;
   mIOTexture = 0;
 }
 
 nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight,
+                                     double aContentsScaleFactor,
                                      AllowOfflineRendererEnum aAllowOfflineRenderer) {
   mAllowOfflineRenderer = aAllowOfflineRenderer;
 
-  if (aWidth == 0 || aHeight == 0)
+  if (aWidth == 0 || aHeight == 0 || aContentsScaleFactor <= 0)
     return NS_ERROR_FAILURE;
 
   if (aWidth == mUnsupportedWidth &&
       aHeight == mUnsupportedHeight) {
     return NS_ERROR_FAILURE;
   }
 
   CALayer* layer = (CALayer*)aCALayer;
@@ -556,44 +575,48 @@ nsresult nsCARenderer::SetupRenderer(voi
   if (caRenderer == nil) {
     mUnsupportedWidth = aWidth;
     mUnsupportedHeight = aHeight;
     Destroy();
     return NS_ERROR_FAILURE;
   }
 
   caRenderer.layer = layer;
+  mContentsScaleFactor = aContentsScaleFactor;
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
   SetBounds(aWidth, aHeight);
 
   // We target rendering to a CGImage if no shared IOSurface are given.
   if (!mIOSurface) {
-    mCGData = malloc(aWidth*aHeight*4);
+    mCGData = malloc(aWidth*intScaleFactor*aHeight*4*intScaleFactor);
     if (!mCGData) {
       mUnsupportedWidth = aWidth;
       mUnsupportedHeight = aHeight;
       Destroy();
       return NS_ERROR_FAILURE;
     }
-    memset(mCGData, 0, aWidth*aHeight*4);
+    memset(mCGData, 0, aWidth*intScaleFactor*aHeight*4*intScaleFactor);
 
     CGDataProviderRef dataProvider = nullptr;
     dataProvider = ::CGDataProviderCreateWithData(mCGData,
-                                        mCGData, aHeight*aWidth*4,
+                                        mCGData, aHeight*intScaleFactor*aWidth*4*intScaleFactor,
                                         cgdata_release_callback);
     if (!dataProvider) {
-      cgdata_release_callback(mCGData, mCGData, aHeight*aWidth*4);
+      cgdata_release_callback(mCGData, mCGData,
+                              aHeight*intScaleFactor*aWidth*4*intScaleFactor);
       mUnsupportedWidth = aWidth;
       mUnsupportedHeight = aHeight;
       Destroy();
       return NS_ERROR_FAILURE;
     }
 
     CGColorSpaceRef colorSpace = CreateSystemColorSpace();
 
-    mCGImage = ::CGImageCreate(aWidth, aHeight, 8, 32, aWidth * 4, colorSpace,
+    mCGImage = ::CGImageCreate(aWidth * intScaleFactor, aHeight * intScaleFactor,
+                8, 32, aWidth * intScaleFactor * 4, colorSpace,
                 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
                 dataProvider, nullptr, true, kCGRenderingIntentDefault);
 
     ::CGDataProviderRelease(dataProvider);
     if (colorSpace) {
       ::CGColorSpaceRelease(colorSpace);
     }
     if (!mCGImage) {
@@ -609,17 +632,18 @@ nsresult nsCARenderer::SetupRenderer(voi
 
   if (mIOSurface) {
     // Create the IOSurface mapped texture.
     ::glGenTextures(1, &mIOTexture);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
     ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     MacIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
-                                           GL_RGBA, aWidth, aHeight,
+                                           GL_RGBA, aWidth * intScaleFactor,
+                                           aHeight * intScaleFactor,
                                            GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                                            mIOSurface->mIOSurfacePtr, 0);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
   } else {
     ::glGenTextures(1, &mFBOTexture);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mFBOTexture);
     ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -682,26 +706,58 @@ void nsCARenderer::SetBounds(int aWidth,
                                    [NSNull null], @"sublayers",
                                    [NSNull null], @"contents",
                                    [NSNull null], @"position",
                                    [NSNull null], @"bounds",
                                    nil];
   layer.actions = newActions;
   [newActions release];
 
+  // If we're in HiDPI mode, mContentsScaleFactor will (presumably) be 2.0.
+  // For some reason, to make things work properly in HiDPI mode we need to
+  // make caRenderer's 'bounds' and 'layer' different sizes -- to set 'bounds'
+  // to the size of 'layer's backing store.  To make plugins display at HiDPI
+  // resolution we also need to set 'layer's contentScale to
+  // mContentsScaleFactor.
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
   [CATransaction setValue: [NSNumber numberWithFloat:0.0f] forKey: kCATransactionAnimationDuration];
   [CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
   [layer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
   [layer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)];
-  caRenderer.bounds = CGRectMake(0, 0, aWidth, aHeight);
+  caRenderer.bounds = CGRectMake(0, 0, aWidth * intScaleFactor, aHeight * intScaleFactor);
+  if (mContentsScaleFactor != 1.0) {
+    CGAffineTransform affineTransform = [layer affineTransform];
+    affineTransform.a = mContentsScaleFactor;
+    affineTransform.d = mContentsScaleFactor;
+    affineTransform.tx = ((double)aWidth)/mContentsScaleFactor;
+    affineTransform.ty = ((double)aHeight)/mContentsScaleFactor;
+    [layer setAffineTransform:affineTransform];
+    if ([layer respondsToSelector:@selector(setContentsScale:)]) {
+      // For reasons that aren't clear (perhaps one or more OS bugs), OOP
+      // Core Graphics plugins (ones that use CGBridgeLayer) can only use
+      // HiDPI mode if the tree is built with the 10.7 SDK or up.
+#if !defined(MAC_OS_X_VERSION_10_7) || \
+    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+      Class CGBridgeLayerClass = ::NSClassFromString(@"CGBridgeLayer");
+      if (!CGBridgeLayerClass || ![layer isKindOfClass:CGBridgeLayerClass])
+#endif
+      {
+        layer.contentsScale = mContentsScaleFactor;
+      }
+    }
+  }
   [CATransaction commit];
 
 }
 
 void nsCARenderer::SetViewport(int aWidth, int aHeight) {
+  size_t intScaleFactor = ceil(mContentsScaleFactor);
+  aWidth *= intScaleFactor;
+  aHeight *= intScaleFactor;
+
   ::glViewport(0.0, 0.0, aWidth, aHeight);
   ::glMatrixMode(GL_PROJECTION);
   ::glLoadIdentity();
   ::glOrtho (0.0, aWidth, 0.0, aHeight, -1, 1);
 
   // Render upside down to speed up CGContextDrawImage
   ::glTranslatef(0.0f, aHeight, 0.0);
   ::glScalef(1.0, -1.0, 1.0);
@@ -716,24 +772,26 @@ void nsCARenderer::AttachIOSurface(RefPt
     return;
   }
 
   mIOSurface = aSurface;
 
   // Update the framebuffer and viewport
   if (mCARenderer) {
     CARenderer* caRenderer = (CARenderer*)mCARenderer;
-    int width = caRenderer.bounds.size.width;
-    int height = caRenderer.bounds.size.height;
+    size_t intScaleFactor = ceil(mContentsScaleFactor);
+    int width = caRenderer.bounds.size.width / intScaleFactor;
+    int height = caRenderer.bounds.size.height / intScaleFactor;
 
     CGLContextObj oldContext = ::CGLGetCurrentContext();
     ::CGLSetCurrentContext(mOpenGLContext);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
     MacIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
-                                           GL_RGBA, mIOSurface->GetWidth(), mIOSurface->GetHeight(),
+                                           GL_RGBA, mIOSurface->GetWidth() * intScaleFactor,
+                                           mIOSurface->GetHeight() * intScaleFactor,
                                            GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                                            mIOSurface->mIOSurfacePtr, 0);
     ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
 
     // Rebind the FBO to make it live
     ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
 
     if (mIOSurface->GetWidth() != width || mIOSurface->GetHeight() != height) {
@@ -753,42 +811,44 @@ IOSurfaceID nsCARenderer::GetIOSurfaceID
   if (!mIOSurface) {
     return 0;
   }
 
   return mIOSurface->GetIOSurfaceID();
 }
 
 nsresult nsCARenderer::Render(int aWidth, int aHeight, 
+                              double aContentsScaleFactor,
                               CGImageRef *aOutCGImage) {
   if (!aOutCGImage && !mIOSurface) {
     NS_ERROR("No target destination for rendering");
   } else if (aOutCGImage) {
     // We are expected to return a CGImageRef, we will set
     // it to nullptr in case we fail before the image is ready.
     *aOutCGImage = nullptr;
   }
 
-  if (aWidth == 0 || aHeight == 0)
+  if (aWidth == 0 || aHeight == 0 || aContentsScaleFactor <= 0)
     return NS_OK;
 
   if (!mCARenderer) {
     return NS_ERROR_FAILURE;
   }
 
   CARenderer* caRenderer = (CARenderer*)mCARenderer;
-  int renderer_width = caRenderer.bounds.size.width;
-  int renderer_height = caRenderer.bounds.size.height;
+  size_t intScaleFactor = ceil(aContentsScaleFactor);
+  int renderer_width = caRenderer.bounds.size.width / intScaleFactor;
+  int renderer_height = caRenderer.bounds.size.height / intScaleFactor;
 
   if (renderer_width != aWidth || renderer_height != aHeight) {
     // XXX: This should be optimized to not rescale the buffer
     //      if we are resizing down.
     CALayer* caLayer = [caRenderer layer];
     Destroy();
-    if (SetupRenderer(caLayer, aWidth, aHeight,
+    if (SetupRenderer(caLayer, aWidth, aHeight, aContentsScaleFactor,
                       mAllowOfflineRenderer) != NS_OK) {
       return NS_ERROR_FAILURE;
     }
 
     caRenderer = (CARenderer*)mCARenderer;
   }
 
   CGLContextObj oldContext = ::CGLGetCurrentContext();
@@ -809,30 +869,32 @@ nsresult nsCARenderer::Render(int aWidth
   }
 
   ::glClearColor(0.0, 0.0, 0.0, 0.0);
   ::glClear(GL_COLOR_BUFFER_BIT);
 
   [CATransaction commit];
   double caTime = ::CACurrentMediaTime();
   [caRenderer beginFrameAtTime:caTime timeStamp:nullptr];
-  [caRenderer addUpdateRect:CGRectMake(0,0, aWidth, aHeight)];
+  [caRenderer addUpdateRect:CGRectMake(0,0, aWidth * intScaleFactor,
+                                       aHeight * intScaleFactor)];
   [caRenderer render];
   [caRenderer endFrame];
 
   // Read the data back either to the IOSurface or mCGImage.
   if (mIOSurface) {
     ::glFlush();
   } else {
     ::glPixelStorei(GL_PACK_ALIGNMENT, 4);
     ::glPixelStorei(GL_PACK_ROW_LENGTH, 0);
     ::glPixelStorei(GL_PACK_SKIP_ROWS, 0);
     ::glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
 
-    ::glReadPixels(0.0f, 0.0f, aWidth, aHeight,
+    ::glReadPixels(0.0f, 0.0f, aWidth * intScaleFactor,
+                        aHeight * intScaleFactor,
                         GL_BGRA, GL_UNSIGNED_BYTE,
                         mCGData);
 
     *aOutCGImage = mCGImage;
   }
 
   if (oldContext) {
     ::CGLSetCurrentContext(oldContext);
@@ -860,44 +922,52 @@ nsresult nsCARenderer::DrawSurfaceToCGCo
 
   if (aX < 0 || aX >= ioWidth ||
       aY < 0 || aY >= ioHeight) {
     surf->Unlock();
     return NS_ERROR_FAILURE;
   }
 
   void* ioData = surf->GetBaseAddress();
+  double scaleFactor = surf->GetContentsScaleFactor();
+  size_t intScaleFactor = ceil(surf->GetContentsScaleFactor());
   CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
-                                      ioData, ioHeight*(bytesPerRow)*4, 
+                                      ioData, ioHeight*intScaleFactor*(bytesPerRow)*4, 
                                       nullptr); //No release callback 
   if (!dataProvider) {
     surf->Unlock();
     return NS_ERROR_FAILURE;
   }
 
-  CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow,
-              aColorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+  CGImageRef cgImage = ::CGImageCreate(ioWidth * intScaleFactor,
+              ioHeight * intScaleFactor, 8, 32, bytesPerRow, aColorSpace,
+              kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
               dataProvider, nullptr, true, kCGRenderingIntentDefault);
   ::CGDataProviderRelease(dataProvider);
   if (!cgImage) {
     surf->Unlock();
     return NS_ERROR_FAILURE;
   }
   CGImageRef subImage = ::CGImageCreateWithImageInRect(cgImage,
-                                       ::CGRectMake(aX, aY, aWidth, aHeight));
+                                       ::CGRectMake(aX * scaleFactor,
+                                                    aY * scaleFactor,
+                                                    aWidth * scaleFactor,
+                                                    aHeight * scaleFactor));
   if (!subImage) {
     ::CGImageRelease(cgImage);
     surf->Unlock();
     return NS_ERROR_FAILURE;
   }
 
   ::CGContextScaleCTM(aContext, 1.0f, -1.0f);
   ::CGContextDrawImage(aContext, 
-                       CGRectMake(aX, -(CGFloat)aY - (CGFloat)aHeight, 
-                                  aWidth, aHeight), 
+                       CGRectMake(aX * scaleFactor,
+                                  (-(CGFloat)aY - (CGFloat)aHeight) * scaleFactor, 
+                                  aWidth * scaleFactor,
+                                  aHeight * scaleFactor), 
                        subImage);
 
   ::CGImageRelease(subImage);
   ::CGImageRelease(cgImage);
   surf->Unlock();
   return NS_OK;
 }
 
@@ -974,28 +1044,29 @@ void nsCARenderer::SaveToDisk(MacIOSurfa
 
 CGImageRef MacIOSurface::CreateImageFromIOSurfaceContext(CGContextRef aContext) {
   if (!MacIOSurfaceLib::isInit())
     return nullptr;
 
   return MacIOSurfaceLib::IOSurfaceContextCreateImage(aContext);
 }
 
-TemporaryRef<MacIOSurface> MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext) {
-  if (!MacIOSurfaceLib::isInit())
+TemporaryRef<MacIOSurface> MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext,
+                                                                    double aContentsScaleFactor) {
+  if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
     return nullptr;
 
   IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceContextGetSurface(aContext);
   if (!surfaceRef)
     return nullptr;
 
   // Retain the IOSurface because MacIOSurface will release it
   CFRetain(surfaceRef);
 
-  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef);
+  RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor);
   if (!ioSurface) {
     ::CFRelease(surfaceRef);
     return nullptr;
   }
   return ioSurface.forget();
 }
 
 
--- a/gfx/layers/basic/BasicTiledThebesLayer.h
+++ b/gfx/layers/basic/BasicTiledThebesLayer.h
@@ -75,16 +75,17 @@ class BasicTiledThebesLayer;
  */
 
 class BasicTiledLayerBuffer : public TiledLayerBuffer<BasicTiledLayerBuffer, BasicTiledLayerTile>
 {
   friend class TiledLayerBuffer<BasicTiledLayerBuffer, BasicTiledLayerTile>;
 
 public:
   BasicTiledLayerBuffer()
+    : mLastPaintOpaque(false)
   {}
 
   void PaintThebes(BasicTiledThebesLayer* aLayer,
                    const nsIntRegion& aNewValidRegion,
                    const nsIntRegion& aPaintRegion,
                    LayerManager::DrawThebesLayerCallback aCallback,
                    void* aCallbackData);
 
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -39,20 +39,20 @@ public:
     gfxContext::AzureState &state = mContext->CurrentState();
 
     if (state.pattern) {
       return *state.pattern->GetPattern(mContext->mDT, state.patternTransformChanged ? &state.patternTransform : nullptr);
     } else if (state.sourceSurface) {
       Matrix transform = state.surfTransform;
 
       if (state.patternTransformChanged) {
-        Matrix mat = mContext->mDT->GetTransform();
+        Matrix mat = mContext->mTransform;
         mat.Invert();
 
-        transform = mat * state.patternTransform * transform;
+        transform = transform * state.patternTransform * mat;
       }
 
       mPattern = new (mSurfacePattern.addr())
         SurfacePattern(state.sourceSurface, EXTEND_CLAMP, transform);
       return *mPattern;
     } else {
       mPattern = new (mColorPattern.addr())
         ColorPattern(state.color);
@@ -178,17 +178,17 @@ gfxContext::GetCairo()
 }
 
 void
 gfxContext::Save()
 {
   if (mCairo) {
     cairo_save(mCairo);
   } else {
-    CurrentState().transform = mDT->GetTransform();
+    CurrentState().transform = mTransform;
     mStateStack.AppendElement(AzureState(CurrentState()));
     CurrentState().clipWasReset = false;
     CurrentState().pushedClips.Clear();
   }
 }
 
 void
 gfxContext::Restore()
@@ -207,21 +207,23 @@ gfxContext::Restore()
 
     mStateStack.RemoveElementAt(mStateStack.Length() - 1);
 
     if (mPathBuilder || mPath || mPathIsRect) {
       // Support here isn't fully correct if the path is continued -after-
       // the restore. We don't currently have users that do this and we should
       // make sure there will not be any. Sadly we can't assert this easily.
       mTransformChanged = true;
-      mPathTransform = mDT->GetTransform();
+      mPathTransform = mTransform;
     }
 
     mDT = CurrentState().drawTarget;
-    mDT->SetTransform(CurrentState().transform);
+
+    mTransform = CurrentState().transform;
+    mDT->SetTransform(GetDTTransform());
   }
 }
 
 // drawing
 void
 gfxContext::NewPath()
 {
   if (mCairo) {
@@ -455,17 +457,17 @@ gfxContext::Rectangle(const gfxRect& rec
 
     cairo_rectangle(mCairo, rect.X(), rect.Y(), rect.Width(), rect.Height());
   } else {
     Rect rec = ToRect(rect);
 
     if (snapToPixels) {
       gfxRect newRect(rect);
       if (UserToDevicePixelSnapped(newRect, true)) {
-        gfxMatrix mat = ThebesMatrix(mDT->GetTransform());
+        gfxMatrix mat = ThebesMatrix(mTransform);
         mat.Invert();
 
         // We need the user space rect.
         rec = ToRect(mat.TransformBounds(newRect));
       }
     }
 
     if (!mPathBuilder && !mPathIsRect) {
@@ -547,77 +549,79 @@ gfxContext::DrawSurface(gfxASurface *sur
 
 // transform stuff
 void
 gfxContext::Translate(const gfxPoint& pt)
 {
   if (mCairo) {
     cairo_translate(mCairo, pt.x, pt.y);
   } else {
-    Matrix newMatrix = mDT->GetTransform();
+    Matrix newMatrix = mTransform;
 
     ChangeTransform(newMatrix.Translate(Float(pt.x), Float(pt.y)));
   }
 }
 
 void
 gfxContext::Scale(gfxFloat x, gfxFloat y)
 {
   if (mCairo) {
     cairo_scale(mCairo, x, y);
   } else {
-    Matrix newMatrix = mDT->GetTransform();
+    Matrix newMatrix = mTransform;
 
     ChangeTransform(newMatrix.Scale(Float(x), Float(y)));
   }
 }
 
 void
 gfxContext::Rotate(gfxFloat angle)
 {
   if (mCairo) {
     cairo_rotate(mCairo, angle);
   } else {
     Matrix rotation = Matrix::Rotation(Float(angle));
-    ChangeTransform(rotation * mDT->GetTransform());
+    ChangeTransform(rotation * mTransform);
   }
 }
 
 void
 gfxContext::Multiply(const gfxMatrix& matrix)
 {
   if (mCairo) {
     const cairo_matrix_t& mat = reinterpret_cast<const cairo_matrix_t&>(matrix);
     cairo_transform(mCairo, &mat);
   } else {
-    ChangeTransform(ToMatrix(matrix) * mDT->GetTransform());
+    ChangeTransform(ToMatrix(matrix) * mTransform);
   }
 }
 
 void
 gfxContext::MultiplyAndNudgeToIntegers(const gfxMatrix& matrix)
 {
   if (mCairo) {
     const cairo_matrix_t& mat = reinterpret_cast<const cairo_matrix_t&>(matrix);
     cairo_transform(mCairo, &mat);
     // XXX nudging to integers not currently supported for Thebes
   } else {
-    Matrix transform = ToMatrix(matrix) * mDT->GetTransform();
+    Matrix transform = ToMatrix(matrix) * mTransform;
     transform.NudgeToIntegers();
     ChangeTransform(transform);
   }
 }
 
 void
 gfxContext::SetMatrix(const gfxMatrix& matrix)
 {
   if (mCairo) {
     const cairo_matrix_t& mat = reinterpret_cast<const cairo_matrix_t&>(matrix);
     cairo_set_matrix(mCairo, &mat);
   } else {
+    Matrix mat;
+    mat.Translate(-CurrentState().deviceOffset.x, -CurrentState().deviceOffset.y);
     ChangeTransform(ToMatrix(matrix));
   }
 }
 
 void
 gfxContext::IdentityMatrix()
 {
   if (mCairo) {
@@ -630,105 +634,105 @@ gfxContext::IdentityMatrix()
 gfxMatrix
 gfxContext::CurrentMatrix() const
 {
   if (mCairo) {
     cairo_matrix_t mat;
     cairo_get_matrix(mCairo, &mat);
     return gfxMatrix(*reinterpret_cast<gfxMatrix*>(&mat));
   } else {
-    return ThebesMatrix(mDT->GetTransform());
+    return ThebesMatrix(mTransform);
   }
 }
 
 void
 gfxContext::NudgeCurrentMatrixToIntegers()
 {
   if (mCairo) {
     cairo_matrix_t mat;
     cairo_get_matrix(mCairo, &mat);
     gfxMatrix(*reinterpret_cast<gfxMatrix*>(&mat)).NudgeToIntegers();
     cairo_set_matrix(mCairo, &mat);
   } else {
     gfxMatrix matrix = ThebesMatrix(mTransform);
     matrix.NudgeToIntegers();
-    mTransform = ToMatrix(matrix);
+    ChangeTransform(ToMatrix(matrix));
   }
 }
 
 gfxPoint
 gfxContext::DeviceToUser(const gfxPoint& point) const
 {
   if (mCairo) {
     gfxPoint ret = point;
     cairo_device_to_user(mCairo, &ret.x, &ret.y);
     return ret;
   } else {
-    Matrix matrix = mDT->GetTransform();
+    Matrix matrix = mTransform;
 
     matrix.Invert();
 
     return ThebesPoint(matrix * ToPoint(point));
   }
 }
 
 gfxSize
 gfxContext::DeviceToUser(const gfxSize& size) const
 {
   if (mCairo) {
     gfxSize ret = size;
     cairo_device_to_user_distance(mCairo, &ret.width, &ret.height);
     return ret;
   } else {
-    Matrix matrix = mDT->GetTransform();
+    Matrix matrix = mTransform;
 
     matrix.Invert();
 
     return ThebesSize(matrix * ToSize(size));
   }
 }
 
 gfxRect
 gfxContext::DeviceToUser(const gfxRect& rect) const
 {
   if (mCairo) {
     gfxRect ret = rect;
     cairo_device_to_user(mCairo, &ret.x, &ret.y);
     cairo_device_to_user_distance(mCairo, &ret.width, &ret.height);
     return ret;
   } else {
-    Matrix matrix = mDT->GetTransform();
+    Matrix matrix = mTransform;
 
     matrix.Invert();
 
     return ThebesRect(matrix.TransformBounds(ToRect(rect)));
   }
 }
 
 gfxPoint
 gfxContext::UserToDevice(const gfxPoint& point) const
 {
   if (mCairo) {
     gfxPoint ret = point;
     cairo_user_to_device(mCairo, &ret.x, &ret.y);
     return ret;
   } else {
-    return ThebesPoint(mDT->GetTransform() * ToPoint(point));
+    return ThebesPoint(mTransform * ToPoint(point));
   }
 }
 
 gfxSize
 gfxContext::UserToDevice(const gfxSize& size) const
 {
   if (mCairo) {
     gfxSize ret = size;
     cairo_user_to_device_distance(mCairo, &ret.width, &ret.height);
     return ret;
   } else {
-    const Matrix &matrix = mDT->GetTransform();
+    const Matrix &matrix = mTransform;
 
     gfxSize newSize = size;
     newSize.width = newSize.width * matrix._11 + newSize.height * matrix._12;
     newSize.height = newSize.width * matrix._21 + newSize.height * matrix._22;
     return newSize;
   }
 }
 
@@ -751,17 +755,17 @@ gfxContext::UserToDevice(const gfxRect& 
         xmin = NS_MIN(xmin, x[i]);
         xmax = NS_MAX(xmax, x[i]);
         ymin = NS_MIN(ymin, y[i]);
         ymax = NS_MAX(ymax, y[i]);
     }
 
     return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin);
   } else {
-    const Matrix &matrix = mDT->GetTransform();
+    const Matrix &matrix = mTransform;
     return ThebesRect(matrix.TransformBounds(ToRect(rect)));
   }
 }
 
 bool
 gfxContext::UserToDevicePixelSnapped(gfxRect& rect, bool ignoreScale) const
 {
   if (GetFlags() & FLAG_DISABLE_SNAPPING)
@@ -775,17 +779,17 @@ gfxContext::UserToDevicePixelSnapped(gfx
   if (mCairo) {
     cairo_matrix_t mat;
     cairo_get_matrix(mCairo, &mat);
     if (!ignoreScale &&
         (!WITHIN_E(mat.xx,1.0) || !WITHIN_E(mat.yy,1.0) ||
           !WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0)))
         return false;
   } else {
-    Matrix mat = mDT->GetTransform();
+    Matrix mat = mTransform;
     if (!ignoreScale &&
         (!WITHIN_E(mat._11,1.0) || !WITHIN_E(mat._22,1.0) ||
           !WITHIN_E(mat._12,0.0) || !WITHIN_E(mat._21,0.0)))
         return false;
   }
 #undef WITHIN_E
 
   gfxPoint p1 = UserToDevice(rect.TopLeft());
@@ -825,17 +829,17 @@ gfxContext::UserToDevicePixelSnapped(gfx
   if (mCairo) {
     cairo_matrix_t mat;
     cairo_get_matrix(mCairo, &mat);
     if (!ignoreScale &&
         (!WITHIN_E(mat.xx,1.0) || !WITHIN_E(mat.yy,1.0) ||
           !WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0)))
         return false;
   } else {
-    Matrix mat = mDT->GetTransform();
+    Matrix mat = mTransform;
     if (!ignoreScale &&
         (!WITHIN_E(mat._11,1.0) || !WITHIN_E(mat._22,1.0) ||
           !WITHIN_E(mat._12,0.0) || !WITHIN_E(mat._21,0.0)))
         return false;
   }
 #undef WITHIN_E
 
   pt = UserToDevice(pt);
@@ -1116,37 +1120,37 @@ gfxContext::CurrentFillRule() const
 void
 gfxContext::Clip(const gfxRect& rect)
 {
   if (mCairo) {
     cairo_new_path(mCairo);
     cairo_rectangle(mCairo, rect.X(), rect.Y(), rect.Width(), rect.Height());
     cairo_clip(mCairo);
   } else {
-    AzureState::PushedClip clip = { NULL, ToRect(rect), mDT->GetTransform() };
+    AzureState::PushedClip clip = { NULL, ToRect(rect), mTransform };
     CurrentState().pushedClips.AppendElement(clip);
     mDT->PushClipRect(ToRect(rect));
     NewPath();
   }
 }
 
 void
 gfxContext::Clip()
 {
   if (mCairo) {
     cairo_clip_preserve(mCairo);
   } else {
     if (mPathIsRect && !mTransformChanged) {
-      AzureState::PushedClip clip = { NULL, mRect, mDT->GetTransform() };
+      AzureState::PushedClip clip = { NULL, mRect, mTransform };
       CurrentState().pushedClips.AppendElement(clip);
       mDT->PushClipRect(mRect);
     } else {
       EnsurePath();
       mDT->PushClip(mPath);
-      AzureState::PushedClip clip = { mPath, Rect(), mDT->GetTransform() };
+      AzureState::PushedClip clip = { mPath, Rect(), mTransform };
       CurrentState().pushedClips.AppendElement(clip);
     }
   }
 }
 
 void
 gfxContext::ResetClip()
 {
@@ -1183,41 +1187,23 @@ gfxContext::UpdateSurfaceClip()
 gfxRect
 gfxContext::GetClipExtents()
 {
   if (mCairo) {
     double xmin, ymin, xmax, ymax;
     cairo_clip_extents(mCairo, &xmin, &ymin, &xmax, &ymax);
     return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin);
   } else {
-    unsigned int lastReset = 0;
-    for (int i = mStateStack.Length() - 1; i > 0; i--) {
-      if (mStateStack[i].clipWasReset) {
-        lastReset = i;
-      }
-    }
-
-    Rect rect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height));
-    for (unsigned int i = lastReset; i < mStateStack.Length(); i++) {
-      for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
-        AzureState::PushedClip &clip = mStateStack[i].pushedClips[c];
-        if (clip.path) {
-          Rect bounds = clip.path->GetBounds(clip.transform);
-          rect.IntersectRect(rect, bounds);
-        } else {
-          rect.IntersectRect(rect, clip.transform.TransformBounds(clip.rect));
-        }
-      }
-    }
+    Rect rect = GetAzureDeviceSpaceClipBounds();
 
     if (rect.width == 0 || rect.height == 0) {
       return gfxRect(0, 0, 0, 0);
     }
 
-    Matrix mat = mDT->GetTransform();
+    Matrix mat = mTransform;
     mat.Invert();
     rect = mat.TransformBounds(rect);
 
     return ThebesRect(rect);
   }
 }
 
 bool
@@ -1464,25 +1450,33 @@ gfxContext::Paint(gfxFloat alpha)
 // groups
 
 void
 gfxContext::PushGroup(gfxASurface::gfxContentType content)
 {
   if (mCairo) {
     cairo_push_group_with_content(mCairo, (cairo_content_t) content);
   } else {
+    Rect clipBounds = GetAzureDeviceSpaceClipBounds();
+    clipBounds.RoundOut();
+
+    clipBounds.width = NS_MAX(1.0f, clipBounds.width);
+    clipBounds.height = NS_MAX(1.0f, clipBounds.height);
+
     RefPtr<DrawTarget> newDT =
-      mDT->CreateSimilarDrawTarget(mDT->GetSize(), gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content));
+      mDT->CreateSimilarDrawTarget(IntSize(int32_t(clipBounds.width), int32_t(clipBounds.height)),
+                                   gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content));
 
     Save();
 
     CurrentState().drawTarget = newDT;
+    CurrentState().deviceOffset = clipBounds.TopLeft();
 
     PushClipsToDT(newDT);
-    newDT->SetTransform(mDT->GetTransform());
+    newDT->SetTransform(GetDTTransform());
     mDT = newDT;
   }
 }
 
 static gfxRect
 GetRoundOutDeviceClipExtents(gfxContext* aCtx)
 {
   gfxContextMatrixAutoSaveRestore save(aCtx);
@@ -1541,21 +1535,28 @@ gfxContext::PushGroupAndCopyBackground(g
     if (mDT->GetFormat() != FORMAT_B8G8R8X8) {
       gfxRect clipRect = GetRoundOutDeviceClipExtents(this);
       clipExtents = IntRect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
     }
     if (mDT->GetFormat() == FORMAT_B8G8R8X8 ||
         mDT->GetOpaqueRect().Contains(clipExtents)) {
       DrawTarget *oldDT = mDT;
       RefPtr<SourceSurface> source = mDT->Snapshot();
+      Point oldDeviceOffset = CurrentState().deviceOffset;
       PushGroup(content);
+
+      Point offset = CurrentState().deviceOffset - oldDeviceOffset;
+      PushGroup(gfxASurface::CONTENT_COLOR);
       Rect surfRect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height));
+      Rect sourceRect = surfRect;
+      sourceRect.x += offset.x;
+      sourceRect.y += offset.y;
       Matrix oldTransform = mDT->GetTransform();
       mDT->SetTransform(Matrix());
-      mDT->DrawSurface(source, surfRect, surfRect); 
+      mDT->DrawSurface(source, surfRect, sourceRect);
       mDT->SetTransform(oldTransform);
       mDT->SetOpaqueRect(oldDT->GetOpaqueRect());
       return;
     }
   }
   PushGroup(content);
 }
 
@@ -1565,43 +1566,52 @@ gfxContext::PopGroup()
   if (mCairo) {
     cairo_pattern_t *pat = cairo_pop_group(mCairo);
     gfxPattern *wrapper = new gfxPattern(pat);
     cairo_pattern_destroy(pat);
     NS_IF_ADDREF(wrapper);
     return wrapper;
   } else {
     RefPtr<SourceSurface> src = mDT->Snapshot();
+    Point deviceOffset = CurrentState().deviceOffset;
 
     Restore();
 
-    Matrix mat = mDT->GetTransform();
+    Matrix mat = mTransform;
     mat.Invert();
-    nsRefPtr<gfxPattern> pat = new gfxPattern(src, mat);
+
+    Matrix deviceOffsetTranslation;
+    deviceOffsetTranslation.Translate(deviceOffset.x, deviceOffset.y);
+
+    nsRefPtr<gfxPattern> pat = new gfxPattern(src, deviceOffsetTranslation * mat);
 
     return pat.forget();
   }
 }
 
 void
 gfxContext::PopGroupToSource()
 {
   if (mCairo) {
     cairo_pop_group_to_source(mCairo);
   } else {
     RefPtr<SourceSurface> src = mDT->Snapshot();
+    Point deviceOffset = CurrentState().deviceOffset;
     Restore();
     CurrentState().sourceSurfCairo = NULL;
     CurrentState().sourceSurface = src;
     CurrentState().pattern = NULL;
     CurrentState().patternTransformChanged = false;
 
-    Matrix mat = mDT->GetTransform();
+    Matrix mat = mTransform;
     mat.Invert();
-    CurrentState().surfTransform = mat;
+
+    Matrix deviceOffsetTranslation;
+    deviceOffsetTranslation.Translate(deviceOffset.x, deviceOffset.y);
+    CurrentState().surfTransform = deviceOffsetTranslation * mat;
   }
 }
 
 bool
 gfxContext::PointInFill(const gfxPoint& pt)
 {
   if (mCairo) {
     return cairo_in_fill(mCairo, pt.x, pt.y);
@@ -1917,17 +1927,17 @@ gfxContext::EnsurePath()
 {
   if (mPathBuilder) {
     mPath = mPathBuilder->Finish();
     mPathBuilder = NULL;
   }
 
   if (mPath) {
     if (mTransformChanged) {
-      Matrix mat = mDT->GetTransform();
+      Matrix mat = mTransform;
       mat.Invert();
       mat = mPathTransform * mat;
       mPathBuilder = mPath->TransformedCopyToBuilder(mat, CurrentState().fillRule);
       mPath = mPathBuilder->Finish();
       mPathBuilder = NULL;
 
       mTransformChanged = false;
     }
@@ -1965,17 +1975,17 @@ gfxContext::EnsurePathBuilder()
   if (mPathIsRect && !mTransformChanged) {
     mPathBuilder->MoveTo(mRect.TopLeft());
     mPathBuilder->LineTo(mRect.TopRight());
     mPathBuilder->LineTo(mRect.BottomRight());
     mPathBuilder->LineTo(mRect.BottomLeft());
     mPathBuilder->Close();
   } else if (mPathIsRect) {
     mTransformChanged = false;
-    Matrix mat = mDT->GetTransform();
+    Matrix mat = mTransform;
     mat.Invert();
     mat = mPathTransform * mat;
     mPathBuilder->MoveTo(mat * mRect.TopLeft());
     mPathBuilder->LineTo(mat * mRect.TopRight());
     mPathBuilder->LineTo(mat * mRect.BottomRight());
     mPathBuilder->LineTo(mat * mRect.BottomLeft());
     mPathBuilder->Close();
   }
@@ -2023,17 +2033,17 @@ gfxContext::PushClipsToDT(DrawTarget *aD
   }
 
   // Don't need to save the old transform, we'll be setting a new one soon!
 
   // Push all clips from the last state on the stack where the clip was
   // reset to the clip before ours.
   for (unsigned int i = lastReset; i < mStateStack.Length() - 1; i++) {
     for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
-      aDT->SetTransform(mStateStack[i].pushedClips[c].transform);
+      aDT->SetTransform(mStateStack[i].pushedClips[c].transform * GetDeviceTransform());
       if (mStateStack[i].pushedClips[c].path) {
         aDT->PushClip(mStateStack[i].pushedClips[c].path);
       } else {
         aDT->PushClipRect(mStateStack[i].pushedClips[c].rect);
       }
     }
   }
 }
@@ -2075,26 +2085,26 @@ gfxContext::GetOp()
  */
 void
 gfxContext::ChangeTransform(const Matrix &aNewMatrix)
 {
   AzureState &state = CurrentState();
 
   if ((state.pattern || state.sourceSurface)
       && !state.patternTransformChanged) {
-    state.patternTransform = mDT->GetTransform();
+    state.patternTransform = mTransform;
     state.patternTransformChanged = true;
   }
 
   if (mPathBuilder || mPathIsRect) {
     Matrix invMatrix = aNewMatrix;
     
     invMatrix.Invert();
 
-    Matrix toNewUS = mDT->GetTransform() * invMatrix;
+    Matrix toNewUS = mTransform * invMatrix;
 
     if (toNewUS.IsRectilinear() && mPathIsRect) {
       mRect = toNewUS.TransformBounds(mRect);
       mRect.NudgeToIntegers();
     } else if (mPathIsRect) {
       mPathBuilder = mDT->CreatePathBuilder(CurrentState().fillRule);
       
       mPathBuilder->MoveTo(toNewUS * mRect.TopLeft());
@@ -2106,10 +2116,56 @@ gfxContext::ChangeTransform(const Matrix
       RefPtr<Path> path = mPathBuilder->Finish();
       // Create path in device space.
       mPathBuilder = path->TransformedCopyToBuilder(toNewUS);
     }
     // No need to consider the transform changed now!
     mTransformChanged = false;
   }
 
-  mDT->SetTransform(aNewMatrix);
+  mTransform = aNewMatrix;
+
+  mDT->SetTransform(GetDTTransform());
 }
+
+Rect
+gfxContext::GetAzureDeviceSpaceClipBounds()
+{
+  unsigned int lastReset = 0;
+  for (int i = mStateStack.Length() - 1; i > 0; i--) {
+    if (mStateStack[i].clipWasReset) {
+      lastReset = i;
+    }
+  }
+
+  Rect rect(CurrentState().deviceOffset.x, CurrentState().deviceOffset.y,
+            Float(mDT->GetSize().width), Float(mDT->GetSize().height));
+  for (unsigned int i = lastReset; i < mStateStack.Length(); i++) {
+    for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
+      AzureState::PushedClip &clip = mStateStack[i].pushedClips[c];
+      if (clip.path) {
+        Rect bounds = clip.path->GetBounds(clip.transform);
+        rect.IntersectRect(rect, bounds);
+      } else {
+        rect.IntersectRect(rect, clip.transform.TransformBounds(clip.rect));
+      }
+    }
+  }
+
+  return rect;
+}
+
+Matrix
+gfxContext::GetDeviceTransform() const
+{
+  Matrix mat;
+  mat.Translate(-CurrentState().deviceOffset.x, -CurrentState().deviceOffset.y);
+  return mat;
+}
+
+Matrix
+gfxContext::GetDTTransform() const
+{
+  Matrix mat = mTransform;
+  mat._31 -= CurrentState().deviceOffset.x;
+  mat._32 -= CurrentState().deviceOffset.y;
+  return mat;
+}
\ No newline at end of file
--- a/gfx/thebes/gfxContext.h
+++ b/gfx/thebes/gfxContext.h
@@ -733,26 +733,31 @@ private:
     bool clipWasReset;
     mozilla::gfx::FillRule fillRule;
     StrokeOptions strokeOptions;
     mozilla::RefPtr<DrawTarget> drawTarget;
     mozilla::RefPtr<DrawTarget> parentTarget;
     mozilla::gfx::AntialiasMode aaMode;
     bool patternTransformChanged;
     Matrix patternTransform;
+    // This is used solely for using minimal intermediate surface size.
+    mozilla::gfx::Point deviceOffset;
   };
 
   // This ensures mPath contains a valid path (in user space!)
   void EnsurePath();
   // This ensures mPathBuilder contains a valid PathBuilder (in user space!)
   void EnsurePathBuilder();
   void FillAzure(mozilla::gfx::Float aOpacity);
   void PushClipsToDT(mozilla::gfx::DrawTarget *aDT);
   CompositionOp GetOp();
   void ChangeTransform(const mozilla::gfx::Matrix &aNewMatrix);
+  Rect GetAzureDeviceSpaceClipBounds();
+  Matrix GetDeviceTransform() const;
+  Matrix GetDTTransform() const;
 
   bool mPathIsRect;
   bool mTransformChanged;
   Matrix mPathTransform;
   Rect mRect;
   mozilla::RefPtr<PathBuilder> mPathBuilder;
   mozilla::RefPtr<Path> mPath;
   Matrix mTransform;
--- a/js/src/builtin/ParallelArray-inl.h
+++ b/js/src/builtin/ParallelArray-inl.h
@@ -23,16 +23,32 @@ ParallelArrayObject::IndexInfo::inBounds
     for (uint32_t d = 0; d < indices.length(); d++) {
         if (indices[d] >= dimensions[d])
             return false;
     }
 
     return true;
 }
 
+inline bool
+ParallelArrayObject::IndexInfo::bump()
+{
+    JS_ASSERT(isInitialized());
+    JS_ASSERT(indices.length() > 0);
+
+    uint32_t d = indices.length() - 1;
+    while (++indices[d] == dimensions[d]) {
+        if (d == 0)
+            return false;
+        indices[d--] = 0;
+    }
+
+    return true;
+}
+
 inline uint32_t
 ParallelArrayObject::IndexInfo::scalarLengthOfDimensions()
 {
     JS_ASSERT(isInitialized());
     return dimensions[0] * partialProducts[0];
 }
 
 inline uint32_t
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -40,40 +40,158 @@ ReportMoreArgsNeeded(JSContext *cx, cons
 
 static bool
 ReportBadArg(JSContext *cx, const char *s = "")
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_ARG, s);
     return false;
 }
 
+static bool
+ReportBadLength(JSContext *cx)
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
+    return false;
+}
+
+static bool
+ReportBadLengthOrArg(JSContext *cx, HandleValue v, const char *s = "")
+{
+    return v.isNumber() ? ReportBadLength(cx) : ReportBadArg(cx, s);
+}
+
+static bool
+ReportBadPartition(JSContext *cx)
+{
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_PARTITION);
+    return false;
+}
+
 bool
 ParallelArrayObject::IndexInfo::isInitialized() const
 {
     return (dimensions.length() > 0 &&
             indices.capacity() >= dimensions.length() &&
             partialProducts.length() == dimensions.length());
 }
 
+static inline bool
+OpenDelimiters(const IndexInfo &iv, StringBuffer &sb)
+{
+    JS_ASSERT(iv.isInitialized());
+
+    uint32_t d = iv.dimensions.length() - 1;
+    do {
+        if (iv.indices[d] != 0)
+            break;
+        if (!sb.append('<'))
+            return false;
+    } while (d-- > 0);
+
+    return true;
+}
+
+static inline bool
+CloseDelimiters(const IndexInfo &iv, StringBuffer &sb)
+{
+    JS_ASSERT(iv.isInitialized());
+
+    uint32_t d = iv.dimensions.length() - 1;
+    do {
+        if (iv.indices[d] != iv.dimensions[d] - 1) {
+            if (!sb.append(','))
+                return false;
+            break;
+        }
+
+        if (!sb.append('>'))
+            return false;
+    } while (d-- > 0);
+
+    return true;
+}
+
+// A version of ToUint32 that reports if the input value is malformed: either
+// it is given to us as a negative integer or it overflows.
+static bool
+ToUint32(JSContext *cx, const Value &v, uint32_t *out, bool *malformed)
+{
+    AssertArgumentsAreSane(cx, v);
+    {
+        js::SkipRoot skip(cx, &v);
+        js::MaybeCheckStackRoots(cx);
+    }
+
+    *malformed = false;
+
+    if (v.isInt32()) {
+        int32_t i = v.toInt32();
+        if (i < 0) {
+            *malformed = true;
+            return true;
+        }
+        *out = static_cast<uint32_t>(i);
+        return true;
+    }
+
+    double d;
+    if (v.isDouble()) {
+        d = v.toDouble();
+    } else {
+        if (!ToNumberSlow(cx, v, &d))
+            return false;
+    }
+
+    *out = ToUint32(d);
+
+    if (!MOZ_DOUBLE_IS_FINITE(d) || d != static_cast<double>(*out)) {
+        *malformed = true;
+        return true;
+    }
+
+    return true;
+}
+
+static bool
+GetLength(JSContext *cx, HandleObject obj, uint32_t *length)
+{
+    // If obj's length cannot overflow, just use GetLengthProperty.
+    if (obj->isArray() || obj->isArguments())
+        return GetLengthProperty(cx, obj, length);
+
+    // Otherwise check that we don't overflow uint32.
+    RootedValue value(cx);
+    if (!JSObject::getProperty(cx, obj, obj, cx->names().length, &value))
+        return false;
+
+    bool malformed;
+    if (!ToUint32(cx, value, length, &malformed))
+        return false;
+    if (malformed)
+        return ReportBadLengthOrArg(cx, value);
+
+    return true;
+}
+
 // Check if obj is a parallel array, and if so, cast to pa and initialize
 // the IndexInfo accordingly.
 //
 // This function is designed to be used in conjunction with
 // GetElementFromArrayLikeObject; see below.
 static bool
 MaybeGetParallelArrayObjectAndLength(JSContext *cx, HandleObject obj,
                                      MutableHandle<ParallelArrayObject *> pa,
                                      IndexInfo *iv, uint32_t *length)
 {
     if (ParallelArrayObject::is(obj)) {
         pa.set(ParallelArrayObject::as(obj));
         if (!pa->isOneDimensional() && !iv->initialize(cx, pa, 1))
             return false;
         *length = pa->outermostDimension();
-    } else if (!GetLengthProperty(cx, obj, length)) {
+    } else if (!GetLength(cx, obj, length)) {
         return false;
     }
 
     return true;
 }
 
 // Store the i-th element of the array-like object obj into vp.
 //
@@ -197,35 +315,42 @@ NewDenseArrayWithType(JSContext *cx, uin
         return NULL;
 
     return *buffer.address();
 }
 
 // Copy an array like object obj into an IndexVector, indices, using
 // ToUint32.
 static inline bool
-ArrayLikeToIndexVector(JSContext *cx, HandleObject obj, IndexVector &indices)
+ArrayLikeToIndexVector(JSContext *cx, HandleObject obj, IndexVector &indices,
+                       bool *malformed)
 {
     IndexInfo iv(cx);
     RootedParallelArrayObject pa(cx);
     uint32_t length;
 
+    *malformed = false;
+
     if (!MaybeGetParallelArrayObjectAndLength(cx, obj, &pa, &iv, &length))
         return false;
 
     if (!indices.resize(length))
         return false;
 
     RootedValue elem(cx);
+    bool malformed_;
     for (uint32_t i = 0; i < length; i++) {
         if (!GetElementFromArrayLikeObject(cx, obj, pa, iv, i, &elem) ||
-            !ToUint32(cx, elem, &indices[i]))
+            !ToUint32(cx, elem, &indices[i], &malformed_))
         {
             return false;
         }
+
+        if (malformed_)
+            *malformed = true;
     }
 
     return true;
 }
 
 static inline bool
 IdIsInBoundsIndex(JSContext *cx, HandleObject obj, HandleId id)
 {
@@ -328,22 +453,21 @@ ParallelArrayObject::SequentialMode::bui
     JS_ASSERT(iv.isInitialized());
 
     uint32_t length = iv.scalarLengthOfDimensions();
 
     InvokeArgsGuard args;
     if (!cx->stack.pushInvokeArgs(cx, iv.dimensions.length(), &args))
         return ExecutionFailed;
 
-    for (uint32_t i = 0; i < length; i++) {
+    for (uint32_t i = 0; i < length; i++, iv.bump()) {
         args.setCallee(ObjectValue(*elementalFun));
         args.setThis(UndefinedValue());
 
         // Compute and set indices.
-        iv.fromScalar(i);
         for (size_t j = 0; j < iv.indices.length(); j++)
             args[j].setNumber(iv.indices[j]);
 
         if (!Invoke(cx, args))
             return ExecutionFailed;
 
         JSObject::setDenseArrayElementWithType(cx, buffer, i, args.rval());
     }
@@ -474,23 +598,29 @@ ParallelArrayObject::SequentialMode::sca
 
     // Iterate over the scatter vector, but not more than the length of the
     // source array.
     RootedValue elem(cx);
     RootedValue telem(cx);
     RootedValue targetElem(cx);
     for (uint32_t i = 0; i < Min(targetsLength, source->outermostDimension()); i++) {
         uint32_t targetIndex;
+        bool malformed;
 
         if (!GetElementFromArrayLikeObject(cx, targets, targetsPA, tiv, i, &telem) ||
-            !ToUint32(cx, telem, &targetIndex))
+            !ToUint32(cx, telem, &targetIndex, &malformed))
         {
             return ExecutionFailed;
         }
 
+        if (malformed) {
+            ReportBadArg(cx, ".prototype.scatter");
+            return ExecutionFailed;
+        }
+
         if (targetIndex >= length) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_SCATTER_BOUNDS);
             return ExecutionFailed;
         }
 
         if (!source->getParallelArrayElement(cx, i, &iv, &elem))
             return ExecutionFailed;
 
@@ -1069,17 +1199,17 @@ ParallelArrayObject::construct(JSContext
     if (args.length() == 1) {
         RootedObject source(cx, NonNullObject(cx, args[0]));
         if (!source)
             return false;
 
         // When using an array value we can only make one dimensional arrays.
         IndexVector dims(cx);
         uint32_t length;
-        if (!dims.resize(1) || !GetLengthProperty(cx, source, &length))
+        if (!dims.resize(1) || !GetLength(cx, source, &length))
             return false;
         dims[0] = length;
 
         RootedObject buffer(cx, NewDenseCopiedArrayWithType(cx, length, source));
         if (!buffer)
             return false;
 
         return create(cx, buffer, 0, dims, args.rval());
@@ -1088,41 +1218,58 @@ ParallelArrayObject::construct(JSContext
     // Second case: initialize using a length/dimensions vector and kernel.
     //
     // If the length is an integer, we build a 1-dimensional parallel
     // array using the kernel.
     //
     // If the length is an array-like object of sizes, the i-th value in the
     // dimension array is the size of the i-th dimension.
     IndexInfo iv(cx);
+    bool malformed;
     if (args[0].isObject()) {
         RootedObject dimObj(cx, &(args[0].toObject()));
-        if (!ArrayLikeToIndexVector(cx, dimObj, iv.dimensions))
+        if (!ArrayLikeToIndexVector(cx, dimObj, iv.dimensions, &malformed))
             return false;
+        if (malformed)
+            return ReportBadLength(cx);
     } else {
-        if (!iv.dimensions.resize(1) || !ToUint32(cx, args[0], &iv.dimensions[0]))
+        if (!iv.dimensions.resize(1))
+            return false;
+
+        if (!ToUint32(cx, args[0], &iv.dimensions[0], &malformed))
             return false;
+        if (malformed) {
+            RootedValue arg0(cx, args[0]);
+            return ReportBadLengthOrArg(cx, arg0);
+        }
     }
 
     // If the first argument wasn't a array-like or had no length, assume
     // empty parallel array, i.e. with shape being [0].
     if (iv.dimensions.length() == 0 && !iv.dimensions.append(0))
         return false;
 
-    if (!iv.initialize(0))
+    // Initialize with every dimension packed.
+    if (!iv.initialize(iv.dimensions.length()))
         return false;
 
+    // We checked that each individual dimension does not overflow; now check
+    // that the scalar length does not overflow.
+    uint32_t length = iv.scalarLengthOfDimensions();
+    double d = iv.dimensions[0];
+    for (uint32_t i = 1; i < iv.dimensions.length(); i++)
+        d *= iv.dimensions[i];
+    if (d != static_cast<double>(length))
+        return ReportBadLength(cx);
+
     // Extract second argument, the elemental function.
     RootedObject elementalFun(cx, ValueToCallable(cx, &args[1]));
     if (!elementalFun)
         return false;
 
-    // How long the flattened array will be.
-    uint32_t length = iv.scalarLengthOfDimensions();
-
     // Create backing store.
     RootedObject buffer(cx, NewDenseArrayWithType(cx, length));
     if (!buffer)
         return false;
 
 #ifdef DEBUG
     if (args.length() > 2) {
         DebugOptions options;
@@ -1286,18 +1433,23 @@ ParallelArrayObject::scatter(JSContext *
         if (!conflictFun)
             return false;
     }
 
     // The length of the result array is optional and defaults to the length
     // of the source array.
     uint32_t resultLength;
     if (args.length() >= 4) {
-        if (!ToUint32(cx, args[3], &resultLength))
+        bool malformed;
+        if (!ToUint32(cx, args[3], &resultLength, &malformed))
             return false;
+        if (malformed) {
+            RootedValue arg3(cx, args[3]);
+            return ReportBadLengthOrArg(cx, arg3, ".prototype.scatter");
+        }
     } else {
         resultLength = outer;
     }
 
     // Create a destination buffer. Fail if we can't maintain denseness.
     RootedObject buffer(cx, NewDenseArrayWithType(cx, resultLength));
     if (!buffer)
         return false;
@@ -1386,27 +1538,28 @@ ParallelArrayObject::flatten(JSContext *
 
 bool
 ParallelArrayObject::partition(JSContext *cx, CallArgs args)
 {
     if (args.length() < 1)
         return ReportMoreArgsNeeded(cx, "ParallelArray.prototype.partition", "0", "s");
 
     uint32_t newDimension;
-    if (!ToUint32(cx, args[0], &newDimension))
+    bool malformed;
+    if (!ToUint32(cx, args[0], &newDimension, &malformed))
         return false;
+    if (malformed)
+        return ReportBadPartition(cx);
 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
 
     // Throw if the outer dimension is not divisible by the new dimension.
     uint32_t outer = obj->outermostDimension();
-    if (newDimension == 0 || outer % newDimension) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_BAD_PARTITION);
-        return false;
-    }
+    if (newDimension == 0 || outer % newDimension)
+        return ReportBadPartition(cx);
 
     IndexVector dims(cx);
     if (!obj->getDimensions(cx, dims))
         return false;
 
     // Set the new outermost dimension to be the quotient of the old outermost
     // dimension and the new dimension.
     if (!dims.insert(dims.begin(), outer / newDimension))
@@ -1428,23 +1581,31 @@ ParallelArrayObject::get(JSContext *cx, 
     RootedParallelArrayObject obj(cx, as(&args.thisv().toObject()));
     RootedObject indicesObj(cx, NonNullObject(cx, args[0]));
     if (!indicesObj)
         return false;
 
     IndexInfo iv(cx);
     if (!iv.initialize(cx, obj, 0))
         return false;
-    if (!ArrayLikeToIndexVector(cx, indicesObj, iv.indices))
+
+    bool malformed;
+    if (!ArrayLikeToIndexVector(cx, indicesObj, iv.indices, &malformed))
         return false;
 
     // Throw if the shape of the index vector is wrong.
     if (iv.indices.length() == 0 || iv.indices.length() > iv.dimensions.length())
         return ReportBadArg(cx, ".prototype.get");
 
+    // Don't throw on overflow, just return undefined.
+    if (malformed) {
+        args.rval().setUndefined();
+        return true;
+    }
+
     return obj->getParallelArrayElement(cx, iv, args.rval());
 }
 
 bool
 ParallelArrayObject::dimensionsGetter(JSContext *cx, CallArgs args)
 {
     RootedObject dimArray(cx, as(&args.thisv().toObject())->dimensionArray());
     RootedObject copy(cx, NewDenseCopiedArray(cx, dimArray->getDenseArrayInitializedLength(),
@@ -1460,76 +1621,42 @@ ParallelArrayObject::dimensionsGetter(JS
 bool
 ParallelArrayObject::lengthGetter(JSContext *cx, CallArgs args)
 {
     args.rval().setNumber(as(&args.thisv().toObject())->outermostDimension());
     return true;
 }
 
 bool
-ParallelArrayObject::toStringBufferImpl(JSContext *cx, IndexInfo &iv, bool useLocale,
-                                        HandleObject buffer, StringBuffer &sb)
+ParallelArrayObject::toStringBuffer(JSContext *cx, bool useLocale, StringBuffer &sb)
 {
-    JS_ASSERT(iv.isInitialized());
-
-    // The dimension we're printing out.
-    uint32_t d = iv.indices.length() + 1;
-
-    // If we still have more dimensions to go.
-    if (d < iv.dimensions.length()) {
-        if (!sb.append('<'))
-            return false;
-
-        iv.indices.infallibleAppend(0);
-        uint32_t length = iv.dimensions[d - 1];
-        for (size_t i = 0; i < length; i++) {
-            iv.indices[d - 1] = i;
-            if (!toStringBufferImpl(cx, iv, useLocale, buffer, sb) ||
-                (i + 1 != length && !sb.append(',')))
-            {
-                return false;
-            }
-        }
-        iv.indices.shrinkBy(1);
-
-        if (!sb.append('>'))
-            return false;
-
-        return true;
-    }
-
-    // We're on the last dimension.
-    if (!sb.append('<'))
+    if (!JS_CHECK_OPERATION_LIMIT(cx))
         return false;
 
-    uint32_t offset;
-    uint32_t length;
+    RootedParallelArrayObject self(cx, this);
+    IndexInfo iv(cx);
 
-    // If the array is flat, we can just use the entire extent.
-    if (d == 1) {
-        offset = bufferOffset();
-        length = iv.dimensions[0];
-    } else {
-        offset = bufferOffset() + iv.toScalar();
-        length = iv.partialProducts[d - 2];
-    }
+    if (!self->getDimensions(cx, iv.dimensions) || !iv.initialize(iv.dimensions.length()))
+        return false;
+
+    uint32_t length = iv.scalarLengthOfDimensions();
 
     RootedValue tmp(cx);
     RootedValue localeElem(cx);
     RootedId id(cx);
 
-    const Value *start = buffer->getDenseArrayElements() + offset;
+    const Value *start = buffer()->getDenseArrayElements() + bufferOffset();
     const Value *end = start + length;
     const Value *elem;
 
-    for (elem = start; elem < end; elem++) {
+    for (elem = start; elem < end; elem++, iv.bump()) {
         // All holes in parallel arrays are eagerly filled with undefined.
         JS_ASSERT(!elem->isMagic(JS_ARRAY_HOLE));
 
-        if (!JS_CHECK_OPERATION_LIMIT(cx))
+        if (!OpenDelimiters(iv, sb))
             return false;
 
         if (!elem->isNullOrUndefined()) {
             if (useLocale) {
                 tmp = *elem;
                 RootedObject robj(cx, ToObject(cx, tmp));
                 if (!robj)
                     return false;
@@ -1541,38 +1668,24 @@ ParallelArrayObject::toStringBufferImpl(
                     return false;
                 }
             } else {
                 if (!ValueToStringBuffer(cx, *elem, sb))
                     return false;
             }
         }
 
-        if (elem + 1 != end && !sb.append(','))
+        if (!CloseDelimiters(iv, sb))
             return false;
     }
 
-    if (!sb.append('>'))
-        return false;
-
     return true;
 }
 
 bool
-ParallelArrayObject::toStringBuffer(JSContext *cx, bool useLocale, StringBuffer &sb)
-{
-    RootedParallelArrayObject self(cx, this);
-    IndexInfo iv(cx);
-    if (!iv.initialize(cx, self, 0))
-        return false;
-    RootedObject buffer(cx, this->buffer());
-    return toStringBufferImpl(cx, iv, useLocale, buffer, sb);
-}
-
-bool
 ParallelArrayObject::toString(JSContext *cx, CallArgs args)
 {
     StringBuffer sb(cx);
     if (!as(&args.thisv().toObject())->toStringBuffer(cx, false, sb))
         return false;
 
     if (JSString *str = sb.finishString()) {
         args.rval().setString(str);
--- a/js/src/builtin/ParallelArray.h
+++ b/js/src/builtin/ParallelArray.h
@@ -114,16 +114,20 @@ class ParallelArrayObject : public JSObj
         // The dimensions vector must be filled already, and space must be <=
         // dimensions.length().
         inline bool initialize(uint32_t space);
 
         // Load dimensions from a source, then initialize as above.
         inline bool initialize(JSContext *cx, HandleParallelArrayObject source,
                                uint32_t space);
 
+        // Bump the index by 1, wrapping over if necessary. Returns false when
+        // the increment would go out of bounds.
+        inline bool bump();
+
         // Get the scalar length according to the dimensions vector, i.e. the
         // product of the dimensions vector.
         inline uint32_t scalarLengthOfDimensions();
 
         // Compute the scalar index from the current index vector.
         inline uint32_t toScalar();
 
         // Set the index vector according to a scalar index.
@@ -317,19 +321,16 @@ class ParallelArrayObject : public JSObj
 #endif
 
     static JSFunctionSpec methods[];
     static Class protoClass;
 
     static inline bool DenseArrayToIndexVector(JSContext *cx, HandleObject obj,
                                                IndexVector &indices);
 
-    bool toStringBufferImpl(JSContext *cx, IndexInfo &iv, bool useLocale,
-                            HandleObject buffer, StringBuffer &sb);
-
     static bool create(JSContext *cx, MutableHandleValue vp);
     static bool create(JSContext *cx, HandleObject buffer, MutableHandleValue vp);
     static bool create(JSContext *cx, HandleObject buffer, uint32_t offset,
                        const IndexVector &dims, MutableHandleValue vp);
     static JSBool construct(JSContext *cx, unsigned argc, Value *vp);
 
     static bool map(JSContext *cx, CallArgs args);
     static bool reduce(JSContext *cx, CallArgs args);
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -394,19 +394,24 @@ case "$target" in
     if test "$GCC" != "yes"; then
         # Check to see if we are really running in a msvc environemnt
         _WIN32_MSVC=1
 
         # Make sure compilers are valid
         CFLAGS="$CFLAGS -TC -nologo"
         CXXFLAGS="$CXXFLAGS -TP -nologo"
         # MSVC warning C4345 warns of newly conformant behavior as of VS2003.
+        # MSVC warning C4351 warns of newly conformant behavior as of VS2005.
+        # MSVC warning C4800 warns when a value is implicitly cast to bool,
+        # because this also forces narrowing to a single byte, which can be a
+        # perf hit.  But this matters so little in practice (and often we want
+        # that behavior) that it's better to turn it off.
         # _CRT_SECURE_NO_WARNINGS disables warnings about using MSVC-specific
         # secure CRT functions.
-        CXXFLAGS="$CXXFLAGS -wd4345 -D_CRT_SECURE_NO_WARNINGS"
+        CXXFLAGS="$CXXFLAGS -wd4345 -wd4351 -wd4800 -D_CRT_SECURE_NO_WARNINGS"
         AC_LANG_SAVE
         AC_LANG_C
         AC_TRY_COMPILE([#include <stdio.h>],
             [ printf("Hello World\n"); ],,
             AC_MSG_ERROR([\$(CC) test failed.  You must have MS VC++ in your path to build.]) )
 
         AC_LANG_CPLUSPLUS
         AC_TRY_COMPILE([#include <new.h>],
@@ -1757,18 +1762,18 @@ ia64*-hpux*)
         MKSHLIB_FORCE_ALL=
         MKSHLIB_UNFORCE_ALL=
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS
         _USE_CPP_INCLUDE_FLAG=1
         _DEFINES_CFLAGS='-FI $(DEPTH)/js-confdefs.h -DMOZILLA_CLIENT'
         _DEFINES_CXXFLAGS='-FI $(DEPTH)/js-confdefs.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
         CXXFLAGS="$CXXFLAGS -W3 -Gy -Fd\$(COMPILE_PDBFILE)"
-        # MSVC warnings C4244 and C4800 are ubiquitous, useless, and annoying.
-        CXXFLAGS="$CXXFLAGS -wd4244 -wd4800"
+        # MSVC warning C4244 is ubiquitous, useless, and annoying.
+        CXXFLAGS="$CXXFLAGS -wd4244"
         # make 'foo == bar;' error out
         CFLAGS="$CFLAGS -we4553"
         CXXFLAGS="$CXXFLAGS -we4553"
         LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib psapi.lib"
         MOZ_DEBUG_FLAGS='-Zi'
         MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV'
         WARNINGS_AS_ERRORS='-WX'
         MOZ_OPTIMIZE_FLAGS="-O2"
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -696,17 +696,17 @@ EnclosingStaticScope(BytecodeEmitter *bc
     if (bce->blockChain)
         return bce->blockChain;
 
     if (!bce->sc->isFunction) {
         JS_ASSERT(!bce->parent);
         return NULL;
     }
 
-    return bce->sc->asFunbox()->fun();
+    return bce->sc->asFunbox()->function();
 }
 
 // Push a block scope statement and link blockObj into bce->blockChain.
 static void
 PushBlockScopeBCE(BytecodeEmitter *bce, StmtInfoBCE *stmt, StaticBlockObject &blockObj,
                   ptrdiff_t top)
 {
     PushStatementBCE(bce, stmt, STMT_BLOCK, top);
@@ -912,17 +912,17 @@ EmitAliasedVarOp(JSContext *cx, JSOp op,
     if (pn->isUsed()) {
         /*
          * As explained in BindNameToSlot, the 'level' of a use indicates how
          * many function scopes (i.e., BytecodeEmitters) to skip to find the
          * enclosing function scope of the definition being accessed.
          */
         for (unsigned i = pn->pn_cookie.level(); i; i--) {
             skippedScopes += ClonedBlockDepth(bceOfDef);
-            JSFunction *funOfDef = bceOfDef->sc->asFunbox()->fun();
+            JSFunction *funOfDef = bceOfDef->sc->asFunbox()->function();
             if (funOfDef->isHeavyweight()) {
                 skippedScopes++;
                 if (funOfDef->isNamedLambda())
                     skippedScopes++;
             }
             bceOfDef = bceOfDef->parent;
         }
     } else {
@@ -1373,17 +1373,17 @@ BindNameToSlot(JSContext *cx, BytecodeEm
 
         /*
          * Currently, the ALIASEDVAR ops do not support accessing the
          * callee of a DeclEnvObject, so use NAME.
          */
         if (dn->pn_cookie.level() != bce->script->staticLevel)
             return true;
 
-        RootedFunction fun(cx, bce->sc->asFunbox()->fun());
+        RootedFunction fun(cx, bce->sc->asFunbox()->function());
         JS_ASSERT(fun->flags & JSFUN_LAMBDA);
         JS_ASSERT(pn->pn_atom == fun->atom());
 
         /*
          * Leave pn->isOp(JSOP_NAME) if bce->fun is heavyweight to
          * address two cases: a new binding introduced by eval, and
          * assignment to the name in strict mode.
          *
@@ -2687,17 +2687,17 @@ MaybeEmitVarDecl(JSContext *cx, Bytecode
     if (!pn->pn_cookie.isFree()) {
         atomIndex = pn->pn_cookie.slot();
     } else {
         if (!bce->makeAtomIndex(pn->pn_atom, &atomIndex))
             return false;
     }
 
     if (JOF_OPTYPE(pn->getOp()) == JOF_ATOM &&
-        (!bce->sc->isFunction || bce->sc->asFunbox()->fun()->isHeavyweight()))
+        (!bce->sc->isFunction || bce->sc->asFunbox()->function()->isHeavyweight()))
     {
         bce->switchToProlog();
         if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin))
             return false;
         if (!EmitIndexOp(cx, prologOp, atomIndex, bce))
             return false;
         bce->switchToMain();
     }
@@ -4830,17 +4830,17 @@ EmitFor(JSContext *cx, BytecodeEmitter *
     return pn->pn_left->isKind(PNK_FORIN)
            ? EmitForIn(cx, bce, pn, top)
            : EmitNormalFor(cx, bce, pn, top);
 }
 
 static JS_NEVER_INLINE bool
 EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
-    RootedFunction fun(cx, pn->pn_funbox->fun());
+    RootedFunction fun(cx, pn->pn_funbox->function());
     JS_ASSERT(fun->isInterpreted());
     if (fun->script()) {
         /*
          * This second pass is needed to emit JSOP_NOP with a source note
          * for the already-emitted function definition prolog opcode. See
          * comments in EmitStatementList.
          */
         JS_ASSERT(pn->functionIsHoisted());
@@ -4886,17 +4886,17 @@ EmitFunc(JSContext *cx, BytecodeEmitter 
             return false;
 
         /* We measured the max scope depth when we parsed the function. */
         if (!EmitFunctionScript(cx, &bce2, pn->pn_body))
             return false;
     }
 
     /* Make the function object a literal in the outer script's pool. */
-    unsigned index = bce->objectList.add(&pn->pn_funbox->objbox);
+    unsigned index = bce->objectList.add(pn->pn_funbox);
 
     /* Non-hoisted functions simply emit their respective op. */
     if (!pn->functionIsHoisted()) {
         if (pn->pn_funbox->inGenexpLambda && NewSrcNote(cx, bce, SRC_GENEXP) < 0)
             return false;
 
         return EmitIndex32(cx, pn->getOp(), index, bce);
     }
@@ -6014,17 +6014,17 @@ frontend::EmitTree(JSContext *cx, Byteco
 
     switch (pn->getKind()) {
       case PNK_FUNCTION:
         ok = EmitFunc(cx, bce, pn);
         break;
 
       case PNK_ARGSBODY:
       {
-        RootedFunction fun(cx, bce->sc->asFunbox()->fun());
+        RootedFunction fun(cx, bce->sc->asFunbox()->function());
         ParseNode *pnlast = pn->last();
 
         // Carefully emit everything in the right order:
         // 1. Destructuring
         // 2. Functions
         // 3. Defaults
         ParseNode *pnchild = pnlast->pn_head;
         if (pnlast->pn_xflags & PNX_DESTRUCT) {
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -170,17 +170,17 @@ class NameResolver
 
     /*
      * Resolve the name of a function. If the function already has a name
      * listed, then it is skipped. Otherwise an intelligent name is guessed to
      * assign to the function's displayAtom field
      */
     JSAtom *resolveFun(ParseNode *pn, HandleAtom prefix) {
         JS_ASSERT(pn != NULL && pn->isKind(PNK_FUNCTION));
-        RootedFunction fun(cx, pn->pn_funbox->fun());
+        RootedFunction fun(cx, pn->pn_funbox->function());
         if (nparents == 0)
             return NULL;
 
         StringBuffer buf(cx);
         this->buf = &buf;
 
         /* If the function already has a name, use that */
         if (fun->displayAtom() != NULL) {
--- a/js/src/frontend/ParseNode-inl.h
+++ b/js/src/frontend/ParseNode-inl.h
@@ -27,17 +27,17 @@ UpvarCookie::set(JSContext *cx, unsigned
     slot_ = newSlot;
     return true;
 }
 
 inline PropertyName *
 ParseNode::name() const
 {
     JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME) || isKind(PNK_INTRINSICNAME));
-    JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->fun()->atom() : pn_atom;
+    JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->function()->atom() : pn_atom;
     return atom->asPropertyName();
 }
 
 inline bool
 ParseNode::isConstant()
 {
     switch (pn_type) {
       case PNK_NUMBER:
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -429,17 +429,17 @@ CloneParseTree(ParseNode *opn, Parser *p
     pn->setDefn(opn->isDefn());
     pn->setUsed(opn->isUsed());
 
     switch (pn->getArity()) {
 #define NULLCHECK(e)    JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO
 
       case PN_FUNC:
         NULLCHECK(pn->pn_funbox =
-                  parser->newFunctionBox(opn->pn_funbox->fun(), pc, opn->pn_funbox->strictModeState));
+                  parser->newFunctionBox(opn->pn_funbox->function(), pc, opn->pn_funbox->strictModeState));
         NULLCHECK(pn->pn_body = CloneParseTree(opn->pn_body, parser));
         pn->pn_cookie = opn->pn_cookie;
         pn->pn_dflags = opn->pn_dflags;
         pn->pn_blockid = opn->pn_blockid;
         break;
 
       case PN_LIST:
         pn->makeEmpty();
@@ -786,8 +786,27 @@ NameNode::dump(int indent)
     else {
         fprintf(stderr, "(%s ", name);
         indent += strlen(name) + 2;
         DumpParseTree(expr(), indent);
         fprintf(stderr, ")");
     }
 }
 #endif
+
+ObjectBox::ObjectBox(JSObject *object, ObjectBox* traceLink)
+  : object(object),
+    traceLink(traceLink),
+    emitLink(NULL)
+{
+}
+
+void
+ObjectBox::trace(JSTracer *trc)
+{
+    ObjectBox *box = this;
+    while (box) {
+        MarkObjectRoot(trc, &box->object, "parser.object");
+        if (box->isFunctionBox())
+            box->asFunctionBox()->bindings.trace(trc);
+        box = box->traceLink;
+    }
+}
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -1452,26 +1452,28 @@ LinkUseToDef(ParseNode *pn, Definition *
     JS_ASSERT(pn != dn->dn_uses);
     pn->pn_link = dn->dn_uses;
     dn->dn_uses = pn;
     dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
     pn->setUsed(true);
     pn->pn_lexdef = dn;
 }
 
-struct ObjectBox {
-    ObjectBox           *traceLink;
-    ObjectBox           *emitLink;
-    JSObject            *object;
+class ObjectBox {
+  public:
+    JSObject *object;
 
-    // An ObjectBox can hold a JSObject or a JSFunction.  In the latter case,
-    // the ObjectBox will be embedded within a FunctionBox;  |funbox| points to
-    // that FunctionBox.
-    FunctionBox         *const funbox;
+    ObjectBox(JSObject *object, ObjectBox *traceLink);
+    bool isFunctionBox() { return object->isFunction(); }
+    FunctionBox *asFunctionBox() { JS_ASSERT(isFunctionBox()); return (FunctionBox *)(this); }
+    void trace(JSTracer *trc);
 
-    ObjectBox(ObjectBox *traceLink, JSObject *obj);
-    ObjectBox(ObjectBox *traceLink, JSFunction *fun, FunctionBox *funbox);
+  protected:
+    friend struct CGObjectList;
+
+    ObjectBox *traceLink;
+    ObjectBox *emitLink;
 };
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* ParseNode_h__ */
--- a/js/src/frontend/Parser-inl.h
+++ b/js/src/frontend/Parser-inl.h
@@ -17,17 +17,17 @@ inline unsigned
 ParseContext::blockid()
 {
     return topStmt ? topStmt->blockid : bodyid;
 }
 
 inline bool
 ParseContext::atBodyLevel()
 {
-    return !topStmt || topStmt->isFunctionBodyBlock;
+    return !topStmt;
 }
 
 inline
 ParseContext::ParseContext(Parser *prs, SharedContext *sc, unsigned staticLevel, uint32_t bodyid)
   : sc(sc),
     bodyid(0),           // initialized in init()
     blockidGen(bodyid),  // used to set |bodyid| and subsequently incremented in init()
     topStmt(NULL),
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -109,17 +109,16 @@ frontend::GenerateBlockId(ParseContext *
     return true;
 }
 
 static void
 PushStatementPC(ParseContext *pc, StmtInfoPC *stmt, StmtType type)
 {
     stmt->blockid = pc->blockid();
     PushStatement(pc, stmt, type);
-    stmt->isFunctionBodyBlock = false;
 }
 
 // See comment on member function declaration.
 bool
 ParseContext::define(JSContext *cx, PropertyName *name, ParseNode *pn, Definition::Kind kind)
 {
     JS_ASSERT(!pn->isUsed());
     JS_ASSERT_IF(pn->isDefn(), pn->isPlaceholder());
@@ -313,17 +312,17 @@ ParseContext::generateFunctionBindings(J
     if (!Bindings::initWithTemporaryStorage(cx, bindings, args_.length(), vars_.length(),
                                             packedBindings))
     {
         return false;
     }
 
     FunctionBox *funbox = sc->asFunbox();
     if (bindings->hasAnyAliasedBindings() || funbox->hasExtensibleScope())
-        funbox->fun()->flags |= JSFUN_HEAVYWEIGHT;
+        funbox->function()->flags |= JSFUN_HEAVYWEIGHT;
 
     return true;
 }
 
 Parser::Parser(JSContext *cx, const CompileOptions &options,
                const jschar *chars, size_t length, bool foldConstants)
   : AutoGCRooter(cx, PARSER),
     context(cx),
@@ -354,60 +353,44 @@ Parser::init()
 
 Parser::~Parser()
 {
     JSContext *cx = context;
     cx->tempLifoAlloc().release(tempPoolMark);
     cx->activeCompilations--;
 }
 
-ObjectBox::ObjectBox(ObjectBox* traceLink, JSObject *obj)
-  : traceLink(traceLink),
-    emitLink(NULL),
-    object(obj),
-    funbox(NULL)
-{
-}
-
-ObjectBox::ObjectBox(ObjectBox* traceLink, JSFunction *fun, FunctionBox *funbox)
-  : traceLink(traceLink),
-    emitLink(NULL),
-    object(fun),
-    funbox(funbox)
-{
-}
-
 ObjectBox *
 Parser::newObjectBox(JSObject *obj)
 {
     JS_ASSERT(obj && !IsPoisonedPtr(obj));
 
     /*
      * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
      * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
      * arenas containing the entries must be alive until we are done with
      * scanning, parsing and code generation for the whole script or top-level
      * function.
      */
 
-    ObjectBox *objbox = context->tempLifoAlloc().new_<ObjectBox>(traceListHead, obj);
+    ObjectBox *objbox = context->tempLifoAlloc().new_<ObjectBox>(obj, traceListHead);
     if (!objbox) {
         js_ReportOutOfMemory(context);
         return NULL;
     }
 
     traceListHead = objbox;
 
     return objbox;
 }
 
 FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fun,
                          ParseContext *outerpc, StrictMode sms)
-  : SharedContext(cx, /* isFunction = */ true, sms),
-    objbox(traceListHead, fun, this),
+  : ObjectBox(fun, traceListHead),
+    SharedContext(cx, /* isFunction = */ true, sms),
     bindings(),
     bufStart(0),
     bufEnd(0),
     ndefaults(0),
     inWith(false),                  // initialized below
     inGenexpLambda(false),
     funCxFlags()
 {
@@ -468,31 +451,25 @@ Parser::newFunctionBox(JSFunction *fun, 
      */
     FunctionBox *funbox =
         context->tempLifoAlloc().new_<FunctionBox>(context, traceListHead, fun, outerpc, sms);
     if (!funbox) {
         js_ReportOutOfMemory(context);
         return NULL;
     }
 
-    traceListHead = &funbox->objbox;
+    traceListHead = funbox;
 
     return funbox;
 }
 
 void
 Parser::trace(JSTracer *trc)
 {
-    ObjectBox *objbox = traceListHead;
-    while (objbox) {
-        MarkObjectRoot(trc, &objbox->object, "parser.object");
-        if (objbox->funbox)
-            objbox->funbox->bindings.trace(trc);
-        objbox = objbox->traceLink;
-    }
+    traceListHead->trace(trc);
 }
 
 static bool
 GenerateBlockIdForStmtNode(ParseNode *pn, ParseContext *pc)
 {
     JS_ASSERT(pc->topStmt);
     JS_ASSERT(pc->topStmt->maybeScope());
     JS_ASSERT(pn->isKind(PNK_STATEMENTLIST) || pn->isKind(PNK_LEXICALSCOPE));
@@ -659,17 +636,17 @@ HasFinalReturn(ParseNode *pn)
     }
 }
 
 static bool
 ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, Parser::Reporter reporter,
                 unsigned errnum, unsigned anonerrnum)
 {
     JSAutoByteString name;
-    JSAtom *atom = parser->pc->sc->asFunbox()->fun()->atom();
+    JSAtom *atom = parser->pc->sc->asFunbox()->function()->atom();
     if (atom) {
         if (!js_AtomToPrintableString(cx, atom, &name))
             return false;
     } else {
         errnum = anonerrnum;
     }
     return (parser->*reporter)(pn, errnum, name.ptr());
 }
@@ -728,21 +705,16 @@ CheckStrictBinding(JSContext *cx, Parser
 
     return true;
 }
 
 ParseNode *
 Parser::functionBody(FunctionBodyType type)
 {
     JS_ASSERT(pc->sc->isFunction);
-
-    StmtInfoPC stmtInfo(context);
-    PushStatementPC(pc, &stmtInfo, STMT_BLOCK);
-    stmtInfo.isFunctionBodyBlock = true;
-
     JS_ASSERT(!pc->funHasReturnExpr && !pc->funHasReturnVoid);
 
     ParseNode *pn;
     if (type == StatementListBody) {
         pn = statements();
     } else {
         JS_ASSERT(type == ExpressionBody);
         JS_ASSERT(JS_HAS_EXPR_CLOSURES);
@@ -768,19 +740,16 @@ Parser::functionBody(FunctionBodyType ty
                 }
             }
         }
     }
 
     if (!pn)
         return NULL;
 
-    JS_ASSERT(!pc->topStmt->isBlockScope);
-    FinishPopStatement(pc);
-
     /* Check for falling off the end of a function that returns a value. */
     if (context->hasStrictOption() && pc->funHasReturnExpr &&
         !CheckFinalReturn(context, this, pn))
     {
         pn = NULL;
     }
 
     /* Time to implement the odd semantics of 'arguments'. */
@@ -822,17 +791,17 @@ Parser::functionBody(FunctionBodyType ty
 
     /*
      * Report error if both rest parameters and 'arguments' are used. Do this
      * check before adding artificial 'arguments' below.
      */
     Definition *maybeArgDef = pc->decls().lookupFirst(arguments);
     bool argumentsHasBinding = !!maybeArgDef;
     bool argumentsHasLocalBinding = maybeArgDef && maybeArgDef->kind() != Definition::ARG;
-    bool hasRest = pc->sc->asFunbox()->fun()->hasRest();
+    bool hasRest = pc->sc->asFunbox()->function()->hasRest();
     if (hasRest && argumentsHasLocalBinding) {
         reportError(NULL, JSMSG_ARGUMENTS_AND_REST);
         return NULL;
     }
 
     /*
      * Even if 'arguments' isn't explicitly mentioned, dynamic name lookup
      * forces an 'arguments' binding. The exception is that functions with rest
@@ -1173,17 +1142,17 @@ LeaveFunction(ParseNode *fn, Parser *par
                  * definitions in the ParseContext by generateFunctionBindings).
                  *
                  * If 'dn' has been assigned to, then we also flag the function
                  * scope has needing a dynamic scope so that dynamic scope
                  * setter can either ignore the set (in non-strict mode) or
                  * produce an error (in strict mode).
                  */
                 if (dn->isClosed() || dn->isAssigned())
-                    funbox->fun()->flags |= JSFUN_HEAVYWEIGHT;
+                    funbox->function()->flags |= JSFUN_HEAVYWEIGHT;
                 continue;
             }
 
             Definition *outer_dn = pc->decls().lookupFirst(atom);
 
             /*
              * Make sure to deoptimize lexical dependencies that are polluted
              * by eval and function statements (which both flag the function as
@@ -3601,17 +3570,17 @@ Parser::letStatement()
         if (stmt && (!stmt->maybeScope() || stmt->isForLetBlock)) {
             reportError(NULL, JSMSG_LET_DECL_NOT_IN_BLOCK);
             return NULL;
         }
 
         if (stmt && stmt->isBlockScope) {
             JS_ASSERT(pc->blockChain == stmt->blockObj);
         } else {
-            if (!stmt || stmt->isFunctionBodyBlock) {
+            if (pc->atBodyLevel()) {
                 /*
                  * ES4 specifies that let at top level and at body-block scope
                  * does not shadow var, so convert back to var.
                  */
                 pn = variables(PNK_VAR);
                 if (!pn)
                     return NULL;
                 pn->pn_xflags |= PNX_POPVAR;
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -26,20 +26,17 @@ namespace js {
 namespace frontend {
 
 struct StmtInfoPC : public StmtInfoBase {
     StmtInfoPC      *down;          /* info for enclosing statement */
     StmtInfoPC      *downScope;     /* next enclosing lexical scope */
 
     uint32_t        blockid;        /* for simplified dominance computation */
 
-    /* True if type == STMT_BLOCK and this block is a function body. */
-    bool            isFunctionBodyBlock;
-
-    StmtInfoPC(JSContext *cx) : StmtInfoBase(cx), isFunctionBodyBlock(false) {}
+    StmtInfoPC(JSContext *cx) : StmtInfoBase(cx) {}
 };
 
 typedef HashSet<JSAtom *> FuncStmtSet;
 struct Parser;
 class SharedContext;
 
 typedef Vector<Definition *, 16> DeclVector;
 
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -185,34 +185,33 @@ class GlobalSharedContext : public Share
     const RootedObject scopeChain_; /* scope chain object for the script */
 
   public:
     inline GlobalSharedContext(JSContext *cx, JSObject *scopeChain, StrictMode sms);
 
     JSObject *scopeChain() const { return scopeChain_; }
 };
 
-class FunctionBox : public SharedContext
+class FunctionBox : public ObjectBox, public SharedContext
 {
   public:
-    ObjectBox       objbox;
     Bindings        bindings;               /* bindings for this function */
     size_t          bufStart;
     size_t          bufEnd;
     uint16_t        ndefaults;
     bool            inWith:1;               /* some enclosing scope is a with-statement
                                                or E4X filter-expression */
     bool            inGenexpLambda:1;       /* lambda from generator expression */
 
     FunctionContextFlags funCxFlags;
 
     FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fun, ParseContext *pc,
                 StrictMode sms);
 
-    JSFunction *fun() const { return objbox.object->toFunction(); }
+    JSFunction *function() const { return object->toFunction(); }
 
     bool isGenerator()              const { return funCxFlags.isGenerator; }
     bool mightAliasLocals()         const { return funCxFlags.mightAliasLocals; }
     bool hasExtensibleScope()       const { return funCxFlags.hasExtensibleScope; }
     bool argumentsHasLocalBinding() const { return funCxFlags.argumentsHasLocalBinding; }
     bool definitelyNeedsArgsObj()   const { return funCxFlags.definitelyNeedsArgsObj; }
 
     void setIsGenerator()                  { funCxFlags.isGenerator              = true; }
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -3985,17 +3985,17 @@ CodeGenerator::visitGetDOMProperty(LGetD
     const Register PrivateReg = ToRegister(ins->getPrivReg());
     const Register ValueReg = ToRegister(ins->getValueReg());
 
     DebugOnly<uint32> initialStack = masm.framePushed();
 
     masm.checkStackAlignment();
 
     /* Make Space for the outparam */
-    masm.adjustStack((int)-sizeof(Value));
+    masm.adjustStack(-int32_t(sizeof(Value)));
     masm.movePtr(StackPointer, ValueReg);
 
     masm.Push(ObjectReg);
 
     // GetReservedSlot(obj, DOM_PROTO_INSTANCE_CLASS_SLOT).toPrivate()
     masm.loadPrivate(Address(ObjectReg, JSObject::getFixedSlotOffset(0)), PrivateReg);
 
     // Rooting will happen at GC time.
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -740,17 +740,17 @@ IonBuilder::snoopControlFlow(JSOp op)
     return ControlStatus_None;
 }
 
 void
 IonBuilder::markPhiBytecodeUses(jsbytecode *pc)
 {
     unsigned nuses = analyze::GetUseCount(script_, pc - script_->code);
     for (unsigned i = 0; i < nuses; i++) {
-        MDefinition *def = current->peek(-(i + 1));
+        MDefinition *def = current->peek(-int32_t(i + 1));
         if (def->isPassArg())
             def = def->toPassArg()->getArgument();
         if (def->isPhi())
             def->toPhi()->setHasBytecodeUses();
     }
 }
 
 bool
--- a/js/src/ion/IonCaches.cpp
+++ b/js/src/ion/IonCaches.cpp
@@ -1020,17 +1020,17 @@ js::ion::BindNameCache(JSContext *cx, si
     IonScript *ion = GetTopIonJSScript(cx)->ionScript();
     IonCacheBindName &cache = ion->getCache(cacheIndex).toBindName();
     HandlePropertyName name = cache.name();
 
     RootedObject holder(cx);
     if (scopeChain->isGlobal()) {
         holder = scopeChain;
     } else {
-        if (!LookupNameForSet(cx, name, scopeChain, &holder))
+        if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &holder))
             return NULL;
     }
 
     // Stop generating new stubs once we hit the stub count limit, see
     // GetPropertyCache.
     if (cache.stubCount() < MAX_STUBS) {
         cache.incrementStubCount();
 
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -50,17 +50,17 @@ LIRGenerator::visitParameter(MParameter 
 
 bool
 LIRGenerator::visitCallee(MCallee *callee)
 {
     LCallee *ins = new LCallee;
     if (!define(ins, callee, LDefinition::PRESET))
         return false;
 
-    ins->getDef(0)->setOutput(LArgument(-sizeof(IonJSFrameLayout)
+    ins->getDef(0)->setOutput(LArgument(-int32_t(sizeof(IonJSFrameLayout))
                                         + IonJSFrameLayout::offsetOfCalleeToken()));
 
     return true;
 }
 
 bool
 LIRGenerator::visitGoto(MGoto *ins)
 {
--- a/js/src/ion/Snapshots.cpp
+++ b/js/src/ion/Snapshots.cpp
@@ -13,16 +13,18 @@
 #include "SnapshotReader.h"
 #include "SnapshotWriter.h"
 
 #ifdef TRACK_SNAPSHOTS
 #include "MIR.h"
 #include "LIR.h"
 #endif
 
+#include "jsscriptinlines.h"
+
 using namespace js;
 using namespace js::ion;
 
 // Snapshot header:
 //
 //   [vwu] bits (n-31]: frame count
 //         bits [0,n):  bailout kind (n = BAILOUT_KIND_BITS)
 //
--- a/js/src/ion/shared/IonFrames-x86-shared.h
+++ b/js/src/ion/shared/IonFrames-x86-shared.h
@@ -236,16 +236,17 @@ class IonNativeExitFrameLayout
     }
     inline uintptr_t argc() const {
         return argc_;
     }
 };
 
 class IonOOLNativeGetterExitFrameLayout
 {
+  protected: // only to silence a clang warning about unused private fields
     IonExitFooterFrame footer_;
     IonExitFrameLayout exit_;
 
     // We need to split the Value into 2 fields of 32 bits, otherwise the C++
     // compiler may add some padding between the fields.
     uint32_t loCalleeResult_;
     uint32_t hiCalleeResult_;
 
@@ -267,16 +268,17 @@ class IonOOLNativeGetterExitFrameLayout
     }
     inline uintptr_t argc() const {
         return 0;
     }
 };
 
 class IonOOLPropertyOpExitFrameLayout
 {
+  protected: // only to silence a clang warning about unused private fields
     IonExitFooterFrame footer_;
     IonExitFrameLayout exit_;
 
     // Object for JSHandleObject
     JSObject *obj_;
 
     // id for JSHandleId
     jsid id_;
--- a/js/src/ion/x86/Assembler-x86.h
+++ b/js/src/ion/x86/Assembler-x86.h
@@ -8,16 +8,18 @@
 #ifndef jsion_cpu_x86_assembler_h__
 #define jsion_cpu_x86_assembler_h__
 
 #include "ion/shared/Assembler-shared.h"
 #include "assembler/assembler/X86Assembler.h"
 #include "ion/CompactBuffer.h"
 #include "ion/IonCode.h"
 
+#include "jsscriptinlines.h"
+
 namespace js {
 namespace ion {
 
 static const Register eax = { JSC::X86Registers::eax };
 static const Register ecx = { JSC::X86Registers::ecx };
 static const Register edx = { JSC::X86Registers::edx };
 static const Register ebx = { JSC::X86Registers::ebx };
 static const Register esp = { JSC::X86Registers::esp };
--- a/js/src/ion/x86/MacroAssembler-x86.cpp
+++ b/js/src/ion/x86/MacroAssembler-x86.cpp
@@ -4,16 +4,18 @@
  * 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/. */
 
 #include "MacroAssembler-x86.h"
 #include "ion/MoveEmitter.h"
 #include "ion/IonFrames.h"
 
+#include "jsscriptinlines.h"
+
 using namespace js;
 using namespace js::ion;
 
 void
 MacroAssemblerX86::setupABICall(uint32 args)
 {
     JS_ASSERT(!inCall_);
     inCall_ = true;
--- a/js/src/ion/x86/Trampoline-x86.cpp
+++ b/js/src/ion/x86/Trampoline-x86.cpp
@@ -9,16 +9,18 @@
 #include "assembler/assembler/MacroAssembler.h"
 #include "ion/IonCompartment.h"
 #include "ion/IonLinker.h"
 #include "ion/IonFrames.h"
 #include "ion/IonSpewer.h"
 #include "ion/Bailouts.h"
 #include "ion/VMFunctions.h"
 
+#include "jsscriptinlines.h"
+
 using namespace js;
 using namespace js::ion;
 
 enum EnterJitEbpArgumentOffset {
     ARG_JITCODE     = 2 * sizeof(void *),
     ARG_ARGC        = 3 * sizeof(void *),
     ARG_ARGV        = 4 * sizeof(void *),
     ARG_STACKFRAME  = 5 * sizeof(void *),
@@ -287,17 +289,17 @@ IonCompartment::generateArgumentsRectifi
 
     // Remove the rectifier frame.
     masm.pop(ebx);            // ebx <- descriptor with FrameType.
     masm.shrl(Imm32(FRAMESIZE_SHIFT), ebx); // ebx <- descriptor.
     masm.pop(edi);            // Discard calleeToken.
     masm.pop(edi);            // Discard number of actual arguments.
 
     // Discard pushed arguments, but not the pushed frame pointer.
-    BaseIndex unwind = BaseIndex(esp, ebx, TimesOne, -sizeof(void*));
+    BaseIndex unwind = BaseIndex(esp, ebx, TimesOne, -int32_t(sizeof(void*)));
     masm.lea(Operand(unwind), esp);
 
     masm.pop(FramePointer);
     masm.ret();
 
     Linker linker(masm);
     return linker.newCode(cx);
 }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testImplicitThisMiss.js
@@ -0,0 +1,2 @@
+// |jit-test| error:TypeError
+Function("Object.defineProperty(this, 'x', { configurable:true, get:function() { delete this['x'] } }); x()")();
--- a/js/src/jit-test/tests/parallelarray/comprehension-throws.js
+++ b/js/src/jit-test/tests/parallelarray/comprehension-throws.js
@@ -1,13 +1,25 @@
 load(libdir + "asserts.js");
 
 function buildComprehension() {
   // Throws if elemental fun not callable
   assertThrowsInstanceOf(function () {
     var p = new ParallelArray([2,2], undefined);
   }, TypeError);
   assertThrowsInstanceOf(function () {
+    var p = new ParallelArray(2, /x/);
+  }, TypeError);
+  assertThrowsInstanceOf(function () {
     var p = new ParallelArray(/x/, /x/);
   }, TypeError);
+  assertThrowsInstanceOf(function () {
+    new ParallelArray([0xffffffff + 1], function() { return 0; });
+  }, RangeError);
+  assertThrowsInstanceOf(function () {
+    new ParallelArray(0xffffffff + 1, function() { return 0; });
+  }, RangeError);
+  assertThrowsInstanceOf(function () {
+    new ParallelArray([0xfffff, 0xffff], function() { return 0; });
+  }, RangeError);
 }
 
 buildComprehension();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parallelarray/constructor-throws.js
@@ -0,0 +1,9 @@
+load(libdir + "asserts.js");
+
+function testThrows() {
+  assertThrowsInstanceOf(function () {
+    new ParallelArray({ length: 0xffffffff + 1 });
+  }, RangeError);
+}
+
+testThrows();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parallelarray/filter-throws.js
@@ -0,0 +1,11 @@
+load(libdir + "asserts.js");
+
+function testFilterThrows() {
+  var p = new ParallelArray([1,2,3,4,5]);
+
+  assertThrowsInstanceOf(function () {
+    p.filter({ length: 0xffffffff + 1 });
+  }, RangeError);
+}
+
+testFilterThrows();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parallelarray/overflow-throws.js
@@ -0,0 +1,12 @@
+load(libdir + "asserts.js");
+
+function testOverflow() {
+  assertThrowsInstanceOf(function () {
+    new ParallelArray([0xffffffff + 1], function() { return 0; });
+  }, RangeError);
+  assertThrowsInstanceOf(function () {
+    new ParallelArray({ length: 0xffffffff + 1 });
+  }, RangeError);
+}
+
+testOverflow();
--- a/js/src/jit-test/tests/parallelarray/scatter-throws.js
+++ b/js/src/jit-test/tests/parallelarray/scatter-throws.js
@@ -1,16 +1,30 @@
 load(libdir + "asserts.js");
 
 function testScatterThrows() {
+  var p = new ParallelArray([1,2,3,4,5]);
+
   // Throw on conflict with no resolution function
   assertThrowsInstanceOf(function () {
-    var p = new ParallelArray([1,2,3,4,5]);
     var r = p.scatter([0,1,0,3,4]);
   }, Error);
   // Throw on out of bounds
   assertThrowsInstanceOf(function () {
-    var p = new ParallelArray([1,2,3,4,5]);
     var r = p.scatter([0,1,0,3,11]);
   }, Error);
+
+  assertThrowsInstanceOf(function () {
+    p.scatter([-1,1,0,3,4], 9, function (a,b) { return a+b; }, 10);
+  }, TypeError);
+  assertThrowsInstanceOf(function () {
+    p.scatter([0,1,0,3,4], 9, function (a,b) { return a+b; }, -1);
+  }, RangeError);
+  assertThrowsInstanceOf(function () {
+    p.scatter([0,1,0,3,4], 9, function (a,b) { return a+b; }, 0xffffffff + 1);
+  }, RangeError);
+  assertThrowsInstanceOf(function () {
+    p.scatter({ length: 0xffffffff + 1 }, 9, function (a,b) { return a+b; }, 10);
+  }, RangeError);
+
 }
 
 testScatterThrows();
--- a/js/src/jit-test/tests/parallelarray/toString-1.js
+++ b/js/src/jit-test/tests/parallelarray/toString-1.js
@@ -1,6 +1,6 @@
 function testToString() {
   var p = new ParallelArray();
-  assertEq(p.toString(), "<>");
+  assertEq(p.toString(), "");
 }
 
 testToString();
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1881,18 +1881,19 @@ END_CASE(JSOP_BINDGNAME)
 BEGIN_CASE(JSOP_BINDNAME)
 {
     RootedObject &scopeChain = rootObject0;
     scopeChain = regs.fp()->scopeChain();
 
     RootedPropertyName &name = rootName0;
     name = script->getName(regs.pc);
 
+    /* Assigning to an undeclared name adds a property to the global object. */
     RootedObject &scope = rootObject1;
-    if (!LookupNameForSet(cx, name, scopeChain, &scope))
+    if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &scope))
         goto error;
 
     PUSH_OBJECT(*scope);
 }
 END_CASE(JSOP_BINDNAME)
 
 #define BITWISE_OP(OP)                                                        \
     JS_BEGIN_MACRO                                                            \
@@ -2550,19 +2551,17 @@ BEGIN_CASE(JSOP_IMPLICITTHIS)
 {
     RootedPropertyName &name = rootName0;
     name = script->getName(regs.pc);
 
     RootedObject &scopeObj = rootObject0;
     scopeObj = cx->stack.currentScriptedScopeChain();
 
     RootedObject &scope = rootObject1;
-    RootedObject &pobj = rootObject2;
-    RootedShape &prop = rootShape0;
-    if (!LookupName(cx, name, scopeObj, &scope, &pobj, &prop))
+    if (!LookupNameWithGlobalDefault(cx, name, scopeObj, &scope))
         goto error;
 
     Value v;
     if (!ComputeImplicitThis(cx, scope, &v))
         goto error;
     PUSH_COPY(v);
 }
 END_CASE(JSOP_IMPLICITTHIS)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4171,18 +4171,18 @@ js::LookupName(JSContext *cx, HandleProp
 
     objp.set(NULL);
     pobjp.set(NULL);
     propp.set(NULL);
     return true;
 }
 
 bool
-js::LookupNameForSet(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
-                     MutableHandleObject objp)
+js::LookupNameWithGlobalDefault(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
+                                MutableHandleObject objp)
 {
     RootedId id(cx, NameToId(name));
 
     RootedObject pobj(cx);
     RootedShape prop(cx);
 
     RootedObject scope(cx, scopeChain);
     for (; !scope->isGlobal(); scope = scope->enclosingScope()) {
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1259,25 +1259,24 @@ static const unsigned RESOLVE_INFER = 0x
 
 /* Read the name using a dynamic lookup on the scopeChain. */
 extern bool
 LookupName(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
            MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp);
 
 /*
  * Like LookupName except returns the global object if 'name' is not found in
- * any preceding non-global scope. This is because assigning to an undeclared
- * name will add a property to the global object.
+ * any preceding non-global scope.
  *
  * Additionally, pobjp and propp are not needed by callers so they are not
  * returned.
  */
 extern bool
-LookupNameForSet(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
-                 MutableHandleObject objp);
+LookupNameWithGlobalDefault(JSContext *cx, HandlePropertyName name, HandleObject scopeChain,
+                            MutableHandleObject objp);
 
 }
 
 extern JSObject *
 js_FindVariableScope(JSContext *cx, JSFunction **funp);
 
 /* JSGET_CACHE_RESULT is the analogue of DNP_CACHE_RESULT for GetMethod. */
 const unsigned JSGET_CACHE_RESULT = 1; // from a caching interpreter opcode
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -5635,30 +5635,19 @@ js_DecompileFunction(JSPrinter *jp)
         jsbytecode *defbegin = NULL;
         int32_t deflen = 0;
         uint16_t defstart = 0;
         unsigned nformal = fun->nargs - fun->hasRest();
 
         if (fun->hasDefaults()) {
             // Since bug 781422, this code is completely wrong. If you ever have
             // the unenviable task of reenabling the decompiler, you'll have to
-            // completely rewrite defaults decompiling.
+            // completely rewrite defaults decompiling.  The previous code for
+            // this is available in version control, if you need inspiration.
             MOZ_CRASH();
-
-            jsbytecode *defpc;
-            LOCAL_ASSERT_RV(defpc < endpc, JS_FALSE);
-            defpc += GetBytecodeLength(defpc);
-            LOCAL_ASSERT_RV(*defpc == JSOP_TABLESWITCH, JS_FALSE);
-            defbegin = defpc;
-            deflen = GET_JUMP_OFFSET(defpc);
-            defpc += JUMP_OFFSET_LEN;
-            defstart = GET_JUMP_OFFSET(defpc);
-            defpc += JUMP_OFFSET_LEN;
-            defpc += JUMP_OFFSET_LEN; // Skip high
-            deftable = defpc;
         }
 
         for (unsigned i = 0; i < fun->nargs; i++) {
             if (i > 0)
                 js_puts(jp, ", ");
 
             bool isRest = fun->hasRest() && i == unsigned(fun->nargs) - 1;
             if (isRest)
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -172,17 +172,17 @@ typedef JSPropertyOp         PropertyOp;
 typedef JSStrictPropertyOp   StrictPropertyOp;
 typedef JSPropertyDescriptor PropertyDescriptor;
 
 namespace frontend {
 
 struct BytecodeEmitter;
 struct Definition;
 class FunctionBox;
-struct ObjectBox;
+class ObjectBox;
 struct Token;
 struct TokenPos;
 struct TokenPtr;
 class TokenStream;
 struct Parser;
 class ParseMapPool;
 struct ParseNode;
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -140,19 +140,21 @@ class NodeBuilder
     RootedValue srcval;                /* source filename JS value or null      */
     Value       callbacks[AST_LIMIT];  /* user-specified callbacks              */
     AutoValueArray callbacksRoots;     /* for rooting |callbacks|               */
     RootedValue userv;                 /* user-specified builder object or null */
     RootedValue undefinedVal;          /* a rooted undefined val, used by opt() */
 
   public:
     NodeBuilder(JSContext *c, bool l, char const *s)
-        : cx(c), saveLoc(l), src(s), srcval(c), callbacks(),
+        : cx(c), saveLoc(l), src(s), srcval(c),
           callbacksRoots(c, callbacks, AST_LIMIT), userv(c), undefinedVal(c, UndefinedValue())
-    { }
+    {
+        MakeRangeGCSafe(callbacks, mozilla::ArrayLength(callbacks));
+    }
 
     bool init(HandleObject userobj = NullPtr()) {
         if (src) {
             if (!atomValue(src, &srcval))
                 return false;
         } else {
             srcval.setNull();
         }
@@ -3208,17 +3210,17 @@ ASTSerializer::identifier(ParseNode *pn,
 
     RootedAtom pnAtom(cx, pn->pn_atom);
     return identifier(pnAtom, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::function(ParseNode *pn, ASTType type, MutableHandleValue dst)
 {
-    RootedFunction func(cx, pn->pn_funbox->fun());
+    RootedFunction func(cx, pn->pn_funbox->function());
 
     bool isGenerator =
 #if JS_HAS_GENERATORS
         pn->pn_funbox->isGenerator();
 #else
         false;
 #endif
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1704,17 +1704,17 @@ JSScript::fullyInitFromEmitter(JSContext
         script->ndefaults = funbox->ndefaults;
     }
 
     RootedFunction fun(cx, NULL);
     if (funbox) {
         JS_ASSERT(!bce->script->noScriptRval);
         script->isGenerator = funbox->isGenerator();
         script->isGeneratorExp = funbox->inGenexpLambda;
-        script->setFunction(funbox->fun());
+        script->setFunction(funbox->function());
     }
 
     /*
      * initScriptCounts updates scriptCountsMap if necessary. The other script
      * maps in JSCompartment are populated lazily.
      */
     if (cx->hasRunOption(JSOPTION_PCCOUNT))
         (void) script->initScriptCounts(cx);
--- a/js/src/jsworkers.h
+++ b/js/src/jsworkers.h
@@ -23,18 +23,19 @@ namespace ion {
 }
 
 #if defined(JS_THREADSAFE) && defined(JS_ION)
 # define JS_PARALLEL_COMPILATION
 
 struct WorkerThread;
 
 /* Per-runtime state for off thread work items. */
-struct WorkerThreadState
+class WorkerThreadState
 {
+  public:
     /* Available threads. */
     WorkerThread *threads;
     size_t numThreads;
 
     enum CondVar {
         MAIN,
         WORKER
     };
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -683,20 +683,20 @@ class CallCompiler : public BaseCompiler
         size_t spOffset = sizeof(StackFrame) +
                           ic.frameSize.staticLocalSlots() * sizeof(Value);
         masm.addPtr(Imm32(spOffset), JSFrameReg, t0);
 
         /* Copy all remaining arguments. */
         for (size_t i = 0; i < argc + 1; i++) {
             /* Copy the argument onto the native stack. */
 #ifdef JS_NUNBOX32
-            masm.push(Address(t0, -((i + 1) * sizeof(Value)) + 4));
-            masm.push(Address(t0, -((i + 1) * sizeof(Value))));
+            masm.push(Address(t0, -int32_t((i + 1) * sizeof(Value)) + 4));
+            masm.push(Address(t0, -int32_t((i + 1) * sizeof(Value))));
 #elif defined JS_PUNBOX64
-            masm.push(Address(t0, -((i + 1) * sizeof(Value))));
+            masm.push(Address(t0, -int32_t((i + 1) * sizeof(Value))));
 #endif
         }
 
         /* Push argc and calleeToken. */
         masm.push(Imm32(argc));
         masm.push(funObjReg);
 
         /* Make and push a frame descriptor. */
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -1938,17 +1938,17 @@ class BindNameCompiler : public PICStubC
         return Lookup_Cacheable;
     }
 
     JSObject *update()
     {
         RecompilationMonitor monitor(cx);
 
         RootedObject scope(cx);
-        if (!LookupNameForSet(cx, name, scopeChain, &scope))
+        if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &scope))
             return NULL;
 
         if (monitor.recompiled())
             return scope;
 
         if (!pic.hit) {
             spew("first hit", "nop");
             pic.hit = true;
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -55,17 +55,17 @@ using namespace js::mjit;
 using namespace js::types;
 using namespace JSC;
 
 void JS_FASTCALL
 stubs::BindName(VMFrame &f, PropertyName *name_)
 {
     RootedPropertyName name(f.cx, name_);
     RootedObject scope(f.cx);
-    if (!LookupNameForSet(f.cx, name, f.fp()->scopeChain(), &scope))
+    if (!LookupNameWithGlobalDefault(f.cx, name, f.fp()->scopeChain(), &scope))
         THROW();
     f.regs.sp[0].setObject(*scope);
 }
 
 JSObject * JS_FASTCALL
 stubs::BindGlobalName(VMFrame &f)
 {
     return &f.fp()->global();
@@ -182,19 +182,18 @@ stubs::ToId(VMFrame &f)
 }
 
 void JS_FASTCALL
 stubs::ImplicitThis(VMFrame &f, PropertyName *name_)
 {
     RootedObject scopeObj(f.cx, f.cx->stack.currentScriptedScopeChain());
     RootedPropertyName name(f.cx, name_);
 
-    RootedObject obj(f.cx), obj2(f.cx);
-    RootedShape prop(f.cx);
-    if (!LookupName(f.cx, name, scopeObj, &obj, &obj2, &prop))
+    RootedObject obj(f.cx);
+    if (!LookupNameWithGlobalDefault(f.cx, name, scopeObj, &obj))
         THROW();
 
     if (!ComputeImplicitThis(f.cx, obj, &f.regs.sp[0]))
         THROW();
 }
 
 void JS_FASTCALL
 stubs::BitOr(VMFrame &f)
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -644,21 +644,26 @@ nsObjectFrame::FixupWindow(const nsSize&
     return;
   }
 #endif
 
   bool windowless = (window->type == NPWindowTypeDrawable);
 
   nsIntPoint origin = GetWindowOriginInPixels(windowless);
 
-  window->x = origin.x;
-  window->y = origin.y;
-
-  window->width = presContext->AppUnitsToDevPixels(aSize.width);
-  window->height = presContext->AppUnitsToDevPixels(aSize.height);
+  // window must be in "display pixels"
+  double scaleFactor = 1.0;
+  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
+    scaleFactor = 1.0;
+  }
+  int intScaleFactor = ceil(scaleFactor);
+  window->x = origin.x / intScaleFactor;
+  window->y = origin.y / intScaleFactor;
+  window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
+  window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
 
   // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
   // us from drawing on screen until the widget is properly positioned, which will not
   // happen until we have finished the reflow process.
 #ifdef XP_MACOSX
   window->clipRect.top = 0;
   window->clipRect.left = 0;
   window->clipRect.bottom = 0;
@@ -704,20 +709,27 @@ nsObjectFrame::CallSetWindow(bool aCheck
   nsPresContext* presContext = PresContext();
   nsRootPresContext* rootPC = presContext->GetRootPresContext();
   if (!rootPC)
     return NS_ERROR_FAILURE;
   int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
   nsIFrame* rootFrame = rootPC->PresShell()->FrameManager()->GetRootFrame();
   nsRect bounds = GetContentRectRelativeToSelf() + GetOffsetToCrossDoc(rootFrame);
   nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
-  window->x = intBounds.x;
-  window->y = intBounds.y;
-  window->width = intBounds.width;
-  window->height = intBounds.height;
+
+  // window must be in "display pixels"
+  double scaleFactor = 1.0;
+  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
+    scaleFactor = 1.0;
+  }
+  size_t intScaleFactor = ceil(scaleFactor);
+  window->x = intBounds.x / intScaleFactor;
+  window->y = intBounds.y / intScaleFactor;
+  window->width = intBounds.width / intScaleFactor;
+  window->height = intBounds.height / intScaleFactor;
 
   // Calling SetWindow might destroy this frame. We need to use the instance
   // owner to clean up so hold a ref.
   nsRefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner);
 
   // This will call pi->SetWindow and take care of window subclassing
   // if needed, see bug 132759. Calling SetWindow can destroy this frame
   // so check for that before doing anything else with this frame's memory.
@@ -1626,17 +1638,23 @@ nsObjectFrame::BuildLayer(nsDisplayListB
   // Create image
   nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
 
   if (!container) {
     // This can occur if our instance is gone.
     return nullptr;
   }
 
-  gfxIntSize size(window->width, window->height);
+  // window is in "display pixels", but size needs to be in device pixels
+  double scaleFactor = 1.0;
+  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
+    scaleFactor = 1.0;
+  }
+  int intScaleFactor = ceil(scaleFactor);
+  gfxIntSize size(window->width * intScaleFactor, window->height * intScaleFactor);
 
   nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
   gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
   // to provide crisper and faster drawing.
   r.Round();
   nsRefPtr<Layer> layer =
     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
 
--- a/layout/generic/test/plugin_focus_helper.html
+++ b/layout/generic/test/plugin_focus_helper.html
@@ -28,18 +28,18 @@ var nativeMouseUp;
 SimpleTest.waitForExplicitFinish();
 
 function activatePlugin(id) {
   return function() {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
     var element = document.getElementById(id);
     var bounds = element.getBoundingClientRect();
-    var x = (bounds.left + window.mozInnerScreenX + 10)*gWindowUtils.screenPixelsPerCSSPixel;
-    var y = (bounds.top + window.mozInnerScreenY + 10)*gWindowUtils.screenPixelsPerCSSPixel;
+    var x = (bounds.left + window.mozInnerScreenX + 10);
+    var y = (bounds.top + window.mozInnerScreenY + 10);
 
     gWindowUtils.sendNativeMouseEvent(x, y, nativeMouseDown, 0, element);
     gWindowUtils.sendNativeMouseEvent(x, y, nativeMouseUp, 0, element);
   };
 }
 
 function done() {
   SimpleTest.finish();
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -2128,19 +2128,21 @@ nsPrintEngine::SetRootView(
   } else {
     nscoord pageWidth, pageHeight;
     mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight);
     adjSize = nsSize(pageWidth, pageHeight);
     documentIsTopLevel = true;
     parentView = GetParentViewForRoot();
   }
 
-  if (aPO->mPresShell->GetViewManager()->GetRootView()) {
+  if (aPO->mViewManager->GetRootView()) {
     // Reuse the root view that is already on the root frame.
-    rootView = aPO->mPresShell->GetRootFrame()->GetView();
+    rootView = aPO->mViewManager->GetRootView();
+    // Remove it from its existing parent if necessary
+    aPO->mViewManager->RemoveChild(rootView);
     reinterpret_cast<nsView*>(rootView)->SetParent(reinterpret_cast<nsView*>(parentView));
   } else {
     // Create a child window of the parent that is our "root view/window"
     nsRect tbounds = nsRect(nsPoint(0, 0), adjSize);
     rootView = aPO->mViewManager->CreateView(tbounds, parentView);
     NS_ENSURE_TRUE(rootView, NS_ERROR_OUT_OF_MEMORY);
   }
     
--- a/layout/style/StyleRule.h
+++ b/layout/style/StyleRule.h
@@ -178,17 +178,19 @@ private:
   int32_t CalcWeightWithoutNegations() const;
 
 public:
   // Get and set the selector's pseudo type
   nsCSSPseudoElements::Type PseudoType() const {
     return static_cast<nsCSSPseudoElements::Type>(mPseudoType);
   }
   void SetPseudoType(nsCSSPseudoElements::Type aType) {
-    NS_ASSERTION(aType > INT16_MIN && aType < INT16_MAX, "Out of bounds");
+    NS_ASSERTION(static_cast<int32_t>(aType) >= INT16_MIN &&
+                 static_cast<int32_t>(aType) <= INT16_MAX,
+                 "Out of bounds - this will overflow mPseudoType");
     mPseudoType = static_cast<int16_t>(aType);
   }
 
   size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   // For case-sensitive documents, mLowercaseTag is the same as mCasedTag,
   // but in case-insensitive documents (HTML) mLowercaseTag is lowercase.
   // Also, for pseudo-elements mCasedTag will be null but mLowercaseTag
--- a/media/libpng/CHANGES
+++ b/media/libpng/CHANGES
@@ -3847,17 +3847,17 @@ Version 1.5.10beta05 [March 10, 2012]
   Fixed an off-by-one error in the palette index checking function.
   Revised example.c to put text strings in a temporary character array
     instead of directly assigning string constants to png_textp members.
     This avoids compiler warnings when -Wwrite-strings is enabled.
 
 Version 1.5.10 [March 29, 2012]
   Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice.
   Revised png_set_text_2() to avoid potential memory corruption (fixes
-    CVE-2011-3048).
+    CVE-2011-3048, also known as CVE-2012-3425).
 
 Version 1.5.11beta01 [April 28, 2012]
   Revised scripts/makefile.darwin: use system zlib; remove quotes around
     architecture list; add missing ppc architecture; add architecture options
     to shared library link; don't try to create a shared lib based on missing
     RELEASE variable.
   Enable png_set_check_for_invalid_index() for both read and write.
   Removed #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED/#endif in pngpriv.h around
@@ -3886,16 +3886,44 @@ Version 1.5.11rc04 [June 6, 2012]
   Improved performance of new do_check_palette_indexes() function.
 
 Version 1.5.11rc05 [June 7, 2012]
   Don't check palette indexes if num_palette is 0 (as it can be in MNG files).
 
 Version 1.5.11 [June 14, 2012]
   Include zlib.h in contrib/gregbook and contrib/visupng examples.
 
+Version 1.5.12 [July 11, 2012]
+  Removed scripts/makefile.cegcc from the *.zip and *.7z distributions; it
+    depends on configure, which is not included in those archives.
+  Changed "a+w" to "u+w" in Makefile.in to fix CVE-2012-3386.
+
+Version 1.5.13beta01 [August 8, 2012]
+  Do not compile PNG_DEPRECATED, PNG_ALLOC and PNG_PRIVATE when __GNUC__ < 3.
+  Removed references to png_zalloc() and png_zfree() from the manual.
+  Revised PNG_FP_EXPORT and PNG_FIXED_EXPORT macros to avoid generating
+    lone semicolons (patch ported from libpng-1.6.0beta11).
+
+Version 1.5.13beta02 [September 10, 2012]
+  Corrected handling of the image array and the row_pointers array in example.c
+  When png_set_filler is used to strip a filler channel during write, the
+    code prior to 1.5 would ignore the case where the output required an
+    alpha channel or when the output was a palettized PNG.  In libpng-1.5 the
+    ignorance was lost and libpng proceeded to strip the channel resulting
+    in a bad (potential memory overwrite) failure later.  This reverts
+    the behavior to the pre-1.5 state but issues a warning. libpng-1.6 is
+    expected to issue an error on the erroneous png_set_filler call.
+  Use png_memset() consistently (pngmem.c contained some bare "memset" calls).
+
+Version 1.5.13rc01 [September 17, 2012]
+  No changes.
+
+Version 1.5.13 [September 27, 2012]
+  No changes.
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
 to subscribe)
 or to glennrp at users.sourceforge.net
 
 Glenn R-P
 #endif
--- a/media/libpng/LICENSE
+++ b/media/libpng/LICENSE
@@ -5,17 +5,17 @@ included in the libpng distribution, the
 
 COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
 
 If you modify libpng you may insert additional notices immediately following
 this sentence.
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.5.11, June 14, 2012, are
+libpng versions 1.2.6, August 15, 2004, through 1.5.13, September 27, 2012, are
 Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
 
    Cosmin Truta
 
 libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are
 Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
@@ -103,9 +103,9 @@ boxes and the like:
 Also, the PNG logo (in PNG format, of course) is supplied in the
 files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
 
 Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is a
 certification mark of the Open Source Initiative.
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-June 14, 2012
+September 27, 2012
--- a/media/libpng/README
+++ b/media/libpng/README
@@ -1,9 +1,9 @@
-README for libpng version 1.5.11 - June 14, 2012 (shared library 15.0)
+README for libpng version 1.5.13 - September 27, 2012 (shared library 15.0)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
 
 Libpng comes in several distribution formats.  Get libpng-*.tar.gz,
 libpng-*.tar.xz or libpng-*.tar.bz2 if you want UNIX-style line endings
 in the text files, or lpng*.zip if you want DOS-style line endings.
 
--- a/media/libpng/apng.patch
+++ b/media/libpng/apng.patch
@@ -1,19 +1,19 @@
 diff -up8 png.h png.h
---- png.h	2012-06-14 07:28:00 -0400
-+++ png.h	2012-07-07 10:21:31 -0400
-@@ -423,24 +423,18 @@
+--- png.h	2012-09-27 07:21:20 -0400
++++ png.h	2012-09-29 11:47:33 -0400
+@@ -427,24 +427,18 @@
  /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
   * We must not include leading zeros.
   * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
   * version 1.0.0 was mis-numbered 100 instead of 10000).  From
   * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
   */
- #define PNG_LIBPNG_VER 10511 /* 1.5.11 */
+ #define PNG_LIBPNG_VER 10513 /* 1.5.13 */
  
 -/* Library configuration: these options cannot be changed after
 - * the library has been built.
 - */
 -#ifndef PNGLCONF_H
 -    /* If pnglibconf.h is missing, you can
 -     * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h
 -     */
@@ -23,17 +23,17 @@ diff -up8 png.h png.h
  #endif
  
  #ifndef PNG_VERSION_INFO_ONLY
  #  ifndef PNG_BUILDING_SYMBOL_TABLE
    /*
     *   Standard header files (not needed for the version info or while
     *   building symbol table -- see scripts/pnglibconf.dfa)
     */
-@@ -540,16 +534,27 @@ extern "C" {
+@@ -544,16 +538,27 @@ extern "C" {
   * Otherwise the calls are mapped to png_error.
   */
  
  /* Section 2: type definitions, including structures and compile time
   * constants.
   * See pngconf.h for base types that vary by machine/system
   */
  
@@ -46,22 +46,22 @@ diff -up8 png.h png.h
 +/* blend_op flags from inside fcTL */
 +#define PNG_BLEND_OP_SOURCE        0x00
 +#define PNG_BLEND_OP_OVER          0x01
 +#endif /* PNG_APNG_SUPPORTED */
 +
  /* This triggers a compiler error in png.c, if png.c and png.h
   * do not agree upon the version number.
   */
- typedef char* png_libpng_version_1_5_11;
+ typedef char* png_libpng_version_1_5_13;
  
  /* Three color definitions.  The order of the red, green, and blue, (and the
   * exact size) is not important, although the size of the fields need to
   * be png_byte or png_uint_16 (as defined below).
-@@ -823,16 +828,20 @@ typedef png_info FAR * FAR * png_infopp;
+@@ -827,16 +832,20 @@ typedef png_info FAR * FAR * png_infopp;
  #define PNG_INFO_oFFs 0x0100
  #define PNG_INFO_tIME 0x0200
  #define PNG_INFO_pCAL 0x0400
  #define PNG_INFO_sRGB 0x0800   /* GR-P, 0.96a */
  #define PNG_INFO_iCCP 0x1000   /* ESR, 1.0.6 */
  #define PNG_INFO_sPLT 0x2000   /* ESR, 1.0.6 */
  #define PNG_INFO_sCAL 0x4000   /* ESR, 1.0.6 */
  #define PNG_INFO_IDAT 0x8000   /* ESR, 1.0.6 */
@@ -72,17 +72,17 @@ diff -up8 png.h png.h
  
  /* This is used for the transformation routines, as some of them
   * change these values for the row.  It also should enable using
   * the routines for other purposes.
   */
  typedef struct png_row_info_struct
  {
     png_uint_32 width;    /* width of row */
-@@ -868,16 +877,20 @@ typedef PNG_CALLBACK(void, *png_flush_pt
+@@ -872,16 +881,20 @@ typedef PNG_CALLBACK(void, *png_flush_pt
  typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32,
      int));
  typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32,
      int));
  
  #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
  typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
@@ -93,17 +93,17 @@ diff -up8 png.h png.h
  
  /* The following callback receives png_uint_32 row_number, int pass for the
   * png_bytep data of the row.  When transforming an interlaced image the
   * row number is the row number within the sub-image of the interlace pass, so
   * the value will increase to the height of the sub-image (not the full image)
   * then reset to 0 for the next pass.
   *
   * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to
-@@ -2644,26 +2657,99 @@ PNG_EXPORT(207, void, png_save_uint_16, 
+@@ -2648,26 +2661,99 @@ PNG_EXPORT(207, void, png_save_uint_16, 
  #endif
  
  #if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
      defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
  PNG_EXPORT(234, void, png_set_check_for_invalid_index, (png_structp png_ptr,
      int allowed));
  #endif
  
@@ -194,18 +194,18 @@ diff -up8 png.h png.h
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* PNG_VERSION_INFO_ONLY */
  /* Do not put anything past this line */
 diff -up8 pngget.c pngget.c
---- pngget.c	2012-06-14 07:28:00 -0400
-+++ pngget.c	2012-04-24 20:51:09 -0400
+--- pngget.c	2012-09-27 07:21:20 -0400
++++ pngget.c	2012-07-04 16:27:29 -0400
 @@ -1116,9 +1116,171 @@ png_get_io_chunk_type (png_const_structp
  png_const_bytep PNGAPI
  png_get_io_chunk_name (png_structp png_ptr)
  {
     PNG_CSTRING_FROM_CHUNK(png_ptr->io_chunk_string, png_ptr->chunk_name);
     return png_ptr->io_chunk_string;
  }
  #endif /* ?PNG_IO_STATE_SUPPORTED */
@@ -369,18 +369,18 @@ diff -up8 pngget.c pngget.c
 +
 +    PNG_UNUSED(info_ptr)
 +
 +    return 0;
 +}
 +#endif /* PNG_APNG_SUPPORTED */
  #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
 diff -up8 pnginfo.h pnginfo.h
---- pnginfo.h	2012-06-14 07:28:00 -0400
-+++ pnginfo.h	2012-03-03 22:17:56 -0500
+--- pnginfo.h	2012-09-27 07:21:20 -0400
++++ pnginfo.h	2012-07-04 16:27:29 -0400
 @@ -260,10 +260,23 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
  
  #ifdef PNG_INFO_IMAGE_SUPPORTED
     /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS)
        non-zero */
     /* Data valid if (valid & PNG_INFO_IDAT) non-zero */
     png_bytepp row_pointers;        /* the image bits */
  #endif
@@ -396,18 +396,18 @@ diff -up8 pnginfo.h pnginfo.h
 +   png_uint_16 next_frame_delay_den;
 +   png_byte next_frame_dispose_op;
 +   png_byte next_frame_blend_op;
 +#endif
 +
  };
  #endif /* PNGINFO_H */
 diff -up8 pngpread.c pngpread.c
---- pngpread.c	2012-06-14 07:28:00 -0400
-+++ pngpread.c	2012-07-16 20:05:38 -0400
+--- pngpread.c	2012-09-27 07:21:20 -0400
++++ pngpread.c	2012-07-17 19:54:14 -0400
 @@ -210,16 +210,119 @@ png_push_read_chunk(png_structp png_ptr,
        png_crc_read(png_ptr, chunk_tag, 4);
        png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
        png_check_chunk_name(png_ptr, png_ptr->chunk_name);
        png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
     }
  
     chunk_name = png_ptr->chunk_name;
@@ -726,18 +726,18 @@ diff -up8 pngpread.c pngpread.c
  png_get_progressive_ptr(png_const_structp png_ptr)
  {
     if (png_ptr == NULL)
        return (NULL);
  
     return png_ptr->io_ptr;
  }
 diff -up8 pngpriv.h pngpriv.h
---- pngpriv.h	2012-06-14 07:28:00 -0400
-+++ pngpriv.h	2012-07-16 20:05:38 -0400
+--- pngpriv.h	2012-09-27 07:21:20 -0400
++++ pngpriv.h	2012-09-29 11:36:24 -0400
 @@ -462,16 +462,20 @@ typedef PNG_CONST png_uint_16p FAR * png
  #define PNG_HAVE_sRGB               0x80
  #define PNG_HAVE_CHUNK_HEADER      0x100
  #define PNG_WROTE_tIME             0x200
  #define PNG_WROTE_INFO_BEFORE_PLTE 0x400
  #define PNG_BACKGROUND_IS_GRAY     0x800
  #define PNG_HAVE_PNG_SIGNATURE    0x1000
  #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
@@ -833,18 +833,18 @@ diff -up8 pngpriv.h pngpriv.h
  #ifdef PNG_CHECK_cHRM_SUPPORTED
  PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr,
      png_fixed_point int_white_x, png_fixed_point int_white_y,
      png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
      int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
      png_fixed_point int_blue_y));
  #endif
 diff -up8 pngread.c pngread.c
---- pngread.c	2012-06-14 07:28:00 -0400
-+++ pngread.c	2012-07-16 20:05:38 -0400
+--- pngread.c	2012-09-27 07:21:20 -0400
++++ pngread.c	2012-07-17 19:54:14 -0400
 @@ -235,16 +235,19 @@ png_read_info(png_structp png_ptr, png_i
        {
           if (!(png_ptr->mode & PNG_HAVE_IHDR))
              png_error(png_ptr, "Missing IHDR before IDAT");
  
           else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
               !(png_ptr->mode & PNG_HAVE_PLTE))
              png_error(png_ptr, "Missing PLTE before IDAT");
@@ -1035,18 +1035,18 @@ diff -up8 pngread.c pngread.c
        }
  
        if (ret != Z_OK)
           png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
               "Decompression error");
  
     } while (png_ptr->zstream.avail_out);
 diff -up8 pngrutil.c pngrutil.c
---- pngrutil.c	2012-06-14 07:28:00 -0400
-+++ pngrutil.c	2012-04-24 20:51:09 -0400
+--- pngrutil.c	2012-09-27 07:21:20 -0400
++++ pngrutil.c	2012-09-29 11:36:24 -0400
 @@ -542,16 +542,21 @@ png_handle_IHDR(png_structp png_ptr, png
     width = png_get_uint_31(png_ptr, buf);
     height = png_get_uint_31(png_ptr, buf + 4);
     bit_depth = buf[8];
     color_type = buf[9];
     compression_type = buf[10];
     filter_type = buf[11];
     interlace_type = buf[12];
@@ -1337,18 +1337,18 @@ diff -up8 pngrutil.c pngrutil.c
 +    png_ptr->zstream.next_out = png_ptr->row_buf;
 +    png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth,
 +        png_ptr->iwidth) + 1;
 +}
 +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 +#endif /* PNG_READ_APNG_SUPPORTED */
  #endif /* PNG_READ_SUPPORTED */
 diff -up8 pngset.c pngset.c
---- pngset.c	2012-06-14 07:28:00 -0400
-+++ pngset.c	2012-07-07 10:21:31 -0400
+--- pngset.c	2012-09-27 07:21:20 -0400
++++ pngset.c	2012-07-07 14:54:14 -0400
 @@ -257,16 +257,21 @@ png_set_IHDR(png_structp png_ptr, png_in
         (PNG_UINT_32_MAX >> 3)      /* 8-byte RRGGBBAA pixels */
         - 48       /* bigrowbuf hack */
         - 1        /* filter byte */
         - 7*8      /* rounding of width to multiple of 8 pixels */
         - 8)       /* extra max_pixel_depth pad */
        info_ptr->rowbytes = 0;
     else
@@ -1520,18 +1520,18 @@ diff -up8 pngset.c pngset.c
  void PNGAPI
  png_set_unknown_chunks(png_structp png_ptr,
     png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
  {
     png_unknown_chunkp np;
     int i;
  
 diff -up8 pngstruct.h pngstruct.h
---- pngstruct.h	2012-06-14 07:28:00 -0400
-+++ pngstruct.h	2012-07-07 10:21:31 -0400
+--- pngstruct.h	2012-09-27 07:21:20 -0400
++++ pngstruct.h	2012-07-07 14:54:14 -0400
 @@ -288,16 +288,37 @@ struct png_struct_def
     png_uint_32 mng_features_permitted;
  #endif
  
  /* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
  #ifdef PNG_MNG_FEATURES_SUPPORTED
     png_byte filter_type;
  #endif
@@ -1561,18 +1561,18 @@ diff -up8 pngstruct.h pngstruct.h
  
  /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
  #ifdef PNG_USER_MEM_SUPPORTED
     png_voidp mem_ptr;             /* user supplied struct for mem functions */
     png_malloc_ptr malloc_fn;      /* function for allocating memory */
     png_free_ptr free_fn;          /* function for freeing memory */
  #endif
 diff -up8 pngwrite.c pngwrite.c
---- pngwrite.c	2012-06-14 07:28:00 -0400
-+++ pngwrite.c	2012-07-07 10:21:31 -0400
+--- pngwrite.c	2012-09-27 07:21:20 -0400
++++ pngwrite.c	2012-07-07 14:54:14 -0400
 @@ -53,16 +53,20 @@ png_write_info_before_PLTE(png_structp p
  #ifdef PNG_WRITE_INTERLACING_SUPPORTED
         info_ptr->interlace_type);
  #else
         0);
  #endif
     /* The rest of these check to see if the valid field has the appropriate
      * flag set, and if it does, writes the chunk.
@@ -1656,18 +1656,18 @@ diff -up8 pngwrite.c pngwrite.c
 +
 +    png_ptr->num_frames_written++;
 +
 +    PNG_UNUSED(info_ptr)
 +}
 +#endif /* PNG_WRITE_APNG_SUPPORTED */
  #endif /* PNG_WRITE_SUPPORTED */
 diff -up8 pngwutil.c pngwutil.c
---- pngwutil.c	2012-06-14 07:28:00 -0400
-+++ pngwutil.c	2012-04-24 20:51:09 -0400
+--- pngwutil.c	2012-09-27 07:21:20 -0400
++++ pngwutil.c	2012-09-29 11:36:24 -0400
 @@ -816,16 +816,21 @@ png_write_IHDR(png_structp png_ptr, png_
     buf[9] = (png_byte)color_type;
     buf[10] = (png_byte)compression_type;
     buf[11] = (png_byte)filter_type;
     buf[12] = (png_byte)interlace_type;
  
     /* Write the chunk */
     png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
@@ -1719,17 +1719,17 @@ diff -up8 pngwutil.c pngwutil.c
     png_ptr->mode |= PNG_HAVE_IDAT;
  
     /* Prior to 1.5.4 this code was replicated in every caller (except at the
      * end, where it isn't technically necessary).  Since this function has
      * flushed the data we can safely reset the zlib output buffer here.
      */
     png_ptr->zstream.next_out = png_ptr->zbuf;
     png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-@@ -1992,16 +2018,74 @@ png_write_tIME(png_structp png_ptr, png_
+@@ -1993,16 +2019,74 @@ png_write_tIME(png_structp png_ptr, png_
     buf[4] = mod_time->hour;
     buf[5] = mod_time->minute;
     buf[6] = mod_time->second;
  
     png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
  }
  #endif
  
@@ -1794,17 +1794,17 @@ diff -up8 pngwutil.c pngwutil.c
  /* Initializes the row writing capability of libpng */
  void /* PRIVATE */
  png_write_start_row(png_structp png_ptr)
  {
  #ifdef PNG_WRITE_INTERLACING_SUPPORTED
     /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  
     /* Start of interlace block */
-@@ -3171,9 +3255,44 @@ png_write_filtered_row(png_structp png_p
+@@ -3172,9 +3256,44 @@ png_write_filtered_row(png_structp png_p
  
     if (png_ptr->flush_dist > 0 &&
         png_ptr->flush_rows >= png_ptr->flush_dist)
     {
        png_write_flush(png_ptr);
     }
  #endif
  }
--- a/media/libpng/libpng-manual.txt
+++ b/media/libpng/libpng-manual.txt
@@ -1,24 +1,24 @@
 Libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.5.11 - June 14, 2012
+ libpng version 1.5.13 - September 27, 2012
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
- Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ Copyright (c) 1998-2012 Glenn Randers-Pehrson
 
  This document is released under the libpng license.
  For conditions of distribution and use, see the disclaimer
  and license in png.h
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.5.11 - June 14, 2012
+ libpng versions 0.97, January 1998, through 1.5.13 - September 27, 2012
  Updated and distributed by Glenn Randers-Pehrson
- Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ Copyright (c) 1998-2012 Glenn Randers-Pehrson
 
  libpng 1.0 beta 6  version 0.96 May 28, 1997
  Updated and distributed by Andreas Dilger
  Copyright (c) 1996, 1997 Andreas Dilger
 
  libpng 1.0 beta 2 - version 0.88  January 26, 1996
  For conditions of distribution and use, see copyright
  notice in png.h. Copyright (c) 1995, 1996 Guy Eric
@@ -718,21 +718,21 @@ The second thing you may need to tell li
 alpha channel information.  Some, but not all, PNG files contain an alpha
 channel.  To display these files correctly you need to compose the data onto a
 suitable background, as described in the PNG specification.
 
 Libpng only supports composing onto a single color (using png_set_background;
 see below).  Otherwise you must do the composition yourself and, in this case,
 you may need to call png_set_alpha_mode:
 
-#if PNG_LIBPNG_VER >= 10504
-   png_set_alpha_mode(png_ptr, mode, screen_gamma);
-#else
-   png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma);
-#endif
+    #if PNG_LIBPNG_VER >= 10504
+       png_set_alpha_mode(png_ptr, mode, screen_gamma);
+    #else
+       png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma);
+    #endif
 
 The screen_gamma value is the same as the argument to png_set_gamma; however,
 how it affects the output depends on the mode.  png_set_alpha_mode() sets the
 file gamma default to 1/screen_gamma, so normally you don't need to call
 png_set_gamma.  If you need different defaults call png_set_gamma() before
 png_set_alpha_mode() - if you call it after it will override the settings made
 by png_set_alpha_mode().
 
@@ -1147,30 +1147,31 @@ gamma when combining semitransparent pix
     png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma);
 
     file_gamma     - the gamma at which the file was
                      written (PNG_INFO_gAMA)
 
     int_file_gamma - 100,000 times the gamma at which the
                      file is written
 
-    png_get_cHRM(png_ptr, info_ptr,  &white_x, &white_y, &red_x, &red_y,
-                     &green_x, &green_y, &blue_x, &blue_y)
+    png_get_cHRM(png_ptr, info_ptr,  &white_x, &white_y, &red_x,
+                     &red_y, &green_x, &green_y, &blue_x, &blue_y)
     png_get_cHRM_XYZ(png_ptr, info_ptr, &red_X, &red_Y, &red_Z, &green_X,
                      &green_Y, &green_Z, &blue_X, &blue_Y, &blue_Z)
     png_get_cHRM_fixed(png_ptr, info_ptr, &int_white_x, &int_white_y,
                      &int_red_x, &int_red_y, &int_green_x, &int_green_y,
                      &int_blue_x, &int_blue_y)
     png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &int_red_X, &int_red_Y,
                      &int_red_Z, &int_green_X, &int_green_Y, &int_green_Z,
                      &int_blue_X, &int_blue_Y, &int_blue_Z)
 
     {white,red,green,blue}_{x,y}
-                     A color space encoding specified using the chromaticities
-                     of the end points and the white point. (PNG_INFO_cHRM)
+                     A color space encoding specified using the
+                     chromaticities of the end points and the
+                     white point. (PNG_INFO_cHRM)
 
     {red,green,blue}_{X,Y,Z}
                      A color space encoding specified using the encoding end
                      points - the CIE tristimulus specification of the intended
                      color of the red, green and blue channels in the PNG RGB
                      data.  The white point is simply the sum of the three end
                      points. (PNG_INFO_cHRM)
 
@@ -1571,27 +1572,29 @@ means tRNS or alpha is present but all p
 Within the matrix,
      "+" identifies entries where 'from' and 'to' are the same.
      "-" means the transformation is not supported.
      "." means nothing is necessary (a tRNS chunk can just be ignored).
      "t" means the transformation is obtained by png_set_tRNS.
      "A" means the transformation is obtained by png_set_add_alpha().
      "X" means the transformation is obtained by png_set_expand().
      "1" means the transformation is obtained by
-         png_set_expand_gray_1_2_4_to_8() (and by png_set_expand() if there
-         is no transparency in the original or the final format).
+         png_set_expand_gray_1_2_4_to_8() (and by png_set_expand()
+         if there is no transparency in the original or the final
+         format).
      "C" means the transformation is obtained by png_set_gray_to_rgb().
      "G" means the transformation is obtained by png_set_rgb_to_gray().
      "P" means the transformation is obtained by
          png_set_expand_palette_to_rgb().
      "p" means the transformation is obtained by png_set_packing().
      "Q" means the transformation is obtained by png_set_quantize().
-     "T" means the transformation is obtained by png_set_tRNS_to_alpha().
-     "B" means the transformation is obtained by png_set_background(), or
-         png_strip_alpha().
+     "T" means the transformation is obtained by
+         png_set_tRNS_to_alpha().
+     "B" means the transformation is obtained by
+         png_set_background(), or png_strip_alpha().
 
 When an entry has multiple transforms listed all are required to cause the
 right overall transformation.  When two transforms are separated by a comma
 either will do the job.  When transforms are enclosed in [] the transform should
 do the job but this is currently unimplemented - a different format will result
 if the suggested transformations are used.
 
 In PNG files, the alpha channel in an image
@@ -1666,18 +1669,18 @@ RGB.  This code will do that conversion:
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);
 
 Conversely, you can convert an RGB or RGBA image to grayscale or grayscale
 with alpha.
 
     if (color_type == PNG_COLOR_TYPE_RGB ||
         color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-       png_set_rgb_to_gray(png_ptr, error_action, double red_weight,
-          double green_weight);
+       png_set_rgb_to_gray(png_ptr, error_action,
+          double red_weight, double green_weight);
 
     error_action = 1: silently do the conversion
 
     error_action = 2: issue a warning if the original
                       image has any pixel where
                       red != green or red != blue
 
     error_action = 3: issue an error and abort the
@@ -1689,17 +1692,18 @@ with alpha.
 
     green_weight:     weight of green component
                       If either weight is negative, default
                       weights are used.
 
 In the corresponding fixed point API the red_weight and green_weight values are
 simply scaled by 100,000:
 
-    png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight,
+    png_set_rgb_to_gray(png_ptr, error_action,
+       png_fixed_point red_weight,
        png_fixed_point green_weight);
 
 If you have set error_action = 1 or 2, you can
 later check whether the image really was gray, after processing
 the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
 It will return a png_byte that is zero if the image was gray or
 1 if there were any non-gray pixels.  Background and sBIT data
 will be silently converted to grayscale, using the green channel
@@ -2184,17 +2188,17 @@ by the user and not by libpng,  and will
 The "seq" parameter is ignored if only one item of the selected data
 type, such as PLTE, is allowed.  If "seq" is not -1, and multiple items
 are allowed for the data type identified in the mask, such as text or
 sPLT, only the n'th item in the structure is freed, where n is "seq".
 
 The default behavior is only to free data that was allocated internally
 by libpng.  This can be changed, so that libpng will not free the data,
 or so that it will free data that was allocated by the user with png_malloc()
-or png_zalloc() and passed in via a png_set_*() function, with
+or png_calloc() and passed in via a png_set_*() function, with
 
     png_data_freer(png_ptr, info_ptr, freer, mask)
 
     freer  - one of
                PNG_DESTROY_WILL_FREE_DATA
                PNG_SET_WILL_FREE_DATA
                PNG_USER_WILL_FREE_DATA
 
@@ -2205,17 +2209,17 @@ This function only affects data that has
 You can call this function after reading the PNG data but before calling
 any png_set_*() functions, to control whether the user or the png_set_*()
 function is responsible for freeing any existing data that might be present,
 and again after the png_set_*() functions to control whether the user
 or png_destroy_*() is supposed to free the data.  When the user assumes
 responsibility for libpng-allocated data, the application must use
 png_free() to free it, and when the user transfers responsibility to libpng
 for data that the user has allocated, the user must have used png_malloc()
-or png_zalloc() to allocate it.
+or png_calloc() to allocate it.
 
 If you allocated your row_pointers in a single block, as suggested above in
 the description of the high level read interface, you must not transfer
 responsibility for freeing it to the png_set_rows or png_read_destroy function,
 because they would also try to free the individual row_pointers[i].
 
 If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
 separately, do not transfer responsibility for freeing text_ptr to libpng,
@@ -3023,18 +3027,18 @@ necessary because the "creation time" of
 depending on whether you mean the PNG file, the time the image was
 created in a non-PNG format, a still photo from which the image was
 scanned, or possibly the subject matter itself.  In order to facilitate
 machine-readable dates, it is recommended that the "Creation Time"
 tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
 although this isn't a requirement.  Unlike the tIME chunk, the
 "Creation Time" tEXt chunk is not expected to be automatically changed
 by the software.  To facilitate the use of RFC 1123 dates, a function
-png_convert_to_rfc1123(png_timep) is provided to convert from PNG
-time to an RFC 1123 format string.
+png_convert_to_rfc1123(png_ptr, png_timep) is provided to convert
+from PNG time to an RFC 1123 format string.
 
 Writing unknown chunks
 
 You can use the png_set_unknown_chunks function to queue up chunks
 for writing.  You give it a chunk name, raw data, and a size; that's
 all there is to it.  The chunks will be written by the next following
 png_write_info_before_PLTE, png_write_info, or png_write_end function.
 Any chunks previously read into the info structure's unknown-chunk
@@ -3386,17 +3390,17 @@ sPLT, only the n'th item in the structur
 
 If you allocated data such as a palette that you passed in to libpng
 with png_set_*, you must not free it until just before the call to
 png_destroy_write_struct().
 
 The default behavior is only to free data that was allocated internally
 by libpng.  This can be changed, so that libpng will not free the data,
 or so that it will free data that was allocated by the user with png_malloc()
-or png_zalloc() and passed in via a png_set_*() function, with
+or png_calloc() and passed in via a png_set_*() function, with
 
     png_data_freer(png_ptr, info_ptr, freer, mask)
 
     freer  - one of
                PNG_DESTROY_WILL_FREE_DATA
                PNG_SET_WILL_FREE_DATA
                PNG_USER_WILL_FREE_DATA
 
@@ -3422,17 +3426,17 @@ structure.
 
 This function only affects data that has already been allocated.
 You can call this function before calling after the png_set_*() functions
 to control whether the user or png_destroy_*() is supposed to free the data.
 When the user assumes responsibility for libpng-allocated data, the
 application must use
 png_free() to free it, and when the user transfers responsibility to libpng
 for data that the user has allocated, the user must have used png_malloc()
-or png_zalloc() to allocate it.
+or png_calloc() to allocate it.
 
 If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
 separately, do not transfer responsibility for freeing text_ptr to libpng,
 because when libpng fills a png_text structure it combines these members with
 the key member, and png_free_data() will free only text_ptr.key.  Similarly,
 if you transfer responsibility for free'ing text_ptr from libpng to your
 application, your application must not separately free those members.
 For a more compact example of writing a PNG image, see the file example.c.
@@ -3450,22 +3454,23 @@ to provide the user with a means of chan
 Memory allocation, input/output, and error handling
 
 All of the memory allocation, input/output, and error handling in libpng
 goes through callbacks that are user-settable.  The default routines are
 in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively.  To change
 these functions, call the appropriate png_set_*_fn() function.
 
 Memory allocation is done through the functions png_malloc(), png_calloc(),
-and png_free().  These currently just call the standard C functions.
-png_calloc() calls png_malloc() and then clears the newly
-allocated memory to zero.  There is limited support for certain systems
-with segmented memory architectures and the types of pointers declared by
-png.h match this; you will have to use appropriate pointers in your
-application.  Since it is
+and png_free().  The png_malloc() and png_free() functions currently just
+call the standard C functions and png_calloc() calls png_malloc() and then
+clears the newly allocated memory to zero; note that png_calloc(png_ptr, size)
+is not the same as the calloc(number, size) function provided by stdlib.h.
+There is limited support for certain systems with segmented memory
+architectures and the types of pointers declared by png.h match this; you
+will have to use appropriate pointers in your application.  Since it is
 unlikely that the method of handling memory allocation on a platform
 will change between applications, these functions must be modified in
 the library at compile time.  If you prefer to use a different method
 of allocating and freeing data, you can use png_create_read_struct_2() or
 png_create_write_struct_2() to register your own functions as described
 above.  These functions also provide a void pointer that can be retrieved
 via
 
@@ -4084,18 +4089,18 @@ The png_permit_empty_plte() was removed.
 since libpng-1.0.9.  Use png_permit_mng_features() instead.
 
 We removed the obsolete stub functions png_get_mmx_flagmask(),
 png_set_mmx_thresholds(), png_get_asm_flags(),
 png_get_mmx_bitdepth_threshold(), png_get_mmx_rowbytes_threshold(),
 png_set_asm_flags(), and png_mmx_supported()
 
 We removed the obsolete png_check_sig(), png_memcpy_check(), and
-png_memset_check() functions.  Instead use !png_sig_cmp(), memcpy(),
-and memset(), respectively.
+png_memset_check() functions.  Instead use !png_sig_cmp(), png_memcpy(),
+and png_memset(), respectively.
 
 The function png_set_gray_1_2_4_to_8() was removed. It has been
 deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with
 png_set_expand_gray_1_2_4_to_8() because the former function also
 expanded any tRNS chunk to an alpha channel.
 
 Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32
 were added and are used by default instead of the corresponding
@@ -4122,17 +4127,19 @@ png_set_compression_buffer_size() to wor
 png_uint_32.
 
 Support for numbered error messages was removed by default, since we
 never got around to actually numbering the error messages. The function
 png_set_strip_error_numbers() was removed from the library by default.
 
 The png_zalloc() and png_zfree() functions are no longer exported.
 The png_zalloc() function no longer zeroes out the memory that it
-allocates.
+allocates.  Applications that called png_zalloc(png_ptr, number, size)
+can call png_calloc(png_ptr, number*size) instead, and can call
+png_free() instead of png_zfree().
 
 Support for dithering was disabled by default in libpng-1.4.0, because
 it has not been well tested and doesn't actually "dither".
 The code was not
 removed, however, and could be enabled by building libpng with
 PNG_READ_DITHER_SUPPORTED defined.  In libpng-1.4.2, this support
 was reenabled, but the function was renamed png_set_quantize() to
 reflect more accurately what it actually does.  At the same time,
@@ -4156,28 +4163,31 @@ This is enabled by default but can be di
       allowed  - one of
                  0: disable
                  1: enable
 
 A. Changes that affect users of libpng
 
 There are no substantial API changes between the non-deprecated parts of
 the 1.4.5 API and the 1.5.0 API; however, the ability to directly access
-the main libpng control structures, png_struct and png_info, deprecated
-in earlier versions of libpng, has been completely removed from
+members of the main libpng control structures, png_struct and png_info,
+deprecated in earlier versions of libpng, has been completely removed from
 libpng 1.5.
 
 We no longer include zlib.h in png.h.  Applications that need access
 to information in zlib.h will need to add the '#include "zlib.h"'
 directive.  It does not matter whether it is placed prior to or after
 the '"#include png.h"' directive.
 
-We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(),
-png_memcmp(), png_sprintf, and png_memcpy() macros into a private
-header file (pngpriv.h) that is not accessible to applications.
+The png_sprintf(), png_strcpy(), and png_strncpy() macros are no longer used
+and were removed.
+
+We moved the png_strlen(), png_memcpy(), png_memset(), and png_memcmp()
+macros into a private header file (pngpriv.h) that is not accessible to
+applications.
 
 In png_get_iCCP, the type of "profile" was changed from png_charpp
 to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep.
 
 There are changes of form in png.h, including new and changed macros to
 declare parts of the API.  Some API functions with arguments that are
 pointers to data not modified within the function have been corrected to
 declare these arguments with PNG_CONST.
@@ -4597,23 +4607,23 @@ with an even number of lower-case hex di
 We do not use the TAB character for indentation in the C sources.
 
 Lines do not exceed 80 characters.
 
 Other rules can be inferred by inspecting the libpng source.
 
 XIV. Y2K Compliance in libpng
 
-June 14, 2012
+September 27, 2012
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.5.11 are Y2K compliant.  It is my belief that earlier
+upward through 1.5.13 are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has two year fields.  One is a 2-byte unsigned integer that
 will hold years up to 65535.  The other holds the date in text
 format, and will hold years up to 9999.
 
 The integer is
     "png_uint_16 year" in png_time_struct.
--- a/media/libpng/png.c
+++ b/media/libpng/png.c
@@ -9,17 +9,17 @@
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_5_11 Your_png_h_is_not_version_1_5_11;
+typedef png_libpng_version_1_5_13 Your_png_h_is_not_version_1_5_13;
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
  * stream we can set num_bytes = 8 so that libpng will not attempt to read
  * or write any of the magic bytes before it starts on the IHDR.
  */
 
 #ifdef PNG_READ_SUPPORTED
@@ -650,23 +650,23 @@ png_const_charp PNGAPI
 png_get_copyright(png_const_structp png_ptr)
 {
    PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
 #ifdef PNG_STRING_COPYRIGHT
    return PNG_STRING_COPYRIGHT
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-     "libpng version 1.5.11 - June 14, 2012" PNG_STRING_NEWLINE \
+     "libpng version 1.5.13 - September 27, 2012" PNG_STRING_NEWLINE \
      "Copyright (c) 1998-2012 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE;
 #  else
-      return "libpng version 1.5.11 - June 14, 2012\
+      return "libpng version 1.5.13 - September 27, 2012\
       Copyright (c) 1998-2012 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
 #  endif
 #endif
 }
 
 /* The following return the library version as a short string in the
--- a/media/libpng/png.h
+++ b/media/libpng/png.h
@@ -1,22 +1,22 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.5.11 - June 14, 2012
+ * libpng version 1.5.13 - September 27, 2012
  * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license (See LICENSE, below)
  *
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.5.11 - June 14, 2012: Glenn
+ *   libpng versions 0.97, January 1998, through 1.5.13 - September 27, 2012: Glenn
  *   See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
  *
  *   Due to various miscommunications, unforeseen code incompatibilities
  *   and occasional factors outside the authors' control, version numbering
  *   on the library has not always been consistent and straightforward.
  *   The following table summarizes matters since version 0.89c, which was
@@ -172,16 +172,20 @@
  *    1.5.9beta01-02          15    10509  15.so.15.9[.0]
  *    1.5.9rc01               15    10509  15.so.15.9[.0]
  *    1.5.9                   15    10509  15.so.15.9[.0]
  *    1.5.10beta01-05         15    10510  15.so.15.10[.0]
  *    1.5.10                  15    10510  15.so.15.10[.0]
  *    1.5.11beta01            15    10511  15.so.15.11[.0]
  *    1.5.11rc01-05           15    10511  15.so.15.11[.0]
  *    1.5.11                  15    10511  15.so.15.11[.0]
+ *    1.5.12                  15    10512  15.so.15.12[.0]
+ *    1.5.13beta01-02         15    10513  15.so.15.13[.0]
+ *    1.5.13rc01              15    10513  15.so.15.13[.0]
+ *    1.5.13                  15    10513  15.so.15.13[.0]
  *
  *   Henceforth the source version will match the shared-library major
  *   and minor numbers; the shared-library major version number will be
  *   used for changes in backward compatibility, as it is intended.  The
  *   PNG_LIBPNG_VER macro, which is not used within libpng but is available
  *   for applications, is an unsigned integer of the form xyyzz corresponding
  *   to the source version x.y.z (leading zeros in y and z).  Beta versions
  *   were given the previous public release number plus a letter, until
@@ -203,17 +207,17 @@
 /*
  * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
  *
  * If you modify libpng you may insert additional notices immediately following
  * this sentence.
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.5.11, June 14, 2012, are
+ * libpng versions 1.2.6, August 15, 2004, through 1.5.13, September 27, 2012, are
  * Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
  *
  *    Cosmin Truta
  *
  * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
  * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
@@ -315,23 +319,23 @@
  *
  * Thanks to Frank J. T. Wojcik for helping with the documentation.
  */
 
 /*
  * Y2K compliance in libpng:
  * =========================
  *
- *    June 14, 2012
+ *    September 27, 2012
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.5.11 are Y2K compliant.  It is my belief that
+ *    upward through 1.5.13 are Y2K compliant.  It is my belief that
  *    earlier versions were also Y2K compliant.
  *
  *    Libpng only has two year fields.  One is a 2-byte unsigned integer
  *    that will hold years up to 65535.  The other holds the date in text
  *    format, and will hold years up to 9999.
  *
  *    The integer is
  *        "png_uint_16 year" in png_time_struct.
@@ -380,27 +384,27 @@
  * with some code on which to build.  This file is useful for looking
  * at the actual function definitions and structure components.
  *
  * If you just need to read a PNG file and don't want to read the documentation
  * skip to the end of this file and read the section entitled 'simplified API'.
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.5.11"
+#define PNG_LIBPNG_VER_STRING "1.5.13"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.5.11 - June 14, 2012\n"
+     " libpng version 1.5.13 - September 27, 2012\n"
 
 #define PNG_LIBPNG_VER_SONUM   15
 #define PNG_LIBPNG_VER_DLLNUM  15
 
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   5
-#define PNG_LIBPNG_VER_RELEASE 11
+#define PNG_LIBPNG_VER_RELEASE 13
 
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  */
 
 #define PNG_LIBPNG_VER_BUILD  0
 
 /* Release Status */
@@ -421,17 +425,17 @@
 #define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
 
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
  * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10511 /* 1.5.11 */
+#define PNG_LIBPNG_VER 10513 /* 1.5.13 */
 
 #ifndef MOZPNGCONF_H
 #   include "mozpngconf.h"
 #endif
 
 #ifndef PNG_VERSION_INFO_ONLY
 #  ifndef PNG_BUILDING_SYMBOL_TABLE
   /*
@@ -548,17 +552,17 @@ extern "C" {
 /* blend_op flags from inside fcTL */
 #define PNG_BLEND_OP_SOURCE        0x00
 #define PNG_BLEND_OP_OVER          0x01
 #endif /* PNG_APNG_SUPPORTED */
 
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char* png_libpng_version_1_5_11;
+typedef char* png_libpng_version_1_5_13;
 
 /* Three color definitions.  The order of the red, green, and blue, (and the
  * exact size) is not important, although the size of the fields need to
  * be png_byte or png_uint_16 (as defined below).
  */
 typedef struct png_color_struct
 {
    png_byte red;
@@ -1165,19 +1169,19 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
 /* Reduce RGB to grayscale. */
 #define PNG_ERROR_ACTION_NONE  1
 #define PNG_ERROR_ACTION_WARN  2
 #define PNG_ERROR_ACTION_ERROR 3
 #define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/
 
 PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr,
-    int error_action, double red, double green));
+    int error_action, double red, double green))
 PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr,
-    int error_action, png_fixed_point red, png_fixed_point green));
+    int error_action, png_fixed_point red, png_fixed_point green))
 
 PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp
     png_ptr));
 #endif
 
 #ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
 PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
     png_colorp palette));
@@ -1235,19 +1239,19 @@ PNG_EXPORT(35, void, png_build_grayscale
 #define PNG_ALPHA_PNG           0 /* according to the PNG standard */
 #define PNG_ALPHA_STANDARD      1 /* according to Porter/Duff */
 #define PNG_ALPHA_ASSOCIATED    1 /* as above; this is the normal practice */
 #define PNG_ALPHA_PREMULTIPLIED 1 /* as above */
 #define PNG_ALPHA_OPTIMIZED     2 /* 'PNG' for opaque pixels, else 'STANDARD' */
 #define PNG_ALPHA_BROKEN        3 /* the alpha channel is gamma encoded */
 
 PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode,
-    double output_gamma));
+    double output_gamma))
 PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr,
-    int mode, png_fixed_point output_gamma));
+    int mode, png_fixed_point output_gamma))
 #endif
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
 /* The output_gamma value is a screen gamma in libpng terminology: it expresses
  * how to decode the output values, not how they are encoded.  The values used
  * correspond to the normal numbers used to describe the overall gamma of a
  * computer display system; for example 2.2 for an sRGB conformant system.  The
  * values are scaled by 100000 in the _fixed version of the API (so 220000 for
@@ -1460,20 +1464,20 @@ PNG_EXPORT(46, void, png_set_invert_mono
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
 /* Handle alpha and tRNS by replacing with a background color.  Prior to
  * libpng-1.5.4 this API must not be called before the PNG file header has been
  * read.  Doing so will result in unexpected behavior and possible warnings or
  * errors if the PNG file contains a bKGD chunk.
  */
 PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr,
     png_const_color_16p background_color, int background_gamma_code,
-    int need_expand, double background_gamma));
+    int need_expand, double background_gamma))
 PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr,
     png_const_color_16p background_color, int background_gamma_code,
-    int need_expand, png_fixed_point background_gamma));
+    int need_expand, png_fixed_point background_gamma))
 #endif
 #ifdef PNG_READ_BACKGROUND_SUPPORTED
 #  define PNG_BACKGROUND_GAMMA_UNKNOWN 0
 #  define PNG_BACKGROUND_GAMMA_SCREEN  1
 #  define PNG_BACKGROUND_GAMMA_FILE    2
 #  define PNG_BACKGROUND_GAMMA_UNIQUE  3
 #endif
 
@@ -1512,19 +1516,19 @@ PNG_EXPORT(49, void, png_set_quantize,
  *
  * These routines accept the same gamma values as png_set_alpha_mode (described
  * above).  The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either
  * API (floating point or fixed.)  Notice, however, that the 'file_gamma' value
  * is the inverse of a 'screen gamma' value.
  */
 PNG_FP_EXPORT(50, void, png_set_gamma,
     (png_structp png_ptr, double screen_gamma,
-    double override_file_gamma));
+    double override_file_gamma))
 PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr,
-    png_fixed_point screen_gamma, png_fixed_point override_file_gamma));
+    png_fixed_point screen_gamma, png_fixed_point override_file_gamma))
 #endif
 
 #ifdef PNG_WRITE_FLUSH_SUPPORTED
 /* Set how many lines between output flushes - 0 for no flushing */
 PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows));
 /* Flush the current PNG output buffer */
 PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr));
 #endif
@@ -1674,21 +1678,21 @@ PNG_EXPORT(67, void, png_set_filter,
  * values in the range [0.0, 1.0) indicate the value is to remain unchanged.
  * The default values for both weights and costs are currently 1.0, but may
  * change if good general weighting/cost heuristics can be found.  If both
  * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
  * to the UNWEIGHTED method, but with added encoding time/computation.
  */
 PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr,
     int heuristic_method, int num_weights, png_const_doublep filter_weights,
-    png_const_doublep filter_costs));
+    png_const_doublep filter_costs))
 PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
     (png_structp png_ptr,
     int heuristic_method, int num_weights, png_const_fixed_point_p
-    filter_weights, png_const_fixed_point_p filter_costs));
+    filter_weights, png_const_fixed_point_p filter_costs))
 #endif /*  PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
 
 /* Heuristic used for row filter selection.  These defines should NOT be
  * changed.
  */
 #define PNG_FILTER_HEURISTIC_DEFAULT    0  /* Currently "UNWEIGHTED" */
 #define PNG_FILTER_HEURISTIC_UNWEIGHTED 1  /* Used by libpng < 0.95 */
 #define PNG_FILTER_HEURISTIC_WEIGHTED   2  /* Experimental feature */
@@ -2060,19 +2064,19 @@ PNG_EXPORT(122, png_uint_32, png_get_pix
     (png_const_structp png_ptr, png_const_infop info_ptr));
 PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter,
     (png_const_structp png_ptr, png_const_infop info_ptr));
 PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter,
     (png_const_structp png_ptr, png_const_infop info_ptr));
 
 /* Returns pixel aspect ratio, computed from pHYs chunk data.  */
 PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio,
-    (png_const_structp png_ptr, png_const_infop info_ptr));
+    (png_const_structp png_ptr, png_const_infop info_ptr))
 PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed,
-    (png_const_structp png_ptr, png_const_infop info_ptr));
+    (png_const_structp png_ptr, png_const_infop info_ptr))
 
 /* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
 PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels,
     (png_const_structp png_ptr, png_const_infop info_ptr));
 PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels,
     (png_const_structp png_ptr, png_const_infop info_ptr));
 PNG_EXPORT(128, png_int_32, png_get_x_offset_microns,
     (png_const_structp png_ptr, png_const_infop info_ptr));
@@ -2095,76 +2099,76 @@ PNG_EXPORT(131, png_uint_32, png_get_bKG
 PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr,
     png_const_color_16p background));
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
 PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr,
    png_const_infop info_ptr, double *white_x, double *white_y, double *red_x,
     double *red_y, double *green_x, double *green_y, double *blue_x,
-    double *blue_y));
+    double *blue_y))
 PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_structp png_ptr,
     png_const_infop info_ptr, double *red_X, double *red_Y, double *red_Z,
     double *green_X, double *green_Y, double *green_Z, double *blue_X,
-    double *blue_Y, double *blue_Z));
+    double *blue_Y, double *blue_Z))
 #ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */
 PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed,
     (png_const_structp png_ptr,
     png_const_infop info_ptr, png_fixed_point *int_white_x,
     png_fixed_point *int_white_y, png_fixed_point *int_red_x,
     png_fixed_point *int_red_y, png_fixed_point *int_green_x,
     png_fixed_point *int_green_y, png_fixed_point *int_blue_x,
-    png_fixed_point *int_blue_y));
+    png_fixed_point *int_blue_y))
 #endif
 PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed,
     (png_structp png_ptr, png_const_infop info_ptr,
     png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
     png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
     png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
     png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
-    png_fixed_point *int_blue_Z));
+    png_fixed_point *int_blue_Z))
 #endif
 
 #ifdef PNG_cHRM_SUPPORTED
 PNG_FP_EXPORT(135, void, png_set_cHRM,
     (png_structp png_ptr, png_infop info_ptr,
     double white_x, double white_y, double red_x, double red_y, double green_x,
-    double green_y, double blue_x, double blue_y));
+    double green_y, double blue_x, double blue_y))
 PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_structp png_ptr,
     png_infop info_ptr, double red_X, double red_Y, double red_Z,
     double green_X, double green_Y, double green_Z, double blue_X,
-    double blue_Y, double blue_Z));
+    double blue_Y, double blue_Z))
 PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr,
     png_infop info_ptr, png_fixed_point int_white_x,
     png_fixed_point int_white_y, png_fixed_point int_red_x,
     png_fixed_point int_red_y, png_fixed_point int_green_x,
     png_fixed_point int_green_y, png_fixed_point int_blue_x,
-    png_fixed_point int_blue_y));
+    png_fixed_point int_blue_y))
 PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_structp png_ptr,
     png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
     png_fixed_point int_red_Z, png_fixed_point int_green_X,
     png_fixed_point int_green_Y, png_fixed_point int_green_Z,
     png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
-    png_fixed_point int_blue_Z));
+    png_fixed_point int_blue_Z))
 #endif
 
 #ifdef PNG_gAMA_SUPPORTED
 PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA,
     (png_const_structp png_ptr, png_const_infop info_ptr,
-    double *file_gamma));
+    double *file_gamma))
 PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed,
     (png_const_structp png_ptr, png_const_infop info_ptr,
-    png_fixed_point *int_file_gamma));
+    png_fixed_point *int_file_gamma))
 #endif
 
 #ifdef PNG_gAMA_SUPPORTED
 PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr,
-    png_infop info_ptr, double file_gamma));
+    png_infop info_ptr, double file_gamma))
 PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr,
-    png_infop info_ptr, png_fixed_point int_file_gamma));
+    png_infop info_ptr, png_fixed_point int_file_gamma))
 #endif
 
 #ifdef PNG_hIST_SUPPORTED
 PNG_EXPORT(141, png_uint_32, png_get_hIST,
     (png_const_structp png_ptr, png_const_infop info_ptr,
     png_uint_16p *hist));
 #endif
 
@@ -2320,38 +2324,38 @@ PNG_EXPORT(167, void, png_set_tRNS,
     (png_structp png_ptr, png_infop info_ptr,
     png_const_bytep trans_alpha, int num_trans,
     png_const_color_16p trans_color));
 #endif
 
 #ifdef PNG_sCAL_SUPPORTED
 PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL,
     (png_const_structp png_ptr, png_const_infop info_ptr,
-    int *unit, double *width, double *height));
+    int *unit, double *width, double *height))
 #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
 /* NOTE: this API is currently implemented using floating point arithmetic,
  * consequently it can only be used on systems with floating point support.
  * In any case the range of values supported by png_fixed_point is small and it
  * is highly recommended that png_get_sCAL_s be used instead.
  */
 PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed,
     (png_structp png_ptr, png_const_infop info_ptr, int *unit,
     png_fixed_point *width,
-    png_fixed_point *height));
+    png_fixed_point *height))
 #endif
 PNG_EXPORT(169, png_uint_32, png_get_sCAL_s,
     (png_const_structp png_ptr, png_const_infop info_ptr,
     int *unit, png_charpp swidth, png_charpp sheight));
 
 PNG_FP_EXPORT(170, void, png_set_sCAL,
     (png_structp png_ptr, png_infop info_ptr,
-    int unit, double width, double height));
+    int unit, double width, double height))
 PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr,
    png_infop info_ptr, int unit, png_fixed_point width,
-   png_fixed_point height));
+   png_fixed_point height))
 PNG_EXPORT(171, void, png_set_sCAL_s,
     (png_structp png_ptr, png_infop info_ptr,
     int unit, png_const_charp swidth, png_const_charp sheight));
 #endif /* PNG_sCAL_SUPPORTED */
 
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
 /* Provide a list of chunks and how they are to be handled, if the built-in
    handling or default unknown chunk handling is not desired.  Any chunks not
@@ -2454,27 +2458,27 @@ PNG_EXPORT(193, png_uint_32, png_get_pix
 
 PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch,
     (png_const_structp png_ptr, png_const_infop info_ptr));
 
 PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch,
     (png_const_structp png_ptr, png_const_infop info_ptr));
 
 PNG_FP_EXPORT(196, float, png_get_x_offset_inches,
-    (png_const_structp png_ptr, png_const_infop info_ptr));
+    (png_const_structp png_ptr, png_const_infop info_ptr))
 #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
 PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed,
-    (png_structp png_ptr, png_const_infop info_ptr));
+    (png_structp png_ptr, png_const_infop info_ptr))
 #endif
 
 PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr,
-    png_const_infop info_ptr));
+    png_const_infop info_ptr))
 #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
 PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed,
-    (png_structp png_ptr, png_const_infop info_ptr));
+    (png_structp png_ptr, png_const_infop info_ptr))
 #endif
 
 #  ifdef PNG_pHYs_SUPPORTED
 PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr,
     png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
     int *unit_type));
 #  endif /* PNG_pHYs_SUPPORTED */
 #endif  /* PNG_INCH_CONVERSIONS_SUPPORTED */
--- a/media/libpng/pngconf.h
+++ b/media/libpng/pngconf.h
@@ -1,12 +1,12 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.5.11 - June 14, 2012
+ * libpng version 1.5.13 - September 27, 2012
  *
  * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
@@ -339,31 +339,33 @@
    */
 #  if defined(__GNUC__)
 #    ifndef PNG_USE_RESULT
 #      define PNG_USE_RESULT __attribute__((__warn_unused_result__))
 #    endif
 #    ifndef PNG_NORETURN
 #      define PNG_NORETURN   __attribute__((__noreturn__))
 #    endif
-#    ifndef PNG_ALLOCATED
-#      define PNG_ALLOCATED  __attribute__((__malloc__))
-#    endif
-#    ifndef PNG_DEPRECATED
-#      define PNG_DEPRECATED __attribute__((__deprecated__))
-#    endif
-#    ifndef PNG_PRIVATE
-#      if 0 /* Doesn't work so we use deprecated instead*/
-#        define PNG_PRIVATE \
-          __attribute__((warning("This function is not exported by libpng.")))
-#      else
-#        define PNG_PRIVATE \
-          __attribute__((__deprecated__))
+#    if __GNUC__ >= 3
+#      ifndef PNG_ALLOCATED
+#        define PNG_ALLOCATED  __attribute__((__malloc__))
+#      endif
+#      ifndef PNG_DEPRECATED
+#        define PNG_DEPRECATED __attribute__((__deprecated__))
 #      endif
-#    endif
+#      ifndef PNG_PRIVATE
+#        if 0 /* Doesn't work so we use deprecated instead*/
+#          define PNG_PRIVATE \
+            __attribute__((warning("This function is not exported by libpng.")))
+#        else
+#          define PNG_PRIVATE \
+            __attribute__((__deprecated__))
+#        endif
+#      endif
+#    endif /*  __GNUC__ >= 3 */
 #  endif /* __GNUC__ */
 
 #  if defined(_MSC_VER)  && (_MSC_VER >= 1300)
 #    ifndef PNG_USE_RESULT
 #      define PNG_USE_RESULT /* not supported */
 #    endif
 #    ifndef PNG_NORETURN
 #      define PNG_NORETURN __declspec(noreturn)
@@ -395,25 +397,25 @@
 #  define PNG_ALLOCATED   /* The result of the function is new memory */
 #endif
 #ifndef PNG_PRIVATE
 #  define PNG_PRIVATE     /* This is a private libpng function */
 #endif
 #ifndef PNG_FP_EXPORT     /* A floating point API. */
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
 #     define PNG_FP_EXPORT(ordinal, type, name, args)\
-         PNG_EXPORT(ordinal, type, name, args)
+         PNG_EXPORT(ordinal, type, name, args);
 #  else                   /* No floating point APIs */
 #     define PNG_FP_EXPORT(ordinal, type, name, args)
 #  endif
 #endif
 #ifndef PNG_FIXED_EXPORT  /* A fixed point API. */
 #  ifdef PNG_FIXED_POINT_SUPPORTED
 #     define PNG_FIXED_EXPORT(ordinal, type, name, args)\
-         PNG_EXPORT(ordinal, type, name, args)
+         PNG_EXPORT(ordinal, type, name, args);
 #  else                   /* No fixed point APIs */
 #     define PNG_FIXED_EXPORT(ordinal, type, name, args)
 #  endif
 #endif
 
 /* The following uses const char * instead of char * for error
  * and warning message functions, so some compilers won't complain.
  * If you do not want to use const, define PNG_NO_CONST here.
--- a/media/libpng/pngmem.c
+++ b/media/libpng/pngmem.c
@@ -1,13 +1,13 @@
 
 /* pngmem.c - stub functions for memory allocation
  *
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.13 [September 27, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  *
  * This file provides a location for all memory allocation.  Users who
@@ -51,17 +51,17 @@ png_create_struct_2,(int type, png_mallo
 
    else
       return (png_get_copyright(NULL));
 
 #  ifdef PNG_USER_MEM_SUPPORTED
    if (malloc_fn != NULL)
    {
       png_struct dummy_struct;
-      memset(&dummy_struct, 0, sizeof dummy_struct);
+      png_memset(&dummy_struct, 0, sizeof dummy_struct);
       dummy_struct.mem_ptr=mem_ptr;
       struct_ptr = (*(malloc_fn))(&dummy_struct, (png_alloc_size_t)size);
    }
 
    else
 #  endif /* PNG_USER_MEM_SUPPORTED */
    struct_ptr = (png_voidp)farmalloc(size);
    if (struct_ptr != NULL)
@@ -85,17 +85,17 @@ png_destroy_struct_2(png_voidp struct_pt
 {
 #  endif
    if (struct_ptr != NULL)
    {
 #  ifdef PNG_USER_MEM_SUPPORTED
       if (free_fn != NULL)
       {
          png_struct dummy_struct;
-         memset(&dummy_struct, 0, sizeof dummy_struct);
+         png_memset(&dummy_struct, 0, sizeof dummy_struct);
          dummy_struct.mem_ptr=mem_ptr;
          (*(free_fn))(&dummy_struct, struct_ptr);
          return;
       }
 
 #  endif /* PNG_USER_MEM_SUPPORTED */
       farfree (struct_ptr);
    }
--- a/media/libpng/pngpriv.h
+++ b/media/libpng/pngpriv.h
@@ -1002,18 +1002,18 @@ PNG_EXTERN void png_do_read_interlace PN
 /* Grab pixels out of a row for an interlaced pass */
 PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
     png_bytep row, int pass));
 #endif
 
 /* Unfilter a row: check the filter value before calling this, there is no point
  * calling it for PNG_FILTER_VALUE_NONE.
  */
-PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row, int filter));
+PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row, int filter));
 
 PNG_EXTERN void png_read_filter_row_up_neon PNGARG((png_row_infop row_info,
     png_bytep row, png_const_bytep prev_row));
 PNG_EXTERN void png_read_filter_row_sub3_neon PNGARG((png_row_infop row_info,
     png_bytep row, png_const_bytep prev_row));
 PNG_EXTERN void png_read_filter_row_sub4_neon PNGARG((png_row_infop row_info,
     png_bytep row, png_const_bytep prev_row));
 PNG_EXTERN void png_read_filter_row_avg3_neon PNGARG((png_row_infop row_info,
@@ -1630,17 +1630,17 @@ PNG_EXTERN void png_ascii_from_fixed PNG
 #define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO)
    /* NZ_MASK: the string is valid and a non-zero negative value */
 #define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO)
    /* Z MASK: the string is valid and a non-zero value. */
    /* PNG_FP_SAW_DIGIT: the string is valid. */
 #define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT)
 #define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK)
 #define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK)
- 
+
 /* The actual parser.  This can be called repeatedly, it updates
  * the index into the string and the state variable (which must
  * be initialzed to 0).  It returns a result code, as above.  There
  * is no point calling the parser any more if it fails to advance to
  * the end of the string - it is stuck on an invalid character (or
  * terminated by '\0').
  *
  * Note that the pointer will consume an E or even an E+ then leave
--- a/media/libpng/pngrtran.c
+++ b/media/libpng/pngrtran.c
@@ -3700,18 +3700,20 @@ png_do_compose(png_row_infop row_info, p
                      {
                         png_uint_16 v;
 
                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
 
                         if (v == png_ptr->trans_color.gray)
                         {
                            /* Background is already in screen gamma */
-                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
-                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+                           *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
+                           *(sp + 1) = (png_byte)(png_ptr->background.gray
+                                & 0xff);
                         }
 
                         else
                         {
                            v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                            *sp = (png_byte)((v >> 8) & 0xff);
                            *(sp + 1) = (png_byte)(v & 0xff);
                         }
@@ -3724,18 +3726,20 @@ png_do_compose(png_row_infop row_info, p
                      for (i = 0; i < row_width; i++, sp += 2)
                      {
                         png_uint_16 v;
 
                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
 
                         if (v == png_ptr->trans_color.gray)
                         {
-                           *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
-                           *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+                           *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
+                           *(sp + 1) = (png_byte)(png_ptr->background.gray
+                                & 0xff);
                         }
                      }
                   }
                   break;
                }
 
                default:
                   break;
@@ -3805,19 +3809,22 @@ png_do_compose(png_row_infop row_info, p
 
                      if (r == png_ptr->trans_color.red &&
                          g == png_ptr->trans_color.green &&
                          b == png_ptr->trans_color.blue)
                      {
                         /* Background is already in screen gamma */
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
                      else
                      {
                         png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                         *sp = (png_byte)((v >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(v & 0xff);
@@ -3848,19 +3855,22 @@ png_do_compose(png_row_infop row_info, p
                          + *(sp + 5));
 
                      if (r == png_ptr->trans_color.red &&
                          g == png_ptr->trans_color.green &&
                          b == png_ptr->trans_color.blue)
                      {
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
                   }
                }
             }
             break;
          }
 
@@ -3933,17 +3943,18 @@ png_do_compose(png_row_infop row_info, p
                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
                         *sp = (png_byte)((v >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(v & 0xff);
                      }
 
                      else if (a == 0)
                      {
                         /* Background is already in screen gamma */
-                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                        *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                      }
 
                      else
                      {
                         png_uint_16 g, v, w;
 
                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
@@ -3963,17 +3974,18 @@ png_do_compose(png_row_infop row_info, p
                   sp = row;
                   for (i = 0; i < row_width; i++, sp += 4)
                   {
                      png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
                          + *(sp + 3));
 
                      if (a == 0)
                      {
-                        *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+                        *sp = (png_byte)((png_ptr->background.gray >> 8)
+                                & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
                      }
 
                      else if (a < 0xffff)
                      {
                         png_uint_16 g, v;
 
                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
@@ -4093,45 +4105,51 @@ png_do_compose(png_row_infop row_info, p
                         *(sp + 5) = (png_byte)(v & 0xff);
                      }
 
                      else if (a == 0)
                      {
                         /* Background is already in screen gamma */
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
                      else
                      {
                         png_uint_16 v, w;
 
                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
                         png_composite_16(w, v, a, png_ptr->background_1.red);
                         if (!optimize)
-                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)]
+                               [w >> 8];
                         *sp = (png_byte)((w >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(w & 0xff);
 
                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
                         png_composite_16(w, v, a, png_ptr->background_1.green);
                         if (!optimize)
-                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)]
+                               [w >> 8];
 
                         *(sp + 2) = (png_byte)((w >> 8) & 0xff);
                         *(sp + 3) = (png_byte)(w & 0xff);
 
                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
                         png_composite_16(w, v, a, png_ptr->background_1.blue);
                         if (!optimize)
-                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+                           w = gamma_16_from_1[((w&0xff) >> gamma_shift)]
+                               [w >> 8];
 
                         *(sp + 4) = (png_byte)((w >> 8) & 0xff);
                         *(sp + 5) = (png_byte)(w & 0xff);
                      }
                   }
                }
 
                else
@@ -4142,19 +4160,22 @@ png_do_compose(png_row_infop row_info, p
                   {
                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
                          << 8) + (png_uint_16)(*(sp + 7)));
 
                      if (a == 0)
                      {
                         *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
                         *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
-                        *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
-                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+                        *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+                                & 0xff);
+                        *(sp + 3) = (png_byte)(png_ptr->background.green
+                                & 0xff);
+                        *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+                                & 0xff);
                         *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
                      }
 
                      else if (a < 0xffff)
                      {
                         png_uint_16 v;
 
                         png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
--- a/media/libpng/pngrutil.c
+++ b/media/libpng/pngrutil.c
@@ -3879,17 +3879,17 @@ png_init_filter_functions_neon(png_struc
 #endif
 
    pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
 
    if (bpp == 3)
    {
       pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
       pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = 
+      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
          png_read_filter_row_paeth3_neon;
    }
 
    else if (bpp == 4)
    {
       pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
       pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
       pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
--- a/media/libpng/pngwtran.c
+++ b/media/libpng/pngwtran.c
@@ -1,13 +1,13 @@
 
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
- * Last changed in libpng 1.5.6 [November 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.13 [September 27, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
@@ -40,18 +40,30 @@ png_do_write_transformations(png_structp
                 /*  png_byte bit_depth;      bit depth of samples */
                 /*  png_byte channels;       number of channels (1-4) */
                 /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
              png_ptr->row_buf + 1);      /* start of pixel data for row */
 #endif
 
 #ifdef PNG_WRITE_FILLER_SUPPORTED
    if (png_ptr->transformations & PNG_FILLER)
-      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
-         !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
+   {
+      if (png_ptr->color_type & (PNG_COLOR_MASK_ALPHA|PNG_COLOR_MASK_PALETTE))
+      {
+         /* GA, RGBA or palette; in any of these cases libpng will not do the
+          * the correct thing (whatever that might be).
+          */
+         png_warning(png_ptr, "incorrect png_set_filler call ignored");
+         png_ptr->transformations &= ~PNG_FILLER;
+      }
+
+      else
+         png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+            !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
+   }
 #endif
 
 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
    if (png_ptr->transformations & PNG_PACKSWAP)
       png_do_packswap(row_info, png_ptr->row_buf + 1);
 #endif
 
 #ifdef PNG_WRITE_PACK_SUPPORTED
--- a/media/libpng/pngwutil.c
+++ b/media/libpng/pngwutil.c
@@ -1391,17 +1391,18 @@ png_write_tRNS(png_structp png_ptr, png_
    {
       if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
       {
          png_warning(png_ptr, "Invalid number of transparent colors specified");
          return;
       }
 
       /* Write the chunk out as it is */
-      png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
+      png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
+         (png_size_t)num_trans);
    }
 
    else if (color_type == PNG_COLOR_TYPE_GRAY)
    {
       /* One 16 bit value */
       if (tran->gray >= (1 << png_ptr->bit_depth))
       {
          png_warning(png_ptr,
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -1064,17 +1064,17 @@ public class GeckoAppShell
     }
 
     static String getExtensionFromMimeType(String aMimeType) {
         return MimeTypeMap.getSingleton().getExtensionFromMimeType(aMimeType);
     }
 
     static String getMimeTypeFromExtensions(String aFileExt) {
         MimeTypeMap mtm = MimeTypeMap.getSingleton();
-        StringTokenizer st = new StringTokenizer(aFileExt, "., ");
+        StringTokenizer st = new StringTokenizer(aFileExt, ".,; ");
         String type = null;
         String subType = null;
         while (st.hasMoreElements()) {
             String ext = st.nextToken();
             String mt = mtm.getMimeTypeFromExtension(ext);
             if (mt == null)
                 continue;
             int slash = mt.indexOf('/');
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -62,16 +62,17 @@ public class GeckoEvent {
     private static final int UNUSED3_EVENT = 23;
     private static final int ACTIVITY_RESUMING = 24;
     private static final int SCREENSHOT = 25;
     private static final int UNUSED2_EVENT = 26;
     private static final int SCREENORIENTATION_CHANGED = 27;
     private static final int COMPOSITOR_PAUSE = 28;
     private static final int COMPOSITOR_RESUME = 29;
     private static final int PAINT_LISTEN_START_EVENT = 30;
+    private static final int NATIVE_GESTURE_EVENT = 31;
 
     /**
      * These DOM_KEY_LOCATION constants mirror the DOM KeyboardEvent's constants.
      * @see https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent#Key_location_constants
      */
     private static final int DOM_KEY_LOCATION_STANDARD = 0;
     private static final int DOM_KEY_LOCATION_LEFT = 1;
     private static final int DOM_KEY_LOCATION_RIGHT = 2;
@@ -93,16 +94,20 @@ public class GeckoEvent {
     public static final int IME_RANGE_SELECTEDRAWTEXT = 3;
     public static final int IME_RANGE_CONVERTEDTEXT = 4;
     public static final int IME_RANGE_SELECTEDCONVERTEDTEXT = 5;
 
     public static final int IME_RANGE_UNDERLINE = 1;
     public static final int IME_RANGE_FORECOLOR = 2;
     public static final int IME_RANGE_BACKCOLOR = 4;
 
+    public static final int ACTION_MAGNIFY_START = 11;
+    public static final int ACTION_MAGNIFY = 12;
+    public static final int ACTION_MAGNIFY_END = 13;
+
     final public int mType;
     public int mAction;
     public long mTime;
     public Point[] mPoints;
     public int[] mPointIndicies;
     public int mPointerIndex; // index of the point that has changed
     public float[] mOrientations;
     public float[] mPressures;
@@ -255,16 +260,31 @@ public class GeckoEvent {
             case KeyEvent.KEYCODE_BUTTON_15:
             case KeyEvent.KEYCODE_BUTTON_16:
                 return true;
             default:
                 return false;
         }
     }
 
+    public static GeckoEvent createNativeGestureEvent(int action, PointF pt, double size) {
+        GeckoEvent event = new GeckoEvent(NATIVE_GESTURE_EVENT);
+        event.mAction = action;
+        event.mCount = 1;
+        event.mPoints = new Point[1];
+
+        PointF geckoPoint = new PointF(pt.x, pt.y);
+        geckoPoint = GeckoApp.mAppContext.getLayerView().convertViewPointToLayerPoint(geckoPoint);
+        event.mPoints[0] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y));
+
+        event.mX = size;
+        event.mTime = System.currentTimeMillis();
+        return event;
+    }
+
     public static GeckoEvent createMotionEvent(MotionEvent m) {
         GeckoEvent event = new GeckoEvent(MOTION_EVENT);
         event.initMotionEvent(m);
         return event;
     }
 
     private void initMotionEvent(MotionEvent m) {
         mAction = m.getAction();
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -467,16 +467,17 @@ RES_DRAWABLE_BASE = \
   res/drawable/ic_menu_bookmark_remove.png \
   res/drawable/ic_menu_desktop_mode_off.xml \
   res/drawable/ic_menu_desktop_mode_on.xml \
   res/drawable/ic_menu_forward.png \
   res/drawable/ic_menu_reload.png \
   res/drawable/ic_menu_save_as_pdf.png \
   res/drawable/ic_menu_share.png \
   res/drawable/ic_menu_quit.xml \
+  res/drawable/ic_status_logo.png \
   res/drawable/remote_tabs_off.png \
   res/drawable/remote_tabs_on.png \
   res/drawable/tab_new.png \
   res/drawable/tab_close.png \
   res/drawable/tab_thumbnail_default.png \
   res/drawable/tab_thumbnail_shadow.png \
   res/drawable/tabs_carat.png \
   res/drawable/address_bar_back_button.xml \
@@ -542,16 +543,17 @@ RES_DRAWABLE_HDPI = \
   res/drawable-hdpi/ic_awesomebar_search.png \
   res/drawable-hdpi/ic_awesomebar_star.png \
   res/drawable-hdpi/ic_menu_bookmark_add.png \
   res/drawable-hdpi/ic_menu_bookmark_remove.png \
   res/drawable-hdpi/ic_menu_forward.png \
   res/drawable-hdpi/ic_menu_reload.png \
   res/drawable-hdpi/ic_menu_save_as_pdf.png \
   res/drawable-hdpi/ic_menu_share.png \
+  res/drawable-hdpi/ic_status_logo.png \
   res/drawable-hdpi/remote_tabs_off.png \
   res/drawable-hdpi/remote_tabs_on.png \
   res/drawable-hdpi/tab_new.png \
   res/drawable-hdpi/tab_close.png \
   res/drawable-hdpi/tab_thumbnail_default.png \
   res/drawable-hdpi/tab_thumbnail_shadow.png \
   res/drawable-hdpi/tabs_carat.png \
   res/drawable-hdpi/address_bar_texture_port.png \
@@ -606,16 +608,17 @@ RES_DRAWABLE_XHDPI = \
   res/drawable-xhdpi/ic_awesomebar_search.png \
   res/drawable-xhdpi/ic_awesomebar_star.png \
   res/drawable-xhdpi/ic_menu_bookmark_add.png \
   res/drawable-xhdpi/ic_menu_bookmark_remove.png \
   res/drawable-xhdpi/ic_menu_forward.png \
   res/drawable-xhdpi/ic_menu_reload.png \
   res/drawable-xhdpi/ic_menu_save_as_pdf.png \
   res/drawable-xhdpi/ic_menu_share.png \
+  res/drawable-xhdpi/ic_status_logo.png \
   res/drawable-xhdpi/tab_new.png \
   res/drawable-xhdpi/tab_close.png \
   res/drawable-xhdpi/tab_thumbnail_default.png \
   res/drawable-xhdpi/tab_thumbnail_shadow.png \
   res/drawable-xhdpi/tabs_carat.png \
   res/drawable-xhdpi/doorhanger_arrow.png \
   res/drawable-xhdpi/doorhanger_bg.9.png \
   res/drawable-xhdpi/doorhanger_shadow_bg.9.png \
@@ -655,16 +658,17 @@ RES_DRAWABLE_MDPI_V11 = \
   res/drawable-mdpi-v11/ic_menu_find_in_page.png \
   res/drawable-mdpi-v11/ic_menu_forward.png \
   res/drawable-mdpi-v11/ic_menu_reload.png \
   res/drawable-mdpi-v11/ic_menu_save_as_pdf.png \
   res/drawable-mdpi-v11/ic_menu_settings.png \
   res/drawable-mdpi-v11/ic_menu_share.png \
   res/drawable-mdpi-v11/ic_menu_tools.png \
   res/drawable-mdpi-v11/ic_menu_quit.png \
+  res/drawable-mdpi-v11/ic_status_logo.png \
   res/drawable-mdpi-v11/menu.png \
   res/drawable-mdpi-v11/menu_panel_bg.9.png \
   res/drawable-mdpi-v11/menu_popup_bg.9.png \
   res/drawable-mdpi-v11/menu_popup_arrow.png \
   res/drawable-mdpi-v11/menu_item_check.png \
   res/drawable-mdpi-v11/menu_item_more.png \
   res/drawable-mdpi-v11/menu_item_uncheck.png \
   $(NULL)
@@ -684,16 +688,17 @@ RES_DRAWABLE_HDPI_V11 = \
   res/drawable-hdpi-v11/ic_menu_find_in_page.png \
   res/drawable-hdpi-v11/ic_menu_forward.png \
   res/drawable-hdpi-v11/ic_menu_reload.png \
   res/drawable-hdpi-v11/ic_menu_save_as_pdf.png \
   res/drawable-hdpi-v11/ic_menu_settings.png \
   res/drawable-hdpi-v11/ic_menu_share.png \
   res/drawable-hdpi-v11/ic_menu_tools.png \
   res/drawable-hdpi-v11/ic_menu_quit.png \
+  res/drawable-hdpi-v11/ic_status_logo.png \
   res/drawable-hdpi-v11/menu.png \
   res/drawable-hdpi-v11/menu_panel_bg.9.png \
   res/drawable-hdpi-v11/menu_popup_bg.9.png \
   res/drawable-hdpi-v11/menu_popup_arrow.png \
   res/drawable-hdpi-v11/menu_item_check.png \
   res/drawable-hdpi-v11/menu_item_more.png \
   res/drawable-hdpi-v11/menu_item_uncheck.png \
   $(NULL)
@@ -713,16 +718,17 @@ RES_DRAWABLE_XHDPI_V11 = \
   res/drawable-xhdpi-v11/ic_menu_find_in_page.png \
   res/drawable-xhdpi-v11/ic_menu_forward.png \
   res/drawable-xhdpi-v11/ic_menu_reload.png \
   res/drawable-xhdpi-v11/ic_menu_save_as_pdf.png \
   res/drawable-xhdpi-v11/ic_menu_settings.png \
   res/drawable-xhdpi-v11/ic_menu_share.png \
   res/drawable-xhdpi-v11/ic_menu_tools.png \
   res/drawable-xhdpi-v11/ic_menu_quit.png \
+  res/drawable-xhdpi-v11/ic_status_logo.png \
   res/drawable-xhdpi-v11/menu.png \
   res/drawable-xhdpi-v11/menu_panel_bg.9.png \
   res/drawable-xhdpi-v11/menu_popup_bg.9.png \
   res/drawable-xhdpi-v11/menu_popup_arrow.png \
   res/drawable-xhdpi-v11/menu_item_check.png \
   res/drawable-xhdpi-v11/menu_item_more.png \
   res/drawable-xhdpi-v11/menu_item_uncheck.png \
   $(NULL)
--- a/mobile/android/base/UpdateService.java
+++ b/mobile/android/base/UpdateService.java
@@ -203,17 +203,17 @@ public class UpdateService extends Inten
         
         int connectionType = netInfo.getType();
         if (!hasFlag(flags, UpdateServiceHelper.FLAG_FORCE_DOWNLOAD) &&
             connectionType != ConnectivityManager.TYPE_WIFI &&
             connectionType != ConnectivityManager.TYPE_ETHERNET) {
             Log.i(LOGTAG, "not connected via wifi or ethernet");
 
             // We aren't autodownloading here, so prompt to start the update
-            Notification notification = new Notification(R.drawable.icon, getResources().getString(R.string.updater_start_ticker), System.currentTimeMillis());
+            Notification notification = new Notification(R.drawable.ic_status_logo, null, System.currentTimeMillis());
 
             Intent notificationIntent = new Intent(UpdateServiceHelper.ACTION_CHECK_FOR_UPDATE);
             notificationIntent.setClass(this, UpdateService.class);
             notificationIntent.putExtra(UpdateServiceHelper.EXTRA_UPDATE_FLAGS_NAME, UpdateServiceHelper.FLAG_FORCE_DOWNLOAD);
 
             PendingIntent contentIntent = PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
             notification.flags = Notification.FLAG_AUTO_CANCEL;
 
@@ -233,17 +233,17 @@ public class UpdateService extends Inten
         Log.i(LOGTAG, "have update package at " + pkg);
 
         saveUpdateInfo(info);
 
         if (mApplyImmediately) {
             applyUpdate(pkg);
         } else {
             // Prompt to apply the update
-            Notification notification = new Notification(R.drawable.icon, getResources().getString(R.string.updater_apply_ticker), System.currentTimeMillis());
+            Notification notification = new Notification(R.drawable.ic_status_logo, null, System.currentTimeMillis());
 
             Intent notificationIntent = new Intent(UpdateServiceHelper.ACTION_APPLY_UPDATE);
             notificationIntent.setClass(this, UpdateService.class);
             notificationIntent.putExtra(UpdateServiceHelper.EXTRA_PACKAGE_PATH_NAME, pkg.getAbsolutePath());
 
             PendingIntent contentIntent = PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
             notification.flags = Notification.FLAG_AUTO_CANCEL;
 
@@ -331,43 +331,42 @@ public class UpdateService extends Inten
         }
     }
 
     private void showDownloadNotification() {
         showDownloadNotification(null);
     }
 
     private void showDownloadNotification(File downloadFile) {
-        Notification notification = new Notification(android.R.drawable.stat_sys_download, getResources().getString(R.string.updater_downloading_ticker), System.currentTimeMillis());
+        Notification notification = new Notification(android.R.drawable.stat_sys_download, null, System.currentTimeMillis());
 
         Intent notificationIntent = new Intent(UpdateServiceHelper.ACTION_APPLY_UPDATE);
         notificationIntent.setClass(this, UpdateService.class);
 
         if (downloadFile != null)
             notificationIntent.putExtra(UpdateServiceHelper.EXTRA_PACKAGE_PATH_NAME, downloadFile.getAbsolutePath());
 
         PendingIntent contentIntent = PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
         notification.setLatestEventInfo(this, getResources().getString(R.string.updater_downloading_title),
-                                        mApplyImmediately ? getResources().getString(R.string.updater_downloading_willapply) :
-                                            getResources().getString(R.string.updater_downloading_select),
+                                        mApplyImmediately ? "" : getResources().getString(R.string.updater_downloading_select),
                                         contentIntent);
         
         mNotificationManager.notify(NOTIFICATION_ID, notification);
     }
 
     private void showDownloadFailure() {
-        Notification notification = new Notification(android.R.drawable.stat_sys_warning, getResources().getString(R.string.updater_downloading_ticker_failed), System.currentTimeMillis());
+        Notification notification = new Notification(R.drawable.ic_status_logo, null, System.currentTimeMillis());
 
         Intent notificationIntent = new Intent(UpdateServiceHelper.ACTION_CHECK_FOR_UPDATE);
         notificationIntent.setClass(this, UpdateService.class);
 
         PendingIntent contentIntent = PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
-        notification.setLatestEventInfo(this, getResources().getString(R.string.updater_downloading_title),
+        notification.setLatestEventInfo(this, getResources().getString(R.string.updater_downloading_title_failed),
                                         getResources().getString(R.string.updater_downloading_retry),
                                         contentIntent);
         
         mNotificationManager.notify(NOTIFICATION_ID, notification);
     }
 
     private File downloadUpdatePackage(UpdateInfo info, boolean overwriteExisting) {
         File downloadFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), new File(info.url.getFile()).getName());
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -225,22 +225,18 @@ just addresses the organization to follo
                                            from Android">
 <!ENTITY bookmarkhistory_import_history "Importing history
                                          from Android">
 <!ENTITY bookmarkhistory_import_wait "Please wait...">
 
 <!ENTITY webapp_generic_name "App">
 
 <!-- Updater notifications -->
-<!ENTITY updater_start_title "&brandShortName;">
-<!ENTITY updater_start_ticker "&brandShortName; update available&#8230;">
-<!ENTITY updater_start_select "Select to download update.">
+<!ENTITY updater_start_title "Update available for &brandShortName;">
+<!ENTITY updater_start_select "Touch to download">
 
 <!ENTITY updater_downloading_title "Downloading &brandShortName;">
-<!ENTITY updater_downloading_ticker "Downloading &brandShortName; update&#8230;">
-<!ENTITY updater_downloading_ticker_failed "Failed to download &brandShortName; update&#8230;">
-<!ENTITY updater_downloading_select "Select to apply update when complete.">
-<!ENTITY updater_downloading_retry "Select to retry update download.">
-<!ENTITY updater_downloading_willapply "Waiting for download to complete.">
+<!ENTITY updater_downloading_title_failed "Download failed">
+<!ENTITY updater_downloading_select "Touch to apply update once downloaded">
+<!ENTITY updater_downloading_retry "Touch to retry">
 
-<!ENTITY updater_apply_title "&brandShortName;">
-<!ENTITY updater_apply_ticker "&brandShortName; update available&#8230;">
-<!ENTITY updater_apply_select "Select to apply downloaded update.">
+<!ENTITY updater_apply_title "Update available for &brandShortName;">
+<!ENTITY updater_apply_select "Touch to update">
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e003d1d29f02b0d699d945705caef282607f4c7b
GIT binary patch
literal 1704
zc%17D@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrIztFlS_jM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtBi9%9p
zdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tbhjOrj{fs
zROII56<bx<DuK<l0<uBE`br95B_-LmN)Sgy_y#CA=NF|anCcnpCL0(UDwvt+8Jd`y
znHlOR7#SEE=^Fr%nXaLUm8qGPk+}jCC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DRmzV36
z8|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQixgCnn{Wme?vO
z!Mu=L;Oh%FIIkEQP{1J5uShJ=H`FuG&&}0`sV*)FN=?JBx;Uh=AXPsowK%`DC>a<Z
zY05}e;nxaM2y~5=e^DkdQWA4q@{>z*Q}aqZU2K(rGI}YQDOPS4=5B_D<|YQ_Mh0dU
zhK3df7RDB?X2zD5rp6X7uFfzsu<5lhcX9@5G%zr6b}}?{HL`GZwQx4IaI-Kmb96Cu
zbc5;j%quQQ%u7y%>CJ@eHFLwO*UGslHL)bWC?r2W2bKZ?GV)9Ei!<^I6r6+26f}Gj
zlQZ)`0-B%*g1R-eD6=dz#jPkmR{<QtR+(5_;NomzYT;^WY~T#_xwD~(ql=@Xi=~sf
zv$><G5>#&rIiaQxbc{Y)a)Ai}(;$cmPy9d*Jo}{P0rN}|FmtGEp1X;Gf$5s3i(^Q|
zttT`5J+3&491l01c*NOd!W*%)Nlx`GDkdNJ+tj(4{M`~<+nubhDC#RZig)vs-rzW>
zFvaT0!Dh!YZmzA9xLRMxrv@(BsF1eA?dNOj4=sr^X5O#ff0uP3yL?%B+Pycw&+e)G
zd{1AUqv=N0q&qjXChy^}dVP@b0*jV|j7Zb|1TmjR@dOSVvGeP;^_&!&!19?fUhQDv
z!TKXbHg-$470=u^pLM!}-QTd)h8%HC`VZJ6n9Z7s0@%N06x%YtO|W^zCA;i=(g&~V
zN0}Fn)!dT0kiO=IX~6r-n@!)TKaJTS*>m}b_*TQW59~UOc~-L~w<W5pvc;+|b)U8`
zHlgj8HOsz0-hGYsvjS~nn&)ME<sV=-V856BHk{>{hQ03vuh~Vjk}sG%{_<wp9GSDr
zbAp!icS}iBI~w0$&vGzyPUqo?xMf|ld<~}#d(qC5F-zUL-)+c0t=62eX?kV=V}wb`
z{2kkTSU1f*v^Mx)p*HJ2gTTgO!5)dXt?N#Iop51>@q*TOdVMMm%s(==<TI}|li#I#
zXIarh&C~4sj;D;S@19!tD|i2anoD&Pm|PEu{`IxqbnsGmnz#KmBel@!xzSQD{Z3u{
zck`KZVVYC;+}1zYN763%KU<>pah3V4D=%$W`x=@0-|@Ns4xSx6U%=`s!w#M{omx?`
z<?p_o2~Fkh`KVC)ljWV2--9*I&sXaQ`7cR4!#m-*#V205y?V84UZ#{gm>=%n*Q_%4
zOr_T|ciYG3+gq5QKi$>2Q;K`RWI-O`DW85liHWc)3EkkU#r$S@m&^RcJw^?x$7EC!
zLyub-sIR#hBKk?{&mxZ)tsQfszp#Z%mP~l$YnIx@byn3+vz9;R#3DoC1*c5ff_Ij&
z&YZqvi=J_2s+GEXUh7|Z^XZzb{FhA9CU`CCk=Sx5aPgLB9bTvUQXZu?`-k{l@%VYM
zEWlG=?%t(~^B0DcUYWG1N_Cav|MSvY>X~>LY!-{~-w~V92&y|gUHx3vIVCg!02ASQ
A@&Et;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d5f16694f34217166e7c2e36f8d79b2e32080499
GIT binary patch
literal 1864
zc%17D@N?(olHy`uVBq!ia0vp^5<slR!3HGnu}7-{DajJoh?3y^w370~qErUQl>DSr
z1<%~X^wgl##FWaylc_cg49ppsArU1JzCKpT`MG+DAT@dwxdjX$U}IlVkeHmETB4AY
znx2_wtMq>NekFy>6kDZmQ(pt$0_W6>OpmIf)Zi+=kmRcDWXlvKdpiZ23M-%ixv3?I
z3Kh9IdBs*0wn|`gt$=Khu)dN4SV>8?trEmh5xxNm&iO^D3Z{C-y2%EHh6-k8dWI&Z
zW@d&u3PuKoM*0RoWTtCqVr6P(Wn``Z1xi5Mic-?7f?V97b^&>|N*N_31y=g{<>lpi
z<;HsXMd|v6mX?+vGmMOMfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZ_=!pRr6smX
zN-!_v7Wn$Y4bCfu1{5&J^eYkz^bPe4^mB9dVXBKuf>P7)t1b?yEJ)Q4N-fSWElLK)
zN18H{Rrs}n6armi<zJKujFiM2m;B_?+|;}hPZwJypp0HhW{Q=8p#?A$%}or<jSS2z
z3=J)u4NV+f935ROoy?uh9Zg|oVAE@4VB~D(=H_N#;%sJU=xSu)>T2O^YT;&KV&>>#
z=;#L1>zP+vl9-pA3e%g3(Cdm<ua$FAYGO%#QAmD%4lD%(WaO9R7iZ)bC^!e3DQNg6
zCTHe>1T;Yr1a)g_QD#|cid#{Bt^zoOtunE=z`%r%&mnqK$O$!lpkwsWk_$`-m<B;i
zc;W|g;MpfN5140)fSJSc^Uq3Po-6ZoaSW-r^=6u{M@XQ^@wv~X=N2wwY!yoqY0T^{
zy0}b9Loqs}Wom+(prYtbjjmHOW*EvIRaACb=(<FLMYk(Ryh(5>%f;h|j1IbXObAKY
z!Z9b`{cU-Uo1Fjq9@b08*xSFq+xvXZ|DXHL8yOo<-Z-Uy+QuX2jSl>0zaT9wJ+)n|
zJ9X*RthG(wQq$7%68AcNTe)Zc$BI9qS8OdUe;#=JvE|<>W|5n@X195#pZ<C{Z~OL_
zyY_XzeYtYwO2-$<_w^i3TfS~lzj5i(qcEwP7cP8Y_q-hD>+fGLcyP{~Ie9mQTPJ!v
z(fO@>!F;iToG4R`fwlGSIG(2OwI)(uciw&Xu9CsPVvgVQ00Rjf<`oPF-|qO&Q`Ov5
z{NbkHx7CMww%7g8JJmGdYun+6&T;F_EwXo%7+ssfv`Osr?;EFGKdOJ5%h#UFaBwz<
zt>C`a73<dN#YIO~bMm{T^cGf6{Qcnb&o!H0bbeUlzvnvRrDPNS(|bAim#h~1v2NmI
zYfjtNimS)cd#A17T7Ak%$I2_t&$0bu$#$-W8{3ml6a?}8yWDbrsjApjEe5CX9@Fg$
ze@8|}K0o_hP2b9AldIGzZB>((P6FLW-%Z+cD#Yf=y6YkD_++<hU+T>fnXhv3?aGQ*
zuU~&&qNw?tqbqmQ@n1VsEW=q3)baf4`}F)}k3-=UfjGgvo^hYbeToFakIvt4XV#1v
z5zQaMMg2c5)M@^}dgHXuyp4UG?5tX^3%05hip8EuXuh6wMfI+}T#uIe!gcSL=+B$9
zT=s(6taHx7dt2{qyq9&#QS<1ee6HIY{3LcI-doS~a1GA{qsdDX_uM}4yR@kP$9As@
zpQ+yi)EjHBRA_Ba*0?O3oEnoR)U?)3?pUea<~2to<n}qgs9W;*n1%e`mc=2A1}9zi
z`t+6`{9UOiw`PCdxy4VMwY<Gc7FZu$`gj6g+qn}S=5L-)5-tx8zO3-IE`{;%u|IY7
zG2$tbrz<YDinEI-tPU)4?5H$WF=GtN+41n%$&TyAmqX?SXoR?y_MEDn@JZ<UmR>gP
z(8*u5!VCL<p6X%T6q&cae(wXuBOg3WeV@-ZK5=8}rHzda3Ca(v*1WnC($ZMHVUO|M
zrSge8LK9AMG8`96-uZ-e=BH=Ro{4{+6)NhUwU>F9ds24Bwp<mH{vYCnA`B7huEg(g
t5BxVN>t%S@!%z3W8XYilIF`@I#&B`v9GmG9*(IR5&C}J-Wt~$(695EU<sSe5
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b49329e9b7a7aded47e731345a1c52e54f0a70c8
GIT binary patch
literal 1405
zc%17D@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+m@_g%B1$5BeXNr6bM+EIYV;~{3m8Da#=fE;F*!T6L?J0P
zJu}Z%>HY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBXRzL%CQ%e#R
zDspr3imfVamB8j&0ofp7eI*63l9Fs&C5WRUd;=7m^NUgyO!bU)lMM_F70k@^3{6bU
z%nWrDj0_Bo^bLT>OxMuF%GAut$Xo#mlz_GsrKDK}xwt{?0`hE?GD=Dctn~HE%ggo3
zjrH=2()A53EiFN27#ZmTRp=I1=9MH?=;jqG!%T2VElw`VEGWs$&r<;L6O-~wOKg>t
zU|z^A@b!fooL3ADC}5E3S0onb8|oS8=jQ6eR2P>7rKaImT^v$bkg6Y)TAW{6lnjiI
zG-V{K@M{Gr1iHq`zbF$JDTz5Q`N^fZsd*)yF1AWQ8NHOu6e~9ib2mdna}xt|BLg!F
zLqiJ#3u6mcGh<6jQ)3GkS7(?R*z_8j7@C<nI+`1pI6D~{x*A!yx>`7!TDV!5m^r!_
zI=aF1dgc|EB<3Zj!t`b$^qS$-Yvo*&npl!w6q28x14{t`8Tlpo#Toep3eLf13L3tN
z$(eZ|0ZmW@LEV~Klv$RV;#QQOs{jsRt4u5|aB(y-wQ#jGHgJae+}Y5?(Z$ix#nQ>#
z+1$}o392`RoKVvTIz}HYxxj>gX%NJOCw?FYo_$jDfO)0}m^p$tdEYTGFs}A=aSW-r
zb>*7B21}sKfseA5KZ+;kK22CEvQ<4?y<J!QslwaFTeccommF!FyhB6tslpQ_chyT?
zlej&Fv`<>Sal85F<or+ZSvAYkKF^wKp0B~a|JRj$Gr!+^e|C@k=2`1r&)eT4b6&oE
zHVb2q65r!O`HgL5A{x=s>pd1p&Hh!sWMi*|UF&ORzS<Pk6;1rA6$fNz32e!fInXpS
zMO@LGQ*D9^Z`6b13ezU&OQuFt%n}T3O5Oa3x34gFnk^TnqUR0GgKhI<-*+rx+&YQH
zap68gjk9`=mT{%eCCV$hxEID1KHIg!$9jT#WRCv}=jn%=dbsy%zn%7S+Tjz+MT!IZ
zqZj^*c^0>>+xL2}>(R1Li##-bzqR`6B_*%0(xV_#bNO2#6_wuW7yI3O9?2MAXt5IX
zo^89^GUM{yqugyROJ8ihQ*UgZaZTn(%5l+e8@oi7>3&~4?UU`fl=fI3qgTo%(XYZ1
zZWMixEPS<P@@bLv>aCS)9ykXrzp8oA|JfnEV<GLaZqN0t`gd5ab1k(fyjj`5M*i$k
z_x<9EQx;wLlVbOn%X-Gqg=;o`d;dSQhSPxIl}SuvyYRwVP=V;_>gTe~DWM4f1;+M+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4f7db2de30056f4db105919749852ddbb509b59
GIT binary patch
literal 2050
zc$}S8dsGu=7Eb~Jgz{KQ5zvKkSUK{_OhOWpKnjyrNqHJ5U{4YA7|2LoP6mm%S`aHB
zbwyDGkGpVisnS(M!B$!-p|wg7k*XD09|fyMX+>nQKG1e2E_n9r>G6;K&dhw@z2EP5
z@BQv~@0se1w0At+gWM?;il;nDq9AA3@w&N?-yGW0N^%M$q`5?<v4AL1;wS~t7*!}B
z*DDKA1*+7nTVq4xDHJCymX%B7rlttgMm<C6z%VR&6U8y&6D%gBx(Foz6<UZHgy4fO
zdqDux2*DgqDx7K(qgpJf6h|{l)3Vg1MQXkVOn4iJw+KiBdX!KC7QN137FdMfOS=Mc
z?NCD?@Df543Bmsam7AIYh>bW3a2PSsYM99cxLgL4&EayHQ2+~OvLKjzxY10ufWsBA
zVu85<lHPDlfj}XV&G{lFA*dw?lK_HBN=g_dF$^PK2r>D5zQYEK6-^?d&Fc(=(h_Yj
zht6A&pk_6WnF!2i035PXWh^FyAUJ;ny(u;Im0^Q<E>UF4AdAujF&QwV*F*DYGoe5W
zUXM0stuvvJ0yP_paW#1#1)=}t>h)9ykc>u<j$`DdD0LE}x>%1I2)RTEk~<6yrV+?^
zu`(tzmJP?UU@niz<iWfco|GHI=W}9s5~+CJ#_w@?u_7^>WWj8)h{=?)cv2}(%;Cv+
zY%U^UBC>g|++Ze@1~od*#Yirb&E#?rMEY8;K#ZeG!iZ-Xjk@^?$j}-IqgiV-0pd(9
zuq;)n#taTcxZ{H6VnuOmEvk{>Mm_K{!vgGgB9O?~9G;XP1B>TQE@rY334%!YqF8Y(
z!U5;Fn*S$j5E%^gKjkv7B5TmGd{z9U@Tz@K1KBe;*&LsQwj&gZGc1=NS(blZ+KVN<
zhxnao!nP(eMq4oD^7n(XHr94M5+gqxO6sWc`NkVjdfeJGkxbY7$d*e`WOYp!Lf_rC
zbm?1%!LL$8HK(HT>u>EmKl0&}+xDwHvv-CD&HSlvN*??*&OCI@Trf0v*N%7VLRZK}
zWhb1qhl<>j=yHI1s=_q9;AC0YRB#XVmvI#(voyNj`JVrc^{$g;zEjz9Cx0j3KWzfX
zh_<t-wM*J6&!vM^k2mG*o6Q>wv@8g+#twVZ5O(+Xi)&p@<2MpqKP%7w;$$MN;pesI
zHum0{8B=#qH@p856uD<X`<jW>F88eYGae1XL-Z9haoaBD3UiH?LSMJ8F<PYcP4QRP
ztzKSj0Uf&{;^ZT3&9r^=LTm8n$99atPpAWlRhuC@)%8H#Uj~9QCbMlpb?)2>M#PBA
zX`4%E;Bu#DZ^+>Es!rciORPv=ED)vLpUBD^seo&fN78(pP9}S8iR$m{^LL+mxW(So
zm$mv#k<a<M0Qbj{Gd*$dh3Wks-WYH7UG6K)ZN*f1)L%<2_2M@VjC^oV+A=PJ#TC@3
z`&ZP{f3AG!0=Zl+SIOxs%U4b`cy+wh^I7gYKH3AlvZsmN^=AUyX!jW#j%Bd?+bsu=
zER-~SYn2TE#r^b*=%<rn@5e8YeJkG3U1+w1+)n1Z7hl>NZ!Tq((Z_Yt+s1MURIUx%
zkHD>0<L^;x`T}m0t~%Z_y$53{UX-5cr_6pxE$Te3uy;@r49{s7{TBV!+V`Siy=1s!
zaM4F$!|y_kc9EA&)_b8g@JRR**Dcqby&2rv$>(-aTJ`BGUoWL^Ry?>{n>NZ>^RYy|
zUHkpF+KU=%emTqQZyvUpG2f7%cR73P!fpooEc-6N<GBJtzm5*80{{55zR>Dn3qJcv
z<3(O&l=H&2&jWJ$QlR2(PJt^2;G7LZXFuARxLq}w>1ikv)Uj$(@aCUr`d!_<KL(%D
z-F)I!5dP!=t*)@i>Roq^&1JXyY4=}=S|q$Zz0J=}(>zLh#HJ;5>bg>v(8p{WVDH6#
z2Sf9l2RWDR1?%^FYqLE&wbl?5?YYa*=0@6V+t_TBy%EY_AR6<YaK)<c%3y_Rw+LJY
z3c)XZ$G84EB&+^_+LYiH(Wmz)w$~VR_b>aLIM9dth_7zz0|IZA{cC4&TGz3->n-7k
zT7EPAeJ@$WC9|Jy;plGDd2>XiO|Eb{9FUhi)c>hp{gy9wr~eoZm5MU&1_`?D_pc#D
zQ^5~F<j|1Y+KIPS1GF3$o4&pr-?1rssQSnS9rpO>bZg7NKlUktr*{0b_~@rK11mSW
zpZGg+FD*l4H&x(+tNrTrcSfIi_c&?GL(YYdBv-2<4|`4|dLHa}6k>a~+RN$M$jPH!
z+D5NC7xs4l;acm*$18@z1fBuDfe(K>Je^)frJUHQ@_*)fX{+O}ESIK9+C{52{Trf|
B9&Z2u
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c8005425416af3def78ac9cbaff0d17d602ce1d4
GIT binary patch
literal 2049
zc$|Gz3se(V8Xf{t5D_1MfVz(1QB=qa2rv=|1R}2h4JpNng^&y+g*==YAkY?Ed5OiU
za4J$>#VsgcVTDq82nK|TwLID)C@Lu^APOf13|)6!+=+_2XV0Pc-nsYw|M|ZE{`bG%
zIg=L_a=>`K)p`H`j060Ax%dj=AI(4?pBcitLVU5r{35Y%Ssa$aM_|BPD2s)`00}=H
z=E8ho>XDnU2LR~Wh<TA%BqtaW$Rs4b7DG}<<bbw$cq!z3K?00{v2eUt${?!SuMt79
zkU{*wg+t-US+Gd#pN7EUX(2p8T7tk`Nc8dqJrocgKmucYP$5Z_qL6|?d=(eM_gXiZ
z2)=?~2@K-vq#`+CAWMe8pbN>#Q9z+mK{}m8b#|fCsSY5GLZy)@_@Fydogo)GL~{k-
zG$MW)B8-E$zU((=;TD4^!Z0~RCa0vNkW!pTG9;c%b$55y#-Pz0afBn9D#iE;M=5H(
z8o?Jv1&COViDgnyYx84eNf?7jT)l!s{x+->eN!g9U}ObfPNtG5<o^M3IDZb6NZz7R
zj0?y8IU41q%3(4WMrBEe0DrhRYb{w0u@IP#$q=4QmbhBQFp&(Cp(2?aWQEf~dk$Y9
zmTDb)UNJZvC_sv0e5n8q@MREj4@oQ*LNp4E<w~K@Db6f9mFh=x^Ye3Kxwx_2oax@a
zRB!ew*H<P;lE6}Il`H%&*L6*<Rt&G%Fd|Ndg=|D70bgAj60e<$^V+$*<_g!&#br${
z8Bd1%e^0&Y!u6xwz7;NRyp=vI#r2Nh!Y<klT>t<*G{D!Jrx=?%_lYRvh{cVRfr0V%
znpRVGmIx^es`ry-h~mEW7sGY|eO0ahu8jCc=6TbTHs|e&`wRp@1s22rDYd`KyuG8n
zvtiIF{;AtQstOH$KEu#F+pku?NFQAKtp3`}AA5fmInQQz1`?QfSH9H$+RV(%{iD)?
zf<}9H_tc!)TFZQvncr+CK{8b2Z?kBXHZn4j{7$WW16ZGDYWql&=4$O>(#3M<yftLP
zd}x6lEEygjUumhTs<MErwjIqj$`bHK71=7a>eT7Z#X}?AFG$byBr0Zfv3}9mE-S<1
zc|)S{8~^&W(|RuY-th2uq_ckMO-HN6Xk?TfLHDmp%k;t9>#opUUDY|uJ-7XTt={dX
zdbn`Ol+qRR_Z>ky5+#xjg8I<3rk4MZmv#0@oaS?OVhbtmQeB-<p4=k7X_~0gzpE27
z*dcc-RSgYM)&+feYex*7@W?LWF8q`LI21M;wEQrg-Q3))Yn;9@$EPw-?-Zd=$08#?
z-q1N++2*0Aih0TGd*?J!5uBB=yo;oa`V|9>HZA*CN0xq3QD<R0$)YfFL$9>-HL{r=
zy~uUrvmXUV?Ythij=fD8ZD}*I$>%pck;78QGpfy!DC0io3*D9N$3~vkd^H>Ze3;!G
zo)7exoKb98nDC?z=nWg}W?tyMm#O@??zi5ZB@pn~Ds-mf%H}Gw%cMe!8f61H8^DO;
ze|doPnqU1PDZec)x75^jiIr2D+_=%Z;&^soxK82NdC^t>i9QUqQ_gvIwG=OuXHK0L
zW&xzaJG7&V-a03bMozL5ernw{_GJ3%&rN-a6Umccv;(F4<gy64Ib}FT)H(1^N7wl!
zr)%M1*=6#|?!(GQYMr^H?fVLH=8VoAw!Toq^XboH^BV47V=PU)d=RLQdf704Df?#2
zbFa~x(01;n={>w?J!a-sNBfGI-yhDY5--;38cf~})0v(Vm+03*KUH%(f9adrCn}l(
zSXSVV$FsNGJ+AEHjv7<nyMO17+bOjx=LWhFXuK2!zI%Zk^JUwU31`Q9-9;|Hw>s9q
zE9~6wj8E^0sPtx+nE~&EsdoL>ReI;red^CJn<$@oi3(0G+xD$|J?k|<h-t_a)px<U
z#s}tgm&d<96k0CJ>#D1-+g;gMCcL~A@U}13w8xH&M>8fZj-iEzPdKS(p?t;j#36@>
z-29-9{o&!^e=9w)?U6sdB&rkTcFrfNV@uy1g%sxI=E=<}57jqG$W~oSS{9+P!31DC
zrR{Ludt0N?%r4ei26IFID9~N3lLDLe7fX$-k?9mVvvv<HDDUyk2NxAo!~TS!PiYaK
ztQ<Hb715Tr2=Ber?A$a(I#MnKCiz!O&Io%w!vb$5t*=;qTrY2}eb2UOzRhfZkL|H@
z3y5pBSI>-*pgHLBV&{qegG1a_leYeilVaVkf^1(rnMOW-Upi=Xb3X54h3&z8qfV{W
zx5RtRHhc0n>ve4Xc0u!bkC%-h@VbYTR}eM;!qM`s(Ai0A?N2$tFT}UrC+66H03>ff
AX8-^I
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..835fc92907274d739d55c4e41e41fdd176f84ef3
GIT binary patch
literal 1533
zc%17D@N?(olHy`uVBq!ia0vp^0zfRu!3HEP{;XRG;*_{XlmzFem6RtIr7}3C<R_&n
zc;+Uirv{}arc@T5OtoQPV9v-4i71Ki^|4CM&(%u=snM&*Enolv8~cia#N_PM5{0DH
z^vpb4rT4q{D=B2A*eZpa`WpBaIHzW0dQ=sq23ProBv)l8Tc#-4+bP&oSOE>lO)W`O
zsL0L9E4HezRRWu91!RMS^_3LBN=mYAl^~9a@C{IK&M!(;Fx4~GO*SwzR4_BsGc++Z
zGc(jtFfuSS(l-DiGhIUyD^oKoBXb2PPy*Ukl#*r@<l+Xk3&^uo$|xx*u+rBrFE7_C
zH`dE9O4m2Ew6p}7VPvEWRH0j3nOBlnp_^B%3^TzcwK%ybv!En1KTiR~PfW@$EwNQn
zf_Wjgz}FXUa9%MqpnyT9Uy)d#Z>VRWpPQ=>Q(asVl$wTLb#X{#L8^XGYH@yPQ8F+-
z(v*>`!mkyi5a=2!|DsG_q$K9J<R_QrrskD+y4WfKW%N=qQ>+XOEr6kDZen0=WMF1t
zXlUVVXyWMN=;&hUWbSP4XbLj}n_hD_7dJ;^0}BHaXA?t1S0f8oR|{uT3pWcBGe;Lg
zM>m*W&%EN2#JuEGnBGi;UUR&9t(=Qe6HD@oLh|!-U@0IVBfliSI3vG6!8zDWLBlsO
zIWrF=pb3f~s9RHuGRsm^+=}vZ6~G~Em5Id#gnbUtn?g>g=>r|3kCt3uLclZ#V!{(Y
zkOR*?sd>OWQv}Q$CT=I@FfcG_d%8G=RNQ(q#n&SwP~`aYyE{KWix#-#>zeTHj>fJo
zgN(TfK`ty4n{Km+?-CH5Io12_4xN|`PDd?{r-z)H7Bod2-C+=rBdPWI@5f{JCGR(X
zpZ7RREN@Ri#q)dB=YIY_f4tUhZ5X%7=8y#^OTRLfXifbj!_s_kUx9_q(yjZ_CERAu
z30(evs#ogn0F5(I)3!cORB$a(5$e=Amb6j-h1<r6m~&~Hn@<S*niRB3f1<|{Rg1c1
zj~A<Q`DI_t`pVA!w8qY!tNUEh&Od#dx7=A=&ro~I<m~i|8DB~@M5InWE$ZL#KRBJ?
zuDZ*-;~S^Hm-(HjvHb2EmxNDk3A2}6V|-zrq%Jx;?9-`EMicoB?_KyCw<tOOb!DzR
zGjFa~gPit@J(G0qc(Cj|`PBH!r1`7~^@-n4Z`-|gq3wkXDa|;0%Xe`vb_d1Q<aO}x
zYrf@JzIK%e$CSHnwd`N@icb6Obay`a<#t2OsmfUPrSgw!zqJ=7%w6BG_J6R#-!D&B
zuJ~}h!lrJ5kDBh6^DL4@?=qh*S^RkSQm>_#qU#stSU$`%oqV$7@;=tx8L}7ly}xnc
zlB}vT(^TR4#s{_UOU~omxBq7LE>oXu`(1B6z6LD5GGm{3%(~t8J9s8@9Q^L+r||aM
z?iJDk74BSX-vr)e$Xynw<s?11?7QU3wHH^m&pYliPm^zcb487(ugvpM3Hz@$YUz%d
zt&F#pU3z@U?!x;MUxdDJJhpvjulU~9cK<(hGx-NT4U7y+u6$W8*0jq8R3Ll0`njxg
HN@xNAXV5|O
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -212,23 +212,19 @@
   <string name="bookmarkhistory_import_bookmarks">&bookmarkhistory_import_bookmarks;</string>
   <string name="bookmarkhistory_import_history">&bookmarkhistory_import_history;</string>
   <string name="bookmarkhistory_import_wait">&bookmarkhistory_import_wait;</string>
 
   <string name="webapp_generic_name">&webapp_generic_name;</string>
 
   <!-- Updater notifications -->
   <string name="updater_start_title">&updater_start_title;</string>
-  <string name="updater_start_ticker">&updater_start_ticker;</string>
   <string name="updater_start_select">&updater_start_select;</string>
 
   <string name="updater_downloading_title">&updater_downloading_title;</string>
-  <string name="updater_downloading_ticker">&updater_downloading_ticker;</string>
-  <string name="updater_downloading_ticker_failed">&updater_downloading_ticker_failed;</string>
+  <string name="updater_downloading_title_failed">&updater_downloading_title_failed;</string>
   <string name="updater_downloading_select">&updater_downloading_select;</string>
   <string name="updater_downloading_retry">&updater_downloading_retry;</string>
-  <string name="updater_downloading_willapply">&updater_downloading_willapply;</string>
   
   <string name="updater_apply_title">&updater_apply_title;</string>
-  <string name="updater_apply_ticker">&updater_apply_ticker;</string>
   <string name="updater_apply_select">&updater_apply_select;</string>
 
 </resources>
--- a/mobile/android/base/ui/PanZoomController.java
+++ b/mobile/android/base/ui/PanZoomController.java
@@ -865,16 +865,18 @@ public class PanZoomController
 
         if (!mTarget.getZoomConstraints().getAllowZoom())
             return false;
 
         setState(PanZoomState.PINCHING);
         mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
         cancelTouch();
 
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY_START, mLastZoomFocus, getMetrics().zoomFactor));
+
         return true;
     }
 
     @Override
     public boolean onScale(SimpleScaleGestureDetector detector) {
         if (GeckoApp.mAppContext == null || GeckoApp.mAppContext.mDOMFullScreen)
             return false;
 
@@ -933,29 +935,36 @@ public class PanZoomController
             scrollBy(new PointF(mLastZoomFocus.x - detector.getFocusX(),
                     mLastZoomFocus.y - detector.getFocusY()));
             PointF focus = new PointF(detector.getFocusX(), detector.getFocusY());
             scaleWithFocus(newZoomFactor, focus);
         }
 
         mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY());
 
+        GeckoEvent event = GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY, mLastZoomFocus, getMetrics().zoomFactor);
+        GeckoAppShell.sendEventToGecko(event);
+
         return true;
     }
 
     @Override
     public void onScaleEnd(SimpleScaleGestureDetector detector) {
         if (mState == PanZoomState.ANIMATED_ZOOM)
             return;
 
         // switch back to the touching state
         startTouch(detector.getFocusX(), detector.getFocusY(), detector.getEventTime());
 
         // Force a viewport synchronisation
         mTarget.setForceRedraw();
+
+        PointF point = new PointF(detector.getFocusX(), detector.getFocusY());
+        GeckoEvent event = GeckoEvent.createNativeGestureEvent(GeckoEvent.ACTION_MAGNIFY_END, point, getMetrics().zoomFactor);
+        GeckoAppShell.sendEventToGecko(event);
     }
 
     /**
      * Scales the viewport, keeping the given focus point in the same place before and after the
      * scale operation. You must hold the monitor while calling this.
      */
     private void scaleWithFocus(float zoomFactor, PointF focus) {
         ViewportMetrics viewportMetrics = getMutableMetrics();
--- a/mobile/android/locales/en-US/chrome/about.dtd
+++ b/mobile/android/locales/en-US/chrome/about.dtd
@@ -1,8 +1,11 @@
+<!-- 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 aboutPage.title                        "About &brandShortName;">
 <!ENTITY aboutPage.warningVersion               "&brandShortName; is experimental and may be unstable.">
 <!ENTITY aboutPage.telemetryStart               " It automatically sends information about performance, hardware, usage and customizations back to ">
 <!ENTITY aboutPage.telemetryMozillaLink         "&vendorShortName;">
 <!ENTITY aboutPage.telemetryEnd                 " to help make &brandShortName; better.">
 <!ENTITY aboutPage.checkForUpdates.link         "Check for Updates »">
 <!ENTITY aboutPage.checkForUpdates.checking     "Looking for updates…">
 <!ENTITY aboutPage.checkForUpdates.none         "No updates available">
--- a/mobile/android/locales/en-US/defines.inc
+++ b/mobile/android/locales/en-US/defines.inc
@@ -1,8 +1,11 @@
+# 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/.
 #filter emptyLines
 
 #define MOZ_LANGPACK_CREATOR mozilla.org
 
 # If non-English locales wish to credit multiple contributors, uncomment this
 # variable definition and use the format specified.
 # #define MOZ_LANGPACK_CONTRIBUTORS <em:contributor>Joe Solon</em:contributor> <em:contributor>Suzy Solon</em:contributor>
 
--- a/mobile/locales/en-US/profile/bookmarks.inc
+++ b/mobile/locales/en-US/profile/bookmarks.inc
@@ -1,8 +1,11 @@
+# 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/.
 #filter emptyLines
 
 # LOCALIZATION NOTE: The 'en-US' strings in the URLs will be replaced with
 # your locale code, and link to your translated pages as soon as they're 
 # live.
 
 # LOCALIZATION NOTE: Some of these URLs are currently 404s, but should be coming
 # online shortly.
--- a/mobile/xul/locales/en-US/chrome/about.dtd
+++ b/mobile/xul/locales/en-US/chrome/about.dtd
@@ -1,8 +1,11 @@
+<!-- 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 aboutPage.title                        "About &brandShortName;">
 <!ENTITY aboutPage.warningVersion               "&brandShortName; is experimental and may be unstable.">
 <!ENTITY aboutPage.telemetryStart               " It automatically sends information about performance, hardware, usage and customizations back to ">
 <!ENTITY aboutPage.telemetryMozillaLink         "&vendorShortName;">
 <!ENTITY aboutPage.telemetryEnd                 " to help make &brandShortName; better.">
 <!ENTITY aboutPage.faq.label                    "FAQ">
 <!ENTITY aboutPage.support.label                "Support">
 <!ENTITY aboutPage.privacyPolicy.label          "Privacy Policy">
--- a/mobile/xul/locales/en-US/defines.inc
+++ b/mobile/xul/locales/en-US/defines.inc
@@ -1,8 +1,11 @@
+# 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/.
 #filter emptyLines
 
 #define MOZ_LANGPACK_CREATOR mozilla.org
 
 # If non-English locales wish to credit multiple contributors, uncomment this
 # variable definition and use the format specified.
 # #define MOZ_LANGPACK_CONTRIBUTORS <em:contributor>Joe Solon</em:contributor> <em:contributor>Suzy Solon</em:contributor>
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1009,16 +1009,17 @@ pref("network.IDN_show_punycode", false)
 // words, all IDNs will be shown in punycode if "network.IDN_show_punycode"
 // is true.
 
 // ccTLDs
 pref("network.IDN.whitelist.ac", true);
 pref("network.IDN.whitelist.ar", true);
 pref("network.IDN.whitelist.at", true);
 pref("network.IDN.whitelist.br", true);
+pref("network.IDN.whitelist.ca", true);
 pref("network.IDN.whitelist.ch", true);
 pref("network.IDN.whitelist.cl", true);
 pref("network.IDN.whitelist.cn", true);
 pref("network.IDN.whitelist.de", true);
 pref("network.IDN.whitelist.dk", true);
 pref("network.IDN.whitelist.ee", true);
 pref("network.IDN.whitelist.es", true);
 pref("network.IDN.whitelist.fi", true);
--- a/modules/libpref/test/unit_ipc/test_user_default_prefs.js
+++ b/modules/libpref/test/unit_ipc/test_user_default_prefs.js
@@ -23,17 +23,17 @@ function check_child_pref_info_eq(contin
         });
 }
 
 function run_test() {
     // We finish in clean_up()
     do_test_pending();
 
     try {
-        if (pb.getCharPref('dom.ipc.processPrelauch.enabled')) {
+        if (pb.getCharPref('dom.ipc.processPrelaunch.enabled')) {
             dump('WARNING: Content process may already have launched, so this test may not be meaningful.');
         }
     } catch(e) { }
 
     initialValue = pb.getCharPref(kPrefName);
 
     test_user_setting();
 }
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -471,27 +471,40 @@ SpecialPowersAPI.prototype = {
     var crashDumpFiles = this._sendSyncMessage("SPProcessCrashService", message)[0];
     crashDumpFiles.forEach(function(aFilename) {
       self._unexpectedCrashDumpFiles[aFilename] = true;
     });
     return crashDumpFiles;
   },
 
   /*
-   * Take in a list of prefs and put the original value on the _prefEnvUndoStack so we can undo
-   * preferences that we set.  Note, that this is a stack of values to revert to, not
-   * what we have set.
+   * Take in a list of pref changes to make, and invoke |callback| once those
+   * changes have taken effect.  When the test finishes, these changes are
+   * reverted.
+   *
+   * |inPrefs| must be an object with up to two properties: "set" and "clear".
+   * pushPrefEnv will set prefs as indicated in |inPrefs.set| and will unset
+   * the prefs indicated in |inPrefs.clear|.
+   *
+   * For example, you might pass |inPrefs| as:
    *
-   * prefs: {set|clear: [[pref, value], [pref, value, Iid], ...], set|clear: [[pref, value], ...], ...}
-   * ex: {'set': [['foo.bar', 2], ['browser.magic', '0xfeedface']], 'clear': [['bad.pref']] }
+   *  inPrefs = {'set': [['foo.bar', 2], ['magic.pref', 'baz']],
+   *             'clear': [['clear.this'], ['also.this']] };
+   *
+   * Notice that |set| and |clear| are both an array of arrays.  In |set|, each
+   * of the inner arrays must have the form [pref_name, value] or [pref_name,
+   * value, iid].  (The latter form is used for prefs with "complex" values.)
    *
-   * In the scenario where our prefs specify the same pref more than once, we do not guarantee
-   * the behavior.  
+   * In |clear|, each inner array should have the form [pref_name].
    *
-   * If a preference is not changing a value, we will ignore it.
+   * If you set the same pref more than once (or both set and clear a pref),
+   * the behavior of this method is undefined.
+   *
+   * (Implementation note: _prefEnvUndoStack is a stack of values to revert to,
+   * not values which have been set!)
    *
    * TODO: complex values for original cleanup?
    *
    */
   pushPrefEnv: function(inPrefs, callback) {
     var prefs = Components.classes["@mozilla.org/preferences-service;1"].
                            getService(Components.interfaces.nsIPrefBranch);
 
--- a/testing/xpcshell/xpcshell.ini
+++ b/testing/xpcshell/xpcshell.ini
@@ -120,16 +120,17 @@ skip-if = os == "win" || os == "mac" || 
 [include:content/base/test/unit_ipc/xpcshell.ini]
 [include:chrome/test/unit_ipc/xpcshell.ini]
 [include:extensions/cookie/test/unit_ipc/xpcshell.ini]
 [include:ipc/testshell/tests/xpcshell.ini]
 [include:modules/libpref/test/unit_ipc/xpcshell.ini]
 [include:netwerk/test/unit_ipc/xpcshell.ini]
 [include:netwerk/cookie/test/unit_ipc/xpcshell.ini]
 [include:toolkit/components/contentprefs/tests/unit_ipc/xpcshell.ini]
+[include:toolkit/addon-sdk/test/unit/xpcshell.ini]
 [include:uriloader/exthandler/tests/unit_ipc/xpcshell.ini]
 
 [include:modules/libmar/tests/unit/xpcshell.ini]
 skip-if = os == "android"
 
 [include:b2g/components/test/unit/xpcshell.ini]
 
 [include:tools/profiler/tests/xpcshell.ini]
--- a/toolkit/addon-sdk/Makefile.in
+++ b/toolkit/addon-sdk/Makefile.in
@@ -15,9 +15,11 @@ DIRS += \
   $(NULL)
 
 JS_MODULES_PATH := $(FINAL_TARGET)/modules/commonjs
 
 EXTRA_JS_MODULES := \
   loader.js \
   $(NULL)
 
+TEST_DIRS += test
+
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/addon-sdk/test/Makefile.in
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH            = @DEPTH@
+topsrcdir        = @top_srcdir@
+srcdir           = @srcdir@
+VPATH            = @srcdir@
+relativesrcdir   = @relativesrcdir@
+
+MODULE           = test_addon_sdk
+XPCSHELL_TESTS = unit
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/addon-sdk/test/unit/head.js
@@ -0,0 +1,74 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+
+Components.utils.import("resource://gre/modules/commonjs/promise/core.js");
+
+let run_promise_tests = function run_promise_tests(tests, cb) {
+  let timer = Components.classes["@mozilla.org/timer;1"]
+     .createInstance(Components.interfaces.nsITimer);
+  let loop = function loop(index) {
+    if (index >= tests.length) {
+      if (cb) {
+        cb.call();
+      }
+      return;
+    }
+    do_print("Launching test " + (index + 1) + "/" + tests.length);
+    let test = tests[index];
+    // Execute from an empty stack
+    let next = function next() {
+      do_print("Test " + (index + 1) + "/" + tests.length + " complete");
+      do_execute_soon(function() {
+        loop(index + 1);
+      });
+    };
+    let result = test();
+    result.then(next, next);
+  };
+  return loop(0);
+};
+
+let make_promise_test = function(test) {
+  return function runtest() {
+    do_print("Test starting: " + test);
+    try {
+      let result = test();
+      if (result && "promise" in result) {
+        result = result.promise;
+      }
+      if (!result || !("then" in result)) {
+        let exn;
+        try {
+          do_throw("Test " + test + " did not return a promise: " + result);
+        } catch (x) {
+          exn = x;
+        }
+        return Promise.reject(exn);
+      }
+      // The test returns a promise
+      result = result.then(
+        // Test complete
+        function onResolve() {
+          do_print("Test complete: " + test);
+        },
+        // The test failed with an unexpected error
+        function onReject(err) {
+          let detail;
+          if (err && typeof err == "object" && "stack" in err) {
+            detail = err.stack;
+          } else {
+            detail = "(no stack)";
+          }
+          do_throw("Test " + test + " rejected with the following reason: "
+              + err + detail);
+      });
+      return result;
+    } catch (x) {
+      // The test failed because of an error outside of a promise
+      do_throw("Error in body of test " + test + ": " + x + " at " + x.stack);
+      return Promise.reject();
+    }
+  };
+};
+
new file mode 100644
--- /dev/null
+++ b/toolkit/addon-sdk/test/unit/test_promise.js
@@ -0,0 +1,396 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let tests = [];
+
+// Utility function to observe an failures in a promise
+// This function is useful if the promise itself is
+// not returned.
+let observe_failures = function observe_failures(promise) {
+  promise.then(null, function onReject(reason) {
+    test.do_throw("Observed failure in test " + test + ": " + reason);
+  });
+};
+
+// Test that all observers are notified
+tests.push(make_promise_test(
+  function notification(test) {
+    // The size of the test
+    const SIZE = 10;
+    const RESULT = "this is an arbitrary value";
+
+    // Number of observers that yet need to be notified
+    let expected = SIZE;
+
+    // |true| once an observer has been notified
+    let notified = [];
+
+    // The promise observed
+    let source = Promise.defer();
+    let result = Promise.defer();
+
+    let install_observer = function install_observer(i) {
+      observe_failures(source.promise.then(
+        function onSuccess(value) {
+          do_check_true(!notified[i], "Ensuring that observer is notified at most once");
+          notified[i] = true;
+
+          do_check_eq(value, RESULT, "Ensuring that the observed value is correct");
+          if (--expected == 0) {
+            result.resolve();
+          }
+        }));
+    };
+
+    // Install a number of observers before resolving
+    let i;
+    for (i = 0; i < SIZE/2; ++i) {
+      install_observer(i);
+    }
+
+    source.resolve(RESULT);
+
+    // Install remaining observers
+    for(;i < SIZE; ++i) {
+      install_observer(i);
+    }
+
+    return result;
+  }));
+
+// Test that all observers are notified at most once, even if source
+// is resolved/rejected several times
+tests.push(make_promise_test(
+  function notification_once(test) {
+    // The size of the test
+    const SIZE = 10;
+    const RESULT = "this is an arbitrary value";
+
+    // Number of observers that yet need to be notified
+    let expected = SIZE;
+
+    // |true| once an observer has been notified
+    let notified = [];
+
+    // The promise observed
+    let observed = Promise.defer();
+    let result = Promise.defer();
+
+    let install_observer = function install_observer(i) {
+      observe_failures(observed.promise.then(
+        function onSuccess(value) {
+          do_check_true(!notified[i], "Ensuring that observer is notified at most once");
+          notified[i] = true;
+
+          do_check_eq(value, RESULT, "Ensuring that the observed value is correct");
+          if (--expected == 0) {
+            result.resolve();
+          }
+        }));
+    };
+
+    // Install a number of observers before resolving
+    let i;
+    for (i = 0; i < SIZE/2; ++i) {
+      install_observer(i);
+    }
+
+    observed.resolve(RESULT);
+
+    // Install remaining observers
+    for(;i < SIZE; ++i) {
+      install_observer(i);
+    }
+
+    // Resolve some more
+    for (i = 0; i < 10; ++i) {
+      observed.resolve(RESULT);
+      observed.reject();
+    }
+
+    return result;
+  }));
+
+// Test that throwing an exception from a onResolve listener
+// does not prevent other observers from receiving the notification
+// of success.
+tests.push(
+  make_promise_test(function exceptions_do_not_stop_notifications(test)  {
+    let source = Promise.defer();
+
+    let exception_thrown = false;
+    let exception_content = new Error("Boom!");
+
+    let observer_1 = source.promise.then(
+      function onResolve() {
+        exception_thrown = true;
+        throw exception_content;
+      });
+
+    let observer_2 = source.promise.then(
+      function onResolve() {
+        do_check_true(exception_thrown, "Second observer called after first observer has thrown");
+      }
+    );
+
+    let result = observer_1.then(
+      function onResolve() {
+        do_throw("observer_1 should not have resolved");
+      },
+      function onReject(reason) {
+        do_check_true(reason == exception_content, "Obtained correct rejection");
+      }
+    );
+
+    source.resolve();
+    return result;
+  }
+));
+
+// Test that, once a promise is resolved, further resolve/reject
+// are ignored.
+tests.push(
+  make_promise_test(function subsequent_resolves_are_ignored(test) {
+    let deferred = Promise.defer();
+    deferred.resolve(1);
+    deferred.resolve(2);
+    deferred.reject(3);
+
+    let result = deferred.promise.then(
+      function onResolve(value) {
+        do_check_eq(value, 1, "Resolution chose the first value");
+      },
+      function onReject(reason) {
+        do_throw("Obtained a rejection while the promise was already resolved");
+      }
+    );
+
+    return result;
+  }));
+
+// Test that, once a promise is rejected, further resolve/reject
+// are ignored.
+tests.push(
+  make_promise_test(function subsequent_rejects_are_ignored(test) {
+    let deferred = Promise.defer();
+    deferred.reject(1);
+    deferred.reject(2);
+    deferred.resolve(3);
+
+    let result = deferred.promise.then(
+      function onResolve() {
+        do_throw("Obtained a resolution while the promise was already rejected");
+      },
+      function onReject(reason) {
+        do_check_eq(reason, 1, "Rejection chose the first value");
+      }
+    );
+
+    return result;
+  }));
+
+// Test that returning normally from a rejection recovers from the error
+// and that listeners are informed of a success.
+tests.push(
+  make_promise_test(function recovery(test) {
+    let boom = new Error("Boom!");
+    let deferred = Promise.defer();
+    const RESULT = "An arbitrary value";
+
+    let promise = deferred.promise.then(
+      function onResolve() {
+        do_throw("A rejected promise should not resolve");
+      },
+      function onReject(reason) {
+        do_check_true(reason == boom, "Promise was rejected with the correct error");
+        return RESULT;
+      }
+    );
+
+    promise = promise.then(
+      function onResolve(value) {
+        do_check_eq(value, RESULT, "Promise was recovered with the correct value");
+      }
+    );
+
+    deferred.reject(boom);
+    return promise;
+  }));
+
+// Test that returning a resolved promise from a onReject causes a resolution
+// (recovering from the error) and that returning a rejected promise
+// from a onResolve listener causes a rejection (raising an error).
+tests.push(
+  make_promise_test(function recovery_with_promise(test) {
+    let boom = new Error("Arbitrary error");
+    let deferred = Promise.defer();
+    const RESULT = "An arbitrary value";
+    const boom2 = new Error("Another arbitrary error");
+
+    // return a resolved promise from a onReject listener
+    let promise = deferred.promise.then(
+      function onResolve() {
+        do_throw("A rejected promise should not resolve");
+      },
+      function onReject(reason) {
+        do_check_true(reason == boom, "Promise was rejected with the correct error");
+        return Promise.resolve(RESULT);
+      }
+    );
+
+    // return a rejected promise from a onResolve listener
+    promise = promise.then(
+      function onResolve(value) {
+        do_check_eq(value, RESULT, "Promise was recovered with the correct value");
+        return Promise.reject(boom2);
+      }
+    );
+
+    promise = promise.then(
+      null,
+      function onReject(reason) {
+        do_check_eq(reason, boom2, "Rejection was propagated with the correct " +
+                "reason, through a promise");
+      }
+    );
+
+    deferred.reject(boom);
+    return promise;
+  }));
+
+// Test that we can resolve with promises of promises
+tests.push(
+  make_promise_test(function test_propagation(test) {
+    const RESULT = "Yet another arbitrary value";
+    let d1 = Promise.defer();
+    let d2 = Promise.defer();
+    let d3 = Promise.defer();
+
+    d3.resolve(d2.promise);
+    d2.resolve(d1.promise);
+    d1.resolve(RESULT);
+
+    return d3.promise.then(
+      function onSuccess(value) {
+        do_check_eq(value, RESULT, "Resolution with a promise eventually yielded "
+                + " the correct result");
+      }
+    );
+  }));
+
+// Test sequences of |then|
+tests.push(
+  make_promise_test(function test_chaining(test) {
+    let error_1 = new Error("Error 1");
+    let error_2 = new Error("Error 2");
+    let result_1 = "First result";
+    let result_2 = "Second result";
+    let result_3 = "Third result";
+
+    let source = Promise.defer();
+
+    let promise = source.promise.then().then();
+
+    source.resolve(result_1);
+
+    // Check that result_1 is correctly propagated
+    promise = promise.then(
+      function onSuccess(result) {
+        do_check_eq(result, result_1, "Result was propagated correctly through " +
+                " several applications of |then|");
+        return result_2;
+      }
+    );
+
+    // Check that returning from the promise produces a resolution
+    promise = promise.then(
+      null,
+      function onReject() {
+        do_throw("Incorrect rejection");
+      }
+    );
+
+    // ... and that the check did not alter the value
+    promise = promise.then(
+      function onResolve(value) {
+        do_check_eq(value, result_2, "Result was propagated correctly once again");
+      }
+    );
+
+    // Now the same kind of tests for rejections
+    promise = promise.then(
+      function onResolve() {
+        throw error_1;
+      }
+    );
+
+    promise = promise.then(
+      function onResolve() {
+        do_throw("Incorrect resolution: the exception should have caused a rejection");
+      }
+    );
+
+    promise = promise.then(
+      null,
+      function onReject(reason) {
+        do_check_true(reason == error_1, "Reason was propagated correctly");
+        throw error_2;
+      }
+    );
+
+    promise = promise.then(
+      null,
+      function onReject(reason) {
+        do_check_true(reason == error_2, "Throwing an error altered the reason " +
+            "as expected");
+        return result_3;
+      }
+    );
+
+    promise = promise.then(
+      function onResolve(result) {
+        do_check_eq(result, result_3, "Error was correctly recovered");
+      }
+    );
+
+    return promise;
+  }));
+
+// Test that resolving with a rejected promise actually rejects
+tests.push(
+  make_promise_test(function resolve_to_rejected(test) {
+    let source = Promise.defer();
+    let error = new Error("Boom");
+
+    let promise = source.promise.then(
+      function onResolve() {
+        do_throw("Incorrect call to onResolve listener");
+      },
+      function onReject(reason) {
+        do_check_eq(reason, error, "Rejection lead to the expected reason");
+      }
+    );
+
+    source.resolve(Promise.reject(error));
+
+    return promise;
+  }));
+
+// Test that Promise.resolve resolves as expected
+tests.push(
+  make_promise_test(function test_resolve(test) {
+    const RESULT = "arbitrary value";
+    let promise = Promise.resolve(RESULT).then(
+      function onResolve(result) {
+        do_check_eq(result, RESULT, "Promise.resolve propagated the correct result");
+      }
+    );
+    return promise;
+  }));
+
+function run_test()
+{
+  do_test_pending();
+  run_promise_tests(tests, do_test_finished);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/addon-sdk/test/unit/xpcshell.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+head = head.js
+tail = 
+
+[test_promise.js]
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -198,16 +198,17 @@ function TelemetryPing() {}
 TelemetryPing.prototype = {
   _histograms: {},
   _initialized: false,
   _prevValues: {},
   // Generate a unique id once per session so the server can cope with
   // duplicate submissions.
   _uuid: generateUUID(),
   // Regex that matches histograms we care about during startup.
+  // Keep this in sync with gen-histogram-bucket-ranges.py.
   _startupHistogramRegex: /SQLITE|HTTP|SPDY|CACHE|DNS/,
   _slowSQLStartup: {},
   _prevSession: null,
   _hasWindowRestoredObserver: false,
   _hasXulWindowVisibleObserver: false,
   _pendingPings: [],
   _doLoadSaveNotifications: false,
   _startupIO : {},
new file mode 100644
--- /dev/null
+++ b/toolkit/components/telemetry/gen-histogram-bucket-ranges.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# 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/.
+
+# Write out detailed histogram information, including the ranges of the
+# buckets specified by each histogram.
+
+import sys
+import re
+import histogram_tools
+import simplejson as json
+
+# Keep this in sync with TelemetryPing.
+startup_histogram_re = re.compile("SQLITE|HTTP|SPDY|CACHE|DNS")
+
+def main(argv):
+    filename = argv[0]
+    all_histograms = json.OrderedDict()
+
+    for histogram in histogram_tools.from_file(filename):
+        name = histogram.name()
+        parameters = json.OrderedDict()
+        table = {
+            'boolean': '2',
+            'flag': '3',
+            'enumerated': '1',
+            'linear': '1',
+            'exponential': '0'
+            }
+        # Use __setitem__ because Python lambdas are so limited.
+        histogram_tools.table_dispatch(histogram.kind(), table,
+                                       lambda k: parameters.__setitem__('kind', k))
+        if histogram.low() == 0:
+            parameters['min'] = 1
+        else:
+            parameters['min'] = histogram.low()
+
+        try:
+            buckets = histogram.ranges()
+            parameters['buckets'] = buckets
+            parameters['max'] = buckets[-1]
+            parameters['bucket_count'] = len(buckets)
+        except histogram_tools.DefinitionException:
+            continue
+        
+        all_histograms.update({ name: parameters });
+
+        if startup_histogram_re.match(name) is not None:
+            all_histograms.update({ "STARTUP_" + name: parameters })
+
+    print json.dumps({ 'histograms': all_histograms})
+
+main(sys.argv[1:])
--- a/toolkit/content/PopupNotifications.jsm
+++ b/toolkit/content/PopupNotifications.jsm
@@ -466,16 +466,19 @@ PopupNotifications.prototype = {
       if (bo.height == 0 && bo.width == 0)
         anchorElement = selectedTab; // hidden
     } else {
       anchorElement = selectedTab; // null
     }
 
     this._currentAnchorElement = anchorElement;
 
+    // On OS X and Linux we need a different panel arrow color for
+    // click-to-play plugins, so copy the popupid and use css.
+    this.panel.setAttribute("popupid", this.panel.firstChild.getAttribute("popupid"));
     this.panel.openPopup(anchorElement, "bottomcenter topleft");
     notificationsToShow.forEach(function (n) {
       this._fireCallback(n, NOTIFICATION_EVENT_SHOWN);
     }, this);
   },
 
   /**
    * Updates the notification state in response to window activation or tab
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -201,17 +201,17 @@ notificationbox {
 
 notification {
   -moz-binding: url("chrome://global/content/bindings/notification.xml#notification");
   transition: margin-top 300ms, opacity 300ms;
 }
 
 /*********** popup notification ************/
 popupnotification {
-  -moz-binding: url("chrome://global/content/bindings/notification.xml#popup-notification")
+  -moz-binding: url("chrome://global/content/bindings/notification.xml#popup-notification");
 }
 
 .popup-notification-menubutton:not([label]) {
   display: none;
 }
 
 /********** image **********/
 
--- a/toolkit/locales/en-US/chrome/global/about.dtd
+++ b/toolkit/locales/en-US/chrome/global/about.dtd
@@ -1,8 +1,11 @@
+<!-- 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 about.version                "version">
 
 <!-- LOCALIZATION NOTE (about.credits.beforeLink): note that there is no space between this phrase and the linked about.credits.linkTitle phrase, so if your locale needs a space between words, add it at the end of this entity. -->
 <!ENTITY about.credits.beforeLink     "See a list of ">
 <!ENTITY about.credits.linkTitle      "contributors">
 <!-- LOCALIZATION NOTE (about.credits.afterLink): note that there is no space between the linked about.credits.linkTitle phrase and this phrase, so if your locale needs a space between words, add it at the start of this entity. -->
 <!ENTITY about.credits.afterLink      " to the Mozilla Project.">
 
--- a/toolkit/locales/en-US/chrome/global/aboutRights.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutRights.dtd
@@ -1,8 +1,11 @@
+<!-- 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/. -->
 <!-- rights.locale-direction instead of the usual local.dir entity, so RTL can skip translating page. -->
 <!ENTITY rights.locale-direction "ltr">
 <!ENTITY rights.pagetitle       "about:rights">
 <!ENTITY rights.intro-header    "About Your Rights">
 <!ENTITY rights.intro "&brandFullName; is free and open source software, built by a community of thousands from all over the world. There are a few things you should know:">
 
 <!-- Note on pointa / pointb / pointc form:
      These points each have an embedded link in the HTML, so each point is
--- a/toolkit/locales/en-US/chrome/global/notification.dtd
+++ b/toolkit/locales/en-US/chrome/global/notification.dtd
@@ -1,7 +1,9 @@
 <!-- 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 closeNotification.tooltip "Close this message">
 
 <!ENTITY closeNotificationItem.label "Not Now">
+
+<!ENTITY checkForUpdates "Check for updates…">
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd
@@ -1,8 +1,11 @@
+<!-- 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 addons.windowTitle                   "Add-ons Manager">
 
 <!ENTITY search.placeholder                   "Search all add-ons">
 <!-- LOCALIZATION NOTE (search.commandKey):
      The search command key should match findOnCmd.commandkey from browser.dtd -->
 <!ENTITY search.commandkey                    "f">
 
 <!ENTITY loading.label                        "Loading…">
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
@@ -1,8 +1,12 @@
+# 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/.
+
 #LOCALIZATION NOTE (aboutWindowTitle) %S is the addon name
 aboutWindowTitle=About %S
 aboutWindowCloseButton=Close
 #LOCALIZATION NOTE (aboutWindowVersionString) %S is the addon version
 aboutWindowVersionString=version %S
 #LOCALIZATION NOTE (aboutAddon) %S is the addon name
 aboutAddon=About %S
 
--- a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
@@ -1,8 +1,11 @@
+<!-- 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 pluginWizard.title                                  "Plugin Finder Service">
 <!ENTITY pluginWizard.firstPage.title                        "Welcome to the &pluginWizard.title;">
 
 <!ENTITY pluginWizard.checkingForPlugins.description.label   "&brandShortName; is now checking for available plugins…">
 
 <!ENTITY pluginWizard.availablePluginsPage.title             "Available Plugin Downloads">
 <!ENTITY pluginWizard.availablePluginsPage.description.label "The following plugins are available:">
 <!ENTITY pluginWizard.availablePluginsPage.continueMsg.label "Press Next to install these plugins.">
@@ -28,18 +31,16 @@
 <!ENTITY unsupportedPlatform.learnMore                       "Learn More…">
 <!-- LOCALIZATION NOTE (unsupportedPlatform.post): Mobile only. Include text here if needed for your locale. -->
 <!ENTITY unsupportedPlatform.post                            "">
 
 <!ENTITY missingPlugin                                       "A plugin is needed to display this content.">
 <!-- LOCALIZATION NOTE (tapToPlayPlugin): Mobile (used for touch interfaces) only has one type of plugin possible. -->
 <!ENTITY tapToPlayPlugin                                     "Tap here to activate plugin.">
 <!ENTITY clickToPlayPlugin                                   "Click here to activate plugin.">
-<!ENTITY clickToPlayPluginVulnerableUpdateAvailable          "Click here to activate vulnerable plugin.">
-<!ENTITY clickToPlayPluginVulnerableNoUpdate                 "Click here to activate vulnerable plugin (no update available).">
 <!ENTITY checkForUpdates                                     "Check for updates…">
 <!ENTITY disabledPlugin                                      "This plugin is disabled.">
 <!ENTITY blockedPlugin.label                                 "This plugin has been blocked for your protection.">
 
 <!ENTITY installPlugin                                       "Install plugin…">
 <!ENTITY managePlugins                                       "Manage plugins…">
 
 <!-- LOCALIZATION NOTE (reloadPlugin.pre): include a trailing space as needed -->
--- a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.properties
@@ -1,8 +1,12 @@
+# 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/.
+
 pluginLicenseAgreement.label=To install %S, you need to agree to the following:
 
 pluginInstallation.download.start=Downloading %S…
 pluginInstallation.download.finish=Finished downloading %S.
 
 pluginInstallation.install.start=Installing %S…
 pluginInstallation.install.finish=Successfully installed %S.
 pluginInstallation.install.error=Failed to install %S (%S).
--- a/toolkit/locales/en-US/chrome/mozapps/update/updates.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/update/updates.dtd
@@ -1,8 +1,11 @@
+<!-- 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  updateWizard.title              "Software Update">
 
 <!ENTITY  checking.title                  "Checking for Updates">
 <!ENTITY  updateCheck.label               "Looking for newer versions of &brandShortName;…">
 
 <!ENTITY  pluginupdatesfound.title        "Found Updates for Plugins">
 <!ENTITY  pluginupdatesfound.label        "Newer versions of one or more of your plugins were found.">
 <!ENTITY  pluginupdateslink.label         "See how to upgrade your plugins.">
--- a/toolkit/locales/en-US/chrome/mozapps/update/updates.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/update/updates.properties
@@ -1,8 +1,12 @@
+# 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/.
+
 # LOCALIZATION NOTE: The 1st %S is the update name and the 2nd %S is the build
 # identifier from the local updates.xml for displaying update history
 # example: MyApplication (20081022033543)
 updateFullName=%S (%S)
 
 # LOCALIZATION NOTE: The 1st %S is brandShortName and 2nd %S is update version
 # where update version from the update xml
 # example: MyApplication 10.0.5
--- a/toolkit/mozapps/plugins/content/pluginProblem.xml
+++ b/toolkit/mozapps/plugins/content/pluginProblem.xml
@@ -23,20 +23,19 @@
 
     <content>
         <xul:vbox class="mainBox" flex="1" chromedir="&locale.dir;">
             <xul:spacer flex="1"/>
             <xul:box class="icon"/>
             <html:div class="msg msgUnsupported">&missingPlugin;</html:div>
             <html:div class="msg msgUnsupportedPlatform">&unsupportedPlatform.pre;<html:a class="unsupportedLearnMoreLink" href="" target="_blank">&unsupportedPlatform.learnMore;</html:a>&unsupportedPlatform.post;</html:div>
             <html:div class="msg msgTapToPlay">&tapToPlayPlugin;</html:div>
+            <html:div class="msg msgVulnerabilityStatus" anonid="vulnerabilityStatus"><!-- set at runtime --></html:div>
+            <html:div class="msg msgCheckForUpdates"><html:a class="checkForUpdatesLink" href="">&checkForUpdates;</html:a></html:div>
             <html:div class="msg msgClickToPlay">&clickToPlayPlugin;</html:div>
-            <html:div class="msg msgVulnerableUpdatable">&clickToPlayPluginVulnerableUpdateAvailable;</html:div>
-            <html:div class="msg msgVulnerableNoUpdate">&clickToPlayPluginVulnerableNoUpdate;</html:div>
-            <html:div class="msg msgCheckForUpdates"><html:a class="checkForUpdatesLink" href="">&checkForUpdates;</html:a></html:div>
             <html:div class="msg msgDisabled">&disabledPlugin;</html:div>
             <html:div class="msg msgBlocked">&blockedPlugin.label;</html:div>
             <html:div class="msg msgCrashed"><!-- set at runtime --></html:div>
 
             <html:div class="installStatus">
                 <html:div class="msg msgInstallPlugin"><html:a class="installPluginLink" href="">&installPlugin;</html:a></html:div>
             </html:div>
             <html:div class="msg msgManagePlugins"><html:a class="managePluginsLink" href="">&managePlugins;</html:a></html:div>
--- a/toolkit/mozapps/plugins/content/pluginProblemContent.css
+++ b/toolkit/mozapps/plugins/content/pluginProblemContent.css
@@ -70,19 +70,21 @@ html|applet:not([height]), html|applet[h
 
 .msg {
   display: none;
 }
 
 :-moz-type-unsupported .msgUnsupported,
 :-moz-type-unsupported-platform .msgUnsupportedPlatform,
 :-moz-handler-clicktoplay .msgClickToPlay,
-:-moz-handler-vulnerable-updatable .msgVulnerableUpdatable,
+:-moz-handler-vulnerable-updatable .msgVulnerabilityStatus,
 :-moz-handler-vulnerable-updatable .msgCheckForUpdates,
-:-moz-handler-vulnerable-no-update .msgVulnerableNoUpdate,
+:-moz-handler-vulnerable-updatable .msgClickToPlay,
+:-moz-handler-vulnerable-no-update .msgVulnerabilityStatus,
+:-moz-handler-vulnerable-no-update .msgClickToPlay,
 :-moz-handler-clicktoplay .msgTapToPlay,
 :-moz-handler-disabled .msgDisabled,
 :-moz-handler-disabled .msgManagePlugins,
 :-moz-handler-blocked .msgBlocked,
 :-moz-handler-crashed .msgCrashed {
   display: block;
 }
 
new file mode 100644
--- /dev/null
+++ b/toolkit/themes/gnomestripe/global/icons/panelarrow-light-vertical.svg
@@ -0,0 +1,13 @@
+<?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/. -->
+
+<svg xmlns="http://www.w3.org/2000/svg"
+     width="20"
+     height="10">
+  <path d="M 0,10 L 10,0 20,10 z"
+        fill="-moz-Dialog"/>
+  <path d="M 0,10 L 10,0 20,10 z"
+        fill="hsla(0,0%,100%,.4)"/>
+</svg>
--- a/toolkit/themes/gnomestripe/global/jar.mn
+++ b/toolkit/themes/gnomestripe/global/jar.mn
@@ -42,12 +42,13 @@ toolkit.jar:
 +  skin/classic/global/icons/autoscroll.png                    (icons/autoscroll.png)
 +  skin/classic/global/icons/blacklist_favicon.png             (icons/blacklist_favicon.png)
 +  skin/classic/global/icons/blacklist_large.png               (icons/blacklist_large.png)
 +  skin/classic/global/icons/find.png                          (icons/find.png)
 +  skin/classic/global/icons/loading_16.png                    (icons/loading_16.png)
 +  skin/classic/global/icons/notloading_16.png                 (icons/notloading_16.png)
 +  skin/classic/global/icons/panelarrow-horizontal.svg         (icons/panelarrow-horizontal.svg)
 +  skin/classic/global/icons/panelarrow-vertical.svg           (icons/panelarrow-vertical.svg)
++  skin/classic/global/icons/panelarrow-light-vertical.svg   (icons/panelarrow-light-vertical.svg)
 +  skin/classic/global/icons/resizer.png                       (icons/resizer.png)
 +  skin/classic/global/icons/sslWarning.png                    (icons/sslWarning.png)
 +  skin/classic/global/icons/wrap.png                          (icons/wrap.png)
 +  skin/classic/global/toolbar/spring.png                      (toolbar/spring.png)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..96636552b0890298e0404001c0dccd6c2c7bd196
GIT binary patch
literal 382
zc$@)#0fGLBP)<h;3K|Lk000e1NJLTq001Wd000mO1^@s6mE2|^0003+Nkl<Zc-p;^
z(T#&J42EwKZX*WhD!eekEpfUHlbD!5n%~8;P`IjvLZwf?ZEW}+`jvCuWasaD$IZVE
zACqgE=GM0D5Aq5*<V!%P>$=~0o--2ti??UV)nX~7TnSz-w=D)L!HeZ;u~DSPJdTAW
z=g9;wlrynunjj*u<QhCz!IR}`F=j4O1qKk}Jfb#4u<!dn+?^_CVkyTMbL1$=5hCaT
z+Z>cWRe~RtGqIE)HVDH|B!-d@1*O*-&vXxS+?n8UxlOU5$Pk1SLMjAoMugOxO7NhZ
ziQx}UM2Eq9RPc!0N-Tt65R#T!Q$P&~t7T7nDt%Z9?vY!I`S2k4l0N$d%)H>M9RN8G
zq_$nmm`(6)IfyZ{iWm<099QkS%^hYI!MEjr^G;sk96+u4z&rUUYRn-c=$&8Y+Ut&j
c=g+=>2Pc2albu=AQUCw|07*qoM6N<$g3lVMy#N3J
--- a/toolkit/themes/pinstripe/global/jar.mn
+++ b/toolkit/themes/pinstripe/global/jar.mn
@@ -74,16 +74,17 @@ toolkit.jar:
   skin/classic/global/arrow/arrow-rit-sharp-end.gif                  (arrow/arrow-rit-sharp-end.gif)
   skin/classic/global/arrow/arrow-rit-sharp.gif                      (arrow/arrow-rit-sharp.gif)
   skin/classic/global/arrow/arrow-rit.gif                            (arrow/arrow-rit.gif)
   skin/classic/global/arrow/arrow-up-dis.gif                         (arrow/arrow-up-dis.gif)
   skin/classic/global/arrow/arrow-up-sharp.gif                       (arrow/arrow-up-sharp.gif)
   skin/classic/global/arrow/arrow-up.gif                             (arrow/arrow-up.gif)
   skin/classic/global/arrow/panelarrow-horizontal.png                (arrow/panelarrow-horizontal.png)
   skin/classic/global/arrow/panelarrow-vertical.png                  (arrow/panelarrow-vertical.png)
+  skin/classic/global/arrow/panelarrow-light-vertical.png            (arrow/panelarrow-light-vertical.png)
   skin/classic/global/checkbox/cbox-check.gif                        (checkbox/cbox-check.gif)
   skin/classic/global/checkbox/cbox-check-dis.gif                    (checkbox/cbox-check-dis.gif)
   skin/classic/global/console/console-error-caret.gif                (console/console-error-caret.gif)
   skin/classic/global/console/console-error-dash.gif                 (console/console-error-dash.gif)
 * skin/classic/global/console/console.css                            (console/console.css)
   skin/classic/global/dirListing/dirListing.css                      (dirListing/dirListing.css)
   skin/classic/global/dirListing/folder.png                          (dirListing/folder.png)
   skin/classic/global/dirListing/local.png                           (dirListing/folder.png)
--- a/toolkit/themes/pinstripe/global/notification.css
+++ b/toolkit/themes/pinstripe/global/notification.css
@@ -116,16 +116,17 @@ notification[type="critical"] {
 .popup-notification-button-container {
   margin-top: 17px;
 }
 
 .popup-notification-menubutton {