Merge mozilla-central into mozilla-inbound; a=merge
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 23 Apr 2012 18:55:55 -0400
changeset 95482 2e95132e00d38d10d2da388b7980de4bd5c6c418
parent 95458 8acbbeca4f425d99614b981847a5a004516cdb49 (current diff)
parent 95481 834a69fbceb9dfc0c135905b876d72ebf8ec0837 (diff)
child 95483 dd7040d1f8b956a9cedcd0915aef125a5b479285
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone14.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 mozilla-central into mozilla-inbound; a=merge
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -8033,28 +8033,34 @@ var gIdentityHandler = {
     delete this._overrideService;
     return this._overrideService = Cc["@mozilla.org/security/certoverride;1"]
                                      .getService(Ci.nsICertOverrideService);
   },
   get _identityIconCountryLabel () {
     delete this._identityIconCountryLabel;
     return this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
   },
+  get _identityIcon () {
+    delete this._identityIcon;
+    return this._identityIcon = document.getElementById("page-proxy-favicon");
+  },
 
   /**
    * Rebuild cache of the elements that may or may not exist depending
    * on whether there's a location bar.
    */
   _cacheElements : function() {
     delete this._identityBox;
     delete this._identityIconLabel;
     delete this._identityIconCountryLabel;
+    delete this._identityIcon;
     this._identityBox = document.getElementById("identity-box");
     this._identityIconLabel = document.getElementById("identity-icon-label");
     this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
+    this._identityIcon = document.getElementById("page-proxy-favicon");
   },
 
   /**
    * Handler for mouseclicks on the "More Information" button in the
    * "identity-popup" panel.
    */
   handleMoreInfoClick : function(event) {
     displaySecurityInfo();
@@ -8349,17 +8355,17 @@ var gIdentityHandler = {
     this._identityBox.setAttribute("open", "true");
     var self = this;
     this._identityPopup.addEventListener("popuphidden", function onPopupHidden(e) {
       e.currentTarget.removeEventListener("popuphidden", onPopupHidden, false);
       self._identityBox.removeAttribute("open");
     }, false);
 
     // Now open the popup, anchored off the primary chrome element
-    this._identityPopup.openPopup(this._identityBox, "bottomcenter topleft");
+    this._identityPopup.openPopup(this._identityIcon, "bottomcenter topleft");
   },
 
   onPopupShown : function(event) {
     let openingDuration = new Date() - this._popupOpenTime;
     this._popupOpenTime = null;
     try {
       Services.telemetry.getHistogramById("FX_IDENTITY_POPUP_OPEN_MS").add(openingDuration);
     } catch (ex) {
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -13,17 +13,16 @@ Cu.import("resource:///modules/Migration
 
 var MigrationWizard = {
   _source: "",                  // Source Profile Migrator ContractID suffix
   _itemsFlags: kIMig.ALL,       // Selected Import Data Sources (16-bit bitfield)
   _selectedProfile: null,       // Selected Profile name to import from
   _wiz: null,
   _migrator: null,
   _autoMigrate: null,
-  _bookmarks: false,
 
   init: function ()
   {
     var os = Components.classes["@mozilla.org/observer-service;1"]
                        .getService(Components.interfaces.nsIObserverService);
     os.addObserver(this, "Migration:Started", false);
     os.addObserver(this, "Migration:ItemBeforeMigrate", false);
     os.addObserver(this, "Migration:ItemAfterMigrate", false);
@@ -59,44 +58,25 @@ var MigrationWizard = {
     os.removeObserver(this, "Migration:ItemError");
     os.removeObserver(this, "Migration:Ended");
     MigrationUtils.finishMigration();
   },
 
   // 1 - Import Source
   onImportSourcePageShow: function ()
   {
-    // Reference to the "From File" radio button 
-    var fromfile = null;
-
-    // init is not called when openDialog opens the wizard, so check for bookmarks here.
-    if ("arguments" in window && window.arguments[0] == "bookmarks") {
-      this._bookmarks = true;
-
-      fromfile = document.getElementById("fromfile");
-      fromfile.hidden = false;
-
-      var importBookmarks = document.getElementById("importBookmarks");
-      importBookmarks.hidden = false;
-
-      var importAll = document.getElementById("importAll");
-      importAll.hidden = true;
-    }
-
     this._wiz.canRewind = false;
 
-    // The migrator to select. If the "fromfile" migrator is available, use it
-    // as the default in case we have no other migrators.
-    var selectedMigrator = fromfile;
+    var selectedMigrator = null;
 
     // Figure out what source apps are are available to import from:
     var group = document.getElementById("importSourceGroup");
     for (var i = 0; i < group.childNodes.length; ++i) {
       var migratorKey = group.childNodes[i].id;
-      if (migratorKey != "nothing" && migratorKey != "fromfile") {
+      if (migratorKey != "nothing") {
         var migrator = MigrationUtils.getMigrator(migratorKey);
         if (migrator) {
           // Save this as the first selectable item, if we don't already have
           // one, or if it is the migrator that was passed to us.
           if (!selectedMigrator || this._source == migratorKey)
             selectedMigrator = group.childNodes[i];
         } else {
           // Hide this option
@@ -123,19 +103,17 @@ var MigrationWizard = {
       this._wiz.canRewind = false;
     }
   },
   
   onImportSourcePageAdvanced: function ()
   {
     var newSource = document.getElementById("importSourceGroup").selectedItem.id;
     
-    if (newSource == "nothing" || newSource == "fromfile") {
-      if(newSource == "fromfile")
-        window.opener.fromFile = true;
+    if (newSource == "nothing") {
       document.documentElement.cancel();
       return false;
     }
     
     if (!this._migrator || (newSource != this._source)) {
       // Create the migrator for the selected source.
       this._migrator = MigrationUtils.getMigrator(newSource);
 
@@ -147,18 +125,16 @@ var MigrationWizard = {
     // check for more than one source profile
     var sourceProfiles = this._migrator.sourceProfiles;    
     if (sourceProfiles && sourceProfiles.length > 1) {
       this._wiz.currentPage.next = "selectProfile";
     }
     else {
       if (this._autoMigrate)
         this._wiz.currentPage.next = "homePageImport";
-      else if (this._bookmarks)
-        this._wiz.currentPage.next = "migrating"
       else
         this._wiz.currentPage.next = "importItems";
 
       if (sourceProfiles && sourceProfiles.length == 1)
         this._selectedProfile = sourceProfiles[0];
       else
         this._selectedProfile = "";
     }
@@ -200,18 +176,16 @@ var MigrationWizard = {
   onSelectProfilePageAdvanced: function ()
   {
     var profiles = document.getElementById("profiles");
     this._selectedProfile = profiles.selectedItem.id;
     
     // If we're automigrating or just doing bookmarks don't show the item selection page
     if (this._autoMigrate)
       this._wiz.currentPage.next = "homePageImport";
-    else if (this._bookmarks)
-      this._wiz.currentPage.next = "migrating"
   },
   
   // 3 - ImportItems
   onImportItemsPageShow: function ()
   {
     var dataSources = document.getElementById("dataSources");
     while (dataSources.hasChildNodes())
       dataSources.removeChild(dataSources.firstChild);
@@ -347,20 +321,16 @@ var MigrationWizard = {
     this._wiz.getButton("cancel").disabled = true;
     this._wiz.canRewind = false;
     this._wiz.canAdvance = false;
     
     // When automigrating, show all of the data that can be received from this source.
     if (this._autoMigrate)
       this._itemsFlags = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
 
-    // When importing bookmarks, show only bookmarks
-    if (this._bookmarks)
-      this._itemsFlags = 32;
-
     this._listItems("migratingItems");
     setTimeout(this.onMigratingMigrate, 0, this);
   },
 
   onMigratingMigrate: function (aOuter)
   {
     aOuter._migrator.migrate(aOuter._itemsFlags, aOuter._autoMigrate, aOuter._selectedProfile);
   },
--- a/browser/components/migration/content/migration.xul
+++ b/browser/components/migration/content/migration.xul
@@ -66,17 +66,16 @@
     <radiogroup id="importSourceGroup" align="start">
       <!-- If you are adding a migrator, please add the appropriate
            hooks to GetDefaultBrowserMigratorKey in
            browser/components/migration/src/nsProfileMigrator.cpp -->
       <radio id="safari"    label="&importFromSafari.label;"    accesskey="&importFromSafari.accesskey;"/>
       <radio id="ie"        label="&importFromIE.label;"        accesskey="&importFromIE.accesskey;"/>
       <radio id="chrome"    label="&importFromChrome.label;"    accesskey="&importFromChrome.accesskey;"/>
       <radio id="firefox"   label="&importFromFirefox.label;"   accesskey="&importFromFirefox.accesskey;"/>
-      <radio id="fromfile"  label="&importFromHTMLFile.label;"  accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
       <radio id="nothing"   label="&importFromNothing.label;"   accesskey="&importFromNothing.accesskey;" hidden="true"/>
     </radiogroup>
     <label id="noSources" hidden="true">&noMigrationSources.label;</label>
   </wizardpage>
 
   <wizardpage id="selectProfile" pageid="selectProfile" label="&selectProfile.title;"
               next="importItems"
               onpageshow="return MigrationWizard.onSelectProfilePageShow();"
--- a/browser/locales/en-US/chrome/browser/migration/migration.dtd
+++ b/browser/locales/en-US/chrome/browser/migration/migration.dtd
@@ -10,18 +10,16 @@
 <!ENTITY importFromNothing.label        "Don't import anything">
 <!ENTITY importFromNothing.accesskey    "D">
 <!ENTITY importFromSafari.label         "Safari">
 <!ENTITY importFromSafari.accesskey     "S">
 <!ENTITY importFromChrome.label         "Chrome">
 <!ENTITY importFromChrome.accesskey     "C">
 <!ENTITY importFromFirefox.label        "Firefox">
 <!ENTITY importFromFirefox.accesskey    "X">
-<!ENTITY importFromHTMLFile.label       "From an HTML File">
-<!ENTITY importFromHTMLFile.accesskey   "F">
 
 <!ENTITY noMigrationSources.label       "No programs that contain bookmarks, history or password data could be found.">
 
 <!ENTITY importSource.title             "Import Settings and Data">
 <!ENTITY importItems.title              "Items to Import">
 <!ENTITY importItems.label              "Select which items to import:">
 
 <!ENTITY migrating.title                "Importing…">
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/743499-negative-size.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+    <title></title>
+    <script type="text/javascript">
+        function go() {
+        var canvas = document.createElement("canvas");
+        var ctx = canvas.getContext('2d');
+        ctx.globalAlpha = 4
+        ctx.lineCap = "foo"
+        ctx.strokeRect(256,1024,8,4)
+        ctx.shadowColor = "black"
+        ctx.shadowOffsetY = 64
+        ctx.stroke()
+        ctx.moveTo(32,1024)
+        ctx.closePath()
+        }
+    </script>
+</head>
+<body onload="go()">
+<canvas id="canvas"></canvas>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/745818-large-source.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+function boom()
+{
+  var a = document.getElementById("a");
+  var b = document.getElementById("b");
+  a.getContext('2d').createPattern(b, 'no-repeat');
+}
+
+</script>
+</head>
+
+<body onload="boom();">
+<canvas id="a" width="61" height="26"></canvas>
+<canvas id="b" width="611" height="439807"></canvas>
+</body>
+
+</html>
--- a/content/canvas/crashtests/crashtests.list
+++ b/content/canvas/crashtests/crashtests.list
@@ -1,8 +1,11 @@
 load 360293-1.html
 load 421715-1.html
 load 553938-1.html
 load 647480.html
 load 0px-size-font-667225.html
 load texImage2D.html
 load 729116.html
 load 745699-1.html
+# this test crashes in a bunch places still
+#load 745818-large-source.html
+load 743499-negative-size.html
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -1968,17 +1968,17 @@ nsCanvasRenderingContext2DAzure::CreateP
     nsLayoutUtils::SurfaceFromElement(content->AsElement(),
       nsLayoutUtils::SFE_WANT_FIRST_FRAME | nsLayoutUtils::SFE_WANT_NEW_SURFACE);
 
   if (!res.mSurface) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // Ignore nsnull cairo surfaces! See bug 666312.
-  if (!res.mSurface->CairoSurface()) {
+  if (!res.mSurface->CairoSurface() || res.mSurface->CairoStatus()) {
     return NS_OK;
   }
 
   RefPtr<SourceSurface> srcSurf =
     gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
 
   nsRefPtr<nsCanvasPatternAzure> pat =
     new nsCanvasPatternAzure(srcSurf, repeatMode, res.mPrincipal,
--- a/dom/base/StructuredCloneTags.h
+++ b/dom/base/StructuredCloneTags.h
@@ -39,18 +39,24 @@
 
 #include "jsapi.h"
 
 namespace mozilla {
 namespace dom {
 
 enum StructuredCloneTags {
   SCTAG_BASE = JS_SCTAG_USER_MIN,
+
+  // These tags are used only for main thread structured clone.
   SCTAG_DOM_BLOB,
   SCTAG_DOM_FILE,
   SCTAG_DOM_FILELIST,
+
+  // These tags are used for both main thread and workers.
+  SCTAG_DOM_IMAGEDATA,
+
   SCTAG_DOM_MAX
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // StructuredCloneTags_h__
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -81,16 +81,18 @@
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsDOMScriptObjectHolder.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
+#include "StructuredCloneTags.h"
+#include "mozilla/dom/ImageData.h"
 
 #include "nsJSPrincipals.h"
 
 #ifdef XP_MACOSX
 // AssertMacros.h defines 'check' and conflicts with AccessCheck.h
 #undef check
 #endif
 #include "AccessCheck.h"
@@ -108,16 +110,17 @@
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/bindings/Utils.h"
 
 #include "sampler.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 const size_t gStackSize = 8192;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gJSDiagnostics;
 #endif
 
 // Thank you Microsoft!
@@ -3605,28 +3608,80 @@ SetMemoryGCSliceTimePrefChangedCallback(
 
 JSObject*
 NS_DOMReadStructuredClone(JSContext* cx,
                           JSStructuredCloneReader* reader,
                           uint32_t tag,
                           uint32_t data,
                           void* closure)
 {
-  // We don't currently support any extensions to structured cloning.
+  if (tag == SCTAG_DOM_IMAGEDATA) {
+    // Read the information out of the stream.
+    uint32_t width, height;
+    JS::Value dataArray;
+    if (!JS_ReadUint32Pair(reader, &width, &height) ||
+        !JS_ReadTypedArray(reader, &dataArray)) {
+      return nsnull;
+    }
+    MOZ_ASSERT(dataArray.isObject());
+
+    // Construct the ImageData.
+    nsCOMPtr<nsIDOMImageData> imageData = new ImageData(width, height,
+                                                        dataArray.toObject());
+    // Wrap it in a jsval.
+    JSObject* global = JS_GetGlobalForScopeChain(cx);
+    if (!global) {
+      return nsnull;
+    }
+    nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
+    JS::Value val;
+    nsresult rv =
+      nsContentUtils::WrapNative(cx, global, imageData, &val,
+                                 getter_AddRefs(wrapper));
+    if (NS_FAILED(rv)) {
+      return nsnull;
+    }
+    return val.toObjectOrNull();
+  }
+
+  // Don't know what this is. Bail.
   nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return nsnull;
 }
 
 JSBool
 NS_DOMWriteStructuredClone(JSContext* cx,
                            JSStructuredCloneWriter* writer,
                            JSObject* obj,
                            void *closure)
 {
-  // We don't currently support any extensions to structured cloning.
+  nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
+  nsContentUtils::XPConnect()->
+    GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
+  nsISupports *native = wrappedNative ? wrappedNative->Native() : nsnull;
+
+  nsCOMPtr<nsIDOMImageData> imageData = do_QueryInterface(native);
+  if (imageData) {
+    // Prepare the ImageData internals.
+    PRUint32 width, height;
+    JS::Value dataArray;
+    if (NS_FAILED(imageData->GetWidth(&width)) ||
+        NS_FAILED(imageData->GetHeight(&height)) ||
+        NS_FAILED(imageData->GetData(cx, &dataArray)))
+    {
+      return false;
+    }
+
+    // Write the internals to the stream.
+    return JS_WriteUint32Pair(writer, SCTAG_DOM_IMAGEDATA, 0) &&
+           JS_WriteUint32Pair(writer, width, height) &&
+           JS_WriteTypedArray(writer, dataArray);
+  }
+
+  // Don't know what this is. Bail.
   nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return JS_FALSE;
 }
 
 void
 NS_DOMStructuredCloneError(JSContext* cx,
                            uint32_t errorid)
 {
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -152,12 +152,15 @@ include $(topsrcdir)/config/rules.mk
 		iframe_bug304459-2.html \
 		test_bug38959.html \
 		iframe_bug38959-1.html \
 		iframe_bug38959-2.html \
 		test_onerror_message.html \
 		test_bug735237.html \
 		test_bug739038.html \
 		test_bug740811.html \
+		test_bug743615.html \
+		utils_bug743615.js \
+		worker_bug743615.js \
 		$(NULL)
 
 libs:: 	$(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug743615.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=743615
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 743615</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="utils_bug743615.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=743615">Mozilla Bug 743615</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<canvas id="c" width="200" height="200"><canvas>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for structured cloning ImageData. **/
+
+SimpleTest.waitForExplicitFinish();
+window.addEventListener('message', windowMessage);
+startTest();
+
+function startTest() {
+  // Make an ImageData.
+  var ctx = document.getElementById('c').getContext('2d');
+  ctx.fillStyle = 'rgb(';
+  ctx.fillRect(30, 30, 50, 50);
+
+  // Make a blank ImageData.
+  var imageData = ctx.createImageData(200, 200);
+  is(imageData.data.length, imageData.width * imageData.height * 4,
+   'right size for data');
+
+  // Write some things into it.
+  var pattern = makePattern(imageData.data.length, 42, 7);
+  setPattern(imageData, pattern);
+  ok(checkPattern(imageData, pattern), 'Can read it back before sending');
+
+  // PostMessage it to ourselves.
+  window.postMessage({ imageData: imageData,
+                       pattern: pattern,
+                       dataRef: imageData.data }, '*');
+}
+
+function windowMessage(evt) {
+  // Check the pattern we received.
+  var imageData = evt.data.imageData;
+  var pattern = evt.data.pattern;
+  ok(checkPattern(imageData, pattern),
+     'postMessage from self worked correctly');
+
+  // We're not spec compliant on this yet.
+  todo_is(imageData.data, evt.data.dataRef,
+          'Should have backrefs for imagedata buffer');
+
+  // Make a new pattern, and send it to a worker.
+  pattern = makePattern(imageData.data.length, 4, 3);
+  setPattern(imageData, pattern);
+  var worker = new Worker('worker_bug743615.js');
+  worker.onmessage = workerMessage;
+  worker.postMessage( {imageData: imageData, pattern: pattern });
+}
+
+function workerMessage(evt) {
+  // Relay the results of the worker-side tests.
+  is(evt.data.statusMessage, 'PASS', evt.data.statusMessage);
+
+  // Test what the worker sent us.
+  ok(checkPattern(evt.data.imageData, evt.data.pattern),
+     'postMessage from worker worked correctly');
+
+  // All done.
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/utils_bug743615.js
@@ -0,0 +1,25 @@
+function makePattern(len, start, inc) {
+  var pattern = [];
+  while(len) {
+    pattern.push(start);
+    start = (start + inc) % 256;
+    --len;
+  }
+  return pattern;
+}
+
+function setPattern(imageData, pattern) {
+  if (pattern.length != imageData.data.length)
+    throw Error('Invalid pattern');
+  for (var i = 0; i < pattern.length; ++i)
+    imageData.data[i] = pattern[i];
+}
+
+function checkPattern(imageData, pattern) {
+  if (pattern.length != imageData.data.length)
+    throw Error('Invalid pattern');
+  for (var i = 0; i < pattern.length; ++i)
+    if (imageData.data[i] != pattern[i])
+      return false;
+  return true;
+}
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/worker_bug743615.js
@@ -0,0 +1,38 @@
+importScripts('utils_bug743615.js');
+
+self.onmessage = function onMessage(evt) {
+  // Check the pattern that was sent.
+  var imageData = evt.data.imageData;
+  var pattern = evt.data.pattern;
+  var statusMessage = checkPattern(imageData, pattern)
+                       ? 'PASS' : 'Got corrupt typed array in worker';
+
+  // Check against the interface object.
+  if (!(imageData instanceof ImageData))
+    statusMessage += ", Bad interface object in worker";
+
+  // Check the getters.
+  if (imageData.width * imageData.height != imageData.data.length / 4) {
+    statusMessage += ", Bad ImageData getters in worker: "
+    statusMessage += [imageData.width, imageData.height].join(', ');
+  }
+
+  // Make sure that writing to .data is a no-op when not in strict mode.
+  var origData = imageData.data;
+  var threw = false;
+  try {
+    imageData.data = [];
+    imageData.width = 2;
+    imageData.height = 2;
+  } catch(e) { threw = true; }
+  if (threw || imageData.data !== origData)
+    statusMessage = statusMessage + ", Should silently ignore sets";
+
+
+
+  // Send back a new pattern.
+  pattern = makePattern(imageData.data.length, 99, 2);
+  setPattern(imageData, pattern);
+  self.postMessage({ statusMessage: statusMessage, imageData: imageData,
+                     pattern: pattern });
+}
new file mode 100644
--- /dev/null
+++ b/dom/workers/ImageData.cpp
@@ -0,0 +1,203 @@
+/* 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 "ImageData.h"
+
+#include "jsfriendapi.h"
+#include "jstypedarray.h"
+
+#include "nsTraceRefcnt.h"
+
+#define PROPERTY_FLAGS \
+  (JSPROP_ENUMERATE | JSPROP_SHARED)
+
+USING_WORKERS_NAMESPACE
+
+namespace {
+
+class ImageData
+{
+  static JSClass sClass;
+  static JSPropertySpec sProperties[];
+
+  enum SLOT {
+    SLOT_width = 0,
+    SLOT_height,
+    SLOT_data,
+
+    SLOT_COUNT
+  };
+
+public:
+  static JSObject*
+  InitClass(JSContext* aCx, JSObject* aObj)
+  {
+    return JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0, sProperties,
+                        NULL, NULL, NULL);
+  }
+
+  static JSObject*
+  Create(JSContext* aCx, uint32_t aWidth, uint32_t aHeight, JSObject *aData)
+  {
+    MOZ_ASSERT(aData);
+    MOZ_ASSERT(js_IsTypedArray(aData));
+    MOZ_ASSERT(JS_GetTypedArrayType(aData) == js::TypedArray::TYPE_UINT8_CLAMPED);
+
+    JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
+    if (!obj) {
+      return NULL;
+    }
+
+    JS_SetReservedSlot(obj, SLOT_width, UINT_TO_JSVAL(aWidth));
+    JS_SetReservedSlot(obj, SLOT_height, UINT_TO_JSVAL(aHeight));
+    JS_SetReservedSlot(obj, SLOT_data, OBJECT_TO_JSVAL(aData));
+
+    // This is an empty object. The point is just to differentiate instances
+    // from the interface object.
+    ImageData* priv = new ImageData();
+    JS_SetPrivate(obj, priv);
+
+    return obj;
+  }
+
+  static bool
+  IsInstance(JSObject* aObj)
+  {
+    return JS_GetClass(aObj) == &sClass;
+  }
+
+  static uint32_t
+  GetWidth(JSObject* aObj)
+  {
+    MOZ_ASSERT(IsInstance(aObj));
+    return JS_DoubleToUint32(JS_GetReservedSlot(aObj, SLOT_width).toNumber());
+  }
+
+  static uint32_t
+  GetHeight(JSObject* aObj)
+  {
+    MOZ_ASSERT(IsInstance(aObj));
+    return JS_DoubleToUint32(JS_GetReservedSlot(aObj, SLOT_height).toNumber());
+  }
+
+  static
+  JSObject* GetData(JSObject* aObj)
+  {
+    MOZ_ASSERT(IsInstance(aObj));
+    return &JS_GetReservedSlot(aObj, SLOT_data).toObject();
+  }
+
+private:
+  ImageData()
+  {
+    MOZ_COUNT_CTOR(mozilla::dom::workers::ImageData);
+  }
+
+  ~ImageData()
+  {
+    MOZ_COUNT_DTOR(mozilla::dom::workers::ImageData);
+  }
+
+  static JSBool
+  Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
+  {
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
+                         sClass.name);
+    return false;
+  }
+
+  static void
+  Finalize(JSFreeOp* aFop, JSObject* aObj)
+  {
+    MOZ_ASSERT(JS_GetClass(aObj) == &sClass);
+    delete static_cast<ImageData*>(JS_GetPrivate(aObj));
+  }
+
+  static JSBool
+  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  {
+    JSClass* classPtr = JS_GetClass(aObj);
+    if (classPtr != &sClass) {
+      JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+                           JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
+                           classPtr->name);
+      return false;
+    }
+
+    MOZ_ASSERT(JSID_IS_INT(aIdval));
+    MOZ_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < SLOT_COUNT);
+
+    *aVp = JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval));
+    return true;
+  }
+};
+
+JSClass ImageData::sClass = {
+  "ImageData",
+  JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
+  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
+};
+
+JSPropertySpec ImageData::sProperties[] = {
+  // These properties are read-only per spec, which means that sets must throw
+  // in strict mode and silently fail otherwise. This is a problem for workers
+  // in general (because js_GetterOnlyPropertyStub throws unconditionally). The
+  // general plan for fixing this involves the new DOM bindings. But Peace
+  // Keeper breaks if we throw when setting these properties, so we need to do
+  // something about it in the mean time. So we use NULL, which defaults to the
+  // class setter (JS_StrictPropertyStub), which is always a silent no-op,
+  // regardless of strict mode. Not ideal, but good enough for now.
+  { "width", SLOT_width, PROPERTY_FLAGS, GetProperty, NULL },
+  { "height", SLOT_height, PROPERTY_FLAGS, GetProperty, NULL },
+  { "data", SLOT_data, PROPERTY_FLAGS, GetProperty, NULL },
+  { 0, 0, 0, NULL, NULL }
+};
+
+} // anonymous namespace
+
+BEGIN_WORKERS_NAMESPACE
+
+namespace imagedata {
+
+bool
+InitClass(JSContext* aCx, JSObject* aGlobal)
+{
+  return !!ImageData::InitClass(aCx, aGlobal);
+}
+
+JSObject*
+Create(JSContext* aCx, uint32_t aWidth, uint32_t aHeight, JSObject* aData)
+{
+  return ImageData::Create(aCx, aWidth, aHeight, aData);
+}
+
+bool
+IsImageData(JSObject* aObj)
+{
+  return ImageData::IsInstance(aObj);
+}
+
+uint32_t
+GetWidth(JSObject* aObj)
+{
+  return ImageData::GetWidth(aObj);
+}
+
+uint32_t
+GetHeight(JSObject* aObj)
+{
+  return ImageData::GetHeight(aObj);
+}
+
+JSObject*
+GetData(JSObject* aObj)
+{
+  return ImageData::GetData(aObj);
+}
+
+
+} // namespace imagedata
+
+END_WORKERS_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/workers/ImageData.h
@@ -0,0 +1,41 @@
+/* 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_dom_workers_imagedata_h__
+#define mozilla_dom_workers_imagedata_h__
+
+#include "Workers.h"
+
+BEGIN_WORKERS_NAMESPACE
+
+namespace imagedata {
+
+bool
+InitClass(JSContext* aCx, JSObject* aGlobal);
+
+JSObject*
+Create(JSContext* aCx, uint32_t aWidth, uint32_t aHeight, JSObject* aData);
+
+/*
+ * All data members live in private slots on the JS Object. Callers must
+ * first check IsImageData, after which they may call the data accessors.
+ */
+
+bool
+IsImageData(JSObject* aObj);
+
+uint32_t
+GetWidth(JSObject* aObj);
+
+uint32_t
+GetHeight(JSObject* aObj);
+
+JSObject*
+GetData(JSObject* aObj);
+
+} // namespace imagedata
+
+END_WORKERS_NAMESPACE
+
+#endif // mozilla_dom_workers_imagedata_h__
--- a/dom/workers/Makefile.in
+++ b/dom/workers/Makefile.in
@@ -19,16 +19,17 @@ CPPSRCS = \
   DOMBindingBase.cpp \
   Events.cpp \
   EventListenerManager.cpp \
   EventTarget.cpp \
   Exceptions.cpp \
   File.cpp \
   FileReaderSync.cpp \
   FileReaderSyncPrivate.cpp \
+  ImageData.cpp \
   Location.cpp \
   Navigator.cpp \
   Principal.cpp \
   RuntimeService.cpp \
   ScriptLoader.cpp \
   Worker.cpp \
   WorkerPrivate.cpp \
   WorkerScope.cpp \
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -74,16 +74,17 @@
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 #include "Events.h"
 #include "Exceptions.h"
 #include "File.h"
+#include "ImageData.h"
 #include "Principal.h"
 #include "RuntimeService.h"
 #include "ScriptLoader.h"
 #include "Worker.h"
 #include "WorkerFeature.h"
 #include "WorkerScope.h"
 
 #if 0 // Define to run GC more often.
@@ -98,16 +99,17 @@
 
 using mozilla::MutexAutoLock;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
 
 USING_WORKERS_NAMESPACE
 using namespace mozilla::dom::workers::events;
+using namespace mozilla::dom;
 
 namespace {
 
 const char gErrorChars[] = "error";
 const char gMessageChars[] = "message";
 
 template <class T>
 class AutoPtrComparator
@@ -328,16 +330,35 @@ struct WorkerStructuredCloneCallbacks
 #endif
 
         // nsIDOMBlob should be threadsafe, thus we will use the same instance
         // in the worker.
         JSObject* jsBlob = file::CreateBlob(aCx, blob);
         return jsBlob;
       }
     }
+    // See if the object is an ImageData.
+    else if (aTag == SCTAG_DOM_IMAGEDATA) {
+      JS_ASSERT(!aData);
+
+      // Read the information out of the stream.
+      uint32_t width, height;
+      jsval dataArray;
+      if (!JS_ReadUint32Pair(aReader, &width, &height) ||
+          !JS_ReadTypedArray(aReader, &dataArray))
+      {
+        return nsnull;
+      }
+      MOZ_ASSERT(dataArray.isObject());
+
+      // Construct the ImageData.
+      JSObject* obj = imagedata::Create(aCx, width, height,
+                                        JSVAL_TO_OBJECT(dataArray));
+      return obj;
+    }
 
     Error(aCx, 0);
     return nsnull;
   }
 
   static JSBool
   Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, JSObject* aObj,
         void* aClosure)
@@ -369,16 +390,29 @@ struct WorkerStructuredCloneCallbacks
             JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0) &&
             JS_WriteBytes(aWriter, &blob, sizeof(blob))) {
           clonedObjects->AppendElement(blob);
           return true;
         }
       }
     }
 
+    // See if this is an ImageData object.
+    if (imagedata::IsImageData(aObj)) {
+      // Pull the properties off the object.
+      uint32_t width = imagedata::GetWidth(aObj);
+      uint32_t height = imagedata::GetHeight(aObj);
+      JSObject* data = imagedata::GetData(aObj);
+
+      // Write the structured clone.
+      return JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEDATA, 0) &&
+             JS_WriteUint32Pair(aWriter, width, height) &&
+             JS_WriteTypedArray(aWriter, OBJECT_TO_JSVAL(data));
+    }
+
     Error(aCx, 0);
     return false;
   }
 
   static void
   Error(JSContext* aCx, uint32_t /* aErrorId */)
   {
     ThrowDOMExceptionForCode(aCx, DATA_CLONE_ERR);
@@ -461,22 +495,16 @@ struct MainThreadWorkerStructuredCloneCa
           Error(aCx, DATA_CLONE_ERR);
           return nsnull;
         }
 
         return JSVAL_TO_OBJECT(wrappedBlob);
       }
     }
 
-    JSObject* clone =
-      WorkerStructuredCloneCallbacks::Read(aCx, aReader, aTag, aData, aClosure);
-    if (clone) {
-      return clone;
-    }
-
     JS_ClearPendingException(aCx);
     return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nsnull);
   }
 
   static JSBool
   Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, JSObject* aObj,
         void* aClosure)
   {
@@ -522,22 +550,16 @@ struct MainThreadWorkerStructuredCloneCa
               JS_WriteBytes(aWriter, &blobPtr, sizeof(blobPtr))) {
             clonedObjects->AppendElement(blob);
             return true;
           }
         }
       }
     }
 
-    JSBool ok =
-      WorkerStructuredCloneCallbacks::Write(aCx, aWriter, aObj, aClosure);
-    if (ok) {
-      return ok;
-    }
-
     JS_ClearPendingException(aCx);
     return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nsnull);
   }
 
   static void
   Error(JSContext* aCx, uint32_t aErrorId)
   {
     AssertIsOnMainThread();
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -50,16 +50,17 @@
 #include "mozilla/Mutex.h"
 #include "mozilla/TimeStamp.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsEventQueue.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsTPriorityQueue.h"
+#include "StructuredCloneTags.h"
 
 #include "EventTarget.h"
 #include "Queue.h"
 #include "WorkerFeature.h"
 
 class JSAutoStructuredCloneBuffer;
 class nsIDocument;
 class nsIPrincipal;
@@ -807,17 +808,17 @@ private:
   ProcessAllControlRunnables();
 };
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx);
 
 enum WorkerStructuredDataType
 {
-  DOMWORKER_SCTAG_FILE = JS_SCTAG_USER_MIN + 0x1000,
+  DOMWORKER_SCTAG_FILE = SCTAG_DOM_MAX,
   DOMWORKER_SCTAG_BLOB,
 
   DOMWORKER_SCTAG_END
 };
 
 JSStructuredCloneCallbacks*
 WorkerStructuredCloneCallbacks(bool aMainRuntime);
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -57,16 +57,17 @@
 #include "ChromeWorkerScope.h"
 #include "Events.h"
 #include "EventListenerManager.h"
 #include "EventTarget.h"
 #include "Exceptions.h"
 #include "File.h"
 #include "FileReaderSync.h"
 #include "Location.h"
+#include "ImageData.h"
 #include "Navigator.h"
 #include "Principal.h"
 #include "ScriptLoader.h"
 #include "Worker.h"
 #include "WorkerPrivate.h"
 #include "XMLHttpRequest.h"
 
 #include "WorkerInlines.h"
@@ -991,16 +992,17 @@ CreateDedicatedWorkerGlobalScope(JSConte
   }
 
   // Init other classes we care about.
   if (!events::InitClasses(aCx, global, false) ||
       !file::InitClasses(aCx, global) ||
       !filereadersync::InitClass(aCx, global) ||
       !exceptions::InitClasses(aCx, global) ||
       !location::InitClass(aCx, global) ||
+      !imagedata::InitClass(aCx, global) ||
       !navigator::InitClass(aCx, global)) {
     return NULL;
   }
 
   // Init other paris-bindings.
   if (!XMLHttpRequest_workers::CreateInterfaceObjects(aCx, global) ||
       !XMLHttpRequestUpload_workers::CreateInterfaceObjects(aCx, global)) {
     return NULL;
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -868,17 +868,17 @@ DrawTargetCG::Init(CGContextRef cgContex
   return true;
 }
 
 bool
 DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
 {
   // XXX: we should come up with some consistent semantics for dealing
   // with zero area drawtargets
-  if (aSize.width == 0 || aSize.height == 0 ||
+  if (aSize.width <= 0 || aSize.height <= 0 ||
       // 32767 is the maximum size supported by cairo
       // we clamp to that to make it easier to interoperate
       aSize.width > 32767 || aSize.height > 32767) {
     mColorSpace = NULL;
     mCg = NULL;
     mData = NULL;
     return false;
   }
--- a/gfx/ots/src/ots.cc
+++ b/gfx/ots/src/ots.cc
@@ -78,17 +78,22 @@ struct Arena {
   }
 
  private:
   std::vector<uint8_t*> hunks_;
 };
 
 // Use a macro instead of a function because gcc 4.4.3 creates static
 // initializers in that case. Note this macro assumes a little-endian system.
+#if defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN)
+// This is the big-endian equivalent.
+#define TAG(d, c, b, a) (a | (b << 8) | (c << 16) | (d << 24))
+#else
 #define TAG(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))
+#endif
 
 const struct {
   uint32_t tag;
   bool (*parse)(ots::OpenTypeFile *otf, const uint8_t *data, size_t length);
   bool (*serialise)(ots::OTSStream *out, ots::OpenTypeFile *file);
   bool (*should_serialise)(ots::OpenTypeFile *file);
   void (*free)(ots::OpenTypeFile *file);
   bool required;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5179,21 +5179,27 @@ JS_SetStructuredCloneCallbacks(JSRuntime
 
 JS_PUBLIC_API(JSBool)
 JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2);
 
 JS_PUBLIC_API(JSBool)
 JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len);
 
 JS_PUBLIC_API(JSBool)
+JS_ReadTypedArray(JSStructuredCloneReader *r, jsval *vp);
+
+JS_PUBLIC_API(JSBool)
 JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data);
 
 JS_PUBLIC_API(JSBool)
 JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len);
 
+JS_PUBLIC_API(JSBool)
+JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v);
+
 /************************************************************************/
 
 /*
  * Locale specific string conversion and error message callbacks.
  */
 struct JSLocaleCallbacks {
     JSLocaleToUpperCase     localeToUpperCase;
     JSLocaleToLowerCase     localeToLowerCase;
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -419,16 +419,23 @@ JSStructuredCloneWriter::checkStack()
         JS_ASSERT(total <= ids.length());
 
     size_t j = objs.length();
     for (size_t i = 0; i < limit; i++)
         JS_ASSERT(memory.has(&objs[--j].toObject()));
 #endif
 }
 
+JS_PUBLIC_API(JSBool)
+JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v)
+{
+    JS_ASSERT(v.isObject());
+    return w->writeTypedArray(&v.toObject());
+}
+
 bool
 JSStructuredCloneWriter::writeTypedArray(JSObject *obj)
 {
     JSObject *arr = TypedArray::getTypedArray(obj);
     if (!out.writePair(ArrayTypeToTag(TypedArray::getType(arr)), TypedArray::getLength(arr)))
         return false;
 
     switch (TypedArray::getType(arr)) {
@@ -684,16 +691,26 @@ JSStructuredCloneReader::readString(uint
     if (!chars.allocate(nchars) || !in.readChars(chars.get(), nchars))
         return NULL;
     JSString *str = js_NewString(context(), chars.get(), nchars);
     if (str)
         chars.forget();
     return str;
 }
 
+JS_PUBLIC_API(JSBool)
+JS_ReadTypedArray(JSStructuredCloneReader *r, jsval *vp)
+{
+    uint32_t tag, nelems;
+    if (!r->input().readPair(&tag, &nelems))
+        return false;
+    JS_ASSERT(tag >= SCTAG_TYPED_ARRAY_MIN && tag <= SCTAG_TYPED_ARRAY_MAX);
+    return r->readTypedArray(tag, nelems, vp);
+}
+
 bool
 JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp)
 {
     JSObject *obj = NULL;
 
     switch (tag) {
       case SCTAG_TYPED_ARRAY_INT8:
         obj = JS_NewInt8Array(context(), nelems);
--- a/js/src/jsclone.h
+++ b/js/src/jsclone.h
@@ -138,16 +138,18 @@ struct JSStructuredCloneReader {
     // Stack of all objects read during this deserialization
     js::AutoValueVector allObjs;
 
     // The user defined callbacks that will be used for cloning.
     const JSStructuredCloneCallbacks *callbacks;
 
     // Any value passed to JS_ReadStructuredClone.
     void *closure;
+
+    friend JSBool JS_ReadTypedArray(JSStructuredCloneReader *r, jsval *vp);
 };
 
 struct JSStructuredCloneWriter {
   public:
     explicit JSStructuredCloneWriter(js::SCOutput &out, const JSStructuredCloneCallbacks *cb,
                                      void *cbClosure)
         : out(out), objs(out.context()), counts(out.context()), ids(out.context()),
           memory(out.context()), callbacks(cb), closure(cbClosure) { }
@@ -191,11 +193,13 @@ struct JSStructuredCloneWriter {
     typedef js::HashMap<JSObject *, uint32_t> CloneMemory;
     CloneMemory memory;
 
     // The user defined callbacks that will be used for cloning.
     const JSStructuredCloneCallbacks *callbacks;
 
     // Any value passed to JS_WriteStructuredClone.
     void *closure;
+
+    friend JSBool JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v);
 };
 
 #endif /* jsclone_h___ */
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -625,51 +625,44 @@ abstract public class GeckoApp
                 Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.FAVICON);
             }
         });
 
         tab.setFaviconLoadId(id);
     }
 
     void handleLocationChange(final int tabId, final String uri,
-                              final String documentURI, final String contentType) {
+                              final String documentURI, final String contentType,
+                              final boolean sameDocument) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         if (Tabs.getInstance().isSelectedTab(tab)) {
             if (uri.equals("about:home"))
                 showAboutHome();
             else 
                 hideAboutHome();
         }
         
