Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Wed, 25 Jul 2012 16:03:21 +0100
changeset 100389 75d16b99e8ab6bd6bf8ce4bb50d280f8c3c53552
parent 100282 345dc425c9ebfcdeffc255cc90b011715e8fa621 (current diff)
parent 100388 607a4fe97df45352d95221bc47986e2c3278e06a (diff)
child 100390 887b70a4b6c24ddf26e2faaa35bc9dea5f41d438
push id23175
push useremorley@mozilla.com
push dateWed, 25 Jul 2012 15:03:49 +0000
treeherdermozilla-central@75d16b99e8ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
build/pylib/blessings/LICENSE
build/pylib/blessings/MANIFEST.in
build/pylib/blessings/PKG-INFO
build/pylib/blessings/README.rst
build/pylib/blessings/blessings/__init__.py
build/pylib/blessings/blessings/tests.py
build/pylib/blessings/setup.cfg
build/pylib/blessings/setup.py
build/pylib/blessings/tox.ini
content/base/test/header.sjs
content/base/test/test_header.html
js/xpconnect/tests/Makefile.in
netwerk/test/unit/test_proxy_preservation_bug235853.js
res/drawable-hdpi/sync_fx_icon.png
res/drawable-ldpi/sync_fx_icon.png
res/drawable-mdpi/sync_fx_icon.png
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -117,21 +117,24 @@ var shell = {
     document.getElementById('shell').appendChild(browserFrame);
 
     browserFrame.contentWindow
                 .QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIWebNavigation)
                 .sessionHistory = Cc["@mozilla.org/browser/shistory;1"]
                                     .createInstance(Ci.nsISHistory);
 
-    ['keydown', 'keypress', 'keyup'].forEach((function listenKey(type) {
-      window.addEventListener(type, this, false, true);
-      window.addEventListener(type, this, true, true);
-    }).bind(this));
-
+    // Capture all key events so we can filter out hardware buttons
+    // And send them to Gaia via mozChromeEvents.
+    // Ideally, hardware buttons wouldn't generate key events at all, or
+    // if they did, they would use keycodes that conform to DOM 3 Events.
+    // See discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=762362
+    window.addEventListener('keydown', this, true);
+    window.addEventListener('keypress', this, true);
+    window.addEventListener('keyup', this, true);
     window.addEventListener('MozApplicationManifest', this);
     window.addEventListener('mozfullscreenchange', this);
     window.addEventListener('sizemodechange', this);
     this.contentBrowser.addEventListener('mozbrowserloadstart', this, true);
 
     // Until the volume can be set from the content side, set it to a
     // a specific value when the device starts. This way the front-end
     // can display a notification when the volume change and show a volume
@@ -160,58 +163,98 @@ var shell = {
     SettingsListener.observe("debug.paint-flashing.enabled", false, function(value) {
       Services.prefs.setBoolPref("nglayout.debug.paint_flashing", value);
     });
 
     this.contentBrowser.src = homeURL;
   },
 
   stop: function shell_stop() {
-    ['keydown', 'keypress', 'keyup'].forEach((function unlistenKey(type) {
-      window.removeEventListener(type, this, false, true);
-      window.removeEventListener(type, this, true, true);
-    }).bind(this));
-
+    window.removeEventListener('keydown', this, true);
+    window.removeEventListener('keypress', this, true);
+    window.removeEventListener('keyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('mozfullscreenchange', this);
     window.removeEventListener('sizemodechange', this);
     this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
 
 #ifndef MOZ_WIDGET_GONK
     delete Services.audioManager;
 #endif
   },
 
-  forwardKeyToContent: function shell_forwardKeyToContent(evt) {
-    let content = shell.contentBrowser.contentWindow;
-    let generatedEvent = content.document.createEvent('KeyboardEvent');
-    generatedEvent.initKeyEvent(evt.type, true, true, evt.view, evt.ctrlKey,
-                                evt.altKey, evt.shiftKey, evt.metaKey,
-                                evt.keyCode, evt.charCode);
+  // If this key event actually represents a hardware button, filter it here
+  // and send a mozChromeEvent with detail.type set to xxx-button-press or
+  // xxx-button-release instead.
+  filterHardwareKeys: function shell_filterHardwareKeys(evt) {
+    var type;
+    switch (evt.keyCode) {
+      case evt.DOM_VK_HOME:         // Home button
+        type = 'home-button';
+        break;
+      case evt.DOM_VK_SLEEP:        // Sleep button
+        type = 'sleep-button';
+        break;
+      case evt.DOM_VK_PAGE_UP:      // Volume up button
+        type = 'volume-up-button';
+        break;
+      case evt.DOM_VK_PAGE_DOWN:    // Volume down button
+        type = 'volume-down-button';
+        break;
+      case evt.DOM_VK_ESCAPE:       // Back button (should be disabled)
+        type = 'back-button';
+        break;
+      case evt.DOM_VK_CONTEXT_MENU: // Menu button
+        type = 'menu-button';
+        break;
+      default:                      // Anything else is a real key
+        return;  // Don't filter it at all; let it propagate to Gaia
+    }
 
-    content.document.documentElement.dispatchEvent(generatedEvent);
+    // If we didn't return, then the key event represents a hardware key
+    // and we need to prevent it from propagating to Gaia
+    evt.stopImmediatePropagation();
+    evt.preventDefault(); // Prevent keypress events (when #501496 is fixed).
+
+    // If it is a key down or key up event, we send a chrome event to Gaia.
+    // If it is a keypress event we just ignore it.
+    switch (evt.type) {
+      case 'keydown':
+        type = type + '-press';
+        break;
+      case 'keyup':
+        type = type + '-release';
+        break;
+      case 'keypress':
+        return;
+    }
+  
+    // On my device, the physical hardware buttons (sleep and volume)
+    // send multiple events (press press release release), but the
+    // soft home button just sends one.  This hack is to manually
+    // "debounce" the keys. If the type of this event is the same as
+    // the type of the last one, then don't send it.  We'll never send
+    // two presses or two releases in a row.
+    // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=761067
+    if (type !== this.lastHardwareButtonEventType) {
+      this.lastHardwareButtonEventType = type;
+      this.sendChromeEvent({type: type});
+    }
   },
+  
+  lastHardwareButtonEventType: null, // property for the hack above
 
   handleEvent: function shell_handleEvent(evt) {
     let content = this.contentBrowser.contentWindow;
     switch (evt.type) {
       case 'keydown':
       case 'keyup':
       case 'keypress':
-        // Redirect the HOME key to System app and stop the applications from
-        // handling it.
-        let rootContentEvt = (evt.target.ownerDocument.defaultView == content);
-        if (!rootContentEvt && evt.eventPhase == evt.CAPTURING_PHASE &&
-            evt.keyCode == evt.DOM_VK_HOME) {
-          this.forwardKeyToContent(evt);
-          evt.preventDefault();
-          evt.stopImmediatePropagation();
-        }
+        this.filterHardwareKeys(evt);
         break;
-
       case 'mozfullscreenchange':
         // When the screen goes fullscreen make sure to set the focus to the
         // main window so noboby can prevent the ESC key to get out fullscreen
         // mode
         if (document.mozFullScreen)
           Services.fm.focusedWindow = window;
         break;
       case 'sizemodechange':
@@ -267,16 +310,19 @@ var shell = {
         }
         break;
     }
   },
   sendEvent: function shell_sendEvent(content, type, details) {
     let event = content.document.createEvent('CustomEvent');
     event.initCustomEvent(type, true, true, details ? details : {});
     content.dispatchEvent(event);
+  },
+  sendChromeEvent: function shell_sendChromeEvent(details) {
+    this.sendEvent(getContentWindow(), "mozChromeEvent", details);
   }
 };
 
 function nsBrowserAccess() {
 }
 
 nsBrowserAccess.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow]),
@@ -305,17 +351,17 @@ nsBrowserAccess.prototype = {
     return contentWindow == window;
   }
 };
 
 // Listen for system messages and relay them to Gaia.
 Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
   let msg = JSON.parse(data);
   let origin = Services.io.newURI(msg.manifest, null, null).prePath;
-  shell.sendEvent(shell.contentBrowser.contentWindow, 'mozChromeEvent', {
+  shell.sendChromeEvent({
     type: 'open-app',
     url: msg.uri,
     origin: origin,
     manifest: msg.manifest
   });
 }, 'system-messages-open-app', false);
 
 (function Repl() {
@@ -410,22 +456,32 @@ var AlertsHelper = {
   },
 
   registerListener: function alert_registerListener(cookie, alertListener) {
     let id = "alert" + this._count++;
     this._listeners[id] = { observer: alertListener, cookie: cookie };
     return id;
   },
 
-  showAlertNotification: function alert_showAlertNotification(imageUrl, title, text, textClickable,
-                                                              cookie, alertListener, name) {
+  showAlertNotification: function alert_showAlertNotification(imageUrl,
+                                                              title,
+                                                              text,
+                                                              textClickable,
+                                                              cookie,
+                                                              alertListener,
+                                                              name)
+  {
     let id = this.registerListener(cookie, alertListener);
-    let content = shell.contentBrowser.contentWindow;
-    shell.sendEvent(content, "mozChromeEvent", { type: "desktop-notification", id: id, icon: imageUrl,
-                                                 title: title, text: text } );
+    shell.sendChromeEvent({
+      type: "desktop-notification",
+      id: id,
+      icon: imageUrl,
+      title: title,
+      text: text
+    });
   }
 }
 
 var WebappsHelper = {
   _installers: {},
   _count: 0,
 
   init: function webapps_init() {
@@ -451,35 +507,38 @@ var WebappsHelper = {
         break;
       case "webapps-install-denied":
         DOMApplicationRegistry.denyInstall(installer);
         break;
     }
   },
 
   observe: function webapps_observe(subject, topic, data) {
-    let content = shell.contentBrowser.contentWindow;
     let json = JSON.parse(data);
     switch(topic) {
       case "webapps-launch":
         DOMApplicationRegistry.getManifestFor(json.origin, function(aManifest) {
           if (!aManifest)
             return;
 
           let manifest = new DOMApplicationManifest(aManifest, json.origin);
-          shell.sendEvent(content, "mozChromeEvent", {
+          shell.sendChromeEvent({
             "type": "webapps-launch",
             "url": manifest.fullLaunchPath(json.startPoint),
             "origin": json.origin
           });
         });
         break;
       case "webapps-ask-install":
         let id = this.registerInstaller(json);
-        shell.sendEvent(content, "mozChromeEvent", { type: "webapps-ask-install", id: id, app: json.app } );
+        shell.sendChromeEvent({
+          type: "webapps-ask-install",
+          id: id,
+          app: json.app
+        });
         break;
     }
   }
 }
 
 // Start the debugger server.
 function startDebugger() {
   if (!DebuggerServer.initialized) {
@@ -524,21 +583,33 @@ window.addEventListener('ContentStart', 
       var context = canvas.getContext('2d');
       var flags =
         context.DRAWWINDOW_DRAW_CARET |
         context.DRAWWINDOW_DRAW_VIEW |
         context.DRAWWINDOW_USE_WIDGET_LAYERS;
       context.drawWindow(window, 0, 0, width, height,
                          'rgb(255,255,255)', flags);
 
-      shell.sendEvent(content, 'mozChromeEvent', {
-          type: 'take-screenshot-success',
-          file: canvas.mozGetAsFile('screenshot', 'image/png')
+      shell.sendChromeEvent({
+        type: 'take-screenshot-success',
+        file: canvas.mozGetAsFile('screenshot', 'image/png')
       });
     } catch (e) {
       dump('exception while creating screenshot: ' + e + '\n');
-      shell.sendEvent(content, 'mozChromeEvent', {
+      shell.sendChromeEvent({
         type: 'take-screenshot-error',
         error: String(e)
       });
     }
   });
 });
+
+Services.obs.addObserver(function ContentHandler(subject, topic, data) {
+  let handler = JSON.parse(data);
+  new MozActivity({
+    name: 'view',
+    data: {
+      type: handler.type,
+      url: handler.url
+    }
+  });
+}, 'content-handler', false);
+
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -33,8 +33,13 @@ category xpcom-directory-providers brows
 # ActivitiesGlue.js
 component {70a83123-7467-4389-a309-3e81c74ad002} ActivitiesGlue.js
 contract @mozilla.org/dom/activities/ui-glue;1 {70a83123-7467-4389-a309-3e81c74ad002}
 
 # ProcessGlobal.js
 component {1a94c87a-5ece-4d11-91e1-d29c29f21b28} ProcessGlobal.js
 contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
 category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
+
+# ContentHandler.js
+component {d18d0216-d50c-11e1-ba54-efb18d0ef0ac} ContentHandler.js
+contract @mozilla.org/uriloader/content-handler;1?type=application/pdf {d18d0216-d50c-11e1-ba54-efb18d0ef0ac}
+
new file mode 100644
--- /dev/null
+++ b/b2g/components/ContentHandler.js
@@ -0,0 +1,48 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+"use strict";
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+const Cu = Components.utils;
+
+const PDF_CONTENT_TYPE = "application/pdf";
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+function log(aMsg) {
+  let msg = "ContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg);
+  Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
+                                     .logStringMessage(msg);
+  dump(msg + "\n");
+}
+
+const NS_ERROR_WONT_HANDLE_CONTENT = 0x805d0001;
+function ContentHandler() {
+}
+
+ContentHandler.prototype = {
+  handleContent: function handleContent(aMimetype, aContext, aRequest) {
+    if (aMimetype != PDF_CONTENT_TYPE)
+      throw NS_ERROR_WONT_HANDLE_CONTENT;
+
+    if (!(aRequest instanceof Ci.nsIChannel))
+      throw NS_ERROR_WONT_HANDLE_CONTENT;
+
+    let detail = {
+      "type": aMimetype,
+      "url": aRequest.URI.spec
+    };
+    Services.obs.notifyObservers(this, "content-handler", JSON.stringify(detail)); 
+
+    aRequest.cancel(Cr.NS_BINDING_ABORTED);
+  },
+
+  classID: Components.ID("{d18d0216-d50c-11e1-ba54-efb18d0ef0ac}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentHandler])
+};
+
+var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentHandler]);
--- a/b2g/components/DirectoryProvider.js
+++ b/b2g/components/DirectoryProvider.js
@@ -17,17 +17,17 @@ function DirectoryProvider() {
 
 DirectoryProvider.prototype = {
   classID: Components.ID("{9181eb7c-6f87-11e1-90b1-4f59d80dd2e5}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]),
 
   getFile: function dp_getFile(prop, persistent) {
 #ifdef MOZ_WIDGET_GONK
-    let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir"];
+    let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir", "permissionDBPDir"];
     if (localProps.indexOf(prop) != -1) {
       prop.persistent = true;
       let file = Cc["@mozilla.org/file/local;1"]
                    .createInstance(Ci.nsILocalFile)
       file.initWithPath(LOCAL_DIR);
       return file;
     }
 #endif
--- a/b2g/components/Makefile.in
+++ b/b2g/components/Makefile.in
@@ -12,23 +12,24 @@ include $(DEPTH)/config/autoconf.mk
 MODULE = B2GComponents
 XPIDL_MODULE = B2GComponents
 
 XPIDLSRCS = \
         b2g.idl \
         $(NULL)
 
 EXTRA_PP_COMPONENTS = \
+        ActivitiesGlue.js \
         AlertsService.js \
         B2GComponents.manifest \
         CameraContent.js \
+        ContentHandler.js \
         ContentPermissionPrompt.js \
         DirectoryProvider.js \
         MozKeyboard.js \
         ProcessGlobal.js \
-        ActivitiesGlue.js \
         $(NULL)
 
 ifdef MOZ_UPDATER
 EXTRA_PP_COMPONENTS += UpdatePrompt.js
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -679,8 +679,9 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/ContentPermissionPrompt.js
 #ifdef MOZ_UPDATER
 @BINPATH@/components/UpdatePrompt.js
 #endif
 @BINPATH@/components/MozKeyboard.js
 @BINPATH@/components/DirectoryProvider.js
 @BINPATH@/components/ActivitiesGlue.js
 @BINPATH@/components/ProcessGlobal.js
+@BINPATH@/components/ContentHandler.js
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -38,22 +38,36 @@
 
 #include "mozilla/Telemetry.h"
 
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
-#if defined(XP_WIN) && !MOZ_WINCONSOLE
-  PRUnichar msg[2048];
-  _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
-  MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
+#ifndef XP_WIN
+  vfprintf(stderr, fmt, ap);
 #else
-  vfprintf(stderr, fmt, ap);
+  char msg[2048];
+  vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap);
+
+  wchar_t wide_msg[2048];
+  MultiByteToWideChar(CP_UTF8,
+                      0,
+                      msg,
+                      -1,
+                      wide_msg,
+                      _countof(wide_msg));
+#if MOZ_WINCONSOLE
+  fwprintf_s(stderr, wide_msg);
+#else
+  MessageBoxW(NULL, wide_msg, L"Firefox", MB_OK
+                                        | MB_ICONERROR
+                                        | MB_SETFOREGROUND);
+#endif
 #endif
 
   va_end(ap);
 }
 
 /**
  * Return true if |arg| matches the given argument name.
  */
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1181,8 +1181,10 @@ pref("pdfjs.previousHandler.alwaysAskBef
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 // (This is intentionally on the high side; see bug 746055.)
 pref("image.mem.max_decoded_image_kb", 256000);
 
 // Example social provider
 pref("social.manifest.motown", "{\"origin\":\"https://motown-dev.mozillalabs.com\",\"name\":\"MoTown\",\"workerURL\":\"https://motown-dev.mozillalabs.com/social/worker.js\",\"iconURL\":\"https://motown-dev.mozillalabs.com/images/motown-icon.png\",\"sidebarURL\":\"https://motown-dev.mozillalabs.com/social/sidebar\"}");
 pref("social.sidebar.open", true);
+pref("browser.social.whitelist", "");
+pref("social.active", false);
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -327,16 +327,20 @@
                 key="key_openAddons"/>
       <splitmenu id="appmenu_customize"
 #ifdef XP_UNIX
                  label="&preferencesCmdUnix.label;"
 #else
                  label="&preferencesCmd2.label;"
 #endif
                  oncommand="openPreferences();">
+          <menuitem id="appmenu_socialToggle"
+                    type="checkbox"
+                    autocheck="false"
+                    command="Social:Toggle"/>
           <menupopup id="appmenu_customizeMenu"
                      onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('appmenu_toggleToolbarsSeparator'));">
             <menuitem id="appmenu_preferences"
 #ifdef XP_UNIX
                       label="&preferencesCmdUnix.label;"
 #else
                       label="&preferencesCmd2.label;"
 #endif
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -491,16 +491,20 @@
                         accesskey="&downloads.accesskey;"
                         key="key_openDownloads"
                         command="Tools:Downloads"/>
               <menuitem id="menu_openAddons"
                         label="&addons.label;"
                         accesskey="&addons.accesskey;"
                         key="key_openAddons"
                         command="Tools:Addons"/>
+              <menuitem id="menu_socialToggle"
+                        type="checkbox"
+                        autocheck="false"
+                        command="Social:Toggle"/>
 #ifdef MOZ_SERVICES_SYNC
               <!-- only one of sync-setup or sync-menu will be showing at once -->
               <menuitem id="sync-setup"
                         label="&syncSetup.label;"
                         accesskey="&syncSetup.accesskey;"
                         observes="sync-setup-state"
                         oncommand="gSyncUI.openSetup()"/>
               <menuitem id="sync-syncnowitem"
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -103,16 +103,17 @@
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing" oncommand="gPrivateBrowsingUI.toggleMode();"/>
     <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
     <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
     <command id="Browser:ToggleAddonBar" oncommand="toggleAddonBar();"/>
     <command id="Social:SharePage" oncommand="SocialShareButton.sharePage();"/>
     <command id="Social:UnsharePage" oncommand="SocialShareButton.unsharePage();"/>
     <command id="Social:ToggleSidebar" oncommand="Social.toggleSidebar();"/>
+    <command id="Social:Toggle" oncommand="Social.toggle();" hidden="true"/>
   </commandset>
 
   <commandset id="placesCommands">
     <command id="Browser:ShowAllBookmarks"
              oncommand="PlacesCommandHook.showPlacesOrganizer('AllBookmarks');"/>
     <command id="Browser:ShowAllHistory"
              oncommand="PlacesCommandHook.showPlacesOrganizer('History');"/>
   </commandset>
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -6,16 +6,18 @@ let SocialUI = {
   // Called on delayed startup to initialize UI
   init: function SocialUI_init() {
     Services.obs.addObserver(this, "social:pref-changed", false);
     Services.obs.addObserver(this, "social:ambient-notification-changed", false);
     Services.obs.addObserver(this, "social:profile-changed", false);
 
     Services.prefs.addObserver("social.sidebar.open", this, false);
 
+    gBrowser.addEventListener("ActivateSocialFeature", this._activationEventHandler, true, true);
+
     Social.init(this._providerReady.bind(this));
   },
 
   // Called on window unload
   uninit: function SocialUI_uninit() {
     Services.obs.removeObserver(this, "social:pref-changed");
     Services.obs.removeObserver(this, "social:ambient-notification-changed");
     Services.obs.removeObserver(this, "social:profile-changed");
@@ -26,36 +28,129 @@ let SocialUI = {
   showProfile: function SocialUI_showProfile() {
     if (Social.provider)
       openUILink(Social.provider.profile.profileURL);
   },
 
   observe: function SocialUI_observe(subject, topic, data) {
     switch (topic) {
       case "social:pref-changed":
+        this.updateToggleCommand();
         SocialShareButton.updateButtonHiddenState();
         SocialToolbar.updateButtonHiddenState();
         SocialSidebar.updateSidebar();
         break;
       case "social:ambient-notification-changed":
         SocialToolbar.updateButton();
         break;
       case "social:profile-changed":
         SocialToolbar.updateProfile();
         break;
       case "nsPref:changed":
         SocialSidebar.updateSidebar();
     }
   },
 
+  get toggleCommand() {
+    return document.getElementById("Social:Toggle");
+  },
+
   // Called once Social.jsm's provider has been set
   _providerReady: function SocialUI_providerReady() {
+    // If we couldn't find a provider, nothing to do here.
+    if (!Social.provider)
+      return;
+
+    this.updateToggleCommand();
+
+    let toggleCommand = this.toggleCommand;
+    let label = gNavigatorBundle.getFormattedString("social.enable.label",
+                                                    [Social.provider.name]);
+    let accesskey = gNavigatorBundle.getString("social.enable.accesskey");
+    toggleCommand.setAttribute("label", label);
+    toggleCommand.setAttribute("accesskey", accesskey);
+
     SocialToolbar.init();
     SocialShareButton.init();
     SocialSidebar.init();
+  },
+
+  updateToggleCommand: function SocialUI_updateToggleCommand() {
+    let toggleCommand = this.toggleCommand;
+    toggleCommand.setAttribute("checked", Social.enabled);
+
+    // FIXME: bug 772808: menu items don't inherit the "hidden" state properly,
+    // need to update them manually.
+    // This should just be: toggleCommand.hidden = !Social.active;
+    for (let id of ["appmenu_socialToggle", "menu_socialToggle"]) {
+      let el = document.getElementById(id);
+      if (!el)
+        continue;
+
+      if (Social.active)
+        el.removeAttribute("hidden");
+      else
+        el.setAttribute("hidden", "true");
+    }
+  },
+
+  // This handles "ActivateSocialFeature" events fired against content documents
+  // in this window.
+  _activationEventHandler: function SocialUI_activationHandler(e) {
+    // Nothing to do if Social is already active, or we don't have a provider
+    // to enable yet.
+    if (Social.active || !Social.provider)
+      return;
+
+    let targetDoc = e.target;
+
+    // Event must be fired against the document
+    if (!(targetDoc instanceof HTMLDocument))
+      return;
+
+    // Ignore events fired in background tabs
+    if (targetDoc.defaultView.top != content)
+      return;
+
+    // Check that the associated document's origin is in our whitelist
+    let prePath = targetDoc.documentURIObject.prePath;
+    let whitelist = Services.prefs.getCharPref("browser.social.whitelist");
+    if (whitelist.split(",").indexOf(prePath) == -1)
+      return;
+
+    // If the last event was received < 1s ago, ignore this one
+    let now = Date.now();
+    if (now - Social.lastEventReceived < 1000)
+      return;
+    Social.lastEventReceived = now;
+
+    // Enable the social functionality, and indicate that it was activated
+    Social.active = true;
+
+    // Show a warning, allow undoing the activation
+    let description = document.getElementById("social-activation-message");
+    let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
+    let message = gNavigatorBundle.getFormattedString("social.activated.message",
+                                                      [Social.provider.name, brandShortName]);
+    description.value = message;
+
+    SocialUI.notificationPanel.hidden = false;
+
+    setTimeout(function () {
+      SocialUI.notificationPanel.openPopup(SocialToolbar.button, "bottomcenter topright");
+    }.bind(this), 0);
+  },
+
+  get notificationPanel() {
+    return document.getElementById("socialActivatedNotification")
+  },
+
+  undoActivation: function SocialUI_undoActivation() {
+    Social.active = false;
+    this.notificationPanel.hidePopup();
   }
 }
 
 let SocialShareButton = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SSB_init() {
     this.updateButtonHiddenState();
 
@@ -148,32 +243,43 @@ let SocialShareButton = {
     }
   }
 };
 
 var SocialToolbar = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SocialToolbar_init() {
     document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
-    
-    // handle button state
-    document.getElementById("social-statusarea-popup").addEventListener("popupshowing", function(e) {
-      document.getElementById("social-toolbar-button").setAttribute("open", "true");
-    }, false);
-    document.getElementById("social-statusarea-popup").addEventListener("popuphiding", function(e) {
-      document.getElementById("social-toolbar-button").removeAttribute("open");
-    }, false);
+
+    let removeItem = document.getElementById("social-remove-menuitem");
+    let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
+    let label = gNavigatorBundle.getFormattedString("social.remove.label",
+                                                    [brandShortName]);
+    let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
+    removeItem.setAttribute("label", label);
+    removeItem.setAttribute("accesskey", accesskey);
+
+    let statusAreaPopup = document.getElementById("social-statusarea-popup");
+    statusAreaPopup.addEventListener("popupshowing", function(e) {
+      this.button.setAttribute("open", "true");
+    }.bind(this));
+    statusAreaPopup.addEventListener("popuphidden", function(e) {
+      this.button.removeAttribute("open");
+    }.bind(this));
 
     this.updateButton();
     this.updateProfile();
   },
 
+  get button() {
+    return document.getElementById("social-toolbar-button");
+  },
+
   updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
-    let toolbarbutton = document.getElementById("social-toolbar-button");
-    toolbarbutton.hidden = !Social.uiVisible;
+    this.button.hidden = !Social.uiVisible;
   },
 
   updateProfile: function SocialToolbar_updateProfile() {
     // Profile may not have been initialized yet, since it depends on a worker
     // response. In that case we'll be called again when it's available, via
     // social:profile-changed
     let profile = Social.provider.profile || {};
     let userPortrait = profile.portrait || "chrome://browser/skin/social/social.png";
@@ -228,20 +334,20 @@ var SocialToolbar = {
   showAmbientPopup: function SocialToolbar_showAmbientPopup(iconContainer) {
     let iconImage = iconContainer.firstChild;
     let panel = document.getElementById("social-notification-panel");
     let notifBrowser = document.getElementById("social-notification-browser");
 
     panel.hidden = false;
 
     function sizePanelToContent() {
-      // XXX Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
-      // XXX need to handle dynamic sizing
+      // FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
+      // Need to handle dynamic sizing
       let doc = notifBrowser.contentDocument;
-      // XXX "notif" is an implementation detail that we should get rid of
+      // "notif" is an implementation detail that we should get rid of
       // eventually
       let body = doc.getElementById("notif") || doc.body.firstChild;
       if (!body)
         return;
       let h = body.scrollHeight > 0 ? body.scrollHeight : 300;
       notifBrowser.style.width = body.scrollWidth + "px";
       notifBrowser.style.height = h + "px";
     }
@@ -249,23 +355,23 @@ var SocialToolbar = {
     notifBrowser.addEventListener("DOMContentLoaded", function onload() {
       notifBrowser.removeEventListener("DOMContentLoaded", onload);
       sizePanelToContent();
     });
 
     panel.addEventListener("popuphiding", function onpopuphiding() {
       panel.removeEventListener("popuphiding", onpopuphiding);
       // unload the panel
-      document.getElementById("social-toolbar-button").removeAttribute("open");
+      SocialToolbar.button.removeAttribute("open");
       notifBrowser.setAttribute("src", "about:blank");
     });
 
     notifBrowser.setAttribute("origin", Social.provider.origin);
     notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
-    document.getElementById("social-toolbar-button").setAttribute("open", "true");
+    this.button.setAttribute("open", "true");
     panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
   }
 }
 
 var SocialSidebar = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SocialSidebar_init() {
     this.updateSidebar();
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -177,16 +177,54 @@
                 class="editBookmarkPanelBottomButton"
                 label="&editBookmark.done.label;"
                 default="true"
                 oncommand="StarUI.panel.hidePopup();"/>
 #endif
       </hbox>
     </panel>
 
+    <panel id="socialActivatedNotification"
+           type="arrow"
+           hidden="true"
+           consumeoutsideclicks="true"
+           align="start"
+           role="alert">
+      <hbox flex="1">
+        <image src="chrome://browser/content/social-icon.png" class="popup-notification-icon"/>
+        <vbox flex="1">
+          <description id="social-activation-message" class="popup-notification-description"/>
+          <spacer flex="1"/>
+          <hbox pack="end" align="center" class="popup-notification-button-container">
+#ifdef XP_UNIX
+        <button id="social-undoactivation-button"
+                label="&social.activated.button.label;"
+                accesskey="&social.activated.button.accesskey;"
+                onclick="SocialUI.undoActivation();"/>
+        <button default="true"
+                autofocus="autofocus"
+                label="&social.ok.label;"
+                accesskey="&social.ok.accesskey;"
+                oncommand="SocialUI.notificationPanel.hidePopup();"/>
+#else
+        <button default="true"
+                autofocus="autofocus"
+                label="&social.ok.label;"
+                accesskey="&social.ok.accesskey;"
+                oncommand="SocialUI.notificationPanel.hidePopup();"/>
+        <button id="social-undoactivation-button"
+                label="&social.activated.button.label;"
+                accesskey="&social.activated.button.accesskey;"
+                onclick="SocialUI.undoActivation();"/>
+#endif
+          </hbox>
+        </vbox>
+      </hbox>
+    </panel>
+
     <panel id="editSharePopup"
            type="arrow"
            orient="vertical"
            ignorekeys="true"
            hidden="true"
            onpopupshown="SocialShareButton.panelShown(event);"
            consumeoutsideclicks="true"
            level="top">
@@ -209,26 +247,26 @@
                 class="editSharePopupBottomButton"
                 label="&social.sharePopup.undo.label;"
                 accesskey="&social.sharePopup.undo.accesskey;"
                 command="Social:UnsharePage"/>
         <button id="editSharePopupOkButton"
                 class="editSharePopupBottomButton"
                 default="true"
                 autofocus="autofocus"
-                label="&social.sharePopup.ok.label;"
-                accesskey="&social.sharePopup.ok.accesskey;"
+                label="&social.ok.label;"
+                accesskey="&social.ok.accesskey;"
                 oncommand="SocialShareButton.dismissSharePopup();"/>
 #else
         <button id="editSharePopupOkButton"
                 class="editSharePopupBottomButton"
                 default="true"
                 autofocus="autofocus"
-                label="&social.sharePopup.ok.label;"
-                accesskey="&social.sharePopup.ok.accesskey;"
+                label="&social.ok.label;"
+                accesskey="&social.ok.accesskey;"
                 oncommand="SocialShareButton.dismissSharePopup();"/>
         <button id="editSharePopupUndoButton"
                 class="editSharePopupBottomButton"
                 label="&social.sharePopup.undo.label;"
                 accesskey="&social.sharePopup.undo.accesskey;"
                 command="Social:UnsharePage"/>
 #endif
       </hbox>
@@ -633,16 +671,18 @@
                 <image id="social-statusarea-user-portrait"/>
                 <vbox>
                   <label id="social-statusarea-notloggedin"
                          value="&social.notLoggedIn.label;"/>
                   <button id="social-statusarea-username"
                           oncommand="SocialUI.showProfile(); document.getElementById('social-statusarea-popup').hidePopup();"/>
                 </vbox>
               </hbox>
+              <menuitem id="social-remove-menuitem"
+                        oncommand="Social.active = false;"/>
               <menuitem id="social-toggle-sidebar-menuitem"
                         type="checkbox"
                         autocheck="false"
                         command="Social:ToggleSidebar"
                         label="&social.toggleSidebar.label;"
                         accesskey="&social.toggleSidebar.accesskey;"/>
             </menupopup>
           </button>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..37e54a1e9a0637be9a078eb4e51465eb609a3174
GIT binary patch
literal 2166
zc$|G!X;f3!8VyLO$O9r!A6UiPFqA$d6Cg<>Ku8#Z#3DoqwhS3=NPr9^mym!1ASe`4
z1{IkVtEC1-5FZY>Bmn_Ir7A@M6~Q7P3RtIywn7sX-&=1jd)B@8obOwEe`lZX>>oEb
zbYq~|vX#qVFqj!Fh#IDwt@ZCxW8GJkyV^`Q*+TwIC|t~gQdm+DM&^pyAV3qc;=nMF
z#Z@MCgI+M$5~P5^gqZXYB1bGlvGf>}LMVahhnJ5+!r~-=5WoiG1R@f0wxtyb2)HC<
zga;i%mry{yAShJ|hNo_1a8eUE1TNCY8}L#Pbp?bV!~zt;M3IcBAR*t?CF<7tG#UxK
zgFp!+<a<#}dMH2<OF_T`g>mIz)?t8kSQOUH-P6-^Er7#dF=z}9jm5cQJ&A5OA_fC|
z7)af2QZA1eMh*C|mo6e9`4A)_qR}ZSDX0`Tlvo;v#u5kweGMGWRflkuDMb)V;VP2Z
zFIJ#}GLBRrfdpa^ppRK>aWX_gA{UP!lzc2Jl6`2Cu3=~eOM=FtFzEjQ(&>K>6$(G1
zWl$K%`+KyEp_G8=Fi<8=mU46#$FtXyB}9r8WI<vnLo7~Q>|!Wi42flYu>_!mdjND6
zM<CM2@9=awktUKsED;B!QAtQ$1|<-1iFkJpcYimWpPxI{AFF%(+^7Vyo4-58k4&Ki
zV6lr_s+f~31Vzvym-}BX<&#{!72dN!sXz{L1EgXh@b1V&!KbwlKCR_Fm-}fg<WF+Z
zIx*<~yXeJ~&OQ3&N89RxkH!Z@I=4%8wywTE2f$!PQ#2}>p%~h>IU&&+v?e_tsu~=e
zP81xFM+RT{F+FyJA~J)Gh5zH%tq)3!)y>QO9USIEY5RiOEtFaO2Nv2(&c;iAW|}w~
z9Al`zL|DOx!v1|U^iAv^LpP`8Ynqzenueq7eH8eeJe;gm_RG2d++81nEYh^sH{VKl
z9kVkzaXY84<EH3-Xmlp4XrfHf!tH+WQ%{fD$~3R!H0jAInNO@U-l>0jo4BiHcE>P|
zcW|cdNLhLxoT&ip-~s1r<`(Q+U0(b;tFF7V*C(xaI?!<V(c|u|P0bfBCWn4KUP7{{
z?aOuU@&%QpD-5<&7!5nwUk#I7IVt(hd)?F5^HmkMBU+(12AbjOndAHGstNa4RjqvO
zGaTMggIb=mIbAEYxn+AgVeM|b0pi5SerPg-HKO_AcTU=w2;p(%>oJl>n=zkX8(b|q
z`)He#%(@Y8v(;#~psnXr(B2c0IQ&RAq#0A5&a$bzjmK<pG1`>5PV(7Z?Fmjq?<(}a
zDq9<>V06ajEq3$GyH0jTMQ6kU>4iVFAE7!GeS=9?aj+`igQfdb$3*ZdHGI!5YG9sL
z`_yLP#PXx_oqc9z6Fui19QN;+-4V9HdZUgQ@O8*9G%39la;Ut~;Wny}%O1~*KkJP*
zFRM0n8Z4sZmd^%gs6q5`E)+F~-Pv)s@*tjMcYiRxJBFL|3w7Xnqr<ma_XAdxBrA2b
zZ@%-?KG;6ZnBsIn*60Y_%X`p(+<ya$GdHDS+pqzXEtU@%dzA|_Pc}#L%B^_Rj`@jY
z4JqL!@g=>QCOE;lw9>qQlBr30y2%jH-g{_SL3k(QKz{Xl#^F#SC;X-P_y>gEl4eR(
zxH?A;PhxAc7>c}SvFX`qnPx7gUd%Ii3pA=C!)s5@nxVHrOINvvVcLJAA}uMkVxw)v
z4^>yz)?H?6xRyD=NZ?M8-_jK&+R+VBb7OviJz>dlcfylhON$MHxVF!JQ<dfpC#|+c
z!Hes6sXA&N8+Y|qc)VR{xC8-~O>xQc@_oghf2l;ZP+!qTLcT#5AA1=H6=F>oSsNR-
z7vXIpGgZOIRiBMEm>9^Tl!G)VDx23-3+of!vaa*Byv}kowJinm3gO113MBk8lcsV;
zmX06}2SoCFM_aPn{;cFRx3$ba;p{%?zvfZxRXKMk%Q|)dmhs$(-RAddbn+hm)Ysf`
zd<GVZ$o0L<jqP+k`#6Q6borsl+>vyCyX=}>rI&BhcsjX>h`5PxJVg6G2ftdvT%cQq
z7&?9N6~blfief$)&yH=Fwz%2@)~D93s}BBw5br5|%@dZ$S4|X*{5;nAy;T(-*t7H1
zgpIj}MdnKLos2+CcUEoEk?a~KK1aU(d_{%!J0JCq)Tck5IF(p%?_2ZvQSwpfWx1Q{
z^9vg`MVrRC=lh0i*e+Y1(-pj>W+3{S(Pl(hulptA)Eh5LJmq7WnW?EE`d4<$m|br#
zzA)?Wk8#HmK5sJ>Bk$~oM}=z(T|4=a1GdJ7^xP2e_xthflNWFI+ouf=HZ;onjs>Ea
z_I7dJ1836ibiItbKXWCfBrn@h(o!30MU|Y-V6|FI9hH^d9J;<kGFvYMA74-{v@|ZX
zy!j&)H~G&I;oL*^;I*2@bL1t06;pBb$mHXZoBn)TcT)IT%5F}3F)v$Kih-r8P1}o8
SO``RG0yO`P)Ox?z%)bDuBY(vJ
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -253,16 +253,20 @@ endif
                  browser_aboutSyncProgress.js \
                  browser_middleMouse_inherit.js \
                  redirect_bug623155.sjs \
                  browser_tabDrop.js \
                  browser_lastAccessedTab.js \
                  browser_bug734076.js \
                  browser_social_toolbar.js \
                  browser_social_sidebar.js \
+                 browser_social_mozSocial_API.js \
+                 social_panel.html \
+                 social_sidebar.html \
+                 social_worker.js \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
 else
 _BROWSER_FILES += \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_social_mozSocial_API.js
@@ -0,0 +1,87 @@
+/* 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/. */
+
+let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+
+function test() {
+  // XXX Bug 775779
+  if (Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2).isDebugBuild) {
+    ok(true, "can't run social sidebar test in debug builds because they falsely report leaks");
+    return;
+  }
+
+  waitForExplicitFinish();
+
+  let manifest = { // normal provider
+    name: "provider 1",
+    origin: "http://example.com",
+    sidebarURL: "http://example.com/browser/browser/base/content/test/social_sidebar.html",
+    workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
+    iconURL: "chrome://branding/content/icon48.png"
+  };
+  runSocialTestWithProvider(manifest, doTest);
+}
+
+function doTest() {
+  let iconsReady = false;
+  let gotSidebarMessage = false;
+
+  function checkNext() {
+    if (iconsReady && gotSidebarMessage)
+      triggerIconPanel();
+  }
+
+  function triggerIconPanel() {
+    let statusIcons = document.getElementById("social-status-iconbox");
+    ok(!statusIcons.firstChild.collapsed, "status icon is visible");
+    // Click the button to trigger its contentPanel
+    let panel = document.getElementById("social-notification-panel");
+    EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
+  }
+
+  let port = Social.provider.port;
+  ok(port, "provider has a port");
+  port.postMessage({topic: "test-init"});
+  Social.provider.port.onmessage = function (e) {
+    let topic = e.data.topic;
+    switch (topic) {
+      case "got-panel-message":
+        ok(true, "got panel message");
+        // Wait for the panel to close before ending the test
+        let panel = document.getElementById("social-notification-panel");
+        panel.addEventListener("popuphidden", function hiddenListener() {
+          panel.removeEventListener("popuphidden", hiddenListener);
+          SocialService.removeProvider(Social.provider.origin, finish);
+        });
+        panel.hidePopup();
+        break;
+      case "got-sidebar-message":
+        // The sidebar message will always come first, since it loads by default
+        ok(true, "got sidebar message");
+        info(topic);
+        gotSidebarMessage = true;
+        checkNext();
+        break;
+    }
+  }
+
+  // Our worker sets up ambient notification at the same time as it responds to
+  // the workerAPI initialization. If it's already initialized, we can
+  // immediately check the icons, otherwise wait for initialization by
+  // observing the topic sent out by the social service.
+  if (Social.provider.workerAPI.initialized) {
+    iconsReady = true;
+    checkNext();
+  } else {
+    Services.obs.addObserver(function obs() {
+      Services.obs.removeObserver(obs, "social:ambient-notification-changed");
+      // Let the other observers (like the one that updates the UI) run before
+      // checking the icons.
+      executeSoon(function () {
+        iconsReady = true;
+        checkNext();
+      });
+    }, "social:ambient-notification-changed", false);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social_panel.html
@@ -0,0 +1,14 @@
+<html>
+  <head>
+    <meta charset="utf-8">
+    <script>
+      function pingWorker() {
+        var port = navigator.mozSocial.getWorker().port;
+        port.postMessage({topic: "panel-message", result: "ok"});
+      }
+    </script>
+  </head>
+  <body onload="pingWorker();">
+    <p>This is a test social panel.</p>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social_sidebar.html
@@ -0,0 +1,14 @@
+<html>
+  <head>
+    <meta charset="utf-8">
+    <script>
+      function pingWorker() {
+        var port = navigator.mozSocial.getWorker().port;
+        port.postMessage({topic: "sidebar-message", result: "ok"});
+      }
+    </script>
+  </head>
+  <body onload="pingWorker();">
+    <p>This is a test social sidebar.</p>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social_worker.js
@@ -0,0 +1,40 @@
+/* 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/. */
+
+let testPort;
+
+onconnect = function(e) {
+  let port = e.ports[0];
+  port.onmessage = function onMessage(event) {
+    let topic = event.data.topic;
+    switch (topic) {
+      case "test-init":
+        testPort = port;
+        break;
+      case "sidebar-message":
+        if (testPort && event.data.result == "ok")
+          testPort.postMessage({topic:"got-sidebar-message"});
+        break;
+      case "panel-message":
+        if (testPort && event.data.result == "ok")
+          testPort.postMessage({topic:"got-panel-message"});
+        break;
+      case "social.initialize":
+        // This is the workerAPI port, respond and set up a notification icon.
+        port.postMessage({topic: "social.initialize-response"});
+        let profile = {
+          userName: "foo"
+        };
+        port.postMessage({topic: "social.user-profile", data: profile});
+        let icon = {
+          name: "testIcon",
+          iconURL: "chrome://branding/content/icon48.png",
+          contentPanel: "http://example.com/browser/browser/base/content/test/social_panel.html",
+          counter: 1
+        };
+        port.postMessage({topic: "social.ambient-notification", data: icon});
+        break;
+    }
+  }
+}
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -96,11 +96,12 @@ browser.jar:
 *       content/browser/downloadManagerOverlay.xul    (content/downloadManagerOverlay.xul)
 *       content/browser/jsConsoleOverlay.xul          (content/jsConsoleOverlay.xul)
 *       content/browser/softwareUpdateOverlay.xul  (content/softwareUpdateOverlay.xul)
 #endif
 *       content/browser/viewSourceOverlay.xul         (content/viewSourceOverlay.xul)
 #ifdef XP_WIN
 *       content/browser/win6BrowserOverlay.xul        (content/win6BrowserOverlay.xul)
 #endif
+        content/browser/social-icon.png               (content/social-icon.png)
 # the following files are browser-specific overrides
 *       content/browser/license.html                  (/toolkit/content/license.html)
 % override chrome://global/content/license.html chrome://browser/content/license.html
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -63,17 +63,17 @@ PlacesViewBase.prototype = {
 
     if (this._rootElt.localName == "menupopup")
       this._rootElt._built = false;
 
     this._result = val;
     if (val) {
       this._resultNode = val.root;
       this._rootElt._placesNode = this._resultNode;
-      this._domNodes = new WeakMap();
+      this._domNodes = new Map();
       this._domNodes.set(this._resultNode, this._rootElt);
 
       // This calls _rebuild through invalidateContainer.
       this._resultNode.containerOpen = true;
     }
     else {
       this._resultNode = null;
       delete this._domNodes;
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -75,17 +75,17 @@ function PlacesController(aView) {
   this._view = aView;
   XPCOMUtils.defineLazyServiceGetter(this, "clipboard",
                                      "@mozilla.org/widget/clipboard;1",
                                      "nsIClipboard");
   XPCOMUtils.defineLazyGetter(this, "profileName", function () {
     return Services.dirsvc.get("ProfD", Ci.nsIFile).leafName;
   });
 
-  this._cachedLivemarkInfoObjects = new WeakMap();
+  this._cachedLivemarkInfoObjects = new Map();
 }
 
 PlacesController.prototype = {
   /**
    * The places view.
    */
   _view: null,
 
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -46,17 +46,17 @@ PlacesTreeView.prototype = {
     return this.__dateService;
   },
 
   QueryInterface: XPCOMUtils.generateQI(PTV_interfaces),
 
   // Bug 761494:
   // ----------
   // Some addons use methods from nsINavHistoryResultObserver and
-  // nsINavHistoryResultTreeViewer, without QIing to these intefaces first.
+  // nsINavHistoryResultTreeViewer, without QIing to these interfaces first.
   // That's not a problem when the view is retrieved through the
   // <tree>.view getter (which returns the wrappedJSObject of this object),
   // it raises an issue when the view retrieved through the treeBoxObject.view
   // getter.  Thus, to avoid breaking addons, the interfaces are prefetched.
   classInfo: XPCOMUtils.generateCI({ interfaces: PTV_interfaces }),
 
   /**
    * This is called once both the result and the tree are set.
@@ -148,22 +148,31 @@ PlacesTreeView.prototype = {
    * container, this method will just return a calculated row value, without
    * making assumptions on existence of the node at that position.
    * @return aNode's row if it's in the rows list or if aForceBuild is set, -1
    *         otherwise.
    */
   _getRowForNode:
   function PTV__getRowForNode(aNode, aForceBuild, aParentRow, aNodeIndex) {
     if (aNode == this._rootNode)
-      throw "The root node is never visible";
+      throw new Error("The root node is never visible");
 
-    let ancestors = PlacesUtils.nodeAncestors(aNode);
-    for (let ancestor in ancestors) {
+    // A node is removed form the view either if it has no parent or if its
+    // root-ancestor is not the root node (in which case that's the node
+    // for which nodeRemoved was called).
+    let ancestors = [x for each (x in PlacesUtils.nodeAncestors(aNode))];
+    if (ancestors.length == 0 ||
+        ancestors[ancestors.length - 1] != this._rootNode) {
+      throw new Error("Removed node passed to _getRowForNode");
+    }
+
+    // Ensure that the entire chain is open, otherwise that node is invisible.
+    for (let ancestor of ancestors) {
       if (!ancestor.containerOpen)
-        throw "Invisible node passed to _getRowForNode";
+        throw new Error("Invisible node passed to _getRowForNode");
     }
 
     // Non-plain containers are initially built with their contents.
     let parent = aNode.parent;
     let parentIsPlain = this._isPlainContainer(parent);
     if (!parentIsPlain) {
       if (parent == this._rootNode)
         return this._rows.indexOf(aNode);
@@ -1092,17 +1101,17 @@ PlacesTreeView.prototype = {
     if (this._result) {
       this._result.removeObserver(this);
       this._rootNode.containerOpen = false;
     }
 
     if (val) {
       this._result = val;
       this._rootNode = this._result.root;
-      this._cellProperties = new WeakMap();
+      this._cellProperties = new Map();
       this._cuttingNodes = new Set();
     }
     else if (this._result) {
       delete this._result;
       delete this._rootNode;
       delete this._cellProperties;
       delete this._cuttingNodes;
     }
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -652,16 +652,26 @@ doesn't display any label, but exposes a
 <!ENTITY markupButton.arialabel          "Markup">
 <!-- LOCALIZATION NOTE (markupButton.accesskey): The key bound to the Markup panel's
 toolbar button -->
 <!ENTITY markupButton.accesskey          "M">
 
 <!ENTITY socialToolbar.title        "Social Toolbar Button">
 <!ENTITY social.notLoggedIn.label   "Not logged in">
 
+<!-- LOCALIZATION NOTE (social.ok.label, social.ok.accesskey): this string is
+     used for the "OK" button for two different social panels. One appears when
+     the feature is activated (social.activated.* below), and the other when
+     the user clicks the "Share" button a second time (social.sharePopup.*
+     below). -->
+<!ENTITY social.ok.label       "OK">
+<!ENTITY social.ok.accesskey   "O">
+
 <!ENTITY social.sharePopup.undo.label     "Unshare">
 <!ENTITY social.sharePopup.undo.accesskey "U">
-<!ENTITY social.sharePopup.ok.label       "OK">
-<!ENTITY social.sharePopup.ok.accesskey   "O">
 <!ENTITY social.sharePopup.shared.label   "You shared this page.">
 <!ENTITY social.sharePopup.portrait.arialabel "User profile picture">
+
 <!ENTITY social.toggleSidebar.label "Show sidebar">
 <!ENTITY social.toggleSidebar.accesskey "s">
+
+<!ENTITY social.activated.button.label "Oops, undo">
+<!ENTITY social.activated.button.accesskey "u">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -367,8 +367,19 @@ telemetryOptOutPrompt = %1$S sends infor
 # LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
 fullscreen.entered=%S is now fullscreen.
 # LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
 fullscreen.rememberDecision=Remember decision for %S
 
 social.shareButton.tooltip=Share this
 social.shareButton.sharedtooltip=You shared this
 social.pageShared.label=Page shared
+
+# LOCALIZATION NOTE (social.enable.label): %S = Social networking provider
+social.enable.label=%S integration
+social.enable.accesskey=n
+
+# LOCALIZATION NOTE (social.remove.label): %S = brandShortName
+social.remove.label=Remove from %S
+social.remove.accesskey=R
+
+# LOCALIZATION NOTE (social.enabled.message): %1$S is the name of the social provider, %2$S is brandShortName (e.g. Firefox)
+social.activated.message=%1$S integration with %2$S has been activated.
--- a/browser/modules/Social.jsm
+++ b/browser/modules/Social.jsm
@@ -12,16 +12,17 @@ const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
   "resource://gre/modules/SocialService.jsm");
 
 let Social = {
+  lastEventReceived: 0,
   provider: null,
   init: function Social_init(callback) {
     if (this.provider) {
       schedule(callback);
       return;
     }
 
     // Eventually this might want to retrieve a specific provider, but for now
@@ -33,16 +34,35 @@ let Social = {
       Services.obs.notifyObservers(null, "test-social-ui-ready", "");
     }.bind(this));
   },
 
   get uiVisible() {
     return this.provider && this.provider.enabled && this.provider.port;
   },
 
+  set enabled(val) {
+    SocialService.enabled = val;
+  },
+  get enabled() {
+    return SocialService.enabled;
+  },
+
+  get active() {
+    return Services.prefs.getBoolPref("social.active");
+  },
+  set active(val) {
+    Services.prefs.setBoolPref("social.active", !!val);
+    this.enabled = !!val;
+  },
+
+  toggle: function Social_toggle() {
+    this.enabled = !this.enabled;
+  },
+
   toggleSidebar: function SocialSidebar_toggle() {
     let prefValue = Services.prefs.getBoolPref("social.sidebar.open");
     Services.prefs.setBoolPref("social.sidebar.open", !prefValue);
   },
 
   sendWorkerMessage: function Social_sendWorkerMessage(message) {
     // Responses aren't handled yet because there is no actions to perform
     // based on the response from the provider at this point.
--- a/build/virtualenv/packages.txt
+++ b/build/virtualenv/packages.txt
@@ -1,9 +1,9 @@
 setup.py:other-licenses/simplejson-2.1.1:develop
 setup.py:testing/mozbase/manifestdestiny:develop
 setup.py:testing/mozbase/mozinfo:develop
 setup.py:testing/mozbase/mozinstall:develop
 setup.py:testing/mozbase/mozlog:develop
 setup.py:testing/mozbase/mozprocess:develop
 setup.py:testing/mozbase/mozprofile:develop
 setup.py:testing/mozbase/mozrunner:develop
-setup.py:build/pylib/blessings:develop
+setup.py:python/blessings:develop
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -286,21 +286,19 @@ HOST_CMMOBJS = $(addprefix host_,$(HOST_
 ifndef HOST_OBJS
 _HOST_OBJS = $(HOST_COBJS) $(HOST_CCOBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
 HOST_OBJS = $(strip $(_HOST_OBJS))
 endif
 
 ifndef MOZ_AUTO_DEPS
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp))
-ifndef NO_GEN_XPT
 MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
 endif
 endif
-endif
 
 ALL_TRASH = \
 	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
 	$(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
 	$(OBJS:.$(OBJ_SUFFIX)=.i) $(OBJS:.$(OBJ_SUFFIX)=.i_o) \
 	$(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\
 	$(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \
 	$(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \
@@ -1293,17 +1291,16 @@ xpidl-preqs = \
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
 	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  $(PLY_INCLUDE) \
 	  $(LIBXUL_DIST)/sdk/bin/header.py $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
-ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
 # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
 $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
 	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  $(PLY_INCLUDE) \
 	  -I$(topsrcdir)/xpcom/typelib/xpt/tools \
 	  $(LIBXUL_DIST)/sdk/bin/typelib.py $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
@@ -1318,18 +1315,16 @@ libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).
 ifndef NO_DIST_INSTALL
 	$(call install_cmd,$(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components)
 ifndef NO_INTERFACES_MANIFEST
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt"
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
 endif
 endif
 
-endif # NO_GEN_XPT
-
 GARBAGE_DIRS		+= $(XPIDL_GEN_DIR)
 
 endif #} XPIDLSRCS
 
 
 ifndef INCLUDED_XPIDL_MK
   include $(topsrcdir)/config/makefiles/xpidl.mk
 endif
--- a/configure.in
+++ b/configure.in
@@ -358,16 +358,20 @@ else
     if test -z "$HOST_AR"; then
         HOST_AR="$AR"
     fi
     if test -z "$HOST_AR_FLAGS"; then
         HOST_AR_FLAGS="$AR_FLAGS"
     fi
 fi
 
+if test -n "$MOZ_WINCONSOLE"; then
+    AC_DEFINE(MOZ_WINCONSOLE)
+fi
+
 MOZ_TOOL_VARIABLES
 
 dnl ========================================================
 dnl Special win32 checks
 dnl ========================================================
 
 # With win8, sdk target=602, WINVER=602
 MOZ_ARG_ENABLE_BOOL(metro,
@@ -4201,16 +4205,17 @@ NECKO_COOKIES=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 MOZ_ANDROID_HISTORY=
 MOZ_WEBSMS_BACKEND=
 MOZ_GRAPHITE=1
 ACCESSIBILITY=1
+MOZ_SYS_MSG=
 
 case "$target_os" in
     mingw*)
         NS_ENABLE_TSF=1
         AC_DEFINE(NS_ENABLE_TSF)
         ;;
 esac
 
@@ -7308,36 +7313,38 @@ fi
 dnl ========================================================
 dnl = Enable Radio Interface for B2G (Gonk usually)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(b2g-ril,
 [  --enable-b2g-ril      Set compile flags necessary for testing B2G Radio Interface Layer via network sockets ],
     MOZ_B2G_RIL=1,
     MOZ_B2G_RIL= )
 if test -n "$MOZ_B2G_RIL"; then
-   AC_DEFINE(MOZ_B2G_RIL)
+    AC_DEFINE(MOZ_B2G_RIL)
 fi
 AC_SUBST(MOZ_B2G_RIL)
 
 dnl ========================================================
 dnl = Enable Bluetooth Interface for B2G (Gonk usually)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(b2g-bt,
 [  --enable-b2g-bt      Set compile flags necessary for compiling Bluetooth API for B2G ],
     MOZ_B2G_BT=1,
     MOZ_B2G_BT= )
 if test -n "$MOZ_B2G_BT"; then
-   AC_DEFINE(MOZ_B2G_BT)
+    AC_DEFINE(MOZ_B2G_BT)
 fi
 AC_SUBST(MOZ_B2G_BT)
 
 dnl ========================================================
 dnl = Enable Support for System Messages API
 dnl ========================================================
-
+if test -n "$MOZ_SYS_MSG"; then
+    AC_DEFINE(MOZ_SYS_MSG)
+fi
 AC_SUBST(MOZ_SYS_MSG)
 
 dnl ========================================================
 dnl = Support for demangling undefined symbols
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     AC_LANG_SAVE
     AC_LANG_CPLUSPLUS
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -173,18 +173,16 @@ MOCHITEST_FILES_A = \
 		test_bug424212.html \
 		test_bug425013.html \
 		bug426308-redirect.sjs \
 		test_bug426308.html \
 		test_bug426646.html \
 		file_bug426646-1.html \
 		file_bug426646-2.html \
 		test_bug429157.html \
-		test_header.html \
-		header.sjs \
 		test_XHR.html \
 		file_XHR_pass1.xml \
 		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 \
deleted file mode 100644
--- a/content/base/test/header.sjs
+++ /dev/null
@@ -1,8 +0,0 @@
-function handleRequest(request, response) {
-  response.setHeader("Content-Type", "text/plain", false);
-  response.setHeader("Cache-Control", "no-cache", false);
-
-  var value = request.hasHeader("SomeHeader") ? request.getHeader("SomeHeader")
-                                             : "";
-  response.write("SomeHeader: " + value);
-}
deleted file mode 100644
--- a/content/base/test/test_header.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for XHR header preservation</title>
-  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-    /** Test for Bug 421622 **/
-    const SJS_URL = "http://mochi.test:8888/tests/content/base/test/header.sjs";
-    const VALUE = "http://www.mozilla.org/";
-
-    var req = new XMLHttpRequest();
-    req.open("GET", SJS_URL, false);
-    req.setRequestHeader("SomeHeader", VALUE);
-    req.send(null);
-
-    is(req.responseText,
-       "SomeHeader: " + VALUE,
-       "Header received by server does not match what was set");
-</script>
-</pre>
-</body>
-</html>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -4897,16 +4897,23 @@ nsDocShell::GetParentNativeWindow(native
 
 NS_IMETHODIMP
 nsDocShell::SetParentNativeWindow(nativeWindow parentNativeWindow)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+nsDocShell::GetNativeHandle(nsAString& aNativeHandle)
+{
+    // the nativeHandle should be accessed from nsIXULWindow
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsDocShell::GetVisibility(bool * aVisibility)
 {
     NS_ENSURE_ARG_POINTER(aVisibility);
 
     *aVisibility = false;
 
     if (!mContentViewer)
         return NS_OK;
--- a/dom/alarm/AlarmService.jsm
+++ b/dom/alarm/AlarmService.jsm
@@ -223,34 +223,34 @@ let AlarmService = {
       ppmm.sendAsyncMessage("AlarmsManager:" + aMessageName, json);
   },
 
   _onAlarmFired: function _onAlarmFired() {
     debug("_onAlarmFired()");
 
     if (this._currentAlarm) {
       debug("Fire system intent: " + JSON.stringify(this._currentAlarm));
-      if (this._currentAlarm.manifestURL)
-        messenger.sendMessage("alarm", this._currentAlarm, this._currentAlarm.manifestURL);
+      let manifestURI = Services.io.newURI(this._currentAlarm.manifestURL, null, null);
+      messenger.sendMessage("alarm", this._currentAlarm, manifestURI);
       this._currentAlarm = null;
     }
 
     // reset the next alarm from the queue
     let nowTime = Date.now();
     let alarmQueue = this._alarmQueue;
     while (alarmQueue.length > 0) {
       let nextAlarm = alarmQueue.shift();
       let nextAlarmTime = this._getAlarmTime(nextAlarm);
 
       // if the next alarm has been expired, directly 
       // fire system intent for it instead of setting it
       if (nextAlarmTime <= nowTime) {
         debug("Fire system intent: " + JSON.stringify(nextAlarm));
-        if (nextAlarm.manifestURL)
-          messenger.sendMessage("alarm", nextAlarm, nextAlarm.manifestURL);
+        let manifestURI = Services.io.newURI(nextAlarm.manifestURL, null, null);
+        messenger.sendMessage("alarm", nextAlarm, manifestURI);
       } else {
         this._currentAlarm = nextAlarm;
         break;
       }
     }
     this._debugCurrentAlarm();
   },
 
--- a/dom/alarm/AlarmsManager.js
+++ b/dom/alarm/AlarmsManager.js
@@ -40,16 +40,21 @@ AlarmsManager.prototype = {
                                       contractID: ALARMSMANAGER_CONTRACTID,
                                       classDescription: "AlarmsManager",
                                       interfaces: [nsIDOMMozAlarmsManager],
                                       flags: nsIClassInfo.DOM_OBJECT }),
 
   add: function add(aDate, aRespectTimezone, aData) {
     debug("add()");
 
+    if (!this._manifestURL) {
+      debug("Cannot add alarms for non-installed apps.");
+      throw Components.results.NS_ERROR_FAILURE;
+    }
+
     let isIgnoreTimezone = true;
     switch (aRespectTimezone) {
       case "honorTimezone":
         isIgnoreTimezone = false;
         break;
 
       case "ignoreTimezone":
         isIgnoreTimezone = true;
@@ -145,18 +150,17 @@ AlarmsManager.prototype = {
     this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
 
     // Add the valid messages to be listened.
     this.initHelper(aWindow, ["AlarmsManager:Add:Return:OK", "AlarmsManager:Add:Return:KO", 
                               "AlarmsManager:GetAll:Return:OK", "AlarmsManager:GetAll:Return:KO"]);
 
     // Get the manifest URL if this is an installed app
     this._manifestURL = null;
-    let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Components.interfaces.nsIDOMWindowUtils);
+    let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
     let app = utils.getApp();
     if (app)
       this._manifestURL = app.manifestURL;
   },
 
   // Called from DOMRequestIpcHelper.
   uninit: function uninit() {
     debug("uninit()");
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1293,17 +1293,17 @@ Navigator::GetMozBluetooth(nsIDOMBluetoo
   return NS_OK;
 }
 #endif //MOZ_B2G_BT
 
 //*****************************************************************************
 //    nsNavigator::nsIDOMNavigatorSystemMessages
 //*****************************************************************************
 #ifdef MOZ_SYS_MSG
-NS_IMETHODIMP
+nsresult
 Navigator::EnsureMessagesManager()
 {
   if (mMessagesManager) {
     return NS_OK;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -5968,16 +5968,19 @@ DefineIDBInterfaceConstants(JSContext *c
     interface = IDBConstant::IDBCursor;
   }
   else if (aIID->Equals(NS_GET_IID(nsIIDBRequest))) {
     interface = IDBConstant::IDBRequest;
   }
   else if (aIID->Equals(NS_GET_IID(nsIIDBTransaction))) {
     interface = IDBConstant::IDBTransaction;
   }
+  else {
+    MOZ_NOT_REACHED("unexpected IID");
+  }
 
   for (int8_t i = 0; i < (int8_t)mozilla::ArrayLength(sIDBConstants); ++i) {
     const IDBConstant& c = sIDBConstants[i];
     if (c.interface != interface) {
       continue;
     }
 
     if (!JS_DefineProperty(cx, obj, c.name, JSVAL_VOID,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9395,19 +9395,17 @@ nsGlobalWindow::SetTimeoutOrInterval(nsI
 
     timeout->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     nsRefPtr<nsTimeout> copy = timeout;
 
-    rv = timeout->mTimer->InitWithFuncCallback(TimerCallback, timeout,
-                                               realInterval,
-                                               nsITimer::TYPE_ONE_SHOT);
+    rv = timeout->InitTimer(TimerCallback, realInterval);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     // The timeout is now also held in the timer's closure.
     copy.forget();
   } else {
     // If we are frozen, however, then we instead simply set
@@ -9632,20 +9630,17 @@ nsGlobalWindow::RescheduleTimeout(nsTime
   // Reschedule the OS timer. Don't bother returning any error codes if
   // this fails since the callers of this method don't care about them.
 
   // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
   // PRTime to make the division do the right thing on 64-bit
   // platforms whether delay is positive or negative (which we
   // know is always positive here, but cast anyways for
   // consistency).
-  nsresult rv = aTimeout->mTimer->
-    InitWithFuncCallback(TimerCallback, aTimeout,
-                         delay.ToMilliseconds(),
-                         nsITimer::TYPE_ONE_SHOT);
+  nsresult rv = aTimeout->InitTimer(TimerCallback, delay.ToMilliseconds());
 
   if (NS_FAILED(rv)) {
     NS_ERROR("Error initializing timer for DOM timeout!");
 
     // We failed to initialize the new OS timer, this timer does
     // us no good here so we just cancel it (just in case) and
     // null out the pointer to the OS timer, this will release the
     // OS timer. As we continue executing the code below we'll end
@@ -9977,21 +9972,17 @@ nsresult nsGlobalWindow::ResetTimersForN
       PR_REMOVE_LINK(timeout);
       // InsertTimeoutIntoList will addref |timeout| and reset
       // mFiringDepth.  Make sure to undo that after calling it.
       PRUint32 firingDepth = timeout->mFiringDepth;
       InsertTimeoutIntoList(timeout);
       timeout->mFiringDepth = firingDepth;
       timeout->Release();
 
-      nsresult rv =
-        timeout->mTimer->InitWithFuncCallback(TimerCallback,
-                                              timeout,
-                                              delay.ToMilliseconds(),
-                                              nsITimer::TYPE_ONE_SHOT);
+      nsresult rv = timeout->InitTimer(TimerCallback, delay.ToMilliseconds());
 
       if (NS_FAILED(rv)) {
         NS_WARNING("Error resetting non background timer for DOM timeout!");
         return rv;
       }
 
       timeout = nextTimeout;
     } else {
@@ -10494,18 +10485,17 @@ nsGlobalWindow::ResumeTimeouts(bool aTha
 
       // Set mWhen back to the time when the timer is supposed to
       // fire.
       t->mWhen = now + t->mTimeRemaining;
 
       t->mTimer = do_CreateInstance("@mozilla.org/timer;1");
       NS_ENSURE_TRUE(t->mTimer, NS_ERROR_OUT_OF_MEMORY);
 
-      rv = t->mTimer->InitWithFuncCallback(TimerCallback, t, delay,
-                                           nsITimer::TYPE_ONE_SHOT);
+      rv = t->InitTimer(TimerCallback, delay);
       if (NS_FAILED(rv)) {
         t->mTimer = nsnull;
         return rv;
       }
 
       // Add a reference for the new timer's closure.
       t->AddRef();
     }
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -148,16 +148,21 @@ struct nsTimeout : PRCList
     return static_cast<nsTimeout*>(PR_NEXT_LINK(this));
   }
 
   nsTimeout* Prev() {
     // Note: might not actually return an nsTimeout.  Use IsTimeout to check.
     return static_cast<nsTimeout*>(PR_PREV_LINK(this));
   }
 
+  nsresult InitTimer(nsTimerCallbackFunc aFunc, PRUint64 delay) {
+    return mTimer->InitWithFuncCallback(aFunc, this, delay,
+                                        nsITimer::TYPE_ONE_SHOT);
+  }
+
   // Window for which this timeout fires
   nsRefPtr<nsGlobalWindow> mWindow;
 
   // The actual timer object
   nsCOMPtr<nsITimer> mTimer;
 
   // True if the timeout was cleared
   bool mCleared;
--- a/dom/bindings/PrimitiveConversions.h
+++ b/dom/bindings/PrimitiveConversions.h
@@ -75,18 +75,19 @@ struct PrimitiveConversionTraits<int32_t
 template<>
 struct PrimitiveConversionTraits<uint32_t> : PrimitiveConversionTraits_smallInt {
 };
 
 template<>
 struct PrimitiveConversionTraits<bool> {
   typedef JSBool jstype;
   typedef bool intermediateType;
-  static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
-    return JS_ValueToBoolean(cx, v, retval);
+  static inline bool converter(JSContext* /* unused */, JS::Value v, jstype* retval) {
+    *retval = JS::ToBoolean(v);
+    return true;
   }
 };
 
 template<>
 struct PrimitiveConversionTraits<int64_t> {
   typedef int64_t jstype;
   typedef int64_t intermediateType;
   static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -398,18 +398,20 @@ EventFilter(DBusConnection* aConn, DBusM
 
   signalName = NS_ConvertUTF8toUTF16(dbus_message_get_member(aMsg));
   BluetoothValue v;
   
   if (dbus_message_is_signal(aMsg, DBUS_ADAPTER_IFACE, "DeviceFound")) {
 
     DBusMessageIter iter;
 
-    NS_ASSERTION(dbus_message_iter_init(aMsg, &iter),
-                 "Can't create message iterator!");
+    if (!dbus_message_iter_init(aMsg, &iter)) {
+      NS_WARNING("Can't create iterator!");
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
 
     InfallibleTArray<BluetoothNamedValue> value;
     const char* addr;
     dbus_message_iter_get_basic(&iter, &addr);
     value.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING("Address"),
                                             NS_ConvertUTF8toUTF16(addr)));
     
     if (dbus_message_iter_next(&iter)) {
--- a/dom/devicestorage/test/test_basic.html
+++ b/dom/devicestorage/test/test_basic.html
@@ -8,30 +8,40 @@ https://bugzilla.mozilla.org/show_bug.cg
 -->
 <head>
   <title>Test for the device storage API </title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="devicestorage_common.js"></script>
 
 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
-<body>
+<body onunload="unload()">
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717103">Mozilla Bug 717103</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+function unload() {
+  delete gDataBlob;
+  gDataBlob = null;
+
+  delete gFileReader;
+  gFileReader = null;
+}
+
+
 devicestorage_setup();
 
 var gFileName = "devicestorage/hi";
 var gData = "My name is Doug Turner.  My IRC nick is DougT.  I like Maple cookies."
 var gDataBlob = new Blob([gData], {type: 'text/plain'});
+var gFileReader = new FileReader();
 
 function getAfterDeleteSuccess(e) {
   ok(false, "file was deleted not successfully");
   devicestorage_cleanup();
 }
 
 function getAfterDeleteError(e) {
   ok(true, "file was deleted successfully");
@@ -58,19 +68,18 @@ function deleteError(e) {
 function getSuccess(e) {
   var storage = navigator.getDeviceStorage("testing");
   ok(navigator.getDeviceStorage, "Should have getDeviceStorage");
 
   ok(e.target.result.name == gFileName, "File name should match");
 
   var name = e.target.result.name;
 
-  var reader = new FileReader();
-  reader.readAsArrayBuffer(gDataBlob);
-  reader.onload = function(e) {
+  gFileReader.readAsArrayBuffer(gDataBlob);
+  gFileReader.onload = function(e) {
     readerCallback(e);
 
     request = storage[0].delete(name)
     request.onsuccess = deleteSuccess;
     request.onerror = deleteError;
   }
 }
 
--- a/dom/ipc/CrashReporterParent.cpp
+++ b/dom/ipc/CrashReporterParent.cpp
@@ -12,25 +12,25 @@
 using namespace base;
 
 namespace mozilla {
 namespace dom {
 
 void
 CrashReporterParent::ActorDestroy(ActorDestroyReason why)
 {
-#if defined(__ANDROID__) && defined(MOZ_CRASHREPORTER)
+#if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER)
   CrashReporter::RemoveLibraryMappingsForChild(ProcessId(OtherProcess()));
 #endif
 }
 
 bool
 CrashReporterParent::RecvAddLibraryMappings(const InfallibleTArray<Mapping>& mappings)
 {
-#if defined(__ANDROID__) && defined(MOZ_CRASHREPORTER)
+#if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER)
   for (PRUint32 i = 0; i < mappings.Length(); i++) {
     const Mapping& m = mappings[i];
     CrashReporter::AddLibraryMappingForChild(ProcessId(OtherProcess()),
                                              m.library_name().get(),
                                              m.file_id().get(),
                                              m.start_address(),
                                              m.mapping_length(),
                                              m.file_offset());
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -1942,16 +1942,78 @@ nsPluginHost::IsLiveTag(nsIPluginTag* aP
   for (tag = mPlugins; tag; tag = tag->mNext) {
     if (tag == aPluginTag) {
       return true;
     }
   }
   return false;
 }
 
+nsPluginTag*
+nsPluginHost::HaveSamePlugin(const nsPluginTag* aPluginTag)
+{
+  for (nsPluginTag* tag = mPlugins; tag; tag = tag->mNext) {
+    if (tag->HasSameNameAndMimes(aPluginTag)) {
+        return tag;
+    }
+  }
+  return nsnull;
+}
+
+nsPluginTag*
+nsPluginHost::FirstPluginWithPath(const nsCString& path)
+{
+  for (nsPluginTag* tag = mPlugins; tag; tag = tag->mNext) {
+    if (tag->mFullPath.Equals(path)) {
+      return tag;
+    }
+  }
+  return nsnull;
+}
+
+namespace {
+
+PRInt64 GetPluginLastModifiedTime(const nsCOMPtr<nsIFile>& localfile)
+{
+  PRInt64 fileModTime = LL_ZERO;
+
+#if defined(XP_MACOSX)
+  // On OS X the date of a bundle's "contents" (i.e. of its Info.plist file)
+  // is a much better guide to when it was last modified than the date of
+  // its package directory.  See bug 313700.
+  nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(localfile);
+  if (localFileMac) {
+    localFileMac->GetBundleContentsLastModifiedTime(&fileModTime);
+  } else {
+    localfile->GetLastModifiedTime(&fileModTime);
+  }
+#else
+  localfile->GetLastModifiedTime(&fileModTime);
+#endif
+
+  return fileModTime;
+}
+
+struct CompareFilesByTime 
+{
+  bool 
+  LessThan(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const 
+  {
+    return LL_CMP(GetPluginLastModifiedTime(a), <, GetPluginLastModifiedTime(b));
+  }
+
+  bool
+  Equals(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
+  {
+    return LL_EQ(GetPluginLastModifiedTime(a), GetPluginLastModifiedTime(b));
+  }
+};
+
+} // anonymous namespace
+
 typedef NS_NPAPIPLUGIN_CALLBACK(char *, NP_GETMIMEDESCRIPTION)(void);
 
 nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
                                             bool aCreatePluginList,
                                             bool *aPluginsChanged)
 {
   NS_ENSURE_ARG_POINTER(aPluginsChanged);
   nsresult rv;
@@ -1986,41 +2048,30 @@ nsresult nsPluginHost::ScanPluginsDirect
     // See bug 197855.
     dirEntry->Normalize();
 
     if (nsPluginsDir::IsPluginFile(dirEntry)) {
       pluginFiles.AppendElement(dirEntry);
     }
   }
 
+  pluginFiles.Sort(CompareFilesByTime());
+
   bool warnOutdated = false;
 
-  for (PRUint32 i = 0; i < pluginFiles.Length(); i++) {
+  for (PRInt32 i = (pluginFiles.Length() - 1); i >= 0; i--) {
     nsCOMPtr<nsIFile>& localfile = pluginFiles[i];
 
     nsString utf16FilePath;
     rv = localfile->GetPath(utf16FilePath);
     if (NS_FAILED(rv))
       continue;
 
-    PRInt64 fileModTime = LL_ZERO;
-#if defined(XP_MACOSX)
-    // On OS X the date of a bundle's "contents" (i.e. of its Info.plist file)
-    // is a much better guide to when it was last modified than the date of
-    // its package directory.  See bug 313700.
-    nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(localfile);
-    if (localFileMac) {
-      localFileMac->GetBundleContentsLastModifiedTime(&fileModTime);
-    } else {
-      localfile->GetLastModifiedTime(&fileModTime);
-    }
-#else
-    localfile->GetLastModifiedTime(&fileModTime);
-#endif
-
+    PRInt64 fileModTime = GetPluginLastModifiedTime(localfile);
+    
     // Look for it in our cache
     NS_ConvertUTF16toUTF8 filePath(utf16FilePath);
     nsRefPtr<nsPluginTag> pluginTag;
     RemoveCachedPluginsInfo(filePath.get(), getter_AddRefs(pluginTag));
 
     bool enabled = true;
     bool seenBefore = false;
     if (pluginTag) {
@@ -2141,16 +2192,31 @@ nsresult nsPluginHost::ScanPluginsDirect
       }
     }
 
     // do it if we still want it
     if (!seenBefore) {
       // We have a valid new plugin so report that plugins have changed.
       *aPluginsChanged = true;
     }
+    
+    // Avoid adding different versions of the same plugin if they are running 
+    // in-process, otherwise we risk undefined behaviour.
+    if (!nsNPAPIPlugin::RunPluginOOP(pluginTag)) {
+      if (nsPluginTag *duplicate = HaveSamePlugin(pluginTag)) {
+        continue;
+      }
+    }
+    
+    // Don't add the same plugin again if it hasn't changed
+    if (nsPluginTag* duplicate = FirstPluginWithPath(pluginTag->mFullPath)) {
+      if (LL_EQ(pluginTag->mLastModifiedTime, duplicate->mLastModifiedTime)) {
+        continue;
+      }
+    }
 
     // If we're not creating a plugin list, simply looking for changes,
     // then we're done.
     if (!aCreatePluginList) {
       return NS_OK;
     }
 
     pluginTag->SetHost(this);
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -262,16 +262,22 @@ private:
 
   // Given a file path, returns the plugins info from our cache
   // and removes it from the cache.
   void RemoveCachedPluginsInfo(const char *filePath,
                                nsPluginTag **result);
 
   // Checks to see if a tag object is in our list of live tags.
   bool IsLiveTag(nsIPluginTag* tag);
+  
+  // Checks our list of live tags for an equivalent tag.
+  nsPluginTag* HaveSamePlugin(const nsPluginTag * aPluginTag);
+    
+  // Returns the first plugin at |path|
+  nsPluginTag* FirstPluginWithPath(const nsCString& path);
 
   nsresult EnsurePrivateDirServiceProvider();
 
   void OnPluginInstanceDestroyed(nsPluginTag* aPluginTag);
 
   nsRefPtr<nsPluginTag> mPlugins;
   nsRefPtr<nsPluginTag> mCachedPlugins;
   nsRefPtr<nsInvalidPluginTag> mInvalidPlugins;
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -374,16 +374,35 @@ PRUint32 nsPluginTag::Flags()
   return mFlags;
 }
 
 bool nsPluginTag::IsEnabled()
 {
   return HasFlag(NS_PLUGIN_FLAG_ENABLED) && !HasFlag(NS_PLUGIN_FLAG_BLOCKLISTED);
 }
 
+bool
+nsPluginTag::HasSameNameAndMimes(const nsPluginTag *aPluginTag) const
+{
+  NS_ENSURE_TRUE(aPluginTag, false);
+
+  if ((!mName.Equals(aPluginTag->mName)) ||
+      (mMimeTypes.Length() != aPluginTag->mMimeTypes.Length())) {
+    return false;
+  }
+
+  for (PRUint32 i = 0; i < mMimeTypes.Length(); i++) {
+    if (!mMimeTypes[i].Equals(aPluginTag->mMimeTypes[i])) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 void nsPluginTag::TryUnloadPlugin(bool inShutdown)
 {
   // We never want to send NPP_Shutdown to an in-process plugin unless
   // this process is shutting down.
   if (mLibrary && !inShutdown) {
     return;
   }
 
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -53,16 +53,17 @@ public:
   virtual ~nsPluginTag();
   
   void SetHost(nsPluginHost * aHost);
   void TryUnloadPlugin(bool inShutdown);
   void Mark(PRUint32 mask);
   void UnMark(PRUint32 mask);
   bool HasFlag(PRUint32 flag);
   PRUint32 Flags();
+  bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
   bool IsEnabled();
   
   nsRefPtr<nsPluginTag> mNext;
   nsPluginHost *mPluginHost;
   nsCString     mName; // UTF-8
   nsCString     mDescription; // UTF-8
   nsTArray<nsCString> mMimeTypes; // UTF-8
   nsTArray<nsCString> mMimeDescriptions; // UTF-8
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -135,27 +135,27 @@ VoicemailStatus.prototype = {
 function RILContentHelper() {
   this.voiceConnectionInfo = new MobileConnectionInfo();
   this.dataConnectionInfo = new MobileConnectionInfo();
 
   this.initRequests();
   this.initMessageListener(RIL_IPC_MSG_NAMES);
   Services.obs.addObserver(this, "xpcom-shutdown", false);
 
-  // Request initial state.
-  let radioState = cpmm.QueryInterface(Ci.nsISyncMessageSender)
-                       .sendSyncMessage("RIL:GetRadioState")[0];
+  // Request initial context.
+  let rilContext = cpmm.QueryInterface(Ci.nsISyncMessageSender)
+                       .sendSyncMessage("RIL:GetRilContext")[0];
 
-  if (!radioState) {
-    debug("Received null radioState from chrome process.");
+  if (!rilContext) {
+    debug("Received null rilContext from chrome process.");
     return;
   }
-  this.cardState = radioState.cardState;
-  this.updateConnectionInfo(radioState.voice, this.voiceConnectionInfo);
-  this.updateConnectionInfo(radioState.data, this.dataConnectionInfo);
+  this.cardState = rilContext.cardState;
+  this.updateConnectionInfo(rilContext.voice, this.voiceConnectionInfo);
+  this.updateConnectionInfo(rilContext.data, this.dataConnectionInfo);
 }
 
 RILContentHelper.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionProvider,
                                          Ci.nsIRILContentHelper,
                                          Ci.nsIObserver]),
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -55,16 +55,17 @@ const DEFAULT_EMERGENCY_NUMBERS = ["112"
 
 let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false;
 let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false;
 // This flag defaults to true since on RIL v6 and later, we get the
 // version number via the UNSOLICITED_RIL_CONNECTED parcel.
 let RILQUIRKS_V5_LEGACY = true;
 let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false;
 let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false;
+let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false;
 
 /**
  * This object contains helpers buffering incoming data & deconstructing it
  * into parcels as well as buffering outgoing data & constructing parcels.
  * For that it maintains two buffers and corresponding uint8 views, indexes.
  *
  * The incoming buffer is a circular buffer where we store incoming data.
  * As soon as a complete parcel is received, it is processed right away, so
@@ -722,16 +723,20 @@ let RIL = {
                   "RILQUIRKS_DATACALLSTATE_DOWN_IS_UP");
           }
           RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = true;
         }
         break;
       case "Qualcomm RIL 1.0":
         let product_model = libcutils.property_get("ro.product.model");
         if (DEBUG) debug("Detected product model " + product_model);
+        if (product_model == "otoro1") {
+          if (DEBUG) debug("Enabling RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS.");
+          RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = true;
+        }
         if (DEBUG) {
           debug("Detected Qualcomm RIL 1.0, " +
                 "disabling RILQUIRKS_V5_LEGACY and " +
                 "enabling RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE.");
         }
         RILQUIRKS_V5_LEGACY = false;
         RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = true;
         break;
@@ -2820,16 +2825,22 @@ RIL[REQUEST_GET_SIM_STATUS] = function R
       app_state:      Buf.readUint32(), // CARD_APPSTATE_*
       perso_substate: Buf.readUint32(), // CARD_PERSOSUBSTATE_*
       aid:            Buf.readString(),
       app_label:      Buf.readString(),
       pin1_replaced:  Buf.readUint32(),
       pin1:           Buf.readUint32(),
       pin2:           Buf.readUint32()
     });
+    if (RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS) {
+      Buf.readUint32();
+      Buf.readUint32();
+      Buf.readUint32();
+      Buf.readUint32();
+    }
   }
 
   if (DEBUG) debug("iccStatus: " + JSON.stringify(iccStatus));
   this._processICCStatus(iccStatus);
 };
 RIL[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) {
   this.sendDOMMessage({type: "iccunlockcardlock",
                        lockType: "pin",
--- a/editor/libeditor/base/PlaceholderTxn.cpp
+++ b/editor/libeditor/base/PlaceholderTxn.cpp
@@ -2,17 +2,19 @@
 /* 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 "PlaceholderTxn.h"
 #include "nsEditor.h"
 #include "IMETextTxn.h"
 #include "nsGkAtoms.h"
-#include "nsISelection.h"
+#include "mozilla/Selection.h"
+
+using namespace mozilla;
 
 PlaceholderTxn::PlaceholderTxn() :  EditAggregateTxn(), 
                                     mAbsorb(true), 
                                     mForwarding(nsnull),
                                     mIMETextTxn(nsnull),
                                     mCommitted(false),
                                     mStartSel(nsnull),
                                     mEndSel(),
@@ -37,17 +39,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTxn)
   NS_INTERFACE_MAP_ENTRY(nsIAbsorbingTransaction)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(EditAggregateTxn)
 
 NS_IMPL_ADDREF_INHERITED(PlaceholderTxn, EditAggregateTxn)
 NS_IMPL_RELEASE_INHERITED(PlaceholderTxn, EditAggregateTxn)
 
-NS_IMETHODIMP PlaceholderTxn::Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)
+NS_IMETHODIMP
+PlaceholderTxn::Init(nsIAtom* aName, nsSelectionState* aSelState,
+                     nsEditor* aEditor)
 {
   NS_ENSURE_TRUE(aEditor && aSelState, NS_ERROR_NULL_POINTER);
 
   mName = aName;
   mStartSel = aSelState;
   mEditor = aEditor;
   return NS_OK;
 }
@@ -251,15 +255,14 @@ NS_IMETHODIMP PlaceholderTxn::ForwardEnd
 NS_IMETHODIMP PlaceholderTxn::Commit()
 {
   mCommitted = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP PlaceholderTxn::RememberEndingSelection()
 {
-  nsCOMPtr<nsISelection> selection;
-  nsresult res = mEditor->GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr<Selection> selection = mEditor->GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-  return mEndSel.SaveSelection(selection);
+  mEndSel.SaveSelection(selection);
+  return NS_OK;
 }
 
--- a/editor/libeditor/base/PlaceholderTxn.h
+++ b/editor/libeditor/base/PlaceholderTxn.h
@@ -39,17 +39,18 @@ public:
 
   NS_DECL_EDITTXN
 
   NS_IMETHOD RedoTransaction();
   NS_IMETHOD Merge(nsITransaction *aTransaction, bool *aDidMerge);
 
 // ------------ nsIAbsorbingTransaction -----------------------
 
-  NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor);
+  NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
+                  nsEditor* aEditor);
   
   NS_IMETHOD GetTxnName(nsIAtom **aName);
   
   NS_IMETHOD StartSelectionEquals(nsSelectionState *aSelState, bool *aResult);
 
   NS_IMETHOD EndPlaceHolderBatch();
 
   NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress);
@@ -67,13 +68,13 @@ protected:
                                 // non-owning for now - can't nsCOMPtr it due to broken transaction interfaces
   bool        mCommitted;       // do we stop auto absorbing any matching placeholder txns?
   // these next two members store the state of the selection in a safe way. 
   // selection at the start of the txn is stored, as is the selection at the end.
   // This is so that UndoTransaction() and RedoTransaction() can restore the
   // selection properly.
   nsAutoPtr<nsSelectionState> mStartSel; // use a pointer because this is constructed before we exist
   nsSelectionState  mEndSel;
-  nsIEditor*        mEditor;   /** the editor for this transaction */
+  nsEditor*         mEditor;   /** the editor for this transaction */
 };
 
 
 #endif
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/base/crashtests/776323.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html contenteditable="true">
+<head>
+<script>
+
+function boom()
+{
+  document.execCommand("inserthtml", false, "b");
+  var myrange = document.createRange();
+  myrange.selectNodeContents(document.getElementsByTagName("img")[0]);
+  window.getSelection().addRange(myrange);
+  document.execCommand("strikethrough", false, null);
+}
+
+</script>
+</head>
+<body onload="boom();"><img></body>
+</html>
--- a/editor/libeditor/base/crashtests/crashtests.list
+++ b/editor/libeditor/base/crashtests/crashtests.list
@@ -12,8 +12,9 @@ load 713427-1.html
 load 713427-2.xhtml
 load 762183.html
 load 766360.html
 load 766413.html
 load 766845.xhtml
 load 768765.html
 needs-focus load 771749.html
 load 772282.html
+load 776323.html
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -899,19 +899,18 @@ nsEditor::BeginPlaceHolderTransaction(ns
 {
   NS_PRECONDITION(mPlaceHolderBatch >= 0, "negative placeholder batch count!");
   if (!mPlaceHolderBatch)
   {
     // time to turn on the batch
     BeginUpdateViewBatch();
     mPlaceHolderTxn = nsnull;
     mPlaceHolderName = aName;
-    nsCOMPtr<nsISelection> selection;
-    nsresult res = GetSelection(getter_AddRefs(selection));
-    if (NS_SUCCEEDED(res)) {
+    nsRefPtr<Selection> selection = GetSelection();
+    if (selection) {
       mSelState = new nsSelectionState();
       mSelState->SaveSelection(selection);
     }
   }
   mPlaceHolderBatch++;
 
   return NS_OK;
 }
@@ -1974,17 +1973,17 @@ nsEditor::DebugUnitTests(PRInt32 *outNum
 
 bool     
 nsEditor::ArePreservingSelection()
 {
   return !(mSavedSel.IsEmpty());
 }
 
 void
-nsEditor::PreserveSelectionAcrossActions(nsISelection *aSel)
+nsEditor::PreserveSelectionAcrossActions(Selection* aSel)
 {
   mSavedSel.SaveSelection(aSel);
   mRangeUpdater.RegisterSelectionState(mSavedSel);
 }
 
 nsresult 
 nsEditor::RestorePreservedSelection(nsISelection *aSel)
 {
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -420,17 +420,17 @@ public:
 
   /** All editor operations which alter the doc should be followed
    *  with a call to EndOperation */
   NS_IMETHOD EndOperation();
 
   /** routines for managing the preservation of selection across 
    *  various editor actions */
   bool     ArePreservingSelection();
-  void     PreserveSelectionAcrossActions(nsISelection *aSel);
+  void     PreserveSelectionAcrossActions(mozilla::Selection* aSel);
   nsresult RestorePreservedSelection(nsISelection *aSel);
   void     StopPreservingSelection();
 
   /** 
    * SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes
    * @param aExistingRightNode   the node to split.  It will become the new node's next sibling.
    * @param aOffset              the offset of aExistingRightNode's content|children to do the split at
    * @param aNewLeftNode         [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
--- a/editor/libeditor/base/nsEditorUtils.cpp
+++ b/editor/libeditor/base/nsEditorUtils.cpp
@@ -1,46 +1,45 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-
+#include "mozilla/Selection.h"
 #include "nsCOMArray.h"
 #include "nsComponentManagerUtils.h"
 #include "nsEditorUtils.h"
 #include "nsError.h"
 #include "nsIClipboardDragDropHookList.h"
 // hooks
 #include "nsIClipboardDragDropHooks.h"
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsINode.h"
-#include "nsISelection.h"
 #include "nsISimpleEnumerator.h"
 
 class nsIDOMRange;
 class nsISupports;
 
+using namespace mozilla;
 
 /******************************************************************************
  * nsAutoSelectionReset
  *****************************************************************************/
 
-nsAutoSelectionReset::nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd) : 
-mSel(nsnull)
-,mEd(nsnull)
+nsAutoSelectionReset::nsAutoSelectionReset(Selection* aSel, nsEditor* aEd)
+  : mSel(nsnull), mEd(nsnull)
 { 
   if (!aSel || !aEd) return;    // not much we can do, bail.
   if (aEd->ArePreservingSelection()) return;   // we already have initted mSavedSel, so this must be nested call.
-  mSel = do_QueryInterface(aSel);
+  mSel = aSel;
   mEd = aEd;
   if (mSel)
   {
     mEd->PreserveSelectionAcrossActions(mSel);
   }
 }
 
 nsAutoSelectionReset::~nsAutoSelectionReset()
--- a/editor/libeditor/base/nsEditorUtils.h
+++ b/editor/libeditor/base/nsEditorUtils.h
@@ -52,22 +52,22 @@ class nsAutoEditBatch : public nsAutoPla
 /***************************************************************************
  * stack based helper class for saving/restoring selection.  Note that this
  * assumes that the nodes involved are still around afterwards!
  */
 class NS_STACK_CLASS nsAutoSelectionReset
 {
   private:
     /** ref-counted reference to the selection that we are supposed to restore */
-    nsCOMPtr<nsISelection> mSel;
+    nsRefPtr<mozilla::Selection> mSel;
     nsEditor *mEd;  // non-owning ref to nsEditor
 
   public:
     /** constructor responsible for remembering all state needed to restore aSel */
-    nsAutoSelectionReset(nsISelection *aSel, nsEditor *aEd);
+    nsAutoSelectionReset(mozilla::Selection* aSel, nsEditor* aEd);
     
     /** destructor restores mSel to its former state */
     ~nsAutoSelectionReset();
 
     /** Abort: cancel selection saver */
     void Abort();
 };
 
--- a/editor/libeditor/base/nsIAbsorbingTransaction.h
+++ b/editor/libeditor/base/nsIAbsorbingTransaction.h
@@ -27,17 +27,18 @@ class nsIAtom;
  * A transaction interface mixin - for transactions that can support. 
  * the placeholder absorbtion idiom. 
  */
 class nsIAbsorbingTransaction  : public nsISupports{
 public:
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID)
 
-  NS_IMETHOD Init(nsIAtom *aName, nsSelectionState *aSelState, nsIEditor *aEditor)=0;
+  NS_IMETHOD Init(nsIAtom* aName, nsSelectionState* aSelState,
+                  nsEditor* aEditor) = 0;
   
   NS_IMETHOD EndPlaceHolderBatch()=0;
   
   NS_IMETHOD GetTxnName(nsIAtom **aName)=0;
 
   NS_IMETHOD StartSelectionEquals(nsSelectionState *aSelState, bool *aResult)=0;
 
   NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress)=0;
--- a/editor/libeditor/base/nsSelectionState.cpp
+++ b/editor/libeditor/base/nsSelectionState.cpp
@@ -1,29 +1,31 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
+#include "mozilla/Selection.h"          // for Selection
 #include "nsAString.h"                  // for nsAString_internal::Length
 #include "nsAutoPtr.h"                  // for nsRefPtr, getter_AddRefs, etc
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
 #include "nsEditor.h"                   // for nsEditor
 #include "nsEditorUtils.h"              // for nsEditorUtils
 #include "nsError.h"                    // for NS_OK, etc
 #include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
 #include "nsIDOMNode.h"                 // for nsIDOMNode
 #include "nsIDOMRange.h"                // for nsIDOMRange, etc
 #include "nsISelection.h"               // for nsISelection
 #include "nsISupportsImpl.h"            // for nsRange::Release
 #include "nsRange.h"                    // for nsRange
 #include "nsSelectionState.h"
 
+using namespace mozilla;
 
 /***************************************************************************
  * class for recording selection info.  stores selection as collection of
  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
  * ranges since dom gravity will possibly change the ranges.
  */
 nsSelectionState::nsSelectionState() : mArray(){}
 
@@ -42,53 +44,40 @@ nsSelectionState::DoTraverse(nsCycleColl
                                        "selection state mArray[i].startNode");
     cb.NoteXPCOMChild(item->startNode);
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
                                        "selection state mArray[i].endNode");
     cb.NoteXPCOMChild(item->endNode);
   }
 }
 
-nsresult  
-nsSelectionState::SaveSelection(nsISelection *aSel)
+void
+nsSelectionState::SaveSelection(Selection* aSel)
 {
-  NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
-  PRInt32 i,rangeCount, arrayCount = mArray.Length();
-  aSel->GetRangeCount(&rangeCount);
-  
+  MOZ_ASSERT(aSel);
+  PRInt32 arrayCount = mArray.Length();
+  PRInt32 rangeCount = aSel->GetRangeCount();
+
   // if we need more items in the array, new them
-  if (arrayCount<rangeCount)
-  {
-    PRInt32 count = rangeCount-arrayCount;
-    for (i=0; i<count; i++)
-    {
+  if (arrayCount < rangeCount) {
+    for (PRInt32 i = arrayCount; i < rangeCount; i++) {
       mArray.AppendElement();
       mArray[i] = new nsRangeStore();
     }
-  }
-  
-  // else if we have too many, delete them
-  else if (arrayCount>rangeCount)
-  {
-    for (i = arrayCount-1; i >= rangeCount; i--)
-    {
+  } else if (arrayCount > rangeCount) {
+    // else if we have too many, delete them
+    for (PRInt32 i = arrayCount - 1; i >= rangeCount; i--) {
       mArray.RemoveElementAt(i);
     }
   }
-  
+
   // now store the selection ranges
-  nsresult res = NS_OK;
-  for (i=0; i<rangeCount; i++)
-  {
-    nsCOMPtr<nsIDOMRange> range;
-    res = aSel->GetRangeAt(i, getter_AddRefs(range));
-    mArray[i]->StoreRange(range);
+  for (PRInt32 i = 0; i < rangeCount; i++) {
+    mArray[i]->StoreRange(aSel->GetRangeAt(i));
   }
-  
-  return res;
 }
 
 nsresult  
 nsSelectionState::RestoreSelection(nsISelection *aSel)
 {
   NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
   nsresult res;
   PRUint32 i, arrayCount = mArray.Length();
--- a/editor/libeditor/base/nsSelectionState.h
+++ b/editor/libeditor/base/nsSelectionState.h
@@ -13,16 +13,19 @@
 #include "nscore.h"
 #include "prtypes.h"
 
 class nsCycleCollectionTraversalCallback;
 class nsIDOMCharacterData;
 class nsIDOMRange;
 class nsISelection;
 class nsRange;
+namespace mozilla {
+class Selection;
+}
 
 /***************************************************************************
  * class for recording selection info.  stores selection as collection of
  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
  * ranges since dom gravity will possibly change the ranges.
  */
 
 // first a helper struct for saving/setting ranges
@@ -47,17 +50,17 @@ class nsSelectionState
   public:
       
     nsSelectionState();
     ~nsSelectionState();
 
     void DoTraverse(nsCycleCollectionTraversalCallback &cb);
     void DoUnlink() { MakeEmpty(); }
   
-    nsresult SaveSelection(nsISelection *aSel);
+    void     SaveSelection(mozilla::Selection *aSel);
     nsresult RestoreSelection(nsISelection *aSel);
     bool     IsCollapsed();
     bool     IsEqual(nsSelectionState *aSelState);
     void     MakeEmpty();
     bool     IsEmpty();
   protected:    
     nsTArray<nsRefPtr<nsRangeStore> > mArray;
     
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -2864,17 +2864,17 @@ nsHTMLEditRules::DidDeleteSelection(nsIS
     }
   }
   
   // call through to base class
   return nsTextEditRules::DidDeleteSelection(aSelection, aDir, aResult);
 }
 
 nsresult
-nsHTMLEditRules::WillMakeList(nsISelection* aSelection,
+nsHTMLEditRules::WillMakeList(Selection* aSelection,
                               const nsAString* aListType,
                               bool aEntireList,
                               const nsAString* aBulletType,
                               bool* aCancel,
                               bool* aHandled,
                               const nsAString* aItemType)
 {
   if (!aSelection || !aListType || !aCancel || !aHandled) {
@@ -3154,17 +3154,17 @@ nsHTMLEditRules::WillMakeList(nsISelecti
     }
   }
 
   return res;
 }
 
 
 nsresult
-nsHTMLEditRules::WillRemoveList(nsISelection *aSelection, 
+nsHTMLEditRules::WillRemoveList(Selection* aSelection,
                                 bool aOrdered, 
                                 bool *aCancel,
                                 bool *aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   // initialize out param
   *aCancel = false;
   *aHandled = true;
@@ -3221,29 +3221,29 @@ nsHTMLEditRules::WillRemoveList(nsISelec
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return res;
 }
 
 
 nsresult
-nsHTMLEditRules::WillMakeDefListItem(nsISelection *aSelection, 
+nsHTMLEditRules::WillMakeDefListItem(Selection* aSelection,
                                      const nsAString *aItemType, 
                                      bool aEntireList, 
                                      bool *aCancel,
                                      bool *aHandled)
 {
   // for now we let WillMakeList handle this
   NS_NAMED_LITERAL_STRING(listType, "dl");
   return WillMakeList(aSelection, &listType, aEntireList, nsnull, aCancel, aHandled, aItemType);
 }
 
 nsresult
-nsHTMLEditRules::WillMakeBasicBlock(nsISelection *aSelection, 
+nsHTMLEditRules::WillMakeBasicBlock(Selection* aSelection,
                                     const nsAString *aBlockType, 
                                     bool *aCancel,
                                     bool *aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   // initialize out param
   *aCancel = false;
   *aHandled = false;
@@ -3390,30 +3390,32 @@ nsHTMLEditRules::DidMakeBasicBlock(nsISe
   PRInt32 offset;
   nsresult res = nsEditor::GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset);
   NS_ENSURE_SUCCESS(res, res);
   res = InsertMozBRIfNeeded(parent);
   return res;
 }
 
 nsresult
-nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
+nsHTMLEditRules::WillIndent(Selection* aSelection,
+                            bool* aCancel, bool* aHandled)
 {
   nsresult res;
   if (mHTMLEditor->IsCSSEnabled()) {
     res = WillCSSIndent(aSelection, aCancel, aHandled);
   }
   else {
     res = WillHTMLIndent(aSelection, aCancel, aHandled);
   }
   return res;
 }
 
 nsresult
-nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
+nsHTMLEditRules::WillCSSIndent(Selection* aSelection,
+                               bool* aCancel, bool* aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
 
   // initialize out param
   // we want to ignore result of WillInsert()
@@ -3609,17 +3611,18 @@ nsHTMLEditRules::WillCSSIndent(nsISelect
         NS_ENSURE_SUCCESS(res, res);
       }
     }
   }
   return res;
 }
 
 nsresult
-nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
+nsHTMLEditRules::WillHTMLIndent(Selection* aSelection,
+                                bool* aCancel, bool* aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
@@ -3837,17 +3840,18 @@ nsHTMLEditRules::WillHTMLIndent(nsISelec
       }
     }
   }
   return res;
 }
 
 
 nsresult
-nsHTMLEditRules::WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled)
+nsHTMLEditRules::WillOutdent(Selection* aSelection,
+                             bool* aCancel, bool* aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   // initialize out param
   *aCancel = false;
   *aHandled = true;
   nsresult res = NS_OK;
   nsCOMPtr<nsIDOMNode> rememberedLeftBQ, rememberedRightBQ;
   bool useCSS = mHTMLEditor->IsCSSEnabled();
@@ -4407,17 +4411,17 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode
 
   NS_ENSURE_TRUE(nodeToTest, NS_ERROR_NULL_POINTER);
   return mHTMLEditor->IsEmptyNode(nodeToTest, outIsEmptyBlock,
                      aMozBRDoesntCount, aListItemsNotEmpty);
 }
 
 
 nsresult
-nsHTMLEditRules::WillAlign(nsISelection *aSelection, 
+nsHTMLEditRules::WillAlign(Selection* aSelection,
                            const nsAString *alignType, 
                            bool *aCancel,
                            bool *aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
 
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
@@ -8565,17 +8569,18 @@ nsHTMLEditRules::RelativeChangeIndentati
   return mHTMLEditor->RemoveContainer(element);
 }
 
 //
 // Support for Absolute Positioning
 //
 
 nsresult
-nsHTMLEditRules::WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
+nsHTMLEditRules::WillAbsolutePosition(Selection* aSelection,
+                                      bool* aCancel, bool* aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
@@ -8781,18 +8786,18 @@ nsresult
 nsHTMLEditRules::DidAbsolutePosition()
 {
   nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
   nsCOMPtr<nsIDOMElement> elt = do_QueryInterface(mNewBlock);
   return absPosHTMLEditor->AbsolutelyPositionElement(elt, true);
 }
 
 nsresult
-nsHTMLEditRules::WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled)
-{
+nsHTMLEditRules::WillRemoveAbsolutePosition(Selection* aSelection,
+                                            bool* aCancel, bool* aHandled) {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
 
   // initialize out param
   // we want to ignore aCancel from WillInsert()
   *aCancel = false;
   *aHandled = true;
@@ -8803,17 +8808,17 @@ nsHTMLEditRules::WillRemoveAbsolutePosit
 
   nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
 
   nsCOMPtr<nsIHTMLAbsPosEditor> absPosHTMLEditor = mHTMLEditor;
   return absPosHTMLEditor->AbsolutelyPositionElement(elt, false);
 }
 
 nsresult
-nsHTMLEditRules::WillRelativeChangeZIndex(nsISelection *aSelection,
+nsHTMLEditRules::WillRelativeChangeZIndex(Selection* aSelection,
                                           PRInt32 aChange,
                                           bool *aCancel,
                                           bool * aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   nsresult res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
 
--- a/editor/libeditor/html/nsHTMLEditRules.h
+++ b/editor/libeditor/html/nsHTMLEditRules.h
@@ -151,28 +151,48 @@ protected:
   nsresult InsertBRIfNeeded(nsISelection *aSelection);
   nsresult GetGoodSelPointForNode(nsIDOMNode *aNode, nsIEditor::EDirection aAction, 
                                   nsCOMPtr<nsIDOMNode> *outSelNode, PRInt32 *outSelOffset);
   nsresult JoinBlocks(nsCOMPtr<nsIDOMNode> *aLeftBlock, nsCOMPtr<nsIDOMNode> *aRightBlock, bool *aCanceled);
   nsresult MoveBlock(nsIDOMNode *aLeft, nsIDOMNode *aRight, PRInt32 aLeftOffset, PRInt32 aRightOffset);
   nsresult MoveNodeSmart(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
   nsresult MoveContents(nsIDOMNode *aSource, nsIDOMNode *aDest, PRInt32 *aOffset);
   nsresult DeleteNonTableElements(nsINode* aNode);
-  nsresult WillMakeList(nsISelection *aSelection, const nsAString *aListType, bool aEntireList, const nsAString *aBulletType, bool *aCancel, bool *aHandled, const nsAString *aItemType=nsnull);
-  nsresult WillRemoveList(nsISelection *aSelection, bool aOrderd, bool *aCancel, bool *aHandled);
-  nsresult WillIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
-  nsresult WillCSSIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
-  nsresult WillHTMLIndent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
-  nsresult WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled);
-  nsresult WillAlign(nsISelection *aSelection, const nsAString *alignType, bool *aCancel, bool *aHandled);
-  nsresult WillAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
-  nsresult WillRemoveAbsolutePosition(nsISelection *aSelection, bool *aCancel, bool * aHandled);
-  nsresult WillRelativeChangeZIndex(nsISelection *aSelection, PRInt32 aChange, bool *aCancel, bool * aHandled);
-  nsresult WillMakeDefListItem(nsISelection *aSelection, const nsAString *aBlockType, bool aEntireList, bool *aCancel, bool *aHandled);
-  nsresult WillMakeBasicBlock(nsISelection *aSelection, const nsAString *aBlockType, bool *aCancel, bool *aHandled);
+  nsresult WillMakeList(mozilla::Selection* aSelection,
+                        const nsAString* aListType,
+                        bool aEntireList,
+                        const nsAString* aBulletType,
+                        bool* aCancel, bool* aHandled,
+                        const nsAString* aItemType = nsnull);
+  nsresult WillRemoveList(mozilla::Selection* aSelection,
+                          bool aOrdered, bool* aCancel, bool* aHandled);
+  nsresult WillIndent(mozilla::Selection* aSelection,
+                      bool* aCancel, bool* aHandled);
+  nsresult WillCSSIndent(mozilla::Selection* aSelection,
+                         bool* aCancel, bool* aHandled);
+  nsresult WillHTMLIndent(mozilla::Selection* aSelection,
+                          bool* aCancel, bool* aHandled);
+  nsresult WillOutdent(mozilla::Selection* aSelection,
+                       bool* aCancel, bool* aHandled);
+  nsresult WillAlign(mozilla::Selection* aSelection,
+                     const nsAString* alignType,
+                     bool* aCancel, bool* aHandled);
+  nsresult WillAbsolutePosition(mozilla::Selection* aSelection,
+                                bool* aCancel, bool* aHandled);
+  nsresult WillRemoveAbsolutePosition(mozilla::Selection* aSelection,
+                                      bool* aCancel, bool* aHandled);
+  nsresult WillRelativeChangeZIndex(mozilla::Selection* aSelection,
+                                    PRInt32 aChange,
+                                    bool* aCancel, bool* aHandled);
+  nsresult WillMakeDefListItem(mozilla::Selection* aSelection,
+                               const nsAString* aBlockType, bool aEntireList,
+                               bool* aCancel, bool* aHandled);
+  nsresult WillMakeBasicBlock(mozilla::Selection* aSelection,
+                              const nsAString* aBlockType,
+                              bool* aCancel, bool* aHandled);
   nsresult DidMakeBasicBlock(nsISelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
   nsresult DidAbsolutePosition();
   nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType);
   nsresult AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType);
   nsresult AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray,
                                   nsINode* aNode);
   nsresult AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray,
                                   nsIDOMNode *aNode);
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -3374,25 +3374,23 @@ SetSelectionAroundHeadChildren(nsISelect
   // Then extend it to just after.
   PRUint32 childCount = headNode->GetChildCount();
   return aSelection->ExtendNative(headNode, childCount + 1);
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
 {
-  nsCOMPtr<nsISelection> selection;
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
 
   // Save current selection
   nsAutoSelectionReset selectionResetter(selection, this);
 
-  res = SetSelectionAroundHeadChildren(selection, mDocWeak);
+  nsresult res = SetSelectionAroundHeadChildren(selection, mDocWeak);
   NS_ENSURE_SUCCESS(res, res);
 
   res = OutputToString(NS_LITERAL_STRING("text/html"),
                        nsIDocumentEncoder::OutputSelectionOnly,
                        aOutputString);
   if (NS_SUCCEEDED(res))
   {
     // Selection always includes <body></body>,
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -1530,36 +1530,33 @@ nsHTMLEditor::RelativeFontChange( PRInt3
 {
   // Can only change font size by + or - 1
   if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
     return NS_ERROR_ILLEGAL_VALUE;
   
   ForceCompositionEnd();
 
   // Get the selection 
-  nsCOMPtr<nsISelection>selection;
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
-  nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));  
   // Is the selection collapsed?
   // if it's collapsed set typing state
   if (selection->Collapsed()) {
     nsCOMPtr<nsIAtom> atom;
     if (aSizeChange==1) atom = nsEditProperty::big;
     else                atom = nsEditProperty::small;
 
     // Let's see in what kind of element the selection is
     PRInt32 offset;
     nsCOMPtr<nsIDOMNode> selectedNode;
     GetStartNodeAndOffset(selection, getter_AddRefs(selectedNode), &offset);
     NS_ENSURE_TRUE(selectedNode, NS_OK);
     if (IsTextNode(selectedNode)) {
       nsCOMPtr<nsIDOMNode> parent;
-      res = selectedNode->GetParentNode(getter_AddRefs(parent));
+      nsresult res = selectedNode->GetParentNode(getter_AddRefs(parent));
       NS_ENSURE_SUCCESS(res, res);
       selectedNode = parent;
     }
     if (!CanContainTag(selectedNode, atom)) {
       return NS_OK;
     }
 
     // manipulating text attributes on a collapsed selection only sets state for the next text insertion
@@ -1570,17 +1567,17 @@ nsHTMLEditor::RelativeFontChange( PRInt3
   // wrap with txn batching, rules sniffing, and selection preservation code
   nsAutoEditBatch batchIt(this);
   nsAutoRules beginRulesSniffing(this, kOpSetTextProperty, nsIEditor::eNext);
   nsAutoSelectionReset selectionResetter(selection, this);
   nsAutoTxnsConserveSelection dontSpazMySelection(this);
 
   // get selection range enumerator
   nsCOMPtr<nsIEnumerator> enumerator;
-  res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
+  nsresult res = selection->GetEnumerator(getter_AddRefs(enumerator));
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
 
   // loop thru the ranges in the selection
   enumerator->First(); 
   nsCOMPtr<nsISupports> currentItem;
   while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
   {
--- a/editor/libeditor/html/nsTableEditor.cpp
+++ b/editor/libeditor/html/nsTableEditor.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdio.h>
 
 #include "mozilla/Assertions.h"
+#include "mozilla/Selection.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsEditProperty.h"
 #include "nsEditor.h"
 #include "nsEditorUtils.h"
@@ -23,18 +24,16 @@
 #include "nsIDOMElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMRange.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsIHTMLEditor.h"
 #include "nsINode.h"
 #include "nsIPresShell.h"
-#include "nsISelection.h"
-#include "nsISelectionPrivate.h"  // For nsISelectionPrivate::TABLESELECTION_ defines
 #include "nsISupportsUtils.h"
 #include "nsITableCellLayout.h" // For efficient access to table cell
 #include "nsITableEditor.h"
 #include "nsITableLayout.h"     //  data owned by the table and cell frames
 #include "nsLayoutErrors.h"
 #include "nsLiteralString.h"
 #include "nsQueryFrame.h"
 #include "nsString.h"
@@ -1948,29 +1947,28 @@ nsHTMLEditor::SwitchTableCellHeaderType(
   // Prevent auto insertion of BR in new cell created by ReplaceContainer
   nsAutoRules beginRulesSniffing(this, kOpInsertNode, nsIEditor::eNext);
 
   nsCOMPtr<nsIDOMNode> newNode;
 
   // Save current selection to restore when done
   // This is needed so ReplaceContainer can monitor selection
   //  when replacing nodes
-  nsCOMPtr<nsISelection>selection;
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
   nsAutoSelectionReset selectionResetter(selection, this);
 
   // Set to the opposite of current type
   nsCOMPtr<nsIAtom> atom = nsEditor::GetTag(aSourceCell);
   nsString newCellType( (atom == nsEditProperty::td) ? NS_LITERAL_STRING("th") : NS_LITERAL_STRING("td"));
 
   // This creates new node, moves children, copies attributes (true)
   //   and manages the selection!
-  res = ReplaceContainer(aSourceCell, address_of(newNode), newCellType, nsnull, nsnull, true);
+  nsresult res = ReplaceContainer(aSourceCell, address_of(newNode),
+                                  newCellType, nsnull, nsnull, true);
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(newNode, NS_ERROR_FAILURE);
 
   // Return the new cell
   if (aNewCell)
   {
     nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newNode);
     *aNewCell = newElement.get();
@@ -2486,23 +2484,22 @@ nsHTMLEditor::FixBadColSpan(nsIDOMElemen
     }
   }
   return GetTableSize(aTable, &rowCount, &aNewColCount);
 }
 
 NS_IMETHODIMP 
 nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable)
 {
-  nsCOMPtr<nsISelection>selection;
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
+  nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDOMElement> table;
-  res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
+  nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"),
+                                             aTable, getter_AddRefs(table));
   NS_ENSURE_SUCCESS(res, res);
   // Don't fail if we didn't find a table
   NS_ENSURE_TRUE(table, NS_OK);
 
   PRInt32 rowCount, colCount, rowIndex, colIndex;
   res = GetTableSize(table, &rowCount, &colCount);
   NS_ENSURE_SUCCESS(res, res);
 
--- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
@@ -579,16 +579,23 @@ nsDocShellTreeOwner::GetParentNativeWind
 
 NS_IMETHODIMP
 nsDocShellTreeOwner::SetParentNativeWindow(nativeWindow aParentNativeWindow)
 {
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
+nsDocShellTreeOwner::GetNativeHandle(nsAString& aNativeHandle)
+{
+  // the nativeHandle should be accessed from nsIXULWindow
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsDocShellTreeOwner::GetVisibility(bool* aVisibility)
 {
   nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin = GetOwnerWin();
   if (ownerWin)
   {
     return ownerWin->GetVisibility(aVisibility);
   }
   return NS_ERROR_NULL_POINTER;
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -1373,16 +1373,22 @@ NS_IMETHODIMP nsWebBrowser::SetParentNat
 {
    NS_ENSURE_STATE(!mDocShell);
 
    mParentNativeWindow = aParentNativeWindow;
 
    return NS_OK;
 }
 
+NS_IMETHODIMP nsWebBrowser::GetNativeHandle(nsAString& aNativeHandle)
+{
+   // the nativeHandle should be accessed from nsIXULWindow
+   return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 NS_IMETHODIMP nsWebBrowser::GetVisibility(bool* visibility)
 {
    NS_ENSURE_ARG_POINTER(visibility);
 
    if(!mDocShell)
       *visibility = mInitInfo->visible;
    else
       NS_ENSURE_SUCCESS(mDocShellAsWin->GetVisibility(visibility), NS_ERROR_FAILURE);
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -298,21 +298,23 @@ nsPermissionManager::Init()
 
   return NS_OK;
 }
 
 nsresult
 nsPermissionManager::InitDB(bool aRemoveFile)
 {
   nsCOMPtr<nsIFile> permissionsFile;
-  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
-  if (!permissionsFile)
-    return NS_ERROR_UNEXPECTED;
+  nsresult rv = NS_GetSpecialDirectory(NS_APP_PERMISSION_PARENT_DIR, getter_AddRefs(permissionsFile));
+  if (NS_FAILED(rv)) {
+    rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
+  }
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
 
-  nsresult rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kPermissionsFileName));
+  rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kPermissionsFileName));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aRemoveFile) {
     bool exists = false;
     rv = permissionsFile->Exists(&exists);
     NS_ENSURE_SUCCESS(rv, rv);
     if (exists) {
       rv = permissionsFile->Remove(false);
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -17,16 +17,17 @@
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"
 
 #include "BasicTiledThebesLayer.h"
 #include "BasicLayersImpl.h"
 #include "BasicThebesLayer.h"
 #include "BasicContainerLayer.h"
 #include "mozilla/Preferences.h"
+#include "nsIWidget.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 /**
  * Clips to the smallest device-pixel-aligned rectangle containing aRect
@@ -127,17 +128,18 @@ BasicLayerManager::~BasicLayerManager()
 
   mRoot = nsnull;
 
   MOZ_COUNT_DTOR(BasicLayerManager);
 }
 
 void
 BasicLayerManager::SetDefaultTarget(gfxContext* aContext,
-                                    BufferMode aDoubleBuffering)
+                                    BufferMode aDoubleBuffering,
+                                    ScreenRotation aRotation)
 {
   NS_ASSERTION(!InTransaction(),
                "Must set default target outside transaction");
   mDefaultTarget = aContext;
   mDoubleBuffering = aDoubleBuffering;
 }
 
 void
@@ -917,17 +919,17 @@ already_AddRefed<ReadbackLayer>
 BasicLayerManager::CreateReadbackLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   nsRefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
   return layer.forget();
 }
 
 BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
-  BasicLayerManager(aWidget)
+  BasicLayerManager(aWidget), mTargetRotation(ROTATION_0)
 {
   MOZ_COUNT_CTOR(BasicShadowLayerManager);
 }
 
 BasicShadowLayerManager::~BasicShadowLayerManager()
 {
   MOZ_COUNT_DTOR(BasicShadowLayerManager);
 }
@@ -938,16 +940,28 @@ BasicShadowLayerManager::GetMaxTextureSi
   if (HasShadowManager()) {
     return ShadowLayerForwarder::GetMaxTextureSize();
   }
 
   return PR_INT32_MAX;
 }
 
 void
+BasicShadowLayerManager::SetDefaultTarget(gfxContext* aContext,
+                                          BufferMode aDoubleBuffering,
+                                          ScreenRotation aRotation)
+{
+  BasicLayerManager::SetDefaultTarget(aContext, aDoubleBuffering, aRotation);
+  mTargetRotation = aRotation;
+  if (mWidget) {
+    mTargetBounds = mWidget->GetNaturalBounds();
+  }
+}
+
+void
 BasicShadowLayerManager::SetRoot(Layer* aLayer)
 {
   if (mRoot != aLayer) {
     if (HasShadowManager()) {
       // Have to hold the old root and its children in order to
       // maintain the same view of the layer tree in this process as
       // the parent sees.  Otherwise layers can be destroyed
       // mid-transaction and bad things can happen (v. bug 612573)
@@ -976,17 +990,17 @@ BasicShadowLayerManager::BeginTransactio
 {
   NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
   nsRefPtr<gfxContext> targetContext = aTarget;
 
   // If the last transaction was incomplete (a failed DoEmptyTransaction),
   // don't signal a new transaction to ShadowLayerForwarder. Carry on adding
   // to the previous transaction.
   if (HasShadowManager()) {
-    ShadowLayerForwarder::BeginTransaction();
+    ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation);
 
     // If we have a non-default target, we need to let our shadow manager draw
     // to it. This will happen at the end of the transaction.
     if (aTarget && (aTarget != mDefaultTarget) &&
         XRE_GetProcessType() == GeckoProcessType_Default) {
       mShadowTarget = aTarget;
 
       // Create a temporary target for ourselves, so that mShadowTarget is only
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -5,21 +5,21 @@
 
 #ifndef GFX_BASICLAYERS_H
 #define GFX_BASICLAYERS_H
 
 #include "Layers.h"
 
 #include "gfxContext.h"
 #include "gfxCachedTempSurface.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "mozilla/WidgetUtils.h"
 #include "nsAutoRef.h"
 #include "nsThreadUtils.h"
 
-#include "mozilla/layers/ShadowLayers.h"
-
 class nsIWidget;
 
 namespace mozilla {
 namespace layers {
 
 class BasicShadowableLayer;
 class ShadowThebesLayer;
 class ShadowContainerLayer;
@@ -75,17 +75,18 @@ public:
    * results, by using a temporary buffer when necessary. In BUFFERED
    * mode we always completely overwrite the contents of aContext's
    * destination surface (within the clip region) using OPERATOR_SOURCE.
    */
   enum BufferMode {
     BUFFER_NONE,
     BUFFER_BUFFERED
   };
-  void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
+  virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
+                                ScreenRotation aRotation);
   gfxContext* GetDefaultTarget() { return mDefaultTarget; }
 
   nsIWidget* GetRetainerWidget() { return mWidget; }
   void ClearRetainerWidget() { mWidget = nsnull; }
 
   virtual bool IsWidgetLayerManager() { return mWidget != nsnull; }
 
   virtual void BeginTransaction();
@@ -216,16 +217,18 @@ public:
   }
   virtual ShadowLayerManager* AsShadowManager()
   {
     return this;
   }
 
   virtual PRInt32 GetMaxTextureSize() const;
 
+  virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
+                                ScreenRotation aRotation) MOZ_OVERRIDE;
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags = END_DEFAULT);
 
   virtual void SetRoot(Layer* aLayer);
 
@@ -256,21 +259,30 @@ public:
   void SetRepeatTransaction() { mRepeatTransaction = true; }
 
 private:
   /**
    * Forward transaction results to the parent context.
    */
   void ForwardTransaction();
 
+  // The bounds of |mTarget| in device pixels.
+  nsIntRect mTargetBounds;
+
+  LayerRefArray mKeepAlive;
+
+  // Sometimes we draw to targets that don't natively support
+  // landscape/portrait orientation.  When we need to implement that
+  // ourselves, |mTargetRotation| describes the induced transform we
+  // need to apply when compositing content to our target.
+  ScreenRotation mTargetRotation;
+
   // Used to repeat the transaction right away (to avoid rebuilding
   // a display list) to support progressive drawing.
   bool mRepeatTransaction;
-
-  LayerRefArray mKeepAlive;
 };
 
 class BasicShadowableThebesLayer;
 class BasicShadowableLayer : public ShadowableLayer
 {
 public:
   BasicShadowableLayer()
   {
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -15,16 +15,17 @@
 
 #include "ContainerLayerD3D10.h"
 #include "ThebesLayerD3D10.h"
 #include "ColorLayerD3D10.h"
 #include "CanvasLayerD3D10.h"
 #include "ReadbackLayerD3D10.h"
 #include "ImageLayerD3D10.h"
 #include "mozilla/layers/PLayerChild.h"
+#include "mozilla/WidgetUtils.h"
 
 #include "../d3d9/Nv3DVUtils.h"
 
 #include "gfxCrashReporterUtils.h"
 
 using namespace std;
 using namespace mozilla::gfx;
 
@@ -443,17 +444,16 @@ LayerManagerD3D10::CreateOptimalSurface(
        aFormat != gfxASurface::ImageFormatARGB32)) {
     return LayerManager::CreateOptimalSurface(aSize, aFormat);
   }
 
   nsRefPtr<ID3D10Texture2D> texture;
   
   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-  desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
   
   HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(texture));
 
   if (FAILED(hr)) {
     NS_WARNING("Failed to create new texture for CreateOptimalSurface!");
     return LayerManager::CreateOptimalSurface(aSize, aFormat);
   }
 
@@ -724,17 +724,18 @@ LayerManagerD3D10::Render()
   }
   device()->RSSetScissorRects(1, &r);
 
   static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
 
   if (mTarget) {
     PaintToTarget();
   } else if (mBackBuffer) {
-    ShadowLayerForwarder::BeginTransaction();
+    ShadowLayerForwarder::BeginTransaction(mWidget->GetNaturalBounds(),
+                                           ROTATION_0);
     
     nsIntRect contentRect = nsIntRect(0, 0, rect.width, rect.height);
     if (!mRootForShadowTree) {
         mRootForShadowTree = new DummyRoot(this);
         mRootForShadowTree->SetShadow(ConstructShadowFor(mRootForShadowTree));
         CreatedContainerLayer(mRootForShadowTree);
         ShadowLayerForwarder::SetRoot(mRootForShadowTree);
     }
--- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
@@ -465,17 +465,16 @@ ThebesLayerD3D10::CreateNewTextures(cons
 {
   if (aSize.width == 0 || aSize.height == 0) {
     // Nothing to do.
     return;
   }
 
   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-  desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
   HRESULT hr;
 
   if (!mTexture) {
     hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
 
     if (FAILED(hr)) {
       NS_WARNING("Failed to create new texture for ThebesLayerD3D10!");
       return;
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -417,16 +417,23 @@ CompositorParent::Composite()
 
   bool requestNextFrame = TransformShadowTree(mLastCompose);
   if (requestNextFrame) {
     ScheduleComposition();
   }
 
   RenderTraceLayers(aLayer, "0000");
 
+  if (LAYERS_OPENGL == mLayerManager->GetBackendType() &&
+      !mTargetConfig.naturalBounds().IsEmpty()) {
+    LayerManagerOGL* lm = static_cast<LayerManagerOGL*>(mLayerManager.get());
+    lm->SetWorldTransform(
+      ComputeGLTransformForRotation(mTargetConfig.naturalBounds(),
+                                    mTargetConfig.rotation()));
+  }
   mLayerManager->EndEmptyTransaction();
 
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   if (mExpectedComposeTime + TimeDuration::FromMilliseconds(15) < TimeStamp::Now()) {
     printf_stderr("Compositor: Composite took %i ms.\n",
                   15 + (int)(TimeStamp::Now() - mExpectedComposeTime).ToMilliseconds());
   }
 #endif
@@ -689,18 +696,20 @@ CompositorParent::SyncViewportInfo(const
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated,
                                             aScrollOffset, aScaleX, aScaleY);
 #endif
 }
 
 void
 CompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+                                      const TargetConfig& aTargetConfig,
                                       bool isFirstPaint)
 {
+  mTargetConfig = aTargetConfig;
   mIsFirstPaint = mIsFirstPaint || isFirstPaint;
   mLayersUpdated = true;
   Layer* root = aLayerTree->GetRoot();
   mLayerManager->SetRoot(root);
   if (root) {
     SetShadowProperties(root);
   }
   ScheduleComposition();
@@ -893,16 +902,17 @@ public:
 
   virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendType,
                                       const uint64_t& aId,
                                       LayersBackend* aBackend,
                                       int32_t* aMaxTextureSize) MOZ_OVERRIDE;
   virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
 
   virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+                                   const TargetConfig& aTargetConfig,
                                    bool isFirstPaint) MOZ_OVERRIDE;
 
 private:
   void DeferredDestroy();
 
   // There can be many CPCPs, and IPDL-generated code doesn't hold a
   // reference to top-level actors.  So we hold a reference to
   // ourself.  This is released (deferred) in ActorDestroy().
@@ -992,18 +1002,20 @@ CrossProcessCompositorParent::DeallocPLa
 {
   ShadowLayersParent* slp = static_cast<ShadowLayersParent*>(aLayers);
   RemoveIndirectTree(slp->GetId());
   delete aLayers;
   return true;
 }
 
 void
-CrossProcessCompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
-                                                  bool isFirstPaint)
+CrossProcessCompositorParent::ShadowLayersUpdated(
+  ShadowLayersParent* aLayerTree,
+  const TargetConfig& aTargetConfig,
+  bool isFirstPaint)
 {
   uint64_t id = aLayerTree->GetId();
   MOZ_ASSERT(id != 0);
   Layer* shadowRoot = aLayerTree->GetRoot();
   if (shadowRoot) {
     SetShadowProperties(shadowRoot);
   }
   UpdateIndirectTree(id, shadowRoot, isFirstPaint);
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -65,16 +65,17 @@ public:
   virtual ~CompositorParent();
 
   virtual bool RecvWillStop() MOZ_OVERRIDE;
   virtual bool RecvStop() MOZ_OVERRIDE;
   virtual bool RecvPause() MOZ_OVERRIDE;
   virtual bool RecvResume() MOZ_OVERRIDE;
 
   virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+                                   const TargetConfig& aTargetConfig,
                                    bool isFirstPaint) MOZ_OVERRIDE;
   void Destroy();
 
   LayerManager* GetLayerManager() { return mLayerManager; }
 
   void SetTransformation(float aScale, nsIntPoint aScrollOffset);
   void AsyncRender();
 
@@ -222,16 +223,17 @@ private:
    * fixed position layers remain in the same position.
    */
   void TransformFixedLayers(Layer* aLayer,
                             const gfxPoint& aTranslation,
                             const gfxPoint& aScaleDiff);
 
   nsRefPtr<LayerManager> mLayerManager;
   nsIWidget* mWidget;
+  TargetConfig mTargetConfig;
   CancelableTask *mCurrentCompositeTask;
   TimeStamp mLastCompose;
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   TimeStamp mExpectedComposeTime;
 #endif
 
   bool mPaused;
   float mXScale;
--- a/gfx/layers/ipc/GeckoContentController.h
+++ b/gfx/layers/ipc/GeckoContentController.h
@@ -17,16 +17,16 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoContentController)
 
   /**
    * Requests a paint of the given FrameMetrics |aFrameMetrics| from Gecko.
    * Implementations per-platform are responsible for actually handling this.
    */
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0;
 
-  GeckoContentController() {};
-  virtual ~GeckoContentController() {};
+  GeckoContentController() {}
+  virtual ~GeckoContentController() {}
 };
 
 }
 }
 
 #endif // mozilla_layers_GeckoContentController_h
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -1,34 +1,41 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=8 et :
  */
 /* 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 LayersSurfaces;
+using mozilla::ScreenRotation;
 include protocol PCompositor;
 include protocol PGrallocBuffer;
 include protocol PLayer;
 include protocol PRenderFrame;
 
 include "gfxipc/ShadowLayerUtils.h";
+include "mozilla/WidgetUtils.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
  */
 
 namespace mozilla {
 namespace layers {
 
+struct TargetConfig {
+  nsIntRect naturalBounds;
+  ScreenRotation rotation;
+};
+
 // Create a shadow layer for |layer|
 struct OpCreateThebesLayer     { PLayer layer; };
 struct OpCreateContainerLayer  { PLayer layer; };
 struct OpCreateImageLayer      { PLayer layer; };
 struct OpCreateColorLayer      { PLayer layer; };
 struct OpCreateCanvasLayer     { PLayer layer; };
 struct OpCreateRefLayer        { PLayer layer; };
 
@@ -186,24 +193,24 @@ parent:
    * is returned.
    */
   sync PGrallocBuffer(gfxIntSize size, gfxContentType content)
     returns (MaybeMagicGrallocBufferHandle handle);
   async PLayer();
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
-  sync Update(Edit[] cset, bool isFirstPaint)
+  sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint)
     returns (EditReply[] reply);
 
   // Composite the layer tree to the given surface, and return the surface.
   sync DrawToSurface(SurfaceDescriptor surfaceIn)
     returns (SurfaceDescriptor surfaceOut);
 
   // We don't need to send a sync transaction if
   // no transaction operate require a swap.
-  async UpdateNoSwap(Edit[] cset, bool isFirstPaint);
+  async UpdateNoSwap(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint);
 
   async __delete__();
 };
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayerUtils.h
+++ b/gfx/layers/ipc/ShadowLayerUtils.h
@@ -6,16 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef IPC_ShadowLayerUtils_h
 #define IPC_ShadowLayerUtils_h
 
 #include "IPC/IPCMessageUtils.h"
 #include "Layers.h"
 #include "GLContext.h"
+#include "mozilla/WidgetUtils.h"
 
 #if defined(MOZ_ENABLE_D3D10_LAYER)
 # include "mozilla/layers/ShadowLayerUtilsD3D10.h"
 #endif
 
 #if defined(MOZ_X11)
 # include "mozilla/layers/ShadowLayerUtilsX11.h"
 #else
@@ -102,11 +103,18 @@ struct ParamTraits<mozilla::gl::TextureI
 template <>
 struct ParamTraits<mozilla::layers::MagicGrallocBufferHandle> {
   typedef mozilla::layers::MagicGrallocBufferHandle paramType;
   static void Write(Message*, const paramType&) {}
   static bool Read(const Message*, void**, paramType*) { return false; }
 };
 #endif  // !defined(MOZ_HAVE_XSURFACEDESCRIPTORGRALLOC)
 
-}
+template <>
+struct ParamTraits<mozilla::ScreenRotation>
+  : public EnumSerializer<mozilla::ScreenRotation,
+                          mozilla::ROTATION_0,
+                          mozilla::ROTATION_COUNT>
+{};
+
+} // namespace IPC
 
 #endif // IPC_ShadowLayerUtils_h
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -36,17 +36,22 @@ typedef std::set<ShadowableLayer*> Shado
 class Transaction
 {
 public:
   Transaction()
     : mSwapRequired(false)
     , mOpen(false)
   {}
 
-  void Begin() { mOpen = true; }
+  void Begin(const nsIntRect& aTargetBounds, ScreenRotation aRotation)
+  {
+    mOpen = true;
+    mTargetBounds = aTargetBounds;
+    mTargetRotation = aRotation;
+  }
 
   void AddEdit(const Edit& aEdit)
   {
     NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
     mCset.push_back(aEdit);
   }
   void AddPaint(const Edit& aPaint)
   {
@@ -87,16 +92,18 @@ public:
     return mCset.empty() && mPaints.empty() && mMutants.empty();
   }
   bool Finished() const { return !mOpen && Empty(); }
 
   EditVector mCset;
   EditVector mPaints;
   BufferArray mDyingBuffers;
   ShadowableLayerSet mMutants;
+  nsIntRect mTargetBounds;
+  ScreenRotation mTargetRotation;
   bool mSwapRequired;
 
 private:
   bool mOpen;
 
   // disabled
   Transaction(const Transaction&);
   Transaction& operator=(const Transaction&);
@@ -118,21 +125,22 @@ ShadowLayerForwarder::ShadowLayerForward
 
 ShadowLayerForwarder::~ShadowLayerForwarder()
 {
   NS_ABORT_IF_FALSE(mTxn->Finished(), "unfinished transaction?");
   delete mTxn;
 }
 
 void
-ShadowLayerForwarder::BeginTransaction()
+ShadowLayerForwarder::BeginTransaction(const nsIntRect& aTargetBounds,
+                                       ScreenRotation aRotation)
 {
   NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
   NS_ABORT_IF_FALSE(mTxn->Finished(), "uncommitted txn?");
-  mTxn->Begin();
+  mTxn->Begin(aTargetBounds, aRotation);
 }
 
 static PLayerChild*
 Shadow(ShadowableLayer* aLayer)
 {
   return aLayer->GetShadow();
 }
 
@@ -320,32 +328,35 @@ ShadowLayerForwarder::EndTransaction(Inf
     cset.AppendElements(&mTxn->mCset.front(), mTxn->mCset.size());
   }
   // Paints after non-paint ops, including attribute changes.  See
   // above.
   if (!mTxn->mPaints.empty()) {
     cset.AppendElements(&mTxn->mPaints.front(), mTxn->mPaints.size());
   }
 
+  TargetConfig targetConfig(mTxn->mTargetBounds, mTxn->mTargetRotation);
+
   MOZ_LAYERS_LOG(("[LayersForwarder] syncing before send..."));
   PlatformSyncBeforeUpdate();
 
   if (mTxn->mSwapRequired) {
     MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
     RenderTraceScope rendertrace3("Forward Transaction", "000093");
-    if (!mShadowManager->SendUpdate(cset, mIsFirstPaint, aReplies)) {
+    if (!mShadowManager->SendUpdate(cset, targetConfig, mIsFirstPaint,
+                                    aReplies)) {
       MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
       return false;
     }
   } else {
     // If we don't require a swap we can call SendUpdateNoSwap which
     // assumes that aReplies is empty (DEBUG assertion)
     MOZ_LAYERS_LOG(("[LayersForwarder] sending no swap transaction..."));
     RenderTraceScope rendertrace3("Forward NoSwap Transaction", "000093");
-    if (!mShadowManager->SendUpdateNoSwap(cset, mIsFirstPaint)) {
+    if (!mShadowManager->SendUpdateNoSwap(cset, targetConfig, mIsFirstPaint)) {
       MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
       return false;
     }
   }
 
   mIsFirstPaint = false;
   MOZ_LAYERS_LOG(("[LayersForwarder] ... done"));
   return true;
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -9,16 +9,17 @@
 #define mozilla_layers_ShadowLayers_h 1
 
 #include "gfxASurface.h"
 #include "GLDefs.h"
 
 #include "ImageLayers.h"
 #include "LayersBackend.h"
 #include "mozilla/ipc/SharedMemory.h"
+#include "mozilla/WidgetUtils.h"
 
 class gfxSharedImageSurface;
 
 namespace mozilla {
 
 namespace gl {
 class GLContext;
 class TextureImage;
@@ -111,17 +112,18 @@ public:
   typedef gfxASurface::gfxContentType gfxContentType;
 
   virtual ~ShadowLayerForwarder();
 
   /**
    * Begin recording a transaction to be forwarded atomically to a
    * ShadowLayerManager.
    */
-  void BeginTransaction();
+  void BeginTransaction(const nsIntRect& aTargetBounds,
+                        ScreenRotation aRotation);
 
   /**
    * The following methods may only be called after BeginTransaction()
    * but before EndTransaction().  They mirror the LayerManager
    * interface in Layers.h.
    */
 
   /**
--- a/gfx/layers/ipc/ShadowLayersManager.h
+++ b/gfx/layers/ipc/ShadowLayersManager.h
@@ -5,22 +5,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_ShadowLayersManager_h
 #define mozilla_layers_ShadowLayersManager_h
 
 namespace mozilla {
 namespace layers {
 
+class TargetConfig;
 class ShadowLayersParent;
 
 class ShadowLayersManager
 {
 public:
     virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
-                                     // FIXME nuke this
+                                     const TargetConfig& aTargetConfig,
                                      bool isFirstPaint) = 0;
 };
 
 } // layers
 } // mozilla
 
 #endif // mozilla_layers_ShadowLayersManager_h
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -114,26 +114,28 @@ ShadowLayersParent::Destroy()
       static_cast<ShadowLayerParent*>(ManagedPLayerParent()[i]);
     slp->Destroy();
   }
 }
 
 /* virtual */
 bool
 ShadowLayersParent::RecvUpdateNoSwap(const InfallibleTArray<Edit>& cset,
-                 const bool& isFirstPaint)
+                                     const TargetConfig& targetConfig,
+                                     const bool& isFirstPaint)
 {
   InfallibleTArray<EditReply> noReplies;
-  bool success = RecvUpdate(cset, isFirstPaint, &noReplies);
+  bool success = RecvUpdate(cset, targetConfig, isFirstPaint, &noReplies);
   NS_ABORT_IF_FALSE(noReplies.Length() == 0, "RecvUpdateNoSwap requires a sync Update to carry Edits");
   return success;
 }
 
 bool
 ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
+                               const TargetConfig& targetConfig,
                                const bool& isFirstPaint,
                                InfallibleTArray<EditReply>* reply)
 {
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   TimeStamp updateStart = TimeStamp::Now();
 #endif
 
   MOZ_LAYERS_LOG(("[ParentSide] received txn with %d edits", cset.Length()));
@@ -412,17 +414,17 @@ ShadowLayersParent::RecvUpdate(const Inf
     reply->AppendElements(&replyv.front(), replyv.size());
   }
 
   // Ensure that any pending operations involving back and front
   // buffers have completed, so that neither process stomps on the
   // other's buffer contents.
   ShadowLayerManager::PlatformSyncBeforeReplyUpdate();
 
-  mShadowLayersManager->ShadowLayersUpdated(this, isFirstPaint);
+  mShadowLayersManager->ShadowLayersUpdated(this, targetConfig, isFirstPaint);
 
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   int compositeTime = (int)(mozilla::TimeStamp::Now() - updateStart).ToMilliseconds();
   if (compositeTime > 15) {
     printf_stderr("Compositor: Layers update took %i ms (blocking gecko).\n", compositeTime);
   }
 #endif
 
--- a/gfx/layers/ipc/ShadowLayersParent.h
+++ b/gfx/layers/ipc/ShadowLayersParent.h
@@ -43,23 +43,25 @@ public:
   uint64_t GetId() const { return mId; }
   ContainerLayer* GetRoot() const { return mRoot; }
 
   virtual void DestroySharedSurface(gfxSharedImageSurface* aSurface);
   virtual void DestroySharedSurface(SurfaceDescriptor* aSurface);
 
 protected:
   virtual bool RecvUpdate(const EditArray& cset,
+                          const TargetConfig& targetConfig,
                           const bool& isFirstPaint,
                           EditReplyArray* reply) MOZ_OVERRIDE;
 
   virtual bool RecvDrawToSurface(const SurfaceDescriptor& surfaceIn,
                                  SurfaceDescriptor* surfaceOut) MOZ_OVERRIDE;
 
   virtual bool RecvUpdateNoSwap(const EditArray& cset,
+                                const TargetConfig& targetConfig,
                                 const bool& isFirstPaint) MOZ_OVERRIDE;
 
   virtual PGrallocBufferParent*
   AllocPGrallocBuffer(const gfxIntSize& aSize, const gfxContentType& aContent,
                       MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
   virtual bool
   DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE;
 
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -3637,16 +3637,39 @@ gfxFontGroup::InitScriptRun(gfxContext *
             }
         }
 
         runStart += matchedLength;
     }
 }
 
 already_AddRefed<gfxFont>
+gfxFontGroup::TryOtherFamilyMembers(gfxFont* aFont, PRUint32 aCh)
+{
+    gfxFontFamily *family = aFont->GetFontEntry()->Family();
+    if (family && !aFont->GetFontEntry()->mIsProxy &&
+        family->TestCharacterMap(aCh)) {
+        // Note that we don't need the actual runScript in matchData for
+        // gfxFontFamily::SearchAllFontsForChar, it's only used for the
+        // system-fallback case. So we can just set it to 0 here.
+        GlobalFontMatch matchData(aCh, 0, &mStyle);
+        family->SearchAllFontsForChar(&matchData);
+        gfxFontEntry *fe = matchData.mBestMatch;
+        if (fe) {
+            bool needsBold = aFont->GetStyle()->weight >= 600 && !fe->IsBold();
+            nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, needsBold);
+            if (font) {
+                return font.forget();
+            }
+        }
+    }
+    return nsnull;
+}
+
+already_AddRefed<gfxFont>
 gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
                               PRInt32 aRunScript, gfxFont *aPrevMatchedFont,
                               PRUint8 *aMatchType)
 {
     // To optimize common cases, try the first font in the font-group
     // before going into the more detailed checks below
     PRUint32 nextIndex = 0;
     bool isJoinControl = gfxFontUtils::IsJoinControl(aCh);
@@ -3655,16 +3678,23 @@ gfxFontGroup::FindFontForChar(PRUint32 a
 
     if (!isJoinControl && !wasJoinCauser && !isVarSelector) {
         gfxFont *firstFont = mFonts[0];
         if (firstFont->HasCharacter(aCh)) {
             *aMatchType = gfxTextRange::kFontGroup;
             firstFont->AddRef();
             return firstFont;
         }
+        // It's possible that another font in the family (e.g. regular face,
+        // where the requested style was italic) will support the character
+        nsRefPtr<gfxFont> font = TryOtherFamilyMembers(firstFont, aCh);
+        if (font) {
+            *aMatchType = gfxTextRange::kFontGroup;
+            return font.forget();
+        }
         // we don't need to check the first font again below
         ++nextIndex;
     }
 
     if (aPrevMatchedFont) {
         // Don't switch fonts for control characters, regardless of
         // whether they are present in the current font, as they won't
         // actually be rendered (see bug 716229)
@@ -3700,32 +3730,20 @@ gfxFontGroup::FindFontForChar(PRUint32 a
     PRUint32 fontListLength = FontListLength();
     for (PRUint32 i = nextIndex; i < fontListLength; i++) {
         nsRefPtr<gfxFont> font = mFonts[i];
         if (font->HasCharacter(aCh)) {
             *aMatchType = gfxTextRange::kFontGroup;
             return font.forget();
         }
 
-        // check other faces of the family
-        gfxFontFamily *family = font->GetFontEntry()->Family();
-        if (family && !font->GetFontEntry()->mIsProxy &&
-            family->TestCharacterMap(aCh))
-        {
-            GlobalFontMatch matchData(aCh, aRunScript, &mStyle);
-            family->SearchAllFontsForChar(&matchData);
-            gfxFontEntry *fe = matchData.mBestMatch;
-            if (fe) {
-                bool needsBold =
-                    font->GetStyle()->weight >= 600 && !fe->IsBold();
-                font = fe->FindOrMakeFont(font->GetStyle(), needsBold);
-                if (font) {
-                    return font.forget();
-                }
-            }
+        font = TryOtherFamilyMembers(font, aCh);
+        if (font) {
+            *aMatchType = gfxTextRange::kFontGroup;
+            return font.forget();
         }
     }
 
     // if character is in Private Use Area, don't do matching against pref or system fonts
     if ((aCh >= 0xE000  && aCh <= 0xF8FF) || (aCh >= 0xF0000 && aCh <= 0x10FFFD))
         return nsnull;
 
     // 2. search pref fonts
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -3176,16 +3176,22 @@ protected:
     bool ForEachFontInternal(const nsAString& aFamilies,
                                nsIAtom *aLanguage,
                                bool aResolveGeneric,
                                bool aResolveFontName,
                                bool aUseFontSet,
                                FontCreationCallback fc,
                                void *closure);
 
+    // Helper for font-matching:
+    // see if aCh is supported in any of the other faces from aFont's family;
+    // if so return the best style match, else return null.
+    already_AddRefed<gfxFont> TryOtherFamilyMembers(gfxFont* aFont,
+                                                    PRUint32 aCh);
+
     static bool FontResolverProc(const nsAString& aName, void *aClosure);
 
     static bool FindPlatformFont(const nsAString& aName,
                                    const nsACString& aGenericName,
                                    bool aUseFontSet,
                                    void *closure);
 
     static NS_HIDDEN_(nsILanguageAtomService*) gLangService;
--- a/intl/uconv/idl/nsIUTF8ConverterService.idl
+++ b/intl/uconv/idl/nsIUTF8ConverterService.idl
@@ -21,26 +21,28 @@ interface nsIUTF8ConverterService : nsIS
    *        'UTF8ness' check. Set this to PR_TRUE only if you suspect that 
    *        aString can be mistaken for ASCII / UTF-8 but is actually NOT 
    *        in ASCII / UTF-8 so that aString has to go through the conversion.
    *        skipping ASCIIness/UTF8ness check.
    *        The most common case is the input is in 7bit non-ASCII charsets
    *        like ISO-2022-JP, HZ or UTF-7 (in its original form or
    *        a modified form used in IMAP folder names).
    * @param aAllowSubstitution when true, allow the decoder to substitute
-   *        invalid input sequences by replacement characters
+   *        invalid input sequences by replacement characters (defaults to
+   *        true)
    * @return the converted string in UTF-8.
    * @throws NS_ERROR_UCONV_NOCONV when there is no decoder for aCharset
    *         or error code of nsIUnicodeDecoder in case of conversion failure
    */
 
+    [optional_argc]
     AUTF8String convertStringToUTF8(in ACString aString, 
                                     in string   aCharset,
                                     in boolean  aSkipCheck,
-                                    in boolean  aAllowSubstitution);
+                                    [optional] in boolean aAllowSubstitution);
 
 /* XXX : To-be-added. convertStringFromUTF8 */
    
   /**
    * Ensure that |aSpec| (after URL-unescaping it) is encoded in UTF-8.  
    * If not,  convert it to UTF-8, assuming it's encoded in |aCharset|,  
    * and return the result.
    *
--- a/intl/uconv/src/nsUTF8ConverterService.cpp
+++ b/intl/uconv/src/nsUTF8ConverterService.cpp
@@ -54,30 +54,33 @@ ToUTF8(const nsACString &aString, const 
   return rv;
 }
 
 NS_IMETHODIMP  
 nsUTF8ConverterService::ConvertStringToUTF8(const nsACString &aString, 
                                             const char *aCharset, 
                                             bool aSkipCheck, 
                                             bool aAllowSubstitution,
+                                            PRUint8 aOptionalArgc,
                                             nsACString &aUTF8String)
 {
+  bool allowSubstitution = (aOptionalArgc == 1) ? aAllowSubstitution : true;
+
   // return if ASCII only or valid UTF-8 providing that the ASCII/UTF-8
   // check is requested. It may not be asked for if a caller suspects
   // that the input is in non-ASCII 7bit charset (ISO-2022-xx, HZ) or 
   // it's in a charset other than UTF-8 that can be mistaken for UTF-8.
   if (!aSkipCheck && (IsASCII(aString) || IsUTF8(aString))) {
     aUTF8String = aString;
     return NS_OK;
   }
 
   aUTF8String.Truncate();
 
-  nsresult rv = ToUTF8(aString, aCharset, aAllowSubstitution, aUTF8String);
+  nsresult rv = ToUTF8(aString, aCharset, allowSubstitution, aUTF8String);
 
   // additional protection for cases where check is skipped and  the input
   // is actually in UTF-8 as opposed to aCharset. (i.e. caller's hunch
   // was wrong.) We don't check ASCIIness assuming there's no charset
   // incompatible with ASCII (we don't support EBCDIC).
   if (aSkipCheck && NS_FAILED(rv) && IsUTF8(aString)) {
     aUTF8String = aString;
     return NS_OK;
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -80,16 +80,96 @@ GetBuildConfiguration(JSContext *cx, uns
 #ifdef JS_THREADSAFE
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
     if (!JS_SetProperty(cx, info, "has-gczeal", &value))
         return false;
 
+#ifdef JS_MORE_DETERMINISTIC
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "more-deterministic", &value))
+        return false;
+
+#ifdef MOZ_PROFILING
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "profiling", &value))
+        return false;
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "dtrace", &value))
+        return false;
+
+#ifdef MOZ_TRACE_JSCALLS
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "trace-jscalls-api", &value))
+        return false;
+
+#ifdef JSGC_INCREMENTAL
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "incremental-gc", &value))
+        return false;
+
+#ifdef JSGC_GENERATIONAL
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "generational-gc", &value))
+        return false;
+
+#ifdef MOZ_VALGRIND
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "valgrind", &value))
+        return false;
+
+#ifdef JS_OOM_DO_BACKTRACES
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "oom-backtraces", &value))
+        return false;
+
+#ifdef JS_METHODJIT
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "methodjit", &value))
+        return false;
+
+#ifdef JS_HAS_XML_SUPPORT
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "e4x", &value))
+        return false;
+
     *vp = ObjectValue(*info);
     return true;
 }
 
 static JSBool
 GC(JSContext *cx, unsigned argc, jsval *vp)
 {
     /*
@@ -378,17 +458,17 @@ GCPreserveCode(JSContext *cx, unsigned a
 static JSBool
 DeterministicGC(JSContext *cx, unsigned argc, jsval *vp)
 {
     if (argc != 1) {
         ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
         return JS_FALSE;
     }
 
-    gc::SetDeterministicGC(cx, js_ValueToBoolean(vp[2]));
+    gc::SetDeterministicGC(cx, ToBoolean(vp[2]));
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 #endif /* JS_GC_ZEAL */
 
 struct JSCountHeapNode {
     void                *thing;
     JSGCTraceKind       kind;
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -286,21 +286,19 @@ HOST_CMMOBJS = $(addprefix host_,$(HOST_
 ifndef HOST_OBJS
 _HOST_OBJS = $(HOST_COBJS) $(HOST_CCOBJS) $(HOST_CPPOBJS) $(HOST_CMOBJS) $(HOST_CMMOBJS)
 HOST_OBJS = $(strip $(_HOST_OBJS))
 endif
 
 ifndef MOZ_AUTO_DEPS
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:=.pp))
-ifndef NO_GEN_XPT
 MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
 endif
 endif
-endif
 
 ALL_TRASH = \
 	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
 	$(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
 	$(OBJS:.$(OBJ_SUFFIX)=.i) $(OBJS:.$(OBJ_SUFFIX)=.i_o) \
 	$(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\
 	$(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \
 	$(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \
@@ -1293,17 +1291,16 @@ xpidl-preqs = \
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
 	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  $(PLY_INCLUDE) \
 	  $(LIBXUL_DIST)/sdk/bin/header.py $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
-ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
 # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
 $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(xpidl-preqs)
 	$(REPORT_BUILD)
 	$(PYTHON_PATH) \
 	  $(PLY_INCLUDE) \
 	  -I$(topsrcdir)/xpcom/typelib/xpt/tools \
 	  $(LIBXUL_DIST)/sdk/bin/typelib.py $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
@@ -1318,18 +1315,16 @@ libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).
 ifndef NO_DIST_INSTALL
 	$(call install_cmd,$(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components)
 ifndef NO_INTERFACES_MANIFEST
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPIDL_MODULE).xpt"
 	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
 endif
 endif
 
-endif # NO_GEN_XPT
-
 GARBAGE_DIRS		+= $(XPIDL_GEN_DIR)
 
 endif #} XPIDLSRCS
 
 
 ifndef INCLUDED_XPIDL_MK
   include $(topsrcdir)/config/makefiles/xpidl.mk
 endif
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -594,16 +594,18 @@ EmitNonLocalJumpFixup(JSContext *cx, Byt
                  * For a for-let-in statement, pushing/popping the block is
                  * interleaved with JSOP_(END)ITER. Just handle both together
                  * here and skip over the enclosing STMT_FOR_IN_LOOP.
                  */
                 JS_ASSERT(stmt->down->type == STMT_FOR_IN_LOOP);
                 stmt = stmt->down;
                 if (stmt == toStmt)
                     break;
+                if (NewSrcNote(cx, bce, SRC_HIDDEN) < 0)
+                    return false;
                 if (Emit1(cx, bce, JSOP_LEAVEFORLETIN) < 0)
                     return false;
                 if (!PopIterator(cx, bce))
                     return false;
                 if (NewSrcNote(cx, bce, SRC_HIDDEN) < 0)
                     return false;
                 EMIT_UINT16_IMM_OP(JSOP_POPN, blockObjCount);
             } else {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/function-tosource-genexpr.js
@@ -0,0 +1,7 @@
+function getgen() {
+    gen = getgen.caller;
+}
+var gen;
+(getgen() for (x of [1])).next();
+assertEq(gen.toSource(), "function genexp() {\n    [generator expression]\n}");
+assertEq(decompileBody(gen), "\n    [generator expression]\n");
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -317,17 +317,17 @@ JS_ConvertArgumentsVA(JSContext *cx, uns
                     }
                 }
                 return JS_FALSE;
             }
             break;
         }
         switch (c) {
           case 'b':
-            *va_arg(ap, JSBool *) = js_ValueToBoolean(*sp);
+            *va_arg(ap, JSBool *) = ToBoolean(*sp);
             break;
           case 'c':
             if (!JS_ValueToUint16(cx, *sp, va_arg(ap, uint16_t *)))
                 return JS_FALSE;
             break;
           case 'i':
             if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32_t *)))
                 return JS_FALSE;
@@ -475,17 +475,17 @@ JS_ConvertValue(JSContext *cx, jsval v, 
             *vp = STRING_TO_JSVAL(str);
         break;
       case JSTYPE_NUMBER:
         ok = JS_ValueToNumber(cx, v, &d);
         if (ok)
             *vp = DOUBLE_TO_JSVAL(d);
         break;
       case JSTYPE_BOOLEAN:
-        *vp = BOOLEAN_TO_JSVAL(js_ValueToBoolean(v));
+        *vp = BooleanValue(ToBoolean(v));
         return JS_TRUE;
       default: {
         char numBuf[12];
         JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE, numBuf);
         ok = JS_FALSE;
         break;
       }
@@ -627,17 +627,17 @@ JS_ValueToUint16(JSContext *cx, jsval v,
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, v);
-    *bp = js_ValueToBoolean(v);
+    *bp = ToBoolean(v);
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSType)
 JS_TypeOfValue(JSContext *cx, jsval v)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -5337,39 +5337,42 @@ JS_CompileFunction(JSContext *cx, JSObje
 
 JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    if (script->function())
-        return JS_DecompileFunction(cx, script->function(), indent);
+    RootedFunction fun(cx, script->function());
+    if (fun)
+        return JS_DecompileFunction(cx, fun, indent);
     return script->sourceData(cx);
 }
 
 JS_PUBLIC_API(JSString *)
-JS_DecompileFunction(JSContext *cx, JSFunction *fun, unsigned indent)
+JS_DecompileFunction(JSContext *cx, JSFunction *funArg, unsigned indent)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, fun);
-    return fun->toString(cx, false, !(indent & JS_DONT_PRETTY_PRINT));
+    assertSameCompartment(cx, funArg);
+    RootedFunction fun(cx, funArg);
+    return FunctionToString(cx, fun, false, !(indent & JS_DONT_PRETTY_PRINT));
 }
 
 JS_PUBLIC_API(JSString *)
-JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, unsigned indent)
+JS_DecompileFunctionBody(JSContext *cx, JSFunction *funArg, unsigned indent)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, fun);
-    return fun->toString(cx, true, !(indent & JS_DONT_PRETTY_PRINT));
+    assertSameCompartment(cx, funArg);
+    RootedFunction fun(cx, funArg);
+    return FunctionToString(cx, fun, true, !(indent & JS_DONT_PRETTY_PRINT));
 }
 
 JS_NEVER_INLINE JS_PUBLIC_API(JSBool)
 JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *scriptArg_, jsval *rval)
 {
     RootedScript scriptArg(cx, scriptArg_);
 
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2659,16 +2659,22 @@ JS_ValueToNumber(JSContext *cx, jsval v,
 
 #ifdef __cplusplus
 namespace js {
 /*
  * DO NOT CALL THIS.  Use JS::ToNumber
  */
 extern JS_PUBLIC_API(bool)
 ToNumberSlow(JSContext *cx, JS::Value v, double *dp);
+
+/*
+ * DO NOT CALL THIS. Use JS::ToBoolean
+ */
+extern JS_PUBLIC_API(bool)
+ToBooleanSlow(const JS::Value &v);
 } /* namespace js */
 
 namespace JS {
 
 /* ES5 9.3 ToNumber. */
 JS_ALWAYS_INLINE bool
 ToNumber(JSContext *cx, const Value &v, double *out)
 {
@@ -2677,16 +2683,36 @@ ToNumber(JSContext *cx, const Value &v, 
     if (v.isNumber()) {
         *out = v.toNumber();
         MaybeCheckStackRoots(cx);
         return true;
     }
     return js::ToNumberSlow(cx, v, out);
 }
 
+JS_ALWAYS_INLINE bool
+ToBoolean(const Value &v)
+{
+    if (v.isBoolean())
+        return v.toBoolean();
+    if (v.isInt32())
+        return v.toInt32() != 0;
+    if (v.isObject())
+        return true;
+    if (v.isNullOrUndefined())
+        return false;
+    if (v.isDouble()) {
+        double d = v.toDouble();
+        return !MOZ_DOUBLE_IS_NaN(d) && d != 0;
+    }
+
+    /* Slow path. Handle Strings. */
+    return js::ToBooleanSlow(v);
+}
+
 } /* namespace JS */
 #endif /* __cplusplus */
 
 extern JS_PUBLIC_API(JSBool)
 JS_DoubleIsInt32(double d, int32_t *ip);
 
 extern JS_PUBLIC_API(int32_t)
 JS_DoubleToInt32(double d);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3086,31 +3086,31 @@ class ArrayForEachBehavior
     static Value lateExitValue() { return UndefinedValue(); }
 };
 
 class ArrayEveryBehavior
 {
   public:
     static bool shouldExit(Value &callval, Value *rval)
     {
-        if (!js_ValueToBoolean(callval)) {
+        if (!ToBoolean(callval)) {
             *rval = BooleanValue(false);
             return true;
         }
         return false;
     }
     static Value lateExitValue() { return BooleanValue(true); }
 };
 
 class ArraySomeBehavior
 {
   public:
     static bool shouldExit(Value &callval, Value *rval)
     {
-        if (js_ValueToBoolean(callval)) {
+        if (ToBoolean(callval)) {
             *rval = BooleanValue(true);
             return true;
         }
         return false;
     }
     static Value lateExitValue() { return BooleanValue(false); }
 };
 
@@ -3342,17 +3342,17 @@ array_filter(JSContext *cx, unsigned arg
             ag.setCallee(ObjectValue(*callable));
             ag.thisv() = thisv;
             ag[0] = kValue;
             ag[1] = NumberValue(k);
             ag[2] = ObjectValue(*obj);
             if (!Invoke(cx, ag))
                 return false;
 
-            if (js_ValueToBoolean(ag.rval())) {
+            if (ToBoolean(ag.rval())) {
                 if(!SetArrayElement(cx, arr, to, kValue))
                     return false;
                 to++;
             }
         }
 
         /* Step d. */
         k++;
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -124,17 +124,17 @@ static JSFunctionSpec boolean_methods[] 
     JS_FS_END
 };
 
 static JSBool
 Boolean(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    bool b = args.length() != 0 ? js_ValueToBoolean(args[0]) : false;
+    bool b = args.length() != 0 ? JS::ToBoolean(args[0]) : false;
 
     if (IsConstructing(vp)) {
         JSObject *obj = BooleanObject::create(cx, b);
         if (!obj)
             return false;
         args.rval().setObject(*obj);
     } else {
         args.rval().setBoolean(b);
@@ -186,44 +186,32 @@ js_InitBooleanClass(JSContext *cx, JSObj
 JSString *
 js_BooleanToString(JSContext *cx, JSBool b)
 {
     return cx->runtime->atomState.booleanAtoms[b ? 1 : 0];
 }
 
 namespace js {
 
+JS_PUBLIC_API(bool)
+ToBooleanSlow(const Value &v)
+{
+    JS_ASSERT(v.isString());
+    return v.toString()->length() != 0;
+}
+
 bool
 BooleanGetPrimitiveValueSlow(JSContext *cx, JSObject &obj, Value *vp)
 {
     InvokeArgsGuard ag;
     if (!cx->stack.pushInvokeArgs(cx, 0, &ag))
         return false;
     ag.calleev() = cx->compartment->maybeGlobal()->booleanValueOf();
     ag.thisv().setObject(obj);
     if (!Invoke(cx, ag))
         return false;
     *vp = ag.rval();
     return true;
 }
 
 }  /* namespace js */
 
-JSBool
-js_ValueToBoolean(const Value &v)
-{
-    if (v.isInt32())
-        return v.toInt32() != 0;
-    if (v.isString())
-        return v.toString()->length() != 0;
-    if (v.isObject())
-        return JS_TRUE;
-    if (v.isNullOrUndefined())
-        return JS_FALSE;
-    if (v.isDouble()) {
-        double d;
 
-        d = v.toDouble();
-        return !MOZ_DOUBLE_IS_NaN(d) && d != 0;
-    }
-    JS_ASSERT(v.isBoolean());
-    return v.toBoolean();
-}
--- a/js/src/jsbool.h
+++ b/js/src/jsbool.h
@@ -21,12 +21,9 @@ js_BooleanToString(JSContext *cx, JSBool
 
 namespace js {
 
 inline bool
 BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp);
 
 } /* namespace js */
 
-extern JSBool
-js_ValueToBoolean(const js::Value &v);
-
 #endif /* jsbool_h___ */
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -521,17 +521,17 @@ JS_FRIEND_DATA(Class) js::FunctionClass 
     fun_hasInstance,
     NULL,                    /* construct   */
     fun_trace
 };
 
 
 /* Find the body of a function (not including braces). */
 static bool
-FindBody(JSContext *cx, JSFunction *fun, const jschar *chars, size_t length,
+FindBody(JSContext *cx, HandleFunction fun, const jschar *chars, size_t length,
          size_t *bodyStart, size_t *bodyEnd)
 {
     // We don't need principals, since those are only used for error reporting.
     TokenStream ts(cx, NULL, NULL, chars, length, "internal-FindBody", 0,
                    fun->script()->getVersion(), NULL);
     JS_ASSERT(chars[0] == '(');
     int nest = 0;
     bool onward = true;
@@ -568,93 +568,102 @@ FindBody(JSContext *cx, JSFunction *fun,
     } else {
         JS_ASSERT(!braced);
     }
     *bodyEnd = p.get() - chars;
     return true;
 }
 
 JSString *
-JSFunction::toString(JSContext *cx, bool bodyOnly, bool lambdaParen)
+js::FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen)
 {
     StringBuffer out(cx);
 
+    if (fun->isInterpreted() && fun->script()->isGeneratorExp) {
+        if ((!bodyOnly && !out.append("function genexp() {")) ||
+            !out.append("\n    [generator expression]\n") ||
+            (!bodyOnly && !out.append("}"))) {
+            return NULL;
+        }
+        return out.finishString();
+    }
     if (!bodyOnly) {
         // If we're not in pretty mode, put parentheses around lambda functions.
-        if (isInterpreted() && !lambdaParen && (flags & JSFUN_LAMBDA)) {
+        if (fun->isInterpreted() && !lambdaParen && (fun->flags & JSFUN_LAMBDA)) {
             if (!out.append("("))
                 return NULL;
         }
         if (!out.append("function "))
             return NULL;
-        if (atom) {
-            if (!out.append(atom))
+        if (fun->atom) {
+            if (!out.append(fun->atom))
                 return NULL;
         }
     }
-    bool haveSource = isInterpreted();
-    if (haveSource && !script()->source && !script()->loadSource(cx, &haveSource))
+    bool haveSource = fun->isInterpreted();
+    if (haveSource && !fun->script()->source && !fun->script()->loadSource(cx, &haveSource))
             return NULL;
     if (haveSource) {
-        RootedString src(cx, script()->sourceData(cx));
+        RootedScript script(cx, fun->script());
+        RootedString src(cx, fun->script()->sourceData(cx));
         if (!src)
             return NULL;
         const jschar *chars = src->getChars(cx);
         if (!chars)
             return NULL;
-        bool exprBody = flags & JSFUN_EXPR_CLOSURE;
+        bool exprBody = fun->flags & JSFUN_EXPR_CLOSURE;
 
         // The source data for functions created by calling the Function
         // constructor is only the function's body.
-        bool funCon = script()->sourceStart == 0 && script()->source->argumentsNotIncluded();
+        bool funCon = script->sourceStart == 0 && script->source->argumentsNotIncluded();
 
         // Functions created with the constructor should not be using the
         // expression body extension.
         JS_ASSERT_IF(funCon, !exprBody);
         JS_ASSERT_IF(!funCon, src->length() > 0 && chars[0] == '(');
 
         // If a function inherits strict mode by having scopes above it that
         // have "use strict", we insert "use strict" into the body of the
         // function. This ensures that if the result of toString is evaled, the
         // resulting function will have the same semantics.
-        bool addUseStrict = script()->strictModeCode && !script()->explicitUseStrict;
+        bool addUseStrict = script->strictModeCode && !script->explicitUseStrict;
 
         // Functions created with the constructor can't have inherited strict
         // mode.
         JS_ASSERT(!funCon || !addUseStrict);
         bool buildBody = funCon && !bodyOnly;
         if (buildBody) {
             // This function was created with the Function constructor. We don't
             // have source for the arguments, so we have to generate that. Part
             // of bug 755821 should be cobbling the arguments passed into the
             // Function constructor into the source string.
             if (!out.append("("))
                 return NULL;
 
             // Fish out the argument names.
             BindingVector *localNames = cx->new_<BindingVector>(cx);
             js::ScopedDeletePtr<BindingVector> freeNames(localNames);
-            if (!GetOrderedBindings(cx, script()->bindings, localNames))
+            if (!GetOrderedBindings(cx, script->bindings, localNames))
                 return NULL;
-            for (unsigned i = 0; i < nargs; i++) {
+            for (unsigned i = 0; i < fun->nargs; i++) {
                 if ((i && !out.append(", ")) ||
-                    (i == unsigned(nargs - 1) && hasRest() && !out.append("...")) ||
+                    (i == unsigned(fun->nargs - 1) && fun->hasRest() && !out.append("...")) ||
                     !out.append((*localNames)[i].maybeName)) {
                     return NULL;
                 }
             }
             if (!out.append(") {\n"))
                 return NULL;
         }
         if ((bodyOnly && !funCon) || addUseStrict) {
             // We need to get at the body either because we're only supposed to
             // return the body or we need to insert "use strict" into the body.
             JS_ASSERT(!buildBody);
             size_t bodyStart = 0, bodyEnd = 0;
-            if (!FindBody(cx, this, chars, src->length(), &bodyStart, &bodyEnd))
+            if (!FindBody(cx, fun, chars, src->length(), &bodyStart, &bodyEnd))
                 return NULL;
 
             if (addUseStrict) {
                 // Output source up to beginning of body.
                 if (!out.append(chars, bodyStart))
                     return NULL;
                 if (exprBody) {
                     // We can't insert a statement into a function with an
@@ -680,29 +689,29 @@ JSFunction::toString(JSContext *cx, bool
         if (buildBody) {
             if (!out.append("\n}"))
                 return NULL;
         }
         if (bodyOnly) {
             // Slap a semicolon on the end of functions with an expression body.
             if (exprBody && !out.append(";"))
                 return NULL;
-        } else if (!lambdaParen && (flags & JSFUN_LAMBDA)) {
+        } else if (!lambdaParen && (fun->flags & JSFUN_LAMBDA)) {
             if (!out.append(")"))
                 return NULL;
         }
-    } else if (isInterpreted()) {
+    } else if (fun->isInterpreted()) {
         if ((!bodyOnly && !out.append("() {\n    ")) ||
             !out.append("[sourceless code]") ||
             (!bodyOnly && !out.append("\n}")))
             return NULL;
-        if (!lambdaParen && (flags & JSFUN_LAMBDA) && (!out.append(")")))
+        if (!lambdaParen && (fun->flags & JSFUN_LAMBDA) && (!out.append(")")))
             return NULL;
     } else {
-        JS_ASSERT(!(flags & JSFUN_EXPR_CLOSURE));
+        JS_ASSERT(!(fun->flags & JSFUN_EXPR_CLOSURE));
         if ((!bodyOnly && !out.append("() {\n    ")) ||
             !out.append("[native code]") ||
             (!bodyOnly && !out.append("\n}")))
             return NULL;
     }
     return out.finishString();
 }
 
@@ -714,21 +723,18 @@ fun_toStringHelper(JSContext *cx, JSObje
             return Proxy::fun_toString(cx, obj, indent);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO,
                              js_Function_str, js_toString_str,
                              "object");
         return NULL;
     }
 
-    JSFunction *fun = obj->toFunction();
-    if (!fun)
-        return NULL;
-
-    return fun->toString(cx, false, indent != JS_DONT_PRETTY_PRINT);
+    RootedFunction fun(cx, obj->toFunction());
+    return FunctionToString(cx, fun, false, indent != JS_DONT_PRETTY_PRINT);
 }
 
 static JSBool
 fun_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_ASSERT(IsFunctionObject(vp[0]));
     uint32_t indent = 0;
 
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -148,18 +148,16 @@ struct JSFunction : public JSObject
     inline bool initBoundFunction(JSContext *cx, js::HandleValue thisArg,
                                   const js::Value *args, unsigned argslen);
 
     inline JSObject *getBoundFunctionTarget() const;
     inline const js::Value &getBoundFunctionThis() const;
     inline const js::Value &getBoundFunctionArgument(unsigned which) const;
     inline size_t getBoundFunctionArgumentCount() const;
 
-    JSString *toString(JSContext *cx, bool bodyOnly, bool pretty);
-
   private:
     inline js::FunctionExtended *toExtended();
     inline const js::FunctionExtended *toExtended() const;
 
     inline bool isExtended() const {
         JS_STATIC_ASSERT(FinalizeKind != ExtendedFinalizeKind);
         JS_ASSERT(!!(flags & JSFUN_EXTENDED) == (getAllocKind() == ExtendedFinalizeKind));
         return !!(flags & JSFUN_EXTENDED);
@@ -243,16 +241,18 @@ inline const js::FunctionExtended *
 JSFunction::toExtended() const
 {
     JS_ASSERT(isExtended());
     return static_cast<const js::FunctionExtended *>(this);
 }
 
 namespace js {
 
+JSString *FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen);
+
 template<XDRMode mode>
 bool
 XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
                        HandleScript enclosingScript, JSObject **objp);
 
 extern JSObject *
 CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -880,20 +880,18 @@ DoIncDec(JSContext *cx, HandleScript scr
 #define POP_COPY_TO(v)           v = *--regs.sp
 #define POP_RETURN_VALUE()       regs.fp()->setReturnValue(*--regs.sp)
 
 #define VALUE_TO_BOOLEAN(cx, vp, b)                                           \
     JS_BEGIN_MACRO                                                            \
         vp = &regs.sp[-1];                                                    \
         if (vp->isNull()) {                                                   \
             b = false;                                                        \
-        } else if (vp->isBoolean()) {                                         \
-            b = vp->toBoolean();                                              \
         } else {                                                              \
-            b = !!js_ValueToBoolean(*vp);                                     \
+            b = ToBoolean(*vp);                                               \
         }                                                                     \
     JS_END_MACRO
 
 #define POP_BOOLEAN(cx, vp, b)   do { VALUE_TO_BOOLEAN(cx, vp, b); regs.sp--; } while(0)
 
 #define FETCH_OBJECT(cx, n, obj)                                              \
     JS_BEGIN_MACRO                                                            \
         Value *vp_ = &regs.sp[n];                                             \
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -730,17 +730,17 @@ Iterator(JSContext *cx, unsigned argc, V
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() == 0) {
         js_ReportMissingArg(cx, args.calleev(), 0);
         return false;
     }
 
     bool keyonly = false;
     if (args.length() >= 2)
-        keyonly = js_ValueToBoolean(args[1]);
+        keyonly = ToBoolean(args[1]);
     unsigned flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
 
     if (!ValueToIterator(cx, flags, &args[0]))
         return false;
     args.rval() = args[0];
     return true;
 }
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1296,27 +1296,27 @@ PropDesc::initialize(JSContext *cx, cons
     RootedId id(cx);
 
     /* 8.10.5 step 3 */
     id = NameToId(cx->runtime->atomState.enumerableAtom);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasEnumerable_ = true;
-        if (js_ValueToBoolean(v))
+        if (ToBoolean(v))
             attrs |= JSPROP_ENUMERATE;
     }
 
     /* 8.10.5 step 4 */
     id = NameToId(cx->runtime->atomState.configurableAtom);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasConfigurable_ = true;
-        if (js_ValueToBoolean(v))
+        if (ToBoolean(v))
             attrs &= ~JSPROP_PERMANENT;
     }
 
     /* 8.10.5 step 5 */
     id = NameToId(cx->runtime->atomState.valueAtom);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
@@ -1325,17 +1325,17 @@ PropDesc::initialize(JSContext *cx, cons
     }
 
     /* 8.10.6 step 6 */
     id = NameToId(cx->runtime->atomState.writableAtom);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasWritable_ = true;
-        if (js_ValueToBoolean(v))
+        if (ToBoolean(v))
             attrs &= ~JSPROP_READONLY;
     }
 
     /* 8.10.7 step 7 */
     id = NameToId(cx->runtime->atomState.getAtom);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -492,16 +492,18 @@ FlowsIntoNext(JSOp op)
  * coherent fashion.
  */
 class PCCounts
 {
     friend struct ::JSScript;
     double *counts;
 #ifdef DEBUG
     size_t capacity;
+#elif JS_BITS_PER_WORD == 32
+    void *padding;
 #endif
 
  public:
 
     enum BaseCounts {
         BASE_INTERP = 0,
         BASE_METHODJIT,
 
@@ -610,16 +612,19 @@ class PCCounts
     }
 
     /* Boolean conversion, for 'if (counters) ...' */
     operator void*() const {
         return counts;
     }
 };
 
+/* Necessary for alignment with the script. */
+JS_STATIC_ASSERT(sizeof(PCCounts) % sizeof(Value) == 0);
+
 } /* namespace js */
 
 #if defined(DEBUG)
 /*
  * Disassemblers, for debugging only.
  */
 extern JS_FRIEND_API(JSBool)
 js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, js::Sprinter *sp);
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -687,17 +687,17 @@ IndicatePropertyNotFound(JSContext *cx, 
 {
     desc->obj = NULL;
     return true;
 }
 
 static bool
 ValueToBool(JSContext *cx, const Value &v, bool *bp)
 {
-    *bp = !!js_ValueToBoolean(v);
+    *bp = ToBoolean(v);
     return true;
 }
 
 static bool
 ArrayToIdVector(JSContext *cx, const Value &array, AutoIdVector &props)
 {
     JS_ASSERT(props.length() == 0);
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -3192,17 +3192,17 @@ reflect_parse(JSContext *cx, uint32_t ar
 
         Value prop;
 
         /* config.loc */
         RootedId locId(cx, NameToId(cx->runtime->atomState.locAtom));
         if (!baseops::GetPropertyDefault(cx, config, locId, BooleanValue(true), &prop))
             return JS_FALSE;
 
-        loc = js_ValueToBoolean(prop);
+        loc = ToBoolean(prop);
 
         if (loc) {
             /* config.source */
             RootedId sourceId(cx, NameToId(cx->runtime->atomState.sourceAtom));
             if (!baseops::GetPropertyDefault(cx, config, sourceId, NullValue(), &prop))
                 return JS_FALSE;
 
             if (!prop.isNullOrUndefined()) {
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -352,16 +352,17 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         StrictModeCode,
         ContainsDynamicNameAccess,
         FunHasExtensibleScope,
         ArgumentsHasVarBinding,
         NeedsArgsObj,
         OwnFilename,
         ParentFilename,
         IsGenerator,
+        IsGeneratorExp,
         HaveSource,
         OwnSource,
         ExplicitUseStrict
     };
 
     uint32_t length, lineno, nslots;
     uint32_t natoms, nsrcnotes, ntrynotes, nobjects, nregexps, nconsts, nClosedArgs, nClosedVars, i;
     uint32_t prologLength, version;
@@ -520,16 +521,18 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         }
         if (script->source) {
             scriptBits |= (1 << HaveSource);
             if (!enclosingScript || enclosingScript->source != script->source)
                 scriptBits |= (1 << OwnSource);
         }
         if (script->isGenerator)
             scriptBits |= (1 << IsGenerator);
+        if (script->isGeneratorExp)
+            scriptBits |= (1 << IsGeneratorExp);
 
         JS_ASSERT(!script->compileAndGo);
         JS_ASSERT(!script->hasSingletons);
     }
 
     if (!xdr->codeUint32(&prologLength))
         return JS_FALSE;
     if (!xdr->codeUint32(&version))
@@ -601,16 +604,18 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         if (scriptBits & (1 << FunHasExtensibleScope))
             script->funHasExtensibleScope = true;
         if (scriptBits & (1 << ArgumentsHasVarBinding))
             script->setArgumentsHasVarBinding();
         if (scriptBits & (1 << NeedsArgsObj))
             script->setNeedsArgsObj(true);
         if (scriptBits & (1 << IsGenerator))
             script->isGenerator = true;
+        if (scriptBits & (1 << IsGeneratorExp))
+            script->isGeneratorExp = true;
     }
 
     JS_STATIC_ASSERT(sizeof(jsbytecode) == 1);
     JS_STATIC_ASSERT(sizeof(jssrcnote) == 1);
     if (!xdr->codeBytes(script->code, length) ||
         !xdr->codeBytes(notes, nsrcnotes) ||
         !xdr->codeUint32(&lineno) ||
         !xdr->codeUint32(&nslots)) {
@@ -843,16 +848,17 @@ JSScript::initScriptCounts(JSContext *cx
 
     DebugOnly<char *> base = cursor;
 
     ScriptCounts scriptCounts;
     scriptCounts.pcCountsVector = (PCCounts *) cursor;
     cursor += length * sizeof(PCCounts);
 
     for (pc = code; pc < code + length; pc = next) {
+        JS_ASSERT(uintptr_t(cursor) % sizeof(double) == 0);
         scriptCounts.pcCountsVector[pc - code].counts = (double *) cursor;
         size_t capacity = PCCounts::numCounts(JSOp(*pc));
 #ifdef DEBUG
         scriptCounts.pcCountsVector[pc - code].capacity = capacity;
 #endif
         cursor += capacity * sizeof(double);
         next = pc + GetBytecodeLength(pc);
     }
@@ -1172,21 +1178,23 @@ ScriptSource::substring(JSContext *cx, u
 ScriptSource *
 ScriptSource::createFromSource(JSContext *cx, const jschar *src, uint32_t length,
                                bool argumentsNotIncluded, SourceCompressionToken *tok,
                                bool ownSource)
 {
     ScriptSource *ss = static_cast<ScriptSource *>(cx->malloc_(sizeof(*ss)));
     if (!ss)
         return NULL;
-    const size_t memlen = length * sizeof(jschar);
-    ss->data.compressed = static_cast<unsigned char *>(cx->malloc_(memlen));
-    if (!ss->data.compressed) {
-        cx->free_(ss);
-        return NULL;
+    if (!ownSource) {
+        const size_t memlen = length * sizeof(jschar);
+        ss->data.compressed = static_cast<unsigned char *>(cx->malloc_(memlen));
+        if (!ss->data.compressed) {
+            cx->free_(ss);
+            return NULL;
+        }
     }
     ss->next = NULL;
     ss->length_ = length;
     ss->compressedLength = 0;
     ss->marked = ss->onRuntime_ = false;
     ss->argumentsNotIncluded_ = argumentsNotIncluded;
 #ifdef DEBUG
     ss->ready_ = false;
@@ -1809,16 +1817,17 @@ JSScript::fullyInitFromEmitter(JSContext
         PodCopy<uint32_t>(script->closedVars()->vector, &bce->closedVars[0], nClosedVars);
 
     script->bindings.transfer(&bce->sc->bindings);
 
     RootedFunction fun(cx, NULL);
     if (bce->sc->inFunction()) {
         JS_ASSERT(!bce->script->noScriptRval);
         script->isGenerator = bce->sc->funIsGenerator();
+        script->isGeneratorExp = bce->sc->funbox() && bce->sc->funbox()->inGenexpLambda;
         script->setFunction(bce->sc->fun());
     }
 
     /*
      * initScriptCounts updates scriptCountsMap if necessary. The other script
      * maps in JSCompartment are populated lazily.
      */
     if (cx->hasRunOption(JSOPTION_PCCOUNT))
@@ -2284,16 +2293,17 @@ js::CloneScript(JSContext *cx, HandleObj
     }
     dst->cloneHasArray(src);
     dst->strictModeCode = src->strictModeCode;
     dst->explicitUseStrict = src->explicitUseStrict;
     dst->bindingsAccessedDynamically = src->bindingsAccessedDynamically;
     dst->funHasExtensibleScope = src->funHasExtensibleScope;
     dst->hasSingletons = src->hasSingletons;
     dst->isGenerator = src->isGenerator;
+    dst->isGeneratorExp = src->isGeneratorExp;
 
     /*
      * initScriptCounts updates scriptCountsMap if necessary. The other script
      * maps in JSCompartment are populated lazily.
      */
     if (cx->hasRunOption(JSOPTION_PCCOUNT))
         (void) dst->initScriptCounts(cx);
 
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -535,16 +535,17 @@ struct JSScript : public js::gc::Cell
     bool            isCachedEval:1;   /* script came from eval(), and is in eval cache */
     bool            uninlineable:1;   /* script is considered uninlineable by analysis */
 #ifdef JS_METHODJIT
     bool            debugMode:1;      /* script was compiled in debug mode */
     bool            failedBoundsCheck:1; /* script has had hoisted bounds checks fail */
 #endif
     bool            callDestroyHook:1;/* need to call destroy hook */
     bool            isGenerator:1;    /* is a generator */
+    bool            isGeneratorExp:1; /* is a generator expression */
     bool            hasScriptCounts:1;/* script has an entry in
                                          JSCompartment::scriptCountsMap */
     bool            hasSourceMap:1;   /* script has an entry in
                                          JSCompartment::sourceMapMap */
     bool            hasDebugScript:1; /* script has an entry in
                                          JSCompartment::debugScriptMap */
 
   private:
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -2384,17 +2384,17 @@ DataViewObject::read(JSContext *cx, Hand
                              JSMSG_MORE_ARGS_NEEDED, method, "0", "s");
         return false;
     }
 
     uint8_t *data;
     if (!getDataPointer(cx, obj, args, sizeof(NativeType), &data))
         return false;
 
-    bool fromLittleEndian = args.length() >= 2 && js_ValueToBoolean(args[1]);
+    bool fromLittleEndian = args.length() >= 2 && ToBoolean(args[1]);
     DataViewIO<NativeType>::fromBuffer(val, data, needToSwapBytes(fromLittleEndian));
     return true;
 }
 
 template <typename NativeType>
 static inline bool
 WebIDLCast(JSContext *cx, const Value &value, NativeType *out)
 {
@@ -2440,17 +2440,17 @@ DataViewObject::write(JSContext *cx, Han
     uint8_t *data;
     if (!getDataPointer(cx, obj, args, sizeof(NativeType), &data))
         return false;
 
     NativeType value;
     if (!WebIDLCast(cx, args[1], &value))
         return false;
 
-    bool toLittleEndian = args.length() >= 3 && js_ValueToBoolean(args[2]);
+    bool toLittleEndian = args.length() >= 3 && ToBoolean(args[2]);
     DataViewIO<NativeType>::toBuffer(data, &value, needToSwapBytes(toLittleEndian));
     return true;
 }
 
 bool
 DataViewObject::getInt8Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -7933,17 +7933,17 @@ js_StepXMLListFilter(JSContext *cx, JSBo
     } else {
         /* We have iterated at least once. */
         JS_ASSERT(!JSVAL_IS_PRIMITIVE(sp[-2]));
         JS_ASSERT(JSVAL_TO_OBJECT(sp[-2])->getClass() == &js_XMLFilterClass);
         filter = (JSXMLFilter *) JSVAL_TO_OBJECT(sp[-2])->getPrivate();
         JS_ASSERT(filter->kid);
 
         /* Check if the filter expression wants to append the element. */
-        if (js_ValueToBoolean(sp[-1]) &&
+        if (ToBoolean(sp[-1]) &&
             !Append(cx, filter->result, filter->kid)) {
             return JS_FALSE;
         }
     }
 
     /* Do the iteration. */
     filter->kid = filter->cursor.getNext();
     if (!filter->kid) {
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -565,17 +565,17 @@ mjit::Compiler::jsop_relational(JSOp op,
 void
 mjit::Compiler::jsop_not()
 {
     FrameEntry *top = frame.peek(-1);
 
     if (top->isConstant()) {
         const Value &v = top->getValue();
         frame.pop();
-        frame.push(BooleanValue(!js_ValueToBoolean(v)));
+        frame.push(BooleanValue(!ToBoolean(v)));
         return;
     }
 
     if (top->isTypeKnown()) {
         JSValueType type = top->getKnownType();
         switch (type) {
           case JSVAL_TYPE_INT32:
           {
@@ -841,17 +841,17 @@ mjit::Compiler::booleanJumpScript(JSOp o
 }
 
 bool
 mjit::Compiler::jsop_ifneq(JSOp op, jsbytecode *target)
 {
     FrameEntry *fe = frame.peek(-1);
 
     if (fe->isConstant()) {
-        JSBool b = js_ValueToBoolean(fe->getValue());
+        JSBool b = ToBoolean(fe->getValue());
 
         frame.pop();
 
         if (op == JSOP_IFEQ)
             b = !b;
         if (b) {
             if (!frame.syncForBranch(target, Uses(0)))
                 return false;
@@ -868,17 +868,17 @@ mjit::Compiler::jsop_ifneq(JSOp op, jsby
 }
 
 bool
 mjit::Compiler::jsop_andor(JSOp op, jsbytecode *target)
 {
     FrameEntry *fe = frame.peek(-1);
 
     if (fe->isConstant()) {
-        JSBool b = js_ValueToBoolean(fe->getValue());
+        JSBool b = ToBoolean(fe->getValue());
 
         /* Short-circuit. */
         if ((op == JSOP_OR && b == JS_TRUE) ||
             (op == JSOP_AND && b == JS_FALSE)) {
             if (!frame.syncForBranch(target, Uses(0)))
                 return false;
             if (!jumpAndRun(masm.jump(), target))
                 return false;
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -443,23 +443,23 @@ JSBool JS_FASTCALL
 stubs::GreaterEqual(VMFrame &f)
 {
     RELATIONAL(>=);
 }
 
 JSBool JS_FASTCALL
 stubs::ValueToBoolean(VMFrame &f)
 {
-    return js_ValueToBoolean(f.regs.sp[-1]);
+    return ToBoolean(f.regs.sp[-1]);
 }
 
 void JS_FASTCALL
 stubs::Not(VMFrame &f)
 {
-    JSBool b = !js_ValueToBoolean(f.regs.sp[-1]);
+    JSBool b = !ToBoolean(f.regs.sp[-1]);
     f.regs.sp[-1].setBoolean(b);
 }
 
 template <bool EQ>
 static inline bool
 StubEqualityOp(VMFrame &f)
 {
     JSContext *cx = f.cx;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1562,17 +1562,17 @@ Debugger::getEnabled(JSContext *cx, unsi
     return true;
 }
 
 JSBool
 Debugger::setEnabled(JSContext *cx, unsigned argc, Value *vp)
 {
     REQUIRE_ARGC("Debugger.set enabled", 1);
     THIS_DEBUGGER(cx, argc, vp, "set enabled", args, dbg);
-    bool enabled = js_ValueToBoolean(args[0]);
+    bool enabled = ToBoolean(args[0]);
 
     if (enabled != dbg->enabled) {
         for (Breakpoint *bp = dbg->firstBreakpoint(); bp; bp = bp->nextInDebugger()) {
             if (enabled)
                 bp->site->inc(cx->runtime->defaultFreeOp());
             else
                 bp->site->dec(cx->runtime->defaultFreeOp());
         }
@@ -2068,17 +2068,17 @@ class Debugger::ScriptQuery {
                                  "neither undefined nor an integer");
             return false;
         }
 
         /* Check for an 'innermost' property. */
         Value innermostProperty;
         if (!query->getProperty(cx, cx->runtime->atomState.innermostAtom, &innermostProperty))
             return false;
-        innermost = js_ValueToBoolean(innermostProperty);
+        innermost = ToBoolean(innermostProperty);
         if (innermost) {
             /* Technically, we need only check hasLine, but this is clearer. */
             if (url.isUndefined() || !hasLine) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL);
                 return false;
             }
         }
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -20,17 +20,17 @@ namespace js {
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 123);
+static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 124);
 
 class XDRBuffer {
   public:
     XDRBuffer(JSContext *cx)
       : context(cx), base(NULL), cursor(NULL), limit(NULL) { }
 
     JSContext *cx() const {
         return context;
--- a/js/xpconnect/src/Makefile.in
+++ b/js/xpconnect/src/Makefile.in
@@ -62,17 +62,16 @@ CPPSRCS		= \
 		$(NULL)
 
 include $(topsrcdir)/config/config.mk
 
 LOCAL_INCLUDES = \
 		-I$(srcdir)/../wrappers \
 		-I$(srcdir)/../loader \
 		-I$(topsrcdir)/caps/include \
-		-I$(topsrcdir)/content/base/public \
 		-I$(topsrcdir)/content/base/src \
 		-I$(topsrcdir)/content/events/src \
 		-I$(topsrcdir)/content/html/content/src \
 		-I$(topsrcdir)/content/html/document/src \
 		-I$(topsrcdir)/content/svg/content/src \
 		-I$(topsrcdir)/layout/style \
 		-I$(topsrcdir)/layout/base \
 		-I$(topsrcdir)/dom/base \
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -9,31 +9,31 @@
 #include "mozilla/Util.h"
 
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "XPCJSMemoryReporter.h"
 #include "WrapperFactory.h"
 #include "dom_quickstubs.h"
 
-#include "Element.h"
 #include "nsIMemoryReporter.h"
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
 #include "mozilla/FunctionTimer.h"
 #include "prsystem.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsContentUtils.h"
 #include "nsCCUncollectableMarker.h"
 #include "jsfriendapi.h"
 #include "js/MemoryMetrics.h"
 #include "mozilla/dom/DOMJSClass.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/Element.h"
 #include "mozilla/Attributes.h"
 
 #include "sampler.h"
 #include "nsJSPrincipals.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2625,16 +2625,20 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
     items.SwapElements(entry->mItems);
     commonClipCount = entry->mCommonClipCount;
     containerLayerFrame = entry->mContainerLayerFrame;
     // Later after this point, due to calls to DidEndTransaction
     // for temporary layer managers, mThebesLayerItems can change,
     // so 'entry' could become invalid.
   }
 
+  if (!containerLayerFrame) {
+    return;
+  }
+
   ThebesDisplayItemLayerUserData* userData =
     static_cast<ThebesDisplayItemLayerUserData*>
       (aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
   NS_ASSERTION(userData, "where did our user data go?");
   if (NS_GET_A(userData->mForcedBackgroundColor) > 0) {
     nsIntRect r = aLayer->GetVisibleRegion().GetBounds();
     aContext->NewPath();
     aContext->Rectangle(gfxRect(r.x, r.y, r.width, r.height));
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/770381-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style id="s"></style>
+<script>
+function boom() { document.getElementById("s").textContent = "div { opacity: 0.5; }"; }
+</script>
+</head>
+<body onload="document.documentElement.offsetHeight; boom();">
+<div><div>X</div></div>
+</body>
+</html>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -353,8 +353,9 @@ load 722137.html
 load 725535.html
 load 727601.html
 skip-if(Android&&!browserIsRemote) asserts(0-2) pref(dom.disable_open_during_load,false) load 735943.html # the assertion is bug 735966, for android bug 760271
 asserts(0-2) load 736389-1.xhtml # sometimes the above assertions are delayed and is reported on this test instead
 asserts-if(winWidget,0-2) load 736924-1.html # bug 738803
 load 749816-1.html
 load 763223-1.html
 test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.lineThreshold,100) load 763702.xhtml
+load 770381-1.html
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -60,16 +60,17 @@ nsDisplayListBuilder::nsDisplayListBuild
       mIncludeAllOutOfFlows(false),
       mSelectedFramesOnly(false),
       mAccurateVisibleRegions(false),
       mInTransform(false),
       mSyncDecodeImages(false),
       mIsPaintingToWindow(false),
       mHasDisplayPort(false),
       mHasFixedItems(false),
+      mIsInFixedPosition(false),
       mIsCompositingCheap(false)
 {
   MOZ_COUNT_CTOR(nsDisplayListBuilder);
   PL_InitArenaPool(&mPool, "displayListArena", 1024,
                    NS_MAX(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
 
   nsPresContext* pc = aReferenceFrame->PresContext();
   nsIPresShell *shell = pc->PresShell();
@@ -2067,18 +2068,20 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayL
   nsRefPtr<Layer> layer = GetLayerBuilderForManager(aManager)->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
                            aContainerParameters, nsnull);
   return layer.forget();
 }
 
 nsDisplayFixedPosition::nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
                                                nsIFrame* aFrame,
+                                               nsIFrame* aFixedPosFrame,
                                                nsDisplayList* aList)
-    : nsDisplayOwnLayer(aBuilder, aFrame, aList) {
+    : nsDisplayOwnLayer(aBuilder, aFrame, aList)
+    , mFixedPosFrame(aFixedPosFrame) {
   MOZ_COUNT_CTOR(nsDisplayFixedPosition);
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayFixedPosition::~nsDisplayFixedPosition() {
   MOZ_COUNT_DTOR(nsDisplayFixedPosition);
 }
 #endif
@@ -2089,17 +2092,17 @@ nsDisplayFixedPosition::BuildLayer(nsDis
                                    const ContainerParameters& aContainerParameters) {
   nsRefPtr<Layer> layer =
     nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters);
 
   // Work out the anchor point for this fixed position layer. We assume that
   // any positioning set (left/top/right/bottom) indicates that the
   // corresponding side of its container should be the anchor point,
   // defaulting to top-left.
-  nsIFrame* viewportFrame = mFrame->GetParent();
+  nsIFrame* viewportFrame = mFixedPosFrame->GetParent();
   nsPresContext *presContext = viewportFrame->PresContext();
 
   // Fixed position frames are reflowed into the scroll-port size if one has
   // been set.
   nsSize containingBlockSize = viewportFrame->GetSize();
   if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
     containingBlockSize = presContext->PresShell()->
       GetScrollPositionClampingScrollPortSize();
@@ -2116,17 +2119,17 @@ nsDisplayFixedPosition::BuildLayer(nsDis
                        aContainerParameters.mYScale,
                      NSAppUnitsToFloatPixels(containingBlockSize.width, factor) *
                        aContainerParameters.mXScale,
                      NSAppUnitsToFloatPixels(containingBlockSize.height, factor) *
                        aContainerParameters.mYScale);
 
   gfxPoint anchor(anchorRect.x, anchorRect.y);
 
-  const nsStylePosition* position = mFrame->GetStylePosition();
+  const nsStylePosition* position = mFixedPosFrame->GetStylePosition();
   if (position->mOffset.GetRightUnit() != eStyleUnit_Auto)
     anchor.x = anchorRect.XMost();
   if (position->mOffset.GetBottomUnit() != eStyleUnit_Auto)
     anchor.y = anchorRect.YMost();
 
   layer->SetFixedPositionAnchor(anchor);
 
   return layer.forget();
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -217,16 +217,22 @@ public:
    */
   bool GetHadToIgnorePaintSuppression() { return mHadToIgnoreSuppression; }
   /**
    * Call this if we're doing normal painting to the window.
    */
   void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
   bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
 
+  /**
+   * @return Returns if the builder is currently building an
+   * nsDisplayFixedPosition sub-tree.
+   */
+  bool IsInFixedPosition() const { return mIsInFixedPosition; }
+
   bool SetIsCompositingCheap(bool aCompositingCheap) { 
     bool temp = mIsCompositingCheap; 
     mIsCompositingCheap = aCompositingCheap;
     return temp;
   }
   bool IsCompositingCheap() const { return mIsCompositingCheap; }
   /**
    * Display the caret if needed.
@@ -386,54 +392,61 @@ public:
    * Allocate memory in our arena. It will only be freed when this display list
    * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
    * destructors are called as soon as the item is no longer used.
    */
   void* Allocate(size_t aSize);
   
   /**
    * A helper class to temporarily set the value of
-   * mIsAtRootOfPseudoStackingContext and temporarily update
-   * mCachedOffsetFrame/mCachedOffset from a frame to its child.
+   * mIsAtRootOfPseudoStackingContext and mIsInFixedPosition, and temporarily
+   * update mCachedOffsetFrame/mCachedOffset from a frame to its child.
    */
   class AutoBuildingDisplayList;
   friend class AutoBuildingDisplayList;
   class AutoBuildingDisplayList {
   public:
     AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, bool aIsRoot)
       : mBuilder(aBuilder),
         mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame),
         mPrevCachedOffset(aBuilder->mCachedOffset),
         mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext) {
       aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
     }
     AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
-                            nsIFrame* aForChild, bool aIsRoot)
+                            nsIFrame* aForChild, bool aIsRoot,
+                            bool aIsInFixedPosition)
       : mBuilder(aBuilder),
         mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame),
         mPrevCachedOffset(aBuilder->mCachedOffset),
-        mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext) {
+        mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
+        mPrevIsInFixedPosition(aBuilder->mIsInFixedPosition) {
       if (mPrevCachedOffsetFrame == aForChild->GetParent()) {
         aBuilder->mCachedOffset += aForChild->GetPosition();
       } else {
         aBuilder->mCachedOffset = aForChild->GetOffsetToCrossDoc(aBuilder->ReferenceFrame());
       }
       aBuilder->mCachedOffsetFrame = aForChild;
       aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
+      if (aIsInFixedPosition) {
+        aBuilder->mIsInFixedPosition = aIsInFixedPosition;
+      }
     }
     ~AutoBuildingDisplayList() {
       mBuilder->mCachedOffsetFrame = mPrevCachedOffsetFrame;
       mBuilder->mCachedOffset = mPrevCachedOffset;
       mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
+      mBuilder->mIsInFixedPosition = mPrevIsInFixedPosition;
     }
   private:
     nsDisplayListBuilder* mBuilder;
     const nsIFrame*       mPrevCachedOffsetFrame;
     nsPoint               mPrevCachedOffset;
     bool                  mPrevIsAtRootOfPseudoStackingContext;
+    bool                  mPrevIsInFixedPosition;
   };
 
   /**
    * A helper class to temporarily set the value of mInTransform.
    */
   class AutoInTransformSetter;
   friend class AutoInTransformSetter;
   class AutoInTransformSetter {
@@ -530,16 +543,17 @@ private:
   bool                           mAccurateVisibleRegions;
   // True when we're building a display list that's directly or indirectly
   // under an nsDisplayTransform
   bool                           mInTransform;
   bool                           mSyncDecodeImages;
   bool                           mIsPaintingToWindow;
   bool                           mHasDisplayPort;
   bool                           mHasFixedItems;
+  bool                           mIsInFixedPosition;
   bool                           mIsCompositingCheap;
 };
 
 class nsDisplayItem;
 class nsDisplayList;
 /**
  * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
  * nsDisplayItemLink holds the link. The lists are linked from lowest to
@@ -1915,25 +1929,28 @@ public:
 /**
  * A display item used to represent fixed position elements. This will ensure
  * the contents gets its own layer, and that the built layer will have
  * position-related metadata set on it.
  */
 class nsDisplayFixedPosition : public nsDisplayOwnLayer {
 public:
   nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                         nsDisplayList* aList);
+                         nsIFrame* aFixedPosFrame, nsDisplayList* aList);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFixedPosition();
 #endif
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters);
   NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
+
+protected:
+  nsIFrame* mFixedPosFrame;
 };
 
 /**
  * This potentially creates a layer for the given list of items, whose
  * visibility is determined by the displayport for the given frame instead of
  * what is passed in to ComputeVisibility.
  *
  * Here in content, we can use this to render more content than is actually
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2098,18 +2098,25 @@ nsIFrame::BuildDisplayListForChild(nsDis
   if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating()) ||
       ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
        IsSVGContentWithCSSClip(this)) ||
       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
     // If you change this, also change IsPseudoStackingContextFromStyle()
     pseudoStackingContext = true;
   }
 
+  // This controls later whether we build an nsDisplayWrapList or an
+  // nsDisplayFixedPosition. We check if we're already building a fixed-pos
+  // item and disallow nesting, to prevent the situation of bug #769541
+  // occurring.
+  bool buildFixedPositionItem = disp->mPosition == NS_STYLE_POSITION_FIXED
+    && !child->GetParent()->GetParent() && !isSVG && !aBuilder->IsInFixedPosition();
+
   nsDisplayListBuilder::AutoBuildingDisplayList
-    buildingForChild(aBuilder, child, pseudoStackingContext);
+    buildingForChild(aBuilder, child, pseudoStackingContext, buildFixedPositionItem);
 
   nsRect overflowClip;
   nscoord overflowClipRadii[8];
   bool applyOverflowClip =
     ApplyOverflowClipping(aBuilder, child, disp, &overflowClip);
   if (applyOverflowClip) {
     child->GetPaddingBoxBorderRadii(overflowClipRadii);
   }
@@ -2199,28 +2206,40 @@ nsIFrame::BuildDisplayListForChild(nsDis
   if (isPositioned || isVisuallyAtomic ||
       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
     // Genuine stacking contexts, and positioned pseudo-stacking-contexts,
     // go in this level.
     if (!list.IsEmpty()) {
       // Make sure the root of a fixed position frame sub-tree gets the
       // correct displaylist item type.
       nsDisplayItem* item;
-      if (!isSVG && !child->GetParent()->GetParent() &&
-          disp->mPosition == NS_STYLE_POSITION_FIXED) {
-        item = new (aBuilder) nsDisplayFixedPosition(aBuilder, child, &list);
+      if (buildFixedPositionItem) {
+        item = new (aBuilder) nsDisplayFixedPosition(aBuilder, child, child, &list);
       } else {
         item = new (aBuilder) nsDisplayWrapList(aBuilder, child, &list);
       }
       if (isSVG) {
         rv = aLists.Content()->AppendNewToTop(item);
       } else {
         rv = aLists.PositionedDescendants()->AppendNewToTop(item);
       }
       NS_ENSURE_SUCCESS(rv, rv);
+
+      // Make sure that extra positioned descendants don't escape having
+      // their fixed-position metadata applied to them.
+      if (buildFixedPositionItem) {
+        while (!extraPositionedDescendants.IsEmpty()) {
+          item = extraPositionedDescendants.RemoveBottom();
+          nsDisplayList fixedPosDescendantList;
+          fixedPosDescendantList.AppendToTop(item);
+          aLists.PositionedDescendants()->AppendNewToTop(
+              new (aBuilder) nsDisplayFixedPosition(aBuilder, item->GetUnderlyingFrame(),
+                                                    child, &fixedPosDescendantList));
+        }
+      }
     }
   } else if (!isSVG && disp->IsFloating()) {
     if (!list.IsEmpty()) {
       rv = aLists.Floats()->AppendNewToTop(new (aBuilder)
           nsDisplayWrapList(aBuilder, child, &list));
       NS_ENSURE_SUCCESS(rv, rv);
     }
   } else {
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -552,16 +552,17 @@ RenderFrameParent::ContentViewScaleChang
 {
   // Since the scale has changed for a view, it and its descendents need their
   // shadow-space attributes updated. It's easiest to rebuild the view map.
   BuildViewMap();
 }
 
 void
 RenderFrameParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+                                       const TargetConfig& aTargetConfig,
                                        bool isFirstPaint)
 {
   // View map must only contain views that are associated with the current
   // shadow layer tree. We must always update the map when shadow layers
   // are updated.
   BuildViewMap();
 
   TriggerRepaint();
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -22,30 +22,32 @@ class nsSubDocumentFrame;
 
 namespace mozilla {
 
 class InputEvent;
 
 namespace layers {
 class AsyncPanZoomController;
 class GestureEventListener;
+class TargetConfig;
 class ShadowLayersParent;
 }
 
 namespace layout {
 
 class RemoteContentController;
 
 class RenderFrameParent : public PRenderFrameParent,
                           public mozilla::layers::ShadowLayersManager
 {
   typedef mozilla::layers::FrameMetrics FrameMetrics;
   typedef mozilla::layers::ContainerLayer ContainerLayer;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
+  typedef mozilla::layers::TargetConfig TargetConfig;
   typedef mozilla::layers::ShadowLayersParent ShadowLayersParent;
   typedef FrameMetrics::ViewID ViewID;
 
 public:
   typedef std::map<ViewID, nsRefPtr<nsContentView> > ViewMap;
 
   /**
    * Select the desired scrolling behavior.  If ASYNC_PAN_ZOOM is
@@ -65,16 +67,17 @@ public:
    * Helper function for getting a non-owning reference to a scrollable.
    * @param aId The ID of the frame.
    */
   nsContentView* GetContentView(ViewID aId = FrameMetrics::ROOT_SCROLL_ID);
 
   void ContentViewScaleChanged(nsContentView* aView);
 
   virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+                                   const TargetConfig& aTargetConfig,
                                    bool isFirstPaint) MOZ_OVERRIDE;
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
                               nsSubDocumentFrame* aFrame,
                               const nsRect& aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/arial-arabic-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Bug 769475 - test for italicized Arabic script in Arial</title>
+<style type="text/css">
+body {
+  font-family: arial, serif;
+  font-size: 36px;
+  line-height: 72px;
+}
+span {
+  color: white;
+}
+</style>
+</head>
+<body lang="ar">
+<!-- the white span should have the same width whether it's italicized or not,
+  -- as Arial does not have Arabic characters in the italic face but we should
+  -- apply synthetic italic to the regular face, NOT fall back to a different
+  -- family from prefs.
+  -->
+<div>العربي <span>العربي</span> العربي</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-matching/arial-arabic.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Bug 769475 - test for italicized Arabic script in Arial</title>
+<style type="text/css">
+body {
+  font-family: arial, serif;
+  font-size: 36px;
+  line-height: 72px;
+}
+span {
+  font-style: italic;
+  color: white;
+}
+</style>
+</head>
+<body lang="ar">
+<!-- the white span should have the same width whether it's italicized or not,
+  -- as Arial does not have Arabic characters in the italic face but we should
+  -- apply synthetic italic to the regular face, NOT fall back to a different
+  -- family from prefs.
+  -->
+<div>العربي <span>العربي</span> العربي</div>
+</body>
+</html>
--- a/layout/reftests/font-matching/reftest.list
+++ b/layout/reftests/font-matching/reftest.list
@@ -76,8 +76,12 @@ HTTP(..) == font-stretch-1.html font-str
 != synthetic-style-2.html synthetic-style-2-notref.html
 
 # Bug 765906 - synthetic bold should be used if necessary together with system fallback.
 # **NOTE** we skip these on Linux because of bug 769659.
 # test 1 uses Cherokee; expected to pass on OS X and Win7
 random-if(!(cocoaWidget||/^Windows\x20NT\x206\.1/.test(http.oscpu))) skip-if(gtk2Widget) != bold-system-fallback-1.html bold-system-fallback-1-notref.html
 # test 2 uses Chess symbols; expected to pass on Android
 random-if(!Android) skip-if(gtk2Widget) != bold-system-fallback-2.html bold-system-fallback-2-notref.html
+
+# Bug 769475 - applying 'italic' to Arabic text in Arial should NOT change family or metrics.
+# Expected to pass on MacOSX and Windows; other platforms unknown, depending on font availability.
+random-if(!(cocoaWidget||winWidget)) == arial-arabic.html arial-arabic-ref.html
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -124,18 +124,17 @@ nsComputedDOMStyle::nsComputedDOMStyle(d
     if (!haveTwoColons &&
         !nsCSSPseudoElements::IsCSS2PseudoElement(mPseudo)) {
       // XXXbz I'd really rather we threw an exception or something, but
       // the DOM spec sucks.
       mPseudo = nsnull;
     }
   }
 
-  nsPresContext *presCtx = aPresShell->GetPresContext();
-  MOZ_ASSERT(presCtx);
+  MOZ_ASSERT(aPresShell->GetPresContext());
 }
 
 
 nsComputedDOMStyle::~nsComputedDOMStyle()
 {
 }
 
 void
--- a/media/libsydneyaudio/src/sydney_audio_android.c
+++ b/media/libsydneyaudio/src/sydney_audio_android.c
@@ -376,18 +376,16 @@ sa_stream_get_write_size(sa_stream_t *s,
 
 int
 sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) {
 
   if (s == NULL || s->output_unit == NULL) {
     return SA_ERROR_NO_INIT;
   }
 
-  ALOG("%p - get position", s);
-
   JNIEnv *jenv = GetJNIForThread();
   *pos  = (*jenv)->CallIntMethod(jenv, s->output_unit, at.getpos);
 
   /* android returns number of frames, so:
      position = frames * (PCM_16_BIT == 2 bytes) * channels
   */
   *pos *= s->channels * sizeof(int16_t);
   return SA_SUCCESS;
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -531,16 +531,19 @@ abstract public class BrowserApp extends
 
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.gecko_menu, mMenu);
         return true;
     }
 
     @Override
     public void openOptionsMenu() {
+        if (!hasTabsSideBar() && areTabsShown())
+            return;
+
         // Scroll custom menu to the top
         if (mMenuPanel != null)
             mMenuPanel.scrollTo(0, 0);
 
         if (!mBrowserToolbar.openOptionsMenu())
             super.openOptionsMenu();
     }
 
--- a/mobile/android/base/BrowserToolbar.java
+++ b/mobile/android/base/BrowserToolbar.java
@@ -215,19 +215,16 @@ public class BrowserToolbar implements V
         mMenu = (ImageButton) mLayout.findViewById(R.id.menu);
         mActionItemBar = (LinearLayout) mLayout.findViewById(R.id.menu_items);
         mHasSoftMenuButton = !GeckoApp.mAppContext.hasPermanentMenuKey();
 
         if (mHasSoftMenuButton) {
             mMenu.setVisibility(View.VISIBLE);
             mMenu.setOnClickListener(new Button.OnClickListener() {
                 public void onClick(View view) {
-                    if (!GeckoApp.mAppContext.hasTabsSideBar() && GeckoApp.mAppContext.areTabsShown())
-                        return;
-
                     GeckoApp.mAppContext.openOptionsMenu();
                 }
             });
         }
 
         if (Build.VERSION.SDK_INT >= 11) {
             View panel = GeckoApp.mAppContext.getMenuPanel();
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -524,30 +524,23 @@ abstract public class GeckoApp
         public MenuPanel(Context context, AttributeSet attrs) {
             super(context, attrs);
             setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                                                        ViewGroup.LayoutParams.WRAP_CONTENT));
         }
 
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            if (getChildCount() == 0) {
-                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-                return;
-            }
-
-            int restrictedHeightSpec;
-            int childHeight = getChildAt(0).getHeight();
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
             DisplayMetrics metrics = new DisplayMetrics();
             ((Activity) GeckoApp.mAppContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
 
             // heightPixels changes during rotation.
-            int preferredHeight = (int) (0.75 * metrics.heightPixels);
-            restrictedHeightSpec = MeasureSpec.makeMeasureSpec(childHeight <= preferredHeight ? childHeight : preferredHeight, MeasureSpec.EXACTLY);
+            int restrictedHeightSpec = MeasureSpec.makeMeasureSpec((int) (0.75 * metrics.heightPixels), MeasureSpec.AT_MOST);
 
             super.onMeasure(widthMeasureSpec, restrictedHeightSpec);
         }
 
         @Override
         public boolean dispatchPopulateAccessibilityEvent (AccessibilityEvent event) {
             if (Build.VERSION.SDK_INT >= 14) // Build.VERSION_CODES.ICE_CREAM_SANDWICH
                 onPopulateAccessibilityEvent(event);
@@ -706,16 +699,27 @@ abstract public class GeckoApp
                     Log.e(LOGTAG, "error building json arguments");
                 }
                 GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("DesktopMode:Change", args.toString()));
                 return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
     }
+ 
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        // Custom Menu should be opened when hardware menu key is pressed.
+        if (Build.VERSION.SDK_INT >= 11 && keyCode == KeyEvent.KEYCODE_MENU) {
+            openOptionsMenu();
+            return true;
+        }
+
+        return super.onKeyDown(keyCode, event);
+    }
 
     private void shareCurrentUrl() {
       Tab tab = Tabs.getInstance().getSelectedTab();
       if (tab == null)
         return;
 
       String url = tab.getURL();
       if (url == null)
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -38,17 +38,17 @@ public final class Tab {
     private int mId;
     private String mUrl;
     private String mTitle;
     private Drawable mFavicon;
     private String mFaviconUrl;
     private int mFaviconSize;
     private JSONObject mIdentityData;
     private boolean mReaderEnabled;
-    private Drawable mThumbnail;
+    private BitmapDrawable mThumbnail;
     private int mHistoryIndex;
     private int mHistorySize;
     private int mParentId;
     private boolean mExternal;
     private boolean mBookmark;
     private boolean mReadingListItem;
     private HashMap<String, DoorHanger> mDoorHangers;
     private long mFaviconLoadId;
@@ -186,20 +186,19 @@ public final class Tab {
     }
 
     public void updateThumbnail(final Bitmap b) {
         final Tab tab = this;
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 if (b != null) {
                     try {
+                        mThumbnail = new BitmapDrawable(b);
                         if (mState == Tab.STATE_SUCCESS)
-                            saveThumbnailToDB(new BitmapDrawable(b));
-
-                        mThumbnail = new BitmapDrawable(b);
+                            saveThumbnailToDB();
                     } catch (OutOfMemoryError oom) {
                         Log.e(LOGTAG, "Unable to create/scale bitmap", oom);
                         mThumbnail = null;
                     }
                 } else {
                     mThumbnail = null;
                 }
                 GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
@@ -584,23 +583,23 @@ public final class Tab {
             if (mHistorySize < 0 || mHistoryIndex < -1) {
                 Log.e(LOGTAG, "Unexpected history state: index = " + mHistoryIndex + ", size = " + mHistorySize);
                 mHistorySize = 0;
                 mHistoryIndex = -1;
             }
         }
     }
 
-    private void saveThumbnailToDB(BitmapDrawable thumbnail) {
+    private void saveThumbnailToDB() {
         try {
             String url = getURL();
             if (url == null)
                 return;
 
-            BrowserDB.updateThumbnailForUrl(mContentResolver, url, thumbnail);
+            BrowserDB.updateThumbnailForUrl(mContentResolver, url, mThumbnail);
         } catch (Exception e) {
             // ignore
         }
     }
 
     public void addPluginView(View view) {
         mPluginViews.add(view);
     }
--- a/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupSuccessActivity.java
@@ -41,17 +41,14 @@ public class SetupSuccessActivity extend
     super.onDestroy();
   }
 
   /* Click Handlers */
   public void settingsClickHandler(View target) {
     SyncAccounts.openSyncSettings(this);
   }
 
-
   public void launchBrowser(View target) {
     Intent intent = new Intent(Intent.ACTION_MAIN);
     intent.setClassName(GlobalConstants.BROWSER_INTENT_PACKAGE, GlobalConstants.BROWSER_INTENT_CLASS);
-    // Start Fennec as a new task. If Fennec is already running, bring it to the front.
-    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     startActivity(intent);
   }
 }
--- a/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
@@ -131,28 +131,28 @@ public class SetupSyncActivity extends A
       if (!isSetup) {
         Logger.debug(LOG_TAG, "Account exists; Pair a Device started.");
         pairWithPin = true;
         displayPairWithPin();
         return;
       }
     }
 
-    final Activity setupActivity = this;
     runOnUiThread(new Runnable() {
       @Override
       public void run() {
         Logger.debug(LOG_TAG, "Only one account supported. Redirecting.");
         // Display toast for "Only one account supported."
         // Redirect to account management.
         Toast toast = Toast.makeText(mContext,
             R.string.sync_notification_oneaccount, Toast.LENGTH_LONG);
         toast.show();
 
-        SyncAccounts.openSyncSettings(setupActivity);
+        // Setting up Sync when an existing account exists only happens from Settings,
+        // so we can safely finish() the activity to return to Settings.
         finish();
       }
     });
   }
 
 
   @Override
   public void onPause() {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -3222,17 +3222,17 @@ var BrowserEventHandler = {
   init: function init() {
     Services.obs.addObserver(this, "Gesture:SingleTap", false);
     Services.obs.addObserver(this, "Gesture:CancelTouch", false);
     Services.obs.addObserver(this, "Gesture:DoubleTap", false);
     Services.obs.addObserver(this, "Gesture:Scroll", false);
     Services.obs.addObserver(this, "dom-touch-listener-added", false);
 
     BrowserApp.deck.addEventListener("DOMUpdatePageReport", PopupBlockerObserver.onUpdatePageReport, false);
-    BrowserApp.deck.addEventListener("touchstart", this, false);
+    BrowserApp.deck.addEventListener("touchstart", this, true);
     BrowserApp.deck.addEventListener("click", SelectHelper, true);
   },
 
   handleEvent: function(aEvent) {
     if (!BrowserApp.isBrowserContentDocumentDisplayed() || aEvent.touches.length > 1 || aEvent.defaultPrevented)
       return;
 
     let closest = aEvent.target;
@@ -3495,40 +3495,40 @@ var BrowserEventHandler = {
     // the element can be out of the aX/aY point because of the touch radius
     // if outside, we gracefully move the touch point to the edge of the element
     if (!(aElement instanceof HTMLHtmlElement)) {
       let isTouchClick = true;
       let rects = ElementTouchHelper.getContentClientRects(aElement);
       for (let i = 0; i < rects.length; i++) {
         let rect = rects[i];
         let inBounds =
-          (aX> rect.left  && aX < (rect.left + rect.width)) &&
+          (aX > rect.left && aX < (rect.left + rect.width)) &&
           (aY > rect.top && aY < (rect.top + rect.height));
         if (inBounds) {
           isTouchClick = false;
           break;
         }
       }
 
       if (isTouchClick) {
         let rect = rects[0];
         if (rect.width != 0 || rect.height != 0) {
-          aX = Math.min(rect.left + rect.width, Math.max(rect.left, aX));
-          aY = Math.min(rect.top + rect.height, Math.max(rect.top,  aY));
+          aX = Math.min(Math.floor(rect.left + rect.width), Math.max(Math.ceil(rect.left), aX));
+          aY = Math.min(Math.floor(rect.top + rect.height), Math.max(Math.ceil(rect.top),  aY));
         }
       }
     }
     return [aX, aY];
   },
 
   _sendMouseEvent: function _sendMouseEvent(aName, aElement, aX, aY) {
     let window = aElement.ownerDocument.defaultView;
     try {
       let cwu = window.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
-      cwu.sendMouseEventToWindow(aName, Math.round(aX), Math.round(aY), 0, 1, 0, true);
+      cwu.sendMouseEventToWindow(aName, aX, aY, 0, 1, 0, true);
     } catch(e) {
       Cu.reportError(e);
     }
   },
 
   _hasScrollableOverflow: function(elem) {
     var win = elem.ownerDocument.defaultView;
     if (!win)
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -587,28 +587,18 @@ nsIOService::LookupProxyInfo(nsIURI *aUR
     nsCOMPtr<nsIProxyInfo> pi;
 
     if (!mProxyService) {
         mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
         if (!mProxyService)
             NS_WARNING("failed to get protocol proxy service");
     }
     if (mProxyService) {
-        PRUint32 flags = 0;
-        if (aScheme->EqualsLiteral("http") || aScheme->EqualsLiteral("https"))
-            flags = nsIProtocolProxyService::RESOLVE_NON_BLOCKING;
         rv = mProxyService->Resolve(aProxyURI ? aProxyURI : aURI, aProxyFlags,
                                     getter_AddRefs(pi));
-        if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
-            // Use an UNKNOWN proxy to defer resolution and avoid blocking.
-            rv = mProxyService->NewProxyInfo(NS_LITERAL_CSTRING("unknown"),
-                                             NS_LITERAL_CSTRING(""),
-                                             -1, 0, 0, nsnull,
-                                             getter_AddRefs(pi));
-        }
         if (NS_FAILED(rv))
             pi = nsnull;
     }
     pi.forget(outPI);
 }
 
 
 NS_IMETHODIMP
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -905,18 +905,17 @@ nsProtocolProxyService::NewProxyInfo(con
                                      PRUint32 aFailoverTimeout,
                                      nsIProxyInfo *aFailoverProxy,
                                      nsIProxyInfo **aResult)
 {
     static const char *types[] = {
         kProxyType_HTTP,
         kProxyType_SOCKS,
         kProxyType_SOCKS4,
-        kProxyType_DIRECT,
-        kProxyType_UNKNOWN
+        kProxyType_DIRECT
     };
 
     // resolve type; this allows us to avoid copying the type string into each
     // proxy info instance.  we just reference the string literals directly :)
     const char *type = nsnull;
     for (PRUint32 i=0; i<ArrayLength(types); ++i) {
         if (aType.LowerCaseEqualsASCII(types[i])) {
             type = types[i];
--- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp
+++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp
@@ -93,17 +93,17 @@ nsMIMEHeaderParamImpl::DoGetParameter(co
     if (!aFallbackCharset.IsEmpty())
     {
         nsCAutoString str2;
         nsCOMPtr<nsIUTF8ConverterService> 
           cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
         if (cvtUTF8 &&
             NS_SUCCEEDED(cvtUTF8->ConvertStringToUTF8(str1, 
                 PromiseFlatCString(aFallbackCharset).get(), false, true,
-                                   str2))) {
+                                   1, str2))) {
           CopyUTF8toUTF16(str2, aResult);
           return NS_OK;
         }
     }
 
     if (IsUTF8(str1)) {
       CopyUTF8toUTF16(str1, aResult);
       return NS_OK;
@@ -287,17 +287,17 @@ bool IsValidOctetSequenceForCharset(nsAC
   }
 
   nsCAutoString tmpRaw;
   tmpRaw.Assign(aOctets);
   nsCAutoString tmpDecoded;
 
   nsresult rv = cvtUTF8->ConvertStringToUTF8(tmpRaw,
                                              PromiseFlatCString(aCharset).get(),
-                                             false, false, tmpDecoded);
+                                             false, false, 1, tmpDecoded);
 
   if (rv != NS_OK) {
     // we can't decode; charset may be unsupported, or the octet sequence
     // is broken (illegal or incomplete octet sequence contained)
     NS_WARNING("RFC2231/5987 parameter value does not decode according to specified charset\n");
     return false;
   }
 
@@ -847,17 +847,17 @@ nsMIMEHeaderParamImpl::DecodeRFC5987Para
 
   // finally convert octet sequence to UTF-8 and be done
   nsresult rv = NS_OK;
   nsCOMPtr<nsIUTF8ConverterService> cvtUTF8 =
     do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString utf8;
-  rv = cvtUTF8->ConvertStringToUTF8(value, charset.get(), true, false, utf8);
+  rv = cvtUTF8->ConvertStringToUTF8(value, charset.get(), true, false, 1, utf8);
   NS_ENSURE_SUCCESS(rv, rv);
 
   CopyUTF8toUTF16(utf8, aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsMIMEHeaderParamImpl::DecodeParameter(const nsACString& aParamValue,
@@ -869,17 +869,17 @@ nsMIMEHeaderParamImpl::DecodeParameter(c
   aResult.Truncate();
   // If aCharset is given, aParamValue was obtained from RFC2231/5987 
   // encoding and we're pretty sure that it's in aCharset.
   if (aCharset && *aCharset)
   {
     nsCOMPtr<nsIUTF8ConverterService> cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
     if (cvtUTF8)
       return cvtUTF8->ConvertStringToUTF8(aParamValue, aCharset,
-          true, true, aResult);
+          true, true, 1, aResult);
   }
 
   const nsAFlatCString& param = PromiseFlatCString(aParamValue);
   nsCAutoString unQuoted;
   nsACString::const_iterator s, e;
   param.BeginReading(s);
   param.EndReading(e);
 
@@ -1049,17 +1049,18 @@ void CopyRawHeader(const char *aInput, P
 
   // If not UTF-8, treat as default charset
   nsCOMPtr<nsIUTF8ConverterService> 
     cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
   nsCAutoString utf8Text;
   if (cvtUTF8 &&
       NS_SUCCEEDED(
       cvtUTF8->ConvertStringToUTF8(Substring(aInput, aInput + aLen), 
-      aDefaultCharset, skipCheck, true, utf8Text))) {
+                                   aDefaultCharset, skipCheck, true, 1,
+                                   utf8Text))) {
     aOutput.Append(utf8Text);
   } else { // replace each octet with Unicode replacement char in UTF-8.
     for (PRUint32 i = 0; i < aLen; i++) {
       c = PRUint8(*aInput++);
       if (c & 0x80)
         aOutput.Append(REPLACEMENT_CHAR);
       else
         aOutput.Append(char(c));
@@ -1182,17 +1183,19 @@ nsresult DecodeRFC2047Str(const char *aH
     {
       nsCOMPtr<nsIUTF8ConverterService> 
         cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
       nsCAutoString utf8Text;
       // skip ASCIIness/UTF8ness test if aCharset is 7bit non-ascii charset.
       if (cvtUTF8 &&
           NS_SUCCEEDED(
             cvtUTF8->ConvertStringToUTF8(nsDependentCString(decodedText),
-            charset, IS_7BIT_NON_ASCII_CHARSET(charset), true, utf8Text))) {
+                                         charset,
+                                         IS_7BIT_NON_ASCII_CHARSET(charset),
+                                         true, 1, utf8Text))) {
         aResult.Append(utf8Text);
       } else {
         aResult.Append(REPLACEMENT_CHAR);
       }
     }
     PR_Free(decodedText);
     begin = r + 2;
     isLastEncodedWord = 1;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1517,22 +1517,21 @@ HttpBaseChannel::IsSafeMethod(nsHttpAtom
          method == nsHttp::Report ||
          method == nsHttp::Search ||
          method == nsHttp::Trace;
 }
 
 nsresult
 HttpBaseChannel::SetupReplacementChannel(nsIURI       *newURI, 
                                          nsIChannel   *newChannel,
-                                         bool          preserveMethod,
-                                         bool          forProxy)
+                                         bool          preserveMethod)
 {
   LOG(("HttpBaseChannel::SetupReplacementChannel "
-     "[this=%p newChannel=%p preserveMethod=%d forProxy=%d]",
-     this, newChannel, preserveMethod, forProxy));
+     "[this=%p newChannel=%p preserveMethod=%d]",
+     this, newChannel, preserveMethod));
   PRUint32 newLoadFlags = mLoadFlags | LOAD_REPLACE;
   // if the original channel was using SSL and this channel is not using
   // SSL, then no need to inhibit persistent caching.  however, if the
   // original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
   // set, then allow the flag to apply to the redirected channel as well.
   // since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
   // we only need to check if the original channel was using SSL.
   if (mConnectionInfo->UsingSSL())
@@ -1645,31 +1644,16 @@ HttpBaseChannel::SetupReplacementChannel
   if (bag)
     mPropertyHash.EnumerateRead(CopyProperties, bag.get());
 
   // transfer timed channel enabled status
   nsCOMPtr<nsITimedChannel> timed(do_QueryInterface(newChannel));
   if (timed)
     timed->SetTimingEnabled(mTimingEnabled);
 
-  if (forProxy) {
-    // Transfer all the headers from the previous channel
-    //  this is needed for any headers that are not covered by the code above
-    //  or have been set separately. e.g. manually setting Referer without
-    //  setting up mReferrer
-    PRUint32 count = mRequestHead.Headers().Count();
-    for (PRUint32 i = 0; i < count; ++i) {
-      nsHttpAtom header;
-      const char *value = mRequestHead.Headers().PeekHeaderAt(i, header);
-
-      httpChannel->SetRequestHeader(nsDependentCString(header),
-                                    nsDependentCString(value), false);
-    }
-  }
-
   return NS_OK;
 }
 
 //------------------------------------------------------------------------------
 
 }  // namespace net
 }  // namespace mozilla
 
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -192,18 +192,17 @@ protected:
   void     DoNotifyListener();
   virtual void DoNotifyListenerCleanup() = 0;
 
   nsresult ApplyContentConversions();
 
   void AddCookiesToRequest();
   virtual nsresult SetupReplacementChannel(nsIURI *,
                                            nsIChannel *,
-                                           bool preserveMethod,
-                                           bool forProxy);
+                                           bool preserveMethod);
 
   // Helper function to simplify getting notification callbacks.
   template <class T>
   void GetCallback(nsCOMPtr<T> &aResult)
   {
     NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
                                   NS_GET_TEMPLATE_IID(T),
                                   getter_AddRefs(aResult));
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -717,17 +717,17 @@ HttpChannelChild::Redirect1Begin(const P
 
   // We won't get OnStartRequest, set cookies here.
   mResponseHead = new nsHttpResponseHead(responseHead);
   SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
 
   bool rewriteToGET = ShouldRewriteRedirectToGET(mResponseHead->Status(), 
                                                  mRequestHead.Method());
   
-  rv = SetupReplacementChannel(uri, newChannel, !rewriteToGET, false);
+  rv = SetupReplacementChannel(uri, newChannel, !rewriteToGET);
   if (NS_FAILED(rv)) {
     // Veto redirect.  nsHttpChannel decides to cancel or continue.
     OnRedirectVerifyCallback(rv);
     return;
   }
 
   mRedirectChannelChild = do_QueryInterface(newChannel);
   if (mRedirectChannelChild) {
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1630,17 +1630,17 @@ nsHttpChannel::AsyncRedirectChannelToHtt
 
     nsCOMPtr<nsIIOService> ioService;
     rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = ioService->NewChannelFromURI(upgradedURI, getter_AddRefs(newChannel));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = SetupReplacementChannel(upgradedURI, newChannel, true, false);
+    rv = SetupReplacementChannel(upgradedURI, newChannel, true);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Inform consumers about this fake redirect
     mRedirectChannel = newChannel;
     PRUint32 flags = nsIChannelEventSink::REDIRECT_PERMANENT;
 
     PushRedirectAsyncFunc(
         &nsHttpChannel::ContinueAsyncRedirectChannelToHttps);
@@ -1727,17 +1727,17 @@ nsHttpChannel::AsyncDoReplaceWithProxy(n
     LOG(("nsHttpChannel::AsyncDoReplaceWithProxy [this=%p pi=%p]", this, pi));
     nsresult rv;
 
     nsCOMPtr<nsIChannel> newChannel;
     rv = gHttpHandler->NewProxiedChannel(mURI, pi, getter_AddRefs(newChannel));
     if (NS_FAILED(rv))
         return rv;
 
-    rv = SetupReplacementChannel(mURI, newChannel, true, true);
+    rv = SetupReplacementChannel(mURI, newChannel, true);
     if (NS_FAILED(rv))
         return rv;
 
     // Inform consumers about this fake redirect
     mRedirectChannel = newChannel;
     PRUint32 flags = nsIChannelEventSink::REDIRECT_INTERNAL;
 
     PushRedirectAsyncFunc(&nsHttpChannel::ContinueDoReplaceWithProxy);
@@ -2275,17 +2275,17 @@ nsHttpChannel::ProcessFallback(bool *wai
     // Close the current cache entry.
     CloseCacheEntry(true);
 
     // Create a new channel to load the fallback entry.
     nsRefPtr<nsIChannel> newChannel;
     rv = gHttpHandler->NewChannel(mURI, getter_AddRefs(newChannel));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = SetupReplacementChannel(mURI, newChannel, true, false);
+    rv = SetupReplacementChannel(mURI, newChannel, true);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Make sure the new channel loads from the fallback key.
     nsCOMPtr<nsIHttpChannelInternal> httpInternal =
         do_QueryInterface(newChannel, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = httpInternal->SetupFallbackChannel(mFallbackKey.get());
@@ -3948,25 +3948,23 @@ nsHttpChannel::ClearBogusContentEncoding
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel <redirect>
 //-----------------------------------------------------------------------------
 
 nsresult
 nsHttpChannel::SetupReplacementChannel(nsIURI       *newURI, 
                                        nsIChannel   *newChannel,
-                                       bool          preserveMethod,
-                                       bool          forProxy)
+                                       bool          preserveMethod)
 {
     LOG(("nsHttpChannel::SetupReplacementChannel "
          "[this=%p newChannel=%p preserveMethod=%d]",
          this, newChannel, preserveMethod));
 
-    nsresult rv = HttpBaseChannel::SetupReplacementChannel(newURI, newChannel,
-                                                           preserveMethod, forProxy);
+    nsresult rv = HttpBaseChannel::SetupReplacementChannel(newURI, newChannel, preserveMethod);
     if (NS_FAILED(rv))
         return rv;
 
     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
     if (!httpChannel)
         return NS_OK; // no other options to set
 
     // convey the mApplyConversion flag (bug 91862)
@@ -3979,38 +3977,16 @@ nsHttpChannel::SetupReplacementChannel(n
         nsCOMPtr<nsIResumableChannel> resumableChannel(do_QueryInterface(newChannel));
         if (!resumableChannel) {
             NS_WARNING("Got asked to resume, but redirected to non-resumable channel!");
             return NS_ERROR_NOT_RESUMABLE;
         }
         resumableChannel->ResumeAt(mStartPos, mEntityID);
     }
 
-    if (forProxy) {
-        // Transfer the cache info to the new channel, if needed.
-        nsCOMPtr<nsICachingChannel> cachingChannel = do_QueryInterface(newChannel);
-        if (cachingChannel) {
-            // cacheKey is just mPostID wrapped in an nsISupportsPRUint32,
-            // we don't need to transfer it if it's 0.
-            if (mPostID) {
-                nsCOMPtr<nsISupports> cacheKey;
-                GetCacheKey(getter_AddRefs(cacheKey));
-                if (cacheKey) {
-                    cachingChannel->SetCacheKey(cacheKey);
-                }
-            }
-        }
-
-        nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel = do_QueryInterface(newChannel);
-        if (appCacheChannel) {
-            // app cache for write
-            appCacheChannel->SetApplicationCacheForWrite(mApplicationCacheForWrite);
-        }
-    }
-
     return NS_OK;
 }
 
 nsresult
 nsHttpChannel::AsyncProcessRedirection(PRUint32 redirectType)
 {
     LOG(("nsHttpChannel::AsyncProcessRedirection [this=%p type=%u]\n",
         this, redirectType));
@@ -4124,17 +4100,17 @@ nsHttpChannel::ContinueProcessRedirectio
     nsCOMPtr<nsIIOService> ioService;
     rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
     if (NS_FAILED(rv)) return rv;
 
     nsCOMPtr<nsIChannel> newChannel;
     rv = ioService->NewChannelFromURI(mRedirectURI, getter_AddRefs(newChannel));
     if (NS_FAILED(rv)) return rv;
 
-    rv = SetupReplacementChannel(mRedirectURI, newChannel, !rewriteToGET, false);
+    rv = SetupReplacementChannel(mRedirectURI, newChannel, !rewriteToGET);
     if (NS_FAILED(rv)) return rv;
 
     PRUint32 redirectFlags;
     if (mRedirectType == 301) // Moved Permanently
         redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
     else
         redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
 
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -175,19 +175,17 @@ private:
 
     // redirection specific methods
     void     HandleAsyncRedirect();
     nsresult ContinueHandleAsyncRedirect(nsresult);
     void     HandleAsyncNotModified();
     void     HandleAsyncFallback();
     nsresult ContinueHandleAsyncFallback(nsresult);
     nsresult PromptTempRedirect();
-    virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *,
-                                             bool preserveMethod,
-                                             bool forProxy);
+    virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, bool preserveMethod);
 
     // proxy specific methods
     nsresult ProxyFailover();
     nsresult AsyncDoReplaceWithProxy(nsIProxyInfo *);
     nsresult ContinueDoReplaceWithProxy(nsresult);
     void HandleAsyncReplaceWithProxy();
     nsresult ContinueHandleAsyncReplaceWithProxy(nsresult);
     nsresult ResolveProxy();
deleted file mode 100644
--- a/netwerk/test/unit/test_proxy_preservation_bug235853.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* 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/. */
-
-do_load_httpd_js();
-
-var ios = Components.classes["@mozilla.org/network/io-service;1"]
-                    .getService(Components.interfaces.nsIIOService);
-
-var prefs = Components.classes["@mozilla.org/preferences-service;1"]
-                    .getService(Components.interfaces.nsIPrefBranch);
-
-function make_channel(url) {
-  return ios.newChannel(url, null, null)
-                .QueryInterface(Components.interfaces.nsIHttpChannel);
-}
-
-var httpserv = null;
-
-// respond with the value of the header
-function responseHandler(request, response) {
-  response.setHeader("Content-Type", "text/plain", false);
-
-  var value = request.hasHeader("SomeHeader") ? request.getHeader("SomeHeader") : "";
-  response.write("SomeHeader: " + value);
-}
-
-function run_test() {
-  httpserv = new nsHttpServer();
-  httpserv.start(4444);
-  httpserv.registerPathHandler("/test", responseHandler);
-  // setup an identity so we can use the server with a different name when using
-  // the server as a proxy
-  httpserv.identity.add("http", "foo", 80);
-
-  // cache key on channel creation
-  var orig_key;
-
-  // setup the properties that we want to be preserved
-  function setup_channel(chan) {
-    chan.setRequestHeader("SomeHeader", "Someval", false);
-
-    // set cache key to something other than 0
-    orig_key = chan.QueryInterface(Ci.nsICachingChannel)
-                      .cacheKey.QueryInterface(Ci.nsISupportsPRUint32);
-    orig_key.data = 0x32;
-    chan.QueryInterface(Ci.nsICachingChannel).cacheKey = orig_key;
-  }
-
-  // check that these properties are preserved
-  function check_response(request, data) {
-    // check that headers are preserved
-    do_check_eq(data, "SomeHeader: Someval");
-
-    // check that the cacheKey is preserved
-    var key = request.QueryInterface(Ci.nsICachingChannel)
-                        .cacheKey.QueryInterface(Ci.nsISupportsPRUint32);
-    do_check_eq(key.data, orig_key.data);
-  }
-
-  function setup_noproxy() {
-    var chan = make_channel("http://localhost:4444/test");
-    setup_channel(chan);
-    chan.asyncOpen(new ChannelListener(test_noproxy, null), null);
-  }
-
-  function test_noproxy(request, data, ctx) {
-    check_response(request, data);
-
-    setup_with_proxy();
-  }
-
-  function setup_with_proxy() {
-    // Setup a PAC rule using the server we setup as the proxy
-    var pac = 'data:text/plain,' +
-      'function FindProxyForURL(url, host) {' +
-      '  return "PROXY localhost:4444";' +
-      '}';
-
-    // Configure PAC
-    prefs.setIntPref("network.proxy.type", 2);
-    prefs.setCharPref("network.proxy.autoconfig_url", pac);
-
-    var chan = make_channel("http://foo/test");
-
-    setup_channel(chan);
-
-    chan.asyncOpen(new ChannelListener(test_with_proxy, null), null);
-  }
-
-  function test_with_proxy(request, data, ctx) {
-    check_response(request, data);
-
-    // cleanup PAC
-    prefs.setCharPref("network.proxy.autoconfig_url", "");
-    prefs.setIntPref("network.proxy.type", 0);
-
-    httpserv.stop(do_test_finished);
-  }
-
-  setup_noproxy();
-
-  do_test_pending();
-}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -153,17 +153,16 @@ skip-if = os == "win"
 [test_parse_content_type.js]
 [test_permmgr.js]
 [test_plaintext_sniff.js]
 [test_post.js]
 [test_progress.js]
 [test_protocolproxyservice.js]
 [test_proxy-failover_canceled.js]
 [test_proxy-failover_passing.js]
-[test_proxy_preservation_bug235853.js]
 [test_proxy-replace_canceled.js]
 [test_proxy-replace_passing.js]
 [test_range_requests.js]
 [test_readline.js]
 [test_redirect-caching_canceled.js]
 [test_redirect-caching_failure.js]
 [test_redirect-caching_passing.js]
 [test_redirect_canceled.js]
new file mode 100644
--- /dev/null
+++ b/python/README
@@ -0,0 +1,14 @@
+This directory contains common Python code.
+
+The basic rule is that if Python code is cross-module (that's "module" in the
+Mozilla meaning - as in "module ownership") and is MPL-compatible, it should
+go here.
+
+What should not go here:
+
+* Python that is not MPL-compatible (see other-licenses/)
+* Python that has good reason to remain close to its "owning" (Mozilla)
+  module (e.g. it is only being consumed from there).
+
+Historical information can be found at
+https://bugzilla.mozilla.org/show_bug.cgi?id=775243
rename from build/pylib/blessings/LICENSE
rename to python/blessings/LICENSE
rename from build/pylib/blessings/MANIFEST.in
rename to python/blessings/MANIFEST.in
rename from build/pylib/blessings/PKG-INFO
rename to python/blessings/PKG-INFO
rename from build/pylib/blessings/README.rst
rename to python/blessings/README.rst
rename from build/pylib/blessings/blessings/__init__.py
rename to python/blessings/blessings/__init__.py
rename from build/pylib/blessings/blessings/tests.py
rename to python/blessings/blessings/tests.py
rename from build/pylib/blessings/setup.cfg
rename to python/blessings/setup.cfg
rename from build/pylib/blessings/setup.py
rename to python/blessings/setup.py
rename from build/pylib/blessings/tox.ini
rename to python/blessings/tox.ini
deleted file mode 100644
deleted file mode 100644
deleted file mode 100644
--- a/services/sync/tests/unit/test_resource_async.js
+++ b/services/sync/tests/unit/test_resource_async.js
@@ -658,36 +658,40 @@ add_test(function test_uri_construction(
   let uri2 = Utils.makeURI("http://foo/")
                   .QueryInterface(Ci.nsIURL);
   uri2.query = query;
   do_check_eq(uri1.query, uri2.query);
 
   run_next_test();
 });
 
+/**
+ * End of tests that rely on a single HTTP server.
+ * All tests after this point must begin and end their own.
+ */
+add_test(function eliminate_server() {
+  server.stop(run_next_test);
+});
+
 add_test(function test_new_channel() {
   _("Ensure a redirect to a new channel is handled properly.");
 
   let resourceRequested = false;
   function resourceHandler(metadata, response) {
     resourceRequested = true;
 
     let body = "Test";
     response.setHeader("Content-Type", "text/plain");
     response.bodyOutputStream.write(body, body.length);
   }
-  let server2 = httpd_setup({"/resource": resourceHandler}, 8081);
+  let server = httpd_setup({"/resource": resourceHandler}, 8080);
 
-  let request = new AsyncResource("http://localhost:8080/redirect");
+  let request = new AsyncResource("http://localhost:8080/resource");
   request.get(function onRequest(error, content) {
     do_check_null(error);
     do_check_true(resourceRequested);
     do_check_eq(200, content.status);
     do_check_true("content-type" in content.headers);
     do_check_eq("text/plain", content.headers["content-type"]);
 
-    server2.stop(run_next_test);
+    server.stop(run_next_test);
   });
 });
-
-add_test(function tear_down() {
-  server.stop(run_next_test);
-});
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -124,17 +124,16 @@
  "dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html": "TIMED_OUT, bug 766586",
  "dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html": "TIMED_OUT, bug 766586",
  "dom/imptests/editing/conformancetest/test_event.html": "",
  "dom/imptests/editing/conformancetest/test_runtest.html": "",
  "dom/imptests/html/tests/submission/Mozilla/test_window-onerror-parse-error.html": "",
  "dom/imptests/html/tests/submission/Mozilla/test_window-onerror-runtime-error-throw.html": "",
  "dom/imptests/html/tests/submission/Mozilla/test_window-onerror-runtime-error.html": "",
  "dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
- "dom/indexedDB/ipc/test_ipc.html": "bug 775982", 
  "dom/network/tests/test_network_basics.html": "",
  "dom/settings/tests/test_settings_events.html": "",
  "dom/settings/tests/test_settings_basics.html": "",
  "dom/contacts/tests/test_contacts_basics.html": "",
  "dom/contacts/tests/test_contacts_events.html": "",
  "dom/sms/tests/test_sms_basics.html": "",
  "dom/tests/mochitest/ajax/offline/test_simpleManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_updatingManifest.html": "TIMED_OUT",
@@ -151,17 +150,17 @@
  "dom/tests/mochitest/bugs/test_bug437361.html": "",
  "dom/tests/mochitest/bugs/test_bug479143.html": "",
  "dom/tests/mochitest/bugs/test_bug504862.html": "RANDOM",
  "dom/tests/mochitest/bugs/test_bug597809.html": "",
  "dom/tests/mochitest/bugs/test_bug61098.html": "",
  "dom/tests/mochitest/bugs/test_bug641552.html": "",
  "dom/tests/mochitest/bugs/test_resize_move_windows.html": "TIMED_OUT",
  "dom/tests/mochitest/bugs/test_window_bar.html": "",
- "dom/devicestorage/ipc/test_ipc.html": "bug 775053",
+ "dom/devicestorage/ipc/test_ipc.html": "",
  "dom/devicestorage/test/test_basic.html": "",
  "dom/devicestorage/test/test_dotdot.html": "",
  "dom/devicestorage/test/test_enumerate.html": "",
  "dom/devicestorage/test/test_enumerateMultipleContinue.html": "",
  "dom/devicestorage/test/test_enumerateOptions.html": "",
  "dom/devicestorage/test/test_lastModificationFilter.html": "",
  "dom/devicestorage/test/test_overwrite.html": "",
  "dom/devicestorage/test/test_sanity.html": "",
--- a/testing/peptest/peptest/extension/resource/mozmill/README.md
+++ b/testing/peptest/peptest/extension/resource/mozmill/README.md
@@ -1,8 +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/. -->
 
-These folders are pulled from https://github.com/mozautomation/mozmill/tree/master/mozmill/mozmill/extension/resource.
+These folders are pulled from:
+https://github.com/mozilla/mozmill/tree/master/mozmill/mozmill/extension/resource
 
 To update them, simply checkout the mozmill repo at https://github.com/mozautomation/mozmill, 
 then copy and paste the 'driver' and 'stdlib' folders to this location. 
--- a/toolkit/components/places/nsLivemarkService.js
+++ b/toolkit/components/places/nsLivemarkService.js
@@ -658,28 +658,28 @@ function Livemark(aLivemarkInfo)
 {
   this.title = aLivemarkInfo.title;
   this.parentId = aLivemarkInfo.parentId;
   this.index = aLivemarkInfo.index;
 
   this._status = Ci.mozILivemark.STATUS_READY;
 
   // Hash of resultObservers, hashed by container.
-  this._resultObservers = new WeakMap();
-  // This keeps a list of the containers used as keys in the weakmap, since
+  this._resultObservers = new Map();
+  // This keeps a list of the containers used as keys in the map, since
   // it's not iterable.  In future may use an iterable Map.
   this._resultObserversList = [];
 
   // Sorted array of objects representing livemark children in the form
   // { uri, title, visited }.
   this._children = [];
 
   // Keeps a separate array of nodes for each requesting container, hashed by
   // the container itself.
-  this._nodes = new WeakMap();
+  this._nodes = new Map();
 
   this._guid = "";
   this._lastModified = 0;
 
   this.loadGroup = null;
   this.feedURI = null;
   this.siteURI = null;
   this.expireTime = 0;
--- a/toolkit/components/places/nsPlacesExportService.cpp
+++ b/toolkit/components/places/nsPlacesExportService.cpp
@@ -183,38 +183,16 @@ nsPlacesExportService::Init()
   NS_ENSURE_TRUE(mAnnotationService, NS_ERROR_OUT_OF_MEMORY);
   mBookmarksService = do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID);
   NS_ENSURE_TRUE(mBookmarksService, NS_ERROR_OUT_OF_MEMORY);
   mLivemarkService = do_GetService(NS_LIVEMARKSERVICE_CONTRACTID);
   NS_ENSURE_TRUE(mLivemarkService, NS_ERROR_OUT_OF_MEMORY);
   return NS_OK;
 }
 
-// SyncChannelStatus
-//
-//    If a function returns an error, we need to set the channel status to be
-//    the same, but only if the channel doesn't have its own error. This returns
-//    the error code that should be sent to OnStopRequest.
-static nsresult
-SyncChannelStatus(nsIChannel* channel, nsresult status)
-{
-  nsresult channelStatus;
-  channel->GetStatus(&channelStatus);
-  if (NS_FAILED(channelStatus))
-    return channelStatus;
-
-  if (NS_SUCCEEDED(status))
-    return NS_OK; // caller and the channel are happy
-
-  // channel was OK, but caller wasn't: set the channel state
-  channel->Cancel(status);
-  return status;
-}
-
-
 static char kFileIntro[] =
     "<!DOCTYPE NETSCAPE-Bookmark-file-1>" NS_LINEBREAK
     // Note: we write bookmarks in UTF-8
     "<!-- This is an automatically generated file." NS_LINEBREAK
     "     It will be read and overwritten." NS_LINEBREAK
     "     DO NOT EDIT! -->" NS_LINEBREAK
     "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">" NS_LINEBREAK
     "<TITLE>Bookmarks</TITLE>" NS_LINEBREAK;
--- a/toolkit/components/social/FrameWorker.jsm
+++ b/toolkit/components/social/FrameWorker.jsm
@@ -28,17 +28,17 @@ function getFrameWorkerHandle(url, clien
   // first create the client port we are going to use.  Later we will
   // message the worker to create the worker port.
   let portid = _nextPortId++;
   let clientPort = new ClientPort(portid, clientWindow);
 
   let existingWorker = workerCache[url];
   if (!existingWorker) {
     // setup the worker and add this connection to the pending queue
-    let worker = new FrameWorker(url, clientWindow, name);
+    let worker = new FrameWorker(url, name);
     worker.pendingPorts.push(clientPort);
     existingWorker = workerCache[url] = worker;
   } else {
     // already have a worker - either queue or make the connection.
     if (existingWorker.loaded) {
       try {
         clientPort._createWorkerAndEntangle(existingWorker);
       }
@@ -248,21 +248,16 @@ function makeHiddenFrame() {
   return iframe;
 }
 
 function WorkerHandle(port, worker) {
   this.port = port;
   this._worker = worker;
 }
 WorkerHandle.prototype = {
-  __exposedProps__: {
-    port: "r",
-    terminate: "r"
-  },
-
   // XXX - workers have no .close() method, but *do* have a .terminate()
   // method which we should implement. However, the worker spec doesn't define
   // a callback to be made in the worker when this happens - it all just dies.
   // TODO: work out a sane impl for 'terminate'.
   terminate: function terminate() {
     this._worker.terminate();
   }
 };
@@ -324,36 +319,36 @@ function initClientMessageHandler(worker
  * Client side of the entangled ports. The ClientPort is used by both XUL
  * windows and Content windows to communicate with the worker
  *
  * constructor:
  * @param {integer} portid
  * @param {nsiDOMWindow} clientWindow, optional
  */
 function ClientPort(portid, clientWindow) {
-  this._clientWindow = clientWindow
+  this._clientWindow = clientWindow;
   this._window = null;
   // messages posted to the worker before the worker has loaded.
   this._pendingMessagesOutgoing = [];
   AbstractPort.call(this, portid);
 }
 
 ClientPort.prototype = {
   __exposedProps__: {
-    'port': 'r',
-    'onmessage': 'rw',
-    'postMessage': 'r',
-    'close': 'r'
+    onmessage: "rw",
+    postMessage: "r",
+    close: "r",
+    toString: "r"
   },
   __proto__: AbstractPort.prototype,
   _portType: "client",
 
   _JSONParse: function fw_ClientPort_JSONParse(data) {
     if (this._clientWindow) {
-      return this._clientWindow.JSON.parse(data);
+      return XPCNativeWrapper.unwrap(this._clientWindow).JSON.parse(data);
     }
     return JSON.parse(data);
   },
 
   _createWorkerAndEntangle: function fw_ClientPort_createWorkerAndEntangle(worker) {
     this._window = worker.frame.contentWindow;
     worker.ports[this._portid] = this;
     this._postControlMessage("port-create");
@@ -378,11 +373,12 @@ ClientPort.prototype = {
     if (!this._portid) {
       return; // already closed.
     }
     // a leaky abstraction due to the worker spec not specifying how the
     // other end of a port knows it is closing.
     this.postMessage({topic: "social.port-closing"});
     AbstractPort.prototype.close.call(this);
     this._window = null;
+    this._clientWindow = null;
     this._pendingMessagesOutgoing = null;
   }
 }
--- a/toolkit/components/social/Makefile.in
+++ b/toolkit/components/social/Makefile.in
@@ -10,15 +10,16 @@ VPATH     = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 EXTRA_JS_MODULES = \
   FrameWorker.jsm \
   MessagePortBase.jsm \
   MessagePortWorker.js \
   SocialService.jsm \
   WorkerAPI.jsm \
+  MozSocialAPI.jsm \
   $(NULL)
 
 TEST_DIRS += \
   test \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/components/social/MessagePortBase.jsm
+++ b/toolkit/components/social/MessagePortBase.jsm
@@ -24,58 +24,57 @@ AbstractPort.prototype = {
 
   // and concrete methods shared by client and workers.
   toString: function fw_AbstractPort_toString() {
     return "MessagePort(portType='" + this._portType + "', portId=" + this._portid + ")";
   },
   _JSONParse: function fw_AbstractPort_JSONParse(data) JSON.parse(data),
 
  _postControlMessage: function fw_AbstractPort_postControlMessage(topic, data) {
-    let postData = {portTopic: topic,
-                    portId: this._portid,
-                    portFromType: this._portType,
-                    data: data,
-                    __exposedProps__: {
-                      portTopic: 'r',
-                      portId: 'r',
-                      portFromType: 'r',
-                      data: 'r'
-                    }
-                   };
+    let postData = {
+      portTopic: topic,
+      portId: this._portid,
+      portFromType: this._portType,
+      data: data
+    };
     this._dopost(postData);
   },
 
   _onmessage: function fw_AbstractPort_onmessage(data) {
     // See comments in postMessage below - we work around a cloning
     // issue by using JSON for these messages.
     // Further, we allow the workers to override exactly how the JSON parsing
     // is done - we try and do such parsing in the client window so things
     // like prototype overrides on Array work as expected.
     data = this._JSONParse(data);
     if (!this._handler) {
       this._pendingMessagesIncoming.push(data);
-    }
-    else {
+    } else {
       try {
-        this._handler({data: data,
-                       __exposedProps__: {data: 'r'}
-                      });
-      }
-      catch (ex) {
+        this._handler({
+          data: data,
+          __exposedProps__: {
+            data: 'r'
+          }
+        });
+      } catch (ex) {
         this._onerror(ex);
       }
     }
   },
 
   set onmessage(handler) { // property setter for onmessage
     this._handler = handler;
     while (this._pendingMessagesIncoming.length) {
       this._onmessage(this._pendingMessagesIncoming.shift());
     }
   },
+  get onmessage() {
+    return this._handler;
+  },
 
   /**
    * postMessage
    *
    * Send data to the onmessage handler on the other end of the port.  The
    * data object should have a topic property.
    *
    * @param {jsobj} data
new file mode 100644
--- /dev/null
+++ b/toolkit/components/social/MozSocialAPI.jsm
@@ -0,0 +1,130 @@
+/* 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/. */
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "SocialService", "resource://gre/modules/SocialService.jsm");
+
+const EXPORTED_SYMBOLS = ["MozSocialAPI"];
+
+var MozSocialAPI = {
+  _enabled: false,
+  set enabled(val) {
+    let enable = !!val;
+    if (enable == this._enabled) {
+      return;
+    }
+    this._enabled = enable;
+
+    if (enable) {
+      Services.obs.addObserver(injectController, "document-element-inserted", false);
+    } else {
+      Services.obs.removeObserver(injectController, "document-element-inserted", false);
+    }
+  }
+};
+
+// Called on document-element-inserted, checks that the API should be injected,
+// and then calls attachToWindow as appropriate
+function injectController(doc, topic, data) {
+  try {
+    let window = doc.defaultView;
+    if (!window)
+      return;
+
+    var containingBrowser = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                                  .getInterface(Ci.nsIWebNavigation)
+                                  .QueryInterface(Ci.nsIDocShell)
+                                  .chromeEventHandler;
+
+    // If the containing browser isn't one of the social browsers, nothing to
+    // do here.
+    // XXX this is app-specific, might want some mechanism for consumers to
+    // whitelist other IDs/windowtypes  
+    if (!(containingBrowser.id == "social-sidebar-browser" ||
+          containingBrowser.id == "social-notification-browser")) {
+      return;
+    }
+
+    let origin = containingBrowser.getAttribute("origin");
+    if (!origin) {
+      return;
+    }
+
+    SocialService.getProvider(origin, function(provider) {
+      if (provider && provider.workerURL) {
+        attachToWindow(provider, window);
+      }
+    });
+  } catch(e) {
+    Cu.reportError("MozSocialAPI injectController: unable to attachToWindow for " + doc.location + ": " + e);
+  }
+}
+
+// Loads mozSocial support functions associated with provider into targetWindow
+function attachToWindow(provider, targetWindow) {
+  let origin = provider.origin;
+  if (!provider.enabled) {
+    throw new Error("MozSocialAPI: cannot attach disabled provider " + origin);
+  }
+
+  let targetDocURI = targetWindow.document.documentURIObject;
+  if (provider.origin != targetDocURI.prePath) {
+    throw new Error("MozSocialAPI: cannot attach " + origin + " to " + targetDocURI.spec);
+  }
+
+  var port = provider._getWorkerPort(targetWindow);
+
+  let mozSocialObj = {
+    // Use a method for backwards compat with existing providers, but we
+    // should deprecate this in favor of a simple .port getter.
+    getWorker: function() {
+      return {
+        port: port,
+        __exposedProps__: {
+          port: "r"
+        }
+      };
+    },
+    hasBeenIdleFor: function () {
+      return false;
+    }
+  };
+
+  let contentObj = Cu.createObjectIn(targetWindow);
+  let propList = {};
+  for (let prop in mozSocialObj) {
+    propList[prop] = {
+      enumerable: true,
+      configurable: true,
+      writable: true,
+      value: mozSocialObj[prop]
+    };
+  }
+  Object.defineProperties(contentObj, propList);
+  Cu.makeObjectPropsNormal(contentObj);
+
+  targetWindow.navigator.wrappedJSObject.__defineGetter__("mozSocial", function() {
+    // We do this in a getter, so that we create these objects
+    // only on demand (this is a potential concern, since
+    // otherwise we might add one per iframe, and keep them
+    // alive for as long as the window is alive).
+    delete targetWindow.navigator.wrappedJSObject.mozSocial;
+    return targetWindow.navigator.wrappedJSObject.mozSocial = contentObj;
+  });
+
+  targetWindow.addEventListener("unload", function () {
+    // We want to close the port, but also want the target window to be
+    // able to use the port during an unload event they setup - so we
+    // set a timer which will fire after the unload events have all fired.
+    schedule(function () { port.close(); });
+  });
+}
+
+function schedule(callback) {
+  Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
+}
--- a/toolkit/components/social/SocialService.jsm
+++ b/toolkit/components/social/SocialService.jsm
@@ -3,16 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const EXPORTED_SYMBOLS = ["SocialService"];
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/MozSocialAPI.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "getFrameWorkerHandle", "resource://gre/modules/FrameWorker.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "WorkerAPI", "resource://gre/modules/WorkerAPI.jsm");
 
 /**
  * The SocialService is the public API to social providers - it tracks which
  * providers are installed and enabled, and is the entry-point for access to
  * the provider itself.
@@ -24,24 +25,27 @@ let SocialServiceInternal = {
   get providerArray() {
     return [p for ([, p] of Iterator(this.providers))];
   }
 };
 
 XPCOMUtils.defineLazyGetter(SocialServiceInternal, "providers", function () {
   // Initialize the service (add a pref observer)
   function prefObserver(subject, topic, data) {
-    SocialService._setEnabled(Services.prefs.getBoolPref(data));
+    SocialService._setEnabled(Services.prefs.getBoolPref("social.enabled"));
   }
   Services.prefs.addObserver("social.enabled", prefObserver, false);
   Services.obs.addObserver(function xpcomShutdown() {
     Services.obs.removeObserver(xpcomShutdown, "xpcom-shutdown");
     Services.prefs.removeObserver("social.enabled", prefObserver);
   }, "xpcom-shutdown", false);
 
+  // Initialize the MozSocialAPI
+  MozSocialAPI.enabled = SocialServiceInternal.enabled;
+
   // Now retrieve the providers
   let providers = {};
   let MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
   let prefs = MANIFEST_PREFS.getChildList("", {});
   prefs.forEach(function (pref) {
     try {
       var manifest = JSON.parse(MANIFEST_PREFS.getCharPref(pref));
       if (manifest && typeof(manifest) == "object") {
@@ -72,16 +76,17 @@ const SocialService = {
       return;
 
     Services.prefs.setBoolPref("social.enabled", enable);
     this._setEnabled(enable);
   },
   _setEnabled: function _setEnabled(enable) {
     SocialServiceInternal.providerArray.forEach(function (p) p.enabled = enable);
     SocialServiceInternal.enabled = enable;
+    MozSocialAPI.enabled = enable;
     Services.obs.notifyObservers(null, "social:pref-changed", enable ? "enabled" : "disabled");
   },
 
   // Adds a provider given a manifest, and returns the added provider.
   addProvider: function addProvider(manifest, onDone) {
     if (SocialServiceInternal.providers[manifest.origin])
       throw new Error("SocialService.addProvider: provider with this origin already exists");
 
--- a/toolkit/components/social/test/browser/browser_workerAPI.js
+++ b/toolkit/components/social/test/browser/browser_workerAPI.js
@@ -27,17 +27,17 @@ let tests = {
   testInitializeWorker: function(next) {
     ok(provider.workerAPI, "provider has a workerAPI");
     is(provider.workerAPI.initialized, false, "workerAPI is not yet initialized");
   
     let port = provider.port;
     ok(port, "should be able to get a port from the provider");
   
     port.onmessage = function onMessage(event) {
-      let {topic, data} = event.data;
+      let topic = event.data.topic;
       if (topic == "test-initialization-complete") {
         is(provider.workerAPI.initialized, true, "workerAPI is now initialized");
         next();
       }
     }
     port.postMessage({topic: "test-initialization"});
   },
 
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc
@@ -145,25 +145,30 @@ bool GetThreadRegisters(ThreadInfo* info
       return false;
     }
   }
 #endif
 
   return true;
 }
 
+// All interesting auvx entry types are below AT_SYSINFO_EHDR
+#define AT_MAX AT_SYSINFO_EHDR
+
 LinuxDumper::LinuxDumper(int pid)
     : pid_(pid),
       threads_suspended_(false),
       threads_(&allocator_, 8),
-      mappings_(&allocator_) {
+      mappings_(&allocator_),
+      auxv_(&allocator_, AT_MAX + 1) {
 }
 
 bool LinuxDumper::Init() {
-  return EnumerateThreads(&threads_) &&
+  return ReadAuxv() &&
+         EnumerateThreads(&threads_) &&
          EnumerateMappings(&mappings_);
 }
 
 bool LinuxDumper::ThreadsAttach() {
   if (threads_suspended_)
     return true;
   for (size_t i = 0; i < threads_.size(); ++i) {
     if (!AttachThread(threads_[i])) {
@@ -266,58 +271,58 @@ LinuxDumper::ElfFileIdentifierForMapping
     return false;
   }
 
   bool success = FileID::ElfFileIdentifierFromMappedFile(base, identifier);
   sys_munmap(base, st.st_size);
   return success;
 }
 
-void*
-LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const {
+bool
+LinuxDumper::ReadAuxv() {
   char auxv_path[80];
-  BuildProcPath(auxv_path, pid, "auxv");
+  BuildProcPath(auxv_path, pid_, "auxv");
 
   // If BuildProcPath errors out due to invalid input, we'll handle it when
   // we try to sys_open the file.
 
-  // Find the AT_SYSINFO_EHDR entry for linux-gate.so
-  // See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
-  // information.
   int fd = sys_open(auxv_path, O_RDONLY, 0);
   if (fd < 0) {
-    return NULL;
+    return false;
   }
 
   elf_aux_entry one_aux_entry;
+  bool res = false;
   while (sys_read(fd,
                   &one_aux_entry,
                   sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
          one_aux_entry.a_type != AT_NULL) {
-    if (one_aux_entry.a_type == AT_SYSINFO_EHDR) {
-      close(fd);
-      return reinterpret_cast<void*>(one_aux_entry.a_un.a_val);
+    if (one_aux_entry.a_type <= AT_MAX) {
+      auxv_[one_aux_entry.a_type] = one_aux_entry.a_un.a_val;
+      res = true;
     }
   }
   close(fd);
-  return NULL;
+  return res;
 }
 
 bool
 LinuxDumper::EnumerateMappings(wasteful_vector<MappingInfo*>* result) const {
   char maps_path[80];
   BuildProcPath(maps_path, pid_, "maps");
 
   // linux_gate_loc is the beginning of the kernel's mapping of
   // linux-gate.so in the process.  It doesn't actually show up in the
-  // maps list as a filename, so we use the aux vector to find it's
-  // load location and special case it's entry when creating the list
-  // of mappings.
+  // maps list as a filename, but it can be found using the AT_SYSINFO_EHDR
+  // aux vector entry, which gives the information necessary to special
+  // case its entry when creating the list of mappings.
+  // See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
+  // information.
   const void* linux_gate_loc;
-  linux_gate_loc = FindBeginningOfLinuxGateSharedLibrary(pid_);
+  linux_gate_loc = reinterpret_cast<void *>(auxv_[AT_SYSINFO_EHDR]);
 
   const int fd = sys_open(maps_path, O_RDONLY, 0);
   if (fd < 0)
     return false;
   LineReader* const line_reader = new(allocator_) LineReader(fd);
 
   const char* line;
   unsigned line_len;
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h
@@ -65,16 +65,19 @@ typedef struct
 
 #if !defined(AT_SYSINFO_EHDR)
 #define AT_SYSINFO_EHDR 33
 #endif
 #endif  // __ANDROID__
 #elif defined(__x86_64__)
 typedef Elf64_auxv_t elf_aux_entry;
 #endif
+
+typedef typeof(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
+
 // When we find the VDSO mapping in the process's address space, this
 // is the name we use for it when writing it to the minidump.
 // This should always be less than NAME_MAX!
 const char kLinuxGateLibraryName[] = "linux-gate.so";
 
 // We produce one of these structures for each thread in the crashed process.
 struct ThreadInfo {
   pid_t tid;    // thread id
@@ -140,16 +143,17 @@ class LinuxDumper {
   // Read information about the given thread. Returns true on success. One must
   // have called |ThreadsAttach| first.
   bool ThreadInfoGet(ThreadInfo* info);
 
   // These are only valid after a call to |Init|.
   const wasteful_vector<pid_t> &threads() { return threads_; }
   const wasteful_vector<MappingInfo*> &mappings() { return mappings_; }
   const MappingInfo* FindMapping(const void* address) const;
+  const wasteful_vector<elf_aux_val_t> &auxv() { return auxv_; }
 
   // Find a block of memory to take as the stack given the top of stack pointer.
   //   stack: (output) the lowest address in the memory area
   //   stack_len: (output) the length of the memory area
   //   stack_top: the current top of the stack
   bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top);
 
   PageAllocator* allocator() { return &allocator_; }
@@ -162,30 +166,26 @@ class LinuxDumper {
   // character array that is overwritten, and node is the final node
   // without any slashes.
   void BuildProcPath(char* path, pid_t pid, const char* node) const;
 
   // Generate a File ID from the .text section of a mapped entry
   bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
                                    uint8_t identifier[sizeof(MDGUID)]);
 
-  // Utility method to find the location of where the kernel has
-  // mapped linux-gate.so in memory(shows up in /proc/pid/maps as
-  // [vdso], but we can't guarantee that it's the only virtual dynamic
-  // shared object.  Parsing the auxilary vector for AT_SYSINFO_EHDR
-  // is the safest way to go.)
-  void* FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const;
  private:
+  bool ReadAuxv();
   bool EnumerateMappings(wasteful_vector<MappingInfo*>* result) const;
   bool EnumerateThreads(wasteful_vector<pid_t>* result) const;
 
   const pid_t pid_;
 
   mutable PageAllocator allocator_;
 
   bool threads_suspended_;
   wasteful_vector<pid_t> threads_;  // the ids of all the threads
   wasteful_vector<MappingInfo*> mappings_;  // info from /proc/<pid>/maps
+  wasteful_vector<elf_aux_val_t> auxv_;  // info from /proc/<pid>/auxv
 };
 
 }  // namespace google_breakpad
 
 #endif  // CLIENT_LINUX_HANDLER_LINUX_DUMPER_H_
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc
@@ -158,17 +158,17 @@ TEST(LinuxDumperTest, BuildProcPath) {
 #endif
 }
 
 #if !defined(__ARM_EABI__)
 TEST(LinuxDumperTest, MappingsIncludeLinuxGate) {
   LinuxDumper dumper(getpid());
   ASSERT_TRUE(dumper.Init());
 
-  void* linux_gate_loc = dumper.FindBeginningOfLinuxGateSharedLibrary(getpid());
+  void* linux_gate_loc = reinterpret_cast<void *>(dumper.auxv()[AT_SYSINFO_EHDR]);
   ASSERT_TRUE(linux_gate_loc);
   bool found_linux_gate = false;
 
   const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
   const MappingInfo* mapping;
   for (unsigned i = 0; i < mappings.size(); ++i) {
     mapping = mappings[i];
     if (!strcmp(mapping->name, kLinuxGateLibraryName)) {
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc
@@ -465,39 +465,19 @@ class MinidumpWriter {
     dumper_.ThreadsDetach();
   }
 
   bool HaveCrashedThread() const {
     return ucontext_ != NULL;
   }
 
   bool Dump() {
-    // The dynamic linker makes information available that helps gdb find all
-    // DSOs loaded into the program. If we can access this information, we dump
-    // it to a MD_LINUX_DSO_DEBUG stream.
-    struct r_debug* r_debug = NULL;
-    uint32_t dynamic_length = 0;
-#if !defined(__ANDROID__)
-    for (int i = 0;;) {
-      ElfW(Dyn) dyn;
-      dynamic_length += sizeof(dyn);
-      dumper_.CopyFromProcess(&dyn, crashing_tid_, _DYNAMIC+i++, sizeof(dyn));
-      if (dyn.d_tag == DT_DEBUG) {
-        r_debug = (struct r_debug*)dyn.d_un.d_ptr;
-        continue;
-      } else if (dyn.d_tag == DT_NULL)
-        break;
-    }
-#endif
-
     // A minidump file contains a number of tagged streams. This is the number
     // of stream which we write.
-    unsigned kNumWriters = 12;
-    if (r_debug)
-      ++kNumWriters;
+    unsigned kNumWriters = 13;
 
     TypedMDRVA<MDRawHeader> header(&minidump_writer_);
     TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
     if (!header.Allocate())
       return false;
     if (!dir.AllocateArray(kNumWriters))
       return false;
     memset(header.get(), 0, sizeof(MDRawHeader));
@@ -566,22 +546,20 @@ class MinidumpWriter {
       NullifyDirectoryEntry(&dirent);
     dir.CopyIndex(dir_index++, &dirent);
 
     dirent.stream_type = MD_LINUX_MAPS;
     if (!WriteProcFile(&dirent.location, crashing_tid_, "maps"))
       NullifyDirectoryEntry(&dirent);
     dir.CopyIndex(dir_index++, &dirent);
 
-    if (r_debug) {
-      dirent.stream_type = MD_LINUX_DSO_DEBUG;
-      if (!WriteDSODebugStream(&dirent, r_debug, dynamic_length))
-        NullifyDirectoryEntry(&dirent);
-      dir.CopyIndex(dir_index++, &dirent);
-    }
+    dirent.stream_type = MD_LINUX_DSO_DEBUG;
+    if (!WriteDSODebugStream(&dirent))
+      NullifyDirectoryEntry(&dirent);
+    dir.CopyIndex(dir_index++, &dirent);
 
     // If you add more directory entries, don't forget to update kNumWriters,
     // above.
 
     dumper_.ThreadsDetach();
     return true;
   }
 
@@ -1032,23 +1010,66 @@ class MinidumpWriter {
     dirent->location = si.location();
 
     WriteCPUInformation(si.get());
     WriteOSInformation(si.get());
 
     return true;
   }
 
-  bool WriteDSODebugStream(MDRawDirectory* dirent, struct r_debug* r_debug,
-                           uint32_t dynamic_length) {
+  bool WriteDSODebugStream(MDRawDirectory* dirent) {
 #if defined(__ANDROID__)
     return false;
 #else
-    // The caller provided us with a pointer to "struct r_debug". We can
-    // look up the "r_map" field to get a linked list of all loaded DSOs.
+    ElfW(Phdr) *phdr = reinterpret_cast<ElfW(Phdr) *>(dumper_.auxv()[AT_PHDR]);
+    char *base;
+    int phnum = dumper_.auxv()[AT_PHNUM];
+    if (!phnum || !phdr)
+      return false;
+
+    // Assume the program base is at the beginning of the same page as the PHDR
+    base = reinterpret_cast<char *>(reinterpret_cast<uintptr_t>(phdr) & ~0xfff);
+
+    // Search for the program PT_DYNAMIC segment
+    ElfW(Addr) dyn_addr = 0;
+    for (; phnum >= 0; phnum--, phdr++) {
+      ElfW(Phdr) ph;
+      dumper_.CopyFromProcess(&ph, crashing_tid_, phdr, sizeof(ph));
+      // Adjust base address with the virtual address of the PT_LOAD segment
+      // corresponding to offset 0
+      if (ph.p_type == PT_LOAD && ph.p_offset == 0)
+        base -= ph.p_vaddr;
+      if (ph.p_type == PT_DYNAMIC)
+        dyn_addr = ph.p_vaddr;
+    }
+    if (!dyn_addr)
+      return false;
+
+    ElfW(Dyn) *dynamic = reinterpret_cast<ElfW(Dyn) *>(dyn_addr + base);
+
+    // The dynamic linker makes information available that helps gdb find all
+    // DSOs loaded into the program. If this information is indeed available,
+    // dump it to a MD_LINUX_DSO_DEBUG stream.
+    struct r_debug* r_debug = NULL;
+    uint32_t dynamic_length = 0;
+
+    for (int i = 0;;) {
+      ElfW(Dyn) dyn;
+      dynamic_length += sizeof(dyn);
+      dumper_.CopyFromProcess(&dyn, crashing_tid_, dynamic+i++, sizeof(dyn));
+      if (dyn.d_tag == DT_DEBUG) {
+        r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
+        continue;
+      } else if (dyn.d_tag == DT_NULL) {
+        break;
+      }
+    }
+
+    // The "r_map" field of that r_debug struct contains a linked list of all
+    // loaded DSOs.
     // Our list of DSOs potentially is different from the ones in the crashing
     // process. So, we have to be careful to never dereference pointers
     // directly. Instead, we use CopyFromProcess() everywhere.
     // See <link.h> for a more detailed discussion of the how the dynamic
     // loader communicates with debuggers.
 
     // Count the number of loaded DSOs
     int dso_count = 0;
@@ -1101,20 +1122,20 @@ class MinidumpWriter {
     dirent->stream_type = MD_LINUX_DSO_DEBUG;
     dirent->location = debug.location();
 
     debug.get()->version = debug_entry.r_version;
     debug.get()->map = linkmap_rva;
     debug.get()->dso_count = dso_count;
     debug.get()->brk = (void*)debug_entry.r_brk;
     debug.get()->ldbase = (void*)debug_entry.r_ldbase;
-    debug.get()->dynamic = (void*)&_DYNAMIC;
+    debug.get()->dynamic = dynamic;
 
     char *dso_debug_data = new char[dynamic_length];
-    dumper_.CopyFromProcess(dso_debug_data, crashing_tid_, &_DYNAMIC,
+    dumper_.CopyFromProcess(dso_debug_data, crashing_tid_, dynamic,
                             dynamic_length);
     debug.CopyIndexAfterObject(0, dso_debug_data, dynamic_length);
     delete[] dso_debug_data;
 
     return true;
 #endif  // __ANDROID__
   }
 
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -150,27 +150,39 @@ static const XP_CHAR dumpFileExtension[]
 static const XP_CHAR extraFileExtension[] = {'.', 'e', 'x', 't',
                                              'r', 'a', '\0'}; // .extra
 
 static google_breakpad::ExceptionHandler* gExceptionHandler = nsnull;
 
 static XP_CHAR* pendingDirectory;
 static XP_CHAR* crashReporterPath;
 
-// if this is false, we don't launch the crash reporter
+// If this is false, we don't launch the crash reporter
 static bool doReport = true;
 
+// If this is true, we don't have a crash reporter
+static bool headlessClient = false;
+
 // if this is true, we pass the exception on to the OS crash reporter
 static bool showOSCrashReporter = false;
 
 // The time of the last recorded crash, as a time_t value.
 static time_t lastCrashTime = 0;
 // The pathname of a file to store the crash time in
 static XP_CHAR lastCrashTimeFilename[XP_PATH_MAX] = {0};
 
+// A marker file to hold the path to the last dump written, which
+// will be checked on startup.
+static XP_CHAR crashMarkerFilename[XP_PATH_MAX] = {0};
+
+// Whether we've already looked for the marker file.
+static bool lastRunCrashID_checked = false;
+// The minidump ID contained in the marker file.
+static nsString* lastRunCrashID = nsnull;
+
 // these are just here for readability
 static const char kCrashTimeParameter[] = "CrashTime=";
 static const int kCrashTimeParameterLen = sizeof(kCrashTimeParameter)-1;
 
 static const char kTimeSinceLastCrashParameter[] = "SecondsSinceLastCrash=";
 static const int kTimeSinceLastCrashParameterLen =
                                      sizeof(kTimeSinceLastCrashParameter)-1;
 
@@ -309,17 +321,17 @@ static cpu_type_t pref_cpu_types[2] = {
 #elif defined(__ppc__)
                                  CPU_TYPE_POWERPC,
 #endif
                                  CPU_TYPE_ANY };
 
 static posix_spawnattr_t spawnattr;
 #endif
 
-#if defined(__ANDROID__)
+#if defined(MOZ_WIDGET_ANDROID)
 // Android builds use a custom library loader,
 // so the embedding will provide a list of shared
 // libraries that are mapped into anonymous mappings.
 typedef struct {
   std::string name;
   std::string debug_id;
   uintptr_t   start_address;
   size_t      length;
@@ -411,16 +423,39 @@ bool MinidumpCallback(const XP_CHAR* dum
 
   static XP_CHAR extraDataPath[XP_PATH_MAX];
   size = XP_PATH_MAX;
   p = Concat(extraDataPath, dump_path, &size);
   p = Concat(p, XP_PATH_SEPARATOR, &size);
   p = Concat(p, minidump_id, &size);
   Concat(p, extraFileExtension, &size);
 
+  if (headlessClient) {
+    // Leave a marker indicating that there was a crash.
+#if defined(XP_WIN32)
+    HANDLE hFile = CreateFile(crashMarkerFilename, GENERIC_WRITE, 0,
+                              NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+                              NULL);
+    if(hFile != INVALID_HANDLE_VALUE) {
+      DWORD nBytes;
+      WriteFile(hFile, minidumpPath, 2*wcslen(minidumpPath), &nBytes, NULL);
+      CloseHandle(hFile);
+    }
+#elif defined(XP_UNIX)
+    int fd = sys_open(crashMarkerFilename,
+                      O_WRONLY | O_CREAT | O_TRUNC,
+                      0600);
+    if (fd != -1) {
+      ssize_t ignored = sys_write(fd, minidumpPath, my_strlen(minidumpPath));
+      (void)ignored;
+      sys_close(fd);
+    }
+#endif
+  }
+
   char oomAllocationSizeBuffer[32];
   int oomAllocationSizeBufferLen = 0;
   if (gOOMAllocationSize) {
     XP_STOA(gOOMAllocationSize, oomAllocationSizeBuffer, 10);
     oomAllocationSizeBufferLen = my_strlen(oomAllocationSizeBuffer);
   }
 
   // calculate time since last crash (if possible), and store
@@ -466,24 +501,16 @@ bool MinidumpCallback(const XP_CHAR* dum
       ssize_t ignored = sys_write(fd, crashTimeString, crashTimeStringLen);
       (void)ignored;
       sys_close(fd);
     }
 #endif
   }
 
 #if defined(XP_WIN32)
-  XP_CHAR cmdLine[CMDLINE_SIZE];
-  size = CMDLINE_SIZE;
-  p = Concat(cmdLine, L"\"", &size);
-  p = Concat(p, crashReporterPath, &size);
-  p = Concat(p, L"\" \"", &size);
-  p = Concat(p, minidumpPath, &size);
-  Concat(p, L"\"", &size);
-
   if (!crashReporterAPIData->IsEmpty()) {
     // write out API data
     HANDLE hFile = CreateFile(extraDataPath, GENERIC_WRITE, 0,
                               NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
                               NULL);
     if(hFile != INVALID_HANDLE_VALUE) {
       DWORD nBytes;
       WriteFile(hFile, crashReporterAPIData->get(),
@@ -534,16 +561,24 @@ bool MinidumpCallback(const XP_CHAR* dum
       CloseHandle(hFile);
     }
   }
 
   if (!doReport) {
     return returnValue;
   }
 
+  XP_CHAR cmdLine[CMDLINE_SIZE];
+  size = CMDLINE_SIZE;
+  p = Concat(cmdLine, L"\"", &size);
+  p = Concat(p, crashReporterPath, &size);
+  p = Concat(p, L"\" \"", &size);
+  p = Concat(p, minidumpPath, &size);
+  Concat(p, L"\"", &size);
+
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
 
   ZeroMemory(&si, sizeof(si));
   si.cb = sizeof(si);
   si.dwFlags = STARTF_USESHOWWINDOW;
   si.wShowWindow = SW_SHOWNORMAL;
   ZeroMemory(&pi, sizeof(pi));
@@ -612,17 +647,17 @@ bool MinidumpCallback(const XP_CHAR* dum
     return false;
 
 #else // !XP_MACOSX
   pid_t pid = sys_fork();
 
   if (pid == -1)
     return false;
   else if (pid == 0) {
-#if !defined(__ANDROID__)
+#if !defined(MOZ_WIDGET_ANDROID)
     // need to clobber this, as libcurl might load NSS,
     // and we want it to load the system NSS.
     unsetenv("LD_LIBRARY_PATH");
     (void) execl(crashReporterPath,
                  crashReporterPath, minidumpPath, (char*)0);
 #else
     // Invoke the reportCrash activity using am
     (void) execlp("/system/bin/am",
@@ -683,28 +718,31 @@ namespace {
     return true;
   }
 }
 
 
 nsresult SetExceptionHandler(nsIFile* aXREDirectory,
                              bool force/*=false*/)
 {
-  nsresult rv;
-
   if (gExceptionHandler)
     return NS_ERROR_ALREADY_INITIALIZED;
 
   const char *envvar = PR_GetEnv("MOZ_CRASHREPORTER_DISABLE");
   if (envvar && *envvar && !force)
     return NS_OK;
 
+#if defined(MOZ_WIDGET_GONK)
+  doReport = false;
+  headlessClient = true;
+#else
   // this environment variable prevents us from launching
   // the crash reporter client
   doReport = ShouldReport();
+#endif
 
   // allocate our strings
   crashReporterAPIData = new nsCString();
   NS_ENSURE_TRUE(crashReporterAPIData, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ASSERTION(!crashReporterAPILock, "Shouldn't have a lock yet");
   crashReporterAPILock = new Mutex("crashReporterAPILock");
   NS_ASSERTION(!notesFieldLock, "Shouldn't have a lock yet");
@@ -714,47 +752,47 @@ nsresult SetExceptionHandler(nsIFile* aX
     new nsDataHashtable<nsCStringHashKey,nsCString>();
   NS_ENSURE_TRUE(crashReporterAPIData_Hash, NS_ERROR_OUT_OF_MEMORY);
 
   crashReporterAPIData_Hash->Init();
 
   notesField = new nsCString();
   NS_ENSURE_TRUE(notesField, NS_ERROR_OUT_OF_MEMORY);
 
-  // locate crashreporter executable
-  nsCOMPtr<nsIFile> exePath;
-  rv = aXREDirectory->Clone(getter_AddRefs(exePath));
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (!headlessClient) {
+    // locate crashreporter executable
+    nsCOMPtr<nsIFile> exePath;
+    nsresult rv = aXREDirectory->Clone(getter_AddRefs(exePath));
+    NS_ENSURE_SUCCESS(rv, rv);
 
 #if defined(XP_MACOSX)
-  exePath->Append(NS_LITERAL_STRING("crashreporter.app"));
-  exePath->Append(NS_LITERAL_STRING("Contents"));
-  exePath->Append(NS_LITERAL_STRING("MacOS"));
+    exePath->Append(NS_LITERAL_STRING("crashreporter.app"));
+    exePath->Append(NS_LITERAL_STRING("Contents"));
+    exePath->Append(NS_LITERAL_STRING("MacOS"));
 #endif
 
-  exePath->AppendNative(NS_LITERAL_CSTRING(CRASH_REPORTER_FILENAME));
+    exePath->AppendNative(NS_LITERAL_CSTRING(CRASH_REPORTER_FILENAME));
 
 #ifdef XP_WIN32
-  nsString crashReporterPath_temp;
-
-  exePath->GetPath(crashReporterPath_temp);
-  crashReporterPath = ToNewUnicode(crashReporterPath_temp);
+    nsString crashReporterPath_temp;
+
+    exePath->GetPath(crashReporterPath_temp);
+    crashReporterPath = ToNewUnicode(crashReporterPath_temp);
 #elif !defined(__ANDROID__)
-  nsCString crashReporterPath_temp;
-
-  exePath->GetNativePath(crashReporterPath_temp);
-  crashReporterPath = ToNewCString(crashReporterPath_temp);
+    nsCString crashReporterPath_temp;
+
+    exePath->GetNativePath(crashReporterPath_temp);
+    crashReporterPath = ToNewCString(crashReporterPath_temp);
 #else
-  // On Android, we launch using the application package name
-  // instead of a filename, so use ANDROID_PACKAGE_NAME to do that here.
-  //TODO: don't hardcode org.mozilla here, so other vendors can
-  // ship XUL apps with different package names on Android?
-  nsCString package(ANDROID_PACKAGE_NAME "/.CrashReporter");
-  crashReporterPath = ToNewCString(package);
+    // On Android, we launch using the application package name
+    // instead of a filename, so use ANDROID_PACKAGE_NAME to do that here.
+    nsCString package(ANDROID_PACKAGE_NAME "/.CrashReporter");
+    crashReporterPath = ToNewCString(package);
 #endif
+  }
 
   // get temp path to use for minidump path
 #if defined(XP_WIN32)
   nsString tempPath;
 
   // first figure out buffer size
   int pathLen = GetTempPath(0, NULL);
   if (pathLen == 0)
@@ -773,22 +811,21 @@ nsresult SetExceptionHandler(nsIFile* aX
   char path[PATH_MAX];
   OSStatus status = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX);
   if (status != noErr)
     return NS_ERROR_FAILURE;
 
   tempPath = path;
 
 #elif defined(__ANDROID__)
-  // GeckoAppShell sets this in the environment
+  // GeckoAppShell or Gonk's init.rc sets this in the environment
   const char *tempenv = PR_GetEnv("TMPDIR");
   if (!tempenv)
     return NS_ERROR_FAILURE;
   nsCString tempPath(tempenv);
-
 #elif defined(XP_UNIX)
   // we assume it's always /tmp on unix systems
   nsCString tempPath = NS_LITERAL_CSTRING("/tmp/");
 #else
 #error "Implement this for your platform"
 #endif
 
 #ifdef XP_MACOSX
@@ -892,17 +929,17 @@ nsresult SetExceptionHandler(nsIFile* aX
   Boolean keyExistsAndHasValidFormat = false;
   Boolean prefValue = ::CFPreferencesGetAppBooleanValue(CFSTR("OSCrashReporter"),
                                                         kCFPreferencesCurrentApplication,
                                                         &keyExistsAndHasValidFormat);
   if (keyExistsAndHasValidFormat)
     showOSCrashReporter = prefValue;
 #endif
 
-#if defined(__ANDROID__)
+#if defined(MOZ_WIDGET_ANDROID)
   for (unsigned int i = 0; i < library_mappings.size(); i++) {
     u_int8_t guid[sizeof(MDGUID)];
     FileIDToGUID(library_mappings[i].debug_id.c_str(), guid);
     gExceptionHandler->AddMappingInfo(library_mappings[i].name,
                                       guid,
                                       library_mappings[i].start_address,
                                       library_mappings[i].length,
                                       library_mappings[i].file_offset);
@@ -1117,16 +1154,44 @@ nsresult SetupExtraData(nsIFile* aAppDat
   nsCAutoString filename;
   rv = lastCrashFile->GetNativePath(filename);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (filename.Length() < XP_PATH_MAX)
     strncpy(lastCrashTimeFilename, filename.get(), filename.Length());
 #endif
 
+  if (headlessClient) {
+    nsCOMPtr<nsIFile> markerFile;
+    rv = dataDirectory->Clone(getter_AddRefs(markerFile));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = markerFile->AppendNative(NS_LITERAL_CSTRING("LastCrashFilename"));
+    NS_ENSURE_SUCCESS(rv, rv);
+    memset(crashMarkerFilename, 0, sizeof(crashMarkerFilename));
+
+#if defined(XP_WIN32)
+    nsAutoString markerFilename;
+    rv = markerFile->GetPath(markerFilename);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (markerFilename.Length() < XP_PATH_MAX)
+      wcsncpy(crashMarkerFilename, markerFilename.get(),
+              markerFilename.Length());
+#else
+    nsCAutoString markerFilename;
+    rv = markerFile->GetNativePath(markerFilename);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (markerFilename.Length() < XP_PATH_MAX)
+      strncpy(crashMarkerFilename, markerFilename.get(),
+              markerFilename.Length());
+#endif
+  }
+
   return NS_OK;
 }
 
 static void OOPDeinit();
 
 nsresult UnsetExceptionHandler()
 {
 #ifdef XP_WIN
@@ -1148,16 +1213,19 @@ nsresult UnsetExceptionHandler()
   notesFieldLock = nsnull;
 
   delete crashReporterAPIData;
   crashReporterAPIData = nsnull;
 
   delete notesField;
   notesField = nsnull;
 
+  delete lastRunCrashID;
+  lastRunCrashID = nsnull;
+
   if (pendingDirectory) {
     NS_Free(pendingDirectory);
     pendingDirectory = nsnull;
   }
 
   if (crashReporterPath) {
     NS_Free(crashReporterPath);
     crashReporterPath = nsnull;
@@ -1508,36 +1576,36 @@ static nsresult PrefSubmitReports(bool* 
 
   nsCAutoString regPath;
 
   regPath.AppendLiteral("Software\\");
 
   // We need to ensure the registry keys are created so we can properly
   // write values to it
   
-  // Create appVendor key
-  if(!appVendor.IsEmpty()) {
-    regPath.Append(appVendor);
-    regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
-                   NS_ConvertUTF8toUTF16(regPath),
-                   nsIWindowsRegKey::ACCESS_SET_VALUE);
-    regPath.AppendLiteral("\\");
-  }
-
-  // Create appName key
-  regPath.Append(appName);
-  regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
-                 NS_ConvertUTF8toUTF16(regPath),
-                 nsIWindowsRegKey::ACCESS_SET_VALUE);
-  regPath.AppendLiteral("\\");
-
-  // Create Crash Reporter key
-  regPath.AppendLiteral("Crash Reporter");
-  regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
-                 NS_ConvertUTF8toUTF16(regPath),
+  // Create appVendor key
+  if(!appVendor.IsEmpty()) {
+    regPath.Append(appVendor);
+    regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+                   NS_ConvertUTF8toUTF16(regPath),
+                   nsIWindowsRegKey::ACCESS_SET_VALUE);
+    regPath.AppendLiteral("\\");
+  }
+
+  // Create appName key
+  regPath.Append(appName);
+  regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+                 NS_ConvertUTF8toUTF16(regPath),
+                 nsIWindowsRegKey::ACCESS_SET_VALUE);
+  regPath.AppendLiteral("\\");
+
+  // Create Crash Reporter key
+  regPath.AppendLiteral("Crash Reporter");
+  regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+                 NS_ConvertUTF8toUTF16(regPath),
                  nsIWindowsRegKey::ACCESS_SET_VALUE);
 
   // If we're saving the pref value, just write it to ROOT_KEY_CURRENT_USER
   // and we're done.
   if (writePref) {
     rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
                       NS_ConvertUTF8toUTF16(regPath),
                       nsIWindowsRegKey::ACCESS_SET_VALUE);
@@ -1690,16 +1758,43 @@ nsresult SetSubmitReports(bool aSubmitRe
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     obsServ->NotifyObservers(nsnull, "submit-reports-pref-changed", nsnull);
     return NS_OK;
 }
 
+static void
+FindPendingDir()
+{
+  if (pendingDirectory)
+    return;
+
+  nsCOMPtr<nsIFile> pendingDir;
+  nsresult rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(pendingDir));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Couldn't get the user appdata directory, crash dumps will go in an unusual location");
+  }
+  else {
+    pendingDir->Append(NS_LITERAL_STRING("Crash Reports"));
+    pendingDir->Append(NS_LITERAL_STRING("pending"));
+
+#ifdef XP_WIN
+    nsString path;
+    pendingDir->GetPath(path);
+    pendingDirectory = ToNewUnicode(path);
+#else
+    nsCString path;
+    pendingDir->GetNativePath(path);
+    pendingDirectory = ToNewCString(path);
+#endif
+  }
+}
+
 // The "pending" dir is Crash Reports/pending, from which minidumps
 // can be submitted. Because this method may be called off the main thread,
 // we store the pending directory as a path.
 static bool
 GetPendingDir(nsIFile** dir)
 {
   MOZ_ASSERT(OOPInitialized());
   if (!pendingDirectory) {
@@ -1939,17 +2034,17 @@ OnChildProcessDumpRequested(void* aConte
   CreateFileFromPath(
 #ifdef XP_MACOSX
                      aFilePath,
 #else
                      *aFilePath,
 #endif
                      getter_AddRefs(minidump));
 
-#if defined(__ANDROID__)
+#if defined(MOZ_WIDGET_ANDROID)
   // Do dump generation here since the CrashGenerationServer doesn't
   // have access to the library mappings.
   MappingMap::const_iterator iter = 
     child_library_mappings.find(aClientInfo->pid_);
   google_breakpad::AppMemoryList a;
   if (iter == child_library_mappings.end()) {
     NS_WARNING("No library mappings found for child, can't write minidump!");
     return;
@@ -2040,17 +2135,17 @@ OOPInit()
 
 #elif defined(XP_LINUX)
   if (!CrashGenerationServer::CreateReportChannel(&serverSocketFd,
                                                   &clientSocketFd))
     NS_RUNTIMEABORT("can't create crash reporter socketpair()");
 
   const std::string dumpPath = gExceptionHandler->dump_path();
   bool generateDumps = true;
-#if defined(__ANDROID__)
+#if defined(MOZ_WIDGET_ANDROID)
   // On Android, the callback will do dump generation, since it needs
   // to pass the library mappings.
   generateDumps = false;
 #endif
   crashServer = new CrashGenerationServer(
     serverSocketFd,
     OnChildProcessDumpRequested, NULL,
     NULL, NULL,                 // we don't care about process exit here
@@ -2076,35 +2171,17 @@ OOPInit()
   if (!crashServer->Start())
     NS_RUNTIMEABORT("can't start crash reporter server()");
 
   pidToMinidump = new ChildMinidumpMap();
   pidToMinidump->Init();
 
   dumpMapLock = new Mutex("CrashReporter::dumpMapLock");
 
-  nsCOMPtr<nsIFile> pendingDir;
-  nsresult rv = NS_GetSpecialDirectory("UAppData", getter_AddRefs(pendingDir));
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Couldn't get the user appdata directory, crash dumps will go in an unusual location");
-  }
-  else {
-    pendingDir->Append(NS_LITERAL_STRING("Crash Reports"));
-    pendingDir->Append(NS_LITERAL_STRING("pending"));
-
-#ifdef XP_WIN
-    nsString path;
-    pendingDir->GetPath(path);
-    pendingDirectory = ToNewUnicode(path);
-#else
-    nsCString path;
-    pendingDir->GetNativePath(path);
-    pendingDirectory = ToNewCString(path);
-#endif
-  }
+  FindPendingDir();
 }
 
 static void
 OOPDeinit()
 {
   if (!OOPInitialized()) {
     NS_WARNING("OOPDeinit() without successful OOPInit()");
     return;
@@ -2202,16 +2279,87 @@ UnregisterInjectorCallback(DWORD process
     return;
 
   MutexAutoLock lock(*dumpMapLock);
   pidToMinidump->RemoveEntry(processID);
 }
 
 #endif // MOZ_CRASHREPORTER_INJECTOR
 
+bool
+CheckForLastRunCrash()
+{
+  if (lastRunCrashID)
+    return true;
+
+  // The exception handler callback leaves the filename of the
+  // last minidump in a known file.
+  nsCOMPtr<nsIFile> lastCrashFile;
+  CreateFileFromPath(crashMarkerFilename,
+                     getter_AddRefs(lastCrashFile));
+
+  bool exists;
+  if (NS_FAILED(lastCrashFile->Exists(&exists)) || !exists) {
+    return false;
+  }
+
+  nsCAutoString lastMinidump_contents;
+  if (NS_FAILED(GetFileContents(lastCrashFile, lastMinidump_contents))) {
+    return false;
+  }
+  lastCrashFile->Remove(false);
+
+#ifdef XP_WIN
+  // Ugly but effective.
+  nsDependentString lastMinidump(
+      reinterpret_cast<const PRUnichar*>(lastMinidump_contents.get()));
+#else
+  nsCAutoString lastMinidump = lastMinidump_contents;
+#endif
+  nsCOMPtr<nsIFile> lastMinidumpFile;
+  CreateFileFromPath(lastMinidump.get(),
+                      getter_AddRefs(lastMinidumpFile));
+
+  if (NS_FAILED(lastMinidumpFile->Exists(&exists)) || !exists) {
+    return false;
+  }
+
+  nsCOMPtr<nsIFile> lastExtraFile;
+  if (!GetExtraFileForMinidump(lastMinidumpFile,
+                               getter_AddRefs(lastExtraFile))) {
+    return false;
+  }
+
+  FindPendingDir();
+
+  // Move {dump,extra} to pending folder
+  if (!MoveToPending(lastMinidumpFile, lastExtraFile)) {
+    return false;
+  }
+
+  lastRunCrashID = new nsString();
+  return GetIDFromMinidump(lastMinidumpFile, *lastRunCrashID);
+}
+
+bool
+GetLastRunCrashID(nsAString& id)
+{
+  if (!lastRunCrashID_checked) {
+    CheckForLastRunCrash();
+    lastRunCrashID_checked = true;
+  }
+
+  if (!lastRunCrashID) {
+    return false;
+  }
+
+  id = *lastRunCrashID;
+  return true;
+}
+
 #if defined(XP_WIN)
 // Child-side API
 bool
 SetRemoteExceptionHandler(const nsACString& crashPipe)
 {
   // crash reporting is disabled
   if (crashPipe.Equals(kNullNotifyPipe))
     return true;
@@ -2474,17 +2622,17 @@ CreatePairedMinidumps(ProcessHandle chil
 bool
 UnsetRemoteExceptionHandler()
 {
   delete gExceptionHandler;
   gExceptionHandler = NULL;
   return true;
 }
 
-#if defined(__ANDROID__)
+#if defined(MOZ_WIDGET_ANDROID)
 void AddLibraryMapping(const char* library_name,
                        const char* file_id,
                        uintptr_t   start_address,
                        size_t      mapping_length,
                        size_t      file_offset)
 {
   if (!gExceptionHandler) {
     mapping_info info;
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -38,16 +38,17 @@ nsresult SetMinidumpPath(const nsAString
 // thread in a chrome process, but may only be called from the main thread in
 // a content process.
 nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data);
 nsresult AppendAppNotesToCrashReport(const nsACString& data);
 
 nsresult SetRestartArgs(int argc, char** argv);
 nsresult SetupExtraData(nsIFile* aAppDataDirectory,
                         const nsACString& aBuildID);
+bool GetLastRunCrashID(nsAString& id);
 
 // Registers an additional memory region to be included in the minidump
 nsresult RegisterAppMemory(void* ptr, size_t length);
 nsresult UnregisterAppMemory(void* ptr);
 
 // Functions for working with minidumps and .extras
 typedef nsDataHashtable<nsCStringHashKey, nsCString> AnnotationTable;
 
@@ -159,17 +160,17 @@ bool CreateNotificationPipeForChild(int*
 
 // Child-side API
 bool SetRemoteExceptionHandler();
 
 #endif  // XP_WIN32
 
 bool UnsetRemoteExceptionHandler();
 
-#if defined(__ANDROID__)
+#if defined(MOZ_WIDGET_ANDROID)
 // Android builds use a custom library loader, so /proc/<pid>/maps
 // will just show anonymous mappings for all the non-system
 // shared libraries. This API is to work around that by providing
 // info about the shared libraries that are mapped into these anonymous
 // mappings.
 void AddLibraryMapping(const char* library_name,
                        const char* file_id,
                        uintptr_t   start_address,
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -816,16 +816,27 @@ NS_IMETHODIMP
 nsXULAppInfo::GetReplacedLockTime(PRInt64 *aReplacedLockTime)
 {
   if (!gProfileLock)
     return NS_ERROR_NOT_AVAILABLE;
   gProfileLock->GetReplacedLockTime(aReplacedLockTime);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXULAppInfo::GetLastRunCrashID(nsAString &aLastRunCrashID)
+{
+#ifdef MOZ_CRASHREPORTER
+  CrashReporter::GetLastRunCrashID(aLastRunCrashID);
+  return NS_OK;
+#else
+  return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
 #ifdef XP_WIN
 // Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
 // safely build with the Vista SDK and without it.
 typedef enum 
 {
   VistaTokenElevationTypeDefault = 1,
   VistaTokenElevationTypeFull,
   VistaTokenElevationTypeLimited
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -449,31 +449,36 @@ public:
     // Pause the profiler during saving.
     // This will prevent us from recording sampling
     // regarding profile saving. This will also
     // prevent bugs caused by the circular buffer not
     // being thread safe. Bug 750989.
     t->SetPaused(true);
 
     // Get file path
+#ifdef ANDROID
+    nsCString tmpPath;
+    tmpPath.AppendPrintf("/sdcard/profile_%i_%i.txt", XRE_GetProcessType(), getpid());
+#else
     nsCOMPtr<nsIFile> tmpFile;
     nsCAutoString tmpPath;
     if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
       LOG("Failed to find temporary directory.");
       return NS_ERROR_FAILURE;
     }
     tmpPath.AppendPrintf("profile_%i_%i.txt", XRE_GetProcessType(), getpid());
 
     nsresult rv = tmpFile->AppendNative(tmpPath);
     if (NS_FAILED(rv))
       return rv;
 
     rv = tmpFile->GetNativePath(tmpPath);
     if (NS_FAILED(rv))
       return rv;
+#endif
 
     // Create a JSContext to run a JSObjectBuilder :(
     // Based on XPCShellEnvironment
     JSRuntime *rt;
     JSContext *cx;
     nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
     if (!rtsvc || NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) {
       LOG("failed to get RuntimeService");
--- a/widget/Makefile.in
+++ b/widget/Makefile.in
@@ -38,26 +38,25 @@ endif
 ifdef MOZ_ENABLE_GTK2
 DIRS += gtk2
 ifdef MOZ_X11
 DIRS += gtkxtbin
 endif
 endif
 
 
-EXPORTS_NAMESPACES = IPC
+EXPORTS_NAMESPACES = IPC mozilla
 
 EXPORTS_IPC = \
 		nsGUIEventIPC.h \
 		$(NULL)
 
-EXPORTS_NAMESPACES += mozilla
-
 EXPORTS_mozilla = \
 		LookAndFeel.h \
+		WidgetUtils.h \
 		$(NULL)
 
 ifdef MOZ_INSTRUMENT_EVENT_LOOP
 EXPORTS_mozilla += \
 		WidgetTraceEvent.h \
 		$(NULL)
 endif
 
new file mode 100644
--- /dev/null
+++ b/widget/WidgetUtils.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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/. */
+
+#ifndef mozilla_WidgetUtils_h
+#define mozilla_WidgetUtils_h
+
+#include "gfxMatrix.h"
+
+namespace mozilla {
+
+// NB: these must match up with pseudo-enum in nsIScreen.idl.
+enum ScreenRotation {
+  ROTATION_0 = 0,
+  ROTATION_90,
+  ROTATION_180,
+  ROTATION_270,
+
+  ROTATION_COUNT
+};
+
+gfxMatrix ComputeGLTransformForRotation(const nsIntRect& aBounds,
+                                        ScreenRotation aRotation);
+
+} // namespace mozilla
+
+#endif // mozilla_WidgetUtils_h
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -63,16 +63,22 @@ static android::FramebufferNativeWindow 
 static bool sFramebufferOpen;
 static bool sUsingOMTC;
 static bool sScreenInitialized;
 static nsRefPtr<gfxASurface> sOMTCSurface;
 static pthread_t sFramebufferWatchThread;
 
 namespace {
 
+static PRUint32
+EffectiveScreenRotation()
+{
+    return (sScreenRotation + sPhysicalScreenRotation) % (360 / 90);
+}
+
 class ScreenOnOffEvent : public nsRunnable {
 public:
     ScreenOnOffEvent(bool on)
         : mIsOn(on)
     {}
 
     NS_IMETHOD Run() {
         nsSizeModeEvent event(true, NS_SIZEMODE, NULL);
@@ -231,17 +237,18 @@ nsWindow::DoDraw(void)
 
         {
             nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
             gfxUtils::PathFromRegion(ctx, event.region);
             ctx->Clip();
 
             // No double-buffering needed.
             AutoLayerManagerSetup setupLayerManager(
-                gWindowToRedraw, ctx, BasicLayerManager::BUFFER_NONE);
+                gWindowToRedraw, ctx, BasicLayerManager::BUFFER_NONE,
+                ScreenRotation(EffectiveScreenRotation()));
             gWindowToRedraw->mEventCallback(&event);
         }
 
         if (!sUsingOMTC) {
             targetSurface->Flush();
             Framebuffer::Present(event.region);
         }
     } else {
@@ -597,16 +604,22 @@ nsWindow::GetGLFrameBufferFormat()
         mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
         // We directly map the hardware fb on Gonk.  The hardware fb
         // has RGB format.
         return LOCAL_GL_RGB;
     }
     return LOCAL_GL_NONE;
 }
 
+nsIntRect
+nsWindow::GetNaturalBounds()
+{
+    return gScreenBounds;
+}
+
 // nsScreenGonk.cpp
 
 nsScreenGonk::nsScreenGonk(void *nativeScreen)
 {
 }
 
 nsScreenGonk::~nsScreenGonk()
 {
@@ -671,42 +684,26 @@ nsScreenGonk::SetRotation(PRUint32 aRota
 {
     if (!(ROTATION_0_DEG <= aRotation && aRotation <= ROTATION_270_DEG))
         return NS_ERROR_ILLEGAL_VALUE;
 
     if (sScreenRotation == aRotation)
         return NS_OK;
 
     sScreenRotation = aRotation;
-    sRotationMatrix.Reset();
-    switch ((aRotation + sPhysicalScreenRotation) % (360 / 90)) {
-    case nsIScreen::ROTATION_0_DEG:
-        sVirtualBounds = gScreenBounds;
-        break;
-    case nsIScreen::ROTATION_90_DEG:
-        sRotationMatrix.Translate(gfxPoint(gScreenBounds.width, 0));
-        sRotationMatrix.Rotate(M_PI / 2);
+    sRotationMatrix =
+        ComputeGLTransformForRotation(gScreenBounds,
+                                      ScreenRotation(EffectiveScreenRotation()));
+    PRUint32 rotation = EffectiveScreenRotation();
+    if (rotation == nsIScreen::ROTATION_90_DEG ||
+        rotation == nsIScreen::ROTATION_270_DEG) {
         sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height,
-                                         gScreenBounds.width);
-        break;
-    case nsIScreen::ROTATION_180_DEG:
-        sRotationMatrix.Translate(gfxPoint(gScreenBounds.width,
-                                           gScreenBounds.height));
-        sRotationMatrix.Rotate(M_PI);
+                                   gScreenBounds.width);
+    } else {
         sVirtualBounds = gScreenBounds;
-        break;
-    case nsIScreen::ROTATION_270_DEG:
-        sRotationMatrix.Translate(gfxPoint(0, gScreenBounds.height));
-        sRotationMatrix.Rotate(M_PI * 3 / 2);
-        sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height,
-                                         gScreenBounds.width);
-        break;
-    default:
-        MOZ_NOT_REACHED("Unknown rotation");
-        break;
     }
 
     for (unsigned int i = 0; i < sTopWindows.Length(); i++)
         sTopWindows[i]->Resize(sVirtualBounds.width,
                                sVirtualBounds.height,
                                !i);
 
     nsAppShell::NotifyScreenRotation();
--- a/widget/gonk/nsWindow.h
+++ b/widget/gonk/nsWindow.h
@@ -100,16 +100,18 @@ public:
     gfxASurface* GetThebesSurface();
 
     NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
                                       const InputContextAction& aAction);
     NS_IMETHOD_(InputContext) GetInputContext();
 
     virtual PRUint32 GetGLFrameBufferFormat() MOZ_OVERRIDE;
 
+    virtual nsIntRect GetNaturalBounds() MOZ_OVERRIDE;
+
 protected:
     nsWindow* mParent;
     bool mVisible;
     nsIntRegion mDirtyRegion;
     InputContext mInputContext;
     nsCOMPtr<nsIIdleServiceInternal> mIdleService;
 
     void BringToTop();
--- a/widget/nsIBaseWindow.idl
+++ b/widget/nsIBaseWindow.idl
@@ -148,16 +148,27 @@ interface nsIBaseWindow : nsISupports
 	implementations.
 
 	On controls that don't support setting nativeWindow parents, setting this
 	will return a NS_ERROR_NOT_IMPLEMENTED error.
 	*/
 	attribute nativeWindow parentNativeWindow;
 
 	/*
+	This is the handle (HWND, GdkWindow*, ...) to the native window of the
+	control, exposed as a DOMString.
+
+	@return DOMString in hex format with "0x" prepended, or empty string if
+	mainWidget undefined
+
+	@throws NS_ERROR_NOT_IMPLEMENTED for non-XULWindows
+	*/
+	readonly attribute DOMString nativeHandle;
+
+	/*
 	Attribute controls the visibility of the object behind this interface.
 	Setting this attribute to false will hide the control.  Setting it to 
 	true will show it.
 	*/
 	attribute boolean visibility;
 
     /*
     a disabled window should accept no user interaction; it's a dead window,
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -82,18 +82,18 @@ typedef nsEventStatus (* EVENT_CALLBACK)
 #endif
 #ifdef XP_WIN
 #define NS_NATIVE_TSF_THREAD_MGR       100
 #define NS_NATIVE_TSF_CATEGORY_MGR     101
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #endif
 
 #define NS_IWIDGET_IID \
-  { 0x97afe930, 0x72d7, 0x4d95, \
-    { 0x88, 0x5f, 0x37, 0x09, 0x14, 0x2a, 0xf4, 0xe2 } }
+  { 0x91aafae4, 0xd814, 0x4803, \
+    { 0x9a, 0xf5, 0xb0, 0x2f, 0x1b, 0x2c, 0xaf, 0x57 } }
 
 /*
  * Window shadow styles
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
@@ -1565,16 +1565,34 @@ class nsIWidget : public nsISupports {
 
     /**
      * Returns true to indicate that this widget paints an opaque background
      * that we want to be visible under the page, so layout should not force
      * a default background.
      */
     virtual bool WidgetPaintsBackground() { return false; }
 
+    /**
+     * Get the natural bounds of this widget.  This method is only
+     * meaningful for widgets for which Gecko implements screen
+     * rotation natively.  When this is the case, GetBounds() returns
+     * the widget bounds taking rotation into account, and
+     * GetNaturalBounds() returns the bounds *not* taking rotation
+     * into account.
+     *
+     * No code outside of the composition pipeline should know or care
+     * about this.  If you're not an agent of the compositor, you
+     * probably shouldn't call this method.
+     */
+    virtual nsIntRect GetNaturalBounds() {
+        nsIntRect bounds;
+        GetBounds(bounds);
+        return bounds;
+    }
+
 protected:
 
     // keep the list of children.  We also keep track of our siblings.
     // The ownership model is as follows: parent holds a strong ref to
     // the first element of the list, and each element holds a strong
     // ref to the next element in the list.  The prevsibling and
     // lastchild pointers are weak, which is fine as long as they are
     // maintained properly.
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -2,16 +2,18 @@
 /* vim:expandtab:shiftwidth=4:tabstop=4:
  */
 /* 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 "mozilla/Util.h"
 
+#include <QtOpenGL/QGLWidget>
+#include <QtOpenGL/QGLContext>
 #include <QApplication>
 #include <QDesktopWidget>
 #include <QtGui/QCursor>
 #include <QIcon>
 #include <QGraphicsScene>
 #include <QGraphicsView>
 #include <QGraphicsSceneContextMenuEvent>
 #include <QGraphicsSceneDragDropEvent>
@@ -93,18 +95,16 @@ using namespace QtMobility;
 #if MOZ_PLATFORM_MAEMO == 6
 #include <X11/Xatom.h>
 static Atom sPluginIMEAtom = nsnull;
 #define PLUGIN_VKB_REQUEST_PROP "_NPAPI_PLUGIN_REQUEST_VKB"
 #include <QThread>
 #endif
 #endif //MOZ_X11
 
-#include <QtOpenGL/QGLWidget>
-#include <QtOpenGL/QGLContext>
 #define GLdouble_defined 1
 #include "Layers.h"
 #include "LayerManagerOGL.h"
 #include "nsFastStartupQt.h"
 
 // If embedding clients want to create widget without real parent window
 // then nsIBaseWindow->Init() should have parent argument equal to PARENTLESS_WIDGET
 #define PARENTLESS_WIDGET (void*)0x13579
--- a/widget/tests/Makefile.in
+++ b/widget/tests/Makefile.in
@@ -25,16 +25,19 @@ endif
 # Test disabled because it requires the internal API.  Re-enabling this test is
 # bug 652123.
 #CPP_UNIT_TESTS += TestChromeMargin.cpp  \
 #                 $(NULL)
 endif
 
 CPP_UNIT_TESTS += TestAppShellSteadyState.cpp
 
+MOCHITEST_FILES =	test_bug760802.html \
+		$(NULL)
+
 MOCHITEST_CHROME_FILES =	test_bug343416.xul \
 		test_bug429954.xul \
 		window_bug429954.xul \
 		test_bug444800.xul \
 		test_bug462106.xul \
 		test_bug478536.xul \
 		window_bug478536.xul \
 		test_bug517396.xul \
@@ -87,21 +90,21 @@ MOCHITEST_CHROME_FILES  += taskbar_previ
 		taskbar_progress.xul \
 		test_chrome_context_menus_win.xul \
 		test_plugin_input_event.html \
 		chrome_context_menus_win.xul \
 		test_mouse_scroll.xul \
 		window_mouse_scroll_win.html \
 		$(NULL)
 
-MOCHITEST_FILES =	test_bug565392.html \
+MOCHITEST_FILES +=	test_bug565392.html \
 		test_picker_no_crash.html \
 		window_picker_no_crash_child.html \
 		$(NULL)
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
-MOCHITEST_FILES = 	plugin_scroll_invalidation.html \
+MOCHITEST_FILES += 	plugin_scroll_invalidation.html \
 		test_plugin_scroll_invalidation.html \
 		$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/widget/tests/test_bug760802.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=760802
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 760802</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=760802">Mozilla Bug 760802</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<iframe id="iframe_not_editable" width="300" height="150"
+        src="data:text/html,&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;"></iframe><br/>
+<pre id="test">
+<script type="application/javascript">
+
+netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function getBaseWindowInterface(win) {
+  return win.QueryInterface(Ci.nsIInterfaceRequestor)
+    .getInterface(Ci.nsIWebNavigation)
+    .QueryInterface(Ci.nsIDocShellTreeItem)
+    .treeOwner
+    .QueryInterface(Ci.nsIInterfaceRequestor)
+    .nsIBaseWindow;
+}
+
+function shouldThrow(fun) {
+  try {
+    fun.call();
+    return false;
+  } catch (e) {
+    return true;
+  }
+}
+function doesntThrow(fun) !shouldThrow(fun)
+
+
+var baseWindow = getBaseWindowInterface(window);
+var nativeHandle = baseWindow.nativeHandle;
+$("display").innerHTML = "found nativeHandle for this window: "+nativeHandle;
+
+var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
+var win = wm.getMostRecentWindow("navigator:browser");
+var docShell = win.gBrowser.docShell;
+
+ok(
+  shouldThrow(function(){docShell.getInterface(Ci.nsIBaseWindow).nativeHandle;}),
+  "nativeHandle should not be implemented for nsDocShell"
+);
+
+ok(typeof(nativeHandle) === "string", "nativeHandle should be a string");
+ok(nativeHandle.match(/^0x[0-9a-f]+$/), "nativeHandle should have a memory address format");
+
+var iWin = window.document.getElementById("iframe_not_editable").contentWindow;
+is(getBaseWindowInterface(iWin).nativeHandle, nativeHandle,
+              "the nativeHandle of an iframe should be its parent's nativeHandle");
+
+var dialog = window.openDialog("data:text/plain,this is an active window.", "_blank",
+                               "chrome,dialog=yes,width=100,height=100");
+
+isnot(getBaseWindowInterface(dialog).nativeHandle, "",
+      "the nativeHandle of a dialog should not be empty");
+
+dialog.close();
+
+todo(false, "the nativeHandle of a window without a mainWidget should be empty"); // how to build a window without a mainWidget ?
+
+</script>
+</pre>
+</body>
+</html>
--- a/widget/windows/JumpListBuilder.cpp
+++ b/widget/windows/JumpListBuilder.cpp
@@ -19,16 +19,18 @@
 #include "mozilla/Preferences.h"
 #include "imgIContainer.h"
 #include "imgITools.h"
 #include "nsStringStream.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "mozilla/LazyIdleThread.h"
 
+#include "WinUtils.h"
+
 // The amount of time, in milliseconds, that our IO thread will stay alive after the last event it processes.
 #define DEFAULT_THREAD_TIMEOUT_MS 30000
 
 namespace mozilla {
 namespace widget {
 
 static NS_DEFINE_CID(kJumpListItemCID,     NS_WIN_JUMPLISTITEM_CID);
 static NS_DEFINE_CID(kJumpListLinkCID,     NS_WIN_JUMPLISTLINK_CID);
@@ -36,20 +38,16 @@ static NS_DEFINE_CID(kJumpListShortcutCI
 
 // defined in WinTaskbar.cpp
 extern const wchar_t *gMozillaJumpListIDGeneric;
 
 bool JumpListBuilder::sBuildingList = false;
 const char kPrefTaskbarEnabled[] = "browser.taskbar.lists.enabled";
 
 NS_IMPL_ISUPPORTS2(JumpListBuilder, nsIJumpListBuilder, nsIObserver)
-NS_IMPL_ISUPPORTS1(AsyncFaviconDataReady, nsIFaviconDataCallback)
-NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncWriteIconToDisk, nsIRunnable)
-NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteIconFromDisk, nsIRunnable)
-NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteAllFaviconsFromDisk, nsIRunnable)
 
 JumpListBuilder::JumpListBuilder() :
   mMaxItems(0),
   mHasCommit(false)
 {
   ::CoInitialize(NULL);
   
   CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER,
@@ -177,17 +175,17 @@ nsresult JumpListBuilder::RemoveIconCach
           
           // The local file path is stored inside the nsIURI
           // Get the nsIURI spec which stores the local path for the icon to remove
           nsCAutoString spec;
           nsresult rv = uri->GetSpec(spec);
           NS_ENSURE_SUCCESS(rv, rv);
 
           nsCOMPtr<nsIRunnable> event 
-            = new AsyncDeleteIconFromDisk(NS_ConvertUTF8toUTF16(spec));
+            = new mozilla::widget::AsyncDeleteIconFromDisk(NS_ConvertUTF8toUTF16(spec));
           mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
 
           // The shortcut was generated from an IShellLinkW so IShellLinkW can
           // only tell us what the original icon is and not the URI.
           // So this field was used only temporarily as the actual icon file
           // path.  It should be cleared.
           shortcut->SetFaviconPageUri(nsnull);
         }
@@ -202,17 +200,18 @@ nsresult JumpListBuilder::RemoveIconCach
 // Ensures that we have no old ICO files left in the jump list cache
 nsresult JumpListBuilder::RemoveIconCacheForAllItems() 
 {
   // Construct the path of our jump list cache
   nsCOMPtr<nsIFile> jumpListCacheDir;
   nsresult rv = NS_GetSpecialDirectory("ProfLDS", 
                                        getter_AddRefs(jumpListCacheDir));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = jumpListCacheDir->AppendNative(nsDependentCString(JumpListItem::kJumpListCacheDir));
+  rv = jumpListCacheDir->AppendNative(nsDependentCString(
+                         mozilla::widget::FaviconHelper::kJumpListCacheDir));
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsISimpleEnumerator> entries;
   rv = jumpListCacheDir->GetDirectoryEntries(getter_AddRefs(entries));
   NS_ENSURE_SUCCESS(rv, rv);
   
   // Loop through each directory entry and remove all ICO files found
   do {
     bool hasMore = false;
@@ -504,239 +503,19 @@ nsresult JumpListBuilder::TransferIObjec
 NS_IMETHODIMP JumpListBuilder::Observe(nsISupports* aSubject,
                                         const char* aTopic,
                                         const PRUnichar* aData)
 {
   if (nsDependentString(aData).EqualsASCII(kPrefTaskbarEnabled)) {
     bool enabled = Preferences::GetBool(kPrefTaskbarEnabled, true);
     if (!enabled) {
       
-      nsCOMPtr<nsIRunnable> event = new AsyncDeleteAllFaviconsFromDisk();
+      nsCOMPtr<nsIRunnable> event = 
+        new mozilla::widget::AsyncDeleteAllFaviconsFromDisk();
       mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
     }
   }
   return NS_OK;
 }
 
-
-AsyncFaviconDataReady::AsyncFaviconDataReady(nsIURI *aNewURI, 
-                                             nsCOMPtr<nsIThread> &aIOThread) 
-                      : mNewURI(aNewURI), 
-                        mIOThread(aIOThread)
-{
-}
-
-NS_IMETHODIMP
-AsyncFaviconDataReady::OnComplete(nsIURI *aFaviconURI,
-                                  PRUint32 aDataLen,
-                                  const PRUint8 *aData, 
-                                  const nsACString &aMimeType)
-{
-  if (!aDataLen || !aData) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIFile> icoFile;
-  nsresult rv = JumpListShortcut::GetOutputIconPath(mNewURI, icoFile);
-  NS_ENSURE_SUCCESS(rv, rv);
-  nsAutoString path;
-  rv = icoFile->GetPath(path);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Allocate a new buffer that we own and can use out of line in 
-  // another thread.  Copy the favicon raw data into it.
-  const fallible_t fallible = fallible_t();
-  PRUint8 *data = new (fallible) PRUint8[aDataLen];
-  if (!data) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  memcpy(data, aData, aDataLen);
-
-  //AsyncWriteIconToDisk takes ownership of the heap allocated buffer.
-  nsCOMPtr<nsIRunnable> event = new AsyncWriteIconToDisk(path, aMimeType, 
-                                                         data, 
-                                                         aDataLen);
-  mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
-
-  return NS_OK;
-}
-
-// Warning: AsyncWriteIconToDisk assumes ownership of the aData buffer passed in
-AsyncWriteIconToDisk::AsyncWriteIconToDisk(const nsAString &aIconPath,
-                                           const nsACString &aMimeTypeOfInputData,
-                                           PRUint8 *aBuffer, 
-                                           PRUint32 aBufferLength)
-                     : mIconPath(aIconPath),
-                       mMimeTypeOfInputData(aMimeTypeOfInputData),
-                       mBuffer(aBuffer),
-                       mBufferLength(aBufferLength)
-
-{
-}
-
-NS_IMETHODIMP AsyncWriteIconToDisk::Run()
-{
-  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");
-
-  // Convert the obtained favicon data to an input stream
-  nsCOMPtr<nsIInputStream> stream;
-  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
-                                      reinterpret_cast<const char*>(mBuffer.get()), 
-                                      mBufferLength,
-                                      NS_ASSIGNMENT_DEPEND);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Decode the image from the format it was returned to us in (probably PNG)
-  nsCOMPtr<imgIContainer> container;
-  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
-  rv = imgtool->DecodeImageData(stream, mMimeTypeOfInputData, 
-                                getter_AddRefs(container));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Get the recommended icon width and height, or if failure to obtain 
-  // these settings, fall back to 16x16 ICOs.  These values can be different
-  // if the user has a different DPI setting other than 100%.
-  // Windows would scale the 16x16 icon themselves, but it's better
-  // we let our ICO encoder do it.
-  PRInt32 systemIconWidth = GetSystemMetrics(SM_CXSMICON);
-  PRInt32 systemIconHeight = GetSystemMetrics(SM_CYSMICON);
-  if (systemIconWidth == 0 || systemIconHeight == 0) {
-    systemIconWidth = 16;
-    systemIconHeight = 16;
-  }
-  // Scale the image to the needed size and in ICO format
-  mMimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
-  nsCOMPtr<nsIInputStream> iconStream;
-  rv = imgtool->EncodeScaledImage(container, mMimeTypeOfInputData,
-                                  systemIconWidth,
-                                  systemIconHeight,
-                                  EmptyString(),
-                                  getter_AddRefs(iconStream));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIFile> icoFile
-    = do_CreateInstance("@mozilla.org/file/local;1");
-  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
-  rv = icoFile->InitWithPath(mIconPath);
-
-  // Setup the output stream for the ICO file on disk
-  nsCOMPtr<nsIOutputStream> outputStream;
-  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Obtain the ICO buffer size from the re-encoded ICO stream
-  PRUint32 bufSize;
-  rv = iconStream->Available(&bufSize);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Setup a buffered output stream from the stream object
-  // so that we can simply use WriteFrom with the stream object
-  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
-  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
-                                  outputStream, bufSize);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Write out the icon stream to disk and make sure we wrote everything
-  PRUint32 wrote;
-  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
-  NS_ASSERTION(bufSize == wrote, "Icon wrote size should be equal to requested write size");
-
-  // Cleanup
-  bufferedOutputStream->Close();
-  outputStream->Close();
-  return rv;
-}
-
-AsyncWriteIconToDisk::~AsyncWriteIconToDisk()
-{
-}
-
-AsyncDeleteIconFromDisk::AsyncDeleteIconFromDisk(const nsAString &aIconPath)
-                        : mIconPath(aIconPath)
-{
-}
-
-NS_IMETHODIMP AsyncDeleteIconFromDisk::Run()
-{
-  // Construct the parent path of the passed in path
-  nsCOMPtr<nsIFile> icoFile = do_CreateInstance("@mozilla.org/file/local;1");
-  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
-  nsresult rv = icoFile->InitWithPath(mIconPath);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Check if the cached ICO file exists
-  bool exists;
-  rv = icoFile->Exists(&exists);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Check that we aren't deleting some arbitrary file that is not an icon
-  if (StringTail(mIconPath, 4).LowerCaseEqualsASCII(".ico")) {
-    // Check if the cached ICO file exists
-    bool exists;
-    if (NS_FAILED(icoFile->Exists(&exists)) || !exists)
-      return NS_ERROR_FAILURE;
-
-    // We found an ICO file that exists, so we should remove it
-    icoFile->Remove(false);
-  }
-
-  return NS_OK;
-}
-
-AsyncDeleteIconFromDisk::~AsyncDeleteIconFromDisk()
-{
-}
-
-AsyncDeleteAllFaviconsFromDisk::AsyncDeleteAllFaviconsFromDisk()
-{
-}
-
-NS_IMETHODIMP AsyncDeleteAllFaviconsFromDisk::Run()
-{
-  // Construct the path of our jump list cache
-  nsCOMPtr<nsIFile> jumpListCacheDir;
-  nsresult rv = NS_GetSpecialDirectory("ProfLDS", 
-    getter_AddRefs(jumpListCacheDir));
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = jumpListCacheDir->AppendNative(nsDependentCString(JumpListItem::kJumpListCacheDir));
-  NS_ENSURE_SUCCESS(rv, rv);
-  nsCOMPtr<nsISimpleEnumerator> entries;
-  rv = jumpListCacheDir->GetDirectoryEntries(getter_AddRefs(entries));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Loop through each directory entry and remove all ICO files found
-  do {
-    bool hasMore = false;
-    if (NS_FAILED(entries->HasMoreElements(&hasMore)) || !hasMore)
-      break;
-
-    nsCOMPtr<nsISupports> supp;
-    if (NS_FAILED(entries->GetNext(getter_AddRefs(supp))))
-      break;
-
-    nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp));
-    nsAutoString path;
-    if (NS_FAILED(currFile->GetPath(path)))
-      continue;
-
-    PRInt32 len = path.Length();
-    if (StringTail(path, 4).LowerCaseEqualsASCII(".ico")) {
-      // Check if the cached ICO file exists
-      bool exists;
-      if (NS_FAILED(currFile->Exists(&exists)) || !exists)
-        continue;
-
-      // We found an ICO file that exists, so we should remove it
-      currFile->Remove(false);
-    }
-  } while(true);
-
-  return NS_OK;
-}
-
-AsyncDeleteAllFaviconsFromDisk::~AsyncDeleteAllFaviconsFromDisk()
-{
-}
-
-
 } // namespace widget
 } // namespace mozilla
 
--- a/widget/windows/JumpListBuilder.h
+++ b/widget/windows/JumpListBuilder.h
@@ -50,72 +50,13 @@ private:
   bool IsSeparator(nsCOMPtr<nsIJumpListItem>& item);
   nsresult TransferIObjectArrayToIMutableArray(IObjectArray *objArray, nsIMutableArray *removedItems);
   nsresult RemoveIconCacheForItems(nsIMutableArray *removedItems);
   nsresult RemoveIconCacheForAllItems();
 
   friend class WinTaskbar;
 };
 
-
-class AsyncFaviconDataReady MOZ_FINAL : public nsIFaviconDataCallback
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIFAVICONDATACALLBACK
-
-  AsyncFaviconDataReady(nsIURI *aNewURI, nsCOMPtr<nsIThread> &aIOThread);
-private:
-  nsCOMPtr<nsIURI> mNewURI;
-  nsCOMPtr<nsIThread> mIOThread;
-};
-
-/**
-  * Asynchronously tries add the list to the build
-  */
-class AsyncWriteIconToDisk : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  // Warning: AsyncWriteIconToDisk assumes ownership of the aData buffer passed in
-  AsyncWriteIconToDisk(const nsAString &aIconPath,
-                       const nsACString &aMimeTypeOfInputData,
-                       PRUint8 *aData, 
-                       PRUint32 aDataLen);
-  virtual ~AsyncWriteIconToDisk();
-
-private:
-  nsAutoString mIconPath;
-  nsCAutoString mMimeTypeOfInputData;
-  nsAutoArrayPtr<PRUint8> mBuffer;
-  PRUint32 mBufferLength;
-};
-
-class AsyncDeleteIconFromDisk : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  AsyncDeleteIconFromDisk(const nsAString &aIconPath);
-  virtual ~AsyncDeleteIconFromDisk();
-
-private:
-  nsAutoString mIconPath;
-};
-
-class AsyncDeleteAllFaviconsFromDisk : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  AsyncDeleteAllFaviconsFromDisk();
-  virtual ~AsyncDeleteAllFaviconsFromDisk();
-};
-
 } // namespace widget
 } // namespace mozilla
 
 #endif /* __JumpListBuilder_h__ */
 
--- a/widget/windows/JumpListItem.cpp
+++ b/widget/windows/JumpListItem.cpp
@@ -18,18 +18,16 @@
 #include "mozIAsyncFavicons.h"
 #include "mozilla/Preferences.h"
 #include "JumpListBuilder.h"
 #include "WinUtils.h"
 
 namespace mozilla {
 namespace widget {
 
-const char JumpListItem::kJumpListCacheDir[] = "jumpListCache";
-
 // ISUPPORTS Impl's
 NS_IMPL_ISUPPORTS1(JumpListItem,
                    nsIJumpListItem)
 
 NS_IMPL_ISUPPORTS_INHERITED1(JumpListSeparator,
                              JumpListItem,
                              nsIJumpListSeparator)
 
@@ -117,36 +115,36 @@ NS_IMETHODIMP JumpListLink::GetUriTitle(
 }
 
 /* readonly attribute long uriHash; */
 NS_IMETHODIMP JumpListLink::GetUriHash(nsACString& aUriHash)
 {
   if (!mURI)
     return NS_ERROR_NOT_AVAILABLE;
 
-  return JumpListItem::HashURI(mCryptoHash, mURI, aUriHash);
+  return mozilla::widget::FaviconHelper::HashURI(mCryptoHash, mURI, aUriHash);
 }
 
 /* boolean compareHash(in nsIURI uri); */
 NS_IMETHODIMP JumpListLink::CompareHash(nsIURI *aUri, bool *aResult)
 {
   nsresult rv;
 
   if (!mURI) {
     *aResult = !aUri;
     return NS_OK;
   }
 
   NS_ENSURE_ARG_POINTER(aUri);
 
   nsCAutoString hash1, hash2;
 
-  rv = JumpListItem::HashURI(mCryptoHash, mURI, hash1);
+  rv = mozilla::widget::FaviconHelper::HashURI(mCryptoHash, mURI, hash1);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = JumpListItem::HashURI(mCryptoHash, aUri, hash2);
+  rv = mozilla::widget::FaviconHelper::HashURI(mCryptoHash, aUri, hash2);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aResult = hash1.Equals(hash2);
 
   return NS_OK;
 }
 
 /* boolean equals(nsIJumpListItem item); */
@@ -316,145 +314,16 @@ nsresult JumpListSeparator::GetSeparator
 
   PropVariantClear(&pv);
 
   aShellLink = dont_AddRef(psl);
 
   return NS_OK;
 }
 
-// Obtains the jump list 'ICO cache timeout in seconds' pref
-static PRInt32 GetICOCacheSecondsTimeout() {
-
-  // Only obtain the setting at most once from the pref service.
-  // In the rare case that 2 threads call this at the same
-  // time it is no harm and we will simply obtain the pref twice.
-  // None of the taskbar list prefs are currently updated via a
-  // pref observer so I think this should suffice.
-  const PRInt32 kSecondsPerDay = 86400;
-  static bool alreadyObtained = false;
-  static PRInt32 icoReCacheSecondsTimeout = kSecondsPerDay;
-  if (alreadyObtained) {
-    return icoReCacheSecondsTimeout;
-  }
-
-  // Obtain the pref
-  const char PREF_ICOTIMEOUT[]  = "browser.taskbar.lists.icoTimeoutInSeconds";
-  icoReCacheSecondsTimeout = Preferences::GetInt(PREF_ICOTIMEOUT, 
-                                                 kSecondsPerDay);
-  alreadyObtained = true;
-  return icoReCacheSecondsTimeout;
-}
-
-// (static) If the data is available, will return the path on disk where 
-// the favicon for page aFaviconPageURI is stored.  If the favicon does not
-// exist, or its cache is expired, this method will kick off an async request
-// for the icon so that next time the method is called it will be available. 
-nsresult JumpListShortcut::ObtainCachedIconFile(nsCOMPtr<nsIURI> aFaviconPageURI,
-                                                nsString &aICOFilePath,
-                                                nsCOMPtr<nsIThread> &aIOThread)
-{
-  // Obtain the ICO file path
-  nsCOMPtr<nsIFile> icoFile;
-  nsresult rv = GetOutputIconPath(aFaviconPageURI, icoFile);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Check if the cached ICO file already exists
-  bool exists;
-  rv = icoFile->Exists(&exists);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (exists) {
-
-    // Obtain the file's last modification date in seconds
-    PRInt64 fileModTime = LL_ZERO;
-    rv = icoFile->GetLastModifiedTime(&fileModTime);
-    fileModTime /= PR_MSEC_PER_SEC;
-    PRInt32 icoReCacheSecondsTimeout = GetICOCacheSecondsTimeout();
-    PRInt64 nowTime = PR_Now() / PRInt64(PR_USEC_PER_SEC);
-
-    // If the last mod call failed or the icon is old then re-cache it
-    // This check is in case the favicon of a page changes
-    // the next time we try to build the jump list, the data will be available.
-    if (NS_FAILED(rv) ||
-        (nowTime - fileModTime) > icoReCacheSecondsTimeout) {
-      CacheIconFileFromFaviconURIAsync(aFaviconPageURI, icoFile, aIOThread);
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-  } else {
-
-    // The file does not exist yet, obtain it async from the favicon service so that
-    // the next time we try to build the jump list it'll be available.
-    CacheIconFileFromFaviconURIAsync(aFaviconPageURI, icoFile, aIOThread);
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // The icoFile is filled with a path that exists, get its path
-  rv = icoFile->GetPath(aICOFilePath);
-  return rv;
-}
-
-// (static) Obtains the ICO file for the favicon at page aFaviconPageURI
-// If successful, the file path on disk is in the format:
-// <ProfLDS>\jumpListCache\<hash(aFaviconPageURI)>.ico
-nsresult JumpListShortcut::GetOutputIconPath(nsCOMPtr<nsIURI> aFaviconPageURI,
-                                             nsCOMPtr<nsIFile> &aICOFile) 
-{
-  // Hash the input URI and replace any / with _
-  nsCAutoString inputURIHash;
-  nsCOMPtr<nsICryptoHash> cryptoHash;
-  nsresult rv = JumpListItem::HashURI(cryptoHash, aFaviconPageURI,
-                                      inputURIHash);
-  NS_ENSURE_SUCCESS(rv, rv);
-  char* cur = inputURIHash.BeginWriting();
-  char* end = inputURIHash.EndWriting();
-  for (; cur < end; ++cur) {
-    if ('/' == *cur) {
-      *cur = '_';
-    }
-  }
-
-  // Obtain the local profile directory and construct the output icon file path
-  rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(aICOFile));
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = aICOFile->AppendNative(nsDependentCString(JumpListItem::kJumpListCacheDir));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Try to create the directory if it's not there yet
-  rv = aICOFile->Create(nsIFile::DIRECTORY_TYPE, 0777);
-  if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
-    return rv;
-  }
-  
-  // Append the icon extension
-  inputURIHash.Append(".ico");
-  rv = aICOFile->AppendNative(inputURIHash);
-
-  return rv;
-}
-
-// (static) Asynchronously creates a cached ICO file on disk for the favicon of
-// page aFaviconPageURI and stores it to disk at the path of aICOFile.
-nsresult 
-JumpListShortcut::CacheIconFileFromFaviconURIAsync(nsCOMPtr<nsIURI> aFaviconPageURI,
-                                                   nsCOMPtr<nsIFile> aICOFile,
-                                                   nsCOMPtr<nsIThread> &aIOThread)
-{
-  // Obtain the favicon service and get the favicon for the specified page
-  nsCOMPtr<mozIAsyncFavicons> favIconSvc(
-                      do_GetService("@mozilla.org/browser/favicon-service;1"));
-  NS_ENSURE_TRUE(favIconSvc, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIFaviconDataCallback> callback = 
-    new AsyncFaviconDataReady(aFaviconPageURI, aIOThread);
-
-  favIconSvc->GetFaviconDataForPage(aFaviconPageURI, callback);
-  return NS_OK;
-}
-
 // (static) Creates a ShellLink that encapsulate a shortcut to local apps.
 nsresult JumpListShortcut::GetShellLink(nsCOMPtr<nsIJumpListItem>& item, 
                                         nsRefPtr<IShellLinkW>& aShellLink,
                                         nsCOMPtr<nsIThread> &aIOThread)
 {
   HRESULT hr;
   IShellLinkW* psl;
   nsresult rv;
@@ -539,17 +408,20 @@ nsresult JumpListShortcut::GetShellLink(
 
   // Store the rest of the params
   psl->SetPath(appPath.get());
   psl->SetDescription(appDescription.get());
   psl->SetArguments(appArgs.get());
 
   if (useUriIcon) {
     nsString icoFilePath;
-    rv = ObtainCachedIconFile(iconUri, icoFilePath, aIOThread);
+    rv = mozilla::widget::FaviconHelper::ObtainCachedIconFile(iconUri, 
+                                                              icoFilePath, 
+                                                              aIOThread,
+                                                              false);
     if (NS_SUCCEEDED(rv)) {
       // Always use the first icon in the ICO file
       // our encoded icon only has 1 resource
       psl->SetIconLocation(icoFilePath.get(), 0);
       usedUriIcon = true;
     }
   }
 
@@ -572,17 +444,17 @@ static nsresult IsPathInOurIconCache(nsC
   NS_ENSURE_ARG_POINTER(aSame);
  
   *aSame = false;
 
   // Construct the path of our jump list cache
   nsCOMPtr<nsIFile> jumpListCache;
   nsresult rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(jumpListCache));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = jumpListCache->AppendNative(nsDependentCString(JumpListItem::kJumpListCacheDir));
+  rv = jumpListCache->AppendNative(nsDependentCString(FaviconHelper::kJumpListCacheDir));
   NS_ENSURE_SUCCESS(rv, rv);
   nsAutoString jumpListCachePath;
   rv = jumpListCache->GetPath(jumpListCachePath);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Construct the parent path of the passed in path
   nsCOMPtr<nsIFile> passedInFile = do_CreateInstance("@mozilla.org/file/local;1");
   NS_ENSURE_TRUE(passedInFile, NS_ERROR_FAILURE);
@@ -767,38 +639,11 @@ bool JumpListShortcut::ExecutableExists(
   if (NS_SUCCEEDED(rv) && executable) {
     bool exists;
     executable->Exists(&exists);
     return exists;
   }
   return false;
 }
 
-// (static) Helper method which will hash a URI
-nsresult JumpListItem::HashURI(nsCOMPtr<nsICryptoHash> &aCryptoHash, 
-                               nsIURI *aUri, nsACString& aUriHash)
-{
-  if (!aUri)
-    return NS_ERROR_INVALID_ARG;
-
-  nsCAutoString spec;
-  nsresult rv = aUri->GetSpec(spec);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (!aCryptoHash) {
-    aCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  rv = aCryptoHash->Init(nsICryptoHash::MD5);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = aCryptoHash->Update(reinterpret_cast<const PRUint8*>(spec.BeginReading()), 
-                                                            spec.Length());
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = aCryptoHash->Finish(true, aUriHash);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
 } // namespace widget
 } // namespace mozilla
 
--- a/widget/windows/JumpListItem.h
+++ b/widget/windows/JumpListItem.h
@@ -43,18 +43,16 @@ public:
   NS_DECL_NSIJUMPLISTITEM
 
   static const char kJumpListCacheDir[];
 
 protected:
   short Type() { return mItemType; }
   short mItemType;
 
-  static nsresult HashURI(nsCOMPtr<nsICryptoHash> &aCryptoHash,
-                          nsIURI *aUri, nsACString& aUriHash);
 };
 
 class JumpListSeparator : public JumpListItem, public nsIJumpListSeparator
 {
 public:
   JumpListSeparator() :
    JumpListItem(nsIJumpListItem::JUMPLIST_ITEM_SEPARATOR)
   {}
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -6,19 +6,44 @@
 
 #include "WinUtils.h"
 #include "nsWindow.h"
 #include "nsWindowDefs.h"
 #include "nsGUIEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "mozilla/Preferences.h"
 
+#include "nsString.h"
+#include "nsDirectoryServiceUtils.h"
+#include "imgIContainer.h"
+#include "imgITools.h"
+#include "nsStringStream.h"
+#include "nsNetUtil.h"
+#include "mozIAsyncFavicons.h"
+ 
+#include "nsIIconURI.h"
+#include "nsIDownloader.h"
+#include "nsINetUtil.h"
+#include "nsIChannel.h"
+#include "nsIObserver.h"
+#include "imgIEncoder.h"
+
 namespace mozilla {
 namespace widget {
 
+  NS_IMPL_ISUPPORTS1(myDownloadObserver, nsIDownloadObserver)
+  NS_IMPL_ISUPPORTS1(AsyncFaviconDataReady, nsIFaviconDataCallback)
+  NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncWriteIconToDisk, nsIRunnable)
+  NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteIconFromDisk, nsIRunnable)
+  NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteAllFaviconsFromDisk, nsIRunnable)
+
+
+  const char FaviconHelper::kJumpListCacheDir[] = "jumpListCache";
+  const char FaviconHelper::kShortcutCacheDir[] = "shortcutCache";
+
 // SHCreateItemFromParsingName is only available on vista and up.
 WinUtils::SHCreateItemFromParsingNamePtr WinUtils::sCreateItemFromParsingName = nsnull;
 
 /* static */ 
 WinUtils::WinVersion
 WinUtils::GetWindowsVersion()
 {
   static PRInt32 version = 0;
@@ -362,16 +387,508 @@ HRESULT
 WinUtils::SHCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc,
                                       REFIID riid, void **ppv)
 {
   if (!VistaCreateItemFromParsingNameInit())
     return E_FAIL;
   return sCreateItemFromParsingName(pszPath, pbc, riid, ppv);
 }
 
+/************************************************************************/
+/* Constructs as AsyncFaviconDataReady Object
+/* @param aIOThread : the thread which performs the action
+/* @param aURLShortcut : Differentiates between (false)Jumplistcache and (true)Shortcutcache
+/************************************************************************/
+
+AsyncFaviconDataReady::AsyncFaviconDataReady(nsIURI *aNewURI, 
+                                             nsCOMPtr<nsIThread> &aIOThread, 
+                                             const bool aURLShortcut):
+  mNewURI(aNewURI),
+  mIOThread(aIOThread),
+  mURLShortcut(aURLShortcut)
+{
+}
+
+NS_IMETHODIMP
+myDownloadObserver::OnDownloadComplete(nsIDownloader *downloader, 
+                                     nsIRequest *request, 
+                                     nsISupports *ctxt, 
+                                     nsresult status, 
+                                     nsIFile *result)
+{
+  return NS_OK;
+}
+
+
+nsresult AsyncFaviconDataReady::OnFaviconDataNotAvailable(void)
+{
+  if (!mURLShortcut) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIFile> icoFile;
+  nsresult rv = FaviconHelper::GetOutputIconPath(mNewURI, icoFile, mURLShortcut);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURI> mozIconURI;
+  rv = NS_NewURI(getter_AddRefs(mozIconURI), "moz-icon://.html?size=32");
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+ 
+  nsCOMPtr<nsIChannel> channel;
+  rv = NS_NewChannel(getter_AddRefs(channel), mozIconURI);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<myDownloadObserver> downloadObserver = new myDownloadObserver;
+  nsCOMPtr<nsIStreamListener> listener;
+  rv = NS_NewDownloader(getter_AddRefs(listener), downloadObserver, icoFile);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  channel->AsyncOpen(listener, NULL);
+  return NS_OK;
+}
+
+
+
+NS_IMETHODIMP
+AsyncFaviconDataReady::OnComplete(nsIURI *aFaviconURI,
+                                  PRUint32 aDataLen,
+                                  const PRUint8 *aData, 
+                                  const nsACString &aMimeType)
+{
+  if (!aDataLen || !aData) {
+    if (mURLShortcut) {
+      OnFaviconDataNotAvailable();
+    }
+    
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIFile> icoFile;
+  nsresult rv = FaviconHelper::GetOutputIconPath(mNewURI, icoFile, mURLShortcut);
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  nsAutoString path;
+  rv = icoFile->GetPath(path);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Allocate a new buffer that we own and can use out of line in 
+  // another thread.  Copy the favicon raw data into it.
+  const fallible_t fallible = fallible_t();
+  PRUint8 *data = new (fallible) PRUint8[aDataLen];
+  if (!data) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  memcpy(data, aData, aDataLen);
+
+  //AsyncWriteIconToDisk takes ownership of the heap allocated buffer.
+  nsCOMPtr<nsIRunnable> event = new AsyncWriteIconToDisk(path, aMimeType, 
+                                                         data, 
+                                                         aDataLen,
+                                                         mURLShortcut);
+  mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
+
+  return NS_OK;
+}
+
+// Warning: AsyncWriteIconToDisk assumes ownership of the aData buffer passed in
+AsyncWriteIconToDisk::AsyncWriteIconToDisk(const nsAString &aIconPath,
+                                           const nsACString &aMimeTypeOfInputData,
+                                           PRUint8 *aBuffer, 
+                                           PRUint32 aBufferLength,
+                                           const bool aURLShortcut): 
+  mIconPath(aIconPath),
+  mMimeTypeOfInputData(aMimeTypeOfInputData),
+  mBuffer(aBuffer),
+  mBufferLength(aBufferLength),
+  mURLShortcut(aURLShortcut)
+
+{
+}
+
+NS_IMETHODIMP AsyncWriteIconToDisk::Run()
+{
+  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");
+
+  // Convert the obtained favicon data to an input stream
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = 
+    NS_NewByteInputStream(getter_AddRefs(stream),
+                          reinterpret_cast<const char*>(mBuffer.get()),
+                          mBufferLength,
+                          NS_ASSIGNMENT_DEPEND);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Decode the image from the format it was returned to us in (probably PNG)
+  nsCOMPtr<imgIContainer> container;
+  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
+  rv = imgtool->DecodeImageData(stream, mMimeTypeOfInputData, 
+                                getter_AddRefs(container));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Get the recommended icon width and height, or if failure to obtain 
+  // these settings, fall back to 16x16 ICOs.  These values can be different
+  // if the user has a different DPI setting other than 100%.
+  // Windows would scale the 16x16 icon themselves, but it's better
+  // we let our ICO encoder do it.
+  nsCOMPtr<nsIInputStream> iconStream;
+  if (!mURLShortcut) {
+    PRInt32 systemIconWidth = GetSystemMetrics(SM_CXSMICON);
+    PRInt32 systemIconHeight = GetSystemMetrics(SM_CYSMICON);
+    if ((systemIconWidth == 0 || systemIconHeight == 0)) {
+      systemIconWidth = 16;
+      systemIconHeight = 16;
+    }
+    // Scale the image to the needed size and in ICO format
+    mMimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
+    rv = imgtool->EncodeScaledImage(container, mMimeTypeOfInputData,
+                                    systemIconWidth,
+                                    systemIconHeight,
+                                    EmptyString(),
+                                    getter_AddRefs(iconStream));
+    } else {
+      nsRefPtr<gfxASurface> s;
+      rv = container->GetFrame(imgIContainer::FRAME_FIRST, 0, getter_AddRefs(s));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      gfxImageSurface* surface =
+        new gfxImageSurface(gfxIntSize(48, 48),
+                            gfxImageSurface::ImageFormatARGB32);
+      gfxContext context(surface);
+      context.SetOperator(gfxContext::OPERATOR_SOURCE);
+      context.SetColor(gfxRGBA(1, 1, 1, 1));
+      context.Rectangle(gfxRect(0, 0, 48, 48));
+      context.Fill();
+
+      context.Translate(gfxPoint(16, 16));
+      context.SetOperator(gfxContext::OPERATOR_OVER);
+      context.DrawSurface(s,  gfxSize(16, 16));
+      gfxIntSize size = surface->GetSize();
+
+      nsRefPtr<imgIEncoder> encoder = 
+        do_CreateInstance("@mozilla.org/image/encoder;2?"
+                          "type=image/vnd.microsoft.icon");
+      NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
+      rv = encoder->InitFromData(surface->Data(), surface->Stride() * size.height,
+                            size.width, size.height, surface->Stride(),
+                            imgIEncoder::INPUT_FORMAT_HOSTARGB, EmptyString());
+      NS_ENSURE_SUCCESS(rv, rv);
+      CallQueryInterface(encoder.get(), getter_AddRefs(iconStream));
+      if (!iconStream) {
+        return NS_ERROR_FAILURE;
+      }
+  }
+
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIFile> icoFile
+    = do_CreateInstance("@mozilla.org/file/local;1");
+  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
+  rv = icoFile->InitWithPath(mIconPath);
+
+  // Setup the output stream for the ICO file on disk
+  nsCOMPtr<nsIOutputStream> outputStream;
+  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Obtain the ICO buffer size from the re-encoded ICO stream
+  PRUint32 bufSize;
+  rv = iconStream->Available(&bufSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Setup a buffered output stream from the stream object
+  // so that we can simply use WriteFrom with the stream object
+  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
+  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
+                                  outputStream, bufSize);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Write out the icon stream to disk and make sure we wrote everything
+  PRUint32 wrote;
+  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
+  NS_ASSERTION(bufSize == wrote, 
+              "Icon wrote size should be equal to requested write size");
+
+  // Cleanup
+  bufferedOutputStream->Close();
+  outputStream->Close();
+  if (mURLShortcut) {
+    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);
+  }
+  return rv;
+}
+
+AsyncWriteIconToDisk::~AsyncWriteIconToDisk()
+{
+}
+
+AsyncDeleteIconFromDisk::AsyncDeleteIconFromDisk(const nsAString &aIconPath)
+  : mIconPath(aIconPath)
+{
+}
+
+NS_IMETHODIMP AsyncDeleteIconFromDisk::Run()
+{
+  // Construct the parent path of the passed in path
+  nsCOMPtr<nsIFile> icoFile = do_CreateInstance("@mozilla.org/file/local;1");
+  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
+  nsresult rv = icoFile->InitWithPath(mIconPath);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check if the cached ICO file exists
+  bool exists;
+  rv = icoFile->Exists(&exists);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check that we aren't deleting some arbitrary file that is not an icon
+  if (StringTail(mIconPath, 4).LowerCaseEqualsASCII(".ico")) {
+    // Check if the cached ICO file exists
+    bool exists;
+    if (NS_FAILED(icoFile->Exists(&exists)) || !exists)
+      return NS_ERROR_FAILURE;
+
+    // We found an ICO file that exists, so we should remove it
+    icoFile->Remove(false);
+  }
+
+  return NS_OK;
+}
+
+AsyncDeleteIconFromDisk::~AsyncDeleteIconFromDisk()
+{
+}
+
+AsyncDeleteAllFaviconsFromDisk::AsyncDeleteAllFaviconsFromDisk()
+{
+}
+
+NS_IMETHODIMP AsyncDeleteAllFaviconsFromDisk::Run()
+{
+  // Construct the path of our jump list cache
+  nsCOMPtr<nsIFile> jumpListCacheDir;
+  nsresult rv = NS_GetSpecialDirectory("ProfLDS", 
+    getter_AddRefs(jumpListCacheDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = jumpListCacheDir->AppendNative(
+      nsDependentCString(FaviconHelper::kJumpListCacheDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsISimpleEnumerator> entries;
+  rv = jumpListCacheDir->GetDirectoryEntries(getter_AddRefs(entries));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Loop through each directory entry and remove all ICO files found
+  do {
+    bool hasMore = false;
+    if (NS_FAILED(entries->HasMoreElements(&hasMore)) || !hasMore)
+      break;
+
+    nsCOMPtr<nsISupports> supp;
+    if (NS_FAILED(entries->GetNext(getter_AddRefs(supp))))
+      break;
+
+    nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp));
+    nsAutoString path;
+    if (NS_FAILED(currFile->GetPath(path)))
+      continue;
+
+    PRInt32 len = path.Length();
+    if (StringTail(path, 4).LowerCaseEqualsASCII(".ico")) {
+      // Check if the cached ICO file exists
+      bool exists;
+      if (NS_FAILED(currFile->Exists(&exists)) || !exists)
+        continue;
+
+      // We found an ICO file that exists, so we should remove it
+      currFile->Remove(false);
+    }
+  } while(true);
+
+  return NS_OK;
+}
+
+AsyncDeleteAllFaviconsFromDisk::~AsyncDeleteAllFaviconsFromDisk()
+{
+}
+
+
+/*
+ * (static) If the data is available, will return the path on disk where 
+ * the favicon for page aFaviconPageURI is stored.  If the favicon does not
+ * exist, or its cache is expired, this method will kick off an async request
+ * for the icon so that next time the method is called it will be available. 
+ * @param aFaviconPageURI The URI of the page to obtain
+ * @param aICOFilePath The path of the icon file
+ * @param aIOThread The thread to perform the Fetch on
+ * @param aURLShortcut to distinguish between jumplistcache(false) and shortcutcache(true)
+ */
+nsresult FaviconHelper::ObtainCachedIconFile(nsCOMPtr<nsIURI> aFaviconPageURI,
+                                             nsString &aICOFilePath,
+                                             nsCOMPtr<nsIThread> &aIOThread,
+                                             bool aURLShortcut)
+{
+  // Obtain the ICO file path
+  nsCOMPtr<nsIFile> icoFile;
+  nsresult rv = GetOutputIconPath(aFaviconPageURI, icoFile, aURLShortcut);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Check if the cached ICO file already exists
+  bool exists;
+  rv = icoFile->Exists(&exists);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (exists) {
+
+    // Obtain the file's last modification date in seconds
+    PRInt64 fileModTime = LL_ZERO;
+    rv = icoFile->GetLastModifiedTime(&fileModTime);
+    fileModTime /= PR_MSEC_PER_SEC;
+    PRInt32 icoReCacheSecondsTimeout = GetICOCacheSecondsTimeout();
+    PRInt64 nowTime = PR_Now() / PRInt64(PR_USEC_PER_SEC);
+
+    // If the last mod call failed or the icon is old then re-cache it
+    // This check is in case the favicon of a page changes
+    // the next time we try to build the jump list, the data will be available.
+    if (NS_FAILED(rv) ||
+        (nowTime - fileModTime) > icoReCacheSecondsTimeout) {
+        CacheIconFileFromFaviconURIAsync(aFaviconPageURI, icoFile, aIOThread, aURLShortcut);
+        return NS_ERROR_NOT_AVAILABLE;
+    }
+  } else {
+
+    // The file does not exist yet, obtain it async from the favicon service so that
+    // the next time we try to build the jump list it'll be available.
+    CacheIconFileFromFaviconURIAsync(aFaviconPageURI, icoFile, aIOThread, aURLShortcut);
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  // The icoFile is filled with a path that exists, get its path
+  rv = icoFile->GetPath(aICOFilePath);
+  return rv;
+}
+
+nsresult FaviconHelper::HashURI(nsCOMPtr<nsICryptoHash> &aCryptoHash, 
+                                nsIURI *aUri, 
+                                nsACString& aUriHash)
+{
+  if (!aUri)
+    return NS_ERROR_INVALID_ARG;
+
+  nsCAutoString spec;
+  nsresult rv = aUri->GetSpec(spec);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!aCryptoHash) {
+    aCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  rv = aCryptoHash->Init(nsICryptoHash::MD5);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = aCryptoHash->Update(reinterpret_cast<const PRUint8*>(spec.BeginReading()), 
+                           spec.Length());
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = aCryptoHash->Finish(true, aUriHash);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+
+
+// (static) Obtains the ICO file for the favicon at page aFaviconPageURI
+// If successful, the file path on disk is in the format:
+// <ProfLDS>\jumpListCache\<hash(aFaviconPageURI)>.ico
+nsresult FaviconHelper::GetOutputIconPath(nsCOMPtr<nsIURI> aFaviconPageURI,
+  nsCOMPtr<nsIFile> &aICOFile,
+  bool aURLShortcut)
+{
+  // Hash the input URI and replace any / with _
+  nsCAutoString inputURIHash;
+  nsCOMPtr<nsICryptoHash> cryptoHash;
+  nsresult rv = HashURI(cryptoHash, aFaviconPageURI,
+                        inputURIHash);
+  NS_ENSURE_SUCCESS(rv, rv);
+  char* cur = inputURIHash.BeginWriting();
+  char* end = inputURIHash.EndWriting();
+  for (; cur < end; ++cur) {
+    if ('/' == *cur) {
+      *cur = '_';
+    }
+  }
+
+  // Obtain the local profile directory and construct the output icon file path
+  rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(aICOFile));
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!aURLShortcut)
+    rv = aICOFile->AppendNative(nsDependentCString(kJumpListCacheDir));
+  else
+    rv = aICOFile->AppendNative(nsDependentCString(kShortcutCacheDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Try to create the directory if it's not there yet
+  rv = aICOFile->Create(nsIFile::DIRECTORY_TYPE, 0777);
+  if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
+    return rv;
+  }
+
+  // Append the icon extension
+  inputURIHash.Append(".ico");
+  rv = aICOFile->AppendNative(inputURIHash);
+
+  return rv;
+}
+
+// (static) Asynchronously creates a cached ICO file on disk for the favicon of
+// page aFaviconPageURI and stores it to disk at the path of aICOFile.
+nsresult 
+  FaviconHelper::CacheIconFileFromFaviconURIAsync(nsCOMPtr<nsIURI> aFaviconPageURI,
+                                                  nsCOMPtr<nsIFile> aICOFile,
+                                                  nsCOMPtr<nsIThread> &aIOThread,
+                                                  bool aURLShortcut)
+{
+  // Obtain the favicon service and get the favicon for the specified page
+  nsCOMPtr<mozIAsyncFavicons> favIconSvc(
+    do_GetService("@mozilla.org/browser/favicon-service;1"));
+  NS_ENSURE_TRUE(favIconSvc, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsIFaviconDataCallback> callback = 
+    new mozilla::widget::AsyncFaviconDataReady(aFaviconPageURI, 
+                                               aIOThread, 
+                                               aURLShortcut);
+
+  favIconSvc->GetFaviconDataForPage(aFaviconPageURI, callback);
+  return NS_OK;
+}
+
+// Obtains the jump list 'ICO cache timeout in seconds' pref
+PRInt32 FaviconHelper::GetICOCacheSecondsTimeout() {
+
+  // Only obtain the setting at most once from the pref service.
+  // In the rare case that 2 threads call this at the same
+  // time it is no harm and we will simply obtain the pref twice.
+  // None of the taskbar list prefs are currently updated via a
+  // pref observer so I think this should suffice.
+  const PRInt32 kSecondsPerDay = 86400;
+  static bool alreadyObtained = false;
+  static PRInt32 icoReCacheSecondsTimeout = kSecondsPerDay;
+  if (alreadyObtained) {
+    return icoReCacheSecondsTimeout;
+  }
+
+  // Obtain the pref
+  const char PREF_ICOTIMEOUT[]  = "browser.taskbar.lists.icoTimeoutInSeconds";
+  icoReCacheSecondsTimeout = Preferences::GetInt(PREF_ICOTIMEOUT, 
+                                                 kSecondsPerDay);
+  alreadyObtained = true;
+  return icoReCacheSecondsTimeout;
+}
+
+
+
+
 /* static */
 bool
 WinUtils::GetShellItemPath(IShellItem* aItem,
                            nsString& aResultString)
 {
   NS_ENSURE_TRUE(aItem, false);
   LPWSTR str = NULL;
   if (FAILED(aItem->GetDisplayName(SIGDN_FILESYSPATH, &str)))
--- a/widget/windows/WinUtils.h
+++ b/widget/windows/WinUtils.h
@@ -7,21 +7,34 @@
 #define mozilla_widget_WinUtils_h__
 
 #include "nscore.h"
 #include <windows.h>
 #include <shobjidl.h>
 #include "nsAutoPtr.h"
 #include "nsString.h"
 
+#include "nsThreadUtils.h"
+#include "nsICryptoHash.h"
+#include "nsIFaviconService.h" 
+#include "nsIDownloader.h"
+
+
 class nsWindow;
 
 namespace mozilla {
 namespace widget {
 
+class myDownloadObserver: public nsIDownloadObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOWNLOADOBSERVER
+};
+
 class WinUtils {
 public:
   enum WinVersion {
     WINXP_VERSION     = 0x501,
     WIN2K3_VERSION    = 0x502,
     VISTA_VERSION     = 0x600,
     // WIN2K8_VERSION    = VISTA_VERSION,
     WIN7_VERSION      = 0x601
@@ -198,12 +211,105 @@ private:
   /**
    * VistaCreateItemFromParsingNameInit() initializes the static pointer for
    * SHCreateItemFromParsingName() API which is usable only on Vista and later.
    * This returns TRUE if the API is available.  Otherwise, FALSE.
    */
   static bool VistaCreateItemFromParsingNameInit();
 };
 
+class AsyncFaviconDataReady : public nsIFaviconDataCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIFAVICONDATACALLBACK
+  
+  AsyncFaviconDataReady(nsIURI *aNewURI, 
+                        nsCOMPtr<nsIThread> &aIOThread, 
+                        const bool aURLShortcut);
+  nsresult OnFaviconDataNotAvailable(void);
+private:
+  nsCOMPtr<nsIURI> mNewURI;