Merge m-c to fx-team, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 06 Sep 2016 17:37:18 -0700
changeset 312850 73a6a267a50a0e1c41e689b265ad3eebe43d7ac6
parent 312816 ae2144aa4356b65c2f8c0de8c9082dcb7e330e24 (current diff)
parent 312849 91c2b9d5c1354ca79e5b174591dbb03b32b15bbf (diff)
child 312851 16a1a91f9269ab95dd83eb29dc5d0227665f7d94
push id20466
push userkwierso@gmail.com
push dateWed, 07 Sep 2016 00:37:21 +0000
treeherderfx-team@73a6a267a50a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone51.0a1
Merge m-c to fx-team, a=merge
taskcluster/scripts/builder/build-l10n.sh
--- a/browser/config/tooltool-manifests/macosx64/cross-releng.manifest
+++ b/browser/config/tooltool-manifests/macosx64/cross-releng.manifest
@@ -19,19 +19,19 @@
 "size": 35215976, 
 "visibility": "internal", 
 "digest": "8be736545ddab25ebded188458ce974d5c9a7e29f3c50d2ebfbcb878f6aff853dd2ff5a3528bdefc64396a10101a1b50fd2fe52000140df33643cebe1ea759da", 
 "algorithm": "sha512", 
 "unpack": true,
 "filename": "MacOSX10.7.sdk.tar.bz2"
 },
 {
-"version": "cargo 0.13.0-nightly (664125b 2016-07-19)",
-"size": 3123796,
-"digest": "4b9d2bcb8488b6649ba6c748e19d33bfceb25c7566e882fc7e00322392e424a5a9c5878c11c61d57cdaecf67bcc110842c6eff95e49736e8f3c83d9ce1677122",
+"version": "cargo 0.13.0-nightly (e713e7f 2016-08-31)",
+"size": 3245716,
+"digest": "d5bb0d88ce7bb1b5a316d7a8ca6341672f5ee8008fa7754511bf53fabd54c0770e95397232896d6087547891f1143f6968d8b1e106e39800b43defeb0025c7c0",
 "algorithm": "sha512",
 "filename": "cargo.tar.xz",
 "unpack": true
 },
 {
 "size": 167175,
 "digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
 "algorithm": "sha512",
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -50,17 +50,16 @@
 }
 
 /* MAIN IDENTITY ICON */
 
 #identity-icon {
   width: 16px;
   height: 16px;
   list-style-image: url(chrome://browser/skin/identity-icon.svg#normal);
-  opacity: .5;
 }
 
 #identity-box:hover > #identity-icon:not(.no-hover),
 #identity-box[open=true] > #identity-icon {
   list-style-image: url(chrome://browser/skin/identity-icon.svg#hover);
 }
 
 #identity-box.grantedPermissions > #identity-icon {
@@ -69,29 +68,27 @@
 
 #identity-box.grantedPermissions:hover > #identity-icon:not(.no-hover),
 #identity-box.grantedPermissions[open=true] > #identity-icon {
   list-style-image: url(chrome://browser/skin/identity-icon.svg#notice-hover);
 }
 
 #urlbar[pageproxystate="valid"] > #identity-box.chromeUI > #identity-icon {
   list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
-  opacity: 1;
 }
 
 #urlbar[pageproxystate="invalid"] > #identity-box > #identity-icon {
-  opacity: .2;
+  opacity: .3;
 }
 
 #urlbar[actiontype="searchengine"] > #identity-box > #identity-icon {
   -moz-image-region: inherit;
   list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon);
   width: 16px;
   height: 16px;
-  opacity: .5;
 }
 
 /* SHARING ICON */
 
 #sharing-icon {
   width: 16px;
   height: 16px;
   margin-inline-start: -16px;
@@ -135,23 +132,20 @@
 /* TRACKING PROTECTION ICON */
 
 #tracking-protection-icon {
   width: 16px;
   height: 16px;
   margin-inline-start: 2px;
   margin-inline-end: 0;
   list-style-image: url(chrome://browser/skin/tracking-protection-16.svg);
-  opacity: .5;
 }
 
 #tracking-protection-icon[state="loaded-tracking-content"] {
   list-style-image: url(chrome://browser/skin/tracking-protection-disabled-16.svg);
-  filter: none;
-  opacity: 1;
 }
 
 #tracking-protection-icon[animate] {
   transition: margin-left 200ms ease-out, margin-right 200ms ease-out;
 }
 
 #tracking-protection-icon:not([state]) {
   margin-inline-end: -18px;
--- a/browser/themes/shared/identity-block/identity-icon.svg
+++ b/browser/themes/shared/identity-block/identity-icon.svg
@@ -4,16 +4,17 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
      width="64" height="16" viewBox="0 0 64 16">
   <defs>
     <style>
       path {
         fill-rule: evenodd;
         fill: -moz-fieldtext;
+        fill-opacity: .5;
       }
     </style>
   </defs>
 
   <view id="normal" viewBox="0 0 16 16"/>
   <g>
     <path d="M128,193a7,7,0,1,1,7-7A7,7,0,0,1,128,193Zm0-13a6,6,0,1,0,6,6A6,6,0,0,0,128,180Zm0,10a1,1,0,0,1-1-1v-3a1,1,0,0,1,2,0v3A1,1,0,0,1,128,190Zm0-6a1,1,0,1,1,1-1A1,1,0,0,1,128,184Z" transform="translate(-120 -178)"/>
   </g>
--- a/browser/themes/shared/identity-block/tracking-protection-16.svg
+++ b/browser/themes/shared/identity-block/tracking-protection-16.svg
@@ -12,10 +12,10 @@
     <mask id="mask-shield-cutout">
       <rect width="16" height="16" fill="#000" />
       <use xlink:href="#shape-shield-outer" fill="#fff" />
       <use xlink:href="#shape-shield-inner" fill="#000" />
       <use xlink:href="#shape-shield-detail" fill="#fff" />
     </mask>
   </defs>
 
-  <use xlink:href="#shape-shield-outer" mask="url(#mask-shield-cutout)" fill="-moz-fieldtext"/>
+  <use xlink:href="#shape-shield-outer" mask="url(#mask-shield-cutout)" fill="-moz-fieldtext" fill-opacity=".5"/>
 </svg>
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -62,17 +62,17 @@
 .popup-notification-icon[popupid="webRTC-shareMicrophone"],
 .popup-notification-icon[popupid="webRTC-shareScreen"],
 .popup-notification-icon[popupid="web-notifications"] {
   filter: url(chrome://browser/skin/filters.svg#fill);
   fill: currentColor;
   opacity: .4;
 }
 
-.notification-anchor-icon:hover {
+.notification-anchor-icon:not(.plugin-blocked):hover {
   opacity: .6;
 }
 
 /* INDIVIDUAL NOTIFICATIONS */
 
 .popup-notification-icon[popupid="web-notifications"],
 .desktop-notification-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#desktop-notification);
@@ -242,17 +242,17 @@
 
 .plugin-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin);
 }
 
 .plugin-icon.plugin-blocked {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin-blocked);
   fill: #d92215;
-  opacity: 1 !important; /* !important to override the default hover opacity */
+  opacity: 1;
 }
 
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
--- a/devtools/client/shared/key-shortcuts.js
+++ b/devtools/client/shared/key-shortcuts.js
@@ -187,22 +187,27 @@ KeyShortcuts.prototype = {
       return false;
     }
     if (shortcut.ctrl != event.ctrlKey) {
       return false;
     }
     if (shortcut.alt != event.altKey) {
       return false;
     }
-    // Shift is a special modifier, it may implicitely be required if the
-    // expected key is a special character accessible via shift.
-    if (shortcut.shift != event.shiftKey && event.key &&
-        event.key.match(/[a-zA-Z]/)) {
-      return false;
+    if (shortcut.shift != event.shiftKey) {
+      // Shift is a special modifier, it may implicitely be required if the expected key
+      // is a special character accessible via shift.
+      let isAlphabetical = event.key && event.key.match(/[a-zA-Z]/);
+      // OSX: distinguish cmd+[key] from cmd+shift+[key] shortcuts (Bug 1300458)
+      let cmdShortcut = shortcut.meta && !shortcut.alt && !shortcut.ctrl;
+      if (isAlphabetical || cmdShortcut) {
+        return false;
+      }
     }
+
     if (shortcut.keyCode) {
       return event.keyCode == shortcut.keyCode;
     } else if (event.key in ElectronKeysMapping) {
       return ElectronKeysMapping[event.key] === shortcut.key;
     }
 
     // get the key from the keyCode if key is not provided.
     let key = event.key || String.fromCharCode(event.keyCode);
--- a/devtools/client/shared/test/browser_key_shortcuts.js
+++ b/devtools/client/shared/test/browser_key_shortcuts.js
@@ -1,30 +1,34 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 var isOSX = Services.appinfo.OS === "Darwin";
 
 add_task(function* () {
   let shortcuts = new KeyShortcuts({
     window
   });
+
   yield testSimple(shortcuts);
   yield testNonLetterCharacter(shortcuts);
   yield testPlusCharacter(shortcuts);
   yield testFunctionKey(shortcuts);
   yield testMixup(shortcuts);
   yield testLooseDigits(shortcuts);
   yield testExactModifiers(shortcuts);
   yield testLooseShiftModifier(shortcuts);
   yield testStrictLetterShiftModifier(shortcuts);
   yield testAltModifier(shortcuts);
   yield testCommandOrControlModifier(shortcuts);
   yield testCtrlModifier(shortcuts);
   yield testInvalidShortcutString(shortcuts);
+  yield testCmdShiftShortcut(shortcuts);
   shortcuts.destroy();
 
   yield testTarget();
 });
 
 // Test helper to listen to the next key press for a given key,
 // returning a promise to help using Tasks.
 function once(shortcuts, key, listener) {
@@ -37,68 +41,68 @@ function once(shortcuts, key, listener) 
       called = true;
       listener(key2, event);
       done();
     };
     shortcuts.on(key, onShortcut);
   });
 }
 