-        String oldBaseURI = tab.getURL();
         tab.updateURL(uri);
         tab.setDocumentURI(documentURI);
-        tab.setContentType(contentType);
-
-        String baseURI = uri;
-        if (baseURI.indexOf('#') != -1)
-            baseURI = uri.substring(0, uri.indexOf('#'));
-
-        if (oldBaseURI != null && oldBaseURI.indexOf('#') != -1)
-            oldBaseURI = oldBaseURI.substring(0, oldBaseURI.indexOf('#'));
-        
-        if (baseURI.equals(oldBaseURI)) {
+
+        if (sameDocument) {
             mMainHandler.post(new Runnable() {
                 public void run() {
                     if (Tabs.getInstance().isSelectedTab(tab)) {
                         mBrowserToolbar.setTitle(uri);
                     }
                 }
             });
             return;
         }
 
+        tab.setContentType(contentType);
         tab.updateFavicon(null);
         tab.updateFaviconURL(null);
         tab.updateSecurityMode("unknown");
         tab.removeTransientDoorHangers();
         tab.setHasTouchListeners(false);
         tab.setCheckerboardColor(Color.WHITE);
 
         maybeCancelFaviconLoad(tab);
@@ -863,33 +856,35 @@ abstract public class GeckoApp
                 // generic log listener
                 final String msg = message.getString("msg");
                 Log.i(LOGTAG, "Log: " + msg);
             } else if (event.equals("Content:LocationChange")) {
                 final int tabId = message.getInt("tabID");
                 final String uri = message.getString("uri");
                 final String documentURI = message.getString("documentURI");
                 final String contentType = message.getString("contentType");
+                final boolean sameDocument = message.getBoolean("sameDocument");
                 Log.i(LOGTAG, "URI - " + uri);
-                handleLocationChange(tabId, uri, documentURI, contentType);
+                handleLocationChange(tabId, uri, documentURI, contentType, sameDocument);
             } else if (event.equals("Content:SecurityChange")) {
                 final int tabId = message.getInt("tabID");
                 final String mode = message.getString("mode");
                 Log.i(LOGTAG, "Security Mode - " + mode);
                 handleSecurityChange(tabId, mode);
             } else if (event.equals("Content:StateChange")) {
                 final int tabId = message.getInt("tabID");
+                final String uri = message.getString("uri");
                 final boolean success = message.getBoolean("success");
                 int state = message.getInt("state");
                 Log.i(LOGTAG, "State - " + state);
                 if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
                     if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
                         Log.i(LOGTAG, "Got a document start");
                         final boolean showProgress = message.getBoolean("showProgress");
-                        handleDocumentStart(tabId, showProgress);
+                        handleDocumentStart(tabId, showProgress, uri);
                     } else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
                         Log.i(LOGTAG, "Got a document stop");
                         handleDocumentStop(tabId, success);
                     }
                 }
             } else if (event.equals("Content:LoadError")) {
                 final int tabId = message.getInt("tabID");
                 final String uri = message.getString("uri");
@@ -1185,29 +1180,30 @@ abstract public class GeckoApp
                 if (tab == null)
                     return;
                 tab.removeDoorHanger(value);
                 mDoorHangerPopup.updatePopup();
             }
         });
     }
 
