Merge autoland to mozilla-central a=merge on a CLOSED TREE
authorCoroiu Cristina <ccoroiu@mozilla.com>
Sun, 05 May 2019 23:04:20 +0300
changeset 531386 7aae4f23a5a189ffda85ab44342669b235c91c38
parent 531373 e5ed24b52564b6a41fd6a4eadde8e8832c4b91c1 (current diff)
parent 531385 c7a5a7b9cd50eff1be7591a5c49ee1164d800349 (diff)
child 531418 1e3244e602fc0373508049b6fe544332f800f033
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to mozilla-central a=merge on a CLOSED TREE
testing/web-platform/meta/svg/render/reftests/blending-002.svg.ini
--- a/accessible/tests/browser/events/browser_test_focus_urlbar.js
+++ b/accessible/tests/browser/events/browser_test_focus_urlbar.js
@@ -77,17 +77,17 @@ async function runTests() {
   info("Ensuring no focus change on text selection and delete");
   EventUtils.synthesizeKey("KEY_ArrowLeft", {shiftKey: true});
   EventUtils.synthesizeKey("KEY_Delete");
   await waitForSearchFinish();
   // Wait a tick for a11y events to fire.
   await TestUtils.waitForTick();
   testStates(textBox, STATE_FOCUSED);
 
-  info("Ensuring autocomplete focus on down arrow");
+  info("Ensuring autocomplete focus on down arrow (1)");
   focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
   EventUtils.synthesizeKey("KEY_ArrowDown");
   event = await focused;
   testStates(event.accessible, STATE_FOCUSED);
 
   info("Ensuring focus of another autocomplete item on down arrow");
   focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
   EventUtils.synthesizeKey("KEY_ArrowDown");
@@ -121,43 +121,43 @@ async function runTests() {
   testStates(textBox, STATE_FOCUSED);
   if (UrlbarPrefs.get("quantumbar")) {
     gURLBar.view.close();
   }
   // On Mac, down arrow when not at the end of the field moves to the end.
   // Move back to the end so the next press of down arrow opens the popup.
   EventUtils.synthesizeKey("KEY_ArrowRight");
 
-  info("Ensuring autocomplete focus on down arrow");
+  info("Ensuring autocomplete focus on down arrow (2)");
   focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
   EventUtils.synthesizeKey("KEY_ArrowDown");
   event = await focused;
   testStates(event.accessible, STATE_FOCUSED);
 
   info("Ensuring text box focus when text is typed");
   focused = waitForEvent(EVENT_FOCUS, textBox);
   EventUtils.sendString("z");
   await focused;
   testStates(textBox, STATE_FOCUSED);
   EventUtils.synthesizeKey("KEY_Backspace");
   await waitForSearchFinish();
 
-  info("Ensuring autocomplete focus on down arrow");
+  info("Ensuring autocomplete focus on down arrow (3)");
   focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
   EventUtils.synthesizeKey("KEY_ArrowDown");
   event = await focused;
   testStates(event.accessible, STATE_FOCUSED);
 
   info("Ensuring text box focus on backspace");
   focused = waitForEvent(EVENT_FOCUS, textBox);
   EventUtils.synthesizeKey("KEY_Backspace");
   await focused;
   testStates(textBox, STATE_FOCUSED);
 
-  info("Ensuring autocomplete focus on down arrow");
+  info("Ensuring autocomplete focus on down arrow (4)");
   focused = waitForEvent(EVENT_FOCUS, isEventForAutocompleteItem);
   EventUtils.synthesizeKey("KEY_ArrowDown");
   event = await focused;
   testStates(event.accessible, STATE_FOCUSED);
 
   info("Ensuring text box focus on text selection");
   focused = waitForEvent(EVENT_FOCUS, textBox);
   EventUtils.synthesizeKey("KEY_ArrowLeft", {shiftKey: true});
--- a/browser/components/urlbar/UrlbarController.jsm
+++ b/browser/components/urlbar/UrlbarController.jsm
@@ -312,32 +312,39 @@ class UrlbarController {
               { reverse: event.keyCode == KeyEvent.DOM_VK_UP ||
                         event.keyCode == KeyEvent.DOM_VK_PAGE_UP });
           }
         } else {
           if (this.keyEventMovesCaret(event)) {
             break;
           }
           if (executeAction) {
+            this.userSelectionBehavior = "arrow";
             this.input.startQuery({ searchString: this.input.textValue });
           }
         }
         event.preventDefault();
         break;
       case KeyEvent.DOM_VK_LEFT:
       case KeyEvent.DOM_VK_RIGHT:
       case KeyEvent.DOM_VK_HOME:
       case KeyEvent.DOM_VK_END:
         this.view.removeAccessibleFocus();
         break;
       case KeyEvent.DOM_VK_DELETE:
       case KeyEvent.DOM_VK_BACK_SPACE:
