Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Sun, 29 Apr 2012 23:41:26 -0700
changeset 95736 005a5bfe547406d6cb7d76b90dabd56ee65fc036
parent 95735 8e59a61ca83136b880fe273dfa7ac69f2cb36cd2 (current diff)
parent 94949 cfaf90b22fc3c05025890bd1acfab2c49ec77594 (diff)
child 95737 5eb0112f34095f79924c770fb6492c372504b305
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone15.0a1
Merge m-c to s-c.
js/src/jit-test/tests/basic/Proxy-function-freeze.js
js/src/jit-test/tests/basic/bug684348.js
js/src/jit-test/tests/for-of/proxy-4.js
js/src/jit-test/tests/jaeger/globalOptimize-3.js
mobile/android/base/SurfaceLockInfo.java
src/test/java/org/mozilla/android/sync/repositories/domain/TabsRecord.java
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -232,17 +232,17 @@ AndroidPresenter.prototype.pivotChanged 
   });
 };
 
 AndroidPresenter.prototype.actionInvoked = function(aObject, aActionName) {
   this.sendMessageToJava({
     gecko: {
       type: 'Accessibility:Event',
       eventType: ANDROID_TYPE_VIEW_CLICKED,
-      text: [UtteranceGenerator.genForAction(aObject, aActionName)]
+      text: UtteranceGenerator.genForAction(aObject, aActionName)
     }
   });
 };
 
 AndroidPresenter.prototype.tabSelected = function(aObject) {
   let vcDoc = aObject.QueryInterface(Ci.nsIAccessibleCursorable);
   let context = [];
 
--- a/accessible/src/jsat/UtteranceGenerator.jsm
+++ b/accessible/src/jsat/UtteranceGenerator.jsm
@@ -49,17 +49,17 @@ var UtteranceGenerator = {
 
     if (aForceName)
       flags |= INCLUDE_NAME;
 
     return func(aAccessible, roleString, flags);
   },
 
   genForAction: function(aObject, aActionName) {
-    return gStringBundle.GetStringFromName(this.gActionMap[aActionName]);
+    return [gStringBundle.GetStringFromName(this.gActionMap[aActionName])];
   },
 
   verbosityRoleMap: {
     'menubar': INCLUDE_ROLE,
     'scrollbar': INCLUDE_ROLE,
     'grip': INCLUDE_ROLE,
     'alert': INCLUDE_ROLE,
     'menupopup': INCLUDE_ROLE,
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -66,20 +66,23 @@ using namespace mozilla::a11y;
 
 nsXULTreeAccessible::
   nsXULTreeAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
   nsAccessibleWrap(aContent, aDoc)
 {
   mFlags |= eXULTreeAccessible;
 
   mTree = nsCoreUtils::GetTreeBoxObject(aContent);
-  if (mTree)
-    mTree->GetView(getter_AddRefs(mTreeView));
+  NS_ASSERTION(mTree, "Can't get mTree!\n");
 
-  NS_ASSERTION(mTree && mTreeView, "Can't get mTree or mTreeView!\n");
+  if (mTree) {
+    nsCOMPtr<nsITreeView> treeView;
+    mTree->GetView(getter_AddRefs(treeView));
+    mTreeView = treeView;
+  }
 
   nsIContent* parentContent = mContent->GetParent();
   if (parentContent) {
     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
       do_QueryInterface(parentContent);
     if (autoCompletePopupElm)
       mFlags |= eAutoCompletePopupAccessible;
   }
@@ -90,24 +93,22 @@ nsXULTreeAccessible::
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeAccessible: nsISupports and cycle collection implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeAccessible,
                                                   nsAccessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
   CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeAccessible,
                                                 nsAccessible)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
   ClearCache(tmp->mAccessibleCache);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeAccessible)
 NS_INTERFACE_MAP_END_INHERITING(nsAccessible)
 
 NS_IMPL_ADDREF_INHERITED(nsXULTreeAccessible, nsAccessible)
 NS_IMPL_RELEASE_INHERITED(nsXULTreeAccessible, nsAccessible)
@@ -140,20 +141,21 @@ nsXULTreeAccessible::NativeState()
     state |= states::MULTISELECTABLE;
 
   return state;
 }
 
 void
 nsXULTreeAccessible::Value(nsString& aValue)
 {
-  // Return the value is the first selected child.
+  aValue.Truncate();
+  if (!mTreeView)
+    return;
 
-  aValue.Truncate();
-
+  // Return the value is the first selected child.
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
   if (!selection)
     return;
 
   PRInt32 currentIndex;
   nsCOMPtr<nsIDOMElement> selectItem;
   selection->GetCurrentIndex(&currentIndex);
@@ -734,23 +736,21 @@ nsXULTreeItemAccessibleBase::
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase: nsISupports implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeItemAccessibleBase)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeItemAccessibleBase,
                                                   nsAccessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeItemAccessibleBase,
                                                 nsAccessible)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULTreeItemAccessibleBase)
   NS_INTERFACE_TABLE_INHERITED1(nsXULTreeItemAccessibleBase,
                                 nsXULTreeItemAccessibleBase)
 NS_INTERFACE_TABLE_TAIL_INHERITING(nsAccessible)
 NS_IMPL_ADDREF_INHERITED(nsXULTreeItemAccessibleBase, nsAccessible)
 NS_IMPL_RELEASE_INHERITED(nsXULTreeItemAccessibleBase, nsAccessible)
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -138,17 +138,17 @@ public:
 
 protected:
   /**
    * Creates tree item accessible for the given row index.
    */
   virtual already_AddRefed<nsAccessible> CreateTreeItemAccessible(PRInt32 aRow);
 
   nsCOMPtr<nsITreeBoxObject> mTree;
-  nsCOMPtr<nsITreeView> mTreeView;
+  nsITreeView* mTreeView;
   nsAccessibleHashtable mAccessibleCache;
 };
 
 /**
  * Base class for tree item accessibles.
  */
 
 #define NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID         \
@@ -239,17 +239,17 @@ protected:
   bool IsExpandable();
 
   /**
    * Return name for cell at the given column.
    */
   void GetCellName(nsITreeColumn* aColumn, nsAString& aName);
 
   nsCOMPtr<nsITreeBoxObject> mTree;
-  nsCOMPtr<nsITreeView> mTreeView;
+  nsITreeView* mTreeView;
   PRInt32 mRow;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeItemAccessibleBase,
                               NS_XULTREEITEMBASEACCESSIBLE_IMPL_CID)
 
 
 /**
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -813,24 +813,22 @@ nsXULTreeGridCellAccessible::
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsISupports implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTreeGridCellAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
                                                   nsLeafAccessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTree)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTreeView)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mColumn)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeGridCellAccessible,
                                                 nsLeafAccessible)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTree)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTreeView)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mColumn)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULTreeGridCellAccessible)
   NS_INTERFACE_TABLE_INHERITED2(nsXULTreeGridCellAccessible,
                                 nsIAccessibleTableCell,
                                 nsXULTreeGridCellAccessible)
 NS_INTERFACE_TABLE_TAIL_INHERITING(nsLeafAccessible)
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -205,17 +205,17 @@ protected:
   /**
    * Return true if value of cell can be modified.
    */
   bool IsEditable() const;
 
   enum { eAction_Click = 0 };
 
   nsCOMPtr<nsITreeBoxObject> mTree;
-  nsCOMPtr<nsITreeView> mTreeView;
+  nsITreeView* mTreeView;
 
   PRInt32 mRow;
   nsCOMPtr<nsITreeColumn> mColumn;
 
   nsString mCachedTextEquiv;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeGridCellAccessible,
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -403,16 +403,18 @@
 @BINPATH@/components/contentSecurityPolicy.manifest
 @BINPATH@/components/contentSecurityPolicy.js
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
 @BINPATH@/components/SettingsManager.js
 @BINPATH@/components/SettingsManager.manifest
+@BINPATH@/components/SettingsService.js
+@BINPATH@/components/SettingsService.manifest
 @BINPATH@/components/nsFilePicker.js
 @BINPATH@/components/nsFilePicker.manifest
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/NetworkManager.manifest
 @BINPATH@/components/NetworkManager.js
 @BINPATH@/components/RadioInterfaceLayer.manifest
 @BINPATH@/components/RadioInterfaceLayer.js
 @BINPATH@/components/RILContentHelper.js
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -57,16 +57,20 @@ PREF_JS_EXPORTS = $(srcdir)/profile/fire
 # hardcode en-US for the moment
 AB_CD = en-US
 
 DEFINES += \
   -DAB_CD=$(AB_CD) \
   -DAPP_VERSION="$(MOZ_APP_VERSION)" \
   -DFIREFOX_ICO=\"$(DIST)/branding/firefox.ico\" \
   -DDOCUMENT_ICO=\"$(DIST)/branding/document.ico\" \
+  -DNEWWINDOW_ICO=\"$(DIST)/branding/newwindow.ico\" \
+  -DNEWTAB_ICO=\"$(DIST)/branding/newtab.ico\" \
+  -DPBMODE_ICO=\"$(DIST)/branding/pbmode.ico\" \
+
   $(NULL)
 
 ifdef LIBXUL_SDK #{
 include $(topsrcdir)/config/rules.mk
 else
 # Build a binary bootstrapping with XRE_main
 
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,15 +1,19 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1333739604000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1335396801000">
   <emItems>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i71" id="youtube@2youtube.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
@@ -76,16 +80,20 @@
       <emItem  blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
                         <versionRange  minVersion="2.0.3" maxVersion="2.0.3">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i83" id="flash@adobee.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i59" id="ghostviewer@youtube2.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i78" id="socialnetworktools@mozilla.doslash.org">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
@@ -94,16 +102,20 @@
                     </versionRange>
                   </emItem>
       <emItem  blockID="i68" id="flashupdate@adobe.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
                         </emItem>
+      <emItem  blockID="i84" id="pink@rosaplugin.info">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i67" id="youtube2@youtube2.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i60" id="youtb3@youtb3.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
@@ -156,16 +168,20 @@
       <emItem  blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
                         <versionRange  minVersion="2.2" maxVersion="2.2">
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
                         <versionRange  minVersion="1.1b1" maxVersion="1.1b1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i3" id="langpack-vi-VN@firefox.mozilla.org">
                         <versionRange  minVersion="2.0" maxVersion="2.0">
                     </versionRange>
                   </emItem>
@@ -191,16 +207,19 @@
       <pluginItem  blockID="p31">
                   <match name="filename" exp="NPMySrch.dll" />                        </pluginItem>
       <pluginItem  blockID="p33">
       <match name="name" exp="[0-6]\.0\.[01]\d{2}\.\d+" />            <match name="filename" exp="npdeploytk.dll" />                      <versionRange  severity="1"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p80">
             <match name="description" exp="[^\d\._]((0(\.\d+(\.\d+([_\.]\d+)?)?)?)|(1\.(([0-5](\.\d+([_\.]\d+)?)?)|(6(\.0([_\.](0?\d|1\d|2\d|30))?)?)|(7(\.0([_\.][0-2])?)?))))([^\d\._]|$)" />      <match name="filename" exp="(npjp2\.dll)|(libnpjp2\.so)" />                      <versionRange  severity="1"></versionRange>
                   </pluginItem>
+      <pluginItem  blockID="p85">
+                  <match name="filename" exp="JavaPlugin2_NPAPI\.plugin" />                      <versionRange  minVersion="0" maxVersion="12.9.0" severity="1"></versionRange>
+                  </pluginItem>
     </pluginItems>
 
   <gfxItems>
     <gfxBlacklistEntry  blockID="g35">      <os>WINNT 6.1</os>      <vendor>0x10de</vendor>              <devices>
                       <device>0x0a6c</device>
                   </devices>
             <feature>DIRECT2D</feature>      <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus>      <driverVersion>8.17.12.5896</driverVersion>      <driverVersionComparator>LESS_THAN_OR_EQUAL</driverVersionComparator>    </gfxBlacklistEntry>
     <gfxBlacklistEntry  blockID="g36">      <os>WINNT 6.1</os>      <vendor>0x10de</vendor>              <devices>
--- a/browser/app/splash.rc
+++ b/browser/app/splash.rc
@@ -40,13 +40,16 @@
 #include <windows.h>
 #include "nsNativeAppSupportWin.h"
 
 1 24 "firefox.exe.manifest"
 
 IDI_APPICON ICON FIREFOX_ICO
 IDI_DOCUMENT ICON DOCUMENT_ICO
 IDI_APPLICATION ICON FIREFOX_ICO
+IDI_NEWWINDOW ICON NEWWINDOW_ICO
+IDI_NEWTAB ICON NEWTAB_ICO
+IDI_PBMODE ICON PBMODE_ICO
 
 STRINGTABLE DISCARDABLE
 BEGIN
     IDS_STARTMENU_APPNAME,              "@MOZ_APP_DISPLAYNAME@"
 END
--- a/browser/base/content/test/browser_locationBarCommand.js
+++ b/browser/base/content/test/browser_locationBarCommand.js
@@ -27,17 +27,17 @@ saveURL = function() {
   runShiftLeftClickTest();
 }
 function runAltLeftClickTest() {
   info("Running test: Alt left click");
   triggerCommand(true, { altKey: true });
 }
 
 function runShiftLeftClickTest() {
-  let listener = new WindowListener("chrome://browser/content/browser.xul", function(aWindow) {
+  let listener = new WindowListener(getBrowserURL(), function(aWindow) {
     Services.wm.removeListener(listener);
     addPageShowListener(aWindow.gBrowser, function() {
       info("URL should be loaded in a new window");
       is(gURLBar.value, "", "Urlbar reverted to original value");       
       is(gFocusManager.focusedElement, null, "There should be no focused element");
       is(gFocusManager.focusedWindow, aWindow.gBrowser.contentWindow, "Content window should be focused");
       is(aWindow.gURLBar.value, TEST_VALUE, "New URL is loaded in new window");
 
--- a/browser/branding/aurora/Makefile.in
+++ b/browser/branding/aurora/Makefile.in
@@ -53,16 +53,19 @@ include $(topsrcdir)/config/rules.mk
 
 WINDOWS_BRANDING_FILES = \
 	firefox.ico \
 	document.ico \
 	branding.nsi \
 	wizHeader.bmp \
 	wizHeaderRTL.bmp \
 	wizWatermark.bmp \
+	newwindow.ico \
+	newtab.ico \
+	pbmode.ico \
 	$(NULL)
 
 OSX_BRANDING_FILES = \
 	background.png \
 	firefox.icns \
 	disk.icns \
 	document.icns \
 	dsstore \
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6e3fee6229beba45996cfd9be6cc839258ec86d3
GIT binary patch
literal 1150
zc$|%sO=uJ`6vyAzwiacQ(W*tkR;<zwcV`L<eqB6Bb=jSjQUs|d1yK?4AXpWPAK;;Q
z^w^6YJ*fx1iH8b%P*6lcC>0f<^vk+hy4y+8dFI6_4AXIKhF>Q0-v6HrF9|?OKei3J
z-vQ_A0k!}@r$&c#<Zs-xCRou9cUsLy(^kQA*^uY3o2$ZQH*#q!f2fVy^e#Pn@M>{-
zOo`dgxEiWcV`}ut$jiLLa(S0sU7Q(T5<k9RoIv`9q+DfcTzD?OQgHd8nEQrFv=3$t
z|H_lsbNFTX^E*ZflyB%7&Kj1#<2v$sj&(_vCosyUGws-Vy#sgO>o(AsVsRaLy&iT!
z{+`4r?BsUbe6ba`4Ye6)OtH9*ym~Lr$@v*f!alpzker`I^6DC%7L{L1a$yeRH1)R_
zl5*PP7hQfzpPd6AUXMOk!k4sHs#2~A)seLCN-v(~GS>d=&JDb`%i34Wuz`p7@7z_@
zd920A@U>f{CC}bn8<{@BYcy*$>-5<?q5K7`1!+hdddOR+X`tIt$nfJzRIwJM32#zE
z=uL(5H0oORN#QF+bx1&ns$a<1$4DD`QXw=?eQ!7K`SkwHV<n{wf&imX?Bm<gqa%B4
vm$Z?!Vfh~pb~IbLwC&_weV-k>7=>b#b6Q}1WNknMxSjexUpYWI26_JgKxLBi
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a30093564c1bf0b4d905de41e46cadc3fdff9832
GIT binary patch
literal 1150
zc$}4#%}Z2K7>AG4!o_gz1ZgB>k%d{!oyBZ3mzpyx7gnxC6f{~yR7eOe`XUSp`~$)k
zEn2wHC?usMlTnEX{|!Iq&fN3y_WoWO7)OHZxjgqA-t&7d_q<%LQVo2i(~9pG)bL5A
znw3&l7%p+;pf00P9T_(+rJ8y|eWwrxZ}Zt;IuT*;t~;ae!o|EeJ5!8H+s?-&N`i@Y
z9GqL%^zA}czp>GtUzwkwmAUuH;H-&uZ6VZCz?+DEef~hMw3P^C;lRyj^($}6RQ&pp
zT(onDwud>PzK$#$xZICt-c)F9;S;&??jbs!=Y;w?vT)#XFDJdN(8kg%xyrt9da#XJ
zAGg!xmsbU>QLFAF3kNPgW5U~*e*c&w7e|5~I7dyRt<*ApUcef)>OQh?;Bx=Ry*2db
z=NEaWTGB&jh5EW=*@4SFeB_;>zpLNmnYA?boe}Eml4S=je|HbOv$VPPoiHb%nuW_}
zxG%Mh<zoQ{Zf~f^ymw@|FUJ86+<d4<thLUXm@N0EmP&b_UO&Aj>laT(WbW@T3f36I
z=O6C5p6Xg(UYK{58=7z+3#T`ex|zFpD(KFnIt!U#kk2!e1Z3gBT|A-GM8nblLUmy8
Ie-J74526(Ex&QzG
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d21799475a2322e259313ecd560ccb842e81d79d
GIT binary patch
literal 1150
zc%03YTTIe%6vzMFmaDD#(rxR($ChpN*jsNsxAjmD7Gn~q!vZe^A^rt4Nf45oToeSk
zDF`HrI2F8BN@)+8#k$%|%eA&z%oy(5|F7AstsYzto!`!H`<-(>=eKiyXFr12L9N_e
zg4*+lqTK{>h#-jLlu{<jvSDAB9O9o#zAlQxVjH&0pHIB~ulT{Hx)TBU4WW-LW7$bE
z$4)YGTKUXE^R>%DOUae|Kk=#2j)Ngp&A3x3%=+~bI2y{}xGhMx)$!8KhEfC#0<_4A
zv(1%-6ZY$jysdlzr@Y_WDE=JxX))DfL$cR~Zfh;(hrM``aAVM=z~h(&)4fI{Jhxzy
zu+pvEf>Shq&Nm4aS%Jxj1!0Q}0b>n9W;wc=YcSo{hMAb1$|XhERE2<EfQUtm`$08K
zqN|HEFA_;yajy~~Q#IvNyc)7=B5{Y#<I_~XAMxuk+@XbEBVLN=YCR#fB;r<9yb0(k
z(b>dD3!ibxcC+Zg+@Kw<`tsCfO(aR~v`BfM=vqbt1{lR9AGh|*EGc?15om->$Qiav
zOFqmFw7{+6!BWjmTWd;F8UZuoxg*5F!zkuQ{7?&-kZ~?#v;tO2!M&I^kt`%52H0iX
z6{EB`J=WO(I>*z56UiPEW`~@3J#`nW3sYE`OJF=`qIx3-{Vs!U72@7TOm!R4uHdh>
z%Gqn7W-{%ny|&n;6=i0kW~|J{@b%>w7H6V(elLjBco2{J9O!RXp+jAj=}?N_c~zn>
zRw-w#Ucg&AX&qgkpUw)#5x11v*QFJ&hK!PISW7O4_0r{lj?4zM(r+<CeJp8GAEjeK
z^(a&)XkZRJL;er`XMfo2J<jri{hQ}*HhUj!+wP42O+ejz_BYMjOF4EC^vAKT$Ikr9
LoIbD-N3-7nrgNc+
--- a/browser/branding/nightly/Makefile.in
+++ b/browser/branding/nightly/Makefile.in
@@ -53,16 +53,19 @@ include $(topsrcdir)/config/rules.mk
 
 WINDOWS_BRANDING_FILES = \
 	firefox.ico \
 	document.ico \
 	branding.nsi \
 	wizHeader.bmp \
 	wizHeaderRTL.bmp \
 	wizWatermark.bmp \
+	newwindow.ico \
+	newtab.ico \
+	pbmode.ico \
 	$(NULL)
 
 OSX_BRANDING_FILES = \
 	background.png \
 	firefox.icns \
 	disk.icns \
 	document.icns \
 	dsstore \
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6e3fee6229beba45996cfd9be6cc839258ec86d3
GIT binary patch
literal 1150
zc$|%sO=uJ`6vyAzwiacQ(W*tkR;<zwcV`L<eqB6Bb=jSjQUs|d1yK?4AXpWPAK;;Q
z^w^6YJ*fx1iH8b%P*6lcC>0f<^vk+hy4y+8dFI6_4AXIKhF>Q0-v6HrF9|?OKei3J
z-vQ_A0k!}@r$&c#<Zs-xCRou9cUsLy(^kQA*^uY3o2$ZQH*#q!f2fVy^e#Pn@M>{-
zOo`dgxEiWcV`}ut$jiLLa(S0sU7Q(T5<k9RoIv`9q+DfcTzD?OQgHd8nEQrFv=3$t
z|H_lsbNFTX^E*ZflyB%7&Kj1#<2v$sj&(_vCosyUGws-Vy#sgO>o(AsVsRaLy&iT!
z{+`4r?BsUbe6ba`4Ye6)OtH9*ym~Lr$@v*f!alpzker`I^6DC%7L{L1a$yeRH1)R_
zl5*PP7hQfzpPd6AUXMOk!k4sHs#2~A)seLCN-v(~GS>d=&JDb`%i34Wuz`p7@7z_@
zd920A@U>f{CC}bn8<{@BYcy*$>-5<?q5K7`1!+hdddOR+X`tIt$nfJzRIwJM32#zE
z=uL(5H0oORN#QF+bx1&ns$a<1$4DD`QXw=?eQ!7K`SkwHV<n{wf&imX?Bm<gqa%B4
vm$Z?!Vfh~pb~IbLwC&_weV-k>7=>b#b6Q}1WNknMxSjexUpYWI26_JgKxLBi
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a30093564c1bf0b4d905de41e46cadc3fdff9832
GIT binary patch
literal 1150
zc$}4#%}Z2K7>AG4!o_gz1ZgB>k%d{!oyBZ3mzpyx7gnxC6f{~yR7eOe`XUSp`~$)k
zEn2wHC?usMlTnEX{|!Iq&fN3y_WoWO7)OHZxjgqA-t&7d_q<%LQVo2i(~9pG)bL5A
znw3&l7%p+;pf00P9T_(+rJ8y|eWwrxZ}Zt;IuT*;t~;ae!o|EeJ5!8H+s?-&N`i@Y
z9GqL%^zA}czp>GtUzwkwmAUuH;H-&uZ6VZCz?+DEef~hMw3P^C;lRyj^($}6RQ&pp
zT(onDwud>PzK$#$xZICt-c)F9;S;&??jbs!=Y;w?vT)#XFDJdN(8kg%xyrt9da#XJ
zAGg!xmsbU>QLFAF3kNPgW5U~*e*c&w7e|5~I7dyRt<*ApUcef)>OQh?;Bx=Ry*2db
z=NEaWTGB&jh5EW=*@4SFeB_;>zpLNmnYA?boe}Eml4S=je|HbOv$VPPoiHb%nuW_}
zxG%Mh<zoQ{Zf~f^ymw@|FUJ86+<d4<thLUXm@N0EmP&b_UO&Aj>laT(WbW@T3f36I
z=O6C5p6Xg(UYK{58=7z+3#T`ex|zFpD(KFnIt!U#kk2!e1Z3gBT|A-GM8nblLUmy8
Ie-J74526(Ex&QzG
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d21799475a2322e259313ecd560ccb842e81d79d
GIT binary patch
literal 1150
zc%03YTTIe%6vzMFmaDD#(rxR($ChpN*jsNsxAjmD7Gn~q!vZe^A^rt4Nf45oToeSk
zDF`HrI2F8BN@)+8#k$%|%eA&z%oy(5|F7AstsYzto!`!H`<-(>=eKiyXFr12L9N_e
zg4*+lqTK{>h#-jLlu{<jvSDAB9O9o#zAlQxVjH&0pHIB~ulT{Hx)TBU4WW-LW7$bE
z$4)YGTKUXE^R>%DOUae|Kk=#2j)Ngp&A3x3%=+~bI2y{}xGhMx)$!8KhEfC#0<_4A
zv(1%-6ZY$jysdlzr@Y_WDE=JxX))DfL$cR~Zfh;(hrM``aAVM=z~h(&)4fI{Jhxzy
zu+pvEf>Shq&Nm4aS%Jxj1!0Q}0b>n9W;wc=YcSo{hMAb1$|XhERE2<EfQUtm`$08K
zqN|HEFA_;yajy~~Q#IvNyc)7=B5{Y#<I_~XAMxuk+@XbEBVLN=YCR#fB;r<9yb0(k
z(b>dD3!ibxcC+Zg+@Kw<`tsCfO(aR~v`BfM=vqbt1{lR9AGh|*EGc?15om->$Qiav
zOFqmFw7{+6!BWjmTWd;F8UZuoxg*5F!zkuQ{7?&-kZ~?#v;tO2!M&I^kt`%52H0iX
z6{EB`J=WO(I>*z56UiPEW`~@3J#`nW3sYE`OJF=`qIx3-{Vs!U72@7TOm!R4uHdh>
z%Gqn7W-{%ny|&n;6=i0kW~|J{@b%>w7H6V(elLjBco2{J9O!RXp+jAj=}?N_c~zn>
zRw-w#Ucg&AX&qgkpUw)#5x11v*QFJ&hK!PISW7O4_0r{lj?4zM(r+<CeJp8GAEjeK
z^(a&)XkZRJL;er`XMfo2J<jri{hQ}*HhUj!+wP42O+ejz_BYMjOF4EC^vAKT$Ikr9
LoIbD-N3-7nrgNc+
--- a/browser/branding/official/Makefile.in
+++ b/browser/branding/official/Makefile.in
@@ -53,16 +53,19 @@ include $(topsrcdir)/config/rules.mk
 
 WINDOWS_BRANDING_FILES = \
 	firefox.ico \
 	document.ico \
 	branding.nsi \
 	wizHeader.bmp \
 	wizHeaderRTL.bmp \
 	wizWatermark.bmp \
+	newwindow.ico \
+	newtab.ico \
+	pbmode.ico \
 	$(NULL)
 
 OSX_BRANDING_FILES = \
 	background.png \
 	firefox.icns \
 	disk.icns \
 	document.icns \
 	dsstore \
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6e3fee6229beba45996cfd9be6cc839258ec86d3
GIT binary patch
literal 1150
zc$|%sO=uJ`6vyAzwiacQ(W*tkR;<zwcV`L<eqB6Bb=jSjQUs|d1yK?4AXpWPAK;;Q
z^w^6YJ*fx1iH8b%P*6lcC>0f<^vk+hy4y+8dFI6_4AXIKhF>Q0-v6HrF9|?OKei3J
z-vQ_A0k!}@r$&c#<Zs-xCRou9cUsLy(^kQA*^uY3o2$ZQH*#q!f2fVy^e#Pn@M>{-
zOo`dgxEiWcV`}ut$jiLLa(S0sU7Q(T5<k9RoIv`9q+DfcTzD?OQgHd8nEQrFv=3$t
z|H_lsbNFTX^E*ZflyB%7&Kj1#<2v$sj&(_vCosyUGws-Vy#sgO>o(AsVsRaLy&iT!
z{+`4r?BsUbe6ba`4Ye6)OtH9*ym~Lr$@v*f!alpzker`I^6DC%7L{L1a$yeRH1)R_
zl5*PP7hQfzpPd6AUXMOk!k4sHs#2~A)seLCN-v(~GS>d=&JDb`%i34Wuz`p7@7z_@
zd920A@U>f{CC}bn8<{@BYcy*$>-5<?q5K7`1!+hdddOR+X`tIt$nfJzRIwJM32#zE
z=uL(5H0oORN#QF+bx1&ns$a<1$4DD`QXw=?eQ!7K`SkwHV<n{wf&imX?Bm<gqa%B4
vm$Z?!Vfh~pb~IbLwC&_weV-k>7=>b#b6Q}1WNknMxSjexUpYWI26_JgKxLBi
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a30093564c1bf0b4d905de41e46cadc3fdff9832
GIT binary patch
literal 1150
zc$}4#%}Z2K7>AG4!o_gz1ZgB>k%d{!oyBZ3mzpyx7gnxC6f{~yR7eOe`XUSp`~$)k
zEn2wHC?usMlTnEX{|!Iq&fN3y_WoWO7)OHZxjgqA-t&7d_q<%LQVo2i(~9pG)bL5A
znw3&l7%p+;pf00P9T_(+rJ8y|eWwrxZ}Zt;IuT*;t~;ae!o|EeJ5!8H+s?-&N`i@Y
z9GqL%^zA}czp>GtUzwkwmAUuH;H-&uZ6VZCz?+DEef~hMw3P^C;lRyj^($}6RQ&pp
zT(onDwud>PzK$#$xZICt-c)F9;S;&??jbs!=Y;w?vT)#XFDJdN(8kg%xyrt9da#XJ
zAGg!xmsbU>QLFAF3kNPgW5U~*e*c&w7e|5~I7dyRt<*ApUcef)>OQh?;Bx=Ry*2db
z=NEaWTGB&jh5EW=*@4SFeB_;>zpLNmnYA?boe}Eml4S=je|HbOv$VPPoiHb%nuW_}
zxG%Mh<zoQ{Zf~f^ymw@|FUJ86+<d4<thLUXm@N0EmP&b_UO&Aj>laT(WbW@T3f36I
z=O6C5p6Xg(UYK{58=7z+3#T`ex|zFpD(KFnIt!U#kk2!e1Z3gBT|A-GM8nblLUmy8
Ie-J74526(Ex&QzG
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d21799475a2322e259313ecd560ccb842e81d79d
GIT binary patch
literal 1150
zc%03YTTIe%6vzMFmaDD#(rxR($ChpN*jsNsxAjmD7Gn~q!vZe^A^rt4Nf45oToeSk
zDF`HrI2F8BN@)+8#k$%|%eA&z%oy(5|F7AstsYzto!`!H`<-(>=eKiyXFr12L9N_e
zg4*+lqTK{>h#-jLlu{<jvSDAB9O9o#zAlQxVjH&0pHIB~ulT{Hx)TBU4WW-LW7$bE
z$4)YGTKUXE^R>%DOUae|Kk=#2j)Ngp&A3x3%=+~bI2y{}xGhMx)$!8KhEfC#0<_4A
zv(1%-6ZY$jysdlzr@Y_WDE=JxX))DfL$cR~Zfh;(hrM``aAVM=z~h(&)4fI{Jhxzy
zu+pvEf>Shq&Nm4aS%Jxj1!0Q}0b>n9W;wc=YcSo{hMAb1$|XhERE2<EfQUtm`$08K
zqN|HEFA_;yajy~~Q#IvNyc)7=B5{Y#<I_~XAMxuk+@XbEBVLN=YCR#fB;r<9yb0(k
z(b>dD3!ibxcC+Zg+@Kw<`tsCfO(aR~v`BfM=vqbt1{lR9AGh|*EGc?15om->$Qiav
zOFqmFw7{+6!BWjmTWd;F8UZuoxg*5F!zkuQ{7?&-kZ~?#v;tO2!M&I^kt`%52H0iX
z6{EB`J=WO(I>*z56UiPEW`~@3J#`nW3sYE`OJF=`qIx3-{Vs!U72@7TOm!R4uHdh>
z%Gqn7W-{%ny|&n;6=i0kW~|J{@b%>w7H6V(elLjBco2{J9O!RXp+jAj=}?N_c~zn>
zRw-w#Ucg&AX&qgkpUw)#5x11v*QFJ&hK!PISW7O4_0r{lj?4zM(r+<CeJp8GAEjeK
z^(a&)XkZRJL;er`XMfo2J<jri{hQ}*HhUj!+wP42O+ejz_BYMjOF4EC^vAKT$Ikr9
LoIbD-N3-7nrgNc+
--- a/browser/branding/unofficial/Makefile.in
+++ b/browser/branding/unofficial/Makefile.in
@@ -53,16 +53,19 @@ include $(topsrcdir)/config/rules.mk
 
 WINDOWS_BRANDING_FILES = \
 	firefox.ico \
 	document.ico \
 	branding.nsi \
 	wizHeader.bmp \
 	wizHeaderRTL.bmp \
 	wizWatermark.bmp \
+	newwindow.ico \
+	newtab.ico \
+	pbmode.ico \
 	$(NULL)
 
 OSX_BRANDING_FILES = \
 	background.png \
 	firefox.icns \
 	disk.icns \
 	document.icns \
 	dsstore \
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6e3fee6229beba45996cfd9be6cc839258ec86d3
GIT binary patch
literal 1150
zc$|%sO=uJ`6vyAzwiacQ(W*tkR;<zwcV`L<eqB6Bb=jSjQUs|d1yK?4AXpWPAK;;Q
z^w^6YJ*fx1iH8b%P*6lcC>0f<^vk+hy4y+8dFI6_4AXIKhF>Q0-v6HrF9|?OKei3J
z-vQ_A0k!}@r$&c#<Zs-xCRou9cUsLy(^kQA*^uY3o2$ZQH*#q!f2fVy^e#Pn@M>{-
zOo`dgxEiWcV`}ut$jiLLa(S0sU7Q(T5<k9RoIv`9q+DfcTzD?OQgHd8nEQrFv=3$t
z|H_lsbNFTX^E*ZflyB%7&Kj1#<2v$sj&(_vCosyUGws-Vy#sgO>o(AsVsRaLy&iT!
z{+`4r?BsUbe6ba`4Ye6)OtH9*ym~Lr$@v*f!alpzker`I^6DC%7L{L1a$yeRH1)R_
zl5*PP7hQfzpPd6AUXMOk!k4sHs#2~A)seLCN-v(~GS>d=&JDb`%i34Wuz`p7@7z_@
zd920A@U>f{CC}bn8<{@BYcy*$>-5<?q5K7`1!+hdddOR+X`tIt$nfJzRIwJM32#zE
z=uL(5H0oORN#QF+bx1&ns$a<1$4DD`QXw=?eQ!7K`SkwHV<n{wf&imX?Bm<gqa%B4
vm$Z?!Vfh~pb~IbLwC&_weV-k>7=>b#b6Q}1WNknMxSjexUpYWI26_JgKxLBi
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a30093564c1bf0b4d905de41e46cadc3fdff9832
GIT binary patch
literal 1150
zc$}4#%}Z2K7>AG4!o_gz1ZgB>k%d{!oyBZ3mzpyx7gnxC6f{~yR7eOe`XUSp`~$)k
zEn2wHC?usMlTnEX{|!Iq&fN3y_WoWO7)OHZxjgqA-t&7d_q<%LQVo2i(~9pG)bL5A
znw3&l7%p+;pf00P9T_(+rJ8y|eWwrxZ}Zt;IuT*;t~;ae!o|EeJ5!8H+s?-&N`i@Y
z9GqL%^zA}czp>GtUzwkwmAUuH;H-&uZ6VZCz?+DEef~hMw3P^C;lRyj^($}6RQ&pp
zT(onDwud>PzK$#$xZICt-c)F9;S;&??jbs!=Y;w?vT)#XFDJdN(8kg%xyrt9da#XJ
zAGg!xmsbU>QLFAF3kNPgW5U~*e*c&w7e|5~I7dyRt<*ApUcef)>OQh?;Bx=Ry*2db
z=NEaWTGB&jh5EW=*@4SFeB_;>zpLNmnYA?boe}Eml4S=je|HbOv$VPPoiHb%nuW_}
zxG%Mh<zoQ{Zf~f^ymw@|FUJ86+<d4<thLUXm@N0EmP&b_UO&Aj>laT(WbW@T3f36I
z=O6C5p6Xg(UYK{58=7z+3#T`ex|zFpD(KFnIt!U#kk2!e1Z3gBT|A-GM8nblLUmy8
Ie-J74526(Ex&QzG
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d21799475a2322e259313ecd560ccb842e81d79d
GIT binary patch
literal 1150
zc%03YTTIe%6vzMFmaDD#(rxR($ChpN*jsNsxAjmD7Gn~q!vZe^A^rt4Nf45oToeSk
zDF`HrI2F8BN@)+8#k$%|%eA&z%oy(5|F7AstsYzto!`!H`<-(>=eKiyXFr12L9N_e
zg4*+lqTK{>h#-jLlu{<jvSDAB9O9o#zAlQxVjH&0pHIB~ulT{Hx)TBU4WW-LW7$bE
z$4)YGTKUXE^R>%DOUae|Kk=#2j)Ngp&A3x3%=+~bI2y{}xGhMx)$!8KhEfC#0<_4A
zv(1%-6ZY$jysdlzr@Y_WDE=JxX))DfL$cR~Zfh;(hrM``aAVM=z~h(&)4fI{Jhxzy
zu+pvEf>Shq&Nm4aS%Jxj1!0Q}0b>n9W;wc=YcSo{hMAb1$|XhERE2<EfQUtm`$08K
zqN|HEFA_;yajy~~Q#IvNyc)7=B5{Y#<I_~XAMxuk+@XbEBVLN=YCR#fB;r<9yb0(k
z(b>dD3!ibxcC+Zg+@Kw<`tsCfO(aR~v`BfM=vqbt1{lR9AGh|*EGc?15om->$Qiav
zOFqmFw7{+6!BWjmTWd;F8UZuoxg*5F!zkuQ{7?&-kZ~?#v;tO2!M&I^kt`%52H0iX
z6{EB`J=WO(I>*z56UiPEW`~@3J#`nW3sYE`OJF=`qIx3-{Vs!U72@7TOm!R4uHdh>
z%Gqn7W-{%ny|&n;6=i0kW~|J{@b%>w7H6V(elLjBco2{J9O!RXp+jAj=}?N_c~zn>
zRw-w#Ucg&AX&qgkpUw)#5x11v*QFJ&hK!PISW7O4_0r{lj?4zM(r+<CeJp8GAEjeK
z^(a&)XkZRJL;er`XMfo2J<jri{hQ}*HhUj!+wP42O+ejz_BYMjOF4EC^vAKT$Ikr9
LoIbD-N3-7nrgNc+
--- a/browser/components/downloads/content/downloads.css
+++ b/browser/components/downloads/content/downloads.css
@@ -44,16 +44,17 @@ richlistitem[type="download"]:not([selec
                               [state="4"]) /* Paused             */)
                                            .downloadCancel,
 
 .download-state:not(:-moz-any([state="2"], /* Failed             */
                               [state="4"]) /* Paused             */)
                                            .downloadCancelMenuItem,
 
 .download-state:not(:-moz-any([state="1"], /* Finished           */
+                              [state="2"], /* Failed             */
                               [state="3"], /* Canceled           */
                               [state="6"], /* Blocked (parental) */
                               [state="8"], /* Blocked (dirty)    */
                               [state="9"]) /* Blocked (policy)   */)
                                            .downloadRemoveFromListMenuItem,
 
 .download-state:not(:-moz-any([state="2"], /* Failed             */
                               [state="3"]) /* Canceled           */)
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -51,50 +51,51 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 /**
  * Main entry point for the downloads panel interface.
  */
 const DownloadsPanel = {
   //////////////////////////////////////////////////////////////////////////////
   //// Initialization and termination
 
   /**
-   * State of the downloads panel, based on one of the kPanel constants.
+   * Internal state of the downloads panel, based on one of the kState
+   * constants.  This is not the same state as the XUL panel element.
    */
-  _panelState: 0,
+  _state: 0,
 
-  /** Download data has not been loaded. */
-  get kPanelUninitialized() 0,
-  /** Download data is loading, but the user interface is invisible. */
-  get kPanelHidden() 1,
+  /** The panel is not linked to downloads data yet. */
+  get kStateUninitialized() 0,
+  /** This object is linked to data, but the panel is invisible. */
+  get kStateHidden() 1,
   /** The panel will be shown as soon as possible. */
-  get kPanelShowing() 2,
-  /** The panel is open, though download data might still be loading. */
-  get kPanelShown() 3,
+  get kStateShowing() 2,
+  /** The panel is open. */
+  get kStateShown() 3,
 
   /**
    * Location of the panel overlay.
    */
   get kDownloadsOverlay()
       "chrome://browser/content/downloads/downloadsOverlay.xul",
 
   /**
    * Starts loading the download data in background, without opening the panel.
    * Use showPanel instead to load the data and open the panel at the same time.
    *
    * @param aCallback
    *        Called when initialization is complete.
    */
   initialize: function DP_initialize(aCallback)
   {
-    if (this._panelState != this.kPanelUninitialized) {
+    if (this._state != this.kStateUninitialized) {
       DownloadsOverlayLoader.ensureOverlayLoaded(this.kDownloadsOverlay,
                                                  aCallback);
       return;
     }
-    this._panelState = this.kPanelHidden;
+    this._state = this.kStateHidden;
 
     window.addEventListener("unload", this.onWindowUnload, false);
 
     // Ensure that the Download Manager service is running.  This resumes
     // active downloads if required.  If there are downloads to be shown in the
     // panel, starting the service will make us load their data asynchronously.
     Services.downloads;
 
@@ -110,29 +111,29 @@ const DownloadsPanel = {
 
   /**
    * Closes the downloads panel and frees the internal resources related to the
    * downloads.  The downloads panel can be reopened later, even after this
    * function has been called.
    */
   terminate: function DP_terminate()
   {
-    if (this._panelState == this.kPanelUninitialized) {
+    if (this._state == this.kStateUninitialized) {
       return;
     }
 
     window.removeEventListener("unload", this.onWindowUnload, false);
 
     // Ensure that the panel is closed before shutting down.
     this.hidePanel();
 
     DownloadsViewController.terminate();
     DownloadsCommon.data.removeView(DownloadsView);
 
-    this._panelState = this.kPanelUninitialized;
+    this._state = this.kStateUninitialized;
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// Panel interface
 
   /**
    * Main panel element in the browser window.
    */
@@ -158,17 +159,17 @@ const DownloadsPanel = {
     this.initialize(function DP_SP_callback() {
       // Delay displaying the panel because this function will sometimes be
       // called while another window is closing (like the window for selecting
       // whether to save or open the file), and that would cause the panel to
       // close immediately.
       setTimeout(function () DownloadsPanel._openPopupIfDataReady(), 0);
     }.bind(this));
 
-    this._panelState = this.kPanelShowing;
+    this._state = this.kStateShowing;
   },
 
   /**
    * Hides the downloads panel, if visible, but keeps the internal state so that
    * the panel can be reopened quickly if required.
    */
   hidePanel: function DP_hidePanel()
   {
@@ -176,26 +177,26 @@ const DownloadsPanel = {
       return;
     }
 
     this.panel.hidePopup();
 
     // Ensure that we allow the panel to be reopened.  Note that, if the popup
     // was open, then the onPopupHidden event handler has already updated the
     // current state, otherwise we must update the state ourselves.
-    this._panelState = this.kPanelHidden;
+    this._state = this.kStateHidden;
   },
 
   /**
    * Indicates whether the panel is shown or will be shown.
    */
   get isPanelShowing()
   {
-    return this._panelState == this.kPanelShowing ||
-           this._panelState == this.kPanelShown;
+    return this._state == this.kStateShowing ||
+           this._state == this.kStateShown;
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// Callback functions from DownloadsView
 
   /**
    * Called after data loading finished.
    */
@@ -215,16 +216,18 @@ const DownloadsPanel = {
 
   onPopupShown: function DP_onPopupShown(aEvent)
   {
     // Ignore events raised by nested popups.
     if (aEvent.target != aEvent.currentTarget) {
       return;
     }
 
+    this._state = this.kStateShown;
+
     // Since at most one popup is open at any given time, we can set globally.
     DownloadsCommon.indicatorData.attentionSuppressed = true;
 
     // Ensure that an item is selected when the panel is focused.
     if (DownloadsView.richListBox.itemCount > 0 &&
         !DownloadsView.richListBox.selectedItem) {
       DownloadsView.richListBox.selectedIndex = 0;
     }
@@ -241,17 +244,17 @@ const DownloadsPanel = {
 
     // Since at most one popup is open at any given time, we can set globally.
     DownloadsCommon.indicatorData.attentionSuppressed = false;
 
     // Allow the anchor to be hidden.
     DownloadsButton.releaseAnchor();
 
     // Allow the panel to be reopened.
-    this._panelState = this.kPanelHidden;
+    this._state = this.kStateHidden;
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// Related operations
 
   /**
    * Shows or focuses the user interface dedicated to downloads history.
    */
@@ -270,17 +273,17 @@ const DownloadsPanel = {
 
   /**
    * Move focus to the main element in the downloads panel, unless another
    * element in the panel is already focused.
    */
   _focusPanel: function DP_focusPanel()
   {
     // We may be invoked while the panel is still waiting to be shown.
-    if (this._panelState != this.kPanelShown) {
+    if (this._state != this.kStateShown) {
       return;
     }
 
     let element = document.commandDispatcher.focusedElement;
     while (element && element != this.panel) {
       element = element.parentNode;
     }
     if (!element) {
@@ -290,29 +293,37 @@ const DownloadsPanel = {
 
   /**
    * Opens the downloads panel when data is ready to be displayed.
    */
   _openPopupIfDataReady: function DP_openPopupIfDataReady()
   {
     // We don't want to open the popup if we already displayed it, or if we are
     // still loading data.
-    if (this._panelState != this.kPanelShowing || DownloadsView.loading) {
+    if (this._state != this.kStateShowing || DownloadsView.loading) {
       return;
     }
 
-    this._panelState = this.kPanelShown;
-
     // Make sure that clicking outside the popup cannot reopen it accidentally.
     this.panel.popupBoxObject.setConsumeRollupEvent(Ci.nsIPopupBoxObject
                                                       .ROLLUP_CONSUME);
 
     // Ensure the anchor is visible.  If that is not possible, show the panel
     // anchored to the top area of the window, near the default anchor position.
     DownloadsButton.getAnchor(function DP_OPIDR_callback(aAnchor) {
+      // At this point, if the window is minimized, opening the panel could fail
+      // without any notification, and there would be no way to either open or
+      // close the panel anymore.  To prevent this, check if the window is
+      // minimized and in that case force the panel to the closed state.
+      if (window.windowState == Ci.nsIDOMChromeWindow.STATE_MINIMIZED) {
+        DownloadsButton.releaseAnchor();
+        this._state = this.kStateHidden;
+        return;
+      }
+
       if (aAnchor) {
         this.panel.openPopup(aAnchor, "bottomcenter topright", 0, 0, false,
                              null);
       } else {
         this.panel.openPopup(document.getElementById("TabsToolbar"),
                              "after_end", 0, 0, false, null);
       }
     }.bind(this));
--- a/browser/components/downloads/src/DownloadsCommon.jsm
+++ b/browser/components/downloads/src/DownloadsCommon.jsm
@@ -390,21 +390,16 @@ const DownloadsData = {
     }
     this.dataItems[aDownloadId] = null;
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// Persistent data loading
 
   /**
-   * Asynchronous database statement used to read the list of downloads.
-   */
-  _statement: null,
-
-  /**
    * Represents an executing statement, allowing its cancellation.
    */
   _pendingStatement: null,
 
   /**
    * Indicates which kind of items from the persistent downloads database have
    * been fully loaded in memory and are available to the views.  This can
    * assume the value of one of the kLoad constants.
@@ -450,37 +445,42 @@ const DownloadsData = {
 
         // Indicate to the views that the batch loading operation is complete.
         this._views.forEach(
           function (view) view.onDataLoadCompleted()
         );
       }
     } else {
       if (this._loadState != this.kLoadAll) {
-        // Reload the list from the database asynchronously.
-        this._statement = Services.downloads.DBConnection.createAsyncStatement(
-                                "SELECT * FROM moz_downloads ORDER BY id DESC");
-        this._pendingStatement = this._statement.executeAsync(this);
+        // Load only the relevant columns from the downloads database.  The
+        // columns are read in the init_FromDataRow method of DownloadsDataItem.
+        let statement = Services.downloads.DBConnection.createAsyncStatement(
+          "SELECT id, target, name, source, referrer, state, "
+        +        "startTime, endTime, currBytes, maxBytes "
+        + "FROM moz_downloads "
+        + "ORDER BY id DESC"
+        );
+        try {
+          this._pendingStatement = statement.executeAsync(this);
+        } finally {
+          statement.finalize();
+        }
       }
     }
   },
 
   /**
    * Cancels any pending data access and ensures views are notified.
    */
   _terminateDataAccess: function DD_terminateDataAccess()
   {
     if (this._pendingStatement) {
       this._pendingStatement.cancel();
       this._pendingStatement = null;
     }
-    if (this._statement) {
-      this._statement.finalize();
-      this._statement = null;
-    }
 
     // Close all the views on the current data.  Create a copy of the array
     // because some views might unregister while processing this event.
     Array.slice(this._views, 0).forEach(
       function (view) view.onDataInvalidated()
     );
   },
 
--- a/browser/components/downloads/src/DownloadsUI.js
+++ b/browser/components/downloads/src/DownloadsUI.js
@@ -73,16 +73,21 @@ DownloadsUI.prototype = {
       // "browser.download.manager.showWhenStarting" and
       // "browser.download.manager.focusWhenStarting" preferences.
       return;
     }
 
     // Show the panel in the most recent browser window, if present.
     let browserWin = gBrowserGlue.getMostRecentBrowserWindow();
     if (browserWin) {
+      // The most recent browser window could have been minimized, in that case
+      // it must be restored to allow the panel to open properly.
+      if (browserWin.windowState == Ci.nsIDOMChromeWindow.STATE_MINIMIZED) {
+        browserWin.restore();
+      }
       browserWin.focus();
       browserWin.DownloadsPanel.showPanel();
       return;
     }
 
     // If no browser window is visible and the user requested to show the
     // current downloads, try and open a new window.  We'll open the panel when
     // delayed loading is finished.
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -1361,17 +1361,17 @@ FeedWriter.prototype = {
   function FW__setFaviconForWebReader(aReaderUrl, aMenuItem) {
     var readerURI = makeURI(aReaderUrl);
     if (!/^https?/.test(readerURI.scheme)) {
       // Don't try to get a favicon for non http(s) URIs.
       return;
     }
     var faviconURI = makeURI(readerURI.prePath + "/favicon.ico");
     var self = this;
-    this._faviconService.setAndLoadFaviconForPage(readerURI, faviconURI, false,
+    this._faviconService.setAndFetchFaviconForPage(readerURI, faviconURI, false,
       function (aURI, aDataLen, aData, aMimeType) {
         if (aDataLen > 0) {
           var dataURL = "data:" + aMimeType + ";base64," +
                         btoa(String.fromCharCode.apply(null, aData));
           self._contentSandbox.menuItem = aMenuItem;
           self._contentSandbox.dataURL = dataURL;
           var codeStr = "menuItem.setAttribute('image', dataURL);";
           Cu.evalInSandbox(codeStr, self._contentSandbox);
--- a/browser/components/feeds/src/WebContentConverter.js
+++ b/browser/components/feeds/src/WebContentConverter.js
@@ -443,19 +443,18 @@ WebContentConverterRegistrar.prototype =
     var buttons, message;
     if (this._protocolHandlerRegistered(aProtocol, uri.spec))
       message = this._getFormattedString("protocolHandlerRegistered",
                                          [aTitle, aProtocol]);
     else {
       // Now Ask the user and provide the proper callback
       message = this._getFormattedString("addProtocolHandler",
                                          [aTitle, uri.host, aProtocol]);
-      var fis = Cc["@mozilla.org/browser/favicon-service;1"].
-                getService(Ci.nsIFaviconService);
-      var notificationIcon = fis.getFaviconLinkForIcon(uri);
+
+      var notificationIcon = uri.prePath + "/favicon.ico";
       var notificationValue = "Protocol Registration: " + aProtocol;
       var addButton = {
         label: this._getString("addProtocolHandlerAddButton"),
         accessKey: this._getString("addHandlerAddButtonAccesskey"),
         protocolInfo: { protocol: aProtocol, uri: uri.spec, name: aTitle },
 
         callback:
         function WCCR_addProtocolHandlerButtonCallback(aNotification, aButtonInfo) {
--- a/browser/components/places/tests/browser/browser_toolbar_migration.js
+++ b/browser/components/places/tests/browser/browser_toolbar_migration.js
@@ -3,28 +3,29 @@
  */
 
 /**
  * Tests PersonalToolbar migration path.
  */
 
 let bg = Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver);
 let gOriginalMigrationVersion;
+const BROWSER_URL = getBrowserURL();
 
 let localStore = {
   get RDF() Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService),
   get store() this.RDF.GetDataSource("rdf:local-store"),
 
   get toolbar()
   {
     delete this.toolbar;
-    let toolbar = this.RDF.GetResource("chrome://browser/content/browser.xul#PersonalToolbar");
+    let toolbar = this.RDF.GetResource(BROWSER_URL + "#PersonalToolbar");
     // Add the entry to the persisted set for this document if it's not there.
     // See nsXULDocument::Persist.
-    let doc = this.RDF.GetResource("chrome://browser/content/browser.xul");
+    let doc = this.RDF.GetResource(BROWSER_URL);
     let persist = this.RDF.GetResource("http://home.netscape.com/NC-rdf#persist");
     if (!this.store.HasAssertion(doc, persist, toolbar, true)) {
       this.store.Assert(doc, persist, toolbar, true);
     }
     return this.toolbar = toolbar;
   },
 
   getPersist: function getPersist(aProperty)
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -128,16 +128,20 @@ PrivateBrowsingService.prototype = {
   _autoStarted: false,
 
   // List of view source window URIs for restoring later
   _viewSrcURLs: [],
 
   // Whether private browsing has been turned on from the command line
   _lastChangedByCommandLine: false,
 
+  // Telemetry measurements
+  _enterTimestamps: {},
+  _exitTimestamps: {},
+
   // XPCOM registration
   classID: Components.ID("{c31f4883-839b-45f6-82ad-a6a9bc5ad599}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPrivateBrowsingService, 
                                          Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference,
                                          Ci.nsICommandLineHandler]),
 
@@ -303,31 +307,77 @@ PrivateBrowsingService.prototype = {
   _notifyIfTransitionComplete: function PBS__notifyIfTransitionComplete() {
     switch (this._currentStatus) {
       case STATE_TRANSITION_STARTED:
         // no session store operation was needed, so just notify of transition completion
       case STATE_RESTORE_FINISHED:
         // restore has been completed
         this._currentStatus = STATE_IDLE;
         this._obs.notifyObservers(null, "private-browsing-transition-complete", "");
+        this._recordTransitionTime("completed");
         break;
       case STATE_WAITING_FOR_RESTORE:
         // too soon to notify...
         break;
       case STATE_IDLE:
         // no need to notify
         break;
       default:
         // unexpected state observed
         Cu.reportError("Unexpected private browsing status reached: " +
                        this._currentStatus);
         break;
     }
   },
 
+  _recordTransitionTime: function PBS__recordTransitionTime(aPhase) {
+    // To record the time spent in private browsing transitions, note that we
+    // cannot use the TelemetryStopwatch module, because it reports its results
+    // immediately when the timer is stopped.  In this case, we need to delay
+    // the actual histogram update after we are out of private browsing mode.
+    if (this._inPrivateBrowsing) {
+      this._enterTimestamps[aPhase] = Date.now();
+    } else {
+      if (this._quitting) {
+        // If we are quitting the browser, we don't care collecting the data,
+        // because we wouldn't be able to record it with telemetry.
+        return;
+      }
+      this._exitTimestamps[aPhase] = Date.now();
+      if (aPhase == "completed") {
+        // After we finished exiting the private browsing mode, we can finally
+        // record the telemetry data, for the enter and the exit processes.
+        this._reportTelemetry();
+      }
+    }
+  },
+
+  _reportTelemetry: function PBS__reportTelemetry() {
+    function reportTelemetryEntry(aHistogramId, aValue) {
+      try {
+        Services.telemetry.getHistogramById(aHistogramId).add(aValue);
+      } catch (ex) {
+        Cu.reportError(ex);
+      }
+    }
+
+    reportTelemetryEntry(
+          "PRIVATE_BROWSING_TRANSITION_ENTER_PREPARATION_MS",
+          this._enterTimestamps.prepared - this._enterTimestamps.started);
+    reportTelemetryEntry(
+          "PRIVATE_BROWSING_TRANSITION_ENTER_TOTAL_MS",
+          this._enterTimestamps.completed - this._enterTimestamps.started);
+    reportTelemetryEntry(
+          "PRIVATE_BROWSING_TRANSITION_EXIT_PREPARATION_MS",
+          this._exitTimestamps.prepared - this._exitTimestamps.started);
+    reportTelemetryEntry(
+          "PRIVATE_BROWSING_TRANSITION_EXIT_TOTAL_MS",
+          this._exitTimestamps.completed - this._exitTimestamps.started);
+  },
+
   _canEnterPrivateBrowsingMode: function PBS__canEnterPrivateBrowsingMode() {
     let cancelEnter = Cc["@mozilla.org/supports-PRBool;1"].
                       createInstance(Ci.nsISupportsPRBool);
     cancelEnter.data = false;
     this._obs.notifyObservers(cancelEnter, "private-browsing-cancel-vote", "enter");
     return !cancelEnter.data;
   },
 
@@ -532,30 +582,34 @@ PrivateBrowsingService.prototype = {
       this._ensureCanCloseWindows();
 
       // start the transition now that we know that we can
       this._currentStatus = STATE_TRANSITION_STARTED;
 
       this._autoStarted = this._prefs.getBoolPref("browser.privatebrowsing.autostart");
       this._inPrivateBrowsing = val != false;
 
+      this._recordTransitionTime("started");
+
       let data = val ? "enter" : "exit";
 
       let quitting = Cc["@mozilla.org/supports-PRBool;1"].
                      createInstance(Ci.nsISupportsPRBool);
       quitting.data = this._quitting;
 
       // notify observers of the pending private browsing mode change
       this._obs.notifyObservers(quitting, "private-browsing-change-granted", data);
 
       // destroy the current session and start initial cleanup
       this._onBeforePrivateBrowsingModeChange();
 
       this._obs.notifyObservers(quitting, "private-browsing", data);
 
+      this._recordTransitionTime("prepared");
+
       // load the appropriate session
       this._onAfterPrivateBrowsingModeChange();
     } catch (ex) {
       // We aborted the transition to/from private browsing, we must restore the
       // beforeunload handling on all the windows for which we switched it off.
       for (let i = 0; i < this._windowsToClose.length; i++)
         this._windowsToClose[i].docShell.contentViewer.resetCloseWindow();
       // We don't log an error when the transition is canceled from beforeunload
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
@@ -32,17 +32,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 function test() {
   // We need to open a new window for this so that its docshell would get destroyed
   // when clearing the PB mode flag.
-  let newWin = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no");
+  let newWin = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
   waitForExplicitFinish();
   SimpleTest.waitForFocus(function() {
     let notificationCount = 0;
     let observer = {
       observe: function(aSubject, aTopic, aData) {
         is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched");
         ++notificationCount;
       }
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/unit/do_test_privatebrowsing_telemetry.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "gPrivateBrowsing",
+                                   PRIVATEBROWSING_CONTRACT_ID,
+                                   "nsIPrivateBrowsingService");
+
+function waitForTransition(aEnabled, aCallback) {
+  Services.obs.addObserver(function PBT_transition(aSubject, aTopic, aData) {
+    Services.obs.removeObserver(PBT_transition, aTopic, false);
+    // Telemetry data is recorded just after the private browsing transition
+    // observers are notified, thus we must wait for this observer to return.
+    do_execute_soon(aCallback);
+  }, "private-browsing-transition-complete", false);
+  gPrivateBrowsing.privateBrowsingEnabled = aEnabled;
+}
+
+function checkHistogram(aId) {
+  // Check that we have data either in the first bucket (that doesn't
+  // count towards the sum) or one of the other buckets, by checking
+  // the sum of the values.
+  let snapshot = Services.telemetry.getHistogramById(aId).snapshot();
+  do_check_true(snapshot.sum > 0 || snapshot.counts[0] > 0);
+}
+
+function do_test() {
+  do_test_pending();
+
+  waitForTransition(true, function PBT_enabled() {
+    waitForTransition(false, function PBT_disabled() {
+      checkHistogram("PRIVATE_BROWSING_TRANSITION_ENTER_PREPARATION_MS");
+      checkHistogram("PRIVATE_BROWSING_TRANSITION_ENTER_TOTAL_MS");
+      checkHistogram("PRIVATE_BROWSING_TRANSITION_EXIT_PREPARATION_MS");
+      checkHistogram("PRIVATE_BROWSING_TRANSITION_EXIT_TOTAL_MS");
+
+      do_test_finished();
+    });
+  });
+}
copy from browser/components/privatebrowsing/test/unit/test_privatebrowsing_autostart.js
copy to browser/components/privatebrowsing/test/unit/test_privatebrowsing_telemetry.js
--- a/browser/components/privatebrowsing/test/unit/test_privatebrowsing_autostart.js
+++ b/browser/components/privatebrowsing/test/unit/test_privatebrowsing_telemetry.js
@@ -30,15 +30,15 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-// This test checks the browser.privatebrowsing.autostart preference.
+// Checks that telemetry data for private browsing transitions is recorded.
 
 function run_test() {
   PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing;1";
-  load("do_test_privatebrowsing_autostart.js");
+  load("do_test_privatebrowsing_telemetry.js");
   do_test();
 }
copy from browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_autostart.js
copy to browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_telemetry.js
--- a/browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_autostart.js
+++ b/browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_telemetry.js
@@ -30,15 +30,15 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-// This test checks the browser.privatebrowsing.autostart preference.
+// Checks that telemetry data for private browsing transitions is recorded.
 
 function run_test() {
   PRIVATEBROWSING_CONTRACT_ID = "@mozilla.org/privatebrowsing-wrapper;1";
-  load("do_test_privatebrowsing_autostart.js");
+  load("do_test_privatebrowsing_telemetry.js");
   do_test();
 }
--- a/browser/components/privatebrowsing/test/unit/xpcshell.ini
+++ b/browser/components/privatebrowsing/test/unit/xpcshell.ini
@@ -7,17 +7,19 @@ tail = tail_privatebrowsing.js
 [test_aboutprivatebrowsing.js]
 [test_geoClearCookie.js]
 [test_httpauth.js]
 [test_openLocationLastURL.js]
 [test_placesTitleNoUpdate.js]
 [test_privatebrowsing_autostart.js]
 [test_privatebrowsing_commandline.js]
 [test_privatebrowsing_exit.js]
+[test_privatebrowsing_telemetry.js]
 [test_privatebrowsingwrapper_autostart.js]
 [test_privatebrowsingwrapper_commandline.js]
 [test_privatebrowsingwrapper_exit.js]
 [test_privatebrowsingwrapper_placesTitleNoUpdate.js]
 [test_privatebrowsingwrapper_removeDataFromDomain.js]
 [test_privatebrowsingwrapper_removeDataFromDomain_activeDownloads.js]
+[test_privatebrowsingwrapper_telemetry.js]
 [test_removeDataFromDomain.js]
 [test_removeDataFromDomain_activeDownloads.js]
 [test_transition_nooffline.js]
--- a/browser/components/sessionstore/test/browser_394759_basic.js
+++ b/browser/components/sessionstore/test/browser_394759_basic.js
@@ -68,22 +68,25 @@ function whenWindowLoaded(aWin, aCallbac
 function test() {
   waitForExplicitFinish();
 
   let testURL = "about:config";
   let uniqueKey = "bug 394759";
   let uniqueValue = "unik" + Date.now();
   let uniqueText = "pi != " + Math.random();
 
+  // Be consistent: let the page actually display, as we are "interacting" with it.
+  Services.prefs.setBoolPref("general.warnOnAboutConfig", false);
+
   // make sure that the next closed window will increase getClosedWindowCount
-  let max_windows_undo = gPrefService.getIntPref("browser.sessionstore.max_windows_undo");
-  gPrefService.setIntPref("browser.sessionstore.max_windows_undo", max_windows_undo + 1);
+  let max_windows_undo = Services.prefs.getIntPref("browser.sessionstore.max_windows_undo");
+  Services.prefs.setIntPref("browser.sessionstore.max_windows_undo", max_windows_undo + 1);
   let closedWindowCount = ss.getClosedWindowCount();
 
-  provideWindow(function (newWin) {
+  provideWindow(function onTestURLLoaded(newWin) {
     newWin.gBrowser.addTab().linkedBrowser.stop();
 
     // mark the window with some unique data to be restored later on
     ss.setWindowValue(newWin, uniqueKey, uniqueValue);
     let textbox = newWin.content.document.getElementById("textbox");
     textbox.value = uniqueText;
 
     newWin.close();
@@ -100,33 +103,36 @@ function test() {
     ok(newWin2 instanceof ChromeWindow,
        "undoCloseWindow actually returned a window");
     is(ss.getClosedWindowCount(), closedWindowCount,
        "The reopened window was removed from Recently Closed Windows");
 
     // SSTabRestored will fire more than once, so we need to make sure we count them
     let restoredTabs = 0;
     let expectedTabs = data.tabs.length;
-    whenWindowLoaded(newWin2, function () {
-      newWin2.gBrowser.tabContainer.addEventListener("SSTabRestored", function(aEvent) {
-        if (++restoredTabs < expectedTabs)
-          return;
-        newWin2.gBrowser.tabContainer.removeEventListener("SSTabRestored", arguments.callee, true);
+    newWin2.addEventListener("SSTabRestored", function sstabrestoredListener(aEvent) {
+      ++restoredTabs;
+      info("Restored tab " + restoredTabs + "/" + expectedTabs);
+      if (restoredTabs < expectedTabs) {
+        return;
+      }
 
-        is(newWin2.gBrowser.tabs.length, 2,
-           "The window correctly restored 2 tabs");
-        is(newWin2.gBrowser.currentURI.spec, testURL,
-           "The window correctly restored the URL");
+      newWin2.removeEventListener("SSTabRestored", sstabrestoredListener, true);
 
-        let textbox = newWin2.content.document.getElementById("textbox");
-        is(textbox.value, uniqueText,
-           "The window correctly restored the form");
-        is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
-           "The window correctly restored the data associated with it");
+      is(newWin2.gBrowser.tabs.length, 2,
+         "The window correctly restored 2 tabs");
+      is(newWin2.gBrowser.currentURI.spec, testURL,
+         "The window correctly restored the URL");
 
-        // clean up
-        newWin2.close();
-        gPrefService.clearUserPref("browser.sessionstore.max_windows_undo");
-        finish();
-      }, true);
-    });
+      let textbox = newWin2.content.document.getElementById("textbox");
+      is(textbox.value, uniqueText,
+         "The window correctly restored the form");
+      is(ss.getWindowValue(newWin2, uniqueKey), uniqueValue,
+         "The window correctly restored the data associated with it");
+
+      // clean up
+      newWin2.close();
+      Services.prefs.clearUserPref("browser.sessionstore.max_windows_undo");
+      Services.prefs.clearUserPref("general.warnOnAboutConfig");
+      finish();
+    }, true);
   }, testURL);
 }
--- a/browser/devtools/webconsole/test/browser_webconsole_chrome.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_chrome.js
@@ -35,20 +35,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that code completion works properly.
 
-const TEST_URI = "chrome://browser/content/browser.xul";
-
 function test() {
-  addTab(TEST_URI);
+  addTab(getBrowserURL());
   browser.addEventListener("DOMContentLoaded", testChrome, false);
 }
 
 function testChrome() {
   browser.removeEventListener("DOMContentLoaded", testChrome, false);
 
   openConsole();
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -632,13 +632,14 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/webapp-uninstaller@BIN_SUFFIX@
 #endif
 @BINPATH@/webapprt-stub@BIN_SUFFIX@
 @BINPATH@/webapprt/webapprt.ini
 @BINPATH@/webapprt/chrome.manifest
 @BINPATH@/webapprt/chrome/webapprt@JAREXT@
 @BINPATH@/webapprt/chrome/webapprt.manifest
 @BINPATH@/webapprt/components/CommandLineHandler.js
+@BINPATH@/webapprt/components/ContentPolicy.js
 @BINPATH@/webapprt/components/DirectoryProvider.js
 @BINPATH@/webapprt/components/components.manifest
 @BINPATH@/webapprt/defaults/preferences/prefs.js
 @BINPATH@/webapprt/modules/WebappRT.jsm
 #endif
--- a/browser/modules/NewTabUtils.jsm
+++ b/browser/modules/NewTabUtils.jsm
@@ -22,16 +22,19 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyModuleGetter(this, "Dict", "resource://gre/modules/Dict.jsm");
 
 // The preference that tells whether this feature is enabled.
 const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
 
 // The maximum number of results we want to retrieve from history.
 const HISTORY_RESULTS_LIMIT = 100;
 
+// The gather telemetry topic.
+const TOPIC_GATHER_TELEMETRY = "gather-telemetry";
+
 /**
  * Singleton that provides storage functionality.
  */
 let Storage = {
   /**
    * The dom storage instance used to persist data belonging to the New Tab Page.
    */
   get domStorage() {
@@ -581,16 +584,57 @@ let Links = {
     this._addObserver = function () {};
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference])
 };
 
 /**
+ * Singleton used to collect telemetry data.
+ *
+ */
+let Telemetry = {
+  /**
+   * Initializes object.
+   */
+  init: function Telemetry_init() {
+    Services.obs.addObserver(this, TOPIC_GATHER_TELEMETRY, false);
+  },
+
+  /**
+   * Collects data.
+   */
+  _collect: function Telemetry_collect() {
+    let probes = [
+      { histogram: "NEWTAB_PAGE_ENABLED",
+        value: AllPages.enabled },
+      { histogram: "NEWTAB_PAGE_PINNED_SITES_COUNT",
+        value: PinnedLinks.links.length },
+      { histogram: "NEWTAB_PAGE_BLOCKED_SITES_COUNT",
+        value: Object.keys(BlockedLinks.links).length }
+    ];
+
+    probes.forEach(function Telemetry_collect_forEach(aProbe) {
+      Services.telemetry.getHistogramById(aProbe.histogram)
+        .add(aProbe.value);
+    });
+  },
+
+  /**
+   * Listens for gather telemetry topic.
+   */
+  observe: function Telemetry_observe(aSubject, aTopic, aData) {
+    this._collect();
+  }
+};
+
+Telemetry.init();
+
+/**
  * Singleton that provides the public API of this JSM.
  */
 let NewTabUtils = {
   /**
    * Restores all sites that have been removed from the grid.
    */
   restore: function NewTabUtils_restore() {
     Storage.clear();
--- a/browser/modules/WindowsJumpLists.jsm
+++ b/browser/modules/WindowsJumpLists.jsm
@@ -136,29 +136,29 @@ var tasksCfg = [
    * open        - Boolean indicates if the command should be visible after the browser opens.
    * close       - Boolean indicates if the command should be visible after the browser closes.
    */
   // Open new window
   {
     get title()       _getString("taskbar.tasks.newTab.label"),
     get description() _getString("taskbar.tasks.newTab.description"),
     args:             "-new-tab about:blank",
-    iconIndex:        0, // Fx app icon
+    iconIndex:        3, // New window icon
     open:             true,
     close:            true, // The jump list already has an app launch icon, but
                             // we don't always update the list on shutdown.
                             // Thus true for consistency.
   },
 
   // Open new tab
   {
     get title()       _getString("taskbar.tasks.newWindow.label"),
     get description() _getString("taskbar.tasks.newWindow.description"),
     args:             "-browser",
-    iconIndex:        0, // Fx app icon
+    iconIndex:        2, // New tab icon
     open:             true,
     close:            true, // No point, but we don't always update the list on
                             //  shutdown.  Thus true for consistency.
   },
 
   // Toggle the Private Browsing mode
   {
     get title() {
@@ -169,17 +169,17 @@ var tasksCfg = [
     },
     get description() {
       if (_privateBrowsingSvc.privateBrowsingEnabled)
         return _getString("taskbar.tasks.exitPrivacyMode.description");
       else
         return _getString("taskbar.tasks.enterPrivacyMode.description");
     },
     args:             "-private-toggle",
-    iconIndex:        0, // Fx app icon
+    iconIndex:        4, // Private browsing mode icon
     get open() {
       // Don't show when inside permanent private browsing mode
       return !_privateBrowsingSvc.autoStarted;
     },
     get close() {
       // Don't show when inside permanent private browsing mode
       return !_privateBrowsingSvc.autoStarted;
     },
new file mode 100644
--- /dev/null
+++ b/build/mobile/b2gautomation.py
@@ -0,0 +1,232 @@
+# 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/.
+
+import automationutils
+import os
+import re
+import socket
+import shutil
+import sys
+import tempfile
+import time
+
+from automation import Automation
+from devicemanager import DeviceManager, NetworkTools
+
+class B2GRemoteAutomation(Automation):
+    _devicemanager = None
+
+    def __init__(self, deviceManager, appName='', remoteLog=None,
+                 marionette=None):
+        self._devicemanager = deviceManager
+        self._appName = appName
+        self._remoteProfile = None
+        self._remoteLog = remoteLog
+        self.marionette = marionette
+
+        # Default our product to b2g
+        self._product = "b2g"
+        Automation.__init__(self)
+
+    def setDeviceManager(self, deviceManager):
+        self._devicemanager = deviceManager
+
+    def setAppName(self, appName):
+        self._appName = appName
+
+    def setRemoteProfile(self, remoteProfile):
+        self._remoteProfile = remoteProfile
+
+    def setProduct(self, product):
+        self._product = product
+
+    def setRemoteLog(self, logfile):
+        self._remoteLog = logfile
+
+    # Set up what we need for the remote environment
+    def environment(self, env=None, xrePath=None, crashreporter=True):
+        # Because we are running remote, we don't want to mimic the local env
+        # so no copying of os.environ
+        if env is None:
+            env = {}
+
+        return env
+
+    def checkForCrashes(self, directory, symbolsPath):
+        # XXX: This will have to be updated after crash reporting on b2g
+        # is in place.
+        dumpDir = tempfile.mkdtemp()
+        self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
+        automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
+        try:
+          shutil.rmtree(dumpDir)
+        except:
+          print "WARNING: unable to remove directory: %s" % (dumpDir)
+
+    def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
+        # if remote profile is specified, use that instead
+        if (self._remoteProfile):
+            profileDir = self._remoteProfile
+
+        cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
+
+        return app, args
+
+    def getLanIp(self):
+        nettools = NetworkTools()
+        return nettools.getLanIp()
+
+    def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime,
+                      debuggerInfo, symbolsPath, logger):
+        """ Wait for mochitest to finish (as evidenced by a signature string
+            in logcat), or for a given amount of time to elapse with no
+            output.
+        """
+        timeout = timeout or 120
+
+        didTimeout = False
+
+        done = time.time() + timeout
+        while True:
+            currentlog = proc.stdout
+            if currentlog:
+                done = time.time() + timeout
+                print currentlog
+                if 'INFO SimpleTest FINISHED' in currentlog:
+                    return 0
+            else:
+                if time.time() > done:
+                    self.log.info("TEST-UNEXPECTED-FAIL | %s | application timed "
+                                  "out after %d seconds with no output",
+                                  self.lastTestSeen, int(timeout))
+                    return 1
+
+    def getDeviceStatus(self, serial=None):
+        # Get the current status of the device.  If we know the device
+        # serial number, we look for that, otherwise we use the (presumably
+        # only) device shown in 'adb devices'.
+        serial = serial or self._devicemanager.deviceSerial
+        status = 'unknown'
+
+        for line in self._devicemanager.runCmd(['devices']).stdout.readlines():
+            result =  re.match('(.*?)\t(.*)', line)
+            if result:
+                thisSerial = result.group(1)
+                if not serial or thisSerial == serial:
+                    serial = thisSerial
+                    status = result.group(2)
+
+        return (serial, status)
+
+    def rebootDevice(self):
+        # find device's current status and serial number
+        serial, status = self.getDeviceStatus()
+
+        # reboot!
+        self._devicemanager.checkCmd(['reboot'])
+
+        # wait for device to come back to previous status
+        print 'waiting for device to come back online after reboot'
+        start = time.time()
+        rserial, rstatus = self.getDeviceStatus(serial)
+        while rstatus != 'device':
+            if time.time() - start > 120:
+                # device hasn't come back online in 2 minutes, something's wrong
+                raise Exception("Device %s (status: %s) not back online after reboot" % (serial, rstatus))
+            time.sleep(5)
+            rserial, rstatus = self.getDeviceStatus(serial)
+        print 'device:', serial, 'status:', rstatus
+
+    def Process(self, cmd, stdout=None, stderr=None, env=None, cwd=None):
+        # On a desktop or fennec run, the Process method invokes a gecko
+        # process in which to run mochitests.  For B2G, we simply
+        # reboot the device (which was configured with a test profile
+        # already), wait for B2G to start up, and then navigate to the
+        # test url using Marionette.  There doesn't seem to be any way
+        # to pass env variables into the B2G process, but this doesn't 
+        # seem to matter.
+
+        instance = self.B2GInstance(self._devicemanager)
+
+        # reboot device so it starts up with the mochitest profile
+        # XXX:  We could potentially use 'stop b2g' + 'start b2g' to achieve
+        # a similar effect; will see which is more stable while attempting
+        # to bring up the continuous integration.
+        self.rebootDevice()
+
+        # Infrequently, gecko comes up before networking does, so wait a little
+        # bit to give the network time to become available.
+        # XXX:  need a more robust mechanism for this
+        time.sleep(20)
+
+        # Set up port forwarding again for Marionette, since any that
+        # existed previously got wiped out by the reboot.
+        self._devicemanager.checkCmd(['forward',
+                                      'tcp:%s' % self.marionette.port,
+                                      'tcp:%s' % self.marionette.port])
+
+        # start a marionette session
+        session = self.marionette.start_session()
+        if 'b2g' not in session:
+            raise Exception("bad session value %s returned by start_session" % session)
+
+        # start the tests by navigating to the mochitest url
+        self.marionette.execute_script("window.location.href='%s';" % self.testURL)
+
+        return instance
+
+    # be careful here as this inner class doesn't have access to outer class members
+    class B2GInstance(object):
+        """Represents a B2G instance running on a device, and exposes
+           some process-like methods/properties that are expected by the
+           automation.
+        """
+
+        def __init__(self, dm):
+            self.dm = dm
+            self.lastloglines = []
+
+        @property
+        def pid(self):
+            # a dummy value to make the automation happy
+            return 0
+
+        @property
+        def stdout(self):
+            # Return any part of logcat output that wasn't returned
+            # previously.  This is done by fetching about the last 50
+            # lines of the log (logcat -t 50 generally fetches 50-58 lines),
+            # and comparing against the previous set to find new lines.
+            t = self.dm.runCmd(['logcat', '-t', '50']).stdout.read()
+            if t == None: return ''
+
+            t = t.strip('\n').strip()
+            loglines = t.split('\n')
+            line_index = 0
+
+            # If there are more than 50 lines, we skip the first 20; this
+            # is because the number of lines returned
+            # by logcat -t 50 varies (usually between 50 and 58).
+            log_index = 20 if len(loglines) > 50 else 0
+
+            for index, line in enumerate(loglines[log_index:]):
+                line_index = index + log_index + 1
+                try:
+                    self.lastloglines.index(line)
+                except ValueError:
+                    break
+
+            newoutput = '\n'.join(loglines[line_index:])
+            self.lastloglines = loglines
+
+            return newoutput
+
+        def wait(self, timeout = None):
+            # this should never happen
+            raise Exception("'wait' called on B2GInstance")
+
+        def kill(self):
+            # this should never happen
+            raise Exception("'kill' called on B2GInstance")
+
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -132,17 +132,17 @@ public class DoCommand {
 
     String    currentDir = "/";
     String    sErrorPrefix = "##AGENT-WARNING## ";
     boolean bTraceOn = false;
 
     String ffxProvider = "org.mozilla.ffxcp";
     String fenProvider = "org.mozilla.fencp";
 
-    private final String prgVersion = "SUTAgentAndroid Version 1.07";
+    private final String prgVersion = "SUTAgentAndroid Version 1.08";
 
     public enum Command
         {
         RUN ("run"),
         EXEC ("exec"),
         EXECCWD ("execcwd"),
         ENVRUN ("envrun"),
         KILL ("kill"),
--- a/caps/tests/mochitest/test_bug246699.html
+++ b/caps/tests/mochitest/test_bug246699.html
@@ -1,34 +1,39 @@
 <!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=246699
 -->
 <head>
   <title>Test for Bug 246699</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.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>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=246699">Mozilla Bug 246699</a>
 <p id="display"></p>
 <div id="content" style="display: none">
-<iframe id="load-frame"></iframe>  
+<iframe id="load-frame"></iframe>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /**
  ** Test for Bug 246699
  ** (should produce stack information for caps errors)
  **/
+function isError(e)
+{
+  return e.constructor.name === "Error" || e.constructor.name === "TypeError";
+}
+
 function hasStack(e)
 {
-  return e.constructor.name === "Error" && /inciteCaps/.test(e.stack);
+  return isError(e) && /inciteCaps/.test(e.stack);
 }
 
 function inciteCaps(f)
 {
     try {
         f();
         return "operation succeeded";
     } catch (e if hasStack(e)) {
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -114,16 +114,17 @@ MOZ_JSDEBUGGER  = @MOZ_JSDEBUGGER@
 MOZ_IPDL_TESTS 	= @MOZ_IPDL_TESTS@
 MOZ_LEAKY	= @MOZ_LEAKY@
 MOZ_MEMORY      = @MOZ_MEMORY@
 MOZ_PROFILING   = @MOZ_PROFILING@
 MOZ_ENABLE_PROFILER_SPS = @MOZ_ENABLE_PROFILER_SPS@
 MOZ_JPROF       = @MOZ_JPROF@
 MOZ_SHARK       = @MOZ_SHARK@
 MOZ_CALLGRIND   = @MOZ_CALLGRIND@
+MOZ_VALGRIND    = @MOZ_VALGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
 MOZ_ETW         = @MOZ_ETW@
 MOZ_TRACE_JSCALLS = @MOZ_TRACE_JSCALLS@
 DEHYDRA_PATH    = @DEHYDRA_PATH@
 
 MOZ_LINKER = @MOZ_LINKER@
 MOZ_OLD_LINKER = @MOZ_OLD_LINKER@
 MOZ_ENABLE_SZIP = @MOZ_ENABLE_SZIP@
--- a/config/makefiles/autotargets.mk
+++ b/config/makefiles/autotargets.mk
@@ -45,13 +45,10 @@ endif
 #################################################################
 # One ring/dep to rule them all:
 #   config/rules.mk::all target is available by default
 #   Add $(AUTO_DEPS) as an explicit target dependency when needed.
 #################################################################
 
 AUTO_DEPS +=$(GENERATED_DIRS_DEPS)
 
-
 # Complain loudly if deps have not loaded so getargv != $(NULL)
-ifndef getargv
-  $(error config/makefiles/makeutil.mk has not been included)
-endif
+$(call requiredfunction,getargv)
--- a/config/makefiles/makeutils.mk
+++ b/config/makefiles/makeutils.mk
@@ -1,22 +1,15 @@
 # -*- makefile -*-
 # vim:set ts=8 sw=8 sts=8 noet:
 #
 # 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/.
 
-# Usage: $(call banner,foo bar tans)
-banner =\
-$(info )\
-$(info ***************************************************************************)\
-$(info ** BANNER: $(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9))\
-$(info ***************************************************************************)\
-
 ## Identify function argument types
 istype =$(if $(value ${1}),list,scalar)
 isval  =$(if $(filter-out list,$(call istype,${1})),true)
 isvar  =$(if $(filter-out scalar,$(call istype,${1})),true)
 
 # Access up to 9 arguments passed, option needed to emulate $*
 # Inline for function expansion, do not use $(call )
 argv  =$(strip
@@ -30,16 +23,72 @@ argv +=)
 ## Access function args as a simple list, inline within user functions.
 ## Usage: $(info ** $(call banner,$(getargv)))
 ##    $(call banner,scalar)
 ##    $(call banner,list0 list1 list2)
 ##    $(call banner,ref) ; ref=foo bar tans
 ## getarglist() would be a more accurate name but is longer to type
 getargv = $(if $(call isvar,$(1)),$($(1)),$(argv))
 
+###########################################################################
+# Strip [n] leading options from an argument list.  This will allow passing
+# extra args to user functions that will not propogate to sub-$(call )'s
+# Usage: $(call subargv,2)
+subargv =$(wordlist $(1),$(words $(getargv)),$(getargv))
+
+###########################################################################
+# Intent: Display a distinct banner heading in the output stream
+# Usage: $(call banner,BUILDING: foo bar tans)
+# Debug:
+#   target-preqs = \
+#     $(call banner,target-preqs-BEGIN) \
+#     foo bar tans \
+#     $(call banner,target-preqs-END) \
+#     $(NULL)
+#   target: $(target-preqs)
+
+banner =\
+$(info )\
+$(info ***************************************************************************)\
+$(info ** $(getargv))\
+$(info ***************************************************************************)\
+$(NULL)
+
+#####################################################################
+# Intent: Determine if a string or pattern is contained in a list
+# Usage: strcmp  - $(call if_XinY,clean,$(MAKECMDGOALS))
+#      : pattern - $(call if_XinY,clean%,$(MAKECMDGOALS))
+is_XinY =$(filter $(1),$(call subargv,3,$(getargv)))
+
+#####################################################################
+# Provide an alternate var to support testing
+ifdef MAKEUTILS_UNIT_TEST
+  mcg_goals=TEST_MAKECMDGOALS
+else
+  mcg_goals=MAKECMDGOALS
+endif
+
+# Intent: Conditionals for detecting common/tier target use
+#   Todo: are check, install, test needed ?
+isTargetStem       = $(sort $(foreach pat, $(1)% %$(1), $(call is_XinY,$(pat),${$(mcg_goals)})))
+isTargetStemClean  = $(call isTargetStem,clean)
+isTargetStemExport = $(call isTargetStem,export)
+isTargetStemLibs   = $(call isTargetStem,libs)
+isTargetStemTools  = $(call isTargetStem,tools)
+
+##################################################
+# Intent: Validation functions / unit test helpers
+
+errorifneq =$(if $(subst $(strip $(1)),$(NULL),$(strip $(2))),$(error expected [$(1)] but found [$(2)]))
+
+# Intent: verify function declaration exists
+requiredfunction =$(foreach func,$(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9),$(if $(value $(func)),$(NULL),$(error required function [$(func)] is unavailable)))
+
+
+
 ## http://www.gnu.org/software/make/manual/make.html#Call-Function
 ## Usage: o = $(call map,origin,o map $(MAKE))
 map = $(foreach val,$(2),$(call $(1),$(val)))
 
 
 ## Disable checking for clean targets
 ifeq (,$(filter %clean clean%,$(MAKECMDGOALS)))
 
--- a/config/makefiles/test/Makefile.in
+++ b/config/makefiles/test/Makefile.in
@@ -5,16 +5,18 @@
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEPTH     = ../../..
 topsrcdir = @top_srcdir@
 srcdir    = @srcdir@
 VPATH     = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
+
+MAKEUTILS_UNIT_TEST = 1
 include $(topsrcdir)/config/makefiles/makeutils.mk
 
 ##------------------_##
 ##---]  TARGETS  [---##
 ##------------------_##
 all::
 
 ###########################################################################
@@ -24,37 +26,41 @@ all::
 ## very handy for testing when pwd==$src/ but for now avoid the overhead.
 ##
 ## Test logic will be interpreted at compile time, 'fast' and 'required' so
 ## the test will always be run when testing is enabled.
 ###########################################################################
 check::
 	@true
 
+###########################################################################
 ## Logic processed at compile time so be selective about when to test
-ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #{
-
+## Verify istype, isval, isvar, getargv, subargv
+ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #
 
 ifdef VERBOSE
 
 $(info ===========================================================================)
 $(info Running test: $(MAKECMDGOALS): pwd=$(CURDIR))
 $(info ===========================================================================)
 
 $(info )
 $(info ===========================================================================)
 $(info Running test: istype, getargv)
 $(info ===========================================================================)
 endif
 
-## Silent errors are oh so much fun
-ifndef istype
-  $(error makeutils.mk was not included)
+ifndef requiredfunction
+  $(error requiredfunction is not defined)
 endif
 
+include $(topsrcdir)/config/makefiles/test/check_XinY.mk
+
+$(call requiredfunc,istype isvar isval)
+
 # arg_scalar = [scalar|literal]
 arg_list = foo bar
 arg_ref  = arg_list
 
 ## Identify type of function argument(s)
 ########################################
 ifneq (scalar,$(call istype,arg_scalar))
   $(error istype(arg_scalar)=scalar, found [$(call istype,arg_scalar)])
@@ -119,9 +125,18 @@ ifdef MANUAL_TEST #{
   xyz=abc
   $(info STATUS: warnIfEmpty - two vars)
   $(call warnIfEmpty,foo xyz bar)
   $(info STATUS: errorIfEmpty - on first var)
   $(call errorIfEmpty,foo xyz bar)
   $(error TEST FAILED: processing should not reach this point)
 endif #}
 
-endif #} check in MAKECMDGOALS
+# Verify subargv expansion
+##########################
+subargs=foo bar tans fans
+subargs_exp=tans fans
+subargs_found=$(call subargv,4,$(subargs))
+ifneq ($(subargs_exp),$(subargs_found))
+  $(error subargv(4,$(subargs)): expected [$(subargs_exp)] found [$(subargs_found)])
+endif
+ 
+endif #} unit_test: istype, isvar, isval, getargv, subargv
new file mode 100644
--- /dev/null
+++ b/config/makefiles/test/check_XinY.mk
@@ -0,0 +1,47 @@
+# -*- makefile -*-
+#
+# 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/.
+
+# Verify dependencies are available
+$(call requiredfunction,getargv subargv is_XinY errorifneq)
+
+#############################
+ifdef VERBOSE
+  $(warning )
+  $(call banner,Unit test: is_XinY)
+endif
+
+zero := 0
+one  := 1
+
+# Verify 'invalid' is not matched
+val  := invalid
+$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
+$(call errorifneq,$(zero),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(zero),$(words $(call is_XinY,clean%,$(val))))
+
+# verify strcmp('clean')
+val  := clean
+$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(one,$(words $(call is_XinY,clean%,$(val)))))
+$(call errorifneq,$(one),$(words $(call is_XinY,%clean,$(val))))
+
+# List match for 'clean'
+val     := blah clean distclean FcleanG clean-level-1
+wanted  := clean distclean clean-level-1
+$(call errorifneq,$(zero),$(words $(call is_XinY_debug,foo,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,distclean,$(val))))
+
+# pattern match 'clean'
+#     match: clean, distclean, clean-level-1
+#   exclude: FcleanG
+TEST_MAKECMDGOALS := $(val)
+$(call errorifneq,3,$(words $(call isTargetStemClean)))
+
+TEST_MAKECMDGOALS := invalid
+$(call errorifneq,$(zero),$(words $(call isTargetStemClean)))
+
--- a/configure.in
+++ b/configure.in
@@ -4604,25 +4604,17 @@ NECKO_WIFI=1
 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
-
-case "${target}" in
-*darwin*)
-    ACCESSIBILITY=
-    ;;
-*)
-    ACCESSIBILITY=1
-    ;;
-esac
+ACCESSIBILITY=1
 
 case "$target_os" in
     mingw*)
         NS_ENABLE_TSF=1
         AC_DEFINE(NS_ENABLE_TSF)
         ;;
 esac
 
@@ -5545,20 +5537,19 @@ MOZ_ARG_DISABLE_BOOL(dbm,
     NSS_DISABLE_DBM=)
 
 dnl bi-directional support always on
 IBMBIDI=1
 AC_DEFINE(IBMBIDI)
 
 dnl ========================================================
 dnl accessibility support on by default on all platforms
-dnl except OS X.
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(accessibility,
-[  --disable-accessibility Disable accessibility support (off by default on OS X)],
+[  --disable-accessibility Disable accessibility support],
     ACCESSIBILITY=,
     ACCESSIBILITY=1 )
 if test "$ACCESSIBILITY"; then
     AC_DEFINE(ACCESSIBILITY)
 fi
 
 dnl ========================================================
 dnl Disable printing
@@ -5830,24 +5821,20 @@ if test -n "$MOZ_TREMOR"; then
     AC_DEFINE(MOZ_TREMOR)
 fi
 
 dnl ========================================================
 dnl = Check alsa availability on Linux if using sydneyaudio
 dnl ========================================================
 
 dnl If using sydneyaudio with Linux, ensure that the alsa library is available
-if test -n "$MOZ_SYDNEYAUDIO"; then
-   case "$target_os" in
-linux*)
-      PKG_CHECK_MODULES(MOZ_ALSA, alsa, ,
+if test -n "$MOZ_SYDNEYAUDIO" -a "$OS_TARGET" = "Linux"; then
+    PKG_CHECK_MODULES(MOZ_ALSA, alsa, ,
          [echo "$MOZ_ALSA_PKG_ERRORS"
           AC_MSG_ERROR([Need alsa for Ogg, Wave or WebM decoding on Linux.  Disable with --disable-ogg --disable-wave --disable-webm.  (On Ubuntu, you might try installing the package libasound2-dev.)])])
-      ;;
-   esac
 fi
 
 dnl ========================================================
 dnl = Enable GStreamer
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gstreamer,
 [  --enable-gstreamer           Enable GStreamer support],
 MOZ_GSTREAMER=1,
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -397,17 +397,17 @@ public:
    * Return whether the node is an Element node
    */
   bool IsElement() const {
     return GetBoolFlag(NodeIsElement);
   }
 
   /**
    * Return this node as an Element.  Should only be used for nodes
-   * for which IsElement() is true.
+   * for which IsElement() is true.  This is defined inline in Element.h.
    */
   mozilla::dom::Element* AsElement();
 
   virtual nsIDOMNode* AsDOMNode() = 0;
 
   /**
    * Return if this node has any children.
    */
@@ -750,19 +750,19 @@ public:
   {
     return mParent;
   }
   
   /**
    * Get the parent nsINode for this node if it is an Element.
    * @return the parent node
    */
-  nsINode* GetElementParent() const
+  mozilla::dom::Element* GetElementParent() const
   {
-    return mParent && mParent->IsElement() ? mParent : nsnull;
+    return mParent && mParent->IsElement() ? mParent->AsElement() : nsnull;
   }
 
   /**
    * Get the root of the subtree this node belongs to.  This never returns
    * null.  It may return 'this' (e.g. for document nodes, and nodes that
    * are the roots of disconnected subtrees).
    */
   nsINode* SubtreeRoot() const
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -357,29 +357,35 @@ nsCCUncollectableMarker::Observe(nsISupp
     if (hw) {
       nsCOMPtr<nsIDocShell> shell;
       hw->GetDocShell(getter_AddRefs(shell));
       nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
       MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
     }
   }
 
-  if (cleanupJS) {
-    nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(sGeneration);
-    MarkMessageManagers();
-    xpc_UnmarkSkippableJSHolders();
-  }
-
 #ifdef MOZ_XUL
   nsXULPrototypeCache* xulCache = nsXULPrototypeCache::GetInstance();
   if (xulCache) {
     xulCache->MarkInCCGeneration(sGeneration);
   }
 #endif
 
+  static bool previousWasJSCleanup = false;
+  if (cleanupJS) {
+    nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(sGeneration);
+    MarkMessageManagers();
+    previousWasJSCleanup = true;
+  } else if (previousWasJSCleanup) {
+    previousWasJSCleanup = false;
+    if (!prepareForCC) {
+      xpc_UnmarkSkippableJSHolders();
+    }
+  }
+
   return NS_OK;
 }
 
 static PLDHashOperator
 TraceActiveWindowGlobal(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
 {
   if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
     if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -127,17 +127,17 @@ public:
    * Call this to reevaluate whether we should start/stop due to our owner
    * document being active or inactive.
    */
   void NotifyOwnerDocumentActivityChanged();
 
   // Called by the video decoder object, on the main thread,
   // when it has read the metadata containing video dimensions,
   // etc.
-  void MetadataLoaded(PRUint32 aChannels, PRUint32 aRate);
+  void MetadataLoaded(PRUint32 aChannels, PRUint32 aRate, bool aHasAudio);
 
   // Called by the video decoder object, on the main thread,
   // when it has read the first frame of the video
   // aResourceFullyLoaded should be true if the resource has been
   // fully loaded and the caller will call ResourceLoaded next.
   void FirstFrameLoaded(bool aResourceFullyLoaded);
 
   // Called by the video decoder object, on the main thread,
@@ -789,11 +789,14 @@ protected:
   // stored in mPreloadURI.
   bool mLoadIsSuspended;
 
   // True if a same-origin check has been done for the media element and resource.
   bool mMediaSecurityVerified;
 
   // The CORS mode when loading the media element
   mozilla::CORSMode mCORSMode;
+
+  // True if the media has an audio track
+  bool mHasAudio;
 };
 
 #endif
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -172,17 +172,17 @@ nsHTMLAudioElement::MozSetup(PRUint32 aC
   nsresult rv = mAudioStream->Init(aChannels, aRate,
                                    nsAudioStream::FORMAT_FLOAT32);
   if (NS_FAILED(rv)) {
     mAudioStream->Shutdown();
     mAudioStream = nsnull;
     return rv;
   }
 
-  MetadataLoaded(aChannels, aRate);
+  MetadataLoaded(aChannels, aRate, true);
   mAudioStream->SetVolume(mVolume);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, PRUint32* aRetVal)
 {
   if (!mAudioStream) {
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1454,17 +1454,18 @@ nsHTMLMediaElement::nsHTMLMediaElement(a
     mHaveQueuedSelectResource(false),
     mSuspendedAfterFirstFrame(false),
     mAllowSuspendAfterFirstFrame(true),
     mHasPlayedOrSeeked(false),
     mHasSelfReference(false),
     mShuttingDown(false),
     mLoadIsSuspended(false),
     mMediaSecurityVerified(false),
-    mCORSMode(CORS_NONE)
+    mCORSMode(CORS_NONE),
+    mHasAudio(false)
 {
 #ifdef PR_LOGGING
   if (!gMediaElementLog) {
     gMediaElementLog = PR_NewLogModule("nsMediaElement");
   }
   if (!gMediaElementEventsLog) {
     gMediaElementEventsLog = PR_NewLogModule("nsMediaElementEvents");
   }
@@ -2253,20 +2254,21 @@ void nsHTMLMediaElement::ProcessMediaFra
     }
   }
   if (start > 0.0) {
     SetCurrentTime(start);
     mFragmentStart = start;
   }
 }
 
-void nsHTMLMediaElement::MetadataLoaded(PRUint32 aChannels, PRUint32 aRate)
+void nsHTMLMediaElement::MetadataLoaded(PRUint32 aChannels, PRUint32 aRate, bool aHasAudio)
 {
   mChannels = aChannels;
   mRate = aRate;
+  mHasAudio = aHasAudio;
   ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
   DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
   DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
   if (mDecoder && mDecoder->IsSeekable()) {
     ProcessMediaFragmentURI();
     mDecoder->SetEndTime(mFragmentEnd);
   }
 }
--- a/content/html/content/src/nsHTMLVideoElement.cpp
+++ b/content/html/content/src/nsHTMLVideoElement.cpp
@@ -214,8 +214,16 @@ NS_IMETHODIMP nsHTMLVideoElement::GetMoz
 }
 
 NS_IMETHODIMP nsHTMLVideoElement::GetMozFrameDelay(double *aMozFrameDelay) {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   VideoFrameContainer* container = GetVideoFrameContainer();
   *aMozFrameDelay = container ?  container->GetFrameDelay() : 0;
   return NS_OK;
 }
+
+
+/* readonly attribute bool mozHasAudio */
+NS_IMETHODIMP nsHTMLVideoElement::GetMozHasAudio(bool *aHasAudio) {
+  NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
+  *aHasAudio = mHasAudio;
+  return NS_OK;
+}
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -67,16 +67,17 @@ class nsIDocShell;
 class nsICachingChannel;
 
 class nsHTMLDocument : public nsDocument,
                        public nsIHTMLDocument,
                        public nsIDOMHTMLDocument
 {
 public:
   using nsDocument::SetDocumentURI;
+  using nsDocument::GetPlugins;
 
   nsHTMLDocument();
   virtual nsresult Init();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   NS_IMETHOD_(nsrefcnt) AddRef(void);
   NS_IMETHOD_(nsrefcnt) Release(void);
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -403,17 +403,18 @@ void nsBuiltinDecoder::AudioAvailable(fl
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (mShuttingDown || !mElement) {
     return;
   }
   mElement->NotifyAudioAvailable(frameBuffer.forget(), aFrameBufferLength, aTime);
 }
 
 void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
-                                      PRUint32 aRate)
+                                      PRUint32 aRate,
+                                      bool aHasAudio)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (mShuttingDown) {
     return;
   }
 
   // Only inform the element of MetadataLoaded if not doing a load() in order
   // to fulfill a seek, otherwise we'll get multiple metadataloaded events.
@@ -430,17 +431,17 @@ void nsBuiltinDecoder::MetadataLoaded(PR
   if (mDuration == -1) {
     SetInfinite(true);
   }
 
   if (mElement && notifyElement) {
     // Make sure the element and the frame (if any) are told about
     // our new size.
     Invalidate();
-    mElement->MetadataLoaded(aChannels, aRate);
+    mElement->MetadataLoaded(aChannels, aRate, aHasAudio);
   }
 
   if (!mResourceLoaded) {
     StartProgress();
   } else if (mElement) {
     // Resource was loaded during metadata loading, when progress
     // events are being ignored. Fire the final progress event.
     mElement->DispatchAsyncEvent(NS_LITERAL_STRING("progress"));
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -550,17 +550,18 @@ public:
   // Change to a new play state. This updates the mState variable and
   // notifies any thread blocking on this object's monitor of the
   // change. Call on the main thread only.
   void ChangeState(PlayState aState);
 
   // Called when the metadata from the media file has been read.
   // Call on the main thread only.
   void MetadataLoaded(PRUint32 aChannels,
-                      PRUint32 aRate);
+                      PRUint32 aRate,
+                      bool aHasAudio);
 
   // Called when the first frame has been loaded.
   // Call on the main thread only.
   void FirstFrameLoaded();
 
   // Called when the video has completed playing.
   // Call on the main thread only.
   void PlaybackEnded();
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -147,31 +147,33 @@ static PRInt64 DurationToUsecs(TimeDurat
 }
 
 class nsAudioMetadataEventRunner : public nsRunnable
 {
 private:
   nsCOMPtr<nsBuiltinDecoder> mDecoder;
 public:
   nsAudioMetadataEventRunner(nsBuiltinDecoder* aDecoder, PRUint32 aChannels,
-                             PRUint32 aRate) :
+                             PRUint32 aRate, bool aHasAudio) :
     mDecoder(aDecoder),
     mChannels(aChannels),
-    mRate(aRate)
+    mRate(aRate),
+    mHasAudio(aHasAudio)
   {
   }
 
   NS_IMETHOD Run()
   {
-    mDecoder->MetadataLoaded(mChannels, mRate);
+    mDecoder->MetadataLoaded(mChannels, mRate, mHasAudio);
     return NS_OK;
   }
 
   const PRUint32 mChannels;
   const PRUint32 mRate;
+  const bool mHasAudio;
 };
 
 // Owns the global state machine thread and counts of
 // state machine and decoder threads. There should
 // only be one instance of this class.
 class StateMachineTracker
 {
 private:
@@ -1510,17 +1512,17 @@ nsresult nsBuiltinDecoderStateMachine::D
     mEventManager.Init(mInfo.mAudioChannels, mInfo.mAudioRate);
     // Set the buffer length at the decoder level to be able, to be able
     // to retrive the value via media element method. The RequestFrameBufferLength
     // will call the nsBuiltinDecoderStateMachine::SetFrameBufferLength().
     PRUint32 frameBufferLength = mInfo.mAudioChannels * FRAMEBUFFER_LENGTH_PER_CHANNEL;
     mDecoder->RequestFrameBufferLength(frameBufferLength);
   }
   nsCOMPtr<nsIRunnable> metadataLoadedEvent =
-    new nsAudioMetadataEventRunner(mDecoder, mInfo.mAudioChannels, mInfo.mAudioRate);
+    new nsAudioMetadataEventRunner(mDecoder, mInfo.mAudioChannels, mInfo.mAudioRate, HasAudio());
   NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL);
 
   if (mState == DECODER_STATE_DECODING_METADATA) {
     LOG(PR_LOG_DEBUG, ("%p Changed state from DECODING_METADATA to DECODING", mDecoder.get()));
     StartDecoding();
   }
 
   if ((mState == DECODER_STATE_DECODING || mState == DECODER_STATE_COMPLETED) &&
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -151,16 +151,17 @@ include $(topsrcdir)/config/rules.mk
 		test_source_write.html \
 		test_standalone.html \
 		test_timeupdate_small_files.html \
 		test_too_many_elements.html \
 		test_volume.html \
 		test_video_to_canvas.html \
 		use_large_cache.js \
 		test_audiowrite.html \
+		test_mozHasAudio.html \
 		$(NULL)
 
 # Don't run in suite
 ifndef MOZ_SUITE
 _TEST_FILES += test_play_twice.html
 else
 $(warning test_play_twice.html is disabled pending investigation. Bug 598252)
 endif
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -42,16 +42,25 @@ var gReplayTests = gSmallTests.concat([
 
 // Used by test_paused_after_ended. Need one test file per decoder backend, plus
 // anything for testing bugs that occur when replying a played file.
 var gPausedAfterEndedTests = gSmallTests.concat([
   { name:"r11025_u8_c1.wav", type:"audio/x-wav", duration:1.0 },
   { name:"small-shot.ogg", type:"video/ogg", duration:0.276 }
 ]);
 
+// Test the mozHasAudio property
+var gMozHasAudioTests = [
+  { name:"big.wav", type:"audio/x-wav", duration:9.278981, size:102444, hasAudio:undefined },
+  { name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.233, size:28942, hasAudio:false },
+  { name:"short-video.ogv", type:"video/ogg", duration:1.081, hasAudio:true },
+  { name:"seek.webm", type:"video/webm", duration:3.966, size:215529, hasAudio:false },
+  { name:"bogus.duh", type:"bogus/duh" }
+];
+
 // These are files that we want to make sure we can play through.  We can
 // also check metadata.  Put files of the same type together in this list so if
 // something crashes we have some idea of which backend is responsible.
 // Used by test_playback, which expects no error event and one ended event.
 var gPlayTests = [
   // 8-bit samples
   { name:"r11025_u8_c1.wav", type:"audio/x-wav", duration:1.0 },
   // 8-bit samples, file is truncated
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_mozHasAudio.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test playback of media files that should play OK</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var manager = new MediaTestManager;
+
+function onloadedmetadata(e) {
+  var t = e.target;
+  is(t.mozHasAudio, t.hasAudio, "The element reports the wrong audio property." + t.token);
+  manager.finished(t.token);
+}
+
+function startTest(test, token) {
+  var elemType = /^audio/.test(test.type) ? "audio" : "video";
+  var element = document.createElement(elemType);
+
+  element.token = token;
+  manager.started(token);
+
+  element.src = test.name;
+  element.name = test.name;
+  element.hasAudio = test.hasAudio;
+  element.addEventListener("loadedmetadata", onloadedmetadata, false);
+
+  element.load();
+}
+
+manager.runTests(gMozHasAudioTests, startTest);
+
+</script>
+</pre>
+</body>
+</html>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3891,16 +3891,20 @@ nsDocShell::LoadURI(const PRUnichar * aU
     PRUint32 loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
     loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(loadType));
     loadInfo->SetPostDataStream(aPostStream);
     loadInfo->SetReferrer(aReferringURI);
     loadInfo->SetHeadersStream(aHeaderStream);
 
     rv = LoadURI(uri, loadInfo, extraFlags, true);
 
+    // Save URI string in case it's needed later when
+    // sending to search engine service in EndPageLoad()
+    mOriginalUriString = uriString; 
+
     return rv;
 }
 
 NS_IMETHODIMP
 nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
                              const PRUnichar *aURL,
                              nsIChannel* aFailedChannel)
 {
@@ -6350,37 +6354,43 @@ nsDocShell::EndPageLoad(nsIWebProgress *
                 // enabled...this is just a bandaid...
                 if (keywordsEnabled && !scheme.IsEmpty() &&
                     (scheme.Find("http") != 0)) {
                     keywordsEnabled = false;
                 }
 
                 if (keywordsEnabled && (kNotFound == dotLoc)) {
                     // only send non-qualified hosts to the keyword server
-                    //
-                    // If this string was passed through nsStandardURL by
-                    // chance, then it may have been converted from UTF-8 to
-                    // ACE, which would result in a completely bogus keyword
-                    // query.  Here we try to recover the original Unicode
-                    // value, but this is not 100% correct since the value may
-                    // have been normalized per the IDN normalization rules.
-                    //
-                    // Since we don't have access to the exact original string
-                    // that was entered by the user, this will just have to do.
-                    bool isACE;
-                    nsCAutoString utf8Host;
-                    nsCOMPtr<nsIIDNService> idnSrv =
-                        do_GetService(NS_IDNSERVICE_CONTRACTID);
-                    if (idnSrv &&
-                        NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
-                        NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host)))
-                        sURIFixup->KeywordToURI(utf8Host,
+                    if (!mOriginalUriString.IsEmpty()) {
+                        sURIFixup->KeywordToURI(mOriginalUriString,
                                                 getter_AddRefs(newURI));
-                    else
-                        sURIFixup->KeywordToURI(host, getter_AddRefs(newURI));
+                    }
+                    else {
+                        //
+                        // If this string was passed through nsStandardURL by
+                        // chance, then it may have been converted from UTF-8 to
+                        // ACE, which would result in a completely bogus keyword
+                        // query.  Here we try to recover the original Unicode
+                        // value, but this is not 100% correct since the value may
+                        // have been normalized per the IDN normalization rules.
+                        //
+                        // Since we don't have access to the exact original string
+                        // that was entered by the user, this will just have to do.
+                        bool isACE;
+                        nsCAutoString utf8Host;
+                        nsCOMPtr<nsIIDNService> idnSrv =
+                            do_GetService(NS_IDNSERVICE_CONTRACTID);
+                        if (idnSrv &&
+                            NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
+                            NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host)))
+                            sURIFixup->KeywordToURI(utf8Host,
+                                                    getter_AddRefs(newURI));
+                        else
+                            sURIFixup->KeywordToURI(host, getter_AddRefs(newURI));
+                    }
                 } // end keywordsEnabled
             }
 
             //
             // Now try change the address, e.g. turn http://foo into
             // http://www.foo.com
             //
             if (aStatus == NS_ERROR_UNKNOWN_HOST ||
@@ -8065,16 +8075,17 @@ nsDocShell::InternalLoad(nsIURI * aURI,
                          nsIInputStream * aHeadersData,
                          PRUint32 aLoadType,
                          nsISHEntry * aSHEntry,
                          bool aFirstParty,
                          nsIDocShell** aDocShell,
                          nsIRequest** aRequest)
 {
     nsresult rv = NS_OK;
+    mOriginalUriString.Truncate();
 
 #ifdef PR_LOGGING
     if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) {
         nsCAutoString spec;
         if (aURI)
             aURI->GetSpec(spec);
         PR_LogPrint("DOCSHELL %p InternalLoad %s\n", this, spec.get());
     }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -843,17 +843,18 @@ protected:
     static nsIURIFixup *sURIFixup;
 
     nsRefPtr<nsDOMNavigationTiming> mTiming;
 
 private:
     nsCOMPtr<nsIAtom> mForcedCharset;
     nsCOMPtr<nsIAtom> mParentCharset;
     nsTObserverArray<nsWeakPtr> mPrivacyObservers;
-    PRInt32          mParentCharsetSource;
+    PRInt32           mParentCharsetSource;
+    nsCString         mOriginalUriString;
 
 #ifdef DEBUG
     // We're counting the number of |nsDocShells| to help find leaks
     static unsigned long gNumberOfDocShells;
 #endif /* DEBUG */
 
 public:
     class InterfaceRequestorProxy : public nsIInterfaceRequestor {
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -530,16 +530,18 @@ using mozilla::dom::indexedDB::IDBWrappe
 #ifdef MOZ_B2G_BT
 #include "BluetoothAdapter.h"
 #include "BluetoothDevice.h"
 #endif
 
 #include "DOMError.h"
 #include "DOMRequest.h"
 
+#include "mozilla/Likely.h"
+
 #undef None // something included above defines this preprocessor symbol, maybe Xlib headers
 #include "WebGLContext.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
@@ -1963,16 +1965,33 @@ WrapNativeParent(JSContext *cx, JSObject
 
   jsval v;
   nsresult rv = WrapNative(cx, scope, native, nativeWrapperCache, false, &v);
   NS_ENSURE_SUCCESS(rv, rv);
   *parentObj = JSVAL_TO_OBJECT(v);
   return NS_OK;
 }
 
+// Helper to handle torn-down inner windows.
+static inline nsresult
+SetParentToWindow(nsGlobalWindow *win, JSObject **parent)
+{
+  MOZ_ASSERT(win);
+  MOZ_ASSERT(win->IsInnerWindow());
+  *parent = win->FastGetGlobalJSObject();
+
+  if (MOZ_UNLIKELY(!*parent)) {
+    // The only known case where this can happen is when the inner window has
+    // been torn down. See bug 691178 comment 11.
+    MOZ_ASSERT(win->IsClosedOrClosing());
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
 // static
 
 nsISupports *
 nsDOMClassInfo::GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj)
 {
   return wrapper ? wrapper->Native() : static_cast<nsISupports*>(js::GetObjectPrivate(obj));
 }
 
@@ -4624,18 +4643,19 @@ nsDOMClassInfo::PreCreate(nsISupports *n
 
   nsCOMPtr<nsPIDOMWindow> piwin = do_QueryWrapper(cx, globalObj);
 
   if (!piwin) {
     return NS_OK;
   }
 
   if (piwin->IsOuterWindow()) {
-    *parentObj = ((nsGlobalWindow *)piwin.get())->
-      GetCurrentInnerWindowInternal()->GetGlobalJSObject();
+    nsGlobalWindow *win = ((nsGlobalWindow *)piwin.get())->
+                            GetCurrentInnerWindowInternal();
+    return SetParentToWindow(win, parentObj);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMClassInfo::Create(nsIXPConnectWrappedNative *wrapper,
                        JSContext *cx, JSObject *obj)
@@ -5160,30 +5180,25 @@ nsWindowSH::PreCreate(nsISupports *nativ
   // after the wrapper is found.
 
   nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeObj));
   NS_ASSERTION(sgo, "nativeObj not a global object!");
 
   nsGlobalWindow *win = nsGlobalWindow::FromSupports(nativeObj);
   NS_ASSERTION(win->IsInnerWindow(), "Should be inner window.");
 
-  JSObject *winObj = win->FastGetGlobalJSObject();
-  if (!winObj) {
-
-    // See bug 691178 comment 11 for why this is necessary.
-    if (win->IsClosedOrClosing())
-      return NS_ERROR_FAILURE;
-
-    NS_ASSERTION(win->GetOuterWindowInternal()->IsCreatingInnerWindow(),
-                 "should have a JS object by this point");
+  // We sometimes get a disconnected window during file api test. :-(
+  if (!win->GetOuterWindowInternal())
+    return NS_ERROR_FAILURE;
+
+  // If we're bootstrapping, we don't have a JS object yet.
+  if (win->GetOuterWindowInternal()->IsCreatingInnerWindow())
     return NS_OK;
-  }
-
-  *parentObj = winObj;
-  return NS_OK;
+
+  return SetParentToWindow(win, parentObj);
 }
 
 // This JS class piggybacks on nsHTMLDocumentSH::ReleaseDocument()...
 
 static JSClass sGlobalScopePolluterClass = {
   "Global Scope Polluter",
   JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE,
   nsWindowSH::SecurityCheckOnAddDelProp,
@@ -6024,18 +6039,17 @@ nsDOMConstructor::PreCreate(JSContext *c
 {
   nsCOMPtr<nsPIDOMWindow> owner(do_QueryReferent(mWeakOwner));
   if (!owner) {
     // Can't do anything.
     return NS_OK;
   }
 
   nsGlobalWindow *win = static_cast<nsGlobalWindow *>(owner.get());
-  *parentObj = win->FastGetGlobalJSObject();
-  return NS_OK;
+  return SetParentToWindow(win, parentObj);
 }
 
 nsresult
 nsDOMConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                             JSObject * obj, PRUint32 argc, jsval * argv,
                             jsval * vp, bool *_retval)
 {
   JSObject* class_obj = JSVAL_TO_OBJECT(argv[-2]);
@@ -7475,17 +7489,17 @@ nsLocationSH::PreCreate(nsISupports *nat
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(ds);
   if (!sgo) {
     NS_WARNING("Refusing to create a location in the wrong scope because the "
                "docshell is being destroyed");
     return NS_ERROR_UNEXPECTED;
   }
 
   *parentObj = sgo->GetGlobalJSObject();
-  return NS_OK;
+  return *parentObj ? NS_OK : NS_ERROR_FAILURE;
 }
 
 // DOM Navigator helper
 
 NS_IMETHODIMP
 nsNavigatorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                           JSObject *obj, jsid id, PRUint32 flags,
                           JSObject **objp, bool *_retval)
@@ -7574,24 +7588,17 @@ nsNavigatorSH::PreCreate(nsISupports *na
 
   Navigator *nav = static_cast<Navigator*>(safeNav.get());
   nsGlobalWindow *win = static_cast<nsGlobalWindow*>(nav->GetWindow());
   if (!win) {
     NS_WARNING("Refusing to create a navigator in the wrong scope");
 
     return NS_ERROR_UNEXPECTED;
   }
-
-  JSObject *global = win->GetGlobalJSObject();
-
-  if (global) {
-    *parentObj = global;
-  }
-
-  return NS_OK;
+  return SetParentToWindow(win, parentObj);
 }
 
 // DOM Node helper
 
 template<nsresult (*func)(JSContext *cx, JSObject *obj, jsval *vp)>
 static JSBool
 GetterShim(JSContext *cx, JSObject *obj, jsid /* unused */, jsval *vp)
 {
@@ -7848,17 +7855,17 @@ nsEventTargetSH::PreCreate(nsISupports *
   nsDOMEventTargetHelper *target =
     nsDOMEventTargetHelper::FromSupports(nativeObj);
 
   nsCOMPtr<nsIScriptGlobalObject> native_parent;
   target->GetParentObject(getter_AddRefs(native_parent));
 
   *parentObj = native_parent ? native_parent->GetGlobalJSObject() : globalObj;
 
-  return NS_OK;
+  return *parentObj ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsEventTargetSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                              JSObject *obj, jsid id, jsval *vp, bool *_retval)
 {
   nsEventTargetSH::PreserveWrapper(GetNative(wrapper, obj));
 
@@ -10000,19 +10007,18 @@ nsHistorySH::PreCreate(nsISupports *nati
 {
   nsHistory *history = (nsHistory *)((nsIDOMHistory*)nativeObj);
   nsCOMPtr<nsPIDOMWindow> innerWindow;
   history->GetWindow(getter_AddRefs(innerWindow));
   if (!innerWindow) {
     NS_WARNING("refusing to create history object in the wrong scope");
     return NS_ERROR_FAILURE;
   }
-
-  *parentObj = static_cast<nsGlobalWindow *>(innerWindow.get())->FastGetGlobalJSObject();
-  return NS_OK;
+  return SetParentToWindow(static_cast<nsGlobalWindow *>(innerWindow.get()),
+                           parentObj);
 }
 
 NS_IMETHODIMP
 nsHistorySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsid id, jsval *vp, bool *_retval)
 {
   bool is_number = false;
   GetArrayIndexFromId(cx, id, &is_number);
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -90,16 +90,22 @@ public:
   void NotifyDOMInteractive(nsIURI* aURI);
   void NotifyDOMComplete(nsIURI* aURI);
   void NotifyDOMContentLoadedStart(nsIURI* aURI);
   void NotifyDOMContentLoadedEnd(nsIURI* aURI);
   nsresult TimeStampToDOM(mozilla::TimeStamp aStamp, DOMTimeMilliSec* aResult);
   nsresult TimeStampToDOMOrFetchStart(mozilla::TimeStamp aStamp, 
                                       DOMTimeMilliSec* aResult);
 
+  inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp)
+  {
+    mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
+    return duration.ToMilliseconds();
+  }
+
 private:
   nsDOMNavigationTiming(const nsDOMNavigationTiming &){};
   ~nsDOMNavigationTiming();
 
   void Clear();
   bool ReportRedirects();
 
   nsCOMPtr<nsIURI> mUnloadedURI;
--- a/dom/base/nsPerformance.cpp
+++ b/dom/base/nsPerformance.cpp
@@ -314,8 +314,16 @@ NS_IMETHODIMP
 nsPerformance::GetNavigation(nsIDOMPerformanceNavigation** aNavigation)
 {
   if (!mNavigation) {
     mNavigation = new nsPerformanceNavigation(mDOMTiming);
   }
   NS_IF_ADDREF(*aNavigation = mNavigation);
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsPerformance::Now(DOMHighResTimeStamp* aNow)
+{
+  *aNow = mDOMTiming->TimeStampToDOMHighRes(mozilla::TimeStamp::Now());
+  return NS_OK;
+}
+
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -796,26 +796,27 @@ class PropertyArrays():
 
 class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
     """
     Generate the CreateInterfaceObjects method for an interface descriptor.
 
     properties should be a PropertyArrays instance.
     """
     def __init__(self, descriptor, properties):
-        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
+        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
+                Argument('JSObject*', 'aReceiver')]
         CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'JSObject*', args)
         self.properties = properties
     def definition_body(self):
         protoChain = self.descriptor.prototypeChain
         if len(protoChain) == 1:
             getParentProto = "JS_GetObjectPrototype(aCx, aGlobal)"
         else:
             parentProtoName = self.descriptor.prototypeChain[-2]
-            getParentProto = "%s::GetProtoObject(aCx, aGlobal)" % (parentProtoName)
+            getParentProto = "%s::GetProtoObject(aCx, aGlobal, aReceiver)" % (parentProtoName)
 
         needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
         needInterfacePrototypeObject = self.descriptor.interface.hasInterfacePrototypeObject()
 
         # if we don't need to create anything, why are we generating this?
         assert needInterfaceObject or needInterfacePrototypeObject
 
         idsToInit = []
@@ -844,17 +845,17 @@ class CGCreateInterfaceObjectsMethod(CGA
         else:
             initIds = None
             
         getParentProto = ("JSObject* parentProto = %s;\n"
                           "if (!parentProto) {\n"
                           "  return NULL;\n"
                           "}") % getParentProto
 
-        call = CGGeneric(("return bindings::CreateInterfaceObjects(aCx, aGlobal, parentProto,\n"
+        call = CGGeneric(("return bindings::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,\n"
                           "                                        %s, %s,\n"
                           "                                        %%(methods)s, %%(attrs)s, %%(consts)s, %%(staticMethods)s,\n"
                           "                                        %s);") % (
             "&PrototypeClass" if needInterfacePrototypeObject else "NULL",
             "&InterfaceObjectClass" if needInterfaceObject else "NULL",
             '"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL"))
 
         if self.properties.hasChromeOnly():
@@ -875,85 +876,99 @@ class CGCreateInterfaceObjectsMethod(CGA
         return CGIndenter(functionBody).define()
 
 class CGGetPerInterfaceObject(CGAbstractMethod):
     """
     A method for getting a per-interface object (a prototype object or interface
     constructor object).
     """
     def __init__(self, descriptor, name, idPrefix=""):
-        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
+        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal'),
+                Argument('JSObject*', 'aReceiver')]
         CGAbstractMethod.__init__(self, descriptor, name,
                                   'JSObject*', args, inline=True)
         self.id = idPrefix + "id::" + self.descriptor.name
     def definition_body(self):
         return """
+
+  /* aGlobal and aReceiver are usually the same, but they can be different
+     too. For example a sandbox often has an xray wrapper for a window as the
+     prototype of the sandbox's global. In that case aReceiver is the xray
+     wrapper and aGlobal is the sandbox's global.
+   */
+
   /* Make sure our global is sane.  Hopefully we can remove this sometime */
   if (!(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL)) {
     return NULL;
   }
   /* Check to see whether the interface objects are already installed */
   JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(aGlobal);
   JSObject* cachedObject = protoOrIfaceArray[%s];
   if (!cachedObject) {
-    protoOrIfaceArray[%s] = cachedObject = CreateInterfaceObjects(aCx, aGlobal);
+    protoOrIfaceArray[%s] = cachedObject = CreateInterfaceObjects(aCx, aGlobal, aReceiver);
   }
 
   /* cachedObject might _still_ be null, but that's OK */
   return cachedObject;""" % (self.id, self.id)
 
 class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
     """
     A method for getting the interface prototype object.
     """
     def __init__(self, descriptor):
-        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
         CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject")
     def definition_body(self):
         return """
   /* Get the interface prototype object for this class.  This will create the
      object as needed. */""" + CGGetPerInterfaceObject.definition_body(self)
 
 class CGGetConstructorObjectMethod(CGGetPerInterfaceObject):
     """
     A method for getting the interface constructor object.
     """
     def __init__(self, descriptor):
-        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
         CGGetPerInterfaceObject.__init__(self, descriptor, "GetConstructorObject", "constructors::")
     def definition_body(self):
         return """
   /* Get the interface object for this class.  This will create the object as
      needed. */""" + CGGetPerInterfaceObject.definition_body(self)
 
-def CheckPref(descriptor, scopeName, varName, retval, wrapperCache = None):
+def CheckPref(descriptor, globalName, varName, retval, wrapperCache = None):
     """
     Check whether bindings should be enabled for this descriptor.  If not, set
     varName to false and return retval.
     """
     if not descriptor.prefable:
         return ""
     if wrapperCache:
-       wrapperCache = "%s->ClearIsDOMBinding();\n" % (wrapperCache)
+       wrapperCache = "      %s->ClearIsDOMBinding();\n" % (wrapperCache)
     else:
         wrapperCache = ""
     return """
-  if (!%s->ExperimentalBindingsEnabled()) {
-%s    %s = false;
-    return %s;
+  {
+    XPCWrappedNativeScope* scope =
+      XPCWrappedNativeScope::FindInJSObjectScope(aCx, %s);
+    if (!scope) {
+      return %s;
+    }
+
+    if (!scope->ExperimentalBindingsEnabled()) {
+%s      %s = false;
+      return %s;
+    }
   }
-""" % (scopeName, wrapperCache, varName, retval)
+""" % (globalName, retval, wrapperCache, varName, retval)
 
 class CGDefineDOMInterfaceMethod(CGAbstractMethod):
     """
     A method for resolve hooks to try to lazily define the interface object for
     a given interface.
     """
     def __init__(self, descriptor):
-        args = [Argument('JSContext*', 'aCx'), Argument('XPCWrappedNativeScope*', 'aScope'),
+        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aReceiver'),
                 Argument('bool*', 'aEnabled')]
         CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'bool', args)
 
     def declare(self):
         if self.descriptor.workers:
             return ''
         return CGAbstractMethod.declare(self)
 
@@ -965,19 +980,21 @@ class CGDefineDOMInterfaceMethod(CGAbstr
     def definition_body(self):
         if self.descriptor.interface.hasInterfacePrototypeObject():
             # We depend on GetProtoObject defining an interface constructor
             # object as needed.
             getter = "GetProtoObject"
         else:
             getter = "GetConstructorObject"
 
-        return CheckPref(self.descriptor, "aScope", "*aEnabled", "false") + """
+        return ("  JSObject* global = JS_GetGlobalForObject(aCx, aReceiver);\n" +
+                CheckPref(self.descriptor, "global", "*aEnabled", "false") + 
+                """
   *aEnabled = true;
-  return !!%s(aCx, aScope->GetGlobalJSObject());""" % (getter)
+  return !!%s(aCx, global, aReceiver);""" % (getter))
 
 class CGNativeToSupportsMethod(CGAbstractStaticMethod):
     """
     A method to cast our native to an nsISupports.  We do it by casting up the
     interface chain in hopes of getting to something that singly-inherits from
     nsISupports.
     """
     def __init__(self, descriptor):
@@ -1017,38 +1034,34 @@ class CGWrapMethod(CGAbstractMethod):
 
   JSAutoEnterCompartment ac;
   if (js::GetGlobalForObjectCrossCompartment(parent) != aScope) {
     if (!ac.enter(aCx, parent)) {
       return NULL;
     }
   }
 
-  XPCWrappedNativeScope* scope =
-    XPCWrappedNativeScope::FindInJSObjectScope(aCx, parent);
-  if (!scope) {
-    return NULL;
-  }
+  JSObject* global = JS_GetGlobalForObject(aCx, parent);
 %s
-  JSObject* proto = GetProtoObject(aCx, scope->GetGlobalJSObject());
+  JSObject* proto = GetProtoObject(aCx, global, global);
   if (!proto) {
     return NULL;
   }
 
   JSObject* obj = JS_NewObject(aCx, &Class.mBase, proto, parent);
   if (!obj) {
     return NULL;
   }
 
   js::SetReservedSlot(obj, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
   NS_ADDREF(aObject);
 
   aObject->SetWrapper(obj);
 
-  return obj;""" % (CheckPref(self.descriptor, "scope", "*aTriedToWrap", "NULL", "aObject"))
+  return obj;""" % (CheckPref(self.descriptor, "global", "*aTriedToWrap", "NULL", "aObject"))
 
 builtinNames = {
     IDLType.Tags.bool: 'bool',
     IDLType.Tags.int8: 'int8_t',
     IDLType.Tags.int16: 'int16_t',
     IDLType.Tags.int32: 'int32_t',
     IDLType.Tags.int64: 'int64_t',
     IDLType.Tags.uint8: 'uint8_t',
--- a/dom/bindings/Utils.cpp
+++ b/dom/bindings/Utils.cpp
@@ -20,17 +20,17 @@ DefineConstants(JSContext* cx, JSObject*
     if (!ok) {
       return false;
     }
   }
   return true;
 }
 
 static JSObject*
-CreateInterfaceObject(JSContext* cx, JSObject* global,
+CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
                       JSClass* constructorClass, JSObject* proto,
                       JSFunctionSpec* staticMethods, ConstantSpec* constants,
                       const char* name)
 {
   JSObject* functionProto = JS_GetFunctionPrototype(cx, global);
   if (!functionProto) {
     return NULL;
   }
@@ -49,17 +49,17 @@ CreateInterfaceObject(JSContext* cx, JSO
     return NULL;
   }
 
   if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) {
     return NULL;
   }
 
   // This is Enumerable: False per spec.
-  if (!JS_DefineProperty(cx, global, name, OBJECT_TO_JSVAL(constructor), NULL,
+  if (!JS_DefineProperty(cx, receiver, name, OBJECT_TO_JSVAL(constructor), NULL,
                          NULL, 0)) {
     return NULL;
   }
 
   return constructor;
 }
 
 static JSObject*
@@ -86,46 +86,46 @@ CreateInterfacePrototypeObject(JSContext
   if (constants && !DefineConstants(cx, ourProto, constants)) {
     return NULL;
   }
 
   return ourProto;
 }
 
 JSObject*
-CreateInterfaceObjects(JSContext *cx, JSObject *global, JSObject *parentProto,
-                       JSClass *protoClass, JSClass *constructorClass,
-                       JSFunctionSpec *methods, JSPropertySpec *properties,
-                       ConstantSpec *constants, JSFunctionSpec *staticMethods,
-                       const char* name)
+CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
+                       JSObject* protoProto, JSClass* protoClass,
+                       JSClass* constructorClass, JSFunctionSpec* methods,
+                       JSPropertySpec* properties, ConstantSpec* constants,
+                       JSFunctionSpec* staticMethods, const char* name)
 {
   MOZ_ASSERT(protoClass || constructorClass, "Need at least one class!");
   MOZ_ASSERT(!(methods || properties) || protoClass,
              "Methods or properties but no protoClass!");
   MOZ_ASSERT(!staticMethods || constructorClass,
              "Static methods but no constructorClass!");
   MOZ_ASSERT(bool(name) == bool(constructorClass),
              "Must have name precisely when we have an interface object");
 
   JSObject* proto;
   if (protoClass) {
-    proto = CreateInterfacePrototypeObject(cx, global, parentProto, protoClass,
+    proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
                                            methods, properties, constants);
     if (!proto) {
       return NULL;
     }
   }
   else {
     proto = NULL;
   }
 
   JSObject* interface;
   if (constructorClass) {
-    interface = CreateInterfaceObject(cx, global, constructorClass, proto,
-                                      staticMethods, constants, name);
+    interface = CreateInterfaceObject(cx, global, receiver, constructorClass,
+                                      proto, staticMethods, constants, name);
     if (!interface) {
       return NULL;
     }
   }
 
   return protoClass ? proto : interface;
 }
 
--- a/dom/bindings/Utils.h
+++ b/dom/bindings/Utils.h
@@ -214,17 +214,21 @@ struct ConstantSpec
   const char* name;
   JS::Value value;
 };
 
 /*
  * Create a DOM interface object (if constructorClass is non-null) and/or a
  * DOM interface prototype object (if protoClass is non-null).
  *
- * parentProto is the prototype to use for the interface prototype object.
+ * global is used as the parent of the interface object and the interface
+ *        prototype object
+ * receiver is the object on which we need to define the interface object as a
+ *          property
+ * protoProto is the prototype to use for the interface prototype object.
  * protoClass is the JSClass to use for the interface prototype object.
  *            This is null if we should not create an interface prototype
  *            object.
  * constructorClass is the JSClass to use for the interface object.
  *                  This is null if we should not create an interface object.
  * methods and properties are to be defined on the interface prototype object;
  *                        these arguments are allowed to be null if there are no
  *                        methods or properties respectively.
@@ -237,21 +241,21 @@ struct ConstantSpec
  * If constructorClass is non-null, the resulting interface object will be
  * defined on the given global with property name |name|, which must also be
  * non-null.
  *
  * returns the interface prototype object if protoClass is non-null, else it
  * returns the interface object.
  */
 JSObject*
-CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* parentProto,
-                       JSClass* protoClass, JSClass* constructorClass,
-                       JSFunctionSpec* methods, JSPropertySpec* properties,
-                       ConstantSpec* constants, JSFunctionSpec* staticMethods,
-                       const char* name);
+CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver,
+                       JSObject* protoProto, JSClass* protoClass,
+                       JSClass* constructorClass, JSFunctionSpec* methods,
+                       JSPropertySpec* properties, ConstantSpec* constants,
+                       JSFunctionSpec* staticMethods, const char* name);
 
 template <class T>
 inline bool
 WrapNewBindingObject(JSContext* cx, JSObject* scope, T* value, JS::Value* vp)
 {
   JSObject* obj = value->GetWrapper();
   if (obj && js::GetObjectCompartment(obj) == js::GetObjectCompartment(scope)) {
     *vp = JS::ObjectValue(*obj);
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -42,16 +42,17 @@
 %{C++
 class nsWrapperCache;
 %}
 
 [ptr] native nsWrapperCachePtr(nsWrapperCache);
 
 typedef unsigned long long DOMTimeStamp;
 typedef unsigned long long DOMTimeMilliSec;
+typedef double DOMHighResTimeStamp;
 
 // Core
 interface nsIDOMAttr;
 interface nsIDOMCDATASection;
 interface nsIDOMCharacterData;
 interface nsIDOMComment;
 interface nsIDOMDOMImplementation;
 interface nsIDOMDocument;
--- a/dom/interfaces/base/nsIDOMPerformance.idl
+++ b/dom/interfaces/base/nsIDOMPerformance.idl
@@ -32,19 +32,21 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "nsISupports.idl"
+#include "domstubs.idl"
 interface nsIDOMPerformanceTiming;
 interface nsIDOMPerformanceNavigation;
 
-[scriptable, uuid(446faf26-000b-4e66-a5fd-ae37c5ed6beb)]
+[scriptable, uuid(ac274ec8-ee9f-44ef-b2f0-b13c22225a98)]
 interface nsIDOMPerformance : nsISupports
 {
   readonly attribute nsIDOMPerformanceTiming timing;
   readonly attribute nsIDOMPerformanceNavigation navigation;
+
+  DOMHighResTimeStamp now();
 };
 
--- a/dom/interfaces/html/nsIDOMHTMLVideoElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLVideoElement.idl
@@ -43,17 +43,17 @@
  * <video> element.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#video
  *
  * @status UNDER_DEVELOPMENT
  */
 
-[scriptable, uuid(E3763903-928B-47C4-AC3B-C47EB43884CA)]
+[scriptable, uuid(0a1c8b44-12a4-4316-b39f-feeee48475f8)]
 interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement
 {
            attribute long width; 
            attribute long height;
   readonly attribute unsigned long videoWidth;
   readonly attribute unsigned long videoHeight;
            attribute DOMString poster;
            
@@ -70,10 +70,13 @@ interface nsIDOMHTMLVideoElement : nsIDO
   // pipeline. We may drop frames if they arrive late at the renderer.
   readonly attribute unsigned long mozPresentedFrames;
 
   // Number of presented frames which were painted on screen.
   readonly attribute unsigned long mozPaintedFrames;
 
   // Time which the last painted video frame was late by, in seconds.
   readonly attribute double mozFrameDelay;
+
+  // True if the video has an audio track available.
+  readonly attribute bool mozHasAudio;
 };
 
--- a/dom/interfaces/settings/Makefile.in
+++ b/dom/interfaces/settings/Makefile.in
@@ -10,11 +10,12 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE         = dom
 XPIDL_MODULE   = dom_settings
 GRE_MODULE     = 1
 
 XPIDLSRCS =                           \
             nsIDOMSettingsManager.idl \
+            nsISettingsService.idl    \
             $(NULL)
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/settings/nsISettingsService.idl
@@ -0,0 +1,27 @@
+/* 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 "domstubs.idl"
+
+[scriptable, uuid(83d67430-8516-11e1-b0c4-0800200c9a66)]
+interface nsISettingsServiceCallback : nsISupports
+{
+  [implicit_jscontext]
+  void handle(in DOMString aName, in jsval aResult);
+  [implicit_jscontext]
+  void handleError(in DOMString aErrorMessage);
+};
+
+[scriptable, uuid(3ab3cbc0-8513-11e1-b0c4-0800200c9a66)]
+interface nsISettingsServiceLock : nsISupports
+{
+  void set(in string aName, in jsval aValue, in nsISettingsServiceCallback aCallback);
+  void get(in string aName, in nsISettingsServiceCallback aCallback);
+};
+
+[scriptable, uuid(3458e760-8513-11e1-b0c4-0800200c9a66)]
+interface nsISettingsService : nsISupports
+{
+  nsISettingsServiceLock getLock();
+};
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1768,71 +1768,33 @@ void nsPluginInstanceOwner::SendSize(int
 bool nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
 {
   void* javaSurface = mInstance->GetJavaSurface();
   if (!javaSurface) {
     mInstance->RequestJavaSurface();
     return false;
   }
 
-  JNIEnv* env = GetJNIForThread();
-  if (!env)
-    return false;
-
-  AndroidBridge::AutoLocalJNIFrame frame(env, 1);
-
-  jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
-
-#ifdef MOZ_JAVA_COMPOSITOR
-  nsAutoString metadata;
-  nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider =
-      AndroidBridge::Bridge()->GetDrawMetadataProvider();
-  metadataProvider->GetDrawMetadata(metadata);
-
-  jstring jMetadata = env->NewString(nsPromiseFlatString(metadata).get(), metadata.Length());
-
-  jmethodID method = env->GetStaticMethodID(cls,
-                                            "addPluginView",
-                                            "(Landroid/view/View;IIIILjava/lang/String;)V");
-
-  env->CallStaticVoidMethod(cls,
-                            method,
-                            javaSurface,
-                            (int)aRect.x,
-                            (int)aRect.y,
-                            (int)aRect.width,
-                            (int)aRect.height,
-                            jMetadata);
-#else
-  jmethodID method = env->GetStaticMethodID(cls,
-                                            "addPluginView",
-                                            "(Landroid/view/View;DDDD)V");
-
-  env->CallStaticVoidMethod(cls,
-                            method,
-                            javaSurface,
-                            aRect.x,
-                            aRect.y,
-                            aRect.width,
-                            aRect.height);
-#endif
+  if (AndroidBridge::Bridge())
+    AndroidBridge::Bridge()->AddPluginView((jobject)javaSurface, aRect);
 
   return true;
 }
 
 void nsPluginInstanceOwner::RemovePluginView()
 {
   if (!mInstance)
     return;
 
   void* surface = mInstance->GetJavaSurface();
   if (!surface)
     return;
 
-  AndroidBridge::RemovePluginView(surface);
+  if (AndroidBridge::Bridge())
+    AndroidBridge::Bridge()->RemovePluginView((jobject)surface);
 }
 
 void nsPluginInstanceOwner::Invalidate() {
   NPRect rect;
   rect.left = rect.top = 0;
   rect.right = mPluginWindow->width;
   rect.bottom = mPluginWindow->height;
   InvalidateRect(&rect);
@@ -2908,36 +2870,47 @@ void nsPluginInstanceOwner::Paint(gfxCon
                                   const gfxRect& aFrameRect,
                                   const gfxRect& aDirtyRect)
 {
   if (!mInstance || !mObjectFrame || !mPluginDocumentActiveState)
     return;
 
   PRInt32 model = mInstance->GetANPDrawingModel();
 
-  float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
-  float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
-
-  gfxRect scaledFrameRect = aFrameRect;
-  scaledFrameRect.Scale(xResolution, yResolution);
+  // Get the offset of the content relative to the page
+
+  nsPoint offset = nsPoint(0, 0);
+  nsIFrame* current = (nsIFrame*)mObjectFrame;
+  while (current && current->GetContent() && current->GetContent()->Tag() != nsGkAtoms::html) {    
+    offset += current->GetPosition();
+    current = current->GetParent();
+  }
+
+  nsRect bounds = nsRect(offset, mObjectFrame->GetSize());
+  nsIntRect intBounds = bounds.ToNearestPixels(mObjectFrame->PresContext()->AppUnitsPerDevPixel());
+  gfxRect pluginRect(intBounds);
 
   if (model == kSurface_ANPDrawingModel) {
-    if (!AddPluginView(scaledFrameRect)) {
+    if (!AddPluginView(pluginRect)) {
       Invalidate();
     }
     return;
   }
 
   if (model == kOpenGL_ANPDrawingModel) {
     if (!mLayer)
       mLayer = new AndroidMediaLayer();
 
-    mLayer->UpdatePosition(scaledFrameRect, xResolution);
-
-    SendSize((int)scaledFrameRect.width, (int)scaledFrameRect.height);
+    mLayer->UpdatePosition(pluginRect);
+
+    float xResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetXResolution();
+    float yResolution = mObjectFrame->PresContext()->GetRootPresContext()->PresShell()->GetYResolution();
+    pluginRect.Scale(xResolution, yResolution);
+
+    SendSize((int)pluginRect.width, (int)pluginRect.height);
     return;
   }
 
   if (model != kBitmap_ANPDrawingModel)
     return;
 
 #ifdef ANP_BITMAP_DRAWING_MODEL
   static nsRefPtr<gfxImageSurface> pluginSurface;
--- a/dom/settings/Makefile.in
+++ b/dom/settings/Makefile.in
@@ -13,16 +13,23 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE         = dom
 LIBRARY_NAME   = jsdomsettings_s
 LIBXUL_LIBRARY = 1
 
 EXTRA_COMPONENTS =         \
   SettingsManager.js       \
   SettingsManager.manifest \
+  SettingsService.js \
+  SettingsService.manifest \
+  $(NULL)
+
+EXTRA_JS_MODULES =   \
+  SettingsQueue.jsm  \
+  SettingsDB.jsm     \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += tests
 endif
 
 # Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
 # subdirectory (and the ipc one).
new file mode 100644
--- /dev/null
+++ b/dom/settings/SettingsDB.jsm
@@ -0,0 +1,36 @@
+/* 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 EXPORTED_SYMBOLS = ["SettingsDB", "SETTINGSDB_NAME", "SETTINGSSTORE_NAME"];
+
+/* static functions */
+let DEBUG = 0;
+if (DEBUG) {
+  debug = function (s) { dump("-*- SettingsDB: " + s + "\n"); }
+} else {
+  debug = function (s) {}
+}
+
+const SETTINGSDB_NAME = "settings";
+const SETTINGSDB_VERSION = 1;
+const SETTINGSSTORE_NAME = "settings";
+
+Components.utils.import("resource://gre/modules/IndexedDBHelper.jsm");
+
+function SettingsDB() {}
+
+SettingsDB.prototype = {
+
+  __proto__: IndexedDBHelper.prototype,
+
+  createSchema: function createSchema(aDb) {
+    let objectStore = aDb.createObjectStore(SETTINGSSTORE_NAME, { keyPath: "settingName" });
+    objectStore.createIndex("settingValue", "settingValue", { unique: false });
+    debug("Created object stores and indexes");
+  },
+
+  init: function init(aGlobal) {
+      this.initDBHelper(SETTINGSDB_NAME, SETTINGSDB_VERSION, SETTINGSSTORE_NAME, aGlobal);
+  }
+}
--- a/dom/settings/SettingsManager.js
+++ b/dom/settings/SettingsManager.js
@@ -6,67 +6,22 @@
 
 /* static functions */
 let DEBUG = 0;
 if (DEBUG)
   debug = function (s) { dump("-*- SettingsManager: " + s + "\n"); }
 else
   debug = function (s) {}
 
-function Queue() {
-  this._queue = [];
-  this._index = 0;
-}
-
-Queue.prototype = {
-  getLength: function() { return (this._queue.length - this._index); },
-
-  isEmpty: function() { return (this._queue.length == 0); },
-
-  enqueue: function(item) { this._queue.push(item); },
-
-  dequeue: function() {
-    if(this.isEmpty())
-      return undefined;
-
-    var item = this._queue[this._index];
-    if (++this._index * 2 >= this._queue.length){
-      this._queue  = this._queue.slice(this._index);
-      this._index = 0;
-    }
-    return item;
-  }
-}
-
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
-Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
-
-const DB_NAME = "settings";
-const DB_VERSION = 1;
-const STORE_NAME = "settings";
-
-function SettingsDB() {}
-
-SettingsDB.prototype = {
-  __proto__: IndexedDBHelper.prototype,
-
-  createSchema: function createSchema(aDb) {
-    let objectStore = aDb.createObjectStore(STORE_NAME, { keyPath: "settingName" });
-    objectStore.createIndex("settingValue", "settingValue", { unique: false });
-    debug("Created object stores and indexes");
-  },
-
-  init: function init(aGlobal) {
-      this.initDBHelper(DB_NAME, DB_VERSION, STORE_NAME, aGlobal);
-  }
-}
-
+Cu.import("resource://gre/modules/SettingsQueue.jsm");
+Cu.import("resource://gre/modules/SettingsDB.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 const nsIClassInfo            = Ci.nsIClassInfo;
 const SETTINGSLOCK_CONTRACTID = "@mozilla.org/settingsLock;1";
 const SETTINGSLOCK_CID        = Components.ID("{ef95ddd0-6308-11e1-b86c-0800200c9a66}");
 const nsIDOMSettingsLock      = Ci.nsIDOMSettingsLock;
 
@@ -78,17 +33,17 @@ function SettingsLock(aSettingsManager)
   this._transaction = null;
 }
 
 SettingsLock.prototype = {
 
   process: function process() {
     let lock = this;
     lock._open = false;
-    let store = lock._transaction.objectStore(STORE_NAME);
+    let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
 
     while (!lock._requests.isEmpty()) {
       let info = lock._requests.dequeue();
       debug("info:" + info.intent);
       let request = info.request;
       switch (info.intent) {
         case "clear":
           let req = store.clear();
@@ -147,17 +102,17 @@ SettingsLock.prototype = {
     lock._open = true;
   },
 
   createTransactionAndProcess: function() {
     if (this._settingsManager._settingsDB._db) {
       var lock;
       while (lock = this._settingsManager._locks.dequeue()) {
         if (!lock._transaction) {
-          lock._transaction = lock._settingsManager._settingsDB._db.transaction(STORE_NAME, "readwrite");
+          lock._transaction = lock._settingsManager._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
         }
         lock.process();
       }
       if (!this._requests.isEmpty())
         this.process();
     }
   },
 
new file mode 100644
--- /dev/null
+++ b/dom/settings/SettingsQueue.jsm
@@ -0,0 +1,30 @@
+/* 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 EXPORTED_SYMBOLS = ["Queue"];
+
+function Queue() {
+  this._queue = [];
+  this._index = 0;
+}
+
+Queue.prototype = {
+  getLength: function() { return (this._queue.length - this._index); },
+
+  isEmpty: function() { return (this._queue.length == 0); },
+
+  enqueue: function(item) { this._queue.push(item); },
+
+  dequeue: function() {
+    if(this.isEmpty())
+      return undefined;
+
+    var item = this._queue[this._index];
+    if (++this._index * 2 >= this._queue.length){
+      this._queue  = this._queue.slice(this._index);
+      this._index = 0;
+    }
+    return item;
+  }
+}
new file mode 100644
--- /dev/null
+++ b/dom/settings/SettingsService.js
@@ -0,0 +1,183 @@
+/* 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/. */
+
+"use strict"
+
+/* static functions */
+let DEBUG = 0;
+if (DEBUG)
+  debug = function (s) { dump("-*- SettingsService: " + s + "\n"); }
+else
+  debug = function (s) {}
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/SettingsQueue.jsm");
+Cu.import("resource://gre/modules/SettingsDB.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+const nsIClassInfo            = Ci.nsIClassInfo;
+
+const SETTINGSSERVICELOCK_CONTRACTID = "@mozilla.org/settingsServiceLock;1";
+const SETTINGSSERVICELOCK_CID        = Components.ID("{3ab3cbc0-8513-11e1-b0c4-0800200c9a66}");
+const nsISettingsServiceLock         = Ci.nsISettingsServiceLock;
+
+function SettingsServiceLock(aSettingsService)
+{
+  debug("settingsServiceLock constr!");
+  this._open = true;
+  this._requests = new Queue();
+  this._settingsService = aSettingsService;
+  this._transaction = null;
+}
+
+SettingsServiceLock.prototype = {
+
+  process: function process() {
+    debug("process!");
+    let lock = this;
+    lock._open = false;
+    let store = lock._transaction.objectStore(SETTINGSSTORE_NAME);
+
+    while (!lock._requests.isEmpty()) {
+      let info = lock._requests.dequeue();
+      debug("info:" + info.intent);
+      let callback = info.callback;
+      let req;
+      let name = info.name;
+      switch (info.intent) {
+        case "set":
+          let value = info.value;
+          if(typeof(value) == 'object')
+            debug("object name:" + name + ", val: " + JSON.stringify(value));
+          req = store.put({settingName: name, settingValue: value});
+
+          req.onsuccess = function() {
+            debug("set on success");
+            lock._open = true;
+            if (callback)
+              callback.handle(name, value);
+            Services.obs.notifyObservers(lock, "mozsettings-changed", JSON.stringify({
+              key: name,
+              value: value
+            }));
+            lock._open = false;
+          };
+
+          req.onerror = function(event) { callback ? callback.handleError(event.target.errorMessage) : null; };
+          break;
+        case "get":
+          req = store.getAll(name);
+          req.onsuccess = function(event) {
+            debug("Request successful. Record count:" + event.target.result.length);
+            debug("result: " + JSON.stringify(event.target.result));
+            this._open = true;
+            if (callback) {
+              if (event.target.result[0]) {
+                if (event.target.result.length > 1) {
+                  debug("Warning: overloaded setting:" + name);
+                }
+                callback.handle(name, event.target.result[0].settingValue);
+              } else
+                callback.handle(name, null);
+            } else {
+              debug("no callback defined!");
+            }
+            this._open = false;
+          }.bind(lock);
+          req.onerror = function error(event) { callback ? callback.handleError(event.target.errorMessage) : null; };
+          break;
+      }
+    }
+    if (!lock._requests.isEmpty())
+      throw Components.results.NS_ERROR_ABORT;
+    lock._open = true;
+  },
+
+  createTransactionAndProcess: function createTransactionAndProcess() {
+    if (this._settingsService._settingsDB._db) {
+      var lock;
+      while (lock = this._settingsService._locks.dequeue()) {
+        if (!lock._transaction) {
+          lock._transaction = lock._settingsService._settingsDB._db.transaction(SETTINGSSTORE_NAME, "readwrite");
+        }
+        lock.process();
+      }
+      if (!this._requests.isEmpty())
+        this.process();
+    }
+  },
+
+  get: function get(aName, aCallback) {
+    debug("get: " + aName + ", " + aCallback);
+    this._requests.enqueue({ callback: aCallback, intent:"get", name: aName });
+    this.createTransactionAndProcess();
+  },
+
+  set: function set(aName, aValue, aCallback) {
+    debug("set: " + aName + ": " + JSON.stringify(aValue));
+    this._requests.enqueue({ callback: aCallback, intent: "set", name: aName, value: aValue});
+    this.createTransactionAndProcess();
+  },
+
+  classID : SETTINGSSERVICELOCK_CID,
+  QueryInterface : XPCOMUtils.generateQI([nsISettingsServiceLock]),
+
+  classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICELOCK_CID,
+                                     contractID: SETTINGSSERVICELOCK_CONTRACTID,
+                                     classDescription: "SettingsServiceLock",
+                                     interfaces: [nsISettingsServiceLock],
+                                     flags: nsIClassInfo.DOM_OBJECT})
+};
+
+const SETTINGSSERVICE_CONTRACTID = "@mozilla.org/settingsService;1";
+const SETTINGSSERVICE_CID        = Components.ID("{3458e760-8513-11e1-b0c4-0800200c9a66}");
+const nsISettingsService         = Ci.nsISettingsService;
+
+let myGlobal = this;
+
+function SettingsService()
+{
+  debug("settingsService Constructor");
+  this._locks = new Queue();
+  var idbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"].getService(Ci.nsIIndexedDatabaseManager);
+  idbManager.initWindowless(myGlobal);
+  this._settingsDB = new SettingsDB();
+  this._settingsDB.init(myGlobal);
+}
+
+SettingsService.prototype = {
+
+  nextTick: function nextTick(aCallback, thisObj) {
+    if (thisObj)
+      aCallback = aCallback.bind(thisObj);
+
+    Services.tm.currentThread.dispatch(aCallback, Ci.nsIThread.DISPATCH_NORMAL);
+  },
+
+  getLock: function getLock() {
+    debug("get lock!");
+    var lock = new SettingsServiceLock(this);
+    this._locks.enqueue(lock);
+    this._settingsDB.ensureDB(
+      function() { lock.createTransactionAndProcess(); },
+      function() { dump("ensureDB error cb!\n"); },
+      myGlobal );
+    this.nextTick(function() { this._open = false; }, lock);
+    return lock;
+  },
+
+  classID : SETTINGSSERVICE_CID,
+  QueryInterface : XPCOMUtils.generateQI([nsISettingsService]),
+
+  classInfo : XPCOMUtils.generateCI({classID: SETTINGSSERVICE_CID,
+                                     contractID: SETTINGSSERVICE_CONTRACTID,
+                                     classDescription: "SettingsService",
+                                     interfaces: [nsISettingsService],
+                                     flags: nsIClassInfo.DOM_OBJECT})
+}
+
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([SettingsService, SettingsServiceLock])
new file mode 100644
--- /dev/null
+++ b/dom/settings/SettingsService.manifest
@@ -0,0 +1,5 @@
+component {3ab3cbc0-8513-11e1-b0c4-0800200c9a66} SettingsService.js
+contract @mozilla.org/settingsServiceLock;1 {3ab3cbc0-8513-11e1-b0c4-0800200c9a66}
+
+component {3458e760-8513-11e1-b0c4-0800200c9a66} SettingsService.js
+contract @mozilla.org/settingsService;1 {3458e760-8513-11e1-b0c4-0800200c9a66}
--- a/dom/settings/tests/Makefile.in
+++ b/dom/settings/tests/Makefile.in
@@ -6,19 +6,16 @@ DEPTH            = ../../..
 topsrcdir        = @top_srcdir@
 srcdir           = @srcdir@
 VPATH            = @srcdir@
 
 relativesrcdir   = dom/settings/tests
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS = \
-  $(NULL)
-
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = \
   test_settings_basics.html \
   test_settings_events.html \
   $(NULL)
 
 _CHROME_TEST_FILES = \
--- a/dom/tests/mochitest/chrome/Makefile.in
+++ b/dom/tests/mochitest/chrome/Makefile.in
@@ -73,16 +73,17 @@ include $(topsrcdir)/config/rules.mk
 		489127.html \
 		test_focus_docnav.xul \
 		window_focus_docnav.xul \
 		test_clonewrapper.xul \
 		test_moving_nodeList.xul \
 		test_callback_wrapping.xul \
 		window_callback_wrapping.xul \
 		test_sandbox_postMessage.html \
+		test_sandbox_bindings.xul \
 		$(NULL)
 
 ifeq (WINNT,$(OS_ARCH))
 _TEST_FILES += \
 		test_sizemode_attribute.xul \
 		sizemode_attribute.xul \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=741267
+-->
+<window title="Mozilla Bug 741267"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <iframe id="t"></iframe>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741267"
+     target="_blank">Mozilla Bug 741267</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+
+  /** Test for Bug 741267 **/
+    function doTest() {
+      var win = $("t").contentWindow;
+      var sandbox = Components.utils.Sandbox(win, { sandboxPrototype: win });
+      try {
+        var nl = Components.utils.evalInSandbox("NodeList", sandbox);
+        is(nl, "[object NodeList]", "'NodeList' in a sandbox should return the NodeList interface prototype object");
+      } catch (e) {
+        ok(false, "'NodeList' shouldn't throw in a sandbox");
+      }
+      try {
+        var et = Components.utils.evalInSandbox("EventTarget", sandbox);
+        ok(et, "'EventTarget' in a sandbox should return the EventTarget interface prototype object");
+      } catch (e) {
+        ok(false, "'EventTarget' shouldn't throw in a sandbox");
+      }
+      try {
+        var xhr = Components.utils.evalInSandbox("XMLHttpRequest()", sandbox);
+        is(xhr, "[object XMLHttpRequest]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object");
+      } catch (e) {
+        ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox");
+      }
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(doTest);
+  ]]>
+  </script>
+</window>
--- a/dom/tests/mochitest/general/Makefile.in
+++ b/dom/tests/mochitest/general/Makefile.in
@@ -71,16 +71,17 @@ include $(topsrcdir)/config/rules.mk
 		test_windowedhistoryframes.html \
 		test_focusrings.xul \
 		file_moving_xhr.html \
 		test_vibrator.html \
 		test_for_of.html \
 		test_focus_legend_noparent.html \
 		file_clonewrapper.html \
 		file_moving_nodeList.html \
+		test_performance_now.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_innerScreen.xul \
 		test_offsets.xul \
 		test_offsets.js \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_performance_now.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for High Resolution Timer</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>
+  <script>
+    ok(window.performance);
+    ok(typeof window.performance.now == 'function');
+    var n = window.performance.now();
+    ok(n >= 0);
+    ok(window.performance.now() >= n);
+    SimpleTest.waitForExplicitFinish();
+    setTimeout(function() {
+      ok(window.performance.now() > n);
+      SimpleTest.finish();
+    }, 20);
+  </script>
+</body>
+</html>
--- a/dom/workers/DOMBindingInlines.h
+++ b/dom/workers/DOMBindingInlines.h
@@ -32,17 +32,17 @@ struct WrapPrototypeTraits
       using namespace mozilla::dom::bindings::prototypes;                      \
       return _class##_workers::Class.ToJSClass();                              \
     }                                                                          \
                                                                                \
     static inline JSObject*                                                    \
     GetProtoObject(JSContext* aCx, JSObject* aGlobal)                          \
     {                                                                          \
       using namespace mozilla::dom::bindings::prototypes;                      \
-      return _class##_workers::GetProtoObject(aCx, aGlobal);                   \
+      return _class##_workers::GetProtoObject(aCx, aGlobal, aGlobal);          \
     }                                                                          \
   };
 
 SPECIALIZE_PROTO_TRAITS(XMLHttpRequest)
 SPECIALIZE_PROTO_TRAITS(XMLHttpRequestUpload)
 
 #undef SPECIALIZE_PROTO_TRAITS
 
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -444,17 +444,17 @@ ResolveWorkerClasses(JSContext* aCx, JSO
 
   if (shouldResolve) {
     // Don't do anything if workers are disabled.
     if (!isChrome && !Preferences::GetBool(PREF_WORKERS_ENABLED)) {
       *aObjp = nsnull;
       return true;
     }
 
-    JSObject* eventTarget = EventTarget_workers::GetProtoObject(aCx, aObj);
+    JSObject* eventTarget = EventTarget_workers::GetProtoObject(aCx, aObj, aObj);
     if (!eventTarget) {
       return false;
     }
 
     JSObject* worker = worker::InitClass(aCx, aObj, eventTarget, true);
     if (!worker) {
       return false;
     }
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -953,17 +953,18 @@ CreateDedicatedWorkerGlobalScope(JSConte
   }
 
   // Proto chain should be:
   //   global -> DedicatedWorkerGlobalScope
   //          -> WorkerGlobalScope
   //          -> EventTarget
   //          -> Object
 
-  JSObject* eventTargetProto = EventTarget_workers::GetProtoObject(aCx, global);
+  JSObject* eventTargetProto =
+    EventTarget_workers::GetProtoObject(aCx, global, global);
   if (!eventTargetProto) {
     return NULL;
   }
 
   JSObject* scopeProto =
     WorkerGlobalScope::InitClass(aCx, global, eventTargetProto);
   if (!scopeProto) {
     return NULL;
@@ -998,18 +999,19 @@ CreateDedicatedWorkerGlobalScope(JSConte
       !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)) {
+  if (!XMLHttpRequest_workers::CreateInterfaceObjects(aCx, global, global) ||
+      !XMLHttpRequestUpload_workers::CreateInterfaceObjects(aCx, global,
+                                                            global)) {
     return NULL;
   }
 
   if (!JS_DefineProfilingFunctions(aCx, global)) {
     return NULL;
   }
 
   return global;
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -1821,19 +1821,16 @@ public class GeckoAppShell
             // http://developer.android.com/guide/practices/screens_support.html
             if ((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE) {
                 return true;
             }
         }
         return false;
     }
 
-    public static void emitGeckoAccessibilityEvent (int eventType, String[] textList, String description, boolean enabled, boolean checked, boolean password) {
-    }
-
     public static double[] getCurrentNetworkInformation() {
         return GeckoNetworkManager.getInstance().getCurrentInformation();
     }
 
     public static void enableNetworkNotifications() {
         GeckoNetworkManager.getInstance().enableNotifications();
     }
 
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -636,16 +636,21 @@ CopyAndPadTextureData(const GLvoid* srcB
 // far work fine with NPOT textures, so don't blacklist those until we
 // have evidence of any problems with them.
 bool
 GLContext::CanUploadSubTextures()
 {
     if (!mWorkAroundDriverBugs)
         return true;
 
+    // Lock surface feature allows to mmap texture memory and modify it directly
+    // this feature allow us modify texture partially without full upload
+    if (HasLockSurface())
+        return true;
+
     // There are certain GPUs that we don't want to use glTexSubImage2D on
     // because that function can be very slow and/or buggy
     if (Renderer() == RendererAdreno200 || Renderer() == RendererAdreno205)
         return false;
 
     // On PowerVR glTexSubImage does a readback, so it will be slower
     // than just doing a glTexImage2D() directly. i.e. 26ms vs 10ms
     if (Renderer() == RendererSGX540 || Renderer() == RendererSGX530)
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -726,16 +726,17 @@ public:
 
     int Renderer() const {
         return mRenderer;
     }
 
     bool CanUploadSubTextures();
     bool CanUploadNonPowerOfTwo();
     bool WantsSmallTiles();
+    virtual bool HasLockSurface() { return false; }
 
     /**
      * If this context wraps a double-buffered target, swap the back
      * and front buffers.  It should be assumed that after a swap, the
      * contents of the new back buffer are undefined.
      */
     virtual bool SwapBuffers() { return false; }
 
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -592,16 +592,20 @@ public:
                                                    EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, (void**) &h))
         {
             return nsnull;
         }
 
         return h;
     }
 
+    virtual bool HasLockSurface() {
+        return sEGLLibrary.HasKHRLockSurface();
+    }
+
 protected:
     friend class GLContextProviderEGL;
 
     EGLConfig  mConfig;
     EGLSurface mSurface;
     EGLContext mContext;
     void *mPlatformContext;
     nsRefPtr<gfxASurface> mThebesSurface;
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -812,18 +812,23 @@ LayerManagerOGL::Render()
     WorldTransformRect(r);
     mGLContext->fScissor(r.x, r.y, r.width, r.height);
   } else {
     mGLContext->fScissor(0, 0, width, height);
   }
 
   mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
 
+  // If the Java compositor is being used, this clear will be done in
+  // DrawWindowUnderlay. Make sure the bits used here match up with those used
+  // in mobile/android/base/gfx/LayerRenderer.java
+#ifndef MOZ_JAVA_COMPOSITOR
   mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
   mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
+#endif
 
   // Allow widget to render a custom background.
   mWidget->DrawWindowUnderlay(this, rect);
 
   // Render our layers.
   RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO,
                            nsIntPoint(0, 0));
 
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -224,16 +224,17 @@ GDIFontEntry::ReadCMAP()
     }
 
     // skip non-SFNT fonts completely
     if (mFontType != GFX_FONT_TYPE_PS_OPENTYPE && 
         mFontType != GFX_FONT_TYPE_TT_OPENTYPE &&
         mFontType != GFX_FONT_TYPE_TRUETYPE) 
     {
         mCharacterMap = new gfxCharacterMap();
+        mCharacterMap->mBuildOnTheFly = true;
         return NS_ERROR_FAILURE;
     }
 
     nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
 
     PRUint32 kCMAP = TRUETYPE_TAG('c','m','a','p');
     nsresult rv;
 
--- a/ipc/chromium/src/base/histogram.cc
+++ b/ipc/chromium/src/base/histogram.cc
@@ -957,16 +957,41 @@ FlagHistogram::Accumulate(Sample value, 
 
   mSwitched = true;
   DCHECK_EQ(value, 1);
   Histogram::Accumulate(value, 1, index);
   size_t zero_index = BucketIndex(0);
   Histogram::Accumulate(1, -1, zero_index);
 }
 
+void
+FlagHistogram::AddSampleSet(const SampleSet& sample) {
+  DCHECK_EQ(bucket_count(), sample.size());
+  // We can't be sure the SampleSet provided came from another FlagHistogram,
+  // so we take the following steps:
+  //  - If our flag has already been set do nothing.
+  //  - Set our flag if the following hold:
+  //      - The sum of the counts in the provided SampleSet is 1.
+  //      - The bucket index for that single value is the same as the index where we
+  //        would place our set flag.
+  //  - Otherwise, take no action.
+
+  if (mSwitched) {
+    return;
+  }
+
+  if (sample.sum() != 1) {
+    return;
+  }
+
+  size_t one_index = BucketIndex(1);
+  if (sample.counts(one_index) == 1) {
+    Accumulate(1, 1, one_index);
+  }
+}
 //------------------------------------------------------------------------------
 // CustomHistogram:
 //------------------------------------------------------------------------------
 
 Histogram* CustomHistogram::FactoryGet(const std::string& name,
                                        const std::vector<Sample>& custom_ranges,
                                        Flags flags) {
   Histogram* histogram(NULL);
--- a/ipc/chromium/src/base/histogram.h
+++ b/ipc/chromium/src/base/histogram.h
@@ -331,16 +331,17 @@ class Histogram {
     // Accessor for histogram to make routine additions.
     void Accumulate(Sample value, Count count, size_t index);
 
     // Accessor methods.
     Count counts(size_t i) const { return counts_[i]; }
     Count TotalCount() const;
     int64 sum() const { return sum_; }
     int64 redundant_count() const { return redundant_count_; }
+    size_t size() const { return counts_.size(); }
 
     // Arithmetic manipulation of corresponding elements of the set.
     void Add(const SampleSet& other);
     void Subtract(const SampleSet& other);
 
     bool Serialize(Pickle* pickle) const;
     bool Deserialize(void** iter, const Pickle& pickle);
 
@@ -387,17 +388,17 @@ class Histogram {
   // This method is an interface, used only by BooleanHistogram.
   virtual void AddBoolean(bool value);
 
   // Accept a TimeDelta to increment.
   void AddTime(TimeDelta time) {
     Add(static_cast<int>(time.InMilliseconds()));
   }
 
-  void AddSampleSet(const SampleSet& sample);
+  virtual void AddSampleSet(const SampleSet& sample);
 
   // This method is an interface, used only by LinearHistogram.
   virtual void SetRangeDescriptions(const DescriptionPair descriptions[]);
 
   // The following methods provide graphical histogram displays.
   void WriteHTMLGraph(std::string* output) const;
   void WriteAscii(bool graph_it, const std::string& newline,
                   std::string* output) const;
@@ -656,16 +657,18 @@ class FlagHistogram : public BooleanHist
 {
 public:
   static Histogram *FactoryGet(const std::string &name, Flags flags);
 
   virtual ClassType histogram_type() const;
 
   virtual void Accumulate(Sample value, Count count, size_t index);
 
+  virtual void AddSampleSet(const SampleSet& sample);
+
 private:
   explicit FlagHistogram(const std::string &name);
   bool mSwitched;
 
   DISALLOW_COPY_AND_ASSIGN(FlagHistogram);
 };
 
 //------------------------------------------------------------------------------
--- a/js/src/config/makefiles/autotargets.mk
+++ b/js/src/config/makefiles/autotargets.mk
@@ -45,13 +45,10 @@ endif
 #################################################################
 # One ring/dep to rule them all:
 #   config/rules.mk::all target is available by default
 #   Add $(AUTO_DEPS) as an explicit target dependency when needed.
 #################################################################
 
 AUTO_DEPS +=$(GENERATED_DIRS_DEPS)
 
-
 # Complain loudly if deps have not loaded so getargv != $(NULL)
-ifndef getargv
-  $(error config/makefiles/makeutil.mk has not been included)
-endif
+$(call requiredfunction,getargv)
--- a/js/src/config/makefiles/makeutils.mk
+++ b/js/src/config/makefiles/makeutils.mk
@@ -1,22 +1,15 @@
 # -*- makefile -*-
 # vim:set ts=8 sw=8 sts=8 noet:
 #
 # 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/.
 
-# Usage: $(call banner,foo bar tans)
-banner =\
-$(info )\
-$(info ***************************************************************************)\
-$(info ** BANNER: $(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9))\
-$(info ***************************************************************************)\
-
 ## Identify function argument types
 istype =$(if $(value ${1}),list,scalar)
 isval  =$(if $(filter-out list,$(call istype,${1})),true)
 isvar  =$(if $(filter-out scalar,$(call istype,${1})),true)
 
 # Access up to 9 arguments passed, option needed to emulate $*
 # Inline for function expansion, do not use $(call )
 argv  =$(strip
@@ -30,16 +23,72 @@ argv +=)
 ## Access function args as a simple list, inline within user functions.
 ## Usage: $(info ** $(call banner,$(getargv)))
 ##    $(call banner,scalar)
 ##    $(call banner,list0 list1 list2)
 ##    $(call banner,ref) ; ref=foo bar tans
 ## getarglist() would be a more accurate name but is longer to type
 getargv = $(if $(call isvar,$(1)),$($(1)),$(argv))
 
+###########################################################################
+# Strip [n] leading options from an argument list.  This will allow passing
+# extra args to user functions that will not propogate to sub-$(call )'s
+# Usage: $(call subargv,2)
+subargv =$(wordlist $(1),$(words $(getargv)),$(getargv))
+
+###########################################################################
+# Intent: Display a distinct banner heading in the output stream
+# Usage: $(call banner,BUILDING: foo bar tans)
+# Debug:
+#   target-preqs = \
+#     $(call banner,target-preqs-BEGIN) \
+#     foo bar tans \
+#     $(call banner,target-preqs-END) \
+#     $(NULL)
+#   target: $(target-preqs)
+
+banner =\
+$(info )\
+$(info ***************************************************************************)\
+$(info ** $(getargv))\
+$(info ***************************************************************************)\
+$(NULL)
+
+#####################################################################
+# Intent: Determine if a string or pattern is contained in a list
+# Usage: strcmp  - $(call if_XinY,clean,$(MAKECMDGOALS))
+#      : pattern - $(call if_XinY,clean%,$(MAKECMDGOALS))
+is_XinY =$(filter $(1),$(call subargv,3,$(getargv)))
+
+#####################################################################
+# Provide an alternate var to support testing
+ifdef MAKEUTILS_UNIT_TEST
+  mcg_goals=TEST_MAKECMDGOALS
+else
+  mcg_goals=MAKECMDGOALS
+endif
+
+# Intent: Conditionals for detecting common/tier target use
+#   Todo: are check, install, test needed ?
+isTargetStem       = $(sort $(foreach pat, $(1)% %$(1), $(call is_XinY,$(pat),${$(mcg_goals)})))
+isTargetStemClean  = $(call isTargetStem,clean)
+isTargetStemExport = $(call isTargetStem,export)
+isTargetStemLibs   = $(call isTargetStem,libs)
+isTargetStemTools  = $(call isTargetStem,tools)
+
+##################################################
+# Intent: Validation functions / unit test helpers
+
+errorifneq =$(if $(subst $(strip $(1)),$(NULL),$(strip $(2))),$(error expected [$(1)] but found [$(2)]))
+
+# Intent: verify function declaration exists
+requiredfunction =$(foreach func,$(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9),$(if $(value $(func)),$(NULL),$(error required function [$(func)] is unavailable)))
+
+
+
 ## http://www.gnu.org/software/make/manual/make.html#Call-Function
 ## Usage: o = $(call map,origin,o map $(MAKE))
 map = $(foreach val,$(2),$(call $(1),$(val)))
 
 
 ## Disable checking for clean targets
 ifeq (,$(filter %clean clean%,$(MAKECMDGOALS)))
 
--- a/js/src/gc/Memory.h
+++ b/js/src/gc/Memory.h
@@ -9,24 +9,29 @@
 #define jsgc_memory_h___
 
 #include <stddef.h>
 #include "jsgc.h"
 
 namespace js {
 namespace gc {
 
-/*
- * Sanity check that our compiled configuration matches the currently running
- * instance and initialize any runtime data needed for allocation.
- */
+// Sanity check that our compiled configuration matches the currently running
+// instance and initialize any runtime data needed for allocation.
 void InitMemorySubsystem();
 
+// Allocate or deallocate pages from the system with the given alignment.
 void *MapAlignedPages(size_t size, size_t alignment);
 void UnmapPages(void *p, size_t size);
 
+// Tell the OS that the given pages are not in use, so they should not
+// be written to a paging file. This may be a no-op on some platforms.
 bool MarkPagesUnused(void *p, size_t size);
+
+// Undo |MarkPagesUnused|: tell the OS that the given pages are of interest
+// and should be paged in and out normally. This may be a no-op on some
+// platforms.
 bool MarkPagesInUse(void *p, size_t size);
 
 } /* namespace gc */
 } /* namespace js */
 
 #endif /* jsgc_memory_h___ */
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -97,40 +97,47 @@ namespace JS {
 
 template <typename T> class Root;
 template <typename T> class RootedVar;
 
 template <typename T>
 struct RootMethods { };
 
 /*
- * Reference to a stack location rooted for GC. See the "Moving GC Stack
- * Rooting" comment above.
+ * Reference to a T that has been rooted elsewhere. This is most useful
+ * as a parameter type, which guarantees that the T lvalue is properly
+ * rooted. See "Move GC Stack Rooting" above.
  */
 template <typename T>
 class Handle
 {
   public:
     /* Copy handles of different types, with implicit coercion. */
     template <typename S> Handle(Handle<S> handle) {
         testAssign<S>();
         ptr = reinterpret_cast<const T *>(handle.address());
     }
 
     /*
-     * Get a handle to a location that may not be a Root or RootedVar, but is
-     * marked and updated by the GC.
+     * This may be called only if the location of the T is guaranteed
+     * to be marked (for some reason other than being a Root or RootedVar),
+     * e.g., if it is guaranteed to be reachable from an implicit root.
+     *
+     * Create a Handle from a raw location of a T.
      */
     static Handle fromMarkedLocation(const T *p) {
         Handle h;
         h.ptr = p;
         return h;
     }
 
-    /* Get a handle from a rooted stack location, with implicit coercion. */
+    /*
+     * Construct a handle from an explicitly rooted location. This is the
+     * normal way to create a handle.
+     */
     template <typename S> inline Handle(const Root<S> &root);
     template <typename S> inline Handle(const RootedVar<S> &root);
 
     const T *address() { return ptr; }
 
     operator T () { return value(); }
     T operator ->() { return value(); }
 
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/Proxy-function-freeze.js
+++ /dev/null
@@ -1,115 +0,0 @@
-// Once a function proxy has been frozen, its handler's traps are no longer called,
-// but its call traps are.
-
-var callTrapCalls;
-function handleCall() {
-    print('call');
-    callTrapCalls++;
-    return 'favor';
-}
-function handleConstruct() {
-    print('construct');
-    callTrapCalls++;
-    return 'compliment';
-}
-
-var descriptorForX = { configurable: true, enumerable: true, writable: true, value: 42 };
-var trapCalls;
-var handler = {
-    getOwnPropertyNames: function () {
-        print('getOwnPropertyNames');
-        trapCalls++;
-        return ['x'];
-    },
-    getPropertyNames: function() {
-        print('getPropertyNames');
-        trapCalls++;
-        return ['x'];
-    },
-    getOwnPropertyDescriptor: function(name) {
-        print('getOwnPropertyDescriptor');
-        trapCalls++;
-        assertEq(name, 'x');
-        return descriptorForX;
-    },
-    getPropertyDescriptor: function(name) {
-        print('getPropertyDescriptor');
-        trapCalls++;
-        assertEq(name, 'x');
-        return descriptorForX;
-    },
-    defineProperty: function(name, propertyDescriptor) {
-        print('defineProperty');
-        trapCalls++;
-    },
-    delete: function(name) {
-        print('delete');
-        trapCalls++;
-        return false;
-    },
-    fix: function() {
-        print('fix');
-        trapCalls++;
-        return { x: descriptorForX };
-    }
-};
-
-var fp = Proxy.createFunction(handler, handleCall, handleConstruct);
-
-trapCalls = callTrapCalls = 0;
-assertEq(Object.getOwnPropertyNames(fp)[0], 'x');
-assertEq(trapCalls > 0, true);
-assertEq(callTrapCalls, 0);
-
-trapCalls = callTrapCalls = 0;
-assertEq(Object.getOwnPropertyDescriptor(fp, 'x').value, 42);
-assertEq(trapCalls > 0, true);
-assertEq(callTrapCalls, 0);
-
-trapCalls = callTrapCalls = 0;
-assertEq(delete fp.x, false);
-assertEq(trapCalls > 0, true);
-assertEq(callTrapCalls, 0);
-
-trapCalls = callTrapCalls = 0;
-assertEq(fp(), 'favor');
-assertEq(trapCalls, 0);
-assertEq(callTrapCalls, 1);
-
-trapCalls = callTrapCalls = 0;
-assertEq(new fp, 'compliment');
-assertEq(trapCalls, 0);
-assertEq(callTrapCalls, 1);
-
-trapCalls = callTrapCalls = 0;
-Object.freeze(fp);
-assertEq(trapCalls > 0, true);
-assertEq(callTrapCalls, 0);
-
-// Once the proxy has been frozen, its traps should never be invoked any
-// more.
-trapCalls = callTrapCalls = 0;
-assertEq(Object.getOwnPropertyNames(fp)[0], 'x');
-assertEq(trapCalls, 0);
-
-trapCalls = callTrapCalls = 0;
-assertEq(Object.getOwnPropertyDescriptor(fp, 'x').value, 42);
-assertEq(trapCalls, 0);
-
-trapCalls = callTrapCalls = 0;
-assertEq(delete fp.x, false);
-assertEq(trapCalls, 0);
-
-trapCalls = callTrapCalls = 0;
-assertEq(fp(), 'favor');
-assertEq(trapCalls, 0);
-assertEq(callTrapCalls, 1);
-
-trapCalls = callTrapCalls = 0;
-assertEq(new fp, 'compliment');
-assertEq(trapCalls, 0);
-assertEq(callTrapCalls, 1);
-
-trapCalls = callTrapCalls = 0;
-Object.freeze(fp);
-assertEq(trapCalls, 0);
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug684348.js
+++ /dev/null
@@ -1,4 +0,0 @@
-var x = Proxy.create({ fix: function() { return []; } });
-Object.__proto__ = x;
-Object.freeze(x);
-quit();
deleted file mode 100644
--- a/js/src/jit-test/tests/for-of/proxy-4.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// for-of on a fixed (non-trapping) proxy does not call the iterate trap.
-
-load(libdir + "asserts.js");
-
-var p = Proxy.create({
-    iterate: function () { throw "FAIL"; },
-    fix: function () { return {}; }
-});
-Object.preventExtensions(p);
-assertThrowsInstanceOf(function () { for (var v of p) {} }, TypeError);
deleted file mode 100644
--- a/js/src/jit-test/tests/jaeger/globalOptimize-3.js
+++ /dev/null
@@ -1,18 +0,0 @@
-
-y = 30;
-function bar() {
-  assertEq(y, 30);
-  Object.defineProperty(this, 'y', {writable:false});
-  y = 10;
-  assertEq(y, 30);
-}
-bar();
-
-x = 30;
-function foo() {
-  assertEq(x, 30);
-  Object.freeze(this);
-  x = 10;
-  assertEq(x, 30);
-}
-foo();
--- a/js/src/jsapi-tests/testOOM.cpp
+++ b/js/src/jsapi-tests/testOOM.cpp
@@ -1,16 +1,18 @@
 #include "tests.h"
 
+#include "mozilla/Util.h"
+
 BEGIN_TEST(testOOM)
 {
     JSString *jsstr = JS_ValueToString(cx, INT_TO_JSVAL(9));
     jsval tmp = STRING_TO_JSVAL(jsstr);
     JS_SetProperty(cx, global, "rootme", &tmp);
-    const jschar *s = JS_GetStringCharsZ(cx, jsstr);
+    mozilla::DebugOnly<const jschar *> s = JS_GetStringCharsZ(cx, jsstr);
     JS_ASSERT(s[0] == '9' && s[1] == '\0');
     return true;
 }
 
 virtual JSRuntime * createRuntime()
 {
     JSRuntime *rt = JS_NewRuntime(0);
     JS_SetGCParameter(rt, JSGC_MAX_BYTES, (uint32_t)-1);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5229,17 +5229,17 @@ JS_DecompileFunctionBody(JSContext *cx, 
 JS_NEVER_INLINE JS_PUBLIC_API(JSBool)
 JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *scriptArg, jsval *rval)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     if (cx->compartment != obj->compartment())
-        *(int *) 0 = 0xf0;
+        *(volatile int *) 0 = 0xf0;
     AutoLastFrameCheck lfc(cx);
 
     JS::Anchor<JSScript *> script;
 
     /*
      * Mozilla caches pre-compiled scripts (e.g., in the XUL prototype cache)
      * and runs them against multiple globals. With a compartment per global,
      * this requires cloning the pre-compiled script into each new global.
@@ -6614,17 +6614,17 @@ JS_IsIdentifier(JSContext *cx, JSString 
 JS_PUBLIC_API(JSBool)
 JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno)
 {
     if (script)
         *script = NULL;
     if (lineno)
         *lineno = 0;
 
-    FrameRegsIter i(cx);
+    ScriptFrameIter i(cx);
     if (i.done())
         return JS_FALSE;
 
     if (script)
         *script = i.script();
     if (lineno)
         *lineno = js::PCToLineNumber(i.script(), i.pc());
     return JS_TRUE;
@@ -6719,15 +6719,15 @@ JS_DecodeInterpretedFunction(JSContext *
     if (!decoder.codeFunction(&funobj))
         return NULL;
     return funobj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetScriptedGlobal(JSContext *cx)
 {
-    FrameRegsIter i(cx);
+    ScriptFrameIter i(cx);
     if (i.done())
         return JS_GetGlobalForScopeChain(cx);
 
     return JS_GetGlobalForFrame(Jsvalify(i.fp()));
 }
 
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1234,35 +1234,16 @@ static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32_t initLength = obj->getDenseArrayInitializedLength();
     MarkArraySlots(trc, initLength, obj->getDenseArrayElements(), "element");
 }
 
-static JSBool
-array_fix(JSContext *cx, JSObject *obj_, bool *success, AutoIdVector *props)
-{
-    RootedVarObject obj(cx, obj_);
-
-    JS_ASSERT(obj->isDenseArray());
-
-    /*
-     * We must slowify dense arrays; otherwise, we'd need to detect assignments to holes,
-     * since that is effectively adding a new property to the array.
-     */
-    if (!JSObject::makeDenseArraySlow(cx, obj) ||
-        !GetPropertyNames(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY, props))
-        return false;
-
-    *success = true;
-    return true;
-}
-
 Class js::ArrayClass = {
     "Array",
     Class::NON_NATIVE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array) | JSCLASS_FOR_OF_ITERATION,
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
@@ -1309,17 +1290,16 @@ Class js::ArrayClass = {
         array_setPropertyAttributes,
         array_setElementAttributes,
         array_setSpecialAttributes,
         array_deleteProperty,
         array_deleteElement,
         array_deleteSpecial,
         NULL,       /* enumerate      */
         array_typeOf,
-        array_fix,
         NULL,       /* thisObject     */
         NULL,       /* clear          */
     }
 };
 
 Class js::SlowArrayClass = {
     "Array",
     JSCLASS_HAS_CACHED_PROTO(JSProto_Array) | JSCLASS_FOR_OF_ITERATION,
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -230,26 +230,16 @@ typedef JSBool
 (* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
 typedef JSBool
 (* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
 typedef JSBool
 (* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
 typedef JSType
 (* TypeOfOp)(JSContext *cx, JSObject *obj);
 
-/*
- * Prepare to make |obj| non-extensible; in particular, fully resolve its properties.
- * On error, return false.
- * If |obj| is now ready to become non-extensible, set |*fixed| to true and return true.
- * If |obj| refuses to become non-extensible, set |*fixed| to false and return true; the
- * caller will throw an appropriate error.
- */
-typedef JSBool
-(* FixOp)(JSContext *cx, JSObject *obj, bool *fixed, AutoIdVector *props);
-
 typedef JSObject *
 (* ObjectOp)(JSContext *cx, JSObject *obj);
 typedef void
 (* FinalizeOp)(FreeOp *fop, JSObject *obj);
 typedef void
 (* ClearOp)(JSContext *cx, JSObject *obj);
 
 #define JS_CLASS_MEMBERS                                                      \
@@ -327,25 +317,24 @@ struct ObjectOps
     ElementAttributesOp setElementAttributes;
     SpecialAttributesOp setSpecialAttributes;
     DeletePropertyOp    deleteProperty;
     DeleteElementOp     deleteElement;
     DeleteSpecialOp     deleteSpecial;
 
     JSNewEnumerateOp    enumerate;
     TypeOfOp            typeOf;
-    FixOp               fix;
     ObjectOp            thisObject;
     ClearOp             clear;
 };
 
 #define JS_NULL_OBJECT_OPS                                                    \
     {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,   \
      NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,        \
-     NULL,NULL,NULL,NULL,NULL,NULL}
+     NULL,NULL,NULL,NULL,NULL}
 
 struct Class
 {
     JS_CLASS_MEMBERS;
     ClassExtension      ext;
     ObjectOps           ops;
     uint8_t             pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
                             sizeof(ClassExtension) - sizeof(ObjectOps)];
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -334,24 +334,23 @@ ReportError(JSContext *cx, const char *m
  */
 static void
 PopulateReportBlame(JSContext *cx, JSErrorReport *report)
 {
     /*
      * Walk stack until we find a frame that is associated with some script
      * rather than a native frame.
      */
-    for (FrameRegsIter iter(cx); !iter.done(); ++iter) {
-        if (iter.fp()->isScriptFrame()) {
-            report->filename = iter.fp()->script()->filename;
-            report->lineno = PCToLineNumber(iter.fp()->script(), iter.pc());
-            report->originPrincipals = iter.fp()->script()->originPrincipals;
-            break;
-        }
-    }
+    ScriptFrameIter iter(cx);
+    if (iter.done())
+        return;
+
+    report->filename = iter.script()->filename;
+    report->lineno = PCToLineNumber(iter.script(), iter.pc());
+    report->originPrincipals = iter.script()->originPrincipals;
 }
 
 /*
  * We don't post an exception in this case, since doing so runs into
  * complications of pre-allocating an exception object which required
  * running the Exception class initializer early etc.
  * Instead we just invoke the errorReporter with an "Out Of Memory"
  * type message, and then hope the process ends swiftly.
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -344,17 +344,16 @@ CallJSNativeConstructor(JSContext *cx, N
      * they allow content to return the callee.
      *
      * CallOrConstructBoundFunction is an exception as well because we
      * might have used bind on a proxy function.
      *
      * (new Object(Object)) returns the callee.
      */
     JS_ASSERT_IF(native != FunctionProxyClass.construct &&
-                 native != CallableObjectClass.construct &&
                  native != js::CallOrConstructBoundFunction &&
                  (!callee->isFunction() || callee->toFunction()->native() != js_Object),
                  !args.rval().isPrimitive() && callee != &args.rval().toObject());
 
     return true;
 }
 
 JS_ALWAYS_INLINE bool
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1710,20 +1710,16 @@ JSBool js_StopPerf()
 
         // Try to reap the process anyway.
         waitpid(perfPid, NULL, WNOHANG);
     }
     else {
         waitpid(perfPid, NULL, 0);
     }
 
-    /*
-     * If kill() failed, assume it failed because perf died early and continue
-     * on as though perf had been successfully killed.
-     */
     perfPid = 0;
     return true;
 }
 
 #endif /* __linux__ */
 
 JS_PUBLIC_API(void)
 JS_DumpBytecode(JSContext *cx, JSScript *script)
@@ -1796,17 +1792,17 @@ JS_PUBLIC_API(JSObject *)
 JS_UnwrapObject(JSObject *obj)
 {
     return UnwrapObject(obj);
 }
 
 JS_FRIEND_API(JSBool)
 js_CallContextDebugHandler(JSContext *cx)
 {
-    FrameRegsIter iter(cx);
+    ScriptFrameIter iter(cx);
     JS_ASSERT(!iter.done());
 
     jsval rval;
     switch (js::CallContextDebugHandler(cx, iter.script(), iter.pc(), &rval)) {
       case JSTRAP_ERROR:
         JS_ClearPendingException(cx);
         return JS_FALSE;
       case JSTRAP_THROW:
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -287,46 +287,41 @@ InitExnPrivate(JSContext *cx, HandleObje
     JS_ASSERT(exnObject->isError());
     JS_ASSERT(!exnObject->getPrivate());
 
     JSCheckAccessOp checkAccess = cx->runtime->securityCallbacks->checkObjectAccess;
 
     Vector<JSStackTraceStackElem> frames(cx);
     {
         SuppressErrorsGuard seg(cx);
-        for (FrameRegsIter i(cx); !i.done(); ++i) {
+        for (ScriptFrameIter i(cx); !i.done(); ++i) {
             StackFrame *fp = i.fp();
 
             /*
              * Ask the crystal CAPS ball whether we can see across compartments.
              * NB: this means 'fp' may point to cross-compartment frames.
              */
-            if (checkAccess && fp->isNonEvalFunctionFrame()) {
+            if (checkAccess && i.isNonEvalFunctionFrame()) {
                 Value v = NullValue();
                 jsid callerid = ATOM_TO_JSID(cx->runtime->atomState.callerAtom);
-                if (!checkAccess(cx, &fp->callee(), callerid, JSACC_READ, &v))
+                if (!checkAccess(cx, i.callee(), callerid, JSACC_READ, &v))
                     break;
             }
 
             if (!frames.growBy(1))
                 return false;
             JSStackTraceStackElem &frame = frames.back();
-            if (fp->isNonEvalFunctionFrame())
+            if (i.isNonEvalFunctionFrame())
                 frame.funName = fp->fun()->atom ? fp->fun()->atom : cx->runtime->emptyString;
             else
                 frame.funName = NULL;
-            if (fp->isScriptFrame()) {
-                frame.filename = SaveScriptFilename(cx, fp->script()->filename);
-                if (!frame.filename)
-                    return false;
-                frame.ulineno = PCToLineNumber(fp->script(), i.pc());
-            } else {
-                frame.ulineno = 0;
-                frame.filename = NULL;
-            }
+            frame.filename = SaveScriptFilename(cx, i.script()->filename);
+            if (!frame.filename)
+                return false;
+            frame.ulineno = PCToLineNumber(i.script(), i.pc());
         }
     }
 
     /* Do not need overflow check: the vm stack is already bigger. */
     JS_STATIC_ASSERT(sizeof(JSStackTraceElem) <= sizeof(StackFrame));
 
     size_t nbytes = offsetof(JSExnPrivate, stackElems) +
                     frames.length() * sizeof(JSStackTraceElem);
@@ -655,44 +650,42 @@ Exception(JSContext *cx, unsigned argc, 
         if (!message)
             return false;
         args[0].setString(message);
     } else {
         message = NULL;
     }
 
     /* Find the scripted caller. */
-    FrameRegsIter iter(cx);
-    while (!iter.done() && !iter.fp()->isScriptFrame())
-        ++iter;
+    ScriptFrameIter iter(cx);
 
     /* Set the 'fileName' property. */
     RootedVarString filename(cx);
     if (args.length() > 1) {
         filename = ToString(cx, args[1]);
         if (!filename)
             return false;
         args[1].setString(filename);
     } else {
         if (!iter.done()) {
-            filename = FilenameToString(cx, iter.fp()->script()->filename);
+            filename = FilenameToString(cx, iter.script()->filename);
             if (!filename)
                 return false;
         } else {
             filename = cx->runtime->emptyString;
         }
     }
 
     /* Set the 'lineNumber' property. */
     uint32_t lineno;
     if (args.length() > 2) {
         if (!ToUint32(cx, args[2], &lineno))
             return false;
     } else {
-        lineno = iter.done() ? 0 : PCToLineNumber(iter.fp()->script(), iter.pc());
+        lineno = iter.done() ? 0 : PCToLineNumber(iter.script(), iter.pc());
     }
 
     int exnType = args.callee().toFunction()->getExtendedSlot(0).toInt32();
     if (!InitExnPrivate(cx, obj, message, filename, lineno, NULL, exnType))
         return false;
 
     args.rval().setObject(*obj);
     return true;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -121,17 +121,17 @@ fun_getProperty(JSContext *cx, JSObject 
     /* Set to early to null in case of error */
     vp->setNull();
 
     /* Find fun's top-most activation record. */
     StackIter iter(cx);
     for (; !iter.done(); ++iter) {
         if (!iter.isFunctionFrame() || iter.isEvalFrame())
             continue;
-        if (iter.callee().toFunction() == fun)
+        if (iter.callee() == fun)
             break;
     }
     if (iter.done())
         return true;
 
     StackFrame *fp = iter.fp();
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.argumentsAtom)) {
@@ -1366,19 +1366,19 @@ js_ReportIsNotFunction(JSContext *cx, co
      *
      * Conversely, values may have been popped from the stack in preparation
      * for a call (e.g., by SplatApplyArgs). Since we must pass an offset from
      * the top of the simulated stack to js_ReportValueError3, we do bounds
      * checking using the minimum of both the simulated and actual stack depth.
      */
     ptrdiff_t spindex = 0;
 
-    FrameRegsIter i(cx);
+    ScriptFrameIter i(cx);
     if (!i.done()) {
-        unsigned depth = js_ReconstructStackDepth(cx, i.fp()->script(), i.pc());
+        unsigned depth = js_ReconstructStackDepth(cx, i.script(), i.pc());
         Value *simsp = i.fp()->base() + depth;
         if (i.fp()->base() <= vp && vp < Min(simsp, i.sp()))
             spindex = vp - simsp;
     }
 
     if (!spindex)
         spindex = ((flags & JSV2F_SEARCH_STACK) ? JSDVG_SEARCH_STACK : JSDVG_IGNORE_STACK);
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3040,57 +3040,58 @@ TypeObject::clearNewScript(JSContext *cx
     /*
      * If we cleared the new script while in the middle of initializing an
      * object, it will still have the new script's shape and reflect the no
      * longer correct state of the object once its initialization is completed.
      * We can't really detect the possibility of this statically, but the new
      * script keeps track of where each property is initialized so we can walk
      * the stack and fix up any such objects.
      */
-    for (FrameRegsIter iter(cx); !iter.done(); ++iter) {
-        StackFrame *fp = iter.fp();
-        if (fp->isScriptFrame() && fp->isConstructing() &&
-            fp->fun() == newScript->fun && fp->thisValue().isObject() &&
-            !fp->thisValue().toObject().hasLazyType() &&
-            fp->thisValue().toObject().type() == this) {
-            JSObject *obj = &fp->thisValue().toObject();
-            jsbytecode *pc = iter.pc();
+    Vector<uint32_t, 32> pcOffsets(cx);
+    for (ScriptFrameIter iter(cx); !iter.done(); ++iter) {
+        pcOffsets.append(uint32_t(iter.pc() - iter.script()->code));
+        if (iter.isConstructing() &&
+            iter.callee() == newScript->fun &&
+            iter.thisv().isObject() &&
+            !iter.thisv().toObject().hasLazyType() &&
+            iter.thisv().toObject().type() == this)
+        {
+            JSObject *obj = &iter.thisv().toObject();
 
             /* Whether all identified 'new' properties have been initialized. */
             bool finished = false;
 
             /* If not finished, number of properties that have been added. */
             uint32_t numProperties = 0;
 
             /*
              * If non-zero, we are scanning initializers in a call which has
              * already finished.
              */
             size_t depth = 0;
+            size_t callDepth = pcOffsets.length() - 1;
+            uint32_t offset = pcOffsets[callDepth];
 
             for (TypeNewScript::Initializer *init = newScript->initializerList;; init++) {
-                uint32_t offset = uint32_t(pc - fp->script()->code);
                 if (init->kind == TypeNewScript::Initializer::SETPROP) {
                     if (!depth && init->offset > offset) {
                         /* Advanced past all properties which have been initialized. */
                         break;
                     }
                     numProperties++;
                 } else if (init->kind == TypeNewScript::Initializer::FRAME_PUSH) {
                     if (depth) {
                         depth++;
                     } else if (init->offset > offset) {
                         /* Advanced past all properties which have been initialized. */
                         break;
                     } else if (init->offset == offset) {
-                        StackSegment &seg = cx->stack.space().containingSegment(fp);
-                        if (seg.maybefp() == fp)
+                        if (!callDepth)
                             break;
-                        fp = seg.computeNextFrame(fp);
-                        pc = fp->pcQuadratic(cx->stack);
+                        offset = pcOffsets[--callDepth];
                     } else {
                         /* This call has already finished. */
                         depth = 1;
                     }
                 } else if (init->kind == TypeNewScript::Initializer::FRAME_POP) {
                     if (depth) {
                         depth--;
                     } else {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2463,18 +2463,17 @@ obj_preventExtensions(JSContext *cx, uns
     JSObject *obj;
     if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.preventExtensions", &obj))
         return false;
 
     vp->setObject(*obj);
     if (!obj->isExtensible())
         return true;
 
-    AutoIdVector props(cx);
-    return obj->preventExtensions(cx, &props);
+    return obj->preventExtensions(cx);
 }
 
 /* static */ inline unsigned
 JSObject::getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it)
 {
     /* Make all attributes permanent; if freezing, make data attributes read-only. */
     if (it == FREEZE && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
         return JSPROP_PERMANENT | JSPROP_READONLY;
@@ -2484,24 +2483,22 @@ JSObject::getSealedOrFrozenAttributes(un
 bool
 JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
 {
     assertSameCompartment(cx, this);
     JS_ASSERT(it == SEAL || it == FREEZE);
 
     RootedVarObject self(cx, this);
 
+    if (isExtensible() && !preventExtensions(cx))
+        return false;
+
     AutoIdVector props(cx);
-    if (isExtensible()) {
-        if (!preventExtensions(cx, &props))
-            return false;
-    } else {
-        if (!GetPropertyNames(cx, this, JSITER_HIDDEN | JSITER_OWNONLY, &props))
-            return false;
-    }
+    if (!GetPropertyNames(cx, this, JSITER_HIDDEN | JSITER_OWNONLY, &props))
+        return false;
 
     /* preventExtensions must slowify dense arrays, so we can assign to holes without checks. */
     JS_ASSERT(!self->isDenseArray());
 
     if (self->isNative() && !self->inDictionaryMode()) {
         /*
          * Seal/freeze non-dictionary objects by constructing a new shape
          * hierarchy mirroring the original one, which can be shared if many
@@ -6201,17 +6198,17 @@ MaybeDumpValue(const char *name, const V
         fputc('\n', stderr);
     }
 }
 
 JS_FRIEND_API(void)
 js_DumpStackFrame(JSContext *cx, StackFrame *start)
 {
     /* This should only called during live debugging. */
-    FrameRegsIter i(cx, StackIter::GO_THROUGH_SAVED);
+    ScriptFrameIter i(cx, StackIter::GO_THROUGH_SAVED);
     if (!start) {
         if (i.done()) {
             fprintf(stderr, "no stack for cx = %p\n", (void*) cx);
             return;
         }
     } else {
         while (!i.done() && i.fp() != start)
             ++i;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -554,17 +554,17 @@ struct JSObject : public js::ObjectImpl
      */
     bool sealOrFreeze(JSContext *cx, ImmutabilityType it);
 
     bool isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp);
 
     static inline unsigned getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it);
 
   public:
-    bool preventExtensions(JSContext *cx, js::AutoIdVector *props);
+    bool preventExtensions(JSContext *cx);
 
     /* ES5 15.2.3.8: non-extensible, all props non-configurable */
     inline bool seal(JSContext *cx) { return sealOrFreeze(cx, SEAL); }
     /* ES5 15.2.3.9: non-extensible, all properties non-configurable, all data props read-only */
     bool freeze(JSContext *cx) { return sealOrFreeze(cx, FREEZE); }
 
     bool isSealed(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, SEAL, resultp); }
     bool isFrozen(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, FREEZE, resultp); }
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -42,17 +42,16 @@
 #define jsobjinlines_h___
 
 #include <new>
 
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsbool.h"
 #include "jscntxt.h"
-#include "jsdate.h"
 #include "jsfun.h"
 #include "jsgcmark.h"
 #include "jsiter.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsprobes.h"
 #include "jspropertytree.h"
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -2715,17 +2715,17 @@ Decompile(SprintStack *ss, jsbytecode *p
             /*
              * Rewrite non-get ops to their "get" format if the error is in
              * the bytecode at pc, or if at an inner opcode of a 'fat' outer
              * opcode at pc, so we don't decompile more than the error
              * expression.
              */
             uint32_t format = cs->format;
             bool matchPC = false;
-            FrameRegsIter iter(cx);
+            ScriptFrameIter iter(cx);
             if (!iter.done()) {
                 jsbytecode *npc = iter.pc();
                 if (pc == npc) {
                     matchPC = true;
                 } else if (format & JOF_DECOMPOSE) {
                     if (unsigned(npc - pc) < GetDecomposeLength(pc, js_CodeSpec[*pc].length))
                         matchPC = true;
                 }
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -77,30 +77,29 @@ GetConstruct(JSObject *proxy)
 static inline HeapSlot &
 GetFunctionProxyConstruct(JSObject *proxy)
 {
     JS_ASSERT(IsFunctionProxy(proxy));
     JS_ASSERT(proxy->slotSpan() > JSSLOT_PROXY_CONSTRUCT);
     return proxy->getSlotRef(JSSLOT_PROXY_CONSTRUCT);
 }
 
+#ifdef DEBUG
 static bool
 OperationInProgress(JSContext *cx, JSObject *proxy)
 {
     PendingProxyOperation *op = cx->runtime->pendingProxyOperation;
     while (op) {
         if (op->object == proxy)
             return true;
         op = op->next;
     }
     return false;
 }
-
-static bool
-FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp);
+#endif
 
 ProxyHandler::ProxyHandler(void *family) : mFamily(family)
 {
 }
 
 ProxyHandler::~ProxyHandler()
 {
 }
@@ -529,17 +528,16 @@ class ScriptedProxyHandler : public Prox
                                        PropertyDescriptor *desc);
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
                                           PropertyDescriptor *desc);
     virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
                                 PropertyDescriptor *desc);
     virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props);
     virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props);
-    virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp);
 
     /* ES5 Harmony derived proxy traps. */
     virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
     virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
                      Value *vp);
     virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);
@@ -643,24 +641,16 @@ ScriptedProxyHandler::enumerate(JSContex
     JSObject *handler = GetProxyHandlerObject(cx, proxy);
     AutoValueRooter tvr(cx);
     return GetFundamentalTrap(cx, handler, ATOM(enumerate), tvr.addr()) &&
            Trap(cx, handler, tvr.value(), 0, NULL, tvr.addr()) &&
            ArrayToIdVector(cx, tvr.value(), props);
 }
 
 bool
-ScriptedProxyHandler::fix(JSContext *cx, JSObject *proxy, Value *vp)
-{
-    JSObject *handler = GetProxyHandlerObject(cx, proxy);
-    return GetFundamentalTrap(cx, handler, ATOM(fix), vp) &&
-           Trap(cx, handler, *vp, 0, NULL, vp);
-}
-
-bool
 ScriptedProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
     JSObject *handler = GetProxyHandlerObject(cx, proxy);
     AutoValueRooter tvr(cx);
     if (!GetDerivedTrap(cx, handler, ATOM(has), tvr.addr()))
         return false;
     if (!js_IsCallable(tvr.value()))
         return ProxyHandler::has(cx, proxy, id, bp);
@@ -836,24 +826,16 @@ bool
 Proxy::enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props)
 {
     JS_CHECK_RECURSION(cx, return false);
     AutoPendingProxyOperation pending(cx, proxy);
     return GetProxyHandler(proxy)->enumerate(cx, proxy, props);
 }
 
 bool
-Proxy::fix(JSContext *cx, JSObject *proxy, Value *vp)
-{
-    JS_CHECK_RECURSION(cx, return false);
-    AutoPendingProxyOperation pending(cx, proxy);
-    return GetProxyHandler(proxy)->fix(cx, proxy, vp);
-}
-
-bool
 Proxy::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
     JS_CHECK_RECURSION(cx, return false);
     AutoPendingProxyOperation pending(cx, proxy);
     return GetProxyHandler(proxy)->has(cx, proxy, id, bp);
 }
 
 bool
@@ -1271,29 +1253,16 @@ proxy_TraceFunction(JSTracer *trc, JSObj
 
 static JSBool
 proxy_Convert(JSContext *cx, JSObject *proxy, JSType hint, Value *vp)
 {
     JS_ASSERT(proxy->isProxy());
     return Proxy::defaultValue(cx, proxy, hint, vp);
 }
 
-static JSBool
-proxy_Fix(JSContext *cx, JSObject *obj, bool *fixed, AutoIdVector *props)
-{
-    JS_ASSERT(obj->isProxy());
-    JSBool isFixed;
-    bool ok = FixProxy(cx, obj, &isFixed);
-    if (ok) {
-        *fixed = isFixed;
-        return GetPropertyNames(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, props);
-    }
-    return false;
-}
-
 static void
 proxy_Finalize(FreeOp *fop, JSObject *obj)
 {
     JS_ASSERT(obj->isProxy());
     if (!obj->getSlot(JSSLOT_PROXY_HANDLER).isUndefined())
         GetProxyHandler(obj)->finalize(fop, obj);
 }
 
@@ -1358,17 +1327,16 @@ JS_FRIEND_DATA(Class) js::ObjectProxyCla
         proxy_SetPropertyAttributes,
         proxy_SetElementAttributes,
         proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         proxy_TypeOf,
-        proxy_Fix,           /* fix             */
         NULL,                /* thisObject      */
         NULL,                /* clear           */
     }
 };
 
 JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = {
     "Proxy",
     Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4),
@@ -1417,17 +1385,16 @@ JS_FRIEND_DATA(Class) js::OuterWindowPro
         proxy_SetPropertyAttributes,
         proxy_SetElementAttributes,
         proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         NULL,                /* typeof          */
-        NULL,                /* fix             */
         NULL,                /* thisObject      */
         NULL,                /* clear           */
     }
 };
 
 static JSBool
 proxy_Call(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1488,17 +1455,16 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
         proxy_SetPropertyAttributes,
         proxy_SetElementAttributes,
         proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         proxy_TypeOf,
-        proxy_Fix,           /* fix             */
         NULL,                /* thisObject      */
         NULL,                /* clear           */
     }
 };
 
 JS_FRIEND_API(JSObject *)
 js::NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv, JSObject *proto,
                    JSObject *parent, JSObject *call, JSObject *construct)
@@ -1601,198 +1567,38 @@ proxy_createFunction(JSContext *cx, unsi
                                      proto, parent, call, construct);
     if (!proxy)
         return false;
 
     vp->setObject(*proxy);
     return true;
 }
 
-#ifdef DEBUG
-
-static JSBool
-proxy_isTrapping(JSContext *cx, unsigned argc, Value *vp)
-{
-    if (argc < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "isTrapping", "0", "s");
-        return false;
-    }
-    JSObject *obj = NonNullObject(cx, vp[2]);
-    if (!obj)
-        return false;
-    vp->setBoolean(obj->isProxy());
-    return true;
-}
-
-static JSBool
-proxy_fix(JSContext *cx, unsigned argc, Value *vp)
-{
-    if (argc < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
-                             "fix", "0", "s");
-        return false;
-    }
-    JSObject *obj = NonNullObject(cx, vp[2]);
-    if (!obj)
-        return false;
-    if (obj->isProxy()) {
-        JSBool flag;
-        if (!FixProxy(cx, obj, &flag))
-            return false;
-        vp->setBoolean(flag);
-    } else {
-        vp->setBoolean(true);
-    }
-    return true;
-}
-
-#endif
-
 static JSFunctionSpec static_methods[] = {
     JS_FN("create",         proxy_create,          2, 0),
     JS_FN("createFunction", proxy_createFunction,  3, 0),
-#ifdef DEBUG
-    JS_FN("isTrapping",     proxy_isTrapping,      1, 0),
-    JS_FN("fix",            proxy_fix,             1, 0),
-#endif
     JS_FS_END
 };
 
-static const uint32_t JSSLOT_CALLABLE_CALL = 0;
-static const uint32_t JSSLOT_CALLABLE_CONSTRUCT = 1;
-
-static JSBool
-callable_Call(JSContext *cx, unsigned argc, Value *vp)
-{
-    JSObject *callable = &JS_CALLEE(cx, vp).toObject();
-    JS_ASSERT(callable->getClass() == &CallableObjectClass);
-    const Value &fval = callable->getSlot(JSSLOT_CALLABLE_CALL);
-    const Value &thisval = vp[1];
-    bool ok = Invoke(cx, thisval, fval, argc, JS_ARGV(cx, vp), vp);
-    return ok;
-}
-
-JSBool
-callable_Construct(JSContext *cx, unsigned argc, Value *vp)
-{
-    JSObject *callable = &vp[0].toObject();
-    JS_ASSERT(callable->getClass() == &CallableObjectClass);
-    Value fval = callable->getSlot(JSSLOT_CALLABLE_CONSTRUCT);
-    if (fval.isUndefined()) {
-        /* We don't have an explicit constructor so allocate a new object and use the call. */
-        fval = callable->getSlot(JSSLOT_CALLABLE_CALL);
-        JS_ASSERT(fval.isObject());
-
-        /* callable is the constructor, so get callable.prototype is the proto of the new object. */
-        Value protov;
-        if (!callable->getProperty(cx, ATOM(classPrototype), &protov))
-            return false;
-
-        JSObject *proto;
-        if (protov.isObject()) {
-            proto = &protov.toObject();
-        } else {
-            proto = callable->global().getOrCreateObjectPrototype(cx);
-            if (!proto)
-                return false;
-        }
-
-        JSObject *newobj = NewObjectWithGivenProto(cx, &ObjectClass, proto, NULL);
-        if (!newobj)
-            return false;
-
-        /* If the call returns an object, return that, otherwise the original newobj. */
-        Value rval;
-        if (!Invoke(cx, ObjectValue(*newobj), callable->getSlot(JSSLOT_CALLABLE_CALL),
-                    argc, vp + 2, &rval)) {
-            return false;
-        }
-        if (rval.isPrimitive())
-            vp->setObject(*newobj);
-        else
-            *vp = rval;
-        return true;
-    }
-
-    bool ok = Invoke(cx, UndefinedValue(), fval, argc, vp + 2, vp);
-    return ok;
-}
-
 Class js::CallableObjectClass = {
     "Function",
     JSCLASS_HAS_RESERVED_SLOTS(2),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     NULL,                    /* finalize    */
     NULL,                    /* checkAccess */
-    callable_Call,
-    callable_Construct,
+    NULL,                    /* call        */
+    NULL                     /* construct   */
 };
 
-static bool
-FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
-{
-    if (OperationInProgress(cx, proxy)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROXY_FIX);
-        return false;
-    }
-
-    AutoValueRooter tvr(cx);
-    if (!Proxy::fix(cx, proxy, tvr.addr()))
-        return false;
-    if (tvr.value().isUndefined()) {
-        *bp = false;
-        return true;
-    }
-
-    JSObject *props = NonNullObject(cx, tvr.value());
-    if (!props)
-        return false;
-
-    JSObject *proto = proxy->getProto();
-    JSObject *parent = proxy->getParent();
-    Class *clasp = IsFunctionProxy(proxy) ? &CallableObjectClass : &ObjectClass;
-
-    /*
-     * Make a blank object from the recipe fix provided to us.  This must have
-     * number of fixed slots as the proxy so that we can swap their contents.
-     */
-    gc::AllocKind kind = proxy->getAllocKind();
-    RootedVarObject newborn(cx);
-    newborn = NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
-    if (!newborn)
-        return false;
-
-    if (clasp == &CallableObjectClass) {
-        newborn->setSlot(JSSLOT_CALLABLE_CALL, GetCall(proxy));
-        newborn->setSlot(JSSLOT_CALLABLE_CONSTRUCT, GetConstruct(proxy));
-    }
-
-    {
-        AutoPendingProxyOperation pending(cx, proxy);
-        if (!js_PopulateObject(cx, newborn, props))
-            return false;
-    }
-
-    /* Trade contents between the newborn object and the proxy. */
-    if (!proxy->swap(cx, newborn))
-        return false;
-
-    /* The GC will dispose of the proxy object. */
-
-    *bp = true;
-    return true;
-}
-
 Class js::ProxyClass = {
     "Proxy",
     JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
--- a/js/src/jsproxy.h
+++ b/js/src/jsproxy.h
@@ -59,17 +59,16 @@ class JS_FRIEND_API(ProxyHandler) {
                                        PropertyDescriptor *desc) = 0;
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
                                           PropertyDescriptor *desc) = 0;
     virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
                                 PropertyDescriptor *desc) = 0;
     virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
     virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0;
     virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
-    virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp) = 0;
 
     /* ES5 Harmony derived proxy traps. */
     virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
     virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
                      Value *vp);
     virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);
@@ -112,17 +111,16 @@ class Proxy {
                                          PropertyDescriptor *desc);
     static bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
                                          Value *vp);
     static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc);
     static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, const Value &v);
     static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props);
     static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props);
-    static bool fix(JSContext *cx, JSObject *proxy, Value *vp);
 
     /* ES5 Harmony derived proxy traps. */
     static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     static bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     static bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
     static bool getElementIfPresent(JSContext *cx, JSObject *proxy, JSObject *receiver,
                                     uint32_t index, Value *vp, bool *present);
     static bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -155,17 +155,17 @@ class InvokeFrameGuard;
 class InvokeArgsGuard;
 class StringBuffer;
 
 class FrameRegs;
 class StackFrame;
 class StackSegment;
 class StackSpace;
 class ContextStack;
-class FrameRegsIter;
+class ScriptFrameIter;
 class CallReceiver;
 class CallArgs;
 
 struct BytecodeEmitter;
 struct Definition;
 struct FunctionBox;
 struct ObjectBox;
 struct ParseNode;
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -1077,36 +1077,32 @@ Shape::setObjectParent(JSContext *cx, JS
 
     StackBaseShape base(last);
     base.parent = parent;
 
     return replaceLastProperty(cx, base, proto, last);
 }
 
 bool
-JSObject::preventExtensions(JSContext *cx, js::AutoIdVector *props)
+JSObject::preventExtensions(JSContext *cx)
 {
     JS_ASSERT(isExtensible());
 
     RootedVarObject self(cx, this);
 
-    if (props) {
-        if (js::FixOp fix = getOps()->fix) {
-            bool success;
-            if (!fix(cx, this, &success, props))
-                return false;
-            if (!success) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CHANGE_EXTENSIBILITY);
-                return false;
-            }
-        } else {
-            if (!js::GetPropertyNames(cx, this, JSITER_HIDDEN | JSITER_OWNONLY, props))
-                return false;
-        }
-    }
+    /*
+     * Force lazy properties to be resolved by iterating over the objects' own
+     * properties.
+     */
+    AutoIdVector props(cx);
+    if (!js::GetPropertyNames(cx, this, JSITER_HIDDEN | JSITER_OWNONLY, &props))
+        return false;
+
+    if (this->isDenseArray())
+        this->makeDenseArraySlow(cx, RootedVarObject(cx, this));
 
     return self->setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE);
 }
 
 bool
 JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateShape generateShape)
 {
     BaseShape::Flag flag = (BaseShape::Flag) flag_;
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1714,30 +1714,28 @@ CurrentLine(JSContext *cx)
 {
     return PCToLineNumber(cx->fp()->script(), cx->regs().pc);
 }
 
 void
 CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *linenop,
                                 JSPrincipals **origin)
 {
-    FrameRegsIter iter(cx);
-    while (!iter.done() && !iter.fp()->isScriptFrame())
-        ++iter;
+    ScriptFrameIter iter(cx);
 
     if (iter.done()) {
         *file = NULL;
         *linenop = 0;
         *origin = NULL;
         return;
     }
 
-    JSScript *script = iter.fp()->script();
+    JSScript *script = iter.script();
     *file = script->filename;
-    *linenop = PCToLineNumber(iter.fp()->script(), iter.pc());
+    *linenop = PCToLineNumber(iter.script(), iter.pc());
     *origin = script->originPrincipals;
 }
 
 }  /* namespace js */
 
 JSScript *
 js::CloneScript(JSContext *cx, JSScript *script)
 {
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -206,23 +206,16 @@ AbstractWrapper::delete_(JSContext *cx, 
 bool
 AbstractWrapper::enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
 {
     // if we refuse to perform this action, props remains empty
     static jsid id = JSID_VOID;
     GET(GetPropertyNames(cx, wrappedObject(wrapper), 0, &props));
 }
 
-bool
-AbstractWrapper::fix(JSContext *cx, JSObject *wrapper, Value *vp)
-{
-    vp->setUndefined();
-    return true;
-}
-
 static bool
 Cond(JSBool b, bool *bp)
 {
     *bp = !!b;
     return true;
 }
 
 bool
@@ -956,17 +949,16 @@ class JS_FRIEND_API(DeadObjectProxy) : p
                                        PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
                                           PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
                                 PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
     virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
-    virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
 
     /* Spidermonkey extensions. */
     virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp);
     virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval);
     virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, Native native, CallArgs args);
     virtual bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, bool *bp);
     virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx);
     virtual JSString *obj_toString(JSContext *cx, JSObject *proxy);
@@ -1031,23 +1023,16 @@ bool
 DeadObjectProxy::enumerate(JSContext *cx, JSObject *wrapper,
                            AutoIdVector &props)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEAD_OBJECT);
     return false;
 }
 
 bool
-DeadObjectProxy::fix(JSContext *cx, JSObject *wrapper, Value *vp)
-{
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEAD_OBJECT);
-    return false;
-}
-
-bool
 DeadObjectProxy::call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEAD_OBJECT);
     return false;
 }
 
 bool
 DeadObjectProxy::construct(JSContext *cx, JSObject *wrapper, unsigned argc,
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -69,17 +69,16 @@ class JS_FRIEND_API(AbstractWrapper) : p
                                        PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
                                           PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
                                 PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
     virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
     virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
-    virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
 
     /* Policy enforcement traps.
      *
      * enter() allows the policy to specify whether the caller may perform |act|
      * on the underlying object's |id| property. In the case when |act| is CALL,
      * |id| is generally JSID_VOID.
      *
      * leave() allows the policy to undo various scoped state changes taken in
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -1778,22 +1778,22 @@ ParseXMLSource(JSContext *cx, JSString *
     offset += srclen;
     dstlen = length - offset + 1;
     InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset, &dstlen);
     chars [offset + dstlen] = 0;
 
     xml = NULL;
     filename = NULL;
     lineno = 1;
-    FrameRegsIter i(cx);
+    ScriptFrameIter i(cx);
     if (!i.done()) {
         op = (JSOp) *i.pc();
         if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) {
-            filename = i.fp()->script()->filename;
-            lineno = PCToLineNumber(i.fp()->script(), i.pc());
+            filename = i.script()->filename;
+            lineno = PCToLineNumber(i.script(), i.pc());
             for (endp = srcp + srclen; srcp < endp; srcp++) {
                 if (*srcp == '\n')
                     --lineno;
             }
         }
     }
 
     {
@@ -5159,24 +5159,16 @@ xml_trace(JSTracer *trc, JSObject *obj)
      * to fix somehow for generational.
      */
     if (xml) {
         MarkXMLUnbarriered(trc, &xml, "private");
         JS_ASSERT(xml == obj->getPrivate());
     }
 }
 
-static JSBool
-xml_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props)
-{
-    JS_ASSERT(obj->isExtensible());
-    *success = false;
-    return true;
-}
-
 static void
 xml_clear(JSContext *cx, JSObject *obj)
 {
 }
 
 static JSBool
 HasSimpleContent(JSXML *xml)
 {
@@ -5407,17 +5399,16 @@ JS_FRIEND_DATA(Class) js::XMLClass = {
         xml_setPropertyAttributes,
         xml_setElementAttributes,
         xml_setSpecialAttributes,
         xml_deleteProperty,
         xml_deleteElement,
         xml_deleteSpecial,
         xml_enumerate,
         xml_typeOf,
-        xml_fix,
         NULL,       /* thisObject     */
         xml_clear
     }
 };
 
 static JSXML *
 StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
 {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1324,17 +1324,17 @@ GetScriptAndPCArgs(JSContext *cx, unsign
 }
 
 static JSTrapStatus
 TrapHandler(JSContext *cx, JSScript *, jsbytecode *pc, jsval *rval,
             jsval closure)
 {
     JSString *str = JSVAL_TO_STRING(closure);
 
-    FrameRegsIter iter(cx);
+    ScriptFrameIter iter(cx);
     JS_ASSERT(!iter.done());
 
     JSStackFrame *caller = Jsvalify(iter.fp());
     JSScript *script = iter.script();
 
     size_t length;
     const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length);
     if (!chars)
@@ -2134,17 +2134,17 @@ DumpStack(JSContext *cx, unsigned argc, 
     if (!evalStr)
         return false;
 
     JSString *globalStr = JS_NewStringCopyZ(cx, "global-code");
     if (!globalStr)
         return false;
 
     StackIter iter(cx);
-    JS_ASSERT(iter.isNativeCall() && iter.callee().toFunction()->native() == DumpStack);
+    JS_ASSERT(iter.isNativeCall() && iter.callee()->native() == DumpStack);
     ++iter;
 
     uint32_t index = 0;
     for (; !iter.done(); ++index, ++iter) {
         Value v;
         if (iter.isNonEvalFunctionFrame() || iter.isNativeCall()) {
             v = iter.calleev();
         } else if (iter.isEvalFrame()) {
@@ -2678,17 +2678,17 @@ EvalInFrame(JSContext *cx, unsigned argc
     JSString *str = JSVAL_TO_STRING(argv[1]);
 
     bool saveCurrent = (argc >= 3 && JSVAL_IS_BOOLEAN(argv[2]))
                         ? !!(JSVAL_TO_BOOLEAN(argv[2]))
                         : false;
 
     JS_ASSERT(cx->hasfp());
 
-    FrameRegsIter fi(cx);
+    ScriptFrameIter fi(cx);
     for (uint32_t i = 0; i < upCount; ++i, ++fi) {
         if (!fi.fp()->prev())
             break;
     }
 
     StackFrame *const fp = fi.fp();
     if (!fp->isScriptFrame()) {
         JS_ReportError(cx, "cannot eval in non-script frame");
--- a/js/src/tests/e4x/extensions/extensibility.js
+++ b/js/src/tests/e4x/extensions/extensibility.js
@@ -22,21 +22,21 @@ assertEq(Object.isExtensible(x), true);
 
 try
 {
   Object.preventExtensions(x);
   throw new Error("didn't throw");
 }
 catch (e)
 {
-  assertEq(e instanceof TypeError, true,
-           "xmlValue.[[Extensible]] cannot be changed");
+  // assertEq(e instanceof TypeError, true,
+  //          "xmlValue.[[Extensible]] cannot be changed");
 }
 
-assertEq(Object.isExtensible(x), true);
+// assertEq(Object.isExtensible(x), true);
 
 
 /******************************************************************************/
 
 if (typeof reportCompare === "function")
   reportCompare(true, true);
 
 print("All tests passed!");
--- a/js/src/tests/js1_5/Regress/regress-328897.js
+++ b/js/src/tests/js1_5/Regress/regress-328897.js
@@ -1,9 +1,8 @@
-// |reftest| fails-if(browserIsRemote)
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
@@ -47,29 +46,30 @@ printBugNumber(BUGNUMBER);
 printStatus (summary);
  
 if (typeof window == 'undefined')
 {
   reportCompare(expect, actual, summary);
 }
 else
 {
-  expect = /(Script error.|Permission denied for <file:\/\/> to get property XPCComponents.classes)/;
+  expect = /(Script error.|Permission denied to access property 'classes')/;
 
   window._onerror = window.onerror;
   window.onerror = (function (msg, page, line) { 
       actual = msg; 
       gDelayTestDriverEnd = false;
       jsTestDriverEnd();
       reportMatch(expect, actual, summary);
     });
 
   gDelayTestDriverEnd = true;
 
-  window.location="javascript:Components.classes";
+  // Trying to set Components.classes will trigger a Permission denied exception
+  window.location="javascript:Components.classes = 42";
   actual = 'No Error';
 }
 
 function onload() 
 {
   if (actual == 'No Error')
   {
     gDelayTestDriverEnd = false;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2104,19 +2104,19 @@ class Debugger::ScriptQuery {
                     return false;
             }
         }
 
         /*
          * Since eval scripts have no global, we need to find them via the call
          * stack, where frame's scope tells us the global in use.
          */
-        for (FrameRegsIter fri(cx); !fri.done(); ++fri) {
-            if (fri.fp()->isEvalFrame()) {
-                JSScript *script = fri.fp()->script();
+        for (ScriptFrameIter fri(cx); !fri.done(); ++fri) {
+            if (fri.isEvalFrame()) {
+                JSScript *script = fri.script();
 
                 /*
                  * If eval scripts never have global objects set, then we don't need
                  * to check the existing script vector for duplicates, since we only
                  * include scripts with globals above.
                  */
                 JS_ASSERT(!script->getGlobalObjectOrNull());
 
@@ -3939,18 +3939,17 @@ DebuggerObject_sealHelper(JSContext *cx,
     } else if (op == Freeze) {
         ok = obj->freeze(cx);
     } else {
         JS_ASSERT(op == PreventExtensions);
         if (!obj->isExtensible()) {
             args.rval().setUndefined();
             return true;
         }
-        AutoIdVector props(cx);
-        ok = obj->preventExtensions(cx, &props);
+        ok = obj->preventExtensions(cx);
     }
     if (!ok)
         return false;
     args.rval().setUndefined();
     return true;
 }
 
 static JSBool
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -36,16 +36,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "GlobalObject.h"
 
 #include "jscntxt.h"
+#include "jsdate.h"
 #include "jsexn.h"
 #include "jsmath.h"
 #include "json.h"
 #include "jsweakmap.h"
 
 #include "builtin/MapObject.h"
 #include "builtin/RegExp.h"
 #include "frontend/BytecodeEmitter.h"
@@ -235,18 +236,17 @@ GlobalObject::initFunctionAndObjectClass
         return NULL;
     self->setOriginalEval(evalobj);
 
     /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
     RootedVarFunction throwTypeError(cx);
     throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL);
     if (!throwTypeError)
         return NULL;
-    AutoIdVector ids(cx);
-    if (!throwTypeError->preventExtensions(cx, &ids))
+    if (!throwTypeError->preventExtensions(cx))
         return NULL;
     self->setThrowTypeError(throwTypeError);
 
     /*
      * The global object should have |Object.prototype| as its [[Prototype]].
      * Eventually we'd like to have standard classes be there from the start,
      * and thus we would know we were always setting what had previously been a
      * null [[Prototype]], but right now some code assumes it can set the
--- a/js/src/vm/NumericConversions.h
+++ b/js/src/vm/NumericConversions.h
@@ -221,18 +221,18 @@ ToInt32(double d)
 "   eor     %Q4, %Q4, %R4, ASR #31\n"
 "   add     %0, %Q4, %R4, LSR #31\n"
 "   b       9f\n"
 "8:\n"
     // +/-INFINITY, +/-0, subnormals, NaNs, and anything else out-of-range that
     // will result in a conversion of '0'.
 "   mov     %0, #0\n"
 "9:\n"
-    : "=r" (i), "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
-    : "r" (d)
+    : "=r" (i), "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2), "=&r" (d)
+    : "4" (d)
     : "cc"
         );
     return i;
 #else
     int32_t i;
     double two32, two31;
 
     if (!MOZ_DOUBLE_IS_FINITE(d))
--- a/js/src/vm/ObjectImpl.cpp
+++ b/js/src/vm/ObjectImpl.cpp
@@ -316,28 +316,42 @@ SparseElementsHeader::getOwnElement(JSCo
 {
     MOZ_ASSERT(this == &obj->elementsHeader());
 
     MOZ_NOT_REACHED("NYI");
     return false;
 }
 
 template<typename T>
+static Value
+ElementToValue(const T t)
+{
+    return NumberValue(t);
+}
+
+template<>
+/* static */ Value
+ElementToValue(const uint8_clamped u)
+{
+    return NumberValue(uint8_t(u));
+}
+
+template<typename T>
 bool
 TypedElementsHeader<T>::getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index,
                                       PropDesc *desc)
 {
     MOZ_ASSERT(this == &obj->elementsHeader());
 
     if (index >= length()) {
         *desc = PropDesc::undefined();
         return true;
     }
 
-    *desc = PropDesc(NumberValue(getElement(index)), PropDesc::Writable,
+    *desc = PropDesc(ElementToValue(getElement(index)), PropDesc::Writable,
                      PropDesc::Enumerable, PropDesc::Configurable);
     return false;
 }
 
 bool
 ArrayBufferElementsHeader::getOwnElement(JSContext *cx, ObjectImpl *obj, uint32_t index,
                                          PropDesc *desc)
 {
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -683,17 +683,16 @@ Class js::WithClass = {
         with_SetPropertyAttributes,
         with_SetElementAttributes,
         with_SetSpecialAttributes,
         with_DeleteProperty,
         with_DeleteElement,
         with_DeleteSpecial,
         with_Enumerate,
         with_TypeOf,
-        NULL,             /* fix   */
         with_ThisObject,
         NULL,             /* clear */
     }
 };
 
 ClonedBlockObject *
 ClonedBlockObject::create(JSContext *cx, StaticBlockObject &block, StackFrame *fp)
 {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1286,31 +1286,46 @@ StackIter::isNonEvalFunctionFrame() cons
       case NATIVE:
       case IMPLICIT_NATIVE:
         return !isEvalFrame() && isFunctionFrame();
     }
     JS_NOT_REACHED("Unexpected state");
     return false;
 }
 
-JSObject &
+bool
+StackIter::isConstructing() const
+{
+    switch (state_) {
+      case DONE:
+        JS_NOT_REACHED("Unexpected state");
+        return false;
+      case SCRIPTED:
+      case NATIVE:
+      case IMPLICIT_NATIVE:
+        return fp()->isConstructing();
+    }
+    return false;
+}
+
+JSFunction *
 StackIter::callee() const
 {
     switch (state_) {
       case DONE:
         break;
       case SCRIPTED:
         JS_ASSERT(isFunctionFrame());
-        return fp()->callee();
+        return fp()->callee().toFunction();
       case NATIVE:
       case IMPLICIT_NATIVE:
-        return nativeArgs().callee();
+        return nativeArgs().callee().toFunction();
     }
     JS_NOT_REACHED("Unexpected state");
-    return *(JSObject *) NULL;
+    return NULL;
 }
 
 Value
 StackIter::calleev() const
 {
     switch (state_) {
       case DONE:
         break;
@@ -1320,16 +1335,32 @@ StackIter::calleev() const
       case NATIVE:
       case IMPLICIT_NATIVE:
         return nativeArgs().calleev();
     }
     JS_NOT_REACHED("Unexpected state");
     return Value();
 }
 
+Value
+StackIter::thisv() const
+{
+    switch (state_) {
+      case DONE:
+        MOZ_NOT_REACHED("Unexpected state");
+        return Value();
+      case SCRIPTED:
+      case NATIVE:
+      case IMPLICIT_NATIVE:
+        return fp()->thisValue();
+    }
+    MOZ_NOT_REACHED("unexpected state");
+    return Value();
+}
+
 /*****************************************************************************/
 
 AllFramesIter::AllFramesIter(StackSpace &space)
   : seg_(space.seg_),
     fp_(seg_ ? seg_->maybefp() : NULL)
 {
     settle();
 }
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -66,17 +66,17 @@ class ContextStack;
 class InvokeArgsGuard;
 class InvokeFrameGuard;
 class FrameGuard;
 class ExecuteFrameGuard;
 class DummyFrameGuard;
 class GeneratorFrameGuard;
 
 class CallIter;
-class FrameRegsIter;
+class ScriptFrameIter;
 class AllFramesIter;
 
 class ArgumentsObject;
 class StaticBlockObject;
 
 #ifdef JS_METHODJIT
 namespace mjit {
     struct JITScript;
@@ -577,17 +577,17 @@ class StackFrame
      * returned through pinlined.
      *
      * Beware, as the name implies, pcQuadratic can lead to quadratic behavior
      * in loops such as:
      *
      *   for ( ...; fp; fp = fp->prev())
      *     ... fp->pcQuadratic(cx->stack);
      *
-     * Using next can avoid this, but in most cases prefer FrameRegsIter;
+     * Using next can avoid this, but in most cases prefer ScriptFrameIter;
      * it is amortized O(1).
      *
      *   When I get to the bottom I go back to the top of the stack
      *   Where I stop and I turn and I go right back
      *   Till I get to the bottom and I see you again...
      */
     jsbytecode *pcQuadratic(const ContextStack &stack, StackFrame *next = NULL,
                             JSInlinedSite **pinlined = NULL);
@@ -1846,51 +1846,42 @@ class StackIter
     bool isNativeCall() const {
         JS_ASSERT(!done());
         return state_ == NATIVE || state_ == IMPLICIT_NATIVE;
     }
 
     bool isFunctionFrame() const;
     bool isEvalFrame() const;
     bool isNonEvalFunctionFrame() const;
+    bool isConstructing() const;
 
     StackFrame *fp() const { JS_ASSERT(isScript()); return fp_; }
     Value      *sp() const { JS_ASSERT(isScript()); return sp_; }
     jsbytecode *pc() const { JS_ASSERT(isScript()); return pc_; }
     JSScript   *script() const { JS_ASSERT(isScript()); return script_; }
-    JSObject   &callee() const;
+    JSFunction *callee() const;
     Value       calleev() const;
+    Value       thisv() const;
 
     CallArgs nativeArgs() const { JS_ASSERT(isNativeCall()); return args_; }
 };
 
 /* A filtering of the StackIter to only stop at scripts. */
-class FrameRegsIter
+class ScriptFrameIter : public StackIter
 {
-    StackIter iter_;
-
     void settle() {
-        while (!iter_.done() && !iter_.isScript())
-            ++iter_;
+        while (!done() && !isScript())
+            StackIter::operator++();
     }
 
   public:
-    FrameRegsIter(JSContext *cx, StackIter::SavedOption opt = StackIter::STOP_AT_SAVED)
-        : iter_(cx, opt) { settle(); }
-
-    bool done() const { return iter_.done(); }
-    FrameRegsIter &operator++() { ++iter_; settle(); return *this; }
+    ScriptFrameIter(JSContext *cx, StackIter::SavedOption opt = StackIter::STOP_AT_SAVED)
+        : StackIter(cx, opt) { settle(); }
 
-    bool operator==(const FrameRegsIter &rhs) const { return iter_ == rhs.iter_; }
-    bool operator!=(const FrameRegsIter &rhs) const { return iter_ != rhs.iter_; }
-
-    StackFrame *fp() const { return iter_.fp(); }
-    Value      *sp() const { return iter_.sp(); }
-    jsbytecode *pc() const { return iter_.pc(); }
-    JSScript   *script() const { return iter_.script(); }
+    ScriptFrameIter &operator++() { StackIter::operator++(); settle(); return *this; }
 };
 
 /*****************************************************************************/
 
 /*
  * Blindly iterate over all frames in the current thread's stack. These frames
  * can be from different contexts and compartments, so beware.
  */
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/crashtests/723465.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+
+<script>
+
+function boom()
+{
+  var f = document.getElementById("f");
+  var fd = f.contentDocument;
+  fd.querySelectorAll("*");
+  fd.documentElement.innerHTML = "3";
+  document.body.removeChild(f);
+}
+
+</script>
+</head>
+
+<body onload="boom();"><iframe id="f" src="data:text/html,<html><head onfocus=2>"></iframe></body>
+</html>
--- a/js/xpconnect/crashtests/crashtests.list
+++ b/js/xpconnect/crashtests/crashtests.list
@@ -30,8 +30,9 @@ load 582649.html
 load 601284-1.html
 load 603146-1.html
 load 603858-1.html
 load 608963.html
 load 616930-1.html
 load 639737-1.html
 load 648206-1.html
 load 705875.html
+load 723465.html
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -55,16 +55,17 @@
 #include "WrapperFactory.h"
 #include "XrayWrapper.h"
 #include "nsNullPrincipal.h"
 #include "nsJSUtils.h"
 #include "mozJSComponentLoader.h"
 #include "nsContentUtils.h"
 #include "jsgc.h"
 #include "jsfriendapi.h"
+#include "AccessCheck.h"
 #include "mozilla/dom/bindings/Utils.h"
 
 using namespace mozilla;
 using namespace js;
 
 using mozilla::dom::bindings::DestroyProtoOrIfaceCache;
 
 /***************************************************************************/
@@ -4188,17 +4189,18 @@ oom:
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
 /* nsISupports getHelperForLanguage (in PRUint32 language); */
 NS_IMETHODIMP
 nsXPCComponents::GetHelperForLanguage(PRUint32 language,
                                       nsISupports **retval)
 {
-    *retval = nsnull;
+    *retval = static_cast<nsIXPCComponents*>(this);
+    NS_ADDREF(this);
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents::GetContractID(char * *aContractID)
 {
     *aContractID = nsnull;
@@ -4240,27 +4242,29 @@ nsXPCComponents::GetFlags(PRUint32 *aFla
 
 /* [notxpcom] readonly attribute nsCID classIDNoAlloc; */
 NS_IMETHODIMP
 nsXPCComponents::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
 {
     return NS_ERROR_NOT_AVAILABLE;
 }
 
-nsXPCComponents::nsXPCComponents()
-    :   mInterfaces(nsnull),
+nsXPCComponents::nsXPCComponents(XPCWrappedNativeScope* aScope)
+    :   mScope(aScope),
+        mInterfaces(nsnull),
         mInterfacesByID(nsnull),
         mClasses(nsnull),
         mClassesByID(nsnull),
         mResults(nsnull),
         mID(nsnull),
         mException(nsnull),
         mConstructor(nsnull),
         mUtils(nsnull)
 {
+    MOZ_ASSERT(aScope, "aScope must not be null");
 }
 
 nsXPCComponents::~nsXPCComponents()
 {
     ClearMembers();
 }
 
 void
@@ -4334,16 +4338,17 @@ nsXPCComponents::GetManager(nsIComponent
 /**********************************************/
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_GETPROPERTY
 #define                             XPC_MAP_WANT_SETPROPERTY
+#define                             XPC_MAP_WANT_PRECREATE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
 #include "xpc_map_end.h" /* This will #undef the above */
 
 /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in PRUint32 flags, out JSObjectPtr objp); */
 NS_IMETHODIMP
 nsXPCComponents::NewResolve(nsIXPConnectWrappedNative *wrapper,
                             JSContext * cx, JSObject * obj,
                             jsid id, PRUint32 flags,
@@ -4422,50 +4427,53 @@ nsXPCComponents::SetProperty(nsIXPConnec
         return NS_ERROR_FAILURE;
     }
 
     return NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN;
 }
 
 // static
 JSBool
-nsXPCComponents::AttachNewComponentsObject(XPCCallContext& ccx,
-                                           XPCWrappedNativeScope* aScope,
-                                           JSObject* aGlobal)
+nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx,
+                                        XPCWrappedNativeScope* aScope,
+                                        JSObject* aGlobal)
 {
     if (!aGlobal)
         return false;
 
-    nsXPCComponents* components = new nsXPCComponents();
-    if (!components)
-        return false;
+    nsXPCComponents* components = aScope->GetComponents();
+    if (!components) {
+        components = new nsXPCComponents(aScope);
+        if (!components)
+            return false;
+        aScope->SetComponents(components);
+    }
 
     nsCOMPtr<nsIXPCComponents> cholder(components);
 
     AutoMarkingNativeInterfacePtr iface(ccx);
     iface = XPCNativeInterface::GetNewOrUsed(ccx, &NS_GET_IID(nsIXPCComponents));
 
     if (!iface)
         return false;
 
     nsCOMPtr<XPCWrappedNative> wrapper;
     xpcObjectHelper helper(cholder);
     XPCWrappedNative::GetNewOrUsed(ccx, helper, aScope, iface, getter_AddRefs(wrapper));
     if (!wrapper)
         return false;
 
-    aScope->SetComponents(components);
-
     jsid id = ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_COMPONENTS);
-    JSObject* obj;
-
-    return NS_SUCCEEDED(wrapper->GetJSObject(&obj)) &&
-           obj && JS_DefinePropertyById(ccx, aGlobal, id, OBJECT_TO_JSVAL(obj),
-                                        nsnull, nsnull,
-                                        JSPROP_PERMANENT | JSPROP_READONLY);
+    JSObject* obj = wrapper->GetSameCompartmentSecurityWrapper(ccx);
+    if (!wrapper)
+        return false;
+   
+    return JS_DefinePropertyById(ccx, aGlobal, id, OBJECT_TO_JSVAL(obj),
+                                 nsnull, nsnull,
+                                 JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
 /* void lookupMethod (); */
 NS_IMETHODIMP
 nsXPCComponents::LookupMethod(const JS::Value& object,
                               const JS::Value& name,
                               JSContext *cx,
                               JS::Value *retval)
@@ -4523,8 +4531,20 @@ nsXPCComponents::CanGetProperty(const ns
 /* string canSetProperty (in nsIIDPtr iid, in wstring propertyName); */
 NS_IMETHODIMP
 nsXPCComponents::CanSetProperty(const nsIID * iid, const PRUnichar *propertyName, char **_retval)
 {
     // If you have to ask, then the answer is NO
     *_retval = nsnull;
     return NS_OK;
 }
+
+NS_IMETHODIMP
+nsXPCComponents::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj)
+{
+  // this should never happen
+  if (!mScope) {
+      NS_WARNING("mScope must not be null when nsXPCComponents::PreCreate is called");
+      return NS_ERROR_FAILURE;
+  }
+  *parentObj = mScope->GetGlobalJSObject();
+  return NS_OK;
+}
\ No newline at end of file
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -1678,16 +1678,18 @@ XPCWrappedNative::ReparentWrapperIfFound
                     if (!innerAC.enter(ccx, aOldScope->GetGlobalJSObject()) ||
                         !wrapper->GetSameCompartmentSecurityWrapper(ccx))
                         return NS_ERROR_FAILURE;
                 }
 
                 JSObject *ww = wrapper->GetWrapper();
                 if (ww) {
                     JSObject *newwrapper;
+                    MOZ_ASSERT(!xpc::WrapperFactory::IsComponentsObject(flat), 
+                               "Components object should never get here");
                     if (xpc::WrapperFactory::IsLocationObject(flat)) {
                         newwrapper = xpc::WrapperFactory::WrapLocationObject(ccx, newobj);
                         if (!newwrapper)
                             return NS_ERROR_FAILURE;
                     } else {
                         NS_ASSERTION(wrapper->NeedsSOW(), "weird wrapper wrapper");
                         newwrapper = xpc::WrapperFactory::WrapSOWObject(ccx, newobj);
                         if (!newwrapper)
@@ -2235,16 +2237,20 @@ XPCWrappedNative::GetSameCompartmentSecu
     if (xpc::WrapperFactory::IsLocationObject(flat)) {
         wrapper = xpc::WrapperFactory::WrapLocationObject(cx, flat);
         if (!wrapper)
             return NULL;
     } else if (NeedsSOW()) {
         wrapper = xpc::WrapperFactory::WrapSOWObject(cx, flat);
         if (!wrapper)
             return NULL;
+    } else if (xpc::WrapperFactory::IsComponentsObject(flat)) {
+        wrapper = xpc::WrapperFactory::WrapComponentsObject(cx, flat);
+        if (!wrapper)
+            return NULL;
     }
 
     // If we made a wrapper, cache it and return it.
     if (wrapper) {
         SetWrapper(wrapper);
         return wrapper;
     }
 
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -880,17 +880,16 @@ XPCWrappedNativeJSClass XPC_WN_NoHelper_
         nsnull, // setAttributes
         nsnull, // setElementAttributes
         nsnull, // setSpecialAttributes
         nsnull, // deleteProperty
         nsnull, // deleteElement
         nsnull, // deleteSpecial
         XPC_WN_JSOp_Enumerate,
         XPC_WN_JSOp_TypeOf_Object,
-        nsnull, // fix
         XPC_WN_JSOp_ThisObject,
         XPC_WN_JSOp_Clear
     }
   },
   0 // interfacesBitmap
 };
 
 
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -185,21 +185,25 @@ XPCWrappedNativeScope::IsDyingScope(XPCW
             return true;
     }
     return false;
 }
 
 void
 XPCWrappedNativeScope::SetComponents(nsXPCComponents* aComponents)
 {
-    NS_IF_ADDREF(aComponents);
-    NS_IF_RELEASE(mComponents);
     mComponents = aComponents;
 }
 
+nsXPCComponents*
+XPCWrappedNativeScope::GetComponents()
+{
+    return mComponents;
+}
+
 // Dummy JS class to let wrappers w/o an xpc prototype share
 // scopes. By doing this we avoid allocating a new scope for every
 // wrapper on creation of the wrapper, and most wrappers won't need
 // their own scope at all for the lifetime of the wrapper.
 // WRAPPER_SLOTS is key here (even though there's never anything
 // in the private data slot in these prototypes), as the number of
 // reserved slots in this class needs to match that of the wrappers
 // for the JS engine to share scopes.
@@ -303,19 +307,24 @@ XPCWrappedNativeScope::~XPCWrappedNative
     if (mMainThreadWrappedNativeProtoMap) {
         NS_ASSERTION(0 == mMainThreadWrappedNativeProtoMap->Count(), "scope has non-empty map");
         delete mMainThreadWrappedNativeProtoMap;
     }
 
     if (mContext)
         mContext->RemoveScope(this);
 
+    // This should not be necessary, since the Components object should die
+    // with the scope but just in case.
+    if (mComponents)
+        mComponents->mScope = nsnull;
+
     // XXX we should assert that we are dead or that xpconnect has shutdown
     // XXX might not want to do this at xpconnect shutdown time???
-    NS_IF_RELEASE(mComponents);
+    mComponents = nsnull;
 
     JSRuntime *rt = mRuntime->GetJSRuntime();
     mGlobalJSObject.finalize(rt);
     mPrototypeJSObject.finalize(rt);
 }
 
 JSObject *
 XPCWrappedNativeScope::GetPrototypeNoHelper(XPCCallContext& ccx)
@@ -901,17 +910,17 @@ void
 XPCWrappedNativeScope::DebugDump(PRInt16 depth)
 {
 #ifdef DEBUG
     depth-- ;
     XPC_LOG_ALWAYS(("XPCWrappedNativeScope @ %x", this));
     XPC_LOG_INDENT();
         XPC_LOG_ALWAYS(("mRuntime @ %x", mRuntime));
         XPC_LOG_ALWAYS(("mNext @ %x", mNext));
-        XPC_LOG_ALWAYS(("mComponents @ %x", mComponents));
+        XPC_LOG_ALWAYS(("mComponents @ %x", mComponents.get()));
         XPC_LOG_ALWAYS(("mGlobalJSObject @ %x", mGlobalJSObject.get()));
         XPC_LOG_ALWAYS(("mPrototypeJSObject @ %x", mPrototypeJSObject.get()));
         XPC_LOG_ALWAYS(("mPrototypeNoHelper @ %x", mPrototypeNoHelper));
 
         XPC_LOG_ALWAYS(("mWrappedNativeMap @ %x with %d wrappers(s)",         \
                         mWrappedNativeMap,                                    \
                         mWrappedNativeMap ? mWrappedNativeMap->Count() : 0));
         // iterate contexts...
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -463,16 +463,21 @@ members = [
     'nsIIDBRequest.*',
     'nsIIDBTransaction.*',
     'nsIIDBFactory.*',
     'nsIIDBOpenDBRequest.*',
     'nsIIDBVersionChangeEvent.*',
     'nsIIndexedDatabaseUsageCallback.*',
     'nsIIndexedDatabaseManager.*',
 
+    # Performance
+    'nsIDOMPerformance.*',
+    'nsIDOMPerformanceTiming.*',
+    'nsIDOMPerformanceNavigation.*',
+
     'nsIDOMDOMError.*',
     ]
 
 # Most interfaces can be found by searching the includePath; to find
 # nsIDOMEvent, for example, just look for nsIDOMEvent.idl.  But IDL filenames
 # for very long interface names are slightly abbreviated, and many interfaces
 # don't have their own files, just for extra wackiness.  So qsgen.py needs
 # a little help.
--- a/js/xpconnect/src/dombindings.cpp
+++ b/js/xpconnect/src/dombindings.cpp
@@ -203,17 +203,17 @@ size_t ListBase<LC>::sProtoMethodsCount 
 
 template<class LC>
 ListBase<LC> ListBase<LC>::instance;
 
 bool
 DefineConstructor(JSContext *cx, JSObject *obj, DefineInterface aDefine, nsresult *aResult)
 {
     bool enabled;
-    bool defined = aDefine(cx, XPCWrappedNativeScope::FindInJSObjectScope(cx, obj), &enabled);
+    bool defined = aDefine(cx, obj, &enabled);
     NS_ASSERTION(!defined || enabled,
                  "We defined a constructor but the new bindings are disabled?");
     *aResult = defined ? NS_OK : NS_ERROR_FAILURE;
     return enabled;
 }
 
 template<class LC>
 typename ListBase<LC>::ListType*
@@ -409,32 +409,47 @@ InvalidateProtoShape_add(JSContext *cx, 
 static JSBool
 InvalidateProtoShape_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
 {
     return InvalidateProtoShape_add(cx, obj, id, vp);
 }
 
 template<class LC>
 JSObject *
-ListBase<LC>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope)
+ListBase<LC>::getPrototype(JSContext *cx, JSObject *receiver, bool *enabled)
+{
+    *enabled = true;
+
+    XPCWrappedNativeScope *scope =
+        XPCWrappedNativeScope::FindInJSObjectScope(cx, receiver);
+    if (!scope)
+        return false;
+
+    return getPrototype(cx, scope, receiver);
+}
+
+template<class LC>
+JSObject *
+ListBase<LC>::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope,
+                           JSObject *receiver)
 {
     nsDataHashtable<nsDepCharHashKey, JSObject*> &cache =
         scope->GetCachedDOMPrototypes();
 
     JSObject *interfacePrototype;
     if (cache.IsInitialized()) {
         if (cache.Get(sInterfaceClass.name, &interfacePrototype)) {
             xpc_UnmarkGrayObject(interfacePrototype);
             return interfacePrototype;
         }
     } else if (!cache.Init()) {
         return NULL;
     }
 
-    JSObject* proto = Base::getPrototype(cx, scope);
+    JSObject* proto = Base::getPrototype(cx, scope, receiver);
     if (!proto)
         return NULL;
 
     JSObject *global = scope->GetGlobalJSObject();
     interfacePrototype = JS_NewObject(cx, Jsvalify(&sInterfacePrototypeClass), proto, global);
     if (!interfacePrototype)
         return NULL;
 
@@ -463,17 +478,17 @@ ListBase<LC>::getPrototype(JSContext *cx
 
     JSObject *interface = JS_NewObject(cx, Jsvalify(&sInterfaceClass), NULL, global);
     if (!interface)
         return NULL;
 
     if (!JS_LinkConstructorAndPrototype(cx, interface, interfacePrototype))
         return NULL;
 
-    if (!JS_DefineProperty(cx, global, sInterfaceClass.name, OBJECT_TO_JSVAL(interface), NULL,
+    if (!JS_DefineProperty(cx, receiver, sInterfaceClass.name, OBJECT_TO_JSVAL(interface), NULL,
                            NULL, 0))
         return NULL;
 
     // This needs to happen after we've set all our own properties on interfacePrototype, to
     // overwrite the value set by InvalidateProtoShape_add when we set our own properties.
     js::SetReservedSlot(interfacePrototype, 0, PrivateUint32Value(USE_CACHE));
 
     if (!cache.Put(sInterfaceClass.name, interfacePrototype))
@@ -488,25 +503,25 @@ ListBase<LC>::create(JSContext *cx, JSOb
                      nsWrapperCache* aWrapperCache, bool *triedToWrap)
 {
     *triedToWrap = true;
 
     JSObject *parent = WrapNativeParent(cx, scope, aList->GetParentObject());
     if (!parent)
         return NULL;
 
+    JSObject *global = js::GetGlobalForObjectCrossCompartment(parent);
+
     JSAutoEnterCompartment ac;
-    if (js::GetGlobalForObjectCrossCompartment(parent) != scope) {
-        if (!ac.enter(cx, parent))
+    if (global != scope) {
+        if (!ac.enter(cx, global))
             return NULL;
     }
 
-    XPCWrappedNativeScope *xpcscope =
-        XPCWrappedNativeScope::FindInJSObjectScope(cx, parent);
-    JSObject *proto = getPrototype(cx, xpcscope, triedToWrap);
+    JSObject *proto = getPrototype(cx, global, triedToWrap);
     if (!proto && !*triedToWrap)
         aWrapperCache->ClearIsDOMBinding();
     if (!proto)
         return NULL;
     JSObject *obj = NewProxyObject(cx, &ListBase<LC>::instance,
                                    PrivateValue(aList), proto, parent);
     if (!obj)
         return NULL;
@@ -788,24 +803,16 @@ ListBase<LC>::enumerate(JSContext *cx, J
 {
     JSObject *proto = JS_GetPrototype(proxy);
     return getOwnPropertyNames(cx, proxy, props) &&
            (!proto || js::GetPropertyNames(cx, proto, 0, &props));
 }
 
 template<class LC>
 bool
-ListBase<LC>::fix(JSContext *cx, JSObject *proxy, Value *vp)
-{
-    vp->setUndefined();
-    return true;
-}
-
-template<class LC>
-bool
 ListBase<LC>::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
     if (hasIndexGetter) {
         int32_t index = GetArrayIndexFromId(cx, id);
         if (index >= 0) {
             IndexGetterType result;
             *bp = getItemAt(getListObject(proxy), PRUint32(index), result);
             return true;
@@ -1234,26 +1241,32 @@ void
 ListBase<LC>::finalize(JSFreeOp *fop, JSObject *proxy)
 {
     ListType *list = getListObject(proxy);
     nsWrapperCache *cache;
     CallQueryInterface(list, &cache);
     if (cache) {
         cache->ClearWrapper();
     }
-    NS_RELEASE(list);
+    XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
+    if (rt) {
+        rt->DeferredRelease(nativeToSupports(list));
+    }
+    else {
+        NS_RELEASE(list);
+    }
 }
 
 
 JSObject*
-NoBase::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope)
+NoBase::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, JSObject *receiver)
 {
     // We need to pass the object prototype to JS_NewObject. If we pass NULL then the JS engine
     // will look up a prototype on the global by using the class' name and we'll recurse into
     // getPrototype.
-    return JS_GetObjectPrototype(cx, scope->GetGlobalJSObject());
+    return JS_GetObjectPrototype(cx, receiver);
 }
 
 
 }
 }
 }
 #include "dombindings_gen.cpp"
--- a/js/xpconnect/src/dombindings.h
+++ b/js/xpconnect/src/dombindings.h
@@ -103,32 +103,37 @@ public:
     typedef ListType LT;
     typedef Base B;
     typedef IndexOps IO;
     typedef NameOps NO;
 };
 
 class NoBase {
 public:
-    static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope);
+    static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope,
+                                  JSObject *receiver);
     static bool shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache)
     {
         *shouldCache = true;
         return true;
     }
     static bool resolveNativeName(JSContext *cx, JSObject *proxy, jsid id, JSPropertyDescriptor *desc)
     {
         return true;
     }
     static bool nativeGet(JSContext *cx, JSObject *proxy, JSObject *proto, jsid id, bool *found,
                           JS::Value *vp)
     {
         *found = false;
         return true;
     }
+    static nsISupports* nativeToSupports(nsISupports* aNative)
+    {
+        return aNative;
+    }
 };
 
 template<class ListType, class IndexOps, class NameOps=NoOps>
 class ListClass : public DerivedListClass<ListType, NoBase, IndexOps, NameOps> {
 };
 
 template<class LC>
 class ListBase : public ProxyHandler {
@@ -189,36 +194,31 @@ private:
     static bool getPropertyOnPrototype(JSContext *cx, JSObject *proxy, jsid id, bool *found,
                                        JS::Value *vp);
     static bool hasPropertyOnPrototype(JSContext *cx, JSObject *proxy, jsid id);
 
 public:
     static JSObject *create(JSContext *cx, JSObject *scope, ListType *list,
                             nsWrapperCache* cache, bool *triedToWrap);
 
-    static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled)
+    static JSObject *getPrototype(JSContext *cx, JSObject *receiver, bool *enabled);
+    static bool DefineDOMInterface(JSContext *cx, JSObject *receiver, bool *enabled)
     {
-        *enabled = true;
-        return getPrototype(cx, scope);
-    }
-    static bool DefineDOMInterface(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled)
-    {
-        return !!getPrototype(cx, scope, enabled);
+        return !!getPrototype(cx, receiver, enabled);
     }
 
     bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
                                JSPropertyDescriptor *desc);
     bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
                                   JSPropertyDescriptor *desc);
     bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
                         JSPropertyDescriptor *desc);
     bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, JS::AutoIdVector &props);
     bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     bool enumerate(JSContext *cx, JSObject *proxy, JS::AutoIdVector &props);
-    bool fix(JSContext *cx, JSObject *proxy, JS::Value *vp);
 
     bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
     bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, JS::Value *vp);
     bool getElementIfPresent(JSContext *cx, JSObject *proxy, JSObject *receiver,
                              uint32_t index, JS::Value *vp, bool *present);
     bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
              JS::Value *vp);
@@ -238,24 +238,29 @@ public:
     }
     static inline bool instanceIsListObject(JSContext *cx, JSObject *obj, JSObject *callee);
     virtual bool isInstanceOf(JSObject *prototype)
     {
         return js::GetObjectClass(prototype) == &sInterfaceClass;
     }
     static inline ListType *getListObject(JSObject *obj);
 
-    static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope);
+    static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope,
+                                  JSObject *receiver);
     static inline bool protoIsClean(JSContext *cx, JSObject *proto, bool *isClean);
     static bool shouldCacheProtoShape(JSContext *cx, JSObject *proto, bool *shouldCache);
     static bool resolveNativeName(JSContext *cx, JSObject *proxy, jsid id,
                                   JSPropertyDescriptor *desc);
     static bool nativeGet(JSContext *cx, JSObject *proxy, JSObject *proto, jsid id, bool *found,
                           JS::Value *vp);
     static ListType *getNative(JSObject *proxy);
+    static nsISupports* nativeToSupports(ListType* aNative)
+    {
+        return Base::nativeToSupports(aNative);
+    }
 };
 
 struct nsISupportsResult
 {
     nsISupportsResult()
     {
     }
     nsISupports *mResult;
--- a/js/xpconnect/src/dombindingsgen.py
+++ b/js/xpconnect/src/dombindingsgen.py
@@ -492,25 +492,30 @@ derivedClassTemplate = (
 "    NS_RUNTIMEABORT(\"Unknown list type!\");\n"
 "    return NULL;\n"
 "}\n"
 "\n")
 
 prefableClassTemplate = (
 "template<>\n"
 "JSObject *\n"
-"${name}Wrapper::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled)\n"
+"${name}Wrapper::getPrototype(JSContext *cx, JSObject *receiver, bool *enabled)\n"
 "{\n"
+"    XPCWrappedNativeScope *scope =\n"
+"        XPCWrappedNativeScope::FindInJSObjectScope(cx, receiver);\n"
+"    if (!scope)\n"
+"        return false;\n"
+"\n"
 "    if (!scope->NewDOMBindingsEnabled()) {\n"
 "        *enabled = false;\n"
 "        return NULL;\n"
 "    }\n"
 "\n"
 "    *enabled = true;\n"
-"    return getPrototype(cx, scope);\n"
+"    return getPrototype(cx, scope, receiver);\n"
 "}\n"
 "\n")
 
 toStringTemplate = (
 "template<>\n"
 "JSString *\n"
 "${name}Wrapper::obj_toString(JSContext *cx, JSObject *proxy)\n"
 "{\n"
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1015,17 +1015,17 @@ nsXPConnect::InitClasses(JSContext * aJS
     XPCWrappedNativeScope* scope =
         XPCWrappedNativeScope::GetNewOrUsed(ccx, aGlobalJSObj);
 
     if (!scope)
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     scope->RemoveWrappedNativeProtos();
 
-    if (!nsXPCComponents::AttachNewComponentsObject(ccx, scope, aGlobalJSObj))
+    if (!nsXPCComponents::AttachComponentsObject(ccx, scope, aGlobalJSObj))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     if (XPCPerThreadData::IsMainThread(ccx)) {
         if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
             return UnexpectedFailure(NS_ERROR_FAILURE);
     }
 
     return NS_OK;
@@ -1217,17 +1217,17 @@ nsXPConnect::InitClassesWithNewWrappedGl
 
     // Apply the system flag, if requested.
     bool system = (aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT) != 0;
     if (system && !JS_MakeSystemObject(aJSContext, global))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     if (!(aFlags & nsIXPConnect::OMIT_COMPONENTS_OBJECT)) {
         // XPCCallContext gives us an active request needed to save/restore.
-        if (!nsXPCComponents::AttachNewComponentsObject(ccx, wrappedGlobal->GetScope(), global))
+        if (!nsXPCComponents::AttachComponentsObject(ccx, wrappedGlobal->GetScope(), global))
             return UnexpectedFailure(NS_ERROR_FAILURE);
 
         if (XPCPerThreadData::IsMainThread(ccx)) {
             if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, global))
                 return UnexpectedFailure(NS_ERROR_FAILURE);
         }
     }
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1412,17 +1412,16 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS
         nsnull, /* setAttributes  */                                          \
         nsnull, /* setElementAttributes  */                                   \
         nsnull, /* setSpecialAttributes  */                                   \
         nsnull, /* deleteProperty */                                          \
         nsnull, /* deleteElement */                                           \
         nsnull, /* deleteSpecial */                                           \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_TypeOf_Function,                                          \
-        nsnull, /* fix            */                                          \
         XPC_WN_JSOp_ThisObject,                                               \
         XPC_WN_JSOp_Clear                                                     \
     }
 
 #define XPC_WN_NoCall_ObjectOps                                               \
     {                                                                         \
         nsnull, /* lookupGeneric */                                           \
         nsnull, /* lookupProperty */                                          \
@@ -1449,17 +1448,16 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS
         nsnull, /* setAttributes  */                                          \
         nsnull, /* setElementAttributes  */                                   \
         nsnull, /* setSpecialAttributes  */                                   \
         nsnull, /* deleteProperty */                                          \
         nsnull, /* deleteElement */                                           \
         nsnull, /* deleteSpecial */                                           \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_TypeOf_Object,                                            \
-        nsnull, /* fix            */                                          \
         XPC_WN_JSOp_ThisObject,                                               \
         XPC_WN_JSOp_Clear                                                     \
     }
 
 // Maybe this macro should check for class->enumerate ==
 // XPC_WN_Shared_Proto_Enumerate or something rather than checking for
 // 4 classes?
 static inline bool IS_PROTO_CLASS(js::Class *clazz)
@@ -1589,16 +1587,17 @@ public:
 
     JSBool
     IsValid() const {return mRuntime != nsnull;}
 
     static JSBool
     IsDyingScope(XPCWrappedNativeScope *scope);
 
     void SetComponents(nsXPCComponents* aComponents);
+    nsXPCComponents *GetComponents();
     void SetGlobal(XPCCallContext& ccx, JSObject* aGlobal, nsISupports* aNative);
 
     static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; }
 
     XPCContext *GetContext() { return mContext; }
     void SetContext(XPCContext *xpcc) { mContext = nsnull; }
 
     nsDataHashtable<nsDepCharHashKey, JSObject*>& GetCachedDOMPrototypes()
@@ -1638,17 +1637,17 @@ protected:
 private:
     static XPCWrappedNativeScope* gScopes;
     static XPCWrappedNativeScope* gDyingScopes;
 
     XPCJSRuntime*                    mRuntime;
     Native2WrappedNativeMap*         mWrappedNativeMap;
     ClassInfo2WrappedNativeProtoMap* mWrappedNativeProtoMap;
     ClassInfo2WrappedNativeProtoMap* mMainThreadWrappedNativeProtoMap;
-    nsXPCComponents*                 mComponents;
+    nsRefPtr<nsXPCComponents>        mComponents;
     XPCWrappedNativeScope*           mNext;
     // The JS global object for this scope.  If non-null, this will be the
     // default parent for the XPCWrappedNatives that have us as the scope,
     // unless a PreCreate hook overrides it.  Note that this _may_ be null (see
     // constructor).
     js::ObjectPtr                    mGlobalJSObject;
 
     // Cached value of Object.prototype
@@ -3882,29 +3881,31 @@ public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
     NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
 public:
     static JSBool
-    AttachNewComponentsObject(XPCCallContext& ccx,
-                              XPCWrappedNativeScope* aScope,
-                              JSObject* aGlobal);
+    AttachComponentsObject(XPCCallContext& ccx,
+                           XPCWrappedNativeScope* aScope,
+                           JSObject* aGlobal);
 
     void SystemIsBeingShutDown() {ClearMembers();}
 
     virtual ~nsXPCComponents();
 
 private:
-    nsXPCComponents();
+    nsXPCComponents(XPCWrappedNativeScope* aScope);
     void ClearMembers();
 
 private:
+    friend class XPCWrappedNativeScope;
+    XPCWrappedNativeScope*          mScope;
     nsXPCComponents_Interfaces*     mInterfaces;
     nsXPCComponents_InterfacesByID* mInterfacesByID;
     nsXPCComponents_Classes*        mClasses;
     nsXPCComponents_ClassesByID*    mClassesByID;
     nsXPCComponents_Results*        mResults;
     nsXPCComponents_ID*             mID;
     nsXPCComponents_Exception*      mException;
     nsXPCComponents_Constructor*    mConstructor;
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -310,17 +310,17 @@ extern int HandlerFamily;
 inline void* ProxyFamily() { return &HandlerFamily; }
 inline bool instanceIsProxy(JSObject *obj)
 {
     return js::IsProxy(obj) &&
            js::GetProxyHandler(obj)->family() == ProxyFamily();
 }
 
 typedef bool
-(*DefineInterface)(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled);
+(*DefineInterface)(JSContext *cx, JSObject *global, bool *enabled);
 
 extern bool
 DefineStaticJSVals(JSContext *cx);
 void
 Register(nsScriptNameSpaceManager* aNameSpaceManager);
 extern bool
 DefineConstructor(JSContext *cx, JSObject *obj, DefineInterface aDefine,
                   nsresult *aResult);
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/unit/test_components.js
@@ -0,0 +1,43 @@
+function run_test() {
+  var Cu = Components.utils;
+  var sb1 = Cu.Sandbox("http://www.blah.com");
+  var sb2 = Cu.Sandbox("http://www.blah.com");
+  var sb3 = Cu.Sandbox(this);
+  var sb4 = Cu.Sandbox("http://www.other.com");
+  var rv;
+
+  // non-chrome accessing chrome Components
+  sb1.C = Components;
+  rv = Cu.evalInSandbox("C.utils", sb1);
+  do_check_eq(rv, undefined);  
+  rv = Cu.evalInSandbox("C.interfaces", sb1);
+  do_check_neq(rv, undefined);
+
+  // non-chrome accessing own Components
+  rv = Cu.evalInSandbox("Components.utils", sb1);
+  do_check_eq(rv, undefined);
+  rv = Cu.evalInSandbox("Components.interfaces", sb1);
+  do_check_neq(rv, undefined); 
+
+  // non-chrome same origin
+  var C2 = Cu.evalInSandbox("Components", sb2);
+  do_check_neq(rv, C2.utils); 
+  sb1.C2 = C2;
+  rv = Cu.evalInSandbox("C2.utils", sb1);
+  do_check_eq(rv, undefined);
+  rv = Cu.evalInSandbox("C2.interfaces", sb1);
+  do_check_neq(rv, undefined);
+
+  // chrome accessing chrome
+  sb3.C = Components;
+  rv = Cu.evalInSandbox("C.utils", sb3);
+  do_check_eq(rv, Cu);
+
+  // non-chrome cross origin
+  sb4.C2 = C2;
+  rv = Cu.evalInSandbox("C2.interfaces", sb1);
+  do_check_neq(rv, undefined);
+  rv = Cu.evalInSandbox("C2.utils", sb1);
+  do_check_eq(rv, undefined);
+
+}
\ No newline at end of file
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -20,8 +20,9 @@ tail =
 [test_localeCompare.js]
 # Bug 676965: test fails consistently on Android
 fail-if = os == "android"
 [test_recursive_import.js]
 [test_xpcomutils.js]
 [test_unload.js]
 [test_attributes.js]
 [test_params.js]
+[test_components.js]
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -602,9 +602,34 @@ ExposedPropertiesOnly::check(JSContext *
         (act != Wrapper::SET && !(access & READ))) {
         return PermitIfUniversalXPConnect(cx, id, act, perm); // Deny
     }
 
     perm = PermitPropertyAccess;
     return true; // Allow
 }
 
+bool
+ComponentsObjectPolicy::check(JSContext *cx, JSObject *wrapper, jsid id, Wrapper::Action act,
+                              Permission &perm) 
+{
+    perm = DenyAccess;
+    JSAutoEnterCompartment ac;
+    if (!ac.enter(cx, wrapper))
+        return false;
+
+    if (JSID_IS_STRING(id) && act == Wrapper::GET) {
+        JSFlatString *flatId = JSID_TO_FLAT_STRING(id);
+        if (JS_FlatStringEqualsAscii(flatId, "isSuccessCode") ||
+            JS_FlatStringEqualsAscii(flatId, "lookupMethod") ||
+            JS_FlatStringEqualsAscii(flatId, "interfaces") ||
+            JS_FlatStringEqualsAscii(flatId, "interfacesByID") ||
+            JS_FlatStringEqualsAscii(flatId, "results"))
+        {
+            perm = PermitPropertyAccess;
+            return true;
+        }
+    }
+
+    return PermitIfUniversalXPConnect(cx, id, act, perm);  // Deny
 }
+
+}
--- a/js/xpconnect/wrappers/AccessCheck.h
+++ b/js/xpconnect/wrappers/AccessCheck.h
@@ -170,9 +170,15 @@ struct LocationPolicy : public Policy {
 
 // This policy only permits access to properties if they appear in the
 // objects exposed properties list.
 struct ExposedPropertiesOnly : public Policy {
     static bool check(JSContext *cx, JSObject *wrapper, jsid id, js::Wrapper::Action act,
                       Permission &perm);
 };
 
+// Components specific policy
+struct ComponentsObjectPolicy : public Policy {
+    static bool check(JSContext *cx, JSObject *wrapper, jsid id, js::Wrapper::Action act,
+                      Permission &perm);
+};
+
 }
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -146,33 +146,39 @@ FilteringWrapper<Base, Policy>::enter(JS
 #define DXOW   FilteringWrapper<XrayDOM, \
                                 CrossOriginAccessiblePropertiesOnly>
 #define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, \
                                CrossOriginAccessiblePropertiesOnly>
 #define LW    FilteringWrapper<XrayWrapper<SameCompartmentSecurityWrapper>, \
                                LocationPolicy>
 #define XLW   FilteringWrapper<XrayWrapper<CrossCompartmentSecurityWrapper>, \
                                LocationPolicy>
-
+#define CW FilteringWrapper<SameCompartmentSecurityWrapper, \
+                            ComponentsObjectPolicy>
+#define XCW FilteringWrapper<CrossCompartmentSecurityWrapper, \
+                            ComponentsObjectPolicy>
 template<> SOW SOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                               WrapperFactory::SOW_FLAG);
 template<> SCSOW SCSOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                                   WrapperFactory::SOW_FLAG);
 template<> COW COW::singleton(0);
 template<> XOW XOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                               WrapperFactory::PARTIALLY_TRANSPARENT);
 template<> PXOW PXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                                 WrapperFactory::PARTIALLY_TRANSPARENT);
 template<> DXOW DXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                                 WrapperFactory::PARTIALLY_TRANSPARENT);
 template<> NNXOW NNXOW::singleton(WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG |
                                   WrapperFactory::PARTIALLY_TRANSPARENT);
 template<> LW  LW::singleton(WrapperFactory::SHADOWING_FORBIDDEN);
 template<> XLW XLW::singleton(WrapperFactory::SHADOWING_FORBIDDEN);
 
+template<> CW CW::singleton(0);
+template<> XCW XCW::singleton(0);
+
 template class SOW;
 template class COW;
 template class XOW;
 template class PXOW;
 template class DXOW;
 template class NNXOW;
 template class LW;
 template class XLW;
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -361,16 +361,19 @@ WrapperFactory::Rewrap(JSContext *cx, JS
             if (IsLocationObject(obj))
                 wrapper = &FilteringWrapper<Xray, LocationPolicy>::singleton;
             else
                 wrapper = &FilteringWrapper<Xray, CrossOriginAccessiblePropertiesOnly>::singleton;
         } else if (mozilla::dom::binding::instanceIsProxy(obj)) {
             wrapper = &FilteringWrapper<XrayProxy, CrossOriginAccessiblePropertiesOnly>::singleton;
         } else if (mozilla::dom::bindings::IsDOMClass(JS_GetClass(obj))) {
             wrapper = &FilteringWrapper<XrayDOM, CrossOriginAccessiblePropertiesOnly>::singleton;
+        } else if (IsComponentsObject(obj)) {
+            wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
+                                        ComponentsObjectPolicy>::singleton;
         } else {
             wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
                                         ExposedPropertiesOnly>::singleton;
         }
     } else if (AccessCheck::isSameOrigin(origin, target)) {
         // For the same-origin case we use a transparent wrapper, unless one
         // of the following is true:
         // * The object is flagged as needing a SOW.
@@ -395,16 +398,19 @@ WrapperFactory::Rewrap(JSContext *cx, JS
         // to the LW in the host compartment, rather than an XLW directly to the
         // Location object. This still doesn't share expandos in the
         // document.domain case, but that's probably fine. Double-wrapping sucks,
         // but it's kind of unavoidable here.
         XrayType type;
         if (AccessCheck::needsSystemOnlyWrapper(obj)) {
             wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
                                         OnlyIfSubjectIsSystem>::singleton;
+        } else if (IsComponentsObject(obj)) {
+            wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
+                                        ComponentsObjectPolicy>::singleton;
         } else if (!targetdata || !targetdata->wantXrays ||
                    (type = GetXrayType(obj)) == NotXray) {
             // Do the double-wrapping if need be.
             if (IsLocationObject(obj)) {
                 JSAutoEnterCompartment ac;
                 if (!ac.enter(cx, obj))
                     return nsnull;
                 XPCWrappedNative *wn = GetWrappedNative(cx, obj);
@@ -519,9 +525,26 @@ WrapperFactory::WrapSOWObject(JSContext 
 {
     JSObject *wrapperObj =
         Wrapper::New(cx, obj, JS_GetPrototype(obj), JS_GetGlobalForObject(cx, obj),
                      &FilteringWrapper<SameCompartmentSecurityWrapper,
                      OnlyIfSubjectIsSystem>::singleton);
     return wrapperObj;
 }
 
+bool
+WrapperFactory::IsComponentsObject(JSObject *obj)
+{
+    const char *name = js::GetObjectClass(obj)->name;
+    return name[0] == 'n' && !strcmp(name, "nsXPCComponents");
 }
+
+JSObject *
+WrapperFactory::WrapComponentsObject(JSContext *cx, JSObject *obj)
+{
+    JSObject *wrapperObj =
+        Wrapper::New(cx, obj, JS_GetPrototype(obj), JS_GetGlobalForObject(cx, obj),
+                     &FilteringWrapper<SameCompartmentSecurityWrapper, ComponentsObjectPolicy>::singleton);
+
+    return wrapperObj;
+}
+
+}
--- a/js/xpconnect/wrappers/WrapperFactory.h
+++ b/js/xpconnect/wrappers/WrapperFactory.h
@@ -105,15 +105,21 @@ class WrapperFactory {
     // Wrap a location object.
     static JSObject *WrapLocationObject(JSContext *cx, JSObject *obj);
 
     // Wrap wrapped object into a waiver wrapper and then re-wrap it.
     static bool WaiveXrayAndWrap(JSContext *cx, jsval *vp);
 
     // Wrap a (same compartment) object in a SOW.
     static JSObject *WrapSOWObject(JSContext *cx, JSObject *obj);
+
+    // Return true if this is a Components object.
+    static bool IsComponentsObject(JSObject *obj);
+
+    // Wrap a (same compartment) Components object.
+    static JSObject *WrapComponentsObject(JSContext *cx, JSObject *obj);
 };
 
 extern js::Wrapper WaiveXrayWrapperWrapper;
 
 }
 
 #endif /* _xpc_WRAPPERFACTORY_H */
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1323,24 +1323,16 @@ template <typename Base, typename Traits
 bool
 XrayWrapper<Base, Traits>::enumerate(JSContext *cx, JSObject *wrapper, JS::AutoIdVector &props)
 {
     return enumerate(cx, wrapper, 0, props);
 }
 
 template <typename Base, typename Traits>
 bool
-XrayWrapper<Base, Traits>::fix(JSContext *cx, JSObject *proxy, js::Value *vp)
-{
-    vp->setUndefined();
-    return true;
-}
-
-template <typename Base, typename Traits>
-bool
 XrayWrapper<Base, Traits>::get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
                                js::Value *vp)
 {
     // Skip our Base if it isn't already ProxyHandler.
     // NB: None of the functions we call are prepared for the receiver not
     // being the wrapper, so ignore the receiver here.
     return ProxyHandler::get(cx, wrapper, wrapper, id, vp);
 }
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -86,17 +86,16 @@ class XrayWrapper : public Base {
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
                                           bool set, js::PropertyDescriptor *desc);
     virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
                                 js::PropertyDescriptor *desc);
     virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
                                      js::AutoIdVector &props);
     virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
     virtual bool enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
-    virtual bool fix(JSContext *cx, JSObject *proxy, js::Value *vp);
 
     /* Derived proxy traps. */
     virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
                      js::Value *vp);
     virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id,
                      bool strict, js::Value *vp);
     virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
     virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
--- a/layout/mathml/nsMathMLmactionFrame.cpp
+++ b/layout/mathml/nsMathMLmactionFrame.cpp
@@ -212,16 +212,17 @@ nsMathMLmactionFrame::GetSelectedFrame()
     childFrame = childFrame->GetNextSibling();
   }
   // cater for invalid user-supplied selection
   if (selection > count || selection < 1) 
     selection = 1;
 
   mChildCount = count;
   mSelection = selection;
+  TransmitAutomaticData();
 
   return mSelectedFrame;
 }
 
 NS_IMETHODIMP
 nsMathMLmactionFrame::SetInitialChildList(ChildListID     aListID,
                                           nsFrameList&    aChildList)
 {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/maction-dynamic-embellished-op-ref.html
@@ -0,0 +1,30 @@
+<html>
+
+<head>
+<title>dynamic maction and embellished op</title>
+</head>
+
+<body>
+
+  <p>'<math><maction id="m1" selection="2"><mi>a</mi><mo>b</mo></maction></math>'</p>
+  <p>'<math><maction id="m2" selection="2"><mo>b</mo><mi>a</mi></maction></math>'</p>
+ 
+  <p>"<math><maction id="m3"><mo>b</mo></maction></math>"</p>
+  <p>"<math><maction id="m3bis"><mi>a</mi><mo>b</mo></maction></math>"</p>
+
+  <p>{<math><maction id="m4"><mi>a</mi></maction></math>}</p>
+  <p>{<math><maction id="m4bis"><mo>b</mo><mi>a</mi></maction></math>}</p>
+
+ 
+  <p>[<math>
+    <mstyle id="m5" selection="2"><maction><mi>a</mi><mo>b</mo></maction></mstyle>
+  </math>]</p>
+  <p>[<math>
+    <mstyle id="m6" selection="2"><maction><mo>b</mo><mi>a</mi></maction></mstyle>
+  </math>]</p>
+
+  <p>(<math id="m7" selection="2"><maction><mi>a</mi><mo>b</mo></maction></math>)</p>
+  <p>(<math id="m8" selection="2"><maction><mo>b</mo><mi>a</mi></maction></math>)</p>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/maction-dynamic-embellished-op.html
@@ -0,0 +1,56 @@
+<html class="reftest-wait">
+
+<head>
+<title>dynamic maction and embellished op</title>
+</head>
+
+<body>
+
+  <p>'<math><maction id="m1"><mi>a</mi><mo>b</mo></maction></math>'</p>
+  <p>'<math><maction id="m2"><mo>b</mo><mi>a</mi></maction></math>'</p>
+ 
+  <p>"<math><maction id="m3"><mi>a</mi><mo>b</mo></maction></math>"</p>
+  <p>"<math><maction id="m3bis"><mo>b</mo></maction></math>"</p>
+
+  <p>{<math><maction id="m4"><mo>b</mo><mi>a</mi></maction></math>}</p>
+  <p>{<math><maction id="m4bis"><mi>a</mi></maction></math>}</p>
+
+ 
+  <p>[<math>
+    <mstyle id="m5"><maction><mi>a</mi><mo>b</mo></maction></mstyle>
+  </math>]</p>
+  <p>[<math>
+    <mstyle id="m6"><maction><mo>b</mo><mi>a</mi></maction></mstyle>
+  </math>]</p>
+
+  <p>(<math id="m7"><maction><mi>a</mi><mo>b</mo></maction></math>)</p>
+  <p>(<math id="m8"><maction><mo>b</mo><mi>a</mi></maction></math>)</p>
+
+<script>
+function doTest()
+{
+  document.getElementById("m1").setAttribute("selection", "2");
+  document.getElementById("m2").setAttribute("selection", "2");
+
+  var m3 = document.getElementById("m3");
+  var m3bis = document.getElementById("m3bis");
+  m3bis.insertBefore(m3.removeChild(m3.firstChild), m3bis.firstChild);
+
+  var m4 = document.getElementById("m4");
+  var m4bis = document.getElementById("m4bis");
+  m4bis.insertBefore(m4.removeChild(m4.firstChild), m4bis.firstChild);
+
+  document.getElementById("m5").setAttribute("selection", "2");
+  document.getElementById("m6").setAttribute("selection", "2");
+
+  document.getElementById("m7").setAttribute("selection", "2");
+  document.getElementById("m8").setAttribute("selection", "2");
+
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+
+</body>
+</html>
--- a/layout/reftests/mathml/reftest.list
+++ b/layout/reftests/mathml/reftest.list
@@ -92,9 +92,10 @@ fails == mstyle-5.xhtml mstyle-5-ref.xht
 == munder-mover-align-accent-true.html munder-mover-align-accent-true-ref.html
 == munder-mover-align-accent-false.html munder-mover-align-accent-false-ref.html
 == mfrac-linethickness-1.xhtml mfrac-linethickness-1-ref.xhtml
 == mathml-negativespace.html mathml-negativespace-ref.html
 != link-1.xhtml link-ref.xhtml
 == munderover-empty-scripts.html munderover-empty-scripts-ref.html
 == positive-namedspace.html positive-namedspace-ref.html
 == mtable-width.html mtable-width-ref.html
-== maction-selection.html maction-selection-ref.html
\ No newline at end of file
+== maction-selection.html maction-selection-ref.html
+== maction-dynamic-embellished-op.html maction-dynamic-embellished-op-ref.html
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -5639,24 +5639,24 @@ nsRuleNode::ComputeBorderData(void* aSta
 
     case eCSSUnit_Initial:
     case eCSSUnit_None:
       border->ClearBorderColors(side);
       break;
 
     case eCSSUnit_Inherit: {
       canStoreInRuleTree = false;
-      nsBorderColors *parentColors;
-      parentBorder->GetCompositeColors(side, &parentColors);
-      if (parentColors) {
-        border->EnsureBorderColors();
-        border->ClearBorderColors(side);
-        border->mBorderColors[side] = parentColors->Clone();
-      } else {
-        border->ClearBorderColors(side);
+      border->ClearBorderColors(side);
+      if (parentContext) {
+        nsBorderColors *parentColors;
+        parentBorder->GetCompositeColors(side, &parentColors);
+        if (parentColors) {
+          border->EnsureBorderColors();
+          border->mBorderColors[side] = parentColors->Clone();
+        }
       }
       break;
     }
 
     case eCSSUnit_List:
     case eCSSUnit_ListDep: {
       // Some composite border color information has been specified for this
       // border side.
--- a/layout/xul/base/src/nsTextBoxFrame.cpp
+++ b/layout/xul/base/src/nsTextBoxFrame.cpp
@@ -926,37 +926,40 @@ nsTextBoxFrame::DoLayout(nsBoxLayoutStat
     }
 
     nsresult rv = nsLeafBoxFrame::DoLayout(aBoxLayoutState);
 
     CalcDrawRect(*aBoxLayoutState.GetRenderingContext());
 
     const nsStyleText* textStyle = GetStyleText();
     
-    nsRect bounds(nsPoint(0, 0), GetSize());
+    nsRect scrollBounds(nsPoint(0, 0), GetSize());
     nsRect textRect = mTextDrawRect;
     
     nsRefPtr<nsFontMetrics> fontMet;
     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
     nsBoundingMetrics metrics = 
-      fontMet->GetInkBoundsForVisualOverflow(mTitle.get(), mTitle.Length(),
+      fontMet->GetInkBoundsForVisualOverflow(mCroppedTitle.get(),
+                                             mCroppedTitle.Length(),
                                              aBoxLayoutState.GetRenderingContext());
 
     textRect.x -= metrics.leftBearing;
     textRect.width = metrics.width;
     // In DrawText() we always draw with the baseline at MaxAscent() (relative to mTextDrawRect), 
     textRect.y += fontMet->MaxAscent() - metrics.ascent;
     textRect.height = metrics.ascent + metrics.descent;
 
-    bounds.UnionRect(bounds, textRect);
-    nsOverflowAreas overflow(bounds, bounds);
+    // Our scrollable overflow is our bounds; our visual overflow may
+    // extend beyond that.
+    nsRect visualBounds;
+    visualBounds.UnionRect(scrollBounds, textRect);
+    nsOverflowAreas overflow(visualBounds, scrollBounds);
 
     if (textStyle->mTextShadow) {
-      // Our scrollable overflow is our bounds; our visual overflow may
-      // extend beyond that.
+      // text-shadow extends our visual but not scrollable bounds
       nsRect &vis = overflow.VisualOverflow();
       vis.UnionRect(vis, nsLayoutUtils::GetTextShadowRectsUnion(mTextDrawRect, this));
     }
     FinishAndStoreOverflow(overflow, GetSize());
 
     return rv;
 }
 
--- a/mfbt/double-conversion/add-mfbt-api-markers.patch
+++ b/mfbt/double-conversion/add-mfbt-api-markers.patch
@@ -14,31 +14,16 @@ index f98edae..e536a01 100644
    }
  
    // Returns a converter following the EcmaScript specification.
 -  static const DoubleToStringConverter& EcmaScriptConverter();
 +  static MFBT_API(const DoubleToStringConverter&) EcmaScriptConverter();
  
    // Computes the shortest string of digits that correctly represent the input
    // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
-@@ -154,12 +155,12 @@ class DoubleToStringConverter {
-   // Returns true if the conversion succeeds. The conversion always succeeds
-   // except when the input value is special and no infinity_symbol or
-   // nan_symbol has been given to the constructor.
--  bool ToShortest(double value, StringBuilder* result_builder) const {
-+  MFBT_API(bool) ToShortest(double value, StringBuilder* result_builder) const {
-     return ToShortestIeeeNumber(value, result_builder, SHORTEST);
-   }
- 
-   // Same as ToShortest, but for single-precision floats.
--  bool ToShortestSingle(float value, StringBuilder* result_builder) const {
-+  MFBT_API(bool) ToShortestSingle(float value, StringBuilder* result_builder) const {
-     return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
-   }
- 
 @@ -197,7 +198,7 @@ class DoubleToStringConverter {
    // The last two conditions imply that the result will never contain more than
    // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
    // (one additional character for the sign, and one for the decimal point).
 -  bool ToFixed(double value,
 +  MFBT_API(bool) ToFixed(double value,
                 int requested_digits,
                 StringBuilder* result_builder) const;
--- a/mfbt/double-conversion/double-conversion.h
+++ b/mfbt/double-conversion/double-conversion.h
@@ -150,22 +150,22 @@ class DoubleToStringConverter {
   // is accurate enough to uniquely identify the input-number.
   // For example the most precise representation of the double 9e59 equals
   // "899999999999999918767229449717619953810131273674690656206848", but
   // the converter will return the shorter (but still correct) "9e59".
   //
   // Returns true if the conversion succeeds. The conversion always succeeds
   // except when the input value is special and no infinity_symbol or
   // nan_symbol has been given to the constructor.
-  MFBT_API(bool) ToShortest(double value, StringBuilder* result_builder) const {
+  bool ToShortest(double value, StringBuilder* result_builder) const {
     return ToShortestIeeeNumber(value, result_builder, SHORTEST);
   }
 
   // Same as ToShortest, but for single-precision floats.
-  MFBT_API(bool) ToShortestSingle(float value, StringBuilder* result_builder) const {
+  bool ToShortestSingle(float value, StringBuilder* result_builder) const {
     return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
   }
 
 
   // Computes a decimal representation with a fixed number of digits after the
   // decimal point. The last emitted digit is rounded.
   //
   // Examples:
--- a/mfbt/double-conversion/update.sh
+++ b/mfbt/double-conversion/update.sh
@@ -8,9 +8,9 @@ cp $1/README ./
 
 # Includes
 cp $1/src/*.h ./
 
 # Source
 cp $1/src/*.cc ./
 
 patch -p3 < add-mfbt-api-markers.patch
-patch -p3 < useStandardInteger.patch
+patch -p3 < use-StandardInteger.patch
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -474,16 +474,17 @@ pref("dom.ipc.plugins.enabled", true);
 pref("plugin.disable", false);
 pref("dom.ipc.plugins.enabled", false);
 #else
 pref("plugin.disable", true);
 pref("dom.ipc.plugins.enabled", true);
 #endif
 
 pref("plugins.click_to_play", true);
+pref("plugins.use_placeholder", 1);
 
 // process priority
 // higher values give content process less CPU time
 #if MOZ_PLATFORM_MAEMO == 5
 pref("dom.ipc.content.nice", 10);
 #else
 pref("dom.ipc.content.nice", 1);
 #endif
--- a/mobile/android/base/AwesomeBarTabs.java
+++ b/mobile/android/base/AwesomeBarTabs.java
@@ -361,51 +361,58 @@ public class AwesomeBarTabs extends TabH
         }
 
         @Override
         protected Cursor doInBackground(Void... arg0) {
             return BrowserDB.getBookmarksInFolder(mContentResolver, mFolderId);
         }
 
         @Override
-        protected void onPostExecute(Cursor cursor) {
-            ListView list = (ListView) findViewById(R.id.bookmarks_list);
-            list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                    handleBookmarkItemClick(parent, view, position, id);
+        protected void onPostExecute(final Cursor cursor) {
+            final ListView list = (ListView) findViewById(R.id.bookmarks_list);
+
+            // Hack: force this to the main thread, even though it should already be on it
+            GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
+                public void run() {
+                    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                            handleBookmarkItemClick(parent, view, position, id);
+                        }
+                    });
+                    
+                    // We need to add the header before we set the adapter, hence make it null
+                    list.setAdapter(null);
+
+                    if (mBookmarksAdapter == null) {
+                        mBookmarksAdapter = new BookmarksListAdapter(mContext, cursor);
+                    } else {
+                        mBookmarksAdapter.changeCursor(cursor);
+                    }
+
+                    LinearLayout headerView = mBookmarksAdapter.getHeaderView();
+                    if (headerView == null) {
+                        headerView = (LinearLayout) mInflater.inflate(R.layout.awesomebar_header_row, null);
+                        mBookmarksAdapter.setHeaderView(headerView);
+                    }
+
+                    // Add/Remove header based on the root folder
+                    if (mFolderId == Bookmarks.FIXED_ROOT_ID) {
+                        if (list.getHeaderViewsCount() == 1)
+                            list.removeHeaderView(headerView);
+                    } else {
+                        if (list.getHeaderViewsCount() == 0)
+                            list.addHeaderView(headerView, null, true);
+
+                        ((TextView) headerView.findViewById(R.id.title)).setText(mFolderTitle);
+                    }
+
+                    list.setAdapter(mBookmarksAdapter);
                 }
             });
-            
-            // We need to add the header before we set the adapter, hence make it null
-            list.setAdapter(null);
 
-            if (mBookmarksAdapter == null) {
-                mBookmarksAdapter = new BookmarksListAdapter(mContext, cursor);
-            } else {
-                mBookmarksAdapter.changeCursor(cursor);
-            }
-
-            LinearLayout headerView = mBookmarksAdapter.getHeaderView();
-            if (headerView == null) {
-                headerView = (LinearLayout) mInflater.inflate(R.layout.awesomebar_header_row, null);
-                mBookmarksAdapter.setHeaderView(headerView);
-            }
-
-            // Add/Remove header based on the root folder
-            if (mFolderId == Bookmarks.FIXED_ROOT_ID) {
-                if (list.getHeaderViewsCount() == 1)
-                    list.removeHeaderView(headerView);
-            } else {
-                if (list.getHeaderViewsCount() == 0)
-                    list.addHeaderView(headerView, null, true);
-
-                ((TextView) headerView.findViewById(R.id.title)).setText(mFolderTitle);
-            }
-
-            list.setAdapter(mBookmarksAdapter);
             mBookmarksQueryTask = null;
         }
     }
 
     private static class GroupList extends LinkedList<Map<String,String>> {
         private static final long serialVersionUID = 0L;
     }
 
@@ -570,38 +577,42 @@ public class AwesomeBarTabs extends TabH
                 new String[] { URLColumns.TITLE },
                 new int[] { R.id.title },
                 result.second
             );
 
             final ExpandableListView historyList =
                     (ExpandableListView) findViewById(R.id.history_list);
 
-            historyList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
-                public boolean onChildClick(ExpandableListView parent, View view,
-                        int groupPosition, int childPosition, long id) {
-                    handleHistoryItemClick(groupPosition, childPosition);
-                    return true;
+            // Hack: force this to the main thread, even though it should already be on it
+            GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
+                public void run() {
+                    historyList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
+                        public boolean onChildClick(ExpandableListView parent, View view,
+                                int groupPosition, int childPosition, long id) {
+                            handleHistoryItemClick(groupPosition, childPosition);
+                            return true;
+                        }
+                    });
+
+                    // This is to disallow collapsing the expandable groups in the
+                    // history expandable list view to mimic simpler sections. We should
+                    // Remove this if we decide to allow expanding/collapsing groups.
+                    historyList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
+                        public boolean onGroupClick(ExpandableListView parent, View v,
+                                int groupPosition, long id) {
+                            return true;
+                        }
+                    });
+
+                    historyList.setAdapter(mHistoryAdapter);
+                    expandAllGroups(historyList);
                 }
             });
 
-            // This is to disallow collapsing the expandable groups in the
-            // history expandable list view to mimic simpler sections. We should
-            // Remove this if we decide to allow expanding/collapsing groups.
-            historyList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
-                public boolean onGroupClick(ExpandableListView parent, View v,
-                        int groupPosition, long id) {
-                    return true;
-                }
-            });
-
-            historyList.setAdapter(mHistoryAdapter);
-
-            expandAllGroups(historyList);
-
             mHistoryQueryTask = null;
         }
     }
 
     private class AwesomeBarCursorAdapter extends SimpleCursorAdapter {
         private String mSearchTerm;
 
         public AwesomeBarCursorAdapter(Context context) {
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -36,22 +36,25 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.gfx.CairoImage;
+import org.mozilla.gecko.gfx.BufferedCairoImage;
 import org.mozilla.gecko.gfx.FloatSize;
 import org.mozilla.gecko.gfx.GeckoLayerClient;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.Layer;
 import org.mozilla.gecko.gfx.LayerController;
 import org.mozilla.gecko.gfx.LayerView;
+import org.mozilla.gecko.gfx.PluginLayer;
 import org.mozilla.gecko.gfx.RectUtils;
 import org.mozilla.gecko.gfx.SurfaceTextureLayer;
 import org.mozilla.gecko.gfx.ViewportMetrics;
 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 import org.mozilla.gecko.Tab.HistoryEntry;
 
 import java.io.*;
 import java.util.*;
@@ -77,16 +80,18 @@ import android.view.ViewGroup.LayoutPara
 import android.content.*;
 import android.content.res.*;
 import android.graphics.*;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.widget.*;
 import android.hardware.*;
 import android.location.*;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityEvent;
 
 import android.util.*;
 import android.net.*;
 import android.database.*;
 import android.database.sqlite.*;
 import android.provider.*;
 import android.content.pm.*;
 import android.content.pm.PackageManager.*;
@@ -672,17 +677,17 @@ abstract public class GeckoApp
                 if (Tabs.getInstance().isSelectedTab(tab)) {
                     mBrowserToolbar.setTitle(uri);
                     mBrowserToolbar.setFavicon(null);
                     mBrowserToolbar.setSecurityMode("unknown");
                     mDoorHangerPopup.updatePopup();
                     mBrowserToolbar.setShadowVisibility(!(tab.getURL().startsWith("about:")));
 
                     if (tab != null)
-                        hidePlugins(tab, true);
+                        hidePlugins(tab);
                 }
             }
         });
     }
 
     void handleSecurityChange(final int tabId, final String mode) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
@@ -1012,32 +1017,40 @@ abstract public class GeckoApp
                         GeckoAppShell.getHandler().post(new Runnable() {
                             public void run() {
                                 BrowserDB.addBookmark(GeckoApp.mAppContext.getContentResolver(), title, url);
                             }
                         });
                     }
                 });
             } else if (event.equals("Accessibility:Event")) {
-                final int eventType = message.getInt("eventType");
+                final AccessibilityEvent accEvent = AccessibilityEvent.obtain(message.getInt("eventType"));
+                accEvent.setClassName(LayerView.class.getName());
+                accEvent.setPackageName(mAppContext.getPackageName());
 
                 final JSONArray text = message.getJSONArray("text");
-                final int len = text.length();
-                final String[] textList = new String[len];
-                for (int i = 0; i < len; i++)
-                    textList[i] = text.getString(i);
-
-                final String description = message.optString("description");
-                final boolean enabled = message.optBoolean("enabled", true);
-                final boolean checked = message.optBoolean("checked");
-                final boolean password = message.optBoolean("password");
+                for (int i = 0; i < text.length(); i++)
+                    accEvent.getText().add(text.getString(i));
+
+                accEvent.setContentDescription(message.optString("description"));
+                accEvent.setEnabled(message.optBoolean("enabled", true));
+                accEvent.setChecked(message.optBoolean("checked"));
+                accEvent.setPassword(message.optBoolean("password"));
+                accEvent.setAddedCount(message.optInt("addedCount"));
+                accEvent.setRemovedCount(message.optInt("removedCount"));
+                accEvent.setFromIndex(message.optInt("fromIndex"));
+                accEvent.setItemCount(message.optInt("itemCount"));
+                accEvent.setCurrentItemIndex(message.optInt("currentItemIndex"));
+                accEvent.setBeforeText(message.optString("beforeText"));
+
                 mMainHandler.post(new Runnable() {
                     public void run() {
-                        GeckoAppShell.emitGeckoAccessibilityEvent(eventType, textList, description,
-                                                                  enabled, checked, password);
+                        AccessibilityManager accessibilityManager =
+                            (AccessibilityManager) mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+                        accessibilityManager.sendAccessibilityEvent(accEvent);
                     }
                 });
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
 
@@ -1315,85 +1328,45 @@ abstract public class GeckoApp
             DownloadManager dm = (DownloadManager) mAppContext.getSystemService(Context.DOWNLOAD_SERVICE);
             dm.addCompletedDownload(displayName, displayName,
                 false /* do not use media scanner */,
                 mimeType, path, size,
                 false /* no notification */);
         }
     }
 
-    void addPluginView(final View view,
-                       final int x, final int y,
-                       final int w, final int h,
-                       final String metadata) {
+    void addPluginView(final View view, final Rect rect) {
         mMainHandler.post(new Runnable() { 
             public void run() {
-                PluginLayoutParams lp;
-
                 Tabs tabs = Tabs.getInstance();
                 Tab tab = tabs.getSelectedTab();
 
-                if (tab == null)
-                    return;
-
-                ImmutableViewportMetrics targetViewport = mLayerController.getViewportMetrics();
-                ImmutableViewportMetrics pluginViewport;
-                
-                try {
-                    JSONObject viewportObject = new JSONObject(metadata);
-                    pluginViewport = new ImmutableViewportMetrics(new ViewportMetrics(viewportObject));
-                } catch (JSONException e) {
-                    Log.e(LOGTAG, "Bad viewport metadata: ", e);
-                    return;
-                }
-
-                if (mPluginContainer.indexOfChild(view) == -1) {
-                    lp = new PluginLayoutParams(x, y, w, h, pluginViewport);
-
-                    view.setWillNotDraw(false);
-                    if (view instanceof SurfaceView) {
-                        SurfaceView sview = (SurfaceView)view;
-
-                        sview.setZOrderOnTop(false);
-                        sview.setZOrderMediaOverlay(true);
-                    }
-
-                    mPluginContainer.addView(view, lp);
-                    tab.addPluginView(view);
+                PluginLayer layer = (PluginLayer) tab.getPluginLayer(view);
+                if (layer == null) {
+                    layer = new PluginLayer(view, rect, mLayerController.getView().getRenderer().getMaxTextureSize());
+                    tab.addPluginLayer(view, layer);
+                    mLayerController.getView().addLayer(layer);
                 } else {
-                    lp = (PluginLayoutParams)view.getLayoutParams();
-                    lp.reset(x, y, w, h, pluginViewport);
-                    lp.reposition(targetViewport);
-                    try {
-                        mPluginContainer.updateViewLayout(view, lp);
-                        view.setVisibility(View.VISIBLE);
-                    } catch (IllegalArgumentException e) {
-                        Log.i(LOGTAG, "e:" + e);
-                        // it can be the case where we
-                        // get an update before the view
-                        // is actually attached.
-                    }
+                    layer.reset(rect);
+                    layer.setVisible(true);
                 }
             }
         });
     }
 
     void removePluginView(final View view) {
         mMainHandler.post(new Runnable() { 
             public void run() {
-                try {
-                    mPluginContainer.removeView(view);
-
-                    Tabs tabs = Tabs.getInstance();
-                    Tab tab = tabs.getSelectedTab();
-                    if (tab == null)
-                        return;
-
-                    tab.removePluginView(view);
-                } catch (Exception e) {}
+                Tabs tabs = Tabs.getInstance();
+                Tab tab = tabs.getSelectedTab();
+
+                PluginLayer layer = (PluginLayer) tab.removePluginLayer(view);
+                if (layer != null) {
+                    layer.destroy();
+                }
             }
         });
     }
 
     public Surface createSurface() {
         Tabs tabs = Tabs.getInstance();
         Tab tab = tabs.getSelectedTab();
         if (tab == null)
@@ -1414,41 +1387,28 @@ abstract public class GeckoApp
         if (tab == null)
             return;
 
         Layer layer = tab.removePluginLayer(surface);
         hidePluginLayer(layer);
     }
 
     public void showSurface(Surface surface, int x, int y,
-                            int w, int h, boolean inverted, boolean blend,
-                            String metadata) {
+                            int w, int h, boolean inverted, boolean blend) {
         Tabs tabs = Tabs.getInstance();
         Tab tab = tabs.getSelectedTab();
         if (tab == null)
             return;
 
-        ViewportMetrics metrics;
-        try {
-            metrics = new ViewportMetrics(new JSONObject(metadata));
-        } catch (JSONException e) {
-            Log.e(LOGTAG, "Bad viewport metadata: ", e);
-            return;
-        }
-
-        PointF origin = metrics.getOrigin();
-        x = x + (int)origin.x;
-        y = y + (int)origin.y;
-
         LayerView layerView = mLayerController.getView();
         SurfaceTextureLayer layer = (SurfaceTextureLayer)tab.getPluginLayer(surface);
         if (layer == null)
             return;
 
-        layer.update(new Rect(x, y, x + w, y + h), metrics.getZoomFactor(), inverted, blend);
+        layer.update(new Rect(x, y, x + w, y + h), inverted, blend);
         layerView.addLayer(layer);
 
         // FIXME: shouldn't be necessary, layer will request
         // one when it gets first frame
         layerView.requestRender();
     }
     
     private void hidePluginLayer(Layer layer) {
@@ -1475,81 +1435,55 @@ abstract public class GeckoApp
 
         hidePluginLayer(layer);
     }
 
     public void requestRender() {
         mLayerController.getView().requestRender();
     }
 
-    public void hidePlugins(boolean hideLayers) {
+    public void hidePlugins() {
         Tabs tabs = Tabs.getInstance();
         Tab tab = tabs.getSelectedTab();
 
         if (tab == null)
             return;
 
-        hidePlugins(tab, hideLayers);
+        hidePlugins(tab);
     }
-
-    public void hidePlugins(Tab tab, boolean hideLayers) {
-        for (View view : tab.getPluginViews()) {
-            view.setVisibility(View.GONE);
-        }
-
-        if (hideLayers) {
-            for (Layer layer : tab.getPluginLayers()) {
-                hidePluginLayer(layer);
+    
+    public void hidePlugins(Tab tab) {
+        for (Layer layer : tab.getPluginLayers()) {
+            if (layer instanceof PluginLayer) {
+                ((PluginLayer) layer).setVisible(false);
             }
 
-            requestRender();
-        }
-    }
-
-    public void showPlugins() {
-        repositionPluginViews(true);
-    }
-
-    public void showPlugins(Tab tab) {
-        repositionPluginViews(tab, true);
-
-        for (Layer layer : tab.getPluginLayers()) {
-            showPluginLayer(layer);
+            hidePluginLayer(layer);
         }
 
         requestRender();
     }
 
-    public void repositionPluginViews(boolean setVisible) {
+    public void showPlugins() {
         Tabs tabs = Tabs.getInstance();
         Tab tab = tabs.getSelectedTab();
 
-        if (tab == null)
-            return;
-
-        repositionPluginViews(tab, setVisible);
+        showPlugins(tab);
     }
 
-    public void repositionPluginViews(Tab tab, boolean setVisible) {
-        ImmutableViewportMetrics targetViewport = mLayerController.getViewportMetrics();
-
-        if (targetViewport == null)
-            return;
-
-        for (View view : tab.getPluginViews()) {
-            PluginLayoutParams lp = (PluginLayoutParams)view.getLayoutParams();
-            lp.reposition(targetViewport);
-
-            if (setVisible) {
-                view.setVisibility(View.VISIBLE);
+    public void showPlugins(Tab tab) {
+        for (Layer layer : tab.getPluginLayers()) {
+            showPluginLayer(layer);
+
+            if (layer instanceof PluginLayer) {
+                ((PluginLayer) layer).setVisible(true);
             }
-
-            if (mPluginContainer.indexOfChild(view) >= 0)
-                mPluginContainer.updateViewLayout(view, lp);
         }
+
+        requestRender();
     }
 
     public void setFullScreen(final boolean fullscreen) {
         mMainHandler.post(new Runnable() { 
             public void run() {
                 // Hide/show the system notification bar
                 Window window = getWindow();
                 window.setFlags(fullscreen ?
@@ -2141,17 +2075,18 @@ abstract public class GeckoApp
     public void onConfigurationChanged(Configuration newConfig)
     {
         Log.i(LOGTAG, "configuration changed");
 
         super.onConfigurationChanged(newConfig);
 
         if (mOrientation != newConfig.orientation) {
             mOrientation = newConfig.orientation;
-            mFormAssistPopup.hide();
+            if (mFormAssistPopup != null)
+                mFormAssistPopup.hide();
             refreshActionBar();
         }
     }
 
     @Override
     public void onLowMemory()
     {
         Log.e(LOGTAG, "low memory");
@@ -2848,16 +2783,18 @@ abstract public class GeckoApp
         Log.i(LOGTAG, "Sending message to Gecko: " + SystemClock.uptimeMillis() + " - Tab:Add");
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Add", args.toString()));
     }
 
     /* This method is referenced by Robocop via reflection. */
     public GeckoLayerClient getLayerClient() { return mLayerClient; }
     public LayerController getLayerController() { return mLayerController; }
 
+    public AbsoluteLayout getPluginContainer() { return mPluginContainer; }
+
     // accelerometer
     public void onAccuracyChanged(Sensor sensor, int accuracy) {}
 
     public void onSensorChanged(SensorEvent event)
     {
         GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorEvent(event));
     }
 
@@ -2889,89 +2826,9 @@ abstract public class GeckoApp
             public boolean onTouch(View view, MotionEvent event) {
                 if (event == null)
                     return true;
                 GeckoAppShell.sendEventToGecko(GeckoEvent.createMotionEvent(event));
                 return true;
             }
         });
     }
-}
-
-class PluginLayoutParams extends AbsoluteLayout.LayoutParams
-{
-    private static final int MAX_DIMENSION = 2048;
-    private static final String LOGTAG = "GeckoApp.PluginLayoutParams";
-
-    private int mOriginalX;
-    private int mOriginalY;
-    private int mOriginalWidth;
-    private int mOriginalHeight;
-    private ImmutableViewportMetrics mOriginalViewport;
-    private float mLastResolution;
-
-    public PluginLayoutParams(int aX, int aY, int aWidth, int aHeight, ImmutableViewportMetrics aViewport) {
-        super(aWidth, aHeight, aX, aY);
-
-        Log.i(LOGTAG, "Creating plugin at " + aX + ", " + aY + ", " + aWidth + "x" + aHeight + ", (" + (aViewport.zoomFactor * 100) + "%)");
-
-        mOriginalX = aX;
-        mOriginalY = aY;
-        mOriginalWidth = aWidth;
-        mOriginalHeight = aHeight;
-        mOriginalViewport = aViewport;
-        mLastResolution = aViewport.zoomFactor;
-
-        clampToMaxSize();
-    }
-
-    private void clampToMaxSize() {
-        if (width > MAX_DIMENSION || height > MAX_DIMENSION) {
-            if (width > height) {
-                height = (int)(((float)height/(float)width) * MAX_DIMENSION);
-                width = MAX_DIMENSION;
-            } else {
-                width = (int)(((float)width/(float)height) * MAX_DIMENSION);
-                height = MAX_DIMENSION;
-            }
-        }
-    }
-
-    public void reset(int aX, int aY, int aWidth, int aHeight, ImmutableViewportMetrics aViewport) {
-        PointF origin = aViewport.getOrigin();
-
-        this.x = mOriginalX = aX;
-        this.y = mOriginalY = aY;
-        width = mOriginalWidth = aWidth;
-        height = mOriginalHeight = aHeight;
-        mOriginalViewport = aViewport;
-        mLastResolution = aViewport.zoomFactor;
-
-        clampToMaxSize();
-    }
-
-    private void reposition(Point aOffset, float aResolution) {
-        this.x = mOriginalX + aOffset.x;
-        this.y = mOriginalY + aOffset.y;
-
-        if (!FloatUtils.fuzzyEquals(mLastResolution, aResolution)) {
-            width = Math.round(aResolution * mOriginalWidth);
-            height = Math.round(aResolution * mOriginalHeight);
-            mLastResolution = aResolution;
-
-            clampToMaxSize();
-        }
-    }
-
-    public void reposition(ImmutableViewportMetrics viewport) {
-        PointF targetOrigin = viewport.getOrigin();
-        PointF originalOrigin = mOriginalViewport.getOrigin();
-
-        Point offset = new Point(Math.round(originalOrigin.x - targetOrigin.x),
-                                 Math.round(originalOrigin.y - targetOrigin.y));
-
-        reposition(offset, viewport.zoomFactor);
-    }
-
-    public float getLastResolution() {
-        return mLastResolution;
-    }
-}
+}
\ No newline at end of file
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -41,16 +41,18 @@ package org.mozilla.gecko;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.gfx.GeckoLayerClient;
 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 import org.mozilla.gecko.gfx.LayerController;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.gfx.ScreenshotLayer;
 import org.mozilla.gecko.FloatUtils;
+import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
+import org.mozilla.gecko.gfx.ViewportMetrics;
 
 import java.io.*;
 import java.lang.reflect.*;
 import java.nio.*;
 import java.text.*;
 import java.util.*;
 import java.util.zip.*;
 import java.util.concurrent.*;
@@ -67,17 +69,16 @@ import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
 import android.location.*;
 import android.webkit.MimeTypeMap;
 import android.media.MediaScannerConnection;
 import android.media.MediaScannerConnection.MediaScannerConnectionClient;
 import android.provider.Settings;
 import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityEvent;
 import android.opengl.GLES20;
 
 import android.util.*;
 import android.net.Uri;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 
 import android.graphics.Bitmap;
@@ -226,16 +227,18 @@ public class GeckoAppShell
     public static native ByteBuffer allocateDirectBuffer(long size);
     public static native void freeDirectBuffer(ByteBuffer buf);
     public static native void scheduleComposite();
     public static native void schedulePauseComposition();
     public static native void scheduleResumeComposition(int width, int height);
 
     public static native void unlockDatabaseFile(String databasePath);
 
+    public static native SurfaceBits getSurfaceBits(Surface surface);
+
     private static class GeckoMediaScannerClient implements MediaScannerConnectionClient {
         private String mFile = "";
         private String mMimeType = "";
         private MediaScannerConnection mScanner = null;
 
         public GeckoMediaScannerClient(Context aContext, String aFile, String aMimeType) {
             mFile = aFile;
             mMimeType = aMimeType;
@@ -1510,43 +1513,44 @@ public class GeckoAppShell
         }
         catch (Exception e) {
             return true;
         }
     }
 
     public static void addPluginView(View view,
                                      int x, int y,
-                                     int w, int h,
-                                     String metadata)
-    {
-        Log.i(LOGTAG, "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + " metadata: " + metadata);
-        GeckoApp.mAppContext.addPluginView(view, x, y, w, h, metadata);
+                                     int w, int h)
+{
+        ImmutableViewportMetrics pluginViewport;
+
+        Log.i(LOGTAG, "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h);
+        
+        GeckoApp.mAppContext.addPluginView(view, new Rect(x, y, x + w, y + h));
     }
 
     public static void removePluginView(View view) {
         Log.i(LOGTAG, "removePluginView:" + view);
         GeckoApp.mAppContext.removePluginView(view);
     }
 
     public static Surface createSurface() {
         Log.i(LOGTAG, "createSurface");
         return GeckoApp.mAppContext.createSurface();
     }
 
     public static void showSurface(Surface surface,
                                    int x, int y,
                                    int w, int h,
                                    boolean inverted,
-                                   boolean blend,
-                                   String metadata)
+                                   boolean blend)
     {
-        Log.i(LOGTAG, "showSurface:" + surface + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + " inverted: " + inverted + " blend: " + blend + " metadata: " + metadata);
+        Log.i(LOGTAG, "showSurface:" + surface + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + " inverted: " + inverted + " blend: " + blend);
         try {
-            GeckoApp.mAppContext.showSurface(surface, x, y, w, h, inverted, blend, metadata);
+            GeckoApp.mAppContext.showSurface(surface, x, y, w, h, inverted, blend);
         } catch (Exception e) {
             Log.i(LOGTAG, "Error in showSurface:", e);
         }
     }
 
     public static void hideSurface(Surface surface) {
         Log.i(LOGTAG, "hideSurface:" + surface);
         GeckoApp.mAppContext.hideSurface(surface);
@@ -1959,39 +1963,16 @@ public class GeckoAppShell
             // http://developer.android.com/guide/practices/screens_support.html
             if ((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE) {
                 return true;
             }
         }
         return false;
     }
 
-    public static void emitGeckoAccessibilityEvent (int eventType, String[] textList, String description, boolean enabled, boolean checked, boolean password) {
-        AccessibilityManager accessibilityManager =
-            (AccessibilityManager) GeckoApp.mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
-
-        if (!accessibilityManager.isEnabled())
-            return;
-
-        LayerController layerController = GeckoApp.mAppContext.getLayerController();
-        LayerView layerView = layerController.getView();
-
-        AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
-        event.setClassName(layerView.getClass().getName());
-        event.setPackageName(GeckoApp.mAppContext.getPackageName());
-        event.setEnabled(enabled);
-        event.setChecked(checked);
-        event.setPassword(password);
-        event.setContentDescription(description);
-        for (String text: textList)
-            event.getText().add(text);
-
-        accessibilityManager.sendAccessibilityEvent(event);
-    }
-
     public static void viewSizeChanged() {
         if (mInputConnection != null && mInputConnection.isIMEEnabled()) {
             sendEventToGecko(GeckoEvent.createBroadcastEvent("ScrollTo:FocusedInput", ""));
         }
     }
 
     public static double[] getCurrentNetworkInformation() {
         return GeckoNetworkManager.getInstance().getCurrentInformation();
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -105,17 +105,17 @@ FENNEC_JAVA_FILES = \
   ProfileMigrator.java \
   PromptService.java \
   sqlite/ByteBufferInputStream.java \
   sqlite/MatrixBlobCursor.java \
   sqlite/SQLiteBridge.java \
   sqlite/SQLiteBridgeException.java \
   RemoteTabs.java \
   SetupScreen.java \
-  SurfaceLockInfo.java \
+  SurfaceBits.java \
   Tab.java \
   Tabs.java \
   TabsTray.java \
   TabsAccessor.java \
   Telemetry.java \
   gfx/BitmapUtils.java \
   gfx/BufferedCairoImage.java \
   gfx/CairoGLInfo.java \
@@ -130,16 +130,17 @@ FENNEC_JAVA_FILES = \
   gfx/GLController.java \
   gfx/ImmutableViewportMetrics.java \
   gfx/InputConnectionHandler.java \
   gfx/IntSize.java \
   gfx/Layer.java \
   gfx/LayerController.java \
   gfx/LayerRenderer.java \
   gfx/LayerView.java \
+  gfx/PluginLayer.java \
   gfx/NinePatchTileLayer.java \
   gfx/PanningPerfAPI.java \
   gfx/PointUtils.java \
   gfx/RectUtils.java \
   gfx/ScreenshotLayer.java \
   gfx/ScrollbarLayer.java \
   gfx/SingleTileLayer.java \
   gfx/SurfaceTextureLayer.java \
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/SurfaceBits.java
@@ -0,0 +1,10 @@
+package org.mozilla.gecko;
+
+import java.nio.ByteBuffer;
+
+public class SurfaceBits {
+    public int width;
+    public int height;
+    public int format;
+    public ByteBuffer buffer;
+}
deleted file mode 100644
--- a/mobile/android/base/SurfaceLockInfo.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.mozilla.gecko;
-
-import android.graphics.Canvas;
-import java.nio.Buffer;
-
-public class SurfaceLockInfo {
-    public int dirtyTop;
-    public int dirtyLeft;
-    public int dirtyRight;
-    public int dirtyBottom;
-
-    public int bpr;
-    public int format;
-    public int width;
-    public int height;
-    public Buffer buffer;
-    public Canvas canvas;
-}
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -85,17 +85,17 @@ public final class Tab {
     private boolean mExternal;
     private boolean mBookmark;
     private HashMap<String, DoorHanger> mDoorHangers;
     private long mFaviconLoadId;
     private String mDocumentURI;
     private String mContentType;
     private boolean mHasTouchListeners;
     private ArrayList<View> mPluginViews;
-    private HashMap<Surface, Layer> mPluginLayers;
+    private HashMap<Object, Layer> mPluginLayers;
     private ContentResolver mContentResolver;
     private ContentObserver mContentObserver;
     private int mCheckerboardColor = Color.WHITE;
     private int mState;
 
     public static final int STATE_DELAYED = 0;
     public static final int STATE_LOADING = 1;
     public static final int STATE_SUCCESS = 2;
@@ -124,17 +124,17 @@ public final class Tab {
         mHistory = new ArrayList<HistoryEntry>();
         mHistoryIndex = -1;
         mBookmark = false;
         mDoorHangers = new HashMap<String, DoorHanger>();
         mFaviconLoadId = 0;
         mDocumentURI = "";
         mContentType = "";
         mPluginViews = new ArrayList<View>();
-        mPluginLayers = new HashMap<Surface, Layer>();
+        mPluginLayers = new HashMap<Object, Layer>();
         setState(STATE_LOADING);
         mContentResolver = Tabs.getInstance().getContentResolver();
         mContentObserver = new ContentObserver(GeckoAppShell.getHandler()) {
             public void onChange(boolean selfChange) {
                 updateBookmark();
             }
         };
         BrowserDB.registerBookmarkObserver(mContentResolver, mContentObserver);
@@ -546,30 +546,30 @@ public final class Tab {
     public void removePluginView(View view) {
         mPluginViews.remove(view);
     }
 
     public View[] getPluginViews() {
         return mPluginViews.toArray(new View[mPluginViews.size()]);
     }
 
-    public void addPluginLayer(Surface surface, Layer layer) {
-        mPluginLayers.put(surface, layer);
+    public void addPluginLayer(Object surfaceOrView, Layer layer) {
+        mPluginLayers.put(surfaceOrView, layer);
     }
 
-    public Layer getPluginLayer(Surface surface) {
-        return mPluginLayers.get(surface);
+    public Layer getPluginLayer(Object surfaceOrView) {
+        return mPluginLayers.get(surfaceOrView);
     }
 
     public Collection<Layer> getPluginLayers() {
         return mPluginLayers.values();
     }
 
-    public Layer removePluginLayer(Surface surface) {
-        return mPluginLayers.remove(surface);
+    public Layer removePluginLayer(Object surfaceOrView) {
+        return mPluginLayers.remove(surfaceOrView);
     }
 
     public int getCheckerboardColor() {
         return mCheckerboardColor;
     }
 
     /** Sets a new color for the checkerboard. */
     public void setCheckerboardColor(int color) {
--- a/mobile/android/base/Tabs.java
+++ b/mobile/android/base/Tabs.java
@@ -137,17 +137,17 @@ public class Tabs implements GeckoEventL
                     GeckoApp.mBrowserToolbar.setFavicon(tab.getFavicon());
                     GeckoApp.mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
                     GeckoApp.mBrowserToolbar.setProgressVisibility(tab.getState() == Tab.STATE_LOADING);
                     GeckoApp.mDoorHangerPopup.updatePopup();
                     GeckoApp.mBrowserToolbar.setShadowVisibility((url == null) || !url.startsWith("about:"));
                     notifyListeners(tab, TabEvents.SELECTED);
 
                     if (oldTab != null)
-                        GeckoApp.mAppContext.hidePlugins(oldTab, true);
+                        GeckoApp.mAppContext.hidePlugins(oldTab);
                 }
             }
         });
 
         // Pass a message to Gecko to update tab state in BrowserApp
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Selected", String.valueOf(tab.getId())));
         return selectedTab = tab;
     }
@@ -199,17 +199,17 @@ public class Tabs implements GeckoEventL
         int tabId = tab.getId();
         removeTab(tabId);
 
         GeckoApp.mAppContext.mMainHandler.post(new Runnable() { 
             public void run() {
                 notifyListeners(tab, TabEvents.CLOSED);
                 GeckoApp.mBrowserToolbar.updateTabCountAndAnimate(Tabs.getInstance().getCount());
                 GeckoApp.mDoorHangerPopup.updatePopup();
-                GeckoApp.mAppContext.hidePlugins(tab, true);
+                GeckoApp.mAppContext.hidePlugins(tab);
                 tab.onDestroy();
             }
         });
 
         // Pass a message to Gecko to update tab state in BrowserApp
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Closed", String.valueOf(tabId)));
     }
 
--- a/mobile/android/base/db/DBUtils.java
+++ b/mobile/android/base/db/DBUtils.java
@@ -67,28 +67,25 @@ public class DBUtils {
         }
 
         if (!aValues.containsKey(aNewKey)) {
             aValues.put(aNewKey, value);
         }
     }
 
     public static void ensureDatabaseIsNotLocked(SQLiteOpenHelper dbHelper, String databasePath) {
-        SQLiteDatabase db = dbHelper.getWritableDatabase();
-
-        // The returned writable database is read-only, this probably means that the
-        // database is permanently locked due to a crash or a non-clean quit in Fennec.
-        // We can assume it's safe to forcefully unlock the database file in this case
-        // as all database access happens through this content provider (see bug 741718).
-        if (db.isReadOnly()) {
-            // Close read-only connection, we don't want to use it
-            dbHelper.close();
-
-            Log.d(LOGTAG, "Database is in read-only mode, trying to forcefully unlock the database file: " + databasePath);
+        try {
+            dbHelper.getWritableDatabase();
+        } catch (Exception e) {
+            Log.d(LOGTAG, "Database is locked, trying to forcefully unlock the database file: " + databasePath);
 
             // Forcefully unlock the database file
             GeckoAppShell.unlockDatabaseFile(databasePath);
 
-            // TODO: maybe check if the connection is still read-only and let the
+            // This call should not throw if the forced unlocking
+            // actually fixed the situation.
+            dbHelper.getWritableDatabase();
+
+            // TODO: maybe check if the database is still locked and let the
             // user know that the device needs rebooting?
         }
     }
 }
--- a/mobile/android/base/gfx/BufferedCairoImage.java
+++ b/mobile/android/base/gfx/BufferedCairoImage.java
@@ -47,27 +47,22 @@ import java.nio.ByteBuffer;
 public class BufferedCairoImage extends CairoImage {
     private ByteBuffer mBuffer;
     private IntSize mSize;
     private int mFormat;
     private boolean mNeedToFreeBuffer = false;
 
     /** Creates a buffered Cairo image from a byte buffer. */
     public BufferedCairoImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) {
-        mBuffer = inBuffer; mSize = new IntSize(inWidth, inHeight); mFormat = inFormat;
+        setBuffer(inBuffer, inWidth, inHeight, inFormat);
     }
 
     /** Creates a buffered Cairo image from an Android bitmap. */
     public BufferedCairoImage(Bitmap bitmap) {
-        mFormat = CairoUtils.bitmapConfigToCairoFormat(bitmap.getConfig());
-        mSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
-        mNeedToFreeBuffer = true;
-        // XXX Why is this * 4? Shouldn't it depend on mFormat?
-        mBuffer = GeckoAppShell.allocateDirectBuffer(mSize.getArea() * 4);
-        bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
+        setBitmap(bitmap);
     }
 
      protected void finalize() throws Throwable {
         try {
             if (mNeedToFreeBuffer && mBuffer != null)
                 GeckoAppShell.freeDirectBuffer(mBuffer);
             mNeedToFreeBuffer = false;
             mBuffer = null;
@@ -77,10 +72,27 @@ public class BufferedCairoImage extends 
     }
 
    @Override
     public ByteBuffer getBuffer() { return mBuffer; }
     @Override
     public IntSize getSize() { return mSize; }
     @Override
     public int getFormat() { return mFormat; }
+
+
+    public void setBuffer(ByteBuffer buffer, int width, int height, int format) {
+        mBuffer = buffer;
+        mSize = new IntSize(width, height);
+        mFormat = format;
+    }
+
+    public void setBitmap(Bitmap bitmap) {
+        mFormat = CairoUtils.bitmapConfigToCairoFormat(bitmap.getConfig());
+        mSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
+        mNeedToFreeBuffer = true;
+
+        int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat);
+        mBuffer = GeckoAppShell.allocateDirectBuffer(mSize.getArea() * bpp);
+        bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
+    }
 }
 
--- a/mobile/android/base/gfx/DisplayPortCalculator.java
+++ b/mobile/android/base/gfx/DisplayPortCalculator.java
@@ -262,17 +262,17 @@ final class DisplayPortCalculator {
         private final float SIZE_MULTIPLIER;
 
         // If the visible rect is within the danger zone (measured as a fraction of the view size
         // from the edge of the displayport) we start redrawing to minimize checkerboarding.
         private final float DANGER_ZONE_X_MULTIPLIER;
         private final float DANGER_ZONE_Y_MULTIPLIER;
 
         FixedMarginStrategy(Map<String, Integer> prefs) {
-            SIZE_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_FM_MULTIPLIER, 1500);
+            SIZE_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_FM_MULTIPLIER, 2000);
             DANGER_ZONE_X_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_FM_DANGER_X, 100);
             DANGER_ZONE_Y_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_FM_DANGER_Y, 200);
         }
 
         public DisplayPortMetrics calculate(ImmutableViewportMetrics metrics, PointF velocity) {
             float displayPortWidth = metrics.getWidth() * SIZE_MULTIPLIER;
             float displayPortHeight = metrics.getHeight() * SIZE_MULTIPLIER;
 
@@ -335,17 +335,17 @@ final class DisplayPortCalculator {
         //    viewportsize * (base + velocity * incr)
         // where base and incr are configurable values.
         private final float DANGER_ZONE_BASE_X_MULTIPLIER;
         private final float DANGER_ZONE_BASE_Y_MULTIPLIER;
         private final float DANGER_ZONE_INCR_X_MULTIPLIER;
         private final float DANGER_ZONE_INCR_Y_MULTIPLIER;
 
         VelocityBiasStrategy(Map<String, Integer> prefs) {
-            SIZE_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_VB_MULTIPLIER, 1500);
+            SIZE_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_VB_MULTIPLIER, 2000);
             VELOCITY_THRESHOLD = GeckoAppShell.getDpi() * getFloatPref(prefs, PREF_DISPLAYPORT_VB_VELOCITY_THRESHOLD, 32);
             REVERSE_BUFFER = getFloatPref(prefs, PREF_DISPLAYPORT_VB_REVERSE_BUFFER, 200);
             DANGER_ZONE_BASE_X_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_VB_DANGER_X_BASE, 1000);
             DANGER_ZONE_BASE_Y_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_VB_DANGER_Y_BASE, 1000);
             DANGER_ZONE_INCR_X_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_VB_DANGER_X_INCR, 0);
             DANGER_ZONE_INCR_Y_MULTIPLIER = getFloatPref(prefs, PREF_DISPLAYPORT_VB_DANGER_Y_INCR, 0);
         }
 
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -125,16 +125,17 @@ public class GeckoLayerClient implements
         view.setListener(this);
         view.setLayerRenderer(mLayerRenderer);
         layerController.setRoot(mRootLayer);
 
         sendResizeEventIfNecessary(true);
 
         JSONArray prefs = new JSONArray();
         DisplayPortCalculator.addPrefNames(prefs);
+        PluginLayer.addPrefNames(prefs);
         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Preferences:Get", prefs.toString()));
     }
 
     DisplayPortMetrics getDisplayPort() {
         return mDisplayPort;
     }
 
     /* Informs Gecko that the screen size has changed. */
@@ -276,17 +277,17 @@ public class GeckoLayerClient implements
                     } catch (JSONException je) {
                         // the pref value couldn't be parsed as an int. drop this pref
                         // and continue with the rest
                     }
                 }
                 // check return value from setStrategy to make sure that this is the
                 // right batch of prefs, since other java code may also have sent requests
                 // for prefs.
-                if (DisplayPortCalculator.setStrategy(prefValues)) {
+                if (DisplayPortCalculator.setStrategy(prefValues) && PluginLayer.setUsePlaceholder(prefValues)) {
                     GeckoAppShell.unregisterGeckoEventListener("Preferences:Data", this);
                 }
             }
         } catch (JSONException e) {
             Log.e(LOGTAG, "Error decoding JSON in " + event + " handler", e);
         }
     }
 
--- a/mobile/android/base/gfx/Layer.java
+++ b/mobile/android/base/gfx/Layer.java
@@ -50,16 +50,17 @@ import org.mozilla.gecko.FloatUtils;
 public abstract class Layer {
     private final ReentrantLock mTransactionLock;
     private boolean mInTransaction;
     private Rect mNewPosition;
     private float mNewResolution;
 
     protected Rect mPosition;
     protected float mResolution;
+    protected boolean mUsesDefaultProgram = true;
 
     public Layer() {
         this(null);
     }
 
     public Layer(IntSize size) {
         mTransactionLock = new ReentrantLock();
         if (size == null) {
@@ -160,16 +161,20 @@ public abstract class Layer {
      * the reciprocal of the resolution in the layer's transform() function.
      * Only valid inside a transaction. */
     public void setResolution(float newResolution) {
         if (!mInTransaction)
             throw new RuntimeException("setResolution() is only valid inside a transaction");
         mNewResolution = newResolution;
     }
 
+    public boolean usesDefaultProgram() {
+        return mUsesDefaultProgram;
+    }
+
     /**
      * Subclasses may override this method to perform custom layer updates. This will be called
      * with the transaction lock held. Subclass implementations of this method must call the
      * superclass implementation. Returns false if there is still work to be done after this
      * update is complete.
      */
     protected void performUpdates(RenderContext context) {
         if (mNewPosition != null) {
--- a/mobile/android/base/gfx/LayerController.java
+++ b/mobile/android/base/gfx/LayerController.java
@@ -188,17 +188,16 @@ public class LayerController {
     public void scrollBy(PointF point) {
         ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
         PointF origin = viewportMetrics.getOrigin();
         origin.offset(point.x, point.y);
         viewportMetrics.setOrigin(origin);
         mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
 
         notifyLayerClientOfGeometryChange();
-        GeckoApp.mAppContext.repositionPluginViews(false);
         mView.requestRender();
     }
 
     /** Sets the current page size. You must hold the monitor while calling this. */
     public void setPageSize(FloatSize size, FloatSize cssSize) {
         if (mViewportMetrics.getCssPageSize().equals(cssSize))
             return;
 
@@ -220,23 +219,16 @@ public class LayerController {
     /**
      * Sets the entire viewport metrics at once. This function does not notify the layer client or
      * the pan/zoom controller, so you will need to call notifyLayerClientOfGeometryChange() or
      * notifyPanZoomControllerOfGeometryChange() after calling this. You must hold the monitor
      * while calling this.
      */
     public void setViewportMetrics(ViewportMetrics viewport) {
         mViewportMetrics = new ImmutableViewportMetrics(viewport);
-        // this function may or may not be called on the UI thread,
-        // but repositionPluginViews must only be called on the UI thread.
-        GeckoApp.mAppContext.runOnUiThread(new Runnable() {
-            public void run() {
-                GeckoApp.mAppContext.repositionPluginViews(false);
-            }
-        });
         mView.requestRender();
     }
 
     public void setAnimationTarget(ViewportMetrics viewport) {
         if (mLayerClient != null) {
             // We know what the final viewport of the animation is going to be, so
             // immediately request a draw of that area by setting the display port
             // accordingly. This way we should have the content pre-rendered by the
@@ -254,17 +246,16 @@ public class LayerController {
     public void scaleWithFocus(float zoomFactor, PointF focus) {
         ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
         viewportMetrics.scaleTo(zoomFactor, focus);
         mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
 
         // We assume the zoom level will only be modified by the
         // PanZoomController, so no need to notify it of this change.
         notifyLayerClientOfGeometryChange();
-        GeckoApp.mAppContext.repositionPluginViews(false);
         mView.requestRender();
     }
 
     public boolean post(Runnable action) { return mView.post(action); }
 
     /**
      * The view as well as the controller itself use this method to notify the layer client that
      * the geometry changed.
--- a/mobile/android/base/gfx/LayerRenderer.java
+++ b/mobile/android/base/gfx/LayerRenderer.java
@@ -95,16 +95,17 @@ public class LayerRenderer implements GL
     private final NinePatchTileLayer mShadowLayer;
     private TextLayer mFrameRateLayer;
     private final ScrollbarLayer mHorizScrollLayer;
     private final ScrollbarLayer mVertScrollLayer;
     private final FadeRunnable mFadeRunnable;
     private final FloatBuffer mCoordBuffer;
     private RenderContext mLastPageContext;
     private int mMaxTextureSize;
+    private int mBackgroundColor;
 
     private ArrayList<Layer> mExtraLayers = new ArrayList<Layer>();
 
     // Dropped frames display
     private int[] mFrameTimings;
     private int mCurrentFrame, mFrameTimingsSum, mDroppedFrames;
 
     // Render profiling output
@@ -181,22 +182,16 @@ public class LayerRenderer implements GL
             mCheckerboardLayer.invalidate();
         } finally {
             mCheckerboardLayer.endTransaction();
         }
     }
 
     public void resetCheckerboard() {
         mCheckerboardLayer.reset();
-        mCheckerboardLayer.beginTransaction();
-        try {
-            mCheckerboardLayer.invalidate();
-        } finally {
-            mCheckerboardLayer.endTransaction();
-        }
     }
 
     public LayerRenderer(LayerView view) {
         mView = view;
 
         LayerController controller = view.getController();
 
         CairoImage backgroundImage = new BufferedCairoImage(controller.getBackgroundPattern());
@@ -418,30 +413,16 @@ public class LayerRenderer implements GL
                     mFrameRateLayer = TextLayer.create(frameRateLayerSize, "-- ms/--");
                     moveFrameRateLayer(mView.getWidth(), mView.getHeight());
                 }
                 mProfileRender = Log.isLoggable(PROFTAG, Log.DEBUG);
             }
         }).start();
     }
 
-    private void updateCheckerboardImage() {
-        int checkerboardColor = mView.getController().getCheckerboardColor();
-        boolean showChecks = mView.getController().checkerboardShouldShowChecks();
-
-        mCheckerboardLayer.beginTransaction();  // called on compositor thread
-        try {
-            if (mCheckerboardLayer.updateBackground(showChecks, checkerboardColor))
-                mCheckerboardLayer.invalidate();
-        } finally {
-            mCheckerboardLayer.endTransaction();
-        }
-
-    }
-
     /*
      * create a vertex shader type (GLES20.GL_VERTEX_SHADER)
      * or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
      */
     public static int loadShader(int type, String shaderCode) {
         int shader = GLES20.glCreateShader(type);
         GLES20.glShaderSource(shader, shaderCode);
         GLES20.glCompileShader(shader);
@@ -559,17 +540,16 @@ public class LayerRenderer implements GL
                 }
             }
             mLastPageContext = mPageContext;
 
             /* Update layers. */
             if (rootLayer != null) mUpdated &= rootLayer.update(mPageContext);  // called on compositor thread
             mUpdated &= mBackgroundLayer.update(mScreenContext);    // called on compositor thread
             mUpdated &= mShadowLayer.update(mPageContext);  // called on compositor thread
-            updateCheckerboardImage();
             mUpdated &= mCheckerboardLayer.update(mPageContext);   // called on compositor thread
             if (mFrameRateLayer != null) mUpdated &= mFrameRateLayer.update(mScreenContext); // called on compositor thread
             mUpdated &= mVertScrollLayer.update(mPageContext);  // called on compositor thread
             mUpdated &= mHorizScrollLayer.update(mPageContext); // called on compositor thread
 
             for (Layer layer : mExtraLayers)
                 mUpdated &= layer.update(mPageContext); // called on compositor thread
 
@@ -594,71 +574,97 @@ public class LayerRenderer implements GL
             // that edge. This is to avoid drawing thin slivers when masking
             // layers.
             if (mask.top <= 2) {
                 mask.top = -1;
             }
             if (mask.left <= 2) {
                 mask.left = -1;
             }
-            if (mask.right >= mPageRect.right - 2) {
-                mask.right = mPageRect.right + 1;
+
+            // Because we're drawing relative to the page-rect, we only need to
+            // take into account its width and height (and not its origin)
+            int pageRight = mPageRect.width();
+            int pageBottom = mPageRect.height();
+
+            if (mask.right >= pageRight - 2) {
+                mask.right = pageRight + 1;
             }
-            if (mask.bottom >= mPageRect.bottom - 2) {
-                mask.bottom = mPageRect.bottom + 1;
+            if (mask.bottom >= pageBottom - 2) {
+                mask.bottom = pageBottom + 1;
             }
 
             return mask;
         }
 
         /** This function is invoked via JNI; be careful when modifying signature. */
         public void drawBackground() {
+            /* Update background color. */
+            mBackgroundColor = mView.getController().getCheckerboardColor();
+
+            /* Clear to the page background colour. The bits set here need to
+             * match up with those used in gfx/layers/opengl/LayerManagerOGL.cpp.
+             */
+            GLES20.glClearColor(((mBackgroundColor>>16)&0xFF) / 255.0f,
+                                ((mBackgroundColor>>8)&0xFF) / 255.0f,
+                                (mBackgroundColor&0xFF) / 255.0f,
+                                0.0f);
+            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT |
+                           GLES20.GL_DEPTH_BUFFER_BIT);
+
             /* Draw the background. */
             mBackgroundLayer.setMask(mPageRect);
             mBackgroundLayer.draw(mScreenContext);
 
             /* Draw the drop shadow, if we need to. */
             RectF untransformedPageRect = new RectF(0.0f, 0.0f, mPageRect.width(),
                                                     mPageRect.height());
             if (!untransformedPageRect.contains(mView.getController().getViewport()))
                 mShadowLayer.draw(mPageContext);
 
-            /* Find the area the root layer will render into, to mask the checkerboard layer */
-            Rect rootMask = getMaskForLayer(mView.getController().getRoot());
+            /* Draw the 'checkerboard'. We use gfx.show_checkerboard_pattern to
+             * determine whether to draw the screenshot layer.
+             */
+            if (mView.getController().checkerboardShouldShowChecks()) {
+                /* Find the area the root layer will render into, to mask the checkerboard layer */
+                Rect rootMask = getMaskForLayer(mView.getController().getRoot());
+                mCheckerboardLayer.setMask(rootMask);
 
-            /* Draw the checkerboard. */
-            setScissorRect();
-            mCheckerboardLayer.setMask(rootMask);
-            mCheckerboardLayer.draw(mPageContext);
-            GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
+                /* Scissor around the page-rect, in case the page has shrunk
+                 * since the screenshot layer was last updated.
+                 */
+                setScissorRect();
+                mCheckerboardLayer.draw(mPageContext);
+                GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
+            }
         }
 
         // Draws the layer the client added to us.
         void drawRootLayer() {
             Layer rootLayer = mView.getController().getRoot();
             if (rootLayer == null) {
                 return;
             }
 
             rootLayer.draw(mPageContext);
         }
 
         /** This function is invoked via JNI; be careful when modifying signature. */
         public void drawForeground() {
             /* Draw any extra layers that were added (likely plugins) */
             if (mExtraLayers.size() > 0) {
-                // This is a hack. SurfaceTextureLayer draws with its own program, so disable ours here
-                // and re-enable when done. If we end up adding other types of Layer here we'll need
-                // to do something different.
-                deactivateDefaultProgram();
-                
-                for (Layer layer : mExtraLayers)
+                for (Layer layer : mExtraLayers) {
+                    if (!layer.usesDefaultProgram())
+                        deactivateDefaultProgram();
+
                     layer.draw(mPageContext);
 
-                activateDefaultProgram();
+                    if (!layer.usesDefaultProgram())
+                        activateDefaultProgram();
+                }
             }
 
             /* Draw the vertical scrollbar. */
             if (mPageRect.height() > mFrameMetrics.getHeight())
                 mVertScrollLayer.draw(mPageContext);
 
             /* Draw the horizontal scrollbar. */
             if (mPageRect.width() > mFrameMetrics.getWidth())
--- a/mobile/android/base/gfx/NinePatchTileLayer.java
+++ b/mobile/android/base/gfx/NinePatchTileLayer.java
@@ -134,16 +134,19 @@ public class NinePatchTileLayer extends 
         int positionHandle = context.positionHandle;
         int textureHandle = context.textureHandle;
 
         // Make sure we are at position zero in the buffer in case other draw methods did not clean
         // up after themselves
         coordBuffer.position(0);
         coordBuffer.put(coords);
 
+        // Unbind any the current array buffer so we can use client side buffers
+        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+
         // Vertex coordinates are x,y,z starting at position 0 into the buffer.
         coordBuffer.position(0);
         GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer);
 
         // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
         coordBuffer.position(3);
         GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 20, coordBuffer);
 
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/gfx/PluginLayer.java
@@ -0,0 +1,323 @@
+package org.mozilla.gecko.gfx;
+
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.PixelFormat;
+import android.view.View;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.widget.AbsoluteLayout;
+import android.util.Log;
+import android.opengl.GLES20;
+import java.nio.FloatBuffer;
+import java.util.Map;
+import org.json.JSONArray;
+
+import org.mozilla.gecko.FloatUtils;
+import org.mozilla.gecko.SurfaceBits;
+import org.mozilla.gecko.GeckoApp;
+import org.mozilla.gecko.GeckoAppShell;
+
+public class PluginLayer extends TileLayer
+{
+    private static final String LOGTAG = "PluginLayer";
+    private static final String PREF_PLUGIN_USE_PLACEHOLDER = "plugins.use_placeholder";
+
+    private static boolean sUsePlaceholder = true;
+
+    private View mView;
+    private SurfaceView mSurfaceView;
+    private PluginLayoutParams mLayoutParams;
+    private AbsoluteLayout mContainer;
+
+    private boolean mViewVisible;
+    private boolean mShowPlaceholder;
+    private boolean mDestroyed;
+
+    private RectF mLastViewport;
+    private float mLastZoomFactor;
+
+    private ShowViewRunnable mShowViewRunnable;
+
+    private static final float TEXTURE_MAP[] = {
+                0.0f, 1.0f, // top left
+                0.0f, 0.0f, // bottom left
+                1.0f, 1.0f, // top right
+                1.0f, 0.0f, // bottom right
+    };
+
+    public PluginLayer(View view, Rect rect, int maxDimension) {
+        super(new BufferedCairoImage(null, 0, 0, 0), TileLayer.PaintMode.NORMAL);
+
+        mView = view;
+        mContainer = GeckoApp.mAppContext.getPluginContainer();
+        mShowViewRunnable = new ShowViewRunnable(this);
+
+        mView.setWillNotDraw(false);
+        if (mView instanceof SurfaceView) {
+            mSurfaceView = (SurfaceView)view;
+            mSurfaceView.setZOrderOnTop(false);
+            mSurfaceView.setZOrderMediaOverlay(true);
+        }
+
+        mLayoutParams = new PluginLayoutParams(rect, maxDimension);
+    }
+
+    static void addPrefNames(JSONArray prefs) {
+        prefs.put(PREF_PLUGIN_USE_PLACEHOLDER);
+    }
+
+    static boolean setUsePlaceholder(Map<String, Integer> prefs) {
+        Integer usePlaceholder = prefs.get(PREF_PLUGIN_USE_PLACEHOLDER);
+        if (usePlaceholder == null) {
+            return false;
+        }
+
+        sUsePlaceholder = (int)usePlaceholder == 1 ? true : false;
+        Log.i(LOGTAG, "Using plugin placeholder: " + sUsePlaceholder);
+        return true;
+    }
+
+    public void setVisible(boolean newVisible) {
+        if (newVisible && !mShowPlaceholder) {
+            showView();
+        } else {
+            hideView();
+        }
+    }
+
+    private void hideView() {
+        if (mViewVisible) {
+            GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
+                public void run() {
+                    mView.setVisibility(View.GONE);
+                }
+            });
+
+            mViewVisible = false;
+        }
+    }
+
+    private void suspendView() {
+        // Right now we can only show a placeholder ("suspend") a 
+        // SurfaceView plugin (Flash)
+        if (mSurfaceView != null) {
+            hideView();
+
+            GeckoApp.mAppContext.mMainHandler.removeCallbacks(mShowViewRunnable);
+            GeckoApp.mAppContext.mMainHandler.postDelayed(mShowViewRunnable, 250);
+        }
+    }
+
+    public void updateView() {
+        showView(true);
+    }
+
+    public void showView() {
+        showView(false);
+    }
+
+    public void showView(boolean forceUpdate) {
+        if (!mViewVisible || forceUpdate) {
+            GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
+                public void run() {
+                    if (mContainer.indexOfChild(mView) < 0) {
+                        mContainer.addView(mView, mLayoutParams);
+                    } else {
+                        mContainer.updateViewLayout(mView, mLayoutParams);
+                        mView.setVisibility(View.VISIBLE);
+                    }
+                }
+            });
+            mViewVisible = true;
+            mShowPlaceholder = false;
+        }
+    }
+
+    public void destroy() {
+        mDestroyed = true;
+
+        mContainer.removeView(mView);
+        GeckoApp.mAppContext.mMainHandler.removeCallbacks(mShowViewRunnable);
+    }
+
+    public void reset(Rect rect) {
+        mLayoutParams.reset(rect);
+    }
+
+    @Override
+    protected void performUpdates(RenderContext context) {
+        if (mDestroyed)
+            return;
+
+        if (!RectUtils.fuzzyEquals(context.viewport, mLastViewport) ||
+            !FloatUtils.fuzzyEquals(context.zoomFactor, mLastZoomFactor)) {
+
+            // Viewport has changed from the last update
+            
+            if (mLastViewport != null && mSurfaceView != null && !mShowPlaceholder && sUsePlaceholder) {
+                // We have a SurfaceView that we can snapshot for a placeholder, and we are
+                // not currently showing a placeholder.
+
+                Surface surface = mSurfaceView.getHolder().getSurface();
+                SurfaceBits bits = GeckoAppShell.getSurfaceBits(surface);
+                if (bits != null) {
+                    int cairoFormat = -1;
+                    switch (bits.format) {
+                    case PixelFormat.RGBA_8888:
+                        cairoFormat = CairoImage.FORMAT_ARGB32;
+                        break;
+                    case PixelFormat.RGB_565:
+                        cairoFormat = CairoImage.FORMAT_RGB16_565;
+                        break;
+                    default:
+                        Log.w(LOGTAG, "Unable to handle format " + bits.format);
+                        break;
+                    }
+
+                    if (cairoFormat >= 0) {
+                        BufferedCairoImage image = (BufferedCairoImage)mImage;
+                        image.setBuffer(bits.buffer, bits.width, bits.height, cairoFormat);
+
+                        mPosition = new Rect(mLayoutParams.x, mLayoutParams.y, mLayoutParams.x + bits.width, mLayoutParams.y + bits.height);
+                        mPosition.offset(Math.round(mLastViewport.left), Math.round(mLastViewport.top));
+
+                        mResolution = mLastZoomFactor;
+
+                        // We've uploaded the snapshot to the texture now (or will in super.performUpdates)
+                        // so we can draw the placeholder
+                        mShowPlaceholder = true;
+                        super.performUpdates(context);
+                    }
+                }
+            }
+
+            mLastZoomFactor = context.zoomFactor;
+            mLastViewport = context.viewport;
+            mLayoutParams.reposition(context.viewport, context.zoomFactor);
+
+            if (mShowPlaceholder) {
+                suspendView();
+            } else {
+                // We aren't showing the placeholder so we need to update the view position immediately
+                updateView();
+            }
+        }
+    }
+
+    @Override
+    public void draw(RenderContext context) {
+        if (!mShowPlaceholder || mDestroyed || !initialized())
+            return;
+
+        RectF bounds;
+        Rect position = getPosition();
+        RectF viewport = context.viewport;
+
+        bounds = getBounds(context);
+
+        float height = mLayoutParams.height;
+        float left = bounds.left - viewport.left;
+        float top = viewport.height() - (bounds.top + height - viewport.top);
+
+        float[] coords = {
+            //x, y, z, texture_x, texture_y
+            left/viewport.width(), top/viewport.height(), 0,
+            0.0f, mLayoutParams.height / bounds.height(),
+
+            left/viewport.width(), (top+height)/viewport.height(), 0,
+            0.0f, 0.0f,
+
+            (left+mLayoutParams.width)/viewport.width(), top/viewport.height(), 0,
+            mLayoutParams.width / bounds.width(), mLayoutParams.height / bounds.height(),
+
+            (left+mLayoutParams.width)/viewport.width(), (top+height)/viewport.height(), 0,
+            mLayoutParams.width / bounds.width(), 0.0f
+        };
+
+        FloatBuffer coordBuffer = context.coordBuffer;
+        int positionHandle = context.positionHandle;
+        int textureHandle = context.textureHandle;
+
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTextureID());
+
+        // Make sure we are at position zero in the buffer
+        coordBuffer.position(0);
+        coordBuffer.put(coords);
+
+        // Unbind any the current array buffer so we can use client side buffers
+        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+
+        // Vertex coordinates are x,y,z starting at position 0 into the buffer.
+        coordBuffer.position(0);
+        GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer);
+
+        // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
+        coordBuffer.position(3);
+        GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 20, coordBuffer);
+        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+    }
+
+    class PluginLayoutParams extends AbsoluteLayout.LayoutParams
+    {
+        private static final String LOGTAG = "GeckoApp.PluginLayoutParams";
+
+        private RectF mRect;
+        private int mMaxDimension;
+        private float mLastResolution;
+
+        public PluginLayoutParams(Rect rect, int maxDimension) {
+            super(0, 0, 0, 0);
+
+            mMaxDimension = maxDimension;
+            reset(rect);
+        }
+
+        private void clampToMaxSize() {
+            if (width > mMaxDimension || height > mMaxDimension) {
+                if (width > height) {
+                    height = Math.round(((float)height/(float)width) * mMaxDimension);
+                    width = mMaxDimension;
+                } else {
+                    width = Math.round(((float)width/(float)height) * mMaxDimension);
+                    height = mMaxDimension;
+                }
+            }
+        }
+
+        public void reset(Rect rect) {
+            mRect = new RectF(rect);
+        }
+
+        public void reposition(RectF viewport, float zoomFactor) {
+
+            RectF scaled = RectUtils.scale(mRect, zoomFactor);
+
+            this.x = Math.round(scaled.left - viewport.left);
+            this.y = Math.round(scaled.top - viewport.top);
+
+            if (!FloatUtils.fuzzyEquals(mLastResolution, zoomFactor)) {
+                width = Math.round(mRect.width() * zoomFactor);
+                height = Math.round(mRect.height() * zoomFactor);
+                mLastResolution = zoomFactor;
+
+                clampToMaxSize();
+            }
+        }
+    }
+
+    class ShowViewRunnable implements Runnable {
+
+        private PluginLayer mLayer;
+
+        public ShowViewRunnable(PluginLayer layer) {
+            mLayer = layer;
+        }
+
+        public void run() {
+            mLayer.showView();
+        }
+    }
+}
--- a/mobile/android/base/gfx/RectUtils.java
+++ b/mobile/android/base/gfx/RectUtils.java
@@ -132,14 +132,19 @@ public final class RectUtils {
     public static RectF interpolate(RectF from, RectF to, float t) {
         return new RectF(FloatUtils.interpolate(from.left, to.left, t),
                          FloatUtils.interpolate(from.top, to.top, t),
                          FloatUtils.interpolate(from.right, to.right, t),
                          FloatUtils.interpolate(from.bottom, to.bottom, t));
     }
 
     public static boolean fuzzyEquals(RectF a, RectF b) {
-        return FloatUtils.fuzzyEquals(a.top, b.top)
-            && FloatUtils.fuzzyEquals(a.left, b.left)
-            && FloatUtils.fuzzyEquals(a.right, b.right)
-            && FloatUtils.fuzzyEquals(a.bottom, b.bottom);
+        if (a == null && b == null)
+            return true;
+        else if ((a == null && b != null) || (a != null && b == null))
+            return false;
+        else
+            return FloatUtils.fuzzyEquals(a.top, b.top)
+                && FloatUtils.fuzzyEquals(a.left, b.left)
+                && FloatUtils.fuzzyEquals(a.right, b.right)
+                && FloatUtils.fuzzyEquals(a.bottom, b.bottom);
     }
 }
--- a/mobile/android/base/gfx/ScreenshotLayer.java
+++ b/mobile/android/base/gfx/ScreenshotLayer.java
@@ -28,54 +28,42 @@ import java.nio.FloatBuffer;
 public class ScreenshotLayer extends SingleTileLayer {
     private static final int SCREENSHOT_SIZE_LIMIT = 1048576;
     private ScreenshotImage mImage;
     // Size of the image buffer
     private IntSize mBufferSize;
     // The size of the bitmap painted in the buffer
     // (may be smaller than mBufferSize due to power of 2 padding)
     private IntSize mImageSize;
-    // Special case to show the page background color prior to painting a screenshot
-    private boolean mIsSingleColor = true;
-    // Force single color, needed for testing
-    private boolean mForceSingleColor = false;
-    // Cache the passed in background color to determine if we need to update
-    // initialized to 0 so it lets the code run to set it to white on init
-    private int mCurrentBackgroundColor = 0;
+    // Whether we have an up-to-date image to draw
+    private boolean mHasImage;
 
     public static int getMaxNumPixels() {
         return SCREENSHOT_SIZE_LIMIT;
     }
 
     public void reset() {
-        mIsSingleColor = true;
-        updateBackground(mForceSingleColor, Color.WHITE);
-        setPaintMode(TileLayer.PaintMode.STRETCH);
+        mHasImage = false;
     }
 
     void setBitmap(Bitmap bitmap) {
-        if (mForceSingleColor)
-            return;
         mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
         int width = IntSize.nextPowerOfTwo(bitmap.getWidth());
         int height = IntSize.nextPowerOfTwo(bitmap.getHeight());
         mBufferSize = new IntSize(width, height);
         mImage.setBitmap(bitmap, width, height, CairoImage.FORMAT_RGB16_565);
-        mIsSingleColor = false;
-        setPaintMode(TileLayer.PaintMode.NORMAL);
+        mHasImage = true;
     }
 
     public void updateBitmap(Bitmap bitmap, float x, float y, float width, float height) {
         mImage.updateBitmap(bitmap, x, y, width, height);
     }
 
     public static ScreenshotLayer create() {
-        // 3 x 3 min for the single color case. Less than 3x3 will blend 
-        // the colors from outside this single color block when scaled
-        return ScreenshotLayer.create(new IntSize(3, 3));
+        return ScreenshotLayer.create(new IntSize(4, 4));
     }
 
     public static ScreenshotLayer create(IntSize size) {
         Bitmap bitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.RGB_565);
         ScreenshotLayer sl = create(bitmap);
         sl.reset();
         return sl;
     }
@@ -87,68 +75,30 @@ public class ScreenshotLayer extends Sin
         // construct the screenshot layer
         ScreenshotLayer sl =  new ScreenshotLayer(new ScreenshotImage(buffer, size.width, size.height, CairoImage.FORMAT_RGB16_565), size);
         // paint the passed in bitmap into the buffer
         sl.setBitmap(bitmap);
         return sl;
     }
 
     private ScreenshotLayer(ScreenshotImage image, IntSize size) {
-        super(image, TileLayer.PaintMode.STRETCH);
+        super(image, TileLayer.PaintMode.NORMAL);
         mBufferSize = size;
         mImage = image;
     }
 
-    public boolean updateBackground(boolean showChecks, int color) {
-        if (!showChecks) {
-            mIsSingleColor = true;
-            mForceSingleColor = true;
-        } else {
-            mForceSingleColor = false;
-        }
-
-        if (!mIsSingleColor || color == mCurrentBackgroundColor)
-            return false;
-
-        mCurrentBackgroundColor = color;
-
-        /* mask each component of the 8888 color and bit shift to least 
-         * sigificant. Then for red and blue multiply by (2^5 -1) and (2^6 - 1)
-         * for green. Finally, divide by (2^8 - 1) for all color values. This
-         * scales the 8 bit color values to 5 or 6 bits
-         */
-        int red =   ((color & 0x00FF0000 >> 16)* 31 / 255);
-        int green = ((color & 0x0000FF00 >> 8) * 63 / 255);
-        int blue =   (color & 0x000000FF) * 31 / 255;
-        /* For the first byte left shift red by 3 positions such that it is the
-         * top 5 bits, right shift green by 3 so its 3 most significant are the
-         * 3 least significant. For the second byte, left shift green by 3 so 
-         * its 3 least significant bits are the 3 most significant bits of the
-         * byte. Finally, set the 5 least significant bits to blue's value. 
-         */
-        byte byte1 = (byte)((red << 3 | green >> 3) & 0x0000FFFF);
-        byte byte2 = (byte)((green << 5 | blue) & 0x0000FFFF);
-        mImage.mBuffer.put(1, byte1);
-        mImage.mBuffer.put(0, byte2);
-        mImage.mBuffer.put(3, byte1);
-        mImage.mBuffer.put(2, byte2);
-        mImage.mBuffer.put(5, byte1);
-        mImage.mBuffer.put(4, byte2);
-        mImage.mBuffer.put(mImageSize.width + 1, byte1);
-        mImage.mBuffer.put(mImageSize.width + 0, byte2);
-        mImage.mBuffer.put(mImageSize.width + 3, byte1);
-        mImage.mBuffer.put(mImageSize.width + 2, byte2);
-        mImage.mBuffer.put(mImageSize.width + 5, byte1);
-        mImage.mBuffer.put(mImageSize.width + 4, byte2);
-        return true;
+    @Override
+    public void draw(RenderContext context) {
+        if (mHasImage)
+            super.draw(context);
     }
 
     /** A Cairo image that simply saves a buffer of pixel data. */
     static class ScreenshotImage extends CairoImage {
-        ByteBuffer mBuffer;
+        private ByteBuffer mBuffer;
         private IntSize mSize;
         private int mFormat;
 
         /** Creates a buffered Cairo image from a byte buffer. */
         public ScreenshotImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) {
             mBuffer = inBuffer; mSize = new IntSize(inWidth, inHeight); mFormat = inFormat;
         }
 
--- a/mobile/android/base/gfx/ScrollbarLayer.java
+++ b/mobile/android/base/gfx/ScrollbarLayer.java
@@ -302,16 +302,19 @@ public class ScrollbarLayer extends Tile
         int positionHandle = mPositionHandle;
         int textureHandle = mTextureHandle;
 
         // Make sure we are at position zero in the buffer in case other draw methods did not
         // clean up after themselves
         coordBuffer.position(0);
         coordBuffer.put(bodyCoords);
 
+        // Unbind any the current array buffer so we can use client side buffers
+        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+
         // Vertex coordinates are x,y,z starting at position 0 into the buffer.
         coordBuffer.position(0);
         GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20,
                 coordBuffer);
 
         // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
         coordBuffer.position(3);
         GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 20,
--- a/mobile/android/base/gfx/SingleTileLayer.java
+++ b/mobile/android/base/gfx/SingleTileLayer.java
@@ -159,16 +159,19 @@ public class SingleTileLayer extends Til
             int textureHandle = context.textureHandle;
 
             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTextureID());
 
             // Make sure we are at position zero in the buffer
             coordBuffer.position(0);
             coordBuffer.put(coords);
 
+            // Unbind any the current array buffer so we can use client side buffers
+            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+
             // Vertex coordinates are x,y,z starting at position 0 into the buffer.
             coordBuffer.position(0);
             GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer);
 
             // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
             coordBuffer.position(3);
             GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 20, coordBuffer);
             GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
--- a/mobile/android/base/gfx/SurfaceTextureLayer.java
+++ b/mobile/android/base/gfx/SurfaceTextureLayer.java
@@ -56,16 +56,18 @@ public class SurfaceTextureLayer extends
     private static final int LOCAL_GL_TEXTURE_EXTERNAL_OES = 0x00008d65; // This is only defined in API level 15 for some reason (Android 4.0.3)
 
     private final SurfaceTexture mSurfaceTexture;
     private final Surface mSurface;
     private int mTextureId;
     private boolean mHaveFrame;
     private float[] mTextureTransform = new float[16];
 
+    private Rect mPageRect;
+
     private boolean mInverted;
     private boolean mNewInverted;
     private boolean mBlend;
     private boolean mNewBlend;
 
     private static int mProgram;
     private static int mPositionHandle;
     private static int mTextureHandle;
@@ -115,16 +117,19 @@ public class SurfaceTextureLayer extends
                 1.0f, 1.0f, // top right
     };
 
     private SurfaceTextureLayer(int textureId) {
         mTextureId = textureId;
         mHaveFrame = true;
         mInverted = false;
 
+        // We have our own special shaders necessary for rendering the SurfaceTexture
+        this.mUsesDefaultProgram = false;
+
         mSurfaceTexture = new SurfaceTexture(mTextureId);
         mSurfaceTexture.setOnFrameAvailableListener(this);
 
         Surface tmp = null;
         try {
             tmp = Surface.class.getConstructor(SurfaceTexture.class).newInstance(mSurfaceTexture); }
         catch (Exception ie) {
             Log.e(LOGTAG, "error constructing the surface", ie);
@@ -142,21 +147,20 @@ public class SurfaceTextureLayer extends
     }
 
     // For SurfaceTexture.OnFrameAvailableListener
     public void onFrameAvailable(SurfaceTexture texture) {
         mHaveFrame = true;
         GeckoApp.mAppContext.requestRender();
     }
 
-    public void update(Rect position, float resolution, boolean inverted, boolean blend) {
-        beginTransaction(); // this is called on the Gecko thread
+    public void update(Rect rect, boolean inverted, boolean blend) {
+        beginTransaction();
 
-        setPosition(position);
-        setResolution(resolution);
+        setPosition(rect);
 
         mNewInverted = inverted;
         mNewBlend = blend;
 
         endTransaction();
     }
 
     @Override
@@ -234,17 +238,16 @@ public class SurfaceTextureLayer extends
         float viewWidth = viewport.width();
         float viewHeight = viewport.height();
 
         float top = viewHeight - rect.top;
         float bot = viewHeight - rect.bottom;
 
         float[] textureCoords = mInverted ? TEXTURE_MAP_INVERTED : TEXTURE_MAP;
 
-        // Coordinates for the scrollbar's body combined with the texture coordinates
         float[] coords = {
             // x, y, z, texture_x, texture_y
             rect.left/viewWidth, bot/viewHeight, 0,
             textureCoords[0], textureCoords[1],
 
             rect.left/viewWidth, (bot+rect.height())/viewHeight, 0,
             textureCoords[2], textureCoords[3],
 
@@ -265,31 +268,35 @@ public class SurfaceTextureLayer extends
         GLES20.glUniformMatrix4fv(mProjectionMatrixHandle, 1, false, PROJECTION_MATRIX, 0);
 
         // Enable the arrays from which we get the vertex and texture coordinates
         GLES20.glEnableVertexAttribArray(mPositionHandle);
         GLES20.glEnableVertexAttribArray(mTextureHandle);
 
         GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
         GLES20.glUniform1i(mSampleHandle, 0);
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
         GLES20.glBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureId);
       
         mSurfaceTexture.updateTexImage();
         mSurfaceTexture.getTransformMatrix(mTextureTransform);
 
         GLES20.glUniformMatrix4fv(mTextureMatrixHandle, 1, false, mTextureTransform, 0);
 
+        // Unbind any the current array buffer so we can use client side buffers
+        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
+        
         // Vertex coordinates are x,y,z starting at position 0 into the buffer.
         coordBuffer.position(0);
         GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 20,
                 coordBuffer);
 
         // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
         coordBuffer.position(3);
-        GLES20.glVertexAttribPointer(mTextureHandle, 3, GLES20.GL_FLOAT, false, 20,
+        GLES20.glVertexAttribPointer(mTextureHandle, 2, GLES20.GL_FLOAT, false, 20,
                 coordBuffer);
 
         if (mBlend) {
             GLES20.glEnable(GLES20.GL_BLEND);
             GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
         }
         
         GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
--- a/mobile/android/base/gfx/TileLayer.java
+++ b/mobile/android/base/gfx/TileLayer.java
@@ -52,20 +52,21 @@ import java.nio.FloatBuffer;
 /**
  * Base class for tile layers, which encapsulate the logic needed to draw textured tiles in OpenGL
  * ES.
  */
 public abstract class TileLayer extends Layer {
     private static final String LOGTAG = "GeckoTileLayer";
 
     private final Rect mDirtyRect;
-    private final CairoImage mImage;
     private IntSize mSize;
     private int[] mTextureIDs;
 
+    protected final CairoImage mImage;
+
     public enum PaintMode { NORMAL, REPEAT, STRETCH };
     private PaintMode mPaintMode;
 
     public TileLayer(CairoImage image, PaintMode paintMode) {
         super(image.getSize());
 
         mPaintMode = paintMode;
         mImage = image;
--- a/mobile/android/base/ui/PanZoomController.java
+++ b/mobile/android/base/ui/PanZoomController.java
@@ -364,17 +364,16 @@ public class PanZoomController
             return false;
 
         case TOUCHING:
             if (panDistance(event) < PAN_THRESHOLD) {
                 return false;
             }
             cancelTouch();
             startPanning(event.getX(0), event.getY(0), event.getEventTime());
-            GeckoApp.mAppContext.hidePlugins(false /* don't hide layers */);
             GeckoApp.mFormAssistPopup.hide();
             track(event);
             return true;
 
         case PANNING_HOLD_LOCKED:
             GeckoApp.mFormAssistPopup.hide();
             mState = PanZoomState.PANNING_LOCKED;
             // fall through
@@ -559,18 +558,16 @@ public class PanZoomController
 
     /* Starts the fling or bounce animation. */
     private void startAnimationTimer(final AnimationRunnable runnable) {
         if (mAnimationTimer != null) {
             Log.e(LOGTAG, "Attempted to start a new fling without canceling the old one!");
             stopAnimationTimer();
         }
 
-        GeckoApp.mAppContext.hidePlugins(false /* don't hide layers */);
-
         mAnimationTimer = new Timer("Animation Timer");
         mAnimationRunnable = runnable;
         mAnimationTimer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() { mController.post(runnable); }
         }, 0, 1000L/60L);
     }
 
@@ -579,18 +576,16 @@ public class PanZoomController
         if (mAnimationTimer != null) {
             mAnimationTimer.cancel();
             mAnimationTimer = null;
         }
         if (mAnimationRunnable != null) {
             mAnimationRunnable.terminate();
             mAnimationRunnable = null;
         }
-
-        GeckoApp.mAppContext.showPlugins();
     }
 
     private float getVelocity() {
         float xvel = mX.getRealVelocity();
         float yvel = mY.getRealVelocity();
         return FloatMath.sqrt(xvel * xvel + yvel * yvel);
     }
 
@@ -756,17 +751,16 @@ public class PanZoomController
 
     private void finishAnimation() {
         checkMainThread();
 
         Log.d(LOGTAG, "Finishing animation at " + mController.getViewportMetrics());
         stopAnimationTimer();
 
         // Force a viewport synchronisation
-        GeckoApp.mAppContext.showPlugins();
         mController.setForceRedraw();
         mController.notifyLayerClientOfGeometryChange();
     }
 
     /* Returns the nearest viewport metrics with no overscroll visible. */
     private ViewportMetrics getValidViewportMetrics() {
         return getValidViewportMetrics(new ViewportMetrics(mController.getViewportMetrics()));
     }
@@ -840,17 +834,16 @@ public class PanZoomController
     public boolean onScaleBegin(SimpleScaleGestureDetector detector) {
         Log.d(LOGTAG, "onScaleBegin in " + mState);
 
         if (mState == PanZoomState.ANIMATED_ZOOM)
             return false;
 
         mState = PanZoomState.PINCHING;
         mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
-        GeckoApp.mAppContext.hidePlugins(false /* don't hide layers, only views */);
         GeckoApp.mFormAssistPopup.hide();
         cancelTouch();
 
         return true;
     }
 
     @Override
     public boolean onScale(SimpleScaleGestureDetector detector) {
@@ -908,17 +901,16 @@ public class PanZoomController
 
         if (mState == PanZoomState.ANIMATED_ZOOM)
             return;
 
         // switch back to the touching state
         startTouch(detector.getFocusX(), detector.getFocusY(), detector.getEventTime());
 
         // Force a viewport synchronisation
-        GeckoApp.mAppContext.showPlugins();
         mController.setForceRedraw();
         mController.notifyLayerClientOfGeometryChange();
     }
 
     public boolean getRedrawHint() {
         switch (mState) {
             case PINCHING:
             case ANIMATED_ZOOM:
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -148,17 +148,19 @@ var Strings = {};
   let [name, bundle] = aStringBundle;
   XPCOMUtils.defineLazyGetter(Strings, name, function() {
     return Services.strings.createBundle(bundle);
   });
 });
 
 var MetadataProvider = {
   getDrawMetadata: function getDrawMetadata() {
-    return JSON.stringify(BrowserApp.selectedTab.getViewport());
+    let viewport = BrowserApp.selectedTab.getViewport();
+    viewport.zoom = BrowserApp.selectedTab._drawZoom;
+    return JSON.stringify(viewport);
   },
 };
 
 var BrowserApp = {
   _tabs: [],
   _selectedTab: null,
 
   deck: null,
@@ -1891,17 +1893,17 @@ Tab.prototype = {
       height: gScreenHeight,
       cssWidth: gScreenWidth / this._zoom,
       cssHeight: gScreenHeight / this._zoom,
       pageWidth: gScreenWidth,
       pageHeight: gScreenHeight,
       // We make up matching css page dimensions
       cssPageWidth: gScreenWidth / this._zoom,
       cssPageHeight: gScreenHeight / this._zoom,
-      zoom: this._zoom
+      zoom: this._zoom,
     };
 
     // Set the viewport offset to current scroll offset
     viewport.cssX = this.browser.contentWindow.scrollX || 0;
     viewport.cssY = this.browser.contentWindow.scrollY || 0;
 
     // Transform coordinates based on zoom
     viewport.x = Math.round(viewport.cssX * viewport.zoom);
@@ -4741,18 +4743,19 @@ var ActivityObserver = {
       case "application-background" :
         isForeground = false;
         break;
       case "application-foreground" :
         isForeground = true;
         break;
     }
 
-    if (BrowserApp.selectedTab.getActive() != isForeground) {
-      BrowserApp.selectedTab.setActive(isForeground);
+    let tab = BrowserApp.selectedTab;
+    if (tab && tab.getActive() != isForeground) {
+      tab.setActive(isForeground);
     }
   }
 };
 
 var WebappsUI = {
   init: function() {
     Cu.import("resource://gre/modules/Webapps.jsm");
 
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -345,16 +345,17 @@ SHELL_WRAPPER7(notifyGetSms, jint, jstri
 SHELL_WRAPPER3(notifyGetSmsFailed, jint, jint, jlong)
 SHELL_WRAPPER3(notifySmsDeleted, jboolean, jint, jlong)
 SHELL_WRAPPER3(notifySmsDeleteFailed, jint, jint, jlong)
 SHELL_WRAPPER2(notifyNoMessageInList, jint, jlong)
 SHELL_WRAPPER8(notifyListCreated, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
 SHELL_WRAPPER7(notifyGotNextMessage, jint, jstring, jstring, jstring, jlong, jint, jlong)
 SHELL_WRAPPER3(notifyReadingMessageListFailed, jint, jint, jlong)
 SHELL_WRAPPER2(notifyFilePickerResult, jstring, jlong)
+SHELL_WRAPPER1_WITH_RETURN(getSurfaceBits, jobject, jobject)
 
 static void * xul_handle = NULL;
 static void * sqlite_handle = NULL;
 static void * nss_handle = NULL;
 static void * nspr_handle = NULL;
 static void * plc_handle = NULL;
 static bool simple_linker_initialized = false;
 
@@ -761,16 +762,17 @@ loadGecko