-    void handleDocumentStart(int tabId, final boolean showProgress) {
+    void handleDocumentStart(int tabId, final boolean showProgress, String uri) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
+        tab.updateURL(uri);
         tab.setState(Tab.STATE_LOADING);
         tab.updateSecurityMode("unknown");
 
         mMainHandler.post(new Runnable() {
             public void run() {
                 if (Tabs.getInstance().isSelectedTab(tab)) {
                     mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
-                    if (showProgress)
+                    if (showProgress && tab.getState() == Tab.STATE_LOADING)
                         mBrowserToolbar.setProgressVisibility(true);
                 }
                 Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START);
             }
         });
     }
 
     void handleDocumentStop(int tabId, boolean success) {
@@ -2158,28 +2154,30 @@ abstract public class GeckoApp
         super.onLowMemory();
     }
 
     @Override
     public void onApplicationPause() {
         Log.i(LOGTAG, "application paused");
         GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true));
 
-        mConnectivityReceiver.unregisterFor(mAppContext);
+        if (mConnectivityReceiver != null)
+            mConnectivityReceiver.unregisterFor(mAppContext);
         GeckoNetworkManager.getInstance().stop();
         GeckoScreenOrientationListener.getInstance().stop();
     }
 
     @Override
     public void onApplicationResume() {
         Log.i(LOGTAG, "application resumed");
         if (checkLaunchState(LaunchState.GeckoRunning))
             GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true));
 
