Merge m-c to fx-team, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 06 Sep 2016 17:37:18 -0700
changeset 313004 73a6a267a50a0e1c41e689b265ad3eebe43d7ac6
parent 313003 ae2144aa4356b65c2f8c0de8c9082dcb7e330e24 (current diff)
parent 312878 91c2b9d5c1354ca79e5b174591dbb03b32b15bbf (diff)
child 313005 16a1a91f9269ab95dd83eb29dc5d0227665f7d94
push id81509
push usercbook@mozilla.com
push dateWed, 07 Sep 2016 15:23:10 +0000
treeherdermozilla-inbound@80dccdd8c94a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge 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.