-function testSimple(shortcuts) {
+function* testSimple(shortcuts) {
   info("Test simple key shortcuts");
 
   let onKey = once(shortcuts, "0", (key, event) => {
     is(event.key, "0");
 
     // Display another key press to ensure that once() correctly stop listening
     EventUtils.synthesizeKey("0", {}, window);
   });
 
   EventUtils.synthesizeKey("0", {}, window);
   yield onKey;
 }
 
-function testNonLetterCharacter(shortcuts) {
+function* testNonLetterCharacter(shortcuts) {
   info("Test non-naive character key shortcuts");
 
   let onKey = once(shortcuts, "[", (key, event) => {
     is(event.key, "[");
   });
 
   EventUtils.synthesizeKey("[", {}, window);
   yield onKey;
 }
 
-function testFunctionKey(shortcuts) {
+function* testFunctionKey(shortcuts) {
   info("Test function key shortcuts");
 
   let onKey = once(shortcuts, "F12", (key, event) => {
     is(event.key, "F12");
   });
 
   EventUtils.synthesizeKey("F12", { keyCode: 123 }, window);
   yield onKey;
 }
 
 // Plus is special. It's keycode is the one for "=". That's because it requires
 // shift to be pressed and is behind "=" key. So it should be considered as a
 // character key
-function testPlusCharacter(shortcuts) {
+function* testPlusCharacter(shortcuts) {
   info("Test 'Plus' key shortcuts");
 
   let onKey = once(shortcuts, "Plus", (key, event) => {
     is(event.key, "+");
   });
 
   EventUtils.synthesizeKey("+", { keyCode: 61, shiftKey: true }, window);
   yield onKey;
 }
 
 // Test they listeners are not mixed up between shortcuts
-function testMixup(shortcuts) {
+function* testMixup(shortcuts) {
   info("Test possible listener mixup");
 
   let hitFirst = false, hitSecond = false;
   let onFirstKey = once(shortcuts, "0", (key, event) => {
     is(event.key, "0");
     hitFirst = true;
   });
   let onSecondKey = once(shortcuts, "Alt+A", (key, event) => {
@@ -123,17 +127,17 @@ function testMixup(shortcuts) {
   // Finally dispatch the second shortcut
   EventUtils.synthesizeKey("a", { altKey: true }, window);
   yield onSecondKey;
   ok(hitSecond, "Got the second shortcut notified once it is actually fired");
 }
 
 // On azerty keyboard, digits are only available by pressing Shift/Capslock,
 // but we accept them even if we omit doing that.
-function testLooseDigits(shortcuts) {
+function* testLooseDigits(shortcuts) {
   info("Test Loose digits");
   let onKey = once(shortcuts, "0", (key, event) => {
     is(event.key, "à");
     ok(!event.altKey);
     ok(!event.ctrlKey);
     ok(!event.metaKey);
     ok(!event.shiftKey);
   });
@@ -156,17 +160,17 @@ function testLooseDigits(shortcuts) {
   EventUtils.synthesizeKey(
     "0",
     { keyCode: 48, shiftKey: true },
     window);
   yield onKey;
 }
 
 // Test that shortcuts is notified only when the modifiers match exactly
-function testExactModifiers(shortcuts) {
+function* testExactModifiers(shortcuts) {
   info("Test exact modifiers match");
 
   let hit = false;
   let onKey = once(shortcuts, "Alt+A", (key, event) => {
     is(event.key, "a");
     ok(event.altKey);
     ok(!event.ctrlKey);
     ok(!event.metaKey);
@@ -204,17 +208,17 @@ function testExactModifiers(shortcuts) {
   yield onKey;
   ok(hit, "Got shortcut notified once it is actually fired");
 }
 
 // Some keys are only accessible via shift and listener should also be called
 // even if the key didn't explicitely requested Shift modifier.
 // For example, `%` on french keyboards is only accessible via Shift.
 // Same thing for `@` on US keybords.
-function testLooseShiftModifier(shortcuts) {
+function* testLooseShiftModifier(shortcuts) {
   info("Test Loose shift modifier");
   let onKey = once(shortcuts, "%", (key, event) => {
     is(event.key, "%");
     ok(!event.altKey);
     ok(!event.ctrlKey);
     ok(!event.metaKey);
     ok(event.shiftKey);
   });
@@ -234,17 +238,17 @@ function testLooseShiftModifier(shortcut
   EventUtils.synthesizeKey(
     "@",
     { accelKey: false, altKey: false, ctrlKey: false, shiftKey: true},
     window);
   yield onKey;
 }
 
 // But Shift modifier is strict on all letter characters (a to Z)
-function testStrictLetterShiftModifier(shortcuts) {
+function* testStrictLetterShiftModifier(shortcuts) {
   info("Test strict shift modifier on letters");
   let hitFirst = false;
   let onKey = once(shortcuts, "a", (key, event) => {
     is(event.key, "a");
     ok(!event.altKey);
     ok(!event.ctrlKey);
     ok(!event.metaKey);
     ok(!event.shiftKey);
@@ -266,33 +270,33 @@ function testStrictLetterShiftModifier(s
 
   EventUtils.synthesizeKey(
     "a",
     { shiftKey: false},
     window);
   yield onKey;
 }
 
-function testAltModifier(shortcuts) {
+function* testAltModifier(shortcuts) {
   info("Test Alt modifier");
   let onKey = once(shortcuts, "Alt+F1", (key, event) => {
     is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
     ok(event.altKey);
     ok(!event.ctrlKey);
     ok(!event.metaKey);
     ok(!event.shiftKey);
   });
   EventUtils.synthesizeKey(
     "VK_F1",
     { altKey: true },
     window);
   yield onKey;
 }
 
-function testCommandOrControlModifier(shortcuts) {
+function* testCommandOrControlModifier(shortcuts) {
   info("Test CommandOrControl modifier");
   let onKey = once(shortcuts, "CommandOrControl+F1", (key, event) => {
     is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
     ok(!event.altKey);
     if (isOSX) {
       ok(!event.ctrlKey);
       ok(event.metaKey);
     } else {
@@ -323,17 +327,17 @@ function testCommandOrControlModifier(sh
       "VK_F1",
       { ctrlKey: true },
       window);
   }
   yield onKey;
   yield onKeyAlias;
 }
 
-function testCtrlModifier(shortcuts) {
+function* testCtrlModifier(shortcuts) {
   info("Test Ctrl modifier");
   let onKey = once(shortcuts, "Ctrl+F1", (key, event) => {
     is(event.keyCode, window.KeyboardEvent.DOM_VK_F1);
     ok(!event.altKey);
     ok(event.ctrlKey);
     ok(!event.metaKey);
     ok(!event.shiftKey);
   });
@@ -347,17 +351,51 @@ function testCtrlModifier(shortcuts) {
   EventUtils.synthesizeKey(
     "VK_F1",
     { ctrlKey: true },
     window);
   yield onKey;
   yield onKeyAlias;
 }
 
-function testTarget() {
+function* testCmdShiftShortcut(shortcuts) {
+  if (!isOSX) {
+    // This test is OSX only (Bug 1300458).
+    return;
+  }
+
+  let onCmdKey = once(shortcuts, "CmdOrCtrl+[", (key, event) => {
+    is(event.key, "[");
+    ok(!event.altKey);
+    ok(!event.ctrlKey);
+    ok(event.metaKey);
+    ok(!event.shiftKey);
+  });
+  let onCmdShiftKey = once(shortcuts, "CmdOrCtrl+Shift+[", (key, event) => {
+    is(event.key, "[");
+    ok(!event.altKey);
+    ok(!event.ctrlKey);
+    ok(event.metaKey);
+    ok(event.shiftKey);
+  });
+
+  EventUtils.synthesizeKey(
+    "[",
+    { metaKey: true, shiftKey: true },
+    window);
+  EventUtils.synthesizeKey(
+    "[",
+    { metaKey: true },
+    window);
+
+  yield onCmdKey;
+  yield onCmdShiftKey;
+}
+
+function* testTarget() {
   info("Test KeyShortcuts with target argument");
 
   let target = document.createElementNS("http://www.w3.org/1999/xhtml",
     "input");
   document.documentElement.appendChild(target);
   target.focus();
 
   let shortcuts = new KeyShortcuts({
--- a/dom/base/CustomElementsRegistry.h
+++ b/dom/base/CustomElementsRegistry.h
@@ -117,20 +117,16 @@ struct CustomElementDefinition
   JS::Heap<JSObject *> mConstructor;
 
   // The prototype to use for new custom elements of this type.
   JS::Heap<JSObject *> mPrototype;
 
   // The lifecycle callbacks to call for this custom element.
   nsAutoPtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
 
-  // Whether we're currently calling the created callback for a custom element
-  // of this type.
-  bool mElementIsBeingCreated;
-
   // A construction stack.
   // TODO: Bug 1287348 - Implement construction stack for upgrading an element
 
   // The document custom element order.
   uint32_t mDocOrder;
 };
 
 class CustomElementsRegistry final : public nsISupports,
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1743,18 +1743,18 @@ CanvasRenderingContext2D::TrySkiaGLTarge
   if (!glue || !glue->GetGrContext() || !glue->GetGLContext()) {
     return false;
   }
 
   SurfaceFormat format = GetSurfaceFormat();
   aOutDT = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(),
                                                       size, format);
   if (!aOutDT) {
+    gfxCriticalNote << "Failed to create a SkiaGL DrawTarget, falling back to software\n";
     return false;
-    gfxCriticalNote << "Failed to create a SkiaGL DrawTarget, falling back to software\n";
   }
 
   MOZ_ASSERT(aOutDT->GetType() == DrawTargetType::HARDWARE_RASTER);
 
   AddDemotableContext(this);
   aOutProvider = new PersistentBufferProviderBasic(aOutDT);
   mIsSkiaGL = true;
   // Drop a note in the debug builds if we ever use accelerated Skia canvas.
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -1017,17 +1017,17 @@ SVGSVGElement::GetLengthInfo()
 
 nsSVGElement::EnumAttributesInfo
 SVGSVGElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             ArrayLength(sEnumInfo));
 }
 
-nsSVGViewBox *
+nsSVGViewBox*
 SVGSVGElement::GetViewBox()
 {
   return &mViewBox;
 }
 
 SVGAnimatedPreserveAspectRatio *
 SVGSVGElement::GetPreserveAspectRatio()
 {
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -283,16 +283,17 @@ public:
   already_AddRefed<SVGIRect> CreateSVGRect();
   already_AddRefed<SVGTransform> CreateSVGTransform();
   already_AddRefed<SVGTransform> CreateSVGTransformFromMatrix(SVGMatrix& matrix);
   using nsINode::GetElementById; // This does what we want
   already_AddRefed<SVGAnimatedRect> ViewBox();
   already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
   uint16_t ZoomAndPan();
   void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv);
+  virtual nsSVGViewBox* GetViewBox() override;
 
 private:
   // nsSVGElement overrides
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
@@ -373,17 +374,16 @@ private:
 
   virtual EnumAttributesInfo GetEnumInfo() override;
 
   enum { ZOOMANDPAN };
   nsSVGEnum mEnumAttributes[1];
   static nsSVGEnumMapping sZoomAndPanMap[];
   static EnumInfo sEnumInfo[1];
 
-  virtual nsSVGViewBox *GetViewBox() override;
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() override;
 
   nsSVGViewBox                   mViewBox;
   SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
 
   // mCurrentViewID and mSVGView are mutually exclusive; we can have
   // at most one non-null.
   nsAutoPtr<nsString>            mCurrentViewID;
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -577,18 +577,17 @@ class FunctionBox : public ObjectBox, pu
     // certain parsing features that are necessary in general, but unnecessary
     // for validated asm.js.
     bool useAsmOrInsideUseAsm() const {
         return useAsm || insideUseAsm;
     }
 
     void setStart(const TokenStream& tokenStream) {
         bufStart = tokenStream.currentToken().pos.begin;
-        startLine = tokenStream.getLineno();
-        startColumn = tokenStream.getColumn();
+        tokenStream.srcCoords.lineNumAndColumnIndex(bufStart, &startLine, &startColumn);
     }
 
     void trace(JSTracer* trc) override;
 };
 
 inline FunctionBox*
 SharedContext::asFunctionBox()
 {
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -328,18 +328,16 @@ class MOZ_STACK_CLASS TokenStream
 
     // Accessors.
     const Token& currentToken() const { return tokens[cursor]; }
     bool isCurrentTokenType(TokenKind type) const {
         return currentToken().type == type;
     }
     const CharBuffer& getTokenbuf() const { return tokenbuf; }
     const char* getFilename() const { return filename; }
-    unsigned getLineno() const { return lineno; }
-    unsigned getColumn() const { return userbuf.offset() - linebase - 1; }
     bool getMutedErrors() const { return mutedErrors; }
     JSVersion versionNumber() const { return VersionNumber(options().version); }
     JSVersion versionWithFlags() const { return options().version; }
 
     PropertyName* currentName() const {
         if (isCurrentTokenType(TOK_YIELD))
             return cx->names().yield;
         MOZ_ASSERT(isCurrentTokenType(TOK_NAME));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/arrow-functions/column-number.js
@@ -0,0 +1,6 @@
+function f() { return g(abcd => Error()); }
+function g(x) { return x(); }
+var err = f(1, 2);
+var lines = err.stack.split("\n");
+assertEq(lines[0].endsWith(":1:33"), true);
+assertEq(lines[1].endsWith(":2:24"), true);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-borderBox-1a.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path border-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path border-box works correctly or not. This test is for clip-path applied to an HTML element.">
+    <style type="text/css">
+      div {
+        position: absolute;
+        left: 50px;
+        top: 50px;
+        background-color: blue;
+        width: 30px;
+        height: 30px;
+        padding: 10px;
+        border: solid blue 25px;
+        clip-path: circle(farthest-side) border-box;
+      }
+    </style>
+  </head>
+  <body>
+    <div></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-borderBox-1b.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path border-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path border-box works correctly or not. This test is for clip-path applied to an SVG element.">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 15px; top: 10px;">
+      <rect x="35" y="40" width="100" height="100" fill="blue"
+            clip-path="circle(50%) border-box"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-borderBox-1c.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path border-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path border-box works correctly or not. This test is for clip-path applied to an SVG  SVG element.">
+    <style type="text/css">
+      svg {
+        position: absolute;
+        left: 50px;
+        top: 50px;
+        background-color: blue;
+        width: 30px;
+        height: 30px;
+        padding: 10px;
+        border: solid blue 25px;
+        clip-path: circle(farthest-side) border-box;
+      }
+    </style>
+  </head>
+  <body>
+    <svg width="200" height="200">
+      <rect x="0" y="0" width="200" height="200" fill="blue"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-contentBox-1a.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path content-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path content-box works correctly or not. This test is for clip-path applied to an HTML element.">
+    <style type="text/css">
+      div {
+        background-color: blue;
+        position: absolute;
+        left: 10px;
+        top: 10px;
+        width: 100px;
+        height: 100px;
+        padding: 40px;
+        clip-path: circle(farthest-side) content-box;
+      }
+    </style>
+  </head>
+  <body>
+    <div></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-contentBox-1b.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path content-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path content-box works correctly or not. This test is for clip-path applied to an SVG element.">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 0px; top: 0px;">
+      <rect x="50" y="50" width="100" height="100" fill="blue"
+            clip-path="circle(50%) content-box"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-contentBox-1c.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path content-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path content-box works correctly or not.">
+  </head>
+  <style type="text/css">
+    svg {
+      position: absolute;
+      left: 10px;
+      top: 10px;
+      width: 100px;
+      height: 100px;
+      padding: 40px;
+      clip-path: circle(farthest-side) content-box;
+    }
+  </style>
+  <body>
+    <svg width="200" height="200">
+      <rect x="0" y="0" width="200" height="200" fill="blue"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-fillBox-1a.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path fill-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path fill-box works correctly or not. This test is for clip-path applied to an SVG  SVG element.">
+    <style type="text/css">
+      svg {
+        position: absolute;
+        left: 40px;
+        top: 40px;
+        background-color: blue;
+        width: 30px;
+        height: 30px;
+        margin: 10px;
+        padding: 10px;
+        border: solid blue 25px;
+        clip-path: circle(farthest-side) fill-box;
+      }
+    </style>
+  </head>
+  <body>
+    <svg width="200" height="200">
+      <rect x="0" y="0" width="200" height="200" fill="blue">
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-geometryBox-1-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path geometry box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 0px; top: 0px;">
+      <circle cx="100" cy="100" r="50" fill="blue"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-geometryBox-2-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path geometry box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 0px; top: 0px;">
+      <polygon points="100,50 150,100 150,150 50,150 50,100" fill="blue"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-geometryBox-2.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path margin-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-2-ref.html">
+    <meta name="assert" content="Test checks whether clip-path margin-box works correctly or not.">
+    <style type="text/css">
+      div {
+        position: absolute;
+        left: 0px;
+        top: 0px;
+        background-color: blue;
+        width: 100px;
+        height: 100px;
+        margin: 50px;
+        clip-path: polygon(0% 75%, 50% 25%, 100% 75%) margin-box;
+      }
+    </style>
+  </head>
+  <body>
+    <div></div>
+  </body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-marginBox-1a.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path margin-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path margin-box works correctly or not. This test is for clip-path applied to an SVG element.">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 10px; top: 15px;">
+      <rect x="40" y="35" width="100" height="100" fill="blue"
+            clip-path="circle(50%) margin-box"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-paddingBox-1a.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path padding-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path padding-box works correctly or not. This test is for clip-path applied to an HTML element.">
+    <style type="text/css">
+      div {
+        position: absolute;
+        left: 50px;
+        top: 50px;
+        background-color: blue;
+        width: 50px;
+        height: 50px;
+        padding: 25px;
+        clip-path: circle(farthest-side) padding-box;
+      }
+    </style>
+  </head>
+  <body>
+    <div></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-paddingBox-1b.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path padding-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path padding-box works correctly or not. This test is for clip-path applied to an SVG element.">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 0px; top: 0px;">
+      <rect x="50" y="50" width="100" height="100" fill="blue"
+            clip-path="circle(50%) padding-box"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-paddingBox-1c.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path padding-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path padding-box works correctly or not. This test is for clip-path applied to an SVG  SVG element.">
+    <style type="text/css">
+      svg {
+        position: absolute;
+        left: 50px;
+        top: 50px;
+        background-color: blue;
+        width: 50px;
+        height: 50px;
+        padding: 25px;
+        clip-path: circle(farthest-side) padding-box;
+      }
+    </style>
+  </head>
+  <body>
+    <svg width="200" height="200">
+      <rect x="0" y="0" width="200" height="200" fill="blue"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-strokeBox-1a.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path stroke-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path stroke-box works correctly or not. This test is for clip-path applied to an SVG  SVG element.">
+    <style type="text/css">
+      svg {
+        position: absolute;
+        left: 40px;
+        top: 40px;
+        background-color: blue;
+        width: 30px;
+        height: 30px;
+        margin: 10px;
+        padding: 10px;
+        border: solid blue 25px;
+        clip-path: circle(farthest-side) stroke-box;
+      }
+    </style>
+  </head>
+  <body>
+    <svg width="200" height="200">
+      <rect x="0" y="0" width="200" height="200" fill="blue"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-strokeBox-1b.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path stroke-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path stroke-box works correctly or not.">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 0px; top: 0px;">
+      <rect x="60" y="60" width="80" height="80" fill="blue" stroke="blue" stroke-width="20" clip-path="circle(50%) stroke-box"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-viewBox-1a.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path view-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path view-box works correctly or not.">
+  </head>
+  <body>
+    <svg width="200" height="200" style="position: absolute; left: 10px; top: 10px;">
+      <rect x="20" y="20" width="135" height="135" fill="blue"
+            clip-path="circle(25% at calc(50% - 10px) calc(50% - 10px)) view-box"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-viewBox-1b.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path view-box with viewbox</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path view-box with viewbox works correctly or not.">
+  </head>
+  <body>
+    <svg width="200" height="200" viewBox="50 50 100 100" preserveAspectRatio="none" style="position: absolute; left: 10px; top: 10px;">
+      <rect x="0" y="0" width="200" height="200" fill="blue"
+            clip-path="circle(25% at calc(50% - 5px) calc(50% - 5px)) view-box"/>
+    </svg>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/masking/clip-path-viewBox-1c.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CSS Masking: clip-path: clip path view-box</title>
+    <link rel="author" title="CJ Ku" href="mailto:cku@mozilla.com">
+    <link rel="author" title="Mozilla" href="https://www.mozilla.org">
+    <link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path">
+    <link rel="match" href="clip-path-geometryBox-1-ref.html">
+    <meta name="assert" content="Test checks whether clip-path view-box works correctly or not. This test is for clip-path applied to an SVG  SVG element.">
+    <style type="text/css">
+      svg {
+        position: absolute;
+        left: 40px;
+        top: 40px;
+        background-color: blue;
+        width: 30px;
+        height: 30px;
+        margin: 10px;
+        padding: 10px;
+        border: solid blue 25px;
+        clip-path: circle(farthest-side) view-box;
+      }
+    </style>
+  </head>
+  <body>
+    <svg width="200" height="200">
+      <rect x="0" y="0" width="200" height="200" fill="blue"/>
+    </svg>
+  </body>
+</html>
--- a/layout/reftests/w3c-css/submitted/masking/reftest.list
+++ b/layout/reftests/w3c-css/submitted/masking/reftest.list
@@ -72,8 +72,30 @@ fails == mask-origin-2.html mask-origin-
 == mask-size-length-auto.html mask-size-length-length-ref.html
 == mask-size-length-length.html mask-size-length-length-ref.html
 == mask-size-length-percent.html mask-size-length-percent-ref.html
 == mask-size-percent.html mask-size-percent-percent-ref.html
 == mask-size-percent-auto.html mask-size-percent-percent-ref.html
 == mask-size-percent-length.html mask-size-percent-percent-ref.html
 == mask-size-percent-percent.html mask-size-percent-percent-ref.html
 == mask-size-percent-percent-stretch.html mask-size-percent-percent-stretch-ref.html
+
+default-preferences pref(layout.css.clip-path-shapes.enabled,true)
+
+fuzzy-if(winWidget,1,21) == clip-path-contentBox-1a.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-contentBox-1b.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-contentBox-1c.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-paddingBox-1a.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-paddingBox-1b.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-paddingBox-1c.html clip-path-geometryBox-1-ref.html
+fuzzy(64,311) == clip-path-borderBox-1a.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-borderBox-1b.html clip-path-geometryBox-1-ref.html
+fuzzy(64,311) == clip-path-borderBox-1c.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-marginBox-1a.html clip-path-geometryBox-1-ref.html
+fuzzy(64,311) == clip-path-fillBox-1a.html clip-path-geometryBox-1-ref.html
+fuzzy(64,311) == clip-path-strokeBox-1a.html clip-path-geometryBox-1-ref.html
+fuzzy(64,311) == clip-path-strokeBox-1b.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-viewBox-1a.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,21) == clip-path-viewBox-1b.html clip-path-geometryBox-1-ref.html
+fuzzy(64,311) == clip-path-viewBox-1c.html clip-path-geometryBox-1-ref.html
+fuzzy-if(winWidget,1,98) == clip-path-geometryBox-2.html clip-path-geometryBox-2-ref.html
+
+default-preferences
--- a/layout/svg/nsCSSClipPathInstance.cpp
+++ b/layout/svg/nsCSSClipPathInstance.cpp
@@ -57,35 +57,133 @@ nsCSSClipPathInstance::HitTestBasicShape
   RefPtr<DrawTarget> drawTarget =
     gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
   RefPtr<Path> path = instance.CreateClipPath(drawTarget);
   float pixelRatio = float(nsPresContext::AppUnitsPerCSSPixel()) /
                      aFrame->PresContext()->AppUnitsPerDevPixel();
   return path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix());
 }
 
-already_AddRefed<Path>
-nsCSSClipPathInstance::CreateClipPath(DrawTarget* aDrawTarget)
+nsRect
+nsCSSClipPathInstance::ComputeSVGReferenceRect()
+{
+  MOZ_ASSERT(mTargetFrame->GetContent()->IsSVGElement());
+  nsRect r;
+
+  // For SVG elements without associated CSS layout box, the used value for
+  // content-box, padding-box, border-box and margin-box is fill-box.
+  switch (mClipPathStyle.GetReferenceBox()) {
+    case StyleClipPathGeometryBox::Stroke: {
+      // XXX Bug 1299876
+      // The size of srtoke-box is not correct if this graphic element has
+      // specific stroke-linejoin or stroke-linecap.
+      gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
+                nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeStroke);
+      r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
+                                         nsPresContext::AppUnitsPerCSSPixel());
+      break;
+    }
+    case StyleClipPathGeometryBox::View: {
+      nsIContent* content = mTargetFrame->GetContent();
+      nsSVGElement* element = static_cast<nsSVGElement*>(content);
+      SVGSVGElement* svgElement = element->GetCtx();
+      MOZ_ASSERT(svgElement);
+
+      if (svgElement && svgElement->HasViewBoxRect()) {
+        // If a ‘viewBox‘ attribute is specified for the SVG viewport creating
+        // element:
+        // 1. The reference box is positioned at the origin of the coordinate
+        //    system established by the ‘viewBox‘ attribute.
+        // 2. The dimension of the reference box is set to the width and height
+        //    values of the ‘viewBox‘ attribute.
+        nsSVGViewBox* viewBox = svgElement->GetViewBox();
+        const nsSVGViewBoxRect& value = viewBox->GetAnimValue();
+        r = nsRect(nsPresContext::CSSPixelsToAppUnits(value.x),
+                   nsPresContext::CSSPixelsToAppUnits(value.y),
+                   nsPresContext::CSSPixelsToAppUnits(value.width),
+                   nsPresContext::CSSPixelsToAppUnits(value.height));
+      } else {
+        // No viewBox is specified, uses the nearest SVG viewport as reference
+        // box.
+        svgFloatSize viewportSize = svgElement->GetViewportSize();
+        r = nsRect(0, 0,
+                   nsPresContext::CSSPixelsToAppUnits(viewportSize.width),
+                   nsPresContext::CSSPixelsToAppUnits(viewportSize.height));
+      }
+
+      break;
+    }
+    case StyleClipPathGeometryBox::NoBox:
+    case StyleClipPathGeometryBox::Border:
+    case StyleClipPathGeometryBox::Content:
+    case StyleClipPathGeometryBox::Padding:
+    case StyleClipPathGeometryBox::Margin:
+    case StyleClipPathGeometryBox::Fill: {
+      gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
+                                         nsSVGUtils::eBBoxIncludeFill);
+      r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
+                                         nsPresContext::AppUnitsPerCSSPixel());
+      break;
+    }
+    default:{
+      MOZ_ASSERT_UNREACHABLE("unknown StyleClipPathGeometryBox type");
+      gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
+                                         nsSVGUtils::eBBoxIncludeFill);
+      r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
+                                         nsPresContext::AppUnitsPerCSSPixel());
+      break;
+    }
+  }
+
+  return r;
+}
+
+nsRect
+nsCSSClipPathInstance::ComputeHTMLReferenceRect()
 {
   nsRect r;
-  // XXXkrit SVG needs to use different boxes.
+
+  // For elements with associated CSS layout box, the used value for fill-box,
+  // stroke-box and view-box is border-box.
   switch (mClipPathStyle.GetReferenceBox()) {
     case StyleClipPathGeometryBox::Content:
       r = mTargetFrame->GetContentRectRelativeToSelf();
       break;
     case StyleClipPathGeometryBox::Padding:
       r = mTargetFrame->GetPaddingRectRelativeToSelf();
       break;
     case StyleClipPathGeometryBox::Margin:
       r = mTargetFrame->GetMarginRectRelativeToSelf();
       break;
-    default: // Use the border box
+    case StyleClipPathGeometryBox::NoBox:
+    case StyleClipPathGeometryBox::Border:
+    case StyleClipPathGeometryBox::Fill:
+    case StyleClipPathGeometryBox::Stroke:
+    case StyleClipPathGeometryBox::View:
+      r = mTargetFrame->GetRectRelativeToSelf();
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("unknown StyleClipPathGeometryBox type");
       r = mTargetFrame->GetRectRelativeToSelf();
+      break;
   }
 
+  return r;
+}
+
+already_AddRefed<Path>
+nsCSSClipPathInstance::CreateClipPath(DrawTarget* aDrawTarget)
+{
+  // We use ComputeSVGReferenceRect for all SVG elements, except <svg>
+  // element, which does have an associated CSS layout box. In this case we
+  // should still use ComputeHTMLReferenceRect for region computing.
+  nsRect r = mTargetFrame->IsFrameOfType(nsIFrame::eSVG) &&
+             (mTargetFrame->GetType() != nsGkAtoms::svgOuterSVGFrame)
+             ? ComputeSVGReferenceRect() : ComputeHTMLReferenceRect();
+
   if (mClipPathStyle.GetType() != StyleShapeSourceType::Shape) {
     // TODO Clip to border-radius/reference box if no shape
     // was specified.
     RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
     return builder->Finish();
   }
 
   nscoord appUnitsPerDevPixel =
--- a/layout/svg/nsCSSClipPathInstance.h
+++ b/layout/svg/nsCSSClipPathInstance.h
@@ -42,16 +42,21 @@ private:
   already_AddRefed<Path> CreateClipPathEllipse(DrawTarget* aDrawTarget,
                                                const nsRect& aRefBox);
 
   already_AddRefed<Path> CreateClipPathPolygon(DrawTarget* aDrawTarget,
                                                const nsRect& aRefBox);
 
   already_AddRefed<Path> CreateClipPathInset(DrawTarget* aDrawTarget,
                                              const nsRect& aRefBox);
+
+
+  nsRect ComputeHTMLReferenceRect();
+  nsRect ComputeSVGReferenceRect();
+
   /**
    * The frame for the element that is currently being clipped.
    */
   nsIFrame* mTargetFrame;
   StyleClipPath mClipPathStyle;
 };
 
 } // namespace mozilla
--- a/taskcluster/ci/legacy/tasks/branches/base_job_flags.yml
+++ b/taskcluster/ci/legacy/tasks/branches/base_job_flags.yml
@@ -9,16 +9,17 @@ flags:
     - linux64-haz    # Firefox desktop browser, rooting hazard analysis
     - linux64-shell-haz  # JS shell, rooting hazard analysis
     - linux64-mulet-haz  # Firefox desktop - b2g gecko linux 64 bit, rooting hazard analysis
     - macosx64_gecko # b2g desktop osx 64 bit
     - win32_gecko    # b2g desktop win 32 bit
     - nexus-5l-eng
     - aries-eng
     - android-api-15
+    - android-api-15-l10n
     - android-api-15-gradle
     - android-api-15-frontend
     - android-partner-sample1
     - android-x86
     - linux
     - linux-l10n    # Desktop l10n
     - linux64
     - linux64-l10n  # Desktop l10n
--- a/taskcluster/ci/legacy/tasks/branches/base_jobs.yml
+++ b/taskcluster/ci/legacy/tasks/branches/base_jobs.yml
@@ -4,16 +4,18 @@
 
 $inherits:
   from: tasks/branches/base_job_flags.yml
 
 builds:
   android-api-15:
     platforms:
       - Android
+    extra-builds:  # see RIDEALONG_BUILDS in `mach taskgraph`
+      - android-api-15-l10n
     types:
       opt:
         task: tasks/builds/android_api_15.yml
       debug:
         task: tasks/builds/android_api_15_debug.yml
   android-x86:
     platforms:
       - Android
--- a/taskcluster/ci/legacy/tasks/branches/try/job_flags.yml
+++ b/taskcluster/ci/legacy/tasks/branches/try/job_flags.yml
@@ -116,16 +116,31 @@ builds:
       debug:
         task: tasks/builds/dbg_linux64_asan.yml
   macosx64-st-an:
     platforms:
       - MacOSX64 Static Analysis
     types:
       opt:
         task: tasks/builds/opt_macosx64_st-an.yml
+  android-api-15-l10n:
+    platforms:
+      - Android
+    types:
+      opt:
+        task: tasks/builds/android_l10n_api_15.yml
+    when:
+      file_patterns:
+        - mobile/android/locales/all-locales
+        - python/compare-locales/**
+        - testing/mozharness/configs/single_locale/**
+        - testing/mozharness/mozharness/mozilla/l10n/locales.py
+        - testing/mozharness/scripts/desktop_l10n.py
+        - toolkit/locales/**
+        - toolkit/mozapps/installer/**
   aries-eng:
     platforms:
       - b2g
     types:
       opt:
         task: tasks/builds/b2g_aries_eng.yml
       debug:
         task: tasks/builds/b2g_aries_debug.yml
new file mode 100644
--- /dev/null
+++ b/taskcluster/ci/legacy/tasks/builds/android_l10n_api_15.yml
@@ -0,0 +1,19 @@
+$inherits:
+  from: 'tasks/builds/android_l10n_base.yml'
+  variables:
+    build_name: 'android-l10n'
+    platform: 'android-api-15'
+task:
+  metadata:
+      name: '[TC] Android API 15 Single Locale Repack'
+      description: 'Android API 15 Single Locale Repack'
+
+  workerType: 'android-api-15'
+
+  extra:
+    treeherder:
+      groupSymbol: tc
+      groupName: Submitted by taskcluster
+      tier: 2
+      symbol: L10n
+
new file mode 100644
--- /dev/null
+++ b/taskcluster/ci/legacy/tasks/builds/android_l10n_base.yml
@@ -0,0 +1,52 @@
+$inherits:
+  from: 'tasks/l10n.yml'
+  variables:
+    platform: 'android-api-15'
+    build_name: 'android-l10n'
+    build_product: 'mobile'
+    build_type: 'opt'
+docker-image: desktop-build
+task:
+  scopes:
+    - 'docker-worker:cache:tooltool-cache'
+    - 'docker-worker:relengapi-proxy:tooltool.download.public'
+    - 'docker-worker:relengapi-proxy:tooltool.download.internal'
+    - 'docker-worker:cache:level-{{level}}-{{project}}-l10n-{{build_name}}-workspace'
+
+  payload:
+    image:
+      type: 'task-image'
+      path: 'public/image.tar'
+      taskId:
+        task-reference: "<docker-image>"
+    cache:
+      tooltool-cache: '/home/worker/tooltool-cache'
+      level-{{level}}-{{project}}-l10n-{{build_name}}-workspace: '/home/worker/workspace'
+
+    features:
+      relengAPIProxy: true
+
+    env:
+      MOZHARNESS_SCRIPT: 'mozharness/scripts/mobile_l10n.py'
+      MOZHARNESS_CONFIG: 'single_locale/{{project}}_{{platform}}.py single_locale/tc_{{platform}}.py'
+      MOZHARNESS_ACTIONS: 'clone-locales list-locales setup repack upload-repacks summary'
+      MOZHARNESS_OPTIONS: 'total-chunks=1 this-chunk=1'
+      JOB_SCRIPT: 'taskcluster/scripts/builder/build-l10n.sh'
+      MH_BRANCH: {{project}}
+      MH_BUILD_POOL: taskcluster
+      # image paths
+      TOOLTOOL_CACHE: '/home/worker/tooltool-cache'
+      NEED_XVFB: true
+
+    maxRunTime: 18000
+
+    command: ["/bin/bash", "bin/build.sh"]
+
+  extra:
+    treeherderEnv:
+      - production
+      - staging
+    treeherder:
+      machine:
+        # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js
+        platform: {{platform}}
old mode 100644
new mode 100755
--- a/taskcluster/taskgraph/test/test_try_option_syntax.py
+++ b/taskcluster/taskgraph/test/test_try_option_syntax.py
@@ -132,17 +132,21 @@ class TestTryOptionSyntax(unittest.TestC
     def test_p_linux_win32(self):
         "-p linux,win32 sets platforms=['linux', 'linux-l10n', 'win32']"
         tos = TryOptionSyntax('try: -p linux,win32', empty_graph)
         self.assertEqual(sorted(tos.platforms), ['linux', 'linux-l10n', 'win32'])
 
     def test_p_expands_ridealongs(self):
         "-p linux,linux64 includes the RIDEALONG_BUILDS"
         tos = TryOptionSyntax('try: -p linux,linux64', empty_graph)
-        ridealongs = list(itertools.chain.from_iterable(RIDEALONG_BUILDS.itervalues()))
+        ridealongs = list(task
+                          for task in itertools.chain.from_iterable(
+                                RIDEALONG_BUILDS.itervalues()
+                          )
+                          if 'android' not in task)  # Don't include android-l10n
         self.assertEqual(sorted(tos.platforms), sorted(['linux', 'linux64'] + ridealongs))
 
     def test_u_none(self):
         "-u none sets unittests=[]"
         tos = TryOptionSyntax('try: -u none', graph_with_jobs)
         self.assertEqual(sorted(tos.unittests), [])
 
     def test_u_all(self):
--- a/taskcluster/taskgraph/try_option_syntax.py
+++ b/taskcluster/taskgraph/try_option_syntax.py
@@ -121,16 +121,19 @@ UNITTEST_PLATFORM_PRETTY_NAMES = {
     # 'win32': [..TODO..],
     # 'win64': [..TODO..],
 }
 
 # We have a few platforms for which we want to do some "extra" builds, or at
 # least build-ish things.  Sort of.  Anyway, these other things are implemented
 # as different "platforms".
 RIDEALONG_BUILDS = {
+    'android-api-15': [
+        'android-api-15-l10n',
+    ],
     'linux': [
         'linux-l10n',
     ],
     'linux64': [
         'linux64-l10n',
         'sm-plain',
         'sm-nonunified',
         'sm-arm-sim',
--- a/testing/firefox-ui/harness/firefox_ui_harness/testcases.py
+++ b/testing/firefox-ui/harness/firefox_ui_harness/testcases.py
@@ -5,16 +5,17 @@
 import os
 import pprint
 from datetime import datetime
 
 import mozfile
 
 from marionette import MarionetteTestCase
 from marionette_driver import Wait
+from marionette_driver.errors import NoSuchWindowException
 
 from firefox_puppeteer.api.prefs import Preferences
 from firefox_puppeteer.api.software_update import SoftwareUpdate
 from firefox_puppeteer.testcases import BaseFirefoxTestCase
 from firefox_puppeteer.ui.update_wizard import UpdateWizardDialog
 
 
 class FirefoxTestCase(BaseFirefoxTestCase, MarionetteTestCase):
@@ -313,18 +314,20 @@ class UpdateTestCase(FirefoxTestCase):
         if force_fallback:
             # Set the downloaded update into failed state
             self.software_update.force_fallback()
 
         # Restart Firefox to apply the downloaded update
         self.restart()
 
     def download_and_apply_forced_update(self):
-        # The update wizard dialog opens automatically after the restart
-        dialog = self.windows.switch_to(lambda win: type(win) is UpdateWizardDialog)
+        # The update wizard dialog opens automatically after the restart but with a short delay
+        dialog = Wait(self.marionette, ignored_exceptions=[NoSuchWindowException]).until(
+            lambda _: self.windows.switch_to(lambda win: type(win) is UpdateWizardDialog)
+        )
 
         # In case of a broken complete update the about window has to be used
         if self.updates[self.current_update_index]['patch']['is_complete']:
             about_window = None
             try:
                 self.assertEqual(dialog.wizard.selected_panel,
                                  dialog.wizard.error)
                 dialog.close()
--- a/testing/mozharness/configs/single_locale/mozilla-central_android-api-15.py
+++ b/testing/mozharness/configs/single_locale/mozilla-central_android-api-15.py
@@ -1,16 +1,18 @@
 BRANCH = "mozilla-central"
 MOZ_UPDATE_CHANNEL = "nightly"
 MOZILLA_DIR = BRANCH
 OBJDIR = "obj-l10n"
 EN_US_BINARY_URL = "http://archive.mozilla.org/pub/mobile/nightly/latest-%s-android-api-15/en-US" % BRANCH
 HG_SHARE_BASE_DIR = "/builds/hg-shared"
 
 config = {
+    # XXX For Try
+    "update_gecko_source_to_enUS": False,
     "branch": BRANCH,
     "log_name": "single_locale",
     "objdir": OBJDIR,
     "is_automation": True,
     "buildbot_json_path": "buildprops.json",
     "force_clobber": True,
     "clobberer_url": "https://api.pub.build.mozilla.org/clobberer/lastclobber",
     "locales_file": "%s/mobile/android/locales/all-locales" % MOZILLA_DIR,
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/single_locale/tc_android-api-15.py
@@ -0,0 +1,18 @@
+import os
+
+config = {
+    "locales_file": "src/mobile/android/locales/all-locales",
+    "tools_repo": "https://hg.mozilla.org/build/tools",
+    "mozconfig": "src/mobile/android/config/mozconfigs/android-api-15/l10n-nightly",
+    "tooltool_config": {
+        "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
+        "output_dir": "%(abs_work_dir)s/src",
+    },
+    "tooltool_servers": ['http://relengapi/tooltool/'],
+
+    "upload_env": {
+        'UPLOAD_HOST': 'localhost',
+        'UPLOAD_PATH': '/home/worker/artifacts/',
+    },
+    "mozilla_dir": "src/",
+}
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/single_locale/try_android-api-15.py
@@ -0,0 +1,97 @@
+BRANCH = "try"
+MOZILLA_DIR = BRANCH
+EN_US_BINARY_URL = "http://archive.mozilla.org/pub/" \
+                   "mobile/nightly/latest-mozilla-central-android-api-15/en-US"
+
+config = {
+    "branch": "try",
+    "log_name": "single_locale",
+    "objdir": "obj-l10n",
+    "is_automation": True,
+    "buildbot_json_path": "buildprops.json",
+    "force_clobber": True,
+    "clobberer_url": "https://api.pub.build.mozilla.org/clobberer/lastclobber",
+    "locales_file": "%s/mobile/android/locales/all-locales" % MOZILLA_DIR,
+    "locales_dir": "mobile/android/locales",
+    "ignore_locales": ["en-US"],
+    "nightly_build": False,
+    'balrog_credentials_file': 'oauth.txt',
+    "tools_repo": "https://hg.mozilla.org/build/tools",
+    "tooltool_config": {
+        "manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
+        "output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
+    },
+    "exes": {
+        'tooltool.py': '/builds/tooltool.py',
+    },
+    "update_gecko_source_to_enUS": False,
+    "repos": [{
+        "vcs": "hg",
+        "repo": "https://hg.mozilla.org/build/tools",
+        "branch": "default",
+        "dest": "tools",
+    }, {
+        "vcs": "hg",
+        "repo": "https://hg.mozilla.org/try",
+        "revision": "%(revision)s",
+        "dest": "try",
+        "clone_upstream_url": "https://hg.mozilla.org/mozilla-central",
+        "clone_by_revision": True,
+        "clone_with_purge": True,
+    }],
+    "hg_l10n_base": "https://hg.mozilla.org/l10n-central",
+    "hg_l10n_tag": "default",
+    'vcs_share_base': "/builds/hg-shared",
+
+    "l10n_dir": "l10n-central",
+    "repack_env": {
+        # so ugly, bug 951238
+        "LD_LIBRARY_PATH": "/lib:/tools/gcc-4.7.2-0moz1/lib:/tools/gcc-4.7.2-0moz1/lib64",
+        "MOZ_OBJDIR": "obj-l10n",
+        "EN_US_BINARY_URL": EN_US_BINARY_URL,
+        "LOCALE_MERGEDIR": "%(abs_merge_dir)s/",
+        "MOZ_UPDATE_CHANNEL": "try", # XXX Invalid
+    },
+    "upload_branch": "%s-android-api-15" % BRANCH,
+    "ssh_key_dir": "~/.ssh",
+    "merge_locales": True,
+    "mozilla_dir": MOZILLA_DIR,
+    "mozconfig": "%s/mobile/android/config/mozconfigs/android-api-15/l10n-nightly" % MOZILLA_DIR,
+    "signature_verification_script": "tools/release/signing/verify-android-signature.sh",
+    "stage_product": "mobile",
+    "platform": "android", # XXX Validate
+    "build_type": "api-15-opt", # XXX Validate
+
+    # Balrog
+    "build_target": "Android_arm-eabi-gcc3",
+
+    # Mock
+    "mock_target": "mozilla-centos6-x86_64-android",
+    "mock_packages": ['autoconf213', 'python', 'zip', 'mozilla-python27-mercurial', 'git', 'ccache',
+                      'glibc-static', 'libstdc++-static', 'perl-Test-Simple', 'perl-Config-General',
+                      'gtk2-devel', 'libnotify-devel', 'yasm',
+                      'alsa-lib-devel', 'libcurl-devel',
+                      'wireless-tools-devel', 'libX11-devel',
+                      'libXt-devel', 'mesa-libGL-devel',
+                      'gnome-vfs2-devel', 'GConf2-devel', 'wget',
+                      'mpfr',  # required for system compiler
+                      'xorg-x11-font*',  # fonts required for PGO
+                      'imake',  # required for makedepend!?!
+                      'gcc45_0moz3', 'gcc454_0moz1', 'gcc472_0moz1', 'gcc473_0moz1', 'yasm', 'ccache',  # <-- from releng repo
+                      'valgrind', 'dbus-x11',
+                      'pulseaudio-libs-devel',
+                      'gstreamer-devel', 'gstreamer-plugins-base-devel',
+                      'freetype-2.3.11-6.el6_1.8.x86_64',
+                      'freetype-devel-2.3.11-6.el6_1.8.x86_64',
+                      'java-1.7.0-openjdk-devel',
+                      'openssh-clients',
+                      'zlib-devel-1.2.3-27.el6.i686',
+                      ],
+    "mock_files": [
+        ("/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"),
+        ('/home/cltbld/.hgrc', '/builds/.hgrc'),
+        ('/builds/relengapi.tok', '/builds/relengapi.tok'),
+        ('/tools/tooltool.py', '/builds/tooltool.py'),
+        ('/usr/local/lib/hgext', '/usr/local/lib/hgext'),
+    ],
+}
--- a/testing/mozharness/scripts/mobile_l10n.py
+++ b/testing/mozharness/scripts/mobile_l10n.py
@@ -101,26 +101,41 @@ class MobileSingleLocale(MockMixin, Loca
          }
     ], [
         ['--total-chunks', ],
         {"action": "store",
          "dest": "total_locale_chunks",
          "type": "int",
          "help": "Specify the total number of chunks of locales"
          }
+    ], [
+        ["--disable-mock"],
+        {"dest": "disable_mock",
+         "action": "store_true",
+         "help": "do not run under mock despite what gecko-config says",
+        }
+    ], [
+        ['--revision', ],
+        {"action": "store",
+         "dest": "revision",
+         "type": "string",
+         "help": "Override the gecko revision to use (otherwise use buildbot supplied"
+                 " value, or en-US revision) "}
     ]]
 
     def __init__(self, require_config_file=True):
         buildscript_kwargs = {
             'all_actions': [
                 "clobber",
                 "pull",
+                "clone-locales",
                 "list-locales",
                 "setup",
                 "repack",
+                "validate-repacks-signed",
                 "upload-repacks",
                 "create-virtualenv",
                 "taskcluster-upload",
                 "submit-to-balrog",
                 "summary",
             ],
             'config': {
                 'taskcluster_credentials_file': 'oauth.txt',
@@ -351,16 +366,18 @@ class MobileSingleLocale(MockMixin, Loca
             # deepcopy() needed because of self.config lock bug :(
             for repo_dict in deepcopy(c['repos']):
                 repo_dict['repo'] = repo_dict['repo'] % replace_dict
                 repos.append(repo_dict)
         else:
             repos = c['repos']
         self.vcs_checkout_repos(repos, parent_dir=dirs['abs_work_dir'],
                                 tag_override=c.get('tag_override'))
+
+    def clone_locales(self):
         self.pull_locale_source()
 
     # list_locales() is defined in LocalesMixin.
 
     def _setup_configure(self, buildid=None):
         c = self.config
         dirs = self.query_abs_dirs()
         env = self.query_repack_env()
@@ -391,17 +408,16 @@ class MobileSingleLocale(MockMixin, Loca
     def setup(self):
         c = self.config
         dirs = self.query_abs_dirs()
         mozconfig_path = os.path.join(dirs['abs_mozilla_dir'], '.mozconfig')
         self.copyfile(os.path.join(dirs['abs_work_dir'], c['mozconfig']),
                       mozconfig_path)
         # TODO stop using cat
         cat = self.query_exe("cat")
-        hg = self.query_exe("hg")
         make = self.query_exe("make")
         self.run_command_m([cat, mozconfig_path])
         env = self.query_repack_env()
         if self.config.get("tooltool_config"):
             self.tooltool_fetch(
                 self.config['tooltool_config']['manifest'],
                 output_dir=self.config['tooltool_config']['output_dir'] % self.query_abs_dirs(),
             )
@@ -411,55 +427,71 @@ class MobileSingleLocale(MockMixin, Loca
                            env=env,
                            error_list=MakefileErrorList,
                            halt_on_failure=True)
         self.run_command_m([make, "unpack"],
                            cwd=dirs['abs_locales_dir'],
                            env=env,
                            error_list=MakefileErrorList,
                            halt_on_failure=True)
-        revision = self.query_revision()
-        if not revision:
-            self.fatal("Can't determine revision!")
-        # TODO do this through VCSMixin instead of hardcoding hg
-        self.run_command_m([hg, "update", "-r", revision],
-                           cwd=dirs["abs_mozilla_dir"],
-                           env=env,
-                           error_list=BaseErrorList,
-                           halt_on_failure=True)
-        self.set_buildbot_property('revision', revision, write_to_file=True)
-        # Configure again since the hg update may have invalidated it.
-        buildid = self.query_buildid()
-        self._setup_configure(buildid=buildid)
+
+        # on try we want the source we already have, otherwise update to the
+        # same as the en-US binary
+        if self.config.get("update_gecko_source_to_enUS", True):
+            revision = self.query_revision()
+            if not revision:
+                self.fatal("Can't determine revision!")
+            hg = self.query_exe("hg")
+            # TODO do this through VCSMixin instead of hardcoding hg
+            self.run_command_m([hg, "update", "-r", revision],
+                               cwd=dirs["abs_mozilla_dir"],
+                               env=env,
+                               error_list=BaseErrorList,
+                               halt_on_failure=True)
+            self.set_buildbot_property('revision', revision, write_to_file=True)
+            # Configure again since the hg update may have invalidated it.
+            buildid = self.query_buildid()
+            self._setup_configure(buildid=buildid)
 
     def repack(self):
         # TODO per-locale logs and reporting.
-        c = self.config
         dirs = self.query_abs_dirs()
         locales = self.query_locales()
         make = self.query_exe("make")
         repack_env = self.query_repack_env()
-        base_package_name = self.query_base_package_name()
-        base_package_dir = os.path.join(dirs['abs_objdir'], 'dist')
         success_count = total_count = 0
         for locale in locales:
             total_count += 1
             self.enable_mock()
             result = self.run_compare_locales(locale)
             self.disable_mock()
             if result:
                 self.add_failure(locale, message="%s failed in compare-locales!" % locale)
                 continue
             if self.run_command_m([make, "installers-%s" % locale],
                                   cwd=dirs['abs_locales_dir'],
                                   env=repack_env,
                                   error_list=MakefileErrorList,
                                   halt_on_failure=False):
                 self.add_failure(locale, message="%s failed in make installers-%s!" % (locale, locale))
                 continue
+            success_count += 1
+        self.summarize_success_count(success_count, total_count,
+                                     message="Repacked %d of %d binaries successfully.")
+
+    def validate_repacks_signed(self):
+        c = self.config
+        dirs = self.query_abs_dirs()
+        locales = self.query_locales()
+        base_package_name = self.query_base_package_name()
+        base_package_dir = os.path.join(dirs['abs_objdir'], 'dist')
+        repack_env = self.query_repack_env()
+        success_count = total_count = 0
+        for locale in locales:
+            total_count += 1
             signed_path = os.path.join(base_package_dir,
                                        base_package_name % {'locale': locale})
             # We need to wrap what this function does with mock, since
             # MobileSigningMixin doesn't know about mock
             self.enable_mock()
             status = self.verify_android_signature(
                 signed_path,
                 script=c['signature_verification_script'],
@@ -468,17 +500,17 @@ class MobileSingleLocale(MockMixin, Loca
             )
             self.disable_mock()
             if status:
                 self.add_failure(locale, message="Errors verifying %s binary!" % locale)
                 # No need to rm because upload is per-locale
                 continue
             success_count += 1
         self.summarize_success_count(success_count, total_count,
-                                     message="Repacked %d of %d binaries successfully.")
+                                     message="Validated signatures on %d of %d binaries successfully.")
 
     def taskcluster_upload(self):
         auth = os.path.join(os.getcwd(), self.config['taskcluster_credentials_file'])
         credentials = {}
         execfile(auth, credentials)
         client_id = credentials.get('taskcluster_clientId')
         access_token = credentials.get('taskcluster_accessToken')
         if not client_id or not access_token:
@@ -574,30 +606,24 @@ class MobileSingleLocale(MockMixin, Loca
             parser = OutputParser(config=self.config, log_obj=self.log_obj,
                                   error_list=MakefileErrorList)
             parser.add_lines(output)
             if parser.num_errors:
                 self.add_failure(locale, message="%s failed in make upload!" % (locale))
                 continue
             package_name = base_package_name % {'locale': locale}
             r = re.compile("(http.*%s)" % package_name)
-            success = False
             for line in output.splitlines():
                 m = r.match(line)
                 if m:
                     self.upload_urls[locale] = m.groups()[0]
                     self.info("Found upload url %s" % self.upload_urls[locale])
-                    success = True
-            if not success:
-                self.add_failure(locale, message="Failed to detect %s url in make upload!" % (locale))
-                print output
-                continue
             success_count += 1
         self.summarize_success_count(success_count, total_count,
-                                     message="Uploaded %d of %d binaries successfully.")
+                                     message="Make Upload for %d of %d locales successful.")
 
     def checkout_tools(self):
         dirs = self.query_abs_dirs()
 
         # We need hg.m.o/build/tools checked out
         self.info("Checking out tools")
         repos = [{
             'repo': self.config['tools_repo'],
@@ -636,16 +662,26 @@ class MobileSingleLocale(MockMixin, Loca
         if not self.config.get("balrog_servers"):
             self.info("balrog_servers not set; skipping balrog submission.")
             return
 
         self.checkout_tools()
 
         dirs = self.query_abs_dirs()
         locales = self.query_locales()
+        balrogReady = True
+        for locale in locales:
+            apk_url = self.query_upload_url(locale)
+            if not apk_url:
+                self.add_failure(locale, message="Failed to detect %s url in make upload!" % (locale))
+                balrogReady = False
+                continue
+        if not balrogReady:
+            return self.fatal(message="Not all repacks successful, abort without submitting to balrog")
+
         for locale in locales:
             apkfile = self.query_apkfile_path(locale)
             apk_url = self.query_upload_url(locale)
 
             # Set other necessary properties for Balrog submission. None need to
             # be passed back to buildbot, so we won't write them to the properties
             #files.
             self.set_buildbot_property("locale", locale)
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -5431,16 +5431,23 @@
     "kind": "flag",
     "description": "a testing histogram; not meant to be touched"
   },
   "TELEMETRY_TEST_COUNT": {
     "expires_in_version": "never",
     "kind": "count",
     "description": "a testing histogram; not meant to be touched"
   },
+  "TELEMETRY_TEST_COUNT2": {
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "count",
+    "bug_numbers": [1288745],
+    "description": "a testing histogram; not meant to be touched"
+  },
   "TELEMETRY_TEST_COUNT_INIT_NO_RECORD": {
     "expires_in_version": "never",
     "kind": "count",
     "description": "a testing histogram; not meant to be touched - initially not recording"
   },
   "TELEMETRY_TEST_CATEGORICAL": {
     "alert_emails": ["telemetry-client-dev@mozilla.com"],
     "bug_numbers": [1188888],
@@ -5506,16 +5513,43 @@
   },
   "TELEMETRY_TEST_KEYED_RELEASE_OPTOUT": {
     "expires_in_version": "never",
     "kind": "flag",
     "keyed": true,
     "releaseChannelCollection": "opt-out",
     "description": "a testing histogram; not meant to be touched"
   },
+  "TELEMETRY_TEST_EXPONENTIAL": {
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "low": 1,
+    "high": 2147483646,
+    "n_buckets": 10,
+    "bug_numbers": [1288745],
+    "description": "a testing histogram; not meant to be touched"
+  },
+  "TELEMETRY_TEST_LINEAR": {
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "low": 1,
+    "high": 2147483646,
+    "n_buckets": 10,
+    "bug_numbers": [1288745],
+    "description": "a testing histogram; not meant to be touched"
+  },
+  "TELEMETRY_TEST_BOOLEAN": {
+    "alert_emails": ["telemetry-client-dev@mozilla.com"],
+    "expires_in_version" : "never",
+    "kind": "boolean",
+    "bug_numbers": [1288745],
+    "description": "a testing histogram; not meant to be touched"
+  },
   "STARTUP_CRASH_DETECTED": {
     "expires_in_version": "never",
     "kind": "flag",
     "description": "Whether there was a crash during the last startup"
   },
   "SAFE_MODE_USAGE": {
     "expires_in_version": "never",
     "kind": "enumerated",
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -1026,26 +1026,16 @@ TelemetryImpl::~TelemetryImpl() {
 }
 
 void
 TelemetryImpl::InitMemoryReporter() {
   RegisterWeakMemoryReporter(this);
 }
 
 NS_IMETHODIMP
-TelemetryImpl::NewHistogram(const nsACString &name, const nsACString &expiration, uint32_t histogramType,
-                            uint32_t min, uint32_t max, uint32_t bucketCount, JSContext *cx,
-                            uint8_t optArgCount, JS::MutableHandle<JS::Value> ret)
-{
-  return TelemetryHistogram::NewHistogram(name, expiration, histogramType,
-                                          min, max, bucketCount,
-                                          cx, optArgCount, ret);
-}
-
-NS_IMETHODIMP
 TelemetryImpl::NewKeyedHistogram(const nsACString &name, const nsACString &expiration, uint32_t histogramType,
                             uint32_t min, uint32_t max, uint32_t bucketCount, JSContext *cx,
                             uint8_t optArgCount, JS::MutableHandle<JS::Value> ret)
 {
   return TelemetryHistogram::NewKeyedHistogram(name, expiration, histogramType,
                                                min, max, bucketCount,
                                                cx, optArgCount, ret);
 }
--- a/toolkit/components/telemetry/TelemetryHistogram.cpp
+++ b/toolkit/components/telemetry/TelemetryHistogram.cpp
@@ -2008,45 +2008,16 @@ const char*
 TelemetryHistogram::GetHistogramName(mozilla::Telemetry::ID id)
 {
   StaticMutexAutoLock locker(gTelemetryHistogramMutex);
   const HistogramInfo& h = gHistograms[id];
   return h.id();
 }
 
 nsresult
-TelemetryHistogram::NewHistogram(const nsACString &name,
-                                 const nsACString &expiration,
-                                 uint32_t histogramType,
-                                 uint32_t min, uint32_t max,
-                                 uint32_t bucketCount, JSContext *cx,
-                                 uint8_t optArgCount,
-                                 JS::MutableHandle<JS::Value> ret)
-{
-  Histogram *h = nullptr;
-  {
-    StaticMutexAutoLock locker(gTelemetryHistogramMutex);
-    if (!internal_IsValidHistogramName(name)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-
-    nsresult rv = internal_HistogramGet(PromiseFlatCString(name).get(),
-                                        PromiseFlatCString(expiration).get(),
-                                        histogramType, min, max, bucketCount,
-                                        optArgCount == 3, &h);
-    if (NS_FAILED(rv))
-      return rv;
-    h->ClearFlags(Histogram::kUmaTargetedHistogramFlag);
-  }
-
-  // Runs without protection from |gTelemetryHistogramMutex|
-  return internal_WrapAndReturnHistogram(h, cx, ret);
-}
-
-nsresult
 TelemetryHistogram::NewKeyedHistogram(const nsACString &name,
                                       const nsACString &expiration,
                                       uint32_t histogramType,
                                       uint32_t min, uint32_t max,
                                       uint32_t bucketCount, JSContext *cx,
                                       uint8_t optArgCount,
                                       JS::MutableHandle<JS::Value> ret)
 {
--- a/toolkit/components/telemetry/TelemetryHistogram.h
+++ b/toolkit/components/telemetry/TelemetryHistogram.h
@@ -52,22 +52,16 @@ GetHistogramById(const nsACString &name,
 nsresult
 GetKeyedHistogramById(const nsACString &name, JSContext *cx,
                       JS::MutableHandle<JS::Value> ret);
 
 const char*
 GetHistogramName(mozilla::Telemetry::ID id);
 
 nsresult
-NewHistogram(const nsACString &name, const nsACString &expiration,
-             uint32_t histogramType, uint32_t min, uint32_t max,
-             uint32_t bucketCount, JSContext *cx,
-             uint8_t optArgCount, JS::MutableHandle<JS::Value> ret);
-
-nsresult
 NewKeyedHistogram(const nsACString &name, const nsACString &expiration,
                   uint32_t histogramType, uint32_t min, uint32_t max,
                   uint32_t bucketCount, JSContext *cx,
                   uint8_t optArgCount, JS::MutableHandle<JS::Value> ret);
 
 nsresult
 HistogramFrom(const nsACString &name, const nsACString &existing_name,
               JSContext *cx, JS::MutableHandle<JS::Value> ret);
--- a/toolkit/components/telemetry/nsITelemetry.idl
+++ b/toolkit/components/telemetry/nsITelemetry.idl
@@ -175,52 +175,39 @@ interface nsITelemetry : nsISupports
    *
    * @param dataset - DATASET_RELEASE_CHANNEL_OPTOUT or DATASET_RELEASE_CHANNEL_OPTIN
    */
   void registeredHistograms(in uint32_t dataset,
                             out uint32_t count,
                             [retval, array, size_is(count)] out string histograms);
 
   /**
-   * Create and return a histogram.  Parameters:
+   * Create a histogram using the current state of an existing histogram.  The
+   * existing histogram must be registered in TelemetryHistograms.h.
    *
    * @param name Unique histogram name
-   * @param expiration Expiration version
-   * @param type - HISTOGRAM_EXPONENTIAL, HISTOGRAM_LINEAR or HISTOGRAM_BOOLEAN
-   * @param min - Minimal bucket size
-   * @param max - Maximum bucket size
-   * @param bucket_count - number of buckets in the histogram.
+   * @param existing_name Existing histogram name
    * The returned object has the following functions:
    *   add(int) - Adds an int value to the appropriate bucket
    *   snapshot() - Returns a snapshot of the histogram with the same data fields as in histogramSnapshots()
    *   clear() - Zeros out the histogram's buckets and sum
    *   dataset() - identifies what dataset this is in: DATASET_RELEASE_CHANNEL_OPTOUT or ...OPTIN
    */
-  [implicit_jscontext, optional_argc]
-  jsval newHistogram(in ACString name, in ACString expiration,
-                     in unsigned long histogram_type,
-                     [optional] in uint32_t min,
-                     [optional] in uint32_t max,
-                     [optional] in uint32_t bucket_count);
-
-  /**
-   * Create a histogram using the current state of an existing histogram.  The
-   * existing histogram must be registered in TelemetryHistograms.h.
-   *
-   * @param name Unique histogram name
-   * @param existing_name Existing histogram name
-   * The returned object has the same functions as a histogram returned from newHistogram.
-   */
   [implicit_jscontext]
   jsval histogramFrom(in ACString name, in ACString existing_name);
 
   /**
-   * Same as newHistogram above, but for histograms registered in TelemetryHistograms.h.
+   * Create and return a histogram registered in TelemetryHistograms.h.
    *
    * @param id - unique identifier from TelemetryHistograms.h
+   * The returned object has the following functions:
+   *   add(int) - Adds an int value to the appropriate bucket
+   *   snapshot() - Returns a snapshot of the histogram with the same data fields as in histogramSnapshots()
+   *   clear() - Zeros out the histogram's buckets and sum
+   *   dataset() - identifies what dataset this is in: DATASET_RELEASE_CHANNEL_OPTOUT or ...OPTIN
    */
   [implicit_jscontext]
   jsval getHistogramById(in ACString id);
 
   /*
    * An object containing a snapshot from all of the currently registered keyed histograms.
    * { name1: {histogramData1}, name2:{histogramData2}...}
    * where the histogramData is as described in histogramSnapshots.
@@ -321,18 +308,16 @@ interface nsITelemetry : nsISupports
   /**
    * Return a histogram previously registered via
    * registerAddonHistogram.  Throws an error if the id/name combo has
    * not been registered via registerAddonHistogram.
    *
    * @param addon_id - Unique ID of the addon
    * @param name - Registered histogram name
    *
-   * The returned object has the same functions as a histogram returned
-   * from newHistogram.
    */
   [implicit_jscontext]
   jsval getAddonHistogram(in ACString addon_id, in ACString name);
 
   /**
    * Delete all histograms associated with the given addon id.
    *
    * @param addon_id - Unique ID of the addon
--- a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js
@@ -34,17 +34,16 @@ const REASON_TEST_PING = "test-ping";
 const REASON_DAILY = "daily";
 const REASON_ENVIRONMENT_CHANGE = "environment-change";
 
 const PLATFORM_VERSION = "1.9.2";
 const APP_VERSION = "1";
 const APP_ID = "xpcshell@tests.mozilla.org";
 const APP_NAME = "XPCShell";
 
-const IGNORE_HISTOGRAM = "test::ignore_me";
 const IGNORE_HISTOGRAM_TO_CLONE = "MEMORY_HEAP_ALLOCATED";
 const IGNORE_CLONED_HISTOGRAM = "test::ignore_me_also";
 const ADDON_NAME = "Telemetry test addon";
 const ADDON_HISTOGRAM = "addon-histogram";
 // Add some unicode characters here to ensure that sending them works correctly.
 const SHUTDOWN_TIME = 10000;
 const FAILED_PROFILE_LOCK_ATTEMPTS = 2;
 
@@ -104,17 +103,17 @@ function fakeGenerateUUID(sessionFunc, s
 }
 
 function fakeIdleNotification(topic) {
   let session = Cu.import("resource://gre/modules/TelemetrySession.jsm");
   return session.TelemetryScheduler.observe(null, topic, null);
 }
 
 function setupTestData() {
-  Telemetry.newHistogram(IGNORE_HISTOGRAM, "never", Telemetry.HISTOGRAM_BOOLEAN);
+
   Telemetry.histogramFrom(IGNORE_CLONED_HISTOGRAM, IGNORE_HISTOGRAM_TO_CLONE);
   Services.startup.interrupted = true;
   Telemetry.registerAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM,
                                    Telemetry.HISTOGRAM_LINEAR,
                                    1, 5, 6);
   let h1 = Telemetry.getAddonHistogram(ADDON_NAME, ADDON_HISTOGRAM);
   h1.add(1);
   let h2 = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT");
@@ -310,17 +309,17 @@ function checkPayload(payload, reason, s
 
   let rh = Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, []);
   for (let name of rh) {
     if (/SQLITE/.test(name) && name in payload.histograms) {
       let histogramName = ("STARTUP_" + name);
       Assert.ok(histogramName in payload.histograms, histogramName + " must be available.");
     }
   }
-  Assert.ok(!(IGNORE_HISTOGRAM in payload.histograms));
+
   Assert.ok(!(IGNORE_CLONED_HISTOGRAM in payload.histograms));
 
   // Flag histograms should automagically spring to life.
   const expected_flag = {
     range: [1, 2],
     bucket_count: 3,
     histogram_type: 3,
     values: {0:1, 1:0},
@@ -479,22 +478,21 @@ add_task(function* test_setup() {
 add_task(function* asyncSetup() {
   yield TelemetryController.testSetup();
   // Load the client ID from the client ID provider to check for pings sanity.
   gClientID = yield ClientID.getClientID();
 });
 
 // Ensures that expired histograms are not part of the payload.
 add_task(function* test_expiredHistogram() {
-  let histogram_id = "FOOBAR";
-  let dummy = Telemetry.newHistogram(histogram_id, "30", Telemetry.HISTOGRAM_EXPONENTIAL, 1, 2, 3);
+
+  let dummy = Telemetry.getHistogramById("TELEMETRY_TEST_EXPIRED");
 
   dummy.add(1);
 
-  do_check_eq(TelemetrySession.getPayload()["histograms"][histogram_id], undefined);
   do_check_eq(TelemetrySession.getPayload()["histograms"]["TELEMETRY_TEST_EXPIRED"], undefined);
 });
 
 // Sends a ping to a non existing server. If we remove this test, we won't get
 // all the histograms we need in the main ping.
 add_task(function* test_noServerPing() {
   yield sendPing();
   // We need two pings in order to make sure STARTUP_MEMORY_STORAGE_SQLIE histograms
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryStopwatch.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryStopwatch.js
@@ -1,17 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 var tmpScope = {};
 Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", tmpScope);
 var TelemetryStopwatch = tmpScope.TelemetryStopwatch;
 
-// We can't create a histogram here since the ones created with
-// newHistogram are not seen by getHistogramById that the module uses.
 const HIST_NAME = "TELEMETRY_PING";
 const HIST_NAME2 = "RANGE_CHECKSUM_ERRORS";
 const KEYED_HIST = { id: "TELEMETRY_INVALID_PING_TYPE_SUBMITTED", key: "TEST" };
 
 var refObj = {}, refObj2 = {};
 
 var originalCount1, originalCount2;
 
--- a/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
+++ b/toolkit/components/telemetry/tests/unit/test_nsITelemetry.js
@@ -52,17 +52,17 @@ function compareHistograms(h1, h2) {
     do_check_eq(s1.counts[i], s2.counts[i]);
 
   do_check_eq(s1.ranges.length, s2.ranges.length);
   for (let i = 0; i < s1.ranges.length; i++)
     do_check_eq(s1.ranges[i], s2.ranges[i]);
 }
 
 function check_histogram(histogram_type, name, min, max, bucket_count) {
-  var h = Telemetry.newHistogram(name, "never", histogram_type, min, max, bucket_count);
+  var h = Telemetry.getHistogramById(name);
   var r = h.snapshot().ranges;
   var sum = 0;
   for (let i=0;i<r.length;i++) {
     var v = r[i];
     sum += v;
     h.add(v);
   }
   var s = h.snapshot();
@@ -119,35 +119,34 @@ function* test_instantiate() {
   Assert.equal(snapshot.sum, subsession[ID].sum,
                "Histogram and subsession histogram sum must match.");
   // Clear the histogram, so we don't void the assumptions from the other tests.
   h.clear();
 });
 
 add_task(function* test_parameterChecks() {
   let kinds = [Telemetry.HISTOGRAM_EXPONENTIAL, Telemetry.HISTOGRAM_LINEAR]
-  for (let histogram_type of kinds) {
+  let testNames = ["TELEMETRY_TEST_EXPONENTIAL", "TELEMETRY_TEST_LINEAR"]
+  for (let i = 0; i < kinds.length; i++) {
+    let histogram_type = kinds[i];
+    let test_type = testNames[i];
     let [min, max, bucket_count] = [1, INT_MAX - 1, 10]
-    check_histogram(histogram_type, "test::"+histogram_type, min, max, bucket_count);
-
-    const nh = Telemetry.newHistogram;
-    expect_fail(() => nh("test::min", "never", histogram_type, 0, max, bucket_count));
-    expect_fail(() => nh("test::bucket_count", "never", histogram_type, min, max, 1));
+    check_histogram(histogram_type, test_type, min, max, bucket_count);
   }
 });
 
 add_task(function* test_noSerialization() {
   // Instantiate the storage for this histogram and make sure it doesn't
   // get reflected into JS, as it has no interesting data in it.
   Telemetry.getHistogramById("NEWTAB_PAGE_PINNED_SITES_COUNT");
   do_check_false("NEWTAB_PAGE_PINNED_SITES_COUNT" in Telemetry.histogramSnapshots);
 });
 
 add_task(function* test_boolean_histogram() {
-  var h = Telemetry.newHistogram("test::boolean histogram", "never", Telemetry.HISTOGRAM_BOOLEAN);
+  var h = Telemetry.getHistogramById("TELEMETRY_TEST_BOOLEAN");
   var r = h.snapshot().ranges;
   // boolean histograms ignore numeric parameters
   do_check_eq(uneval(r), uneval([0, 1, 2]))
   var sum = 0
   for (var i=0;i<r.length;i++) {
     var v = r[i];
     sum += v;
     h.add(v);
@@ -158,17 +157,17 @@ add_task(function* test_boolean_histogra
   do_check_eq(s.histogram_type, Telemetry.HISTOGRAM_BOOLEAN);
   // last bucket should always be 0 since .add parameters are normalized to either 0 or 1
   do_check_eq(s.counts[2], 0);
   do_check_eq(s.sum, 3);
   do_check_eq(s.counts[0], 2);
 });
 
 add_task(function* test_flag_histogram() {
-  var h = Telemetry.newHistogram("test::flag histogram", "never", Telemetry.HISTOGRAM_FLAG);
+  var h = Telemetry.getHistogramById("TELEMETRY_TEST_FLAG");
   var r = h.snapshot().ranges;
   // Flag histograms ignore numeric parameters.
   do_check_eq(uneval(r), uneval([0, 1, 2]));
   // Should already have a 0 counted.
   var c = h.snapshot().counts;
   var s = h.snapshot().sum;
   do_check_eq(uneval(c), uneval([1, 0, 0]));
   do_check_eq(s, 0);
@@ -183,17 +182,17 @@ add_task(function* test_flag_histogram()
   var c3 = h.snapshot().counts;
   var s3 = h.snapshot().sum;
   do_check_eq(uneval(c3), uneval([0, 1, 0]));
   do_check_eq(s3, 1);
   do_check_eq(h.snapshot().histogram_type, Telemetry.HISTOGRAM_FLAG);
 });
 
 add_task(function* test_count_histogram() {
-  let h = Telemetry.newHistogram("test::count histogram", "never", Telemetry.HISTOGRAM_COUNT, 1, 2, 3);
+  let h = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT2");
   let s = h.snapshot();
   do_check_eq(uneval(s.ranges), uneval([0, 1, 2]));
   do_check_eq(uneval(s.counts), uneval([0, 0, 0]));
   do_check_eq(s.sum, 0);
   h.add();
   s = h.snapshot();
   do_check_eq(uneval(s.counts), uneval([1, 0, 0]));
   do_check_eq(s.sum, 1);
@@ -284,17 +283,17 @@ add_task(function* test_getWebrtc() {
   var webrtc = Telemetry.webrtcStats;
   do_check_true("IceCandidatesStats" in webrtc);
   var icestats = webrtc.IceCandidatesStats;
   do_check_true(("webrtc" in icestats) && ("loop" in icestats));
 });
 
 // Check that telemetry doesn't record in private mode
 add_task(function* test_privateMode() {
-  var h = Telemetry.newHistogram("test::private_mode_boolean", "never", Telemetry.HISTOGRAM_BOOLEAN);
+  var h = Telemetry.getHistogramById("TELEMETRY_TEST_BOOLEAN");
   var orig = h.snapshot();
   Telemetry.canRecordExtended = false;
   h.add(1);
   do_check_eq(uneval(orig), uneval(h.snapshot()));
   Telemetry.canRecordExtended = true;
   h.add(1);
   do_check_neq(uneval(orig), uneval(h.snapshot()));
 });
@@ -320,17 +319,17 @@ add_task(function* test_histogramRecordi
   // Extended histograms should not be recorded.
   h = Telemetry.getHistogramById("TELEMETRY_TEST_RELEASE_OPTIN");
   orig = h.snapshot();
   h.add(1);
   Assert.equal(orig.sum, h.snapshot().sum,
                "Histograms should be equal after recording.");
 
   // Runtime created histograms should not be recorded.
-  h = Telemetry.newHistogram("test::runtime_created_boolean", "never", Telemetry.HISTOGRAM_BOOLEAN);
+  h = Telemetry.getHistogramById("TELEMETRY_TEST_BOOLEAN");
   orig = h.snapshot();
   h.add(1);
   Assert.equal(orig.sum, h.snapshot().sum,
                "Histograms should be equal after recording.");
 
   // Check that extended histograms are recorded when required.
   Telemetry.canRecordExtended = true;
 
@@ -437,29 +436,27 @@ add_task(function* test_addons() {
   Telemetry.unregisterAddonHistograms(addon_id);
   snapshots = Telemetry.addonHistogramSnapshots;
   do_check_false(addon_id in snapshots);
   // Make sure other addons are unaffected.
   do_check_true(extra_addon in snapshots);
 });
 
 add_task(function* test_expired_histogram() {
-  var histogram_id = "FOOBAR";
   var test_expired_id = "TELEMETRY_TEST_EXPIRED";
   var clone_id = "ExpiredClone";
-  var dummy = Telemetry.newHistogram(histogram_id, "28.0a1", Telemetry.HISTOGRAM_EXPONENTIAL, 1, 2, 3);
+  var dummy = Telemetry.getHistogramById(test_expired_id);
   var dummy_clone = Telemetry.histogramFrom(clone_id, test_expired_id);
   var rh = Telemetry.registeredHistograms(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, []);
   Assert.ok(!!rh);
 
   dummy.add(1);
   dummy_clone.add(1);
 
   do_check_eq(Telemetry.histogramSnapshots["__expired__"], undefined);
-  do_check_eq(Telemetry.histogramSnapshots[histogram_id], undefined);
   do_check_eq(Telemetry.histogramSnapshots[test_expired_id], undefined);
   do_check_eq(Telemetry.histogramSnapshots[clone_id], undefined);
   do_check_eq(rh[test_expired_id], undefined);
 });
 
 add_task(function* test_keyed_histogram() {
   // Check that invalid names get rejected.