-        mConnectivityReceiver.registerFor(mAppContext);
+        if (mConnectivityReceiver != null)
+            mConnectivityReceiver.registerFor(mAppContext);
         GeckoNetworkManager.getInstance().start();
         GeckoScreenOrientationListener.getInstance().start();
     }
 
     abstract public String getPackageName();
     abstract public String getContentProcessName();
 
     public void addEnvToIntent(Intent intent) {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2079,38 +2079,40 @@ Tab.prototype = {
     let contentWin = aWebProgress.DOMWindow;
     if (contentWin != contentWin.top)
         return;
 
     let browser = BrowserApp.getBrowserForWindow(contentWin);
     let uri = browser.currentURI.spec;
     let documentURI = "";
     let contentType = "";
+    let sameDocument = (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) != 0;
     if (browser.contentDocument) {
       documentURI = browser.contentDocument.documentURIObject.spec;
       contentType = browser.contentDocument.contentType;
     }
 
     // Reset state of click-to-play plugin notifications.
     this.clickToPlayPluginDoorhangerShown = false;
     this.clickToPlayPluginsActivated = false;
 
     let message = {
       gecko: {
         type: "Content:LocationChange",
         tabID: this.id,
         uri: uri,
         documentURI: documentURI,
-        contentType: contentType
+        contentType: contentType,
+        sameDocument: sameDocument
       }
     };
 
     sendMessageToJava(message);
 
-    if ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) == 0) {
+    if (!sameDocument) {
       // XXX This code assumes that this is the earliest hook we have at which
       // browser.contentDocument is changed to the new document we're loading
       this.contentDocumentIsDisplayed = false;
     } else {
       this.sendViewportUpdate();
     }
   },
 