-        if (event.shiftKey && this.view.isOpen &&
-            (!executeAction || this._handleDeleteEntry())) {
-          event.preventDefault();
+        if (!this.view.isOpen) {
+          break;
+        }
+        if (event.shiftKey) {
+          if (!executeAction || this._handleDeleteEntry()) {
+            event.preventDefault();
+          }
+        } else if (executeAction) {
+          this.view.removeAccessibleFocus();
         }
         break;
     }
   }
 
   /**
    * Tries to initialize a speculative connection on a result.
    * Speculative connections are only supported for a subset of all the results.
--- a/browser/components/urlbar/UrlbarView.jsm
+++ b/browser/components/urlbar/UrlbarView.jsm
@@ -210,17 +210,17 @@ class UrlbarView {
     this._updateResults(queryContext);
 
     let isFirstPreselectedResult = false;
     if (queryContext.lastResultCount == 0) {
       if (queryContext.preselected) {
         isFirstPreselectedResult = true;
         this._selectItem(this._rows.firstElementChild, {
           updateInput: false,
-          setAccessibleFocus: false,
+          setAccessibleFocus: this.controller._userSelectionBehavior == "arrow",
         });
       } else {
         // Clear the selection when we get a new set of results.
         this._selectItem(null);
       }
       // Hide the one-off search buttons if the input starts with a potential @
       // search alias or the search restriction character.
       let trimmedValue = this.input.textValue.trim();
--- a/browser/config/whats_new_page.yml
+++ b/browser/config/whats_new_page.yml
@@ -63,35 +63,39 @@
       release-types: [beta, release-rc]
       products: [firefox]
       update-channel: beta
       # e.g.: ["<61.0"]. {version.major_number} reflects the current version.
       # This is done by taskgraph.
       versions: ["<{version.major_number}.0"]
       locales:
           - be
-          - bs
           - cak
           - cs
           - cy
           - da
           - de
-          - el
+          - dsb
           - en-CA
           - en-GB
           - en-US
           - es-AR
+          - es-CL
           - es-ES
+          - es-MX
           - fr
           - fy-NL
+          - gn
+          - hsb
           - hu
           - ia
           - id
           - it
           - ka
+          - lij
           - nl
           - nn-NO
           - pl
           - pt-BR
           - pt-PT
           - rm
           - ro
           - ru
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2054,17 +2054,18 @@ void nsJSContext::PokeShrinkingGC() {
 }
 
 // static
 void nsJSContext::MaybePokeCC() {
   if (sCCRunner || sICCRunner || !sHasRunGC || sShuttingDown) {
     return;
   }
 
-  if (!sLastCCEndTime.IsNull()) {
+  // Don't run consecutive CCs too often.
+  if (sCleanupsSinceLastGC && !sLastCCEndTime.IsNull()) {
     uint32_t sinceLastCCEnd = TimeUntilNow(sLastCCEndTime);
     if (sinceLastCCEnd < NS_CC_DELAY) {
       return;
     }
   }
 
   // If GC hasn't run recently and forget skippable only cycle was run,
   // don't start a new cycle too soon.
--- a/dom/media/PeerConnection.jsm
+++ b/dom/media/PeerConnection.jsm
@@ -1636,16 +1636,29 @@ class RTCPeerConnection {
 
     if (maxPacketLifeTime === undefined) {
       maxPacketLifeTime = maxRetransmitTime;
     }
 
     if (maxRetransmitTime !== undefined) {
       this.logWarning("Use maxPacketLifeTime instead of deprecated maxRetransmitTime which will stop working soon in createDataChannel!");
     }
+
+    if (protocol.length > 32767) {
+      // At least 65536/2 UTF-16 characters. UTF-8 might be too long.
+      // Spec says to check how long |protocol| and |label| are in _bytes_. This
+      // is a little ambiguous. For now, examine the length of the utf-8 encoding.
+      const byteCounter = new TextEncoder("utf-8");
+
+      if (byteCounter.encode(protocol).length > 65535) {
+        throw new this._win.DOMException(
+            "protocol cannot be longer than 65535 bytes", "TypeError");
+      }
+    }
+
     if (!negotiated) {
       id = null;
     } else if (id === null) {
       throw new this._win.DOMException(
           "id is required when negotiated is true", "TypeError");
     }
     if (maxPacketLifeTime !== undefined && maxRetransmits !== undefined) {
       throw new this._win.DOMException(
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -965,16 +965,31 @@ void Grouper::PaintContainerItem(DIGroup
       aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext,
                              aRecorder);
       aContext->GetDrawTarget()->PopLayer();
       GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
          aItem->GetPerFrameKey());
       aContext->GetDrawTarget()->FlushItem(aItemBounds);
       break;
     }
+    case DisplayItemType::TYPE_BLEND_CONTAINER: {
+      aContext->GetDrawTarget()->PushLayer(false, 1.0,
+                                           nullptr, mozilla::gfx::Matrix(),
+                                           aItemBounds);
+      GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
+         aItem->GetPerFrameKey());
+      aContext->GetDrawTarget()->FlushItem(aItemBounds);
+      aGroup->PaintItemRange(this, aChildren->GetBottom(), nullptr, aContext,
+                             aRecorder);
+      aContext->GetDrawTarget()->PopLayer();
+      GP("endGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
+         aItem->GetPerFrameKey());
+      aContext->GetDrawTarget()->FlushItem(aItemBounds);
+      break;
+    }
     case DisplayItemType::TYPE_MASK: {
       GP("Paint Mask\n");
       auto maskItem = static_cast<nsDisplayMasksAndClipPaths*>(aItem);
       maskItem->SetPaintRect(maskItem->GetClippedBounds(mDisplayListBuilder));
       if (maskItem->IsValidMask()) {
         maskItem->PaintWithContentsPaintCallback(
             mDisplayListBuilder, aContext, [&] {
               GP("beginGroup %s %p-%d\n", aItem->Name(), aItem->Frame(),
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -9,17 +9,17 @@ use clip::{ClipDataStore, ClipNodeFlags,
 use clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId};
 use glyph_rasterizer::GlyphFormat;
 use gpu_cache::{GpuBlockData, GpuCache, GpuCacheHandle, GpuCacheAddress};
 use gpu_types::{BrushFlags, BrushInstance, PrimitiveHeaders, ZBufferId, ZBufferIdGenerator};
 use gpu_types::{ClipMaskInstance, SplitCompositeInstance, SnapOffsets};
 use gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance};
 use gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette};
 use internal_types::{FastHashMap, SavedTargetIndex, TextureSource};
-use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureSurface};
+use picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive};
 use prim_store::{DeferredResolve, EdgeAaSegmentMask, PrimitiveInstanceKind, PrimitiveVisibilityIndex};
 use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
 use prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex, VECS_PER_SEGMENT};
 use prim_store::image::ImageSource;
 use render_backend::DataStores;
 use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree, TileBlit};
 use renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
 use renderer::{BLOCKS_PER_UV_RECT, MAX_VERTEX_TEXTURE_WIDTH};
@@ -1027,26 +1027,22 @@ impl AlphaBatchBuilder {
                                         ctx.clip_scroll_tree,
                                     ),
                             };
 
                             let raster_config = pic
                                 .raster_config
                                 .as_ref()
                                 .expect("BUG: 3d primitive was not assigned a surface");
-                            let (uv_rect_address, _) = ctx
-                                .surfaces[raster_config.surface_index.0]
-                                .surface
-                                .as_ref()
-                                .expect("BUG: no surface")
-                                .resolve(
-                                    render_tasks,
-                                    ctx.resource_cache,
-                                    gpu_cache,
-                                );
+                            let (uv_rect_address, _) = render_tasks.resolve_surface(
+                                ctx.surfaces[raster_config.surface_index.0]
+                                    .surface
+                                    .expect("BUG: no surface"),
+                                gpu_cache,
+                            );
 
                             let prim_header_index = prim_headers.push(&prim_header, z_id, [
                                 uv_rect_address.as_int(),
                                 if raster_config.establishes_raster_root { 1 } else { 0 },
                                 0,
                                 clip_task_address.0 as i32,
                             ]);
 
@@ -1094,19 +1090,17 @@ impl AlphaBatchBuilder {
                             brush_flags |= BrushFlags::PERSPECTIVE_INTERPOLATION;
                         };
 
                         let clip_task_address = ctx.get_prim_clip_task_address(
                             prim_info.clip_task_index,
                             render_tasks,
                         ).unwrap_or(OPAQUE_TASK_ADDRESS);
 
-                        let surface = ctx.surfaces[raster_config.surface_index.0]
-                            .surface
-                            .as_ref();
+                        let surface = ctx.surfaces[raster_config.surface_index.0].surface;
 
                         match raster_config.composite_mode {
                             PictureCompositeMode::TileCache { .. } => {
                                 let tile_cache = picture.tile_cache.as_ref().unwrap();
 
                                 // If the tile cache is disabled, just recurse into the
                                 // picture like a normal pass-through picture, adding
                                 // any child primitives into the parent surface batches.
@@ -1258,23 +1252,20 @@ impl AlphaBatchBuilder {
                             }
                             PictureCompositeMode::Filter(ref filter) => {
                                 assert!(filter.is_visible());
                                 match filter {
                                     FilterOp::Blur(..) => {
                                         let kind = BatchKind::Brush(
                                             BrushBatchKind::Image(ImageBufferKind::Texture2DArray)
                                         );
-                                        let (uv_rect_address, textures) = surface
-                                            .expect("bug: surface must be allocated by now")
-                                            .resolve(
-                                                render_tasks,
-                                                ctx.resource_cache,
-                                                gpu_cache,
-                                            );
+                                        let (uv_rect_address, textures) = render_tasks.resolve_surface(
+                                            surface.expect("bug: surface must be allocated by now"),
+                                            gpu_cache,
+                                        );
                                         let key = BatchKey::new(
                                             kind,
                                             non_segmented_blend_mode,
                                             textures,
                                         );
                                         let prim_header_index = prim_headers.push(&prim_header, z_id, [
                                             ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
                                             RasterizationSpace::Screen as i32,
@@ -1322,19 +1313,17 @@ impl AlphaBatchBuilder {
                                             ],
                                         };
 
                                         // Build batch keys for shadow/content
                                         let shadow_key = BatchKey::new(kind, non_segmented_blend_mode, shadow_textures);
                                         let content_key = BatchKey::new(kind, non_segmented_blend_mode, content_textures);
 
                                         // Retrieve the UV rect addresses for shadow/content.
-                                        let cache_task_id = surface
-                                            .expect("bug: surface must be allocated by now")
-                                            .resolve_render_task_id();
+                                        let cache_task_id = surface.expect("bug: surface must be allocated by now");
                                         let shadow_uv_rect_address = render_tasks[cache_task_id]
                                             .get_texture_address(gpu_cache)
                                             .as_int();
                                         let content_uv_rect_address = render_tasks[secondary_id]
                                             .get_texture_address(gpu_cache)
                                             .as_int();
 
                                         // Get the GPU cache address of the extra data handle.
@@ -1437,23 +1426,20 @@ impl AlphaBatchBuilder {
                                                 unreachable!();
                                             }
                                             FilterOp::ColorMatrix(_) => {
                                                 picture.extra_gpu_data_handle.as_int(gpu_cache)
                                             }
                                             FilterOp::ComponentTransfer => unreachable!(),
                                         };
 
-                                        let (uv_rect_address, textures) = surface
-                                            .expect("bug: surface must be allocated by now")
-                                            .resolve(
-                                                render_tasks,
-                                                ctx.resource_cache,
-                                                gpu_cache,
-                                            );
+                                        let (uv_rect_address, textures) = render_tasks.resolve_surface(
+                                            surface.expect("bug: surface must be allocated by now"),
+                                            gpu_cache,
+                                        );
 
                                         let key = BatchKey::new(
                                             BatchKind::Brush(BrushBatchKind::Blend),
                                             BlendMode::PremultipliedAlpha,
                                             textures,
                                         );
 
                                         let prim_header_index = prim_headers.push(&prim_header, z_id, [
@@ -1489,23 +1475,20 @@ impl AlphaBatchBuilder {
                                 let filter_mode : i32 = 13 |
                                     ((filter_data.data.r_func.to_int() << 28 |
                                       filter_data.data.g_func.to_int() << 24 |
                                       filter_data.data.b_func.to_int() << 20 |
                                       filter_data.data.a_func.to_int() << 16) as i32);
 
                                 let user_data = filter_data.gpu_cache_handle.as_int(gpu_cache);
 
-                                let (uv_rect_address, textures) = surface
-                                    .expect("bug: surface must be allocated by now")
-                                    .resolve(
-                                        render_tasks,
-                                        ctx.resource_cache,
-                                        gpu_cache,
-                                    );
+                                let (uv_rect_address, textures) = render_tasks.resolve_surface(
+                                    surface.expect("bug: surface must be allocated by now"),
+                                    gpu_cache,
+                                );
 
                                 let key = BatchKey::new(
                                     BatchKind::Brush(BrushBatchKind::Blend),
                                     BlendMode::PremultipliedAlpha,
                                     textures,
                                 );
 
                                 let prim_header_index = prim_headers.push(&prim_header, z_id, [
@@ -1527,23 +1510,20 @@ impl AlphaBatchBuilder {
                                 self.current_batch_list().push_single_instance(
                                     key,
                                     bounding_rect,
                                     z_id,
                                     PrimitiveInstanceData::from(instance),
                                 );
                             }
                             PictureCompositeMode::MixBlend(mode) if ctx.use_advanced_blending => {
-                                let (uv_rect_address, textures) = surface
-                                    .expect("bug: surface must be allocated by now")
-                                    .resolve(
-                                        render_tasks,
-                                        ctx.resource_cache,
-                                        gpu_cache,
-                                    );
+                                let (uv_rect_address, textures) = render_tasks.resolve_surface(
+                                    surface.expect("bug: surface must be allocated by now"),
+                                    gpu_cache,
+                                );
                                 let key = BatchKey::new(
                                     BatchKind::Brush(
                                         BrushBatchKind::Image(ImageBufferKind::Texture2DArray),
                                     ),
                                     BlendMode::Advanced(mode),
                                     textures,
                                 );
                                 let prim_header_index = prim_headers.push(&prim_header, z_id, [
@@ -1565,19 +1545,17 @@ impl AlphaBatchBuilder {
                                 self.current_batch_list().push_single_instance(
                                     key,
                                     bounding_rect,
                                     z_id,
                                     PrimitiveInstanceData::from(instance),
                                 );
                             }
                             PictureCompositeMode::MixBlend(mode) => {
-                                let cache_task_id = surface
-                                    .expect("bug: surface must be allocated by now")
-                                    .resolve_render_task_id();
+                                let cache_task_id = surface.expect("bug: surface must be allocated by now");
                                 let backdrop_id = picture.secondary_render_task_id.expect("no backdrop!?");
 
                                 let key = BatchKey::new(
                                     BatchKind::Brush(
                                         BrushBatchKind::MixBlend {
                                             task_id,
                                             source_id: cache_task_id,
                                             backdrop_id,
@@ -1607,19 +1585,17 @@ impl AlphaBatchBuilder {
                                 self.current_batch_list().push_single_instance(
                                     key,
                                     bounding_rect,
                                     z_id,
                                     PrimitiveInstanceData::from(instance),
                                 );
                             }
                             PictureCompositeMode::Blit(_) => {
-                                let cache_task_id = surface
-                                    .expect("bug: surface must be allocated by now")
-                                    .resolve_render_task_id();
+                                let cache_task_id = surface.expect("bug: surface must be allocated by now");
                                 let uv_rect_address = render_tasks[cache_task_id]
                                     .get_texture_address(gpu_cache)
                                     .as_int();
                                 let batch_params = BrushBatchParameters::shared(
                                     BrushBatchKind::Image(ImageBufferKind::Texture2DArray),
                                     BatchTextures::render_target_cache(),
                                     [
                                         ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
@@ -2648,57 +2624,26 @@ impl PrimitiveInstance {
             Some(ImageProperties { external_image: Some(_), .. }) => {
                 false
             }
             _ => true
         }
     }
 }
 
-impl PictureSurface {
-    // Retrieve the uv rect handle, and texture for a picture surface.
-    fn resolve(
+impl RenderTaskTree {
+    fn resolve_surface(
         &self,
-        render_tasks: &RenderTaskTree,
-        resource_cache: &ResourceCache,
+        task_id: RenderTaskId,
         gpu_cache: &GpuCache,
     ) -> (GpuCacheAddress, BatchTextures) {
-        match *self {
-            PictureSurface::TextureCache(ref handle) => {
-                let rt_cache_entry = resource_cache
-                    .get_cached_render_task(handle);
-                let cache_item = resource_cache
-                    .get_texture_cache_item(&rt_cache_entry.handle);
-
-                (
-                    gpu_cache.get_address(&cache_item.uv_rect_handle),
-                    BatchTextures::color(cache_item.texture_id),
-                )
-            }
-            PictureSurface::RenderTask(task_id) => {
-                (
-                    render_tasks[task_id].get_texture_address(gpu_cache),
-                    BatchTextures::render_target_cache(),
-                )
-            }
-        }
-    }
-
-    // Retrieve the render task id for a picture surface. Should only
-    // be used where it's known that this picture surface will never
-    // be persisted in the texture cache.
-    fn resolve_render_task_id(&self) -> RenderTaskId {
-        match *self {
-            PictureSurface::TextureCache(..) => {
-                panic!("BUG: unexpectedly cached render task");
-            }
-            PictureSurface::RenderTask(task_id) => {
-                task_id
-            }
-        }
+        (
+            self[task_id].get_texture_address(gpu_cache),
+            BatchTextures::render_target_cache(),
+        )
     }
 }
 
 pub fn resolve_image(
     request: ImageRequest,
     resource_cache: &ResourceCache,
     gpu_cache: &mut GpuCache,
     deferred_resolves: &mut Vec<DeferredResolve>,
--- a/gfx/wr/webrender/src/frame_builder.rs
+++ b/gfx/wr/webrender/src/frame_builder.rs
@@ -9,17 +9,17 @@ use clip::{ClipDataStore, ClipStore, Cli
 use clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex};
 use display_list_flattener::{DisplayListFlattener};
 use gpu_cache::{GpuCache, GpuCacheHandle};
 use gpu_types::{PrimitiveHeaders, TransformPalette, UvRectKind, ZBufferIdGenerator};
 use hit_test::{HitTester, HitTestingScene};
 #[cfg(feature = "replay")]
 use hit_test::HitTestingSceneStats;
 use internal_types::{FastHashMap, PlaneSplitter};
-use picture::{PictureSurface, PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex};
+use picture::{PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex};
 use picture::{RetainedTiles, TileCache, DirtyRegion};
 use prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, PrimitiveScratchBuffer};
 #[cfg(feature = "replay")]
 use prim_store::{PrimitiveStoreStats};
 use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
 use render_backend::{DataStores, FrameStamp};
 use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree, RenderTaskTreeCounters};
 use resource_cache::{ResourceCache};
@@ -423,16 +423,34 @@ impl FrameBuilder {
             gpu_cache,
             transforms: transform_palette,
             segment_builder: SegmentBuilder::new(),
             surfaces,
             dirty_region_stack: Vec::new(),
             clip_chain_stack: ClipChainStack::new(),
         };
 
+        let root_render_task = RenderTask::new_picture(
+            RenderTaskLocation::Fixed(self.output_rect),
+            self.output_rect.size.to_f32(),
+            self.root_pic_index,
+            DeviceIntPoint::zero(),
+            Vec::new(),
+            UvRectKind::Rect,
+            root_spatial_node_index,
+            global_device_pixel_scale,
+        );
+
+        let root_render_task_id = frame_state.render_tasks.add(root_render_task);
+        frame_state
+            .surfaces
+            .first_mut()
+            .unwrap()
+            .surface = Some(root_render_task_id);
+
         // Push a default dirty region which culls primitives
         // against the screen world rect, in absence of any
         // other dirty regions.
         let mut default_dirty_region = DirtyRegion::new();
         default_dirty_region.push(
             frame_context.screen_world_rect,
         );
         frame_state.push_dirty_region(default_dirty_region);
@@ -473,34 +491,24 @@ impl FrameBuilder {
         );
 
         frame_state.pop_dirty_region();
 
         let child_tasks = frame_state
             .surfaces[ROOT_SURFACE_INDEX.0]
             .take_render_tasks();
 
-        let root_render_task = RenderTask::new_picture(
-            RenderTaskLocation::Fixed(self.output_rect),
-            self.output_rect.size.to_f32(),
-            self.root_pic_index,
-            DeviceIntPoint::zero(),
-            child_tasks,
-            UvRectKind::Rect,
-            root_spatial_node_index,
-            global_device_pixel_scale,
-        );
+        for child_task_id in child_tasks {
+            frame_state.render_tasks.add_dependency(
+                root_render_task_id,
+                child_task_id,
+            );
+        }
 
-        let render_task_id = frame_state.render_tasks.add(root_render_task);
-        frame_state
-            .surfaces
-            .first_mut()
-            .unwrap()
-            .surface = Some(PictureSurface::RenderTask(render_task_id));
-        Some(render_task_id)
+        Some(root_render_task_id)
     }
 
     pub fn build(
         &mut self,
         resource_cache: &mut ResourceCache,
         gpu_cache: &mut GpuCache,
         stamp: FrameStamp,
         clip_scroll_tree: &mut ClipScrollTree,
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -22,17 +22,17 @@ use gpu_cache::{GpuCache, GpuCacheAddres
 use gpu_types::{TransformPalette, UvRectKind};
 use plane_split::{Clipper, Polygon, Splitter};
 use prim_store::{CoordinateSpaceMapping, SpaceMapper};
 use prim_store::{PictureIndex, PrimitiveInstance, PrimitiveInstanceKind};
 use prim_store::{get_raster_rects, PrimitiveScratchBuffer, VectorKey, PointKey};
 use prim_store::{OpacityBindingStorage, ImageInstanceStorage, OpacityBindingIndex, RectangleKey};
 use print_tree::PrintTreePrinter;
 use render_backend::DataStores;
-use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle, TileBlit};
+use render_task::{ClearMode, RenderTask, TileBlit};
 use render_task::{RenderTaskId, RenderTaskLocation};
 use resource_cache::ResourceCache;
 use scene::{FilterOpHelpers, SceneProperties};
 use scene_builder::Interners;
 use smallvec::SmallVec;
 use std::{mem, u16};
 use std::sync::atomic::{AtomicUsize, Ordering};
 use texture_cache::TextureCacheHandle;
@@ -1789,17 +1789,17 @@ pub struct SurfaceInfo {
     /// Helper structs for mapping local rects in different
     /// coordinate systems into the surface coordinates.
     pub map_local_to_surface: SpaceMapper<LayoutPixel, PicturePixel>,
     /// Defines the positioning node for the surface itself,
     /// and the rasterization root for this surface.
     pub raster_spatial_node_index: SpatialNodeIndex,
     pub surface_spatial_node_index: SpatialNodeIndex,
     /// This is set when the render task is created.
-    pub surface: Option<PictureSurface>,
+    pub surface: Option<RenderTaskId>,
     /// A list of render tasks that are dependencies of this surface.
     pub tasks: Vec<RenderTaskId>,
     /// How much the local surface rect should be inflated (for blur radii).
     pub inflation_factor: f32,
     /// The device pixel ratio specific to this surface.
     pub device_pixel_scale: DevicePixelScale,
     /// If true, subpixel AA rendering can be used on this surface.
     pub allow_subpixel_aa: bool,
@@ -1893,27 +1893,16 @@ pub enum PictureCompositeMode {
     /// is used for CSS isolation, and plane splitting.
     Blit(BlitReason),
     /// Used to cache a picture as a series of tiles.
     TileCache {
         clear_color: ColorF,
     },
 }
 
-// Stores the location of the picture if it is drawn to
-// an intermediate surface. This can be a render task if
-// it is not persisted, or a texture cache item if the
-// picture is cached in the texture cache.
-#[derive(Debug)]
-pub enum PictureSurface {
-    RenderTask(RenderTaskId),
-    #[allow(dead_code)]
-    TextureCache(RenderTaskCacheEntryHandle),
-}
-
 /// Enum value describing the place of a picture in a 3D context.
 #[derive(Clone, Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 pub enum Picture3DContext<C> {
     /// The picture is not a part of 3D context sub-hierarchy.
     Out,
     /// The picture is a part of 3D context.
     In {
@@ -2492,24 +2481,24 @@ impl PicturePrimitive {
     }
 
     /// Add a primitive instance to the plane splitter. The function would generate
     /// an appropriate polygon, clip it against the frustum, and register with the
     /// given plane splitter.
     pub fn add_split_plane(
         splitter: &mut PlaneSplitter,
         transforms: &TransformPalette,
-        prim_instance: &PrimitiveInstance,
+        prim_spatial_node_index: SpatialNodeIndex,
         original_local_rect: LayoutRect,
         combined_local_clip_rect: &LayoutRect,
         world_rect: WorldRect,
         plane_split_anchor: usize,
     ) -> bool {
         let transform = transforms
-            .get_world_transform(prim_instance.spatial_node_index);
+            .get_world_transform(prim_spatial_node_index);
         let matrix = transform.cast();
 
         // Apply the local clip rect here, before splitting. This is
         // because the local clip rect can't be applied in the vertex
         // shader for split composites, since we are drawing polygons
         // rather that rectangles. The interpolation still works correctly
         // since we determine the UVs by doing a bilerp with a factor
         // from the original local rect.
@@ -2518,17 +2507,17 @@ impl PicturePrimitive {
         {
             Some(rect) => rect.cast(),
             None => return false,
         };
         let world_rect = world_rect.cast();
 
         if transform.is_simple_translation() {
             let inv_transform = transforms
-                .get_world_inv_transform(prim_instance.spatial_node_index);
+                .get_world_inv_transform(prim_spatial_node_index);
             let polygon = Polygon::from_transformed_rect_with_inverse(
                 local_rect,
                 &matrix,
                 &inv_transform.cast(),
                 plane_split_anchor,
             ).unwrap();
             splitter.add(polygon);
         } else {
@@ -2881,17 +2870,16 @@ impl PicturePrimitive {
                 parent_surface.rect = parent_surface.rect.union(&parent_surface_rect);
             }
         }
     }
 
     pub fn prepare_for_render(
         &mut self,
         pic_index: PictureIndex,
-        prim_instance: &PrimitiveInstance,
         clipped_prim_bounding_rect: WorldRect,
         surface_index: SurfaceIndex,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         data_stores: &mut DataStores,
     ) -> bool {
         let (mut pic_state_for_children, pic_context) = self.take_state_and_context();
 
@@ -2911,17 +2899,17 @@ impl PicturePrimitive {
             (
                 surface_info.raster_spatial_node_index,
                 surface_info.take_render_tasks(),
                 surface_info.device_pixel_scale,
             )
         };
 
         let (map_raster_to_world, map_pic_to_raster) = create_raster_mappers(
-            prim_instance.spatial_node_index,
+            self.spatial_node_index,
             raster_spatial_node_index,
             frame_context.screen_world_rect,
             frame_context.clip_scroll_tree,
         );
 
         let pic_rect = PictureRect::from_untyped(&self.local_rect.to_untyped());
 
         let (clipped, unclipped) = match get_raster_rects(
@@ -3010,17 +2998,17 @@ impl PicturePrimitive {
                     RenderTargetKind::Color,
                     ClearMode::Transparent,
                 );
 
                 let render_task_id = frame_state.render_tasks.add(blur_render_task);
 
                 frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
 
-                PictureSurface::RenderTask(render_task_id)
+                render_task_id
             }
             PictureCompositeMode::Filter(FilterOp::DropShadow(offset, blur_radius, color)) => {
                 let blur_std_deviation = blur_radius * device_pixel_scale.0;
                 let blur_range = (blur_std_deviation * BLUR_SAMPLE_SCALE).ceil() as i32;
                 let rounded_std_dev = blur_std_deviation.round();
                 let rounded_std_dev = DeviceSize::new(rounded_std_dev, rounded_std_dev);
                 // The clipped field is the part of the picture that is visible
                 // on screen. The unclipped field is the screen-space rect of
@@ -3096,17 +3084,17 @@ impl PicturePrimitive {
                         0.0,
                     ]);
 
                     // segment rect / extra data
                     request.push(shadow_rect);
                     request.push([0.0, 0.0, 0.0, 0.0]);
                 }
 
-                PictureSurface::RenderTask(render_task_id)
+                render_task_id
             }
             PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {
                 let uv_rect_kind = calculate_uv_rect_kind(
                     &pic_rect,
                     &transform,
                     &clipped,
                     device_pixel_scale,
                     true,
@@ -3127,17 +3115,17 @@ impl PicturePrimitive {
                     RenderTask::new_readback(clipped)
                 );
 
                 self.secondary_render_task_id = Some(readback_task_id);
                 frame_state.surfaces[surface_index.0].tasks.push(readback_task_id);
 
                 let render_task_id = frame_state.render_tasks.add(picture_task);
                 frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
-                PictureSurface::RenderTask(render_task_id)
+                render_task_id
             }
             PictureCompositeMode::Filter(ref filter) => {
                 if let FilterOp::ColorMatrix(m) = *filter {
                     if let Some(mut request) = frame_state.gpu_cache.request(&mut self.extra_gpu_data_handle) {
                         for i in 0..5 {
                             request.push([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]);
                         }
                     }
@@ -3159,17 +3147,17 @@ impl PicturePrimitive {
                     child_tasks,
                     uv_rect_kind,
                     pic_context.raster_spatial_node_index,
                     device_pixel_scale,
                 );
 
                 let render_task_id = frame_state.render_tasks.add(picture_task);
                 frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
-                PictureSurface::RenderTask(render_task_id)
+                render_task_id
             }
             PictureCompositeMode::ComponentTransferFilter(handle) => {
                 let filter_data = &mut data_stores.filter_data[handle];
                 filter_data.update(frame_state);
 
                 let uv_rect_kind = calculate_uv_rect_kind(
                     &pic_rect,
                     &transform,
@@ -3186,17 +3174,17 @@ impl PicturePrimitive {
                     child_tasks,
                     uv_rect_kind,
                     pic_context.raster_spatial_node_index,
                     device_pixel_scale,
                 );
 
                 let render_task_id = frame_state.render_tasks.add(picture_task);
                 frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
-                PictureSurface::RenderTask(render_task_id)
+                render_task_id
             }
             PictureCompositeMode::MixBlend(..) |
             PictureCompositeMode::Blit(_) => {
                 // The SplitComposite shader used for 3d contexts doesn't snap
                 // to pixels, so we shouldn't snap our uv coordinates either.
                 let supports_snapping = match self.context_3d {
                     Picture3DContext::In{ .. } => false,
                     _ => true,
@@ -3218,17 +3206,17 @@ impl PicturePrimitive {
                     child_tasks,
                     uv_rect_kind,
                     pic_context.raster_spatial_node_index,
                     device_pixel_scale,
                 );
 
                 let render_task_id = frame_state.render_tasks.add(picture_task);
                 frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
-                PictureSurface::RenderTask(render_task_id)
+                render_task_id
             }
         };
 
         frame_state.surfaces[raster_config.surface_index.0].surface = Some(surface);
 
         true
     }
 }
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -2437,88 +2437,26 @@ impl PrimitiveStore {
             }
         }
 
         #[cfg(debug_assertions)]
         {
             prim_instance.prepared_frame_id = frame_state.render_tasks.frame_id();
         }
 
-        match prim_instance.kind {
-            PrimitiveInstanceKind::Picture { pic_index, segment_instance_index, .. } => {
-                let pic = &mut self.pictures[pic_index.0];
-                let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
-                if pic.prepare_for_render(
-                    pic_index,
-                    prim_instance,
-                    prim_info.clipped_world_rect,
-                    pic_context.surface_index,
-                    frame_context,
-                    frame_state,
-                    data_stores,
-                ) {
-                    if let Some(ref mut splitter) = pic_state.plane_splitter {
-                        PicturePrimitive::add_split_plane(
-                            splitter,
-                            frame_state.transforms,
-                            prim_instance,
-                            pic.local_rect,
-                            &prim_info.combined_local_clip_rect,
-                            frame_context.screen_world_rect,
-                            plane_split_anchor,
-                        );
-                    }
-
-                    // If this picture uses segments, ensure the GPU cache is
-                    // up to date with segment local rects.
-                    // TODO(gw): This entire match statement above can now be
-                    //           refactored into prepare_interned_prim_for_render.
-                    if pic.can_use_segments() {
-                        write_segment(
-                            segment_instance_index,
-                            frame_state,
-                            &mut scratch.segments,
-                            &mut scratch.segment_instances,
-                            |request| {
-                                request.push(PremultipliedColorF::WHITE);
-                                request.push(PremultipliedColorF::WHITE);
-                                request.push([
-                                    -1.0,       // -ve means use prim rect for stretch size
-                                    0.0,
-                                    0.0,
-                                    0.0,
-                                ]);
-                            }
-                        );
-                    }
-                } else {
-                    prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
-                }
-            }
-            PrimitiveInstanceKind::TextRun { .. } |
-            PrimitiveInstanceKind::Clear { .. } |
-            PrimitiveInstanceKind::Rectangle { .. } |
-            PrimitiveInstanceKind::NormalBorder { .. } |
-            PrimitiveInstanceKind::ImageBorder { .. } |
-            PrimitiveInstanceKind::YuvImage { .. } |
-            PrimitiveInstanceKind::Image { .. } |
-            PrimitiveInstanceKind::LinearGradient { .. } |
-            PrimitiveInstanceKind::RadialGradient { .. } |
-            PrimitiveInstanceKind::LineDecoration { .. } => {
-                self.prepare_interned_prim_for_render(
-                    prim_instance,
-                    pic_context,
-                    pic_state,
-                    frame_context,
-                    frame_state,
-                    data_stores,
-                    scratch,
-                );
-            }
-        }
+        self.prepare_interned_prim_for_render(
+            prim_instance,
+            plane_split_anchor,
+            pic_context,
+            pic_state,
+            frame_context,
+            frame_state,
+            data_stores,
+            scratch,
+        );
 
         true
     }
 
     pub fn prepare_primitives(
         &mut self,
         prim_list: &mut PrimitiveList,
         pic_context: &PictureContext,
@@ -2597,18 +2535,19 @@ impl PrimitiveStore {
     }
 
     /// Prepare an interned primitive for rendering, by requesting
     /// resources, render tasks etc. This is equivalent to the
     /// prepare_prim_for_render_inner call for old style primitives.
     fn prepare_interned_prim_for_render(
         &mut self,
         prim_instance: &mut PrimitiveInstance,
+        plane_split_anchor: usize,
         pic_context: &PictureContext,
-        pic_state: &PictureState,
+        pic_state: &mut PictureState,
         frame_context: &FrameBuildingContext,
         frame_state: &mut FrameBuildingState,
         data_stores: &mut DataStores,
         scratch: &mut PrimitiveScratchBuffer,
     ) {
         let is_chased = prim_instance.is_chased();
         let device_pixel_scale = frame_state.surfaces[pic_context.surface_index.0].device_pixel_scale;
 
@@ -2988,18 +2927,64 @@ impl PrimitiveStore {
                     if visible_tiles_range.is_empty() {
                         prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
                     }
                 }
 
                 // TODO(gw): Consider whether it's worth doing segment building
                 //           for gradient primitives.
             }
-            _ => {
-                unreachable!();
+            PrimitiveInstanceKind::Picture { pic_index, segment_instance_index, .. } => {
+                let pic = &mut self.pictures[pic_index.0];
+                let prim_info = &scratch.prim_info[prim_instance.visibility_info.0 as usize];
+                if pic.prepare_for_render(
+                    *pic_index,
+                    prim_info.clipped_world_rect,
+                    pic_context.surface_index,
+                    frame_context,
+                    frame_state,
+                    data_stores,
+                ) {
+                    if let Some(ref mut splitter) = pic_state.plane_splitter {
+                        PicturePrimitive::add_split_plane(
+                            splitter,
+                            frame_state.transforms,
+                            prim_instance.spatial_node_index,
+                            pic.local_rect,
+                            &prim_info.combined_local_clip_rect,
+                            frame_context.screen_world_rect,
+                            plane_split_anchor,
+                        );
+                    }
+
+                    // If this picture uses segments, ensure the GPU cache is
+                    // up to date with segment local rects.
+                    // TODO(gw): This entire match statement above can now be
+                    //           refactored into prepare_interned_prim_for_render.
+                    if pic.can_use_segments() {
+                        write_segment(
+                            *segment_instance_index,
+                            frame_state,
+                            &mut scratch.segments,
+                            &mut scratch.segment_instances,
+                            |request| {
+                                request.push(PremultipliedColorF::WHITE);
+                                request.push(PremultipliedColorF::WHITE);
+                                request.push([
+                                    -1.0,       // -ve means use prim rect for stretch size
+                                    0.0,
+                                    0.0,
+                                    0.0,
+                                ]);
+                            }
+                        );
+                    }
+                } else {
+                    prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
+                }
             }
         };
     }
 }
 
 fn write_segment<F>(
     segment_instance_index: SegmentInstanceIndex,
     frame_state: &mut FrameBuildingState,
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -134,16 +134,27 @@ impl RenderTaskTree {
         self.tasks.push(task);
         RenderTaskId {
             index,
             #[cfg(debug_assertions)]
             frame_id: self.frame_id,
         }
     }
 
+    /// Express a render task dependency between a parent and child task.
+    /// This is used to assign tasks to render passes.
+    pub fn add_dependency(
+        &mut self,
+        parent_id: RenderTaskId,
+        child_id: RenderTaskId,
+    ) {
+        let parent = &mut self[parent_id];
+        parent.children.push(child_id);
+    }
+
     /// Assign this frame's render tasks to render passes ordered so that passes appear
     /// earlier than the ones that depend on them.
     pub fn generate_passes(
         &self,
         main_render_task: Option<RenderTaskId>,
         screen_size: DeviceIntSize,
         gpu_supports_fast_clears: bool,
     ) -> Vec<RenderPass> {
--- a/mobile/android/base/java/org/mozilla/gecko/icons/IconTask.java
+++ b/mobile/android/base/java/org/mozilla/gecko/icons/IconTask.java
@@ -146,34 +146,34 @@ import java.util.concurrent.Callable;
 
             processor.process(request, response);
 
             logProcessor(processor);
         }
     }
 
     private void handleException(final Throwable t) {
-        if (AppConstants.NIGHTLY_BUILD) {
+        if (AppConstants.NIGHTLY_BUILD || AppConstants.FENNEC_NIGHTLY) {
             // We want to be aware of problems: Let's re-throw the exception on the main thread to
             // force an app crash. However we only do this in Nightly builds. Every other build
             // (especially release builds) should just carry on and log the error.
             ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
                     throw new RuntimeException("Icon task thread crashed", t);
                 }
             });
         } else {
             Log.e(LOGTAG, "Icon task crashed", t);
         }
     }
 
     private boolean shouldLog() {
         // Do not log anything if debugging is disabled and never log anything in a non-nightly build.
-        return DEBUG && AppConstants.NIGHTLY_BUILD;
+        return DEBUG && (AppConstants.NIGHTLY_BUILD || AppConstants.FENNEC_NIGHTLY);
     }
 
     private void logPreparer(IconRequest request, Preparer preparer) {
         if (!shouldLog()) {
             return;
         }
 
         Log.d(LOGTAG, String.format("  PREPARE %s" + " (%s)",
--- a/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/media/MediaControlService.java
@@ -35,19 +35,19 @@ public class MediaControlService extends
     }
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         Log.d(LOGTAG, "onStartCommand");
 
         if (intent.hasExtra(GeckoMediaControlAgent.EXTRA_NOTIFICATION_DATA)) {
             if (GeckoMediaControlAgent.getInstance().isAttachedToContext() ||
-                    /* bug 1516665 - If we are not attached to context but the build is not release or beta continue
+                    /* bug 1516665 - If we are not attached to context but the build is a Nightly, continue
                     in order to gather more information */
