Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Tue, 21 Aug 2012 15:59:12 -0700
changeset 104893 c797118c02a869e2eda77a380f0f646b84fe6679
parent 104506 32dd9f9afa382cc0b340f78837dd117b3a80ad63 (current diff)
parent 104892 9315dc9bb36f4c0c7c11f4eb639861b272645fa8 (diff)
child 104894 d6599c909132ffa2e368233d7cc730d8137ef9bc
push id45
push usershu@rfrn.org
push dateThu, 23 Aug 2012 00:57:43 +0000
milestone17.0a1
Merge from mozilla-central.
accessible/src/html/HTMLTableAccessible.cpp
b2g/chrome/jar.mn
browser/app/profile/firefox.js
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/jar.mn
browser/components/sessionstore/test/Makefile.in
browser/locales/en-US/chrome/browser/browser.properties
browser/themes/winstripe/browser.css
caps/include/nsPrincipal.h
caps/src/nsNullPrincipal.cpp
caps/src/nsPrincipal.cpp
caps/src/nsScriptSecurityManager.cpp
caps/src/nsSystemPrincipal.cpp
configure.in
content/base/public/nsContentUtils.h
content/base/public/nsDeprecatedOperationList.h
content/base/public/nsIDocument.h
content/base/public/nsLineBreaker.h
content/base/src/Makefile.in
content/base/src/nsContentSink.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsCrossSiteListenerProxy.cpp
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsGkAtomList.h
content/base/src/nsLineBreaker.cpp
content/base/src/nsNodeInfo.cpp
content/base/src/nsNodeInfo.h
content/base/src/nsNodeInfoManager.cpp
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsObjectLoadingContent.h
content/base/src/nsScriptLoader.cpp
content/base/src/nsXMLHttpRequest.cpp
content/canvas/src/WebGLContext.cpp
content/canvas/test/test_canvas.html
content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
content/events/src/nsDOMPopupBlockedEvent.cpp
content/events/src/nsDOMPopupBlockedEvent.h
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventStateManager.cpp
content/events/src/nsEventStateManager.h
content/events/src/nsIMEStateManager.cpp
content/events/test/Makefile.in
content/events/test/test_bug422132.html
content/html/content/public/nsHTMLMediaElement.h
content/html/content/src/nsHTMLCanvasElement.cpp
content/html/content/src/nsHTMLFormElement.cpp
content/html/content/src/nsHTMLIFrameElement.cpp
content/html/content/src/nsHTMLInputElement.cpp
content/html/content/src/nsHTMLInputElement.h
content/html/content/src/nsHTMLMediaElement.cpp
content/html/content/src/nsHTMLVideoElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/media/MediaResource.cpp
content/media/MediaResource.h
content/media/nsAudioStream.cpp
content/media/nsBuiltinDecoder.cpp
content/media/nsBuiltinDecoder.h
content/media/nsBuiltinDecoderReader.cpp
content/media/nsBuiltinDecoderReader.h
content/media/nsBuiltinDecoderStateMachine.cpp
content/media/nsBuiltinDecoderStateMachine.h
content/media/nsMediaDecoder.h
content/media/ogg/nsOggDecoderStateMachine.cpp
content/media/ogg/nsOggDecoderStateMachine.h
content/media/ogg/nsOggReader.cpp
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLPrototypeHandler.cpp
content/xbl/src/nsXBLService.cpp
content/xml/document/src/nsXMLContentSink.cpp
content/xml/document/src/nsXMLDocument.cpp
content/xul/document/src/nsXULDocument.cpp
content/xul/templates/src/nsXULTemplateBuilder.cpp
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/test/browser/browser_bug435325.js
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/base/nsPluginArray.cpp
dom/bluetooth/BluetoothDeviceEvent.cpp
dom/bluetooth/BluetoothDeviceEvent.h
dom/indexedDB/IDBTransaction.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PBrowser.ipdl
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/locales/en-US/chrome/dom/dom.properties
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginsDirUnix.cpp
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/test/reftest/reftest.list
dom/src/jsurl/nsJSProtocolHandler.cpp
dom/wifi/WifiWorker.js
dom/workers/ScriptLoader.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/XMLHttpRequest.cpp
editor/composer/src/nsComposerDocumentCommands.cpp
editor/composer/src/nsEditingSession.cpp
editor/libeditor/html/nsHTMLEditor.cpp
embedding/android/GeckoAppShell.java
embedding/android/GeckoSurfaceView.java
embedding/browser/webBrowser/nsWebBrowserContentPolicy.cpp
embedding/components/windowwatcher/src/nsWindowWatcher.cpp
embedding/components/windowwatcher/src/nsWindowWatcher.h
extensions/permissions/nsContentBlocker.cpp
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderGLX.cpp
gfx/gl/GLXLibrary.h
gfx/harfbuzz/src/hb-fallback-shape-private.hh
gfx/harfbuzz/src/hb-graphite2-private.hh
gfx/harfbuzz/src/hb-ot-shape.cc
gfx/harfbuzz/src/hb-ot-shape.h
gfx/harfbuzz/src/hb-uniscribe-private.hh
gfx/layers/ImageLayers.h
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicBuffers.h
gfx/layers/basic/BasicCanvasLayer.cpp
gfx/layers/basic/BasicImageLayer.cpp
gfx/layers/basic/BasicImages.cpp
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/basic/BasicLayersImpl.h
gfx/layers/d3d10/CanvasLayerD3D10.cpp
gfx/layers/d3d10/CanvasLayerD3D10.h
gfx/layers/d3d10/ImageLayerD3D10.cpp
gfx/layers/d3d10/ImageLayerD3D10.h
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/d3d9/CanvasLayerD3D9.h
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/ImageLayerD3D9.h
gfx/layers/d3d9/ThebesLayerD3D9.cpp
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayerUtilsX11.cpp
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/CanvasLayerOGL.h
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.h
gfx/thebes/gfxBlur.h
gfx/thebes/gfxDrawable.cpp
gfx/thebes/gfxUtils.h
gfx/thebes/gfxXlibSurface.h
image/src/RasterImage.cpp
js/jsd/jsd_scpt.c
js/src/Makefile.in
js/src/configure.in
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/FoldConstants.cpp
js/src/frontend/ParseNode.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/SemanticAnalysis.cpp
js/src/frontend/TreeContext-inl.h
js/src/frontend/TreeContext.cpp
js/src/frontend/TreeContext.h
js/src/gc/Statistics.h
js/src/ion/CodeGenerator.cpp
js/src/jitstats.tbl
js/src/js.msg
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscompartment.h
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinterpinlines.h
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsopcode.tbl
js/src/jsproto.tbl
js/src/jsreflect.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsscriptinlines.h
js/src/jsstr.cpp
js/src/jsstr.h
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/jsxml.cpp
js/src/methodjit/BaseAssembler.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/FastOps.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/SPSProfiler.cpp
js/src/vm/ScopeObject.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/vm/String.h
js/xpconnect/idl/xpccomponents.idl
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/tests/chrome/test_bug758563.xul
js/xpconnect/tests/mochitest/file_bug758563.html
js/xpconnect/wrappers/AccessCheck.cpp
js/xpconnect/wrappers/WrapperFactory.cpp
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/nsCSSRendering.cpp
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/forms/nsTextControlFrame.cpp
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
layout/generic/nsImageFrame.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/generic/nsVideoFrame.cpp
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLChar.h
layout/reftests/bugs/reftest.list
layout/reftests/css-namespace/LICENSE
layout/reftests/css-namespace/README
layout/reftests/css-namespace/prefix-001.xml
layout/reftests/css-namespace/prefix-002.xml
layout/reftests/css-namespace/prefix-003.xml
layout/reftests/css-namespace/prefix-004.xml
layout/reftests/css-namespace/prefix-005.xml
layout/reftests/css-namespace/prefix-006.xml
layout/reftests/css-namespace/ref-lime-1-block.xml
layout/reftests/css-namespace/ref-lime-1-generic.xml
layout/reftests/css-namespace/ref-lime-1.xml
layout/reftests/css-namespace/ref-lime-2-generic.xml
layout/reftests/css-namespace/ref-lime-2.xml
layout/reftests/css-namespace/ref-lime-3.xml
layout/reftests/css-namespace/ref-lime-5.xml
layout/reftests/css-namespace/ref-lime-6.xml
layout/reftests/css-namespace/reftest.list
layout/reftests/css-namespace/scope-001.xml
layout/reftests/css-namespace/scope-002.xml
layout/reftests/css-namespace/support/fail.css
layout/reftests/css-namespace/support/scope-002a.css
layout/reftests/css-namespace/support/scope-002b.css
layout/reftests/css-namespace/support/syntax-007.css
layout/reftests/css-namespace/syntax-001.xml
layout/reftests/css-namespace/syntax-002.xml
layout/reftests/css-namespace/syntax-003.xml
layout/reftests/css-namespace/syntax-004.xml
layout/reftests/css-namespace/syntax-005.xml
layout/reftests/css-namespace/syntax-006.xml
layout/reftests/css-namespace/syntax-007.xml
layout/reftests/css-namespace/syntax-008.xml
layout/reftests/css-namespace/syntax-009.xml
layout/reftests/css-namespace/syntax-010.xml
layout/reftests/css-namespace/syntax-011.xml
layout/reftests/css-namespace/syntax-012.xml
layout/reftests/css-namespace/syntax-013.xml
layout/reftests/css-namespace/syntax-014.xml
layout/reftests/css-namespace/syntax-015.xml
layout/reftests/reftest.list
layout/reftests/text/reftest.list
layout/style/Loader.cpp
layout/style/nsAnimationManager.cpp
layout/style/nsAnimationManager.h
layout/style/nsCSSParser.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
layout/xul/base/src/nsImageBoxFrame.cpp
media/omx-plugin/include/ics/OMX.h
media/omx-plugin/lib/ics/libstagefright_omx/Makefile.in
media/omx-plugin/lib/ics/libstagefright_omx/libstagefright_omx.cpp
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/Makefile.in
mobile/android/base/resources/drawable-hdpi-v11/ic_menu_clear_site_settings.png
mobile/android/base/resources/drawable-hdpi/abouthome_sync_bg.9.png
mobile/android/base/resources/drawable-hdpi/abouthome_sync_pressed_bg.9.png
mobile/android/base/resources/drawable-mdpi-v11/ic_menu_clear_site_settings.png
mobile/android/base/resources/drawable-xhdpi-v11/ic_menu_clear_site_settings.png
mobile/android/base/resources/drawable-xhdpi/abouthome_sync_bg.9.png
mobile/android/base/resources/drawable-xhdpi/abouthome_sync_pressed_bg.9.png
mobile/android/base/resources/drawable/abouthome_sync_bg.9.png
mobile/android/base/resources/drawable/abouthome_sync_box.xml
mobile/android/base/resources/drawable/abouthome_sync_pressed_bg.9.png
mobile/android/chrome/content/browser.js
mobile/android/themes/core/aboutReader.css
mobile/android/themes/core/images/reader-dark-bg.png
mobile/android/themes/core/images/reader-light-bg.png
mobile/android/themes/core/images/reader-sepia-bg.png
mobile/xul/installer/package-manifest.in
modules/libpref/src/init/all.js
netwerk/cache/nsCacheEntryDescriptor.cpp
netwerk/cache/nsCacheEntryDescriptor.h
netwerk/cache/nsCacheService.cpp
netwerk/cache/nsCacheService.h
netwerk/cache/nsDiskCacheMap.cpp
netwerk/cache/nsDiskCacheMap.h
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/http/nsHttpTransaction.h
parser/html/nsHtml5Parser.cpp
parser/html/nsHtml5StreamParser.cpp
parser/html/nsHtml5TreeOpExecutor.cpp
rdf/base/src/nsRDFXMLDataSource.cpp
rdf/tests/rdfcat/rdfcat.cpp
rdf/tests/triplescat/triplescat.cpp
security/manager/ssl/src/nsNSSComponent.cpp
security/manager/ssl/src/nsPKCS12Blob.cpp
testing/jetpack/jetpack-location.txt
testing/mochitest/tests/SimpleTest/setup.js
toolkit/components/startup/nsAppStartup.cpp
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/components/telemetry/TelemetryPing.js
toolkit/components/telemetry/tests/unit/test_TelemetryPing.js
toolkit/content/license.html
toolkit/mozapps/extensions/AddonRepository.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
toolkit/mozapps/installer/packager.mk
toolkit/webapps/WebappsInstaller.jsm
view/src/nsView.cpp
view/src/nsView.h
view/src/nsViewManager.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/nsAppShell.cpp
widget/android/nsWindow.cpp
widget/cocoa/nsChildView.mm
widget/cocoa/nsNativeThemeCocoa.mm
widget/nsGUIEvent.h
widget/nsIWidget.h
widget/qt/nsWindow.cpp
widget/windows/nsNativeThemeWin.cpp
widget/windows/nsWindow.cpp
widget/windows/nsWindowDefs.h
widget/xpwidgets/PuppetWidget.cpp
widget/xpwidgets/nsBaseFilePicker.cpp
widget/xpwidgets/nsBaseFilePicker.h
widget/xpwidgets/nsBaseWidget.cpp
xpcom/io/nsLocalFileCommon.cpp
xpcom/tests/TestDeadlockDetector.cpp
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -1208,23 +1208,23 @@ HTMLTableAccessible::IsProbablyLayoutTab
     RETURN_LAYOUT_ANSWER(false, ">=5 columns");
   }
 
   // Now we know there are 2-4 columns and 2 or more rows
   // Check to see if there are visible borders on the cells
   // XXX currently, we just check the first cell -- do we really need to do more?
   nsCOMPtr<nsIDOMElement> cellElement;
   nsresult rv = GetCellAt(0, 0, *getter_AddRefs(cellElement));
-  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+  NS_ENSURE_SUCCESS(rv, false);
 
   nsCOMPtr<nsIContent> cellContent(do_QueryInterface(cellElement));
-  NS_ENSURE_TRUE(cellContent, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(cellContent, false);
   nsIFrame *cellFrame = cellContent->GetPrimaryFrame();
   if (!cellFrame) {
-    return NS_OK;
+    RETURN_LAYOUT_ANSWER(false, "Could not get frame for cellContent");
   }
   nsMargin border;
   cellFrame->GetBorder(border);
   if (border.top && border.bottom && border.left && border.right) {
     RETURN_LAYOUT_ANSWER(false, "Has nonzero border-width on table cell");
   }
 
   /**
--- a/accessible/src/jsat/AccessFu.css
+++ b/accessible/src/jsat/AccessFu.css
@@ -1,22 +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/. */
 
-#virtual-cursor-box { 
+#virtual-cursor-box {
   position: fixed;
   border: 1px solid orange;
   pointer-events: none;
   display: none;
   border-radius: 2px;
   box-shadow: 1px 1px 1px #444;
 }
 
-#virtual-cursor-inset { 
+#virtual-cursor-inset {
   border-radius: 1px;
   box-shadow: inset 1px 1px 1px #444;
   display: block;
   box-sizing: border-box;
   width: 100%;
   height: 100%;
   pointer-events: none;
-}
\ No newline at end of file
+}
+
+#accessfu-glass {
+  width: 100%;
+  height: 100%;
+  position: fixed;
+  top: 0px;
+  left: 0px;
+}
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -11,16 +11,17 @@ const Cr = Components.results;
 
 var EXPORTED_SYMBOLS = ['AccessFu'];
 
 Cu.import('resource://gre/modules/Services.jsm');
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 Cu.import('resource://gre/modules/accessibility/Presenters.jsm');
 Cu.import('resource://gre/modules/accessibility/VirtualCursorController.jsm');