--- a/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js
+++ b/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js
@@ -18,59 +18,68 @@
  * to ensure that this test is independent from locale, commercial agreements
  * and configuration of Firefox.
  */
 
 do_load_httpd_js();
 
 function run_test()
 {
+  do_print("Preparing test");
   removeMetadata();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2");
   do_load_manifest("data/chrome.manifest");
 
   let httpServer = new nsHttpServer();
   httpServer.start(4444);
   httpServer.registerDirectory("/", do_get_cwd());
 
   let search = Services.search;
 
+  do_print("Setting up observer");
   function observer(aSubject, aTopic, aData) {
+    do_print("Observing topic " + aTopic);
     if ("engine-added" == aData) {
       let engine1 = search.getEngineByName("Test search engine");
       let engine2 = search.getEngineByName("Sherlock test search engine");
-      dumpn("Got engine 2: "+engine2);
+      do_print("Currently, engine1 is " + engine1);
+      do_print("Currently, engine2 is " + engine2);
       if(engine1 && engine2)
       {
         search.moveEngine(engine1, 0);
         search.moveEngine(engine2, 1);
+        do_print("Next step is forcing flush");
         do_timeout(0,
                    function() {
+                     do_print("Forcing flush");
                      // Force flush
                      // Note: the timeout is needed, to avoid some reentrency
                      // issues in nsSearchService.
                      search.QueryInterface(Ci.nsIObserver).
                        observe(observer, "quit-application", "<no verb>");
                    });
         afterCommit(
           function()
           {
+            do_print("Commit complete");
             // Check that search-metadata.json has been created
             let metadata = gProfD.clone();
             metadata.append("search-metadata.json");
             do_check_true(metadata.exists());
 
             // Check that the entries are placed as specified correctly
-	    let stream = NetUtil.newChannel(metadata).open();
+            let stream = NetUtil.newChannel(metadata).open();
             let json = parseJsonFromStream(stream);
             do_check_eq(json["[app]/test-search-engine.xml"].order, 1);
             do_check_eq(json["[profile]/sherlock-test-search-engine.xml"].order, 2);
-	    httpServer.stop(function() {});
-	    stream.close(); // Stream must be closed under Windows
-	    removeMetadata();
+
+            do_print("Cleaning up");
+            httpServer.stop(function() {});
+            stream.close(); // Stream must be closed under Windows
+            removeMetadata();
             do_test_finished();
           }
         );
       }
     }
   };
   Services.obs.addObserver(observer, "browser-search-engine-modified",
                            false);
@@ -79,9 +88,13 @@ function run_test()
 
   search.addEngine("http://localhost:4444/data/engine.xml",
                    Ci.nsISearchEngine.DATA_XML,
                    null, false);
   search.addEngine("http://localhost:4444/data/engine.src",
                    Ci.nsISearchEngine.DATA_TEXT,
                    "http://localhost:4444/data/ico-size-16x16-png.ico",
                    false);
+
+  do_timeout(120000, function() {
+    do_throw("Timeout");
+  });
 }
--- a/webapprt/win/webapprt.cpp
+++ b/webapprt/win/webapprt.cpp
@@ -282,16 +282,17 @@ namespace {
         return false;
       }
 
       ScopedXREAppData webShellAppData;
       rv = webShellAppData.create(rtINI);
       NS_ENSURE_SUCCESS(rv, rv);
 
       SetAllocatedString(webShellAppData->profile, profile);
+      SetAllocatedString(webShellAppData->name, profile);
 
       nsCOMPtr<nsILocalFile> directory;
       rv = XRE_GetFileFromPath(rtPath, getter_AddRefs(directory));
       NS_ENSURE_SUCCESS(rv, false);
 
       nsCOMPtr<nsILocalFile> xreDir;
       rv = XRE_GetFileFromPath(greDir, getter_AddRefs(xreDir));
       NS_ENSURE_SUCCESS(rv, false);