-                    !AppConstants.RELEASE_OR_BETA) {
+                    AppConstants.FENNEC_NIGHTLY) {
                     currentNotification = GeckoMediaControlAgent.getInstance().createNotification(
                             (MediaNotification) intent.getParcelableExtra(GeckoMediaControlAgent.EXTRA_NOTIFICATION_DATA));
             } else {
                 intent.setAction(GeckoMediaControlAgent.ACTION_SHUTDOWN);
             }
         }
 
         startForeground(R.id.mediaControlNotification, currentNotification);
--- a/mobile/android/chrome/content/about.xhtml
+++ b/mobile/android/chrome/content/about.xhtml
@@ -52,25 +52,29 @@
 
     <ul id="aboutLinks">
       <div class="top-border"></div>
       <li><a id="faqURL">&aboutPage.faq.label;</a></li>
       <li><a id="supportURL">&aboutPage.support.label;</a></li>
       <li><a id="privacyURL">&aboutPage.privacyPolicy.label;</a></li>
       <li><a href="about:rights">&aboutPage.rights.label;</a></li>
 #ifndef NIGHTLY_BUILD
+#ifndef FENNEC_NIGHTLY
       <li><a id="releaseNotesURL">&aboutPage.relNotes.label;</a></li>
 #endif
+#endif
       <li><a id="creditsURL">&aboutPage.credits.label;</a></li>
       <li><a href="about:license">&aboutPage.license.label;</a></li>
       <div class="bottom-border"></div>
     </ul>
 
 #ifdef RELEASE_OR_BETA