+Cu.import('resource://gre/modules/accessibility/TouchAdapter.jsm');
 
 const ACCESSFU_DISABLE = 0;
 const ACCESSFU_ENABLE = 1;
 const ACCESSFU_AUTO = 2;
 
 var AccessFu = {
   /**
    * Attach chrome-layer accessibility functionality to the given chrome window.
@@ -39,32 +40,55 @@ var AccessFu = {
     this.chromeWin = aWindow;
     this.presenters = [];
 
     this.prefsBranch = Cc['@mozilla.org/preferences-service;1']
       .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.');
     this.prefsBranch.addObserver('activate', this, false);
     this.prefsBranch.addObserver('explorebytouch', this, false);
 
-    if (Utils.MozBuildApp == 'mobile/android')
-      Services.obs.addObserver(this, 'Accessibility:Settings', false);
+    this.touchAdapter = TouchAdapter;
+
+    switch(Utils.MozBuildApp) {
+      case 'mobile/android':
+        Services.obs.addObserver(this, 'Accessibility:Settings', false);
+        this.touchAdapter = AndroidTouchAdapter;
+        break;
+      case 'b2g':
+        aWindow.addEventListener(
+          'ContentStart',
+          (function(event) {
+             let content = aWindow.shell.contentBrowser.contentWindow;
+             content.addEventListener('mozContentEvent', this, false, true);
+           }).bind(this), false);
+        break;
+      default:
+        break;
+    }
 
     this._processPreferences();
   },
 
   /**
    * Start AccessFu mode, this primarily means controlling the virtual cursor
    * with arrow keys.
    */
   _enable: function _enable() {
     if (this._enabled)
       return;
     this._enabled = true;
 
     Logger.info('enable');
+
+    // Add stylesheet
+    let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
+    this.stylesheet = this.chromeWin.document.createProcessingInstruction(
+      'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
+    this.chromeWin.document.insertBefore(this.stylesheet, this.chromeWin.document.firstChild);
+
     this.addPresenter(new VisualPresenter());
 
     // Implicitly add the Android presenter on Android.
     if (Utils.MozBuildApp == 'mobile/android')
       this.addPresenter(new AndroidPresenter());
     else if (Utils.MozBuildApp == 'b2g')
       this.addPresenter(new SpeechPresenter());
 
@@ -83,16 +107,18 @@ var AccessFu = {
    */
   _disable: function _disable() {
     if (!this._enabled)
       return;
     this._enabled = false;
 
     Logger.info('disable');
 
+    this.chromeWin.document.removeChild(this.stylesheet);
+
     this.presenters.forEach(function(p) { p.detach(); });
     this.presenters = [];
 
     VirtualCursorController.detach();
 
     Services.obs.removeObserver(this, 'accessible-event');
     this.chromeWin.removeEventListener('DOMActivate', this, true);
     this.chromeWin.removeEventListener('resize', this, true);
@@ -125,18 +151,20 @@ var AccessFu = {
       }
     }
 
     if (accessPref == ACCESSFU_ENABLE)
       this._enable();
     else
       this._disable();
 
-    VirtualCursorController.exploreByTouch = ebtPref == ACCESSFU_ENABLE;
-    Logger.info('Explore by touch:', VirtualCursorController.exploreByTouch);
+    if (ebtPref == ACCESSFU_ENABLE)
+      this.touchAdapter.attach(this.chromeWin);
+    else
+      this.touchAdapter.detach(this.chromeWin);
   },
 
   addPresenter: function addPresenter(presenter) {
     this.presenters.push(presenter);
     presenter.attach(this.chromeWin);
   },
 
   handleEvent: function handleEvent(aEvent) {
@@ -187,16 +215,24 @@ var AccessFu = {
         break;
       }
       case 'scroll':
       case 'resize':
       {
         this.presenters.forEach(function(p) { p.viewportChanged(); });
         break;
       }
+      case 'mozContentEvent':
+      {
+        if (aEvent.detail.type == 'accessibility-screenreader') {
+          let pref = aEvent.detail.enabled + 0;
+          this._processPreferences(pref, pref);
+        }
+        break;
+      }
     }
   },
 
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case 'Accessibility:Settings':
         this._processPreferences(JSON.parse(aData).enabled + 0,
                                  JSON.parse(aData).exploreByTouch + 0);
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -112,38 +112,31 @@ VisualPresenter.prototype = {
   /**
    * The padding in pixels between the object and the highlight border.
    */
   BORDER_PADDING: 2,
 
   attach: function VisualPresenter_attach(aWindow) {
     this.chromeWin = aWindow;
 
-    // Add stylesheet
-    let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
-    this.stylesheet = aWindow.document.createProcessingInstruction(
-      'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
-    aWindow.document.insertBefore(this.stylesheet, aWindow.document.firstChild);
-
     // Add highlight box
     this.highlightBox = this.chromeWin.document.
       createElementNS('http://www.w3.org/1999/xhtml', 'div');
     this.chromeWin.document.documentElement.appendChild(this.highlightBox);
     this.highlightBox.id = 'virtual-cursor-box';
 
     // Add highlight inset for inner shadow
     let inset = this.chromeWin.document.
       createElementNS('http://www.w3.org/1999/xhtml', 'div');
     inset.id = 'virtual-cursor-inset';
 
     this.highlightBox.appendChild(inset);
   },
 
   detach: function VisualPresenter_detach() {
-    this.chromeWin.document.removeChild(this.stylesheet);
     this.highlightBox.parentNode.removeChild(this.highlightBox);
     this.highlightBox = this.stylesheet = null;
   },
 
   viewportChanged: function VisualPresenter_viewportChanged() {
     if (this._currentObject)
       this._highlight(this._currentObject);
   },
new file mode 100644
--- /dev/null
+++ b/accessible/src/jsat/TouchAdapter.jsm
@@ -0,0 +1,402 @@
+/* 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';
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const Cr = Components.results;
+
+var EXPORTED_SYMBOLS = ['TouchAdapter', 'AndroidTouchAdapter'];
+
+Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+
+// We should not be emitting explore events more than 10 times a second.
+// It is granular enough to feel natural, and it does not hammer the CPU.
+const EXPLORE_THROTTLE = 100;
+
+var TouchAdapter = {
+  // minimal swipe distance in inches
+  SWIPE_MIN_DISTANCE: 0.4,
+
+  // maximum duration of swipe
+  SWIPE_MAX_DURATION: 400,
+
+  // how straight does a swipe need to be
+  SWIPE_DIRECTNESS: 1.2,
+
+  // maximum consecutive
+  MAX_CONSECUTIVE_GESTURE_DELAY: 400,
+
+  // delay before tap turns into dwell
+  DWELL_THRESHOLD: 500,
+
+  // delay before distinct dwell events
+  DWELL_REPEAT_DELAY: 300,
+
+  // maximum distance the mouse could move during a tap in inches
+  TAP_MAX_RADIUS: 0.2,
+
+  attach: function TouchAdapter_attach(aWindow) {
+    if (this.chromeWin)
+      return;
+
+    Logger.info('TouchAdapter.attach');
+
+    this.chromeWin = aWindow;
+    this._touchPoints = {};
+    this._dwellTimeout = 0;
+    this._prevGestures = {};
+    this._lastExploreTime = 0;
+    this._dpi = this.chromeWin.QueryInterface(Ci.nsIInterfaceRequestor).
+      getInterface(Ci.nsIDOMWindowUtils).displayDPI;
+
+    this.glass = this.chromeWin.document.
+      createElementNS('http://www.w3.org/1999/xhtml', 'div');
+    this.glass.id = 'accessfu-glass';
+    this.chromeWin.document.documentElement.appendChild(this.glass);
+
+    this.glass.addEventListener('touchend', this, true, true);
+    this.glass.addEventListener('touchmove', this, true, true);
+    this.glass.addEventListener('touchstart', this, true, true);
+
+    if (Utils.OS != 'Android')
+      Mouse2Touch.attach(aWindow);
+  },
+
+  detach: function TouchAdapter_detach(aWindow) {
+    if (!this.chromeWin)
+      return;
+
+    Logger.info('TouchAdapter.detach');
+
+    this.glass.removeEventListener('touchend', this, true, true);
+    this.glass.removeEventListener('touchmove', this, true, true);
+    this.glass.removeEventListener('touchstart', this, true, true);
+    this.glass.parentNode.removeChild(this.glass);
+
+    if (Utils.OS != 'Android')
+      Mouse2Touch.detach(aWindow);
+
+    delete this.chromeWin;
+  },
+
+  handleEvent: function TouchAdapter_handleEvent(aEvent) {
+    let touches = aEvent.changedTouches;
+    switch (aEvent.type) {
+      case 'touchstart':
+        for (var i = 0; i < touches.length; i++) {
+          let touch = touches[i];
+          let touchPoint = new TouchPoint(touch, aEvent.timeStamp, this._dpi);
+          this._touchPoints[touch.identifier] = touchPoint;
+          this._lastExploreTime = aEvent.timeStamp + this.SWIPE_MAX_DURATION;
+        }
+        this._dwellTimeout = this.chromeWin.setTimeout(
+          (function () {
+             this.compileAndEmit(aEvent.timeStamp + this.DWELL_THRESHOLD);
+           }).bind(this), this.DWELL_THRESHOLD);
+        break;
+      case 'touchmove':
+        for (var i = 0; i < touches.length; i++) {
+          let touch = touches[i];
+          let touchPoint = this._touchPoints[touch.identifier];
+          touchPoint.update(touch, aEvent.timeStamp);
+        }
+        if (aEvent.timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
+          this.compileAndEmit(aEvent.timeStamp);
+          this._lastExploreTime = aEvent.timeStamp;
+        }
+        break;
+      case 'touchend':
+        for (var i = 0; i < touches.length; i++) {
+          let touch = touches[i];
+          let touchPoint = this._touchPoints[touch.identifier];
+          touchPoint.update(touch, aEvent.timeStamp);
+          touchPoint.finish();
+        }
+        this.compileAndEmit(aEvent.timeStamp);
+        break;
+    }
+  },
+
+  cleanupTouches: function cleanupTouches() {
+    for (var identifier in this._touchPoints) {
+      if (!this._touchPoints[identifier].done)
+        continue;
+
+      delete this._touchPoints[identifier];
+    }
+  },
+
+  compile: function TouchAdapter_compile(aTime) {
+    let multiDetails = {};
+
+    // Compound multiple simultaneous touch gestures.
+    for (let identifier in this._touchPoints) {
+      let touchPoint = this._touchPoints[identifier];
+      let details = touchPoint.compile(aTime);
+
+      if (!details)
+        continue;
+
+      details.touches = [identifier];
+
+      let otherTouches = multiDetails[details.type];
+      if (otherTouches) {
+        otherTouches.touches.push(identifier);
+        otherTouches.startTime =
+          Math.min(otherTouches.startTime, touchPoint.startTime);
+      } else {
+        details.startTime = touchPoint.startTime;
+        details.endTime = aTime;
+        multiDetails[details.type] = details;
+      }
+    }
+
+    // Compound multiple consecutive touch gestures.
+    for each (let details in multiDetails) {
+      let idhash = details.touches.slice().sort().toString();
+      let prevGesture = this._prevGestures[idhash];
+
+      if (prevGesture) {
+        // The time delta is calculated as the period between the end of the
+        // last gesture and the start of this one.
+        let timeDelta = details.startTime - prevGesture.endTime;
+        if (timeDelta > this.MAX_CONSECUTIVE_GESTURE_DELAY) {
+          delete this._prevGestures[idhash];
+        } else {
+          if (details.type == 'tap' && prevGesture.type == 'tap')
+            details.type = 'doubletap';
+          if (details.type == 'tap' && prevGesture.type == 'doubletap')
+            details.type = 'tripletap';
+          if (details.type == 'dwell' && prevGesture.type == 'tap')
+            details.type = 'taphold';
+        }
+      }
+
+      this._prevGestures[idhash] = details;
+    }
+
+    this.chromeWin.clearTimeout(this._dwellTimeout);
+    this.cleanupTouches();
+
+    return multiDetails;
+  },
+
+  emitGesture: function TouchAdapter_emitGesture(aDetails) {
+    let evt = this.chromeWin.document.createEvent('CustomEvent');
+    evt.initCustomEvent('mozAccessFuGesture', true, true, aDetails);
+    this.chromeWin.dispatchEvent(evt);
+  },
+
+  compileAndEmit: function TouchAdapter_compileAndEmit(aTime) {
+    for each (let details in this.compile(aTime)) {
+      this.emitGesture(details);
+    }
+  }
+};
+
+/***
+ * A TouchPoint represents a single touch from the moment of contact until it is
+ * lifted from the surface. It is capable of compiling gestures from the scope
+ * of one single touch.
+ */
+function TouchPoint(aTouch, aTime, aDPI) {
+  this.startX = aTouch.screenX;
+  this.startY = aTouch.screenY;
+  this.startTime = aTime;
+  this.distanceTraveled = 0;
+  this.dpi = aDPI;
+  this.done = false;
+}
+
+TouchPoint.prototype = {
+  update: function TouchPoint_update(aTouch, aTime) {
+    let lastX = this.x;
+    let lastY = this.y;
+    this.x = aTouch.screenX;
+    this.y = aTouch.screenY;
+    this.time = aTime;
+
+    if (lastX != undefined && lastY != undefined)
+      this.distanceTraveled += this.getDistanceToCoord(lastX, lastY);
+  },
+
+  getDistanceToCoord: function TouchPoint_getDistanceToCoord(aX, aY) {
+    return Math.sqrt(Math.pow(this.x - aX, 2) + Math.pow(this.y - aY, 2));
+  },
+
+  finish: function TouchPoint_finish() {
+    this.done = true;
+  },
+
+  /**
+   * Compile a gesture from an individual touch point. This is used by the
+   * TouchAdapter to compound multiple single gestures in to higher level
+   * gestures.
+   */
+  compile: function TouchPoint_compile(aTime) {
+    let directDistance = this.directDistanceTraveled;
+    let duration = aTime - this.startTime;
+
+    // To be considered a tap/dwell...
+    if ((this.distanceTraveled / this.dpi) < TouchAdapter.TAP_MAX_RADIUS) { // Didn't travel
+      if (duration < TouchAdapter.DWELL_THRESHOLD) {
+        // Mark it as done so we don't use this touch for another gesture.
+        this.finish();
+        return {type: 'tap', x: this.startX, y: this.startY};
+      } else if (!this.done && duration == TouchAdapter.DWELL_THRESHOLD) {
+        return {type: 'dwell', x: this.startX, y: this.startY};
+      }
+    }
+
+    // To be considered a swipe...
+    if (duration <= TouchAdapter.SWIPE_MAX_DURATION && // Quick enough
+        (directDistance / this.dpi) >= TouchAdapter.SWIPE_MIN_DISTANCE && // Traveled far
+        (directDistance * 1.2) >= this.distanceTraveled) { // Direct enough
+
+      let swipeGesture = {x1: this.startX, y1: this.startY,
+                          x2: this.x, y2: this.y};
+      let deltaX = this.x - this.startX;
+      let deltaY = this.y - this.startY;
+
+      if (Math.abs(deltaX) > Math.abs(deltaY)) {
+        // Horizontal swipe.
+        if (deltaX > 0)
+          swipeGesture.type = 'swiperight';
+        else
+          swipeGesture.type = 'swipeleft';
+      } else if (Math.abs(deltaX) < Math.abs(deltaY)) {
+        // Vertical swipe.
+        if (deltaY > 0)
+          swipeGesture.type = 'swipedown';
+        else
+          swipeGesture.type = 'swipeup';
+      } else {
+        // A perfect 45 degree swipe?? Not in our book.
+          return null;
+      }
+
+      this.finish();
+
+      return swipeGesture;
+    }
+
+    // To be considered an explore...
+    if (!this.done &&
+        duration > TouchAdapter.SWIPE_MAX_DURATION &&
+        (this.distanceTraveled / this.dpi) > TouchAdapter.TAP_MAX_RADIUS) {
+      return {type: 'explore', x: this.x, y: this.y};
+    }
+
+    return null;
+  },
+
+  get directDistanceTraveled() {
+    return this.getDistanceToCoord(this.startX, this.startY);
+  }
+};
+
+var Mouse2Touch = {
+  _MouseToTouchMap: {
+    mousedown: 'touchstart',
+    mouseup: 'touchend',
+    mousemove: 'touchmove'
+  },
+
+  attach: function Mouse2Touch_attach(aWindow) {
+    this.chromeWin = aWindow;
+    this.chromeWin.addEventListener('mousedown', this, true, true);
+    this.chromeWin.addEventListener('mouseup', this, true, true);
+    this.chromeWin.addEventListener('mousemove', this, true, true);
+  },
+
+  detach: function Mouse2Touch_detach(aWindow) {
+    this.chromeWin.removeEventListener('mousedown', this, true, true);
+    this.chromeWin.removeEventListener('mouseup', this, true, true);
+    this.chromeWin.removeEventListener('mousemove', this, true, true);
+  },
+
+  handleEvent: function Mouse2Touch_handleEvent(aEvent) {
+    if (aEvent.buttons == 0)
+      return;
+
+    let name = this._MouseToTouchMap[aEvent.type];
+    let evt = this.chromeWin.document.createEvent("touchevent");
+    let points = [this.chromeWin.document.createTouch(
+                    this.chromeWin, aEvent.target, 0,
+                    aEvent.pageX, aEvent.pageY, aEvent.screenX, aEvent.screenY,
+                    aEvent.clientX, aEvent.clientY, 1, 1, 0, 0)];
+
+    // Simulate another touch point at a 5px offset when ctrl is pressed.
+    if (aEvent.ctrlKey)
+      points.push(this.chromeWin.document.createTouch(
+                    this.chromeWin, aEvent.target, 1,
+                    aEvent.pageX + 5, aEvent.pageY + 5,
+                    aEvent.screenX + 5, aEvent.screenY + 5,
+                    aEvent.clientX + 5, aEvent.clientY + 5,
+                    1, 1, 0, 0));
+
+    // Simulate another touch point at a -5px offset when alt is pressed.
+    if (aEvent.altKey)
+      points.push(this.chromeWin.document.createTouch(
+                    this.chromeWin, aEvent.target, 2,
+                    aEvent.pageX - 5, aEvent.pageY - 5,
+                    aEvent.screenX - 5, aEvent.screenY - 5,
+                    aEvent.clientX - 5, aEvent.clientY - 5,
+                    1, 1, 0, 0));
+
+    let touches = this.chromeWin.document.createTouchList(points);
+    if (name == "touchend") {
+      let empty = this.chromeWin.document.createTouchList();
+      evt.initTouchEvent(name, true, true, this.chromeWin, 0,
+                         false, false, false, false, empty, empty, touches);
+    } else {
+      evt.initTouchEvent(name, true, true, this.chromeWin, 0,
+                         false, false, false, false, touches, touches, touches);
+    }
+    aEvent.target.dispatchEvent(evt);
+    aEvent.preventDefault();
+    aEvent.stopImmediatePropagation();
+  }
+};
+
+var AndroidTouchAdapter = {
+  attach: function AndroidTouchAdapter_attach(aWindow) {
+    if (this.chromeWin)
+      return;
+
+    Logger.info('AndroidTouchAdapter.attach');
+
+    this.chromeWin = aWindow;
+    this.chromeWin.addEventListener('mousemove', this, true, true);
+    this._lastExploreTime = 0;
+  },
+
+  detach: function AndroidTouchAdapter_detach(aWindow) {
+    if (!this.chromeWin)
+      return;
+
+    Logger.info('AndroidTouchAdapter.detach');
+
+    this.chromeWin.removeEventListener('mousemove', this, true, true);
+    delete this.chromeWin;
+  },
+
+  handleEvent: function AndroidTouchAdapter_handleEvent(aEvent) {
+    // On non-Android we use the shift key to simulate touch.
+    if (Utils.MozBuildApp != 'mobile/android' && !aEvent.shiftKey)
+      return;
+
+    if (aEvent.timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
+      let evt = this.chromeWin.document.createEvent('CustomEvent');
+      evt.initCustomEvent(
+        'mozAccessFuGesture', true, true,
+        {type: 'explore', x: aEvent.screenX, y: aEvent.screenY});
+      this.chromeWin.dispatchEvent(evt);
+      this._lastExploreTime = aEvent.timeStamp;
+    }
+  }
+};
\ No newline at end of file
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -66,16 +66,30 @@ var Utils = {
   },
 
   getCurrentContentDoc: function getCurrentContentDoc(aWindow) {
     if (this.MozBuildApp == "b2g")
       return this.getBrowserApp(aWindow).contentBrowser.contentDocument;
     return this.getBrowserApp(aWindow).selectedBrowser.contentDocument;
   },
 
+  getAllDocuments: function getAllDocuments(aWindow) {
+    let doc = gAccRetrieval.
+      getAccessibleFor(this.getCurrentContentDoc(aWindow)).
+      QueryInterface(Ci.nsIAccessibleDocument);
+    let docs = [];
+    function getAllDocuments(aDocument) {
+      docs.push(aDocument.DOMDocument);
+      for (let i = 0; i < aDocument.childDocumentCount; i++)
+        getAllDocuments(aDocument.getChildDocumentAt(i));
+    }
+    getAllDocuments(doc);
+    return docs;
+  },
+
   getViewport: function getViewport(aWindow) {
     switch (this.MozBuildApp) {
       case 'mobile/android':
         return aWindow.BrowserApp.selectedTab.getViewport();
       default:
         return null;
     }
   },
@@ -98,16 +112,93 @@ var Utils = {
       try {
         return doc.QueryInterface(Ci.nsIAccessibleCursorable).virtualCursor;
       } catch (x) {
         doc = doc.parentDocument;
       }
     }
 
     return null;
+  },
+
+  scroll: function scroll(aWindow, aPage, aHorizontal) {
+    for each (let doc in this.getAllDocuments(aWindow)) {
+      // First see if we could scroll a window.
+      let win = doc.defaultView;
+      if (!aHorizontal && win.scrollMaxY &&
+          ((aPage > 0 && win.scrollY < win.scrollMaxY) ||
+           (aPage < 0 && win.scrollY > 0))) {
+        win.scroll(0, win.innerHeight);
+        return true;
+      } else if (aHorizontal && win.scrollMaxX &&
+                 ((aPage > 0 && win.scrollX < win.scrollMaxX) ||
+                  (aPage < 0 && win.scrollX > 0))) {
+        win.scroll(win.innerWidth, 0);
+        return true;
+      }
+
+      // Second, try to scroll main section or current target if there is no
+      // main section.
+      let main = doc.querySelector('[role=main]') ||
+        doc.querySelector(':target');
+
+      if (main) {
+        if ((!aHorizontal && main.clientHeight < main.scrollHeight) ||
+          (aHorizontal && main.clientWidth < main.scrollWidth)) {
+          let s = win.getComputedStyle(main);
+          if (!aHorizontal) {
+            if (s.overflowY == 'scroll' || s.overflowY == 'auto') {
+              main.scrollTop += aPage * main.clientHeight;
+              return true;
+            }
+          } else {
+            if (s.overflowX == 'scroll' || s.overflowX == 'auto') {
+              main.scrollLeft += aPage * main.clientWidth;
+              return true;
+            }
+          }
+        }
+      }
+    }
+
+    return false;
+  },
+
+  changePage: function changePage(aWindow, aPage) {
+    for each (let doc in this.getAllDocuments(aWindow)) {
+      // Get current main section or active target.
+      let main = doc.querySelector('[role=main]') ||
+        doc.querySelector(':target');
+      if (!main)
+        continue;
+
+      let mainAcc = gAccRetrieval.getAccessibleFor(main);
+      if (!mainAcc)
+        continue;
+
+      let controllers = mainAcc.
+        getRelationByType(Ci.nsIAccessibleRelation.RELATION_CONTROLLED_BY);
+
+      for (var i=0; controllers.targetsCount > i; i++) {
+        let controller = controllers.getTarget(i);
+        // If the section has a controlling slider, it should be considered
+        // the page-turner.
+        if (controller.role == Ci.nsIAccessibleRole.ROLE_SLIDER) {
+          // Sliders are controlled with ctrl+right/left. I just decided :)
+          let evt = doc.createEvent("KeyboardEvent");
+          evt.initKeyEvent('keypress', true, true, null,
+                           true, false, false, false,
+                           (aPage > 0) ? evt.DOM_VK_RIGHT : evt.DOM_VK_LEFT, 0);
+          controller.DOMNode.dispatchEvent(evt);
+          return true;
+        }
+      }
+    }
+
+    return false;
   }
 };
 
 var Logger = {
   DEBUG: 0,
   INFO: 1,
   WARNING: 2,
   ERROR: 3,
--- a/accessible/src/jsat/VirtualCursorController.jsm
+++ b/accessible/src/jsat/VirtualCursorController.jsm
@@ -192,68 +192,91 @@ var TraversalRules = {
 
 var VirtualCursorController = {
   exploreByTouch: false,
   editableState: 0,
 
   attach: function attach(aWindow) {
     this.chromeWin = aWindow;
     this.chromeWin.document.addEventListener('keypress', this, true);
-    this.chromeWin.document.addEventListener('mousemove', this, true);
+    this.chromeWin.addEventListener('mozAccessFuGesture', this, true);
   },
 
   detach: function detach() {
     this.chromeWin.document.removeEventListener('keypress', this, true);
-    this.chromeWin.document.removeEventListener('mousemove', this, true);
+    this.chromeWin.removeEventListener('mozAccessFuGesture', this, true);
   },
 
   handleEvent: function VirtualCursorController_handleEvent(aEvent) {
     switch (aEvent.type) {
       case 'keypress':
         this._handleKeypress(aEvent);
         break;
-      case 'mousemove':
-        this._handleMousemove(aEvent);
+      case 'mozAccessFuGesture':
+        this._handleGesture(aEvent);
         break;
     }
   },
 
-  _handleMousemove: function _handleMousemove(aEvent) {
-    // Explore by touch is disabled.
-    if (!this.exploreByTouch)
-      return;
+  _handleGesture: function _handleGesture(aEvent) {
+    let document = Utils.getCurrentContentDoc(this.chromeWin);
+    let detail = aEvent.detail;
+    Logger.info('Gesture', detail.type,
+                '(fingers: ' + detail.touches.length + ')');
 
-    // On non-Android we use the shift key to simulate touch.
-    if (Utils.OS != 'Android' && !aEvent.shiftKey)
-      return;
-
-    // We should not be calling moveToPoint more than 10 times a second.
-    // It is granular enough to feel natural, and it does not hammer the CPU.
-    if (!this._handleMousemove._lastEventTime ||
-        aEvent.timeStamp - this._handleMousemove._lastEventTime >= 100) {
-      this.moveToPoint(Utils.getCurrentContentDoc(this.chromeWin),
-                       aEvent.screenX, aEvent.screenY);
-      this._handleMousemove._lastEventTime = aEvent.timeStamp;
+    if (detail.touches.length == 1) {
+      switch (detail.type) {
+        case 'swiperight':
+          this.moveForward(document, aEvent.shiftKey);
+          break;
+        case 'swipeleft':
+          this.moveBackward(document, aEvent.shiftKey);
+          break;
+        case 'doubletap':
+          this.activateCurrent(document);
+          break;
+        case 'explore':
+          this.moveToPoint(document, detail.x, detail.y);
+          break;
+      }
     }
 
-    aEvent.preventDefault();
-    aEvent.stopImmediatePropagation();
+    if (detail.touches.length == 3) {
+      switch (detail.type) {
+        case 'swiperight':
+          if (!Utils.scroll(this.chromeWin, -1, true))
+            Utils.changePage(this.chromeWin, -1);
+          break;
+        case 'swipedown':
+          Utils.scroll(this.chromeWin, -1);
+          break;
+        case 'swipeleft':
+          if (!Utils.scroll(this.chromeWin, 1, true))
+            Utils.changePage(this.chromeWin, 1);
+        case 'swipeup':
+          Utils.scroll(this.chromeWin, 1);
+          break;
+      }
+    }
   },
 
   _handleKeypress: function _handleKeypress(aEvent) {
     let document = Utils.getCurrentContentDoc(this.chromeWin);
     let target = aEvent.target;
 
+    // Ignore keys with modifiers so the content could take advantage of them.
+    if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
+      return;
+
     switch (aEvent.keyCode) {
       case 0:
         // an alphanumeric key was pressed, handle it separately.
         // If it was pressed with either alt or ctrl, just pass through.
         // If it was pressed with meta, pass the key on without the meta.
-        if (this.editableState ||
-            aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
+        if (this.editableState)
           return;
 
         let key = String.fromCharCode(aEvent.charCode);
         let methodName = '', rule = {};
         try {
           [methodName, rule] = this.keyMap[key];
         } catch (x) {
           return;
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -483,16 +483,23 @@ pref("dom.experimental_forms", true);
 pref("gfx.gralloc.enabled", false);
 
 // XXXX REMOVE FOR PRODUCTION. Turns on GC and CC logging 
 pref("javascript.options.mem.log", true);
 
 // Increase mark slice time from 10ms to 30ms
 pref("javascript.options.mem.gc_incremental_slice_ms", 30);
 
+pref("javascript.options.mem.gc_high_frequency_heap_growth_max", 120);
+pref("javascript.options.mem.gc_high_frequency_heap_growth_min", 101);
+pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 40);
+pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 10);
+pref("javascript.options.mem.gc_low_frequency_heap_growth", 105);
+pref("javascript.options.mem.high_water_mark", 16);
+
 // Show/Hide scrollbars when active/inactive
 pref("ui.showHideScrollbars", 1);
 
 // Enable the ProcessPriorityManager, and give processes with no visible
 // documents a 1s grace period before they're eligible to be marked as
 // background.
 pref("dom.ipc.processPriorityManager.enabled", true);
 pref("dom.ipc.processPriorityManager.gracePeriodMS", 1000);
@@ -503,8 +510,11 @@ pref("hal.processPriorityManager.gonk.ma
 pref("hal.processPriorityManager.gonk.foregroundNice", 0);
 pref("hal.processPriorityManager.gonk.backgroundNice", 10);
 
 // Enable pre-launching content processes for improved startup time
 // (hiding latency).
 pref("dom.ipc.processPrelauch.enabled", true);
 // Wait this long before pre-launching a new subprocess.
 pref("dom.ipc.processPrelauch.delayMs", 1000);
+
+// Ignore the "dialog=1" feature in window.open.
+pref("dom.disable_window_open_dialog_feature", true);
new file mode 100644
--- /dev/null
+++ b/b2g/chrome/content/runapp.js
@@ -0,0 +1,93 @@
+// runapp.js:
+// Provide a --runapp APPNAME command-line option.
+
+window.addEventListener('load', function() {
+  // Get the command line arguments that were passed to the b2g client
+  let args = window.arguments[0].QueryInterface(Ci.nsICommandLine);
+  let appname;
+
+  // - Check if the argument is present before doing any work.
+  try {
+    // Returns null if the argument was not specified.  Throws
+    // NS_ERROR_INVALID_ARG if there is no parameter specified (because
+    // it was the last argument or the next argument starts with '-').
+    // However, someone could still explicitly pass an empty argument!
+    appname = args.handleFlagWithParam('runapp', false);
+  }
+  catch(e) {
+    // treat a missing parameter like an empty parameter (=> show usage)
+    appname = '';
+  }
+
+  // not specified, bail.
+  if (appname === null)
+    return;
+
+  // - Get the list of apps since the parameter was specified
+  let appsReq = navigator.mozApps.mgmt.getAll();
+  appsReq.onsuccess = function() {
+    let apps = appsReq.result;
+    function findAppWithName(name) {
+      let normalizedSearchName = name.replace(/[- ]+/g, '').toLowerCase();
+
+      for (let i = 0; i < apps.length; i++) {
+        let app = apps[i];
+        let normalizedAppName =
+              app.manifest.name.replace(/[- ]+/g, '').toLowerCase();
+        if (normalizedSearchName === normalizedAppName) {
+          return app;
+        }
+      }
+      return null;
+    }
+
+    function usageAndDie(justApps) {
+      if (!justApps)
+        dump(
+          'The --runapp argument specifies an app to automatically run at\n'+
+          'startup.  We match against app names per their manifest and \n' +
+          'ignoring capitalization, dashes, and whitespace.\n' +
+          '\nThe system will load as usual except the lock screen will be ' +
+          'automatically be disabled.\n\n' +
+          'Known apps:\n');
+
+      for (let i = 0; i < apps.length; i++) {
+        dump('  ' + apps[i].manifest.name + '\n');
+      }
+
+      // Exit the b2g client
+      Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit);
+    }
+
+    if (appname === '') {
+      usageAndDie();
+      return;
+    }
+
+    let app = findAppWithName(appname);
+    if (!app) {
+      dump('Could not find app: "' + appname + '". Maybe you meant one of:\n');
+      usageAndDie(true);
+      return;
+    }
+
+    let setReq =
+      navigator.mozSettings.getLock().set({'lockscreen.enabled': false});
+    setReq.onsuccess = function() {
+      // give the event loop another turn to disable the lock screen
+      window.setTimeout(function() {
+        dump('--runapp launching app: ' + app.manifest.name + '\n');
+        app.launch();
+      }, 0);
+    };
+    setReq.onerror = function() {
+      dump('--runapp failed to disable lock-screen.  Giving up.\n');
+    };
+
+    dump('--runapp found app: ' + app.manifest.name +
+         ', disabling lock screen...\n');
+ };
+ appsReq.onerror = function() {
+   dump('Problem getting the list of all apps!');
+ };
+});
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -11,16 +11,18 @@ const Cr = Components.results;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/ContactService.jsm');
 Cu.import('resource://gre/modules/SettingsChangeNotifier.jsm');
 Cu.import('resource://gre/modules/Webapps.jsm');
 Cu.import('resource://gre/modules/AlarmService.jsm');
 Cu.import('resource://gre/modules/ActivitiesService.jsm');
+Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
+Cu.import('resource://gre/modules/ObjectWrapper.jsm');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'env',
                                    '@mozilla.org/process/environment;1',
                                    'nsIEnvironment');
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'ss',
                                    '@mozilla.org/content/style-sheet-service;1',
                                    'nsIStyleSheetService');
@@ -309,17 +311,18 @@ var shell = {
 
   sendEvent: function shell_sendEvent(content, type, details) {
     let event = content.document.createEvent('CustomEvent');
     event.initCustomEvent(type, true, true, details ? details : {});
     content.dispatchEvent(event);
   },
 
   sendChromeEvent: function shell_sendChromeEvent(details) {
-    this.sendEvent(getContentWindow(), "mozChromeEvent", details);
+    this.sendEvent(getContentWindow(), "mozChromeEvent",
+                   ObjectWrapper.wrap(details, getContentWindow()));
   },
 
   receiveMessage: function shell_receiveMessage(message) {
     if (message.name != 'content-handler') {
       return;
     }
     let handler = message.json;
     new MozActivity({
@@ -367,24 +370,24 @@ nsBrowserAccess.prototype = {
 Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
   let msg = JSON.parse(data);
   let origin = Services.io.newURI(msg.manifest, null, null).prePath;
   shell.sendChromeEvent({
     type: 'open-app',
     url: msg.uri,
     origin: origin,
     manifest: msg.manifest,
+    isActivity: (msg.type == 'activity'),
     target: msg.target
   });
 }, 'system-messages-open-app', false);
 
 Services.obs.addObserver(function(aSubject, aTopic, aData) {
-  shell.sendEvent(shell.contentBrowser.contentWindow,
-                  "mozChromeEvent", { type: "fullscreenoriginchange",
-                                      fullscreenorigin: aData } );
+  shell.sendChromeEvent({ type: "fullscreenoriginchange",
+                          fullscreenorigin: aData });
 }, "fullscreen-origin-change", false);
 
 (function Repl() {
   if (!Services.prefs.getBoolPref('b2g.remote-js.enabled')) {
     return;
   }
   const prompt = 'JS> ';
   let output;
@@ -641,8 +644,29 @@ window.addEventListener('ContentStart', 
     if (gGeolocationActiveCount + oldCount == 1) {
       shell.sendChromeEvent({
         type: 'geolocation-status',
         active: (gGeolocationActiveCount == 1)
       });
     }
 }, "geolocation-device-events", false);
 })();
+
+(function recordingStatusTracker() {
+  let gRecordingActiveCount = 0;
+
+  Services.obs.addObserver(function(aSubject, aTopic, aData) {
+    let oldCount = gRecordingActiveCount;
+    if (aData == "starting") {
+      gRecordingActiveCount += 1;
+    } else if (aData == "shutdown") {
+      gRecordingActiveCount -= 1;
+    }
+
+    // We need to track changes from 1 <-> 0
+    if (gRecordingActiveCount + oldCount == 1) {
+      shell.sendChromeEvent({
+        type: 'recording-status',
+        active: (gRecordingActiveCount == 1)
+      });
+    }
+}, "recording-device-events", false);
+})();
--- a/b2g/chrome/content/shell.xul
+++ b/b2g/chrome/content/shell.xul
@@ -15,11 +15,13 @@
         onunload="shell.stop();">
 
   <script type="application/javascript" src="chrome://browser/content/settings.js"/>
   <script type="application/javascript" src="chrome://browser/content/shell.js"/>
 
 #ifndef ANDROID
   <!-- this script handles the screen argument for desktop builds -->
   <script type="application/javascript" src="chrome://browser/content/screen.js"/>
+  <!-- this script handles the "runapp" argument for desktop builds -->
+  <script type="application/javascript" src="chrome://browser/content/runapp.js"/>
 #endif
   <!-- The html:iframe containing the UI is created here. -->
 </window>
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -11,16 +11,17 @@ chrome.jar:
   content/arrow.svg                     (content/arrow.svg)
   content/dbg-browser-actors.js         (content/dbg-browser-actors.js)
   content/forms.js                      (content/forms.js)
   content/settings.js                   (content/settings.js)
 * content/shell.xul                     (content/shell.xul)
 * content/shell.js                      (content/shell.js)
 #ifndef ANDROID
   content/screen.js                     (content/screen.js)
+  content/runapp.js                     (content/runapp.js)
 #endif
   content/content.css                   (content/content.css)
   content/touchcontrols.css             (content/touchcontrols.css)
 
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
 % override chrome://global/skin/netError.css chrome://browser/content/netError.css
 % override chrome://global/skin/media/videocontrols.css chrome://browser/content/touchcontrols.css
 
--- a/b2g/components/ActivitiesGlue.js
+++ b/b2g/components/ActivitiesGlue.js
@@ -28,35 +28,34 @@ ActivitiesDialog.prototype = {
     });
 
 
     // Keep up the frond-end of an activity choice. The messages contains
     // a list of {names, icons} for applications able to handle this particular
     // activity. The front-end should display a UI to pick one.
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     let content = browser.getContentWindow();
-    let event = content.document.createEvent("CustomEvent");
-    event.initCustomEvent("mozChromeEvent", true, true, {
+    let detail = {
       type: "activity-choice",
       id: id,
       name: activity.name,
       choices: choices
-    });
+    };
 
     // Listen the resulting choice from the front-end. If there is no choice,
     // let's return -1, which means the user has cancelled the dialog.
     content.addEventListener("mozContentEvent", function act_getChoice(evt) {
       if (evt.detail.id != id)
         return;
 
       content.removeEventListener("mozContentEvent", act_getChoice);
       activity.callback.handleEvent(evt.detail.value ? evt.detail.value : -1);
     });
 
-    content.dispatchEvent(event);
+    browser.shell.sendChromeEvent(detail);
   },
 
   chooseActivity: function ap_chooseActivity(aName, aActivities, aCallback) {
     this.activities.push({
       name: aName,
       list: aActivities,
       callback: aCallback
     });
--- a/b2g/components/ContentPermissionPrompt.js
+++ b/b2g/components/ContentPermissionPrompt.js
@@ -53,19 +53,17 @@ ContentPermissionPrompt.prototype = {
     });
 
     let details = {
       "type": "permission-prompt",
       "permission": request.type,
       "id": requestId,
       "url": request.principal.URI.spec
     };
-    let event = content.document.createEvent("CustomEvent");
-    event.initCustomEvent("mozChromeEvent", true, true, details);
-    content.dispatchEvent(event);
+    browser.shell.sendChromeEvent(details);
   },
 
   classID: Components.ID("{8c719f03-afe0-4aac-91ff-6c215895d467}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionPrompt])
 };
 
 
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -6,16 +6,17 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const kFormsFrameScript = "chrome://browser/content/forms.js";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
 const messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
                          .getService(Ci.nsIChromeFrameMessageManager);
 
 
 // -----------------------------------------------------------------------
 // MozKeyboard
 // -----------------------------------------------------------------------
@@ -98,17 +99,18 @@ MozKeyboard.prototype = {
     let handler = this._focusHandler;
     if (!handler || !(handler instanceof Ci.nsIDOMEventListener))
       return;
 
     let detail = {
       "detail": msg.json
     };
 
-    let evt = new this._window.CustomEvent("focuschanged", detail);
+    let evt = new this._window.CustomEvent("focuschanged",
+                                           ObjectWrapper.wrap(detail, this._window));
     handler.handleEvent(evt);
   },
 
   observe: function mozKeyboardObserve(subject, topic, data) {
     switch (topic) {
     case "inner-window-destroyed": {
       let wId = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
       if (wId == this.innerWindowID) {
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly
+++ b/b2g/config/mozconfigs/macosx64_gecko/nightly
@@ -1,8 +1,10 @@
+. $topsrcdir/build/macosx/common
+
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
@@ -11,17 +13,16 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 #ac_add_options --with-macbundlename-prefix=Firefox
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
 ac_add_options --enable-warnings-as-errors
-ac_add_options --with-ccache
 
 # B2G Stuff
 ac_add_options --enable-application=b2g
 ac_add_options --enable-debug-symbols
 ac_add_options --with-ccache
 ac_add_options --enable-marionette
 
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
copy from browser/config/tooltool-manifests/macosx64/releng.manifest
copy to b2g/config/tooltool-manifests/macosx64/releng.manifest
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,227 +1,100 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1344613852000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1345147390000">
   <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>
       <emItem  blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}">
                         <versionRange  minVersion=" " severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i43" id="supportaccessplugin@gmail.com">
-                        </emItem>
-      <emItem  blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i107" os="WINNT" id="{ABDE892B-13A8-4d1b-88E6-365A6E755758}">
                         <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i88" id="anttoolbar@ant.com">
                         <versionRange  minVersion="2.4.6.4" maxVersion="2.4.6.4" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
-                        <versionRange  minVersion="2.2" maxVersion="2.2">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i98" id="youtubeeing@youtuberie.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
-                        <versionRange  minVersion="0.1" maxVersion="*">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="9.0a1" maxVersion="9.0" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i65" id="activity@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i66" id="youtubeer@youtuber.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i54" id="applebeegifts@mozilla.doslash.org">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}">
-                        <versionRange  minVersion="1.0" maxVersion="1.0">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}">
-                        <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i92" id="play5@vide04flash.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i108" id="{28bfb930-7620-11e1-b0c4-0800200c9a66}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i105" id="{95ff02bc-ffc6-45f0-a5c8-619b8226a9de}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i61" id="youtube@youtube3.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                                <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
-                        </emItem>
-      <emItem  blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
-                        <versionRange  minVersion="2.1" maxVersion="3.3">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.0a1" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                                <versionRange  minVersion=" " maxVersion="6.9.8">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i63" id="youtube@youtuber.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i101" id="{3a12052a-66ef-49db-8c39-e5b0bd5c83fa}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i18" id="msntoolbar@msn.com">
-                        <versionRange  minVersion=" " maxVersion="6.*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
-                        </emItem>
       <emItem  blockID="i117" id="{ce7e73df-6a44-4028-8079-5927a588c948}">
                         <versionRange  minVersion="0" maxVersion="1.0.8" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
-                        <versionRange  minVersion="0.1" maxVersion="1.3.328.4" severity="1">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
-                          </targetApplication>
+      <emItem  blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
+                        <versionRange  minVersion="2.5.0" maxVersion="2.5.0" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i64" id="royal@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i72" os="WINNT" id="{4ED1F68A-5463-4931-9384-8FFF5ED91D92}">
                         <versionRange  minVersion="3.4.1" maxVersion="3.4.1.194" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i97" id="support3_en@adobe122.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
-                        <versionRange  minVersion="1.2" maxVersion="1.2">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.0a1" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com">
-                        <versionRange  minVersion="1.9.0" maxVersion="1.9.0" severity="1">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="9.0a1" maxVersion="9.*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
       <emItem  blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i100" id="{394DCBA4-1F92-4f8e-8EC9-8D2CB90CB69B}">
-                        <versionRange  minVersion="2.5.0" maxVersion="2.5.0" severity="1">
-                    </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>
-      <emItem  blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
-                        <versionRange  minVersion="2.0.3" maxVersion="2.0.3">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i51" id="admin@youtubeplayer.com">
+      <emItem  blockID="i101" id="{3a12052a-66ef-49db-8c39-e5b0bd5c83fa}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i68" id="flashupdate@adobe.com">
-                        <versionRange  minVersion="0" maxVersion="*">
+      <emItem  blockID="i5" id="support@daemon-tools.cc">
+                        <versionRange  minVersion=" " maxVersion="1.0.0.5">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
-                        </emItem>
-      <emItem  blockID="i90" id="videoplugin@player.com">
+      <emItem  blockID="i97" id="support3_en@adobe122.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i91" id="crossriderapp4926@crossrider.com">
-                        <versionRange  minVersion="0" maxVersion="0.81.43" severity="1">
+      <emItem  blockID="i11" id="yslow@yahoo-inc.com">
+                        <versionRange  minVersion="2.0.5" maxVersion="2.0.5">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.5.7" maxVersion="*" />
+                          </targetApplication>
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i84" id="pink@rosaplugin.info">
+      <emItem  blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}">
-                        <versionRange  minVersion="0.1" maxVersion="14.4.0" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i67" id="youtube2@youtube2.com">
+      <emItem  blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i60" id="youtb3@youtb3.com">
-                        <versionRange  minVersion="0" maxVersion="*">
+      <emItem  blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}">
+                        <versionRange  minVersion="1.1b1" maxVersion="1.1b1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i111" os="WINNT" id="{C3949AC2-4B17-43ee-B4F1-D26B9D42404D}">
                         <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i38" id="{B7082FAA-CB62-4872-9106-E42DD88EDE45}">
                         <versionRange  minVersion="0.1" maxVersion="3.3.0.*">
@@ -230,207 +103,347 @@
                           </targetApplication>
                     </versionRange>
                                 <versionRange  minVersion="3.3.1" maxVersion="*">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="5.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
+      <emItem  blockID="i98" id="youtubeeing@youtuberie.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i39" id="{c2d64ff7-0ab8-4263-89c9-ea3b0f8f050c}">
+                        <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i42" id="{D19CA586-DD6C-4a0a-96F8-14644F340D60}">
+                        <versionRange  minVersion="0.1" maxVersion="14.4.0" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i93" id="{68b8676b-99a5-46d1-b390-22411d8bcd61}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}">
+                        <versionRange  minVersion="2.0.3" maxVersion="2.0.3">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i63" id="youtube@youtuber.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i18" id="msntoolbar@msn.com">
+                        <versionRange  minVersion=" " maxVersion="6.*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
+                        <versionRange  minVersion="1.2" maxVersion="1.2">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i75" os="Darwin,Linux" id="firebug@software.joehewitt.com">
+                        <versionRange  minVersion="1.9.0" maxVersion="1.9.0" severity="1">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="9.0a1" maxVersion="9.*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i127" id="plugin@youtubeplayer.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i59" id="ghostviewer@youtube2.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i51" id="admin@youtubeplayer.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}">
+                        <versionRange  minVersion="0.1" maxVersion="*">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="9.0a1" maxVersion="9.0" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i22" id="ShopperReports@ShopperReports.com">
+                        <versionRange  minVersion="3.1.22.0" maxVersion="3.1.22.0">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i44" id="sigma@labs.mozilla">
+                        </emItem>
+      <emItem  blockID="i48" id="admin@youtubespeedup.com">
+                        </emItem>
+      <emItem  blockID="i109" id="{392e123b-b691-4a5e-b52f-c4c1027e749c}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i79" id="GifBlock@facebook.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}">
+                        <versionRange  minVersion="2.2" maxVersion="2.2">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i115" id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}">
+                        </emItem>
+      <emItem  blockID="i52" id="ff-ext@youtube">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i43" id="supportaccessplugin@gmail.com">
+                        </emItem>
+      <emItem  blockID="i54" id="applebeegifts@mozilla.doslash.org">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i16" id="{27182e60-b5f3-411c-b545-b44205977502}">
+                        <versionRange  minVersion="1.0" maxVersion="1.0">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i92" id="play5@vide04flash.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}">
+                        </emItem>
+      <emItem  blockID="i1" id="mozilla_cc@internetdownloadmanager.com">
+                        <versionRange  minVersion="2.1" maxVersion="3.3">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                                <versionRange  minVersion=" " maxVersion="6.9.8">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}">
+                        </emItem>
+      <emItem  blockID="i83" id="flash@adobee.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i104" id="yasd@youasdr3.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i76" id="crossriderapp3924@crossrider.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i91" id="crossriderapp4926@crossrider.com">
+                        <versionRange  minVersion="0" maxVersion="0.81.43" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i67" id="youtube2@youtube2.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i56" id="flash@adobe.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i2" id="fdm_ffext@freedownloadmanager.org">
+                        <versionRange  minVersion="1.0" maxVersion="1.3.1">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
+                        <versionRange  minVersion=" " maxVersion="8.5">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i12" id="masterfiler@gmail.com">
+                        <versionRange  severity="3">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
+                        <versionRange  minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i47" id="youtube@youtube2.com">
+                        </emItem>
+      <emItem  blockID="i103" id="kdrgun@gmail.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i3" id="langpack-vi-VN@firefox.mozilla.org">
+                        <versionRange  minVersion="2.0" maxVersion="2.0">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
+                        <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i15" id="personas@christopher.beard">
+                        <versionRange  minVersion="1.6" maxVersion="1.6">
+                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+                              <versionRange  minVersion="3.6" maxVersion="3.6.*" />
+                          </targetApplication>
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i86" id="{45147e67-4020-47e2-8f7a-55464fb535aa}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i108" id="{28bfb930-7620-11e1-b0c4-0800200c9a66}">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i61" id="youtube@youtube3.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                                <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i84" id="pink@rosaplugin.info">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i60" id="youtb3@youtb3.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
       <emItem  blockID="i23" id="firefox@bandoo.com">
                         <versionRange  minVersion="5.0" maxVersion="5.0" severity="1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
                               <versionRange  minVersion="3.7a1pre" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
       <emItem  blockID="i55" id="youtube@youtube7.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i47" id="youtube@youtube2.com">
-                        </emItem>
-      <emItem  blockID="i22" id="ShopperReports@ShopperReports.com">
-                        <versionRange  minVersion="3.1.22.0" maxVersion="3.1.22.0">
+      <emItem  blockID="i90" id="videoplugin@player.com">
+                        <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i2" id="fdm_ffext@freedownloadmanager.org">
-                        <versionRange  minVersion="1.0" maxVersion="1.3.1">
+      <emItem  blockID="i68" id="flashupdate@adobe.com">
+                        <versionRange  minVersion="0" maxVersion="*">
+                    </versionRange>
+                  </emItem>
+      <emItem  blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}">
+                        <versionRange  minVersion="0.1" maxVersion="7.6.1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.0a1" maxVersion="*" />
+                              <versionRange  minVersion="8.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i44" id="sigma@labs.mozilla">
-                        </emItem>
-      <emItem  blockID="i5" id="support@daemon-tools.cc">
-                        <versionRange  minVersion=" " maxVersion="1.0.0.5">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i6" id="{3f963a5b-e555-4543-90e2-c3908898db71}">
-                        <versionRange  minVersion=" " maxVersion="8.5">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i12" id="masterfiler@gmail.com">
-                        <versionRange  severity="3">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i48" id="admin@youtubespeedup.com">
-                        </emItem>
-      <emItem  blockID="i20" id="{AB2CE124-6272-4b12-94A9-7303C7397BD1}">
-                        <versionRange  minVersion="0.1" maxVersion="5.2.0.7164" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i104" id="yasd@youasdr3.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i76" id="crossriderapp3924@crossrider.com">
+      <emItem  blockID="i82" id="{8f42fb8b-b6f6-45de-81c0-d6d39f54f971}">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i79" id="GifBlock@facebook.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i115" id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i56" id="flash@adobe.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i103" id="kdrgun@gmail.com">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i99" id="pfzPXmnzQRXX6@2iABkVe.com">
-                        <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>
       <emItem  blockID="i73" id="a1g0a9g219d@a1.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
       <emItem  blockID="i96" id="youtubeee@youtuber3.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                   </emItem>
-      <emItem  blockID="i77" id="{fa277cfc-1d75-4949-a1f9-4ac8e41b2dfd}">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i106" os="WINNT" id="{97E22097-9A2F-45b1-8DAF-36AD648C7EF4}">
-                        <versionRange  minVersion="0" maxVersion="15.0.5" severity="1">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i11" id="yslow@yahoo-inc.com">
-                        <versionRange  minVersion="2.0.5" maxVersion="2.0.5">
+      <emItem  blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}">
+                        <versionRange  minVersion="0.1" maxVersion="1.3.328.4" severity="1">
                       <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.5.7" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i52" id="ff-ext@youtube">
-                        <versionRange  minVersion="0" maxVersion="*">
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}">
-                        <versionRange  minVersion="0.1" maxVersion="7.6.1">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="8.0a1" maxVersion="*" />
-                          </targetApplication>
-                    </versionRange>
-                  </emItem>
-      <emItem  blockID="i15" id="personas@christopher.beard">
-                        <versionRange  minVersion="1.6" maxVersion="1.6">
-                      <targetApplication  id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-                              <versionRange  minVersion="3.6" maxVersion="3.6.*" />
+                              <versionRange  minVersion="3.7a1pre" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                   </emItem>
       <emItem  blockID="i21" id="support@update-firefox.com">
                         </emItem>
     </emItems>
 
   <pluginItems>