+#ifndef FENNEC_NIGHTLY
     <div id="aboutDetails">
       <p>&aboutPage.logoTrademark;</p>
     </div>
 #endif
+#endif
 
     <script type="application/javascript" src="chrome://browser/content/about.js" />
 
 </body>
 </html>
--- a/mobile/android/installer/Makefile.in
+++ b/mobile/android/installer/Makefile.in
@@ -62,20 +62,22 @@ MOZ_PACKAGER_MINIFY=1
 include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
 
 # Note that JS_BINARY can be defined in packager.mk, so this test must come
 # after including that file. MOZ_PACKAGER_MINIFY_JS is used in packager.mk, but
 # since recipe evaluation is deferred, we can set it here after the inclusion.
 ifneq (,$(JS_BINARY))
 ifndef MOZ_DEBUG
 ifndef NIGHTLY_BUILD
+ifndef FENNEC_NIGHTLY
 MOZ_PACKAGER_MINIFY_JS=1
 endif
 endif
 endif
+endif
 
 ifeq (bundle, $(MOZ_FS_LAYOUT))
 BINPATH = $(_BINPATH)
 DEFINES += -DAPPNAME=$(_APPNAME)
 else
 # Every other platform just winds up in dist/bin
 BINPATH = bin
 endif
--- a/old-configure.in
+++ b/old-configure.in
@@ -3117,17 +3117,17 @@ fi
 AC_SUBST(MOZ_SOURCE_REPO)
 AC_SUBST(MOZ_SOURCE_CHANGESET)
 AC_SUBST(MOZ_INCLUDE_SOURCE_INFO)
 
 if test "$MOZ_TELEMETRY_REPORTING"; then
     AC_DEFINE(MOZ_TELEMETRY_REPORTING)
 
     # Enable Telemetry by default for nightly and aurora channels
-    if test -z "$RELEASE_OR_BETA"; then
+    if test -z "$RELEASE_OR_BETA" || test -n "$FENNEC_NIGHTLY"; then
       AC_DEFINE(MOZ_TELEMETRY_ON_BY_DEFAULT)
     fi
 fi
 
 dnl If we have any service that uploads data (and requires data submission
 dnl policy alert), set MOZ_DATA_REPORTING.
 dnl We need SUBST for build system and DEFINE for xul preprocessor.
 if test -n "$MOZ_TELEMETRY_REPORTING" || test -n "$MOZ_SERVICES_HEALTHREPORT" || test -n "$MOZ_CRASHREPORTER"; then
--- a/security/manager/ssl/ContentSignatureVerifier.cpp
+++ b/security/manager/ssl/ContentSignatureVerifier.cpp
@@ -2,79 +2,148 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ContentSignatureVerifier.h"
 
 #include "BRNameMatchingPolicy.h"
+#include "CryptoTask.h"
 #include "ScopedNSSTypes.h"
 #include "SharedCertVerifier.h"
 #include "cryptohi.h"
 #include "keyhi.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Unused.h"
+#include "mozilla/dom/Promise.h"
 #include "nsCOMPtr.h"
 #include "nsPromiseFlatString.h"
 #include "nsSecurityHeaderParser.h"
 #include "nsWhitespaceTokenizer.h"
 #include "mozpkix/pkix.h"
 #include "mozpkix/pkixtypes.h"
 #include "secerr.h"
 
 NS_IMPL_ISUPPORTS(ContentSignatureVerifier, nsIContentSignatureVerifier)
 
 using namespace mozilla;
 using namespace mozilla::pkix;
 using namespace mozilla::psm;