+      <pluginItem  blockID="p32">
+                  <match name="filename" exp="npViewpoint.dll" />                      <versionRange >
+                      <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
+              <versionRange  minVersion="3.0" maxVersion="*" />
+            </targetApplication>
+                  </versionRange>
+                  </pluginItem>
       <pluginItem  blockID="p26">
       <match name="name" exp="^Yahoo Application State Plugin$" />      <match name="description" exp="^Yahoo Application State Plugin$" />      <match name="filename" exp="npYState.dll" />                      <versionRange >
                       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
               <versionRange  minVersion="3.0a1" maxVersion="3.*" />
             </targetApplication>
                   </versionRange>
                   </pluginItem>
       <pluginItem  blockID="p27">
       <match name="name" exp="QuickTime Plug-in 7[.]1[.]" />            <match name="filename" exp="npqtplugin.?[.]dll" />                      <versionRange >
                       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
               <versionRange  minVersion="3.0a1" maxVersion="3.*" />
             </targetApplication>
                   </versionRange>
                   </pluginItem>
-      <pluginItem  blockID="p28">
-                  <match name="filename" exp="NPFFAddOn.dll" />                        </pluginItem>
-      <pluginItem  blockID="p31">
-                  <match name="filename" exp="NPMySrch.dll" />                        </pluginItem>
-      <pluginItem  blockID="p32">
-                  <match name="filename" exp="npViewpoint.dll" />                      <versionRange >
-                      <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-              <versionRange  minVersion="3.0" maxVersion="*" />
-            </targetApplication>
-                  </versionRange>
-                  </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="p34">
                   <match name="filename" exp="[Nn][Pp][Jj][Pp][Ii]1[56]0_[0-9]+\.[Dd][Ll][Ll]" />                      <versionRange >
                       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
               <versionRange  minVersion="3.6a1pre" maxVersion="*" />
             </targetApplication>
                   </versionRange>
                   </pluginItem>
+      <pluginItem  blockID="p28">
+                  <match name="filename" exp="NPFFAddOn.dll" />                        </pluginItem>
+      <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="name" exp="\(TM\)" />      <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="p119">
+      <match name="name" exp="Java\(TM\) Plug-in 1\.(6\.0_(\d|[0-2]\d?|3[0-2])|7\.0(_0?([1-4]))?)([^\d\._]|$)" />            <match name="filename" exp="libnpjp2\.so" />                      <versionRange  severity="1"></versionRange>
+                  </pluginItem>
+      <pluginItem  blockID="p125">
+      <match name="name" exp="Java\(TM\) Platform SE ((6( U(\d|([0-2]\d)|3[0-2]))?)|(7(\sU[0-4])?))(\s[^\d\._U]|$)" />            <match name="filename" exp="npjp2\.dll" />                      <versionRange  severity="1"></versionRange>
+                  </pluginItem>
       <pluginItem  blockID="p85">
                   <match name="filename" exp="JavaPlugin2_NPAPI\.plugin" />                      <versionRange  minVersion="0" maxVersion="13.6.0" severity="1"></versionRange>
                   </pluginItem>
       <pluginItem  os="Darwin" blockID="p89">
                   <match name="filename" exp="AdobePDFViewerNPAPI\.plugin" />                      <versionRange  minVersion="0" maxVersion="10.1.3" severity="1"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p94">
                   <match name="filename" exp="(NPSWF32\.dll)|(Flash\ Player\.plugin)" />                      <versionRange  minVersion="0" maxVersion="10.2.159.1" severity="0"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p102">
                   <match name="filename" exp="npmozax\.dll" />                      <versionRange  minVersion="0" maxVersion="*"></versionRange>
                   </pluginItem>
       <pluginItem  blockID="p113">
                   <match name="filename" exp="npuplaypc\.dll" />                      <versionRange  minVersion="0" maxVersion="1.0.0.0" severity="1"></versionRange>
                   </pluginItem>
+      <pluginItem  blockID="p123">
+                  <match name="filename" exp="JavaPlugin2_NPAPI\.plugin" />                      <versionRange  minVersion="0" maxVersion="14.2.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/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1123,16 +1123,22 @@ pref("browser.panorama.animate_zoom", tr
 // Defines the url to be used for new tabs.
 pref("browser.newtab.url", "about:newtab");
 // Activates preloading of the new tab url.
 pref("browser.newtab.preload", false);
 
 // Toggles the content of 'about:newtab'. Shows the grid when enabled.
 pref("browser.newtabpage.enabled", true);
 
+// number of rows of newtab grid
+pref("browser.newtabpage.rows", 3);
+
+// number of columns of newtab grid
+pref("browser.newtabpage.columns", 3);
+
 // Enable the DOM fullscreen API.
 pref("full-screen-api.enabled", true);
 
 // True if the fullscreen API requires approval upon a domain entering fullscreen.
 // Domains that have already had fullscreen permission granted won't re-request
 // approval.
 pref("full-screen-api.approval-required", true);
 
--- a/browser/base/content/aboutRobots.xhtml
+++ b/browser/base/content/aboutRobots.xhtml
@@ -37,16 +37,20 @@
           var newLabel = button.getAttribute("label2");
           button.textContent = newLabel;
           buttonClicked = true;
         }
       }
     ]]></script>
 
     <style type="text/css"><![CDATA[
+      #errorPageContainer {
+        background-image: none;
+      }
+
       #errorPageContainer:before {
         content: url('chrome://browser/content/aboutRobots-icon.png');
         position: absolute;
       }
 
       body[dir=rtl] #icon,
       body[dir=rtl] #errorPageContainer:before {
         transform: scaleX(-1);
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -28,20 +28,28 @@ let SocialUI = {
   showProfile: function SocialUI_showProfile() {
     if (Social.provider)
       openUILink(Social.provider.profile.profileURL);
   },
 
   observe: function SocialUI_observe(subject, topic, data) {
     switch (topic) {
       case "social:pref-changed":
-        this.updateToggleCommand();
-        SocialShareButton.updateButtonHiddenState();
-        SocialToolbar.updateButtonHiddenState();
-        SocialSidebar.updateSidebar();
+        // Exceptions here sometimes don't get reported properly, report them
+        // manually :(
+        try {
+          this.updateToggleCommand();
+          SocialShareButton.updateButtonHiddenState();
+          SocialToolbar.updateButtonHiddenState();
+          SocialSidebar.updateSidebar();
+          SocialChatBar.update();
+        } catch (e) {
+          Components.utils.reportError(e);
+          throw e;
+        }
         break;
       case "social:ambient-notification-changed":
         SocialToolbar.updateButton();
         break;
       case "social:profile-changed":
         SocialToolbar.updateProfile();
         SocialShareButton.updateProfileInfo();
         break;
@@ -145,16 +153,37 @@ let SocialUI = {
   },
 
   undoActivation: function SocialUI_undoActivation() {
     Social.active = false;
     this.notificationPanel.hidePopup();
   }
 }
 
+let SocialChatBar = {
+  get chatbar() {
+    return document.getElementById("pinnedchats");
+  },
+  // Whether the chats can be shown for this window.
+  get canShow() {
+    let docElem = document.documentElement;
+    let chromeless = docElem.getAttribute("disablechrome") ||
+                     docElem.getAttribute("chromehidden").indexOf("extrachrome") >= 0;
+    return Social.uiVisible && !chromeless;
+  },
+  newChat: function(aProvider, aURL, aCallback) {
+    if (this.canShow)
+      this.chatbar.newChat(aProvider, aURL, aCallback);
+  },
+  update: function() {
+    if (!this.canShow)
+      this.chatbar.removeAll();
+  }
+}
+
 let SocialShareButton = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SSB_init() {
     this.updateButtonHiddenState();
     this.updateProfileInfo();
   },
 
   updateProfileInfo: function SSB_updateProfileInfo() {
@@ -248,45 +277,50 @@ let SocialShareButton = {
   }
 };
 
 var SocialToolbar = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SocialToolbar_init() {
     document.getElementById("social-provider-image").setAttribute("image", Social.provider.iconURL);
 
-    let notifBrowser = document.getElementById("social-notification-browser");
-    notifBrowser.docShell.isAppTab = true;
-
     let removeItem = document.getElementById("social-remove-menuitem");
     let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
     let label = gNavigatorBundle.getFormattedString("social.remove.label",
                                                     [brandShortName]);
     let accesskey = gNavigatorBundle.getString("social.remove.accesskey");
     removeItem.setAttribute("label", label);
     removeItem.setAttribute("accesskey", accesskey);
 
     let statusAreaPopup = document.getElementById("social-statusarea-popup");
-    statusAreaPopup.addEventListener("popupshowing", function(e) {
+    statusAreaPopup.addEventListener("popupshown", function(e) {
       this.button.setAttribute("open", "true");
     }.bind(this));
     statusAreaPopup.addEventListener("popuphidden", function(e) {
       this.button.removeAttribute("open");
     }.bind(this));
 
     this.updateButton();
     this.updateProfile();
   },
 
   get button() {
     return document.getElementById("social-toolbar-button");
   },
 
   updateButtonHiddenState: function SocialToolbar_updateButtonHiddenState() {
     this.button.hidden = !Social.uiVisible;
+    if (!Social.provider || !Social.provider.profile || !Social.provider.profile.userName) {
+      ["social-notification-box",
+       "social-status-iconbox"].forEach(function removeChildren(parentId) {
+        let parent = document.getElementById(parentId);
+        while(parent.hasChildNodes())
+          parent.removeChild(parent.firstChild);
+      });
+    }
   },
 
   updateProfile: function SocialToolbar_updateProfile() {
     // Profile may not have been initialized yet, since it depends on a worker
     // response. In that case we'll be called again when it's available, via
     // social:profile-changed
     let profile = Social.provider.profile || {};
     let userPortrait = profile.portrait || "chrome://browser/skin/social/social.png";
@@ -301,84 +335,143 @@ var SocialToolbar = {
     } else {
       notLoggedInLabel.hidden = false;
       userNameBtn.hidden = true;
     }
   },
 
   updateButton: function SocialToolbar_updateButton() {
     this.updateButtonHiddenState();
-
     let provider = Social.provider;
-    // if there are no ambient icons, we collapse them in the following loop
     let iconNames = Object.keys(provider.ambientNotificationIcons);
     let iconBox = document.getElementById("social-status-iconbox");
-    for (var i = 0; i < iconBox.childNodes.length; i++) {
-      let iconContainer = iconBox.childNodes[i];
-      if (i > iconNames.length - 1) {
-        iconContainer.collapsed = true;
-        continue;
+    let notifBox = document.getElementById("social-notification-box");
+    let notifBrowsers = document.createDocumentFragment();
+    let iconContainers = document.createDocumentFragment();
+
+    for each(let name in iconNames) {
+      let icon = provider.ambientNotificationIcons[name];
+
+      let notifBrowserId = "social-status-" + icon.name;
+      let notifBrowser = document.getElementById(notifBrowserId);
+      if (!notifBrowser) {
+        notifBrowser = document.createElement("iframe");
+        notifBrowser.setAttribute("type", "content");
+        notifBrowser.setAttribute("id", notifBrowserId);
+        notifBrowsers.appendChild(notifBrowser);
       }
-
-      iconContainer.collapsed = false;
-      let icon = provider.ambientNotificationIcons[iconNames[i]];
-      let iconImage = iconContainer.firstChild;
-      let iconCounter = iconImage.nextSibling;
+      notifBrowser.setAttribute("origin", provider.origin);
+      if (notifBrowser.getAttribute("src") != icon.contentPanel)
+        notifBrowser.setAttribute("src", icon.contentPanel);
 
-      iconImage.setAttribute("contentPanel", icon.contentPanel);
-      iconImage.setAttribute("src", icon.iconURL);
+      let iconId = "social-notification-icon-" + icon.name;
+      let iconContainer = document.getElementById(iconId);
+      let iconImage, iconCounter;
+      if (iconContainer) {
+        iconImage = iconContainer.getElementsByClassName("social-notification-icon-image")[0];
+        iconCounter = iconContainer.getElementsByClassName("social-notification-icon-counter")[0];
+      } else {
+        iconContainer = document.createElement("box");
+        iconContainer.setAttribute("id", iconId);
+        iconContainer.classList.add("social-notification-icon-container");
+        iconContainer.addEventListener("click", function (e) { SocialToolbar.showAmbientPopup(iconContainer); }, false);
 
-      if (iconCounter.firstChild)
-        iconCounter.removeChild(iconCounter.firstChild);
+        iconImage = document.createElement("image");
+        iconImage.classList.add("social-notification-icon-image");
+        iconImage = iconContainer.appendChild(iconImage);
 
-      if (icon.counter) {
-        iconCounter.appendChild(document.createTextNode(icon.counter));
-        iconCounter.collapsed = false;
-      } else {
-        iconCounter.collapsed = true;
+        iconCounter = document.createElement("box");
+        iconCounter.classList.add("social-notification-icon-counter");
+        iconCounter.appendChild(document.createTextNode(""));
+        iconCounter = iconContainer.appendChild(iconCounter);
+
+        iconContainers.appendChild(iconContainer);
       }
+      if (iconImage.getAttribute("src") != icon.iconURL)
+        iconImage.setAttribute("src", icon.iconURL);
+      iconImage.setAttribute("notifBrowserId", notifBrowserId);
+
+      iconCounter.collapsed = !icon.counter;
+      iconCounter.firstChild.textContent = icon.counter || "";
+    }
+    notifBox.appendChild(notifBrowsers);
+    iconBox.appendChild(iconContainers);
+
+    let browserIter = notifBox.firstElementChild;
+    while (browserIter) {
+      browserIter.docShell.isAppTab = true;
+      browserIter = browserIter.nextElementSibling;
     }
   },
 
   showAmbientPopup: function SocialToolbar_showAmbientPopup(iconContainer) {
     let iconImage = iconContainer.firstChild;
     let panel = document.getElementById("social-notification-panel");
-    let notifBrowser = document.getElementById("social-notification-browser");
+    let notifBox = document.getElementById("social-notification-box");
+    let notifBrowser = document.getElementById(iconImage.getAttribute("notifBrowserId"));
 
     panel.hidden = false;
 
     function sizePanelToContent() {
       // FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
       // Need to handle dynamic sizing
       let doc = notifBrowser.contentDocument;
+      if (!doc) {
+        return;
+      }
       // "notif" is an implementation detail that we should get rid of
       // eventually
-      let body = doc.getElementById("notif") || (doc.body && doc.body.firstChild);
-      if (!body)
+      let body = doc.getElementById("notif") || doc.body;
+      if (!body || !body.firstChild) {
         return;
-      let h = body.scrollHeight > 0 ? body.scrollHeight : 300;
-      notifBrowser.style.width = body.scrollWidth + "px";
-      notifBrowser.style.height = h + "px";
+      }
+
+      // Clear dimensions on all browsers so the panel size will
+      // only use the selected browser.
+      let browserIter = notifBox.firstElementChild;
+      while (browserIter) {
+        browserIter.hidden = (browserIter != notifBrowser);
+        browserIter = browserIter.nextElementSibling;
+      }
+
+      let [height, width] = [body.firstChild.offsetHeight || 300, 330];
+      notifBrowser.style.width = width + "px";
+      notifBrowser.style.height = height + "px";
     }
 
-    notifBrowser.addEventListener("DOMContentLoaded", function onload() {
-      notifBrowser.removeEventListener("DOMContentLoaded", onload);
-      sizePanelToContent();
-    });
+    sizePanelToContent();
+
+    function dispatchPanelEvent(name) {
+      let evt = notifBrowser.contentDocument.createEvent("CustomEvent");
+      evt.initCustomEvent(name, true, true, {});
+      notifBrowser.contentDocument.documentElement.dispatchEvent(evt);
+    }
 
     panel.addEventListener("popuphiding", function onpopuphiding() {
       panel.removeEventListener("popuphiding", onpopuphiding);
-      // unload the panel
       SocialToolbar.button.removeAttribute("open");
-      notifBrowser.setAttribute("src", "about:blank");
+      dispatchPanelEvent("socialFrameHide");
     });
 
-    notifBrowser.setAttribute("origin", Social.provider.origin);
-    notifBrowser.setAttribute("src", iconImage.getAttribute("contentPanel"));
-    this.button.setAttribute("open", "true");
+    panel.addEventListener("popupshown", function onpopupshown() {
+      panel.removeEventListener("popupshown", onpopupshown);
+      SocialToolbar.button.setAttribute("open", "true");
+      if (notifBrowser.contentDocument.readyState == "complete") {
+        dispatchPanelEvent("socialFrameShow");
+      } else {
+        // first time load, wait for load and dispatch after load
+        notifBrowser.addEventListener("load", function panelBrowserOnload(e) {
+          notifBrowser.removeEventListener("load", panelBrowserOnload, true);
+          setTimeout(function() {
+            dispatchPanelEvent("socialFrameShow");
+          }, 0);
+        }, true);
+      }
+    });
+
     panel.openPopup(iconImage, "bottomcenter topleft", 0, 0, false, false);
   }
 }
 
 var SocialSidebar = {
   // Called once, after window load, when the Social.provider object is initialized
   init: function SocialSidebar_init() {
     let sbrowser = document.getElementById("social-sidebar-browser");
@@ -421,33 +514,34 @@ var SocialSidebar = {
     // Hide the sidebar if it cannot appear, or has been toggled off.
     // Also set the command "checked" state accordingly.
     let hideSidebar = !this.canShow || !this.enabled;
     let broadcaster = document.getElementById("socialSidebarBroadcaster");
     broadcaster.hidden = hideSidebar;
     command.setAttribute("checked", !hideSidebar);
 
     let sbrowser = document.getElementById("social-sidebar-browser");
+    sbrowser.docShell.isActive = !hideSidebar;
     if (hideSidebar) {
-      this.dispatchEvent("sidebarhide");
+      this.dispatchEvent("socialFrameHide");
       // If we're disabled, unload the sidebar content
       if (!this.canShow) {
         sbrowser.removeAttribute("origin");
         sbrowser.setAttribute("src", "about:blank");
       }
     } else {
       // Make sure the right sidebar URL is loaded
       if (sbrowser.getAttribute("origin") != Social.provider.origin) {
         sbrowser.setAttribute("origin", Social.provider.origin);
         sbrowser.setAttribute("src", Social.provider.sidebarURL);
         sbrowser.addEventListener("load", function sidebarOnShow() {
           sbrowser.removeEventListener("load", sidebarOnShow);
           // let load finish, then fire our event
           setTimeout(function () {
-            SocialSidebar.dispatchEvent("sidebarshow");
+            SocialSidebar.dispatchEvent("socialFrameShow");
           }, 0);
         });
       } else {
-        this.dispatchEvent("sidebarshow");
+        this.dispatchEvent("socialFrameShow");
       }
     }
   }
 }
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -610,8 +610,17 @@ stack[anonid=browserStack][responsivemod
 
 stack[anonid=browserStack][responsivemode] {
   transition-property: min-width, max-width, min-height, max-height;
 }
 
 stack[anonid=browserStack][responsivemode][notransition] {
   transition: none;
 }
+
+chatbox {
+  -moz-binding: url("chrome://browser/content/socialchat.xml#chatbox");
+}
+
+chatbar {
+  -moz-binding: url("chrome://browser/content/socialchat.xml#chatbar");
+  height: 0;
+}
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3156,16 +3156,62 @@ var DownloadsButtonDNDObserver = {
 const DOMLinkHandler = {
   handleEvent: function (event) {
     switch (event.type) {
       case "DOMLinkAdded":
         this.onLinkAdded(event);
         break;
     }
   },
+  getLinkIconURI: function(aLink) {
+    let targetDoc = aLink.ownerDocument;
+    var uri = makeURI(aLink.href, targetDoc.characterSet);
+
+    // Verify that the load of this icon is legal.
+    // Some error or special pages can load their favicon.
+    // To be on the safe side, only allow chrome:// favicons.
+    var isAllowedPage = [
+      /^about:neterror\?/,
+      /^about:blocked\?/,
+      /^about:certerror\?/,
+      /^about:home$/,
+    ].some(function (re) re.test(targetDoc.documentURI));
+
+    if (!isAllowedPage || !uri.schemeIs("chrome")) {
+      var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].
+                getService(Ci.nsIScriptSecurityManager);
+      try {
+        ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri,
+                                      Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
+      } catch(e) {
+        return null;
+      }
+    }
+
+    try {
+      var contentPolicy = Cc["@mozilla.org/layout/content-policy;1"].
+                          getService(Ci.nsIContentPolicy);
+    } catch(e) {
+      return null; // Refuse to load if we can't do a security check.
+    }
+
+    // Security says okay, now ask content policy
+    if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
+                                 uri, targetDoc.documentURIObject,
+                                 aLink, aLink.type, null)
+                                 != Ci.nsIContentPolicy.ACCEPT)
+      return null;
+    
+    try {
+      uri.userPass = "";
+    } catch(e) {
+      // some URIs are immutable
+    }
+    return uri;
+  },
   onLinkAdded: function (event) {
     var link = event.originalTarget;
     var rel = link.rel && link.rel.toLowerCase();
     if (!link || !link.ownerDocument || !rel || !link.href)
       return;
 
     var feedAdded = false;
     var iconAdded = false;
@@ -3189,64 +3235,30 @@ const DOMLinkHandler = {
             }
           }
           break;
         case "icon":
           if (!iconAdded) {
             if (!gPrefService.getBoolPref("browser.chrome.site_icons"))
               break;
 
-            var targetDoc = link.ownerDocument;
-            var uri = makeURI(link.href, targetDoc.characterSet);
+            var uri = this.getLinkIconURI(link);
+            if (!uri)
+              break;
 
             if (gBrowser.isFailedIcon(uri))
               break;
 
-            // Verify that the load of this icon is legal.
-            // Some error or special pages can load their favicon.
-            // To be on the safe side, only allow chrome:// favicons.
-            var isAllowedPage = [
-              /^about:neterror\?/,
-              /^about:blocked\?/,
-              /^about:certerror\?/,
-              /^about:home$/,
-            ].some(function (re) re.test(targetDoc.documentURI));
-
-            if (!isAllowedPage || !uri.schemeIs("chrome")) {
-              var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].
-                        getService(Ci.nsIScriptSecurityManager);
-              try {
-                ssm.checkLoadURIWithPrincipal(targetDoc.nodePrincipal, uri,
-                                              Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
-              } catch(e) {
-                break;
-              }
-            }
-
-            try {
-              var contentPolicy = Cc["@mozilla.org/layout/content-policy;1"].
-                                  getService(Ci.nsIContentPolicy);
-            } catch(e) {
-              break; // Refuse to load if we can't do a security check.
-            }
-
-            // Security says okay, now ask content policy
-            if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
-                                         uri, targetDoc.documentURIObject,
-                                         link, link.type, null)
-                                         != Ci.nsIContentPolicy.ACCEPT)
-              break;
-
-            var browserIndex = gBrowser.getBrowserIndexForDocument(targetDoc);
+            var browserIndex = gBrowser.getBrowserIndexForDocument(link.ownerDocument);
             // no browser? no favicon.
             if (browserIndex == -1)
               break;
 
             let tab = gBrowser.tabs[browserIndex];
-            gBrowser.setIcon(tab, link.href);
+            gBrowser.setIcon(tab, uri.spec);
             iconAdded = true;
           }
           break;
         case "search":
           if (!searchAdded) {
             var type = link.type && link.type.toLowerCase();
             type = type.replace(/^\s+|\s*(?:;.*)?$/g, "");
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -264,17 +264,17 @@
                 label="&social.sharePopup.undo.label;"
                 accesskey="&social.sharePopup.undo.accesskey;"
                 command="Social:UnsharePage"/>
 #endif
       </hbox>
     </panel>
 
     <panel id="social-notification-panel" type="arrow" hidden="true" noautofocus="true">
-      <browser id="social-notification-browser" type="content" flex="1"/>
+      <box id="social-notification-box" flex="1"></box>
     </panel>
 
     <menupopup id="inspector-node-popup">
       <menuitem id="inspectorHTMLCopyInner"
                 label="&inspectorHTMLCopyInner.label;"
                 accesskey="&inspectorHTMLCopyInner.accesskey;"
                 command="Inspector:CopyInner"/>
       <menuitem id="inspectorHTMLCopyOuter"
@@ -680,31 +680,16 @@
                         type="checkbox"
                         autocheck="false"
                         command="Social:ToggleSidebar"
                         label="&social.toggleSidebar.label;"
                         accesskey="&social.toggleSidebar.accesskey;"/>
             </menupopup>
           </button>
           <hbox id="social-status-iconbox" flex="1">
-            <box class="social-notification-icon-container" collapsed="true"
-                     onclick="SocialToolbar.showAmbientPopup(this);">
-              <image class="social-notification-icon-image"/>
-              <box class="social-notification-icon-counter" collapsed="true"/>
-            </box>
-            <box class="social-notification-icon-container" collapsed="true"
-                     onclick="SocialToolbar.showAmbientPopup(this);">
-              <image class="social-notification-icon-image"/>
-              <box class="social-notification-icon-counter" collapsed="true"/>
-            </box>
-            <box class="social-notification-icon-container" collapsed="true"
-                     onclick="SocialToolbar.showAmbientPopup(this);">
-              <image class="social-notification-icon-image"/>
-              <box class="social-notification-icon-counter" collapsed="true"/>
-            </box>
           </hbox>
         </hbox>
       </toolbaritem>
 
       <toolbaritem id="bookmarks-menu-button-container"
                    class="chromeclass-toolbar-additional"
                    removable="true"
                    title="&bookmarksMenuButton.label;">
@@ -1061,16 +1046,17 @@
     <splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" hidden="true"/>
     <vbox id="appcontent" flex="1">
       <tabbrowser id="content" disablehistory="true"
                   flex="1" contenttooltip="aHTMLTooltip"
                   tabcontainer="tabbrowser-tabs"
                   contentcontextmenu="contentAreaContextMenu"
                   autocompletepopup="PopupAutoComplete"
                   onclick="contentAreaClick(event, false);"/>
+      <chatbar id="pinnedchats" layer="true" mousethrough="always"/>
       <statuspanel id="statusbar-display" inactive="true"/>
     </vbox>
     <splitter id="devtools-side-splitter" hidden="true"/>
     <vbox id="devtools-sidebar-box" hidden="true"
           style="min-width: 18em; width: 22em; max-width: 42em;" persist="width">
       <toolbar id="devtools-sidebar-toolbar"
                class="devtools-toolbar"
                nowindowdrag="true"/>
--- a/browser/base/content/newtab/grid.js
+++ b/browser/base/content/newtab/grid.js
@@ -17,41 +17,32 @@ let gGrid = {
   /**
    * The cached DOM fragment for sites.
    */
   _siteFragment: null,
 
   /**
    * All cells contained in the grid.
    */
-  get cells() {
-    let cells = [];
-    let children = this.node.querySelectorAll(".newtab-cell");
-    for (let i = 0; i < children.length; i++)
-      cells.push(new Cell(this, children[i]));
-
-    // Replace the getter with our cached value.
-    Object.defineProperty(this, "cells", {value: cells, enumerable: true});
-
-    return cells;
-  },
+  _cells: null,
+  get cells() this._cells,
 
   /**
    * All sites contained in the grid's cells. Sites may be empty.
    */
   get sites() [cell.site for each (cell in this.cells)],
 
   /**
    * Initializes the grid.
    * @param aSelector The query selector of the grid.
    */
   init: function Grid_init() {
     this._node = document.getElementById("newtab-grid");
     this._createSiteFragment();
-    this._draw();
+    this._render();
   },
 
   /**
    * Creates a new site in the grid.
    * @param aLink The new site's link.
    * @param aCell The cell that will contain the new site.
    * @return The newly created site.
    */
@@ -69,18 +60,18 @@ let gGrid = {
     this.cells.forEach(function (cell) {
       let node = cell.node;
       let child = node.firstElementChild;
 
       if (child)
         node.removeChild(child);
     }, this);
 
-    // Draw the grid again.
-    this._draw();
+    // Render the grid again.
+    this._render();
   },
 
   /**
    * Locks the grid to block all pointer events.
    */
   lock: function Grid_lock() {
     this.node.setAttribute("locked", "true");
   },
@@ -88,16 +79,42 @@ let gGrid = {
   /**
    * Unlocks the grid to allow all pointer events.
    */
   unlock: function Grid_unlock() {
     this.node.removeAttribute("locked");
   },
 
   /**
+   * Creates the newtab grid.
+   */
+  _renderGrid: function Grid_renderGrid() {
+    let row = document.createElementNS(HTML_NAMESPACE, "div");
+    let cell = document.createElementNS(HTML_NAMESPACE, "div");
+    row.classList.add("newtab-row");
+    cell.classList.add("newtab-cell");
+
+    // Clear the grid
+    this._node.innerHTML = "";
+
+    // Creates the structure of one row
+    for (let i = 0; i < gGridPrefs.gridColumns; i++) {
+      row.appendChild(cell.cloneNode(true));
+    }
+    // Creates the grid
+    for (let j = 0; j < gGridPrefs.gridRows; j++) {
+      this._node.appendChild(row.cloneNode(true));
+    }
+
+    // (Re-)initialize all cells.
+    let cellElements = this.node.querySelectorAll(".newtab-cell");
+    this._cells = [new Cell(this, cell) for (cell of cellElements)];
+  },
+
+  /**
    * Creates the DOM fragment that is re-used when creating sites.
    */
   _createSiteFragment: function Grid_createSiteFragment() {
     let site = document.createElementNS(HTML_NAMESPACE, "div");
     site.classList.add("newtab-site");
     site.setAttribute("draggable", "true");
 
     // Create the site's inner HTML code.
@@ -111,23 +128,41 @@ let gGrid = {
       '<input type="button" title="' + newTabString("block") + '"' +
       '       class="newtab-control newtab-control-block"/>';
 
     this._siteFragment = document.createDocumentFragment();
     this._siteFragment.appendChild(site);
   },
 
   /**
-   * Draws the grid, creates all sites and puts them into their cells.
+   * Renders the sites, creates all sites and puts them into their cells.
    */
-  _draw: function Grid_draw() {
+  _renderSites: function Grid_renderSites() {
     let cells = this.cells;
-
     // Put sites into the cells.
     let links = gLinks.getLinks();
     let length = Math.min(links.length, cells.length);
 
     for (let i = 0; i < length; i++) {
       if (links[i])
         this.createSite(links[i], cells[i]);
     }
+  },
+
+  /**
+   * Renders the grid.
+   */
+  _render: function Grid_render() {
+    if (this._shouldRenderGrid()) {
+      this._renderGrid();
+    }
+
+    this._renderSites();
+  },
+
+  _shouldRenderGrid : function Grid_shouldRenderGrid() {
+    let rowsLength = this._node.querySelectorAll(".newtab-row").length;
+    let cellsLength = this._node.querySelectorAll(".newtab-cell").length;
+
+    return (rowsLength != gGridPrefs.gridRows ||
+            cellsLength != (gGridPrefs.gridRows * gGridPrefs.gridColumns));
   }
 };
--- a/browser/base/content/newtab/newTab.js
+++ b/browser/base/content/newtab/newTab.js
@@ -15,17 +15,18 @@ Cu.import("resource:///modules/NewTabUti
 XPCOMUtils.defineLazyModuleGetter(this, "Rect",
   "resource://gre/modules/Geometry.jsm");
 
 let {
   links: gLinks,
   allPages: gAllPages,
   linkChecker: gLinkChecker,
   pinnedLinks: gPinnedLinks,
-  blockedLinks: gBlockedLinks
+  blockedLinks: gBlockedLinks,
+  gridPrefs: gGridPrefs
 } = NewTabUtils;
 
 XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
   return Services.strings.
     createBundle("chrome://browser/locale/newTab.properties");
 });
 
 function newTabString(name) gStringBundle.GetStringFromName('newtab.' + name);
--- a/browser/base/content/newtab/newTab.xul
+++ b/browser/base/content/newtab/newTab.xul
@@ -21,31 +21,16 @@
 
     <div id="newtab-vertical-margin">
       <div id="newtab-margin-top"/>
 
       <div id="newtab-horizontal-margin">
         <div class="newtab-side-margin"/>
 
         <div id="newtab-grid">
-          <div class="newtab-row">
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-          </div>
-          <div class="newtab-row">
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-          </div>
-          <div class="newtab-row">
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-            <div class="newtab-cell"/>
-          </div>
         </div>
 
         <div class="newtab-side-margin"/>
       </div>
 
       <div id="newtab-margin-bottom"/>
     </div>
     <input id="newtab-toggle" type="button"/>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/socialchat.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0"?>
+
+<bindings id="socialChatBindings"
+    xmlns="http://www.mozilla.org/xbl"
+    xmlns:xbl="http://www.mozilla.org/xbl"
+    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <binding id="chatbox">
+    <content orient="vertical" mousethrough="never">
+      <xul:hbox class="chat-titlebar" xbl:inherits="minimized">
+        <xul:image class="chat-status-icon" xbl:inherits="src=image"/>
+        <xul:label class="chat-title" flex="1" xbl:inherits="value=label,crop"/>
+        <xul:toolbarbutton class="chat-toggle-button chat-toolbarbutton"
+                           xbl:inherits="minimized"
+                           oncommand="document.getBindingParent(this).toggle();"/>
+        <xul:toolbarbutton class="chat-close-button chat-toolbarbutton"
+                           oncommand="document.getBindingParent(this).close();"/>
+      </xul:hbox>
+      <xul:iframe anonid="iframe" class="chat-frame" flex="1"
+                  xbl:inherits="src,origin,collapsed=minimized" type="content"/>
+    </content>
+
+    <implementation implements="nsIDOMEventListener">
+      <field name="iframe" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "iframe");
+      </field>
+
+      <method name="init">
+        <parameter name="aProvider"/>
+        <parameter name="aURL"/>
+        <parameter name="aCallback"/>
+        <body><![CDATA[
+          this._callback = aCallback;
+          this.setAttribute("origin", aProvider.origin);
+          this.setAttribute("src", aURL);
+        ]]></body>
+      </method>
+
+      <method name="close">
+        <body><![CDATA[
+          this.parentNode.remove(this);
+        ]]></body>
+      </method>
+
+      <method name="toggle">
+        <body><![CDATA[
+          let type;
+          if (this.getAttribute("minimized") == "true") {
+            this.removeAttribute("minimized");
+            type = "socialFrameShow";
+          } else {
+            this.setAttribute("minimized", "true");
+            type = "socialFrameHide";
+          }
+          // let the chat frame know if it is being shown or hidden
+          let evt = this.iframe.contentDocument.createEvent("CustomEvent");
+          evt.initCustomEvent(type, true, true, {});
+          this.iframe.contentDocument.documentElement.dispatchEvent(evt);
+        ]]></body>
+      </method>
+    </implementation>
+
+    <handlers>
+      <handler event="focus" phase="capturing">
+        this.parentNode.selectedChat = this;
+      </handler>
+      <handler event="DOMContentLoaded" action="if (this._callback) this._callback(this.iframe.contentWindow);"/>
+      <handler event="DOMTitleChanged" action="this.setAttribute('label', this.iframe.contentDocument.title);"/>
+      <handler event="DOMLinkAdded"><![CDATA[
+        // much of this logic is from DOMLinkHandler in browser.js
+        // this sets the presence icon for a chat user, we simply use favicon style updating
+        let link = event.originalTarget;
+        let rel = link.rel && link.rel.toLowerCase();
+        if (!link || !link.ownerDocument || !rel || !link.href)
+          return;
+        if (link.rel.indexOf("icon") < 0)
+          return;
+
+        let uri = DOMLinkHandler.getLinkIconURI(link);
+        if (!uri)
+          return;
+
+        // we made it this far, use it
+        this.setAttribute('image', uri.spec);
+      ]]></handler>
+    </handlers>
+  </binding>
+
+  <binding id="chatbar">
+    <content>
+      <xul:hbox align="end" pack="end" anonid="innerbox" class="chatbar-innerbox" mousethrough="always" flex="1">
+        <xul:toolbarbutton anonid="nub" class="chatbar-button" type="menu" collapsed="true" mousethrough="never">
+          <xul:menupopup anonid="nubMenu" oncommand="document.getBindingParent(this).swapChat(event)"/>
+        </xul:toolbarbutton>
+        <xul:spacer flex="1" anonid="spacer" class="chatbar-overflow-spacer"/>
+        <children/>
+      </xul:hbox>
+    </content>
+
+    <implementation implements="nsIDOMEventListener">
+
+      <field name="innerbox" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "innerbox");
+      </field>
+
+      <field name="menupopup" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "nubMenu");
+      </field>
+
+      <property name="emptyWidth">
+        <getter>
+          return document.getAnonymousElementByAttribute(this, "anonid", "spacer").boxObject.width;
+        </getter>
+      </property>
+
+      <field name="selectedChat"/>
+
+      <field name="menuitemMap">new WeakMap()</field>
+
+      <property name="firstCollapsedChild">
+        <getter><![CDATA[
+          let child = this.lastChild;
+          while (child && !child.collapsed) {
+            child = child.previousSibling;
+          }
+          return child;
+        ]]></getter>
+      </property>
+
+      <property name="firstVisibleChild">
+        <getter><![CDATA[
+          let child = this.firstChild;
+          while (child && child.collapsed) {
+            child = child.nextSibling;
+          }
+          return child;
+        ]]></getter>
+      </property>
+
+      <property name="firstRemovableChild">
+        <getter><![CDATA[
+          let child = this.firstChild;
+          // find the first visible non-focused chatbox, always keep one visible if we
+          // have enough width to do so.
+          while (child &&
+                (child.collapsed || child == this.selectedChat)) {
+            child = child.nextSibling;
+          }
+          if (!child && this.selectedChat) {
+            child = this.selectedChat;
+          }
+          return child;
+        ]]></getter>
+      </property>
+
+      <method name="resize">
+        <body><![CDATA[
+          let child = this.firstCollapsedChild;
+          if (child && this.emptyWidth > 200) {
+            this.showChat(child);
+          }
+          if (!this.firstCollapsedChild) {
+            window.removeEventListener("resize", this);
+            this.menupopup.parentNode.collapsed = true;
+          }
+        ]]></body>
+      </method>
+
+      <method name="handleEvent">
+        <parameter name="aEvent"/>
+        <body><![CDATA[
+          if (aEvent.type == "resize") {
+            this.resize();
+          }
+        ]]></body>
+      </method>
+
+      <method name="swapChat">
+        <parameter name="aEvent"/>
+        <body><![CDATA[
+          let menuitem = aEvent.target;
+          let newChat = menuitem.chat;
+          let oldChat = this.firstVisibleChild;
+          if (oldChat)
+            this.collapseChat(oldChat);
+          if (newChat) 
+            this.showChat(newChat);
+        ]]></body>
+      </method>
+
+      <method name="collapseChat">
+        <parameter name="aChatbox"/>
+        <body><![CDATA[
+          aChatbox.collapsed = true;
+          let menu = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem");
+          menu.setAttribute("label", aChatbox.iframe.contentDocument.title);
+          menu.chat = aChatbox;
+          this.menuitemMap.set(aChatbox, menu);
+          this.menupopup.appendChild(menu);
+          this.menupopup.parentNode.collapsed = false;
+        ]]></body>
+      </method>
+
+      <method name="showChat">
+        <parameter name="aChatbox"/>
+        <body><![CDATA[
+          let menuitem = this.menuitemMap.get(aChatbox);
+          this.menuitemMap.delete(aChatbox);
+          this.menupopup.removeChild(menuitem);
+          aChatbox.collapsed = false;
+        ]]></body>
+      </method>
+
+      <method name="remove">
+        <parameter name="aChatbox"/>
+        <body><![CDATA[
+          if (this.selectedChat == aChatbox) {
+            this.selectedChat = aChatbox.previousSibling ? aChatbox.previousSibling : aChatbox.nextSibling
+          }
+          this.removeChild(aChatbox);
+          this.resize();
+        ]]></body>
+      </method>
+
+      <method name="removeAll">
+        <body><![CDATA[
+          while (this.firstChild) {
+            this.removeChild(this.firstChild);
+          }
+        ]]></body>
+      </method>
+
+      <method name="newChat">
+        <parameter name="aProvider"/>
+        <parameter name="aURL"/>
+        <parameter name="aCallback"/>
+        <body><![CDATA[
+          let cb = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "chatbox");
+          this.selectedChat = cb;
+          this.appendChild(cb);
+          cb.init(aProvider, aURL, aCallback);
+        ]]></body>
+      </method>
+
+    </implementation>
+    <handlers>
+      <handler event="overflow"><![CDATA[
+        // make sure we're not getting an overflow from content
+        if (event.originalTarget != this.innerbox)
+          return;
+
+        let hasHidden = this.firstCollapsedChild;
+        let child = this.firstRemovableChild;
+        if (child)
+          this.collapseChat(child);
+        if (!hasHidden) {
+          window.addEventListener("resize", this);
+        }
+      ]]></handler>
+    </handlers>
+  </binding>
+
+</bindings>
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -59,16 +59,19 @@ endif
 # 480169)
 
 # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
 
 # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
 
 # browser_pageInfo.js + feed_tab.html is disabled for leaking (bug 767896)
 
+# browser_social_shareButton.js is disabled for not properly
+#   tearing down the social providers (bug 780010).
+
 _BROWSER_FILES = \
                  head.js \
                  browser_typeAheadFind.js \
                  browser_keywordSearch.js \
                  browser_allTabsPanel.js \
                  browser_alltabslistener.js \
                  browser_bug304198.js \
                  title_test.svg \
@@ -84,16 +87,17 @@ endif
                  browser_bug417483.js \
                  browser_bug419612.js \
                  browser_identity_UI.js \
                  browser_bug422590.js \
                  browser_bug424101.js \
                  browser_bug427559.js \
                  browser_bug432599.js \
                  browser_bug435035.js \
+                 browser_bug435325.js \
                  browser_bug441778.js \
                  browser_popupNotification.js \
                  browser_bug455852.js \
                  browser_bug460146.js \
                  browser_bug462673.js \
                  browser_bug477014.js \
                  browser_bug479408.js \
                  browser_bug479408_sample.html \
@@ -151,17 +155,16 @@ endif
                  browser_bug710878.js \
                  browser_bug719271.js \
                  browser_bug724239.js \
                  browser_bug735471.js \
                  browser_bug743421.js \
                  browser_bug749738.js \
                  browser_bug763468.js \
                  browser_bug767836.js \
-                 browser_social_shareButton.js \
                  browser_canonizeURL.js \
                  browser_customize.js \
                  browser_findbarClose.js \
                  browser_homeDrop.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
@@ -256,18 +259,21 @@ endif
                  browser_middleMouse_inherit.js \
                  redirect_bug623155.sjs \
                  browser_tabDrop.js \
                  browser_lastAccessedTab.js \
                  browser_bug734076.js \
                  browser_social_toolbar.js \
                  browser_social_sidebar.js \
                  browser_social_mozSocial_API.js \
+                 browser_social_isVisible.js \
+                 browser_social_chatwindow.js \
                  social_panel.html \
                  social_sidebar.html \
+                 social_chat.html \
                  social_window.html \
                  social_worker.js \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
rename from docshell/test/browser/browser_bug435325.js
rename to browser/base/content/test/browser_bug435325.js
--- a/docshell/test/browser/browser_bug435325.js
+++ b/browser/base/content/test/browser_bug435325.js
@@ -1,13 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /* Ensure that clicking the button in the Offline mode neterror page makes the browser go online. See bug 435325. */
-/* TEST_PATH=docshell/test/browser/browser_bug435325.js make -C $(OBJDIR) mochitest-browser-chrome */
 
 function test() {
   waitForExplicitFinish();
 
   gBrowser.selectedTab = gBrowser.addTab();
   window.addEventListener("DOMContentLoaded", checkPage, false);
 
   // Go offline and disable the cache, then try to load the test URL.
@@ -29,19 +28,18 @@ function checkPage() {
   is(gBrowser.contentDocument.documentURI.substring(0,27),
     "about:neterror?e=netOffline", "Loading the Offline mode neterror page.");
 
   // Now press the "Try Again" button
   ok(gBrowser.contentDocument.getElementById("errorTryAgain"),
     "The error page has got a #errorTryAgain element");
   gBrowser.contentDocument.getElementById("errorTryAgain").click();
 
-  ok(!Services.io.offline, "After clicking the Try Again button, we're back "
-   +" online. This depends on Components.interfaces.nsIDOMWindowUtils being "
-   +"available from untrusted content (bug 435325).");
+  ok(!Services.io.offline, "After clicking the Try Again button, we're back " +
+                           "online.");
 
   finish();
 }
 
 registerCleanupFunction(function() {
   Services.prefs.setBoolPref("browser.cache.disk.enable", true);
   Services.prefs.setBoolPref("browser.cache.memory.enable", true);
   Services.io.offline = false;
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_social_chatwindow.js
@@ -0,0 +1,94 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function test() {
+  waitForExplicitFinish();
+
+  let manifest = { // normal provider
+    name: "provider 1",
+    origin: "https://example.com",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    iconURL: "chrome://branding/content/icon48.png"
+  };
+  runSocialTestWithProvider(manifest, function (finishcb) {
+    runSocialTests(tests, undefined, undefined, function () {
+      let chats = document.getElementById("pinnedchats");
+      ok(chats.children.length == 0, "no chatty children left behind");
+      finishcb();
+    });
+  });
+}
+
+var tests = {
+  testOpenCloseChat: function(next) {
+    let chats = document.getElementById("pinnedchats");
+    let port = Social.provider.port;
+    ok(port, "provider has a port");
+    port.onmessage = function (e) {
+      let topic = e.data.topic;
+      switch (topic) {
+        case "got-sidebar-message":
+          port.postMessage({topic: "test-chatbox-open"});
+          break;
+        case "got-chatbox-visibility":
+          if (e.data.result == "hidden") {
+            ok(true, "chatbox got minimized");
+            chats.selectedChat.toggle();
+          } else if (e.data.result == "shown") {
+            ok(true, "chatbox got shown");
+            // close it now
+            let iframe = chats.selectedChat.iframe;
+            iframe.addEventListener("unload", function chatUnload() {
+              iframe.removeEventListener("unload", chatUnload, true);
+              ok(true, "got chatbox unload on close");
+              next();
+            }, true);
+            chats.selectedChat.close();
+          }
+          break;
+        case "got-chatbox-message":
+          ok(true, "got chatbox message");
+          ok(e.data.result == "ok", "got chatbox windowRef result: "+e.data.result);
+          chats.selectedChat.toggle();
+          break;
+      }
+    }
+    port.postMessage({topic: "test-init"});
+  },
+  testManyChats: function(next) {
+    // open enough chats to overflow the window, then check
+    // if the menupopup is visible
+    let port = Social.provider.port;
+    ok(port, "provider has a port");
+    let width = document.documentElement.boxObject.width;
+    let numToOpen = (width / 200) + 1;
+    port.onmessage = function (e) {
+      let topic = e.data.topic;
+      switch (topic) {
+        case "got-chatbox-message":
+          numToOpen--;
+          if (numToOpen >= 0) {
+            // we're waiting for all to open
+            ok(true, "got a chat window opened");
+            break;
+          }
+          // close our chats now
+          let chats = document.getElementById("pinnedchats");
+          ok(!chats.menupopup.parentNode.collapsed, "menu selection is visible");
+          while (chats.selectedChat) {
+            chats.selectedChat.close();
+          }
+          ok(!chats.selectedChat, "chats are all closed");
+          next();
+          break;
+      }
+    }
+    let num = numToOpen;
+    while (num-- > 0) {
+      port.postMessage({topic: "test-chatbox-open"});
+    }
+  }
+}
+
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_social_isVisible.js
@@ -0,0 +1,62 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function test() {
+  waitForExplicitFinish();
+
+  let manifest = { // normal provider
+    name: "provider 1",
+    origin: "https://example.com",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    iconURL: "chrome://branding/content/icon48.png"
+  };
+  runSocialTestWithProvider(manifest, function (finishcb) {
+    runSocialTests(tests, undefined, undefined, finishcb);
+  });
+}
+
+var tests = {
+  testSidebarMessage: function(next) {
+    let port = Social.provider.port;
+    ok(port, "provider has a port");
+    port.postMessage({topic: "test-init"});
+    Social.provider.port.onmessage = function (e) {
+      let topic = e.data.topic;
+      switch (topic) {
+        case "got-sidebar-message":
+          // The sidebar message will always come first, since it loads by default
+          ok(true, "got sidebar message");
+          next();
+          break;
+      }
+    };
+  },
+  testIsVisible: function(next) {
+    let port = Social.provider.port;
+    port.onmessage = function (e) {
+      let topic = e.data.topic;
+      switch (topic) {
+        case "got-isVisible-response":
+          is(e.data.result, true, "Sidebar should be visible by default");
+          Social.toggleSidebar();
+          next();
+      }
+    };
+    port.postMessage({topic: "test-isVisible"});
+  },
+  testIsNotVisible: function(next) {
+    let port = Social.provider.port;
+    port.onmessage = function (e) {
+      let topic = e.data.topic;
+      switch (topic) {
+        case "got-isVisible-response":
+          is(e.data.result, false, "Sidebar should be hidden");
+          Services.prefs.clearUserPref("social.sidebar.open");
+          next();
+      }
+    };
+    port.postMessage({topic: "test-isVisible"});
+  }
+}
--- a/browser/base/content/test/browser_social_mozSocial_API.js
+++ b/browser/base/content/test/browser_social_mozSocial_API.js
@@ -2,19 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
-    origin: "http://example.com",
-    sidebarURL: "http://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
+    origin: "https://example.com",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
     iconURL: "chrome://branding/content/icon48.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
@@ -24,46 +24,48 @@ var tests = {
 
     function checkNext() {
       if (iconsReady && gotSidebarMessage)
         triggerIconPanel();
     }
 
     function triggerIconPanel() {
       let statusIcons = document.getElementById("social-status-iconbox");
-      ok(!statusIcons.firstChild.collapsed, "status icon is visible");
+      ok(!statusIcons.firstChild.hidden, "status icon is visible");
       // Click the button to trigger its contentPanel
       let panel = document.getElementById("social-notification-panel");
       EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
     }
 
     let port = Social.provider.port;
     ok(port, "provider has a port");
-    port.postMessage({topic: "test-init"});
-    Social.provider.port.onmessage = function (e) {
+    port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-panel-message":
           ok(true, "got panel message");
-          // Wait for the panel to close before ending the test
-          let panel = document.getElementById("social-notification-panel");
-          panel.addEventListener("popuphidden", function hiddenListener() {
-            panel.removeEventListener("popuphidden", hiddenListener);
+          break;
+        case "got-social-panel-visibility":
+          if (e.data.result == "shown") {
+            ok(true, "panel shown");
+            let panel = document.getElementById("social-notification-panel");
+            panel.hidePopup();
+          } else if (e.data.result == "hidden") {
+            ok(true, "panel hidden");
             next();
-          });
-          panel.hidePopup();
-          break;
+          }
         case "got-sidebar-message":
           // The sidebar message will always come first, since it loads by default
           ok(true, "got sidebar message");
           gotSidebarMessage = true;
           checkNext();
           break;
       }
     }
+    port.postMessage({topic: "test-init"});
 
     // Our worker sets up ambient notification at the same time as it responds to
     // the workerAPI initialization. If it's already initialized, we can
     // immediately check the icons, otherwise wait for initialization by
     // observing the topic sent out by the social service.
     if (Social.provider.workerAPI.initialized) {
       iconsReady = true;
       checkNext();
--- a/browser/base/content/test/browser_social_sidebar.js
+++ b/browser/base/content/test/browser_social_sidebar.js
@@ -33,23 +33,23 @@ function doTest(finishcb) {
     if (shouldBeShown)
       is(browser.getAttribute('src'), Social.provider.sidebarURL, "sidebar url should be set");
   }
 
   // First check the the sidebar is initially visible, and loaded
   ok(!command.hidden, "toggle command should be visible");
   checkShown(true);
 
-  browser.addEventListener("sidebarhide", function sidebarhide() {
-    browser.removeEventListener("sidebarhide", sidebarhide);
+  browser.addEventListener("socialFrameHide", function sidebarhide() {
+    browser.removeEventListener("socialFrameHide", sidebarhide);
 
     checkShown(false);
 
-    browser.addEventListener("sidebarshow", function sidebarshow() {
-      browser.removeEventListener("sidebarshow", sidebarshow);
+    browser.addEventListener("socialFrameShow", function sidebarshow() {
+      browser.removeEventListener("socialFrameShow", sidebarshow);
 
       checkShown(true);
 
       // Finish the test
       finishcb();
     });
 
     // Toggle it back on
--- a/browser/base/content/test/browser_social_toolbar.js
+++ b/browser/base/content/test/browser_social_toolbar.js
@@ -57,16 +57,16 @@ var tests = {
     Social.provider.updateUserProfile({});
     // check dom values
     let portrait = document.getElementById("social-statusarea-user-portrait").getAttribute("src");
     is(portrait, "chrome://browser/skin/social/social.png", "portrait is generic");
     let userButton = document.getElementById("social-statusarea-username");
     ok(userButton.hidden, "username is not visible");
     let ambience = document.getElementById("social-status-iconbox").firstChild;
     while (ambience) {
-      ok(ambience.collapsed, "ambient icon is collapsed");
+      ok(ambience.collapsed, "ambient icon (" + ambience.id + ") is collapsed");
       ambience = ambience.nextSibling;
     }
     
     next();
   }
 }
 
--- a/browser/base/content/test/newtab/Makefile.in
+++ b/browser/base/content/test/newtab/Makefile.in
@@ -23,14 +23,15 @@ include $(topsrcdir)/config/rules.mk
 	browser_newtab_unpin.js \
 	browser_newtab_bug721442.js \
 	browser_newtab_bug722273.js \
 	browser_newtab_bug723102.js \
 	browser_newtab_bug723121.js \
 	browser_newtab_bug725996.js \
 	browser_newtab_bug734043.js \
 	browser_newtab_bug735987.js \
+	browser_newtab_bug752841.js \
 	browser_newtab_bug765628.js \
 	head.js \
 	$(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/newtab/browser_newtab_bug752841.js
@@ -0,0 +1,53 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
+const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
+
+function runTests() {
+  let testValues = [
+    {row: 0, column: 0},
+    {row: -1, column: -1},
+    {row: -1, column: 0},
+    {row: 0, column: -1},
+    {row: 2, column: 4},
+    {row: 2, column: 5},
+  ];
+
+  // Expected length of grid
+  let expectedValues = [1, 1, 1, 1, 8, 10];
+
+   // Values before setting new pref values (9 is the default value -> 3 x 3)
+  let previousValues = [9, 1, 1, 1, 1, 8];
+
+  let existingTab, existingTabGridLength, newTab, newTabGridLength;
+  yield addNewTabPageTab();
+  existingTab = gBrowser.selectedTab;
+
+  for (let i = 0; i < expectedValues.length; i++) {
+    gBrowser.selectedTab = existingTab;
+    existingTabGridLength = getGrid().cells.length;
+    is(existingTabGridLength, previousValues[i],
+      "Grid length of existing page before update is correctly.");
+
+    Services.prefs.setIntPref(PREF_NEWTAB_ROWS, testValues[i].row);
+    Services.prefs.setIntPref(PREF_NEWTAB_COLUMNS, testValues[i].column);
+
+    existingTabGridLength = getGrid().cells.length;
+    is(existingTabGridLength, expectedValues[i],
+      "Existing page grid is updated correctly.");
+
+    yield addNewTabPageTab();
+    newTab = gBrowser.selectedTab;
+    newTabGridLength = getGrid().cells.length;
+    is(newTabGridLength, expectedValues[i],
+      "New page grid is updated correctly.");
+
+    gBrowser.removeTab(newTab);
+  }
+
+  gBrowser.removeTab(existingTab);
+
+  Services.prefs.clearUserPref(PREF_NEWTAB_ROWS);
+  Services.prefs.clearUserPref(PREF_NEWTAB_COLUMNS);
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social_chat.html
@@ -0,0 +1,22 @@
+<html>
+  <head>
+    <meta charset="utf-8">
+    <script>
+      function pingWorker() {
+        var port = navigator.mozSocial.getWorker().port;
+        port.postMessage({topic: "chatbox-message", result: "ok"});
+      }
+      window.addEventListener("socialFrameShow", function(e) {
+        var port = navigator.mozSocial.getWorker().port;
+        port.postMessage({topic: "chatbox-visibility", result: "shown"});
+      }, false);
+      window.addEventListener("socialFrameHide", function(e) {
+        var port = navigator.mozSocial.getWorker().port;
+        port.postMessage({topic: "chatbox-visibility", result: "hidden"});
+      }, false);
+    </script>
+  </head>
+  <body onload="pingWorker();">
+    <p>This is a test social chat window.</p>
+  </body>
+</html>
--- a/browser/base/content/test/social_panel.html
+++ b/browser/base/content/test/social_panel.html
@@ -1,14 +1,22 @@
 <html>
   <head>
     <meta charset="utf-8">
     <script>
       function pingWorker() {
         var port = navigator.mozSocial.getWorker().port;
         port.postMessage({topic: "panel-message", result: "ok"});
       }
+      window.addEventListener("socialFrameShow", function(e) {
+        var port = navigator.mozSocial.getWorker().port;
+        port.postMessage({topic: "status-panel-visibility", result: "shown"});
+      }, false);
+      window.addEventListener("socialFrameHide", function(e) {
+        var port = navigator.mozSocial.getWorker().port;
+        port.postMessage({topic: "status-panel-visibility", result: "hidden"});
+      }, false);
     </script>
   </head>
   <body onload="pingWorker();">
     <p>This is a test social panel.</p>
   </body>
 </html>
--- a/browser/base/content/test/social_sidebar.html
+++ b/browser/base/content/test/social_sidebar.html
@@ -3,16 +3,21 @@
     <meta charset="utf-8">
     <script>
       var win;
       function pingWorker() {
         var port = navigator.mozSocial.getWorker().port;
         port.onmessage = function(e) {
           var topic = e.data.topic;
           switch (topic) {
+            case "test-chatbox-open":
+              navigator.mozSocial.openChatWindow("social_chat.html", function(chatwin) {
+                port.postMessage({topic: "chatbox-opened", result: chatwin ? "ok" : "failed"});
+              });
+              break;
             case "test-service-window":
               win = navigator.mozSocial.openServiceWindow("social_window.html", "test-service-window", "width=300,height=300");
               break;
             case "test-service-window-twice":
               win = navigator.mozSocial.openServiceWindow("social_window.html", "test-service-window", "width=300,height=300");
               var win2 = navigator.mozSocial.openServiceWindow("social_window.html", "test-service-window", "");
               var result;
               if (win == win2)
@@ -23,16 +28,19 @@
               break;
             case "test-close-service-window":
               win.addEventListener("unload", function watchClose() {
                 win.removeEventListener("unload", watchClose);
                 port.postMessage({topic: "service-window-closed-message", result: "ok"});
               }, false)
               win.close();
               break;
+            case "test-isVisible":
+              port.postMessage({topic: "test-isVisible-response", result: navigator.mozSocial.isVisible});
+              break;
           }
         }
         port.postMessage({topic: "sidebar-message", result: "ok"});
       }
     </script>
   </head>
   <body onload="pingWorker();">
     <p>This is a test social sidebar.</p>
--- a/browser/base/content/test/social_worker.js
+++ b/browser/base/content/test/social_worker.js
@@ -34,26 +34,44 @@ onconnect = function(e) {
         break;
       case "test-close-service-window":
         sidebarPort.postMessage({topic:"test-close-service-window"});
         break;
       case "panel-message":
         if (testPort && event.data.result == "ok")
           testPort.postMessage({topic:"got-panel-message"});
         break;
+      case "status-panel-visibility":
+        testPort.postMessage({topic:"got-social-panel-visibility", result: event.data.result });
+        break;
+      case "test-chatbox-open":
+        sidebarPort.postMessage({topic:"test-chatbox-open"});
+        break;
+      case "chatbox-message":
+        testPort.postMessage({topic:"got-chatbox-message", result: event.data.result});
+        break;
+      case "chatbox-visibility":
+        testPort.postMessage({topic:"got-chatbox-visibility", result: event.data.result});
+        break;
       case "social.initialize":
         // This is the workerAPI port, respond and set up a notification icon.
         port.postMessage({topic: "social.initialize-response"});
         let profile = {
           userName: "foo"
         };
         port.postMessage({topic: "social.user-profile", data: profile});
         let icon = {
           name: "testIcon",
           iconURL: "chrome://branding/content/icon48.png",
-          contentPanel: "http://example.com/browser/browser/base/content/test/social_panel.html",
+          contentPanel: "https://example.com/browser/browser/base/content/test/social_panel.html",
           counter: 1
         };
         port.postMessage({topic: "social.ambient-notification", data: icon});
         break;
+      case "test-isVisible":
+        sidebarPort.postMessage({topic: "test-isVisible"});
+        break;
+      case "test-isVisible-response":
+        testPort.postMessage({topic: "got-isVisible-response", result: event.data.result});
+        break;
     }
   }
 }
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -97,11 +97,12 @@ browser.jar:
 *       content/browser/jsConsoleOverlay.xul          (content/jsConsoleOverlay.xul)
 *       content/browser/softwareUpdateOverlay.xul  (content/softwareUpdateOverlay.xul)
 #endif
 *       content/browser/viewSourceOverlay.xul         (content/viewSourceOverlay.xul)
 #ifdef XP_WIN
         content/browser/win6BrowserOverlay.xul        (content/win6BrowserOverlay.xul)
 #endif
         content/browser/social-icon.png               (content/social-icon.png)
+        content/browser/socialchat.xml                (content/socialchat.xml)
 # the following files are browser-specific overrides
 *       content/browser/license.html                  (/toolkit/content/license.html)
 % override chrome://global/content/license.html chrome://browser/content/license.html
--- a/browser/components/feeds/src/FeedConverter.js
+++ b/browser/components/feeds/src/FeedConverter.js
@@ -280,17 +280,17 @@ FeedConverter.prototype = {
     // Check for a header that tells us there was no sniffing
     // The value doesn't matter.
     try {
       var httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
       // Make sure to check requestSucceeded before the potentially-throwing
       // getResponseHeader.
       if (!httpChannel.requestSucceeded) {
         // Just give up, but don't forget to cancel the channel first!
-        request.cancel(0x804b0002); // NS_BINDING_ABORTED
+        request.cancel(Cr.NS_BINDING_ABORTED);
         return;
       }
       var noSniff = httpChannel.getResponseHeader("X-Moz-Is-Feed");
     }
     catch (ex) {
       this._sniffed = true;
     }
 
--- a/browser/components/sessionstore/test/Makefile.in
+++ b/browser/components/sessionstore/test/Makefile.in
@@ -55,21 +55,16 @@ MOCHITEST_BROWSER_FILES = \
 	browser_461743.js \
 	browser_461743_sample.html \
 	browser_463205.js \
 	browser_463205_helper.html \
 	browser_463205_sample.html \
 	browser_463206.js \
 	browser_463206_sample.html \
 	browser_464199.js \
-	browser_464620_a.js \
-	browser_464620_a.html \
-	browser_464620_b.js \
-	browser_464620_b.html \
-	browser_464620_xd.html \
 	browser_465215.js \
 	browser_465223.js \
 	browser_466937.js \
 	browser_466937_sample.html \
 	browser_467409-backslashplosion.js \
 	browser_477657.js \
 	browser_480148.js \
 	browser_480893.js \
@@ -131,16 +126,30 @@ MOCHITEST_BROWSER_FILES = \
 	browser_701377.js \
 	browser_705597.js \
 	browser_707862.js \
 	browser_739531.js \
 	browser_739531_sample.html \
 	browser_739805.js \
 	$(NULL)
 
+# Disabled on Windows for frequent intermittent failures
+ifneq ($(OS_ARCH), WINNT)
+MOCHITEST_FILES += \
+	browser_464620_a.js \
+	browser_464620_a.html \
+	browser_464620_b.js \
+	browser_464620_b.html \
+	browser_464620_xd.html \
+	$(NULL)
+else
+$(warning browser_464620_a.js is disabled on Windows for intermittent failures. Bug 552424)
+$(warning browser_464620_b.js is disabled on Windows for intermittent failures. Bug 552424)
+endif
+
 ifneq ($(OS_ARCH),Darwin)
 MOCHITEST_BROWSER_FILES += \
 	browser_597071.js \
 	browser_625016.js \
 	$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -1,14 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/orion.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/debugger.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/debugger.css" type="text/css"?>
 <!DOCTYPE window [
 <!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd" >
  %debuggerDTD;
 ]>
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
--- a/browser/devtools/webconsole/WebConsoleUtils.jsm
+++ b/browser/devtools/webconsole/WebConsoleUtils.jsm
@@ -904,58 +904,73 @@ function JSPropertyProvider(aScope, aInp
 
   let completionPart = aInputValue.substring(beginning.startPos);
 
   // Don't complete on just an empty string.
   if (completionPart.trim() == "") {
     return null;
   }
 
-  let properties = completionPart.split(".");
-  let matchProp;
-  if (properties.length > 1) {
-    matchProp = properties.pop().trimLeft();
-    for (let i = 0; i < properties.length; i++) {
-      let prop = properties[i].trim();
-      if (!prop) {
-        return null;
-      }
+  let matches = null;
+  let matchProp = "";
+
+  let lastDot = completionPart.lastIndexOf(".");
+  if (lastDot > 0 &&
+      (completionPart[0] == "'" || completionPart[0] == '"') &&
+      completionPart[lastDot - 1] == completionPart[0]) {
+    // We are completing a string literal.
+    obj = obj.String.prototype;
+    matchProp = completionPart.slice(lastDot + 1);
+
+  }
+  else {
+    // We are completing a variable / a property lookup.
 
-      // If obj is undefined or null (which is what "== null" does),
-      // then there is no chance to run completion on it. Exit here.
-      if (obj == null) {
-        return null;
-      }
+    let properties = completionPart.split(".");
+    if (properties.length > 1) {
+      matchProp = properties.pop().trimLeft();
+      for (let i = 0; i < properties.length; i++) {
+        let prop = properties[i].trim();
+        if (!prop) {
+          return null;
+        }
 
-      // Check if prop is a getter function on obj. Functions can change other
-      // stuff so we can't execute them to get the next object. Stop here.
-      if (WCU.isNonNativeGetter(obj, prop)) {
-        return null;
-      }
-      try {
-        obj = obj[prop];
-      }
-      catch (ex) {
-        return null;
+        // If obj is undefined or null (which is what "== null" does),
+        // then there is no chance to run completion on it. Exit here.
+        if (obj == null) {
+          return null;
+        }
+
+        // Check if prop is a getter function on obj. Functions can change other
+        // stuff so we can't execute them to get the next object. Stop here.
+        if (WCU.isNonNativeGetter(obj, prop)) {
+          return null;
+        }
+        try {
+          obj = obj[prop];
+        }
+        catch (ex) {
+          return null;
+        }
       }
     }
-  }
-  else {
-    matchProp = properties[0].trimLeft();
-  }
+    else {
+      matchProp = properties[0].trimLeft();
+    }
 
-  // If obj is undefined or null (which is what "== null" does),
-  // then there is no chance to run completion on it. Exit here.
-  if (obj == null) {
-    return null;
-  }
+    // If obj is undefined or null (which is what "== null" does),
+    // then there is no chance to run completion on it. Exit here.
+    if (obj == null) {
+      return null;
+    }
 
-  // Skip Iterators and Generators.
-  if (WCU.isIteratorOrGenerator(obj)) {
-    return null;
+    // Skip Iterators and Generators.
+    if (WCU.isIteratorOrGenerator(obj)) {
+      return null;
+    }
   }
 
   let matches = Object.keys(getMatchedProps(obj, {matchProp:matchProp}));
 
   return {
     matchProp: matchProp,
     matches: matches.sort(),
   };
--- a/browser/devtools/webconsole/test/browser_webconsole_completion.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_completion.js
@@ -100,13 +100,20 @@ function testCompletion(hud) {
 
   // Test non-object autocompletion.
   input.value = "Object.name.sl";
   jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
   yield;
 
   is(jsterm.completeNode.value, "              ice", "non-object completion");
 
+  // Test string literal autocompletion.
+  input.value = "'Asimov'.sl";
+  jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
+  yield;
+
+  is(jsterm.completeNode.value, "           ice", "string literal completion");
+
   testDriver = jsterm = input = null;
   executeSoon(finishTest);
   yield;
 }
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -701,11 +701,12 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/webapprt/chrome/@AB_CD@@JAREXT@
 @BINPATH@/webapprt/chrome/@AB_CD@.manifest
 @BINPATH@/webapprt/components/CommandLineHandler.js
 @BINPATH@/webapprt/components/ContentPermission.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/Startup.jsm
 @BINPATH@/webapprt/modules/WebappRT.jsm
 @BINPATH@/webapprt/modules/WebappsHandler.jsm
 #endif
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -353,16 +353,19 @@ telemetryNoButtonLabel = No
 telemetryNoButtonAccessKey = N
 
 # Webapps notification popup
 webapps.install = Install
 webapps.install.accesskey = I
 #LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
 webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
 webapps.install.success = Application Installed
+# LOCALIZATION NOTE (webapps.uninstall.notification): %S will be replaced with the name of the uninstalled web app
+webapps.uninstall.notification = %S has been uninstalled from your computer.
+webapps.uninstall.label = Uninstall App
 
 # Telemetry opt-out prompt for Aurora and Nightly
 # LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
 # brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner preference.
 telemetryOptOutPrompt = %1$S sends information about performance, hardware, usage and customizations back to %2$S to help improve %3$S.
 
 # LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
 fullscreen.entered=%S is now fullscreen.
--- a/browser/modules/NewTabUtils.jsm
+++ b/browser/modules/NewTabUtils.jsm
@@ -19,16 +19,22 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyGetter(this, "gPrincipal", function () {
   let uri = Services.io.newURI("about:newtab", null, null);
   return Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
 });
 
 // The preference that tells whether this feature is enabled.
 const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
 
+// The preference that tells the number of rows of the newtab grid.
+const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
+
+// The preference that tells the number of columns of the newtab grid.
+const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
+
 // 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.
@@ -179,16 +185,70 @@ let AllPages = {
     this._addObserver = function () {};
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference])
 };
 
 /**
+ * Singleton that keeps Grid preferences
+ */
+let GridPrefs = {
+  /**
+   * Cached value that tells the number of rows of newtab grid.
+   */
+  _gridRows: null,
+  get gridRows() {
+    if (!this._gridRows) {
+      this._gridRows = Math.max(1, Services.prefs.getIntPref(PREF_NEWTAB_ROWS));
+    }
+
+    return this._gridRows;
+  },
+
+  /**
+   * Cached value that tells the number of columns of newtab grid.
+   */
+  _gridColumns: null,
+  get gridColumns() {
+    if (!this._gridColumns) {
+      this._gridColumns = Math.max(1, Services.prefs.getIntPref(PREF_NEWTAB_COLUMNS));
+    }
+
+    return this._gridColumns;
+  },
+
+
+  /**
+   * Initializes object. Adds a preference observer
+   */
+  init: function GridPrefs_init() {
+    Services.prefs.addObserver(PREF_NEWTAB_ROWS, this, false);
+    Services.prefs.addObserver(PREF_NEWTAB_COLUMNS, this, false);
+  },
+
+  /**
+   * Implements the nsIObserver interface to get notified when the preference
+   * value changes.
+   */
+  observe: function GridPrefs_observe(aSubject, aTopic, aData) {
+    if (aData == PREF_NEWTAB_ROWS) {
+      this._gridRows = null;
+    } else {
+      this._gridColumns = null;
+    }
+
+    AllPages.update();
+  }
+};
+
+GridPrefs.init();
+
+/**
  * Singleton that keeps track of all pinned links and their positions in the
  * grid.
  */
 let PinnedLinks = {
   /**
    * The cached list of pinned links.
    */
   _links: null,
@@ -601,10 +661,11 @@ let NewTabUtils = {
       AllPages.update();
     }, true);
   },
 
   links: Links,
   allPages: AllPages,
   linkChecker: LinkChecker,
   pinnedLinks: PinnedLinks,
-  blockedLinks: BlockedLinks
+  blockedLinks: BlockedLinks,
+  gridPrefs: GridPrefs
 };
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -2743,8 +2743,131 @@ stack[anonid=browserStack][responsivemod
 
 #social-notification-panel {
   min-height: 100px;
   min-width: 100px;
   max-height: 600px;
   max-width: 400px;
 }
 
+
+.chat-status-icon {
+  max-height: 16px;
+  max-width: 16px;
+  padding: 0;
+}
+
+.chat-toolbarbutton {
+  -moz-appearance: none;
+  border: none;
+  padding: 0;
+  margin: 0;
+  background: none;
+}
+
+.chat-toolbarbutton > .toolbarbutton-text {
+  display: none;
+}
+
+.chat-close-button {
+  list-style-image: url("chrome://global/skin/icons/close.png");
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.chat-close-button:hover {
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+.chat-close-button:hover:active {
+  -moz-image-region: rect(0, 48px, 16px, 32px);
+}
+
+
+.chat-toggle-button {
+  /* XXX get a real image for this */
+  list-style-image: url("chrome://global/skin/icons/checkbox.png");
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+.chat-toggle-button:hover {
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.chat-toggle-button[minimized="true"] {
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.chat-toggle-button[minimized="true"]:hover {
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+.chat-title {
+  font-weight: bold;
+  color: -moz-dialogtext;
+}
+
+.chat-titlebar {
+  background-image: linear-gradient(white, #ddd);
+  height: 20px;
+  min-height: 20px;
+  width: 100%;
+  margin: 0;
+  padding: 2px;
+  border: none;
+  border-bottom: 1px solid gray;
+}
+
+.chat-titlebar[minimized="true"] {
+  border-bottom: none;
+}
+
+.chat-frame {
+  padding: 0;
+  margin: 0;
+  overflow: hidden;
+}
+
+.chatbar-button {
+  /* XXX get a real image for this */
+  list-style-image: url("chrome://browser/skin/social/social.png");
+  border: none;
+  margin: 0;
+  padding: 2px;
+  height: 21px;
+  width: 21px;
+  border-top: 1px solid gray;
+  -moz-border-end: 1px solid gray;
+}
+
+.chatbar-button[open="true"],
+.chatbar-button:active:hover {
+  box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
+}
+
+/* toolbarbutton-icon */
+.chatbar-button > .toolbarbutton-text,
+.chatbar-button > .toolbarbutton-menu-dropmarker {
+  display: none;
+}
+
+.chatbar-innerbox {
+  background: transparent;
+  margin: -200px -1px 0 -1px;
+  overflow: hidden;
+}
+
+chatbar > chatbox {
+  height: 200px;
+  width: 200px;
+  background-color: white;
+  border: 1px solid gray;
+  border-bottom: none;
+}
+
+chatbar > chatbox[minimized="true"] {
+  width: 100px;
+  height: 20px;
+  border-bottom: none;
+}
+
+chatbar > chatbox + chatbox {
+  -moz-margin-start: -1px;
+}
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -3514,8 +3514,134 @@ stack[anonid=browserStack][responsivemod
 }
 
 #social-notification-panel .panel-arrow[side="right"] {
   list-style-image: url("chrome://browser/skin/social/panelarrow-horiz.png");
   margin-left: -1px;
 }
 
 /* === end of social toolbar panels === */
+
+
+.chat-status-icon {
+  max-height: 16px;
+  max-width: 16px;
+  padding: 0;
+}
+
+.chat-toolbarbutton {
+  -moz-appearance: none;
+  border: none;
+  padding: 0;
+  margin: 0;
+  background: none;
+}
+
+.chat-toolbarbutton > .toolbarbutton-text {
+  display: none;
+}
+
+.chat-close-button {
+  list-style-image: url("chrome://global/skin/icons/close.png");
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.chat-close-button:hover {
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+.chat-close-button:hover:active {
+  -moz-image-region: rect(0, 48px, 16px, 32px);
+}
+
+
+.chat-toggle-button {
+  /* XXX get a real image for this */
+  list-style-image: url("chrome://global/skin/icons/checkbox.png");
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+.chat-toggle-button:hover {
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.chat-toggle-button[minimized="true"] {
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.chat-toggle-button[minimized="true"]:hover {
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+.chat-title {
+  font-weight: bold;
+  color: -moz-dialogtext;
+}
+
+.chat-titlebar {
+  background-image: linear-gradient(white, #ddd);
+  height: 20px;
+  min-height: 20px;
+  width: 100%;
+  margin: 0;
+  padding: 2px;
+  border: none;
+  border-bottom: 1px solid #404040;
+}
+
+.chat-titlebar[minimized="true"] {
+  border-bottom: none;
+}
+
+.chat-frame {
+  padding: 0;
+  margin: 0;
+  overflow: hidden;
+}
+
+.chatbar-button {
+  /* XXX get a real image for this */
+  background-image: linear-gradient(white, #ddd);
+  list-style-image: url("chrome://browser/skin/social/social.png");
+  border: none;
+  margin: 0;
+  padding: 2px;
+  height: 21px;
+  width: 21px;
+  border-top: 1px solid #404040;
+  -moz-border-end: 1px solid #404040;
+}
+
+.chatbar-button[open="true"],
+.chatbar-button:active:hover {
+  box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
+}
+
+/* toolbarbutton-icon */
+.chatbar-button > .toolbarbutton-text,
+.chatbar-button > .toolbarbutton-menu-dropmarker {
+  display: none;
+}
+
+.chatbar-innerbox {
+  background: transparent;
+  margin: -200px -1px 0 -1px;
+  overflow: hidden;
+}
+
+chatbar > chatbox {
+  height: 200px;
+  width: 200px;
+  background-color: white;
+  border: 1px solid #404040;
+  border-bottom: none;
+}
+
+chatbar > chatbox[minimized="true"] {
+  width: 100px;
+  height: 20px;
+  border-bottom: none;
+}
+
+chatbar > chatbox + chatbox {
+  -moz-margin-start: -1px;
+}
+
--- a/browser/themes/winstripe/browser-aero.css
+++ b/browser/themes/winstripe/browser-aero.css
@@ -105,16 +105,22 @@
     -moz-margin-start: 0;
     -moz-margin-end: -3px;
   }
 
   .menu-accel,
   .menu-iconic-accel {
     color: graytext;
   }
+
+  .chatbar-button,
+  chatbar > chatbox {
+    border-color: #A9B7C9;
+  }
+  
 }
 
 @media (-moz-windows-compositor) {
   /* These should be hidden w/ glass enabled. Windows draws its own buttons. */
   .titlebar-button {
     display: none;
   }
 
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -3445,8 +3445,141 @@ stack[anonid=browserStack][responsivemod
 }
 
 #social-notification-panel {
   min-height: 100px;
   min-width: 100px;
   max-height: 600px;
   max-width: 400px;
 }
+
+
+.chat-status-icon {
+  max-height: 16px;
+  max-width: 16px;
+  padding: 0;
+}
+
+.chat-toolbarbutton {
+  -moz-appearance: none;
+  border: none;
+  padding: 0;
+  margin: 0;
+  background: none;
+}
+
+.chat-toolbarbutton > .toolbarbutton-text {
+  display: none;
+}
+
+.chat-close-button {
+  list-style-image: url("chrome://global/skin/icons/Close.gif");
+  padding: 2px 4px;
+}
+
+.chat-close-button:hover {
+  box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
+}
+
+.chat-close-button:hover:active {
+  box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
+}
+
+
+.chat-toggle-button {
+  /* XXX get a real image for this */
+  list-style-image: url("chrome://global/skin/icons/expand.png");
+}
+
+.chat-toggle-button:hover {
+  box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
+}
+
+.chat-toggle-button[minimized="true"] {
+  list-style-image: url("chrome://global/skin/icons/collapse.png");
+}
+
+.chat-toggle-button[minimized="true"]:hover {
+  box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
+}
+
+.chat-title {
+  font-weight: bold;
+  color: -moz-dialogtext;
+}
+
+.chat-titlebar {
+  background-image: linear-gradient(white, #ddd);
+  height: 20px;
+  min-height: 20px;
+  width: 100%;
+  margin: 0;
+  padding: 2px;
+  border: none;
+  border-bottom: 1px solid gray;
+}
+
+.chat-titlebar[minimized="true"] {
+  border-bottom: none;
+}
+
+.chat-frame {
+  padding: 0;
+  margin: 0;
+  overflow: hidden;
+}
+
+.chatbar-button {
+  /* XXX get a real image for this */
+  -moz-appearance: none;
+  list-style-image: url("chrome://browser/skin/social/social.png");
+  background-image: linear-gradient(white, #ddd);
+  border: none;
+  margin: 0;
+  padding: 2px;
+  height: 21px;
+  width: 21px;
+  border-top: 1px solid gray;
+  -moz-border-end: 1px solid gray;
+}
+
+.chatbar-button > .button-box > .box-inherit > .button-icon {
+  max-height: 16px;
+  max-width: 16px;
+  padding: 2px;
+}
+
+.chatbar-button[open="true"],
+.chatbar-button:hover,
+.chatbar-button:active:hover {
+  box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), 0 1px rgba(255,255,255,0.2);
+}
+
+/* toolbarbutton-icon */
+.chatbar-button > .toolbarbutton-text,
+.chatbar-button > .toolbarbutton-menu-dropmarker {
+  display: none;
+}
+
+.chatbar-innerbox {
+  background: transparent;
+  margin: -200px -1px 0 -1px;
+  overflow: hidden;
+}
+
+chatbar > chatbox {
+  height: 200px;
+  width: 200px;
+  background-color: white;
+  border: 1px solid gray;
+  border-bottom: none;
+}
+
+chatbar > chatbox[minimized="true"] {
+  width: 100px;
+  height: 20px;
+  border-bottom: none;
+}
+
+chatbar > chatbox + chatbox {
+  -moz-margin-start: -1px;
+}
+
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -80,17 +80,21 @@ dnl A high level macro for selecting com
 AC_DEFUN([MOZ_COMPILER_OPTS],
 [
   MOZ_RTTI
 if test "$CLANG_CXX"; then
     ## We disable return-type-c-linkage because jsval is defined as a C++ type but is
     ## returned by C functions. This is possible because we use knowledge about the ABI
     ## to typedef it to a C type with the same layout when the headers are included
     ## from C.
-    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
+    ##
+    ## mismatched-tags is disabled (bug 780474) mostly because it's useless.
+    ## Worse, it's not supported by gcc, so it will cause tryserver bustage
+    ## without any easy way for non-Clang users to check for it.
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-mismatched-tags"
 fi
 
 if test "$GNU_CC"; then
     CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
     CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fno-exceptions"
 fi
 
 dnl ========================================================
--- a/build/autoconf/config.status.m4
+++ b/build/autoconf/config.status.m4
@@ -69,28 +69,30 @@ test "x$exec_prefix" = xNONE && exec_pre
 trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
 
 : ${CONFIG_STATUS=./config.status}
 
 dnl We're going to need [ ] for python syntax.
 changequote(<<<, >>>)dnl
 echo creating $CONFIG_STATUS
 
+extra_python_path=${COMM_BUILD:+"'mozilla', "}
+
 cat > $CONFIG_STATUS <<EOF
 #!${PYTHON}
 # coding=$encoding
 
 import os, sys
 dnl topsrcdir is the top source directory in native form, as opposed to a
 dnl form suitable for make.
 topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
 if not os.path.isabs(topsrcdir):
     topsrcdir = os.path.normpath(os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir))
 dnl Don't rely on virtualenv here. Standalone js doesn't use it.
-sys.path.append(os.path.join(topsrcdir, ${COMM_BUILD:+'mozilla',} 'build'))
+sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
 from ConfigStatus import config_status
 
 args = {
     'topsrcdir': topsrcdir,
     'topobjdir': os.path.dirname(<<<__file__>>>),
 
 dnl All defines and substs are stored with an additional space at the beginning
 dnl and at the end of the string, to avoid any problem with values starting or
--- a/build/mobile/sutagent/android/CmdWorkerThread.java
+++ b/build/mobile/sutagent/android/CmdWorkerThread.java
@@ -93,17 +93,17 @@ public class CmdWorkerThread extends Thr
         try {
             OutputStream cmdOut = socket.getOutputStream();
             InputStream cmdIn = socket.getInputStream();
             PrintWriter out = new PrintWriter(cmdOut, true);
             BufferedInputStream in = new BufferedInputStream(cmdIn);
             String inputLine, outputLine;
             DoCommand dc = new DoCommand(theParent.svc);
 
-            SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "CmdWorkerThread starts: "+getId());
+            SUTAgentAndroid.logToFile(dc, "CmdWorkerThread starts: "+getId());
 
             int nAvail = cmdIn.available();
             cmdIn.skip(nAvail);
 
             out.print(prompt);
             out.flush();
 
             while (bListening)
@@ -131,17 +131,17 @@ public class CmdWorkerThread extends Thr
                     }
                 else
                     inputLine = "";
 
                 if ((inputLine += readLine(in)) != null)
                     {
                     String message = String.format("%s : %s",
                                      socket.getInetAddress().getHostAddress(), inputLine);
-                    SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), message);
+                    SUTAgentAndroid.logToFile(dc, message);
 
                     outputLine = dc.processCommand(inputLine, out, in, cmdOut);
                     if (outputLine.length() > 0)
                         {
                         out.print(outputLine + "\n" + prompt);
                         }
                     else
                         out.print(prompt);
@@ -161,17 +161,17 @@ public class CmdWorkerThread extends Thr
                 else
                     break;
                 }
             out.close();
             out = null;
             in.close();
             in = null;
             socket.close();
-            SUTAgentAndroid.logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "CmdWorkerThread ends: "+getId());
+            SUTAgentAndroid.logToFile(dc, "CmdWorkerThread ends: "+getId());
         }
     catch (IOException e)
         {
         // TODO Auto-generated catch block
         e.printStackTrace();
         }
     }
 }
--- a/build/mobile/sutagent/android/SUTAgentAndroid.java
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -70,16 +70,17 @@ public class SUTAgentAndroid extends Act
     public PrintWriter dataOut = null;
 
     private static boolean bNetworkingStarted = false;
     private static String RegSvrIPAddr = "";
     private static String RegSvrIPPort = "";
     private static String HardwareID = "";
     private static String Pool = "";
     private static String sRegString = "";
+    private static boolean LogCommands = false;
 
     private WifiLock wl = null;
 
     private BroadcastReceiver battReceiver = null;
 
     private TextView  tv = null;
 
     public boolean onCreateOptionsMenu(Menu menu)
@@ -147,27 +148,30 @@ public class SUTAgentAndroid extends Act
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.main);
 
         fixScreenOrientation();
 
         DoCommand dc = new DoCommand(getApplication());
 
-        logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onCreate");
-
         // Get configuration settings from "ini" file
         File dir = getFilesDir();
         File iniFile = new File(dir, "SUTAgent.ini");
         String sIniFile = iniFile.getAbsolutePath();
 
+        String lc = dc.GetIniData("General", "LogCommands", sIniFile);
+        if (lc != "" && Integer.parseInt(lc) == 1) {
+            SUTAgentAndroid.LogCommands = true;
+        }
         SUTAgentAndroid.RegSvrIPAddr = dc.GetIniData("Registration Server", "IPAddr", sIniFile);
         SUTAgentAndroid.RegSvrIPPort = dc.GetIniData("Registration Server", "PORT", sIniFile);
         SUTAgentAndroid.HardwareID = dc.GetIniData("Registration Server", "HARDWARE", sIniFile);
         SUTAgentAndroid.Pool = dc.GetIniData("Registration Server", "POOL", sIniFile);
+        logToFile(dc, "onCreate");
 
         tv = (TextView) this.findViewById(R.id.Textview01);
 
         if (getLocalIpAddress() == null)
             setUpNetwork(sIniFile);
 
         String macAddress = "Unknown";
         if (android.os.Build.VERSION.SDK_INT > 8) {
@@ -349,61 +353,61 @@ public class SUTAgentAndroid extends Act
             {
                Toast.makeText(getApplication().getApplicationContext(), "SUTAgent startprg finished ...", Toast.LENGTH_LONG).show();
             }
         }
 
     @Override
     public void onDestroy()
         {
+        DoCommand dc = new DoCommand(getApplication());
         super.onDestroy();
-        DoCommand dc = new DoCommand(getApplication());
         if (isFinishing())
             {
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onDestroy - finishing");
+            logToFile(dc, "onDestroy - finishing");
             Intent listenerSvc = new Intent(this, ASMozStub.class);
             listenerSvc.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
             stopService(listenerSvc);
             bNetworkingStarted = false;
 
             unregisterReceiver(battReceiver);
 
             if (wl != null)
                 wl.release();
 
             System.exit(0);
             }
         else
             {
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onDestroy - not finishing");
+            logToFile(dc, "onDestroy - not finishing");
             }
         }
 
     @Override
     public void onLowMemory()
         {
         System.gc();
         DoCommand dc = new DoCommand(getApplication());
         if (dc != null)
             {
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), "onLowMemory");
-            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.GetMemoryInfo());
+            logToFile(dc, "onLowMemory");
+            logToFile(dc, dc.GetMemoryInfo());
             String procInfo = dc.GetProcessInfo();
             if (procInfo != null)
                 {
                 String lines[] = procInfo.split("\n");
                 for (String line : lines) 
                     {
                     if (line.contains("mozilla"))
                         {
-                        logToFile(dc.GetTestRoot(), dc.GetSystemTime(), line);
+                        logToFile(dc, line);
                         String words[] = line.split("\t");
                         if ((words != null) && (words.length > 1))
                             {
-                            logToFile(dc.GetTestRoot(), dc.GetSystemTime(), dc.StatProcess(words[1]));
+                            logToFile(dc, dc.StatProcess(words[1]));
                             }
                         }
                     }
                 }
             }
         else
             {
             Log.e("SUTAgentAndroid", "onLowMemory: unable to log to file!");
@@ -753,27 +757,39 @@ public class SUTAgentAndroid extends Act
             }
         catch (SocketException ex)
             {
             Toast.makeText(getApplication().getApplicationContext(), ex.toString(), Toast.LENGTH_LONG).show();
             }
         return null;
         }
 
-    public static void logToFile(String testRoot, String datestamp, String message)
+    public static void logToFile(DoCommand dc, String message)
         {
-        if (testRoot == null ||
-            datestamp == null ||
-            message == null)
+        if (SUTAgentAndroid.LogCommands == false)
+            {
+            return;
+            }
+
+        if (message == null)
             {
             Log.e("SUTAgentAndroid", "bad arguments in logToFile()!");
             return;
             }
         Log.i("SUTAgentAndroid", message);
         String fileDateStr = "00";
+        String testRoot = dc.GetTestRoot();
+        String datestamp = dc.GetSystemTime();
+        if (testRoot == null || datestamp == null)
+            {
+            Log.e("SUTAgentAndroid", "Unable to get testRoot or datestamp in logToFile!");
+            return;
+            }
+
+
         try 
             {
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
             Date dateStr = sdf.parse(datestamp);
             SimpleDateFormat sdf_file = new SimpleDateFormat("yyyy-MM-dd");
             fileDateStr = sdf_file.format(dateStr);
             } 
         catch (ParseException pe) {}
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -16,17 +16,17 @@ struct JSPrincipals;
 
 interface nsIURI;
 interface nsIContentSecurityPolicy;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 [ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
 
-[scriptable, uuid(6df7d16d-5b26-42a1-b1f7-069d46c37aa8)]
+[scriptable, uuid(825ffce8-962d-11e1-aef3-8f2b6188709b)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Values of capabilities for each principal. Order is
      * significant: if an operation is performed on a set
      * of capabilities, the minimum is computed.
      */
     const short ENABLE_DENIED                = 1;
@@ -168,33 +168,43 @@ interface nsIPrincipal : nsISerializable
      */
     boolean subsumesIgnoringDomain(in nsIPrincipal other);
 
     /**
      * Checks whether this principal is allowed to load the network resource
      * located at the given URI under the same-origin policy. This means that
      * codebase principals are only allowed to load resources from the same
      * domain, the system principal is allowed to load anything, and null
-     * principals are not allowed to load anything.
+     * principals are not allowed to load anything. This is changed slightly
+     * by the optional flag allowIfInheritsPrincipal (which defaults to false)
+     * which allows the load of a data: URI (which inherits the principal of
+     * its loader) or a URI with the same principal as its loader (eg. a 
+     * Blob URI).
+     * In these cases, with allowIfInheritsPrincipal set to true, the URI can
+     * be loaded by a null principal.
      *
      * If the load is allowed this function does nothing. If the load is not
      * allowed the function throws NS_ERROR_DOM_BAD_URI.
      *
      * NOTE: Other policies might override this, such as the Access-Control
      *       specification.
      * NOTE: The 'domain' attribute has no effect on the behaviour of this
      *       function.
      *
      *
      * @param uri    The URI about to be loaded.
      * @param report If true, will report a warning to the console service
      *               if the load is not allowed.
+     * @param allowIfInheritsPrincipal   If true, the load is allowed if the
+     *                                   loadee inherits the principal of the
+     *                                   loader.
      * @throws NS_ERROR_DOM_BAD_URI if the load is not allowed.
      */
-    void checkMayLoad(in nsIURI uri, in boolean report);
+    void checkMayLoad(in nsIURI uri, in boolean report,
+                      in boolean allowIfInheritsPrincipal);
 
     /**
      * The subject name for the certificate.  This actually identifies the
      * subject of the certificate.  This may well not be a string that would
      * mean much to a typical user on its own (e.g. it may have a number of
      * different names all concatenated together with some information on what
      * they mean in between).
      *
--- a/caps/include/nsNullPrincipal.h
+++ b/caps/include/nsNullPrincipal.h
@@ -10,16 +10,17 @@
  */
 
 #ifndef nsNullPrincipal_h__
 #define nsNullPrincipal_h__
 
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
 #include "nsCOMPtr.h"
+#include "nsPrincipal.h"
 
 class nsIURI;
 
 #define NS_NULLPRINCIPAL_CLASSNAME "nullprincipal"
 #define NS_NULLPRINCIPAL_CID \
 { 0xdd156d62, 0xd26f, 0x4441, \
  { 0x9c, 0xdb, 0xe8, 0xf0, 0x91, 0x07, 0xc2, 0x73 } }
 #define NS_NULLPRINCIPAL_CONTRACTID "@mozilla.org/nullprincipal;1"
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -8,16 +8,19 @@
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsVoidArray.h"
 #include "nsHashtable.h"
 #include "nsJSPrincipals.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
+#include "nsIProtocolHandler.h"
+#include "nsNetUtil.h"
+#include "nsScriptSecurityManager.h"
 
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
 class DomainPolicy; 
 
 class nsBasePrincipal : public nsJSPrincipals
 {
 public:
@@ -118,17 +121,17 @@ public:
   NS_IMETHOD EqualsIgnoringDomain(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD GetHashValue(PRUint32* aHashValue);
   NS_IMETHOD GetURI(nsIURI** aURI);
   NS_IMETHOD GetDomain(nsIURI** aDomain);
   NS_IMETHOD SetDomain(nsIURI* aDomain);
   NS_IMETHOD GetOrigin(char** aOrigin);
   NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
-  NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
+  NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
   NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
   NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
   NS_IMETHOD GetAppId(PRUint32* aAppStatus);
   NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
 #ifdef DEBUG
   virtual void dumpImpl();
 #endif
 
@@ -153,16 +156,33 @@ public:
                               bool aIsCert,
                               bool aTrusted,
                               PRUint32 aAppId,
                               bool aInMozBrowser);
 
   virtual void GetScriptLocation(nsACString& aStr) MOZ_OVERRIDE;
   void SetURI(nsIURI* aURI);
 
+  static bool IsPrincipalInherited(nsIURI* aURI) {
+    // return true if the loadee URI has
+    // the URI_INHERITS_SECURITY_CONTEXT flag set.
+    bool doesInheritSecurityContext;
+    nsresult rv =
+    NS_URIChainHasFlags(aURI,
+                        nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
+                        &doesInheritSecurityContext);
+
+    if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
+      return true;
+    }
+
+    return false;
+  }
+
+
   /**
    * Computes the puny-encoded origin of aURI.
    */
   static nsresult GetOriginForURI(nsIURI* aURI, char **aOrigin);
 
   nsCOMPtr<nsIURI> mDomain;
   nsCOMPtr<nsIURI> mCodebase;
   PRUint32 mAppId;
@@ -197,17 +217,17 @@ public:
   NS_IMETHOD EqualsIgnoringDomain(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD GetHashValue(PRUint32* aHashValue);
   NS_IMETHOD GetURI(nsIURI** aURI);
   NS_IMETHOD GetDomain(nsIURI** aDomain);
   NS_IMETHOD SetDomain(nsIURI* aDomain);
   NS_IMETHOD GetOrigin(char** aOrigin);
   NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD SubsumesIgnoringDomain(nsIPrincipal* other, bool* _retval);
-  NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report);
+  NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
   NS_IMETHOD GetExtendedOrigin(nsACString& aExtendedOrigin);
   NS_IMETHOD GetAppStatus(PRUint16* aAppStatus);
   NS_IMETHOD GetAppId(PRUint32* aAppStatus);
   NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
 #ifdef DEBUG
   virtual void dumpImpl();
 #endif
   
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -287,18 +287,36 @@ nsNullPrincipal::Subsumes(nsIPrincipal *
 
 NS_IMETHODIMP
 nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
 {
   return Subsumes(aOther, aResult);
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
-{
+nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
+ {
+  if (aAllowIfInheritsPrincipal) {
+    if (nsPrincipal::IsPrincipalInherited(aURI)) {
+      return NS_OK;
+    }
+
+    // Also allow the load if the principal of the URI being checked is exactly
+    // us ie this.
+    nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
+    if (uriPrinc) {
+      nsCOMPtr<nsIPrincipal> principal;
+      uriPrinc->GetPrincipal(getter_AddRefs(principal));
+
+      if (principal && principal == this) {
+        return NS_OK;
+      }
+    }
+  }
+
   if (aReport) {
     nsScriptSecurityManager::ReportError(
       nullptr, NS_LITERAL_STRING("CheckSameOriginError"), mURI, aURI);
   }
 
   return NS_ERROR_DOM_BAD_URI;
 }
 
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -841,18 +841,26 @@ URIIsLocalFile(nsIURI *aURI)
 
   return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
                                 nsIProtocolHandler::URI_IS_LOCAL_FILE,
                                 &isFile)) &&
          isFile;
 }
 
 NS_IMETHODIMP
-nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
+nsPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
 {
+   if (aAllowIfInheritsPrincipal) {
+    // If the caller specified to allow loads of URIs that inherit
+    // our principal, allow the load if this URI inherits its principal
+    if (nsPrincipal::IsPrincipalInherited(aURI)) {
+      return NS_OK;
+    }
+  }
+
   if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
     if (nsScriptSecurityManager::GetStrictFileOriginPolicy() &&
         URIIsLocalFile(aURI)) {
       nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(aURI));
 
       if (!URIIsLocalFile(mCodebase)) {
         // If the codebase is not also a file: uri then forget it
         // (don't want resource: principals in a file: doc)
@@ -1427,21 +1435,21 @@ nsExpandedPrincipal::Subsumes(nsIPrincip
 
 NS_IMETHODIMP
 nsExpandedPrincipal::SubsumesIgnoringDomain(nsIPrincipal* aOther, bool* aResult)
 {
   return ::Subsumes(this, &nsIPrincipal::SubsumesIgnoringDomain, aOther, aResult);
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
+nsExpandedPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
 {
   nsresult rv;
   for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
-    rv = mPrincipals[i]->CheckMayLoad(uri, aReport);
+    rv = mPrincipals[i]->CheckMayLoad(uri, aReport, aAllowIfInheritsPrincipal);
     if (NS_SUCCEEDED(rv))
       return rv;
   }
 
   return NS_ERROR_DOM_BAD_URI;
 }
 
 NS_IMETHODIMP
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -841,20 +841,19 @@ nsScriptSecurityManager::CheckPropertyAc
         objectPrincipal = nullptr;
 
         NS_ConvertUTF8toUTF16 className(classInfoData.GetName());
         nsCAutoString subjectOrigin;
         nsCAutoString subjectDomain;
         if (!nsAutoInPrincipalDomainOriginSetter::sInPrincipalDomainOrigin) {
             nsCOMPtr<nsIURI> uri, domain;
             subjectPrincipal->GetURI(getter_AddRefs(uri));
-            // Subject can't be system if we failed the security
-            // check, so |uri| is non-null.
-            NS_ASSERTION(uri, "How did that happen?");
-            GetOriginFromURI(uri, subjectOrigin);
+            if (uri) { // Object principal might be expanded
+                GetOriginFromURI(uri, subjectOrigin);
+            }
             subjectPrincipal->GetDomain(getter_AddRefs(domain));
             if (domain) {
                 GetOriginFromURI(domain, subjectDomain);
             }
         } else {
             subjectOrigin.AssignLiteral("the security manager");
         }
         NS_ConvertUTF8toUTF16 subjectOriginUnicode(subjectOrigin);
@@ -1064,66 +1063,74 @@ nsScriptSecurityManager::LookupPolicy(ns
     }
 
     if (!dpolicy && mOriginToPolicyMap)
     {
         //-- Look up the relevant domain policy, if any
 #ifdef DEBUG_CAPS_LookupPolicy
         printf("DomainLookup ");
 #endif
-
-        nsCAutoString origin;
-        rv = GetPrincipalDomainOrigin(aPrincipal, origin);
-        NS_ENSURE_SUCCESS(rv, rv);
+        if (nsCOMPtr<nsIExpandedPrincipal> exp = do_QueryInterface(aPrincipal)) 
+        {
+            // For expanded principals domain origin is not defined so let's just
+            // use the default policy
+            dpolicy = mDefaultPolicy;
+        }
+        else
+        {
+            nsCAutoString origin;
+            rv = GetPrincipalDomainOrigin(aPrincipal, origin);
+            NS_ENSURE_SUCCESS(rv, rv);
  
-        char *start = origin.BeginWriting();
-        const char *nextToLastDot = nullptr;
-        const char *lastDot = nullptr;
-        const char *colon = nullptr;
-        char *p = start;
-
-        //-- search domain (stop at the end of the string or at the 3rd slash)
-        for (PRUint32 slashes=0; *p; p++)
-        {
-            if (*p == '/' && ++slashes == 3) 
-            {
-                *p = '\0'; // truncate at 3rd slash
-                break;
-            }
-            if (*p == '.')
+            char *start = origin.BeginWriting();
+            const char *nextToLastDot = nullptr;
+            const char *lastDot = nullptr;
+            const char *colon = nullptr;
+            char *p = start;
+
+            //-- search domain (stop at the end of the string or at the 3rd slash)
+            for (PRUint32 slashes=0; *p; p++)
             {
-                nextToLastDot = lastDot;
-                lastDot = p;
-            } 
-            else if (!colon && *p == ':')
-                colon = p;
+                if (*p == '/' && ++slashes == 3) 
+                {
+                    *p = '\0'; // truncate at 3rd slash
+                    break;
+                }
+                if (*p == '.')
+                {
+                    nextToLastDot = lastDot;
+                    lastDot = p;
+                } 
+                else if (!colon && *p == ':')
+                    colon = p;
+            }
+
+            nsCStringKey key(nextToLastDot ? nextToLastDot+1 : start);
+            DomainEntry *de = (DomainEntry*) mOriginToPolicyMap->Get(&key);
+            if (!de)
+            {
+                nsCAutoString scheme(start, colon-start+1);
+                nsCStringKey schemeKey(scheme);
+                de = (DomainEntry*) mOriginToPolicyMap->Get(&schemeKey);
+            }
+
+            while (de)
+            {
+                if (de->Matches(start))
+                {
+                    dpolicy = de->mDomainPolicy;
+                    break;
+                }
+                de = de->mNext;
+            }
+
+            if (!dpolicy)
+                dpolicy = mDefaultPolicy;
         }
 
-        nsCStringKey key(nextToLastDot ? nextToLastDot+1 : start);
-        DomainEntry *de = (DomainEntry*) mOriginToPolicyMap->Get(&key);
-        if (!de)
-        {
-            nsCAutoString scheme(start, colon-start+1);
-            nsCStringKey schemeKey(scheme);
-            de = (DomainEntry*) mOriginToPolicyMap->Get(&schemeKey);
-        }
-
-        while (de)
-        {
-            if (de->Matches(start))
-            {
-                dpolicy = de->mDomainPolicy;
-                break;
-            }
-            de = de->mNext;
-        }
-
-        if (!dpolicy)
-            dpolicy = mDefaultPolicy;
-
         aPrincipal->SetSecurityPolicy((void*)dpolicy);
     }
 
     ClassPolicy* cpolicy = nullptr;
 
     if ((dpolicy == mDefaultPolicy) && aCachedClassPolicy)
     {
         // No per-domain policy for this principal (the more common case)
@@ -1382,17 +1389,17 @@ nsScriptSecurityManager::CheckLoadURIWit
     // Check for uris that are only loadable by principals that subsume them
     bool hasFlags;
     rv = NS_URIChainHasFlags(targetBaseURI,
                              nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS,
                              &hasFlags);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (hasFlags) {
-        return aPrincipal->CheckMayLoad(targetBaseURI, true);
+        return aPrincipal->CheckMayLoad(targetBaseURI, true, false);
     }
 
     //-- get the source scheme
     nsCAutoString sourceScheme;
     rv = sourceBaseURI->GetScheme(sourceScheme);
     if (NS_FAILED(rv)) return rv;
 
     if (sourceScheme.LowerCaseEqualsLiteral(NS_NULLPRINCIPAL_SCHEME)) {
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -110,17 +110,17 @@ nsSystemPrincipal::Subsumes(nsIPrincipal
 NS_IMETHODIMP
 nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result)
 {
     *result = true;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
+nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport, bool aAllowIfInheritsPrincipal)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSystemPrincipal::GetHashValue(PRUint32 *result)
 {
     *result = NS_PTR_TO_INT32(this);
--- a/caps/tests/mochitest/test_bug292789.html.in
+++ b/caps/tests/mochitest/test_bug292789.html.in
@@ -8,17 +8,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <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=292789">Mozilla Bug 292789</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   <script src="chrome://global/content/strres.js"></script>
-  <script src="chrome://mozapps/content/xpinstall/xpinstallConfirm.js"></script>
+  <script type="application/javascript;version=1.8" src="chrome://mozapps/content/xpinstall/xpinstallConfirm.js"></script>
+  <script id="resjs" type="application/javascript;version=1.8"></script>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 292789
  **
  ** Selectively allow access to whitelisted chrome packages
  ** even for ALLOW_CHROME mechanisms (<script>, <img> etc)
@@ -31,23 +32,23 @@ function testScriptSrc(aCallback) {
     is(typeof srGetStrBundle, "function",
        "content can still load <script> from chrome://global");
     is(typeof XPInstallConfirm, "undefined",
        "content should not be able to load <script> from chrome://mozapps");
     
     /** make sure the last one didn't pass because someone
      ** moved the resource
      **/
-    var resjs = document.createElement("script");
+    var resjs = document.getElementById("resjs");
+    resjs.onload = scriptOnload;
 #ifdef MOZ_CHROME_FILE_FORMAT_JAR
     resjs.src = "jar:resource://gre/chrome/toolkit.jar!/content/mozapps/xpinstall/xpinstallConfirm.js";
 #else
     resjs.src = "resource://gre/chrome/toolkit/content/mozapps/xpinstall/xpinstallConfirm.js";
 #endif
-    resjs.onload = scriptOnload;
     document.getElementById("content").appendChild(resjs);
 
     function scriptOnload() {
       is(typeof XPInstallConfirm, "object",
          "xpinstallConfirm.js has not moved unexpectedly");
   
       // trigger the callback
       if (aCallback)
--- a/chrome/test/unit/data/test_bug519468.manifest
+++ b/chrome/test/unit/data/test_bug519468.manifest
@@ -1,3 +1,4 @@
 locale testmatchos en-US jar:en-US.jar!/locale/en-US/global/
 locale testmatchos fr-FR jar:en-US.jar!/locale/en-US/global/
 locale testmatchos de-DE jar:en-US.jar!/locale/en-US/global/
+locale testmatchos xx-AA jar:en-US.jar!/locale/en-US/global/
--- a/chrome/test/unit/test_bug519468.js
+++ b/chrome/test/unit/test_bug519468.js
@@ -2,61 +2,114 @@
  * 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/.
  */
 
 var MANIFESTS = [
   do_get_file("data/test_bug519468.manifest")
 ];
 
+// Stub in the locale service so we can control what gets returned as the OS locale setting
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+let stubOSLocale = null;
+
+stubID = Components.ID("9d09d686-d913-414c-a1e6-4be8652d7d93");
+localeContractID = "@mozilla.org/intl/nslocaleservice;1";
+
+StubLocaleService = {
+  classDescription: "Stub version of Locale service for testing",
+  classID:          stubID,
+  contractID:       localeContractID,
+  QueryInterface:   XPCOMUtils.generateQI([Ci.nsILocaleService, Ci.nsISupports, Ci.nsIFactory]),
+
+  createInstance: function (outer, iid) {
+    if (outer)
+      throw Components.results.NS_ERROR_NO_AGGREGATION;
+    return this.QueryInterface(iid);
+  },
+  lockFactory: function (lock) {
+    throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+  },
+
+  getLocaleComponentForUserAgent: function SLS_getLocaleComponentForUserAgent()
+  {
+    return stubOSLocale;
+  }
+}
+
+let registrar = Components.manager.nsIComponentRegistrar;
+// Save original factory.
+let localeCID = registrar.contractIDToCID(localeContractID)
+let originalFactory =
+      Components.manager.getClassObject(Components.classes[localeContractID],
+                                        Components.interfaces.nsIFactory);
+
+registrar.registerFactory(stubID, "Unit test Locale Service", localeContractID, StubLocaleService);
+
+// Now fire up the test
 do_test_pending()
 registerManifests(MANIFESTS);
 
 var chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
                 .getService(Ci.nsIXULChromeRegistry)
                 .QueryInterface(Ci.nsIToolkitChromeRegistry);
 chromeReg.checkForNewChrome();
 
-var localeService = Cc["@mozilla.org/intl/nslocaleservice;1"]
-                    .getService(Ci.nsILocaleService);
-
 var prefService = Cc["@mozilla.org/preferences-service;1"]
                   .getService(Ci.nsIPrefService)
                   .QueryInterface(Ci.nsIPrefBranch);
 var os = Cc["@mozilla.org/observer-service;1"]
          .getService(Ci.nsIObserverService);
 
-var systemLocale = localeService.getLocaleComponentForUserAgent();
-var count = 0;
 var testsLocale = [
-  {matchOS: false, selected: null, locale: "en-US"},
-  {matchOS: true, selected: null, locale: systemLocale},
-  {matchOS: true, selected: "fr-FR", locale: systemLocale},
-  {matchOS: false, selected: "fr-FR", locale: "fr-FR"},
-  {matchOS: false, selected: "de-DE", locale: "de-DE"},
-  {matchOS: true, selected: null, locale: systemLocale}
+  // These tests cover when the OS local is included in our manifest
+  {matchOS: false, selected: "en-US", osLocale: "xx-AA", locale: "en-US"},
+  {matchOS: true, selected: "en-US", osLocale: "xx-AA", locale: "xx-AA"},
+  {matchOS: false, selected: "fr-FR", osLocale: "xx-AA", locale: "fr-FR"},
+  {matchOS: true, selected: "fr-FR", osLocale: "xx-AA", locale: "xx-AA"},
+  {matchOS: false, selected: "de-DE", osLocale: "xx-AA", locale: "de-DE"},
+  {matchOS: true, selected: "de-DE", osLocale: "xx-AA", locale: "xx-AA"},
+  // these tests cover the case where the OS locale is not available in our manifest, but the
+  // base language is (ie, substitute xx-AA which we have for xx-BB which we don't)
+  {matchOS: false, selected: "en-US", osLocale: "xx-BB", locale: "en-US"},
+  {matchOS: true, selected: "en-US", osLocale: "xx-BB", locale: "xx-AA"},
+  {matchOS: false, selected: "fr-FR", osLocale: "xx-BB", locale: "fr-FR"},
+  {matchOS: true, selected: "fr-FR", osLocale: "xx-BB", locale: "xx-AA"},
+  // These tests cover where the language is not available
+  {matchOS: false, selected: "en-US", osLocale: "xy-BB", locale: "en-US"},
+  {matchOS: true, selected: "en-US", osLocale: "xy-BB", locale: "en-US"},
+  {matchOS: false, selected: "fr-FR", osLocale: "xy-BB", locale: "fr-FR"},
+  {matchOS: true, selected: "fr-FR", osLocale: "xy-BB", locale: "en-US"},
 ];
 
+var observedLocale = null;
+
 function test_locale(aTest) {
+  observedLocale = null;
+
+  stubOSLocale = aTest.osLocale;
   prefService.setBoolPref("intl.locale.matchOS", aTest.matchOS);
-  prefService.setCharPref("general.useragent.locale", aTest.selected || "en-US");
+  prefService.setCharPref("general.useragent.locale", aTest.selected);
 
   chromeReg.reloadChrome();
+
+  do_check_eq(observedLocale, aTest.locale);
 }
 
+// Callback function for observing locale change. May be called more than once
+// per test iteration.
 function checkValidity() {
-  var selectedLocale = chromeReg.getSelectedLocale("testmatchos");
-  do_check_eq(selectedLocale, testsLocale[count].locale);
-
-  count++;
-  if (count >= testsLocale.length) {
-    os.removeObserver(checkValidity, "selected-locale-has-changed");
-    do_test_finished();
-  }
-  else {
-    test_locale(testsLocale[count]);
-  }
+  observedLocale = chromeReg.getSelectedLocale("testmatchos");
+  dump("checkValidity called back with locale = " + observedLocale + "\n");
 }
 
 function run_test() {
   os.addObserver(checkValidity, "selected-locale-has-changed", false);
-  test_locale(testsLocale[count]);
+
+  for (let count = 0 ; count < testsLocale.length ; count++) {
+    dump("count = " + count + " " + testsLocale[count].toSource() + "\n");
+    test_locale(testsLocale[count]);
+  }
+
+  os.removeObserver(checkValidity, "selected-locale-has-changed");
+  do_test_finished();
 }
--- a/configure.in
+++ b/configure.in
@@ -4330,17 +4330,17 @@ dnl ====================================
 
 if test -z "$gonkdir" ; then
     # Minimum Android SDK API Level we require.
     case "$MOZ_BUILD_APP" in
     mobile/xul)
         android_min_api_level=13
         ;;
     mobile/android)
-        android_min_api_level=14
+        android_min_api_level=16
         ;;
     esac
 
     MOZ_ANDROID_SDK($android_min_api_level)
 fi
 
 dnl ========================================================
 dnl =
@@ -5268,18 +5268,23 @@ MOZ_ARG_DISABLE_BOOL(webm,
     MOZ_WEBM=1)
 
 if test -n "$MOZ_WEBM"; then
     AC_DEFINE(MOZ_WEBM)
     MOZ_VP8=1
 fi;
 
 dnl ========================================================
-dnl = Disable media plugin support
-dnl ========================================================
+dnl = Enable media plugin support
+dnl ========================================================
+if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
+  dnl Enable support on android by default
+  MOZ_MEDIA_PLUGINS=1
+fi
+
 MOZ_ARG_ENABLE_BOOL(media-plugins,
 [  --enable-media-plugins  Enable support for media plugins],
     MOZ_MEDIA_PLUGINS=1,
     MOZ_MEDIA_PLUGINS=)
 
 if test -n "$MOZ_MEDIA_PLUGINS"; then
   AC_DEFINE(MOZ_MEDIA_PLUGINS)
 fi
@@ -5294,16 +5299,21 @@ MOZ_ARG_ENABLE_BOOL(media-navigator,
 
 if test -n "$MOZ_MEDIA_NAVIGATOR"; then
   AC_DEFINE(MOZ_MEDIA_NAVIGATOR)
 fi
 
 dnl ========================================================
 dnl = Enable building OMX media plugin (B2G or Android)
 dnl ========================================================
+if test "$OS_TARGET" = Android -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
+  dnl Enable support on android by default
+  MOZ_OMX_PLUGIN=1
+fi
+
 MOZ_ARG_ENABLE_BOOL(omx-plugin,
 [  --enable-omx-plugin      Enable building OMX plugin (B2G)],
     MOZ_OMX_PLUGIN=1,
     MOZ_OMX_PLUGIN=)
 
 if test -n "$MOZ_OMX_PLUGIN"; then
     if test "$OS_TARGET" = "Android"; then
         dnl Only allow building OMX plugin on Gonk (B2G) or Android
@@ -5791,26 +5801,26 @@ esac
 MOZ_ARG_DISABLE_BOOL(crashreporter,
 [  --disable-crashreporter Disable breakpad crash reporting],
     MOZ_CRASHREPORTER=,
     MOZ_CRASHREPORTER=1)
 
 if test -n "$MOZ_CRASHREPORTER"; then
    AC_DEFINE(MOZ_CRASHREPORTER)
 
-  if (test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS") && \
+  if test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS" && \
     test -z "$SKIP_LIBRARY_CHECKS"; then
     PKG_CHECK_MODULES(MOZ_GTHREAD, gthread-2.0)
     AC_SUBST(MOZ_GTHREAD_CFLAGS)
     AC_SUBST(MOZ_GTHREAD_LIBS)
 
     MOZ_CHECK_HEADERS([curl/curl.h], [], [AC_MSG_ERROR([Couldn't find curl/curl.h which is required for the crash reporter.  Use --disable-crashreporter to disable the crash reporter.])])
   fi
 
-  if (test "$OS_ARCH" != "$HOST_OS_ARCH"); then
+  if test "$OS_ARCH" != "$HOST_OS_ARCH"; then
     AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH.  Use --disable-crashreporter.])
   fi
 
   if test "$OS_ARCH" = "WINNT" -a -z "$HAVE_64BIT_OS"; then
     MOZ_CRASHREPORTER_INJECTOR=1
     AC_DEFINE(MOZ_CRASHREPORTER_INJECTOR)
   fi
 fi
@@ -7676,17 +7686,17 @@ MOZ_ARG_DISABLE_BOOL(md,
      _cpp_md_flag=1
    fi
   dnl Default is to use -xM if using Sun Studio on Solaris
    if test "$SOLARIS_SUNPRO_CC"; then
      _cpp_md_flag=1
    fi])
 if test "$_cpp_md_flag"; then
   COMPILER_DEPEND=1
-  _DEPEND_CFLAGS='$(filter-out %/.pp,-MD -MF $(MDDEPDIR)/$(@F).pp)'
+  _DEPEND_CFLAGS='$(filter-out %/.pp,-MMD -MF $(MDDEPDIR)/$(@F).pp)'
   dnl Sun Studio on Solaris use -xM instead of -MD, see config/rules.mk
   if test "$SOLARIS_SUNPRO_CC"; then
     _DEPEND_CFLAGS=
   fi
 else
   COMPILER_DEPEND=
   dnl Don't override this for MSVC
   if test -z "$_WIN32_MSVC"; then
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -812,16 +812,26 @@ public:
   /**
    * Get the localized string named |aKey| in properties file |aFile|.
    */
   static nsresult GetLocalizedString(PropertiesFile aFile,
                                      const char* aKey,
                                      nsXPIDLString& aResult);
 
   /**
+   * A helper function that parses a sandbox attribute (of an <iframe> or
+   * a CSP directive) and converts it to the set of flags used internally.
+   *
+   * @param aAttribute 	the value of the sandbox attribute
+   * @return 			the set of flags
+   */
+  static PRUint32 ParseSandboxAttributeToFlags(const nsAString& aSandboxAttr);
+
+
+  /**
    * Fill (with the parameters given) the localized string named |aKey| in
    * properties file |aFile|.
    */
 private:
   static nsresult FormatLocalizedString(PropertiesFile aFile,
                                         const char* aKey,
                                         const PRUnichar** aParams,
                                         PRUint32 aParamsLength,
@@ -1689,17 +1699,17 @@ public:
    *
    * @param aScriptContext the script context to get the document for; can be null
    *
    * @return the document associated with the script context
    */
   static already_AddRefed<nsIDocument>
   GetDocumentFromScriptContext(nsIScriptContext *aScriptContext);
 
-  static bool CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel);
+  static bool CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal);
 
   /**
    * The method checks whether the caller can access native anonymous content.
    * If there is no JS in the stack or privileged JS is running, this
    * method returns true, otherwise false.
    */
   static bool CanAccessNativeAnon();
 
@@ -1945,42 +1955,44 @@ public:
    * from the document it comes from.
    */
   static nsresult URIInheritsSecurityContext(nsIURI *aURI, bool *aResult);
 
   /**
    * Set the given principal as the owner of the given channel, if
    * needed.  aURI must be the URI of aChannel.  aPrincipal may be
    * null.  If aSetUpForAboutBlank is true, then about:blank will get
-   * the principal set up on it.
-   *
+   * the principal set up on it. If aForceOwner is true, the owner
+   * will be set on the channel, even if the principal can be determined
+   * from the channel.
    * The return value is whether the principal was set up as the owner
    * of the channel.
    */
   static bool SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
                                 nsIChannel* aChannel,
                                 nsIURI* aURI,
-                                bool aSetUpForAboutBlank);
+                                bool aSetUpForAboutBlank,
+                                bool aForceOwner = false);
 
   static nsresult Btoa(const nsAString& aBinaryData,
                        nsAString& aAsciiBase64String);
 
   static nsresult Atob(const nsAString& aAsciiString,
                        nsAString& aBinaryData);
 
   /** If aJSArray is a Javascript array, this method iterates over its
    *  elements and appends values to aRetVal as nsIAtoms.
    *  @throw NS_ERROR_ILLEGAL_VALUE if aJSArray isn't a JS array.
    */ 
   static nsresult JSArrayToAtomArray(JSContext* aCx, const JS::Value& aJSArray,
                                      nsCOMArray<nsIAtom>& aRetVal);
 
   /**
    * Returns whether the input element passed in parameter has the autocomplete
-   * functionnality enabled. It is taking into account the form owner.
+   * functionality enabled. It is taking into account the form owner.
    * NOTE: the caller has to make sure autocomplete makes sense for the
    * element's type.
    *
    * @param aInput the input element to check. NOTE: aInput can't be null.
    * @return whether the input element has autocomplete enabled.
    */
   static bool IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput);
 
--- a/content/base/public/nsDeprecatedOperationList.h
+++ b/content/base/public/nsDeprecatedOperationList.h
@@ -40,11 +40,10 @@ DEPRECATED_OPERATION(IsEqualNode)
 DEPRECATED_OPERATION(TextContent)
 DEPRECATED_OPERATION(EnablePrivilege)
 DEPRECATED_OPERATION(Position)
 DEPRECATED_OPERATION(TotalSize)
 DEPRECATED_OPERATION(InputEncoding)
 DEPRECATED_OPERATION(MozBeforePaint)
 DEPRECATED_OPERATION(MozBlobBuilder)
 DEPRECATED_OPERATION(DOMExceptionCode)
-DEPRECATED_OPERATION(NoExposedProps)
 DEPRECATED_OPERATION(MutationEvent)
 DEPRECATED_OPERATION(MozSlice)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -74,18 +74,18 @@ class ImageLoader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
-{ 0xdb888523, 0x541f, 0x49e3, \
-  { 0xa9, 0x71, 0xb5, 0xea, 0xd1, 0xf0, 0xc3, 0xcf } }
+{ 0x57fe44ae, 0x6656, 0x44b8, \
+  { 0x8d, 0xc0, 0xfc, 0xa7, 0x43, 0x28, 0xbe, 0x86 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
@@ -395,16 +395,35 @@ public:
    * change to actually change anything immediately.
    * @see nsBidiUtils.h
    */
   void SetBidiOptions(PRUint32 aBidiOptions)
   {
     mBidiOptions = aBidiOptions;
   }
 
+
+  /**
+   * Get the sandbox flags for this document.
+   * @see nsSandboxFlags.h for the possible flags
+   */
+  PRUint32 GetSandboxFlags() const
+  {
+    return mSandboxFlags;
+  }
+
+  /**
+   * Set the sandbox flags for this document.
+   * @see nsSandboxFlags.h for the possible flags
+   */
+  void SetSandboxFlags(PRUint32 sandboxFlags)
+  {
+    mSandboxFlags = sandboxFlags;
+  }
+
   inline mozilla::directionality::Directionality GetDocumentDirectionality() {
     return mDirectionality;
   }
   
   /**
    * Access HTTP header data (this may also get set from other
    * sources, like HTML META tags).
    */
@@ -451,16 +470,21 @@ public:
 
   /**
    * Set the parent document of this document.
    */
   void SetParentDocument(nsIDocument* aParent)
   {
     mParentDocument = aParent;
   }
+  
+  /**
+   * Are plugins allowed in this document ?
+   */
+  virtual nsresult GetAllowPlugins (bool* aAllowPlugins) = 0;
 
   /**
    * Set the sub document for aContent to aSubDoc.
    */
   virtual nsresult SetSubDocumentFor(Element* aContent,
                                      nsIDocument* aSubDoc) = 0;
 
   /**
@@ -1862,16 +1886,21 @@ protected:
   // If mIsStaticDocument is true, mOriginalDocument points to the original
   // document.
   nsCOMPtr<nsIDocument> mOriginalDocument;
 
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
+  // The sandbox flags on the document. These reflect the value of the sandbox attribute of the
+  // associated IFRAME or CSP-protectable content, if existent. These are set at load time and
+  // are immutable - see nsSandboxFlags.h for the possible flags.
+  PRUint32 mSandboxFlags;
+
   // The root directionality of this document.
   mozilla::directionality::Directionality mDirectionality;
 
   nsCString mContentLanguage;
 private:
   nsCString mContentType;
 protected:
 
--- a/content/base/public/nsLineBreaker.h
+++ b/content/base/public/nsLineBreaker.h
@@ -142,24 +142,24 @@ public:
   nsresult AppendInvisibleWhitespace(PRUint32 aFlags);
 
   /**
    * Feed Unicode text into the linebreaker for analysis. aLength must be
    * nonzero.
    * @param aSink can be null if the breaks are not actually needed (we may
    * still be setting up state for later breaks)
    */
-  nsresult AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32 aLength,
+  nsresult AppendText(nsIAtom* aHyphenationLanguage, const PRUnichar* aText, PRUint32 aLength,
                       PRUint32 aFlags, nsILineBreakSink* aSink);
   /**
    * Feed 8-bit text into the linebreaker for analysis. aLength must be nonzero.
    * @param aSink can be null if the breaks are not actually needed (we may
    * still be setting up state for later breaks)
    */
-  nsresult AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aLength,
+  nsresult AppendText(nsIAtom* aHyphenationLanguage, const PRUint8* aText, PRUint32 aLength,
                       PRUint32 aFlags, nsILineBreakSink* aSink);
   /**
    * Reset all state. This means the current run has ended; any outstanding
    * calls through nsILineBreakSink are made, and all outstanding references to
    * nsILineBreakSink objects are dropped.
    * After this call, this linebreaker can be reused.
    * This must be called at least once between any call to AppendText() and
    * destroying the object.
@@ -193,27 +193,27 @@ private:
   // State for the nonwhitespace "word" that started in previous text and hasn't
   // finished yet.
 
   // When the current word ends, this computes the linebreak opportunities
   // *inside* the word (excluding either end) and sets them through the
   // appropriate sink(s). Then we clear the current word state.
   nsresult FlushCurrentWord();
 
-  void UpdateCurrentWordLangGroup(nsIAtom *aLangGroup);
+  void UpdateCurrentWordLanguage(nsIAtom *aHyphenationLanguage);
 
   void FindHyphenationPoints(nsHyphenator *aHyphenator,
                              const PRUnichar *aTextStart,
                              const PRUnichar *aTextLimit,
                              PRUint8 *aBreakState);
 
   nsAutoTArray<PRUnichar,100> mCurrentWord;
   // All the items that contribute to mCurrentWord
   nsAutoTArray<TextItem,2>    mTextItems;
-  nsIAtom*                    mCurrentWordLangGroup;
+  nsIAtom*                    mCurrentWordLanguage;
   bool                        mCurrentWordContainsMixedLang;
   bool                        mCurrentWordContainsComplexChar;
 
   // True if the previous character was breakable whitespace
   bool                        mAfterBreakableSpace;
   // True if a break must be allowed at the current position because
   // a run of breakable whitespace ends here
   bool                        mBreakHere;
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -8,16 +8,17 @@
  * Overview
  * This contains a set of classes and utilities for CSP.  It is in this
  * separate file for testing purposes.
  */
 
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
 // Module stuff
 var EXPORTED_SYMBOLS = ["CSPRep", "CSPSourceList", "CSPSource", "CSPHost",
                         "CSPWarning", "CSPError", "CSPdebug",
                         "CSPViolationReportListener", "CSPLocalizer"];
@@ -26,16 +27,51 @@ var STRINGS_URI = "chrome://global/local
 
 // these are not exported
 var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
                  .getService(Components.interfaces.nsIIOService);
 
 var gETLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
                    .getService(Components.interfaces.nsIEffectiveTLDService);
 
+// These regexps represent the concrete syntax on the w3 spec as of 7-5-2012
+// scheme          = <scheme production from RFC 3986>
+const R_SCHEME     = new RegExp ("([a-zA-Z0-9\\-]+)", 'i');
+const R_GETSCHEME  = new RegExp ("^" + R_SCHEME.source + "(?=\\:)", 'i');
+
+// scheme-source   = scheme ":"
+const R_SCHEMESRC  = new RegExp ("^" + R_SCHEME.source + "\\:$", 'i');
+
+// host-char       = ALPHA / DIGIT / "-"
+const R_HOSTCHAR   = new RegExp ("[a-zA-Z0-9\\-]", 'i');
+
+// host            = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
+const R_HOST       = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
+                                      "+)(\\." + R_HOSTCHAR.source +"+)+)",'i');
+// port            = ":" ( 1*DIGIT / "*" )
+const R_PORT       = new RegExp ("(\\:([0-9]+|\\*))", 'i');
+
+// host-source     = [ scheme "://" ] host [ port ]
+const R_HOSTSRC    = new RegExp ("^((" + R_SCHEME.source + "\\:\\/\\/)?("
+                                       +   R_HOST.source + ")"
+                                       +   R_PORT.source + "?)$", 'i');
+
+// ext-host-source = host-source "/" *( <VCHAR except ";" and ","> )
+//                 ; ext-host-source is reserved for future use.
+const R_EXTHOSTSRC = new RegExp ("^" + R_HOSTSRC.source + "\\/[:print:]+$", 'i');
+
+// keyword-source  = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
+const R_KEYWORDSRC = new RegExp ("^('self'|'unsafe-inline'|'unsafe-eval')$", 'i');
+
+// source-exp      = scheme-source / host-source / keyword-source
+const R_SOURCEEXP  = new RegExp (R_SCHEMESRC.source + "|" +
+                                   R_HOSTSRC.source + "|" +
+                                R_KEYWORDSRC.source,  'i');
+
+
 var gPrefObserver = {
   get debugEnabled () {
     if (!this._branch)
       this._initialize();
     return this._debugEnabled;
   },
 
   _initialize: function() {
@@ -474,18 +510,20 @@ CSPRep.prototype = {
    *        a new CSPRep instance of the intersection
    */
   intersectWith:
   function cspsd_intersectWith(aCSPRep) {
     var newRep = new CSPRep();
 
     for (var dir in CSPRep.SRC_DIRECTIVES) {
       var dirv = CSPRep.SRC_DIRECTIVES[dir];
-      newRep._directives[dirv] = this._directives[dirv]
-               .intersectWith(aCSPRep._directives[dirv]);
+      if (this._directives.hasOwnProperty(dirv))
+        newRep._directives[dirv] = this._directives[dirv].intersectWith(aCSPRep._directives[dirv]);
+      else
+        newRep._directives[dirv] = aCSPRep._directives[dirv];
     }
 
     // REPORT_URI
     var reportURIDir = CSPRep.URI_DIRECTIVES.REPORT_URI;
     if (this._directives[reportURIDir] && aCSPRep._directives[reportURIDir]) {
       newRep._directives[reportURIDir] =
         this._directives[reportURIDir].concat(aCSPRep._directives[reportURIDir]);
     }
@@ -493,22 +531,16 @@ CSPRep.prototype = {
       // blank concat makes a copy of the string.
       newRep._directives[reportURIDir] = this._directives[reportURIDir].concat();
     }
     else if (aCSPRep._directives[reportURIDir]) {
       // blank concat makes a copy of the string.
       newRep._directives[reportURIDir] = aCSPRep._directives[reportURIDir].concat();
     }
 
-    for (var dir in CSPRep.SRC_DIRECTIVES) {
-      var dirv = CSPRep.SRC_DIRECTIVES[dir];
-      newRep._directives[dirv] = this._directives[dirv]
-               .intersectWith(aCSPRep._directives[dirv]);
-    }
-
     newRep._allowEval =          this.allowsEvalInScripts
                            && aCSPRep.allowsEvalInScripts;
 
     newRep._allowInlineScripts = this.allowsInlineScripts 
                            && aCSPRep.allowsInlineScripts;
 
     return newRep;
   },
@@ -583,46 +615,53 @@ function CSPSourceList() {
  *        URI or CSPSource representing the "self" source
  * @param enforceSelfChecks (optional)
  *        if present, and "true", will check to be sure "self" has the
  *        appropriate values to inherit when they are omitted from the source.
  * @returns
  *        an instance of CSPSourceList 
  */
 CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
-  // Source list is:
-  //    <host-dir-value> ::= <source-list>
-  //                       | "'none'"
-  //    <source-list>    ::= <source>
-  //                       | <source-list>" "<source>
+  // source-list = *WSP [ source-expression *( 1*WSP source-expression ) *WSP ]
+  //             / *WSP "'none'" *WSP
 
   /* If self parameter is passed, convert to CSPSource,
      unless it is already a CSPSource. */
   if(self && !(self instanceof CSPSource)) {
      self = CSPSource.create(self);
   }
 
   var slObj = new CSPSourceList();
-  if (aStr === "'none'")
-    return slObj;
-
-  if (aStr === "*") {
-    slObj._permitAllSources = true;
+  aStr = aStr.trim();
+  // w3 specifies case insensitive equality
+  if (aStr.toUpperCase() === "'NONE'"){
+    slObj._permitAllSources = false;
     return slObj;
   }
 
   var tokens = aStr.split(/\s+/);
   for (var i in tokens) {
-    if (tokens[i] === "") continue;
+    if (!R_SOURCEEXP.test(tokens[i])){
+      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
+                                           [tokens[i]]));
+      continue;
+    }
     var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
     if (!src) {
-      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource", [tokens[i]]));
+      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
+                                           [tokens[i]]));
       continue;
     }
-    slObj._sources.push(src);
+    // if a source is a *, then we can permit all sources
+    if (src.permitAll){
+      slObj._permitAllSources = true;
+      return slObj;
+    } else {
+      slObj._sources.push(src);
+    }
   }
 
   return slObj;
 };
 
 CSPSourceList.prototype = {
   /**
    * Compares one CSPSourceList to another.
@@ -731,16 +770,18 @@ CSPSourceList.prototype = {
    * @returns
    *        a new instance of a CSPSourceList representing the intersection
    */
   intersectWith:
   function cspsd_intersectWith(that) {
 
     var newCSPSrcList = null;
 
+    if (!that) return this.clone();
+
     if (this.isNone() || that.isNone())
       newCSPSrcList = CSPSourceList.fromString("'none'");
 
     if (this.isAll()) newCSPSrcList = that.clone();
     if (that.isAll()) newCSPSrcList = this.clone();
 
     if (!newCSPSrcList) {
       // the shortcuts didn't apply, must do intersection the hard way.
@@ -782,16 +823,19 @@ CSPSourceList.prototype = {
 /**
  * Class to model a source (scheme, host, port)
  */
 function CSPSource() {
   this._scheme = undefined;
   this._port = undefined;
   this._host = undefined;
 
+  //when set to true, this allows all source
+  this._permitAll = false;
+
   // when set to true, this source represents 'self'
   this._isSelf = false;
 }
 
 /**
  * General factory method to create a new source from one of the following
  * types:
  *  - nsURI
@@ -919,157 +963,93 @@ CSPSource.fromString = function(aStr, se
   if (!aStr)
     return null;
 
   if (!(typeof aStr === 'string')) {
     CSPError(CSPLocalizer.getStr("argumentIsNotString"));
     return null;
   }
 
+  var sObj = new CSPSource();
+  sObj._self = self;
+
+  // if equal, return does match
+  if (aStr === "*"){
+    sObj._permitAll = true;
+    return sObj;
+  }
+
   if (!self && enforceSelfChecks) {
     CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
     return null;
   }
 
   if (self && !(self instanceof CSPSource)) {
     self = CSPSource.create(self, undefined, false);
   }
 
-  var sObj = new CSPSource();
-  sObj._self = self;
+  // check for scheme-source match
+  if (R_SCHEMESRC.test(aStr)){
+    var schemeSrcMatch = R_GETSCHEME.exec(aStr);
+    sObj._scheme = schemeSrcMatch[0];
+    if (!sObj._host) sObj._host = CSPHost.fromString("*");
+    if (!sObj._port) sObj._port = "*";
+    return sObj;
+  }
+
+  // check for host-source or ext-host-source match
+  if (R_HOSTSRC.test(aStr) || R_EXTHOSTSRC.test(aStr)){
+    var schemeMatch = R_GETSCHEME.exec(aStr);
+    if (!schemeMatch)
+      sObj._scheme = self.scheme;
+    else {
+      sObj._scheme = schemeMatch[0];
+    }
 
-  // take care of 'self' keyword
-  if (aStr === "'self'") {
-    if (!self) {
+    var hostMatch = R_HOST.exec(aStr);
+    if (!hostMatch) {
+      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
+      return null;
+    }
+    sObj._host = CSPHost.fromString(hostMatch[0]);
+    var portMatch = R_PORT.exec(aStr);
+    if (!portMatch) {
+      // gets the default port for the given scheme
+      defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
+      if (!defPort) {
+        CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
+        return null;
+      }
+      sObj._port = defPort;
+    }
+    else {
+      // strip the ':' from the port
+      sObj._port = portMatch[0].substr(1);
+    }
+    return sObj;
+  }
+
+  // check for 'self' (case insensitive)
+  if (aStr.toUpperCase() === "'SELF'"){
+    if (!self){
       CSPError(CSPLocalizer.getStr("selfKeywordNoSelfData"));
       return null;
     }
     sObj._self = self.clone();
     sObj._isSelf = true;
     return sObj;
   }
-
-  // We could just create a URI and then send this off to fromURI, but
-  // there's no way to leave out the scheme or wildcard the port in an nsURI.
-  // That has to be supported here.
-
-  // split it up
-  var chunks = aStr.split(":");
-
-  // If there is only one chunk, it's gotta be a host.
-  if (chunks.length == 1) {
-    sObj._host = CSPHost.fromString(chunks[0]);
-    if (!sObj._host) {
-      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-      return null;
-    }
-
-    // enforce 'self' inheritance
-    if (enforceSelfChecks) {
-      // note: the non _scheme accessor checks sObj._self
-      if (!sObj.scheme || !sObj.port) {
-        CSPError(CSPLocalizer.getFormatStr("hostSourceWithoutData",[aStr]));
-        return null;
-      }
-    }
-    return sObj;
-  }
-
-  // If there are two chunks, it's either scheme://host or host:port
-  //   ... but scheme://host can have an empty host.
-  //   ... and host:port can have an empty host
-  if (chunks.length == 2) {
-
-    // is the last bit a port?
-    if (chunks[1] === "*" || chunks[1].match(/^\d+$/)) {
-      sObj._port = chunks[1];
-      // then the previous chunk *must* be a host or empty.
-      if (chunks[0] !== "") {
-        sObj._host = CSPHost.fromString(chunks[0]);
-        if (!sObj._host) {
-          CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-          return null;
-        }
-      }
-      // enforce 'self' inheritance 
-      // (scheme:host requires port, host:port does too.  Wildcard support is
-      // only available if the scheme and host are wildcarded)
-      if (enforceSelfChecks) {
-        // note: the non _scheme accessor checks sObj._self
-        if (!sObj.scheme || !sObj.host || !sObj.port) {
-          CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
-          return null;
-        }
-      }
-    }
-    // is the first bit a scheme?
-    else if (CSPSource.validSchemeName(chunks[0])) {
-      sObj._scheme = chunks[0];
-      // then the second bit *must* be a host or empty
-      if (chunks[1] === "") {
-        // Allow scheme-only sources!  These default to wildcard host/port,
-        // especially since host and port don't always matter.
-        // Example: "javascript:" and "data:" 
-        if (!sObj._host) sObj._host = CSPHost.fromString("*");
-        if (!sObj._port) sObj._port = "*";
-      } else {
-        // some host was defined.
-        // ... remove <= 3 leading slashes (from the scheme) and parse
-        var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
-        // ... and parse
-        sObj._host = CSPHost.fromString(cleanHost);
-        if (!sObj._host) {
-          CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidHost",[cleanHost]));
-          return null;
-        }
-      }
-
-      // enforce 'self' inheritance (scheme-only should be scheme:*:* now, and
-      // if there was a host provided it should be scheme:host:selfport
-      if (enforceSelfChecks) {
-        // note: the non _scheme accessor checks sObj._self
-        if (!sObj.scheme || !sObj.host || !sObj.port) {
-          CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
-          return null;
-        }
-      }
-    }
-    else  {
-      // AAAH!  Don't know what to do!  No valid scheme or port!
-      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-      return null;
-    }
-
-    return sObj;
-  }
-
-  // If there are three chunks, we got 'em all!
-  if (!CSPSource.validSchemeName(chunks[0])) {
-    CSPError(CSPLocalizer.getFormatStr("couldntParseScheme",[aStr]));
-    return null;
-  }
-  sObj._scheme = chunks[0];
-  if (!(chunks[2] === "*" || chunks[2].match(/^\d+$/))) {
-    CSPError(CSPLocalizer.getFormatStr("couldntParsePort",[aStr]));
-    return null;
-  }
-
-  sObj._port = chunks[2];
-
-  // ... remove <= 3 leading slashes (from the scheme) and parse
-  var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
-  sObj._host = CSPHost.fromString(cleanHost);
-
-  return sObj._host ? sObj : null;
+  CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
+  return null;
 };
 
 CSPSource.validSchemeName = function(aStr) {
   // <scheme-name>       ::= <alpha><scheme-suffix>
-  // <scheme-suffix>     ::= <scheme-chr> 
-  //                      | <scheme-suffix><scheme-chr> 
+  // <scheme-suffix>     ::= <scheme-chr>
+  //                      | <scheme-suffix><scheme-chr>
   // <scheme-chr>        ::= <letter> | <digit> | "+" | "." | "-"
   
   return aStr.match(/^[a-zA-Z][a-zA-Z0-9+.-]*$/);
 };
 
 CSPSource.prototype = {
 
   get scheme () {
@@ -1083,17 +1063,23 @@ CSPSource.prototype = {
   get host () {
     if (this._isSelf && this._self)
       return this._self.host;
     if (!this._host && this._self)
       return this._self.host;
     return this._host;
   },
 
-  /** 
+  get permitAll () {
+    if (this._isSelf && this._self)
+      return this._self.permitAll;
+    return this._permitAll;
+  },
+
+  /**
    * If this doesn't have a nonstandard port (hard-defined), use the default
    * port for this source's scheme. Should never inherit port from 'self'.
    */
   get port () {
     if (this._isSelf && this._self)
       return this._self.port;
     if (this._port) return this._port;
     // if no port, get the default port for the scheme
@@ -1194,64 +1180,64 @@ CSPSource.prototype = {
     // 'self' is not part of the intersection.  Intersect the raw values from
     // the source, self must be set by someone creating this source.
     // When intersecting, we take the more specific of the two: if one scheme,
     // host or port is undefined, the other is taken.  (This is contrary to
     // when "permits" is called -- there, the value of 'self' is looked at 
     // when a scheme, host or port is undefined.)
 
     // port
-    if (!this._port)
-      newSource._port = that._port;
-    else if (!that._port)
-      newSource._port = this._port;
-    else if (this._port === "*") 
-      newSource._port = that._port;
-    else if (that._port === "*")
-      newSource._port = this._port;
-    else if (that._port === this._port)
-      newSource._port = this._port;
+    if (!this.port)
+      newSource._port = that.port;
+    else if (!that.port)
+      newSource._port = this.port;
+    else if (this.port === "*")
+      newSource._port = that.port;
+    else if (that.port === "*")
+      newSource._port = this.port;
+    else if (that.port === this.port)
+      newSource._port = this.port;
     else {
       CSPError(CSPLocalizer.getFormatStr("notIntersectPort", [this.toString(), that.toString()]));
       return null;
     }
 
     // scheme
-    if (!this._scheme)
-      newSource._scheme = that._scheme;
-    else if (!that._scheme)
-      newSource._scheme = this._scheme;
-    if (this._scheme === "*")
-      newSource._scheme = that._scheme;
-    else if (that._scheme === "*")
-      newSource._scheme = this._scheme;
-    else if (that._scheme === this._scheme)
-      newSource._scheme = this._scheme;
+    if (!this.scheme)
+      newSource._scheme = that.scheme;
+    else if (!that.scheme)
+      newSource._scheme = this.scheme;
+    if (this.scheme === "*")
+      newSource._scheme = that.scheme;
+    else if (that.scheme === "*")
+      newSource._scheme = this.scheme;
+    else if (that.scheme === this.scheme)
+      newSource._scheme = this.scheme;
     else {
       CSPError(CSPLocalizer.getFormatStr("notIntersectScheme", [this.toString(), that.toString()]));
       return null;
     }
 
     // NOTE: Both sources must have a host, if they don't, something funny is
     // going on.  The fromString() factory method should have set the host to
     // * if there's no host specified in the input. Regardless, if a host is
     // not present either the scheme is hostless or any host should be allowed.
     // This means we can use the other source's host as the more restrictive
     // host expression, or if neither are present, we can use "*", but the
     // error should still be reported.
 
     // host
-    if (this._host && that._host) {
-      newSource._host = this._host.intersectWith(that._host);
-    } else if (this._host) {
+    if (this.host && that.host) {
+      newSource._host = this.host.intersectWith(that.host);
+    } else if (this.host) {
       CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [that.toString()]));
-      newSource._host = this._host.clone();
-    } else if (that._host) {
+      newSource._host = this.host.clone();
+    } else if (that.host) {
       CSPError(CSPLocalizer.getFormatStr("intersectingSourceWithUndefinedHost", [this.toString()]));
-      newSource._host = that._host.clone();
+      newSource._host = that.host.clone();
     } else {
       CSPError(CSPLocalizer.getFormatStr("intersectingSourcesWithUndefinedHosts", [this.toString(), that.toString()]));
       newSource._host = CSPHost.fromString("*");
     }
 
     return newSource;
   },
 
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -35,16 +35,17 @@ EXPORTS		= \
 		nsFrameMessageManager.h \
 		nsAttrAndChildArray.h \
 		nsAttrValue.h \
 		nsCrossSiteListenerProxy.h \
 		nsDOMAttributeMap.h \
 		nsGenericElement.h \
 		nsMappedAttributeElement.h \
 		nsStyledElement.h \
+    nsSandboxFlags.h \
 		$(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
   Link.h \
   $(NULL)
 
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1059,17 +1059,17 @@ nsContentSink::ProcessOfflineManifest(co
     nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
                                               aManifestSpec, mDocument,
                                               mDocumentURI);
     if (!manifestURI) {
       return;
     }
 
     // Documents must list a manifest from the same origin
-    rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, true);
+    rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, true, false);
     if (NS_FAILED(rv)) {
       action = CACHE_SELECTION_RESELECT_WITHOUT_MANIFEST;
     }
     else {
       // Only continue if the document has permission to use offline APIs.
       if (!nsContentUtils::OfflineAppAllowed(mDocument->NodePrincipal())) {
         return;
       }
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -7,16 +7,17 @@
 /* A namespace class for static layout utilities. */
 
 #include "mozilla/Util.h"
 
 #include "jsapi.h"
 #include "jsdbgapi.h"
 #include "jsfriendapi.h"
 
+#include "Layers.h"
 #include "nsJSUtils.h"
 #include "nsCOMPtr.h"
 #include "nsAString.h"
 #include "nsPrintfCString.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsDOMCID.h"
 #include "nsContentUtils.h"
@@ -154,16 +155,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsICharsetDetector.h"
 #include "nsICharsetDetectionObserver.h"
 #include "nsIPlatformCharset.h"
 #include "nsIEditor.h"
 #include "nsIEditorDocShell.h"
 #include "mozilla/Attributes.h"
 #include "nsIParserService.h"
 #include "nsIDOMScriptObjectFactory.h"
+#include "nsSandboxFlags.h"
 
 #include "nsWrapperCacheInlines.h"
 
 extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
                                       const char** next, PRUnichar* result);
 extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
                                  int ns_aware, const char** colon);
 
@@ -917,16 +919,63 @@ nsContentUtils::GetParserService()
     if (NS_FAILED(rv)) {
       sParserService = nullptr;
     }
   }
 
   return sParserService;
 }
 
+/**
+ * A helper function that parses a sandbox attribute (of an <iframe> or
+ * a CSP directive) and converts it to the set of flags used internally.
+ *
+ * @param aAttribute    the value of the sandbox attribute
+ * @return              the set of flags
+ */
+PRUint32
+nsContentUtils::ParseSandboxAttributeToFlags(const nsAString& aSandboxAttrValue)
+{
+  // If there's a sandbox attribute at all (and there is if this is being
+  // called), start off by setting all the restriction flags.
+  PRUint32 out = SANDBOXED_NAVIGATION |
+                 SANDBOXED_TOPLEVEL_NAVIGATION |
+                 SANDBOXED_PLUGINS |
+                 SANDBOXED_ORIGIN |
+                 SANDBOXED_FORMS |
+                 SANDBOXED_SCRIPTS |
+                 SANDBOXED_AUTOMATIC_FEATURES;
+
+  if (!aSandboxAttrValue.IsEmpty()) {
+    // The separator optional flag is used because the HTML5 spec says any
+    // whitespace is ok as a separator, which is what this does.
+    HTMLSplitOnSpacesTokenizer tokenizer(aSandboxAttrValue, ' ',
+      nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>::SEPARATOR_OPTIONAL);
+
+    while (tokenizer.hasMoreTokens()) {
+      nsDependentSubstring token = tokenizer.nextToken();
+
+      if (token.LowerCaseEqualsLiteral("allow-same-origin")) {
+        out &= ~SANDBOXED_ORIGIN;
+      } else if (token.LowerCaseEqualsLiteral("allow-forms")) {
+        out &= ~SANDBOXED_FORMS;
+      } else if (token.LowerCaseEqualsLiteral("allow-scripts")) {
+        // allow-scripts removes both SANDBOXED_SCRIPTS and
+        // SANDBOXED_AUTOMATIC_FEATURES.
+        out &= ~SANDBOXED_SCRIPTS;
+        out &= ~SANDBOXED_AUTOMATIC_FEATURES;
+      } else if (token.LowerCaseEqualsLiteral("allow-top-navigation")) {
+        out &= ~SANDBOXED_TOPLEVEL_NAVIGATION;
+      }
+    }
+  }
+
+  return out;
+}
+
 #ifdef MOZ_XTF
 nsIXTFService*
 nsContentUtils::GetXTFService()
 {
   if (!sXTFService) {
     nsresult rv = CallGetService(kXTFServiceCID, &sXTFService);
     if (NS_FAILED(rv)) {
       sXTFService = nullptr;
@@ -4552,17 +4601,17 @@ nsContentUtils::CheckSecurityBeforeLoad(
 
   // Same Origin
   if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
       ((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
        SchemeIs(aURIToLoad, "chrome"))) {
     return NS_OK;
   }
 
-  return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true);
+  return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true, false);
 }
 
 bool
 nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
 {
   bool isSystem;
   nsresult rv = sSecurityManager->IsSystemPrincipal(aPrincipal, &isSystem);
   return NS_SUCCEEDED(rv) && isSystem;
@@ -5702,19 +5751,19 @@ nsContentUtils::CheckSameOrigin(nsIChann
 
   nsCOMPtr<nsIURI> newURI;
   aNewChannel->GetURI(getter_AddRefs(newURI));
   nsCOMPtr<nsIURI> newOriginalURI;
   aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
 
   NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
 
-  nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
+  nsresult rv = oldPrincipal->CheckMayLoad(newURI, false, false);
   if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
-    rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
+    rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false);
   }
 
   return rv;
 }
 
 NS_IMPL_ISUPPORTS2(SameOriginChecker,
                    nsIChannelEventSink,
                    nsIInterfaceRequestor)
@@ -5875,23 +5924,23 @@ nsContentUtils::GetDocumentFromScriptCon
       CallQueryInterface(domdoc, &doc);
     }
   }
   return doc;
 }
 
 /* static */
 bool
-nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel)
+nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel, bool aAllowIfInheritsPrincipal)
 {
   nsCOMPtr<nsIURI> channelURI;
   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
   NS_ENSURE_SUCCESS(rv, false);
 
-  return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false));
+  return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false, aAllowIfInheritsPrincipal));
 }
 
 nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
   : mString(aString), mService(nullptr)
 {
   CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService);
 }
 
@@ -6550,16 +6599,28 @@ nsContentUtils::FindInternalContentViewe
         if (docFactory && aLoaderType) {
           *aLoaderType = TYPE_CONTENT;
         }
         return docFactory.forget();
       }
     }
   }
 #endif
+
+#ifdef MOZ_MEDIA_PLUGINS
+  if (nsHTMLMediaElement::IsMediaPluginsEnabled() &&
+      nsHTMLMediaElement::IsMediaPluginsType(nsDependentCString(aType))) {
+    docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
+    if (docFactory && aLoaderType) {
+      *aLoaderType = TYPE_CONTENT;
+    }
+    return docFactory.forget();
+  }
+#endif // MOZ_MEDIA_PLUGINS
+
 #endif // MOZ_MEDIA
 
   return NULL;
 }
 
 // static
 bool
 nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
@@ -6605,17 +6666,18 @@ nsContentUtils::URIInheritsSecurityConte
                              aResult);
 }
 
 // static
 bool
 nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
                                   nsIChannel* aChannel,
                                   nsIURI* aURI,
-                                  bool aSetUpForAboutBlank)
+                                  bool aSetUpForAboutBlank,
+                                  bool aForceOwner)
 {
   //
   // Set the owner of the channel, but only for channels that can't
   // provide their own security context.
   //
   // XXX: It seems wrong that the owner is ignored - even if one is
   //      supplied) unless the URI is javascript or data or about:blank.
   // XXX: If this is ever changed, check all callers for what owners
@@ -6623,37 +6685,49 @@ nsContentUtils::SetUpChannelOwner(nsIPri
   //      comments in nsDocShell::LoadURI where we fall back on
   //      inheriting the owner if called from chrome.  That would be
   //      very wrong if this code changed anything but channels that
   //      can't provide their own security context!
   //
   //      (Currently chrome URIs set the owner when they are created!
   //      So setting a NULL owner would be bad!)
   //
+  // If aForceOwner is true, the owner will be set, even for a channel that
+  // can provide its own security context. This is used for the HTML5 IFRAME
+  // sandbox attribute, so we can force the channel (and its document) to
+  // explicitly have a null principal.
   bool inherit;
   // We expect URIInheritsSecurityContext to return success for an
   // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
   // This condition needs to match the one in nsDocShell::InternalLoad where
   // we're checking for things that will use the owner.
-  if (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherit)) &&
-      (inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))) {
+  if (aForceOwner || ((NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherit)) &&
+      (inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))))) {
+#ifdef DEBUG
+    // Assert that aForceOwner is only set for null principals
+    if (aForceOwner) {
+      nsCOMPtr<nsIURI> ownerURI;
+      nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(ownerURI));
+      MOZ_ASSERT(NS_SUCCEEDED(rv) && SchemeIs(ownerURI, NS_NULLPRINCIPAL_SCHEME));
+    }
+#endif
     aChannel->SetOwner(aLoadingPrincipal);
     return true;
   }
 
   //
   // file: uri special-casing
   //
   // If this is a file: load opened from another file: then it may need
   // to inherit the owner from the referrer so they can script each other.
   // If we don't set the owner explicitly then each file: gets an owner
   // based on its own codebase later.
   //
   if (URIIsLocalFile(aURI) && aLoadingPrincipal &&
-      NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false)) &&
+      NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false, false)) &&
       // One more check here.  CheckMayLoad will always return true for the
       // system principal, but we do NOT want to inherit in that case.
       !IsSystemPrincipal(aLoadingPrincipal)) {
     aChannel->SetOwner(aLoadingPrincipal);
     return true;
   }
 
   return false;
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -738,20 +738,20 @@ nsCORSListenerProxy::UpdateChannel(nsICh
   if (originalURI != uri) {
     rv = nsContentUtils::GetSecurityManager()->
       CheckLoadURIWithPrincipal(mRequestingPrincipal, originalURI,
                                 nsIScriptSecurityManager::STANDARD);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (!mHasBeenCrossSite &&
-      NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false)) &&
+      NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, false, false)) &&
       (originalURI == uri ||
        NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(originalURI,
-                                                       false)))) {
+                                                       false, false)))) {
     return NS_OK;
   }
 
   // It's a cross site load
   mHasBeenCrossSite = true;
 
   nsCString userpass;
   uri->GetUserPass(userpass);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -163,16 +163,17 @@
 #include "mozilla/dom/Link.h"
 #include "nsXULAppAPI.h"
 #include "nsDOMTouchEvent.h"
 
 #include "mozilla/Preferences.h"
 
 #include "imgILoader.h"
 #include "nsWrapperCacheInlines.h"