+using dom::Promise;
 
 static LazyLogModule gCSVerifierPRLog("ContentSignatureVerifier");
 #define CSVerifier_LOG(args) MOZ_LOG(gCSVerifierPRLog, LogLevel::Debug, args)
 
 // Content-Signature prefix
 const unsigned char kPREFIX[] = {'C', 'o', 'n', 't', 'e', 'n', 't',
                                  '-', 'S', 'i', 'g', 'n', 'a', 't',
                                  'u', 'r', 'e', ':', 0};
 
+class VerifyContentSignatureTask : public CryptoTask {
+ public:
+  VerifyContentSignatureTask(const nsACString& aData,
+                             const nsACString& aCSHeader,
+                             const nsACString& aCertChain,
+                             const nsACString& aHostname,
+                             RefPtr<Promise>& aPromise)
+      : mData(aData),
+        mCSHeader(aCSHeader),
+        mCertChain(aCertChain),
+        mHostname(aHostname),
+        mSignatureVerified(false),
+        mPromise(aPromise) {}
+
+ private:
+  virtual nsresult CalculateResult() override;
+  virtual void CallCallback(nsresult rv) override;
+
+  nsCString mData;
+  nsCString mCSHeader;
+  nsCString mCertChain;
+  nsCString mHostname;
+  bool mSignatureVerified;
+  RefPtr<Promise> mPromise;
+};
+
 NS_IMETHODIMP
-ContentSignatureVerifier::VerifyContentSignature(const nsACString& aData,
-                                                 const nsACString& aCSHeader,
-                                                 const nsACString& aCertChain,
-                                                 const nsACString& aHostname,
-                                                 bool* _retval) {
-  NS_ENSURE_ARG(_retval);
-  *_retval = false;
+ContentSignatureVerifier::AsyncVerifyContentSignature(
+    const nsACString& aData, const nsACString& aCSHeader,
+    const nsACString& aCertChain, const nsACString& aHostname, JSContext* aCx,
+    Promise** aPromise) {
+  NS_ENSURE_ARG_POINTER(aCx);
+
+  nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aCx);
+  if (NS_WARN_IF(!globalObject)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  ErrorResult result;
+  RefPtr<Promise> promise = Promise::Create(globalObject, result);
+  if (NS_WARN_IF(result.Failed())) {
+    return result.StealNSResult();
+  }
 
+  RefPtr<VerifyContentSignatureTask> task(new VerifyContentSignatureTask(
+      aData, aCSHeader, aCertChain, aHostname, promise));
+  nsresult rv = task->Dispatch("ContentSig");
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  promise.forget(aPromise);
+  return NS_OK;
+}
+
+static nsresult VerifyContentSignatureInternal(
+    const nsACString& aData, const nsACString& aCSHeader,
+    const nsACString& aCertChain, const nsACString& aHostname,
+    /* out */
+    mozilla::Telemetry::LABELS_CONTENT_SIGNATURE_VERIFICATION_ERRORS&
+        aErrorLabel,
+    /* out */ nsACString& aCertFingerprint, /* out */ uint32_t& aErrorValue);
+static nsresult ParseContentSignatureHeader(
+    const nsACString& aContentSignatureHeader,
+    /* out */ nsCString& aSignature);
+
+nsresult VerifyContentSignatureTask::CalculateResult() {
   // 3 is the default, non-specific, "something failed" error.
   Telemetry::LABELS_CONTENT_SIGNATURE_VERIFICATION_ERRORS errorLabel =
       Telemetry::LABELS_CONTENT_SIGNATURE_VERIFICATION_ERRORS::err3;
   nsAutoCString certFingerprint;
   uint32_t errorValue = 3;
   nsresult rv =
-      VerifyContentSignatureInternal(aData, aCSHeader, aCertChain, aHostname,
+      VerifyContentSignatureInternal(mData, mCSHeader, mCertChain, mHostname,
                                      errorLabel, certFingerprint, errorValue);
   if (NS_FAILED(rv)) {
     CSVerifier_LOG(("CSVerifier: Signature verification failed"));
     if (certFingerprint.Length() > 0) {
       Telemetry::AccumulateCategoricalKeyed(certFingerprint, errorLabel);
     }
     Accumulate(Telemetry::CONTENT_SIGNATURE_VERIFICATION_STATUS, errorValue);
     if (rv == NS_ERROR_INVALID_SIGNATURE) {
       return NS_OK;
     }
     return rv;
   }
 
-  *_retval = true;
+  mSignatureVerified = true;
   Accumulate(Telemetry::CONTENT_SIGNATURE_VERIFICATION_STATUS, 0);
 
   return NS_OK;
 }
 
+void VerifyContentSignatureTask::CallCallback(nsresult rv) {
+  if (NS_FAILED(rv)) {
+    mPromise->MaybeReject(rv);
+  } else {
+    mPromise->MaybeResolve(mSignatureVerified);
+  }
+}
+
 bool IsNewLine(char16_t c) { return c == '\n' || c == '\r'; }
 
 nsresult ReadChainIntoCertList(const nsACString& aCertChain,
                                CERTCertList* aCertList) {
   bool inBlock = false;
   bool certFound = false;
 
   const nsCString header = NS_LITERAL_CSTRING("-----BEGIN CERTIFICATE-----");
@@ -133,17 +202,17 @@ nsresult ReadChainIntoCertList(const nsA
 
 // Given data to verify, a content signature header value, a string representing
 // a list of PEM-encoded certificates, and a hostname to validate the
 // certificates against, this function attempts to validate the certificate
 // chain, extract the signature from the header, and verify the data using the
 // key in the end-entity certificate from the chain. Returns NS_OK if everything
 // is satisfactory and a failing nsresult otherwise. The output parameters are
 // filled with telemetry data to report in the case of failures.
-nsresult ContentSignatureVerifier::VerifyContentSignatureInternal(
+static nsresult VerifyContentSignatureInternal(
     const nsACString& aData, const nsACString& aCSHeader,
     const nsACString& aCertChain, const nsACString& aHostname,
     /* out */
     Telemetry::LABELS_CONTENT_SIGNATURE_VERIFICATION_ERRORS& aErrorLabel,
     /* out */ nsACString& aCertFingerprint,
     /* out */ uint32_t& aErrorValue) {
   UniqueCERTCertList certCertList(CERT_NewCertList());
   if (!certCertList) {
@@ -311,17 +380,17 @@ nsresult ContentSignatureVerifier::Verif
     aErrorLabel = Telemetry::LABELS_CONTENT_SIGNATURE_VERIFICATION_ERRORS::err1;
     aErrorValue = 1;
     return NS_ERROR_INVALID_SIGNATURE;
   }
 
   return NS_OK;
 }
 
-nsresult ContentSignatureVerifier::ParseContentSignatureHeader(
+static nsresult ParseContentSignatureHeader(
     const nsACString& aContentSignatureHeader,
     /* out */ nsCString& aSignature) {
   // We only support p384 ecdsa.
   NS_NAMED_LITERAL_CSTRING(signature_var, "p384ecdsa");
 
   aSignature.Truncate();
 
   const nsCString& flatHeader = PromiseFlatCString(aContentSignatureHeader);
--- a/security/manager/ssl/ContentSignatureVerifier.h
+++ b/security/manager/ssl/ContentSignatureVerifier.h
@@ -22,22 +22,11 @@
 
 class ContentSignatureVerifier final : public nsIContentSignatureVerifier {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTSIGNATUREVERIFIER
 
  private:
   ~ContentSignatureVerifier() = default;
-
-  nsresult VerifyContentSignatureInternal(
-      const nsACString& aData, const nsACString& aCSHeader,
-      const nsACString& aCertChain, const nsACString& aHostname,
-      /* out */
-      mozilla::Telemetry::LABELS_CONTENT_SIGNATURE_VERIFICATION_ERRORS&
-          aErrorLabel,
-      /* out */ nsACString& aCertFingerprint, /* out */ uint32_t& aErrorValue);
-  nsresult ParseContentSignatureHeader(
-      const nsACString& aContentSignatureHeader,
-      /* out */ nsCString& aSignature);
 };
 
 #endif  // ContentSignatureVerifier_h
--- a/security/manager/ssl/nsIContentSignatureVerifier.idl
+++ b/security/manager/ssl/nsIContentSignatureVerifier.idl
@@ -22,17 +22,18 @@ interface nsIContentSignatureVerifier : 
    *
    * @param aData                   The data to be tested.
    * @param aContentSignatureHeader The content-signature header,
    *                                url-safe base64 encoded.
    * @param aCertificateChain       The certificate chain to use for verification.
    *                                PEM encoded string.
    * @param aHostname               The hostname for which the end entity must
                                     be valid.
-   * @returns true if the signature matches the data and aCertificateChain is
-   *          valid within aContext, false if not.
+   * @returns Promise that resolves with the value true if the signature
+   *          matches the data and aCertificateChain is valid within aContext,
+   *          and false if not. Rejects if another error occurred.
    */
-  [must_use]
-  boolean verifyContentSignature(in ACString aData,
-                                 in ACString aContentSignatureHeader,
-                                 in ACString aCertificateChain,
-                                 in ACString aHostname);
+  [implicit_jscontext, must_use]
+  Promise asyncVerifyContentSignature(in ACString aData,
+                                      in ACString aContentSignatureHeader,
+                                      in ACString aCertificateChain,
+                                      in ACString aHostname);
 };
--- a/security/manager/ssl/tests/unit/test_content_signing.js
+++ b/security/manager/ssl/tests/unit/test_content_signing.js
@@ -58,17 +58,17 @@ function check_telemetry(expected_index,
     equal(VERIFICATION_HISTOGRAM.snapshot().values[i] || 0, expected_value,
       "count " + i + ": " + VERIFICATION_HISTOGRAM.snapshot().values[i] +
       " expected " + expected_value);
   }
   VERIFICATION_HISTOGRAM.clear();
   ERROR_HISTOGRAM.clear();
 }
 
-function run_test() {
+add_task(async function run_test() {
   // set up some data
   const DATA = readFile(do_get_file(TEST_DATA_DIR + "test.txt"));
   const GOOD_SIGNATURE = "p384ecdsa=" +
       readFile(do_get_file(TEST_DATA_DIR + "test.txt.signature"))
       .trim();
 
   const BAD_SIGNATURE = "p384ecdsa=WqRXFQ7tnlVufpg7A-ZavXvWd2Zln0o4woHBy26C2r" +
                         "UWM4GJke4pE8ecHiXoi-7KnZXty6Pe3s4o3yAIyKDP9jUC52Ek1G" +
@@ -92,123 +92,123 @@ function run_test() {
   let notValidYetOneCRLChain = loadChain(TEST_DATA_DIR + "content_signing",
                                          ["onecrl_ee_not_valid_yet", "int",
                                           "root"]);
 
   // Check signature verification works without error before the root is set
   VERIFICATION_HISTOGRAM.clear();
   let chain1 = oneCRLChain.join("\n");
   let verifier = getSignatureVerifier();
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain1, ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain1, ONECRL_NAME),
      "Before the root is set, signatures should fail to verify but not throw.");
   // Check for generic chain building error.
   check_telemetry(6, 1, getCertHash("content_signing_onecrl_ee"));
 
   setRoot(TEST_DATA_DIR + "content_signing_root.pem");
 
   // Check good signatures from good certificates with the correct SAN
-  ok(verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain1, ONECRL_NAME),
+  ok(await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain1, ONECRL_NAME),
      "A OneCRL signature should verify with the OneCRL chain");
   let chain2 = remoteNewTabChain.join("\n");
-  ok(verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain2,
-                                     ABOUT_NEWTAB_NAME),
+  ok(await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain2,
+                                                ABOUT_NEWTAB_NAME),
      "A newtab signature should verify with the newtab chain");
   // Check for valid signature
   check_telemetry(0, 2, getCertHash("content_signing_remote_newtab_ee"));
 
   // Check a bad signature when a good chain is provided
   chain1 = oneCRLChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, BAD_SIGNATURE, chain1, ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, BAD_SIGNATURE, chain1, ONECRL_NAME),
      "A bad signature should not verify");
   // Check for invalid signature
   check_telemetry(1, 1, getCertHash("content_signing_onecrl_ee"));
 
   // Check a good signature from cert with good SAN but a different key than the
   // one used to create the signature
   let badKeyChain = oneCRLBadKeyChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, badKeyChain,
-                                      ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, badKeyChain,
+                                                 ONECRL_NAME),
      "A signature should not verify if the signing key is wrong");
   // Check for wrong key in cert.
   check_telemetry(9, 1, getCertHash("content_signing_onecrl_wrong_key_ee"));
 
   // Check a good signature from cert with good SAN but a different key than the
   // one used to create the signature (this time, an RSA key)
   let rsaKeyChain = oneCRLBadKeyChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, rsaKeyChain,
-                                      ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, rsaKeyChain,
+                                                 ONECRL_NAME),
      "A signature should not verify if the signing key is wrong (RSA)");
   // Check for wrong key in cert.
   check_telemetry(9, 1, getCertHash("content_signing_onecrl_wrong_key_ee"));
 
   // Check a good signature from cert with good SAN but with chain missing root
   let missingRoot = [oneCRLChain[0], oneCRLChain[1]].join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, missingRoot,