+#include "nsSandboxFlags.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::directionality;
 
 typedef nsTArray<Link*> LinkArray;
 
 // Reference to the document which requested DOM full-screen mode.
@@ -1059,28 +1060,22 @@ nsExternalResourceMap::PendingLoad::Star
 
   nsIPrincipal* requestingPrincipal = aRequestingNode->NodePrincipal();
 
   nsresult rv = nsContentUtils::GetSecurityManager()->
     CheckLoadURIWithPrincipal(requestingPrincipal, aURI,
                               nsIScriptSecurityManager::STANDARD);
   NS_ENSURE_SUCCESS(rv, rv);
   
-  // Allow data URIs (let them skip the CheckMayLoad call), since we want
+  // Allow data URIs and other URI's that inherit their principal by passing
+  // true as the 3rd argument of CheckMayLoad, since we want
   // to allow external resources from data URIs regardless of the difference
   // in URI scheme.
-  bool doesInheritSecurityContext;
-  rv =
-    NS_URIChainHasFlags(aURI,
-                        nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
-                        &doesInheritSecurityContext);
-  if (NS_FAILED(rv) || !doesInheritSecurityContext) {
-    rv = requestingPrincipal->CheckMayLoad(aURI, true);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
+  rv = requestingPrincipal->CheckMayLoad(aURI, true, true);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OTHER,
                                  aURI,
                                  requestingPrincipal,
                                  aRequestingNode,
                                  EmptyCString(), //mime guess
                                  nullptr,         //extra
@@ -2407,16 +2402,25 @@ nsDocument::StartDocumentLoad(const char
     FindCharInReadable(';', semicolon, end);
     SetContentTypeInternal(Substring(start, semicolon));
   }
 
   RetrieveRelevantHeaders(aChannel);
 
   mChannel = aChannel;
 
+  // If this document is being loaded by a docshell, copy its sandbox flags
+  // to the document. These are immutable after being set here.
+  nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aContainer);
+
+  if (docShell) {
+    nsresult rv = docShell->GetSandboxFlags(&mSandboxFlags);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
   nsresult rv = InitCSP();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 nsDocument::InitCSP()
@@ -2715,16 +2719,34 @@ nsDocument::SetContentType(const nsAStri
 {
   NS_ASSERTION(GetContentTypeInternal().IsEmpty() ||
                GetContentTypeInternal().Equals(NS_ConvertUTF16toUTF8(aContentType)),
                "Do you really want to change the content-type?");
 
   SetContentTypeInternal(NS_ConvertUTF16toUTF8(aContentType));
 }
 
+nsresult
+nsDocument::GetAllowPlugins(bool * aAllowPlugins)
+{
+  // First, we ask our docshell if it allows plugins.
+  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+
+  if (docShell) {
+    docShell->GetAllowPlugins(aAllowPlugins);
+      
+    // If the docshell allows plugins, we check whether
+    // we are sandboxed and plugins should not be allowed.
+    if (*aAllowPlugins)
+      *aAllowPlugins = !(mSandboxFlags & SANDBOXED_PLUGINS);
+  }
+
+  return NS_OK;
+}
+
 /* Return true if the document is in the focused top-level window, and is an
  * ancestor of the focused DOMWindow. */
 NS_IMETHODIMP
 nsDocument::HasFocus(bool* aResult)
 {
   *aResult = false;
 
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
@@ -6410,16 +6432,22 @@ nsDocument::GetXMLDeclaration(nsAString&
       aStandalone.AssignLiteral("no");
     }
   }
 }
 
 bool
 nsDocument::IsScriptEnabled()
 {
+  // If this document is sandboxed without 'allow-scripts'
+  // script is not enabled
+  if (mSandboxFlags & SANDBOXED_SCRIPTS) {
+    return false;
+  }
+
   nsCOMPtr<nsIScriptSecurityManager> sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
   NS_ENSURE_TRUE(sm, false);
 
   nsIScriptGlobalObject* globalObject = GetScriptGlobalObject();
   NS_ENSURE_TRUE(globalObject, false);
 
   nsIScriptContext *scriptContext = globalObject->GetContext();
   NS_ENSURE_TRUE(scriptContext, false);
@@ -8487,20 +8515,23 @@ DispatchFullScreenChange(nsIDocument* aT
                         true,
                         false);
   e->PostDOMEvent();
 }
 
 NS_IMETHODIMP
 nsDocument::MozCancelFullScreen()
 {
-  if (!nsContentUtils::IsRequestFullScreenAllowed()) {
-    return NS_OK;
-  }
-  RestorePreviousFullScreenState();
+  // Only perform fullscreen changes if we're running in a webapp
+  // same-origin to the web app, or if we're in a user generated event
+  // handler.
+  if (NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
+      nsContentUtils::IsRequestFullScreenAllowed()) {
+    RestorePreviousFullScreenState();
+  }
<