-                                      ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, missingRoot,
+                                                 ONECRL_NAME),
      "A signature should not verify if the chain is incomplete (missing root)");
   // Check for generic chain building error.
   check_telemetry(6, 1, getCertHash("content_signing_onecrl_ee"));
 
   // Check a good signature from cert with good SAN but with no path to root
   let missingInt = [oneCRLChain[0], oneCRLChain[2]].join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, missingInt,
-                                      ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, missingInt,
+                                                 ONECRL_NAME),
      "A signature should not verify if the chain is incomplete (missing int)");
   // Check for generic chain building error.
   check_telemetry(6, 1, getCertHash("content_signing_onecrl_ee"));
 
   // Check good signatures from good certificates with the wrong SANs
   chain1 = oneCRLChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain1,
-                                      ABOUT_NEWTAB_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain1,
+                                                 ABOUT_NEWTAB_NAME),
      "A OneCRL signature should not verify if we require the newtab SAN");
   // Check for invalid EE cert.
   check_telemetry(7, 1, getCertHash("content_signing_onecrl_ee"));
 
   chain2 = remoteNewTabChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain2,
-                                      ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain2,
+                                                 ONECRL_NAME),
      "A newtab signature should not verify if we require the OneCRL SAN");
   // Check for invalid EE cert.
   check_telemetry(7, 1, getCertHash("content_signing_remote_newtab_ee"));
 
   // Check good signatures with good chains with some other invalid names
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain1, ""),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain1, ""),
      "A signature should not verify if the SANs do not match an empty name");
   // Check for invalid EE cert.
   check_telemetry(7, 1, getCertHash("content_signing_onecrl_ee"));
 
   // Test expired certificate.
   let chainExpired = expiredOneCRLChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chainExpired, ""),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chainExpired, ""),
      "A signature should not verify if the signing certificate is expired");
   // Check for expired cert.
   check_telemetry(4, 1, getCertHash("content_signing_onecrl_ee_expired"));
 
   // Test not valid yet certificate.
   let chainNotValidYet = notValidYetOneCRLChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chainNotValidYet, ""),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chainNotValidYet, ""),
      "A signature should not verify if the signing certificate is not valid yet");
   // Check for not yet valid cert.
   check_telemetry(5, 1, getCertHash("content_signing_onecrl_ee_not_valid_yet"));
 
   let relatedName = "subdomain." + ONECRL_NAME;
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain1,
-                                      relatedName),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain1,
+                                                 relatedName),
      "A signature should not verify if the SANs do not match a related name");
 
   let randomName = "\xb1\x9bU\x1c\xae\xaa3\x19H\xdb\xed\xa1\xa1\xe0\x81\xfb" +
                    "\xb2\x8f\x1cP\xe5\x8b\x9c\xc2s\xd3\x1f\x8e\xbbN";
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain1, randomName),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain1, randomName),
      "A signature should not verify if the SANs do not match a random name");
 
   // check good signatures with chains that have strange or missing SANs
   chain1 = noSANChain.join("\n");
-  ok(!verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, chain1,
-                                      ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, chain1,
+                                                 ONECRL_NAME),
      "A signature should not verify if the SANs do not match a supplied name");
 
   // Check malformed signature data
   chain1 = oneCRLChain.join("\n");
   let bad_signatures = [
     // wrong length
     "p384ecdsa=WqRXFQ7tnlVufpg7A-ZavXvWd2Zln0o4woHBy26C2rUWM4GJke4pE8ecHiXoi-" +
     "7KnZXty6Pe3s4o3yAIyKDP9jUC52Ek1Gq25j_X703nP5rk5gM1qz5Fe-qCWakPPl6L==",
@@ -221,19 +221,18 @@ function run_test() {
     // actually sha256 with RSA
     "p384ecdsa=XS_jiQsS5qlzQyUKaA1nAnQn_OvxhvDfKybflB8Xe5gNH1wNmPGK1qN-jpeTfK" +
     "6ob3l3gCTXrsMnOXMeht0kPP3wLfVgXbuuO135pQnsv0c-ltRMWLe56Cm4S4Z6E7WWKLPWaj" +
     "jhAcG5dZxjffP9g7tuPP4lTUJztyc4d1z_zQZakEG7R0vN7P5_CaX9MiMzP4R7nC3H4Ba6yi" +
     "yjlGvsZwJ_C5zDQzWWs95czUbMzbDScEZ_7AWnidw91jZn-fUK3xLb6m-Zb_b4GAqZ-vnXIf" +
     "LpLB1Nzal42BQZn7i4rhAldYdcVvy7rOMlsTUb5Zz6vpVW9LCT9lMJ7Sq1xbU-0g==",
     ];
   for (let badSig of bad_signatures) {
-    throws(() => {
-      verifier.verifyContentSignature(DATA, badSig, chain1, ONECRL_NAME);
-    }, /NS_ERROR/, `Bad or malformed signature "${badSig}" should be rejected`);
+    await Assert.rejects(verifier.asyncVerifyContentSignature(DATA, badSig, chain1, ONECRL_NAME),
+                         /NS_ERROR/, `Bad or malformed signature "${badSig}" should be rejected`);
   }
 
   // Check malformed and missing certificate chain data
   let chainSuffix = [oneCRLChain[1], oneCRLChain[2]].join("\n");
   let badChains = [
     // no data
     "",
     // completely wrong data
@@ -254,22 +253,25 @@ function run_test() {
   for (let badSection of badSections) {
     // ensure we test each bad section on its own...
     badChains.push(badSection);
     // ... and as part of a chain with good certificates
     badChains.push(badSection + "\n" + chainSuffix);
   }
 
   for (let badChain of badChains) {
-    throws(() => {
-      verifier.verifyContentSignature(DATA, GOOD_SIGNATURE, badChain,
-                                      ONECRL_NAME);
-    }, /NS_ERROR/, `Bad chain data starting "${badChain.substring(0, 80)}" ` +
-                   "should be rejected");
+    await Assert.rejects(verifier.asyncVerifyContentSignature(DATA, GOOD_SIGNATURE, badChain,
+                                                              ONECRL_NAME),
+                         /NS_ERROR/,
+                         `Bad chain data starting "${badChain.substring(0, 80)}" ` +
+                         "should be rejected");
   }
 
-  ok(!verifier.verifyContentSignature(DATA + "appended data", GOOD_SIGNATURE, chain1, ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA + "appended data", GOOD_SIGNATURE, chain1,
+                                                 ONECRL_NAME),
      "A good signature should not verify if the data is tampered with (append)");
-  ok(!verifier.verifyContentSignature("prefixed data" + DATA, GOOD_SIGNATURE, chain1, ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature("prefixed data" + DATA, GOOD_SIGNATURE, chain1,
+                                                 ONECRL_NAME),
      "A good signature should not verify if the data is tampered with (prefix)");
-  ok(!verifier.verifyContentSignature(DATA.replace(/e/g, "i"), GOOD_SIGNATURE, chain1, ONECRL_NAME),
+  ok(!await verifier.asyncVerifyContentSignature(DATA.replace(/e/g, "i"), GOOD_SIGNATURE, chain1,
+                                                 ONECRL_NAME),
      "A good signature should not verify if the data is tampered with (modify)");
-}
+});
--- a/services/common/tests/unit/test_blocklist_signatures.js
+++ b/services/common/tests/unit/test_blocklist_signatures.js
@@ -131,26 +131,24 @@ add_task(async function test_check_signa
   // First, perform a signature verification with known data and signature
   // to ensure things are working correctly
   let verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
                    .createInstance(Ci.nsIContentSignatureVerifier);
 
   const emptyData = "[]";
   const emptySignature = "p384ecdsa=zbugm2FDitsHwk5-IWsas1PpWwY29f0Fg5ZHeqD8fzep7AVl2vfcaHA7LdmCZ28qZLOioGKvco3qT117Q4-HlqFTJM7COHzxGyU2MMJ0ZTnhJrPOC1fP3cVQjU1PTWi9";
   const name = "onecrl.content-signature.mozilla.org";
-  ok(verifier.verifyContentSignature(emptyData, emptySignature,
-                                     getCertChain(), name));
-
-  verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
-               .createInstance(Ci.nsIContentSignatureVerifier);
+  ok(await verifier.asyncVerifyContentSignature(emptyData, emptySignature,
+                                                getCertChain(), name));
 
   const collectionData = '[{"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","created":"2016-01-18T14:43:37Z","name":"GlobalSign certs","who":".","why":"."},"enabled":true,"id":"97fbf7c4-3ef2-f54f-0029-1ba6540c63ea","issuerName":"MHExKDAmBgNVBAMTH0dsb2JhbFNpZ24gUm9vdFNpZ24gUGFydG5lcnMgQ0ExHTAbBgNVBAsTFFJvb3RTaWduIFBhcnRuZXJzIENBMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMQswCQYDVQQGEwJCRQ==","last_modified":2000,"serialNumber":"BAAAAAABA/A35EU="},{"details":{"bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1155145","created":"2016-01-18T14:48:11Z","name":"GlobalSign certs","who":".","why":"."},"enabled":true,"id":"e3bd531e-1ee4-7407-27ce-6fdc9cecbbdc","issuerName":"MIGBMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTElMCMGA1UECxMcUHJpbWFyeSBPYmplY3QgUHVibGlzaGluZyBDQTEwMC4GA1UEAxMnR2xvYmFsU2lnbiBQcmltYXJ5IE9iamVjdCBQdWJsaXNoaW5nIENB","last_modified":3000,"serialNumber":"BAAAAAABI54PryQ="}]';
   const collectionSignature = "p384ecdsa=f4pA2tYM5jQgWY6YUmhUwQiBLj6QO5sHLD_5MqLePz95qv-7cNCuQoZnPQwxoptDtW8hcWH3kLb0quR7SB-r82gkpR9POVofsnWJRA-ETb0BcIz6VvI3pDT49ZLlNg3p";
 
-  ok(verifier.verifyContentSignature(collectionData, collectionSignature, getCertChain(), name));
+  ok(await verifier.asyncVerifyContentSignature(collectionData, collectionSignature,
+                                                getCertChain(), name));
 
   // set up prefs so the kinto updater talks to the test server
   Services.prefs.setCharPref(PREF_SETTINGS_SERVER,
     `http://localhost:${server.identity.primaryPort}/v1`);
 
   // These are records we'll use in the test collections
   const RECORD1 = {
     details: {
--- a/services/settings/RemoteSettingsClient.jsm
+++ b/services/settings/RemoteSettingsClient.jsm
@@ -448,20 +448,20 @@ class RemoteSettingsClient extends Event
       localRecords = data.map(r => kintoCollection.cleanLocalFields(r));
     }
 
     const serialized = await RemoteSettingsWorker.canonicalStringify(localRecords,
                                                                      remoteRecords,
                                                                      timestamp);
     const verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
       .createInstance(Ci.nsIContentSignatureVerifier);
-    if (!verifier.verifyContentSignature(serialized,
-                                         "p384ecdsa=" + signature,
-                                         certChain,
-                                         this.signerName)) {
+    if (!await verifier.asyncVerifyContentSignature(serialized,
+                                                    "p384ecdsa=" + signature,
+                                                    certChain,
+                                                    this.signerName)) {
       throw new RemoteSettingsClient.InvalidSignatureError(`${bucket}/${collection}`);
     }
   }
 
   /**
    * Fetch the whole list of records from the server, verify the signature again
    * and then compute a synchronization result as if the diff-based sync happened.
    * And eventually, wipe out the local data.
deleted file mode 100644
--- a/testing/web-platform/meta/svg/render/reftests/blending-002.svg.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[blending-002.svg]
-  expected:
-    if webrender and (os == "linux"): FAIL
-    if webrender and (os == "win"): FAIL
--- a/testing/web-platform/meta/webrtc/RTCPeerConnection-createDataChannel.html.ini
+++ b/testing/web-platform/meta/webrtc/RTCPeerConnection-createDataChannel.html.ini
@@ -18,23 +18,19 @@
   [createDataChannel with invalid priority should throw TypeError]
     expected: FAIL
     bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531100
 
   [createDataChannel with negotiated false and long label should throw TypeError]
     expected: FAIL
     bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531908
 
-  [createDataChannel with negotiated false and long protocol should throw TypeError]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531910
-
   [createDataChannel with negotiated true and long label and long protocol should succeed]
     expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531908 and https://bugzilla.mozilla.org/show_bug.cgi?id=1531910
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531908
 
   [Channels created after SCTP transport is established should have id assigned]
     expected: FAIL
     bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1526253
 
   [createDataChannel with negotiated false should succeed]
     expected: FAIL
 
@@ -60,17 +56,11 @@
     expected: FAIL
 
   [createDataChannel with negotiated true and id null should throw TypeError]
     expected: FAIL
 
   [createDataChannel with both maxPacketLifeTime and maxRetransmits null should succeed]
     expected: FAIL
 
-  [createDataChannel with too long protocol (2 byte unicode) should throw TypeError]
-    expected: FAIL
-
   [Channels created (after setRemoteDescription) should have id assigned]
     expected: FAIL
 
-  [createDataChannel with too long protocol should throw TypeError]
-    expected: FAIL
-
--- a/toolkit/components/normandy/lib/NormandyApi.jsm
+++ b/toolkit/components/normandy/lib/NormandyApi.jsm
@@ -129,17 +129,17 @@ var NormandyApi = {
 
     const serialized = typeof data == "string" ? data : CanonicalJSON.stringify(data);
 
     const verifier = Cc["@mozilla.org/security/contentsignatureverifier;1"]
       .createInstance(Ci.nsIContentSignatureVerifier);
 
     let valid;
     try {
-      valid = verifier.verifyContentSignature(
+      valid = await verifier.asyncVerifyContentSignature(
         serialized,
         builtSignature,
         certChain,
         "normandy.content-signature.mozilla.org"
       );
     } catch (err) {
       throw new NormandyApi.InvalidSignatureError(`${type} signature validation failed: ${err}`);
     }
--- a/toolkit/modules/AppConstants.jsm
+++ b/toolkit/modules/AppConstants.jsm
@@ -17,16 +17,23 @@ this.AppConstants = Object.freeze({
   // defines: https://wiki.mozilla.org/Platform/Channel-specific_build_defines
   NIGHTLY_BUILD:
 #ifdef NIGHTLY_BUILD
   true,
 #else
   false,
 #endif
 
+  FENNEC_NIGHTLY:
+#ifdef FENNEC_NIGHTLY
+  true,
+#else
+  false,
+#endif
+
   RELEASE_OR_BETA:
 #ifdef RELEASE_OR_BETA
   true,
 #else
   false,
 #endif
 
   EARLY_BETA_OR_EARLIER:
--- a/toolkit/mozapps/update/tests/browser/head.js
+++ b/toolkit/mozapps/update/tests/browser/head.js
@@ -574,16 +574,17 @@ function runDoorhangerUpdateTest(updateP
     })();
   }
 
   return (async function() {
     gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
     await SpecialPowers.pushPrefEnv({
       set: [
         [PREF_APP_UPDATE_DISABLEDFORTESTING, false],
+        [PREF_APP_UPDATE_IDLETIME, 0],
         [PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
         [PREF_APP_UPDATE_URL_DETAILS, gDetailsURL],
       ],
     });
 
     await setupTestUpdater();
 
     let updateURL = URL_HTTP_UPDATE_SJS + "?detailsURL=" + gDetailsURL +
@@ -598,18 +599,18 @@ function runDoorhangerUpdateTest(updateP
           for (var i = 0; i < checkAttempts - 1; i++) {
             await waitForEvent("update-error", "check-attempt-failed");
             gAUS.checkForBackgroundUpdates();
           }
         })();
       });
     } else {
       // Perform a startup processing doorhanger test.
+      writeStatusFile(STATE_FAILED_CRC_ERROR);
       reloadUpdateManagerData();
-      writeStatusFile(STATE_FAILED_CRC_ERROR);
       testPostUpdateProcessing();
     }
 
     for (let step of steps) {
       await processDoorhangerStep(step);
     }
   })();
 }
--- a/tools/tryselect/docs/tasks.rst
+++ b/tools/tryselect/docs/tasks.rst
@@ -53,17 +53,17 @@ skip the wait the next time you run ``ma
 
     Watchman triggers are persistent and don't need to be added more than once.
     See `Managing Triggers`_ for how to remove a trigger.
 
 You can test that everything is working by running these commands:
 
 .. code-block:: shell
 
-    $ statedir=`mach python -c "from mozboot.util import get_state_dir; get_state_dir(srcdir=True)"`
+    $ statedir=`mach python -c "from mozboot.util import get_state_dir; print(get_state_dir(srcdir=True))"`
     $ rm -rf $statedir/cache/taskgraph
     $ touch taskcluster/mach_commands.py
     # wait a minute for generation to trigger and finish
     $ ls $statedir/cache/taskgraph
 
 If the ``target_task_set`` file exists, you are good to go. If not you can look at the ``watchman``
 log to see if there were any errors. This typically lives somewhere like
 ``/usr/local/var/run/watchman/<user>-state/log``. In this case please file a bug under ``Firefox